diff options
-rwxr-xr-x | build.sh | 2 | ||||
-rw-r--r-- | cgen.c | 18 | ||||
-rw-r--r-- | copy.c | 61 | ||||
-rw-r--r-- | decls_cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | infer.c | 9 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | parse.c | 67 | ||||
-rw-r--r-- | sdecls_cgen.c | 7 | ||||
-rw-r--r-- | test.toc | 72 | ||||
-rw-r--r-- | types.c | 30 | ||||
-rw-r--r-- | types.h | 3 |
12 files changed, 179 insertions, 99 deletions
@@ -29,6 +29,8 @@ fi DEBUG_FLAGS="-O0 $WARNINGS -std=c11 -DTOC_DEBUG" if [ "$CC" = "gcc" ]; then DEBUG_FLAGS="$DEBUG_FLAGS -no-pie -gdwarf-2 -pipe" +elif [ "$CC" = "clang" ]; then + DEBUG_FLAGS="$DEBUG_FLAGS -no-pie -gdwarf-2 -pipe" fi RELEASE_FLAGS="-O3 -s -DNDEBUG $WARNINGS -std=c11" @@ -35,14 +35,16 @@ static void cgen_defs_block(CGenerator *g, Block *b); static void cgen_defs_decl(CGenerator *g, Declaration *d); #define cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f) \ - FnExpr *prev_fn = g->f##n; \ - g->f##n = fn; \ - arr_foreach(fn->params, Declaration, param) \ - decl_f(g, param); \ - arr_foreach(fn->ret_decls, Declaration, r) \ - decl_f(g, r); \ - block_f(g, &fn->body); \ - g->f##n = prev_fn; + if (!(fn->flags & FN_EXPR_FOREIGN)) { \ + FnExpr *prev_fn = g->f##n; \ + g->f##n = fn; \ + arr_foreach(fn->params, Declaration, param) \ + decl_f(g, param); \ + arr_foreach(fn->ret_decls, Declaration, r) \ + decl_f(g, r); \ + block_f(g, &fn->body); \ + g->f##n = prev_fn; \ + } /* calls f on every sub-expression of e, block_f on every sub-block, and decl_f on every sub-declaration. */ #define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \ @@ -172,31 +172,44 @@ static Type *copy_type_(Copier *c, Type *in) { return out; } +static inline void *copier_malloc(Copier *c, size_t n) { + return allocr_malloc(c->allocr, n); +} + static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) { *fout = *fin; - Block *prev; - if (copy_body) { - prev = c->block; - c->block = &fout->body; - idents_create(&fout->body.idents, c->allocr, &fout->body); - } - size_t i; - size_t nparam_decls = arr_len(fin->params); - fout->params = NULL; - arr_set_lena(&fout->params, nparam_decls, c->allocr); - for (i = 0; i < nparam_decls; ++i) - copy_decl(c, fout->params + i, fin->params + i); - size_t nret_decls = arr_len(fin->ret_decls); - if (fin->ret_decls) { - fout->ret_decls = NULL; - arr_set_lena(&fout->ret_decls, nret_decls, c->allocr); - for (i = 0; i < nret_decls; ++i) - copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); - } - copy_type(c, &fout->ret_type, &fin->ret_type); - if (copy_body) { - copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); - c->block = prev; + if (fin->flags & FN_EXPR_FOREIGN) { + copy_expr(c, fout->foreign.name_expr = copier_malloc(c, sizeof *fin->foreign.name_expr), fin->foreign.name_expr); + copy_expr(c, fout->foreign.lib_expr = copier_malloc(c, sizeof *fin->foreign.lib_expr), fin->foreign.lib_expr); + copy_type(c, &fout->foreign.type, &fin->foreign.type); + size_t nctypes = arr_len(fin->foreign.type.fn.types); + fout->foreign.ctypes = copier_malloc(c, nctypes * sizeof(CType)); + memcpy(fout->foreign.ctypes, fin->foreign.ctypes, nctypes * sizeof(CType)); + } else { + Block *prev; + if (copy_body) { + prev = c->block; + c->block = &fout->body; + idents_create(&fout->body.idents, c->allocr, &fout->body); + } + size_t i; + size_t nparam_decls = arr_len(fin->params); + fout->params = NULL; + arr_set_lena(&fout->params, nparam_decls, c->allocr); + for (i = 0; i < nparam_decls; ++i) + copy_decl(c, fout->params + i, fin->params + i); + size_t nret_decls = arr_len(fin->ret_decls); + if (fin->ret_decls) { + fout->ret_decls = NULL; + arr_set_lena(&fout->ret_decls, nret_decls, c->allocr); + for (i = 0; i < nret_decls; ++i) + copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); + } + copy_type(c, &fout->ret_type, &fin->ret_type); + if (copy_body) { + copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); + c->block = prev; + } } } @@ -335,7 +348,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { sout->to = copy_expr_(c, sin->to); } break; case EXPR_TYPE: - copy_type(c, &out->typeval, &in->typeval); + copy_type(c, out->typeval = copier_malloc(c, sizeof *out->typeval), in->typeval); break; case EXPR_VAL: copy_val(a, &out->val, &in->val, &in->type); diff --git a/decls_cgen.c b/decls_cgen.c index 7dcd311..70e405c 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -184,7 +184,7 @@ static void cgen_decls_expr(CGenerator *g, Expression *e) { cgen_fn_decl(g, e->fn, &e->type); } break; case EXPR_TYPE: { - Type *type = &e->typeval; + Type *type = e->typeval; cgen_decls_type(g, type); } break; case EXPR_CAST: @@ -986,11 +986,11 @@ static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location whe Declaration *d = NULL; if (is_decl) { d = ident->decl; - if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval.kind == TYPE_STRUCT) { + if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval->kind == TYPE_STRUCT) { v->type = allocr_malloc(ev->allocr, sizeof *v->type); v->type->flags = TYPE_IS_RESOLVED; v->type->kind = TYPE_STRUCT; - v->type->struc = d->expr.typeval.struc; + v->type->struc = d->expr.typeval->struc; return true; } else { if (!types_decl(ev->typer, d)) return false; @@ -1526,7 +1526,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } } break; case EXPR_TYPE: - v->type = &e->typeval; + v->type = e->typeval; break; case EXPR_NMS: v->nms = e->nms; @@ -32,7 +32,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi break; case EXPR_CALL: { - if (to->kind == EXPR_TYPE && to->typeval.kind == TYPE_STRUCT) { + if (to->kind == EXPR_TYPE && to->typeval->kind == TYPE_STRUCT) { /* maybe it's a parameterized struct? */ /* it might not be possible that it's not, but might as well keep that possibility around. */ Value fn_val = {0}; @@ -52,7 +52,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi free(order); return false; } - Declaration *params = to->typeval.struc->params; + Declaration *params = to->typeval->struc->params; int arg_idx = 0; arr_foreach(params, Declaration, param) { int ident_idx = 0; @@ -96,7 +96,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi } if (to->kind != EXPR_CALL) { if (to->kind == EXPR_TYPE) { - to = to->typeval.was_expr; + to = to->typeval->was_expr; } if (!to || to->kind != EXPR_CALL) return true; /* give up */ @@ -208,7 +208,8 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents Expression *to_expr = to->was_expr; Expression e = {0}; e.kind = EXPR_TYPE; - e.typeval = *to; + e.typeval = allocr_malloc(tr->allocr, sizeof *e.typeval); + *e.typeval = *to; e.flags = EXPR_FOUND_TYPE; Type *type = &e.type; type->flags = TYPE_IS_RESOLVED; @@ -8,7 +8,6 @@ /* TODO: -remove Location from Type. fix x ::= fn_that_returns_array(); fn_that_takes_array(x); #if variadic fns @@ -461,10 +461,13 @@ static Status parse_args(Parser *p, Argument **args) { return true; } -static Status parse_type(Parser *p, Type *type) { +/* where will be filled out with the location, if not NULL */ +static Status parse_type(Parser *p, Type *type, Location *where) { Tokenizer *t = p->tokr; - type->where = parser_mk_loc(p); - type->where.start = t->token; + if (where) { + *where = parser_mk_loc(p); + where->start = t->token; + } type->flags = 0; switch (t->token->kind) { case TOKEN_KW: @@ -494,9 +497,10 @@ static Status parse_type(Parser *p, Type *type) { if (!token_is_kw(t->token, KW_RPAREN)) { while (1) { Type *param_type = parser_arr_add(p, &type->fn.types); - if (!parse_type(p, param_type)) return false; + Location type_where; + if (!parse_type(p, param_type, &type_where)) return false; if (param_type->kind == TYPE_TUPLE) { - err_print(param_type->where, "Functions cannot have tuples as parameters."); + err_print(type_where, "Functions cannot have tuples as parameters."); return false; } if (token_is_kw(t->token, KW_RPAREN)) @@ -520,7 +524,7 @@ static Status parse_type(Parser *p, Type *type) { ret_type->kind = TYPE_VOID; ret_type->flags = 0; } else { - if (!parse_type(p, ret_type)) + if (!parse_type(p, ret_type, NULL)) return false; } break; @@ -534,9 +538,10 @@ static Status parse_type(Parser *p, Type *type) { type->kind = TYPE_SLICE; type->slice = parser_malloc(p, sizeof *type->slice); ++t->token; /* move past ] */ - if (!parse_type(p, type->slice)) return false; + Location slice_where; + if (!parse_type(p, type->slice, &slice_where)) return false; if (type->slice->kind == TYPE_TUPLE) { - err_print(type->where, "You cannot have a slice of tuples."); + err_print(slice_where, "You cannot have a slice of tuples."); return false; } break; @@ -546,9 +551,10 @@ static Status parse_type(Parser *p, Type *type) { if (!parse_expr(p, type->arr.n_expr, end)) return false; t->token = end + 1; /* go past ] */ type->arr.of = parser_malloc(p, sizeof *type->arr.of); - if (!parse_type(p, type->arr.of)) return false; + Location of_where; + if (!parse_type(p, type->arr.of, &of_where)) return false; if (type->arr.of->kind == TYPE_TUPLE) { - err_print(type->where, "You cannot have an array of tuples."); + err_print(of_where, "You cannot have an array of tuples."); return false; } } break; @@ -559,9 +565,10 @@ static Status parse_type(Parser *p, Type *type) { ++t->token; /* move past < */ while (1) { Type *child = parser_arr_add(p, &type->tuple); - if (!parse_type(p, child)) return false; + Location child_where; + if (!parse_type(p, child, &child_where)) return false; if (child->kind == TYPE_TUPLE) { - err_print(child->where, "Tuples cannot contain tuples."); + err_print(child_where, "Tuples cannot contain tuples."); return false; } if (token_is_kw(t->token, KW_GT)) { /* we're done with the tuple */ @@ -577,17 +584,18 @@ static Status parse_type(Parser *p, Type *type) { } } break; - case KW_AMPERSAND: + case KW_AMPERSAND: { /* pointer */ type->kind = TYPE_PTR; type->ptr = parser_malloc(p, sizeof *type->ptr); ++t->token; /* move past & */ - if (!parse_type(p, type->ptr)) return false; + Location ptr_where; + if (!parse_type(p, type->ptr, &ptr_where)) return false; if (type->ptr->kind == TYPE_TUPLE) { - err_print(type->ptr->where, "You cannot have a pointer to a tuple."); + err_print(ptr_where, "You cannot have a pointer to a tuple."); return false; } - break; + } break; case KW_STRUCT: { /* struct */ type->kind = TYPE_STRUCT; @@ -694,7 +702,8 @@ static Status parse_type(Parser *p, Type *type) { } } break; } - type->where.end = t->token; + if (where) + where->end = t->token; return true; } @@ -791,9 +800,8 @@ static bool parser_is_definitely_type(Parser *p, Token **end) { goto end; } Type return_type; - if (!parse_type(p, &return_type)) { - /* couldn't parse a return type. this shouldn't happen in theory. */ - assert(0); + if (!parse_type(p, &return_type, NULL)) { + return false; } if (token_is_kw(t->token, KW_LBRACE)) { /* non-void fn expr */ @@ -983,7 +991,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { f->ret_type.kind = TYPE_VOID; f->ret_type.flags = 0; } else { - if (!parse_type(p, &f->ret_type)) { + if (!parse_type(p, &f->ret_type, NULL)) { success = false; goto ret; } @@ -1203,7 +1211,7 @@ static Status parse_c_type(Parser *p, CType *ctype, Type *type) { return false; } else { ctype->kind = CTYPE_NONE; - if (!parse_type(p, type)) + if (!parse_type(p, type, NULL)) return false; } return true; @@ -1237,7 +1245,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { if (parser_is_definitely_type(p, NULL)) { /* it's a type! */ e->kind = EXPR_TYPE; - if (!parse_type(p, &e->typeval)) + if (!parse_type(p, e->typeval = parser_malloc(p, sizeof *e->typeval), NULL)) return false; if (t->token == end) goto success; /* there's more stuff after */ @@ -1455,7 +1463,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } if (!token_is_kw(t->token, KW_EQ)) { fo->flags |= FOR_ANNOTATED_TYPE; - if (!parse_type(p, &fo->type)) + if (!parse_type(p, &fo->type, NULL)) goto for_fail; if (!token_is_kw(t->token, KW_EQ)) { tokr_err(t, "Expected = in for statement."); @@ -1666,7 +1674,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { return false; } ++t->token; - if (!parse_type(p, &e->new.type)) return false; + if (!parse_type(p, &e->new.type, NULL)) return false; if (token_is_kw(t->token, KW_COMMA)) { /* new(int, 5) */ ++t->token; @@ -1729,7 +1737,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { if (!parse_c_type(p, &unused, &e->cast.type)) return false; } else { - if (!parse_type(p, &e->cast.type)) + if (!parse_type(p, &e->cast.type, NULL)) return false; } if (t->token != end) { @@ -2233,12 +2241,13 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f if (annotates_type) { d->flags |= DECL_ANNOTATES_TYPE; Type type; - if (!parse_type(p, &type)) { + Location type_where; + if (!parse_type(p, &type, &type_where)) { goto ret_false; } d->type = type; if (type.kind == TYPE_TUPLE && arr_len(d->type.tuple) != arr_len(d->idents)) { - err_print(type.where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents)); + err_print(type_where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents)); goto ret_false; } } @@ -2738,7 +2747,7 @@ static void fprint_expr(FILE *out, Expression *e) { fprintf(out, "]"); } break; case EXPR_TYPE: - fprint_type(out, &e->typeval); + fprint_type(out, e->typeval); break; case EXPR_VAL: fprint_val(out, e->val, &e->type); diff --git a/sdecls_cgen.c b/sdecls_cgen.c index 4ad038f..ce89ad6 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -75,7 +75,7 @@ static void cgen_sdecls_expr(CGenerator *g, Expression *e) { e->fn->c.id = ++g->ident_counter; break; case EXPR_TYPE: - cgen_sdecls_type(g, &e->typeval); + cgen_sdecls_type(g, e->typeval); break; case EXPR_NMS: { char *prefix_part = cgen_nms_prefix_part(g, e->nms); @@ -107,8 +107,9 @@ static void cgen_sdecls_decl(CGenerator *g, Declaration *d) { } for (int idx = 0; idx < (int)arr_len(d->idents); ++idx) { Type *type = decl_type_at_index(d, idx); - Value *val = decl_val_at_index(d, idx); - if (type_is_builtin(type, BUILTIN_TYPE)) { + + if (type_is_builtin(type, BUILTIN_TYPE) && !(d->flags & DECL_IS_PARAM)) { + Value *val = decl_val_at_index(d, idx); cgen_sdecls_type(g, val->type); } } @@ -1,16 +1,70 @@ -#include "std/io.toc", io; +puti ::= fn(x: int) { +//tcc's giving me "incompatible types for redefinition of 'printf'" for some reason (even though the declarations have the exact same type) + #C("#ifndef __TINYC__ +extern int printf(const char *fmt, ...); +#endif +"); + #C("printf(\"%ld\\n\", (long)x);"); +}; +putf ::= fn(x: float) { + #C("#ifndef __TINYC__ +extern int printf(const char *fmt, ...); +#endif +"); + #C("printf(\"%f\\n\", (double)x);"); +}; -Foo ::= struct (n ::= 12) { - x ::= n; +// it would be nice if Arr.data.len == Arr.len (: but this will require some C code... +Arr ::= fn (t :: Type) Type { + struct { + data : []t; + len, cap : int; + } }; -Bar ::= struct { - a ::= -1243.3; +arr_add ::= fn(t :: Type, a : &Arr(t), x : t) { + if a.len >= a.cap { + a.cap = a.cap * 2 + 2; + new_data := new(t, a.cap); + for i := 0..a.len-1 { + new_data[i] = a.data[i]; + } + a.data = new_data; + } + a.data[a.len] = x; + a.len += 1; +}; + +square ::= fn(t :: Type, x : t) t { + a : Arr(t); + for i := 1,2..2*x-1 { + arr_add(t, &a, i); + }; + sum := 0 as t; + for i := 0..a.len-1 { + sum += a.data[i]; + }; + sum }; -main ::= fn() { - io.puti(Foo(3).x); - io.puti(Foo().n); - io.puti(Bar.a as int); +ArrInt ::= Arr(int); + +inc ::= fn(t :: Type, x : t) t { + x + 1 +}; + +main ::= fn() { + arr : ArrInt; + farr : Arr(float); + for i := 1..100 { + arr_add(int, &arr, inc(int, square(int, i))); + arr_add(float, &farr, inc(float, square(float, i as float))); + } + for i := 0..arr.len - 1 { + puti(arr.data[i]); + } + for i := 0..farr.len - 1 { + putf(farr.data[i]); + } }; @@ -508,7 +508,6 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { f->ret_type.flags = TYPE_IS_RESOLVED; f->ret_type.was_expr = NULL; f->ret_type.tuple = NULL; - f->ret_type.where = f->ret_decls[0].where; arr_foreach(f->ret_decls, Declaration, d) { arr_foreach(d->idents, Identifier, i) { *(Type *)arr_add(&f->ret_type.tuple) = d->type; @@ -517,7 +516,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } } if (!generic) { - if (!type_resolve(tr, &f->ret_type, f->ret_type.where)) { + if (!type_resolve(tr, &f->ret_type, f->where)) { success = false; goto ret; } @@ -1725,7 +1724,6 @@ static Status types_expr(Typer *tr, Expression *e) { if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE)) { Value val; - if (!eval_expr(tr->evalr, f, &val)) return false; if (type_is_builtin(&f->type, BUILTIN_TYPE)) { @@ -1841,10 +1839,10 @@ static Status types_expr(Typer *tr, Expression *e) { /* expression is actually a type */ e->kind = EXPR_TYPE; - memset(&e->typeval, 0, sizeof e->typeval); - e->typeval.kind = TYPE_STRUCT; - e->typeval.flags = TYPE_IS_RESOLVED; - e->typeval.struc = &inst->struc; + e->typeval = typer_calloc(tr, 1, sizeof *e->typeval); + e->typeval->kind = TYPE_STRUCT; + e->typeval->flags = TYPE_IS_RESOLVED; + e->typeval->struc = &inst->struc; t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_TYPE; arr_clear(&arg_types); @@ -2025,16 +2023,17 @@ static Status types_expr(Typer *tr, Expression *e) { } return false; } - + Value val_copy; Type *type = &expr->type; + copy_val(tr->allocr, &val_copy, arg_val, type); + *(Type *)typer_arr_add(tr, &table_index_type.tuple) = *type; - + arg_exprs[i].kind = EXPR_VAL; arg_exprs[i].flags = EXPR_FOUND_TYPE; - copy_val(tr->allocr, &arg_exprs[i].val, arg_val, type); - arg_exprs[i].val = *arg_val; - copy_val(tr->allocr, ¶m_decl->val, arg_val, type); + arg_exprs[i].val = val_copy; param_decl->flags |= DECL_FOUND_VAL; + copy_val(tr->allocr, ¶m_decl->val, &val_copy, type); if (!(param_decl->flags & DECL_ANNOTATES_TYPE)) { param_decl->type = *type; } @@ -2510,6 +2509,7 @@ static Status types_expr(Typer *tr, Expression *e) { Value lval = {0}; if (!eval_expr(tr->evalr, lhs, &lval)) return false; + lhs->kind = EXPR_VAL; lhs->flags = EXPR_FOUND_TYPE; lhs->val = lval; @@ -2613,7 +2613,7 @@ static Status types_expr(Typer *tr, Expression *e) { break; } case EXPR_TYPE: { - Type *tval = &e->typeval; + Type *tval = e->typeval; if (tval->kind == TYPE_STRUCT && tval->struc->params) { /* don't try to resolve this */ t->kind = TYPE_BUILTIN; @@ -2706,8 +2706,8 @@ static Status types_decl(Typer *tr, Declaration *d) { if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE - && d->expr.typeval.kind == TYPE_STRUCT) { - d->expr.typeval.struc->name = d->idents[0]; + && d->expr.typeval->kind == TYPE_STRUCT) { + d->expr.typeval->struc->name = d->idents[0]; } if (d->flags & DECL_INFER) { @@ -445,7 +445,6 @@ enum { }; typedef U8 TypeFlags; typedef struct Type { - Location where; struct Expression *was_expr; /* if non-NULL, indicates that this type used to be an expression (TYPE_EXPR) */ TypeKind kind; TypeFlags flags; @@ -827,7 +826,7 @@ typedef struct Expression { SliceExpr slice; Block *block; struct Expression *tuple; /* dynamic array, even after typing */ - Type typeval; + Type *typeval; Value val; }; } Expression; |