Introduce new logging API, fixes #858
PiperOrigin-RevId: 930744288 Change-Id: I6ec1203b55c031390f3eef23192e2337508ce886
This commit is contained in:
committed by
Copybara-Service
parent
a2abaf7aef
commit
58f6d52491
@@ -15,7 +15,9 @@
|
||||
"""Utility functions for code generation."""
|
||||
|
||||
import os
|
||||
from typing import Union
|
||||
from introspect import ast_nodes
|
||||
from wasm.codegen.generators import constants
|
||||
|
||||
|
||||
def write_to_file(filepath: str, content: str) -> None:
|
||||
@@ -87,12 +89,27 @@ def get_inner_value_type(
|
||||
return param.type.inner_type
|
||||
|
||||
|
||||
def is_struct_value_type(
|
||||
t: Union[ast_nodes.ValueType, ast_nodes.ArrayType, ast_nodes.PointerType],
|
||||
) -> bool:
|
||||
"""Checks if a type is a struct passed by value."""
|
||||
if isinstance(t, ast_nodes.ValueType):
|
||||
return (
|
||||
t.name not in constants.PRIMITIVE_TYPES
|
||||
and t.name != "void"
|
||||
and not t.name.startswith("mjf")
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
def should_be_wrapped(func: ast_nodes.FunctionDecl) -> bool:
|
||||
"""Checks if a MuJoCo function needs a wrapper function."""
|
||||
if get_pointer_return_inner_value_type(func):
|
||||
return True
|
||||
if is_struct_value_type(func.return_type):
|
||||
return True
|
||||
for param in func.parameters:
|
||||
if get_inner_value_type(param):
|
||||
if get_inner_value_type(param) or is_struct_value_type(param.type):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ _SKIPPED_MEMORY_FUNCTIONS: tuple[str, ...] = (
|
||||
"mju_error",
|
||||
"mju_free",
|
||||
"mju_malloc",
|
||||
"mju_setLogHandler",
|
||||
"mju_strncpy",
|
||||
"mju_warning",
|
||||
# go/keep-sorted end
|
||||
@@ -230,6 +231,7 @@ MANUAL_WRAPPER_FUNCTIONS: tuple[str, ...] = (
|
||||
"mj_saveModel",
|
||||
"mj_setLengthRange",
|
||||
"mju_error",
|
||||
"mju_info",
|
||||
# go/keep-sorted end
|
||||
)
|
||||
|
||||
@@ -276,6 +278,8 @@ STRUCTS_TO_BIND: list[str] = list(
|
||||
NO_DEFAULT_CONSTRUCTORS: tuple[str, ...] = (
|
||||
# go/keep-sorted start
|
||||
"mjContact",
|
||||
"mjLogConfig",
|
||||
"mjLogMessage",
|
||||
"mjPreContact",
|
||||
"mjSolverStat",
|
||||
"mjStatistic",
|
||||
|
||||
@@ -154,6 +154,14 @@ def get_param_string(p: ast_nodes.FunctionParameterDecl) -> str:
|
||||
return f"const NumberArray& {p.name}"
|
||||
else:
|
||||
return f"const val& {p.name}"
|
||||
elif common.is_struct_value_type(p.type):
|
||||
# Struct by value parameters
|
||||
value_type = cast(ast_nodes.ValueType, p.type)
|
||||
const_qualifier = "const " if value_type.is_const else "const "
|
||||
return (
|
||||
f"{const_qualifier}{common.capitalize(value_type.name)}&"
|
||||
f" {p.name}"
|
||||
)
|
||||
else:
|
||||
# This case should ideally not be reached if AST is well-formed
|
||||
# and types are categorized by the helper booleans correctly.
|
||||
@@ -183,6 +191,8 @@ def get_params_string_maybe_with_conversion(
|
||||
native_params.append(f"{p.name}.get()")
|
||||
elif param_is_primitive_value(p):
|
||||
native_params.append(p.name)
|
||||
elif common.is_struct_value_type(p.type):
|
||||
native_params.append(f"*{p.name}.get()")
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Unhandled parameter type for conversion: {p.type} for param"
|
||||
@@ -201,6 +211,14 @@ def get_compatible_return_code(func: ast_nodes.FunctionDecl) -> str:
|
||||
return f"{c_call};"
|
||||
if func.return_type.name in constants.PRIMITIVE_TYPES:
|
||||
return f"return {c_call};"
|
||||
if common.is_struct_value_type(func.return_type):
|
||||
struct_name = func.return_type.name
|
||||
w = common.wrapped_struct_name(struct_name)
|
||||
builder = code_builder.CodeBuilder()
|
||||
builder.line(f"{w} result;")
|
||||
builder.line(f"*result.get() = {c_call};")
|
||||
builder.line("return result;")
|
||||
return builder.to_string()
|
||||
|
||||
if inner_type := common.get_pointer_return_inner_value_type(func):
|
||||
if inner_type.name == "char":
|
||||
@@ -230,6 +248,9 @@ def get_compatible_return_type(func: ast_nodes.FunctionDecl) -> str:
|
||||
and func.return_type.name in constants.PRIMITIVE_TYPES
|
||||
):
|
||||
return f"{func.return_type.name}"
|
||||
if common.is_struct_value_type(func.return_type):
|
||||
return_type = cast(ast_nodes.ValueType, func.return_type)
|
||||
return common.wrapped_struct_name(return_type.name)
|
||||
return "val"
|
||||
|
||||
|
||||
|
||||
@@ -229,6 +229,36 @@ def _generate_field_data(
|
||||
binding=_get_property_binding(f, w, setter=False, reference=True),
|
||||
)
|
||||
|
||||
# Case 2.5: const char* without array_extent (C strings like body, func).
|
||||
elif (
|
||||
inner_type_name == "char"
|
||||
and not is_dynamically_sized
|
||||
):
|
||||
builder = code_builder.CodeBuilder()
|
||||
if f.type.inner_type.is_const:
|
||||
with builder.function(f"std::string {f.name}() const"):
|
||||
builder.line(
|
||||
f'return ptr_->{f.name} ? std::string(ptr_->{f.name}) : "";'
|
||||
)
|
||||
else:
|
||||
with builder.function(f"std::string {f.name}() const"):
|
||||
builder.line(
|
||||
f'return ptr_->{f.name} ? std::string(ptr_->{f.name}) : "";'
|
||||
)
|
||||
with builder.function(f"void set_{f.name}(const std::string& value)"):
|
||||
with builder.block(f"if (ptr_->{f.name})"):
|
||||
builder.line(
|
||||
f"std::strncpy(ptr_->{f.name}, value.c_str(),"
|
||||
f" sizeof(ptr_->{f.name}));"
|
||||
)
|
||||
return WrappedFieldData(
|
||||
declaration=builder.to_string(),
|
||||
typename=_get_field_struct_type(f, s),
|
||||
binding=_get_property_binding(
|
||||
f, w, setter=not f.type.inner_type.is_const, reference=True
|
||||
),
|
||||
)
|
||||
|
||||
# Case 3: Non-dynamically sized pointer fields to other structs.
|
||||
elif (
|
||||
not is_dynamically_sized
|
||||
|
||||
Reference in New Issue
Block a user