diff options
Diffstat (limited to '')
-rw-r--r-- | src/mds-kbdc/compile-layout.c | 5 | ||||
-rw-r--r-- | src/mds-kbdc/variables.c | 58 | ||||
-rw-r--r-- | src/mds-kbdc/variables.h | 15 |
3 files changed, 74 insertions, 4 deletions
diff --git a/src/mds-kbdc/compile-layout.c b/src/mds-kbdc/compile-layout.c index 8eac14c..477ba33 100644 --- a/src/mds-kbdc/compile-layout.c +++ b/src/mds-kbdc/compile-layout.c @@ -167,8 +167,8 @@ static int let(size_t variable, const char32_t* restrict string, const mds_kbdc_ int saved_errno; /* Warn if this is a possible shadow attempt. */ - if (possibile_shadow_attempt && variables_let_will_override(variable) && - statement && (statement->processed != PROCESS_LEVEL)) + if (possibile_shadow_attempt && variables_let_will_override(variable) && statement && + (variables_has_been_used_in_for(variable) == 0) && (statement->processed != PROCESS_LEVEL)) { statement->processed = PROCESS_LEVEL; NEW_ERROR(statement, WARNING, "does not shadow existing definition"); @@ -2110,6 +2110,7 @@ static int compile_for(mds_kbdc_tree_for_t* restrict tree) if (*first == *last) break; } + fail_if (variables_was_used_in_for(variable)); /* Catch `break` and `continue`, they may not propagate further. */ if (break_level < 3) diff --git a/src/mds-kbdc/variables.c b/src/mds-kbdc/variables.c index 155edd7..4d4f941 100644 --- a/src/mds-kbdc/variables.c +++ b/src/mds-kbdc/variables.c @@ -41,11 +41,18 @@ typedef struct variable struct variable* restrict previous; /** - * The original scope the current shadow - * of the variable was created in + * The original scope in which the current + * shadow of the variable was created */ size_t scope; + /** + * The latest scope the in which the + * variable has been used in a for-loop, + * `~0' if never, or below `scope` + */ + size_t used_in_for; + } variable_t; @@ -173,6 +180,7 @@ int variables_let(size_t variable, mds_kbdc_tree_t* restrict value) variables[variable]->value = value; variables[variable]->previous = previous; variables[variable]->scope = current_scope; + variables[variable]->used_in_for = (size_t)(~0LL); } return 0; @@ -197,3 +205,49 @@ mds_kbdc_tree_t* variables_get(size_t variable) return variables[variable]->value; } + +/** + * Mark a variable as having been unsed in a for-loop in the current scope + * + * @param variable The variable index, must already be defined + * @return Zero on success, -1 on error + */ +int variables_was_used_in_for(size_t variable) +{ + variable_t* previous; + + /* Already marked. */ + if (variables[variable]->used_in_for == current_scope) + return 0; + + /* Not marked. */ + if (variables[variable]->used_in_for == (size_t)(~0LL)) + return variables[variable]->used_in_for = current_scope, 0; + + /* Marked for another scope. */ + previous = variables[variable]; + if (xmalloc(variables[variable], 1, variable_t)) + fail_if (variables[variable] = previous, 1); + variables[variable]->value = mds_kbdc_tree_dup(previous->value); + fail_if (variables[variable]->value == NULL); + variables[variable]->previous = previous; + variables[variable]->scope = current_scope; + variables[variable]->used_in_for = current_scope; + + return 0; + fail: + return -1; +} + + +/** + * Check whether a variable has been used in a for-loop in the current scope + * + * @param variable The variable index, must already be defined + * @return Whether `variables_was_used_in_for` has been unused on the variable + */ +int variables_has_been_used_in_for(size_t variable) +{ + return variables[variable]->used_in_for == current_scope; +} + diff --git a/src/mds-kbdc/variables.h b/src/mds-kbdc/variables.h index c01c163..c678c59 100644 --- a/src/mds-kbdc/variables.h +++ b/src/mds-kbdc/variables.h @@ -74,6 +74,21 @@ int variables_let(size_t variable, mds_kbdc_tree_t* restrict value); */ mds_kbdc_tree_t* variables_get(size_t variable) __attribute__((pure)); +/** + * Mark a variable as having been unsed in a for-loop in the current scope + * + * @param variable The variable index, must already be defined + * @return Zero on success, -1 on error + */ +int variables_was_used_in_for(size_t variable); + +/** + * Check whether a variable has been used in a for-loop in the current scope + * + * @param variable The variable index, must already be defined + * @return Whether `variables_was_used_in_for` has been unused on the variable + */ +int variables_has_been_used_in_for(size_t variable) __attribute__((pure)); #endif |