From 119950ebde3c9f096d1866ba6448d6bd9b22d063 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum
Date: Fri, 3 Jul 2020 16:09:10 -0400
Subject: removed ability to evaluate a function before it is declared at
compile time; that was causing too many problems
---
abbrevs.txt | 1 -
allocator.c | 7 --
cgen.c | 92 ++++++++++----------
copy.c | 16 ++--
development.md | 50 +----------
docs/00.html | 2 +-
eval.c | 9 ++
main.c | 6 +-
misc.c | 9 +-
parse.c | 235 ++++++---------------------------------------------
test.toc | 6 +-
tests/init.toc | 15 ++--
tests/misc.toc | 22 ++---
tests/std/base.toc | 5 +-
tests/tests.c | 1 +
tests/types.toc | 46 +++++-----
types.c | 242 +++++++++++++++++++++++++++++++++++++++++++++--------
types.h | 30 ++++---
18 files changed, 371 insertions(+), 423 deletions(-)
diff --git a/abbrevs.txt b/abbrevs.txt
index d865020..d486c78 100644
--- a/abbrevs.txt
+++ b/abbrevs.txt
@@ -17,7 +17,6 @@ eval - evaluate
evalr - evaluator
expr - expression
fn - function
-gctx - global context
ident - identifier
inc - include
init - initialization
diff --git a/allocator.c b/allocator.c
index f3fbff6..98005ef 100644
--- a/allocator.c
+++ b/allocator.c
@@ -114,10 +114,3 @@ static void allocr_free_all(Allocator *a) {
page = next;
}
}
-
-static char *allocr_str_to_cstr(Allocator *a, String s) {
- char *ret = allocr_malloc(a, s.len + 1);
- memcpy(ret, s.str, s.len);
- ret[s.len] = 0;
- return ret;
-}
diff --git a/cgen.c b/cgen.c
index cdc16b4..c4427e1 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1628,7 +1628,7 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
break;
case STMT_EXPR: {
Expression *e = s->expr;
- if ((g->block != NULL || e->kind == EXPR_C) && !type_is_compileonly(&e->type)) {
+ if (!type_is_compileonly(&e->type)) {
cgen_expr_pre(g, e);
cgen_expr(g, e);
if (e->kind != EXPR_C)
@@ -1882,6 +1882,9 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
case STMT_BLOCK:
cgen_block(g, s->block, 0);
break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
}
@@ -1997,38 +2000,39 @@ static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
g->fn = NULL;
g->file = f;
- cgen_write(g, "#include \n"
- "#include \n"
- "typedef int8_t i8;\n"
- "typedef int16_t i16;\n"
- "typedef int32_t i32;\n"
- "typedef int64_t i64;\n"
- "typedef uint8_t u8;\n"
- "typedef uint16_t u16;\n"
- "typedef uint32_t u32;\n"
- "typedef uint64_t u64;\n"
- "typedef float f32;\n"
- "typedef double f64;\n"
- "typedef u8 bool;\n"
- "typedef struct { void *data; i64 len; } slice_;\n"
- "#define false ((bool)0)\n"
- "#define true ((bool)1)\n"
- "#ifdef __linux__\n" /* see also toc.c */
- "#define platform__ " stringify(PLATFORM_LINUX) "\n"
- "#elif defined _WIN32\n"
- "#define platform__ " stringify(PLATFORM_WINDOWS) "\n"
- "#elif defined __APPLE__\n"
- "#define platform__ " stringify(PLATFORM_OSX) "\n"
- "#elif defined __FreeBSD__\n"
- "#define platform__ " stringify(PLATFORM_FREEBSD) "\n"
- "#elif defined __OpenBSD__\n"
- "#define platform__ " stringify(PLATFORM_OPENBSD) "\n"
- "#elif defined __unix__\n"
- "#define platform__ " stringify(PLATFORM_MISC_UNIX) "\n"
- "#else\n"
- "#define platform__ " stringify(PLATFORM_OTHER) "\n"
- "#endif\n"
- "static slice_ mkslice_(void *data, i64 len) { slice_ ret; ret.data = data; ret.len = len; return ret; }\n");
+ cgen_write(g,
+ "#include \n"
+ "#include \n"
+ "typedef int8_t i8;\n"
+ "typedef int16_t i16;\n"
+ "typedef int32_t i32;\n"
+ "typedef int64_t i64;\n"
+ "typedef uint8_t u8;\n"
+ "typedef uint16_t u16;\n"
+ "typedef uint32_t u32;\n"
+ "typedef uint64_t u64;\n"
+ "typedef float f32;\n"
+ "typedef double f64;\n"
+ "typedef u8 bool;\n"
+ "typedef struct { void *data; i64 len; } slice_;\n"
+ "#define false ((bool)0)\n"
+ "#define true ((bool)1)\n"
+ "#ifdef __linux__\n" /* see also toc.c */
+ "#define platform__ " stringify(PLATFORM_LINUX) "\n"
+ "#elif defined _WIN32\n"
+ "#define platform__ " stringify(PLATFORM_WINDOWS) "\n"
+ "#elif defined __APPLE__\n"
+ "#define platform__ " stringify(PLATFORM_OSX) "\n"
+ "#elif defined __FreeBSD__\n"
+ "#define platform__ " stringify(PLATFORM_FREEBSD) "\n"
+ "#elif defined __OpenBSD__\n"
+ "#define platform__ " stringify(PLATFORM_OPENBSD) "\n"
+ "#elif defined __unix__\n"
+ "#define platform__ " stringify(PLATFORM_MISC_UNIX) "\n"
+ "#else\n"
+ "#define platform__ " stringify(PLATFORM_OTHER) "\n"
+ "#endif\n"
+ "static slice_ mkslice_(void *data, i64 len) { slice_ ret; ret.data = data; ret.len = len; return ret; }\n");
cgen_write(g, "/* types */\n");
/* struct declarations */
arr_foreach(tr->all_structs, StructDefPtr, sdefp) {
@@ -2083,20 +2087,6 @@ static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
}
cgen_write(g, "/* code */\n");
- cgen_write(g, "int main(void) {\n");
- g->indent_lvl = 1;
- arr_foreach(tr->gctx->inits, Initialization, init) {
- Statement *s = &init->stmt;
- if (s->kind == STMT_EXPR) { /* these wouldn't be generated otherwise */
- cgen_expr(g, s->expr);
- cgen_writeln(g, ";");
- } else {
- cgen_stmt(g, s);
- }
- }
- cgen_nl(g);
- cgen_write(g, "main_();\n\treturn 0;\n}\n\n");
- g->indent_lvl = 0;
/* function definitions */
arr_foreach(tr->all_fns, FnWithCtx, fn_ctx) {
g->nms = fn_ctx->nms;
@@ -2106,7 +2096,13 @@ static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
g->nms = NULL;
g->block = NULL;
- arr_foreach(f->stmts, Statement, s) {
+ cgen_write(g, "int main(void) {\n");
+ g->indent_lvl = 1;
+ arr_foreach(tr->gctx->inits, Initialization, init) {
+ Statement *s = init->stmt;
cgen_stmt(g, s);
}
+ cgen_nl(g);
+ cgen_write(g, "main_();\n\treturn 0;\n}\n\n");
+ g->indent_lvl = 0;
}
diff --git a/copy.c b/copy.c
index 0adce52..b6716f5 100644
--- a/copy.c
+++ b/copy.c
@@ -348,6 +348,11 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
if (in->ret->flags & RET_HAS_EXPR)
copy_expr(c, &out->ret->expr, &in->ret->expr);
break;
+ case STMT_INCLUDE:
+ out->inc = copier_malloc(c, sizeof *out->inc);
+ *out->inc = *in->inc;
+ copy_expr(c, &out->inc->filename, &in->inc->filename);
+ break;
case STMT_EXPR:
out->expr = copy_expr_(c, in->expr);
break;
@@ -417,14 +422,9 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
case STMT_BLOCK:
copy_block(c, out->block = copier_malloc(c, sizeof *out->block), in->block, 0);
break;
- case STMT_INLINE_BLOCK: {
- size_t nstmts = arr_len(in->inline_block);
- out->inline_block = NULL;
- arr_set_lena(out->inline_block, nstmts, c->allocr);
- for (size_t i = 0; i < nstmts; ++i) {
- copy_stmt(c, &out->inline_block[i], &in->inline_block[i]);
- }
- } break;
+ case STMT_INLINE_BLOCK:
+ assert(0); /* only exists after typing */
+ break;
}
}
diff --git a/development.md b/development.md
index 9f0980c..6795987 100644
--- a/development.md
+++ b/development.md
@@ -26,7 +26,7 @@ Sometimes a type ending in Ptr is defined, e.g. typedef Declaration \*Declaratio
for the arr\_foreach macro, and not meant for normal use.
The fixed-width types U8/16/32/64 and I8/16/32/64 have been defined.
-data\_structures.c contains a dynamic array implementation and string hash table which are very useful.
+data\_structures.c contains a dynamic array implementation which is very useful.
### Notes
@@ -37,51 +37,3 @@ declaration).
It is assumed that the number of identifiers in a declaration, or parameters to a function
will fit in an int, since a function with (at least) 32768 parameters is ridiculous.
-### Miscellaneous thoughts
-
-#### includes during parsing
-Wouldn't it be nice if `#include` could be done during typing, so that the filename wouldn't have to be a
-string literal? Well, unfortunately we end up in situations like this:
-```
-asdf ::= fn() {
- x ::= bar();
- a: [x]int;
- // ...
-}
-#include "foo.toc"; // foo defined here
-bar ::= fn() int {
- return foo(17);
-}
-```
-The way we evaluate `bar()` is by typing the function `bar` when we come across it in the declaration `x ::= bar();`.
-In order to evaluate `foo`, we need to know what it refers to, and we don't know at this point that it comes from the
-include, because we haven't expanded it yet. We could potentially expand all includes preceding any function which
-is evaluated during typing, but that seems a bit cumbersome and would probably cause other problems.
-
-
-#### Why `#if` is complicated
-Allowing arbitrary `#if` conditions leads to the following problem:
-```
-bar1 ::= fn() bool { ... };
-bar2 ::= fn() bool { ... };
-foo1 ::= fn() bool { ... };
-foo2 ::= fn() bool { ... };
-
-#if foo() {
- bar ::= bar1;
-} else {
- bar ::= bar2;
-}
-
-#if bar() {
- foo ::= foo1;
-} else {
- foo ::= foo2;
-}
-```
-
-In order to determine which version of `bar` to use, we need to call `foo`, and in order to determine which version of `foo`
-to use, we need to call `bar`. You could just error on circular dependencies like these, but there is still the fact that you
-have to figure out where the declaration for `foo` is when `foo()` is evaluated, and it could be in some other `#if`. To
-avoid things getting complicated, we restrict `#if`s to make this situation impossible. While it's not ideal, it is necessary
-to avoid some edge cases where we can't find out which declaration you're referring to.
diff --git a/docs/00.html b/docs/00.html
index b32be13..7609f7b 100644
--- a/docs/00.html
+++ b/docs/00.html
@@ -66,6 +66,6 @@ x ::= 5+3;
y :: float = 5.123;
-Here, "constant" means constant at compile time, not read-only as it does in C. One interesting thing about toc is that normal functions can run at compile time, so pretty much any expression is a valid initializer for a constant, e.g. doing x ::= some_function(); runs some_function at compile time, not at run time.
+Here, "constant" means constant at compile time, not read-only as it does in C.