###### Expressions: dereference
###### Binode types
- Deref,
+ Deref, AddressOf,
###### term grammar
print_exec(b->left, -1, bracket);
printf("@");
break;
+ case AddressOf:
+ print_exec(b->left, -1, bracket);
+ break;
###### propagate binode cases
case Deref:
return t->reference.referent;
break;
+ case AddressOf:
+ /* left must be lval, we create reference to it */
+ if (!type || type->free != reference_free)
+ t = propagate_types(b->left, c, perr, type, 0); // UNTESTED
+ else
+ t = propagate_types(b->left, c, perr,
+ type->reference.referent, 0);
+ if (t)
+ t = find_anon_type(c, &reference_prototype, "@%.*s",
+ t->name.len, t->name.txt);
+ return t;
+
###### interp binode cases
- case Deref: {
+ case Deref:
left = interp_exec(c, b->left, <ype);
lrv = left.ref;
rvtype = ltype->reference.referent;
break;
- }
+
+ case AddressOf:
+ rv.ref = linterp_exec(c, b->left, &rvtype);
+ rvtype = find_anon_type(c, &reference_prototype, "@%.*s",
+ rvtype->name.len, rvtype->name.txt);
+ break;
#### Functions
return 0;
}
+ static struct exec *take_addr(struct exec *e)
+ {
+ struct binode *rv = new(binode);
+ rv->op = AddressOf;
+ rv->left = e;
+ return rv;
+ }
+
static void function_check_args(struct parse_context *c, enum prop_err *perr,
struct type *require, struct exec *args)
{
while (param) {
struct var *pv = cast(var, param->left);
+ struct type *t = pv->var->type, *t2;
if (!arg) {
type_err(c, "error: insufficient arguments to function.",
args, NULL, 0, NULL);
break;
}
*perr = 0;
- propagate_types(arg->left, c, perr, pv->var->type, 0);
+ t2 = propagate_types(arg->left, c, perr, t, Rrefok);
+ if (t->free == reference_free &&
+ t->reference.referent == t2 &&
+ !(*perr & Erval)) {
+ arg->left = take_addr(arg->left);
+ } else if (!(*perr & Efail) && !type_compat(t2, t, 0)) {
+ type_err(c, "error: cannot pass rval when reference expected",
+ arg->left, NULL, 0, NULL);
+ }
param = cast(binode, param->right);
arg = cast(binode, arg->right);
}