fprintf(stderr, "oceani: no main function found.\n");
context.parse_error = 1;
}
+ if (context.prog && !context.parse_error) {
+ if (!analyse_prog(context.prog, &context)) {
+ fprintf(stderr, "oceani: type error in program - not running.\n");
+ context.parse_error = 1;
+ }
+ }
if (context.prog && doprint) {
## print const decls
## print type decls
print_exec(context.prog, 0, brackets);
}
- if (context.prog && doexec && !context.parse_error) {
- if (!analyse_prog(context.prog, &context)) {
- fprintf(stderr, "oceani: type error in program - not running.\n");
- exit(1);
- }
+ if (context.prog && doexec && !context.parse_error)
interp_prog(&context, context.prog, argc - optind, argv+optind);
- }
free_exec(context.prog);
while (s) {
enclosed the declaration, and that has closed.
- "conditionally in scope". The "in scope" block and all parallel
- scopes have closed, and no further mention of the name has been
- seen. This state includes a secondary nest depth which records the
- outermost scope seen since the variable became conditionally in
- scope. If a use of the name is found, the variable becomes "in
- scope" and that secondary depth becomes the recorded scope depth.
- If the name is declared as a new variable, the old variable becomes
- "out of scope" and the recorded scope depth stays unchanged.
+ scopes have closed, and no further mention of the name has been seen.
+ This state includes a secondary nest depth (`min_depth`) which records
+ the outermost scope seen since the variable became conditionally in
+ scope. If a use of the name is found, the variable becomes "in scope"
+ and that secondary depth becomes the recorded scope depth. If the
+ name is declared as a new variable, the old variable becomes "out of
+ scope" and the recorded scope depth stays unchanged.
- "out of scope". The variable is neither in scope nor conditionally
in scope. It is permanently out of scope now and can be removed from
static void var_block_close(struct parse_context *c, enum closetype ct)
{
- /* Close off all variables that are in_scope */
+ /* Close off all variables that are in_scope.
+ * Some variables in c->scope may already be not-in-scope,
+ * such as when a PendingScope variable is hidden by a new
+ * variable with the same name.
+ * So we check for v->name->var != v and drop them.
+ * If we choose to make a variable OutScope, we drop it
+ * immediately too.
+ */
struct variable *v, **vp, *v2;
scope_pop(c);
(v->scope == OutScope || v->name->var != v)
? (*vp = v->in_scope, 0)
: ( vp = &v->in_scope, 0)) {
- if (v->name->var != v) {
+ v->min_depth = c->scope_depth;
+ if (v->name->var != v)
/* This is still in scope, but we haven't just
* closed the scope.
*/
continue;
- }
switch (ct) {
case CloseElse:
case CloseParallel: /* handle PendingScope */
case InScope:
case CondScope:
if (c->scope_stack->child_count == 1)
+ /* first among parallel branches */
v->scope = PendingScope;
else if (v->previous &&
v->previous->scope == PendingScope)
+ /* all previous branches used name */
v->scope = PendingScope;
- else if (v->type == Tlabel) // UNTESTED
+ else if (v->type == Tlabel)
+ /* Labels remain pending even when not used */
v->scope = PendingScope; // UNTESTED
- else if (v->name->var == v) // UNTESTED
- v->scope = OutScope; // UNTESTED
+ else
+ v->scope = OutScope;
if (ct == CloseElse) {
/* All Pending variables with this name
* are now Conditional */
}
break;
case PendingScope:
- for (v2 = v;
- v2 && v2->scope == PendingScope;
- v2 = v2->previous)
- if (v2->type != Tlabel)
- v2->scope = OutScope;
- break;
- case OutScope: break; // UNTESTED
+ /* Not possible as it would require
+ * parallel scope to be nested immediately
+ * in a parallel scope, and that never
+ * happens.
+ */
+ case OutScope:
+ /* Not possible as we already tested for
+ * OutScope
+ */
+ abort(); // NOTEST
}
break;
case CloseSequential:
v2 = v2->previous)
if (v2->type == Tlabel) {
v2->scope = CondScope;
- v2->min_depth = c->scope_depth;
} else
v2->scope = OutScope;
break;
do_indent(indent, "");
print_exec(b->left, indent, bracket);
if (cast(var, b->left)->var->constant) {
+ printf("::");
if (v->where_decl == v->where_set) {
- printf("::");
type_print(v->type, stdout);
printf(" ");
- } else
- printf(" ::");
+ }
} else {
+ printf(":");
if (v->where_decl == v->where_set) {
- printf(":");
type_print(v->type, stdout);
printf(" ");
- } else
- printf(" :");
+ }
}
if (b->right) {
printf("= ");
}
al = cast(binode, al->right);
}
- v = interp_exec(c, p->right, &vtype);
+ v = interp_exec(c, p, &vtype);
free_value(vtype, &v);
}
###### interp binode cases
- case List:
- case Func: abort(); // NOTEST
+ case List: abort(); // NOTEST
+
+ case Func:
+ rv = interp_exec(c, b->right, &rvtype);
+ break;
## And now to test it out.