]> ocean-lang.org Git - ocean/commitdiff
oceani: add the option for "const" sections
authorNeilBrown <neil@brown.name>
Mon, 13 May 2019 06:17:12 +0000 (16:17 +1000)
committerNeilBrown <neil@brown.name>
Mon, 13 May 2019 06:17:12 +0000 (16:17 +1000)
These are introduced with "const" and can define one or
more constants - on one line with ';' or multiple lines
with {} or :

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

index a41b199d0cb6e14e2d839b821714f8325c45e88f..10a3b709daa49c5bc92122ee1d3eb0820561b285 100644 (file)
@@ -131,6 +131,29 @@ Next we change the value of variables
 ###### output: setvar
        1.07374e+09 1
 
+Now some contants
+
+###### test list
+       oceani_tests += "consts"
+
+###### test: consts
+       const:
+               pi ::= 3.1415926
+               four ::= 2 + 2 ; five ::= 10/2
+       const pie ::= "I like Pie";
+               cake ::= "The cake is"
+                 ++ " a lie"
+
+       program:
+               print "Hello World, what lovely oceans you have!"
+               print "are there", five, "?"
+               print pi, pie, "but", cake
+
+###### output: consts
+       Hello World, what lovely oceans you have!
+       are there 5 ?
+       3.14159 I like Pie but The cake is a lie
+
 ## Conditions and Loops
 
 Now we need to test if/else and some different loops
@@ -646,6 +669,39 @@ various places that `type_err()` are called.
        .tmp.code:3:14: info: this is where 'b' was set to label
        oceani: type error in program - not running.
 
+###### test list
+       oceani_failing_tests += type_err_const type_err_const1
+
+###### test: type_err_const
+       const:
+               foo :: number = 45
+               bar ::= "string" + 56
+       const:
+               bar ::= "baz"
+       program:
+               foo := 4
+               print foo, bar
+
+###### 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
+
+###### test: type_err_const1
+       const:
+               foo : number = 45
+               bar := "string"
+       program:
+               foo := 4
+               print foo, bar
+
+###### output: type_err_const1
+       .tmp.code:3:12: error: unhandled parse error: :
+       oceani: no program found.
+
+
 ## Test erroneous command line args
 
 To improve coverage, we want to test correct handling of strange command
index 48ce0587b4491fa2adc4e7f054d13a9cce6bc745..58d5d32009f297102359c4feabeed21c7ea4f15f 100644 (file)
@@ -1081,6 +1081,8 @@ no longer be primary.
 
                        v = t->previous;
                        free_value(t->val);
+                       if (t->min_depth == 0)
+                               free_exec(t->where_decl);
                        free(t);
                }
        }
@@ -3574,6 +3576,73 @@ various declarations in the parse context.
 
        ## top level grammar
 
+### The `const` section
+
+As well as being defined in with the code that uses them, constants
+can be declared at the top level.  These have full-file scope, so they
+are always `InScope`.  The value of a top level constant can be given
+as an expression, and this is evaluated immediately rather than in the
+later interpretation stage.  Once we add functions to the language, we
+will need rules concern which, if any, can be used to define a top
+level constant.
+
+Constants are defined in a sectiont that starts with the reserved word
+`const` and then has a block with a list of assignment statements.
+For syntactic consistency, these must use the double-colon syntax to
+make it clear that they are constants.  Type can also be given: if
+not, the type will be determined during analysis, as with other
+constants.
+
+###### top level grammar
+
+       DeclareConstant -> const Open ConstList Close
+               | const Open Newlines ConstList Close
+               | const Open SimpleConstList }
+               | const Open Newlines SimpleConstList }
+               | const : ConstList
+               | const SimpleConstList
+
+       ConstList -> ComplexConsts
+       ComplexConsts -> ComplexConst ComplexConsts
+               | ComplexConst
+       ComplexConst -> SimpleConstList NEWLINE
+       SimpleConstList -> Const ; SimpleConstList
+               | Const
+               | Const ; SimpleConstList ;
+
+       $*type
+       CType -> Type   ${ $0 = $<1; }$
+               |       ${ $0 = NULL; }$
+       $void
+       Const -> IDENTIFIER :: CType = Expression ${ {
+               int ok;
+               struct variable *v;
+
+               v = var_decl(config2context(config), $1.txt);
+               if (v) {
+                       struct var *var = new_pos(var, $1);
+                       v->where_decl = var;
+                       v->where_set = var;
+                       var->var = v;
+                       v->constant = 1;
+               } else {
+                       v = var_ref(config2context(config), $1.txt);
+                       tok_err(config2context(config), "error: name already declared", &$1);
+                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                                v->where_decl, NULL, 0, NULL);
+               }
+               do {
+                       ok = 1;
+                       propagate_types($5, config2context(config), &ok, $3, 0);
+               } while (ok == 2);
+               if (!ok)
+                       config2context(config)->parse_error = 1;
+               else if (v) {
+                       v->val = interp_exec($5);
+               }
+       } }$
+
+
 ### Finally the whole program.
 
 Somewhat reminiscent of Pascal a (current) Ocean program starts with
@@ -3735,8 +3804,18 @@ Fibonacci, and performs a binary search for a number.
 
 ###### test: hello
 
+       const:
+               pi ::= 3.1415926
+               four ::= 2 + 2 ; five ::= 10/2
+       const pie ::= "I like Pie";
+               cake ::= "The cake is"
+                 ++ " a lie"
+
        program A B:
                print "Hello World, what lovely oceans you have!"
+               print "are there", five, "?"
+               print pi, pie, "but", cake
+
                /* When a variable is defined in both branches of an 'if',
                 * and used afterwards, the variables are merged.
                 */