X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=1ec640f1b4ed6520b17723d36d00d15c1e3a011d;hp=0f2174de2a8f05aae2f5c0f565df28a97c47785f;hb=5c455fe9ef93d88b349bb25733d5ea20a8984050;hpb=d445e961d9ca6d339f882607eb3685c78ed86f4a diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 0f2174d..1ec640f 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -367,14 +367,14 @@ context so indicate that parsing failed. static void fput_loc(struct exec *loc, FILE *f); static void type_err(struct parse_context *c, char *fmt, struct exec *loc, - struct type *t1, int rules, struct type *t2); + struct type *t1, enum val_rules rules, struct type *t2); static void tok_err(struct parse_context *c, char *fmt, struct token *t); ###### core functions static void type_err(struct parse_context *c, char *fmt, struct exec *loc, - struct type *t1, int rules, struct type *t2) + struct type *t1, enum val_rules rules, struct type *t2) { fprintf(stderr, "%s:", c->file_name); fput_loc(loc, stderr); @@ -598,18 +598,18 @@ the value can only be assigned once, when the variable is declared. ###### ast - enum val_rules {Rboolok = 1<<0,}; + enum val_rules {Rboolok = 1<<0, Rrefok = 1<<1,}; enum prop_err {Efail = 1<<0, Eretry = 1<<1, Eruntime = 1<<2, Emaycopy = 1<<3, Erval = 1<<4, Econst = 1<<5}; ###### forward decls static struct type *propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr, - struct type *type, int rules); + struct type *type, enum val_rules rules); ###### core functions static struct type *__propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr, enum prop_err *perr_local, - struct type *type, int rules) + struct type *type, enum val_rules rules) { struct type *t; @@ -631,7 +631,7 @@ the value can only be assigned once, when the variable is declared. } static struct type *propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr, - struct type *type, int rules) + struct type *type, enum val_rules rules) { int pre_err = c->parse_error; enum prop_err perr_local = 0; @@ -991,7 +991,7 @@ which might be reported in error messages. ###### forward decls static void free_value(struct type *type, struct value *v); - static int type_compat(struct type *require, struct type *have, int rules); + static int type_compat(struct type *require, struct type *have, enum val_rules rules); static void type_print(struct type *type, FILE *f); static void val_init(struct type *type, struct value *v); static void dup_value(struct type *type, @@ -1056,11 +1056,12 @@ A separate function encoding these cases will simplify some code later. ###### type functions - int (*compat)(struct type *this, struct type *other); + int (*compat)(struct type *this, struct type *other, enum val_rules rules); ###### ast functions - static int type_compat(struct type *require, struct type *have, int rules) + static int type_compat(struct type *require, struct type *have, + enum val_rules rules) { if ((rules & Rboolok) && have == Tbool) return 1; // NOTEST @@ -1068,7 +1069,7 @@ A separate function encoding these cases will simplify some code later. return 1; if (require->compat) - return require->compat(require, have); + return require->compat(require, have, rules); return require == have; } @@ -2292,9 +2293,7 @@ correctly. *perr |= Eruntime; if (v->constant) *perr |= Econst; - if (!type) - return v->type; - return type; + return v->type; } ###### interp exec cases @@ -2461,7 +2460,8 @@ with a const size by whether they are prepared at parse time or not. free(ptr); } - static int array_compat(struct type *require, struct type *have) + static int array_compat(struct type *require, struct type *have, + enum val_rules rules) { if (have->compat != require->compat) return 0; @@ -2917,24 +2917,31 @@ function will be needed. } ###### top level grammar - DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ { - struct type *t; - t = find_type(c, $ID.txt); - if (!t) - t = add_type(c, $ID.txt, &structure_prototype); - else if (t->size >= 0) { + $*type + StructName -> IDENTIFIER ${ { + struct type *t = find_type(c, $ID.txt); + + if (t && t->size >= 0) { tok_err(c, "error: type already declared", &$ID); tok_err(c, "info: this is location of declartion", &t->first_use); - /* Create a new one - duplicate */ - t = add_type(c, $ID.txt, &structure_prototype); - } else { - struct type tmp = *t; - *t = structure_prototype; - t->name = tmp.name; - t->next = tmp.next; + t = NULL; } - t->structure.field_list = $first_use = $ID; + $0 = t; + } }$ + $void + DeclareStruct -> struct StructName FieldBlock Newlines ${ { + struct type *t = $name = tmp.name; + t->next = tmp.next; + t->first_use = tmp.first_use; + + t->structure.field_list = $reference.referent == have) + return 1; if (have->compat != require->compat) return 0; if (have->reference.referent != require->reference.referent) @@ -3147,7 +3158,6 @@ anything in the heap or on the stack. A reference can be assigned return Tnone; } - static struct type reference_prototype = { .print_type = reference_print_type, .cmp_eq = reference_cmp, @@ -3445,7 +3455,8 @@ further detailed when Expression Lists are introduced. val->function = NULL; } - static int function_compat(struct type *require, struct type *have) + static int function_compat(struct type *require, struct type *have, + enum val_rules rules) { // FIXME can I do anything here yet? return 0; @@ -4712,8 +4723,8 @@ it is declared, it is assumed to be a global constant which are allowed to be declared at any time. ###### Binode types - Assign, - Declare, + Assign, AssignRef, + Declare, DeclareRef, ###### declare terminals $TERM = @@ -4749,6 +4760,7 @@ be declared at any time. ###### print binode cases case Assign: + case AssignRef: do_indent(indent, ""); print_exec(b->left, -1, bracket); printf(" = "); @@ -4758,6 +4770,7 @@ be declared at any time. break; case Declare: + case DeclareRef: { struct variable *v = cast(var, b->left)->var; do_indent(indent, ""); @@ -4787,8 +4800,10 @@ be declared at any time. ###### propagate binode cases case Assign: + case AssignRef: case Declare: - /* Both must match and not be labels, + case DeclareRef: + /* Both must match, or left may be ref and right an lval * Type must support 'dup', * For Assign, left must not be constant. * result is Tnone @@ -4799,10 +4814,23 @@ be declared at any time. return Tnone; if (t) { - if (propagate_types(b->right, c, perr_local, t, 0) != t) - if (b->left->type == Xvar) - type_err(c, "info: variable '%v' was set as %1 here.", - cast(var, b->left)->var->where_set, t, rules, NULL); + struct type *t2 = propagate_types(b->right, c, perr_local, + t, Rrefok); + if (!t2 || t2 == t || (*perr_local & Efail)) + ; // No more effort needed + else if (t->free == reference_free && + t->reference.referent == t2 && + !(*perr_local & Erval)) { + if (b->op == Assign) + b->op = AssignRef; + if (b->op == Declare) + b->op = DeclareRef; + } + else if (t->free == reference_free && + t->reference.referent == t2 && + (*perr_local & Erval)) + type_err(c, "error: Cannot assign an rval to a reference.", + b, NULL, 0, NULL); } else { t = propagate_types(b->right, c, perr_local, NULL, 0); if (t) @@ -4811,7 +4839,7 @@ be declared at any time. if (*perr & Erval) type_err(c, "error: cannot assign to an rval", b, NULL, 0, NULL); - else if (b->op == Assign && (*perr & Econst)) { + else if ((b->op == Assign || b->op == AssignRef) && (*perr & Econst)) { type_err(c, "error: Cannot assign to a constant: %v", b->left, NULL, 0, NULL); if (b->left->type == Xvar) { @@ -4823,6 +4851,9 @@ be declared at any time. } if (t && t->dup == NULL && !(*perr_local & Emaycopy)) type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL); + if (b->left->type == Xvar && (*perr_local & Efail)) + type_err(c, "info: variable '%v' was set as %1 here.", + cast(var, b->left)->var->where_set, t, rules, NULL); return Tnone; break; @@ -4830,13 +4861,21 @@ be declared at any time. ###### interp binode cases case Assign: + case AssignRef: lleft = linterp_exec(c, b->left, <ype); - if (lleft) + if (!lleft) + // FIXME lleft==NULL probably means illegal array ref + // should that cause a runtime error + ; + else if (b->op == AssignRef) + lleft->ref = linterp_exec(c, b->right, &rtype); + else dinterp_exec(c, b->right, lleft, ltype, 1); ltype = Tnone; break; case Declare: + case DeclareRef: { struct variable *v = cast(var, b->left)->var; struct value *val; @@ -4844,10 +4883,12 @@ be declared at any time. val = var_value(c, v); if (v->type->prepare_type) v->type->prepare_type(c, v->type, 0); - if (b->right) - dinterp_exec(c, b->right, val, v->type, 0); - else + if (!b->right) val_init(v->type, val); + else if (b->op == DeclareRef) + val->ref = linterp_exec(c, b->right, &rtype); + else + dinterp_exec(c, b->right, val, v->type, 0); break; } @@ -5657,8 +5698,8 @@ is a bit more interesting at this level. struct value fn = {.function = code}; struct type *t; var_block_close(c, CloseFunction, code); - t = add_anon_type(c, &function_prototype, - "func %.*s", name->name->name.len, + 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); @@ -5770,7 +5811,7 @@ is a bit more interesting at this level. all_ok = 0; if (!v->type->function.inline_result && !v->type->function.return_type->dup) { - type_err(c, "error: function cannot return value of type %1", + type_err(c, "error: function cannot return value of type %1", v->where_decl, v->type->function.return_type, 0, NULL); }