]> ocean-lang.org Git - ocean/commitdiff
oceani: fix parsing for function declaration parameters
authorNeilBrown <neil@brown.name>
Fri, 12 Nov 2021 22:02:19 +0000 (09:02 +1100)
committerNeilBrown <neil@brown.name>
Sat, 13 Nov 2021 22:50:58 +0000 (09:50 +1100)
Multiple lines of declarations weren't handle properly.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index 2314ce3ea4d9ec070c7cf23867f04f3072fd71b3..78b458b3a455adf33dae58958dccea7e15fe40b1 100644 (file)
@@ -630,6 +630,14 @@ Test functions.  They don't return anything, so we need to get them to print
        do
                pass
 
+       func twoarg
+               a:number
+               b:string
+       do
+               while a > 0:
+                       print b
+                       a = a - 1
+
        func test(n:number; s:string)
                if n >= 1:
                        print n,s,
@@ -936,6 +944,10 @@ Test for type errors with functions
        func test2(a:number; b:string; c:[3]Boolean)
                print a, b, c[1]
 
+       func test3()
+               # use undefined names
+               print a, z
+
        func main()
                truth:[3]Boolean
                truth[1] = True
@@ -949,17 +961,19 @@ Test for type errors with functions
                        pass
 
 ###### output: func_err_args
-       .tmp.code:11:14: error: insufficient arguments to function.
-       .tmp.code:12:14: error: expected number found string
-       .tmp.code:12:22: error: expected string found number
-       .tmp.code:12:14: error: insufficient arguments to function.
-       .tmp.code:14:17: error: expected string found number
-       .tmp.code:15:14: error: too many arguments to function.
-       .tmp.code:16:14: error: attempt to call a non-function.
-       .tmp.code:16:32: error: expected string found number
-       .tmp.code:16:28: error: insufficient arguments to function.
-       .tmp.code:17:20: error: expected  func but variable 'test2' is  func
+       .tmp.code:15:14: error: insufficient arguments to function.
+       .tmp.code:16:14: error: expected number found string
+       .tmp.code:16:22: error: expected string found number
+       .tmp.code:16:14: error: insufficient arguments to function.
+       .tmp.code:18:17: error: expected string found number
+       .tmp.code:19:14: error: too many arguments to function.
+       .tmp.code:20:14: error: attempt to call a non-function.
+       .tmp.code:20:32: error: expected string found number
+       .tmp.code:20:28: error: insufficient arguments to function.
+       .tmp.code:21:20: error: expected  func but variable 'test2' is  func
        .tmp.code:??:??: info: this is where 'NOTVAR' was set to  func
+       .tmp.code:10:14: error: variable used but not declared: a
+       .tmp.code:10:17: error: variable used but not declared: z
        oceani: type error in program - not running.
 
 ###### test: func_err_redeclare
index c89ecafc6c33890f838890eceb91b815e07575f3..fabfe188c07ebd5bc9abdca9dd492aad34041de2 100644 (file)
@@ -2340,19 +2340,22 @@ has a type which includes the set of parameters and the return value.
 As yet these types cannot be declared separately from the function
 itself.
 
-The parameters can be specified either in parentheses as a list, such as
+The parameters can be specified either in parentheses as a ';' separated
+list, such as
 
 ##### Example: function 1
 
-       func main(av:[ac::number]string)
+       func main(av:[ac::number]string; env:[envc::number]string)
                code block
 
-or as an indented list of one parameter per line
+or as an indented list of one parameter per line (though each line can
+be a ';' separated list)
 
 ##### Example: function 2
 
        func main
                argv:[argc::number]string
+               env:[envc::number]string
        do
                code block
 
@@ -2479,12 +2482,21 @@ further detailed when Expression Lists are introduced.
 
 
        $*binode
-       Args -> ${ $0 = NULL; }$
+       Args -> ArgsLine NEWLINE ${ $0 = $<AL; }$
+               | Args ArgsLine NEWLINE ${ {
+                       struct binode *b = $<AL;
+                       struct binode **bp = &b;
+                       while (*bp)
+                               bp = (struct binode **)&(*bp)->left;
+                       *bp = $<A;
+                       $0 = b;
+               } }$
+
+       ArgsLine -> ${ $0 = NULL; }$
                | Varlist ${ $0 = $<1; }$
                | Varlist ; ${ $0 = $<1; }$
-               | Varlist NEWLINE ${ $0 = $<1; }$
 
-       Varlist -> Varlist ; ArgDecl ${ // UNTESTED
+       Varlist -> Varlist ; ArgDecl ${
                        $0 = new(binode);
                        $0->op = List;
                        $0->left = $<Vl;
@@ -4725,10 +4737,10 @@ analysis is a bit more interesting at this level.
 ###### top level grammar
 
        $*variable
-       DeclareFunction -> func FuncName ( OpenScope Args ) Block Newlines ${
+       DeclareFunction -> func FuncName ( OpenScope ArgsLine ) Block Newlines ${
                        $0 = declare_function(c, $<FN, $<Ar, $<Bl);
                }$
-               | func FuncName IN OpenScope OptNL Args OUT OptNL do Block Newlines ${
+               | func FuncName IN OpenScope Args OUT OptNL do Block Newlines ${
                        $0 = declare_function(c, $<FN, $<Ar, $<Bl);
                }$
                | func FuncName NEWLINE OpenScope OptNL do Block Newlines ${
@@ -4770,9 +4782,10 @@ analysis is a bit more interesting at this level.
        static int analyse_funcs(struct parse_context *c)
        {
                struct variable *v;
-               int ok = 1;
-               for (v = c->in_scope; ok && v; v = v->in_scope) {
+               int all_ok = 1;
+               for (v = c->in_scope; v; v = v->in_scope) {
                        struct value *val;
+                       int ok = 1;
                        if (v->depth != 0 || !v->type || !v->type->check_args)
                                continue;
                        val = var_value(c, v);
@@ -4783,9 +4796,11 @@ analysis is a bit more interesting at this level.
                        if (ok)
                                /* Make sure everything is still consistent */
                                propagate_types(val->function, c, &ok, Tnone, 0);
+                       if (!ok)
+                               all_ok = 0;
                        v->type->function.local_size = scope_finalize(c);
                }
-               return ok;
+               return all_ok;
        }
 
        static int analyse_main(struct type *type, struct parse_context *c)