diff --git a/ast.c b/ast.c index 5ac5a32..f726bc4 100644 --- a/ast.c +++ b/ast.c @@ -156,7 +156,7 @@ CORD ast_to_xml(ast_t *ast) T(Optional, "%r", ast_to_xml(data.value)) T(NonOptional, "%r", ast_to_xml(data.value)) T(DocTest, "%r%r", optional_tagged("expression", data.expr), xml_escape(data.output)) - T(Use, "%r", xml_escape(data.path)) + T(Use, "%r%r", optional_tagged("var", data.var), xml_escape(data.path)) T(InlineCCode, "%r", xml_escape(data.code)) default: return "???"; #undef T diff --git a/ast.h b/ast.h index 2301100..fbbdb70 100644 --- a/ast.h +++ b/ast.h @@ -311,6 +311,7 @@ struct ast_s { bool skip_source:1; } DocTest; struct { + ast_t *var; const char *path; enum { USE_LOCAL, USE_MODULE, USE_SHARED_OBJECT, USE_HEADER, USE_C_CODE, USE_ASM } what; } Use; diff --git a/compile.c b/compile.c index 9e675f0..d7dcd3a 100644 --- a/compile.c +++ b/compile.c @@ -569,9 +569,7 @@ CORD compile_statement(env_t *env, ast_t *ast) } case Declare: { auto decl = Match(ast, Declare); - if (decl->value->tag == Use) { - return compile_statement(env, decl->value); - } else if (streq(Match(decl->var, Var)->name, "_")) { // Explicit discard + if (streq(Match(decl->var, Var)->name, "_")) { // Explicit discard return CORD_all("(void)", compile(env, decl->value), ";"); } else { type_t *t = get_type(env, decl->value); @@ -3584,7 +3582,7 @@ CORD compile_file(env_t *env, ast_t *ast) type_t *t = get_type(env, decl->value); if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType) code_err(stmt->ast, "You can't declare a variable with a %T value", t); - if (!(decl->value->tag == Use || is_constant(env, decl->value))) { + if (!is_constant(env, decl->value)) { CORD val_code = compile_maybe_incref(env, decl->value); if (t->tag == FunctionType) { assert(promote(env, &val_code, t, Type(ClosureType, t))); @@ -3609,9 +3607,7 @@ CORD compile_file(env_t *env, ast_t *ast) CORD full_name = CORD_all(namespace_prefix(env, env->namespace), decl_name); bool is_private = (decl_name[0] == '_'); type_t *t = get_type(env, decl->value); - if (decl->value->tag == Use) { - assert(compile_statement(env, stmt->ast) == CORD_EMPTY); - } else if (!is_constant(env, decl->value)) { + if (!is_constant(env, decl->value)) { env->code->staticdefs = CORD_all( env->code->staticdefs, "static bool ", full_name, "$initialized = false;\n", @@ -3665,9 +3661,6 @@ CORD compile_statement_header(env_t *env, ast_t *ast) switch (ast->tag) { case Declare: { auto decl = Match(ast, Declare); - if (decl->value->tag == Use) - return compile_statement_header(env, decl->value); - const char *decl_name = Match(decl->var, Var)->name; bool is_private = (decl_name[0] == '_'); if (is_private) diff --git a/parse.c b/parse.c index 3734cf5..09a7eb2 100644 --- a/parse.c +++ b/parse.c @@ -133,7 +133,6 @@ static PARSER(parse_table); static PARSER(parse_term); static PARSER(parse_term_no_suffix); static PARSER(parse_text); -static PARSER(parse_top_declaration); static PARSER(parse_update); static PARSER(parse_use); static PARSER(parse_var); @@ -1750,20 +1749,6 @@ PARSER(parse_declaration) { return NewAST(ctx->file, start, pos, Declare, .var=var, .value=val); } -PARSER(parse_top_declaration) { - const char *start = pos; - ast_t *var = parse_var(ctx, pos); - if (!var) return NULL; - pos = var->end; - spaces(&pos); - if (!match(&pos, ":=")) return NULL; - spaces(&pos); - ast_t *val = optional(ctx, &pos, parse_use); - if (!val) val = optional(ctx, &pos, parse_extended_expr); - if (!val) parser_err(ctx, pos, strchrnul(pos, '\n'), "This declaration value didn't parse"); - return NewAST(ctx->file, start, pos, Declare, .var=var, .value=val); -} - PARSER(parse_update) { const char *start = pos; ast_t *lhs = optional(ctx, &pos, parse_expr); @@ -1980,7 +1965,7 @@ PARSER(parse_file_body) { ||(stmt=optional(ctx, &pos, parse_use)) ||(stmt=optional(ctx, &pos, parse_extern)) ||(stmt=optional(ctx, &pos, parse_inline_c)) - ||(stmt=optional(ctx, &pos, parse_top_declaration))) + ||(stmt=optional(ctx, &pos, parse_declaration))) { statements = new(ast_list_t, .ast=stmt, .next=statements); pos = stmt->end; @@ -2348,6 +2333,15 @@ PARSER(parse_say) { PARSER(parse_use) { const char *start = pos; + + ast_t *var = parse_var(ctx, pos); + if (var) { + pos = var->end; + spaces(&pos); + if (!match(&pos, ":=")) return NULL; + spaces(&pos); + } + if (!match_word(&pos, "use")) return NULL; spaces(&pos); size_t name_len = strcspn(pos, " \t\r\n;"); @@ -2384,7 +2378,7 @@ PARSER(parse_use) { name = hash; } } - return NewAST(ctx->file, start, pos, Use, .path=name, .what=what); + return NewAST(ctx->file, start, pos, Use, .var=var, .path=name, .what=what); } ast_t *parse_file(const char *path, jmp_buf *on_err) { diff --git a/typecheck.c b/typecheck.c index f993604..fd0b9d6 100644 --- a/typecheck.c +++ b/typecheck.c @@ -255,11 +255,7 @@ void bind_statement(env_t *env, ast_t *statement) return; if (get_binding(env, name)) code_err(decl->var, "A %T called '%s' has already been defined", get_binding(env, name)->type, name); - if (decl->value->tag == Use) { - (void)load_module(env, decl->value); - } else { - bind_statement(env, decl->value); - } + bind_statement(env, decl->value); type_t *type = get_type(env, decl->value); if (!type) code_err(decl->value, "I couldn't figure out the type of this value"); @@ -394,9 +390,15 @@ void bind_statement(env_t *env, ast_t *statement) if (Table$str_get(*env->types, entry->name)) continue; -//code_err(statement, "This module imports a type called '%s', which would clobber another type", entry->name); Table$str_set(env->types, entry->name, entry->type); } + + ast_t *var = Match(statement, Use)->var; + if (var) { + type_t *type = get_type(env, statement); + assert(type); + set_binding(env, Match(var, Var)->name, new(binding_t, .type=type)); + } break; } case Extern: {