summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-22 14:32:49 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-22 14:32:49 -0500
commit7dfcdf50dda531095f1b1235fafa002457107e6c (patch)
tree6a5b9211b94f0c7abb9a64bedb3aee9e82603c65
parent48361dc5b443b9fb03a07ab7cfc51accedcad518 (diff)
more exporting
-rw-r--r--binfile.c31
-rw-r--r--export.c56
-rw-r--r--parse.c5
-rw-r--r--test.toc4
-rw-r--r--toc.c4
-rw-r--r--tokenizer.c8
-rw-r--r--types.c8
-rw-r--r--types.h12
8 files changed, 107 insertions, 21 deletions
diff --git a/binfile.c b/binfile.c
new file mode 100644
index 0000000..8a45084
--- /dev/null
+++ b/binfile.c
@@ -0,0 +1,31 @@
+#define BINFILE_PORTABLE 1
+
+static inline void write_u8(FILE *fp, U8 u8) {
+ putc(u8, fp);
+}
+
+/*
+ note: a bit of testing seems to reveal that the portable versions for u16/32 are faster than fwrite
+ (but this is not the case for u64).
+ */
+
+static inline void write_u16(FILE *fp, U16 u16) {
+ putc(u16 & 0xFF, fp);
+ putc(u16 >> 8, fp);
+}
+
+static inline void write_u32(FILE *fp, U32 u32) {
+ write_u16(fp, u32 & 0xFFFF);
+ write_u16(fp, (U16)(u32 >> 16));
+}
+
+static void write_u64(FILE *fp, U64 u64) {
+#if BINFILE_PORTABLE
+ write_u32(fp, u64 & 0xFFFFFFFF);
+ write_u32(fp, (U32)(u64 >> 32));
+#else
+ fwrite(&u64, sizeof u64, 1, fp);
+#endif
+}
+
+
diff --git a/export.c b/export.c
index 422bed4..571701e 100644
--- a/export.c
+++ b/export.c
@@ -1,5 +1,39 @@
+/*
+ Copyright (C) 2019 Leo Tenenbaum.
+ This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
+ You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
+*/
static void exptr_create(Exporter *exptr, FILE *out) {
exptr->out = out;
+ exptr->export_locations = true;
+}
+
+static void export_u8(Exporter *ex, U8 u8) {
+ write_u8(ex->out, u8);
+}
+
+static void export_u16(Exporter *ex, U16 u16) {
+ write_u16(ex->out, u16);
+}
+
+static void export_u32(Exporter *ex, U32 u32) {
+ write_u32(ex->out, u32);
+}
+
+static void export_u64(Exporter *ex, U64 u64) {
+ write_u64(ex->out, u64);
+}
+
+static void export_location(Exporter *ex, Location where) {
+ if (ex->export_locations) {
+ export_u32(ex, where.line);
+ export_u32(ex, where.pos);
+ }
+}
+
+static void export_ident(Exporter *ex, Identifier i) {
+ assert(i->id);
+ export_u64(ex, i->id);
}
static bool export_decl(Exporter *ex, Declaration *d) {
@@ -7,6 +41,26 @@ static bool export_decl(Exporter *ex, Declaration *d) {
err_print(d->where, "Trying to export declaration, but a package output was not specified.");
return false;
}
- putc((int)(d->idents[0]->id % 256), ex->out);
+ export_location(ex, d->where);
+ if (arr_len(d->idents) > 65535) {
+ err_print(d->where, "Too many identifiers in a declaration (the maximum is 65535).");
+ return false;
+ }
+ export_u16(ex, (U16)arr_len(d->idents));
+ arr_foreach(d->idents, Identifier, ident) {
+ export_ident(ex, *ident);
+ }
+
+ U8 constness = 0;
+ if (d->flags & DECL_IS_CONST) constness = 1;
+ else if (d->flags & DECL_SEMI_CONST) constness = 2;
+ export_u8(ex, constness);
+
+ U8 expr_kind = 0;
+ if (d->flags & DECL_HAS_EXPR) expr_kind = 1; /* export expression */
+ if (d->flags & DECL_FOUND_VAL) expr_kind = 2; /* export value */
+ export_u8(ex, expr_kind);
+
+
return true;
}
diff --git a/parse.c b/parse.c
index 18f3e39..23bad30 100644
--- a/parse.c
+++ b/parse.c
@@ -1737,14 +1737,15 @@ static inline bool ends_decl(Token *t, DeclEndKind ends_with) {
}
static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 flags) {
- d->where = p->tokr->token->where;
- d->idents = NULL;
Tokenizer *t = p->tokr;
+ d->where = t->token->where;
+ d->idents = NULL;
d->flags = 0;
if ((flags & PARSE_DECL_ALLOW_EXPORT) && token_is_direct(t->token, DIRECT_EXPORT)) {
d->flags |= DECL_EXPORT;
++t->token;
+ d->where = t->token->where;
}
while (1) {
diff --git a/test.toc b/test.toc
index ffac0c2..edb175d 100644
--- a/test.toc
+++ b/test.toc
@@ -1,2 +1,2 @@
-#export
-asdf ::= 5; \ No newline at end of file
+foo ::= 7;
+#export asdf, dsajkhf, sadjkfh ::= 5; \ No newline at end of file
diff --git a/toc.c b/toc.c
index dd8f4ac..a60d667 100644
--- a/toc.c
+++ b/toc.c
@@ -24,6 +24,7 @@
/* forward declarations for debugging */
static void print_val(Value v, Type *t);
+/* utilities */
#include "allocator.c"
#include "arr.c"
#include "location.c"
@@ -33,13 +34,12 @@ static void print_val(Value v, Type *t);
#include "str.c"
#include "instance_table.c"
#include "copy.c"
+#include "binfile.c"
#include "identifiers.c"
#include "tokenizer.c"
#include "parse.c"
#include "scope.c"
-
-
#include "eval.c"
#include "infer.c"
#include "export.c"
diff --git a/tokenizer.c b/tokenizer.c
index 6423eed..5d245d9 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -150,7 +150,7 @@ static void tokenization_err(Tokenizer *t, const char *fmt, ...) {
Location where;
where.line = t->line;
where.ctx = t->err_ctx;
- where.pos = (CodePos)(t->s - where.ctx->str);
+ where.pos = (U32)(t->s - where.ctx->str);
va_start(args, fmt);
err_vprint(where, fmt, args);
va_end(args);
@@ -189,7 +189,7 @@ static void tokr_err_(
static void tokr_put_location(Tokenizer *tokr, Token *t) {
t->where.line = tokr->line;
t->where.ctx = tokr->err_ctx;
- t->where.pos = (CodePos)(tokr->s - t->where.ctx->str);
+ t->where.pos = (U32)(tokr->s - t->where.ctx->str);
}
static void tokr_get_location(Tokenizer *tokr, Token *t) {
@@ -278,7 +278,7 @@ static bool tokenize_string(Tokenizer *t, char *str) {
/* it's a directive */
Token *token = tokr_add(t);
tokr_put_location(t, token);
- token->where.pos = (CodePos)(start_s - token->where.ctx->str);
+ token->where.pos = (U32)(start_s - token->where.ctx->str);
token->kind = TOKEN_DIRECT;
token->direct = direct;
continue;
@@ -295,7 +295,7 @@ static bool tokenize_string(Tokenizer *t, char *str) {
/* it's a keyword */
Token *token = tokr_add(t);
tokr_put_location(t, token);
- token->where.pos = (CodePos)(start_s - token->where.ctx->str);
+ token->where.pos = (U32)(start_s - token->where.ctx->str);
token->kind = TOKEN_KW;
token->kw = kw;
continue;
diff --git a/types.c b/types.c
index 9bde9e1..075c8de 100644
--- a/types.c
+++ b/types.c
@@ -2022,9 +2022,11 @@ static bool types_decl(Typer *tr, Declaration *d) {
/* pretend we found the type even if we didn't to prevent too many errors */
d->flags |= DECL_FOUND_TYPE;
if (success) {
- /* export it! */
- if (!export_decl(tr->exptr, d))
- success = false;
+ if (d->flags & DECL_EXPORT) {
+ /* export it! */
+ if (!export_decl(tr->exptr, d))
+ success = false;
+ }
} else {
/* use unknown type if we didn't get the type */
d->type.flags = TYPE_IS_RESOLVED;
diff --git a/types.h b/types.h
index 245e6a0..3fd0fa2 100644
--- a/types.h
+++ b/types.h
@@ -50,10 +50,7 @@ typedef double F64;
#define F32_FMT "%.16f"
#define F64_FMT "%.16f"
-typedef U32 IdentID; /* identifier ID for cgen (anonymous variables) */
-
-typedef U32 LineNo;
-typedef U32 CodePos;
+typedef U32 IdentID; /* identifier ID for cgen (anonymous variables). not to be confused with IdentTree.id */
#define join(a,b) a##b
@@ -70,8 +67,8 @@ typedef U32 CodePos;
typedef struct Location {
- LineNo line;
- CodePos pos; /* position in ctx->str */
+ U32 line;
+ U32 pos; /* position in ctx->str */
struct ErrCtx *ctx;
} Location;
@@ -304,7 +301,7 @@ typedef struct Tokenizer {
Token *tokens;
char *s; /* string being parsed */
ErrCtx *err_ctx;
- LineNo line;
+ U32 line;
Token *token; /* token currently being processed */
Identifiers *idents;
} Tokenizer;
@@ -733,6 +730,7 @@ typedef struct Typer {
typedef struct Exporter {
FILE *out; /* .top (toc package) to output to */
+ bool export_locations;
} Exporter;
typedef struct CGenerator {