-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anonymous structs and case types and compile-time flags #85
Conversation
…ith both makefile and batch mode support
… fix grouping of fields; fix expected output in one case
FYI, as part of the generalization of the syntax to support nested structs and unions, I fixed the syntax to insist on every field declaration in a struct concluding with a semi-colon. This is in keeping with C syntax, whereas previously we would allow things like |
and field' = | ||
| AtomicField of atomic_field | ||
| RecordField : record -> ident -> field' | ||
| SwitchCaseField : switch_case -> ident -> field' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one of the main changes in the PR.
A field is no longer just an atomic field. It can be a composite field too, enabled nested structs (RecordField) and unions (SwitchCaseField)
match field.v with | ||
| RecordField _ _ | ||
| SwitchCaseField _ _ -> | ||
Inl (rewrite_composite_field field) :: out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recurse to rewrite_field, to group bitfields within the record or union
then Inr(index, typ, af :: atomic_fields) :: tl //extend this bitfield group | ||
else Inr(bf.v.bitfield_identifier, bf.v.bitfield_type, [af]) :: out //new bitfield group | ||
|
||
| _ -> Inr (bf.v.bitfield_identifier, bf.v.bitfield_type, [af]) :: out //new bitfield group |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The behavior on atomic fields is the same as before
|
||
let get_config () = | ||
match !parsed_config with | ||
| Some c -> Some c |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parse the config once and memoize it
| This -> error "'this' is not allowed in the guard of an #if" e.range | ||
| Static _ -> failwith "static should have been eliminated already" | ||
| Constant _ -> () | ||
| Identifier i -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ensures that all variables in a #if are declared as compile-time flags in the config
Summary
We now support anonymous nested structs and case types. Previously, all such types had to be named at the top level.
You can use a #if to enforce some constraints based on compile-time boolean expressions in the constraint associated with a field.
You can also use #if to selectively add fields to a type, with some restrictions explained in the detailed section later in this email.
The generated code preserves those #if expressions, so that the C code can be compiled for multiple compile-time configurations.
Limitations
Since we are generating C code that contains the #if (since the goal is to be able to generate C code for multiple compile-time configurations at once from a single 3d specification), we are NOT using a preprocessor to just evaluate the #if terms away at the 3D level. This means, unlike C, you cannot use
#if
everywhere to syntactically preprocess terms (e.g., conditionally adding a function argument, renaming a type, etc.)Note also, due to FStarLang/karamel#293 some examples do not yet produce compilable C code. See, tests/ifdefs/src/AnonNestedStructIfDefs.3d, which produces C code, but the compilation to produce a .o is currently excluded from the regression suite until the krml bug is fixed.
How it works
A config file
Associated with 3d project (which may consist of multiple 3d files), we associate a new JSON formatted .3d.config file.
See tests/ifdefs/src/CompileTimeIfFlags.3d.config, for an example, reproduced here:
It contains a key called
compile_time_flags
whose value contains:.h
file that provides definitions for all those flags, e.g., "compile_time_flags.h"Based on these configuration options, 3d will
Check that if you are writing
#if F1 && F2
, that all the variables mentioned inF1 && F2
are recorded in the config file. The flags field of the config is a clear contract between 3d and include file (compile_time_flags.h), meaning that if definitions for all the flags variables are provided, then we guarantee that the code produced by 3d should be compilable for all values of those flags.When 3d generates code, in every C file it produces, it will also inject the following directive in its corresponding .h file:
It is then responsibility of the user to actually provide
compile_time_flags.h
, making sure that it is available on the include path, and that it provides definitions for all the flags.It also provides the user with the flexibility to define those flags however they please, e.g., using complex macro expressions, referencing other header files, etc.
In a typical usage, one could:
Some more details
##.
#if
in constraintsIn the constraint associated with a field, you can use a #if to enforce some constraints based on compile-time boolean expressions:
For example, you can write:
This produces the following C code fragment for validating the
y
field:#if
in the fields of a typeYou can also use #if to selectively add fields to a type, based on some compile-time boolean expressions.
For example:
Which produces C code of the following shape:
Note, dependence between the branches of a #if is not allowed. For example, you cannot write
If you must have dependence between the fields, then you need to distribute the fields between the branches,
For example, this is legal: