summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c35
-rw-r--r--decls_cgen.c6
-rw-r--r--main.c1
-rw-r--r--out.c30
-rw-r--r--parse.c2
-rw-r--r--test.toc9
-rw-r--r--types.h2
7 files changed, 64 insertions, 21 deletions
diff --git a/cgen.c b/cgen.c
index 27fb0cf..8bd9964 100644
--- a/cgen.c
+++ b/cgen.c
@@ -9,6 +9,8 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e
g->ident_counter = 0;
g->main_ident = ident_get(ids, "main");
g->evalr = ev;
+ g->will_indent = true;
+ g->indent_lvl = 0;
}
static void cgen_block_enter(CGenerator *g, Block *b) {
@@ -19,6 +21,7 @@ static void cgen_block_enter(CGenerator *g, Block *b) {
} else {
stmts = b->stmts;
}
+ if (b) g->indent_lvl++;
block_enter(b, stmts);
}
@@ -31,6 +34,7 @@ static void cgen_block_exit(CGenerator *g, Block *into) {
stmts = b->stmts;
}
block_exit(b, stmts);
+ if (b) g->indent_lvl--;
g->block = into;
}
@@ -38,15 +42,26 @@ static inline FILE *cgen_writing_to(CGenerator *g) {
return g->outc; /* for now */
}
-static void cgen_write(CGenerator *g, const char *fmt, ...) {
+/* indent iff needed */
+static inline void cgen_indent(CGenerator *g) {
+ if (g->will_indent) {
+ for (int i = 0; i < g->indent_lvl; i++)
+ fprintf(cgen_writing_to(g), "\t");
+ g->will_indent = false;
+ }
+}
+
+static inline void cgen_write(CGenerator *g, const char *fmt, ...) {
va_list args;
+ cgen_indent(g);
va_start(args, fmt);
vfprintf(cgen_writing_to(g), fmt, args);
va_end(args);
}
-static void cgen_nl(CGenerator *g) {
+static inline void cgen_nl(CGenerator *g) {
fprintf(cgen_writing_to(g), "\n");
+ g->will_indent = true;
}
/* should declaration be a direct function declaration C (as opposed to using a function pointer or not being a function) */
@@ -54,7 +69,7 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) {
return g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1;
}
-static bool cgen_uses_out_param(Type *t) {
+static bool cgen_uses_ptr(Type *t) {
switch (t->kind) {
case TYPE_TUPLE:
case TYPE_ARR:
@@ -75,6 +90,7 @@ static void cgen_ident(CGenerator *g, Identifier i) {
/* don't conflict with C's main! */
cgen_write(g, "main__");
} else {
+ cgen_indent(g);
fprint_ident(cgen_writing_to(g), i);
}
}
@@ -112,7 +128,7 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
cgen_write(g, "(");
break;
case TYPE_FN:
- if (cgen_uses_out_param(&t->fn.types[0])) {
+ if (cgen_uses_ptr(&t->fn.types[0])) {
cgen_write(g, "void");
} else {
if (!cgen_type_pre(g, &t->fn.types[0], where))
@@ -145,7 +161,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
return false;
break;
case TYPE_FN: {
- bool out_param = cgen_uses_out_param(&t->fn.types[0]);
+ bool out_param = cgen_uses_ptr(&t->fn.types[0]);
cgen_write(g, ")(");
for (size_t i = 1; i < arr_len(t->fn.types); i++) {
if (i != 1)
@@ -164,6 +180,8 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
if (!cgen_type_post(g, &t->fn.types[0], where))
return false;
}
+ if (arr_len(t->fn.types) == 1 && !out_param)
+ cgen_write(g, "void");
cgen_write(g, ")");
if (!out_param)
if (!cgen_type_post(g, &t->fn.types[0], where))
@@ -179,7 +197,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
}
static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
- bool out_param = cgen_uses_out_param(&f->ret_type);
+ bool out_param = cgen_uses_ptr(&f->ret_type);
bool any_params = false;
if (out_param) {
cgen_write(g, "void ");
@@ -218,6 +236,8 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
if (!cgen_type_post(g, &f->ret_type, where))
return false;
}
+ if (!out_param && arr_len(f->params) == 0)
+ cgen_write(g, "void");
cgen_write(g, ")");
return true;
}
@@ -430,6 +450,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
Value val;
if (!eval_expr(g->evalr, &e->direct.args[0], &val))
return false;
+ cgen_indent(g);
fwrite(val.arr, 1, e->direct.args[0].type.arr.n, cgen_writing_to(g));
} break;
case DIRECT_COUNT: assert(0); break;
@@ -547,7 +568,7 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
case STMT_RET:
if (g->fn->ret_type.kind == TYPE_VOID) {
cgen_write(g, "return");
- } else if (cgen_uses_out_param(&g->fn->ret_type)) {
+ } else if (cgen_uses_ptr(&g->fn->ret_type)) {
if (!cgen_set(g, NULL, "*ret__", &s->ret.expr, NULL)) return false;
cgen_write(g, "return");
} else {
diff --git a/decls_cgen.c b/decls_cgen.c
index 7f0fad0..990a21b 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -54,7 +54,8 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
e->fn.c.id = g->ident_counter++;
if (!cgen_fn_header(g, &e->fn, e->where))
return false;
- cgen_write(g, ";\n");
+ cgen_write(g, ";");
+ cgen_nl(g);
if (!cgen_decls_block(g, &e->fn.body))
return false;
break;
@@ -85,7 +86,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
d->expr.fn.c.name = d->idents[0];
if (!cgen_fn_header(g, &d->expr.fn, d->where))
return false;
- cgen_write(g, ";\n");
+ cgen_write(g, ";");
+ cgen_nl(g);
if (!cgen_decls_block(g, &d->expr.fn.body))
return false;
} else if (d->flags & DECL_FLAG_HAS_EXPR) {
diff --git a/main.c b/main.c
index 05a41b6..8fe25d6 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,6 @@
/*
TODO:
re-do cgen
-arrs are pointers
make sure initializers for global variables are compile-time constants
allow, e.g.: x := "foo"; x[0] = 'g';
any odd number of "s for a string
diff --git a/out.c b/out.c
index 024b9fa..45a817b 100644
--- a/out.c
+++ b/out.c
@@ -18,7 +18,8 @@ typedef unsigned char bool;
/* declarations */
i64 puti(i64 i);
void dbl(i64((* x)[3]));
-void main__();
+i64 foo(void);
+void main__(void);
/* code */
int main() {
main__();
@@ -26,19 +27,28 @@ int main() {
}
i64 puti(i64 i) {
-printf("%ld\n", i);
+ printf("%ld\n", i);
}
void dbl(i64((* x)[3])) {
-((*x)[0]) = (((*x)[0])*2);;
-((*x)[1]) = (((*x)[1])*2);;
-((*x)[2]) = (((*x)[2])*2);;
+ ((*x)[0]) = (((*x)[0])*2);;
+ ((*x)[1]) = (((*x)[1])*2);;
+ ((*x)[2]) = (((*x)[2])*2);;
}
-void main__() {
-i64( a[3]) = {0};
-(a[0]) = 1;;
-(dbl((&a)));
-(puti((a[0])));
+i64 foo(void) {
+ a = 3;;
+ if (true) {
+ a = 4;;
+ } else if (false) {
+ a = (17+(1/0));;
+ };
+}
+
+void main__(void) {
+ i64( a[3]) = {0};
+ (a[0]) = 1;;
+ (dbl((&a)));
+ (puti((a[0])));
}
diff --git a/parse.c b/parse.c
index 01f8096..2cef0c2 100644
--- a/parse.c
+++ b/parse.c
@@ -542,7 +542,7 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
if (!parse_decl_list(p, &f->ret_decls, DECL_END_LBRACE_COMMA))
return false;
t->token--; /* move back to { */
- if (arr_len(f->ret_decls) > 1 || arr_len(f->ret_decls[0].idents)) {
+ if (arr_len(f->ret_decls) > 1 || arr_len(f->ret_decls[0].idents) > 1) {
f->ret_type.kind = TYPE_TUPLE;
f->ret_type.flags = 0;
f->ret_type.tuple = NULL;
diff --git a/test.toc b/test.toc
index 148c6de..c0ba997 100644
--- a/test.toc
+++ b/test.toc
@@ -10,6 +10,15 @@ dbl @= fn(x: &[3]int) {
(*x)[2] = (*x)[2] * 2;
};
+foo @= fn() a: int {
+ a = 3;
+ if true {
+ a = 4;
+ } elif false {
+ a = 17+1/0;
+ }
+};
+
main @= fn() {
a : [3]int;
a[0] = 1;
diff --git a/types.h b/types.h
index f21ff3f..9a375bd 100644
--- a/types.h
+++ b/types.h
@@ -499,6 +499,8 @@ typedef struct Typer {
typedef struct {
FILE *outc;
IdentID ident_counter;
+ int indent_lvl; /* how many levels of indentation? */
+ bool will_indent; /* will the next thing be indented? */
ParsedFile *file;
Block *block;
FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */