summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c1
-rw-r--r--main.c2
-rw-r--r--test.toc16
-rw-r--r--types.c85
4 files changed, 63 insertions, 41 deletions
diff --git a/cgen.c b/cgen.c
index ba14ebb..b78c5e0 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1133,6 +1133,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
if (e->new.n) cgen_expr_pre(g, e->new.n);
break;
case EXPR_VAL:
+ /* TODO: don't make a variable for this if it's not needed */
if (type_is_compileonly(&e->type))
break;
cgen_val_pre(g, e->val, &e->type, e->where);
diff --git a/main.c b/main.c
index e4e1a18..f954e8c 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,8 @@
/*
TODO:
+remove Location from Type.
+fix x ::= fn_that_returns_array(); fn_that_takes_array(x);
#if
variadic fns
#foreign variadic fns
diff --git a/test.toc b/test.toc
index d442d91..f4a1cd6 100644
--- a/test.toc
+++ b/test.toc
@@ -1,10 +1,16 @@
#include "std/io.toc", io;
+Foo ::= struct (n ::= 12) {
+ x ::= n;
+};
+
+Bar ::= struct {
+ a ::= -1243.3;
+};
main ::= fn() {
- if 3 > 5 {
-
- } elif 45 > 32 {
- } else {
- }
+
+ io.puti(Foo(3).x);
+ io.puti(Foo().n);
+ io.puti(Bar.a as int);
};
diff --git a/types.c b/types.c
index 2f2a8e0..f10834c 100644
--- a/types.c
+++ b/types.c
@@ -1363,6 +1363,35 @@ static void get_builtin_val_type(Allocator *a, BuiltinVal val, Type *t) {
}
+/* gets a struct's constant or parameter, and puts it into e->val. */
+static Status get_struct_constant(StructDef *struc, Identifier member, Expression *e) {
+ Identifier i = ident_translate(member, &struc->scope.idents);
+ if (!i || i->decl_kind == IDECL_NONE) {
+ char *member_s = ident_to_str(member);
+ char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct";
+ err_print(e->where, "%s is not a member of structure %s.", member_s, struc_s);
+ info_print(struc->where, "struct was declared here.");
+ free(member_s);
+ if (struc->name) free(struc_s);
+ return false;
+ }
+ assert((i->decl_kind == IDECL_DECL) && (i->decl->flags & DECL_IS_CONST));
+ if (i->decl->flags & DECL_FOUND_VAL) {
+ /* replace with decl value */
+ int ident_idx = decl_ident_index(i->decl, i);
+ e->kind = EXPR_VAL;
+ e->flags = EXPR_FOUND_TYPE;
+ e->val = *decl_val_at_index(i->decl, ident_idx);
+ e->type = *decl_type_at_index(i->decl, ident_idx);
+ return true;
+ } else {
+ char *member_s = ident_to_str(member);
+ char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct";
+ err_print(e->where, "Cannot get value %s from struct %s. Are you missing parameters to this struct?", member_s, struc_s);
+ return false;
+ }
+}
+
static Status types_expr(Typer *tr, Expression *e) {
if (e->flags & EXPR_FOUND_TYPE) return true;
Type *t = &e->type;
@@ -2476,7 +2505,25 @@ static Status types_expr(Typer *tr, Expression *e) {
expr_kind_to_str(rhs->kind));
return false;
}
- if (struct_type->kind == TYPE_STRUCT) {
+ if (type_is_builtin(struct_type, BUILTIN_TYPE)) {
+ /* accessing struct constant/parameter with a Type */
+ Value lval = {0};
+ if (!eval_expr(tr->evalr, lhs, &lval))
+ return false;
+ lhs->kind = EXPR_VAL;
+ lhs->flags = EXPR_FOUND_TYPE;
+ lhs->val = lval;
+ Type *struc = lhs->val.type;
+ if (struc->kind != TYPE_STRUCT) {
+ char *s = type_to_str(struc);
+ err_print(lhs->where, "Cannot access member from non-struct type (%s).", s);
+ free(s);
+ return false;
+ }
+ if (!get_struct_constant(struc->struc, rhs->ident, e))
+ return false;
+ break;
+ } else if (struct_type->kind == TYPE_STRUCT) {
bool is_field = false;
arr_foreach(struct_type->struc->fields, Field, f) {
if (ident_eq(f->name, rhs->ident)) {
@@ -2486,42 +2533,8 @@ 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) {
- ident_idx = 0;
- arr_foreach(p->idents, Identifier, ident) {
- if (ident_eq(*ident, rhs->ident)) {
- param = p;
- goto dblbreak_dot;
- }
- ++ident_idx;
- }
- }
- dblbreak_dot:
- if (!param) {
- char *member = ident_to_str(rhs->ident);
- char *struc = type_to_str(struct_type);
- err_print(e->where, "%s is not a member of structure %s.", member, struc);
+ if (!get_struct_constant(struct_type->struc, rhs->ident, e))
return false;
- }
-#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(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) {