diff options
Diffstat (limited to 'src/analyze.c')
| -rw-r--r-- | src/analyze.c | 778 |
1 files changed, 691 insertions, 87 deletions
diff --git a/src/analyze.c b/src/analyze.c index 0c06096..04b7856 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1,12 +1,23 @@ /* SPDX-License-Identifier: copyleft-next-0.3.1 */ /* Copyright 2024 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ +#include <fwd/compiler.h> #include <fwd/analyze.h> +#include <fwd/rewrite.h> +#include <fwd/mod.h> + #include <stdlib.h> +#include <stdarg.h> #include <string.h> #include <assert.h> +#include <dlfcn.h> + +enum state_flags { + STATE_PROC_REQ_FRAME = (1 << 0) +}; struct state { + enum state_flags flags; }; static int analyze(struct state *state, struct scope *scope, struct ast *node); @@ -62,7 +73,13 @@ static int analyze_proc(struct state *state, struct scope *scope, if (!proc_body(node)) return 0; - return analyze_known_block(&proc_state, proc_scope, proc_body(node)); + if (analyze_known_block(&proc_state, proc_scope, proc_body(node))) + return -1; + + if (proc_state.flags & STATE_PROC_REQ_FRAME) + ast_set_flags(node, AST_REQ_FRAME); + + return 0; } static int analyze_unop(struct state *state, struct scope *scope, @@ -89,6 +106,19 @@ static int analyze_binop(struct state *state, struct scope *scope, if (analyze(state, scope, rhs)) return -1; + /* allow pointer arithmetic, follows C conventions */ + if (node->k == AST_ADD || node->k == AST_SUB) { + if (is_ptr_type(lhs->t->k) && is_int_type(rhs->t->k)) { + node->t = lhs->t; + return 0; + } + + if (is_ptr_type(rhs->t->k) && is_int_type(lhs->t->k)) { + node->t = rhs->t; + return 0; + } + } + if (!types_match(lhs->t, rhs->t)) { type_mismatch(scope, node, lhs->t, rhs->t); @@ -118,17 +148,9 @@ static int analyze_comparison(struct state *state, struct scope *scope, return -1; } - /** @todo check type is some primitive */ - char *tf = strdup("bool"); - if (!tf) { - internal_error("failed allocating comparison bool str"); - return -1; - } - - node->t = tgen_id(tf, node->loc); + node->t = tgen_type(TYPE_BOOL, NULL, NULL, node->loc); if (!node->t) { internal_error("failed allocating comparison bool type"); - free(tf); return -1; } @@ -144,28 +166,6 @@ static int analyze_known_block(struct state *state, struct scope *scope, struct if (analyze_list(state, scope, block_body(node))) return -1; - struct ast *err = block_error(node); - if (!err) - return 0; - - if (error_str(err)) - return 0; - - struct ast *id = error_id(err); - assert(id); - - struct ast *def = file_scope_find_symbol(scope, id_str(id)); - if (!def) { - semantic_error(scope, id, "no such symbol"); - return -1; - } - - struct type *t = def->t; - if (t->k != TYPE_ERR) { - semantic_error(scope, id, "invalid error variable type"); - return -1; - } - return 0; } @@ -195,10 +195,14 @@ static int analyze_var(struct state *state, struct scope *scope, static int analyze_let(struct state *state, struct scope *scope, struct ast *node) { - if (analyze(state, scope, let_var(node))) + if (analyze(state, scope, let_expr(node))) return -1; - if (analyze(state, scope, let_expr(node))) + struct ast *var = let_var(node); + if (!(var_type(var))) + var_type(var) = (let_expr(node))->t; + + if (analyze(state, scope, var)) return -1; struct type *l = (let_var(node))->t; @@ -221,16 +225,40 @@ static int analyze_init(struct state *state, struct scope *scope, if (analyze(state, scope, init_body(node))) return -1; - /** @todo check that all parameters match, though that requires that the - * type is defined in fwd and not in C++, so this might have to wait a - * bit */ - node->t = tgen_construct(strdup(init_id(node)), init_args(node), - node->loc); - if (!node->t) { - internal_error("failed allocating type for construct"); + internal_error("init unimplemented"); + return -1; +} + +static int deduce_closure_types(struct scope *scope, struct ast *node, struct type *type) +{ + /* a bit of checking duplication here, hmm */ + if (node->k != AST_CLOSURE) + return 0; + + if (type->k != TYPE_CLOSURE && type->k != TYPE_PURE_CLOSURE) { + semantic_error(scope, node, "surprise closure"); + return -1; + } + + struct ast *param = closure_bindings(node); + struct type *t = (type->k == TYPE_CLOSURE) + ? tclosure_args(type) + : tpure_closure_args(type) + ; + + if (ast_list_len(param) != type_list_len(t)) { + semantic_error(scope, node, "expected %zu closure parameters, got %zu", + type_list_len(t), ast_list_len(param)); return -1; } + for (; param && t; param = param->n, t = t->n) { + if (var_type(param)) + continue; + + var_type(param) = t; + } + return 0; } @@ -248,8 +276,6 @@ static int analyze_call(struct state *state, struct scope *scope, struct type *types = callable_types(expr->t); struct ast *args = call_args(node); - if (analyze_list(state, scope, args)) - return -1; size_t expected = type_list_len(types); size_t got = ast_list_len(args); @@ -260,15 +286,24 @@ static int analyze_call(struct state *state, struct scope *scope, } struct type *type = types; - foreach_node(arg, args) { + struct ast *arg = args; + for (; arg && type; type = type->n, arg = arg->n) { + if (deduce_closure_types(scope, arg, type)) + return -1; + + if (analyze(state, scope, arg)) + return -1; + + if (arg->k == AST_CLOSURE) + state->flags |= STATE_PROC_REQ_FRAME; + if (!types_match(type, arg->t)) { - type_mismatch(scope, node, type, arg->t); + type_mismatch(scope, arg, type, arg->t); return -1; } /* clone group info */ arg->t->group = type->group; - type = type->n; } node->t = tgen_void(node->loc); @@ -277,7 +312,7 @@ static int analyze_call(struct state *state, struct scope *scope, return -1; } - return analyze(state, scope, call_err(node)); + return 0; } static int analyze_ref(struct state *state, struct scope *scope, @@ -313,7 +348,7 @@ static int analyze_deref(struct state *state, struct scope *scope, semantic_error(node->scope, node, "deref of raw ptr not allowed"); semantic_info(node->scope, node, - "use fwd_null() to convert to ref"); + "use a nil check to convert to ref"); return -1; } @@ -323,7 +358,7 @@ static int analyze_deref(struct state *state, struct scope *scope, return -1; } - node->t = tptr_base(expr->t); + node->t = tref_base(expr->t); return 0; } @@ -362,7 +397,6 @@ static int analyze_closure(struct state *state, struct scope *scope, } node->scope = closure_scope; - closure_scope->flags |= SCOPE_PROC; scope_add_scope(scope, closure_scope); if (analyze_list(state, closure_scope, closure_bindings(node))) @@ -396,17 +430,10 @@ static int analyze_int(struct state *state, struct scope *scope, (void)state; (void)scope; - /** @todo do this properly, very hacky, bad bad bad */ - char *i = strdup("int"); - if (!i) { - internal_error("failed allocating constant int type string"); - return -1; - } - - node->t = tgen_id(i, node->loc); + /* start with largest possible and work down */ + node->t = tgen_type(TYPE_I64, NULL, NULL, node->loc); if (!node->t) { internal_error("failed allocating constant int type"); - free(i); return -1; } @@ -443,6 +470,189 @@ static int analyze_str(struct state *state, struct scope *scope, return 0; } +static int analyze_template(struct state *state, struct scope *scope, struct ast *node) +{ + struct scope *template_scope = create_scope(); + scope_add_scope(scope, template_scope); + + /* enough for vec example since traits are as of yet unimplemented */ + + node->t = tgen_void(node->loc); + return 0; +} + +static int analyze_instance(struct state *state, struct scope *scope, struct ast *node) +{ + (void)state; + + struct ast *id = instance_templ(node); + struct ast *template = file_scope_find_template(scope, id_str(id)); + if (!template) { + semantic_error(scope, node, "no such template: %s\n", id_str(id)); + return -1; + } + + /** @todo check that type implements trait */ + struct ast *params = template_type_params(template); + struct type *args = instance_type_args(node); + if (ast_list_len(params) != type_list_len(args)) { + semantic_error(scope, node, "expected %zu types, got %zu\n", + ast_list_len(params), type_list_len(args)); + return -1; + } + + /* make a working copy that we modify */ + struct ast *copy = clone_ast(template); + if (!copy) { + internal_error("failed copying template body"); + return -1; + } + + if (rewrite_holes(copy, instance_id(node))) + return -1; + + /* replace type args */ + struct ast *p = params; + struct type *a = args; + for (; p && a; p = p->n, a = a->n) { + if (rewrite_types(copy, var_id(p), tid_str(a))) + return -1; + } + + printf("// --- instance %s ---\n", instance_id(node)); + ast_dump(0, copy); + + /* analyze newly initialized things (might not work for supertemplates?) */ + if (analyze_root(scope, template_body(copy))) + return -1; + + node->t = tgen_void(node->loc); + return 0; +} + +static int analyze_struct(struct state *state, struct scope *scope, struct ast *node) +{ + struct scope *struct_scope = create_scope(); + scope_add_scope(scope, struct_scope); + node->scope = struct_scope; + + if (analyze_list(state, struct_scope, struct_body(node))) + return -1; + + node->t = tgen_void(node->loc); + return 0; +} + +static int analyze_construct(struct state *state, struct scope *scope, struct ast *node) +{ + struct ast *def = file_scope_find_type(scope, construct_id(node)); + if (!def) { + semantic_error(scope, node, "no such type: %s", construct_id(node)); + return -1; + } + + if (def->k != AST_STRUCT_DEF) { + semantic_error(scope, node, "type is not a struct"); + return -1; + } + + struct ast *params = struct_body(def); + struct ast *args = construct_members(node); + + if (ast_list_len(params) != ast_list_len(args)) { + semantic_error(scope, node, "expected %zu args, got %zu\n", + ast_list_len(params), ast_list_len(args)); + return -1; + } + + foreach_node(arg, args) { + struct ast *exists = scope_find_symbol(def->scope, construction_id(arg)); + if (!exists) { + semantic_error(scope, arg, "no member %s in %s\n", + construction_id(arg), construct_id(node)); + return -1; + } + + struct ast *expr = construction_expr(arg); + if (analyze(state, scope, expr)) + return -1; + + if (!types_match(exists->t, expr->t)) { + type_mismatch(scope, arg, exists->t, expr->t); + return -1; + } + + /** @todo check for duplicates, preferably not in O(n^2) or with + * a memory allocation? */ + } + + node->t = tgen_id(strdup(construct_id(node)), node->loc); + return 0; +} + +static int analyze_explode(struct state *state, struct scope *scope, struct ast *node) +{ + if (analyze(state, scope, explode_expr(node))) + return -1; + + struct type *type = (explode_expr(node))->t; + if (type->k != TYPE_ID) { + char *str = type_str(type); + semantic_error(scope, explode_expr(node), + "expected struct type, got %s\n", + str); + free(str); + return -1; + } + + struct ast *def = file_scope_find_type(scope, type->id); + if (!def || def->k != AST_STRUCT_DEF) { + semantic_error(scope, explode_expr(node), + "no such struct type: %s\n", + type->id); + return -1; + } + + struct ast *params = struct_body(def); + struct ast *args = explode_deconstruct(node); + + if (ast_list_len(params) != ast_list_len(args)) { + semantic_error(scope, node, "expected %zu args, got %zu\n", + ast_list_len(params), ast_list_len(args)); + return -1; + } + + foreach_node(arg, args) { + struct ast *var = deconstruction_var(arg); + struct ast *exists = scope_find_symbol(def->scope, deconstruction_id(arg)); + if (!exists) { + semantic_error(scope, arg, "no member %s in %s\n", + deconstruction_id(arg), type->id); + return -1; + } + + if (!var_type(var)) + (var_type(var)) = exists->t; + + if (analyze(state, scope, var)) + return -1; + + if (!types_match(exists->t, var->t)) { + type_mismatch(scope, arg, exists->t, var->t); + return -1; + } + + if (scope_add_symbol(scope, var)) + return -1; + + /** @todo check for duplicates, preferably not in O(n^2) or with + * a memory allocation? */ + } + + node->t = tgen_void(node->loc); + return 0; +} + static int analyze_if(struct state *state, struct scope *scope, struct ast *node) { @@ -464,38 +674,162 @@ static int analyze_if(struct state *state, struct scope *scope, return 0; } -static int analyze_err_branch(struct state *state, struct scope *scope, struct ast *node) +static int analyze_nil(struct state *state, struct scope *scope, struct ast *node) { - struct scope *branch_scope = create_scope(); - if (!branch_scope) { - internal_error("failed allocating err branch scope"); + (void)state; + (void)scope; + + node->t = tgen_nil(node->loc); + return 0; +} + +static bool castable_type(struct type *type) +{ + switch (type->k) { + case TYPE_PTR: + case TYPE_FUNC_PTR: + case TYPE_I8: + case TYPE_I16: + case TYPE_I32: + case TYPE_I64: + case TYPE_U8: + case TYPE_U16: + case TYPE_U32: + case TYPE_U64: + return true; + + default: + return false; + } + + return false; +} + +static int analyze_as(struct state *state, struct scope *scope, struct ast *node) +{ + if (analyze(state, scope, as_expr(node))) + return -1; + + if (analyze_type(state, scope, as_type(node))) + return -1; + + /* for now, any 'register' size type can be cast to any other. Might + * restrict this, like signed to unsigned might be weird if its negative + * etc and should be done via a helper function */ + struct type *expr_type = (as_expr(node))->t; + struct type *type = as_type(node); + if (!castable_type(expr_type)) { + char *s = type_str(expr_type); + semantic_error(scope, as_expr(node), "can't cast from %s\n", s); + free(s); return -1; } - node->t = tgen_void(node->loc); + if (!castable_type(type)) { + char *s = type_str(type); + type_error(scope, type, "can't cast to %s\n", s); + free(s); + return -1; + } - scope_add_scope(scope, branch_scope); - struct ast *var = gen_var(strdup(err_branch_id(node)), NULL, node->loc); - struct type *err_type = tgen_err(node->loc); - var->t = err_type; - scope_add_symbol(branch_scope, var); - return analyze(state, branch_scope, err_branch_body(node)); + node->t = type; + return 0; } -static int analyze_own(struct state *state, struct scope *scope, struct ast *node) +static int analyze_sizeof(struct state *state, struct scope *scope, struct ast *node) { - struct ast *found = file_scope_find_symbol(scope, own_id(node)); - if (!found) { - semantic_error(scope, node, "no symbol named \"%s\"", - own_id(node)); + if (analyze_type(state, scope, sizeof_type(node))) + return -1; + + /* hmm, no built-in size_t */ + node->t = tgen_type(TYPE_U64, NULL, NULL, node->loc); + return 0; +} + +static int analyze_nil_check(struct state *state, struct scope *scope, struct ast *node) +{ + struct ast *expr = nil_check_expr(node); + if (analyze(state, scope, expr)) + return -1; + + if (!is_ptr_type(expr->t->k)) { + char *s = type_str(expr->t); + semantic_error(scope, expr, "expected ptr type, got %s", s); + free(s); return -1; } - if (is_trivially_copyable(found->t)) - semantic_warn(scope, node, "trivially copyable type is never owned"); + if (analyze(state, scope, nil_check_body(node))) + return -1; + + struct ast *var = nil_check_ref(node); + struct type *base = tptr_base(expr->t); + struct type *ref = tgen_ref(clone_type(base), node->loc); + if (!var_type(var)) + var_type(var) = ref; + + if (analyze(state, scope, var)) + return -1; + + if (!types_match(ref, var->t)) { + type_mismatch(scope, var, ref, var->t); + return -1; + } + + if (analyze(state, scope, nil_check_rest(node))) + return -1; + + node->t = tgen_void(node->loc); + return 0; +} + +static int analyze_forget(struct state *state, struct scope *scope, struct ast *node) +{ + struct ast *def = file_scope_find_symbol(scope, forget_id(node)); + if (!def) { + semantic_error(scope, node, "no such symbol"); + return -1; + } node->t = tgen_void(node->loc); - return analyze(state, scope, own_body(node)); + return 0; +} + +static int analyze_put(struct state *state, struct scope *scope, struct ast *put) +{ + struct ast *dst = put_dst(put); + if (analyze(state, scope, dst)) + return -1; + + struct type *type = dst->t; + if (type->k != TYPE_REF) { + char *str = type_str(type); + semantic_error(scope, put, "trying to write to non-ref type %s\n", str); + free(str); + return -1; + } + + put->t = tref_base(type); + return 0; +} + +static int analyze_write(struct state *state, struct scope *scope, struct ast *write) +{ + struct ast *src = write_src(write); + if (analyze(state, scope, src)) + return -1; + + struct ast *dst = write_dst(write); + if (analyze(state, scope, dst)) + return -1; + + if (!types_match(src->t, dst->t)) { + type_mismatch(scope, write, src->t, dst->t); + return -1; + } + + write->t = tgen_void(write->loc); + return 0; } static int analyze(struct state *state, struct scope *scope, struct ast *node) @@ -535,7 +869,6 @@ static int analyze(struct state *state, struct scope *scope, struct ast *node) } switch (node->k) { - case AST_ERR_BRANCH: ret = analyze_err_branch(state, scope, node); break; case AST_CLOSURE: ret = analyze_closure(state, scope, node); break; case AST_PROC_DEF: ret = analyze_proc(state, scope, node); break; case AST_VAR_DEF: ret = analyze_var(state, scope, node); break; @@ -545,17 +878,45 @@ static int analyze(struct state *state, struct scope *scope, struct ast *node) case AST_CALL: ret = analyze_call(state, scope, node); break; case AST_REF: ret = analyze_ref(state, scope, node); break; case AST_LET: ret = analyze_let(state, scope, node); break; - case AST_OWN: ret = analyze_own(state, scope, node); break; case AST_ID: ret = analyze_id(state, scope, node); break; case AST_IF: ret = analyze_if(state, scope, node); break; + case AST_NIL_CHECK: ret = analyze_nil_check(state, scope, node); break; + case AST_CONST_INT: ret = analyze_int(state, scope, node); break; case AST_CONST_STR: ret = analyze_str(state, scope, node); break; + case AST_INSTANCE: ret = analyze_instance(state, scope, node); break; + case AST_TEMPLATE: ret = analyze_template(state, scope, node); break; + + case AST_STRUCT_DEF: ret = analyze_struct(state, scope, node); break; + case AST_CONSTRUCT: ret = analyze_construct(state, scope, node); break; + case AST_EXPLODE: ret = analyze_explode(state, scope, node); break; + + case AST_SIZEOF: ret = analyze_sizeof(state, scope, node); break; + case AST_NIL: ret = analyze_nil(state, scope, node); break; + case AST_AS: ret = analyze_as(state, scope, node); break; + + case AST_WRITE: ret = analyze_write(state, scope, node); break; + case AST_PUT: ret = analyze_put(state, scope, node); break; + + case AST_FORGET: ret = analyze_forget(state, scope, node); break; + + case AST_TRAIT_DEF: + node->t = tgen_void(node->loc); + ret = 0; + break; + case AST_EMPTY: node->t = tgen_void(node->loc); ret = 0; break; + + case AST_IMPORT: + node->t = tgen_void(node->loc); + ret = 0; + break; + default: internal_error("missing ast analysis for %s", ast_str(node->k)); return -1; @@ -585,11 +946,70 @@ static int analyze_list(struct state *state, struct scope *scope, static int analyze_type(struct state *state, struct scope *scope, struct type *type) { - /* for now, let's just say all types are fine as they are, specified by - * the user. */ - (void)state; - (void)scope; - (void)type; + if (type->t0 && analyze_type_list(state, scope, type->t0)) + return -1; + + /* temporary */ + if (!type->id) + return 0; + + char *id = type->id; + + /* handle primitives */ + if (strcmp(id, "i8") == 0) { + type->k = TYPE_I8; + return 0; + } + + if (strcmp(id, "u8") == 0) { + type->k = TYPE_U8; + return 0; + } + + if (strcmp(id, "i16") == 0) { + type->k = TYPE_I16; + return 0; + } + + if (strcmp(id, "u16") == 0) { + type->k = TYPE_U16; + return 0; + } + + if (strcmp(id, "i32") == 0) { + type->k = TYPE_I32; + return 0; + } + + if (strcmp(id, "u32") == 0) { + type->k = TYPE_U32; + return 0; + } + + if (strcmp(id, "i64") == 0) { + type->k = TYPE_I64; + return 0; + } + + if (strcmp(id, "u64") == 0) { + type->k = TYPE_U64; + return 0; + } + + if (strcmp(id, "bool") == 0) { + type->k = TYPE_BOOL; + return 0; + } + + /* check for user-defined types */ + struct ast *def = file_scope_find_type(scope, id); + if (!def) { + type_error(scope, type, "no such type: %s", id); + return -1; + } + + /* don't change type->k since we might want to check up on this again + * later */ return 0; } @@ -604,6 +1024,168 @@ static int analyze_type_list(struct state *state, struct scope *scope, return 0; } +static int copy_scope(bool reexport, struct scope *to, struct scope *from) +{ + foreach(visible, symbol, &from->symbols) { + struct ast *def = symbol->data; + if (!reexport && def->scope != from) + continue; + + if (!ast_flags(def, AST_FLAG_PUBLIC)) + continue; + + if (scope_add_symbol(to, def)) + return -1; + } + + foreach(visible, type, &from->types) { + struct ast *def = type->data; + if (!reexport && def->scope != from) + continue; + + if (!ast_flags(def, AST_FLAG_PUBLIC)) + continue; + + if (scope_add_type(to, def)) + return -1; + } + + foreach(visible, trait, &from->traits) { + struct ast *def = trait->data; + if (!reexport && def->scope != from) + continue; + + if (!ast_flags(def, AST_FLAG_PUBLIC)) + continue; + + if (scope_add_trait(to, def)) + return -1; + } + + foreach(visible, template, &from->templates) { + struct ast *def = template->data; + if (!reexport && def->scope != from) + continue; + + if (!ast_flags(def, AST_FLAG_PUBLIC)) + continue; + + if (scope_add_template(to, def)) + return -1; + } + + return 0; +} + +/* allowed to be noisy */ +static int try_import_file(struct scope *scope, struct ast *node) +{ + const char *file = import_file(node); + struct scope *child = compile_file(file); + if (!child) { + semantic_info(scope, node, "imported here"); + return -1; + } + + if (copy_scope(ast_flags(node, AST_FLAG_PUBLIC), scope, child)) { + semantic_info(scope, node, "imported here"); + return -1; + } + + return 0; +} + +/* should be quiet upon failure */ +static int try_import_mod(struct scope *scope, struct ast *node) +{ + /** @todo cleanup */ + void *mod = dlopen(import_file(node), RTLD_LAZY); + if (!mod) + return -1; + + fwd_open_t fwdopen = dlsym(mod, "fwdopen"); + if (!fwdopen) { + dlclose(mod); + return -1; + } + + mod_vec_append(&scope->mods, mod); + return fwdopen((void *)scope); +} + +static struct type *fwd_type_kind(fwd_type_t type) +{ + switch (type) { + case FWD_VOID: return tgen_void(NULL_LOC()); + case FWD_I64: return tgen_type(TYPE_I64, NULL, NULL, NULL_LOC()); + case FWD_U64: return tgen_type(TYPE_U64, NULL, NULL, NULL_LOC()); + case FWD_PTR: { + /* hack? */ + return tgen_nil(NULL_LOC()); + } + + default: + break; + } + + abort(); + return NULL; +} + +int fwd_register(struct fwd_state *state, const char *name, fwd_extern_t func, fwd_type_t rtype, ...) +{ + struct scope *scope = (void *)state; + struct ast *vars = NULL; + + va_list args; + va_start(args, rtype); + + size_t idx = 0; + while (1) { + fwd_type_t type = va_arg(args, enum fwd_type); + if (type == FWD_END) + break; + + /* eight bytes is likely more than enough, since first three are + * var, then we have four bytes for indexes and one trailing + * NULL */ + char *name = calloc(8, sizeof(char)); + assert(name); + + sprintf(name, "%s%zu", "var", idx); + struct ast *new = gen_var(name, fwd_type_kind(type), NULL_LOC()); + + if (vars) + new->n = vars; + + vars = new; + idx++; + } + va_end(args); + + /* append 'return' as a continuation */ + if (rtype != FWD_VOID) { + char *name = strdup("ret"); + struct ast *new = gen_var(name, + tgen_closure(fwd_type_kind(rtype), NULL_LOC()), + NULL_LOC()); + if (vars) + new->n = vars; + + vars = new; + } + + vars = reverse_ast_list(vars); + + struct ast *def = gen_proc(strdup(name), vars, + fwd_type_kind(rtype), NULL, NULL_LOC()); + + if (scope_add_symbol(scope, def)) + return -1; + + return 0; +} + int analyze_root(struct scope *scope, struct ast *root) { foreach_node(node, root) { @@ -619,8 +1201,7 @@ int analyze_root(struct scope *scope, struct ast *root) break; case AST_STRUCT_CONT: - if (scope_add_chain(scope, node)) - return -1; + abort(); break; case AST_TRAIT_DEF: @@ -628,6 +1209,29 @@ int analyze_root(struct scope *scope, struct ast *root) return -1; break; + case AST_IMPORT: { + if (!try_import_mod(scope, node)) + break; + + if (!try_import_file(scope, node)) + break; + + return -1; + } + + case AST_TEMPLATE: + if (scope_add_template(scope, node)) + return -1; + break; + + case AST_SUPERTEMPLATE: + if (scope_add_template(scope, node)) + return -1; + break; + + case AST_INSTANCE: + break; + default: abort(); } |
