summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-06-22 02:26:12 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-06-22 02:26:12 -0400
commit230f0ca4c0b5bbae800aee31899879a355dd91ac (patch)
tree63f34fa3fcdd5272b5832aa0bf4786d21907154b
parentac6e0671373351c07ee05e5217108a636cb707cc (diff)
found bug with evaling future functions
-rw-r--r--main.c2
-rw-r--r--parse.c46
-rw-r--r--test.toc84
-rw-r--r--tokenizer.c59
-rw-r--r--types.c17
-rw-r--r--types.h29
6 files changed, 105 insertions, 132 deletions
diff --git a/main.c b/main.c
index b7e5fa5..cd61f6d 100644
--- a/main.c
+++ b/main.c
@@ -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:
diff --git a/parse.c b/parse.c
index 33e8fe2..d8c20eb 100644
--- a/parse.c
+++ b/parse.c
@@ -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);
diff --git a/test.toc b/test.toc
index 73d1ad1..532cc56 100644
--- a/test.toc
+++ b/test.toc
@@ -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;
}
diff --git a/types.c b/types.c
index 17f85ed..c30e9df 100644
--- a/types.c
+++ b/types.c
@@ -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) {
diff --git a/types.h b/types.h
index 035543c..922a7bf 100644
--- a/types.h
+++ b/types.h
@@ -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;