diff options
-rw-r--r-- | main.c | 18 | ||||
-rw-r--r-- | test.toc | 20 | ||||
-rw-r--r-- | types.c | 84 |
3 files changed, 64 insertions, 58 deletions
@@ -5,16 +5,24 @@ */ /* -TODO: -check arr.toc's Arr works @ compile time -new version of copy_val for copying types?? + NOTE: + + Structure of the toc compiler: + tokenizer => parser => typing (types.c) => typdefs_cgen, decls_cgen, cgen + (lexing) -there are probably places where we enter a function and never exit (in typing?) if there's an error -switch struct."field" to struct["field"] + toc tries to continue even after the first error. + It will not continue during cgen, but it will during tokenization, + parsing, and typing. If one stage fails, the following ones do not + start. +*/ +/* +TODO: packages X ::= newtype(int); or something don't allow while {3; 5} (once break is added) +better printing of types (take was_expr into account) any odd number of "s for a string make sure futurely/currently-declared types are only used by pointer/slice allow omission of trailing ; in foo ::= fn() {}? @@ -7,22 +7,12 @@ putf ::= fn(x: float) { "); }; -foo ::= fn(x ::= 5) (int, int) { -x, 2*x +Point ::= struct { + x, y : int; }; main ::= fn() { - puti(f()); - puti(f(7)); - puti(f(4)); - - f ::= fn(a,b::=3) z := a+b { }; - - r ::= f(); - puti(r); - s ::= f(7); - puti(s); - t ::= f(4); - puti(t); - + p : Point; + p.x = 5; + puti(p[if 5 > 6 { "x" } else { "y" }]); };
\ No newline at end of file @@ -1535,8 +1535,8 @@ static bool types_expr(Typer *tr, Expression *e) { break; } case BINARY_AT_INDEX: - /* TODO(eventually): support non-builtin numerical (or even perhaps non-numerical) indices */ - if (rhs_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(rhs_type->builtin)) { + if ((lhs_type->kind == TYPE_ARR || lhs_type->kind == TYPE_SLICE) && + (rhs_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(rhs_type->builtin))) { err_print(e->where, "The index of an array must be a builtin numerical type."); return false; } @@ -1547,6 +1547,41 @@ static bool types_expr(Typer *tr, Expression *e) { case TYPE_SLICE: *t = *lhs_type->slice; break; + case TYPE_PTR: + lhs_type = lhs_type->ptr; + if (lhs_type->kind != TYPE_STRUCT) break; + /* fallthrough */ + case TYPE_STRUCT: + /* allow accessing struct members with a string */ + if (rhs_type->kind != TYPE_SLICE + || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) { + char *s = type_to_str(rhs_type); + err_print(e->where, "Expected a string for struct member access with [], but got type %s.", s); + return false; + } + Value field_name; + + /* replace with BINARY_DOT */ + e->binary.op = BINARY_DOT; + bool is_field = false; + if (!eval_expr(tr->evalr, rhs, &field_name)) return false; + arr_foreach(lhs_type->struc->fields, Field, f) { + if (ident_eq_str(f->name, field_name.slice.data)) { + is_field = true; + *t = *f->type; + e->binary.field = f; + } + } + if (!is_field) { + char *fstr = err_malloc((size_t)(field_name.slice.n + 1)); + memcpy(fstr, field_name.slice.data, (size_t)field_name.slice.n); + fstr[field_name.slice.n] = 0; /* null-terminate */ + char *typestr = type_to_str(lhs_type); + err_print(e->where, "%s is not a field of structure %s.", fstr, typestr); + free(fstr); free(typestr); + return false; + } + break; default: { char *s = type_to_str(lhs_type); err_print(e->where, "Trying to take index of non-array type %s.", s); @@ -1560,7 +1595,11 @@ static bool types_expr(Typer *tr, Expression *e) { Type *struct_type = lhs_type; if (struct_type->kind == TYPE_PTR) struct_type = struct_type->ptr; - + if (rhs->kind != EXPR_IDENT) { + err_print(rhs->where, "Expected identifier for struct member access, but got %s.", + expr_kind_to_str(rhs->kind)); + return false; + } if (struct_type->kind == TYPE_STRUCT) { bool is_field = false; if (rhs->kind == EXPR_IDENT) { @@ -1575,41 +1614,10 @@ static bool types_expr(Typer *tr, Expression *e) { } if (!is_field) { - /* allow some_struct."foo" */ - Value field_name; - if (!types_expr(tr, rhs)) return false; - if (rhs_type->kind != TYPE_SLICE || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) { - char *struct_typestr = type_to_str(lhs_type); - if (rhs->kind == EXPR_IDENT) { - char *fstr = ident_to_str(rhs->ident); - err_print(e->where, "%s is not a field of structure %s.", fstr, struct_typestr); - free(fstr); - } else { - char *field_typestr = type_to_str(rhs_type); - err_print(e->where, "Invalid type %s for field of structure %s .", rhs_type, struct_typestr); - free(field_typestr); - } - free(struct_typestr); - return false; - - } - if (!eval_expr(tr->evalr, rhs, &field_name)) return false; - arr_foreach(struct_type->struc->fields, Field, f) { - if (ident_eq_str(f->name, field_name.slice.data)) { - is_field = true; - *t = *f->type; - e->binary.field = f; - } - } - if (!is_field) { - char *fstr = err_malloc((size_t)(field_name.slice.n + 1)); - memcpy(fstr, field_name.slice.data, (size_t)field_name.slice.n); - fstr[field_name.slice.n] = 0; /* null-terminate */ - char *typestr = type_to_str(lhs_type); - err_print(e->where, "%s is not a field of structure %s.", fstr, typestr); - free(fstr); free(typestr); - return false; - } + char *member = ident_to_str(rhs->ident); + char *struc = type_to_str(struct_type); + err_print(e->where, "%s is not a member of structure %s.", member, struc); + return false; } } else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR) { if (!(rhs->kind == EXPR_IDENT && ident_eq_str(rhs->ident, "len"))) { |