aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-02-16 00:20:18 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-02-16 00:20:18 +0200
commita83f6a2e53de7a9322755d68ebc9f13e3babecc2 (patch)
tree599c2a5173f42d5a9b99e5cfdc1dcfe288bb2165 /src
parentc85e4b4d2411e60af7387dec663ea62b03743eab (diff)
downloadek-a83f6a2e53de7a9322755d68ebc9f13e3babecc2.tar.gz
ek-a83f6a2e53de7a9322755d68ebc9f13e3babecc2.zip
rework
+ Kind of only a partial commit, but whatever, this history is pretty ugly anyway
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c147
-rw-r--r--src/asm.c18
-rw-r--r--src/ast.c368
-rw-r--r--src/compiler.c25
-rw-r--r--src/debug.c17
-rw-r--r--src/lexer.l3
-rw-r--r--src/ops.c120
-rw-r--r--src/parser.y176
-rw-r--r--src/scope.c709
9 files changed, 511 insertions, 1072 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 694eca9..591df1a 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -288,7 +288,7 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
case AST_IMPORT: {
const char *file = AST_IMPORT(node).file;
ret |= process_file(&scope,
- ast_flags(node, AST_FLAG_PUBLIC), file);
+ ast_flags(node, AST_FLAG_PUBLIC), file);
break;
}
@@ -329,11 +329,6 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
break;
}
- case AST_TYPE_CONSTRUCT: {
- ret |= scope_add_type_construct(scope, node);
- break;
- }
-
case AST_MACRO_CONSTRUCT: {
ret |= scope_add_macro(scope, node);
break;
@@ -377,7 +372,6 @@ static int analyze(struct scope *scope, struct ast_node *tree)
int analyze_root(struct scope *scope, struct ast_node *tree)
{
- scope_add_defaults(scope);
if (analyze(scope, tree))
return -1;
@@ -410,10 +404,6 @@ int types_match(struct ast_node *a, struct ast_node *b)
assert(a->node_type == AST_TYPE);
assert(b->node_type == AST_TYPE);
- /* typeofs match 'everything' */
- if (AST_TYPE(a).kind == AST_TYPE_TYPEOF || AST_TYPE(b).kind == AST_TYPE_TYPEOF)
- return 1;
-
/* if the type kind doesn't match, we're done. */
if (AST_TYPE(a).kind != AST_TYPE(b).kind)
return 0;
@@ -423,7 +413,7 @@ int types_match(struct ast_node *a, struct ast_node *b)
if (AST_TYPE(a).kind == AST_TYPE_POINTER)
return types_match(AST_PTR_TYPE(a).base,
- AST_PTR_TYPE(b).base);
+ AST_PTR_TYPE(b).base);
if (AST_TYPE(a).kind == AST_TYPE_PRIMITIVE)
return primitives_match(a, b);
@@ -467,7 +457,7 @@ static int replace_id(struct ast_node *body, struct ast_node *id,
}
static int actualize_macro_construct(struct act_state *state,
- struct scope *scope, struct ast_node *n)
+ struct scope *scope, struct ast_node *n)
{
UNUSED(state);
/* macro bodies, arguments, etc aren't expanded upon until the macro is
@@ -476,18 +466,6 @@ static int actualize_macro_construct(struct act_state *state,
return scope_add_macro(scope, n);
}
-struct ast_node *extract_typeof(struct ast_node *type)
-{
- if (!type)
- return 0;
-
- assert(type->node_type == AST_TYPE);
- if (type->_type.kind == AST_TYPE_TYPEOF)
- return type;
-
- return extract_typeof(type->_type.next);
-}
-
struct ast_node *extract_trait(struct ast_node *type)
{
if (!type)
@@ -501,7 +479,7 @@ struct ast_node *extract_trait(struct ast_node *type)
}
static void actualize_trait_types(struct ast_node *params,
- struct ast_node *args)
+ struct ast_node *args)
{
/** @todo replace trait types with arg types, should probably be merged
* */
@@ -534,11 +512,12 @@ static int actualize_proc_call(struct act_state *state,
}
static int actualize_macro_expand(struct act_state *state,
- struct scope *scope, struct ast_node *macro_expand)
+ struct scope *scope,
+ struct ast_node *macro_expand)
{
assert(macro_expand->node_type == AST_MACRO_EXPAND);
struct ast_node *id = AST_MACRO_EXPAND(macro_expand).id;
- struct ast_node *macro = file_scope_resolve_macro(scope, id);
+ struct ast_node *macro = file_scope_find_macro(scope, id);
if (!macro) {
semantic_error(scope->fctx, macro_expand, "no such macro");
return -1;
@@ -596,11 +575,16 @@ static int actualize_call(struct act_state *state,
/* check that arguments exist, make sure they have types etc. */
/* TODO: procedure callbacks? */
- int ret = actualize(state, scope, call->_call.args);
+ int ret = actualize(state, scope, AST_CALL(call).args);
if (ret)
return ret;
- struct ast_node *callable = file_scope_resolve_call(scope, call);
+ ret = actualize(state, scope, AST_CALL(call).expr);
+ if (ret)
+ return ret;
+
+ /** @todo check if call args and expr types match */
+ struct ast_node *callable = file_scope_find_proc(scope, call);
if (!callable) {
char *str = call_str(call);
semantic_error(scope->fctx, call, "no such callable: %s", str);
@@ -609,6 +593,8 @@ static int actualize_call(struct act_state *state,
}
assert(callable->node_type == AST_PROC);
+ /** @todo we should probably start with just iterating over all procs and check
+ * if they're valid rather than generating them on 'demand' */
return actualize_proc_call(state, scope, call, callable);
}
@@ -622,7 +608,7 @@ static void warn_unused_labels(struct act_state *state, struct scope *scope)
struct ast_node *label = labels->node;
if (!ast_flags(label, AST_FLAG_ACTUAL))
semantic_warn(scope->fctx, label,
- "unused label");
+ "unused label");
} while ((labels = labels->next));
}
@@ -638,7 +624,7 @@ static int undefined_gotos(struct act_state *state, struct scope *scope)
struct ast_node *got = gotos->node;
if (!ast_flags(got, AST_FLAG_ACTUAL)) {
semantic_warn(scope->fctx, got,
- "undefined label");
+ "undefined label");
ret = -1;
}
@@ -808,27 +794,27 @@ static int actualize_id(struct act_state *state,
/** @todo at the moment we always assume an ID is a variable, but stuff
* like function callbacks should be added in the future */
struct ast_node *decl = file_scope_find_var(scope, id);
- if (!decl) {
- semantic_error(scope->fctx, id, "no such object");
- return -1;
+ if (decl) {
+ id->type = decl->type;
+ return 0;
}
- if (!decl->type) {
- semantic_error(scope->fctx, id,
- "no type associated with object");
- return -1;
+ decl = file_scope_find_proc(scope, id);
+ if (decl) {
+ id->type = decl->type;
+ return 0;
}
- id->type = decl->type;
- return 0;
+ semantic_error(scope->fctx, id, "no such object");
+ return -1;
}
static int actualize_var(struct act_state *state,
struct scope *scope, struct ast_node *var)
{
assert(var && var->node_type == AST_VAR);
- struct ast_node *init = var->_var.init;
- struct ast_node *type = var->_var.type;
+ struct ast_node *init = AST_VAR(var).init;
+ struct ast_node *type = AST_VAR(var).type;
/* one of these must be defined, otherwise the parser fucked up */
assert(type || init);
@@ -881,11 +867,11 @@ static int actualize_var(struct act_state *state,
enum act_flags old_flags = state->flags; \
struct ast_node *old_trait = state->cur_trait;
-#define EXIT_ACT(r) \
- do { \
+#define EXIT_ACT(r) \
+ do { \
state->cur_trait = old_trait; \
- state->flags = old_flags; \
- return r; \
+ state->flags = old_flags; \
+ return r; \
} while (0);
static int actualize_type(struct act_state *state,
@@ -908,10 +894,12 @@ static int actualize_type(struct act_state *state,
* they're missing, void */
if (!AST_ID_TYPE(type).id) {
/* no ID means void */
- AST_ID_TYPE(type).id = gen_id(strdup("void"), NULL_LOC());
+ AST_ID_TYPE(type).id =
+ gen_id(strdup("void"), NULL_LOC());
}
- struct ast_node *exists = file_scope_find_type(scope, AST_ID_TYPE(type).id);
+ struct ast_node *exists = file_scope_find_type(scope, AST_ID_TYPE(
+ type).id);
if (!exists) {
semantic_error(scope->fctx, type, "no such type");
EXIT_ACT(-1);
@@ -945,26 +933,16 @@ static int actualize_type(struct act_state *state,
break;
}
- case AST_TYPE_ARR:
- /* TODO: expression should be expandable to integer constant */
+ case AST_TYPE_CONSTRUCT:
+ semantic_info(scope->fctx, type,
+ "constructs unimplemented, continuing with compilation to see what breaks");
break;
- case AST_TYPE_TYPEOF: {
- struct ast_node *expr = AST_TYPEOF_TYPE(type).expr;
- /* TODO: expressions in top-level type declarations should
- * probably be checked for, as we might not want to accidentally
- * actualize procedure calls? */
- if (actualize(state, scope, expr))
- EXIT_ACT(-1);
-
- /* TODO: for now just trust that the expression is not looped or
- * anything dumb like that, but I would feel better if I figure
- * out some check */
- assert(type->_type.next == NULL);
- /** @todo add in some 'from' field for this situation? */
- type->type = expr->type;
+ case AST_TYPE_ARR:
+ /* TODO: expression should be expandable to integer constant */
+ semantic_info(scope->fctx, type,
+ "arrays unimplemented, continuing with compilation to see what breaks");
break;
- }
case AST_TYPE_POINTER:
assert(AST_PTR_TYPE(type).base);
@@ -1019,7 +997,7 @@ static int actualize_empty(struct act_state *state,
return -1;
}
- node->type = gen_type(AST_TYPE_ID, void_id, NULL, NULL);
+ node->type = gen_type(AST_TYPE_ID, void_id, NULL, NULL_LOC());
if (!node->type) {
internal_error("couldn't allocate type for empty statement\n");
return -1;
@@ -1186,11 +1164,11 @@ static int init_struct(struct act_state *state, struct scope *scope,
break;
}
- if (!implements(0, scope, args->type, member->type)) {
+ if (!types_match(args->type, member->type)) {
char *astr = type_str(args->type);
char *mstr = type_str(member->type);
semantic_error(scope->fctx, args,
- "%s does not implement %s", astr, mstr);
+ "%s does not match %s", astr, mstr);
free(astr);
free(mstr);
ret = -1;
@@ -1351,7 +1329,7 @@ static int actualize_alias(struct act_state *state, struct scope *scope,
}
static int actualize_trait(struct act_state *state, struct scope *scope,
- struct ast_node *trait)
+ struct ast_node *trait)
{
assert(trait->node_type == AST_TRAIT);
ast_set_flags(trait, AST_FLAG_ACTUAL);
@@ -1565,8 +1543,9 @@ static int actualize_unop(struct act_state *state,
}
case AST_REF: {
- node->type = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
- node->type->_type.next = expr->type;
+ node->type = gen_type(AST_TYPE_POINTER, NULL, NULL,
+ NULL_LOC());
+ node->AST_TYPE(type).next = expr->type;
break;
}
@@ -1613,7 +1592,8 @@ static int actualize_struct(struct act_state *state,
/* cloning slightly odd, but I guess it's fine? */
struct ast_node *clone_id = clone_ast_node(node->_struct.id);
- node->type = gen_type(AST_TYPE_STRUCT, clone_id, NULL, NULL);
+ node->type =
+ gen_type(AST_TYPE_STRUCT, clone_id, NULL, NULL_LOC());
ast_set_flags(node, AST_FLAG_ACTUAL);
return 0;
@@ -1634,6 +1614,9 @@ static int has_members(struct ast_node *type)
if (AST_TYPE(type).kind == AST_TYPE_TRAIT)
return 1;
+ if (AST_TYPE(type).kind == AST_TYPE_CONSTRUCT)
+ return 1;
+
return 0;
}
@@ -1708,7 +1691,8 @@ static int actualize_assign(struct act_state *state, struct scope *scope,
/** @todo rvalue vs lvalue? */
if (!is_lvalue(to)) {
- semantic_error(scope->fctx, node, "rvalue used where lvalue required");
+ semantic_error(scope->fctx, node,
+ "rvalue used where lvalue required");
return -1;
}
@@ -1730,7 +1714,8 @@ static int actualize_fetch(struct act_state *state, struct scope *scope,
}
struct ast_node *id = fetch->_fetch.id;
- struct ast_node *def = file_scope_find_type(scope, AST_ID_TYPE(type).id);
+ struct ast_node *def =
+ file_scope_find_type(scope, AST_ID_TYPE(type).id);
assert(def);
struct ast_node *member = lookup_enum_member(def, id);
@@ -1806,7 +1791,8 @@ static int actualize(struct act_state *state, struct scope *scope,
if (!node->scope)
node->scope = scope;
- if (ast_flags(node, AST_FLAG_INIT) && !ast_flags(node, AST_FLAG_ACTUAL)) {
+ if (ast_flags(node,
+ AST_FLAG_INIT) && !ast_flags(node, AST_FLAG_ACTUAL)) {
semantic_error(scope->fctx, node, "detected dependency loop");
return -1;
}
@@ -1823,8 +1809,10 @@ static int actualize(struct act_state *state, struct scope *scope,
case AST_TRAIT: ret |= actualize_trait(state, scope, node); break;
case AST_ALIAS: ret |= actualize_alias(state, scope, node); break;
- case AST_MACRO_CONSTRUCT: ret |= actualize_macro_construct(state, scope, node); break;
- case AST_MACRO_EXPAND: ret |= actualize_macro_expand(state, scope, node); break;
+ case AST_MACRO_CONSTRUCT: ret |= actualize_macro_construct(state, scope,
+ node); break;
+ case AST_MACRO_EXPAND: ret |=
+ actualize_macro_expand(state, scope, node); break;
case AST_CALL: ret |= actualize_call(state, scope, node); break;
case AST_BINOP: ret |= actualize_binop(state, scope, node); break;
case AST_BLOCK: ret |= actualize_block(state, scope, node); break;
@@ -1866,12 +1854,11 @@ static int actualize(struct act_state *state, struct scope *scope,
int actualize_main(struct scope *root)
{
struct ast_node *main_id = gen_id(strdup("main"), NULL_LOC());
- struct ast_node *main_call = gen_call(main_id, NULL);
struct act_state state = {0};
/* skip checking signature for now */
- struct ast_node *main = file_scope_resolve_call(root, main_call);
+ struct ast_node *main = file_scope_find_proc(root, main_id);
if (!main) {
/* libraries are not really compilable... */
error("no main");
diff --git a/src/asm.c b/src/asm.c
index e2076f5..8e49aa9 100644
--- a/src/asm.c
+++ b/src/asm.c
@@ -5,8 +5,10 @@
/* I guess using the zero register might be okay in some scenarios, but for now
* I'll just keep it an illegal register */
-#define ASSERT_REG(x) {assert(x->kind == LOC_REG); assert(x->reg > 0 && x->reg < 81);}
-#define ASSERT_MEM(x) {assert(x->kind == LOC_MEM); assert(x->reg > 0 && x->reg < 81);}
+#define ASSERT_REG(x) {assert(x->kind == LOC_REG); assert( \
+ x->reg > 0 && x->reg < 81);}
+#define ASSERT_MEM(x) {assert(x->kind == LOC_MEM); assert( \
+ x->reg > 0 && x->reg < 81);}
static int print_comment(struct op *op, FILE *f)
{
@@ -59,6 +61,7 @@ static int print_stt(struct op *op, FILE *f)
static int print_ret(struct op *op, FILE *f)
{
+ (void)op;
/* technically speaking ret takes a number of inputs, but they should be
* marshaled into registers with moves etc. so don't worry about them
* here */
@@ -84,16 +87,8 @@ static int print_op(struct op *op, FILE *f)
return ret;
}
-int print_asm(struct ops *ops, const char *output)
+int print_asm(struct ops *ops, FILE *f)
{
- FILE *f = fopen(output, "w");
-
- /* main should probably be mangled here as well */
- fprintf(f, "jal x21, main\n");
- /* tell simulator to turn off (very much temp) */
- fprintf(f, "li x1, 3\n");
- fprintf(f, "csrrw mpower, x0, x1\n");
-
int ret = 0;
struct op *op = ops->base;
while (op) {
@@ -103,6 +98,5 @@ int print_asm(struct ops *ops, const char *output)
op = op->next;
}
- fclose(f);
return ret;
}
diff --git a/src/ast.c b/src/ast.c
index 0fc7c8c..8660ae2 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -31,9 +31,9 @@ static void destroy_ast_node(struct ast_node *node)
switch (node->node_type) {
case AST_ID: free((void *)AST_ID(node).id); break;
case AST_CONST:
- if (AST_CONST(node).kind == AST_CONST_STRING)
- free((void *)AST_CONST(node).str);
- break;
+ if (AST_CONST(node).kind == AST_CONST_STRING)
+ free((void *)AST_CONST(node).str);
+ break;
default:
}
@@ -59,7 +59,9 @@ static struct ast_node *create_ast_node()
else if (ast_nodes.n >= ast_nodes.s) {
ast_nodes.s *= 2;
- ast_nodes.v = realloc(ast_nodes.v, ast_nodes.s * sizeof(struct ast_node *));
+ ast_nodes.v =
+ realloc(ast_nodes.v,
+ ast_nodes.s * sizeof(struct ast_node *));
}
struct ast_node *n = calloc(1, sizeof(struct ast_node));
@@ -69,11 +71,11 @@ static struct ast_node *create_ast_node()
/** @todo alloc should maybe also keep track of all nodes in a vector or
* something and mass free all AST at a time to keep my sanity */
-#define ALLOC_NODE(n, type) \
- struct ast_node *n = create_ast_node(); \
- if (!n) { \
- fprintf(stderr, "failed allocating" type "\n"); \
- return NULL; \
+#define ALLOC_NODE(n, type) \
+ struct ast_node *n = create_ast_node(); \
+ if (!n) { \
+ fprintf(stderr, "failed allocating" type "\n"); \
+ return NULL; \
}
#define DESTROY_LIST(x) \
@@ -86,7 +88,8 @@ static struct ast_node *create_ast_node()
} while ((prev = cur)); \
}
-struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, struct src_loc loc)
+struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx,
+ struct src_loc loc)
{
ALLOC_NODE(n, "arr_access");
n->node_type = AST_ARR_ACCESS;
@@ -96,7 +99,8 @@ struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, str
return n;
}
-struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args, struct src_loc loc)
+struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args,
+ struct src_loc loc)
{
ALLOC_NODE(n, "macro_expand");
n->node_type = AST_MACRO_EXPAND;
@@ -106,23 +110,9 @@ struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args, st
return n;
}
-struct ast_node *gen_type_construct(struct ast_node *id,
- struct ast_node *params,
- struct ast_node *body,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "type_construct");
- n->node_type = AST_TYPE_CONSTRUCT;
- AST_TYPE_CONSTRUCT(n).id = id;
- AST_TYPE_CONSTRUCT(n).params = params;
- AST_TYPE_CONSTRUCT(n).body = body;
- n->loc = loc;
- return n;
-}
-
struct ast_node *gen_type_expand(struct ast_node *id,
- struct ast_node *args,
- struct src_loc loc)
+ struct ast_node *args,
+ struct src_loc loc)
{
ALLOC_NODE(n, "type_expand");
n->node_type = AST_TYPE_EXPAND;
@@ -134,8 +124,8 @@ struct ast_node *gen_type_expand(struct ast_node *id,
struct ast_node *gen_binop(enum ast_binops op,
struct ast_node *left,
- struct ast_node *right,
- struct src_loc loc)
+ struct ast_node *right,
+ struct src_loc loc)
{
ALLOC_NODE(n, "binop");
n->node_type = AST_BINOP;
@@ -156,13 +146,14 @@ struct ast_node *gen_unop(enum ast_unops op, struct ast_node *expr)
return n;
}
-struct ast_node *gen_call(struct ast_node *id, struct ast_node *args)
+struct ast_node *gen_call(struct ast_node *expr, struct ast_node *args,
+ struct src_loc loc)
{
ALLOC_NODE(n, "call");
n->node_type = AST_CALL;
- n->_call.id = id;
- n->_call.args = args;
- n->loc = id->loc;
+ AST_CALL(n).expr = expr;
+ AST_CALL(n).args = args;
+ n->loc = loc;
return n;
}
@@ -251,12 +242,13 @@ struct ast_node *gen_goto(struct ast_node *label)
return n;
}
-struct ast_node *gen_dot(struct ast_node *expr, struct ast_node *id)
+struct ast_node *gen_dot(struct ast_node *expr, struct ast_node *id, struct src_loc loc)
{
ALLOC_NODE(n, "dot");
n->node_type = AST_DOT;
- n->_dot.expr = expr;
- n->_dot.id = id;
+ AST_DOT(n).expr = expr;
+ AST_DOT(n).id = id;
+ n->loc = loc;
return n;
}
@@ -289,8 +281,8 @@ struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type)
}
struct ast_node *gen_macro_construct(struct ast_node *id,
- struct ast_node *params,
- struct ast_node *body)
+ struct ast_node *params,
+ struct ast_node *body)
{
ALLOC_NODE(n, "macro_construct");
n->node_type = AST_MACRO_CONSTRUCT;
@@ -347,13 +339,15 @@ struct ast_node *gen_primitive(enum ast_primitive type, struct src_loc loc)
}
struct ast_node *gen_type(enum ast_type_kind kind,
- struct ast_node *t0,
+ struct ast_node *t0,
struct ast_node *t1,
- struct ast_node *t2)
+ struct src_loc loc)
{
ALLOC_NODE(n, "type");
n->node_type = AST_TYPE;
AST_TYPE(n).kind = kind;
+ n->loc = loc;
+
switch (kind) {
case AST_TYPE_TRAIT:
AST_TRAIT_TYPE(n).def = t0;
@@ -363,15 +357,16 @@ struct ast_node *gen_type(enum ast_type_kind kind,
AST_ID_TYPE(n).id = t0;
break;
+ case AST_TYPE_CONSTRUCT:
+ AST_CONSTRUCT_TYPE(n).id = t0;
+ AST_CONSTRUCT_TYPE(n).args = t1;
+ break;
+
case AST_TYPE_ARR:
AST_ARR_TYPE(n).size = t0;
AST_ARR_TYPE(n).base = t1;
break;
- case AST_TYPE_TYPEOF:
- AST_TYPEOF_TYPE(n).expr = t0;
- break;
-
case AST_TYPE_POINTER:
AST_PTR_TYPE(n).base = t0;
break;
@@ -438,17 +433,14 @@ void destroy_defer(struct ast_node *defer)
}
struct ast_node *gen_var(struct ast_node *id, struct ast_node *type,
- struct ast_node *init)
+ struct ast_node *init, struct src_loc loc)
{
ALLOC_NODE(n, "var");
n->node_type = AST_VAR;
- n->_var.id = id;
- n->_var.type = type;
- n->_var.init = init;
- if (id)
- n->loc = id->loc;
- else
- n->loc = type->loc;
+ AST_VAR(n).id = id;
+ AST_VAR(n).type = type;
+ AST_VAR(n).init = init;
+ n->loc = loc;
return n;
}
@@ -521,13 +513,15 @@ struct ast_node *gen_alias(struct ast_node *id, struct ast_node *type)
return n;
}
-struct ast_node *gen_trait(struct ast_node *id, struct ast_node *body)
+struct ast_node *gen_trait(struct ast_node *id, struct ast_node *params,
+ struct ast_node *body, struct src_loc loc)
{
ALLOC_NODE(n, "trait");
n->node_type = AST_TRAIT;
- n->_trait.id = id;
- n->_trait.body = body;
- n->loc = id->loc;
+ AST_TRAIT(n).id = id;
+ AST_TRAIT(n).params = params;
+ AST_TRAIT(n).body = body;
+ n->loc = loc;
return n;
}
@@ -777,8 +771,8 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_flags(node);
putchar('\n');
- dump_ast(depth + 1, node->_call.id);
- dump_ast(depth + 1, node->_call.args);
+ dump_ast(depth + 1, AST_CALL(node).expr);
+ dump_ast(depth + 1, AST_CALL(node).args);
dump(depth, "}\n");
break;
@@ -894,7 +888,8 @@ static void __dump_ast(int depth, struct ast_node *node)
switch (node->_type.kind) {
case AST_TYPE_PRIMITIVE:
- printf(" PRIMITIVE %s\n", primitive_str(AST_PRIMITIVE_TYPE(node).type));
+ printf(" PRIMITIVE %s\n",
+ primitive_str(AST_PRIMITIVE_TYPE(node).type));
break;
case AST_TYPE_TRAIT:
@@ -919,11 +914,6 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_ast(depth + 1, AST_PTR_TYPE(node).base);
break;
- case AST_TYPE_TYPEOF:
- printf(" TYPEOF\n");
- dump_ast(depth + 1, AST_TYPEOF_TYPE(node).expr);
- break;
-
case AST_TYPE_STRUCT:
printf(" STRUCT\n");
/* oh yeah, struc is at least right now just an ID that
@@ -1073,7 +1063,8 @@ static void __dump_ast(int depth, struct ast_node *node)
dump(depth, "{CONST:");
dump_flags(node);
switch (node->_const.kind) {
- case AST_CONST_INTEGER: printf(" %lli", AST_CONST(node).integer);
+ case AST_CONST_INTEGER: printf(" %lli",
+ AST_CONST(node).integer);
break;
case AST_CONST_STRING: printf(" \"%s\"", AST_CONST(node).str);
break;
@@ -1131,24 +1122,16 @@ struct ast_node *clone_ast_node(struct ast_node *node)
switch (node->node_type) {
case AST_ARR_ACCESS:
new = gen_arr_access(
- clone_ast_node(AST_ARR_ACCESS(node).base),
- clone_ast_node(AST_ARR_ACCESS(node).idx),
- node->loc);
- break;
-
- case AST_TYPE_CONSTRUCT:
- new = gen_type_construct(
- clone_ast_node(AST_TYPE_CONSTRUCT(node).id),
- clone_ast_node(AST_TYPE_CONSTRUCT(node).params),
- clone_ast_node(AST_TYPE_CONSTRUCT(node).body),
- node->loc);
+ clone_ast_node(AST_ARR_ACCESS(node).base),
+ clone_ast_node(AST_ARR_ACCESS(node).idx),
+ node->loc);
break;
case AST_TYPE_EXPAND:
new = gen_type_expand(
- clone_ast_node(AST_TYPE_EXPAND(node).id),
- clone_ast_node(AST_TYPE_EXPAND(node).args),
- node->loc);
+ clone_ast_node(AST_TYPE_EXPAND(node).id),
+ clone_ast_node(AST_TYPE_EXPAND(node).args),
+ node->loc);
break;
case AST_FETCH:
@@ -1167,8 +1150,9 @@ struct ast_node *clone_ast_node(struct ast_node *node)
case AST_SIZEOF: new = gen_sizeof(clone_ast_node(node->_sizeof.expr));
break;
- case AST_DOT: new = gen_dot(clone_ast_node(node->_dot.expr),
- clone_ast_node(node->_dot.id));
+ case AST_DOT: new = gen_dot(clone_ast_node(AST_DOT(node).expr),
+ clone_ast_node(AST_DOT(node).id),
+ node->loc);
break;
case AST_AS: new = gen_as(clone_ast_node(node->_as.type));
@@ -1183,31 +1167,32 @@ struct ast_node *clone_ast_node(struct ast_node *node)
case AST_BINOP: new = gen_binop(node->binop.op,
clone_ast_node(node->binop.left),
clone_ast_node(node->binop.right),
- node->loc);
+ node->loc);
break;
case AST_UNOP: new = gen_unop(node->_unop.op,
clone_ast_node(node->_unop.expr));
break;
- case AST_CALL: new = gen_call(clone_ast_node(node->_call.id),
- clone_ast_node(node->_call.args));
+ case AST_CALL: new = gen_call(clone_ast_node(AST_CALL(node).expr),
+ clone_ast_node(AST_CALL(node).args),
+ node->loc);
break;
case AST_DEFER: new = gen_defer(clone_ast_node(node->_defer.expr));
break;
case AST_MACRO_CONSTRUCT: new = gen_macro_construct(
- clone_ast_node(AST_MACRO_CONSTRUCT(node).id),
- clone_ast_node(AST_MACRO_CONSTRUCT(node).params),
- clone_ast_node(AST_MACRO_CONSTRUCT(node).body));
- break;
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).id),
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).params),
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).body));
+ break;
case AST_MACRO_EXPAND: new = gen_macro_expand(
- clone_ast_node(AST_MACRO_EXPAND(node).id),
- clone_ast_node(AST_MACRO_EXPAND(node).args),
- node->loc);
- break;
+ clone_ast_node(AST_MACRO_EXPAND(node).id),
+ clone_ast_node(AST_MACRO_EXPAND(node).args),
+ node->loc);
+ break;
case AST_CAST: new = gen_cast(clone_ast_node(node->_cast.expr),
clone_ast_node(node->_cast.type));
@@ -1216,26 +1201,14 @@ struct ast_node *clone_ast_node(struct ast_node *node)
case AST_PROC: new = gen_proc(clone_ast_node(node->_proc.id),
clone_ast_node(node->_proc.sign),
clone_ast_node(node->_proc.body),
- node->loc);
+ node->loc);
break;
- case AST_VAR: {
- /* I don't like how messy this is, should maybe try and come up
- * with something better */
- struct ast_node *type = NULL;
- if (node->type)
- type = clone_ast_node(node->type);
- else
- type = clone_ast_node(node->_var.type);
-
- new = gen_var(clone_ast_node(node->_var.id),
- type,
- clone_ast_node(node->_var.init));
- /* vars always reference the type associated with them? */
- if (node->type)
- new->type = type;
+ case AST_VAR: new = gen_var(clone_ast_node(AST_VAR(node).id),
+ clone_ast_node(AST_VAR(node).type),
+ clone_ast_node(AST_VAR(node).init),
+ node->loc);
break;
- }
case AST_FOR: new = gen_for(clone_ast_node(node->_for.pre),
clone_ast_node(node->_for.cond),
@@ -1258,60 +1231,55 @@ struct ast_node *clone_ast_node(struct ast_node *node)
* correctly... */
switch (node->_type.kind) {
case AST_TYPE_PRIMITIVE:
- new = gen_primitive(AST_PRIMITIVE_TYPE(node).type, node->loc);
+ new = gen_primitive(AST_PRIMITIVE_TYPE(
+ node).type, node->loc);
break;
case AST_TYPE_TRAIT:
new = gen_type(AST_TYPE_TRAIT,
AST_TRAIT_TYPE(node).def,
- NULL,
- NULL);
+ NULL,
+ node->loc);
break;
case AST_TYPE_ID:
new = gen_type(AST_TYPE_ID,
clone_ast_node(AST_ID_TYPE(node).id),
NULL,
- NULL);
+ node->loc);
break;
case AST_TYPE_ARR:
new = gen_type(AST_TYPE_ARR,
clone_ast_node(AST_ARR_TYPE(node).size),
clone_ast_node(AST_ARR_TYPE(node).base),
- NULL);
- break;
-
- case AST_TYPE_TYPEOF:
- new = gen_type(AST_TYPE_TYPEOF,
- clone_ast_node(AST_TYPEOF_TYPE(node).expr),
- NULL,
- NULL);
+ node->loc);
break;
case AST_TYPE_POINTER:
- new = gen_type(AST_TYPE_POINTER, AST_PTR_TYPE(node).base, NULL, NULL);
+ new = gen_type(AST_TYPE_POINTER, AST_PTR_TYPE(node).base,
+ NULL,
+ node->loc);
break;
case AST_TYPE_STRUCT:
new = gen_type(AST_TYPE_STRUCT,
clone_ast_node(AST_STRUCT_TYPE(node).def),
- NULL,
- NULL);
+ NULL, node->loc);
break;
case AST_TYPE_ENUM:
new = gen_type(AST_TYPE_ENUM,
clone_ast_node(AST_ENUM_TYPE(node).def),
- NULL,
- NULL);
+ NULL,
+ node->loc);
break;
case AST_TYPE_SIGN:
new = gen_type(AST_TYPE_SIGN,
clone_ast_node(AST_SIGN_TYPE(node).params),
clone_ast_node(AST_SIGN_TYPE(node).ret),
- NULL);
+ node->loc);
break;
}
@@ -1386,8 +1354,10 @@ struct ast_node *clone_ast_node(struct ast_node *node)
break;
case AST_TRAIT:
- new = gen_trait(clone_ast_node(node->_trait.id),
- clone_ast_node(node->_trait.body));
+ new = gen_trait(clone_ast_node(AST_TRAIT(node).id),
+ clone_ast_node(AST_TRAIT(node).params),
+ clone_ast_node(AST_TRAIT(node).body),
+ node->loc);
break;
case AST_IF:
@@ -1506,10 +1476,10 @@ static int identical_unop(int exact, struct ast_node *a, struct ast_node *b)
static int identical_call(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_call.id, b->_call.id))
+ if (!identical_ast_nodes(exact, AST_CALL(a).expr, AST_CALL(b).expr))
return 0;
- if (!identical_ast_nodes(exact, a->_call.args, b->_call.args))
+ if (!identical_ast_nodes(exact, AST_CALL(a).args, AST_CALL(b).args))
return 0;
return 1;
@@ -1531,23 +1501,31 @@ static int identical_defer(int exact, struct ast_node *a, struct ast_node *b)
return identical_ast_nodes(exact, a->_defer.expr, b->_defer.expr);
}
-static int identical_macro_construct(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_macro_construct(int exact, struct ast_node *a,
+ struct ast_node *b)
{
- if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).id, AST_MACRO_CONSTRUCT(b).id))
+ if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).id,
+ AST_MACRO_CONSTRUCT(b).id))
return 0;
- if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).params, AST_MACRO_CONSTRUCT(b).params))
+ if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).params,
+ AST_MACRO_CONSTRUCT(b).params))
return 0;
- return identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).body, AST_MACRO_CONSTRUCT(b).body);
+ return identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(
+ a).body,
+ AST_MACRO_CONSTRUCT(b).body);
}
-static int identical_macro_expand(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_macro_expand(int exact, struct ast_node *a,
+ struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_macro_expand.id, b->_macro_expand.id))
+ if (!identical_ast_nodes(exact, a->_macro_expand.id,
+ b->_macro_expand.id))
return 0;
- if (!identical_ast_nodes(exact, a->_macro_expand.args, b->_macro_expand.args))
+ if (!identical_ast_nodes(exact, a->_macro_expand.args,
+ b->_macro_expand.args))
return 0;
return 1;
@@ -1627,29 +1605,27 @@ static int identical_type_id(int exact, struct ast_node *a, struct ast_node *b)
static int identical_type_arr(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, AST_ARR_TYPE(a).size, AST_ARR_TYPE(b).size))
+ if (!identical_ast_nodes(exact, AST_ARR_TYPE(a).size,
+ AST_ARR_TYPE(b).size))
return 0;
- return identical_ast_nodes(exact, AST_ARR_TYPE(a).base, AST_ARR_TYPE(b).base);
+ return identical_ast_nodes(exact, AST_ARR_TYPE(a).base, AST_ARR_TYPE(
+ b).base);
}
-static int identical_type_trait(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_type_trait(int exact, struct ast_node *a,
+ struct ast_node *b)
{
- return identical_ast_nodes(exact, AST_TRAIT_TYPE(a).def, AST_TRAIT_TYPE(b).def);
+ return identical_ast_nodes(exact, AST_TRAIT_TYPE(a).def,
+ AST_TRAIT_TYPE(b).def);
}
-static int identical_type_primitive(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_type_primitive(int exact, struct ast_node *a,
+ struct ast_node *b)
{
return AST_PRIMITIVE_TYPE(a).type == AST_PRIMITIVE_TYPE(b).type;
}
-static int identical_type_typeof(int exact, struct ast_node *a,
- struct ast_node *b)
-{
- return identical_ast_nodes(exact, AST_TYPEOF_TYPE(a).expr,
- AST_TYPEOF_TYPE(b).expr);
-}
-
static int identical_type_sign(int exact, struct ast_node *a,
struct ast_node *b)
{
@@ -1657,19 +1633,22 @@ static int identical_type_sign(int exact, struct ast_node *a,
AST_SIGN_TYPE(b).params))
return 0;
- return identical_ast_nodes(exact, AST_SIGN_TYPE(a).ret, AST_SIGN_TYPE(b).ret);
+ return identical_ast_nodes(exact, AST_SIGN_TYPE(a).ret, AST_SIGN_TYPE(
+ b).ret);
}
static int identical_type_struct(int exact, struct ast_node *a,
struct ast_node *b)
{
- return identical_ast_nodes(exact, AST_STRUCT_TYPE(a).def, AST_STRUCT_TYPE(b).def);
+ return identical_ast_nodes(exact, AST_STRUCT_TYPE(
+ a).def, AST_STRUCT_TYPE(b).def);
}
static int identical_type_enum(int exact, struct ast_node *a,
struct ast_node *b)
{
- return identical_ast_nodes(exact, AST_ENUM_TYPE(a).def, AST_ENUM_TYPE(b).def);
+ return identical_ast_nodes(exact, AST_ENUM_TYPE(a).def, AST_ENUM_TYPE(
+ b).def);
}
static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
@@ -1679,12 +1658,12 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->_type.kind) {
- case AST_TYPE_PRIMITIVE: ret = identical_type_primitive(exact, a, b); break;
+ case AST_TYPE_PRIMITIVE: ret = identical_type_primitive(exact, a, b);
+ break;
case AST_TYPE_ENUM: ret = identical_type_enum(exact, a, b); break;
case AST_TYPE_TRAIT: ret = identical_type_trait(exact, a, b); break;
case AST_TYPE_ID: ret = identical_type_id(exact, a, b); break;
case AST_TYPE_ARR: ret = identical_type_arr(exact, a, b); break;
- case AST_TYPE_TYPEOF: ret = identical_type_typeof(exact, a, b); break;
case AST_TYPE_SIGN: ret = identical_type_sign(exact, a, b); break;
case AST_TYPE_STRUCT: ret = identical_type_struct(exact, a, b); break;
case AST_TYPE_POINTER: break;
@@ -1850,31 +1829,26 @@ static int identical_fetch(int exact, struct ast_node *a, struct ast_node *b)
return 1;
}
-static int identical_type_expand(int exact, struct ast_node *a, struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, AST_TYPE_EXPAND(a).id, AST_TYPE_EXPAND(b).id))
- return 0;
-
- return identical_ast_nodes(exact, AST_TYPE_EXPAND(a).args, AST_TYPE_EXPAND(b).args);
-}
-
-static int identical_type_construct(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_type_expand(int exact, struct ast_node *a,
+ struct ast_node *b)
{
- if (!identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).id, AST_TYPE_CONSTRUCT(b).id))
- return 0;
-
- if (!identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).params, AST_TYPE_CONSTRUCT(b).params))
+ if (!identical_ast_nodes(exact, AST_TYPE_EXPAND(a).id,
+ AST_TYPE_EXPAND(b).id))
return 0;
- return identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).body, AST_TYPE_CONSTRUCT(b).body);
+ return identical_ast_nodes(exact, AST_TYPE_EXPAND(
+ a).args, AST_TYPE_EXPAND(b).args);
}
-static int identical_arr_access(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_arr_access(int exact, struct ast_node *a,
+ struct ast_node *b)
{
- if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).base, AST_ARR_ACCESS(b).base))
+ if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).base,
+ AST_ARR_ACCESS(b).base))
return 0;
- if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).idx, AST_ARR_ACCESS(b).idx))
+ if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).idx,
+ AST_ARR_ACCESS(b).idx))
return 0;
return 1;
@@ -1913,7 +1887,6 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->node_type) {
case AST_ARR_ACCESS: ret = identical_arr_access(exact, a, b); break;
- case AST_TYPE_CONSTRUCT: ret = identical_type_construct(exact, a, b); break;
case AST_TYPE_EXPAND: ret = identical_type_expand(exact, a, b); break;
case AST_FETCH: ret = identical_fetch(exact, a, b); break;
case AST_ASSIGN: ret = identical_assign(exact, a, b); break;
@@ -1928,7 +1901,8 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
case AST_CALL: ret = identical_call(exact, a, b); break;
case AST_CAST: ret = identical_cast(exact, a, b); break;
case AST_DEFER: ret = identical_defer(exact, a, b); break;
- case AST_MACRO_CONSTRUCT: ret = identical_macro_construct(exact, a, b); break;
+ case AST_MACRO_CONSTRUCT: ret = identical_macro_construct(exact, a, b);
+ break;
case AST_MACRO_EXPAND: ret = identical_macro_expand(exact, a, b); break;
case AST_PROC: ret = identical_proc(exact, a, b); break;
case AST_VAR: ret = identical_var(exact, a, b); break;
@@ -2068,7 +2042,7 @@ static int call_on_alias(int (*call)(struct ast_node *,
}
static int call_on_trait(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+ void *), struct ast_node *node, void *data)
{
int ret = 0;
ret |= call(node->_trait.id, data);
@@ -2134,7 +2108,7 @@ static int call_on_case(int (*call)(struct ast_node *,
}
static int call_on_type_trait(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+ void *), struct ast_node *node, void *data)
{
int ret = 0;
ret |= call(AST_TRAIT_TYPE(node).def, data);
@@ -2153,12 +2127,6 @@ static int call_on_type_arr(int (*call)(struct ast_node *,
return call(AST_ARR_TYPE(node).size, data);
}
-static int call_on_type_typeof(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_TYPEOF_TYPE(node).expr, data);
-}
-
static int call_on_type_struct(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
@@ -2193,8 +2161,8 @@ static int call_on_type(int (*call)(struct ast_node *,
case AST_TYPE_TRAIT: ret = call_on_type_trait(call, node, data); break;
case AST_TYPE_ID: ret = call_on_type_id(call, node, data); break;
case AST_TYPE_ARR: ret = call_on_type_arr(call, node, data); break;
- case AST_TYPE_TYPEOF: ret = call_on_type_typeof(call, node, data); break;
- case AST_TYPE_STRUCT: ret = call_on_type_struct(call, node, data); break;
+ case AST_TYPE_STRUCT: ret = call_on_type_struct(call, node, data);
+ break;
case AST_TYPE_SIGN: ret = call_on_type_sign(call, node, data); break;
case AST_TYPE_POINTER: break;
case AST_TYPE_PRIMITIVE: break;
@@ -2234,13 +2202,13 @@ static int call_on_call(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_call.id, data);
- ret |= call(node->_call.args, data);
+ ret |= call(AST_CALL(node).expr, data);
+ ret |= call(AST_CALL(node).args, data);
return ret;
}
static int call_on_macro_construct(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+ void *), struct ast_node *node, void *data)
{
int ret = 0;
ret |= call(AST_MACRO_CONSTRUCT(node).id, data);
@@ -2274,7 +2242,8 @@ static int call_on_fetch(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_macro_expand(int (*call)(struct ast_node *, void *), struct ast_node *node, void *data)
+static int call_on_macro_expand(int (*call)(struct ast_node *,
+ void *), struct ast_node *node, void *data)
{
int ret = 0;
ret |= call(node->_macro_expand.id, data);
@@ -2282,17 +2251,8 @@ static int call_on_macro_expand(int (*call)(struct ast_node *, void *), struct a
return ret;
}
-static int call_on_type_construct(int (*call)(struct ast_node *, void *), struct ast_node *type_construct, void *data)
-{
- int ret = 0;
- /* pretty verbose, hmm */
- ret |= call(AST_TYPE_CONSTRUCT(type_construct).id, data);
- ret |= call(AST_TYPE_CONSTRUCT(type_construct).params, data);
- ret |= call(AST_TYPE_CONSTRUCT(type_construct).body, data);
- return ret;
-}
-
-static int call_on_type_expand(int (*call)(struct ast_node *, void *), struct ast_node *type_expand, void *data)
+static int call_on_type_expand(int (*call)(struct ast_node *,
+ void *), struct ast_node *type_expand, void *data)
{
int ret = 0;
ret |= call(AST_TYPE_EXPAND(type_expand).id, data);
@@ -2316,8 +2276,8 @@ int ast_call_on(int (*call)(struct ast_node *,
switch (node->node_type) {
case AST_ARR_ACCESS:
- case AST_TYPE_CONSTRUCT: ret = call_on_type_construct(call, node, data); break;
- case AST_TYPE_EXPAND: ret = call_on_type_expand(call, node, data); break;
+ case AST_TYPE_EXPAND: ret = call_on_type_expand(call, node, data);
+ break;
case AST_FETCH: ret = call_on_fetch(call, node, data); break;
case AST_ASSIGN: ret = call_on_assign(call, node, data); break;
case AST_INIT: ret = call_on_init(call, node, data); break;
@@ -2344,8 +2304,10 @@ int ast_call_on(int (*call)(struct ast_node *,
case AST_BINOP: ret = call_on_binop(call, node, data); break;
case AST_UNOP: ret = call_on_unop(call, node, data); break;
case AST_CALL: ret = call_on_call(call, node, data); break;
- case AST_MACRO_CONSTRUCT: ret = call_on_macro_construct(call, node, data); break;
- case AST_MACRO_EXPAND: ret = call_on_macro_expand(call, node, data); break;
+ case AST_MACRO_CONSTRUCT: ret =
+ call_on_macro_construct(call, node, data); break;
+ case AST_MACRO_EXPAND: ret = call_on_macro_expand(call, node, data);
+ break;
case AST_PROC: ret = call_on_proc(call, node, data); break;
case AST_BLOCK: ret = call_on_block(call, node, data); break;
case AST_EMBED: break;
diff --git a/src/compiler.c b/src/compiler.c
index a096878..5845283 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -103,7 +103,6 @@ static int process(struct scope **parent, int public, const char *file)
scope->fctx.fbuf = buf;
scope->fctx.fname = strdup(file);
- scope->actuals = create_actuals();
scope_set_flags(scope, SCOPE_FILE);
if (*parent)
@@ -173,31 +172,21 @@ int compile(const char *input, const char *output) {
return ret;
}
- ret = actualize_main(root);
- if (ret) {
+ if ((ret = actualize_main(root))) {
destroy_scope(root);
destroy_ast_nodes();
error("compilation of %s stopped due to errors", input);
return ret;
}
- struct ops *ops = create_ops();
- ret = lower_ops(root, ops);
- destroy_scope(root);
- destroy_ast_nodes();
-
- if (ret) {
- destroy_ops(ops);
- error("compilation of %s stopped due to errors", input);
- return ret;
- }
-
- ret = alloc_regs(ops);
- if (ret) {
- destroy_ops(ops);
+ if ((ret = lower_ops(root, output))) {
+ destroy_scope(root);
+ destroy_ast_nodes();
error("compilation of %s stopped due to errors", input);
return ret;
}
- return print_asm(ops, output);
+ destroy_scope(root);
+ destroy_ast_nodes();
+ return 0;
}
diff --git a/src/debug.c b/src/debug.c
index b110b9b..2c873a2 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -225,14 +225,9 @@ static void _type_str(FILE *fp, struct ast_node *type)
break;
}
- case AST_TYPE_TYPEOF: {
- fprintf(fp, "(typeof)");
- break;
- }
-
case AST_TYPE_PRIMITIVE: {
fprintf(fp, "%s", primitive_str(AST_PRIMITIVE_TYPE(type).type));
- break;
+ break;
}
default:
@@ -271,11 +266,13 @@ char *type_str(struct ast_node *node)
*/
static void _call_str(FILE *f, struct ast_node *call)
{
- struct ast_node *id = call->_call.id;
- const char *id_str = id->_id.id;
- fprintf(f, "%s", id_str);
+ struct ast_node *expr = AST_CALL(call).expr;
+ if (expr->node_type == AST_ID) {
+ const char *id_str = AST_ID(expr).id;
+ fprintf(f, "%s", id_str);
+ }
- struct ast_node *args = call->_call.args;
+ struct ast_node *args = AST_CALL(call).args;
fprintf(f, "(");
while (args) {
diff --git a/src/lexer.l b/src/lexer.l
index a446c49..c819328 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -39,7 +39,7 @@ HEXF [+-]?0[xX][0-9a-fA-F]+([pP][+-]?[0-9]+)
DECF [+-]?[0-9]+[.]([eE]?[+-]?[0-9]+)?[fF]?
ID [_a-zA-Z][_a-zA-Z0-9]*
-APPLY {ID}[[:space:]]*!
+APPLY {ID}!
STRING \"(\\.|[^"\\])*\"
@@ -151,7 +151,6 @@ STRING \"(\\.|[^"\\])*\"
"struct" {return STRUCT;}
"typedef" {return TYPEDEF;}
"import" {return IMPORT;}
-"typeof" {return TYPEOF;}
"sizeof" {return SIZEOF;}
"embed" {return EMBED;}
"if" {return IF;}
diff --git a/src/ops.c b/src/ops.c
index 9562035..cc2650c 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -43,7 +43,7 @@ static size_t trivial_type_width(struct ast_node *type)
return 3;
}
-struct ops *create_ops()
+static struct ops *create_ops()
{
struct ops *ops = calloc(1, sizeof(struct ops));
@@ -56,15 +56,22 @@ struct ops *create_ops()
return ops;
}
-void destroy_ops(struct ops *ops)
+static void destroy_ops(struct ops *ops)
{
if (!ops)
return;
- struct op *base = ops->base;
- while (base) {
- struct op *prev = base;
- base = base->next;
+ struct op *op = ops->base;
+ while (op) {
+ struct op *prev = op;
+ op = op->next;
+
+ switch (prev->opcode) {
+ case OP_COMMENT: free((void *)prev->string); break;
+ case OP_LABEL: free((void *)prev->string); break;
+ default:
+ }
+
free(prev);
}
@@ -143,9 +150,9 @@ static int lower_var(struct ast_node *n, struct ops *ops)
* immediately run out of registers? */
struct ast_node *type = d->type;
if (AST_TYPE(type).kind != AST_TYPE_PRIMITIVE
- && AST_TYPE(type).kind != AST_TYPE_POINTER) {
+ && AST_TYPE(type).kind != AST_TYPE_POINTER) {
semantic_error(n->scope->fctx, n,
- "only trivial type lowering implemented");
+ "only trivial type lowering implemented");
return -1;
}
@@ -177,7 +184,8 @@ static int lower_cast(struct ast_node *n, struct ops *ops)
static int lower_const(struct ast_node *n, struct ops *ops)
{
if (AST_CONST(n).kind != AST_CONST_INTEGER) {
- semantic_error(n->scope->fctx, n, "only integer constant lowering implemented");
+ semantic_error(n->scope->fctx, n,
+ "only integer constant lowering implemented");
return -1;
}
@@ -209,7 +217,8 @@ static int lower_assign(struct ast_node *n, struct ops *ops)
static int lower_unop(struct ast_node *n, struct ops *ops)
{
if (AST_UNOP(n).op != AST_DEREF) {
- semantic_error(n->scope->fctx, n, "unop lowering not implemented");
+ semantic_error(n->scope->fctx, n,
+ "unop lowering not implemented");
return -1;
}
@@ -281,8 +290,8 @@ static int lower_op(struct ast_node *n, struct ops *ops)
case AST_ID: ret = lower_id(n, ops); break;
case AST_RETURN: ret = lower_ret(n, ops); break;
default:
- semantic_error(n->scope->fctx, n, "unimplemented lowering");
- return -1;
+ semantic_error(n->scope->fctx, n, "unimplemented lowering");
+ return -1;
}
if (ret)
@@ -353,21 +362,6 @@ static void print_ops(struct ops *ops)
}
}
-int lower_ops(struct scope *root, struct ops *ops)
-{
- for (struct actual *a = root->actuals; a; a = a->next) {
- assert(a->node);
- int ret = lower_op(a->node, ops);
- if (ret)
- return ret;
- }
-
- printf("Lowered ops before lifetime analysis:\n");
- print_ops(ops);
-
- return 0;
-}
-
static enum opcode st_opc(struct loc *loc)
{
switch (loc->width) {
@@ -395,8 +389,9 @@ static int realize_moves(struct ops *ops)
/* completely arbitrary and *will* have to be made better in the near
* future */
static const size_t tmp_reg = 9;
+ struct op *prev = NULL;
struct op *op = ops->base;
- for (; op; op = op->next) {
+ for (; op; prev = op, op = op->next) {
if (op->opcode != OP_MV) {
continue;
}
@@ -407,12 +402,18 @@ static int realize_moves(struct ops *ops)
assert(i->next == NULL);
if (i->kind == LOC_REG && o->kind == LOC_REG) {
- continue;
- } else if (i->kind == LOC_REG && o->kind == LOC_MEM) {
+ /* if move is between the same register, skip it */
+ if (i->reg == o->reg && prev)
+ prev->next = op->next;
+
+ }
+ else if (i->kind == LOC_REG && o->kind == LOC_MEM) {
op->opcode = st_opc(o);
- } else if (i->kind == LOC_MEM && o->kind == LOC_REG) {
+ }
+ else if (i->kind == LOC_MEM && o->kind == LOC_REG) {
op->opcode = ld_opc(i);
- } else if (i->kind == LOC_MEM && o->kind == LOC_MEM) {
+ }
+ else if (i->kind == LOC_MEM && o->kind == LOC_MEM) {
op->opcode = ld_opc(i);
/* our input/output are references, so call this before
* setting registers for our original operation. Also,
@@ -428,12 +429,59 @@ static int realize_moves(struct ops *ops)
return 0;
}
-int alloc_regs(struct ops *ops)
+static int alloc_regs(struct ops *ops)
{
/** @todo analyze lifetime, for now just convert moves to correct ldst
* etc. */
- int ret = realize_moves(ops);
- printf("Lowered ops after lifetime analysis:\n");
- print_ops(ops);
+ /** @todo lifetime analysis could be done by looping over all ops, and
+ * when we encounter a virtual register we haven't seen before, add it
+ * to a list. When we encounter it used again, extend its lifetime to
+ * wherever we are in the function. */
+ return realize_moves(ops);
+}
+
+int lower_ops(struct scope *root, const char *fname)
+{
+ FILE *f = fopen(fname, "w");
+
+ /* main should probably be mangled here as well */
+ fprintf(f, "jal x21, main\n");
+ /* tell simulator to turn off (very much temp) */
+ fprintf(f, "li x1, 3\n");
+ fprintf(f, "csrrw mpower, x0, x1\n");
+
+ /* this can potentially be parallelized in the future */
+ int ret = 0;
+ for (struct actual *a = root->actuals; a; a = a->next) {
+ assert(a->node);
+
+ struct ops *ops = create_ops();
+ if ((ret = lower_op(a->node, ops))) {
+ destroy_ops(ops);
+ break;
+ }
+
+ printf("Lowered ops before lifetime analysis:\n");
+ print_ops(ops);
+
+ if ((ret = alloc_regs(ops))) {
+ destroy_ops(ops);
+ break;
+ }
+
+ printf("Lowered ops after lifetime analysis:\n");
+ print_ops(ops);
+
+ if ((ret = print_asm(ops, f))) {
+ /* kind of silly as of now but eh */
+ destroy_ops(ops);
+ break;
+ }
+
+ destroy_ops(ops);
+ }
+
+ fclose(f);
return ret;
}
+
diff --git a/src/parser.y b/src/parser.y
index 4def5fd..1d09856 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -44,9 +44,6 @@
%token SEMICOLON ";"
%token COLON ":"
%token BANG "!"
-/* still not sure if this should be just typeof, would be slower to type I guess */
-%token TYPEOF "typeof"
-/* typeof does sort of fit into sizeof, hmmm */
%token SIZEOF "sizeof"
%token STAR "*"
%token DIV "/"
@@ -119,7 +116,7 @@
%left "<<" ">>"
%left "+" "-"
%left "*" "/" "%"
-%left "as" "sizeof" "typeof"
+%left "as" "sizeof"
%right "'" "!" "~"
%left "." "=>" "(" ")"
%left "::"
@@ -129,12 +126,12 @@
%nterm <node> while do_while statement statements body references macro
%nterm <node> exprs if for case cases switch const
%nterm <node> func_sign type var_decl var
-%nterm <node> var_init proc trait_elem trait_elems
+%nterm <node> var_init proc
%nterm <node> alias trait enum_val enums enum top unit id
-%nterm <node> embed param_decl members struct_elem
+%nterm <node> embed param_decl members
%nterm <node> top_if const_if const_for defer goto assign
%nterm <node> construct construct_args construct_arg
-%nterm <node> statelet apply
+%nterm <node> statelet apply types
%nterm <node> tagged_struct anon_struct tagged_union anon_union
@@ -143,11 +140,15 @@
%nterm <node> macro_expand type_expand
-%nterm <node> type_construct type_params type_param
+%nterm <node> type_params type_param
/* array stuff */
%nterm <node> arr arr_inits arr_init
+/* optional stuff */
+%nterm <node> opt_args opt_exprs proc_decl member opt_members
+%nterm <node> opt_statements opt_types
+
%{
/** Modifies the signature of yylex to fit our parser better. */
@@ -278,8 +279,12 @@ unop
| "*" expr { $$ = gen_unop(AST_DEREF, $2); }
arr_init
- : "=>" const_expr "..." const_expr "=" arg { $$ = gen_var($2, $4, $6); }
- | "=>" const_expr "=" arg { $$ = gen_var($2, NULL, $4); }
+ : "=>" const_expr "..." const_expr "=" arg {
+ $$ = gen_var($2, $4, $6, src_loc(@$));
+ }
+ | "=>" const_expr "=" arg {
+ $$ = gen_var($2, NULL, $4, src_loc(@$));
+ }
| arg
arr_inits
@@ -302,7 +307,7 @@ args
| arg
param_decl
- : type { $$ = gen_var(NULL, $1, NULL); }
+ : type { $$ = gen_var(NULL, $1, NULL, src_loc(@$)); }
| var_decl
decls
@@ -366,15 +371,15 @@ const_expr
/* TODO: concatenate multiple strings together? Or is that the lexer's job? */
expr
- : expr "." id { $$ = gen_dot($1, $3); }
+ : expr "." id { $$ = gen_dot($1, $3, src_loc(@$)); }
| "..." id { $$ = $2; }
| INT { $$ = gen_int($1); }
| STRING {
$$ = gen_string(clone_string($1));
}
| "(" expr ")" { $$ = $2; }
- | expr "(" args ")" { $$ = gen_call($1, $3); }
- | expr "(" ")" { $$ = gen_call($1, NULL); }
+ | expr "(" args ")" { $$ = gen_call($1, $3, src_loc(@$)); }
+ | expr "(" ")" { $$ = gen_call($1, NULL, src_loc(@$)); }
| expr "[" expr "]" { $$ = gen_arr_access($1, $3, src_loc(@$)); /** @todo add arr access */}
| "(" var_init ")" { $$ = $2; }
| "sizeof" expr { $$ = gen_sizeof($2); }
@@ -404,16 +409,14 @@ goto
statelet
: "return" args { $$ = gen_return($2); }
| "return" { $$ = gen_return(NULL); }
- | "break" { $$ = gen_ctrl(AST_CTRL_BREAK, src_loc(yylloc)); }
- | "continue" { $$ = gen_ctrl(AST_CTRL_CONTINUE, src_loc(yylloc)); }
+ | "break" { $$ = gen_ctrl(AST_CTRL_BREAK, src_loc(@$)); }
+ | "continue" { $$ = gen_ctrl(AST_CTRL_CONTINUE, src_loc(@$)); }
| trait
| import
| alias
| exprs
- | const
| goto
| var
- | ";" { $$ = gen_empty(); }
| error {
/* TODO: figure out how to destroy any and all possible ast nodes we
* may have generated up until the error */
@@ -439,8 +442,10 @@ statement
| for
| defer
| if
+ | const
| enum
| macro
+ | ";" { $$ = gen_empty(); }
| id ":" { $$ = gen_label($1); }
statements
@@ -448,10 +453,12 @@ statements
| statement
| statelet
+opt_statements
+ : statements
+ | {$$ = NULL;}
body
- : "{" statements "}" { $$ = gen_block($2); }
- | "{" "}" { $$ = gen_block(gen_empty()); }
+ : "{" opt_statements "}" { $$ = gen_block($2); }
references
: id "," references { $$ = $1; $$->next = $3; }
@@ -481,7 +488,7 @@ exprs
construct_arg
: "." id "=" expr {
- $$ = gen_var($2, NULL, $4);
+ $$ = gen_var($2, NULL, $4, src_loc(@$));
ast_set_flags($$, AST_FLAG_MEMBER);
}
@@ -497,9 +504,17 @@ if
| "if" expr body "else" body { $$ = gen_if($2, $3, $5); }
| "if" expr body "else" if { $$ = gen_if($2, $3, $5); }
-/* todo how about leaving out some parts? */
+opt_args
+ : args
+ | {$$ = NULL;}
+
+opt_exprs
+ : exprs
+ | {$$ = NULL;}
+
for
- : "for" arg ";" expr ";" expr body { $$ = gen_for($2, $4, $6, $7); }
+ : "for" opt_args ";" opt_exprs ";" exprs body { $$ = gen_for($2, $4, $6, $7); }
+ | "for" opt_args ";" opt_exprs ";" body {}
case
: "case" const_expr ":" statements {
@@ -509,6 +524,8 @@ case
$$ = gen_case($2, $4);
}
| "default" ":" statements {
+ /* default seems like it would be useful as something other than
+ * a keyword... */
$$ = gen_case(NULL, $3);
}
@@ -550,29 +567,26 @@ const
func_sign
: "(" decls "=>" type ")" {
- $$ = gen_type(AST_TYPE_SIGN, $2, $4, NULL);
+ $$ = gen_type(AST_TYPE_SIGN, $2, $4, src_loc(@$));
}
- | "(" decls ")" { $$ = gen_type(AST_TYPE_SIGN, $2, NULL, NULL); }
- | "(" decls "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, $2, NULL, NULL); }
- | "(" "=>" type ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $3, NULL); }
- | "(" "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, NULL); }
- | "(" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, NULL); }
+ | "(" decls ")" { $$ = gen_type(AST_TYPE_SIGN, $2, NULL, src_loc(@$)); }
+ | "(" decls "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, $2, NULL, src_loc(@$)); }
+ | "(" "=>" type ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $3, src_loc(@$)); }
+ | "(" "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, src_loc(@$)); }
+ | "(" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, src_loc(@$)); }
type
- : id { $$ = gen_type(AST_TYPE_ID, $1, NULL, NULL); }
+ : id { $$ = gen_type(AST_TYPE_ID, $1, NULL, src_loc(@$)); }
| "^" func_sign {
/* still not entirely sold on this signature, but it's not terrible I
* guess */
- $$ = gen_type(AST_TYPE_POINTER, $2, NULL, NULL);
+ $$ = gen_type(AST_TYPE_POINTER, $2, NULL, src_loc(@$));
}
| "*" type {
- $$ = gen_type(AST_TYPE_POINTER, $2, NULL, NULL);
+ $$ = gen_type(AST_TYPE_POINTER, $2, NULL, src_loc(@$));
}
| "[" const_expr "]" type {
- $$ = gen_type(AST_TYPE_ARR, $2, $4, NULL);
- }
- | "typeof" expr {
- $$ = gen_type(AST_TYPE_TYPEOF, $2, NULL, NULL);
+ $$ = gen_type(AST_TYPE_ARR, $2, $4, src_loc(@$));
}
| "const" type {
$$ = $2;
@@ -581,32 +595,37 @@ type
$$ = $2; ast_set_flags($$, AST_FLAG_MUTABLE);
}
| anon_struct
- /* syntactic sugar for struct {union {...} } */
| anon_union
- /* syntactic sugar for anon_struct */
- | type_expand
+ | apply "[" opt_types "]" {
+ $$ = gen_type(AST_TYPE_CONSTRUCT, $1, $3, src_loc(@$));
+ }
types
- : type "," types
+ : type "," types { $$ = $1; $$->next = $3; }
| type
-/* vec![int] is effectively struct {vec![int]} */
+opt_types
+ : types
+ | { $$ = NULL; }
+
type_expand
- : apply "[" types "]"
- /* legal, but weird */
- | apply "[" "]"
+ : apply "[" opt_types "]" { $$ = gen_type_expand($1, $3, src_loc(@$)); }
var_decl
- : type id { $$ = gen_var($2, $1, NULL); }
+ : type id { $$ = gen_var($2, $1, NULL, src_loc(@$)); }
var_init
: var_decl "=" arg { $$ = $1; $$->_var.init = $3; }
- | "const" id "=" arg { $$ = gen_var($2, NULL, $4); }
+ | "const" id "=" arg { $$ = gen_var($2, NULL, $4, src_loc(@$)); }
| "mut" id "=" arg {
- $$ = gen_var($2, NULL, $4);
+ $$ = gen_var($2, NULL, $4, src_loc(@$));
ast_set_flags($$, AST_FLAG_MUTABLE);
}
+proc_decl
+ : id func_sign {
+ $$ = gen_proc($1, $2, NULL, src_loc(@$));
+ }
proc
: id func_sign body {
$$ = gen_proc($1, $2, $3, src_loc(@$));
@@ -619,74 +638,55 @@ proc
ast_set_flags($$, AST_FLAG_EXTERN);
}
-struct_elem
- : var_decl
- | type_expand
+member
+ : var_decl ";"
+ | type_expand ";"
+ | proc_decl ";"
+ | id ";"
+ | proc
;
members
- : struct_elem ";" members { $$ = $1; $1->next = $3; }
- | struct_elem ";"
+ : member members { $$ = $1; $1->next = $2; }
+ | member
+
+opt_members
+ : members
+ | {$$ = NULL;}
tagged_union
- : "union" id "{" members "}" {
+ : "union" id "{" opt_members "}" {
/* essentially struct {union{members}} */
$$ = gen_struct($2, NULL, $4);
}
anon_union
- : "union" "{" members "}" { $$ = gen_struct(NULL, NULL, $3); }
+ : "union" "{" opt_members "}" { $$ = gen_struct(NULL, NULL, $3); }
macro_expand
- : apply "(" ")" { $$ = gen_macro_expand($1, NULL, src_loc(@$)); }
- | apply "(" args ")" { $$ = gen_macro_expand($1, $3, src_loc(@$)); }
+ : apply "(" opt_args ")" { $$ = gen_macro_expand($1, $3, src_loc(@$)); }
tagged_struct
- : "struct" id "{" members "}" {
+ : "typedef" id "{" opt_members "}" {
$$ = gen_struct($2, NULL, $4);
}
anon_struct
- : "struct" "{" members "}" { $$ = gen_struct(NULL, NULL, $3); }
-
-trait_elem
- : id /* trait */
- | id func_sign { $$ = gen_proc($1, $2, NULL, src_loc(@$)); } /* proc */
- | var_decl /* member */
- | type_expand /* type construction */
-
-trait_elems
- : trait_elem ";" trait_elems { $$ = $1; $1->next = $3; }
- | trait_elem ";"
- | trait_elem
+ : "typedef" "{" opt_members "}" { $$ = gen_struct(NULL, NULL, $3); }
alias
: "typedef" id type { $$ = gen_alias($2, $3); }
-/* we'll parse the arg list later in the AST and check that each node is of some
- * specific type */
-trait
- : "typedef" id "{" trait_elems "}" {
- $$ = gen_trait($2, $4);
- }
- | "typedef" id "{" "}" {
- /* should match anything, but doesn't implement anything */
- $$ = gen_trait($2, NULL);
- }
-
type_param
- : id id { $$ = gen_var($2, $1, NULL); }
+ : id id { $$ = gen_var($2, $1, NULL, src_loc(@$)); }
type_params
: type_param "," type_params { $$ = $1; $1->next = $3; }
| type_param
-type_construct
- : "typedef" id "[" type_params "]" "{" members "}" {
- $$ = gen_type_construct($2, $4, $7, src_loc(@$));
- }
- | "typedef" id "[" "]" "{" members "}" {
- $$ = gen_type_construct($2, NULL, $6, src_loc(@$));
+trait
+ : "typedef" id "[" type_params "]" "{" opt_members "}" {
+ $$ = gen_trait($2, $4, $7, src_loc(@$));
}
enum_val
@@ -726,7 +726,6 @@ top
| proc
| tagged_struct
| tagged_union
- | type_construct
| macro { $$ = $1; }
| top_if { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); }
| import { $$ = $1; }
@@ -735,7 +734,6 @@ top
| "pub" enum { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" tagged_struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" tagged_union { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
- | "pub" type_construct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" proc { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" macro { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" import { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
diff --git a/src/scope.c b/src/scope.c
index 6c94aec..329b5f1 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -17,158 +17,6 @@
#include <ek/scope.h>
#include <ek/actualize.h>
-static struct ast_node *match_proc(struct scope *scope,
- struct ast_node *id,
- struct ast_node *args);
-
-static struct ast_node *match_macro(struct scope *scope,
- struct ast_node *id, struct ast_node *args);
-
-static struct param_node *find_matching_param(struct resolve_node *node,
- struct ast_node *type)
-{
- struct param_node *param = node->params;
- while (param) {
- if (types_match(type, param->type))
- return param;
-
- param = param->next;
- }
-
- return NULL;
-}
-
-static int traits_resolve(struct ast_node *arg_type, struct ast_node *param_type)
-{
- /** @todo are more checks required? arg_type should already be in
- * `as`-form*/
- return AST_TRAIT_TYPE(arg_type).def == AST_TRAIT_TYPE(param_type).def;
-}
-
-static int types_resolve(struct ast_node *arg_type, struct ast_node *param_type)
-{
- /* untyped resolves all */
- if (!param_type)
- return 1;
-
- /* if arg is specifying to be matches as `as`, then do it */
- if (AST_TYPE(arg_type).as)
- return types_resolve(AST_TYPE(arg_type).as, param_type);
-
- if (AST_TYPE(param_type).kind == AST_TYPE_TRAIT)
- return traits_resolve(arg_type, param_type);
-
- /* typeof is matched later */
- if (AST_TYPE(param_type).kind == AST_TYPE_TYPEOF)
- return 1;
-
- return types_match(arg_type, param_type);
-}
-
-static struct param_node *find_resolving_param(struct resolve_node *node,
- struct ast_node *type)
-{
- struct param_node *param = node->params;
- while (param) {
- if (types_resolve(type, param->type))
- return param;
-
- param = param->next;
- }
-
- return NULL;
-}
-
-static struct resolve_node *insert_resolve(struct resolve_node *node,
- struct ast_node *type)
-{
- struct param_node *new = calloc(1, sizeof(struct param_node));
- if (!new) {
- return NULL;
- }
- new->type = type;
-
- struct resolve_node *next = calloc(1, sizeof(struct resolve_node));
- if (!next) {
- free(new);
- return NULL;
- }
- new->resolved = next;
-
- if (!node->params) {
- node->params = new;
- return next;
- }
-
- new->next = node->params;
- node->params = new;
-
- return next;
-}
-
-static int add_next_resolve(struct scope *scope, struct ast_node *resolve,
- struct resolve_node *node, struct ast_node *params)
-{
- assert(node);
-
- /* TODO: variadics in macros? */
- /* we've run out of params, check if this is a suitable node */
- if (!params) {
- /* node is already occupied, error on ambiguous definition */
- if (node->resolved) {
- semantic_error(scope->fctx, resolve, "ambiguous resolution");
- semantic_error(scope->fctx, node->resolved, "matches here");
- return -1;
- }
-
- node->resolved = resolve;
- return 0;
- }
-
- assert(params->node_type == AST_VAR);
- struct param_node *match = find_matching_param(node, params->type);
- if (match)
- return add_next_resolve(scope, resolve,
- match->resolved,
- params->next);
-
- /** @todo referential stuff, should only one be allowed per slot or
- * something? */
- struct resolve_node *next = insert_resolve(node, params->type);
- if (!next)
- return -1;
-
- return add_next_resolve(scope, resolve, next, params->next);
-}
-
-static int add_resolve(struct scope *scope, struct resolve *resolve,
- struct ast_node *proc)
-{
- struct ast_node *sign = AST_PROC(proc).sign;
- struct ast_node *params = AST_SIGN_TYPE(sign).params;
- return add_next_resolve(scope, proc, resolve->root, params);
-}
-
-static struct ast_node *resolve(struct scope *scope,
- struct resolve_node *node,
- struct ast_node *args)
-{
- assert(node);
- /* check for no parameters case */
- if (!args) {
- if (node->resolved)
- return node->resolved;
-
- return NULL;
- }
-
- struct param_node *found = find_resolving_param(node, args->type);
- if (found)
- return resolve(scope, found->resolved, args->next);
-
- return NULL;
-}
-
struct scope *create_scope()
{
/* if I ever try making the parser multithreaded, this should be atomic. */
@@ -184,17 +32,6 @@ struct scope *create_scope()
return scope;
}
-struct actual *create_actuals()
-{
- struct actual *actuals = calloc(1, sizeof(struct actual));
- if (!actuals) {
- internal_error("ran out of memory allocating actuals");
- return NULL;
- }
-
- return actuals;
-}
-
void destroy_visible(struct scope *scope, struct visible *visible)
{
struct visible *prev = visible, *cur;
@@ -206,63 +43,16 @@ void destroy_visible(struct scope *scope, struct visible *visible)
} while ((prev = cur));
}
-void destroy_actuals(struct actual *actuals)
-{
- struct actual *prev = actuals, *cur;
- if (prev)
- do {
- cur = prev->next;
- free(prev);
- } while ((prev = cur));
-}
-
-void destroy_resolve_node(struct resolve_node *);
-
-void destroy_param_nodes(struct param_node *param)
-{
- if (!param)
- return;
-
- destroy_resolve_node(param->resolved);
- destroy_param_nodes(param->next);
- free(param);
-}
-
-void destroy_resolve_node(struct resolve_node *resolve)
-{
- if (!resolve)
- return;
-
- destroy_param_nodes(resolve->params);
- free(resolve);
-}
-
-void destroy_resolve(struct resolve *resolve)
-{
- struct resolve *prev = resolve, *cur;
- if (prev)
- do {
- cur = prev->next;
- destroy_resolve_node(prev->root);
- free(prev);
- } while ((prev = cur));
-}
-
void destroy_scope(struct scope *scope)
{
if (!scope)
return;
if (scope_flags(scope, SCOPE_FILE)) {
- destroy_actuals(scope->actuals);
free((void *)scope->fctx.fbuf);
free((void *)scope->fctx.fname);
}
- destroy_resolve(scope->proc_resolve);
- destroy_resolve(scope->macro_resolve);
- destroy_resolve(scope->type_construct_resolve);
-
destroy_visible(scope, scope->vars);
destroy_visible(scope, scope->types);
@@ -297,7 +87,8 @@ static struct visible *create_visible(struct ast_node *id,
return visible;
}
-struct visible *create_type(struct scope *scope, struct ast_node *id, struct ast_node *type)
+struct visible *create_type(struct scope *scope, struct ast_node *id,
+ struct ast_node *type)
{
struct visible *n = create_visible(id, type);
if (!n)
@@ -305,10 +96,12 @@ struct visible *create_type(struct scope *scope, struct ast_node *id, struct ast
n->next = scope->types;
scope->types = n;
+
return n;
}
-struct visible *create_var(struct scope *scope, struct ast_node *id, struct ast_node *var)
+struct visible *create_var(struct scope *scope, struct ast_node *id,
+ struct ast_node *var)
{
struct visible *n = create_visible(id, var);
if (!n)
@@ -316,6 +109,33 @@ struct visible *create_var(struct scope *scope, struct ast_node *id, struct ast_
n->next = scope->vars;
scope->vars = n;
+
+ return n;
+}
+
+struct visible *create_macro(struct scope *scope, struct ast_node *id,
+ struct ast_node *macro)
+{
+ struct visible *n = create_visible(id, macro);
+ if (!n)
+ return NULL;
+
+ n->next = scope->macros;
+ scope->macros = n;
+
+ return n;
+}
+
+struct visible *create_proc(struct scope *scope, struct ast_node *id,
+ struct ast_node *proc)
+{
+ struct visible *n = create_visible(id, proc);
+ if (!n)
+ return NULL;
+
+ n->next = scope->procs;
+ scope->procs = n;
+
return n;
}
@@ -329,13 +149,15 @@ int scope_add_var(struct scope *scope, struct ast_node *var)
}
create_var(scope, AST_VAR(var).id, var);
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(var, AST_FLAG_PUBLIC))
+ if (scope->parent &&
+ scope_flags(scope, SCOPE_FILE) && ast_flags(var, AST_FLAG_PUBLIC))
return scope_add_var(scope->parent, var);
return 0;
}
-int scope_add_type(struct scope *scope, struct ast_node *id, struct ast_node *type)
+int scope_add_type(struct scope *scope, struct ast_node *id,
+ struct ast_node *type)
{
struct ast_node *exists = file_scope_find_type(scope, id);
if (exists) {
@@ -345,333 +167,74 @@ int scope_add_type(struct scope *scope, struct ast_node *id, struct ast_node *ty
}
create_type(scope, id, type);
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(type, AST_FLAG_PUBLIC))
+ if (scope->parent &&
+ scope_flags(scope, SCOPE_FILE) && ast_flags(type, AST_FLAG_PUBLIC))
return scope_add_type(scope->parent, id, type);
return 0;
}
-static void remove_implementation(struct ast_node *trait,
- struct ast_node *type)
-{
- assert(trait->node_type == AST_TRAIT);
- struct trait_implemented *prev = trait->_trait.impl_by, *cur;
- if (prev)
- do {
- cur = prev->next;
- if (!cur)
- break;
-
- if (identical_ast_nodes(0, cur->type, type)) {
- struct trait_implemented *next = cur->next;
- prev->next = next;
- free(cur);
- return;
- }
- } while ((prev = cur));
-}
-
-static int implements_proc(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type, struct ast_node *proc)
-{
- (void)(flags);
- (void)(scope);
- (void)(arg_type);
- (void)(param_type);
- assert(proc->node_type == AST_PROC);
- /** @todo implement */
- return 0;
-}
-
-static int implements_var(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type, struct ast_node *var)
-{
- (void)(flags);
- (void)(scope);
- (void)(arg_type);
- (void)(param_type);
- assert(var->node_type == AST_VAR);
- /** @todo implement */
- return 0;
-}
-
-static int implements_trait(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type)
-{
- assert(AST_TYPE(param_type).kind == AST_TYPE_TRAIT);
- struct ast_node *trait = AST_TRAIT_TYPE(param_type).def;
- struct ast_node *body = AST_TRAIT(trait).body;
-
- /* if the body is empty, match */
- struct ast_node *elem = body;
- if (!elem)
- return 1;
-
- /* this is somewhat ugly, hmmm */
- do {
- if (elem->node_type == AST_VAR) {
- if (implements_var(flags, scope, arg_type,
- param_type,
- elem))
- continue;
-
- char *type = type_str(arg_type);
- struct ast_node *id = elem->_proc.id;
- semantic_error(scope->fctx, elem,
- "%s does not have member %s",
- type, id->_id.id);
- free(type);
- goto not_implemented;
- }
-
- else if (elem->node_type == AST_PROC) {
- if (implements_proc(flags, scope, arg_type,
- param_type,
- elem))
- continue;
-
- char *type = type_str(arg_type);
- struct ast_node *id = elem->_proc.id;
- semantic_error(scope->fctx, elem,
- "%s does not implement %s",
- type, id->_id.id);
- free(type);
- goto not_implemented;
- }
-
- else {
- semantic_error(scope->fctx, elem,
- "illegal trait element");
- goto not_implemented;
- }
- } while ((elem = elem->next));
-
- return 1;
-
-not_implemented:
- remove_implementation(trait, arg_type);
- return 0;
-}
-
-static int implements_typeof(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type)
-{
- internal_error("typeof implementation unimplemented");
- return implements(flags, scope, arg_type, param_type);
-}
-
-int implements(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type, struct ast_node *param_type)
-{
- /* if both types are null, they are uninitialized and we'll assume they
- * don't implement eachother. This essentially means that during the
- * analysis phase everything is added to the procs */
- if (!arg_type && !param_type)
- return 0;
-
- /* slight hack: macro arguments also don't have a type, so they will
- * also 'implement' type */
- if (!param_type)
- return 1;
-
- /* at this point, we should always have some type for the argument */
- assert(arg_type);
-
- if (AST_TYPE(param_type).kind == AST_TYPE_TYPEOF)
- return implements_typeof(flags, scope, arg_type, param_type);
-
- if (AST_TYPE(param_type).kind == AST_TYPE_TRAIT)
- return implements_trait(flags, scope, arg_type, param_type);
-
- return types_match(arg_type, param_type);
-}
-
-static int match_actual_params(enum match_flags flags, struct scope *scope,
- struct ast_node *args, struct ast_node *params)
-{
- /** @todo essentially just iterate over the parameters, right? */
- return 0;
-}
-
-static struct ast_node *match_resolve(struct scope *scope,
- struct resolve *s,
- struct ast_node *id,
- struct ast_node *args)
-{
- while (s) {
- /** @todo linear search, a hashmap would be faster */
- if (identical_ast_nodes(0, s->id, id))
- return resolve(scope, s->root, args);
-
- s = s->next;
- }
-
- return NULL;
-}
-
-static struct ast_node *match_macro(struct scope *scope,
- struct ast_node *id,
- struct ast_node *args)
-{
- return match_resolve(scope, scope->macro_resolve, id, args);
-}
-
-static struct ast_node *match_proc(struct scope *scope,
- struct ast_node *id,
- struct ast_node *args)
-{
- return match_resolve(scope, scope->proc_resolve, id, args);
-}
-
-static struct ast_node *match_type_construct(struct scope *scope,
- struct ast_node *id,
- struct ast_node *args)
-{
- return match_resolve(scope, scope->type_construct_resolve, id, args);
-}
-
-
-static int add_proc_resolve(struct scope *scope, struct ast_node *proc)
-{
- if (!scope->proc_resolve) {
- scope->proc_resolve = calloc(1, sizeof(struct resolve));
- }
-
- struct resolve *resolve = scope->proc_resolve;
- while (resolve) {
- if (identical_ast_nodes(0, resolve->id, proc->_proc.id))
- return add_resolve(scope, resolve, proc);
-
- resolve = resolve->next;
- }
-
- resolve = calloc(1, sizeof(struct resolve));
- resolve->root = calloc(1, sizeof(struct resolve_node));
- resolve->id = clone_ast_node(proc->_proc.id);
- resolve->next = scope->proc_resolve;
- scope->proc_resolve = resolve;
-
- return add_resolve(scope, resolve, proc);
-}
-
-static int add_macro_resolve(struct scope *scope, struct ast_node *macro)
-{
- if (!scope->macro_resolve) {
- scope->macro_resolve = calloc(1, sizeof(struct resolve));
- }
-
- struct resolve *resolve = scope->macro_resolve;
- while (resolve) {
- if (identical_ast_nodes(0, resolve->id, AST_MACRO_CONSTRUCT(macro).id))
- return add_resolve(scope, resolve, macro);
-
- resolve = resolve->next;
- }
-
- resolve = calloc(1, sizeof(struct resolve));
- resolve->root = calloc(1, sizeof(struct resolve_node));
- resolve->id = clone_ast_node(AST_MACRO_CONSTRUCT(macro).id);
- resolve->next = scope->macro_resolve;
- scope->macro_resolve = resolve;
-
- return add_resolve(scope, resolve, macro);
-}
-
int scope_add_macro(struct scope *scope, struct ast_node *macro)
{
assert(macro->node_type == AST_MACRO_CONSTRUCT);
- struct ast_node *id = AST_MACRO_CONSTRUCT(macro).id;
- struct ast_node *params = AST_MACRO_CONSTRUCT(macro).params;
-
- struct ast_node *exists = match_macro(scope, id, params);;
+ struct ast_node *exists = file_scope_find_macro(scope, AST_MACRO_CONSTRUCT(
+ macro).id);
if (exists) {
semantic_error(scope->fctx, macro, "macro redefined");
semantic_info(scope->fctx, exists, "previously here");
return -1;
}
- add_macro_resolve(scope, macro);
-
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(macro, AST_FLAG_PUBLIC))
+ /* always add to scope, do resolve checking later */
+ create_macro(scope, AST_MACRO_CONSTRUCT(macro).id, macro);
+ if (scope->parent &&
+ scope_flags(scope, SCOPE_FILE) && ast_flags(macro, AST_FLAG_PUBLIC))
return scope_add_macro(scope->parent, macro);
return 0;
}
-int add_type_construct_resolve(struct scope *scope, struct ast_node *type_construct)
-{
- if (!scope->type_construct_resolve) {
- scope->type_construct_resolve = calloc(1, sizeof(struct resolve));
- }
-
- struct resolve *resolve = scope->type_construct_resolve;
- while (resolve) {
- if (identical_ast_nodes(0, resolve->id, AST_TYPE_CONSTRUCT(type_construct).id))
- return add_resolve(scope, resolve, type_construct);
-
- resolve = resolve->next;
- }
-
- resolve = calloc(1, sizeof(struct resolve));
- resolve->root = calloc(1, sizeof(struct resolve_node));
- resolve->id = clone_ast_node(AST_TYPE_CONSTRUCT(type_construct).id);
- resolve->next = scope->type_construct_resolve;
- scope->type_construct_resolve = resolve;
-
- return add_resolve(scope, resolve, type_construct);
-}
-
int scope_add_proc(struct scope *scope, struct ast_node *proc)
{
assert(proc->node_type == AST_PROC);
-
- struct ast_node *id = AST_PROC(proc).id;
- struct ast_node *sign = AST_PROC(proc).sign;
- struct ast_node *params = AST_SIGN_TYPE(sign).params;
-
- struct ast_node *exists = match_proc(scope, id, params);
-
+ struct ast_node *exists =
+ file_scope_find_proc(scope, AST_PROC(proc).id);
if (exists) {
semantic_error(scope->fctx, proc, "proc redefined");
semantic_info(scope->fctx, exists, "previously here");
return -1;
}
-
- add_proc_resolve(scope, proc);
-
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(proc, AST_FLAG_PUBLIC))
+ /* always add to scope, do resolve checking later */
+ create_proc(scope, AST_PROC(proc).id, proc);
+ if (scope->parent &&
+ scope_flags(scope, SCOPE_FILE) && ast_flags(proc, AST_FLAG_PUBLIC))
return scope_add_proc(scope->parent, proc);
return 0;
}
-int scope_add_type_construct(struct scope *scope, struct ast_node *type_construct)
+int scope_add_trait(struct scope *scope, struct ast_node *trait)
{
- assert(type_construct->node_type == AST_TYPE_CONSTRUCT);
-
- struct ast_node *id = AST_TYPE_CONSTRUCT(type_construct).id;
- struct ast_node *params = AST_TYPE_CONSTRUCT(type_construct).params;
+ assert(trait->node_type == AST_TRAIT);
- struct ast_node *exists = match_type_construct(scope, id, params);
+ struct ast_node *id = AST_TRAIT(trait).id;
+ struct ast_node *exists = file_scope_find_type(scope, id);
if (exists) {
- semantic_error(scope->fctx, type_construct, "type construct redefined");
+ semantic_error(scope->fctx, trait, "type redefined");
semantic_info(scope->fctx, exists, "previously here");
return -1;
}
- add_type_construct_resolve(scope, type_construct);
-
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(type_construct, AST_FLAG_PUBLIC))
- return scope_add_type_construct(scope->parent, type_construct);
+ create_type(scope, id, trait);
+ if (scope->parent &&
+ scope_flags(scope, SCOPE_FILE) && ast_flags(trait, AST_FLAG_PUBLIC))
+ return scope_add_trait(scope->parent, trait);
return 0;
}
-static struct ast_node *scope_find_visible(struct visible *v, struct ast_node *id)
+static struct ast_node *scope_find_visible(struct visible *v,
+ struct ast_node *id)
{
if (!v)
return NULL;
@@ -708,134 +271,71 @@ struct ast_node *file_scope_find_type(struct scope *scope,
return NULL;
}
-struct ast_node *scope_find_var(struct scope *scope, struct ast_node *var)
+struct ast_node *scope_find_macro(struct scope *scope, struct ast_node *macro)
{
- return scope_find_visible(scope->vars, var);
+ return scope_find_visible(scope->macros, macro);
}
-struct ast_node *file_scope_find_var(struct scope *scope, struct ast_node *var)
+struct ast_node *file_scope_find_macro(struct scope *scope,
+ struct ast_node *macro)
{
- assert(var->node_type == AST_ID);
+ assert(macro->node_type == AST_ID);
if (!scope)
return NULL;
- struct ast_node *found = scope_find_var(scope, var);
+ struct ast_node *found = scope_find_macro(scope, macro);
if (found)
return found;
if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_find_var(scope->parent, var);
+ return file_scope_find_macro(scope->parent, macro);
return NULL;
}
-struct ast_node *scope_resolve_macro(struct scope *scope, struct ast_node *macro)
-{
- assert(macro->node_type == AST_MACRO_EXPAND);
- struct ast_node *id = macro->_macro_expand.id;
- struct ast_node *args = macro->_macro_expand.args;
- return match_macro(scope, id, args);
-}
-
-struct ast_node *scope_resolve_proc(struct scope *scope, struct ast_node *call)
+struct ast_node *scope_find_proc(struct scope *scope, struct ast_node *proc)
{
- assert(call->node_type == AST_CALL);
- struct ast_node *id = call->_call.id;
- struct ast_node *args = call->_call.args;
- return match_proc(scope, id, args);
+ return scope_find_visible(scope->procs, proc);
}
-struct ast_node *scope_resolve_actual(struct scope *scope,
- struct ast_node *call)
+struct ast_node *file_scope_find_proc(struct scope *scope,
+ struct ast_node *proc)
{
- assert(call->node_type == AST_CALL);
- struct actual *prev = scope->actuals, *cur;
-
- if (prev)
- do {
- cur = prev->next;
- struct ast_node *actual = prev->node;
- if (!actual)
- continue;
-
- if (!identical_ast_nodes(0, actual->_proc.id,
- call->_call.id))
- continue;
-
- assert(!ast_flags(actual, AST_FLAG_VARIADIC));
- /* could also check that arguments aren't traits */
- struct ast_node *args = AST_CALL(call).args;
- struct ast_node *sign = AST_PROC(actual).sign;
- struct ast_node *params = AST_SIGN_TYPE(sign).params;
- if (match_actual_params(0, scope, args, params))
- return actual;
-
- } while ((prev = cur));
-
- return NULL;
-}
+ assert(proc->node_type == AST_ID);
+ if (!scope)
+ return NULL;
-struct ast_node *scope_resolve_call(struct scope *scope, struct ast_node *call)
-{
- assert(call->node_type == AST_CALL);
- /* unsure if actual should be here or somewhere else but eh */
- struct ast_node *found = scope_resolve_actual(scope, call);
+ struct ast_node *found = scope_find_proc(scope, proc);
if (found)
return found;
- found = scope_resolve_proc(scope, call);
- if (found)
- return found;
+ if (!scope_flags(scope, SCOPE_FILE))
+ return file_scope_find_proc(scope->parent, proc);
return NULL;
}
-struct ast_node *file_scope_resolve_call(struct scope *scope,
- struct ast_node *call)
+struct ast_node *scope_find_var(struct scope *scope, struct ast_node *var)
{
- struct ast_node *found = scope_resolve_call(scope, call);
- if (found)
- return found;
-
- if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_resolve_call(scope->parent, call);
-
- return NULL;
+ return scope_find_visible(scope->vars, var);
}
-struct ast_node *file_scope_resolve_macro(struct scope *scope, struct ast_node *macro)
+struct ast_node *file_scope_find_var(struct scope *scope, struct ast_node *var)
{
- struct ast_node *found = scope_resolve_macro(scope, macro);
+ assert(var->node_type == AST_ID);
+ if (!scope)
+ return NULL;
+
+ struct ast_node *found = scope_find_var(scope, var);
if (found)
return found;
if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_resolve_macro(scope->parent, macro);
+ return file_scope_find_var(scope->parent, var);
return NULL;
}
-/* this might be useful somewhere else as well */
-static enum ast_primitive default_types[] = {AST_VOID, AST_I9, AST_I27};
-static const char *default_names[] = {"void", "i9", "i27"};
-
-/* TODO: add error checking */
-int scope_add_defaults(struct scope *root)
-{
- for (size_t i = 0;
- i < sizeof(default_types) / sizeof(default_types[0]);
- ++i) {
- struct ast_node *n = gen_id(strdup(default_names[i]), NULL_LOC());
- struct ast_node *a = gen_primitive(default_types[i], NULL_LOC());
- if (!a)
- return -1;
-
- scope_add_type(root, n, a);
- }
-
- return 0;
-}
-
void scope_add_scope(struct scope *parent, struct scope *child)
{
assert(parent);
@@ -874,38 +374,3 @@ int scope_add_actual(struct scope *scope, struct ast_node *node)
{
return add_actual(scope->actuals, node);
}
-
-static struct ast_node *find_actual(struct actual *actuals,
- struct ast_node *node)
-{
- assert(node->node_type == AST_ID);
-
- if (!actuals)
- return NULL;
-
- do {
- struct ast_node *actual = actuals->node;
- if (identical_ast_nodes(0, actual->_proc.id, node))
- return actual;
-
- } while ((actuals = actuals->next));
-
- return NULL;
-}
-
-struct ast_node *scope_find_actual(struct scope *scope, struct ast_node *node)
-{
- return find_actual(scope->actuals, node);
-}
-
-struct scope *create_temp_scope(struct scope *parent)
-{
- struct scope *scope = create_scope();
- if (!scope) {
- internal_error("failed allocating temp scope");
- }
-
- scope->parent = parent;
- scope->fctx = parent->fctx;
- return scope;
-}