summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-17 16:16:23 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-17 16:16:23 -0400
commit3b28d9cb8a760bc0ee2e49cd6f96dc6014afb9ba (patch)
treefa8a92fee3e283f0827de560bebbb4c6fe472345
parentc147565ad06a23b13d0ac7c7e8fa6f449beb4ebe (diff)
started defer
-rw-r--r--Makefile7
-rw-r--r--README.md2
-rw-r--r--cgen.c3
-rw-r--r--copy.c3
-rw-r--r--decls_cgen.c6
-rw-r--r--parse.c11
-rw-r--r--test.toc4
-rw-r--r--toc.c1
-rw-r--r--types.c8
-rw-r--r--types.h7
10 files changed, 47 insertions, 5 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f568f2a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+toc: *.[ch]
+ ./build.sh
+release: *.[ch]
+ ./build.sh release
+
+clean:
+ rm toc
diff --git a/README.md b/README.md
index 0bd8f54..f409b19 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ See `docs` for more information (in progress).
`tests` has some test programs written in `toc`.
-To compile the compiler on a Unix-y system, just run `./build.sh release`. You can supply a compiler by running `CC=tcc ./build.sh release`, or build it in debug mode without the `release`. To disable compile time foreign function support (which you will need to do if you don't have ffcall/dl), prefix this with `COMPILE_TIME_FOREIGN_FN_SUPPORT=no`.
+To compile the compiler on a Unix-y system, just run `./build.sh release` (or `make release`). You can supply a compiler by running `CC=tcc ./build.sh release`, or build it in debug mode without the `release`. To disable compile time foreign function support (which you will need to do if you don't have ffcall/dl), prefix this with `COMPILE_TIME_FOREIGN_FN_SUPPORT=no`.
On other systems, you can just compile main.c with a C compiler. `toc` uses several C99 and a couple of C11 features, so it might not work on all compilers. But it does compile on quite a few, including `clang`, `gcc`, and `tcc`. It can also be compiled as if it were C++, so and `g++` can also compile it (it does rely on implicit casting of `void *` though). MSVC can also compile toc. The *outputted* code should be C99-compliant.
diff --git a/cgen.c b/cgen.c
index d1ebab7..3595ed4 100644
--- a/cgen.c
+++ b/cgen.c
@@ -2067,6 +2067,9 @@ static void cgen_defs_stmt(CGenerator *g, Statement *s) {
case STMT_CONT:
case STMT_MESSAGE:
break;
+ case STMT_DEFER:
+ cgen_defs_stmt(g, s->defer);
+ break;
}
}
diff --git a/copy.c b/copy.c
index f99d880..3919e46 100644
--- a/copy.c
+++ b/copy.c
@@ -433,6 +433,9 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
case STMT_MESSAGE:
copy_expr(c, &out->message.text, &in->message.text);
break;
+ case STMT_DEFER:
+ copy_stmt(c, out->defer = allocr_malloc(c->allocr, sizeof *out->defer), in->defer);
+ break;
case STMT_BREAK:
case STMT_CONT:
break;
diff --git a/decls_cgen.c b/decls_cgen.c
index 371d91f..048dd9d 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -159,6 +159,9 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) {
break;
case STMT_MESSAGE:
break;
+ case STMT_DEFER:
+ cgen_sdecls_stmt(g, s->defer);
+ break;
}
}
@@ -430,6 +433,9 @@ static void cgen_decls_stmt(CGenerator *g, Statement *s) {
case STMT_CONT:
case STMT_MESSAGE:
break;
+ case STMT_DEFER:
+ cgen_decls_stmt(g, s->defer);
+ break;
}
}
diff --git a/parse.c b/parse.c
index 290bb5d..7c6fe7d 100644
--- a/parse.c
+++ b/parse.c
@@ -2448,6 +2448,13 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
return false;
}
goto success;
+ case KW_DEFER:
+ s->kind = STMT_DEFER;
+ ++t->token;
+ s->defer = parser_malloc(p, sizeof *s->defer);
+ if (!parse_stmt(p, s->defer, was_a_statement))
+ return false;
+ goto success;
default: break;
}
} else if (t->token->kind == TOKEN_DIRECT) {
@@ -2932,6 +2939,10 @@ static void fprint_stmt(FILE *out, Statement *s) {
case STMT_CONT:
fprintf(out, "continue;");
break;
+ case STMT_DEFER:
+ fprintf(out, "defer ");
+ fprint_stmt(out, s->defer);
+ break;
}
}
diff --git a/test.toc b/test.toc
index f953cfe..66dfe61 100644
--- a/test.toc
+++ b/test.toc
@@ -1,3 +1,5 @@
+#include "std/io.toc";
main ::= fn() {
- x ::= {return; 3}
+ defer puts("bye");
+ puts("hello");
}
diff --git a/toc.c b/toc.c
index 75c25b1..6c1932d 100644
--- a/toc.c
+++ b/toc.c
@@ -4,7 +4,6 @@
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-
/*
NOTE:
Structure of the toc compiler:
diff --git a/types.c b/types.c
index 2d2d63a..9766997 100644
--- a/types.c
+++ b/types.c
@@ -3395,6 +3395,14 @@ static Status types_stmt(Typer *tr, Statement *s) {
return false;
}
} break;
+ case STMT_DEFER:
+ if (!types_stmt(tr, s->defer))
+ return false;
+ if (s->defer->kind == STMT_DEFER) {
+ err_print(s->where, "You can't defer a defer!");
+ return false;
+ }
+ break;
}
s->flags |= STMT_TYPED;
return true;
diff --git a/types.h b/types.h
index fbd3386..b2efa50 100644
--- a/types.h
+++ b/types.h
@@ -298,6 +298,7 @@ typedef enum {
KW_RETURN,
KW_BREAK,
KW_CONTINUE,
+ KW_DEFER,
KW_FN,
KW_AS,
KW_STRUCT,
@@ -333,7 +334,7 @@ static const char *const keywords[KW_COUNT] =
"+", "-", "*", "!", "&", "/", "%", "..", ".",
"=",
"if", "elif", "else", "while", "for", "return", "break",
- "continue", "fn", "as", "struct",
+ "continue", "defer", "fn", "as", "struct",
"int", "i8", "i16", "i32", "i64",
"u8", "u16", "u32", "u64", "float", "f32", "f64", "Type",
"Namespace",
@@ -913,7 +914,8 @@ typedef enum {
STMT_BREAK,
STMT_CONT,
STMT_INCLUDE,
- STMT_MESSAGE
+ STMT_MESSAGE,
+ STMT_DEFER
} StatementKind;
enum {
@@ -978,6 +980,7 @@ typedef struct Statement {
Include inc;
Message message; /* #error, #warn, #info */
Block *referring_to; /* for break/continue; set during typing */
+ struct Statement *defer;
};
} Statement;