]> ocean-lang.org Git - ocean/commitdiff
oceani: add transparent AddressOf operator for function parameters.
authorNeilBrown <neil@brown.name>
Sat, 18 Dec 2021 02:47:45 +0000 (13:47 +1100)
committerNeilBrown <neil@brown.name>
Sat, 18 Dec 2021 02:47:45 +0000 (13:47 +1100)
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>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index c990bad78a101383f5aa942537b5bbbecf96f4d0..958575c63cb4e1860d4fb88d1501df726b8fc8a7 100644 (file)
@@ -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
index 1ec640f1b4ed6520b17723d36d00d15c1e3a011d..891ce74c2e4d097b0cb9e4143f9dac97c0ec1e77 100644 (file)
@@ -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, &ltype);
                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);
                }