]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani-tests.mdc
oceani: free variables as soon as they go out of scope.
[ocean] / csrc / oceani-tests.mdc
index 87a7aa99a548b876a4ef5962b446d03f0ec74800..dccfb2a47bc2bdb50f7f3a39e7c3adf09ccf1b01 100644 (file)
@@ -80,11 +80,11 @@ arguments separated from the name by commas.  For each test, there is a section
                @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage || true
                @ awk '/NOTEST/ { next } /^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \
                    END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \
                @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage || true
                @ awk '/NOTEST/ { next } /^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \
                    END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \
-                        if (ran < (ran + skip) *0.94) exit(1) }' \
+                        if (ran < (ran + skip) *0.959) exit(1) }' \
                        coverage/oceani.mdc.gcov
                @rm -f .tmp*
 
                        coverage/oceani.mdc.gcov
                @rm -f .tmp*
 
-               @for T in $(oceani_tests); do \
+               @[ -n "$$SKIP_VALGRIND" ] || for T in $(oceani_tests); do \
                    echo -n "Valgrind $$T.. "; \
                    i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \
                    if ! valgrind --error-exitcode=1 --log-file=.tmp.valg ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \
                    echo -n "Valgrind $$T.. "; \
                    i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \
                    if ! valgrind --error-exitcode=1 --log-file=.tmp.valg ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \
@@ -110,7 +110,9 @@ calculations on them.
 
 ###### test: valvar
 
 
 ###### test: valvar
 
-       program:
+       func main
+               argv:[argc::]string
+       do
                a := 23; b:=12 ; b1 := -b
                print a, b, a+b, a-b, a*b, a/b, a%b
                print a<b, a<=b, a>b, a>=b, a<a, a==b, a==a
                a := 23; b:=12 ; b1 := -b
                print a, b, a+b, a-b, a*b, a/b, a%b
                print a<b, a<=b, a>b, a>=b, a<a, a==b, a==a
@@ -147,7 +149,7 @@ Next we change the value of variables
 
 ###### test: setvar
 
 
 ###### test: setvar
 
-       program:
+       func main()
                a := 4
                a = a * a
                a = (a + a) * (a + a)
                a := 4
                a = a * a
                a = (a + a) * (a + a)
@@ -163,14 +165,14 @@ Now some contants
        oceani_tests += "consts"
 
 ###### test: consts
        oceani_tests += "consts"
 
 ###### test: consts
-       const:
+       const
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
                cake ::= "The cake is"
                  ++ " a lie"
 
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
                cake ::= "The cake is"
                  ++ " a lie"
 
-       program:
+       func main()
                print "Hello World, what lovely oceans you have!"
                print "are there", five, "?"
                print pi, pie, "but", cake
                print "Hello World, what lovely oceans you have!"
                print "are there", five, "?"
                print pi, pie, "but", cake
@@ -187,19 +189,32 @@ Test merging of variables from multiple cases
 
 ###### test: varmerge
 
 
 ###### test: varmerge
 
-       program:
+       func main()
                for i:=0; then i=i+1; while i < 5:
                for i:=0; then i=i+1; while i < 5:
-                       switch i
+                       switch i:
+                               case 0: num:="zero"
+                               case 1: scratch:=42; num:="one"
+                               case 2: num:="two"
+                               case 3: num:="three"
+                               else    num:="many"
+                       print num,", ",
+               print
+
+               for i:=0; then i=i+1; while i < 5:
+                       switch i:
                                case 0: num:="zero"
                                case 1: num:="one"
                                case 2: num:="two"
                                case 3: num:="three"
                                case 0: num:="zero"
                                case 1: num:="one"
                                case 2: num:="two"
                                case 3: num:="three"
-                               else:   num:="many"
+                               else    num:="many"
+                       // re-declare a CondScope variable
+                       num := i*i
                        print num,", ",
                print
 
 ###### output: varmerge
        zero , one , two , three , many , 
                        print num,", ",
                print
 
 ###### output: varmerge
        zero , one , two , three , many , 
+       0 , 1 , 4 , 9 , 16 , 
 
 ## Conditions and Loops
 
 
 ## Conditions and Loops
 
@@ -210,11 +225,11 @@ Now we need to test if/else and some different loops
 
 ###### test: cond_loop
 
 
 ###### test: cond_loop
 
-       program:
+       func main()
                a := 4
                if a < 5:
                        print "Success"
                a := 4
                if a < 5:
                        print "Success"
-               else:
+               else
                        print "Failure"
                for b:=1; then b=b+b; while b < 100:
                        print '', b,
                        print "Failure"
                for b:=1; then b=b+b; while b < 100:
                        print '', b,
@@ -222,12 +237,12 @@ Now we need to test if/else and some different loops
                // Newtons method for square root of 2
                target ::= 2
                guess := target
                // Newtons method for square root of 2
                target ::= 2
                guess := target
-               for:
+               for
                        count: number = 0
                        count: number = 0
-               while:
+               while
                        current := guess * guess
                        use +(current - target) > 0.000000001
                        current := guess * guess
                        use +(current - target) > 0.000000001
-               do:
+               do
                        guess = (guess + (target / guess) ) / 2
                        print count, guess
                        count = count + 1
                        guess = (guess + (target / guess) ) / 2
                        print count, guess
                        count = count + 1
@@ -236,7 +251,7 @@ Now we need to test if/else and some different loops
                for j:=0; then j = j+3 ; while j < 10:
                        if j != 0 and then 20 / j > 3:
                                print "20 /", j," =", 20 / j
                for j:=0; then j = j+3 ; while j < 10:
                        if j != 0 and then 20 / j > 3:
                                print "20 /", j," =", 20 / j
-                       else:
+                       else
                                print "I won't calculate 20 /", j
                pi ::= 3.1415926535897
                if 355/113 == pi or else +(pi - 355/113) < 0.001:
                                print "I won't calculate 20 /", j
                pi ::= 3.1415926535897
                if 355/113 == pi or else +(pi - 355/113) < 0.001:
@@ -249,9 +264,16 @@ Now we need to test if/else and some different loops
                then { i = i+1 }
                while i <= 10:
                        sum = sum + i
                then { i = i+1 }
                while i <= 10:
                        sum = sum + i
-               else:
+               else
                        pass
                        print "sum 1..10 is", sum
                        pass
                        print "sum 1..10 is", sum
+               if
+                       PI1 := 22/7
+                       use PI1 < pi
+               then
+                       print "Smaller"
+               else
+                       print 'larger'
 
 ###### output: cond_loop
        Success
 
 ###### output: cond_loop
        Success
@@ -270,6 +292,7 @@ Now we need to test if/else and some different loops
        pi exceeds three
        pi sufficient
        sum 1..10 is 55
        pi exceeds three
        pi sufficient
        sum 1..10 is 55
+       larger
 
 ## Say Hello
 
 
 ## Say Hello
 
@@ -282,14 +305,17 @@ Here I break it into two parts, keeping the array code separate.
 
 ###### test: sayhello
 
 
 ###### test: sayhello
 
-       program A B astr bbool:
+       func main(av:[ac::number]string)
+               A := $av[1]; B := $av[2]
+               astr := av[3]
+               bbool := av[ac-1] == "True"
                print "Hello World, what lovely oceans you have!"
                /* When a variable is defined in both branches of an 'if',
                 * and used afterwards, the variables are merged.
                 */
                if A > B:
                        bigger := "yes"
                print "Hello World, what lovely oceans you have!"
                /* When a variable is defined in both branches of an 'if',
                 * and used afterwards, the variables are merged.
                 */
                if A > B:
                        bigger := "yes"
-               else:
+               else
                        bigger := "no"
                print "Is", A, "bigger than", B,"? ", bigger
                /* If a variable is not used after the 'if', no
                        bigger := "no"
                print "Is", A, "bigger than", B,"? ", bigger
                /* If a variable is not used after the 'if', no
@@ -298,26 +324,27 @@ Here I break it into two parts, keeping the array code separate.
                if A > B * 2:
                        double:string = "yes"
                        print A, "is more than twice", B, "?", double
                if A > B * 2:
                        double:string = "yes"
                        print A, "is more than twice", B, "?", double
-               else:
+               else
                        double := B*2
                        print "double", B, "is", double
 
                a : number
                a = A;
                b:number = B
                        double := B*2
                        print "double", B, "is", double
 
                a : number
                a = A;
                b:number = B
+               print "still", bigger // check for regression in scoping
                if a > 0 and b > 0:
                        while a != b:
                                if a < b:
                                        b = b - a
                if a > 0 and b > 0:
                        while a != b:
                                if a < b:
                                        b = b - a
-                               else:
+                               else
                                        a = a - b
                        print "GCD of", A, "and", B,"is", a
                else if a <= 0:
                        print a, "is not positive, cannot calculate GCD"
                                        a = a - b
                        print "GCD of", A, "and", B,"is", a
                else if a <= 0:
                        print a, "is not positive, cannot calculate GCD"
-               else:
+               else
                        print b, "is not positive, cannot calculate GCD"
 
                        print b, "is not positive, cannot calculate GCD"
 
-               for:
+               for
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
@@ -331,34 +358,36 @@ Here I break it into two parts, keeping the array code separate.
 
                if bbool:
                        print astr ++ " was the str"
 
                if bbool:
                        print astr ++ " was the str"
-               else:
+               else
                        print "I found the str over " ++ astr
 
                /* Binary search... */
                        print "I found the str over " ++ astr
 
                /* Binary search... */
-               for:
+               for
                        lo:= 0; hi := 100
                        target := 77
                        lo:= 0; hi := 100
                        target := 77
-               while:
+               while
                        mid := (lo + hi) / 2
                        if mid == target:
                                use Found
                        if mid < target:
                                lo = mid
                        mid := (lo + hi) / 2
                        if mid == target:
                                use Found
                        if mid < target:
                                lo = mid
-                       else:
+                       else
                                hi = mid
                        if hi - lo < 1:
                                hi = mid
                        if hi - lo < 1:
+                               lo = mid
                                use GiveUp
                        use True
                                use GiveUp
                        use True
-               do: pass
+               do pass
                case Found:
                        print "Yay, I found", target
                case GiveUp:
                case Found:
                        print "Yay, I found", target
                case GiveUp:
-                       print "Closest I found was", mid
+                       print "Closest I found was", lo
 
 ###### output: sayhello,55,33,hello,True
        Hello World, what lovely oceans you have!
        Is 55 bigger than 33 ?  yes
        double 33 is 66
 
 ###### output: sayhello,55,33,hello,True
        Hello World, what lovely oceans you have!
        Is 55 bigger than 33 ?  yes
        double 33 is 66
+       still yes
        GCD of 55 and 33 is 11
        Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
        hello was the str
        GCD of 55 and 33 is 11
        Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
        hello was the str
@@ -368,6 +397,7 @@ Here I break it into two parts, keeping the array code separate.
        Hello World, what lovely oceans you have!
        Is 12 bigger than 60 ?  no
        double 60 is 120
        Hello World, what lovely oceans you have!
        Is 12 bigger than 60 ?  no
        double 60 is 120
+       still no
        GCD of 12 and 60 is 12
        Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
        I found the str over there
        GCD of 12 and 60 is 12
        Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
        I found the str over there
@@ -376,7 +406,7 @@ Here I break it into two parts, keeping the array code separate.
 ###### test list
        oceani_tests += "insert_sort"
 ###### test: insert_sort
 ###### test list
        oceani_tests += "insert_sort"
 ###### test: insert_sort
-       program:
+       func main()
                size::=55
                list:[size]number
                list[0] = 1_234
                size::=55
                list:[size]number
                list[0] = 1_234
@@ -522,7 +552,7 @@ ad-hoc things array related.
 
 ###### test: arrays
 
 
 ###### test: arrays
 
-       program:
+       func main()
                bools:[5]Boolean
                strings:[4]string
 
                bools:[5]Boolean
                strings:[4]string
 
@@ -530,11 +560,15 @@ ad-hoc things array related.
                bools[1] = strings[2] <= "there"
 
                for i:=0; then i=i+1; while i<5:
                bools[1] = strings[2] <= "there"
 
                for i:=0; then i=i+1; while i<5:
-                       print '', bools[i],
+                       j ::= i
+                       ra:[j]number
+                       ra[i-1] = i*i
+                       ra[6] = 42 // mustn't crash
+                       print '', bools[i], ra[j-1],
                print
 
 ###### output: arrays
                print
 
 ###### output: arrays
-        False True False False False
+        False 0 True 1 False 4 False 9 False 16
 
 ## Structures
 
 
 ## Structures
 
@@ -545,14 +579,16 @@ Time to test if structure declarations and accesses work correctly.
 
 ###### test: structs
 
 
 ###### test: structs
 
-       struct foo:
-               size:[3]number
+       const three ::= 3
+       struct foo
+               size:[three]number
                name:string
                name:string
-               active:Boolean
+               active:Boolean = True
 
        struct baz { a:number; b:Boolean; }
 
 
        struct baz { a:number; b:Boolean; }
 
-       program:
+       func main
+       do
                info:[4]foo
 
                for i:=0; then i=i+1; while i < 4:
                info:[4]foo
 
                for i:=0; then i=i+1; while i < 4:
@@ -560,11 +596,12 @@ Time to test if structure declarations and accesses work correctly.
                        case 2: nm:= "peter"
                        case 0: nm:= "bob"
                        case 1: nm:= "jane"
                        case 2: nm:= "peter"
                        case 0: nm:= "bob"
                        case 1: nm:= "jane"
-                       else: nm:= "janine"
+                       else    nm:= "janine"
 
                        info[i].name = nm
                        info[i].size[0] = i*i
 
                        info[i].name = nm
                        info[i].size[0] = i*i
-                       info[i].active = nm == "jane"
+                       if nm != "jane":
+                               info[i].active = False
 
                for i:=0; then i=i+1; while i < 4:
                        print info[i].name, info[i].active, info[i].size[0]
 
                for i:=0; then i=i+1; while i < 4:
                        print info[i].name, info[i].active, info[i].size[0]
@@ -612,14 +649,14 @@ separate file first, then run from there.
 
 ###### test: syn1
 
 
 ###### test: syn1
 
-       program:
+       func main()
                if then else while do
 
 ###### output: syn1
        .tmp.code:3:11: Syntax error in statement: then
 
 ###### test: tokerr
                if then else while do
 
 ###### output: syn1
        .tmp.code:3:11: Syntax error in statement: then
 
 ###### test: tokerr
-       program:
+       func main()
                a := 1i  // imaginary numbers aren't understood
                b:[2i]number // array sizes are handled separately
                c:[3.14159]Boolean // array sizes must be integers
                a := 1i  // imaginary numbers aren't understood
                b:[2i]number // array sizes are handled separately
                c:[3.14159]Boolean // array sizes must be integers
@@ -669,7 +706,7 @@ various places that `type_err()` are called.
 
 ###### test: type_err1
 
 
 ###### test: type_err1
 
-       program:
+       func main()
                print "hello" ++ 5, 5 ++ "hello"
 
                b ::= 3
                print "hello" ++ 5, 5 ++ "hello"
 
                b ::= 3
@@ -689,7 +726,7 @@ various places that `type_err()` are called.
 
 ###### test: type_err2
 
 
 ###### test: type_err2
 
-       program:
+       func main()
                a := 1
                a := 2
                a ::= 3
                a := 1
                a := 2
                a ::= 3
@@ -710,11 +747,11 @@ various places that `type_err()` are called.
 
 ###### test: type_err3
 
 
 ###### test: type_err3
 
-       struct foo:
+       struct foo
                a: number
                b:string = "hello"
 
                a: number
                b:string = "hello"
 
-       program:
+       func main()
                c := "hello"
                c = c + 1
                c = "hello" ++ (True and False)
                c := "hello"
                c = c + 1
                c = "hello" ++ (True and False)
@@ -722,11 +759,11 @@ various places that `type_err()` are called.
                print 45 + ( "Hello" ++ "there")
                c[5] = 1
 
                print 45 + ( "Hello" ++ "there")
                c[5] = 1
 
-               while:
+               while
                        use 1
                        use True
                        use "Hello"
                        use 1
                        use True
                        use "Hello"
-               do:
+               do
                        print
                case 1: print "one"
                case "Hello": print "Hello"
                        print
                case 1: print "one"
                case "Hello": print "Hello"
@@ -742,6 +779,14 @@ various places that `type_err()` are called.
                bar:foo
                foo.c = 43
                print c.foo
                bar:foo
                foo.c = 43
                print c.foo
+               print bar.c
+               print bar.b + 42
+               
+
+               // trigger 'labels not permitted' error message
+               while 1 if True else False:
+                       print
+               case 2: print "two"
 
 ###### output: type_err3
        .tmp.code:8:12: error: expected number but variable 'c' is string
 
 ###### output: type_err3
        .tmp.code:8:12: error: expected number but variable 'c' is string
@@ -771,10 +816,13 @@ various places that `type_err()` are called.
        .tmp.code:32:8: error: field reference attempted on none, not a struct
        .tmp.code:32:16: error: expected none found number
        .tmp.code:33:14: error: field reference attempted on string, not a struct
        .tmp.code:32:8: error: field reference attempted on none, not a struct
        .tmp.code:32:16: error: expected none found number
        .tmp.code:33:14: error: field reference attempted on string, not a struct
+       .tmp.code:34:14: error: cannot find requested field in foo
+       .tmp.code:35:17: error: have string but need number
+       .tmp.code:39:29: error: expected number (labels not permitted) found Boolean
        oceani: type error in program - not running.
 
 ###### test: type_err4
        oceani: type error in program - not running.
 
 ###### test: type_err4
-       program:
+       func main()
                a:=1; b=2; c::=3
                print a, b, c
 
                a:=1; b=2; c::=3
                print a, b, c
 
@@ -785,30 +833,38 @@ various places that `type_err()` are called.
        oceani: type error in program - not running.
 
 ###### test list
        oceani: type error in program - not running.
 
 ###### test list
-       oceani_failing_tests += type_err_const type_err_const1
+       oceani_failing_tests += type_err_const type_err_const1 missing_program
 
 ###### test: type_err_const
 
 ###### test: type_err_const
-       const:
+       const
                foo :: number = 45
                bar ::= "string" + 56
                foo :: number = 45
                bar ::= "string" + 56
-       const:
+       const
                bar ::= "baz"
                bar ::= "baz"
-       program:
+       func main()
                foo := 4
                print foo, bar
 
                foo := 4
                print foo, bar
 
+       // trigger duplicate-main error
+       func main()
+               foo := 6
+               print bar, foo
+
 ###### output: type_err_const
        .tmp.code:4:16: error: expected number found string
        .tmp.code:6:8: error: name already declared: bar
        .tmp.code:4:8: info: this is where 'bar' was first declared
        .tmp.code:8:8: error: variable 'foo' redeclared
        .tmp.code:3:8: info: this is where 'foo' was first declared
 ###### output: type_err_const
        .tmp.code:4:16: error: expected number found string
        .tmp.code:6:8: error: name already declared: bar
        .tmp.code:4:8: info: this is where 'bar' was first declared
        .tmp.code:8:8: error: variable 'foo' redeclared
        .tmp.code:3:8: info: this is where 'foo' was first declared
+       .tmp.code:13:8: error: variable 'foo' redeclared
+       .tmp.code:3:8: info: this is where 'foo' was first declared
+       .tmp.code:13:8: "main" defined a second time
 
 ###### test: type_err_const1
 
 ###### test: type_err_const1
-       const:
+       const
                foo : number = 45
                bar := "string"
                foo : number = 45
                bar := "string"
-       program:
+       func main()
                foo := 4
                print foo, bar
 
                foo := 4
                print foo, bar
 
@@ -816,6 +872,13 @@ various places that `type_err()` are called.
        .tmp.code:3:12: Syntax error in constant: :
        .tmp.code:4:12: Syntax error in constant: :
 
        .tmp.code:3:12: Syntax error in constant: :
        .tmp.code:4:12: Syntax error in constant: :
 
+###### test: missing_program
+       const
+               foo::="bar"
+
+###### output: missing_program
+       oceani: no main function found.
+
 ## Test erroneous command line args
 
 To improve coverage, we want to test correct handling of strange command
 ## Test erroneous command line args
 
 To improve coverage, we want to test correct handling of strange command
@@ -850,7 +913,7 @@ command list possible.
 
 ###### output: cmd,-zyx
        ./oceani: invalid option -- 'z'
 
 ###### output: cmd,-zyx
        ./oceani: invalid option -- 'z'
-       Usage: oceani --trace --print --noexec --brackets--section=SectionName prog.ocn
+       Usage: oceani --trace --print --noexec --brackets --section=SectionName prog.ocn
 
 ###### output: cmd,nofile
        oceani: cannot open nofile
 
 ###### output: cmd,nofile
        oceani: cannot open nofile