diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-06-22 02:26:12 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-06-22 02:26:12 -0400 |
commit | 230f0ca4c0b5bbae800aee31899879a355dd91ac (patch) | |
tree | 63f34fa3fcdd5272b5832aa0bf4786d21907154b | |
parent | ac6e0671373351c07ee05e5217108a636cb707cc (diff) |
found bug with evaling future functions
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | parse.c | 46 | ||||
-rw-r--r-- | test.toc | 84 | ||||
-rw-r--r-- | tokenizer.c | 59 | ||||
-rw-r--r-- | types.c | 17 | ||||
-rw-r--r-- | types.h | 29 |
6 files changed, 105 insertions, 132 deletions
@@ -8,6 +8,8 @@ /* @TODO: +i think what we need to do is put all of the standalone statements (like main();) and all of the constant decls into an array, + and iterate over all of them after everything is typed, and after all the initializations are run. initialization statements (maybe #init(-50), where -50 is the priority and <0 is reserved for standard library) if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared) improve type_to_str: @@ -802,7 +802,8 @@ static bool parser_is_definitely_type(Parser *p, Token **end) { } } break; case TOKEN_DIRECT: - case TOKEN_LITERAL_NUM: + case TOKEN_LITERAL_INT: + case TOKEN_LITERAL_FLOAT: case TOKEN_LITERAL_CHAR: case TOKEN_LITERAL_STR: case TOKEN_EOF: @@ -1260,19 +1261,15 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { if (end - t->token == 1) { /* 1-token expression */ switch (t->token->kind) { - case TOKEN_LITERAL_NUM: { - NumLiteral *num = &t->token->num; - switch (num->kind) { - case NUM_LITERAL_FLOAT: - e->kind = EXPR_LITERAL_FLOAT; - e->floatl = num->floatval; - break; - case NUM_LITERAL_INT: - e->kind = EXPR_LITERAL_INT; - e->intl = num->intval; - break; - } - } break; + case TOKEN_LITERAL_INT: + e->kind = EXPR_LITERAL_INT; + e->intl = t->token->intl; + break; + case TOKEN_LITERAL_FLOAT: + e->kind = EXPR_LITERAL_FLOAT; + e->floatl = t->token->floatl; + break; + break; case TOKEN_IDENT: e->kind = EXPR_IDENT; e->ident_str.str = t->token->ident; @@ -2523,10 +2520,29 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { return false; } ++t->token; - if (!parse_expr(p, &init->priority_expr, expr_find_end(p, 0))) { + bool negative = false; /* negative priority? */ + if (token_is_kw(t->token, KW_MINUS)) { + negative = true; + ++t->token; + } else if (token_is_kw(t->token, KW_PLUS)) { + /* ignore unary + in priority */ + ++t->token; + } + if (t->token->kind != TOKEN_LITERAL_INT) { + tokr_err(t, "Priority for #init must be an integer literal (like 50)."); + tokr_skip_semicolon(t); + return false; + } + U64 priority = t->token->intl; + ++t->token; + if (priority > I64_MAX) { + tokr_err(t, "Priority must be less than 9223372036854775808."); tokr_skip_semicolon(t); return false; } + I64 signed_priority = (I64)priority; + if (negative) signed_priority = -signed_priority; + init->priority = signed_priority; if (!token_is_kw(t->token, KW_RPAREN)) { tokr_err(t, "Expected ) after #init priority."); tokr_skip_semicolon(t); @@ -1,70 +1,22 @@ -#include "tests/std/io.toc", io; -#include "tests/std/mem.toc"; - -z ::= nms { - Foo ::= struct(f ::= fn() int { return 7; }) { - x: int; - } - - Bar ::= fn() &(struct { x, y: int; f ::= fn() int { return 13; } } ) { - x : u64; - return &x as &void; - } - - - foo ::= fn() total : int = 0 { - f: Foo(); - total += f.f(); - total += Bar().f(); - } +init(3); + +#include "tests/std/io.toc"; + +/* +#init(-50) init(1); +#init(30) init(2); +#init(-7) init(3); +#init(-42) init(4); +*/ + +x: int; +init ::= fn(a: int) { + writes("Initializing... #"); + writei(a); + x = 5; } - 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; - } - 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:]); - } -} - -LinkedList ::= struct (of :: Type) { - head: of; - tail: &LinkedList(of); -} - -Foo ::= struct { - k: int; - b: &Bar; -} - -Bar ::= struct { - f: Foo; + writes("Main's value of x is: "); + puti(x); } diff --git a/tokenizer.c b/tokenizer.c index 9c48a1a..6b4cc1b 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -57,7 +57,8 @@ static const char *token_kind_to_str(TokenKind t) { case TOKEN_KW: return "keyword"; case TOKEN_IDENT: return "identifier"; case TOKEN_DIRECT: return "directive"; - case TOKEN_LITERAL_NUM: return "numerical literal"; + case TOKEN_LITERAL_INT: return "integer literal"; + case TOKEN_LITERAL_FLOAT: return "floating-point literal"; case TOKEN_LITERAL_CHAR: return "character literal"; case TOKEN_LITERAL_STR: return "string literal"; case TOKEN_EOF: return "end of file"; @@ -76,16 +77,11 @@ static void fprint_token(FILE *out, Token *t) { fprintf(out, "identifier: "); fprint_ident_str(out, t->ident); } break; - case TOKEN_LITERAL_NUM: - fprintf(out, "number: "); - switch (t->num.kind) { - case NUM_LITERAL_INT: - fprintf(out, U64_FMT, t->num.intval); - break; - case NUM_LITERAL_FLOAT: - fprintf(out, "%g", (double)t->num.floatval); - break; - } + case TOKEN_LITERAL_INT: + fprintf(out, U64_FMT, t->intl); + break; + case TOKEN_LITERAL_FLOAT: + fprintf(out, "%g", (double)t->floatl); break; case TOKEN_LITERAL_CHAR: fprintf(out, "char: '%c' (%d)", t->chr, t->chr); @@ -360,9 +356,8 @@ static Status tokenize_file(Tokenizer *t, File *file) { int base = 10; Floating decimal_pow10 = 0; Token *token = tokr_add(t); - NumLiteral *n = &token->num; - n->kind = NUM_LITERAL_INT; - n->intval = 0; + token->kind = TOKEN_LITERAL_INT; + token->intl = 0; if (*t->s == '0') { tokr_nextchar(t); @@ -392,7 +387,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { /* .. (not a decimal point; end the number here) */ break; } - if (n->kind == NUM_LITERAL_FLOAT) { + if (token->kind == TOKEN_LITERAL_FLOAT) { tokenization_err(t, "Double . in number."); goto err; } @@ -400,16 +395,18 @@ static Status tokenize_file(Tokenizer *t, File *file) { tokenization_err(t, "Decimal point in non base 10 number."); goto err; } - n->kind = NUM_LITERAL_FLOAT; + token->kind = TOKEN_LITERAL_FLOAT; decimal_pow10 = 0.1; - n->floatval = (Floating)n->intval; + U64 i = token->intl; + token->floatl = (Floating)i; tokr_nextchar(t); continue; } else if (*t->s == 'e' && base != 16) { tokr_nextchar(t); - if (n->kind == NUM_LITERAL_INT) { - n->kind = NUM_LITERAL_FLOAT; - n->floatval = (Floating)n->intval; + if (token->kind == TOKEN_LITERAL_INT) { + token->kind = TOKEN_LITERAL_FLOAT; + U64 i = token->intl; + token->floatl = (Floating)i; } /* @TODO: check if exceeding maximum exponent */ int exponent = 0; @@ -428,9 +425,9 @@ static Status tokenize_file(Tokenizer *t, File *file) { /* @OPTIM: Slow for very large exponents (unlikely to happen) */ for (int i = 0; i < exponent; ++i) { if (negative_exponent) - n->floatval /= 10; + token->floatl /= 10; else - n->floatval *= 10; + token->floatl *= 10; } break; @@ -455,26 +452,26 @@ static Status tokenize_file(Tokenizer *t, File *file) { /* end of numeric literal */ break; } - switch (n->kind) { - case NUM_LITERAL_INT: - if (n->intval > U64_MAX / (U64)base || - n->intval * (U64)base > U64_MAX - (U64)digit) { + switch (token->kind) { + case TOKEN_LITERAL_INT: + if (token->intl > U64_MAX / (U64)base || + token->intl * (U64)base > U64_MAX - (U64)digit) { /* too big! */ tokenization_err(t, "Number too big to fit in a numeric literal."); goto err; } - n->intval *= (U64)base; - n->intval += (U64)digit; + token->intl *= (U64)base; + token->intl += (U64)digit; break; - case NUM_LITERAL_FLOAT: - n->floatval += decimal_pow10 * (Floating)digit; + case TOKEN_LITERAL_FLOAT: + token->floatl += decimal_pow10 * (Floating)digit; decimal_pow10 /= 10; break; + default: break; } tokr_nextchar(t); } tokr_put_end_pos(t, token); - token->kind = TOKEN_LITERAL_NUM; continue; } @@ -3961,10 +3961,27 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a str_hash_table_create(&tr->included_files, sizeof(IncludedFile), tr->allocr); } +static int compare_inits(const void *av, const void *bv) { + const Initialization *a = av, *b = bv; + if (a->priority < b->priority) return -1; + if (a->priority > b->priority) return +1; + return 0; +} + static Status types_file(Typer *tr, ParsedFile *f) { bool ret = true; tr->parsed_file = f; tr->uses = NULL; + /* @TODO(eventually): better sorting algorithm - a radix sort, perhaps */ + qsort(f->inits, arr_len(f->inits), sizeof *f->inits, compare_inits); + arr_foreach(f->inits, Initialization, init) { + if (!types_stmt(tr, &init->stmt)) + return false; + if (!eval_stmt(tr->evalr, &init->stmt)) + return false; + } + /* avoid accidentally using inits after they are run */ + f->inits = NULL; arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { if (tr->had_include_err) { @@ -217,7 +217,8 @@ typedef enum { TOKEN_KW, TOKEN_IDENT, TOKEN_DIRECT, - TOKEN_LITERAL_NUM, + TOKEN_LITERAL_INT, + TOKEN_LITERAL_FLOAT, TOKEN_LITERAL_CHAR, TOKEN_LITERAL_STR, TOKEN_EOF @@ -334,20 +335,6 @@ static const char *const keywords[KW_COUNT] = { "typeof", "sizeof", "alignof", "null" }; - -typedef enum { - NUM_LITERAL_INT, - NUM_LITERAL_FLOAT -} NumLiteralKind; - -typedef struct NumLiteral { - NumLiteralKind kind; - union { - U64 intval; - Floating floatval; - }; -} NumLiteral; - typedef struct String { char *str; size_t len; @@ -368,7 +355,8 @@ typedef struct Token { Keyword kw; Directive direct; char *ident; - NumLiteral num; + U64 intl; + Floating floatl; char chr; StrLiteral str; }; @@ -1000,14 +988,15 @@ typedef Statement *StatementPtr; */ typedef struct { Statement stmt; - union { - Expression priority_expr; /* before resolving */ - I64 priority; /* after resolving */ - }; + I64 priority; } Initialization; typedef struct ParsedFile { Statement *stmts; + /* + statements run before any typing happens + after they are run, inits is set to NULL to avoid accidental usage + */ Initialization *inits; } ParsedFile; |