From 43408ef4df909452c7a10992daff911bab97040d Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum
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
.
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++, but it does break the standard in a few places*. So, MSVC can also compile it. The outputted code should be C99-compliant.
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, MSVC and g++
can also compile it (it does rely on implicit casting of void *
though). The outputted code should be C99-compliant.
toc
compiles to C for three reasons:
toc
compiles to C. Here are some reasons why:
The last three of those could all be removed fairly easily (assuming the system actually has 8-, 16-, 32-, and 64-bit signed and unsigned types).
-And here are all of its C11 features:
If you find a bug, you can report it through GitHub’s issue tracker, or by emailing pommicket@gmail.com.
Just send me the toc
source code which results in the bug, and I’ll try to fix it.
* for those curious, it has to do with goto
. In C, this program:
-int main() {
- goto label;
- int x = 5;
- label:
- return 0;
-}
-
-
-
-Is completely fine. x
will hold an unspecified value after the jump (but it isn’t used so it doesn’t really matter). Apparently, in C++, this is an ill-formed program. This is a bit ridiculous since
-int main() {
- goto label;
- int x; x = 5;
- label:
- return 0;
-}
-
-
-
-is fine. So that’s an interesting little “fun fact”: int x = 5;
isn’t always the same as int x; x = 5;
in C++.
-int main() {
- goto label;
- int x = 5;
- label:
- return 0;
-}
-
-Is completely fine. `x` will hold an unspecified value after the jump (but it isn't used so it doesn't really matter). Apparently, in C++, this is an ill-formed program. This is a bit ridiculous since
-
-int main() {
- goto label;
- int x; x = 5;
- label:
- return 0;
-}
-
-is fine. So that's an interesting little "fun fact": `int x = 5;` isn't always the same as `int x; x = 5;` in C++.
diff --git a/binfile.c b/binfile.c
index 11ebf9d..7f58736 100644
--- a/binfile.c
+++ b/binfile.c
@@ -1,9 +1,25 @@
-/* #define BINFILE_PORTABLE 1 */
+#define BINFILE_PORTABLE 1
+
+#ifdef TOC_DEBUG
+#define BINFILE_PRINT
+#endif
static inline void write_u8(FILE *fp, U8 u8) {
putc(u8, fp);
+#ifdef BINFILE_PRINT
+ static int col = 0;
+ printf("%02x ", u8);
+ ++col;
+ if (col == 8) printf(" ");
+ if (col == 16) {
+ col = 0;
+ printf("\n");
+ }
+#endif
}
+#undef BINFILE_PRINT /* don't need it anymore */
+
static inline void write_i8(FILE *fp, I8 i8) {
write_u8(fp, (U8)i8);
}
@@ -14,8 +30,8 @@ static inline void write_i8(FILE *fp, I8 i8) {
*/
static inline void write_u16(FILE *fp, U16 u16) {
- putc(u16 & 0xFF, fp);
- putc(u16 >> 8, fp);
+ write_u8(fp, (U8)(u16 & 0xFF));
+ write_u8(fp, (U8)(u16 >> 8));
}
static inline void write_i16(FILE *fp, I16 i16) {
@@ -76,14 +92,14 @@ static void write_f32(FILE *fp, F32 f32) {
f32 *= (F32)2;
fraction_bit >>= 1;
}
- putc(fraction & 0xFF, fp);
- putc((fraction & 0xFF00) >> 8, fp);
+ write_u8(fp, fraction & 0xFF);
+ write_u8(fp, (fraction & 0xFF00) >> 8);
unsigned byte3 = (fraction & 0x7F0000) >> 16;
byte3 |= (exponent & 1) << 7;
- putc((int)byte3, fp);
+ write_u8(fp, (U8)byte3);
unsigned byte4 = exponent >> 1;
byte4 |= (sign << 7);
- putc((int)byte4, fp);
+ write_u8(fp, (U8)byte4);
#else
fwrite(&f32, sizeof f32, 1, fp);
#endif
@@ -115,28 +131,27 @@ static void write_f64(FILE *fp, F64 f64) {
f64 *= (F64)2;
fraction_bit >>= 1;
}
- printf("%lu\n",fraction);
- putc(fraction & 0xFF, fp);
- putc((fraction & 0xFF00) >> 8, fp);
- putc((fraction & 0xFF0000) >> 16, fp);
- putc((fraction & 0xFF000000) >> 24, fp);
- putc((fraction & 0xFF00000000) >> 32, fp);
- putc((fraction & 0xFF0000000000) >> 40, fp);
+ write_u8(fp, fraction & 0xFF);
+ write_u8(fp, (fraction & 0xFF00) >> 8);
+ write_u8(fp, (fraction & 0xFF0000) >> 16);
+ write_u8(fp, (fraction & 0xFF000000) >> 24);
+ write_u8(fp, (fraction & 0xFF00000000) >> 32);
+ write_u8(fp, (fraction & 0xFF0000000000) >> 40);
unsigned byte7 = (fraction & 0xF000000000000) >> 48;
byte7 |= (exponent & 0xF) << 4;
- putc((int)byte7, fp);
+ write_u8(fp, (U8)byte7);
unsigned byte8 = (exponent & 0x7F0) >> 4;
byte8 |= (sign << 7);
- putc((int)byte8, fp);
+ write_u8(fp, (U8)byte8);
#else
fwrite(&f64, sizeof f64, 1, fp);
#endif
}
static void write_bool(FILE *fp, bool b) {
- putc(b, fp);
+ write_u8(fp, b);
}
static void write_char(FILE *fp, char c) {
- putc(c, fp);
+ write_u8(fp, (U8)c);
}
diff --git a/docs.sh b/docs.sh
index 87e4112..7dcf5e1 100755
--- a/docs.sh
+++ b/docs.sh
@@ -1,6 +1,7 @@
#!/bin/sh
markdown README.md > README.html
+echo README.md
for x in docs/*.md; do
- echo $x
markdown $x > $(dirname $x)/$(basename $x .md).html
+ echo $x
done
diff --git a/eval.c b/eval.c
index 2739564..cdbeee9 100644
--- a/eval.c
+++ b/eval.c
@@ -23,7 +23,6 @@ static void evalr_create(Evaluator *ev, Typer *tr, Allocator *allocr) {
static void evalr_free(Evaluator *ev) {
typedef void *VoidPtr;
arr_foreach(ev->to_free, VoidPtr, f) {
- printf("Freeing %p\n",*f);
free(*f);
}
arr_clear(&ev->to_free);
diff --git a/parse.c b/parse.c
index 9f7877f..8f24134 100644
--- a/parse.c
+++ b/parse.c
@@ -1789,69 +1789,73 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
goto ret_false;
}
- bool annotates_type = !token_is_kw(t->token, KW_EQ) && !token_is_kw(t->token, KW_COMMA);
- if (annotates_type) {
- d->flags |= DECL_ANNOTATES_TYPE;
- Type type;
- if (!parse_type(p, &type)) {
- goto ret_false;
- }
- d->type = type;
- if (type.kind == TYPE_TUPLE && arr_len(d->type.tuple) != arr_len(d->idents)) {
- err_print(d->where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents));
- goto ret_false;
- }
- }
- const char *end_str = NULL;
- switch (ends_with) {
- case DECL_END_SEMICOLON: end_str = "';'"; break;
- case DECL_END_RPAREN_COMMA: end_str = "')' or ','"; break;
- case DECL_END_LBRACE_COMMA: end_str = "'{' or ','"; break;
- }
-
- if (token_is_kw(t->token, KW_EQ)) {
- ++t->token;
- if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
- /* inferred expression */
- d->flags |= DECL_INFER;
- if (arr_len(d->idents) > 1) {
- err_print(d->where, "Inferred declarations can only have one identifier. Please separate this declaration.");
+ {
+ bool annotates_type = !token_is_kw(t->token, KW_EQ) && !token_is_kw(t->token, KW_COMMA);
+ if (annotates_type) {
+ d->flags |= DECL_ANNOTATES_TYPE;
+ Type type;
+ if (!parse_type(p, &type)) {
goto ret_false;
}
- if (!(d->flags & DECL_IS_CONST)) {
- tokr_err(t, "Inferred parameters must be constant.");
+ d->type = type;
+ if (type.kind == TYPE_TUPLE && arr_len(d->type.tuple) != arr_len(d->idents)) {
+ err_print(d->where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents));
goto ret_false;
}
+ }
+ }
+ {
+ const char *end_str = NULL;
+ switch (ends_with) {
+ case DECL_END_SEMICOLON: end_str = "';'"; break;
+ case DECL_END_RPAREN_COMMA: end_str = "')' or ','"; break;
+ case DECL_END_LBRACE_COMMA: end_str = "'{' or ','"; break;
+ }
+
+ if (token_is_kw(t->token, KW_EQ)) {
++t->token;
- } else {
- d->flags |= DECL_HAS_EXPR;
- uint16_t expr_flags = 0;
- if (ends_with == DECL_END_RPAREN_COMMA)
- expr_flags |= EXPR_CAN_END_WITH_COMMA;
- if (ends_with == DECL_END_LBRACE_COMMA)
- expr_flags |= EXPR_CAN_END_WITH_LBRACE;
- Token *end = expr_find_end(p, expr_flags);
- if (!end || !ends_decl(end, ends_with)) {
- t->token = end;
- tokr_err(t, "Expected %s at end of declaration.", end_str);
- goto ret_false;
- }
- if (!parse_expr(p, &d->expr, end)) {
- t->token = end; /* move to ; */
- goto ret_false;
- }
- if (ends_decl(t->token, ends_with)) {
+ if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
+ /* inferred expression */
+ d->flags |= DECL_INFER;
+ if (arr_len(d->idents) > 1) {
+ err_print(d->where, "Inferred declarations can only have one identifier. Please separate this declaration.");
+ goto ret_false;
+ }
+ if (!(d->flags & DECL_IS_CONST)) {
+ tokr_err(t, "Inferred parameters must be constant.");
+ goto ret_false;
+ }
++t->token;
} else {
- tokr_err(t, "Expected %s at end of declaration.", end_str);
- goto ret_false;
+ d->flags |= DECL_HAS_EXPR;
+ uint16_t expr_flags = 0;
+ if (ends_with == DECL_END_RPAREN_COMMA)
+ expr_flags |= EXPR_CAN_END_WITH_COMMA;
+ if (ends_with == DECL_END_LBRACE_COMMA)
+ expr_flags |= EXPR_CAN_END_WITH_LBRACE;
+ Token *end = expr_find_end(p, expr_flags);
+ if (!end || !ends_decl(end, ends_with)) {
+ t->token = end;
+ tokr_err(t, "Expected %s at end of declaration.", end_str);
+ goto ret_false;
+ }
+ if (!parse_expr(p, &d->expr, end)) {
+ t->token = end; /* move to ; */
+ goto ret_false;
+ }
+ if (ends_decl(t->token, ends_with)) {
+ ++t->token;
+ } else {
+ tokr_err(t, "Expected %s at end of declaration.", end_str);
+ goto ret_false;
+ }
}
+ } else if (ends_decl(t->token, ends_with)) {
+ ++t->token;
+ } else {
+ tokr_err(t, "Expected %s or '=' at end of delaration.", end_str);
+ goto ret_false;
}
- } else if (ends_decl(t->token, ends_with)) {
- ++t->token;
- } else {
- tokr_err(t, "Expected %s or '=' at end of delaration.", end_str);
- goto ret_false;
}
if ((d->flags & DECL_IS_CONST) && !(d->flags & DECL_HAS_EXPR) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) {
diff --git a/test.toc b/test.toc
index 0f46697..9f0e76c 100644
--- a/test.toc
+++ b/test.toc
@@ -1,4 +1,4 @@
#export foo :: f64 = 0.07321;
// asdf, dsajkhf, sadjkfh ::= 5;
// #export asdf ::= "asdfasdfasdf";
-#export zla := foo;
\ No newline at end of file
+#export zla, asdf := foo, 9;
\ No newline at end of file
diff --git a/toc.c b/toc.c
index 8544ef4..0bdbb1e 100644
--- a/toc.c
+++ b/toc.c
@@ -16,7 +16,6 @@
#include