summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-09 12:51:50 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-09 12:51:50 -0500
commit30f1ae4c7e0c07a722f1fa4d770409246ed9788c (patch)
tree57ef6212dcb0d250381654c620c2f7fcea4297dc
parent03a74d7b41e3abce86f9465a6a4994edb5c37e5b (diff)
made cgen pass arrays by value
-rw-r--r--cgen.c97
-rw-r--r--main.c3
-rw-r--r--std/io.toc24
-rw-r--r--test.toc17
-rw-r--r--types.h27
5 files changed, 88 insertions, 80 deletions
diff --git a/cgen.c b/cgen.c
index b6055e2..9f4ba16 100644
--- a/cgen.c
+++ b/cgen.c
@@ -23,6 +23,8 @@ enum {
static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, uint16_t flags);
static bool cgen_expr_pre(CGenerator *g, Expression *e);
static bool cgen_expr(CGenerator *g, Expression *e);
+static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
+ const char *to_str);
static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to);
static bool cgen_type_pre(CGenerator *g, Type *t, Location where);
static bool cgen_type_post(CGenerator *g, Type *t, Location where);
@@ -257,10 +259,10 @@ static void cgen_ident(CGenerator *g, Identifier i) {
}
-#define CGEN_IDENT_ID_STR_SIZE 48
+#define CGEN_IDENT_ID_STR_SIZE 32
/* buffer should be at least CGEN_IDENT_ID_STR_SIZE bytes */
static inline void cgen_ident_id_to_str(char *buffer, IdentID id) {
- snprintf(buffer, 32, "a%lu_", (unsigned long)id);
+ snprintf(buffer, CGEN_IDENT_ID_STR_SIZE, "a%lu_", (unsigned long)id);
}
static char *cgen_nms_prefix(CGenerator *g, Namespace *n) {
@@ -558,6 +560,36 @@ static bool cgen_fn_args(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_c
return true;
}
+static inline bool cgen_arg_pre(CGenerator *g, Expression *arg) {
+ if (!cgen_expr_pre(g, arg)) return false;
+ if (arg->type.kind == TYPE_ARR) {
+ /* create copy of array */
+ IdentID copy = ++g->ident_counter;
+ arg->cgen.id = copy;
+ if (!cgen_type_pre(g, &arg->type, arg->where))
+ return false;
+ char s[CGEN_IDENT_ID_STR_SIZE];
+ cgen_ident_id_to_str(s, copy);
+
+ cgen_write(g, " %s", s);
+ if (!cgen_type_post(g, &arg->type, arg->where))
+ return false;
+ cgen_write(g, "; ");
+ if (!cgen_set(g, NULL, s, arg, NULL))
+ return false;
+ }
+ return true;
+}
+
+static inline bool cgen_arg(CGenerator *g, Expression *arg) {
+ if (arg->type.kind == TYPE_ARR) {
+ cgen_ident_id(g, arg->cgen.id);
+ return true;
+ } else {
+ return cgen_expr(g, arg);
+ }
+}
+
/* unless f has const/semi-const args, instance and which_are_const can be set to 0 */
static bool cgen_fn_header(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
bool out_param = cgen_uses_ptr(&f->ret_type);
@@ -663,7 +695,6 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
/* one of exprs, idents, and prefix should be NULL. does NOT call cgen_expr_pre for to/exprs */
static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
- IdentID prefix_id; /* ID of prefix for block */
switch (to->kind) {
case EXPR_VAL:
assert(0); /* never needed at the moment */
@@ -696,7 +727,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
/* e.g. a, b = fn_which_returns_tuple(); */
arr_foreach(to->call.arg_exprs, Expression, arg) {
if (!constness || !arg_is_const(arg, constness[i])) {
- if (!cgen_expr_pre(g, arg))
+ if (!cgen_arg_pre(g, arg))
return false;
}
}
@@ -713,7 +744,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
if (any_args)
cgen_write(g, ", ");
any_args = true;
- if (!cgen_expr(g, arg))
+ if (!cgen_arg(g, arg))
return false;
}
++i;
@@ -738,18 +769,10 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
cgen_writeln(g, "); ");
} break;
case EXPR_IF:
- prefix_id = to->if_.c.id;
- goto prefixed;
case EXPR_BLOCK:
- prefix_id = to->block_ret_id;
- goto prefixed;
case EXPR_WHILE:
- prefix_id = to->while_.c.id;
- goto prefixed;
- case EXPR_FOR:
- prefix_id = to->for_->c.id;
- goto prefixed;
- prefixed:
+ case EXPR_FOR: {
+ IdentID prefix_id = to->cgen.id = ++g->ident_counter;
for (size_t i = 0; i < arr_len(to->type.tuple); ++i) {
if (exprs)
if (!cgen_expr_pre(g, &exprs[i]))
@@ -770,8 +793,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
cgen_write(g, "%lu_", i);
cgen_write(g, "; ");
}
- break;
-
+ } break;
/* things which can never be tuples */
case EXPR_SLICE:
case EXPR_IDENT:
@@ -834,7 +856,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_IF: {
IfExpr *curr = &e->if_;
- curr->c.id = id;
+ e->cgen.id = id;
while (1) {
if (curr->cond) {
cgen_write(g, "if (");
@@ -852,7 +874,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
} break;
case EXPR_WHILE: {
WhileExpr *w = &e->while_;
- w->c.id = id;
+ e->cgen.id = id;
cgen_write(g, "while (");
if (w->cond) {
if (!cgen_expr(g, w->cond))
@@ -874,7 +896,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!cgen_expr_pre(g, fo->of)) return false;
}
- fo->c.id = id;
+ e->cgen.id = id;
cgen_write(g, "{");
if (is_range) {
if (fo->range.to) {
@@ -1051,7 +1073,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
cgen_write(g, "}}");
} break;
case EXPR_BLOCK:
- e->block_ret_id = id;
+ e->cgen.id = id;
if (!cgen_block(g, &e->block, ret_name, 0))
return false;
break;
@@ -1061,7 +1083,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
Constness *constness = e->call.fn->type.fn.constness;
arr_foreach(e->call.arg_exprs, Expression, arg) {
if (!constness || !arg_is_const(arg, constness[i])) {
- if (!cgen_expr_pre(g, arg)) return false;
+ if (!cgen_arg_pre(g, arg)) return false;
}
++i;
}
@@ -1090,7 +1112,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!constness || !arg_is_const(arg, constness[i])) {
if (any_args) cgen_write(g, ", ");
any_args = true;
- if (!cgen_expr(g, arg))
+ if (!cgen_arg(g, arg))
return false;
}
++i;
@@ -1103,10 +1125,10 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
}
cgen_write(g, ");");
} else if (cgen_uses_ptr(&e->type)) {
- e->call.c.id = ++g->ident_counter;
+ e->cgen.id = ++g->ident_counter;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
cgen_write(g, " ");
- cgen_ident_id(g, e->call.c.id);
+ cgen_ident_id(g, id);
if (!cgen_type_post(g, &e->type, e->where)) return false;
cgen_write(g, ";"); cgen_nl(g);
if (!cgen_expr(g, e->call.fn)) return false;
@@ -1120,7 +1142,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!constness || !arg_is_const(arg, constness[i])) {
if (any_args) cgen_write(g, ", ");
any_args = true;
- if (!cgen_expr(g, arg))
+ if (!cgen_arg(g, arg))
return false;
}
++i;
@@ -1129,7 +1151,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
cgen_write(g, ", ");
}
cgen_write(g, "&");
- cgen_ident_id(g, e->call.c.id);
+ cgen_ident_id(g, e->cgen.id);
cgen_write(g, ");");
cgen_nl(g);
}
@@ -1214,9 +1236,9 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!cgen_val_pre(g, e->val, &e->type, e->where))
return false;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
- e->val_c_id = ++g->ident_counter;
+ e->cgen.id = ++g->ident_counter;
cgen_write(g, " ");
- cgen_ident_id(g, e->val_c_id);
+ cgen_ident_id(g, e->cgen.id);
if (!cgen_type_post(g, &e->type, e->where)) return false;
cgen_write(g, " = ");
if (!cgen_val(g, e->val, &e->type, e->where))
@@ -1497,26 +1519,17 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
}
} break;
case EXPR_IF:
- if (e->type.kind != TYPE_VOID)
- cgen_ident_id(g, e->if_.c.id);
- break;
case EXPR_WHILE:
- if (e->type.kind != TYPE_VOID)
- cgen_ident_id(g, e->while_.c.id);
- break;
case EXPR_BLOCK:
- if (e->type.kind != TYPE_VOID)
- cgen_ident_id(g, e->block_ret_id);
- break;
case EXPR_FOR:
if (e->type.kind != TYPE_VOID)
- cgen_ident_id(g, e->for_->c.id);
+ cgen_ident_id(g, e->cgen.id);
break;
case EXPR_CALL:
if (e->type.kind == TYPE_TUPLE) {
/* the only situation in which this could happen is if the return value doesn't matter */
} else if (cgen_uses_ptr(&e->type)) {
- cgen_ident_id(g, e->call.c.id);
+ cgen_ident_id(g, e->cgen.id);
} else {
FnType *fn_type = &e->call.fn->type.fn;
cgen_write(g, "(");
@@ -1533,7 +1546,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
if (!first_arg)
cgen_write(g, ", ");
first_arg = false;
- if (!cgen_expr(g, arg))
+ if (!cgen_arg(g, arg))
return false;
}
++i;
@@ -1618,7 +1631,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
cgen_ident_id(g, e->slice.c.id);
break;
case EXPR_VAL:
- cgen_ident_id(g, e->val_c_id);
+ cgen_ident_id(g, e->cgen.id);
break;
case EXPR_NMS:
break;
diff --git a/main.c b/main.c
index dcf4e07..223c8d5 100644
--- a/main.c
+++ b/main.c
@@ -18,7 +18,6 @@
/*
TODO:
-change the way arrays work (a := b, where b is an array probably shouldn't copy)
struct parameters - to allow circular dependencies in types
foo, _ := bar();
nice syntax for #including something into a namespace
@@ -32,7 +31,7 @@ switch to / add as an alternative: libffi
---
X ::= newtype(int); or something
-don't allow while {3; 5} (once break is added)
+don't allow while {3; 5} or for 0..10 { 3; 5 } (once break is added)
do we need was_expr? (now that, presumably, we have struct arguments)
any odd number of "s for a string
make sure futurely/currently-declared types are only used by pointer/slice
diff --git a/std/io.toc b/std/io.toc
index 51cfd76..fac4921 100644
--- a/std/io.toc
+++ b/std/io.toc
@@ -38,16 +38,20 @@ puti ::= fn(x: int) {
toc_putchar('-');
// NOTE: don't do x = -x; here to make sure I64_MIN works
}
- abs ::= fn(x: int) int { if x < 0 { -x } else { x } };
- scan_digit := 1000000000000000000;
- started := false;
- while scan_digit > 0 {
- digit := abs((x / scan_digit) % 10);
- if digit > 0 { started = true; }
- if started {
- toc_putchar((('0' as int) + digit) as char);
+ if x == 0 {
+ toc_putchar('0');
+ } else {
+ abs ::= fn(x: int) int { if x < 0 { -x } else { x } };
+ scan_digit := 1000000000000000000;
+ started := false;
+ while scan_digit > 0 {
+ digit := abs((x / scan_digit) % 10);
+ if digit > 0 { started = true; }
+ if started {
+ toc_putchar((('0' as int) + digit) as char);
+ }
+ scan_digit /= 10;
}
- scan_digit /= 10;
}
toc_putchar('\n');
-}; \ No newline at end of file
+};
diff --git a/test.toc b/test.toc
index 6c0920d..56b4092 100644
--- a/test.toc
+++ b/test.toc
@@ -1,13 +1,20 @@
-p ::= fn() [3]int {
- x: [3]int;
- x[0] = 16;
- x
+io ::= nms{
+ #include "std/io.toc";
+};
+
+foo ::= fn(a: [3]int) {
+ a[0] = 128;
};
f ::= fn() int {
- a := p();
+ a : [3]int;
+ foo(a);
a[0]
};
main ::= fn() {
a ::= f();
+ b := f();
+ io.puti(a);
+ io.puti(b);
+
};
diff --git a/types.h b/types.h
index 74c469f..620451c 100644
--- a/types.h
+++ b/types.h
@@ -551,25 +551,16 @@ typedef struct CallExpr {
struct Expression *arg_exprs; /* after typing */
};
struct Instance *instance; /* NULL = ordinary function, no compile time args */
- struct {
- IdentID id;
- } c;
} CallExpr;
typedef struct IfExpr {
struct Expression *cond; /* NULL = this is an else */
struct Expression *next_elif; /* next elif/else of this statement */
- struct {
- IdentID id;
- } c;
Block body;
} IfExpr;
typedef struct WhileExpr {
struct Expression *cond;
- struct {
- IdentID id;
- } c;
Block body;
} WhileExpr;
@@ -581,9 +572,6 @@ enum {
typedef struct ForExpr {
U8 flags;
- struct {
- IdentID id;
- } c;
Type type; /* uninitialized unless typed or flags & FOR_ANNOTATED_TYPE */
Identifier index; /* NULL = no index */
Identifier value; /* NULL = no value */
@@ -707,8 +695,11 @@ enum {
typedef struct Expression {
Type type;
Location where;
- ExprKind kind;
+ ExprKind kind : 8;
U8 flags;
+ struct {
+ IdentID id; /* cgen ID used for this expression */
+ } cgen;
union {
Floating floatl;
/* Floating floatl; */
@@ -751,16 +742,10 @@ typedef struct Expression {
FnExpr *fn;
CastExpr cast;
SliceExpr slice;
- struct {
- Block block;
- IdentID block_ret_id;
- };
+ Block block;
struct Expression *tuple;
Type typeval;
- struct {
- Value val;
- IdentID val_c_id;
- };
+ Value val;
};
} Expression;