diff --git a/ast.c b/ast.c index b380a04..901144f 100644 --- a/ast.c +++ b/ast.c @@ -152,7 +152,7 @@ CORD ast_to_xml(ast_t *ast) T(FieldAccess, "%r", data.field, ast_to_xml(data.fielded)) T(Optional, "%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.name)) + T(Use, "%r", xml_escape(data.path)) T(LinkerDirective, "%r", xml_escape(data.directive)) T(InlineCCode, "%r", xml_escape(data.code)) #undef T diff --git a/ast.h b/ast.h index 1d295e5..53adb6a 100644 --- a/ast.h +++ b/ast.h @@ -291,7 +291,7 @@ struct ast_s { bool skip_source:1; } DocTest; struct { - const char *name; + const char *path; enum { USE_LOCAL, USE_MODULE, USE_SHARED_OBJECT, USE_HEADER } what; } Use; struct { diff --git a/compile.c b/compile.c index a15e058..804acb6 100644 --- a/compile.c +++ b/compile.c @@ -1169,10 +1169,10 @@ CORD compile_statement(env_t *env, ast_t *ast) case Use: { auto use = Match(ast, Use); if (use->what == USE_LOCAL) { - CORD name = file_base_name(Match(ast, Use)->name); + CORD name = file_base_name(Match(ast, Use)->path); env->code->variable_initializers = CORD_all(env->code->variable_initializers, name, "$$initialize();\n"); } else if (use->what == USE_MODULE) { - const char *libname = file_base_name(use->name); + const char *libname = file_base_name(use->path); const char *files_filename = heap_strf("%s/lib%s.files", libname, libname); const char *resolved_path = resolve_path(files_filename, ast->file->filename, getenv("TOMO_IMPORT_PATH")); if (!resolved_path) @@ -1183,7 +1183,7 @@ CORD compile_statement(env_t *env, ast_t *ast) const char *line = get_line(files_f, i); line = GC_strndup(line, strcspn(line, "\r\n")); env->code->variable_initializers = CORD_all( - env->code->variable_initializers, use->name, "$", file_base_name(line), "$$initialize();\n"); + env->code->variable_initializers, use->path, "$", file_base_name(line), "$$initialize();\n"); } } return CORD_EMPTY; @@ -3262,11 +3262,11 @@ CORD compile_statement_imports(env_t *env, ast_t *ast) auto use = Match(ast, Use); switch (use->what) { case USE_MODULE: - return CORD_all("#include name, ".h>\n"); + return CORD_all("#include path, ".h>\n"); case USE_LOCAL: - return CORD_all("#include \"", use->name, ".h\"\n"); + return CORD_all("#include \"", use->path, ".h\"\n"); case USE_HEADER: - return CORD_all("#include ", use->name, "\n"); + return CORD_all("#include ", use->path, "\n"); default: return CORD_EMPTY; } diff --git a/parse.c b/parse.c index 36ce3dd..f1273be 100644 --- a/parse.c +++ b/parse.c @@ -110,6 +110,7 @@ static PARSER(parse_func_def); static PARSER(parse_extern); static PARSER(parse_inline_c); static PARSER(parse_declaration); +static PARSER(parse_top_declaration); static PARSER(parse_doctest); static PARSER(parse_say); static PARSER(parse_use); @@ -1558,6 +1559,24 @@ ast_t *parse_expr(parse_ctx_t *ctx, const char *pos) { } PARSER(parse_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_extended_expr); + if (!val) { + if (optional(ctx, &pos, parse_use)) + parser_err(ctx, start, pos, "'use' statements are only allowed at the top level of a file"); + else + parser_err(ctx, pos, strchrnul(pos, '\n'), "This is not a valid expression"); + } + 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; @@ -1789,7 +1808,7 @@ PARSER(parse_file_body) { ||(stmt=optional(ctx, &pos, parse_linker)) ||(stmt=optional(ctx, &pos, parse_extern)) ||(stmt=optional(ctx, &pos, parse_inline_c)) - ||(stmt=optional(ctx, &pos, parse_declaration))) + ||(stmt=optional(ctx, &pos, parse_top_declaration))) { statements = new(ast_list_t, .ast=stmt, .next=statements); pos = stmt->end; @@ -2194,7 +2213,7 @@ PARSER(parse_use) { what = USE_SHARED_OBJECT; else what = USE_MODULE; - return NewAST(ctx->file, start, pos, Use, .name=name, .what=what); + return NewAST(ctx->file, start, pos, Use, .path=name, .what=what); } PARSER(parse_linker) { diff --git a/tomo.c b/tomo.c index 01bdf5a..6371a25 100644 --- a/tomo.c +++ b/tomo.c @@ -324,9 +324,9 @@ void build_file_dependency_graph(const char *filename, table_t *to_compile, tabl switch (use->what) { case USE_LOCAL: { - const char *path = use->name; + const char *path = use->path; path = resolve_path(path, filename, ""); - if (!path) errx(1, "Couldn't resolve import: %s", use->name); + if (!path) errx(1, "Couldn't resolve import: %s", use->path); if (Table$str_get(*to_compile, path)) continue; build_file_dependency_graph(path, to_compile, to_link); @@ -334,16 +334,16 @@ void build_file_dependency_graph(const char *filename, table_t *to_compile, tabl break; } case USE_MODULE: { - const char *base_name = file_base_name(use->name); + const char *base_name = file_base_name(use->path); const char *lib_path = heap_strf("%s/lib%s.so", base_name, base_name); const char *libfile = resolve_path(lib_path, filename, getenv("TOMO_IMPORT_PATH")); if (!libfile) errx(1, "Couldn't resolve path: %s", lib_path); - const char *lib = heap_strf("-l%s", use->name); + const char *lib = heap_strf("-l%s", use->path); Table$str_set(to_link, lib, lib); break; } case USE_SHARED_OBJECT: { - const char *lib = heap_strf("-l:%s", use->name); + const char *lib = heap_strf("-l:%s", use->path); Table$str_set(to_link, lib, lib); break; } diff --git a/typecheck.c b/typecheck.c index b5a4a4c..af1ea77 100644 --- a/typecheck.c +++ b/typecheck.c @@ -130,20 +130,20 @@ static env_t *load_module(env_t *env, ast_t *module_ast) auto use = Match(module_ast, Use); switch (use->what) { case USE_LOCAL: { - const char *resolved_path = resolve_path(use->name, module_ast->file->filename, module_ast->file->filename); + const char *resolved_path = resolve_path(use->path, module_ast->file->filename, module_ast->file->filename); env_t *module_env = Table$str_get(*env->imports, resolved_path); if (module_env) return module_env; if (!resolved_path) - code_err(module_ast, "No such file exists: \"%s\"", use->name); + code_err(module_ast, "No such file exists: \"%s\"", use->path); ast_t *ast = parse_file(resolved_path, NULL); if (!ast) errx(1, "Could not compile file %s", resolved_path); return load_module_env(env, ast); } case USE_MODULE: { - const char *libname = file_base_name(use->name); + const char *libname = file_base_name(use->path); const char *files_filename = heap_strf("%s/lib%s.files", libname, libname); const char *resolved_path = resolve_path(files_filename, module_ast->file->filename, getenv("TOMO_IMPORT_PATH")); if (!resolved_path) @@ -152,7 +152,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast) if (!files_f) errx(1, "Couldn't open file: %s", resolved_path); env_t *module_env = fresh_scope(env); - Table$str_set(env->imports, use->name, module_env); + Table$str_set(env->imports, use->path, module_env); char *libname_id = GC_strdup(libname); for (char *c = libname_id; *c; c++) { if (!isalnum(*c) && *c != '_') @@ -834,9 +834,9 @@ type_t *get_type(env_t *env, ast_t *ast) case Use: { switch (Match(ast, Use)->what) { case USE_LOCAL: - return Type(ModuleType, resolve_path(Match(ast, Use)->name, ast->file->filename, ast->file->filename)); + return Type(ModuleType, resolve_path(Match(ast, Use)->path, ast->file->filename, ast->file->filename)); default: - return Type(ModuleType, Match(ast, Use)->name); + return Type(ModuleType, Match(ast, Use)->path); } } case Return: {