aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c598
-rw-r--r--src/debug.c5
-rw-r--r--src/lower.c17
-rw-r--r--src/parser.y4
-rw-r--r--src/scope.c54
-rw-r--r--src/vec.c5
6 files changed, 414 insertions, 269 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 7d30a0f..39f3ae3 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -15,6 +15,7 @@
#include <ek/actualize.h>
#include <ek/compiler.h>
#include <ek/debug.h>
+#include <ek/vec.h>
#define UNUSED(x) do { (void)(x); } while (0)
@@ -53,6 +54,54 @@ static int actualize_type(struct act_state *state, struct scope *scope,
static int actualize_type_list(struct act_state *state, struct scope *scope,
struct type *node);
+static struct ast *actualized_scope_find_symbol(struct act_state *state, struct scope *scope, char *id)
+{
+ struct ast *exists = scope_find_symbol(scope, id);
+ if (!exists)
+ return NULL;
+
+ if (!exists->t && actualize(state, exists->scope, exists))
+ return NULL;
+
+ return exists;
+}
+
+static struct ast *actualized_scope_find_type(struct act_state *state, struct scope *scope, char *id)
+{
+ struct ast *exists = scope_find_symbol(scope, id);
+ if (!exists)
+ return NULL;
+
+ if (!exists->t && actualize(state, exists->scope, exists))
+ return NULL;
+
+ return exists;
+}
+
+static struct ast *actualized_file_scope_find_symbol(struct act_state *state, struct scope *scope, char *id)
+{
+ struct ast *exists = file_scope_find_symbol(scope, id);
+ if (!exists)
+ return NULL;
+
+ if (!exists->t && actualize(state, exists->scope, exists))
+ return NULL;
+
+ return exists;
+}
+
+static struct ast *actualized_file_scope_find_type(struct act_state *state, struct scope *scope, char *id)
+{
+ struct ast *exists = file_scope_find_type(scope, id);
+ if (!exists)
+ return NULL;
+
+ if (!exists->t && actualize(state, exists->scope, exists))
+ return NULL;
+
+ return exists;
+}
+
static int is_lvalue(struct ast *n)
{
if (n->k == AST_ARR)
@@ -336,15 +385,10 @@ static int analyze_visibility(struct scope *scope, struct ast *node)
return 0;
}
-static int analyze_var(struct scope *scope, struct ast *node)
-{
- struct act_state state = {0};
- return actualize(&state, scope, node);
-}
-
-static void set_type(struct ast *node, struct type *type)
+static int set_type(struct ast *node, struct type *type)
{
node->t = clone_type_list(type);
+ return node->t == NULL;
}
/* important to keep in mind that this does not maintain list state, must be
@@ -416,8 +460,7 @@ static int analyze_proc(struct scope *scope, struct ast *node)
type_append(callable_ptypes(callable), p->t);
}
- set_type(node, callable);
- return 0;
+ return set_type(node, callable);
}
static struct ast *analyze_type_expand(struct scope *scope,
@@ -445,6 +488,7 @@ static struct ast *analyze_type_expand(struct scope *scope,
replace_type_id(body, var_id(pt), pa);
pa = pa->n;
}
+
return body;
}
@@ -456,113 +500,9 @@ static int implements_trait(struct ast *body, char *id)
continue;
if (same_id(id_str(n), id))
- return 1;
- }
-
- return 0;
-}
-
-static int analyze_struct(struct scope *scope, struct ast *node)
-{
- assert(node->k == AST_STRUCT_DEF);
- struct ast *params = struct_params(node);
- struct scope *struct_scope = create_scope();
- if (!struct_scope)
- return -1;
-
- scope_add_scope(node->scope, struct_scope);
- node->scope = struct_scope;
- if (params)
- ast_set_flags(node, AST_FLAG_GENERIC);
-
- struct type *type = tgen_type(TYPE_STRUCT,
- NULL, NULL,
- node, NULL,
- strdup(struct_id(node)),
- node->loc);
-
- foreach_node(n, struct_body(node)) {
- if (n->k != AST_TYPE_EXPAND)
- continue;
-
- if (implements_trait(struct_body(node), type_expand_id(n))) {
- n->k = AST_EMPTY;
- continue;
- }
-
- if (same_id(struct_id(node), type_expand_id(n))) {
- semantic_error(scope->fctx, n,
- "recursive trait implementations not allowed");
- return -1;
- }
-
- struct ast *body = analyze_type_expand(scope, n);
- if (!body) {
- n->k = AST_EMPTY;
- continue;
- }
-
- replace_type_id(body, type_expand_id(n), type);
- ast_block_last(body)->n = n->n;
- n->n = body;
- }
-
- foreach_node(n, struct_body(node)) {
- switch (n->k) {
- case AST_EMPTY: continue;
- case AST_ID: continue;
- /* prototypes are checked later */
- case AST_PROC_DEF: if (!proc_body(n)) continue;
- default:
- }
-
- if (analyze_visibility(struct_scope, n))
return -1;
}
- foreach_node(n, struct_body(node)) {
- /* also checks prototypes */
- if (n->k != AST_PROC_DEF)
- continue;
-
- if (analyze_proc(struct_scope, n))
- return -1;
- }
-
- /* check that all prototypes are implemented */
- foreach_node(n, struct_body(node)) {
- if (n->k != AST_PROC_DEF)
- continue;
-
- if (proc_body(n))
- continue;
-
- struct ast *proc = scope_find_proc(struct_scope, proc_id(n));
- if (!proc) {
- semantic_error(scope->fctx, n,
- "missing implementation");
- return -1;
- }
-
- if (!types_match(n->t, proc->t)) {
- semantic_error(scope->fctx, n, "mismatched signatures");
- semantic_info(scope->fctx, proc, "note: here");
- return -1;
- }
- }
-
- char *id = strdup(struct_id(node));
- if (same_id(id, "i27"))
- node->t = tgen_primitive(TYPE_I27, id, node, node->loc);
- else if (same_id(id, "i9"))
- node->t = tgen_primitive(TYPE_I9, id, node, node->loc);
- else if (same_id(id, "bool"))
- node->t = tgen_primitive(TYPE_BOOL, id, node, node->loc);
- else
- node->t = tgen_struct(id, node, node->loc);
-
- /** @todo there is the possibility that two different traits add the
- * same prototype, which is reported in traits but not structs? */
return 0;
}
@@ -664,35 +604,11 @@ static int analyze_trait(struct scope *scope, struct ast *node)
node->t = tgen_trait(strdup(struct_id(node)), node, node->loc);
- return 0;
-}
-
-static int analyze_signs(struct scope *scope, struct ast *node)
-{
- /** @todo aliases? */
- switch (node->k) {
- case AST_VAR_DEF: return analyze_var(scope, node); break;
- case AST_PROC_DEF: return analyze_proc(scope, node); break;
- case AST_STRUCT_DEF: return analyze_struct(scope, node); break;
- case AST_TRAIT_DEF: return analyze_trait(scope, node); break;
- default:
- }
-
- return 0;
+ return node->t == NULL;
}
static int analyze(struct scope *scope, struct ast *tree)
{
- foreach_node(node, tree) {
- if (analyze_visibility(scope, node))
- return -1;
- }
-
- foreach_node(node, tree) {
- if (analyze_signs(scope, node))
- return -1;
- }
-
foreach_node(node, tree){
struct act_state state = {0};
if (actualize(&state, scope, node))
@@ -839,8 +755,14 @@ static int actualize_macro_expand(struct act_state *state,
free(macro_expand_id(macro_expand));
replace_ast(macro_expand, body);
+
/* actualize the new content */
- return actualize(state, scope, macro_expand);
+ if (actualize(state, scope, macro_expand)) {
+ semantic_info(scope->fctx, macro_expand, "while expanding %s", id);
+ return -1;
+ }
+
+ return 0;
}
static int simplify_refderef(struct act_state *state, struct scope *scope, struct ast *n)
@@ -871,6 +793,8 @@ static int maybe_ufcs(struct act_state *state, struct scope *scope, struct ast *
struct ast *expr = dot_expr(dot);
call_expr(call) = gen_fetch(dot_id(dot), clone_type(expr->t), dot->loc);
+ (call_expr(call))->t = clone_type(dot->t);
+ (call_expr(call))->scope = scope;
/* hard core type */
struct ast *ref = gen_unop(AST_REF, expr, dot->loc);
@@ -880,7 +804,7 @@ static int maybe_ufcs(struct act_state *state, struct scope *scope, struct ast *
if (simplify_refderef(state, scope, ref))
return -1;
- ast_prepend(call_args(call), ref);
+ call_args(call) = ast_prepend(call_args(call), ref);
return 0;
}
@@ -978,6 +902,32 @@ static int actualize_proc(struct act_state *state,
struct act_state new_state = {0};
/* params should already have been actualized, should maybe check */
+ if (actualize_list(&new_state, proc->scope, proc_params(proc))) {
+ destroy_act_state(&new_state);
+ return -1;
+ }
+
+ if (!proc_rtype(proc))
+ proc_rtype(proc) = void_type();
+
+ if (actualize_type_list(&new_state, proc->scope, proc_rtype(proc))) {
+ destroy_act_state(&new_state);
+ return -1;
+ }
+
+ struct type *callable = tgen_callable(NULL, proc_rtype(proc), proc->loc);
+ foreach_node(p, proc_params(proc)) {
+ /* we must manually 'start' the chain **/
+ if (!callable_ptypes(callable)) {
+ callable_ptypes(callable) = clone_type(p->t);
+ continue;
+ }
+
+ type_append(callable_ptypes(callable), p->t);
+ }
+
+ set_type(proc, callable);
+ scope_add_proc(scope, proc);
/* actualize body */
new_state.cur_proc = proc;
@@ -1118,22 +1068,15 @@ static int actualize_id(struct act_state *state,
* Either add in some syntax to distinguish procedure calls and
* pointer calls or make procs and vars share the same namespace.
* */
- struct ast *decl = file_scope_find_var(scope, id_str(id));
- if (decl) {
- set_type(id, decl->t);
- decl->uses++;
- return 0;
- }
-
- decl = file_scope_find_proc(scope, id_str(id));
- if (decl) {
- set_type(id, decl->t);
- decl->uses++;
- return 0;
+ struct ast *decl = actualized_file_scope_find_symbol(state, scope, id_str(id));
+ if (!decl) {
+ semantic_error(scope->fctx, id, "no such symbol");
+ return -1;
}
- semantic_error(scope->fctx, id, "no such object");
- return -1;
+ set_type(id, decl->t);
+ decl->uses++;
+ return 0;
}
static int actualize_var(struct act_state *state,
@@ -1151,12 +1094,6 @@ static int actualize_var(struct act_state *state,
if (type && actualize_type_list(state, scope, type))
return -1;
- if (init && init->k == AST_INIT) {
- assert(!init->t);
- set_type(init, type);
- /* TODO: some kind of check_init() */
- }
-
if (init && type) {
/* make sure the asked type and the actualized types match */
if (!types_match(init->t, type)) {
@@ -1201,6 +1138,9 @@ static int actualize_tid(struct act_state *state, struct scope *scope, struct ty
return -1;
}
+ if (!def->t && actualize(state, def->scope, def))
+ return -1;
+
assert(t->n == NULL);
assert(def->k != AST_TRAIT_DEF);
@@ -1300,6 +1240,23 @@ static int actualize_bool(struct act_state *state, struct scope *scope, struct t
return 0;
}
+static int actualize_tstruct(struct act_state *state, struct scope *scope, struct type *t)
+{
+ UNUSED(state);
+ /* not much to do */
+ if (t->d)
+ return 0;
+
+ struct ast *def = file_scope_find_type(scope, t->id);
+ if (!def) {
+ error("missing definition of type %s", t->id);
+ return -1;
+ }
+
+ t->d = def;
+ return 0;
+}
+
static int actualize_type(struct act_state *state,
struct scope *scope,
struct type *t)
@@ -1319,6 +1276,7 @@ static int actualize_type(struct act_state *state,
case TYPE_ID: return actualize_tid(state, scope, t);
case TYPE_PTR: return actualize_ptr(state, scope, t);
case TYPE_CALLABLE: return actualize_callable(state, scope, t);
+ case TYPE_STRUCT: return actualize_tstruct(state, scope, t);
case TYPE_VOID: return 0; /* void is by default actualized */
default:
@@ -1530,28 +1488,6 @@ static int init_struct(struct act_state *state, struct scope *scope,
return ret;
}
-static int actualize_struct_init_cast(struct act_state *state,
- struct scope *scope,
- struct ast *init,
- struct type *type)
-{
- struct ast *def = type->d;
- return init_struct(state, scope, def, init);
-}
-
-static int actualize_init_cast(struct act_state *state,
- struct scope *scope, struct ast *init,
- struct type *type)
-{
- if (type->k == TYPE_STRUCT)
- return actualize_struct_init_cast(state, scope, init, type);
-
- type_error(scope->fctx, type,
- "type is not a struct");
- return -1;
-
-}
-
static int actualize_cast(struct act_state *state,
struct scope *scope, struct ast *cast)
{
@@ -1565,11 +1501,6 @@ static int actualize_cast(struct act_state *state,
if (actualize(state, scope, expr))
return -1;
- if (expr->k == AST_INIT) {
- set_type(cast, type);
- return actualize_init_cast(state, scope, expr, type);
- }
-
if (types_match(expr->t, type)) {
set_type(cast, type);
return 0;
@@ -1621,8 +1552,8 @@ static int actualize_const(struct act_state *state, struct scope *scope,
if (cons->t)
return 0;
- semantic_error(scope->fctx, cons, "unimplemented constant");
- return 1;
+ semantic_error(scope->fctx, cons, "illegal constant");
+ return -1;
}
static int actualize_alias(struct act_state *state, struct scope *scope,
@@ -1865,6 +1796,9 @@ static int actualize_unop(struct act_state *state,
return -1;
}
+ if (!node->t)
+ return -1;
+
return 0;
}
@@ -1966,23 +1900,101 @@ static int actualize_trait(struct act_state *state, struct scope *scope,
static int actualize_struct(struct act_state *state,
struct scope *scope, struct ast *node)
{
- UNUSED(scope);
assert(node->k == AST_STRUCT_DEF);
+ struct ast *params = struct_params(node);
+ struct scope *struct_scope = create_scope();
+ if (!struct_scope)
+ return -1;
+
+ scope_add_type(scope, struct_id(node), node);
+
+ scope_add_scope(node->scope, struct_scope);
+ node->scope = struct_scope;
+ if (params)
+ ast_set_flags(node, AST_FLAG_GENERIC);
+
+ /* do type setting first to make sure body checking works */
+ char *id = strdup(struct_id(node));
+ if (same_id(id, "i27"))
+ node->t = tgen_primitive(TYPE_I27, id, node, node->loc);
+ else if (same_id(id, "i9"))
+ node->t = tgen_primitive(TYPE_I9, id, node, node->loc);
+ else if (same_id(id, "bool"))
+ node->t = tgen_primitive(TYPE_BOOL, id, node, node->loc);
+ else
+ node->t = tgen_struct(id, node, node->loc);
+
+
+ foreach_node(n, struct_body(node)) {
+ if (n->k != AST_TYPE_EXPAND)
+ continue;
+
+ if (implements_trait(struct_body(node), type_expand_id(n))) {
+ n->k = AST_EMPTY;
+ continue;
+ }
+
+ if (same_id(struct_id(node), type_expand_id(n))) {
+ semantic_error(scope->fctx, n,
+ "recursive trait implementations not allowed");
+ return -1;
+ }
+
+ struct ast *body = analyze_type_expand(scope, n);
+ if (!body) {
+ n->k = AST_EMPTY;
+ continue;
+ }
+
+ replace_type_id(body, type_expand_id(n), node->t);
+ ast_block_last(body)->n = n->n;
+ n->n = body;
+ }
+
+ /*
+ foreach_node(n, struct_body(node)) {
+ switch (n->k) {
+ case AST_EMPTY: continue;
+ case AST_ID: continue;
+ case AST_PROC_DEF: if (!proc_body(n)) continue;
+ default:
+ }
+
+ if (analyze_visibility(struct_scope, n))
+ return -1;
+ }
+ */
+
+ foreach_node(n, struct_body(node)) {
+ struct act_state state = {0};
+ if (actualize(&state, struct_scope, n))
+ return -1;
+ }
+
+ /* check that all prototypes are implemented */
foreach_node(n, struct_body(node)) {
- /* there's really only prodcedure body actualization left I
- * guess, as type stuff was taken care of in the analysis phase
- * */
if (n->k != AST_PROC_DEF)
continue;
- /* don't actualize prototypes, duh */
- if (!proc_body(n))
+ if (proc_body(n))
continue;
- if (actualize(state, node->scope, n))
+ struct ast *proc = scope_find_proc(struct_scope, proc_id(n));
+ if (!proc) {
+ semantic_error(scope->fctx, n,
+ "missing implementation");
+ return -1;
+ }
+
+ if (!types_match(n->t, proc->t)) {
+ semantic_error(scope->fctx, n, "mismatched signatures");
+ semantic_info(scope->fctx, proc, "note: here");
return -1;
+ }
}
+ /** @todo there is the possibility that two different traits add the
+ * same prototype, which is reported in traits but not structs? */
return 0;
}
@@ -1999,6 +2011,9 @@ static int actualize_dot(struct act_state *state,
struct ast *def = NULL;
switch (type->k) {
+ case TYPE_I9:
+ case TYPE_I27:
+ case TYPE_BOOL:
case TYPE_TRAIT:
case TYPE_STRUCT: def = type->d; break;
default: {
@@ -2011,14 +2026,7 @@ static int actualize_dot(struct act_state *state,
}
}
- struct ast *exists = scope_find_var(def->scope, id);
- if (exists) {
- assert(exists->t);
- set_type(node, exists->t);
- return 0;
- }
-
- exists = scope_find_proc(def->scope, id);
+ struct ast *exists = actualized_scope_find_symbol(state, def->scope, id);
if (exists) {
assert(exists->t);
set_type(node, exists->t);
@@ -2030,13 +2038,88 @@ static int actualize_dot(struct act_state *state,
return -1;
}
+struct init_helper {
+ char *id;
+ struct ast *n;
+};
+
+static int init_sort(const struct init_helper *a, const struct init_helper *b)
+{
+ return strcmp(a->id, b->id);
+}
+
static int actualize_init(struct act_state *state,
struct scope *scope, struct ast *node)
{
assert(node->k == AST_INIT);
- /* for now just do the types, the named stuff will be checked later */
- /* TODO: how to make sure all members are initialized? */
- return actualize_list(state, scope, init_body(node));
+ struct ast *def = actualized_file_scope_find_type(state, scope, init_id(node));
+ if (!def) {
+ semantic_error(scope->fctx, node, "no such type");
+ return -1;
+ }
+
+ struct vec init_args = vec_create(sizeof(struct init_helper));
+ struct vec struct_members = vec_create(sizeof(struct init_helper));
+
+ foreach_node(n, struct_body(def)) {
+ if (n->k != AST_VAR_DEF)
+ continue;
+
+ struct init_helper h = {var_id(n), n};
+ vect_append(struct init_helper, struct_members, &h);
+ }
+
+ foreach_node(n, init_body(node)) {
+ /* don't initialize init members as regular vars */
+ /* kind of hacky, could maybe add a AST_MEMBER enum or something */
+ if (actualize(state, scope, var_init(n)))
+ goto err;
+
+ set_type(n, (var_init(n))->t);
+ struct init_helper h = {var_id(n), n};
+ vect_append(struct init_helper, init_args, &h);
+ }
+
+ vec_sort(&init_args, (vec_comp_t)init_sort);
+ vec_sort(&struct_members, (vec_comp_t)init_sort);
+
+ if (vec_len(&init_args) != vec_len(&struct_members)) {
+ semantic_error(scope->fctx, node, "expected %zs args, got %zs",
+ vec_len(&struct_members),
+ vec_len(&init_args));
+ goto err;
+ }
+
+ /* not insanely fast but good enough I suppose */
+ foreach_vec(ai, init_args) {
+ struct init_helper arg = vect_at(struct init_helper, init_args, ai);
+
+ struct init_helper mem = {0};
+ foreach_vec(mi, struct_members) {
+ mem = vect_at(struct init_helper, struct_members, mi);
+ if (same_id(mem.id, arg.id))
+ goto ok;
+ }
+
+ semantic_error(scope->fctx, arg.n, "unknown argument %s", arg.id);
+ goto err;
+
+ok:
+ if (!types_match(arg.n->t, mem.n->t)) {
+ type_mismatch(scope, "init type mismatch", arg.n, arg.n->t, mem.n->t);
+ goto err;
+ }
+ }
+
+ vec_destroy(&init_args);
+ vec_destroy(&struct_members);
+ set_type(node, def->t);
+ return 0;
+
+err:
+ vec_destroy(&init_args);
+ vec_destroy(&struct_members);
+ return -1;
}
static int actualize_assign(struct act_state *state, struct scope *scope,
@@ -2051,11 +2134,6 @@ static int actualize_assign(struct act_state *state, struct scope *scope,
if (actualize_list(state, scope, from))
return -1;
- if (from->k == AST_INIT) {
- set_type(node, to->t);
- return actualize_init_cast(state, scope, from, to->t);
- }
-
if (!types_match(to->t, from->t)) {
type_mismatch(scope, "assign type mismatch", node, to->t, from->t);
return -1;
@@ -2223,8 +2301,7 @@ static int actualize_comparison(struct act_state *state, struct scope *scope, st
return -1;
}
- set_type(node, bool_type(scope));
- return 0;
+ return set_type(node, bool_type(scope));
}
static int actualize(struct act_state *state, struct scope *scope,
@@ -2233,46 +2310,68 @@ static int actualize(struct act_state *state, struct scope *scope,
if (!node)
return 0;
+ if (ast_flags(node, AST_FLAG_ACTUAL)) {
+ assert(node->t);
+ return 0;
+ }
+
+ if (ast_flags(node, AST_FLAG_INIT)) {
+ /* I don't think this should ever happen but just to be safe */
+ semantic_error(scope->fctx, node, "semantic loop detected");
+ return -1;
+ }
+
+ ast_set_flags(node, AST_FLAG_INIT);
+
if (!node->scope)
node->scope = scope;
- if (is_unop(node))
- return actualize_unop(state, scope, node);
+ int ret = 0;
+ if (is_unop(node)) {
+ ret = actualize_unop(state, scope, node);
+ goto out;
+ }
- if (is_binop(node))
- return actualize_binop(state, scope, node);
+ if (is_binop(node)) {
+ ret = actualize_binop(state, scope, node);
+ goto out;
+ }
- if (is_comparison(node))
- return actualize_comparison(state, scope, node);
+ if (is_comparison(node)) {
+ ret = actualize_comparison(state, scope, node);
+ goto out;
+ }
- if (is_const(node))
- return actualize_const(state, scope, node);
+ if (is_const(node)) {
+ ret = actualize_const(state, scope, node);
+ goto out;
+ }
switch (node->k) {
- case AST_PROC_DEF: return actualize_proc(state, scope, node);
- case AST_TRAIT_DEF: return actualize_trait(state, scope, node);
- case AST_ALIAS_DEF: return actualize_alias(state, scope, node);
- case AST_ENUM_DEF: return actualize_enum(state, scope, node);
- case AST_MACRO_DEF: return actualize_macro_def(state, scope, node);
- case AST_STRUCT_DEF: return actualize_struct(state, scope, node);
- case AST_VAR_DEF: return actualize_var(state, scope, node);
- case AST_CALL: return actualize_call(state, scope, node);
- case AST_BLOCK: return actualize_block(state, scope, node);
- case AST_ID: return actualize_id(state, scope, node);
- case AST_EMPTY: return actualize_empty(state, scope, node);
- case AST_CAST: return actualize_cast(state, scope, node);
- case AST_DEFER: return actualize_defer(state, scope, node);
- case AST_RETURN: return actualize_return(state, scope, node);
- case AST_GOTO: return actualize_goto(state, scope, node);
- case AST_LABEL: return actualize_label(state, scope, node);
- case AST_AS: return actualize_as(state, scope, node);
- case AST_DOT: return actualize_dot(state, scope, node);
- case AST_INIT: return actualize_init(state, scope, node);
- case AST_ASSIGN: return actualize_assign(state, scope, node);
- case AST_FETCH: return actualize_fetch(state, scope, node);
- case AST_IF: return actualize_if(state, scope, node);
- case AST_FOR: return actualize_for(state, scope, node);
- case AST_MACRO_EXPAND: return actualize_macro_expand(state, scope, node);
+ case AST_PROC_DEF: ret = actualize_proc(state, scope, node); break;
+ case AST_TRAIT_DEF: ret = actualize_trait(state, scope, node); break;
+ case AST_ALIAS_DEF: ret = actualize_alias(state, scope, node); break;
+ case AST_ENUM_DEF: ret = actualize_enum(state, scope, node); break;
+ case AST_MACRO_DEF: ret = actualize_macro_def(state, scope, node); break;
+ case AST_STRUCT_DEF: ret = actualize_struct(state, scope, node); break;
+ case AST_VAR_DEF: ret = actualize_var(state, scope, node); break;
+ case AST_CALL: ret = actualize_call(state, scope, node); break;
+ case AST_BLOCK: ret = actualize_block(state, scope, node); break;
+ case AST_ID: ret = actualize_id(state, scope, node); break;
+ case AST_EMPTY: ret = actualize_empty(state, scope, node); break;
+ case AST_CAST: ret = actualize_cast(state, scope, node); break;
+ case AST_DEFER: ret = actualize_defer(state, scope, node); break;
+ case AST_RETURN: ret = actualize_return(state, scope, node); break;
+ case AST_GOTO: ret = actualize_goto(state, scope, node); break;
+ case AST_LABEL: ret = actualize_label(state, scope, node); break;
+ case AST_AS: ret = actualize_as(state, scope, node); break;
+ case AST_DOT: ret = actualize_dot(state, scope, node); break;
+ case AST_INIT: ret = actualize_init(state, scope, node); break;
+ case AST_ASSIGN: ret = actualize_assign(state, scope, node); break;
+ case AST_FETCH: ret = actualize_fetch(state, scope, node); break;
+ case AST_IF: ret = actualize_if(state, scope, node); break;
+ case AST_FOR: ret = actualize_for(state, scope, node); break;
+ case AST_MACRO_EXPAND: ret = actualize_macro_expand(state, scope, node); break;
default:
/* more like internal_error, maybe? */
semantic_error(scope->fctx, node,
@@ -2280,6 +2379,13 @@ static int actualize(struct act_state *state, struct scope *scope,
return -1;
}
+out:
+ if (ret)
+ return ret;
+
+ assert(node->t);
+ assert(node->scope);
+ ast_set_flags(node, AST_FLAG_ACTUAL);
return 0;
}
diff --git a/src/debug.c b/src/debug.c
index d16aab2..3be9d21 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -217,6 +217,11 @@ static void _type_str(FILE *fp, struct type *type)
return;
switch (type->k) {
+ case TYPE_VOID: {
+ fprintf(fp, "void");
+ break;
+ }
+
case TYPE_PTR:
fputc('*', fp);
_type_str(fp, ptr_base(type));
diff --git a/src/lower.c b/src/lower.c
index bf36fae..9ad9a53 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -273,8 +273,10 @@ static int lower_var(struct lower_state *s, struct ast *v,
{
assert(v->k == AST_VAR_DEF);
struct vec input = retval_create();
- if (lower_expr(s, var_init(v), &input))
+ if (lower_expr(s, var_init(v), &input)) {
+ retval_destroy(&input);
return -1;
+ }
/* if we have a struct, we should add the member name to the base name
* */
@@ -847,16 +849,13 @@ int lower(struct scope *root)
if (!scope_flags(root, SCOPE_FILE))
return 0;
- for (struct visible *v = root->vars; v; v = v->next) {
- assert(v->node);
- if (lower_global_var(v->node))
- return -1;
- }
-
- for (struct visible *p = root->procs; p; p = p->next) {
+ foreach_visible(p, root->symbols) {
assert(p->node);
- if (lower_proc(p->node))
+ struct ast *node = p->node;
+ if (node->k == AST_PROC_DEF && lower_proc(p->node))
return -1;
+
+ /** @todo variables, structs, etc. */
}
return 0;
diff --git a/src/parser.y b/src/parser.y
index fb137b1..1bec7e2 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -520,10 +520,10 @@ construct_args
construct
: APPLY "{" construct_args "}" {
/** @todo add type info? */
- $$ = gen_init($3, src_loc(@$));
+ $$ = gen_init($1, NULL, $3, src_loc(@$));
}
| APPLY "[" opt_types "]" "{" construct_args "}" {
- $$ = gen_init($6, src_loc(@$));
+ $$ = gen_init($1, $3, $6, src_loc(@$));
}
if
diff --git a/src/scope.c b/src/scope.c
index 13c3dce..c1ece2e 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -53,8 +53,7 @@ void destroy_scope(struct scope *scope)
free((void *)scope->fctx.fname);
}
- destroy_visible(scope->vars);
- destroy_visible(scope->procs);
+ destroy_visible(scope->symbols);
destroy_visible(scope->macros);
destroy_visible(scope->types);
@@ -106,8 +105,8 @@ struct visible *create_var(struct scope *scope, char *id, struct ast *var)
if (!n)
return NULL;
- n->next = scope->vars;
- scope->vars = n;
+ n->next = scope->symbols;
+ scope->symbols = n;
return n;
}
@@ -130,15 +129,15 @@ struct visible *create_proc(struct scope *scope, char *id, struct ast *proc)
if (!n)
return NULL;
- n->next = scope->procs;
- scope->procs = n;
+ n->next = scope->symbols;
+ scope->symbols = n;
return n;
}
int scope_add_var(struct scope *scope, struct ast *var)
{
- struct ast *exists = file_scope_find_var(scope, var_id(var));
+ struct ast *exists = file_scope_find_symbol(scope, var_id(var));
if (exists) {
semantic_error(scope->fctx, var, "var redefined");
semantic_info(scope->fctx, exists, "previously here");
@@ -192,7 +191,7 @@ int scope_add_macro(struct scope *scope, struct ast *macro)
int scope_add_proc(struct scope *scope, struct ast *proc)
{
assert(proc->k == AST_PROC_DEF);
- struct ast *exists = file_scope_find_proc(scope, proc_id(proc));
+ struct ast *exists = file_scope_find_symbol(scope, proc_id(proc));
if (exists) {
semantic_error(scope->fctx, proc, "proc redefined");
semantic_info(scope->fctx, exists, "previously here");
@@ -284,27 +283,58 @@ struct ast *file_scope_find_macro(struct scope *scope, char *id)
struct ast *scope_find_proc(struct scope *scope, char *id)
{
- return scope_find_visible(scope->procs, id);
+ struct ast *n = scope_find_visible(scope->symbols, id);
+ if (!n)
+ return NULL;
+
+ if (n->k != AST_PROC_DEF)
+ return NULL;
+
+ return n;
}
struct ast *file_scope_find_proc(struct scope *scope, char *id)
{
+ struct ast *n = file_scope_find_symbol(scope, id);
+ if (!n)
+ return NULL;
+
+ if (n->k != AST_PROC_DEF)
+ return NULL;
+
+ return n;
+}
+
+struct ast *scope_find_symbol(struct scope *scope, char *id)
+{
+ return scope_find_visible(scope->symbols, id);
+}
+
+struct ast *file_scope_find_symbol(struct scope *scope, char *id)
+{
if (!scope)
return NULL;
- struct ast *found = scope_find_proc(scope, id);
+ struct ast *found = scope_find_symbol(scope, id);
if (found)
return found;
if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_find_proc(scope->parent, id);
+ return file_scope_find_symbol(scope->parent, id);
return NULL;
}
struct ast *scope_find_var(struct scope *scope, char *id)
{
- return scope_find_visible(scope->vars, id);
+ struct ast *n = scope_find_visible(scope->symbols, id);
+ if (!n)
+ return NULL;
+
+ if (n->k != AST_VAR_DEF)
+ return NULL;
+
+ return n;
}
struct ast *file_scope_find_var(struct scope *scope, char *id)
diff --git a/src/vec.c b/src/vec.c
index 3f1aac6..8e8d2ea 100644
--- a/src/vec.c
+++ b/src/vec.c
@@ -58,3 +58,8 @@ void vec_reset(struct vec *v)
void vec_destroy(struct vec *v) {
free(v->buf);
}
+
+void vec_sort(struct vec *v, vec_comp_t comp)
+{
+ qsort(v->buf, v->n, v->ns, comp);
+}