summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c35
-rw-r--r--eval.c73
-rw-r--r--main.c1
-rw-r--r--parse.c1
-rw-r--r--test.toc79
-rw-r--r--types.c25
-rw-r--r--types.h4
7 files changed, 55 insertions, 163 deletions
diff --git a/cgen.c b/cgen.c
index 6a63eba..9bbeb36 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
diff --git a/eval.c b/eval.c
index 0271fb0..8c4b7d0 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/main.c b/main.c
index 0c8bd0b..a4a48ad 100644
--- a/main.c
+++ b/main.c
@@ -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)
diff --git a/parse.c b/parse.c
index 2add2cb..d22af8a 100644
--- a/parse.c
+++ b/parse.c
@@ -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";
diff --git a/test.toc b/test.toc
index af1c2fd..ec65787 100644
--- a/test.toc
+++ b/test.toc
@@ -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);
}
diff --git a/types.c b/types.c
index afc69e4..d595075 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index ce2fb09..fec1d01 100644
--- a/types.h
+++ b/types.h
@@ -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;