diff options
-rw-r--r-- | cgen.c | 35 | ||||
-rw-r--r-- | eval.c | 73 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | parse.c | 1 | ||||
-rw-r--r-- | test.toc | 79 | ||||
-rw-r--r-- | types.c | 25 | ||||
-rw-r--r-- | types.h | 4 |
7 files changed, 55 insertions, 163 deletions
@@ -226,6 +226,10 @@ static inline void cgen_nl(CGenerator *g) { g->will_indent = true; } +static inline void cgen_string(CGenerator *g, String s) { + fwrite(s.str, 1, s.len, cgen_writing_to(g)); +} + static inline char *cgen_ident_to_str(Identifier i) { return ident_to_str_reduced_charset(i); } @@ -989,7 +993,7 @@ static void cgen_truthiness(CGenerator *g, Expression *e) { switch (e->type.kind) { case TYPE_SLICE: cgen_expr(g, e); - cgen_write(g, ".n"); + cgen_write(g, ".len"); break; default: cgen_expr(g, e); @@ -1179,11 +1183,11 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { cgen_ident_id(g, from_id); cgen_write(g, "; "); cgen_ident_id(g, s_id); - cgen_write(g, ".n = "); + cgen_write(g, ".len = "); if (s->to) { cgen_expr(g, s->to); } else { - cgen_write(g, "of__.n"); + cgen_write(g, "of__.len"); } cgen_write(g, " - "); cgen_ident_id(g, from_id); @@ -1399,7 +1403,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { cgen_expr(g, lhs); bool is_ptr = lhs->type.kind == TYPE_PTR; cgen_write(g, is_ptr ? "->" :"."); - cgen_write(g, "data"); + cgen_string(g, rhs->ident_str); } } break; } @@ -1435,7 +1439,6 @@ static void cgen_expr(CGenerator *g, Expression *e) { } break; case EXPR_UNARY_OP: { const char *s = NULL; - Type *of_type = &e->unary.of->type; switch (e->unary.op) { case UNARY_MINUS: s = "-"; break; @@ -1456,22 +1459,6 @@ static void cgen_expr(CGenerator *g, Expression *e) { cgen_type_post(g, e->unary.of->val.type); cgen_write(g, ")"); break; - case UNARY_LEN: { - bool is_ptr = of_type->kind == TYPE_PTR; - if (is_ptr) { - of_type = of_type->ptr; - } - switch (of_type->kind) { - case TYPE_SLICE: - cgen_expr(g, e->unary.of); - cgen_write(g, "%sn", is_ptr ? "->" : "."); - break; - case TYPE_ARR: - cgen_write(g, "%lu", (unsigned long)of_type->arr.n); - break; - default: assert(0); break; - } - } break; case UNARY_TYPEOF: case UNARY_DSIZEOF: case UNARY_DALIGNOF: @@ -1607,7 +1594,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { cgen_write(g, U64_FMT, (U64)of_type->arr.n); break; case TYPE_SLICE: - cgen_write(g, "of_.n"); + cgen_write(g, "of_.len"); break; default: assert(0); break; } @@ -2283,7 +2270,7 @@ static void cgen_file(CGenerator *g, ParsedFile *f) { "typedef float f32;\n" "typedef double f64;\n" "typedef u8 bool;\n" - "typedef struct { void *data; i64 n; } slice_;\n" + "typedef struct { void *data; i64 len; } slice_;\n" "#define false ((bool)0)\n" "#define true ((bool)1)\n" "#ifdef __linux__\n" /* see also toc.c */ @@ -2301,7 +2288,7 @@ static void cgen_file(CGenerator *g, ParsedFile *f) { "#else\n" "#define platform__ " stringify(PLATFORM_OTHER) "\n" "#endif\n" - "static slice_ mkslice_(void *data, i64 n) { slice_ ret; ret.data = data; ret.n = n; return ret; }\n"); + "static slice_ mkslice_(void *data, i64 len) { slice_ ret; ret.data = data; ret.len = len; return ret; }\n"); cgen_sdecls_file(g, f); cgen_decls_file(g, f); @@ -721,14 +721,15 @@ static inline bool eval_address_of_ident(Evaluator *ev, Identifier i, Location w } static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void **p) { - Type *struct_type = &dot_expr->binary.lhs->type; + Expression *lhs = dot_expr->binary.lhs; + Type *struct_type = &lhs->type; bool is_ptr = struct_type->kind == TYPE_PTR; if (is_ptr) { struct_type = struct_type->ptr; } if (struct_type->kind == TYPE_STRUCT) { Value struc; - if (!eval_expr(ev, dot_expr->binary.lhs, &struc)) + if (!eval_expr(ev, lhs, &struc)) return false; void *struc_data; if (is_ptr) { @@ -742,11 +743,25 @@ static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void } *p = (char *)struc_data + dot_expr->binary.field->offset; } else if (struct_type->kind == TYPE_SLICE) { + String member = dot_expr->binary.rhs->ident_str; void *ptr; - if (!eval_address_of(ev, dot_expr->binary.lhs, &ptr)) - return false; - /* access struct data */ - *p = &((Slice *)ptr)->data; + if (is_ptr) { + Value v; + if (!eval_expr(ev, lhs, &v)) + return false; + ptr = v.ptr; + } else { + if (!eval_address_of(ev, lhs, &ptr)) + return false; + } + if (str_eq_cstr(member, "data")) { + /* access struct data */ + *p = &((Slice *)ptr)->data; + } else { + assert(str_eq_cstr(member, "len")); + /* access struct length */ + *p = &((Slice *)ptr)->len; + } } return true; } @@ -764,20 +779,6 @@ static Status eval_address_of(Evaluator *ev, Expression *e, void **ptr) { if (!eval_expr(ev, e, &v)) return false; *ptr = v.ptr; } break; - case UNARY_LEN: { - Type *of_type = &e->unary.of->type; - Slice *slice; - Value of_val; - if (!eval_expr(ev, e, &of_val)) return false; - if (of_type->kind == TYPE_PTR) { - assert(of_type->ptr->kind == TYPE_SLICE); - slice = of_val.ptr; - } else { - assert(of_type->kind == TYPE_SLICE); - slice = &of_val.slice; - } - *ptr = &slice->len; - } break; default: assert(0); return false; } break; @@ -821,21 +822,6 @@ static Status eval_set(Evaluator *ev, Expression *set, Value *to) { if (!eval_expr(ev, set->unary.of, &ptr)) return false; eval_deref_set(ptr.ptr, to, &set->type); } break; - case UNARY_LEN: { - Type *of_type = &set->unary.of->type; - if (of_type->kind == TYPE_PTR) { - /* if it's a pointer, we can just eval it and set its length */ - Value of; - if (!eval_expr(ev, set->unary.of, &of)) return false; - ((Slice *)of.ptr)->len = to->i64; - } else { - /* otherwise, we need a pointer to the slice */ - void *p; - if (!eval_address_of(ev, set->unary.of, &p)) - return false; - ((Slice *)p)->len = to->i64; - } - } break; default: assert(0); break; } break; @@ -1092,7 +1078,6 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { case EXPR_UNARY_OP: { Value of; if (!eval_expr(ev, e->unary.of, &of)) return false; - Type *of_type = &e->unary.of->type; switch (e->unary.op) { case UNARY_ADDRESS: { Expression *o = e->unary.of; @@ -1119,22 +1104,6 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { case UNARY_NOT: v->boolv = !val_truthiness(of, &e->unary.of->type); break; - case UNARY_LEN: - if (of_type->kind == TYPE_PTR) { - /* dereference of */ - eval_deref(&of, of.ptr, of_type->ptr); - of_type = of_type->ptr; - } - switch (of_type->kind) { - case TYPE_SLICE: - v->i64 = of.slice.len; - break; - case TYPE_ARR: - v->i64 = (I64)of_type->arr.n; - break; - default: assert(0); break; - } - break; case UNARY_SIZEOF: v->i64 = (I64)compiler_sizeof(of.type); break; @@ -8,7 +8,6 @@ /* @TODO: -get rid of UNARY_LEN? detect circular declarations (A ::= B; B ::= A) either detect circular #includes or set a #include depth limit (maybe sometimes you want finite circular includes with #if) initialization statements (maybe #init(-50), where -50 is the priority and <0 is reserved for standard library) @@ -70,7 +70,6 @@ static const char *unary_op_to_str(UnaryOp u) { case UNARY_ADDRESS: return "&"; case UNARY_DEREF: return "*"; case UNARY_NOT: return "!"; - case UNARY_LEN: return "len"; case UNARY_DSIZEOF: return "#sizeof"; case UNARY_DALIGNOF: return "#alignof"; case UNARY_SIZEOF: return "sizeof"; @@ -1,70 +1,23 @@ +#include "std/mem.toc", mem; #include "tests/std/io.toc", io; -#include "std/mem.toc"; - - -z ::= nms { - Foo ::= struct(f ::= fn() int { 7 }) { - x: int; - } - - Bar ::= fn() &(struct { x, y: int; f ::= fn() int { 13 } } ) { - x : u64; - &x as &void - } - - - foo ::= fn() total : int = 0 { - f: Foo(); - total += f.f(); - total += Bar().f(); - } -} - -main ::= fn() { - nums := news(int, 10); - for x, i := &nums { - *x = i*i; - } - l := slice_to_ll(nums); - p := &l; - while p { - io.puti(p.head); - p = p.tail; +use mem; +sum_slice ::= fn(a : &[]int) total := 0 { + for i := 0..a.len-1 { + total += a[i]; } - f: Foo; - f.k = -173; - f.b = new(Bar); - f.b.f.b = new(Bar); - f.b.f.b.f.k = 9; - io.puti(f.k); - io.puti(f.b.f.k); - io.puti(f.b.f.b.f.k); - x := z.foo(); - y ::= z.foo(); - io.puti(x); - io.puti(y); } -slice_to_ll ::= fn(t::=, slice: []t) use ll: LinkedList(t) { - head = slice[0]; - if slice.len == 1 { - tail = null; - } else { - tail = new(LinkedList(t)); - *tail = slice_to_ll(slice[1:]); - } +thing ::= fn() int { + bar : []int; + defer dels(bar); + bar = news(int, 3); + b := sum_slice(&bar); + b } -LinkedList ::= struct (of :: Type) { - head: of; - tail: &LinkedList(of); -} - -Foo ::= struct { - k: int; - b: &Bar; -} - -Bar ::= struct { - f: Foo; +main ::= fn() { + a := thing(); + b ::= thing(); + io.puti(a); + io.puti(b); } @@ -480,16 +480,6 @@ static Status expr_must_lval(Expression *e, const char *purpose) { } case EXPR_UNARY_OP: if (e->unary.op == UNARY_DEREF) return true; - if (e->unary.op == UNARY_LEN) { - Type *of_type = &e->unary.of->type; - if (of_type->kind != TYPE_PTR && !expr_must_lval(e->unary.of, purpose)) { /* can't set length of a non-lvalue slice */ - return false; - } - - return of_type->kind == TYPE_SLICE - || (of_type->kind == TYPE_PTR - && of_type->ptr->kind == TYPE_SLICE); - } err_print(e->where, "Cannot %s operator %s.", purpose, unary_op_to_str(e->unary.op)); return false; case EXPR_BINARY_OP: @@ -502,7 +492,9 @@ static Status expr_must_lval(Expression *e, const char *purpose) { return false; } return true; - case BINARY_DOT: return true; + case BINARY_DOT: + if (e->type.kind == TYPE_PTR) return true; /* structure->member is always an lvalue */ + return expr_must_lval(e->binary.lhs, purpose); default: break; } err_print(e->where, "Cannot %s operator %s.", purpose, binary_op_to_str(e->binary.op)); @@ -2888,9 +2880,6 @@ static Status types_expr(Typer *tr, Expression *e) { t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_BOOL; break; - case UNARY_LEN: - assert(0); /* types_expr is what makes things UNARY_LEN */ - break; case UNARY_TYPEOF: { if (type_is_builtin(&of->type, BUILTIN_VARARGS)) { err_print(of->where, "You can't apply typeof to varargs."); @@ -3241,11 +3230,9 @@ static Status types_expr(Typer *tr, Expression *e) { Declaration *decl = ident->decl; e->kind = EXPR_VAL; e->val.i64 = (I64)arr_len(decl->val.varargs); - } else { - /* change expr to UNARY_LEN */ - e->kind = EXPR_UNARY_OP; - e->unary.op = UNARY_LEN; - e->unary.of = of; + } else if (struct_type->kind == TYPE_ARR) { + e->kind = EXPR_VAL; + e->val.i64 = (I64)struct_type->arr.n; } } else if (type_is_builtin(struct_type, BUILTIN_NMS)) { Value nms_val; @@ -600,7 +600,6 @@ typedef enum { UNARY_DEREF, /* *x */ UNARY_NOT, /* !x */ UNARY_TYPEOF, /* typeof x */ - UNARY_LEN, /* x.len ; replaces BINARY_DOT len when typing */ UNARY_DSIZEOF, UNARY_DALIGNOF, UNARY_SIZEOF, @@ -889,8 +888,7 @@ typedef struct Declaration { /* for eval, for non-constant decls the pointers to values need to be fixed, which is why this isn't just Value *. - no, this can't be a union with val, because of global variables and possibly - other things (varargs maybe?) + no, this can't be a union with val, because of global variables and varargs */ Value **val_stack; } Declaration; |