diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-04 01:48:14 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-04 01:48:14 -0500 |
commit | 67975f14c4297c95c9ea01572e463a04bbfc47cd (patch) | |
tree | 688ea8db60b6e16caf262744987e1af23017b141 | |
parent | 0c06ed6f6933d0eeac797f877d352dd7ec37056e (diff) |
more exporting
-rw-r--r-- | err.c | 68 | ||||
-rw-r--r-- | package.c | 117 | ||||
-rw-r--r-- | parse.c | 14 | ||||
-rw-r--r-- | test.toc | 12 | ||||
-rw-r--r-- | types.h | 17 |
5 files changed, 127 insertions, 101 deletions
@@ -56,57 +56,69 @@ static void err_vfprint(const char *fmt, va_list args) { static void err_print_header_(Location where) { if (!where.ctx) - err_fprint("Error (no location available):\n"); + err_fprint(TEXT_ERROR("error") ":\n"); + else { #if ERR_EMACS - err_fprint("%s:%lu: " TEXT_ERROR("error") ":\n", where.ctx->filename, (unsigned long)where.line); + err_fprint("%s:%lu: " TEXT_ERROR("error") ":\n", where.ctx->filename, (unsigned long)where.line); #else - err_fprint(TEXT_ERROR("error") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); + err_fprint(TEXT_ERROR("error") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); #endif + } } static void info_print_header_(Location where) { if (!where.ctx) - err_fprint("Info (no location available):\n"); + err_fprint(TEXT_INFO("info") ":\n"); + else { #if ERR_EMACS - err_fprint("%s:%lu: " TEXT_INFO("info") ":\n", where.ctx->filename, (unsigned long)where.line); + err_fprint("%s:%lu: " TEXT_INFO("info") ":\n", where.ctx->filename, (unsigned long)where.line); #else - err_fprint(TEXT_INFO("info") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); + err_fprint(TEXT_INFO("info") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); #endif + } } static void warn_print_header_(Location where) { if (!where.ctx) - err_fprint("Warning (no location available):\n"); + err_fprint(TEXT_WARN("warning") ":\n"); + else { #if ERR_EMACS - err_fprint("%s:%lu: " TEXT_WARN("warning") ":\n", where.ctx->filename, (unsigned long)where.line); + err_fprint("%s:%lu: " TEXT_WARN("warning") ":\n", where.ctx->filename, (unsigned long)where.line); #else - err_fprint(TEXT_WARN("warning") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); + err_fprint(TEXT_WARN("warning") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename); #endif + } } static void err_print_location_text(Location where) { - const char *text = where.ctx->str + where.pos; - const char *end = strchr(text, '\n'); - int has_newline = end != NULL; - if (!has_newline) - end = strchr(text, '\0'); - assert(end); - err_fprint("\there: --> "); - if (!text[0]) - err_fprint("<end of file>"); - else - err_fwrite(text, 1, (size_t)(end - text)); - err_fprint("\n"); + if (where.ctx) { + const char *text = where.ctx->str + where.pos; + const char *end = strchr(text, '\n'); + int has_newline = end != NULL; + if (!has_newline) + end = strchr(text, '\0'); + assert(end); + err_fprint("\there: --> "); + if (!text[0]) + err_fprint("<end of file>"); + else + err_fwrite(text, 1, (size_t)(end - text)); + err_fprint("\n"); + } else { + err_fprint("\t<no location available>"); + } } static void err_print_footer_(Location where) { ErrCtx *ctx = where.ctx; - err_fprint("\n"); + err_fprint("\n"); err_print_location_text(where); - arr_foreach(ctx->instance_stack, Location, inst) { - err_fprint("While generating the instance of a function\n"); - err_print_location_text(*inst); + if (ctx) { + arr_foreach(ctx->instance_stack, Location, inst) { + err_fprint("While generating the instance of a function\n"); + err_print_location_text(*inst); + } } } @@ -127,7 +139,7 @@ static void err_print_( #endif Location where, const char *fmt, ...) { va_list args; - if (!where.ctx->enabled) return; + if (where.ctx && !where.ctx->enabled) return; #if ERR_SHOW_SOURCE_LOCATION if (file) err_fprint("Generated by line %d of %s:\n", line, file); @@ -145,7 +157,7 @@ static void err_print_( static void info_print(Location where, const char *fmt, ...) { va_list args; - if (!where.ctx->enabled) return; + if (where.ctx && !where.ctx->enabled) return; va_start(args, fmt); info_print_header_(where); err_vfprint(fmt, args); @@ -159,7 +171,7 @@ static void warn_print_( #endif Location where, const char *fmt, ...) { va_list args; - if (!where.ctx->enabled) return; + if (where.ctx && !where.ctx->enabled) return; #if ERR_SHOW_SOURCE_LOCATION if (file) err_fprint("Generated by line %d of %s:\n", line, file); @@ -70,30 +70,9 @@ static void export_ident(Exporter *ex, Identifier i) { } } -static bool export_len8(Exporter *ex, size_t len, const char *for_, Location where) { - if (len > U8_MAX) { - err_print(where, "Too many %s (the maximum is " STRINGIFY(U8_MAX) ").", for_); - return false; - } - export_u8(ex, (U8)len); - return true; -} - -static bool export_len16(Exporter *ex, size_t len, const char *for_, Location where) { - if (len > U16_MAX) { - err_print(where, "Too many %s (the maximum is " STRINGIFY(U16_MAX) ").", for_); - return false; - } - export_u16(ex, (U16)len); - return true; -} - -static bool export_len32(Exporter *ex, size_t len, const char *for_, Location where) { - if (len > U32_MAX) { - err_print(where, "Too many %s (the maximum is " STRINGIFY(U32_MAX) ").", for_); - return false; - } - export_u32(ex, (U32)len); +/* TODO: replace with vlq */ +static bool export_len(Exporter *ex, size_t len) { + export_u64(ex, (U64)len); return true; } @@ -111,8 +90,7 @@ static bool export_type(Exporter *ex, Type *type, Location where) { export_u8(ex, (U8)type->builtin); break; case TYPE_TUPLE: - if (!export_len16(ex, arr_len(type->tuple), "types in a tuple", where)) - return false; + export_len(ex, arr_len(type->tuple)); arr_foreach(type->tuple, Type, sub) if (!export_type(ex, sub, where)) return false; @@ -123,8 +101,7 @@ static bool export_type(Exporter *ex, Type *type, Location where) { return false; break; case TYPE_FN: - if (!export_len16(ex, arr_len(type->fn.types), "types in a function type", where)) - return false; + export_len(ex, arr_len(type->fn.types)); arr_foreach(type->fn.types, Type, sub) if (!export_type(ex, sub, where)) return false; @@ -134,6 +111,21 @@ static bool export_type(Exporter *ex, Type *type, Location where) { arr_foreach(type->fn.constness, Constness, c) export_u8(ex, *c); break; + case TYPE_STRUCT: { + StructDef *struc = type->struc; + if (struc->export.id == 0) { + StructDef **ptr = arr_add(&ex->exported_structs); + *ptr = struc; + size_t nexported_structs = arr_len(ex->exported_structs); + if (nexported_structs > U32_MAX) { + err_print(struc->where, "Too many exported structure definitions (the maximum is " STRINGIFY(U32_MAX) ")."); + return false; + } + + struc->export.id = (U32)nexported_structs; + } + export_len(ex, (size_t)struc->export.id); + } break; case TYPE_EXPR: assert(0); return false; @@ -143,15 +135,16 @@ static bool export_type(Exporter *ex, Type *type, Location where) { static bool export_fn_ptr(Exporter *ex, FnExpr *f, Location where) { if (f->export.id == 0) { - FnWithLocation *floc = arr_add(&ex->exported_fns); - floc->fn = f; - floc->where = where; - if (arr_len(ex->exported_fns) > U32_MAX) { + FnExpr **fptr = arr_add(&ex->exported_fns); + *fptr = f; + size_t nexported_fns = arr_len(ex->exported_fns); + if (nexported_fns > U32_MAX) { err_print(where, "Too many exported functions (the maximum is " STRINGIFY(U32_MAX) ")."); + return false; } - f->export.id = (U32)arr_len(ex->exported_fns); + f->export.id = (U32)nexported_fns; } - export_u32(ex, f->export.id); + export_len(ex, (size_t)f->export.id); return true; } @@ -272,8 +265,20 @@ static bool export_expr(Exporter *ex, Expression *e) { break; case EXPR_BINARY_OP: export_u8(ex, (U8)e->binary.op); - if (!export_expr(ex, e->binary.lhs) - || !export_expr(ex, e->binary.rhs)) + if (!export_expr(ex, e->binary.lhs)) + return false; + if (e->binary.op == BINARY_DOT) { + /* rhs may not typed (if it's a string it will be)! */ + Expression *rhs = e->binary.rhs; + if (!(rhs->flags & EXPR_FOUND_TYPE)) { + export_u8(ex, 0); + assert(rhs->kind == EXPR_IDENT); + export_ident(ex, rhs->ident); + break; + } else + export_u8(ex, 1); + } + if (!export_expr(ex, e->binary.rhs)) return false; break; case EXPR_VAL: @@ -281,8 +286,7 @@ static bool export_expr(Exporter *ex, Expression *e) { return false; break; case EXPR_TUPLE: - if (!export_len16(ex, arr_len(e->tuple), "expressions in a tuple", e->where)) - return false; + export_len(ex, arr_len(e->tuple)); arr_foreach(e->tuple, Expression, item) if (!export_expr(ex, item)) return false; @@ -327,8 +331,7 @@ static bool export_decl(Exporter *ex, Declaration *d) { return false; } export_location(ex, d->where); - if (!export_len16(ex, arr_len(d->idents), "identifiers in one declaration", d->where)) - return false; + export_len(ex, arr_len(d->idents)); arr_foreach(d->idents, Identifier, ident) { export_ident(ex, *ident); } @@ -383,8 +386,7 @@ static bool export_stmt(Exporter *ex, Statement *s) { static bool export_block(Exporter *ex, Block *b) { export_location(ex, b->start); export_location(ex, b->end); - if (!export_len32(ex, arr_len(b->stmts), "statements in a block", b->start)) - return false; + export_len(ex, arr_len(b->stmts)); arr_foreach(b->stmts, Statement, s) { if (!export_stmt(ex, s)) return false; @@ -396,14 +398,12 @@ static bool export_block(Exporter *ex, Block *b) { return true; } -static bool export_fn(Exporter *ex, FnExpr *f, Location where) { - if (!export_len16(ex, arr_len(f->params), "parameters in a function", where)) - return false; +static bool export_fn(Exporter *ex, FnExpr *f) { + export_len(ex, arr_len(f->params)); arr_foreach(f->params, Declaration, param) if (!export_decl(ex, param)) return false; - if (!export_len8(ex, arr_len(f->ret_decls), "return declarations", where)) - return false; + export_len(ex, arr_len(f->ret_decls)); arr_foreach(f->ret_decls, Declaration, ret_decl) if (!export_decl(ex, ret_decl)) return false; @@ -413,10 +413,11 @@ static bool export_fn(Exporter *ex, FnExpr *f, Location where) { return true; } -static bool export_struct(Exporter *ex, StructDef *s, Location where) { +static bool export_struct(Exporter *ex, StructDef *s) { + export_len(ex, arr_len(s->fields)); arr_foreach(s->fields, Field, f) { export_ident(ex, f->name); - if (!export_type(ex, f->type, where)) + if (!export_type(ex, f->type, s->where)) return false; } return true; @@ -424,17 +425,23 @@ static bool export_struct(Exporter *ex, StructDef *s, Location where) { /* does NOT close the file */ static bool exptr_finish(Exporter *ex) { - if (!export_len32(ex, arr_len(ex->exported_fns), "exported functions", LOCATION_NONE)) - return false; - arr_foreach(ex->exported_fns, FnWithLocation, f) { - if (!export_fn(ex, f->fn, f->where)) + export_len(ex, arr_len(ex->exported_fns)); + typedef FnExpr *FnExprPtr; + arr_foreach(ex->exported_fns, FnExprPtr, f) { + if (!export_fn(ex, *f)) return false; } arr_clear(&ex->exported_fns); - arr_foreach(ex->exported_structs, StructDefWithLocation, s) { - if (!export_struct(ex, s->struc, s->where)) + export_len(ex, arr_len(ex->exported_structs)); + typedef StructDef *StructDefPtr; + arr_foreach(ex->exported_structs, StructDefPtr, s) { + if (!export_struct(ex, *s)) return false; } arr_clear(&ex->exported_structs); + + if (ferror(ex->out)) { + warn_print(LOCATION_NONE, "An error occured while writing the package output. It may be incorrect."); + } return true; } @@ -570,12 +570,15 @@ static bool parse_type(Parser *p, Type *type) { case KW_STRUCT: /* struct */ type->kind = TYPE_STRUCT; - type->struc = parser_malloc(p, sizeof *type->struc); - type->struc->flags = 0; + StructDef *struc = type->struc = parser_malloc(p, sizeof *type->struc); + struc->flags = 0; /* help cgen out */ - type->struc->c.name = NULL; - type->struc->c.id = 0; - type->struc->fields = NULL; + struc->c.name = NULL; + struc->c.id = 0; + struc->fields = NULL; + struc->export.id = 0; + struc->where = t->token->where; + ++t->token; if (!token_is_kw(t->token, KW_LBRACE)) { err_print(t->token->where, "Expected { or ( to follow struct."); @@ -729,6 +732,7 @@ static bool parser_is_definitely_type(Parser *p, Token **end) { if (is_decl(t)) /* has return declaration */ goto end; Type return_type; + /* TODO: think of a better way of determining if it's a void fn type. (maybe followed by ;/,/)?)*/ bool *enabled = &t->token->where.ctx->enabled; bool prev_enabled = *enabled; *enabled = false; @@ -1,4 +1,12 @@ -#export main ::= fn() int { - {3} + +Foo ::= struct { + x: int; }; + +#export main ::= fn() Foo { + f: Foo; + f.x = 13; + f +}; + // #export ghjk := #sizeof(asdf);
\ No newline at end of file @@ -379,12 +379,16 @@ enum { typedef struct { Field *fields; + Location where; U16 flags; size_t size; /* size of this struct during compile time */ struct { Identifier name; IdentID id; } c; + struct { + U32 id; /* (index into exptr->exported_structs) + 1, or 0 if hasn't been exported */ + } export; } StructDef; enum { @@ -749,21 +753,12 @@ typedef struct Typer { FnExpr *fn; /* the function we're currently parsing. */ } Typer; -typedef struct { - FnExpr *fn; - Location where; -} FnWithLocation; - -typedef struct { - StructDef *struc; - Location where; -} StructDefWithLocation; typedef struct Exporter { FILE *out; /* .top (toc package) to output to */ bool export_locations; - FnWithLocation *exported_fns; - StructDefWithLocation *exported_structs; + FnExpr **exported_fns; + StructDef **exported_structs; } Exporter; typedef struct CGenerator { |