summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-01 15:47:55 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-01 15:47:55 -0500
commit8929fa724f66d3d653cd1b9d4bd119c31697d3f2 (patch)
tree42792ea21752fc7eefdf0662a7f5571d52b872fb
parent825c98523b8a03733579df33247ab87dae4e3408 (diff)
constants in structs
-rw-r--r--copy.c7
-rw-r--r--main.c20
-rw-r--r--parse.c45
-rwxr-xr-xtest-build.sh8
-rw-r--r--test.toc11
-rw-r--r--types.c27
-rw-r--r--types.h4
7 files changed, 87 insertions, 35 deletions
diff --git a/copy.c b/copy.c
index e0306e8..0699474 100644
--- a/copy.c
+++ b/copy.c
@@ -100,6 +100,13 @@ static void copy_struct(Copier *c, StructDef *out, StructDef *in) {
for (size_t i = 0; i < nparams; ++i) {
copy_decl(c, &out->params[i], &in->params[i]);
}
+ out->constants = NULL;
+ size_t nconstants = arr_len(in->constants);
+ arr_set_lena(&out->constants, nconstants, c->allocr);
+ for (size_t i = 0; i < nconstants; ++i) {
+ copy_decl(c, &out->constants[i], &in->constants[i]);
+ }
+
c->block = prev;
}
diff --git a/main.c b/main.c
index 41114a0..e4e1a18 100644
--- a/main.c
+++ b/main.c
@@ -8,14 +8,17 @@
/*
TODO:
-constants in structs
#if
variadic fns
#foreign variadic fns
#returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf)
-switch to / add as an alternative: libffi
-
+break
+continue
+switch
+enums
+macros
---
+switch to / add as an alternative: libffi
X ::= newtype(int); or something
don't allow while {3; 5} or for 0..10 { 3; 5 } (once break is added)
do we need was_expr? (now that, presumably, we have struct arguments)
@@ -79,12 +82,17 @@ int main(int argc, char **argv) {
err_ctx.color_enabled = true;
for (int i = 1; i < argc; ++i) {
- if (i > 1 && strs_equal(argv[i-1], "-o")) {
- out_filename = argv[i];
- } else if ((i == 1 || argv[i-1][0] != '-') && argv[i][0] != '-') {
+ if ((i == 1 || argv[i-1][0] != '-') && argv[i][0] != '-') {
in_filename = argv[i];
} else if (strs_equal(argv[i], "-no-color")) {
err_ctx.color_enabled = false;
+ } else if (strs_equal(argv[i], "-o")) {
+ if (i == argc-1) {
+ fprintf(stderr, "-o cannot be the last argument to toc.\n");
+ return EXIT_FAILURE;
+ }
+ out_filename = argv[i+1];
+ ++i;
} else {
fprintf(stderr, "Unrecognized option: %s.\n", argv[i]);
return EXIT_FAILURE;
diff --git a/parse.c b/parse.c
index bad5956..bdd7608 100644
--- a/parse.c
+++ b/parse.c
@@ -9,7 +9,8 @@ enum {
PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR = 0x01,
PARSE_DECL_ALLOW_SEMI_CONST = 0x02,
PARSE_DECL_ALLOW_INFER = 0x04,
- PARSE_DECL_ALLOW_EXPORT = 0x08
+ PARSE_DECL_ALLOW_EXPORT = 0x08,
+ PARSE_DECL_DONT_SET_IDECLS = 0x10
};
static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_t flags);
static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end);
@@ -597,6 +598,7 @@ static Status parse_type(Parser *p, Type *type) {
struc->c.id = 0;
struc->fields = NULL;
struc->params = NULL;
+ struc->constants = NULL;
struc->where = parser_mk_loc(p);
struc->where.start = t->token;
memset(&struc->scope, 0, sizeof struc->scope);
@@ -637,26 +639,33 @@ static Status parse_type(Parser *p, Type *type) {
{
while (!token_is_kw(t->token, KW_RBRACE)) {
Declaration field_decl;
- if (!parse_decl(p, &field_decl, DECL_END_SEMICOLON, 0)) {
+ if (!parse_decl(p, &field_decl, DECL_END_SEMICOLON, PARSE_DECL_DONT_SET_IDECLS)) {
goto struct_fail;
}
if (field_decl.flags & DECL_IS_CONST) {
- /* TODO */
- err_print(field_decl.where, "Constant struct members are not supported (yet).");
- goto struct_fail;
- }
- if (field_decl.flags & DECL_HAS_EXPR) {
- err_print(field_decl.where, "struct members cannot have initializers.");
- goto struct_fail;
+ Declaration *d = parser_arr_add(p, &struc->constants);
+ *d = field_decl;
+ } else {
+ if (field_decl.flags & DECL_HAS_EXPR) {
+ err_print(field_decl.where, "struct members cannot have initializers.");
+ goto struct_fail;
+ }
+ long idx = 0;
+ arr_foreach(field_decl.idents, Identifier, fident) {
+ Type *ftype = field_decl.type.kind == TYPE_TUPLE ? &field_decl.type.tuple[idx] : &field_decl.type;
+ Field *f = parser_arr_add(p, &struc->fields);
+ f->name = *fident;
+ f->where = field_decl.where;
+ f->type = *ftype;
+ ++idx;
+ }
}
- long idx = 0;
- arr_foreach(field_decl.idents, Identifier, fident) {
- Type *ftype = field_decl.type.kind == TYPE_TUPLE ? &field_decl.type.tuple[idx] : &field_decl.type;
- Field *f = parser_arr_add(p, &struc->fields);
- f->name = *fident;
- f->where = field_decl.where;
- f->type = *ftype;
- ++idx;
+ }
+ arr_foreach(struc->constants, Declaration, c) {
+ arr_foreach(c->idents, Identifier, ip) {
+ Identifier i = *ip;
+ i->decl = c;
+ i->decl_kind = IDECL_DECL;
}
}
++t->token;
@@ -2181,7 +2190,7 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f
goto ret_false;
}
*ident = parser_ident_insert(p, t->token->ident);
- if (!ident_eq_str(*ident, "_")) {
+ if (!(flags & PARSE_DECL_DONT_SET_IDECLS) && !ident_eq_str(*ident, "_")) {
Identifier i = *ident;
if (!check_ident_redecl(p, i))
goto ret_false;
diff --git a/test-build.sh b/test-build.sh
index 38f667a..370e329 100755
--- a/test-build.sh
+++ b/test-build.sh
@@ -1,8 +1,8 @@
#!/bin/sh
for CC in tcc gcc clang g++ ; do
- CC="$CC" ./build.sh || exit 1
- CC="$CC" ./build.sh release || exit 1
+ CC="$CC" CFLAGS='-Werror' ./build.sh || exit 1
+ CC="$CC" CFLAGS='-Werror' ./build.sh release || exit 1
done
-./build.sh release || exit 1
-./build.sh || exit 1
+CFLAGS='-Werror' ./build.sh release || exit 1
+CFLAGS='-Werror' ./build.sh || exit 1
diff --git a/test.toc b/test.toc
index 1e41663..43ed69b 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,15 @@
#include "std/io.toc", io;
+Foo ::= struct(n::=12) {
+ x ::= (n as float)*2.3;
+};
main ::= fn() {
- io.puts("Hello!");
- io.puti(17);
+ f : Foo();
+ io.puti(f.n);
+ io.puti(f.x as int);
+ g : Foo(3);
+ io.puti(g.n);
+ io.puti(g.x as int);
};
main(); \ No newline at end of file
diff --git a/types.c b/types.c
index 7b323b0..c518768 100644
--- a/types.c
+++ b/types.c
@@ -81,7 +81,7 @@ static Status struct_find_offsets(StructDef *s) {
}
s->flags |= STRUCT_DEF_FINDING_OFFSETS;
size_t bytes = 0;
- size_t total_align = 0;
+ size_t total_align = 1;
arr_foreach(s->fields, Field, f) {
size_t size = compiler_sizeof(&f->type);
if (size == SIZE_MAX) {
@@ -768,6 +768,12 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
return false;
}
}
+ arr_foreach(t->struc->constants, Declaration, c) {
+ if (!types_decl(tr, c)) {
+ typer_block_exit(tr);
+ return false;
+ }
+ }
typer_block_exit(tr);
assert(tr->block != &t->struc->scope);
t->struc->instance_id = 0;
@@ -2480,6 +2486,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
if (!is_field) {
+#if 0
Declaration *param = NULL;
int ident_idx;
arr_foreach(struct_type->struc->params, Declaration, p) {
@@ -2499,10 +2506,22 @@ static Status types_expr(Typer *tr, Expression *e) {
err_print(e->where, "%s is not a member of structure %s.", member, struc);
return false;
}
- /* replace with parameter value */
+#endif
+ Identifier i = ident_translate(rhs->ident, &struct_type->struc->scope.idents);
+ if (!i || i->decl_kind == IDECL_NONE) {
+ char *member = ident_to_str(rhs->ident);
+ char *struc_s = type_to_str(struct_type);
+ err_print(e->where, "%s is not a member of structure %s.", member, struc_s);
+ free(member);
+ free(struc_s);
+ return false;
+ }
+ assert((i->decl_kind == IDECL_DECL) && (i->decl->flags & DECL_IS_CONST));
+ /* replace with decl value */
+ int ident_idx = decl_ident_index(i->decl, i);
e->kind = EXPR_VAL;
- e->val = *decl_val_at_index(param, ident_idx);
- *t = *decl_type_at_index(param, ident_idx);
+ e->val = *decl_val_at_index(i->decl, ident_idx);
+ *t = *decl_type_at_index(i->decl, ident_idx);
break;
}
} else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR) {
diff --git a/types.h b/types.h
index b7c1b0b..f3fa76c 100644
--- a/types.h
+++ b/types.h
@@ -501,9 +501,10 @@ enum {
};
typedef struct StructDef {
Field *fields;
+ struct Declaration *constants;
Location where;
U8 flags;
- Block scope; /* to make sure that parameters live somewhere. fields are not kept here. */
+ Block scope; /* to make sure that parameters and constants live somewhere. fields are not kept here. */
union {
HashTable instances;
struct {
@@ -831,6 +832,7 @@ typedef struct Expression {
};
} Expression;
+
typedef struct Argument {
Location where;
char *name; /* NULL = no name */