X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=7371535bf7c555ec127028eb89f3113901be0561;hp=3befc631dbf4ce72dd2adf34517a0deaeeb97c9d;hb=57c69adf13069b9daf3ed59f4401f16de3312975;hpb=2193e1c775bee42588715d13076496c8f8f2974a diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 3befc63..7371535 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -130,7 +130,7 @@ structures can be used. struct parse_context *c = config2context(config); ###### Parser: code - + #define _GNU_SOURCE #include #include #include @@ -763,6 +763,10 @@ have not yet been implemented. Named type are stored in a simple linked list. Objects of each type are "values" which are often passed around by value. +There are both explicitly named types, and anonymous types. Anonymous +cannot be accessed by name, but are used internally and have a name +which might be reported in error messages. + ###### ast struct value { @@ -776,6 +780,7 @@ Named type are stored in a simple linked list. Objects of each type are struct text name; struct type *next; int size, align; + int anon; void (*init)(struct type *type, struct value *val); void (*prepare_type)(struct parse_context *c, struct type *type, int parse_time); void (*print)(struct type *type, struct value *val, FILE *f); @@ -800,31 +805,54 @@ Named type are stored in a simple linked list. Objects of each type are struct type *typelist; +###### includes + #include + ###### ast functions static struct type *find_type(struct parse_context *c, struct text s) { - struct type *l = c->typelist; + struct type *t = c->typelist; - while (l && - text_cmp(l->name, s) != 0) - l = l->next; - return l; + while (t && (t->anon || + text_cmp(t->name, s) != 0)) + t = t->next; + return t; } - static struct type *add_type(struct parse_context *c, struct text s, - struct type *proto) + static struct type *_add_type(struct parse_context *c, struct text s, + struct type *proto, int anon) { struct type *n; n = calloc(1, sizeof(*n)); *n = *proto; n->name = s; + n->anon = anon; n->next = c->typelist; c->typelist = n; return n; } + static struct type *add_type(struct parse_context *c, struct text s, + struct type *proto) + { + return _add_type(c, s, proto, 0); + } + + static struct type *add_anon_type(struct parse_context *c, + struct type *proto, char *name, ...) + { + struct text t; + va_list ap; + + va_start(ap, name); + vasprintf(&t.txt, name, ap); + va_end(ap); + t.len = strlen(name); + return _add_type(c, t, proto, 1); + } + static void free_type(struct type *t) { /* The type is always a reference to something in the @@ -844,12 +872,12 @@ Named type are stored in a simple linked list. Objects of each type are { if (!type) fputs("*unknown*type*", f); // NOTEST - else if (type->name.len) + else if (type->name.len && !type->anon) fprintf(f, "%.*s", type->name.len, type->name.txt); else if (type->print_type) type->print_type(type, f); else - fputs("*invalid*type*", f); // NOTEST + fputs("*invalid*type*", f); } static void val_init(struct type *type, struct value *val) @@ -903,6 +931,8 @@ Named type are stored in a simple linked list. Objects of each type are context.typelist = t->next; if (t->free_type) t->free_type(t); + if (t->anon) + free(t->name.txt); free(t); } @@ -1155,44 +1185,38 @@ executable. $*val Value -> True ${ - $0 = new_val(Tbool, $1); - $0->val.bool = 1; - }$ - | False ${ - $0 = new_val(Tbool, $1); - $0->val.bool = 0; - }$ - | NUMBER ${ - $0 = new_val(Tnum, $1); - { - char tail[3]; - if (number_parse($0->val.num, tail, $1.txt) == 0) - mpq_init($0->val.num); // UNTESTED - if (tail[0]) - tok_err(c, "error: unsupported number suffix", - &$1); - } - }$ - | STRING ${ - $0 = new_val(Tstr, $1); - { - char tail[3]; - string_parse(&$1, '\\', &$0->val.str, tail); - if (tail[0]) - tok_err(c, "error: unsupported string suffix", - &$1); - } - }$ - | MULTI_STRING ${ - $0 = new_val(Tstr, $1); - { - char tail[3]; - string_parse(&$1, '\\', &$0->val.str, tail); + $0 = new_val(Tbool, $1); + $0->val.bool = 1; + }$ + | False ${ + $0 = new_val(Tbool, $1); + $0->val.bool = 0; + }$ + | NUMBER ${ { + char tail[3]; + $0 = new_val(Tnum, $1); + if (number_parse($0->val.num, tail, $1.txt) == 0) + mpq_init($0->val.num); // UNTESTED if (tail[0]) - tok_err(c, "error: unsupported string suffix", + tok_err(c, "error: unsupported number suffix", &$1); - } - }$ + } }$ + | STRING ${ { + char tail[3]; + $0 = new_val(Tstr, $1); + string_parse(&$1, '\\', &$0->val.str, tail); + if (tail[0]) + tok_err(c, "error: unsupported string suffix", + &$1); + } }$ + | MULTI_STRING ${ { + char tail[3]; + $0 = new_val(Tstr, $1); + string_parse(&$1, '\\', &$0->val.str, tail); + if (tail[0]) + tok_err(c, "error: unsupported string suffix", + &$1); + } }$ ###### print exec cases case Xval: @@ -1969,7 +1993,7 @@ correctly. v->where_decl, NULL, 0, NULL); } } }$ - | IDENTIFIER :: ${ { + | IDENTIFIER :: ${ { struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; @@ -1985,7 +2009,7 @@ correctly. v->where_decl, NULL, 0, NULL); } } }$ - | IDENTIFIER : Type ${ { + | IDENTIFIER : Type ${ { struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; @@ -2003,7 +2027,7 @@ correctly. v->where_decl, NULL, 0, NULL); } } }$ - | IDENTIFIER :: Type ${ { + | IDENTIFIER :: Type ${ { struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; @@ -2037,7 +2061,7 @@ correctly. } } cast(var, $0)->var = v; - } }$ + } }$ ###### print exec cases case Xvar: @@ -2147,8 +2171,8 @@ simple "Value" (to be explained later). ###### Grammar $*exec Term -> Value ${ $0 = $<1; }$ - | Variable ${ $0 = $<1; }$ - ## term grammar + | Variable ${ $0 = $<1; }$ + ## term grammar Thus far the complex types we have are arrays and structs. @@ -2284,8 +2308,10 @@ with a const size by whether they are prepared at parse time or not. struct binding *b = type->array.vsize->name; fprintf(f, "%.*s%s]", b->name.len, b->name.txt, type->array.unspec ? "::" : ""); - } else + } else if (type->array.size) fprintf(f, "%d]", type->array.size); + else + fprintf(f, "]"); type_print(type->array.member, f); } @@ -2307,19 +2333,16 @@ with a const size by whether they are prepared at parse time or not. | [ NUMBER ] Type ${ { char tail[3]; mpq_t num; - struct text noname = { "", 0 }; struct type *t; + int elements = 0; - $0 = t = add_type(c, noname, &array_prototype); - t->array.member = $<4; - t->array.vsize = NULL; if (number_parse(num, tail, $2.txt) == 0) tok_err(c, "error: unrecognised number", &$2); else if (tail[0]) { tok_err(c, "error: unsupported number suffix", &$2); mpq_clear(num); } else { - t->array.size = mpz_get_ui(mpq_numref(num)); + elements = mpz_get_ui(mpq_numref(num)); if (mpz_cmp_ui(mpq_denref(num), 1) != 0) { tok_err(c, "error: array size must be an integer", &$2); @@ -2328,6 +2351,11 @@ with a const size by whether they are prepared at parse time or not. &$2); mpq_clear(num); } + + $0 = t = add_anon_type(c, &array_prototype, "array[%d]", elements ); + t->array.size = elements; + t->array.member = $<4; + t->array.vsize = NULL; t->array.static_size = 1; t->size = t->array.size * t->array.member->size; t->align = t->array.member->align; @@ -2335,14 +2363,13 @@ with a const size by whether they are prepared at parse time or not. | [ IDENTIFIER ] Type ${ { struct variable *v = var_ref(c, $2.txt); - struct text noname = { "", 0 }; if (!v) tok_err(c, "error: name undeclared", &$2); else if (!v->constant) tok_err(c, "error: array size must be a constant", &$2); - $0 = add_type(c, noname, &array_prototype); + $0 = add_anon_type(c, &array_prototype, "array[%.*s]", $2.txt.len, $2.txt.txt); $0->array.member = $<4; $0->array.size = 0; $0->array.vsize = v; @@ -2357,13 +2384,12 @@ with a const size by whether they are prepared at parse time or not. | [ IDENTIFIER :: OptType ] Type ${ { struct variable *v = var_decl(c, $ID.txt); - struct text noname = { "", 0 }; v->type = $constant = 1; if (!v->type) v->type = Tnum; - $0 = add_type(c, noname, &array_prototype); + $0 = add_anon_type(c, &array_prototype, "array[var]"); $0->array.member = $<6; $0->array.size = 0; $0->array.unspec = 1; @@ -2650,79 +2676,79 @@ function will be needed. ###### top level grammar DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ { - struct type *t = - add_type(c, $2.txt, &structure_prototype); - int cnt = 0; - struct fieldlist *f; - - for (f = $3; f; f=f->prev) - cnt += 1; - - t->structure.nfields = cnt; - t->structure.fields = calloc(cnt, sizeof(struct field)); - f = $3; - while (cnt > 0) { - int a = f->f.type->align; - cnt -= 1; - t->structure.fields[cnt] = f->f; - if (t->size & (a-1)) - t->size = (t->size | (a-1)) + 1; - t->structure.fields[cnt].offset = t->size; - t->size += ((f->f.type->size - 1) | (a-1)) + 1; - if (a > t->align) - t->align = a; - f->f.init = NULL; - f = f->prev; - } - } }$ + struct type *t = + add_type(c, $2.txt, &structure_prototype); + int cnt = 0; + struct fieldlist *f; + + for (f = $3; f; f=f->prev) + cnt += 1; + + t->structure.nfields = cnt; + t->structure.fields = calloc(cnt, sizeof(struct field)); + f = $3; + while (cnt > 0) { + int a = f->f.type->align; + cnt -= 1; + t->structure.fields[cnt] = f->f; + if (t->size & (a-1)) + t->size = (t->size | (a-1)) + 1; + t->structure.fields[cnt].offset = t->size; + t->size += ((f->f.type->size - 1) | (a-1)) + 1; + if (a > t->align) + t->align = a; + f->f.init = NULL; + f = f->prev; + } + } }$ $*fieldlist FieldBlock -> { IN OptNL FieldLines OUT OptNL } ${ $0 = $ SimpleFieldList Newlines ${ $0 = $prev = $prev = $ Field ${ $0 = $prev = $prev = $ IDENTIFIER : Type = Expression ${ { - int ok; + int ok; - $0 = calloc(1, sizeof(struct fieldlist)); - $0->f.name = $1.txt; - $0->f.type = $<3; - $0->f.init = NULL; - do { - ok = 1; - propagate_types($<5, c, &ok, $3, 0); - } while (ok == 2); - if (!ok) - c->parse_error = 1; // UNTESTED - else { - struct value vl = interp_exec(c, $5, NULL); - $0->f.init = global_alloc(c, $0->f.type, NULL, &vl); - } - } }$ - | IDENTIFIER : Type ${ - $0 = calloc(1, sizeof(struct fieldlist)); - $0->f.name = $1.txt; - $0->f.type = $<3; - if ($0->f.type->prepare_type) - $0->f.type->prepare_type(c, $0->f.type, 1); - }$ + $0 = calloc(1, sizeof(struct fieldlist)); + $0->f.name = $1.txt; + $0->f.type = $<3; + $0->f.init = NULL; + do { + ok = 1; + propagate_types($<5, c, &ok, $3, 0); + } while (ok == 2); + if (!ok) + c->parse_error = 1; // UNTESTED + else { + struct value vl = interp_exec(c, $5, NULL); + $0->f.init = global_alloc(c, $0->f.type, NULL, &vl); + } + } }$ + | IDENTIFIER : Type ${ + $0 = calloc(1, sizeof(struct fieldlist)); + $0->f.name = $1.txt; + $0->f.type = $<3; + if ($0->f.type->prepare_type) + $0->f.type->prepare_type(c, $0->f.type, 1); + }$ ###### forward decls static void structure_print_type(struct type *t, FILE *f); @@ -2758,7 +2784,8 @@ function will be needed. while (target != 0) { int i = 0; for (t = context.typelist; t ; t=t->next) - if (t->print_type_decl && !t->check_args && t->name.txt[0] != ' ') { + if (!t->anon && t->print_type_decl && + !t->check_args) { i += 1; if (i == target) break; @@ -2960,50 +2987,50 @@ further detailed when Expression Lists are introduced. $*variable FuncName -> IDENTIFIER ${ { - struct variable *v = var_decl(c, $1.txt); - struct var *e = new_pos(var, $1); + struct variable *v = var_decl(c, $1.txt); + struct var *e = new_pos(var, $1); + e->var = v; + if (v) { + v->where_decl = e; + $0 = v; + } else { + v = var_ref(c, $1.txt); e->var = v; - if (v) { - v->where_decl = e; - $0 = v; - } else { - v = var_ref(c, $1.txt); - e->var = v; - type_err(c, "error: function '%v' redeclared", - e, NULL, 0, NULL); - type_err(c, "info: this is where '%v' was first declared", - v->where_decl, NULL, 0, NULL); - free_exec(e); - } - } }$ + type_err(c, "error: function '%v' redeclared", + e, NULL, 0, NULL); + type_err(c, "info: this is where '%v' was first declared", + v->where_decl, NULL, 0, NULL); + free_exec(e); + } + } }$ $*binode Args -> ArgsLine NEWLINE ${ $0 = $left; - *bp = $left; + *bp = $ ${ $0 = NULL; }$ - | Varlist ${ $0 = $<1; }$ - | Varlist ; ${ $0 = $<1; }$ + | Varlist ${ $0 = $<1; }$ + | Varlist ; ${ $0 = $<1; }$ Varlist -> Varlist ; ArgDecl ${ - $0 = new(binode); - $0->op = List; - $0->left = $right = $op = List; - $0->left = NULL; - $0->right = $op = List; + $0->left = $right = $op = List; + $0->left = NULL; + $0->right = $ IDENTIFIER : FormalType ${ { @@ -3140,7 +3167,7 @@ Term - others will follow. $*exec Expression -> Term ${ $0 = $ ExpressionList , Expression ${ - $0 = new(binode); - $0->op = List; - $0->left = $<1; - $0->right = $<3; - }$ - | Expression ${ - $0 = new(binode); - $0->op = List; - $0->left = NULL; - $0->right = $<1; - }$ + $0 = new(binode); + $0->op = List; + $0->left = $<1; + $0->right = $<3; + }$ + | Expression ${ + $0 = new(binode); + $0->op = List; + $0->left = NULL; + $0->right = $<1; + }$ ### Expressions: Boolean @@ -3287,42 +3314,42 @@ evaluate the second expression if not necessary. $LEFT not ###### expression grammar - | Expression or Expression ${ { - struct binode *b = new(binode); - b->op = Or; - b->left = $<1; - b->right = $<3; - $0 = b; - } }$ - | Expression or else Expression ${ { - struct binode *b = new(binode); - b->op = OrElse; - b->left = $<1; - b->right = $<4; - $0 = b; - } }$ + | Expression or Expression ${ { + struct binode *b = new(binode); + b->op = Or; + b->left = $<1; + b->right = $<3; + $0 = b; + } }$ + | Expression or else Expression ${ { + struct binode *b = new(binode); + b->op = OrElse; + b->left = $<1; + b->right = $<4; + $0 = b; + } }$ - | Expression and Expression ${ { - struct binode *b = new(binode); - b->op = And; - b->left = $<1; - b->right = $<3; - $0 = b; - } }$ - | Expression and then Expression ${ { - struct binode *b = new(binode); - b->op = AndThen; - b->left = $<1; - b->right = $<4; - $0 = b; - } }$ + | Expression and Expression ${ { + struct binode *b = new(binode); + b->op = And; + b->left = $<1; + b->right = $<3; + $0 = b; + } }$ + | Expression and then Expression ${ { + struct binode *b = new(binode); + b->op = AndThen; + b->left = $<1; + b->right = $<4; + $0 = b; + } }$ - | not Expression ${ { - struct binode *b = new(binode); - b->op = Not; - b->right = $<2; - $0 = b; - } }$ + | not Expression ${ { + struct binode *b = new(binode); + b->op = Not; + b->right = $<2; + $0 = b; + } }$ ###### print binode cases case And: @@ -3444,12 +3471,12 @@ expression operator, and the `CMPop` non-terminal will match one of them. ###### Grammar $eop - CMPop -> < ${ $0.op = Less; }$ - | > ${ $0.op = Gtr; }$ - | <= ${ $0.op = LessEq; }$ - | >= ${ $0.op = GtrEq; }$ - | == ${ $0.op = Eql; }$ - | != ${ $0.op = NEql; }$ + CMPop -> < ${ $0.op = Less; }$ + | > ${ $0.op = Gtr; }$ + | <= ${ $0.op = LessEq; }$ + | >= ${ $0.op = GtrEq; }$ + | == ${ $0.op = Eql; }$ + | != ${ $0.op = NEql; }$ ###### print binode cases @@ -3589,17 +3616,17 @@ parentheses around an expression converts it into a Term, ###### Grammar $eop - Eop -> + ${ $0.op = Plus; }$ - | - ${ $0.op = Minus; }$ + Eop -> + ${ $0.op = Plus; }$ + | - ${ $0.op = Minus; }$ - Uop -> + ${ $0.op = Absolute; }$ - | - ${ $0.op = Negate; }$ - | $ ${ $0.op = StringConv; }$ + Uop -> + ${ $0.op = Absolute; }$ + | - ${ $0.op = Negate; }$ + | $ ${ $0.op = StringConv; }$ - Top -> * ${ $0.op = Times; }$ - | / ${ $0.op = Divide; }$ - | % ${ $0.op = Rem; }$ - | ++ ${ $0.op = Concat; }$ + Top -> * ${ $0.op = Times; }$ + | / ${ $0.op = Divide; }$ + | % ${ $0.op = Rem; }$ + | ++ ${ $0.op = Concat; }$ ###### print binode cases case Plus: @@ -3836,78 +3863,78 @@ the common header for all reductions to use. $*binode Block -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $ OpenScope { IN OptNL Statementlist OUT OptNL } ${ $0 = $ { OpenScope IN OptNL Statementlist OUT OptNL } ${ $0 = $ { IN OptNL Statementlist OUT OptNL } ${ $0 = $ ComplexStatements ${ $0 = reorder_bilist($ ComplexStatements ComplexStatement ${ - if ($2 == NULL) { - $0 = $<1; - } else { - $0 = new(binode); - $0->op = Block; - $0->left = $<1; - $0->right = $<2; - } - }$ - | ComplexStatement ${ - if ($1 == NULL) { - $0 = NULL; - } else { - $0 = new(binode); - $0->op = Block; - $0->left = NULL; - $0->right = $<1; - } - }$ - - $*exec - ComplexStatement -> SimpleStatements Newlines ${ - $0 = reorder_bilist($ SimpleStatements ; SimpleStatement ${ + if ($2 == NULL) { + $0 = $<1; + } else { $0 = new(binode); $0->op = Block; $0->left = $<1; - $0->right = $<3; - }$ - | SimpleStatement ${ + $0->right = $<2; + } + }$ + | ComplexStatement ${ + if ($1 == NULL) { + $0 = NULL; + } else { $0 = new(binode); $0->op = Block; $0->left = NULL; $0->right = $<1; - }$ + } + }$ + + $*exec + ComplexStatement -> SimpleStatements Newlines ${ + $0 = reorder_bilist($ SimpleStatements ; SimpleStatement ${ + $0 = new(binode); + $0->op = Block; + $0->left = $<1; + $0->right = $<3; + }$ + | SimpleStatement ${ + $0 = new(binode); + $0->op = Block; + $0->left = NULL; + $0->right = $<1; + }$ $TERM pass $*exec SimpleStatement -> pass ${ $0 = NULL; }$ - | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$ - ## SimpleStatement Grammar + | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$ + ## SimpleStatement Grammar ###### print binode cases case Block: @@ -4078,31 +4105,31 @@ it is declared, and error will be raised as the name is created as ###### SimpleStatement Grammar | Term = Expression ${ - $0 = b= new(binode); - b->op = Assign; - b->left = $<1; - b->right = $<3; - }$ + $0 = b= new(binode); + b->op = Assign; + b->left = $<1; + b->right = $<3; + }$ | VariableDecl = Expression ${ - $0 = b= new(binode); - b->op = Declare; - b->left = $<1; - b->right =$<3; - }$ + $0 = b= new(binode); + b->op = Declare; + b->left = $<1; + b->right =$<3; + }$ | VariableDecl ${ - if ($1->var->where_set == NULL) { - type_err(c, - "Variable declared with no type or value: %v", - $1, NULL, 0, NULL); - free_var($1); - } else { - $0 = b = new(binode); - b->op = Declare; - b->left = $<1; - b->right = NULL; - } - }$ + if ($1->var->where_set == NULL) { + type_err(c, + "Variable declared with no type or value: %v", + $1, NULL, 0, NULL); + free_var($1); + } else { + $0 = b = new(binode); + b->op = Declare; + b->left = $<1; + b->right = NULL; + } + }$ ###### print binode cases @@ -4387,136 +4414,136 @@ casepart` to track a list of case parts. // ForPart, SwitchPart, and IfPart open scopes, o we have to close // them. WhilePart opens and closes its own scope. CondStatement -> ForPart OptNL ThenPart OptNL WhilePart CondSuffix ${ - $0 = $forpart = $thenpart = $looppart = $forpart = $looppart = $looppart = $condpart = $next = $0->casepart; - $0->casepart = $condpart = $next = $0->casepart; - $0->casepart = $condpart = $IP.condpart; $IP.condpart = NULL; - $0->thenpart = $IP.thenpart; $IP.thenpart = NULL; - // This is where we close an "if" statement - var_block_close(c, CloseSequential, $0); - }$ + $0 = $forpart = $thenpart = $looppart = $forpart = $looppart = $looppart = $condpart = $next = $0->casepart; + $0->casepart = $condpart = $next = $0->casepart; + $0->casepart = $condpart = $IP.condpart; $IP.condpart = NULL; + $0->thenpart = $IP.thenpart; $IP.thenpart = NULL; + // This is where we close an "if" statement + var_block_close(c, CloseSequential, $0); + }$ CondSuffix -> IfSuffix ${ - $0 = $<1; - }$ - | Newlines CasePart CondSuffix ${ - $0 = $next = $0->casepart; - $0->casepart = $next = $0->casepart; - $0->casepart = $next = $0->casepart; + $0->casepart = $next = $0->casepart; + $0->casepart = $ Newlines ${ $0 = new(cond_statement); }$ - | Newlines ElsePart ${ $0 = $ else OpenBlock Newlines ${ - $0 = new(cond_statement); - $0->elsepart = $elsepart); - }$ - | else OpenScope CondStatement ${ - $0 = new(cond_statement); - $0->elsepart = $elsepart); - }$ + $0 = new(cond_statement); + $0->elsepart = $elsepart); + }$ + | else OpenScope CondStatement ${ + $0 = new(cond_statement); + $0->elsepart = $elsepart); + }$ $*casepart CasePart -> case Expression OpenScope ColonBlock ${ - $0 = calloc(1,sizeof(struct casepart)); - $0->value = $action = $action); - }$ + $0 = calloc(1,sizeof(struct casepart)); + $0->value = $action = $action); + }$ $*exec // These scopes are closed in CondStatement ForPart -> for OpenBlock ${ - $0 = $ then OpenBlock ${ - $0 = $ while UseBlock OptNL do OpenBlock ${ - $0 = new(binode); - $0->op = Loop; - $0->left = $right = $right); - var_block_close(c, CloseSequential, $0); - }$ - | while OpenScope Expression OpenScope ColonBlock ${ - $0 = new(binode); - $0->op = Loop; - $0->left = $right = $right); - var_block_close(c, CloseSequential, $0); - }$ + $0 = new(binode); + $0->op = Loop; + $0->left = $right = $right); + var_block_close(c, CloseSequential, $0); + }$ + | while OpenScope Expression OpenScope ColonBlock ${ + $0 = new(binode); + $0->op = Loop; + $0->left = $right = $right); + var_block_close(c, CloseSequential, $0); + }$ $cond_statement IfPart -> if UseBlock OptNL then OpenBlock ${ - $0.condpart = $ switch OpenScope Expression ${ - $0 = $ - | OptNL NEWLINE + | OptNL NEWLINE + Newlines -> NEWLINE - | Newlines NEWLINE + | Newlines NEWLINE DeclarationList -> Declaration - | DeclarationList Declaration + | DeclarationList Declaration Declaration -> ERROR Newlines ${ - tok_err(c, // UNTESTED - "error: unhandled parse error", &$1); - }$ - | DeclareConstant - | DeclareFunction - | DeclareStruct + tok_err(c, // UNTESTED + "error: unhandled parse error", &$1); + }$ + | DeclareConstant + | DeclareFunction + | DeclareStruct ## top level grammar @@ -4823,21 +4851,24 @@ searching through for the Nth constant for decreasing N. $TERM const DeclareConstant -> const { IN OptNL ConstList OUT OptNL } Newlines - | const { SimpleConstList } Newlines - | const IN OptNL ConstList OUT Newlines - | const SimpleConstList Newlines + | const { SimpleConstList } Newlines + | const IN OptNL ConstList OUT Newlines + | const SimpleConstList Newlines ConstList -> ConstList SimpleConstLine - | SimpleConstLine + | SimpleConstLine + SimpleConstList -> SimpleConstList ; Const - | Const - | SimpleConstList ; + | Const + | SimpleConstList ; + SimpleConstLine -> SimpleConstList Newlines - | ERROR Newlines ${ tok_err(c, "Syntax error in constant", &$1); }$ + | ERROR Newlines ${ tok_err(c, "Syntax error in constant", &$1); }$ $*type CType -> Type ${ $0 = $<1; }$ - | ${ $0 = NULL; }$ + | ${ $0 = NULL; }$ + $void Const -> IDENTIFIER :: CType = Expression ${ { int ok; @@ -4922,8 +4953,8 @@ is a bit more interesting at this level. /* Create a 'struct' type from the results list, which * is a list for 'struct var' */ - struct text result_type_name = { " function_result", 5 }; - struct type *t = add_type(c, result_type_name, &structure_prototype); + struct type *t = add_anon_type(c, &structure_prototype, + " function result"); int cnt = 0; struct binode *b; @@ -4957,12 +4988,13 @@ is a bit more interesting at this level. struct binode *results, struct exec *code) { - struct text funcname = {" func", 5}; if (name) { struct value fn = {.function = code}; struct type *t; var_block_close(c, CloseFunction, code); - t = add_type(c, funcname, &function_prototype); + t = add_anon_type(c, &function_prototype, + "func %.*s", name->name->name.len, + name->name->name.txt); name->type = t; t->function.params = reorder_bilist(args); if (!ret) { @@ -4990,32 +5022,32 @@ is a bit more interesting at this level. $*variable DeclareFunction -> func FuncName ( OpenScope ArgsLine ) Block Newlines ${ - $0 = declare_function(c, $array.member = Tstr; argv_type->array.unspec = 1;