###### core functions
static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
###### core functions
static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
- struct type *type, int rules)
+ struct type *type, int rules);
+ static struct type *__propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+ struct type *type, int rules)
+ static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+ struct type *type, int rules)
+ {
+ struct type *ret = __propagate_types(prog, c, ok, type, rules);
+
+ if (c->parse_error)
+ *ok = 0;
+ return ret;
+ }
+
t = propagate_types(b->left, c, ok, NULL, rules & Rnoconstant);
if (!t || t->compat != array_compat) {
type_err(c, "error: %1 cannot be indexed", prog, t, 0, NULL);
t = propagate_types(b->left, c, ok, NULL, rules & Rnoconstant);
if (!t || t->compat != array_compat) {
type_err(c, "error: %1 cannot be indexed", prog, t, 0, NULL);
return NULL;
} else {
if (!type_compat(type, t->array.member, rules)) {
type_err(c, "error: have %1 but need %2", prog,
t->array.member, rules, type);
return NULL;
} else {
if (!type_compat(type, t->array.member, rules)) {
type_err(c, "error: have %1 but need %2", prog,
t->array.member, rules, type);
f->left, st, 0, NULL);
else if (f->index == -2) {
f->index = find_struct_index(st, f->name);
f->left, st, 0, NULL);
else if (f->index == -2) {
f->index = find_struct_index(st, f->name);
type_err(c, "error: have %1 but need %2", prog,
ft, rules, type);
type_err(c, "error: have %1 but need %2", prog,
ft, rules, type);
- propagate_types($<5, config2context(config), &ok, $3, 0);
+ propagate_types($<5, c, &ok, $3, 0);
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
type_err(c, "error: expected %1%r found %2",
prog, type, rules, val->val.type);
type_err(c, "error: expected %1%r found %2",
prog, type, rules, val->val.type);
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER : Type ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER : Type ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: Type ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: Type ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
$*exec
Variable -> IDENTIFIER ${ {
v->where_decl, NULL, 0, NULL);
}
} }$
$*exec
Variable -> IDENTIFIER ${ {
struct variable *v = var->var;
if (!v) {
type_err(c, "%d:BUG: no variable!!", prog, NULL, 0, NULL); // NOTEST
struct variable *v = var->var;
if (!v) {
type_err(c, "%d:BUG: no variable!!", prog, NULL, 0, NULL); // NOTEST
prog, NULL, 0, NULL);
type_err(c, "info: name was defined as a constant here",
v->where_decl, NULL, 0, NULL);
prog, NULL, 0, NULL);
type_err(c, "info: name was defined as a constant here",
v->where_decl, NULL, 0, NULL);
type, rules, v->val.type);
type_err(c, "info: this is where '%v' was set to %1", v->where_set,
v->val.type, rules, NULL);
type, rules, v->val.type);
type_err(c, "info: this is where '%v' was set to %1", v->where_set,
v->val.type, rules, NULL);
/* both must be Tbool, result is Tbool */
propagate_types(b->left, c, ok, Tbool, 0);
propagate_types(b->right, c, ok, Tbool, 0);
/* both must be Tbool, result is Tbool */
propagate_types(b->left, c, ok, Tbool, 0);
propagate_types(b->right, c, ok, Tbool, 0);
type_err(c, "error: %1 operation found where %2 expected", prog,
Tbool, 0, type);
type_err(c, "error: %1 operation found where %2 expected", prog,
Tbool, 0, type);
if (t)
t = propagate_types(b->left, c, ok, t, 0);
}
if (t)
t = propagate_types(b->left, c, ok, t, 0);
}
type_err(c, "error: Comparison returns %1 but %2 expected", prog,
Tbool, rules, type);
type_err(c, "error: Comparison returns %1 but %2 expected", prog,
Tbool, rules, type);
* unary ops fit here too */
propagate_types(b->left, c, ok, Tnum, 0);
propagate_types(b->right, c, ok, Tnum, 0);
* unary ops fit here too */
propagate_types(b->left, c, ok, Tnum, 0);
propagate_types(b->right, c, ok, Tnum, 0);
type_err(c, "error: Arithmetic returns %1 but %2 expected", prog,
Tnum, rules, type);
type_err(c, "error: Arithmetic returns %1 but %2 expected", prog,
Tnum, rules, type);
return Tnum;
case Concat:
/* both must be Tstr, result is Tstr */
propagate_types(b->left, c, ok, Tstr, 0);
propagate_types(b->right, c, ok, Tstr, 0);
return Tnum;
case Concat:
/* both must be Tstr, result is Tstr */
propagate_types(b->left, c, ok, Tstr, 0);
propagate_types(b->right, c, ok, Tstr, 0);
type_err(c, "error: Concat returns %1 but %2 expected", prog,
Tstr, rules, type);
type_err(c, "error: Concat returns %1 but %2 expected", prog,
Tstr, rules, type);
type_err(c, "error: expected %1%r, found %2",
e->left, type, rules, t);
type_err(c, "error: expected %1%r, found %2",
e->left, type, rules, t);
propagate_types(b->left, c, ok, t,
(b->op == Assign ? Rnoconstant : 0));
}
propagate_types(b->left, c, ok, t,
(b->op == Assign ? Rnoconstant : 0));
}
type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);
type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);
+ if ($0->right->type == Xvar) {
+ struct var *v = cast(var, $0->right);
+ if (v->var->val.type == Tnone) {
+ /* Convert this to a label */
+ v->var->val = val_prepare(Tlabel);
+ v->var->val.label = &v->var->val;
+ }
+ }
$0->condpart = $1.condpart; $1.condpart = NULL;
$0->thenpart = $1.thenpart; $1.thenpart = NULL;
// This is where we close an "if" statement
$0->condpart = $1.condpart; $1.condpart = NULL;
$0->thenpart = $1.thenpart; $1.thenpart = NULL;
// This is where we close an "if" statement
}$
CondSuffix -> IfSuffix ${
$0 = $<1;
// This is where we close scope of the whole
// "for" or "while" statement
}$
CondSuffix -> IfSuffix ${
$0 = $<1;
// This is where we close scope of the whole
// "for" or "while" statement
- v = var_ref(config2context(config), $1.txt);
- tok_err(config2context(config), "error: name already declared", &$1);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ v = var_ref(c, $1.txt);
+ tok_err(c, "error: name already declared", &$1);
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
do {
ok = 1;
v->where_decl, NULL, 0, NULL);
}
do {
ok = 1;
- propagate_types($5, config2context(config), &ok, $3, 0);
+ propagate_types($5, c, &ok, $3, 0);
- var_block_close(config2context(config), CloseSequential);
- if (config2context(config)->scope_stack) abort();
+ var_block_close(c, CloseSequential);
+ if (c->scope_stack && !c->parse_error) abort();