]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani-tests.mdc
oceani: propagate_type should return the found type, not what it was compatible with
[ocean] / csrc / oceani-tests.mdc
index d9be788450c88baf56d37a6e613b18fb31e88dff..1a36534abf4ba13b6079e4f80ecc22132ecc1b46 100644 (file)
@@ -35,6 +35,8 @@ arguments separated from the name by commas.  For each test, there is a section
 
        oceani_tests :=
        ## test list
 
        oceani_tests :=
        ## test list
+       oceani_valg_tests := $(oceani_tests)
+       ## combine test lists
 
        tests:: oceani_test_suite
        oceani_test_suite: oceani coverage_oceani
 
        tests:: oceani_test_suite
        oceani_test_suite: oceani coverage_oceani
@@ -78,17 +80,13 @@ arguments separated from the name by commas.  For each test, there is a section
                @for i in coverage/#*.gcda; do mv $$i coverage/$${i##*#}; done
                @gcov -o coverage oceani.mdc > /dev/null 2> /dev/null
                @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage || true
                @for i in coverage/#*.gcda; do mv $$i coverage/$${i##*#}; done
                @gcov -o coverage oceani.mdc > /dev/null 2> /dev/null
                @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage || true
-               @[ -n "$$SKIP_COVERAGE_CHECK" ] || awk '/NOTEST/ { next } /^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \
-                   END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \
-                        if (ran < (ran + skip) *0.968) exit(1) }' \
-                       coverage/oceani.mdc.gcov
                @rm -f .tmp*
 
                @rm -f .tmp*
 
-               @[ -n "$$SKIP_VALGRIND" ] || for T in $(oceani_tests); do \
+               @[ -n "$$SKIP_VALGRIND" ] || for T in $(oceani_valg_tests); do \
                    echo -n "Valgrind $$T.. "; \
                    i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \
                    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+"$$@"} \
-                        > /dev/null 2>&1 ; then \
+                   if valgrind --error-exitcode=42 --log-file=.tmp.valg ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \
+                        > /dev/null 2>&1 ; [ $$? -eq 42 ] ; then \
                       echo "FAILED"; cat .tmp.valg; exit 1; fi ; \
                    if grep 'LEAK SUMMARY' .tmp.valg > /dev/null; then \
                       echo "valgrind found LEAKS"; cat .tmp.valg ; exit 1 ; fi; \
                       echo "FAILED"; cat .tmp.valg; exit 1; fi ; \
                    if grep 'LEAK SUMMARY' .tmp.valg > /dev/null; then \
                       echo "valgrind found LEAKS"; cat .tmp.valg ; exit 1 ; fi; \
@@ -96,6 +94,11 @@ arguments separated from the name by commas.  For each test, there is a section
                       echo "valgrind found memory in use at exit"; cat .tmp.valg ; exit 1 ; fi; \
                    echo " passed"; \
                done
                       echo "valgrind found memory in use at exit"; cat .tmp.valg ; exit 1 ; fi; \
                    echo " passed"; \
                done
+               ## valgrind test code
+               @[ -n "$$SKIP_COVERAGE_CHECK" ] || awk '/NOTEST/ { next } /^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \
+                   END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \
+                        if (ran < (ran + skip) *0.972) exit(1) }' \
+                       coverage/oceani.mdc.gcov
 
        coverage_oceani: oceani.c
                $(CC) $(CFLAGS) --coverage -fprofile-dir=coverage -o coverage_oceani oceani.c $(LDLIBS)
 
        coverage_oceani: oceani.c
                $(CC) $(CFLAGS) --coverage -fprofile-dir=coverage -o coverage_oceani oceani.c $(LDLIBS)
@@ -131,14 +134,26 @@ calculations on them.
                  + b1
                  + b
 
                  + b1
                  + b
 
+               z:Boolean= True
+               w:Boolean = False
+               if ?z:
+                       print "w??z", w??z
+                       print "z??w", z??w
+                       print "z??False", z??False, "w??False", w??False
+               if ?w:
+                       print "Weird?"
+
 ###### output: valvar
 
 ###### output: valvar
 
-       23 12 35 11 276 1.91667 11
+       23 12 35 11 276 1.916666667 11
        False False True True False False True
        23 12 12 -23 -12 12
        False True True False False False
        This is a string  field theory This is a string field theory
        81
        False False True True False False True
        23 12 12 -23 -12 12
        False True True False False False
        This is a string  field theory This is a string field theory
        81
+       w??z True
+       z??w True
+       z??False True w??False False
 
 Next we change the value of variables
 
 
 Next we change the value of variables
 
@@ -155,7 +170,7 @@ Next we change the value of variables
                print a, a/a
 
 ###### output: setvar
                print a, a/a
 
 ###### output: setvar
-       1.07374e+09 1
+       1073741824 1
 
 Now some contants
 
 
 Now some contants
 
@@ -164,6 +179,7 @@ Now some contants
 
 ###### test: consts
        const
 
 ###### test: consts
        const
+               tau ::= pi * 2
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
@@ -173,12 +189,12 @@ Now some contants
        func main()
                print "Hello World, what lovely oceans you have!"
                print "are there", five, "?"
        func main()
                print "Hello World, what lovely oceans you have!"
                print "are there", five, "?"
-               print pi, pie, "but", cake
+               print pi, pie, "but", cake, "Tau is", tau
 
 ###### output: consts
        Hello World, what lovely oceans you have!
        are there 5 ?
 
 ###### output: consts
        Hello World, what lovely oceans you have!
        are there 5 ?
-       3.14159 I like Pie but The cake is a lie
+       3.141592653 I like Pie but The cake is a lie Tau is 6.283185306
 
 Test merging of variables from multiple cases
 
 
 Test merging of variables from multiple cases
 
@@ -277,13 +293,13 @@ Now we need to test if/else and some different loops
        Success
         1 2 4 8 16 32 64
        0 1.5
        Success
         1 2 4 8 16 32 64
        0 1.5
-       1 1.41667
-       2 1.41422
-       3 1.41421
-       error is  -4.51095e-12
+       1 1.416666667
+       2 1.414215686
+       3 1.414213562
+       error is  -4.510950445e-12
        I won't calculate 20 / 0
        I won't calculate 20 / 0
-       20 / 3  = 6.66667
-       20 / 6  = 3.33333
+       20 / 3  = 6.666666667
+       20 / 6  = 3.333333333
        I won't calculate 20 / 9
        Close enough
        higher
        I won't calculate 20 / 9
        Close enough
        higher
@@ -366,19 +382,19 @@ Here I break it into two parts, keeping the array code separate.
                while
                        mid := (lo + hi) / 2
                        if mid == target:
                while
                        mid := (lo + hi) / 2
                        if mid == target:
-                               use Found
+                               use .Found
                        if mid < target:
                                lo = mid
                        else
                                hi = mid
                        if hi - lo < 1:
                                lo = mid
                        if mid < target:
                                lo = mid
                        else
                                hi = mid
                        if hi - lo < 1:
                                lo = mid
-                               use GiveUp
+                               use .GiveUp
                        use True
                do pass
                        use True
                do pass
-               case Found:
+               case .Found:
                        print "Yay, I found", target
                        print "Yay, I found", target
-               case GiveUp:
+               case .GiveUp:
                        print "Closest I found was", lo
 
 ###### output: sayhello,55,33,hello,True
                        print "Closest I found was", lo
 
 ###### output: sayhello,55,33,hello,True
@@ -389,7 +405,7 @@ Here I break it into two parts, keeping the array code separate.
        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
-       Closest I found was 77.3438
+       Closest I found was 77.34375
 
 ###### output: sayhello,12,60,there,False
        Hello World, what lovely oceans you have!
 
 ###### output: sayhello,12,60,there,False
        Hello World, what lovely oceans you have!
@@ -399,7 +415,7 @@ Here I break it into two parts, keeping the array code separate.
        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
-       Closest I found was 77.3438
+       Closest I found was 77.34375
 
 ###### test list
        oceani_tests += "insert_sort"
 
 ###### test list
        oceani_tests += "insert_sort"
@@ -581,6 +597,7 @@ Time to test if structure declarations and accesses work correctly.
        struct foo
                size:[three]number
                name:string
        struct foo
                size:[three]number
                name:string
+               thing:baz
                active:Boolean = True
 
        struct baz { a:number; b:Boolean; }
                active:Boolean = True
 
        struct baz { a:number; b:Boolean; }
@@ -603,6 +620,7 @@ Time to test if structure declarations and accesses work correctly.
 
                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]
+               info[0].thing.b = True
 
 ###### output: structs
 
 
 ###### output: structs
 
@@ -616,11 +634,11 @@ Time to test if structure declarations and accesses work correctly.
 Test functions.  They don't return anything, so we need to get them to print
 
 ###### test list
 Test functions.  They don't return anything, so we need to get them to print
 
 ###### test list
-       oceani_tests += functions
+       oceani_tests += functions func_ret_type
 
 ###### test: functions
 
 
 ###### test: functions
 
-       func test1 then
+       func test1
                t: Boolean
        do
                if t:
                t: Boolean
        do
                if t:
@@ -630,15 +648,35 @@ Test functions.  They don't return anything, so we need to get them to print
        do
                pass
 
        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,
                        test(n-1, "."++s)
                else
                        print "done"
        func test(n:number; s:string)
                if n >= 1:
                        print n,s,
                        test(n-1, "."++s)
                else
                        print "done"
+
+       func to_polar
+               x:number; y:number
+       return
+               rho:number
+               theta:number
+       do
+               rho = x + y
+               theta = x - y
+
        func main()
                for i:=0; then i = i + 1; while i < 5:
                        test(i, " ")
        func main()
                for i:=0; then i = i + 1; while i < 5:
                        test(i, " ")
+               angular := to_polar(32, 23)
+               print angular.rho, angular.theta
 
 ###### output: functions
        done
 
 ###### output: functions
        done
@@ -646,6 +684,92 @@ Test functions.  They don't return anything, so we need to get them to print
        2  1 . done
        3  2 . 1 .. done
        4  3 . 2 .. 1 ... done
        2  1 . done
        3  2 . 1 .. done
        4  3 . 2 .. 1 ... done
+       55 9
+
+###### test: func_ret_type
+
+       func double(n:number):number
+               use n+n
+
+       func answer
+               prefix:string
+               suffix:string
+       return string
+       do
+               use prefix ++ suffix
+
+       func noarg_returns
+       return Boolean
+       do
+               use 22/7 == 3.14159
+
+       func main()
+               for j:=10; then j = j - 3; while j > -5:
+                       print answer("dou","ble"), j, "is", double(j)
+
+###### output: func_ret_type
+       double 10 is 20
+       double 7 is 14
+       double 4 is 8
+       double 1 is 2
+       double -2 is -4
+
+## References
+
+A simple linked list example
+
+###### test list
+       oceani_tests += "linked_list,one,two,three,four"
+
+###### test: linked_list
+
+       struct node
+               next: @node
+               this: string
+
+       func insert(list:@node; new:string):@node
+               p:=list
+               prev := @nil
+               while ?p and then p.this < new:
+                       prev = p
+                       p = p.next
+               if ?prev:
+                       prev.next = @new()
+                       prev.next.next = p
+                       prev.next.this = new
+               else
+                       list = @new()
+                       list.next = p
+                       list.this = new
+               use list
+
+       func printlist(list:@node)
+               while ?list:
+                       print list@.this
+                       list = list@.next
+
+       func freelist(list:@node)
+               if list != @nil:
+                       freelist(list.next)
+                       @free = list
+
+       func main(argv:[ac::]string)
+               list := insert(@nil, "@start")
+               list = insert(list, "~end")
+               for i:=1; then i=i+1; while i < ac:
+                       list = insert(list, argv[i])
+               list = insert(list, "Hello!")
+               printlist(list)
+               freelist(list)
+
+###### output: linked_list,one,two,three,four
+       @start
+       Hello!
+       four
+       one
+       three
+       two
+       ~end
 
 ## Test code with syntax errors
 
 
 ## Test code with syntax errors
 
@@ -677,6 +801,9 @@ separate file first, then run from there.
            ./coverage_oceani --section "test: $$t" oceani-tests.mdc > /dev/null 2>&1 ;\
        done || true
 
            ./coverage_oceani --section "test: $$t" oceani-tests.mdc > /dev/null 2>&1 ;\
        done || true
 
+###### combine test lists
+       oceani_valg_tests += $(oceani_failing_tests)
+
 ###### test list
        oceani_failing_tests := syn1
        oceani_failing_tests += tokerr
 ###### test list
        oceani_failing_tests := syn1
        oceani_failing_tests += tokerr
@@ -720,10 +847,10 @@ separate file first, then run from there.
                This is a multiline string
                With an unsupportable suffix
                """Aa
                This is a multiline string
                With an unsupportable suffix
                """Aa
-       .tmp.code:14:11: error: undefined type: unknown
        .tmp.code:15:12: error: name undeclared: unknowable
        .tmp.code:17:12: error: array size must be a constant: zzsize
        .tmp.code:20:12: error: unrecognised number: 00123
        .tmp.code:15:12: error: name undeclared: unknowable
        .tmp.code:17:12: error: array size must be a constant: zzsize
        .tmp.code:20:12: error: unrecognised number: 00123
+       .tmp.code:14:11: error: type used but not declared: unknown
 
 ## Tests for type errors
 
 
 ## Tests for type errors
 
@@ -736,7 +863,7 @@ These programs were generated by looking for the
 various places that `type_err()` are called.
 
 ###### test list
 various places that `type_err()` are called.
 
 ###### test list
-       oceani_failing_tests += type_err1 type_err2 type_err3 type_err4
+       oceani_failing_tests += type_err1 type_err2 type_err3 type_err4 type_err5 type_err6
 
 ###### test: type_err1
 
 
 ###### test: type_err1
 
@@ -747,15 +874,18 @@ various places that `type_err()` are called.
                b = b + 1
 
                if 3 * 4 and not True: print "Weird"
                b = b + 1
 
                if 3 * 4 and not True: print "Weird"
+               d:number = .fred
+               (d + b) = 12
 
 ###### output: type_err1
        .tmp.code:3:25: error: expected string found number
        .tmp.code:3:28: error: expected string found number
        .tmp.code:6:8: error: Cannot assign to a constant: b
        .tmp.code:5:8: info: name was defined as a constant here
 
 ###### output: type_err1
        .tmp.code:3:25: error: expected string found number
        .tmp.code:3:28: error: expected string found number
        .tmp.code:6:8: error: Cannot assign to a constant: b
        .tmp.code:5:8: info: name was defined as a constant here
-       .tmp.code:6:8: error: Cannot assign to a constant: b
-       .tmp.code:5:8: info: name was defined as a constant here
        .tmp.code:8:11: error: Arithmetic returns number but Boolean expected
        .tmp.code:8:11: error: Arithmetic returns number but Boolean expected
+       .tmp.code:9:20: error: expected number found label
+       .tmp.code:9:8: info: variable 'd' was set as number here.
+       .tmp.code:10:8: error: cannot assign to an rval
        oceani: type error in program - not running.
 
 ###### test: type_err2
        oceani: type error in program - not running.
 
 ###### test: type_err2
@@ -815,7 +945,6 @@ various places that `type_err()` are called.
                print c.foo
                print bar.c
                print bar.b + 42
                print c.foo
                print bar.c
                print bar.b + 42
-               
 
                // trigger 'labels not permitted' error message
                while 1 if True else False:
 
                // trigger 'labels not permitted' error message
                while 1 if True else False:
@@ -838,21 +967,23 @@ various places that `type_err()` are called.
        .tmp.code:24:8: error: cannot assign value of type [5]number
        .tmp.code:25:13: error: expected [5]number but variable 'a3' is [10]number
        .tmp.code:23:36: info: this is where 'a3' was set to [10]number
        .tmp.code:24:8: error: cannot assign value of type [5]number
        .tmp.code:25:13: error: expected [5]number but variable 'a3' is [10]number
        .tmp.code:23:36: info: this is where 'a3' was set to [10]number
+       .tmp.code:23:8: info: variable 'a1' was set as [5]number here.
        .tmp.code:25:8: error: cannot assign value of type [5]number
        .tmp.code:26:13: error: expected [5]number but variable 'a4' is [5]string
        .tmp.code:23:51: info: this is where 'a4' was set to [5]string
        .tmp.code:25:8: error: cannot assign value of type [5]number
        .tmp.code:26:13: error: expected [5]number but variable 'a4' is [5]string
        .tmp.code:23:51: info: this is where 'a4' was set to [5]string
+       .tmp.code:23:8: info: variable 'a1' was set as [5]number here.
        .tmp.code:26:8: error: cannot assign value of type [5]number
        .tmp.code:27:16: error: expected number found string
        .tmp.code:28:16: error: expected string found Boolean
        .tmp.code:29:12: error: have number but need string
        .tmp.code:7:8: info: variable 'c' was set as string here.
        .tmp.code:32:8: error: variable used but not declared: foo
        .tmp.code:26:8: error: cannot assign value of type [5]number
        .tmp.code:27:16: error: expected number found string
        .tmp.code:28:16: error: expected string found Boolean
        .tmp.code:29:12: error: have number but need string
        .tmp.code:7:8: info: variable 'c' was set as string here.
        .tmp.code:32:8: error: variable used but not declared: foo
-       .tmp.code:32:8: error: field reference attempted on none, not a struct
+       .tmp.code:32:8: error: field reference on none is not supported
        .tmp.code:32:16: error: expected none found number
        .tmp.code:32:16: error: expected none found number
-       .tmp.code:33:14: error: field reference attempted on string, not a struct
+       .tmp.code:33:14: error: field reference on string is not supported
        .tmp.code:34:14: error: cannot find requested field in foo
        .tmp.code:35:17: error: have string but need number
        .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
+       .tmp.code:38:29: error: expected number found Boolean
        oceani: type error in program - not running.
 
 ###### test: type_err4
        oceani: type error in program - not running.
 
 ###### test: type_err4
@@ -866,8 +997,38 @@ various places that `type_err()` are called.
        .tmp.code:3:14: info: variable 'b' was set as none here.
        oceani: type error in program - not running.
 
        .tmp.code:3:14: info: variable 'b' was set as none here.
        oceani: type error in program - not running.
 
+###### test: type_err5
+       struct foo
+               bar:baz
+               a:number
+       struct baz
+               bat:foo
+               b:string
+       struct foo
+               c:number
+
+###### output: type_err5
+       .tmp.code:8:7: error: type already declared: foo
+       .tmp.code:2:7: info: this is location of declartion: foo
+       .tmp.code:2:7: error: type has recursive definition: foo
+       .tmp.code:5:7: error: type has recursive definition: baz
+
+###### test: type_err6
+
+       func main()
+               a:= "hello"
+               if ?a:
+                       print "no"
+               print a ?? "there"
+
+###### output: type_err6
+       .tmp.code:4:12: error: '?' requires a testable value, not string
+       .tmp.code:6:14: error: "??" requires a testable value, not string
+       oceani: type error in program - not running.
+
+
 ###### test list
 ###### test list
-       oceani_failing_tests += type_err_const type_err_const1 missing_program bad_main
+       oceani_failing_tests += type_err_const type_err_const1 type_err_const2 missing_program bad_main
 
 ###### test: type_err_const
        const
 
 ###### test: type_err_const
        const
@@ -885,7 +1046,6 @@ various places that `type_err()` are called.
                print bar, foo
 
 ###### output: type_err_const
                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: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
@@ -894,6 +1054,7 @@ various places that `type_err()` are called.
        .tmp.code:7:5: info: this is where 'main' 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:7:5: info: this is where 'main' 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:4:16: error: expected number found string
 
 ###### test: type_err_const1
        const
 
 ###### test: type_err_const1
        const
@@ -907,6 +1068,15 @@ 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: type_err_const2
+       const
+               four ::= two + two
+               two ::= four / 2
+       
+###### output: type_err_const2
+       .tmp.code:3:8: error: const four cannot be resolved.
+       .tmp.code:4:8: error: const two cannot be resolved.
+
 ###### test: missing_program
        const
                foo::="bar"
 ###### test: missing_program
        const
                foo::="bar"
@@ -919,8 +1089,8 @@ various places that `type_err()` are called.
                print foo
 
 ###### output: bad_main
                print foo
 
 ###### output: bad_main
-       .tmp.code:??:??: error: expected  argv but variable 'foo' is string
-       .tmp.code:??:??: info: this is where 'NOTVAR' was set to string
+       .tmp.code:2:10: error: expected []string but variable 'foo' is string
+       .tmp.code:2:10: info: this is where 'foo' was set to string
        oceani: main has wrong type.
 
 Test for type errors with functions
        oceani: main has wrong type.
 
 Test for type errors with functions
@@ -936,6 +1106,10 @@ Test for type errors with functions
        func test2(a:number; b:string; c:[3]Boolean)
                print a, b, c[1]
 
        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
        func main()
                truth:[3]Boolean
                truth[1] = True
@@ -948,18 +1122,38 @@ Test for type errors with functions
                if test1 == test2:
                        pass
 
                if test1 == test2:
                        pass
 
+       func test4(a:number):string
+               use a * a
+
+       func test5(a:number):string
+               print a
+
+       struct foo
+               a: number
+               b:string = "hello"
+
+       func test6(a:number):foo
+               b:foo
+               b.a = a
+               use b
+
 ###### output: func_err_args
 ###### 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:??:??: info: this is where 'NOTVAR' was set to  func
+       .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: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 test1" but variable 'test2' is "func test2"
+       .tmp.code:5:5: info: this is where 'test2' was set to "func test2"
+       .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
        oceani: type error in program - not running.
 
 ###### test: func_err_redeclare
@@ -971,7 +1165,7 @@ Test for type errors with functions
        do
                pass
 
        do
                pass
 
-       func test1 then
+       func test1
                b:Boolean
        do
                pass
                b:Boolean
        do
                pass
@@ -982,6 +1176,47 @@ Test for type errors with functions
        .tmp.code:9:5: error: function 'test1' redeclared
        .tmp.code:2:5: info: this is where 'test1' was first declared
 
        .tmp.code:9:5: error: function 'test1' redeclared
        .tmp.code:2:5: info: this is where 'test1' was first declared
 
+Test for errors with references
+
+###### test list
+       oceani_failing_tests += ref_err1 ref_err2
+
+###### test: ref_err1
+       func main()
+               ref:@number
+               @foo = ref
+               ref = @old()
+               if ref == @null:
+                       print "null"
+
+###### output: ref_err1
+       .tmp.code:4:9: error: only "@free" makes sense here: foo
+       .tmp.code:5:15: error: Only reference function is "@new()": old
+       .tmp.code:6:19: error: Only reference value is "@nil": null
+
+###### test: ref_err2
+       func main()
+               ref:@number
+               ref2:@string
+               num:number = @new()
+               print num@
+               if num == @nil or ref == ref2 or ref == 2 or ref.foo:
+                       @free = num
+
+###### output: ref_err2
+       .tmp.code:5:22: error: @new() can only be used with references, not number
+       .tmp.code:5:8: info: variable 'num' was set as number here.
+       .tmp.code:6:14: error: Cannot dereference number
+       .tmp.code:7:19: error: @nil can only be used with reference, not number
+       .tmp.code:7:33: error: expected @number but variable 'ref2' is @string
+       .tmp.code:4:8: info: this is where 'ref2' was set to @string
+       .tmp.code:7:48: error: expected @number found number
+       .tmp.code:7:53: error: field reference on number is not supported
+       .tmp.code:7:56: error: have none but need Boolean
+       .tmp.code:8:17: error: @free can only be assigned a reference, not number
+       .tmp.code:8:17: error: @free can only be assigned a reference, not number
+       oceani: type error in program - not running.
+
 ## 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
@@ -1003,6 +1238,19 @@ command list possible.
            echo  "passed"; \
            ./coverage_oceani $${1+"$$@"} > /dev/null 2>&1 ;\
        done || true
            echo  "passed"; \
            ./coverage_oceani $${1+"$$@"} > /dev/null 2>&1 ;\
        done || true
+###### valgrind test code
+       @[ -n "$$SKIP_VALGRIND" ] || for t in $(oceani_special_tests); do\
+           echo -n "Valgrind $$t.. "; \
+           i="$$IFS"; IFS=,; set $$t; IFS="$$i"; shift ;\
+           if valgrind --error-exitcode=42 --log-file=.tmp.valg ./oceani $${1+"$$@"} > .tmp.have 2>&1 ;\
+              [ $$? -eq 42 ]; then \
+                      echo "FAILED"; cat .tmp.valg; exit 1; fi ; \
+           if grep 'LEAK SUMMARY' .tmp.valg > /dev/null; then \
+              echo "valgrind found LEAKS"; cat .tmp.valg ; exit 1 ; fi; \
+           if grep 'in use at exit [1-9]' .tmp.valg > /dev/null; then \
+              echo "valgrind found memory in use at exit"; cat .tmp.valg ; exit 1 ; fi; \
+           echo " passed"; \
+       done
 
 ###### test list
        oceani_special_tests += "cmd"
 
 ###### test list
        oceani_special_tests += "cmd"