If a function parameters is a declared as an reference, and the passed
argument is not, then we insert the new AddressOf operator so that
the correct value is passed.
This allow "var" parameters much like Pascal - though with completely
different syntax.
Signed-off-by: NeilBrown <neil@brown.name>
func main(argv:[ac::]string)
list : linkage
func main(argv:[ac::]string)
list : linkage
- insert(lp, "@start");
- insert(lp, "~end")
+ insert(list, "@start");
+ insert(list, "~end")
for i:=1; then i=i+1; while i < ac:
for i:=1; then i=i+1; while i < ac:
- insert(lp, argv[i])
- insert(lp, "Hello!")
- printlist(lp)
- freelist(lp)
+ insert(list, argv[i])
+ insert(list, "Hello!")
+ printlist(list)
+ freelist(list)
###### output: linked_list,one,two,three,four
@start
###### output: linked_list,one,two,three,four
@start
+ func test7(a:@number)
+ test7(45)
+ test7("45")
+
###### output: func_err_args
###### output: func_err_args
+ .tmp.code:40:14: error: cannot pass rval when reference expected
+ .tmp.code:41:14: error: expected @number found string
.tmp.code:34:5: error: function cannot return value of type foo
.tmp.code:28:8: error: expected string, found none
.tmp.code:25:8: error: expected string, found number
.tmp.code:34:5: error: function cannot return value of type foo
.tmp.code:28:8: error: expected string, found none
.tmp.code:25:8: error: expected string, found number
###### Expressions: dereference
###### Binode types
###### Expressions: dereference
###### Binode types
print_exec(b->left, -1, bracket);
printf("@");
break;
print_exec(b->left, -1, bracket);
printf("@");
break;
+ case AddressOf:
+ print_exec(b->left, -1, bracket);
+ break;
###### propagate binode cases
case Deref:
###### propagate binode cases
case Deref:
return t->reference.referent;
break;
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
###### interp binode cases
left = interp_exec(c, b->left, <ype);
lrv = left.ref;
rvtype = ltype->reference.referent;
break;
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;
+ 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)
{
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);
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;
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);
}
param = cast(binode, param->right);
arg = cast(binode, arg->right);
}