McStasMcXtrace / mccode-antlr

McCode grammar implemented with ANTLR4
1 stars 0 forks source link

More robust component `DECLARE` variable handling #74

Closed g5t closed 1 month ago

g5t commented 1 month ago

Component definition files are allowed to define any valid C variable in a DECLARE section; such defined variables are then included in the generated component-type parameter struct as 'private' members.

Adding the definition to the struct is straightforward, as it can be copied verbatim (minus any static initialization). But later accessing the struct member can be less straightforward due to complexities in identifying its name.

For example, a component could include a library that defines a labeled struct libDataStructure and aliases it to LibData like

typedef struct libDataStruct {
  int a;
  double b;
  char c[10];
} LibData;

and then have a DECLARE section like

DECLARE %{
float nearly_pi=3.14159f;
LibData my_lds={.b=3.14159, .a=-1, .c="nearly pi"};
void (*compare_fun_ptr)(LibData *, LibData*);
int numbers[]={0, 1, 2, 3, 4, 5};
%}

Which would need to produce a component parameters struct like

struct _struct_comp_parameters {
...
// private
float nearly_pi;
LibData my_lds;
int (*compare_fun_ptr)(LibData*, LibData*);
int numbers[6];
}
typedef struct _struct_comp_parameters _class_comp_parameters;

And later, each component instance will have its own _class_comp_parameters variable, with initialization like,

_class_comp_parameters comp_parameters;
comp_parameters.nearly_pi=3.14159f;
comp_parameters.my_lds.b=3.14159;
comp_parameters.my_lds.a=-1;
comp_parameters.my_lds.c="nearly pi"};
comp_parameters.compare_fun_ptr=NULL;
comp_parameters.numbers[0]=0;
comp_parameters.numbers[1]=1;
comp_parameters.numbers[2]=2;
comp_parameters.numbers[3]=3;
comp_parameters.numbers[4]=4;
comp_parameters.numbers[5]=5;

Current implementation

The named type, variable identifier, and initialized value are all extracted from the DECLARE block lines as strings, and returned as, e.g,

def extract_declare(declare_string: str) -> tuple[str, tuple[str, str | None]]:
    pass

(variable_identifier, (named_type, initialized_value) = extract_declare("float nearly_pi=3.14159f;")
assert named_type == "float"
assert variable_identifier == "nearly_pi"
assert initialized_value == "3.14159f"

Plus an attempt is made to identify stack arrays and pointer-valued variables, to ensure they are initialized safely, and with an eye toward possibly translating the user-defined C code into a different language in the future. This is achieved by looking for "*", "[]", and r"\[[0-9]*\]" and converting the tuple[str, tuple[str, str | None]] to a NamedTuple with extra fields is_pointer and is_array.

Current limitations

Proposed improvement

Replace the tuple[str, tuple[str, str | None]] with a class object earlyier. Current parsing requires the use of two such objects to keep track of whether a declaration includes function pointer. Those objects should be augmented to take the place of the NamedTuple used presently.