-
Notifications
You must be signed in to change notification settings - Fork 357
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
Additional annotation parsing #919
Changes from all commits
bffd2d9
2b1d67e
0adc5f9
9c17082
010289e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,6 +129,44 @@ annotate_autoid( | |
return IDL_RETCODE_OK; | ||
} | ||
|
||
static idl_retcode_t | ||
annotate_optional( | ||
idl_pstate_t *pstate, | ||
idl_annotation_appl_t *annotation_appl, | ||
idl_node_t *node) | ||
{ | ||
const idl_const_expr_t *const_expr; | ||
idl_member_t *mem = (idl_member_t*)node; | ||
bool value = true; | ||
|
||
assert(annotation_appl); | ||
|
||
if (!idl_is_member(node)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@optional can only be assigned to members"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} else if (mem->key.value) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@optional cannot be assigned to key members"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} else if (mem->value.annotation) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@optional cannot be assigned to members with explicit default values"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
|
||
if (annotation_appl->parameters) { | ||
const_expr = annotation_appl->parameters->const_expr; | ||
assert(const_expr); | ||
value = ((const idl_literal_t*)const_expr)->value.bln; | ||
} | ||
|
||
mem->optional.annotation = annotation_appl; | ||
mem->optional.value = value; | ||
|
||
return IDL_RETCODE_OK; | ||
} | ||
|
||
static idl_retcode_t | ||
annotate_value( | ||
idl_pstate_t *pstate, | ||
|
@@ -250,8 +288,13 @@ annotate_key( | |
} | ||
|
||
if (idl_mask(node) & IDL_MEMBER) { | ||
((idl_member_t *)node)->key.annotation = annotation_appl; | ||
((idl_member_t *)node)->key.value = key; | ||
if (((idl_member_t*)node)->optional.value) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@key cannot be applied to optional members"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
((idl_member_t*)node)->key.annotation = annotation_appl; | ||
((idl_member_t*)node)->key.value = key; | ||
} else if (idl_mask(node) & IDL_SWITCH_TYPE_SPEC) { | ||
((idl_switch_type_spec_t *)node)->key.annotation = annotation_appl; | ||
((idl_switch_type_spec_t *)node)->key.value = key; | ||
|
@@ -306,6 +349,70 @@ set_nested( | |
return IDL_RETCODE_OK; | ||
} | ||
|
||
static idl_retcode_t | ||
annotate_default( | ||
idl_pstate_t *pstate, | ||
idl_annotation_appl_t *annotation_appl, | ||
idl_node_t *node) | ||
{ | ||
idl_const_expr_t *value; | ||
idl_member_t *mem = (idl_member_t*)node; | ||
idl_type_spec_t *mem_spec = mem->type_spec; | ||
|
||
assert(annotation_appl); | ||
assert(annotation_appl->parameters); | ||
|
||
if (!idl_is_member(node)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@default can only be assigned to members"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} else if (mem->optional.value) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@default cannot be set on optional members"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
|
||
value = annotation_appl->parameters->const_expr; | ||
assert(idl_is_literal(value)); | ||
|
||
/*check whether type of literal matches and falls inside spec of member*/ | ||
idl_type_t mem_type = idl_type(mem_spec); | ||
if (mem_type != idl_type(value)) { | ||
idl_retcode_t ret = IDL_RETCODE_OK; | ||
idl_literal_t *literal = NULL; | ||
if ((ret = idl_evaluate(pstate, value, mem_type, &literal))) | ||
return ret; | ||
|
||
assert(literal); | ||
annotation_appl->parameters->const_expr = literal; | ||
literal->node.parent = (idl_node_t*)annotation_appl->parameters; | ||
} | ||
|
||
((idl_member_t *)node)->value.annotation = annotation_appl; | ||
((idl_member_t *)node)->value.value = annotation_appl->parameters->const_expr; | ||
|
||
return IDL_RETCODE_OK; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
static idl_retcode_t | ||
annotate_default_literal( | ||
idl_pstate_t *pstate, | ||
idl_annotation_appl_t *annotation_appl, | ||
idl_node_t *node) | ||
{ | ||
assert(pstate); | ||
|
||
if (!idl_is_enumerator(node)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@default_literal can only be assigned to enumerators"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
|
||
node->mask |= IDL_DEFAULT_ENUMERATOR; | ||
|
||
return IDL_RETCODE_OK; | ||
} | ||
|
||
static idl_retcode_t | ||
annotate_nested( | ||
idl_pstate_t *pstate, | ||
|
@@ -430,12 +537,11 @@ static const idl_builtin_annotation_t annotations[] = { | |
"instructs to automatically allocate identifiers to elements that have " | ||
"not been assigned a 32-bit unsigned identifiers explicitly.</p>", | ||
.callback = &annotate_autoid }, | ||
#if 0 | ||
{ .syntax = "@annotation optional { boolean value default TRUE; };", | ||
.summary = | ||
"<p>Set optionality on any element that makes sense to be optional.</p>", | ||
.callback = annotate_optional }, | ||
#endif | ||
"<p>Indicates that the annotated member may be in a NULL state, not" | ||
"containing any value.</p>", | ||
.callback = &annotate_optional }, | ||
{ .syntax = "@annotation value { any value; };", | ||
.summary = | ||
"<p>Set a constant value to any element that may be given a constant " | ||
|
@@ -466,17 +572,23 @@ static const idl_builtin_annotation_t annotations[] = { | |
"<p>Specify a data member is part of the key for the object whose type " | ||
"is the constructed data type owning this element.</p>", | ||
.callback = annotate_key }, | ||
{ .syntax = "@annotation default { any value; };", | ||
.summary = | ||
"<p>Specify the value with which the annotated member should be default" | ||
"initialized.</p>", | ||
.callback = &annotate_default }, | ||
{ .syntax = "@annotation default_literal { };", | ||
.summary = | ||
"<p>Explicity sets the default value for an enum to the annotated enumerator" | ||
"instead of the first entry.</p>", | ||
.callback = &annotate_default_literal }, | ||
#if 0 | ||
{ .syntax = "@annotation must_understand { boolean value default TRUE; };", | ||
.summary = | ||
"<p>Specify the data member must be understood by any application " | ||
"making use of that piece of data.</p>", | ||
.callback = annotate_must_understand }, | ||
/* units and ranges */ | ||
{ .syntax = "@annotation default { any value; };", | ||
.summary = | ||
"<p>Specify a default value for the annotated element.</p>", | ||
.callback = annotate_default }, | ||
{ .syntax = "@annotation range { any min; any max; };", | ||
.summary = | ||
"<p>Specify a range of allowed value for the annotated element.</p>", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -784,6 +784,19 @@ uint32_t idl_bound(const void *node) | |
return 0u; | ||
} | ||
|
||
const idl_literal_t *idl_default_value(const void *node) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move to a separate PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the function name |
||
if (idl_is_member(node)) { | ||
return ((const idl_member_t*)node)->value.value; | ||
} else if (idl_is_declarator(node)) { | ||
const idl_node_t *parent = idl_parent(node); | ||
if (idl_is_member(parent)) | ||
return idl_default_value(parent); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
bool idl_is_sequence(const void *ptr) | ||
{ | ||
idl_mask_t mask; | ||
|
@@ -2016,6 +2029,23 @@ idl_create_enum( | |
ret = IDL_RETCODE_SEMANTIC_ERROR; | ||
goto err_clash; | ||
} | ||
if (idl_mask(e1) == IDL_DEFAULT_ENUMERATOR) { | ||
if (node->default_enumerator) { | ||
idl_error(pstate, idl_location(e1), | ||
"Assigning default to enumerator '%s' clashes with '%s' already being set as default.", | ||
e1->name->identifier, node->default_enumerator->name->identifier); | ||
ret = IDL_RETCODE_SEMANTIC_ERROR; | ||
goto err_defaults; | ||
} else { | ||
node->default_enumerator = e1; | ||
} | ||
} | ||
} | ||
|
||
//fallback to the first entry | ||
if (!node->default_enumerator) { | ||
node->default_enumerator = enumerators; | ||
node->default_enumerator->node.mask = IDL_IMPLICIT_DEFAULT_ENUMERATOR; | ||
} | ||
|
||
if ((ret = idl_declare(pstate, kind, name, node, NULL, NULL))) | ||
|
@@ -2025,6 +2055,7 @@ idl_create_enum( | |
return IDL_RETCODE_OK; | ||
err_declare: | ||
err_clash: | ||
err_defaults: | ||
free(node); | ||
err_alloc: | ||
return ret; | ||
|
@@ -2062,7 +2093,9 @@ static void *iterate_enumerator(const void *ptr, const void *cur) | |
static const char *describe_enumerator(const void *ptr) | ||
{ | ||
(void)ptr; | ||
assert(idl_mask(ptr) == IDL_ENUMERATOR); | ||
assert(idl_mask(ptr) == IDL_ENUMERATOR | ||
|| idl_mask(ptr) == IDL_DEFAULT_ENUMERATOR | ||
|| idl_mask(ptr) == IDL_IMPLICIT_DEFAULT_ENUMERATOR); | ||
return "enumerator"; | ||
} | ||
|
||
|
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.
Shouldn't
((idl_member_t *)node)->is_optional
be set at this point?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 no longer relevant, after rebasing I have changed to using the IDL_ANNOTATABLE macro