From 038c114a1ceec224aeaa6c15c025c6bb4b3c2b6d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 18 Dec 2021 13:47:45 +1100 Subject: [PATCH] oceani: add transparent AddressOf operator for function parameters. 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 --- csrc/oceani-tests.mdc | 19 +++++++++++------- csrc/oceani.mdc | 45 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index c990bad..958575c 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -751,15 +751,14 @@ A simple linked list example func main(argv:[ac::]string) list : linkage - lp:@linkage = list - insert(lp, "@start"); - insert(lp, "~end") + insert(list, "@start"); + insert(list, "~end") 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 @@ -1137,7 +1136,13 @@ Test for type errors with functions b.a = a use b + func test7(a:@number) + test7(45) + test7("45") + ###### 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 diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 1ec640f..891ce74 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -3327,7 +3327,7 @@ anything in the heap or on the stack. A reference can be assigned ###### Expressions: dereference ###### Binode types - Deref, + Deref, AddressOf, ###### term grammar @@ -3343,6 +3343,9 @@ anything in the heap or on the stack. A reference can be assigned print_exec(b->left, -1, bracket); printf("@"); break; + case AddressOf: + print_exec(b->left, -1, bracket); + break; ###### propagate binode cases case Deref: @@ -3356,13 +3359,30 @@ anything in the heap or on the stack. A reference can be assigned 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 @@ -3462,6 +3482,14 @@ further detailed when Expression Lists are introduced. 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) { @@ -3473,13 +3501,22 @@ further detailed when Expression Lists are introduced. 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); } -- 2.43.0