diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index fc4540d66..5d1d69b44 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -20,12 +20,7 @@ Vmem tokdata_arena; Vmem decl_arena; Vmem type_info_arena; -static void global_context_clear_errors(void) -{ - global_context.in_panic_mode = false; - global_context.errors_found = 0; - global_context.warnings_found = 0; -} + void compiler_init(const char *std_lib_dir) { @@ -98,10 +93,6 @@ void compiler_parse(void) exit_compiler(COMPILER_SUCCESS_EXIT); } -static inline void halt_on_error(void) -{ - if (global_context.errors_found > 0) exit_compiler(EXIT_FAILURE); -} typedef struct CompileData_ { @@ -122,111 +113,7 @@ void thread_compile_task_tb(void *compiledata) data->object_name = tinybackend_codegen(data->context); } -void sema_analyze_stage(Module *module, AnalysisStage stage) -{ - while (module->stage < stage) - { - module->stage++; - switch (module->stage) - { - case ANALYSIS_NOT_BEGUN: - UNREACHABLE - case ANALYSIS_IMPORTS: - sema_analysis_pass_process_imports(module); - break; - case ANALYSIS_REGISTER_GLOBALS: - sema_analysis_pass_register_globals(module); - break; - case ANALYSIS_CONDITIONAL_COMPILATION: - sema_analysis_pass_conditional_compilation(module); - break; - case ANALYSIS_DECLS: - sema_analysis_pass_decls(module); - break; - case ANALYSIS_CT_ASSERT: - sema_analysis_pass_ct_assert(module); - break; - case ANALYSIS_FUNCTIONS: - sema_analysis_pass_functions(module); - break; - } - if (global_context.errors_found) return; - } -} -static void register_generic_decls(Module *module, Decl **decls) -{ - VECEACH(decls, i) - { - Decl *decl = decls[i]; - decl->module = module; - switch (decl->decl_kind) - { - case DECL_POISONED: - case DECL_ENUM_CONSTANT: - case DECL_ERRVALUE: - case DECL_IMPORT: - case DECL_LABEL: - case DECL_CT_ASSERT: - continue; - case DECL_ATTRIBUTE: - break; - case DECL_CT_CASE: - register_generic_decls(module, decl->ct_case_decl.body); - continue; - case DECL_CT_ELIF: - register_generic_decls(module, decl->ct_elif_decl.then); - continue; - case DECL_CT_ELSE: - register_generic_decls(module, decl->ct_else_decl); - continue; - case DECL_CT_IF: - register_generic_decls(module, decl->ct_if_decl.then); - continue; - case DECL_CT_SWITCH: - register_generic_decls(module, decl->ct_switch_decl.cases); - continue; - case DECL_MACRO: - case DECL_DEFINE: - case DECL_DISTINCT: - case DECL_ENUM: - case DECL_GENERIC: - case DECL_ERRTYPE: - case DECL_FUNC: - case DECL_STRUCT: - case DECL_TYPEDEF: - case DECL_UNION: - case DECL_VAR: - case DECL_BITSTRUCT: - break; - } - if (decl->visibility > VISIBLE_MODULE) - { - stable_set(&module->public_symbols, decl->name, decl); - } - stable_set(&module->symbols, decl->name, decl); - } - -} -static void analyze_generic_module(Module *module) -{ - assert(module->parameters && module->is_generic); - // TODO maybe do this analysis: sema_analysis_pass_process_imports(module); - VECEACH(module->contexts, index) - { - Context *context = module->contexts[index]; - register_generic_decls(module, context->global_decls); - } -} - -static void analyze_to_stage(AnalysisStage stage) -{ - VECEACH(global_context.module_list, i) - { - sema_analyze_stage(global_context.module_list[i], stage); - } - halt_on_error(); -} static void add_global_define(const char *name, Expr *value) { @@ -249,28 +136,6 @@ static void add_global_define(const char *name, Expr *value) stable_set(&dec->module->symbols, dec->name, dec); } -static void setup_int_define(const char *id, uint64_t i, Type *type) -{ - TokenType token_type = TOKEN_CONST_IDENT; - id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); - Expr *expr = expr_new(EXPR_CONST, INVALID_RANGE); - assert(type_is_integer(type)); - expr_const_set_int(&expr->const_expr, i, type->type_kind); - if (expr_const_will_overflow(&expr->const_expr, type->type_kind)) - { - error_exit("Integer define %s overflow.", id); - } - expr->type = type; - expr->const_expr.narrowable = true; - expr->span = INVALID_RANGE; - expr->resolve_status = RESOLVE_NOT_DONE; - void *previous = stable_set(&global_context.compiler_defines, id, expr); - if (previous) - { - error_exit("Redefined ident %s", id); - } -} - static const char *active_target_name(void) { if (active_target.name) return active_target.name; @@ -285,72 +150,9 @@ static const char *active_target_name(void) } } -static void setup_bool_define(const char *id, bool value) -{ - TokenType token_type = TOKEN_CONST_IDENT; - id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); - Expr *expr = expr_new(EXPR_CONST, INVALID_RANGE); - expr_const_set_bool(&expr->const_expr, value); - expr->type = type_bool; - expr->span = INVALID_RANGE; - expr->resolve_status = RESOLVE_NOT_DONE; - void *previous = stable_set(&global_context.compiler_defines, id, expr); - if (previous) - { - error_exit("Redefined ident %s", id); - } -} - void compiler_compile(void) { - setup_int_define("C_SHORT_SIZE", platform_target.width_c_short, type_long); - setup_int_define("C_INT_SIZE", platform_target.width_c_int, type_long); - setup_int_define("C_LONG_SIZE", platform_target.width_c_long, type_long); - setup_int_define("C_LONG_LONG_SIZE", platform_target.width_c_long_long, type_long); - setup_bool_define("C_CHAR_IS_SIGNED", platform_target.signed_c_char); - setup_bool_define("PLATFORM_BIG_ENDIAN", platform_target.big_endian); - setup_bool_define("PLATFORM_I128_SUPPORTED", platform_target.int128); - setup_int_define("COMPILER_OPT_LEVEL", (uint64_t)active_target.optimization_level, type_int); - setup_int_define("COMPILER_SIZE_OPT_LEVEL", (uint64_t)active_target.size_optimization_level, type_int); - setup_bool_define("COMPILER_SAFE_MODE", active_target.feature.safe_mode); - - type_init_cint(); - - global_context_clear_errors(); - - if (global_context.lib_dir) - { - file_add_wildcard_files(&global_context.sources, global_context.lib_dir, true, ".c3", ".c3i"); - } - bool has_error = false; - VECEACH(global_context.sources, i) - { - bool loaded = false; - File *file = source_file_load(global_context.sources[i], &loaded); - if (loaded) continue; - if (!parse_file(file)) has_error = true; - } - - if (has_error) exit_compiler(EXIT_FAILURE); - - global_context.std_module_path = (Path) { .module = kw_std, .span = INVALID_RANGE, .len = (uint32_t) strlen(kw_std) }; - global_context.std_module = (Module){ .name = &global_context.std_module_path }; - global_context.std_module.stage = ANALYSIS_LAST; - stable_init(&global_context.std_module.symbols, 0x10000); - - if (!global_context.module_list) - { - if (global_context.errors_found) exit_compiler(EXIT_FAILURE); - error_exit("No modules to compile."); - } - VECEACH(global_context.generic_module_list, i) - { - analyze_generic_module(global_context.generic_module_list[i]); - } - for (AnalysisStage stage = ANALYSIS_NOT_BEGUN + 1; stage <= ANALYSIS_LAST; stage++) - { - analyze_to_stage(stage); - } + sema_analysis_run(); Module **modules = global_context.module_list; unsigned module_count = vec_size(modules); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index b3d60ec02..27c9120d2 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -323,7 +323,6 @@ typedef struct Path *path; TokenId symbol; bool private; - bool aliased; } ImportDecl; typedef struct @@ -362,17 +361,35 @@ typedef struct VarDecl_ }; union { - void *backend_debug_ref; - unsigned scope_depth; - Expr *start; - unsigned start_bit; - }; - union - { - void *failable_ref; - struct ABIArgInfo_ *abi_info; - Expr *end; - unsigned end_bit; + struct SemaContext_ *context; // Hash var + unsigned scope_depth; // CT var + struct + { + void *backend_debug_ref; + union + { + // Param + struct ABIArgInfo_ *abi_info; + // Variable + void *failable_ref; + }; + }; + struct + { + union + { + struct + { + Expr *start; + Expr *end; + }; + struct + { + unsigned start_bit; + unsigned end_bit; + }; + }; + }; }; } VarDecl; @@ -494,7 +511,7 @@ typedef struct struct Ast_ *body; Decl **body_parameters; TokenId block_parameter; - struct Context_ *context; + struct CompilationUnit_ *unit; } MacroDecl; typedef struct @@ -567,6 +584,7 @@ typedef struct Decl_ bool needs_additional_pad : 1; bool is_substruct : 1; bool has_variable_array : 1; + bool no_scope : 1; void *backend_ref; const char *extname; AlignSize alignment; @@ -822,6 +840,7 @@ typedef struct typedef struct { + bool no_scope; Ast **stmts; Expr **args; Decl **params; @@ -1289,7 +1308,7 @@ typedef struct Module_ Decl** generic_cache; STable symbols; STable public_symbols; - struct Context_ **contexts; + struct CompilationUnit_ **units; } Module; @@ -1300,28 +1319,14 @@ typedef struct DynamicScope_ bool allow_dead_code : 1; bool jump_end : 1; ScopeFlags flags; - Decl **local_decl_start; - Decl **current_local; + unsigned local_decl_start; + unsigned current_local; AstId defer_last; AstId defer_start; Ast *in_defer; unsigned depth; } DynamicScope; -typedef struct MacroScope_ -{ - Decl *macro; - uint32_t inline_line; - uint32_t original_inline_line; - Decl **locals_start; - unsigned depth; - Decl **yield_symbol_start; - Decl **yield_symbol_end; - Decl **yield_args; - Ast *yield_body; - bool in_yield; - const char *body_param; -} MacroScope; typedef union { @@ -1359,42 +1364,62 @@ typedef struct unsigned char *latest_token_type; } Lexer; + +typedef struct CompilationUnit_ +{ + Module *module; + File* file; + Decl** imports; + Decl **types; + Decl **functions; + Decl **enums; + Decl **errtypes; + struct + { + // Not properly implemented + Decl **generic_methods; + Decl **generics; + Decl **generic_defines; + }; + Decl **ct_ifs; + Decl **ct_asserts; + Decl **vars; + Decl **macros; + Decl **methods; + Decl **macro_methods; + Decl **global_decls; + Decl *main_function; + STable local_symbols; + struct { + STable external_symbols; + Decl **external_symbol_list; + }; + struct + { + void *debug_file; + void *debug_compile_unit; + } llvm; +} CompilationUnit; + typedef struct { uint32_t lexer_index; Token tok; TokenId prev_tok; Token next_tok; -} LexingContext; - -typedef struct Context_ -{ - Path *module_name; - File* file; - Decl** imports; - Module *module; - STable local_symbols; - Decl **global_decls; - Decl **enums; - Decl **errtypes; - Decl **types; - Decl **generic_defines; - Decl **functions; - Decl *main_function; - Decl **macros; - Decl **generics; - Decl **generic_methods; - Decl **templates; - Decl **methods; - Decl **macro_methods; - Decl **vars; - Decl **ct_ifs; - Decl **ct_asserts; - Decl *active_function_for_analysis; + CompilationUnit *unit; Token *comments; Token *lead_comment; Token *trailing_comment; Token *next_lead_comment; +} ParseContext; + +typedef struct SemaContext_ +{ + CompilationUnit *unit; + CompilationUnit *compilation_unit; + Decl *current_function; + Decl *current_macro; ScopeId scope_id; AstId break_target; AstId break_defer; @@ -1405,6 +1430,9 @@ typedef struct Context_ AstId next_defer; struct { + uint32_t original_inline_line; + Decl **yield_params; + Ast *yield_body; Type *expected_block_type; Ast **returns; bool expr_failable_return; @@ -1412,17 +1440,10 @@ typedef struct Context_ Ast **returns_cache; }; Type *rtype; - MacroScope macro_scope; - struct { - STable external_symbols; - Decl **external_symbol_list; - }; - Decl* locals[MAX_LOCALS]; + struct SemaContext_ *yield_context; + Decl** locals; DynamicScope active_scope; - LexingContext lex; - void *llvm_debug_file; - void *llvm_debug_compile_unit; -} Context; +} SemaContext; typedef struct { @@ -1440,6 +1461,7 @@ typedef struct unsigned errors_found; unsigned warnings_found; char scratch_buffer[MAX_STRING_BUFFER]; + Decl ***locals_list; uint32_t scratch_buffer_len; STable compiler_defines; Module std_module; @@ -1632,9 +1654,9 @@ static inline Ast *new_ast(AstKind kind, SourceSpan range) -static inline Ast *extend_ast_with_prev_token(Context *context, Ast *ast) +static inline Ast *extend_ast_with_prev_token(ParseContext *context, Ast *ast) { - ast->span.end_loc = context->lex.prev_tok; + ast->span.end_loc = context->prev_tok; return ast; } @@ -1776,18 +1798,20 @@ void tinybackend_codegen_setup(); void header_gen(Module *module); +static inline void global_context_clear_errors(void); void global_context_add_type(Type *type); Decl *compiler_find_symbol(const char *name); Module *compiler_find_or_create_module(Path *module_name, TokenId *parameters, bool is_private); Module *global_context_find_module(const char *name); void compiler_register_public_symbol(Decl *decl); -Context *context_create(File *file); -void context_register_global_decl(Context *context, Decl *decl); -void context_register_external_symbol(Context *context, Decl *decl); -bool context_add_import(Context *context, Path *path, Token symbol, Token alias, bool private_import); -bool context_set_module_from_filename(Context *context); -bool context_set_module(Context *context, Path *path, TokenId *generic_parameters, bool is_private); +CompilationUnit * unit_create(File *file); +void unit_register_global_decl(CompilationUnit *unit, Decl *decl); +void unit_register_external_symbol(CompilationUnit *unit, Decl *decl); + +bool unit_add_import(CompilationUnit *unit, Path *path, Token token, bool private_import); +bool context_set_module_from_filename(ParseContext *context); +bool context_set_module(ParseContext *context, Path *path, TokenId *generic_parameters, bool is_private); // --- Decl functions @@ -1905,8 +1929,6 @@ static inline TokenData *tokendata_from_token(Token token) { return tokdataptr(t #define TOKSTR(T) TOKDATA(T)->string -#define TOKREAL(T) TOKDATA(T)->value - static inline TokenType tokenid_type(TokenId token) { return (TokenType)toktypeptr(token.index)[0]; } static inline TokenType token_type(Token token) { return (TokenType)toktypeptr(token.id.index)[0]; } #define TOKTYPE(T) _Generic((T), TokenId: tokenid_type, Token: token_type)(T) @@ -1925,47 +1947,41 @@ Path *path_find_parent_path(Path *path); #define SEMA_PREV(_node, ...) sema_prev_at_range3((_node)->span, __VA_ARGS__) #define SEMA_TOKID_PREV(_tok_id, ...) sema_prev_at_range3(source_span_from_token_id(_tok_id), __VA_ARGS__) -void sema_analysis_pass_process_imports(Module *module); -void sema_analysis_pass_register_globals(Module *module); -void sema_analysis_pass_conditional_compilation(Module *module); -void sema_analysis_pass_decls(Module *module); -void sema_analysis_pass_ct_assert(Module *module); -void sema_analysis_pass_functions(Module *module); -void sema_analyze_stage(Module *module, AnalysisStage stage); +void sema_analysis_run(void); bool sema_failed_cast(Expr *expr, Type *from, Type *to); -bool sema_add_member(Context *context, Decl *decl); -bool sema_add_local(Context *context, Decl *decl); -bool sema_unwrap_var(Context *context, Decl *decl); -bool sema_rewrap_var(Context *context, Decl *decl); -bool sema_erase_var(Context *context, Decl *decl); -bool sema_erase_unwrapped(Context *context, Decl *decl); -bool sema_analyse_cond_expr(Context *context, Expr *expr); +bool sema_add_member(SemaContext *context, Decl *decl); +bool sema_add_local(SemaContext *context, Decl *decl); +bool sema_unwrap_var(SemaContext *context, Decl *decl); +bool sema_rewrap_var(SemaContext *context, Decl *decl); +bool sema_erase_var(SemaContext *context, Decl *decl); +bool sema_erase_unwrapped(SemaContext *context, Decl *decl); +bool sema_analyse_cond_expr(SemaContext *context, Expr *expr); -bool sema_analyse_expr_rhs(Context *context, Type *to, Expr *expr, bool allow_failable); -MemberIndex sema_get_initializer_const_array_size(Context *context, Expr *initializer, bool *may_be_array, bool *is_const_size); -bool sema_analyse_expr(Context *context, Expr *expr); -bool sema_analyse_inferred_expr(Context *context, Type *to, Expr *expr); -bool sema_analyse_decl(Context *context, Decl *decl); +bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_failable); +MemberIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size); +bool sema_analyse_expr(SemaContext *context, Expr *expr); +bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr); +bool sema_analyse_decl(SemaContext *context, Decl *decl); -bool sema_analyse_var_decl(Context *context, Decl *decl, bool local); -bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement); -bool sema_analyse_statement(Context *context, Ast *statement); -bool sema_expr_analyse_assign_right_side(Context *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped_var); +bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local); +bool sema_analyse_ct_assert_stmt(SemaContext *context, Ast *statement); +bool sema_analyse_statement(SemaContext *context, Ast *statement); +bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped_var); -bool sema_expr_analyse_general_call(Context *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable); -Decl *sema_resolve_symbol_in_current_dynamic_scope(Context *context, const char *symbol); -Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path *path); -Decl *sema_resolve_method(Context *context, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref); +bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable); +Decl *sema_resolve_symbol_in_current_dynamic_scope(SemaContext *context, const char *symbol); +Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, TokenId symbol, Path *path); +Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref); Decl *sema_find_extension_method_in_module(Module *module, Type *type, const char *method_name); -Decl *sema_resolve_normal_symbol(Context *context, TokenId symbol, Path *path, bool handle_error); -Decl *sema_resolve_string_symbol(Context *context, const char *symbol, SourceSpan span, Path *path, bool report_error); +Decl *sema_resolve_normal_symbol(SemaContext *context, TokenId symbol, Path *path, bool handle_error); +Decl *sema_resolve_string_symbol(SemaContext *context, const char *symbol, SourceSpan span, Path *path, bool report_error); -bool sema_resolve_type(Context *context, Type *type); -bool sema_resolve_array_like_len(Context *context, TypeInfo *type_info, ArraySize *len_ref); -bool sema_resolve_type_info(Context *context, TypeInfo *type_info); -bool sema_resolve_type_info_maybe_inferred(Context *context, TypeInfo *type_info, bool allow_inferred_type); -bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info, bool allow_inferred_type, bool in_shallow); +bool sema_resolve_type(SemaContext *context, Type *type); +bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, ArraySize *len_ref); +bool sema_resolve_type_info(SemaContext *context, TypeInfo *type_info); +bool sema_resolve_type_info_maybe_inferred(SemaContext *context, TypeInfo *type_info, bool allow_inferred_type); +bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool allow_inferred_type, bool in_shallow); Type *sema_type_lower_by_size(Type *type, ArraySize element_size); void sema_error_at_prev_end(Token token, const char *message, ...); @@ -1973,7 +1989,7 @@ void sema_error_at_prev_end(Token token, const char *message, ...); void sema_error_range(SourceSpan span, const char *message, ...); void sema_verror_range(SourceLocation *location, const char *message, va_list args); -void sema_error(Context *context, const char *message, ...); +void sema_error(ParseContext *context, const char *message, ...); void sema_prev_at_range3(SourceSpan span, const char *message, ...); void sema_shadow_error(Decl *decl, Decl *old); @@ -1986,7 +2002,7 @@ static inline SourceSpan source_span_from_token_id(TokenId id) } -#define RANGE_EXTEND_PREV(x) ((x)->span.end_loc = context->lex.prev_tok) +#define RANGE_EXTEND_PREV(x) ((x)->span.end_loc = context->prev_tok) void stable_init(STable *table, uint32_t initial_size); void *stable_set(STable *table, const char *key, void *value); @@ -2244,12 +2260,12 @@ static inline const char* struct_union_name_from_token(TokenType type) } -void advance(Context *context); +void advance(ParseContext *context); // Useful sanity check function. -static inline void advance_and_verify(Context *context, TokenType token_type) +static inline void advance_and_verify(ParseContext *context, TokenType token_type) { - assert(context->lex.tok.type == token_type); + assert(context->tok.type == token_type); advance(context); } @@ -2492,3 +2508,10 @@ static inline Type *abi_returntype(FunctionSignature *signature) Type *type = signature->rtype->type; return type->type_kind == TYPE_FAILABLE ? type_anyerr : type; } + +static inline void global_context_clear_errors(void) +{ + global_context.in_panic_mode = false; + global_context.errors_found = 0; + global_context.warnings_found = 0; +} diff --git a/src/compiler/context.c b/src/compiler/context.c index 474e4f5c7..6d9adbca9 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -5,36 +5,36 @@ #include "compiler_internal.h" -Context *context_create(File *file) +CompilationUnit * unit_create(File *file) { - Context *context = CALLOCS(Context); - context->file = file; - stable_init(&context->local_symbols, 1024); - stable_init(&context->external_symbols, 1024); - return context; + CompilationUnit *unit = CALLOCS(CompilationUnit); + unit->file = file; + stable_init(&unit->local_symbols, 1024); + stable_init(&unit->external_symbols, 1024); + return unit; } -static inline bool create_module_or_check_name(Context *context, Path *module_name, TokenId *parameters, bool is_private) +static inline bool create_module_or_check_name(CompilationUnit *unit, Path *module_name, TokenId *parameters, bool is_private) { - context->module_name = module_name; - if (context->module == NULL) + Module *module = unit->module; + if (!module) { - context->module = compiler_find_or_create_module(module_name, parameters, is_private); + module = unit->module = compiler_find_or_create_module(module_name, parameters, is_private); } else { - if (context->module->name->module != module_name->module) + if (unit->module->name->module != module_name->module) { SEMA_ERROR(module_name, "Module name here '%s' did not match actual module '%s'.", module_name->module, - context->module->name->module); + module->name->module); return false; } } - if (context->module->is_private != is_private) + if (module->is_private != is_private) { if (is_private) { @@ -47,7 +47,7 @@ static inline bool create_module_or_check_name(Context *context, Path *module_na return false; } - vec_add(context->module->contexts, context); + vec_add(module->units, unit); return true; } @@ -80,11 +80,12 @@ static bool filename_to_module_in_buffer(const char *path) return true; } -bool context_set_module_from_filename(Context *context) +bool context_set_module_from_filename(ParseContext *context) { - if (!filename_to_module_in_buffer(context->file->full_path)) + File *file = context->unit->file; + if (!filename_to_module_in_buffer(file->full_path)) { - sema_error(context, "The filename '%s' could not be converted to a valid module name, try using an explicit module name.", context->file->full_path); + sema_error(context, "The filename '%s' could not be converted to a valid module name, try using an explicit module name.", file->full_path); return false; } @@ -97,44 +98,43 @@ bool context_set_module_from_filename(Context *context) if (type != TOKEN_IDENT) { sema_error(context, "Generating a filename from the file '%s' resulted in a name that is a reserved keyword, " - "try using an explicit module name.", context->file->full_path); + "try using an explicit module name.", file->full_path); return false; } Path *path = CALLOCS(Path); path->span = INVALID_RANGE; path->module = module_name; path->len = global_context.scratch_buffer_len; - return create_module_or_check_name(context, path, NULL, true); + return create_module_or_check_name(context->unit, path, NULL, true); } -bool context_set_module(Context *context, Path *path, TokenId *generic_parameters, bool is_private) +bool context_set_module(ParseContext *context, Path *path, TokenId *generic_parameters, bool is_private) { // Note that we allow the illegal name for now, to be able to parse further. - context->module_name = path; if (!is_all_lower(path->module)) { SEMA_ERROR(path, "A module name may not have any upper case characters."); return false; } - return create_module_or_check_name(context, path, generic_parameters, is_private); + return create_module_or_check_name(context->unit, path, generic_parameters, is_private); } -void context_register_external_symbol(Context *context, Decl *decl) +void unit_register_external_symbol(CompilationUnit *unit, Decl *decl) { assert(decl->external_name && "Missing external name"); - Decl *prev = stable_get(&context->external_symbols, decl->external_name); + Decl *prev = stable_get(&unit->external_symbols, decl->external_name); if (prev) return; - stable_set(&context->external_symbols, decl->external_name, decl); - vec_add(context->external_symbol_list, decl); + stable_set(&unit->external_symbols, decl->external_name, decl); + vec_add(unit->external_symbol_list, decl); } -void context_register_global_decl(Context *context, Decl *decl) +void unit_register_global_decl(CompilationUnit *unit, Decl *decl) { - decl->module = context->module; + decl->module = unit->module; switch (decl->decl_kind) { case DECL_POISONED: @@ -143,12 +143,12 @@ void context_register_global_decl(Context *context, Decl *decl) assert(decl->name); if (decl->macro_decl.type_parent) { - vec_add(context->generic_methods, decl); + vec_add(unit->generic_methods, decl); return; } else { - vec_add(context->generics, decl); + vec_add(unit->generics, decl); } decl_set_external_name(decl); break; @@ -156,12 +156,12 @@ void context_register_global_decl(Context *context, Decl *decl) assert(decl->name); if (decl->macro_decl.type_parent) { - vec_add(context->macro_methods, decl); + vec_add(unit->macro_methods, decl); return; } else { - vec_add(context->macros, decl); + vec_add(unit->macros, decl); } decl_set_external_name(decl); break; @@ -169,17 +169,17 @@ void context_register_global_decl(Context *context, Decl *decl) assert(decl->name); if (decl->func_decl.type_parent) { - vec_add(context->methods, decl); + vec_add(unit->methods, decl); return; } else { - vec_add(context->functions, decl); + vec_add(unit->functions, decl); } break; case DECL_VAR: assert(decl->name); - vec_add(context->vars, decl); + vec_add(unit->vars, decl); decl_set_external_name(decl); break; case DECL_DISTINCT: @@ -189,17 +189,17 @@ void context_register_global_decl(Context *context, Decl *decl) case DECL_ERRTYPE: case DECL_BITSTRUCT: assert(decl->name); - vec_add(context->types, decl); + vec_add(unit->types, decl); decl_set_external_name(decl); break; case DECL_DEFINE: assert(decl->name); - vec_add(context->generic_defines, decl); + vec_add(unit->generic_defines, decl); decl_set_external_name(decl); break; case DECL_ENUM: assert(decl->name); - vec_add(context->enums, decl); + vec_add(unit->enums, decl); decl_set_external_name(decl); break; case DECL_ERRVALUE: @@ -213,23 +213,23 @@ void context_register_global_decl(Context *context, Decl *decl) UNREACHABLE case DECL_CT_IF: case DECL_CT_SWITCH: - vec_add(context->ct_ifs, decl); + vec_add(unit->ct_ifs, decl); return; case DECL_CT_ASSERT: - vec_add(context->ct_asserts, decl); + vec_add(unit->ct_asserts, decl); return; } - DEBUG_LOG("Registering symbol '%s' in %s.", decl->name, context->module->name->module); + DEBUG_LOG("Registering symbol '%s' in %s.", decl->name, unit->module->name->module); - Decl *old = stable_set(&context->local_symbols, decl->name, decl); + Decl *old = stable_set(&unit->local_symbols, decl->name, decl); if (!old) { - old = stable_set(&context->module->symbols, decl->name, decl); + old = stable_set(&unit->module->symbols, decl->name, decl); } if (!old && decl->visibility == VISIBLE_PUBLIC) { compiler_register_public_symbol(decl); - old = stable_set(&context->module->public_symbols, decl->name, decl); + old = stable_set(&unit->module->public_symbols, decl->name, decl); } if (old != NULL) { @@ -239,7 +239,7 @@ void context_register_global_decl(Context *context, Decl *decl) } } -bool context_add_import(Context *context, Path *path, Token token, Token alias, bool private_import) +bool unit_add_import(CompilationUnit *unit, Path *path, Token token, bool private_import) { DEBUG_LOG("SEMA: Add import of '%s'.", path->module); @@ -257,24 +257,8 @@ bool context_add_import(Context *context, Path *path, Token token, Token alias, import->import.path = path; import->import.private = private_import; import->import.symbol = token.id; - if (alias.type != TOKEN_INVALID_TOKEN) - { - const char *alias_name = TOKSTR(alias); - if (alias_name == TOKSTR(token)) - { - SEMA_TOKEN_ERROR(alias, "If an alias would be the same as the symbol aliased, it wouldn't have any effect."); - return false; - } - if (alias_name == context->module_name->module) - { - SEMA_TOKEN_ERROR(alias, "An alias cannot have not have the same as the name of the current module."); - return false; - } - import->import.aliased = true; - TODO - } - vec_add(context->imports, import); + vec_add(unit->imports, import); DEBUG_LOG("Added import %s", path->module); return true; } diff --git a/src/compiler/diagnostics.c b/src/compiler/diagnostics.c index 4fdbfd287..61acefd21 100644 --- a/src/compiler/diagnostics.c +++ b/src/compiler/diagnostics.c @@ -207,10 +207,10 @@ void sema_error_at_prev_end(Token token, const char *message, ...) } -void sema_error(Context *context, const char *message, ...) +void sema_error(ParseContext *context, const char *message, ...) { global_context.errors_found++; - File *file = context->file; + File *file = context->unit->file; va_list list; va_start(list, message); eprintf("(%s:0) Error: ", file->name); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index a2db89d9a..cb29cc5fd 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -629,6 +629,7 @@ typedef enum ATTR_INTERFACE = 1 << 10, ATTR_CALL = 1 << 11, ATTR_BITSTRUCT = 1 << 12, + ATTR_MACRO = 1 << 13, } AttributeDomain; typedef enum @@ -647,6 +648,7 @@ typedef enum ATTRIBUTE_UNUSED, ATTRIBUTE_USED, ATTRIBUTE_NAKED, + ATTRIBUTE_NOSCOPE, ATTRIBUTE_CDECL, ATTRIBUTE_STDCALL, ATTRIBUTE_VECCALL, diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 3c5b8281e..fefd2d257 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -16,12 +16,12 @@ static void indent_line(FILE *file, int indent) } static void header_gen_decl(FILE *file, int indent, Decl *decl); -static void header_gen_method(FILE *file, Context *c, Decl *decl) +static void header_gen_method(FILE *file, SemaContext *c, Decl *decl) { fprintf(file, "/* method */\n"); } -static void header_gen_function(FILE *file, Context *c, Decl *decl) +static void header_gen_function(FILE *file, SemaContext *c, Decl *decl) { fprintf(file, "/* function */\n"); } @@ -217,7 +217,7 @@ static void header_gen_decl(FILE *file, int indent, Decl *decl) UNREACHABLE } -static void header_gen_var(FILE *file, Context *c, Decl *decl) +static void header_gen_var(FILE *file, SemaContext *c, Decl *decl) { fprintf(file, "/* vars */\n"); } @@ -225,8 +225,8 @@ static void header_gen_var(FILE *file, Context *c, Decl *decl) void header_gen(Module *module) { TODO - Context *context = module->contexts[0]; - const char *filename = strcat_arena(context->file->name, ".h"); + CompilationUnit *unit = module->units[0]; + const char *filename = strcat_arena(unit->file->name, ".h"); FILE *file = fopen(filename, "w"); OUTPUT("#include \n"); OUTPUT("#ifndef __c3__\n"); @@ -235,11 +235,13 @@ void header_gen(Module *module) header_print_type(file, type_flatten(type_typeid)); OUTPUT(" c3typeid_t;\n"); OUTPUT("#endif\n"); - VECEACH(context->types, i) + VECEACH(unit->types, i) { - header_gen_decl(file, 0, context->types[i]); + header_gen_decl(file, 0, unit->types[i]); } + TODO + /* VECEACH(context->vars, i) { header_gen_var(file, context, context->vars[i]); @@ -251,6 +253,6 @@ void header_gen(Module *module) VECEACH(context->functions, i) { header_gen_function(file, context, context->functions[i]); - } + }*/ fclose(file); } diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 6fa712bc0..cb974bb33 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -982,69 +982,69 @@ const char *llvm_codegen(void *context) void *llvm_gen(Module *module) { - if (!vec_size(module->contexts)) return NULL; + if (!vec_size(module->units)) return NULL; assert(intrinsics_setup); GenContext *gen_context = cmalloc(sizeof(GenContext)); gencontext_init(gen_context, module); gencontext_begin_module(gen_context); - VECEACH(module->contexts, j) + VECEACH(module->units, j) { - Context *context = module->contexts[j]; - gencontext_init_file_emit(gen_context, context); - gen_context->debug.compile_unit = context->llvm_debug_compile_unit; - gen_context->debug.file = context->llvm_debug_file; + CompilationUnit *unit = module->units[j]; + gencontext_init_file_emit(gen_context, unit); + gen_context->debug.compile_unit = unit->llvm.debug_compile_unit; + gen_context->debug.file = unit->llvm.debug_file; - VECEACH(context->external_symbol_list, i) + VECEACH(unit->external_symbol_list, i) { - Decl *d = context->external_symbol_list[i]; + Decl *d = unit->external_symbol_list[i]; // Avoid duplicating symbol - if (d->module == context->module) continue; - llvm_emit_extern_decl(gen_context, context->external_symbol_list[i]); + if (d->module == unit->module) continue; + llvm_emit_extern_decl(gen_context, unit->external_symbol_list[i]); } - VECEACH(context->methods, i) + VECEACH(unit->methods, i) { - llvm_emit_function_decl(gen_context, context->methods[i]); + llvm_emit_function_decl(gen_context, unit->methods[i]); } - VECEACH(context->types, i) + VECEACH(unit->types, i) { - llvm_emit_type_decls(gen_context, context->types[i]); + llvm_emit_type_decls(gen_context, unit->types[i]); } - VECEACH(context->functions, i) + VECEACH(unit->functions, i) { - llvm_emit_function_decl(gen_context, context->functions[i]); + llvm_emit_function_decl(gen_context, unit->functions[i]); } - if (context->main_function) llvm_emit_function_decl(gen_context, context->main_function); + if (unit->main_function) llvm_emit_function_decl(gen_context, unit->main_function); } - VECEACH(module->contexts, j) + VECEACH(module->units, j) { - Context *context = module->contexts[j]; - gen_context->debug.compile_unit = context->llvm_debug_compile_unit; - gen_context->debug.file = context->llvm_debug_file; + CompilationUnit *unit = module->units[j]; + gen_context->debug.compile_unit = unit->llvm.debug_compile_unit; + gen_context->debug.file = unit->llvm.debug_file; - VECEACH(context->vars, i) + VECEACH(unit->vars, i) { - gencontext_emit_global_variable_definition(gen_context, context->vars[i]); + gencontext_emit_global_variable_definition(gen_context, unit->vars[i]); } - VECEACH(context->vars, i) + VECEACH(unit->vars, i) { - llvm_emit_global_variable_init(gen_context, context->vars[i]); + llvm_emit_global_variable_init(gen_context, unit->vars[i]); } - VECEACH(context->functions, i) + VECEACH(unit->functions, i) { - Decl *decl = context->functions[i]; + Decl *decl = unit->functions[i]; if (decl->func_decl.body) llvm_emit_function_body(gen_context, decl); } - if (context->main_function) llvm_emit_function_body(gen_context, context->main_function); + if (unit->main_function) llvm_emit_function_body(gen_context, unit->main_function); - VECEACH(context->methods, i) + VECEACH(unit->methods, i) { - Decl *decl = context->methods[i]; + Decl *decl = unit->methods[i]; if (decl->func_decl.body) llvm_emit_function_body(gen_context, decl); } - gencontext_end_file_emit(gen_context, context); + gencontext_end_file_emit(gen_context, unit); } // EmitDeferred() diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 7e97b3990..30a3bf5e9 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4824,7 +4824,15 @@ static inline void llvm_emit_macro_block(GenContext *context, BEValue *be_value, llvm_emit_expr(context, &value, expr->macro_block.args[i]); llvm_store_aligned_decl(context, decl, llvm_value_rvalue_store(context, &value)); } - + if (expr->macro_block.no_scope) + { + VECEACH(expr->macro_block.stmts, i) + { + llvm_emit_stmt(context, expr->macro_block.stmts[i]); + } + llvm_value_set(be_value, NULL, type_void); + return; + } llvm_emit_return_block(context, be_value, expr->type, expr->macro_block.stmts); } diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 66c938d68..9031aa18a 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -475,6 +475,7 @@ void llvm_emit_function_body(GenContext *context, Decl *decl) } LLVMDisposeBuilder(context->builder); + context->builder = NULL; if (llvm_use_debug(context)) { diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 05c915269..04bff7e58 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -191,8 +191,8 @@ extern LLVMAttributes attribute_id; // LLVM Attributes void gencontext_begin_module(GenContext *c); -void gencontext_init_file_emit(GenContext *c, Context *ast); -void gencontext_end_file_emit(GenContext *c, Context *ast); +void gencontext_init_file_emit(GenContext *c, CompilationUnit *unit); +void gencontext_end_file_emit(GenContext *c, CompilationUnit *ast); void gencontext_end_module(GenContext *context); LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal); diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c index 369a021e1..0dd3224b2 100644 --- a/src/compiler/llvm_codegen_module.c +++ b/src/compiler/llvm_codegen_module.c @@ -78,18 +78,18 @@ void gencontext_begin_module(GenContext *c) } } -void gencontext_init_file_emit(GenContext *c, Context *ast) +void gencontext_init_file_emit(GenContext *c, CompilationUnit *unit) { if (active_target.debug_info != DEBUG_INFO_NONE) { - const char *filename = ast->file->name; - const char *dir_path = ast->file->dir_path; + const char *filename = unit->file->name; + const char *dir_path = unit->file->dir_path; // Set runtime version here. - ast->llvm_debug_file = LLVMDIBuilderCreateFile(c->debug.builder, - filename, - strlen(filename), - dir_path, - strlen(dir_path)); + unit->llvm.debug_file = LLVMDIBuilderCreateFile(c->debug.builder, + filename, + strlen(filename), + dir_path, + strlen(dir_path)); bool is_optimized = active_target.optimization_level != OPTIMIZATION_NONE; const char *dwarf_flags = ""; @@ -102,34 +102,34 @@ void gencontext_init_file_emit(GenContext *c, Context *ast) const char *sysroot = ""; const char *sdk = ""; unsigned dwo_id = 0; - ast->llvm_debug_compile_unit = LLVMDIBuilderCreateCompileUnit(c->debug.builder, - LLVMDWARFSourceLanguageC, - ast->llvm_debug_file, - DWARF_PRODUCER_NAME, - strlen(DWARF_PRODUCER_NAME), - is_optimized, - dwarf_flags, - strlen(dwarf_flags), - runtime_version, - debug_output_file, - strlen(debug_output_file), - emission_kind, - dwo_id, - split_debug_inlining, - emit_debug_info_for_profiling + unit->llvm.debug_compile_unit = LLVMDIBuilderCreateCompileUnit(c->debug.builder, + LLVMDWARFSourceLanguageC, + unit->llvm.debug_file, + DWARF_PRODUCER_NAME, + strlen(DWARF_PRODUCER_NAME), + is_optimized, + dwarf_flags, + strlen(dwarf_flags), + runtime_version, + debug_output_file, + strlen(debug_output_file), + emission_kind, + dwo_id, + split_debug_inlining, + emit_debug_info_for_profiling #if LLVM_VERSION_MAJOR >= 11 , - sysroot, - strlen(sysroot), - sdk, - strlen(sdk) + sysroot, + strlen(sysroot), + sdk, + strlen(sdk) #endif - ); + ); } } -void gencontext_end_file_emit(GenContext *c, Context *ast) +void gencontext_end_file_emit(GenContext *c, CompilationUnit *ast) { } diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index ec04b0369..e08eb5b4d 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -177,8 +177,6 @@ void llvm_emit_jmp(GenContext *context, LLVMBasicBlockRef block) static inline void gencontext_emit_return(GenContext *c, Ast *ast) { - // Ensure we are on a branch that is non empty. - if (!llvm_emit_check_block_branch(c)) return; bool in_expression_block = c->in_block > 0; @@ -239,7 +237,7 @@ static inline void gencontext_emit_return(GenContext *c, Ast *ast) llvm_emit_return_abi(c, NULL, &value); c->current_block = NULL; } - LLVMBasicBlockRef post_ret_block = llvm_basic_block_new(c, "ret"); + LLVMBasicBlockRef post_ret_block = llvm_basic_block_new(c, "postreturn"); llvm_emit_block(c, post_ret_block); } diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index ade3e8635..382a0d01b 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -6,8 +6,8 @@ #include "parser_internal.h" -typedef Expr *(*ParseFn)(Context *context, Expr *); -static Expr *parse_rethrow_expr(Context *context, Expr *left); +typedef Expr *(*ParseFn)(ParseContext *context, Expr *); +static Expr *parse_rethrow_expr(ParseContext *context, Expr *left); typedef struct { @@ -19,15 +19,15 @@ typedef struct extern ParseRule rules[TOKEN_EOF + 1]; -inline Expr *parse_precedence_with_left_side(Context *context, Expr *left_side, Precedence precedence) +inline Expr *parse_precedence_with_left_side(ParseContext *context, Expr *left_side, Precedence precedence) { while (1) { - Precedence token_precedence = rules[context->lex.tok.type].precedence; + Precedence token_precedence = rules[context->tok.type].precedence; bool special_question = false; - if (context->lex.tok.type == TOKEN_QUESTION) + if (context->tok.type == TOKEN_QUESTION) { - ParseRule rule = rules[context->lex.next_tok.type]; + ParseRule rule = rules[context->next_tok.type]; if (!rule.prefix) { token_precedence = PREC_CALL; @@ -36,10 +36,10 @@ inline Expr *parse_precedence_with_left_side(Context *context, Expr *left_side, } if (precedence > token_precedence) break; if (!expr_ok(left_side)) return left_side; - ParseFn infix_rule = special_question ? &parse_rethrow_expr : rules[context->lex.tok.type].infix; + ParseFn infix_rule = special_question ? &parse_rethrow_expr : rules[context->tok.type].infix; if (!infix_rule) { - SEMA_TOKEN_ERROR(context->lex.tok, "An expression was expected."); + SEMA_TOKEN_ERROR(context->tok, "An expression was expected."); return poisoned_expr; } left_side = infix_rule(context, left_side); @@ -48,13 +48,13 @@ inline Expr *parse_precedence_with_left_side(Context *context, Expr *left_side, } -static Expr *parse_precedence(Context *context, Precedence precedence) +static Expr *parse_precedence(ParseContext *context, Precedence precedence) { // Get the rule for the previous token. - ParseFn prefix_rule = rules[context->lex.tok.type].prefix; + ParseFn prefix_rule = rules[context->tok.type].prefix; if (prefix_rule == NULL) { - SEMA_TOKEN_ERROR(context->lex.tok, "An expression was expected."); + SEMA_TOKEN_ERROR(context->tok, "An expression was expected."); return poisoned_expr; } @@ -63,22 +63,22 @@ static Expr *parse_precedence(Context *context, Precedence precedence) return parse_precedence_with_left_side(context, left_side, precedence); } -Expr *parse_expr_or_initializer_list(Context *context) +Expr *parse_expr_or_initializer_list(ParseContext *context) { return parse_expr(context); } -static inline bool next_is_try_unwrap(Context *context) +static inline bool next_is_try_unwrap(ParseContext *context) { - return tok_is(context, TOKEN_TRY) && context->lex.next_tok.type != TOKEN_LPAREN; + return tok_is(context, TOKEN_TRY) && context->next_tok.type != TOKEN_LPAREN; } -static inline bool next_is_catch_unwrap(Context *context) +static inline bool next_is_catch_unwrap(ParseContext *context) { - return tok_is(context, TOKEN_CATCH) && context->lex.next_tok.type != TOKEN_LPAREN; + return tok_is(context, TOKEN_CATCH) && context->next_tok.type != TOKEN_LPAREN; } -static inline Expr *parse_for_try_expr(Context *context) +static inline Expr *parse_for_try_expr(ParseContext *context) { return parse_precedence(context, PREC_AND + 1); } @@ -86,10 +86,10 @@ static inline Expr *parse_for_try_expr(Context *context) /** * catch_unwrap ::= CATCH IDENT | (type? IDENT '=' (expr | '(' expr (',' expr) ')')) */ -static inline Expr *parse_catch_unwrap(Context *context) +static inline Expr *parse_catch_unwrap(ParseContext *context) { advance_and_verify(context, TOKEN_CATCH); - Expr *expr = expr_new(EXPR_CATCH_UNWRAP, source_span_from_token_id(context->lex.prev_tok)); + Expr *expr = expr_new(EXPR_CATCH_UNWRAP, source_span_from_token_id(context->prev_tok)); if (parse_next_is_decl(context)) { ASSIGN_TYPE_ELSE(expr->catch_unwrap_expr.type, parse_type(context), poisoned_expr); @@ -103,7 +103,7 @@ static inline Expr *parse_catch_unwrap(Context *context) { if (expr->catch_unwrap_expr.type) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a '=' here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a '=' here."); return poisoned_expr; } vec_add(expr->catch_unwrap_expr.exprs, expr->catch_unwrap_expr.variable); @@ -132,9 +132,9 @@ static inline Expr *parse_catch_unwrap(Context *context) /** * try_unwrap ::= TRY (IDENT | type? IDENT '=' non_and_expr) */ -static inline Expr *parse_try_unwrap(Context *context) +static inline Expr *parse_try_unwrap(ParseContext *context) { - Expr *expr = EXPR_NEW_TOKEN(EXPR_TRY_UNWRAP, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_TRY_UNWRAP, context->tok); advance_and_verify(context, TOKEN_TRY); if (parse_next_is_decl(context)) { @@ -158,7 +158,7 @@ static inline Expr *parse_try_unwrap(Context *context) * try_unwrap_chain ::= try_unwrap ('&&' (try_unwrap | non_and_expr))* * try_unwrap ::= TRY (IDENT | type? IDENT '=' non_and_expr) */ -static inline Expr *parse_try_unwrap_chain(Context *context) +static inline Expr *parse_try_unwrap_chain(ParseContext *context) { Expr **unwraps = NULL; ASSIGN_EXPR_ELSE(Expr *first_unwrap , parse_try_unwrap(context), poisoned_expr); @@ -180,7 +180,7 @@ static inline Expr *parse_try_unwrap_chain(Context *context) return try_unwrap_chain; } -Expr *parse_assert_expr(Context *context) +Expr *parse_assert_expr(ParseContext *context) { if (next_is_try_unwrap(context)) { @@ -194,9 +194,9 @@ Expr *parse_assert_expr(Context *context) * * @return bool */ -Expr *parse_cond(Context *context) +Expr *parse_cond(ParseContext *context) { - Expr *decl_expr = EXPR_NEW_TOKEN(EXPR_COND, context->lex.tok); + Expr *decl_expr = EXPR_NEW_TOKEN(EXPR_COND, context->tok); decl_expr->cond_expr = NULL; while (1) { @@ -242,12 +242,12 @@ Expr *parse_cond(Context *context) // These used to be explicitly inlined, but that seems to lead to confusing MSVC linker errors. // They are probably still inlined by the compiler, though I haven't checked. -Expr* parse_expr(Context *context) +Expr* parse_expr(ParseContext *context) { return parse_precedence(context, PREC_ASSIGNMENT); } -Expr* parse_constant_expr(Context *context) +Expr* parse_constant_expr(ParseContext *context) { return parse_precedence(context, PREC_TERNARY); } @@ -259,7 +259,7 @@ Expr* parse_constant_expr(Context *context) * @param path reference to the path to return * @return true if parsing succeeds, false otherwise. */ -static bool parse_param_path(Context *context, DesignatorElement ***path) +static bool parse_param_path(ParseContext *context, DesignatorElement ***path) { *path = NULL; while (true) @@ -288,7 +288,7 @@ static bool parse_param_path(Context *context, DesignatorElement ***path) advance(context); DesignatorElement *element = CALLOCS(DesignatorElement); element->kind = DESIGNATOR_FIELD; - element->field = TOKSTR(context->lex.tok.id); + element->field = TOKSTR(context->tok.id); EXPECT_OR(TOKEN_IDENT, false); advance(context); vec_add(*path, element); @@ -302,7 +302,7 @@ static bool parse_param_path(Context *context, DesignatorElement ***path) * * parameter ::= (param_path '=')? expr */ -bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool *unsplat) +bool parse_arg_list(ParseContext *context, Expr ***result, TokenType param_end, bool *unsplat) { *result = NULL; if (unsplat) *unsplat = false; @@ -310,7 +310,7 @@ bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool { Expr *expr = NULL; DesignatorElement **path; - Token current = context->lex.tok; + Token current = context->tok; if (!parse_param_path(context, &path)) return false; if (path != NULL) { @@ -341,7 +341,7 @@ bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool if (TOKEN_IS(param_end)) return true; if (unsplat && *unsplat) { - SEMA_TOKEN_ERROR(context->lex.tok, "'...' is only allowed on the last argument in a call."); + SEMA_TOKEN_ERROR(context->tok, "'...' is only allowed on the last argument in a call."); return false; } } @@ -350,10 +350,10 @@ bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool /** * macro_expansion ::= '@' non_at_expression */ -static Expr *parse_macro_expansion(Context *context, Expr *left) +static Expr *parse_macro_expansion(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *macro_expression = EXPR_NEW_TOKEN(EXPR_MACRO_EXPANSION, context->lex.tok); + Expr *macro_expression = EXPR_NEW_TOKEN(EXPR_MACRO_EXPANSION, context->tok); advance_and_verify(context, TOKEN_AT); ASSIGN_EXPR_ELSE(Expr *inner, parse_precedence(context, PREC_MACRO), poisoned_expr); macro_expression->macro_expansion_expr.inner = inner; @@ -370,9 +370,9 @@ static Expr *parse_macro_expansion(Context *context, Expr *left) * ; * @return Ast * */ -Expr *parse_expression_list(Context *context, bool allow_decl) +Expr *parse_expression_list(ParseContext *context, bool allow_decl) { - Expr *expr_list = EXPR_NEW_TOKEN(EXPR_EXPRESSION_LIST, context->lex.tok); + Expr *expr_list = EXPR_NEW_TOKEN(EXPR_EXPRESSION_LIST, context->tok); while (1) { Expr *expr; @@ -381,7 +381,7 @@ Expr *parse_expression_list(Context *context, bool allow_decl) ASSIGN_DECL_ELSE(Decl *decl, parse_decl(context), poisoned_expr); if (!allow_decl) { - SEMA_TOKEN_ERROR(context->lex.tok, "This looks like a declaration, which isn't allowed here."); + SEMA_TOKEN_ERROR(context->tok, "This looks like a declaration, which isn't allowed here."); return poisoned_expr; } expr = expr_new(EXPR_DECL, decl->span); @@ -401,16 +401,16 @@ Expr *parse_expression_list(Context *context, bool allow_decl) * @param left must be null. * @return Expr* */ -static Expr *parse_type_identifier(Context *context, Expr *left) +static Expr *parse_type_identifier(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); return parse_type_expression_with_path(context, NULL); } -static Expr *parse_typeof_expr(Context *context, Expr *left) +static Expr *parse_typeof_expr(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_TYPEINFO, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_TYPEINFO, context->tok); ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), poisoned_expr); expr->span = type->span; expr->type_expr = type; @@ -418,13 +418,13 @@ static Expr *parse_typeof_expr(Context *context, Expr *left) } -static Expr *parse_unary_expr(Context *context, Expr *left) +static Expr *parse_unary_expr(ParseContext *context, Expr *left) { assert(!left && "Did not expect a left hand side!"); - TokenType operator_type = context->lex.tok.type; + TokenType operator_type = context->tok.type; - Expr *unary = EXPR_NEW_TOKEN(EXPR_UNARY, context->lex.tok); + Expr *unary = EXPR_NEW_TOKEN(EXPR_UNARY, context->tok); unary->unary_expr.operator = unaryop_from_token(operator_type); advance(context); Expr *right_side = parse_precedence(context, PREC_UNARY); @@ -436,12 +436,12 @@ static Expr *parse_unary_expr(Context *context, Expr *left) return unary; } -static Expr *parse_post_unary(Context *context, Expr *left) +static Expr *parse_post_unary(ParseContext *context, Expr *left) { assert(expr_ok(left)); - Expr *unary = EXPR_NEW_TOKEN(EXPR_POST_UNARY, context->lex.tok); + Expr *unary = EXPR_NEW_TOKEN(EXPR_POST_UNARY, context->tok); unary->unary_expr.expr = left; - unary->unary_expr.operator = unaryop_from_token(context->lex.tok.type); + unary->unary_expr.operator = unaryop_from_token(context->tok.type); unary->span.loc = left->span.loc; advance(context); return unary; @@ -450,7 +450,7 @@ static Expr *parse_post_unary(Context *context, Expr *left) -static Expr *parse_ternary_expr(Context *context, Expr *left_side) +static Expr *parse_ternary_expr(ParseContext *context, Expr *left_side) { assert(expr_ok(left_side)); @@ -482,10 +482,10 @@ static Expr *parse_ternary_expr(Context *context, Expr *left_side) * : '(' expression ')' ('(' expression ')')? * ; */ -static Expr *parse_grouping_expr(Context *context, Expr *left) +static Expr *parse_grouping_expr(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_GROUP, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_GROUP, context->tok); advance_and_verify(context, TOKEN_LPAREN); ASSIGN_EXPR_ELSE(expr->inner_expr, parse_expr(context), poisoned_expr); CONSUME_OR(TOKEN_RPAREN, poisoned_expr); @@ -494,7 +494,7 @@ static Expr *parse_grouping_expr(Context *context, Expr *left) TypeInfo *info = expr->inner_expr->type_expr; if (TOKEN_IS(TOKEN_LBRACE) && info->resolve_status != RESOLVE_DONE) { - SEMA_TOKEN_ERROR(context->lex.tok, "Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type."); + SEMA_TOKEN_ERROR(context->tok, "Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type."); return poisoned_expr; } ASSIGN_EXPR_ELSE(Expr *cast_expr, parse_expr(context), poisoned_expr); @@ -517,11 +517,11 @@ static Expr *parse_grouping_expr(Context *context, Expr *left) * @param context * @return the parsed expression */ -Expr *parse_initializer(Context *context) +Expr *parse_initializer(ParseContext *context) { if (TOKEN_IS(TOKEN_VOID)) { - Expr *expr = EXPR_NEW_TOKEN(EXPR_UNDEF, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_UNDEF, context->tok); expr->type = type_void; expr->resolve_status = RESOLVE_DONE; advance(context); @@ -544,10 +544,10 @@ Expr *parse_initializer(Context *context) * @param elements * @return */ -Expr *parse_initializer_list(Context *context, Expr *left) +Expr *parse_initializer_list(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST, context->lex.tok); + Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST, context->tok); advance_and_verify(context, TOKEN_LBRACE); if (!try_consume(context, TOKEN_RBRACE)) { @@ -590,7 +590,7 @@ Expr *parse_initializer_list(Context *context, Expr *left) return initializer_list; } -static Expr *parse_failable(Context *context, Expr *left_side) +static Expr *parse_failable(ParseContext *context, Expr *left_side) { Expr *failable = expr_new(EXPR_FAILABLE, left_side->span); advance_and_verify(context, TOKEN_BANG); @@ -601,12 +601,12 @@ static Expr *parse_failable(Context *context, Expr *left_side) -static Expr *parse_binary(Context *context, Expr *left_side) +static Expr *parse_binary(ParseContext *context, Expr *left_side) { assert(left_side && expr_ok(left_side)); // Remember the operator. - TokenType operator_type = context->lex.tok.type; + TokenType operator_type = context->tok.type; advance(context); @@ -630,7 +630,7 @@ static Expr *parse_binary(Context *context, Expr *left_side) return expr; } -static Expr *parse_call_expr(Context *context, Expr *left) +static Expr *parse_call_expr(ParseContext *context, Expr *left) { assert(left && expr_ok(left)); @@ -650,7 +650,7 @@ static Expr *parse_call_expr(Context *context, Expr *left) } if (!TOKEN_IS(TOKEN_RPAREN)) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Expected the ending ')' here."); + SEMA_TOKID_ERROR(context->prev_tok, "Expected the ending ')' here."); return poisoned_expr; } advance(context); @@ -663,7 +663,7 @@ static Expr *parse_call_expr(Context *context, Expr *left) RANGE_EXTEND_PREV(call); if (body_args && !TOKEN_IS(TOKEN_LBRACE)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a macro body here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a macro body here."); return poisoned_expr; } if (TOKEN_IS(TOKEN_LBRACE)) @@ -676,7 +676,7 @@ static Expr *parse_call_expr(Context *context, Expr *left) -static Expr *parse_subscript_expr(Context *context, Expr *left) +static Expr *parse_subscript_expr(ParseContext *context, Expr *left) { assert(left && expr_ok(left)); advance_and_verify(context, TOKEN_LBRACKET); @@ -697,7 +697,7 @@ static Expr *parse_subscript_expr(Context *context, Expr *left) } else { - index = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); + index = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); index->type = type_uint; index->resolve_status = RESOLVE_DONE; expr_const_set_int(&index->const_expr, 0, type_uint->type_kind); @@ -733,7 +733,7 @@ static Expr *parse_subscript_expr(Context *context, Expr *left) } -static Expr *parse_access_expr(Context *context, Expr *left) +static Expr *parse_access_expr(ParseContext *context, Expr *left) { assert(left && expr_ok(left)); advance_and_verify(context, TOKEN_DOT); @@ -746,39 +746,39 @@ static Expr *parse_access_expr(Context *context, Expr *left) -static Expr *parse_ct_ident(Context *context, Expr *left) +static Expr *parse_ct_ident(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); if (try_consume(context, TOKEN_CT_CONST_IDENT)) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Compile time identifiers may not be constants."); + SEMA_TOKID_ERROR(context->prev_tok, "Compile time identifiers may not be constants."); return poisoned_expr; } - Expr *expr = EXPR_NEW_TOKEN(EXPR_CT_IDENT, context->lex.tok); - expr->ct_ident_expr.identifier = context->lex.tok.id; + Expr *expr = EXPR_NEW_TOKEN(EXPR_CT_IDENT, context->tok); + expr->ct_ident_expr.identifier = context->tok.id; advance(context); return expr; } -static Expr *parse_hash_ident(Context *context, Expr *left) +static Expr *parse_hash_ident(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_HASH_IDENT, context->lex.tok); - expr->ct_ident_expr.identifier = context->lex.tok.id; + Expr *expr = EXPR_NEW_TOKEN(EXPR_HASH_IDENT, context->tok); + expr->ct_ident_expr.identifier = context->tok.id; advance(context); return expr; } -static Expr *parse_ct_call(Context *context, Expr *left) +static Expr *parse_ct_call(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_CT_CALL, context->lex.tok); - expr->ct_call_expr.token_type = context->lex.tok.type; + Expr *expr = EXPR_NEW_TOKEN(EXPR_CT_CALL, context->tok); + expr->ct_call_expr.token_type = context->tok.type; advance(context); CONSUME_OR(TOKEN_LPAREN, poisoned_expr); ASSIGN_EXPR_ELSE(Expr *internal, parse_precedence(context, PREC_FIRST + 1), poisoned_expr); ExprFlatElement *flat_path = NULL; - if (context->lex.tok.type == TOKEN_DOT || context->lex.tok.type == TOKEN_LBRACKET) + if (context->tok.type == TOKEN_DOT || context->tok.type == TOKEN_LBRACKET) { while (1) { @@ -788,7 +788,7 @@ static Expr *parse_ct_call(Context *context, Expr *left) ASSIGN_EXPR_ELSE(Expr *int_expr, parse_expr(context), poisoned_expr); if (int_expr->expr_kind != EXPR_CONST || int_expr->const_expr.const_kind != CONST_INTEGER) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected an integer index."); + SEMA_TOKEN_ERROR(context->tok, "Expected an integer index."); return poisoned_expr; } Int value = int_expr->const_expr.ixx; @@ -810,11 +810,11 @@ static Expr *parse_ct_call(Context *context, Expr *left) { TRY_CONSUME_OR(TOKEN_IDENT, "Expected an identifier here.", poisoned_expr); flat_element.array = false; - flat_element.ident = TOKSTR(context->lex.prev_tok); + flat_element.ident = TOKSTR(context->prev_tok); } else { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected '.' or '[' here."); + SEMA_TOKEN_ERROR(context->tok, "Expected '.' or '[' here."); return poisoned_expr; } vec_add(flat_path, flat_element); @@ -829,23 +829,23 @@ static Expr *parse_ct_call(Context *context, Expr *left) return expr; } -static Expr *parse_identifier(Context *context, Expr *left) +static Expr *parse_identifier(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(context->lex.tok.type == TOKEN_CONST_IDENT ? EXPR_CONST_IDENTIFIER : EXPR_IDENTIFIER , context->lex.tok); - expr->identifier_expr.identifier = context->lex.tok.id; + Expr *expr = EXPR_NEW_TOKEN(context->tok.type == TOKEN_CONST_IDENT ? EXPR_CONST_IDENTIFIER : EXPR_IDENTIFIER , context->tok); + expr->identifier_expr.identifier = context->tok.id; advance(context); return expr; } -static Expr *parse_identifier_starting_expression(Context *context, Expr *left) +static Expr *parse_identifier_starting_expression(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); bool had_error; Path *path = parse_path_prefix(context, &had_error); if (had_error) return poisoned_expr; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_IDENT: case TOKEN_CONST_IDENT: @@ -857,19 +857,19 @@ static Expr *parse_identifier_starting_expression(Context *context, Expr *left) case TOKEN_TYPE_IDENT: return parse_type_expression_with_path(context, path); default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a type, function or constant."); + SEMA_TOKEN_ERROR(context->tok, "Expected a type, function or constant."); return poisoned_expr; } } -static Expr *parse_try_expr(Context *context, Expr *left) +static Expr *parse_try_expr(ParseContext *context, Expr *left) { assert(!left && "Unexpected left hand side"); bool is_try = TOKEN_IS(TOKEN_TRY); advance(context); - Expr *try_expr = expr_new(is_try ? EXPR_TRY : EXPR_CATCH, source_span_from_token_id(context->lex.prev_tok)); + Expr *try_expr = expr_new(is_try ? EXPR_TRY : EXPR_CATCH, source_span_from_token_id(context->prev_tok)); if (!try_consume(context, TOKEN_LPAREN)) { if (is_try) @@ -889,7 +889,7 @@ static Expr *parse_try_expr(Context *context, Expr *left) return try_expr; } -static Expr *parse_rethrow_expr(Context *context, Expr *left) +static Expr *parse_rethrow_expr(ParseContext *context, Expr *left) { Expr *rethrow_expr = EXPR_NEW_EXPR(EXPR_RETHROW, left); advance(context); @@ -898,7 +898,7 @@ static Expr *parse_rethrow_expr(Context *context, Expr *left) return rethrow_expr; } -static Expr *parse_force_unwrap_expr(Context *context, Expr *left) +static Expr *parse_force_unwrap_expr(ParseContext *context, Expr *left) { Expr *force_unwrap_expr = EXPR_NEW_EXPR(EXPR_FORCE_UNWRAP, left); advance(context); @@ -907,12 +907,12 @@ static Expr *parse_force_unwrap_expr(Context *context, Expr *left) return force_unwrap_expr; } -static Expr *parse_or_error_expr(Context *context, Expr *left) +static Expr *parse_or_error_expr(ParseContext *context, Expr *left) { - Expr *else_expr = EXPR_NEW_TOKEN(EXPR_OR_ERROR, context->lex.tok); + Expr *else_expr = EXPR_NEW_TOKEN(EXPR_OR_ERROR, context->tok); advance_and_verify(context, TOKEN_QUESTQUEST); else_expr->or_error_expr.expr = left; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_RETURN: case TOKEN_BREAK: @@ -938,17 +938,17 @@ static Expr *parse_or_error_expr(Context *context, Expr *left) return else_expr; } -static Expr *parse_builtin(Context *context, Expr *left) +static Expr *parse_builtin(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_BUILTIN, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_BUILTIN, context->tok); advance_and_verify(context, TOKEN_BUILTIN); - expr->builtin_expr.identifier = context->lex.tok; + expr->builtin_expr.identifier = context->tok; CONSUME_OR(TOKEN_IDENT, poisoned_expr); RANGE_EXTEND_PREV(expr); return expr; } -static Expr *parse_placeholder(Context *context, Expr *left) +static Expr *parse_placeholder(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); advance_and_verify(context, TOKEN_PLACEHOLDER); @@ -981,12 +981,12 @@ static int read_num_type(const char *string, size_t loc, size_t len) return i; } -static Expr *parse_integer(Context *context, Expr *left) +static Expr *parse_integer(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *expr_int = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); - size_t len = TOKLEN(context->lex.tok); - const char *string = TOKSTR(context->lex.tok); + Expr *expr_int = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); + size_t len = TOKLEN(context->tok); + const char *string = TOKSTR(context->tok); Int128 i = { 0, 0 }; bool is_unsigned = false; int type_bits = 0; @@ -1092,7 +1092,7 @@ static Expr *parse_integer(Context *context, Expr *left) } if (wrapped) { - SEMA_TOKEN_ERROR(context->lex.tok, "Integer size exceeded 128 bits, max 128 bits are supported."); + SEMA_TOKEN_ERROR(context->tok, "Integer size exceeded 128 bits, max 128 bits are supported."); return poisoned_expr; } expr_int->const_expr.const_kind = CONST_INTEGER; @@ -1103,7 +1103,7 @@ static Expr *parse_integer(Context *context, Expr *left) { if (type_bits < 0 || !is_power_of_two((uint64_t)type_bits) || type_bits > 128) { - SEMA_TOKEN_ERROR(context->lex.tok, "Integer type suffix should be i8, i16, i32, i64 or i128."); + SEMA_TOKEN_ERROR(context->tok, "Integer type suffix should be i8, i16, i32, i64 or i128."); return poisoned_expr; } } @@ -1114,7 +1114,7 @@ static Expr *parse_integer(Context *context, Expr *left) type_bits = 4 * hex_characters; if (type_bits > 128) { - SEMA_TOKEN_ERROR(context->lex.tok, "%d hex digits indicates a bit width over 128, which is not supported.", hex_characters); + SEMA_TOKEN_ERROR(context->tok, "%d hex digits indicates a bit width over 128, which is not supported.", hex_characters); return poisoned_expr; } } @@ -1123,7 +1123,7 @@ static Expr *parse_integer(Context *context, Expr *left) type_bits = 3 * oct_characters; if (type_bits > 128) { - SEMA_TOKEN_ERROR(context->lex.tok, "%d octal digits indicates a bit width over 128, which is not supported.", oct_characters); + SEMA_TOKEN_ERROR(context->tok, "%d octal digits indicates a bit width over 128, which is not supported.", oct_characters); return poisoned_expr; } } @@ -1132,7 +1132,7 @@ static Expr *parse_integer(Context *context, Expr *left) type_bits = binary_characters; if (type_bits > 128) { - SEMA_TOKEN_ERROR(context->lex.tok, "%d binary digits indicates a bit width over 128, which is not supported.", binary_characters); + SEMA_TOKEN_ERROR(context->tok, "%d binary digits indicates a bit width over 128, which is not supported.", binary_characters); return poisoned_expr; } } @@ -1157,12 +1157,12 @@ static Expr *parse_integer(Context *context, Expr *left) if (binary_characters) radix = 2; if (type_bits) { - SEMA_TOKEN_ERROR(context->lex.tok, "'%s' does not fit in a '%c%d' literal.", + SEMA_TOKEN_ERROR(context->tok, "'%s' does not fit in a '%c%d' literal.", i128_to_string(i, radix, true), is_unsigned ? 'u' : 'i', type_bits); } else { - SEMA_TOKEN_ERROR(context->lex.tok, "'%s' does not fit in an %s literal.", + SEMA_TOKEN_ERROR(context->tok, "'%s' does not fit in an %s literal.", i128_to_string(i, radix, true), is_unsigned ? "unsigned int" : "int"); } return poisoned_expr; @@ -1237,10 +1237,10 @@ static void parse_base64(char **result_pointer, char *result_pointer_end, const *result_pointer = data_current; } -static Expr *parse_bytes_expr(Context *context, Expr *left) +static Expr *parse_bytes_expr(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - TokenId tok = context->lex.tok.id; + TokenId tok = context->tok.id; ArraySize len = 0; while (TOKTYPE(tok) == TOKEN_BYTES) { @@ -1250,11 +1250,11 @@ static Expr *parse_bytes_expr(Context *context, Expr *left) char *data = len > 0 ? MALLOC(len) : NULL; char *data_current = data; - Expr *expr_bytes = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); - while (context->lex.tok.type == TOKEN_BYTES) + Expr *expr_bytes = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); + while (context->tok.type == TOKEN_BYTES) { - TokenData *token_data = tokendata_from_token(context->lex.tok); - SourceLocation *loc = TOKLOC(context->lex.tok); + TokenData *token_data = tokendata_from_token(context->tok); + SourceLocation *loc = TOKLOC(context->tok); File *file = source_file_by_id(loc->file_id); if (token_data->is_base64) { @@ -1279,12 +1279,12 @@ static Expr *parse_bytes_expr(Context *context, Expr *left) return expr_bytes; } -static Expr *parse_char_lit(Context *context, Expr *left) +static Expr *parse_char_lit(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *expr_int = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); + Expr *expr_int = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); expr_int->const_expr.is_character = true; - TokenData *data = tokendata_from_id(context->lex.tok.id); + TokenData *data = tokendata_from_id(context->tok.id); expr_int->const_expr.ixx.i = data->char_value; expr_int->const_expr.narrowable = true; expr_int->const_expr.const_kind = CONST_INTEGER; @@ -1320,17 +1320,17 @@ static Expr *parse_char_lit(Context *context, Expr *left) } -static Expr *parse_double(Context *context, Expr *left) +static Expr *parse_double(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); char *err; - Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); - const char *original = TOKSTR(context->lex.tok); + Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); + const char *original = TOKSTR(context->tok); bool is_hex = original[0] == '0' && original[1] == 'x'; Float f = is_hex ? float_from_hex(original, &err) : float_from_string(original, &err); if (f.type == TYPE_POISONED) { - SEMA_TOKEN_ERROR(context->lex.tok, err); + SEMA_TOKEN_ERROR(context->tok, err); return poisoned_expr; } number->const_expr.fxx = f; @@ -1430,12 +1430,12 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src return scanned; } -static Expr *parse_string_literal(Context *context, Expr *left) +static Expr *parse_string_literal(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); + Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); - TokenData *data = TOKDATA(context->lex.tok); + TokenData *data = TOKDATA(context->tok); const char *str = data->string; size_t len = data->strlen; advance_and_verify(context, TOKEN_STRING); @@ -1444,7 +1444,7 @@ static Expr *parse_string_literal(Context *context, Expr *left) // and can be optimized. while (TOKEN_IS(TOKEN_STRING)) { - data = TOKDATA(context->lex.tok); + data = TOKDATA(context->tok); char *buffer = malloc_string(len + data->strlen + 1); memcpy(buffer, str, len); memcpy(buffer + len, data->string, data->strlen); @@ -1456,7 +1456,7 @@ static Expr *parse_string_literal(Context *context, Expr *left) if (len > UINT32_MAX) { - SEMA_TOKEN_ERROR(context->lex.tok, "String exceeded max size."); + SEMA_TOKEN_ERROR(context->tok, "String exceeded max size."); return poisoned_expr; } assert(str); @@ -1467,27 +1467,27 @@ static Expr *parse_string_literal(Context *context, Expr *left) return expr_string; } -static Expr *parse_bool(Context *context, Expr *left) +static Expr *parse_bool(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); + Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); number->const_expr = (ExprConst) { .b = TOKEN_IS(TOKEN_TRUE), .const_kind = CONST_BOOL }; number->type = type_bool; advance(context); return number; } -static Expr *parse_null(Context *context, Expr *left) +static Expr *parse_null(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok); + Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); number->const_expr.const_kind = CONST_POINTER; number->type = type_voidptr; advance(context); return number; } -Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *type_info) +Expr *parse_type_compound_literal_expr_after_type(ParseContext *context, TypeInfo *type_info) { Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type_info->span); expr->expr_compound_literal.type_info = type_info; @@ -1505,14 +1505,14 @@ Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *ty * @param left must be null. * @return Expr* */ -Expr *parse_type_expression_with_path(Context *context, Path *path) +Expr *parse_type_expression_with_path(ParseContext *context, Path *path) { TypeInfo *type; if (path) { type = type_info_new(TYPE_INFO_IDENTIFIER, path->span); type->unresolved.path = path; - type->unresolved.name_loc = context->lex.tok.id; + type->unresolved.name_loc = context->tok.id; advance_and_verify(context, TOKEN_TYPE_IDENT); RANGE_EXTEND_PREV(type); ASSIGN_TYPE_ELSE(type, parse_type_with_base(context, type), poisoned_expr); @@ -1538,10 +1538,10 @@ Expr *parse_type_expression_with_path(Context *context, Path *path) * function_block * : '{|' stmt_list '|}' */ -static Expr* parse_expr_block(Context *context, Expr *left) +static Expr* parse_expr_block(ParseContext *context, Expr *left) { assert(!left && "Had left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_EXPR_BLOCK, context->lex.tok); + Expr *expr = EXPR_NEW_TOKEN(EXPR_EXPR_BLOCK, context->tok); advance_and_verify(context, TOKEN_LBRAPIPE); while (!try_consume(context, TOKEN_RBRAPIPE)) { diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 2ae7d3209..48c29657f 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1,13 +1,13 @@ #include "compiler_internal.h" #include "parser_internal.h" -static Decl *parse_const_declaration(Context *context, Visibility visibility); -static inline Decl *parse_func_definition(Context *context, Visibility visibility, bool is_interface); -static inline bool parse_bitstruct_body(Context *context, Decl *decl); +static Decl *parse_const_declaration(ParseContext *context, Visibility visibility); +static inline Decl *parse_func_definition(ParseContext *context, Visibility visibility, bool is_interface); +static inline bool parse_bitstruct_body(ParseContext *context, Decl *decl); -static bool context_next_is_path_prefix_start(Context *context) +static bool context_next_is_path_prefix_start(ParseContext *context) { - return context->lex.tok.type == TOKEN_IDENT && context->lex.next_tok.type == TOKEN_SCOPE; + return context->tok.type == TOKEN_IDENT && context->next_tok.type == TOKEN_SCOPE; } /** @@ -15,12 +15,12 @@ static bool context_next_is_path_prefix_start(Context *context) * * @return true if there is a type at the end. */ -static bool context_next_is_type_with_path_prefix(Context *context) +static bool context_next_is_type_with_path_prefix(ParseContext *context) { // We assume it's called after "foo::" parsing. if (!context_next_is_path_prefix_start(context)) return false; - TokenId current = context->lex.next_tok.id; + TokenId current = context->next_tok.id; while (1) { TokenType tok; @@ -45,14 +45,14 @@ static bool context_next_is_type_with_path_prefix(Context *context) } } -static bool context_next_is_type_and_not_ident(Context *context) +static bool context_next_is_type_and_not_ident(ParseContext *context) { - if (context->lex.tok.type == TOKEN_IDENT) + if (context->tok.type == TOKEN_IDENT) { - if (context->lex.next_tok.type != TOKEN_SCOPE) return false; + if (context->next_tok.type != TOKEN_SCOPE) return false; return context_next_is_type_with_path_prefix(context); } - return token_is_any_type(context->lex.tok.type); + return token_is_any_type(context->tok.type); } @@ -65,12 +65,12 @@ static bool context_next_is_type_and_not_ident(Context *context) * doc comment start, asm, typeof, TYPE_IDENT, const, IDENT * - are sync points only if they appear in the first column. */ -void recover_top_level(Context *context) +void recover_top_level(ParseContext *context) { advance(context); while (!TOKEN_IS(TOKEN_EOF)) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_PRIVATE: case TOKEN_IMPORT: @@ -96,7 +96,7 @@ void recover_top_level(Context *context) case TOKEN_BITSTRUCT: case TYPELIKE_TOKENS: // Only recover if this is in the first col. - if (TOKLOC(context->lex.tok)->col == 1) return; + if (TOKLOC(context->tok)->col == 1) return; advance(context); break; default: @@ -108,7 +108,7 @@ void recover_top_level(Context *context) // --- Parse CT conditional code -static inline bool parse_top_level_block(Context *context, Decl ***decls, TokenType end1, TokenType end2, TokenType end3) +static inline bool parse_top_level_block(ParseContext *context, Decl ***decls, TokenType end1, TokenType end2, TokenType end3) { CONSUME_OR(TOKEN_COLON, false); while (!TOKEN_IS(end1) && !TOKEN_IS(end2) && !TOKEN_IS(end3) && !TOKEN_IS(TOKEN_EOF)) @@ -135,10 +135,10 @@ static inline bool parse_top_level_block(Context *context, Decl ***decls, TokenT * @param context * @return the declaration if successfully parsed, poisoned_decl otherwise. */ -static inline Decl *parse_ct_if_top_level(Context *context) +static inline Decl *parse_ct_if_top_level(ParseContext *context) { advance_and_verify(context, TOKEN_CT_IF); - Decl *ct = decl_new_ct(DECL_CT_IF, context->lex.prev_tok); + Decl *ct = decl_new_ct(DECL_CT_IF, context->prev_tok); ASSIGN_EXPR_ELSE(ct->ct_if_decl.expr, parse_const_paren_expr(context), poisoned_decl); if (!parse_top_level_block(context, &ct->ct_if_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl; @@ -147,7 +147,7 @@ static inline Decl *parse_ct_if_top_level(Context *context) while (TOKEN_IS(TOKEN_CT_ELIF)) { advance_and_verify(context, TOKEN_CT_ELIF); - Decl *ct_elif = decl_new_ct(DECL_CT_ELIF, context->lex.prev_tok); + Decl *ct_elif = decl_new_ct(DECL_CT_ELIF, context->prev_tok); ASSIGN_EXPR_ELSE(ct_elif->ct_elif_decl.expr, parse_const_paren_expr(context), poisoned_decl); if (!parse_top_level_block(context, &ct_elif->ct_elif_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl; @@ -157,7 +157,7 @@ static inline Decl *parse_ct_if_top_level(Context *context) if (TOKEN_IS(TOKEN_CT_ELSE)) { advance_and_verify(context, TOKEN_CT_ELSE); - Decl *ct_else = decl_new_ct(DECL_CT_ELSE, context->lex.prev_tok); + Decl *ct_else = decl_new_ct(DECL_CT_ELSE, context->prev_tok); ct_if_decl->elif = ct_else; if (!parse_top_level_block(context, &ct_else->ct_else_decl, TOKEN_CT_ENDIF, TOKEN_CT_ENDIF, TOKEN_CT_ENDIF)) return poisoned_decl; } @@ -172,28 +172,28 @@ static inline Decl *parse_ct_if_top_level(Context *context) * @param context * @return poisoned decl if parsing fails. */ -static inline Decl *parse_ct_case(Context *context) +static inline Decl *parse_ct_case(ParseContext *context) { Decl *decl; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_CT_DEFAULT: advance(context); - decl = decl_new_ct(DECL_CT_CASE, context->lex.tok.id); + decl = decl_new_ct(DECL_CT_CASE, context->tok.id); break; case TOKEN_CT_CASE: - decl = decl_new_ct(DECL_CT_CASE, context->lex.tok.id); + decl = decl_new_ct(DECL_CT_CASE, context->tok.id); advance(context); ASSIGN_TYPE_ELSE(decl->ct_case_decl.type, parse_type(context), poisoned_decl); break; default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a $case or $default statement here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a $case or $default statement here."); return poisoned_decl; } TRY_CONSUME_OR(TOKEN_COLON, "Expected ':' here.", poisoned_decl); while (1) { - TokenType type = context->lex.tok.type; + TokenType type = context->tok.type; if (type == TOKEN_CT_DEFAULT || type == TOKEN_CT_CASE || type == TOKEN_LBRACE) break; ASSIGN_DECL_ELSE(Decl *stmt, parse_top_level_statement(context), poisoned_decl); vec_add(decl->ct_case_decl.body, stmt); @@ -206,10 +206,10 @@ static inline Decl *parse_ct_case(Context *context) * @param context * @return the declaration if successfully parsed, NULL otherwise. */ -static inline Decl *parse_ct_switch_top_level(Context *context) +static inline Decl *parse_ct_switch_top_level(ParseContext *context) { advance_and_verify(context, TOKEN_CT_SWITCH); - Decl *ct = decl_new_ct(DECL_CT_SWITCH, context->lex.prev_tok); + Decl *ct = decl_new_ct(DECL_CT_SWITCH, context->prev_tok); ASSIGN_EXPR_ELSE(ct->ct_switch_decl.expr, parse_const_paren_expr(context), poisoned_decl); CONSUME_OR(TOKEN_LBRACE, poisoned_decl); @@ -230,36 +230,36 @@ static inline Decl *parse_ct_switch_top_level(Context *context) * @param context * @return path or null if parsing failed. */ -static inline Path *parse_module_path(Context *context) +static inline Path *parse_module_path(ParseContext *context) { assert(TOKEN_IS(TOKEN_IDENT)); scratch_buffer_clear(); - SourceSpan span = source_span_from_token_id(context->lex.tok.id); + SourceSpan span = source_span_from_token_id(context->tok.id); while (1) { - TokenId last_token = context->lex.tok.id; - const char *string = TOKSTR(context->lex.tok); + TokenId last_token = context->tok.id; + const char *string = TOKSTR(context->tok); if (!try_consume(context, TOKEN_IDENT)) { - if (token_is_keyword(context->lex.tok.type)) + if (token_is_keyword(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "The module path cannot contain a reserved keyword, try another name."); + SEMA_TOKEN_ERROR(context->tok, "The module path cannot contain a reserved keyword, try another name."); return false; } - if (token_is_some_ident(context->lex.tok.type)) + if (token_is_some_ident(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "The elements of a module path must consist of only lower case letters, 0-9 and '_'."); + SEMA_TOKEN_ERROR(context->tok, "The elements of a module path must consist of only lower case letters, 0-9 and '_'."); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "Each '::' must be followed by a regular lower case sub module name."); + SEMA_TOKEN_ERROR(context->tok, "Each '::' must be followed by a regular lower case sub module name."); return NULL; } if (string == kw_main) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "'main' is not a valid name in a module path, please pick something else."); + SEMA_TOKID_ERROR(context->prev_tok, "'main' is not a valid name in a module path, please pick something else."); return NULL; } - scratch_buffer_append_len(string, TOKLEN(context->lex.prev_tok)); + scratch_buffer_append_len(string, TOKLEN(context->prev_tok)); if (!try_consume(context, TOKEN_SCOPE)) { span.end_loc = last_token; @@ -285,7 +285,7 @@ static inline Path *parse_module_path(Context *context) * | module_params ',' module_param * ; */ -static inline bool parse_optional_module_params(Context *context, TokenId **tokens) +static inline bool parse_optional_module_params(ParseContext *context, TokenId **tokens) { *tokens = NULL; @@ -294,32 +294,32 @@ static inline bool parse_optional_module_params(Context *context, TokenId **toke if (try_consume(context, TOKEN_GREATER)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Generic parameter list cannot be empty."); + SEMA_TOKEN_ERROR(context->tok, "Generic parameter list cannot be empty."); return false; } // No params while (1) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_TYPE_IDENT: break; case TOKEN_COMMA: - SEMA_TOKEN_ERROR(context->lex.tok, "Unexpected ','"); + SEMA_TOKEN_ERROR(context->tok, "Unexpected ','"); return false; case TOKEN_IDENT: - SEMA_TOKEN_ERROR(context->lex.tok, "The module parameter must be a type."); + SEMA_TOKEN_ERROR(context->tok, "The module parameter must be a type."); return false; case TOKEN_CT_IDENT: case TOKEN_CT_TYPE_IDENT: - SEMA_TOKEN_ERROR(context->lex.tok, "The module parameter cannot be a $-prefixed name."); + SEMA_TOKEN_ERROR(context->tok, "The module parameter cannot be a $-prefixed name."); return false; default: - SEMA_TOKEN_ERROR(context->lex.tok, "Only generic parameters are allowed here as parameters to the module."); + SEMA_TOKEN_ERROR(context->tok, "Only generic parameters are allowed here as parameters to the module."); return false; } - vec_add(*tokens, context->lex.tok.id); + vec_add(*tokens, context->tok.id); advance(context); if (!try_consume(context, TOKEN_COMMA)) { @@ -331,7 +331,7 @@ static inline bool parse_optional_module_params(Context *context, TokenId **toke /** * module ::= MODULE module_path ('<' module_params '>')? EOS */ -bool parse_module(Context *context) +bool parse_module(ParseContext *context) { if (!try_consume(context, TOKEN_MODULE)) { @@ -342,23 +342,23 @@ bool parse_module(Context *context) if (TOKEN_IS(TOKEN_STRING)) { - SEMA_TOKEN_ERROR(context->lex.tok, "'module' should be followed by a plain identifier, not a string. Did you accidentally put the module name between \"\"?"); + SEMA_TOKEN_ERROR(context->tok, "'module' should be followed by a plain identifier, not a string. Did you accidentally put the module name between \"\"?"); return false; } if (!TOKEN_IS(TOKEN_IDENT)) { - if (token_is_keyword(context->lex.tok.type)) + if (token_is_keyword(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "The module name cannot contain a reserved keyword, try another name."); + SEMA_TOKEN_ERROR(context->tok, "The module name cannot contain a reserved keyword, try another name."); return false; } - if (token_is_some_ident(context->lex.tok.type)) + if (token_is_some_ident(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "The module name must consist of only lower case letters, 0-9 and '_'."); + SEMA_TOKEN_ERROR(context->tok, "The module name must consist of only lower case letters, 0-9 and '_'."); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "'module' should be followed by a module name."); + SEMA_TOKEN_ERROR(context->tok, "'module' should be followed by a module name."); return false; } @@ -390,81 +390,45 @@ bool parse_module(Context *context) return true; } -/** - * specified_import ::= IDENT (AS IDENT)? - * | CONST_IDENT (AS CONST_IDENT)? - * | TYPE_IDENT (AS TYPE_IDENT)? - * - * @return true if import succeeded - */ -static inline bool parse_specified_import(Context *context, Path *path) -{ - if (!token_is_symbol(context->lex.tok.type)) - { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a symbol name here, the syntax is 'import : '."); - return false; - } - Token symbol = context->lex.tok; - advance(context); - // Alias? - if (!try_consume(context, TOKEN_AS)) - { - return context_add_import(context, path, symbol, NO_TOKEN, false); - } - if (context->lex.tok.type != symbol.type) - { - if (!token_is_symbol(context->lex.tok.type)) - { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a symbol name here, the syntax is 'import : AS '."); - return false; - } - SEMA_TOKEN_ERROR(context->lex.tok, "Expected the alias be the same type of name as the symbol aliased."); - return false; - } - Token alias = context->lex.tok; - advance(context); - return context_add_import(context, path, symbol, alias, false); -} - -bool consume_ident(Context *context, const char* name) +bool consume_ident(ParseContext *context, const char* name) { if (try_consume(context, TOKEN_IDENT)) return true; if (TOKEN_IS(TOKEN_TYPE_IDENT) || TOKEN_IS(TOKEN_CONST_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "A %s must start with a lower case letter.", name); + SEMA_TOKEN_ERROR(context->tok, "A %s must start with a lower case letter.", name); return false; } - if (token_is_keyword(context->lex.tok.type)) + if (token_is_keyword(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "This is a reserved keyword, did you accidentally use it?"); + SEMA_TOKEN_ERROR(context->tok, "This is a reserved keyword, did you accidentally use it?"); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "A %s was expected.", name); + SEMA_TOKEN_ERROR(context->tok, "A %s was expected.", name); return false; } -static bool consume_type_name(Context *context, const char* type) +static bool consume_type_name(ParseContext *context, const char* type) { - if (TOKEN_IS(TOKEN_IDENT) || token_is_keyword(context->lex.tok.type)) + if (TOKEN_IS(TOKEN_IDENT) || token_is_keyword(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Names of %ss must start with an upper case letter.", type); + SEMA_TOKEN_ERROR(context->tok, "Names of %ss must start with an upper case letter.", type); return false; } if (TOKEN_IS(TOKEN_CONST_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Names of %ss cannot be all upper case.", type); + SEMA_TOKEN_ERROR(context->tok, "Names of %ss cannot be all upper case.", type); return false; } if (!consume(context, TOKEN_TYPE_IDENT, "'%s' should be followed by the name of the %s.", type, type)) return false; return true; } -bool consume_const_name(Context *context, const char* type) +bool consume_const_name(ParseContext *context, const char* type) { if (TOKEN_IS(TOKEN_IDENT) || TOKEN_IS(TOKEN_TYPE_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Names of %ss must be all upper case.", type); + SEMA_TOKEN_ERROR(context->tok, "Names of %ss must be all upper case.", type); return false; } if (!consume(context, TOKEN_CONST_IDENT, "The constant name was expected here, did you forget it?")) return false; @@ -472,29 +436,29 @@ bool consume_const_name(Context *context, const char* type) } -Path *parse_path_prefix(Context *context, bool *had_error) +Path *parse_path_prefix(ParseContext *context, bool *had_error) { *had_error = false; - if (!TOKEN_IS(TOKEN_IDENT) || context->lex.next_tok.type != TOKEN_SCOPE) return NULL; + if (!TOKEN_IS(TOKEN_IDENT) || context->next_tok.type != TOKEN_SCOPE) return NULL; char *scratch_ptr = global_context.scratch_buffer; uint32_t offset = 0; Path *path = CALLOCS(Path); - path->span = source_span_from_token_id(context->lex.tok.id); - unsigned len = TOKLEN(context->lex.tok); - memcpy(scratch_ptr, TOKSTR(context->lex.tok.id), len); + path->span = source_span_from_token_id(context->tok.id); + unsigned len = TOKLEN(context->tok); + memcpy(scratch_ptr, TOKSTR(context->tok.id), len); offset += len; - TokenId last_token = context->lex.tok.id; + TokenId last_token = context->tok.id; advance(context); advance(context); - while (TOKEN_IS(TOKEN_IDENT) && context->lex.next_tok.type == TOKEN_SCOPE) + while (TOKEN_IS(TOKEN_IDENT) && context->next_tok.type == TOKEN_SCOPE) { - last_token = context->lex.tok.id; + last_token = context->tok.id; scratch_ptr[offset++] = ':'; scratch_ptr[offset++] = ':'; - len = TOKLEN(context->lex.tok); - memcpy(scratch_ptr + offset, TOKSTR(context->lex.tok.id), len); + len = TOKLEN(context->tok); + memcpy(scratch_ptr + offset, TOKSTR(context->tok.id), len); offset += len; advance(context); advance(context); } @@ -540,18 +504,18 @@ Path *parse_path_prefix(Context *context, bool *had_error) * Assume prev_token is the type. * @return TypeInfo (poisoned if fails) */ -static inline TypeInfo *parse_base_type(Context *context) +static inline TypeInfo *parse_base_type(ParseContext *context) { if (try_consume(context, TOKEN_CT_TYPEOF)) { - TypeInfo *type_info = type_info_new(TYPE_INFO_EXPRESSION, source_span_from_token_id(context->lex.prev_tok)); + TypeInfo *type_info = type_info_new(TYPE_INFO_EXPRESSION, source_span_from_token_id(context->prev_tok)); CONSUME_OR(TOKEN_LPAREN, poisoned_type_info); ASSIGN_EXPR_ELSE(type_info->unresolved_type_expr, parse_expr(context), poisoned_type_info); CONSUME_OR(TOKEN_RPAREN, poisoned_type_info); RANGE_EXTEND_PREV(type_info); return type_info; } - SourceSpan range = source_span_from_token_id(context->lex.tok.id); + SourceSpan range = source_span_from_token_id(context->tok.id); bool had_error; Path *path = parse_path_prefix(context, &had_error); if (had_error) return poisoned_type_info; @@ -559,7 +523,7 @@ static inline TypeInfo *parse_base_type(Context *context) { TypeInfo *type_info = type_info_new(TYPE_INFO_IDENTIFIER, range); type_info->unresolved.path = path; - type_info->unresolved.name_loc = context->lex.tok.id; + type_info->unresolved.name_loc = context->tok.id; if (!consume_type_name(context, "type")) return poisoned_type_info; RANGE_EXTEND_PREV(type_info); return type_info; @@ -567,24 +531,24 @@ static inline TypeInfo *parse_base_type(Context *context) TypeInfo *type_info = NULL; Type *type_found = NULL; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_TYPE_IDENT: case TOKEN_CT_TYPE_IDENT: - type_info = type_info_new(TYPE_INFO_IDENTIFIER, source_span_from_token_id(context->lex.tok.id)); - type_info->unresolved.name_loc = context->lex.tok.id; + type_info = type_info_new(TYPE_INFO_IDENTIFIER, source_span_from_token_id(context->tok.id)); + type_info->unresolved.name_loc = context->tok.id; break; case TYPE_TOKENS: - type_found = type_from_token(context->lex.tok.type); + type_found = type_from_token(context->tok.type); break; default: - SEMA_TOKEN_ERROR(context->lex.tok, "A type name was expected here."); + SEMA_TOKEN_ERROR(context->tok, "A type name was expected here."); return poisoned_type_info; } if (type_found) { assert(!type_info); - type_info = type_info_new(TYPE_INFO_IDENTIFIER, source_span_from_token_id(context->lex.tok.id)); + type_info = type_info_new(TYPE_INFO_IDENTIFIER, source_span_from_token_id(context->tok.id)); type_info->resolve_status = RESOLVE_DONE; type_info->type = type_found; } @@ -604,7 +568,7 @@ static inline TypeInfo *parse_base_type(Context *context) * @param type the type to wrap, may not be poisoned. * @return type (poisoned if fails) */ -static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type) +static inline TypeInfo *parse_array_type_index(ParseContext *context, TypeInfo *type) { assert(type_info_ok(type)); @@ -641,7 +605,7 @@ static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type) * @param type the type to wrap, may not be poisoned. * @return type (poisoned if fails) */ -static inline TypeInfo *parse_vector_type_index(Context *context, TypeInfo *type) +static inline TypeInfo *parse_vector_type_index(ParseContext *context, TypeInfo *type) { assert(type_info_ok(type)); @@ -663,11 +627,11 @@ static inline TypeInfo *parse_vector_type_index(Context *context, TypeInfo *type * Assume already stepped into. * @return Type, poisoned if parsing is invalid. */ -TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info) +TypeInfo *parse_type_with_base(ParseContext *context, TypeInfo *type_info) { while (type_info_ok(type_info)) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_LVEC: type_info = parse_vector_type_index(context, type_info); @@ -701,13 +665,13 @@ TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info) * Assume already stepped into. * @return Type, poisoned if parsing is invalid. */ -TypeInfo *parse_type(Context *context) +TypeInfo *parse_type(ParseContext *context) { ASSIGN_TYPE_ELSE(TypeInfo *base, parse_base_type(context), poisoned_type_info); return parse_type_with_base(context, base); } -TypeInfo *parse_failable_type(Context *context) +TypeInfo *parse_failable_type(ParseContext *context) { ASSIGN_TYPE_ELSE(TypeInfo *info, parse_base_type(context), poisoned_type_info); ASSIGN_TYPE_ELSE(info, parse_type_with_base(context, info), poisoned_type_info); @@ -733,17 +697,17 @@ TypeInfo *parse_failable_type(Context *context) * @param type * @return */ -Decl *parse_decl_after_type(Context *context, TypeInfo *type) +Decl *parse_decl_after_type(ParseContext *context, TypeInfo *type) { if (TOKEN_IS(TOKEN_LPAREN)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected '{'."); + SEMA_TOKEN_ERROR(context->tok, "Expected '{'."); return poisoned_decl; } EXPECT_IDENT_FOR_OR("variable name", poisoned_decl); - TokenId name = context->lex.tok.id; + TokenId name = context->tok.id; advance(context); Decl *decl = decl_new_var(name, type, VARDECL_LOCAL, VISIBLE_LOCAL); @@ -752,7 +716,7 @@ Decl *parse_decl_after_type(Context *context, TypeInfo *type) { if (!decl) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected an identifier before '='."); + SEMA_TOKEN_ERROR(context->tok, "Expected an identifier before '='."); return poisoned_decl; } advance_and_verify(context, TOKEN_EQ); @@ -767,7 +731,7 @@ Decl *parse_decl_after_type(Context *context, TypeInfo *type) * * @return Decl* (poisoned on error) */ -Decl *parse_decl(Context *context) +Decl *parse_decl(ParseContext *context) { if (TOKEN_IS(TOKEN_CONST)) { @@ -797,11 +761,11 @@ Decl *parse_decl(Context *context) * : 'const' type? IDENT '=' const_expr * ; */ -static Decl *parse_const_declaration(Context *context, Visibility visibility) +static Decl *parse_const_declaration(ParseContext *context, Visibility visibility) { advance_and_verify(context, TOKEN_CONST); - SourceSpan span = { .loc = context->lex.prev_tok, .end_loc = context->lex.tok.id }; + SourceSpan span = { .loc = context->prev_tok, .end_loc = context->tok.id }; TypeInfo *type_info = NULL; @@ -812,7 +776,7 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility) if (!consume_const_name(context, "const")) return poisoned_decl; - Decl *decl = decl_new_var(context->lex.prev_tok, type_info, VARDECL_CONST, visibility); + Decl *decl = decl_new_var(context->prev_tok, type_info, VARDECL_CONST, visibility); CONSUME_OR(TOKEN_EQ, poisoned_decl); @@ -831,16 +795,16 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility) * * @return true if this is a function start. */ -static inline bool is_function_start(Context *context) +static inline bool is_function_start(ParseContext *context) { // If it's a ! then it must be function! if (TOKEN_IS(TOKEN_BANG)) return true; if (TOKEN_IS(TOKEN_IDENT)) { - if (context->lex.next_tok.type == TOKEN_EQEQ || context->lex.next_tok.type == TOKEN_EOS) return false; - if (context->lex.next_tok.type == TOKEN_LPAREN) return true; + if (context->next_tok.type == TOKEN_EQEQ || context->next_tok.type == TOKEN_EOS) return false; + if (context->next_tok.type == TOKEN_LPAREN) return true; } - TokenId current = context->lex.tok.id; + TokenId current = context->tok.id; TokenType tok = TOKTYPE(current); while (1) { @@ -859,10 +823,10 @@ static inline bool is_function_start(Context *context) } -bool parse_next_is_decl(Context *context) +bool parse_next_is_decl(ParseContext *context) { - TokenType next_tok = context->lex.next_tok.type; - switch (context->lex.tok.type) + TokenType next_tok = context->next_tok.type; + switch (context->tok.type) { case TYPELIKE_TOKENS: return next_tok != TOKEN_DOT && next_tok != TOKEN_LPAREN && next_tok != TOKEN_LBRACE; @@ -874,10 +838,10 @@ bool parse_next_is_decl(Context *context) } } -bool parse_next_is_type(Context *context) +bool parse_next_is_type(ParseContext *context) { - TokenType next_tok = context->lex.next_tok.type; - switch (context->lex.tok.type) + TokenType next_tok = context->next_tok.type; + switch (context->tok.type) { case TYPELIKE_TOKENS: return true; @@ -890,10 +854,10 @@ bool parse_next_is_type(Context *context) } -bool parse_next_is_case_type(Context *context) +bool parse_next_is_case_type(ParseContext *context) { - TokenType next_tok = context->lex.next_tok.type; - switch (context->lex.tok.type) + TokenType next_tok = context->next_tok.type; + switch (context->tok.type) { case TYPELIKE_TOKENS: return (next_tok == TOKEN_STAR) | (next_tok == TOKEN_LBRACKET) | (next_tok == TOKEN_COMMA) | (next_tok == TOKEN_COLON) | (next_tok == TOKEN_EOS); @@ -925,7 +889,7 @@ bool parse_next_is_case_type(Context *context) * * @return true if parsing succeeded, false if recovery is needed */ -bool parse_attributes(Context *context, Attr ***attributes_ref) +bool parse_attributes(ParseContext *context, Attr ***attributes_ref) { *attributes_ref = NULL; @@ -937,7 +901,7 @@ bool parse_attributes(Context *context, Attr ***attributes_ref) Attr *attr = CALLOCS(Attr); - attr->name = context->lex.tok.id; + attr->name = context->tok.id; attr->path = path; TRY_CONSUME_OR(TOKEN_IDENT, "Expected an attribute", false); @@ -972,31 +936,31 @@ bool parse_attributes(Context *context, Attr ***attributes_ref) * @param visibility * @return true if parsing succeeded */ -static inline Decl *parse_global_declaration(Context *context, Visibility visibility) +static inline Decl *parse_global_declaration(ParseContext *context, Visibility visibility) { bool threadlocal = try_consume(context, TOKEN_TLOCAL); ASSIGN_TYPE_ELSE(TypeInfo *type, parse_failable_type(context), poisoned_decl); - Decl *decl = decl_new_var(context->lex.tok.id, type, VARDECL_GLOBAL, visibility); + Decl *decl = decl_new_var(context->tok.id, type, VARDECL_GLOBAL, visibility); decl->var.is_threadlocal = threadlocal; if (TOKEN_IS(TOKEN_CONST_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "This looks like a constant variable, did you forget 'const'?"); + SEMA_TOKEN_ERROR(context->tok, "This looks like a constant variable, did you forget 'const'?"); return poisoned_decl; } if (!try_consume(context, TOKEN_IDENT)) { - if (token_is_some_ident(context->lex.tok.type)) + if (token_is_some_ident(context->tok.type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "I expected a variable name here, but global variables need to start with lower case."); + SEMA_TOKEN_ERROR(context->tok, "I expected a variable name here, but global variables need to start with lower case."); return poisoned_decl; } - SEMA_TOKEN_ERROR(context->lex.tok, "The name of a global variable was expected here"); + SEMA_TOKEN_ERROR(context->tok, "The name of a global variable was expected here"); return poisoned_decl; } @@ -1015,13 +979,13 @@ static inline Decl *parse_global_declaration(Context *context, Visibility visibi * param_declaration ::= type_expression '...'?) (IDENT ('=' initializer)?)? * ; */ -static inline bool parse_param_decl(Context *context, Visibility parent_visibility, Decl*** parameters, bool require_name) +static inline bool parse_param_decl(ParseContext *context, Visibility parent_visibility, Decl*** parameters, bool require_name) { - TokenId first = context->lex.tok.id; + TokenId first = context->tok.id; ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), false); bool vararg = try_consume(context, TOKEN_ELLIPSIS); - Decl *param = decl_new_var(context->lex.tok.id, type, VARDECL_PARAM, parent_visibility); - param->span = (SourceSpan) { first, context->lex.tok.id }; + Decl *param = decl_new_var(context->tok.id, type, VARDECL_PARAM, parent_visibility); + param->span = (SourceSpan) { first, context->tok.id }; param->var.vararg = vararg; if (!try_consume(context, TOKEN_IDENT)) { @@ -1035,10 +999,10 @@ static inline bool parse_param_decl(Context *context, Visibility parent_visibili { if (TOKEN_IS(TOKEN_CT_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Compile time identifiers are only allowed as macro parameters."); + SEMA_TOKEN_ERROR(context->tok, "Compile time identifiers are only allowed as macro parameters."); return false; } - sema_error_at_prev_end(context->lex.tok, "Unexpected end of the parameter list, did you forget an ')'?"); + sema_error_at_prev_end(context->tok, "Unexpected end of the parameter list, did you forget an ')'?"); return false; } SEMA_ERROR(type, "The parameter must be named."); @@ -1060,7 +1024,7 @@ static inline bool parse_param_decl(Context *context, Visibility parent_visibili * parameter ::= type ELLIPSIS? (non_type_ident ('=' expr))? * | ELLIPSIS (CT_TYPE_IDENT | non_type_ident ('=' expr)?)? */ -bool parse_parameters(Context *context, Visibility visibility, Decl ***params_ref) +bool parse_parameters(ParseContext *context, Visibility visibility, Decl ***params_ref) { Decl** params = NULL; bool var_arg_found = false; @@ -1075,7 +1039,7 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re // there is an ambiguity here, since ($Type) and ($Type x) is potentially possible // to evaluate. However, at the top level we never have global compile time values. // so consequently we need fix this and ignore CT_TYPE_IDENT - if (!ellipsis && context_next_is_type_and_not_ident(context) && context->lex.tok.type != TOKEN_CT_TYPE_IDENT ) + if (!ellipsis && context_next_is_type_and_not_ident(context) && context->tok.type != TOKEN_CT_TYPE_IDENT ) { ASSIGN_TYPE_ELSE(type, parse_type(context), false); ellipsis = try_consume(context, TOKEN_ELLIPSIS); @@ -1083,15 +1047,15 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re if (ellipsis && var_arg_found) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Only a single vararg parameter is allowed."); + SEMA_TOKID_ERROR(context->prev_tok, "Only a single vararg parameter is allowed."); return false; } VarDeclKind param_kind; - TokenId token = context->lex.tok.id; + TokenId token = context->tok.id; bool no_name = false; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_IDENT: // normal foo @@ -1104,17 +1068,17 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re case TOKEN_AMP: // reference &foo advance(context); - token = context->lex.tok.id; + token = context->tok.id; if (!TOKEN_IS(TOKEN_IDENT)) { - SEMA_TOKEN_ERROR(context->lex.tok, "Only normal variables may be passed by reference."); + SEMA_TOKEN_ERROR(context->tok, "Only normal variables may be passed by reference."); return false; } param_kind = VARDECL_PARAM_REF; break; case TOKEN_HASH_TYPE_IDENT: // #Foo (not allowed) - SEMA_TOKEN_ERROR(context->lex.tok, "An unevaluated expression can never be a type, did you mean to use $Type?"); + SEMA_TOKEN_ERROR(context->tok, "An unevaluated expression can never be a type, did you mean to use $Type?"); return false; case TOKEN_HASH_IDENT: // expression #foo @@ -1129,15 +1093,15 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re case TOKEN_RPAREN: if (!type && !ellipsis) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a parameter."); + SEMA_TOKEN_ERROR(context->tok, "Expected a parameter."); return false; } no_name = true; - token = context->lex.prev_tok; + token = context->prev_tok; param_kind = VARDECL_PARAM; break; default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a parameter."); + SEMA_TOKEN_ERROR(context->tok, "Expected a parameter."); return false; } Decl *param = decl_new_var(token, type, param_kind, visibility); @@ -1168,7 +1132,7 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re * * parameter_type_list ::= '(' parameters ')' */ -static inline bool parse_parameter_list(Context *context, Visibility parent_visibility, FunctionSignature *signature, bool is_interface) +static inline bool parse_parameter_list(ParseContext *context, Visibility parent_visibility, FunctionSignature *signature, bool is_interface) { CONSUME_OR(TOKEN_LPAREN, false); Decl **decls; @@ -1217,7 +1181,7 @@ static inline bool parse_parameter_list(Context *context, Visibility parent_visi * * @param parent the parent of the struct */ -bool parse_struct_body(Context *context, Decl *parent) +bool parse_struct_body(ParseContext *context, Decl *parent) { CONSUME_OR(TOKEN_LBRACE, false); @@ -1225,22 +1189,22 @@ bool parse_struct_body(Context *context, Decl *parent) MemberIndex index = 0; while (!TOKEN_IS(TOKEN_RBRACE)) { - TokenType token_type = context->lex.tok.type; + TokenType token_type = context->tok.type; if (token_type == TOKEN_STRUCT || token_type == TOKEN_UNION || token_type == TOKEN_BITSTRUCT) { DeclKind decl_kind = decl_from_token(token_type); Decl *member; - if (context->lex.next_tok.type != TOKEN_IDENT) + if (context->next_tok.type != TOKEN_IDENT) { member = decl_new_with_type(NO_TOKEN_ID, decl_kind, parent->visibility); - member->span = source_span_from_token_id(context->lex.tok.id); + member->span = source_span_from_token_id(context->tok.id); advance(context); } else { advance(context); - member = decl_new_with_type(context->lex.tok.id, decl_kind, parent->visibility); - member->span.loc = context->lex.prev_tok; + member = decl_new_with_type(context->tok.id, decl_kind, parent->visibility); + member->span.loc = context->prev_tok; advance_and_verify(context, TOKEN_IDENT); } if (decl_kind == DECL_BITSTRUCT) @@ -1264,16 +1228,16 @@ bool parse_struct_body(Context *context, Decl *parent) continue; } bool was_inline = false; - if (token_type == TOKEN_IDENT && TOKSTR(context->lex.tok) == kw_inline) + if (token_type == TOKEN_IDENT && TOKSTR(context->tok) == kw_inline) { if (parent->decl_kind != DECL_STRUCT) { - SEMA_TOKEN_ERROR(context->lex.tok, "Only structs may have 'inline' elements, did you make a mistake?"); + SEMA_TOKEN_ERROR(context->tok, "Only structs may have 'inline' elements, did you make a mistake?"); return false; } if (index > 0) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Only the first element may be 'inline', did you order your fields wrong?"); + SEMA_TOKID_ERROR(context->prev_tok, "Only the first element may be 'inline', did you order your fields wrong?"); return false; } parent->is_substruct = true; @@ -1285,7 +1249,7 @@ bool parse_struct_body(Context *context, Decl *parent) while (1) { EXPECT_OR(TOKEN_IDENT, false); - Decl *member = decl_new_var(context->lex.tok.id, type, VARDECL_MEMBER, parent->visibility); + Decl *member = decl_new_var(context->tok.id, type, VARDECL_MEMBER, parent->visibility); vec_add(parent->strukt.members, member); index++; if (index > MAX_MEMBERS) @@ -1316,14 +1280,14 @@ bool parse_struct_body(Context *context, Decl *parent) * * @param visibility */ -static inline Decl *parse_struct_declaration(Context *context, Visibility visibility) +static inline Decl *parse_struct_declaration(ParseContext *context, Visibility visibility) { - TokenType type = context->lex.tok.type; + TokenType type = context->tok.type; advance(context); const char* type_name = struct_union_name_from_token(type); - TokenId name = context->lex.tok.id; + TokenId name = context->tok.id; if (!consume_type_name(context, type_name)) return poisoned_decl; Decl *decl = decl_new_with_type(name, decl_from_token(type), visibility); @@ -1347,7 +1311,7 @@ static inline Decl *parse_struct_declaration(Context *context, Visibility visibi * @param decl * @return */ -static inline bool parse_bitstruct_body(Context *context, Decl *decl) +static inline bool parse_bitstruct_body(ParseContext *context, Decl *decl) { CONSUME_OR(TOKEN_LBRACE, false); @@ -1359,13 +1323,13 @@ static inline bool parse_bitstruct_body(Context *context, Decl *decl) { if (try_consume(context, TOKEN_CONST_IDENT) || try_consume(context, TOKEN_TYPE_IDENT)) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Expected a field name with an initial lower case."); + SEMA_TOKID_ERROR(context->prev_tok, "Expected a field name with an initial lower case."); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a field name at this position."); + SEMA_TOKEN_ERROR(context->tok, "Expected a field name at this position."); return false; } - Decl *member_decl = decl_new_var(context->lex.prev_tok, type, VARDECL_BITMEMBER, VISIBLE_LOCAL); + Decl *member_decl = decl_new_var(context->prev_tok, type, VARDECL_BITMEMBER, VISIBLE_LOCAL); CONSUME_OR(TOKEN_COLON, false); ASSIGN_EXPR_ELSE(member_decl->var.start, parse_constant_expr(context), false); if (try_consume(context, TOKEN_DOTDOT)) @@ -1385,11 +1349,11 @@ static inline bool parse_bitstruct_body(Context *context, Decl *decl) /** * bitstruct_declaration = 'bitstruct' IDENT ':' type bitstruct_body */ -static inline Decl *parse_bitstruct_declaration(Context *context, Visibility visibility) +static inline Decl *parse_bitstruct_declaration(ParseContext *context, Visibility visibility) { advance_and_verify(context, TOKEN_BITSTRUCT); - TokenId name = context->lex.tok.id; + TokenId name = context->tok.id; if (!consume_type_name(context, "bitstruct")) return poisoned_decl; Decl *decl = decl_new_with_type(name, DECL_BITSTRUCT, visibility); @@ -1412,7 +1376,7 @@ static inline Decl *parse_bitstruct_declaration(Context *context, Visibility vis } -static inline Decl *parse_top_level_const_declaration(Context *context, Visibility visibility) +static inline Decl *parse_top_level_const_declaration(ParseContext *context, Visibility visibility) { ASSIGN_DECL_ELSE(Decl *decl, parse_const_declaration(context, visibility), poisoned_decl); TRY_CONSUME_EOS_OR(poisoned_decl); @@ -1425,7 +1389,7 @@ static inline Decl *parse_top_level_const_declaration(Context *context, Visibili * * trailing_block_parameter ::= '@' IDENT ( '(' parameters ')' )? */ -static bool parse_macro_arguments(Context *context, Visibility visibility, Decl ***params_ref, Decl ***body_params, TokenId *block_parameter) +static bool parse_macro_arguments(ParseContext *context, Visibility visibility, Decl ***params_ref, Decl ***body_params, TokenId *block_parameter) { CONSUME_OR(TOKEN_LPAREN, false); *params_ref = NULL; @@ -1439,9 +1403,9 @@ static bool parse_macro_arguments(Context *context, Visibility visibility, Decl { // Consume '@' IDENT TRY_CONSUME_OR(TOKEN_AT, "Expected a trailing block with the format '@block(...).", false); - *block_parameter = context->lex.tok.id; + *block_parameter = context->tok.id; if (!consume_ident(context, "variable name")) return false; - TokenId name = context->lex.prev_tok; + TokenId name = context->prev_tok; if (try_consume(context, TOKEN_LPAREN)) { if (!parse_parameters(context, visibility, body_params)) return false; @@ -1458,14 +1422,14 @@ static bool parse_macro_arguments(Context *context, Visibility visibility, Decl * * @return NULL if parsing failed, otherwise a list of Type* */ -static inline TypeInfo **parse_generic_parameters(Context *context) +static inline TypeInfo **parse_generic_parameters(ParseContext *context) { TypeInfo **types = NULL; while (!try_consume(context, TOKEN_GREATER)) { ASSIGN_TYPE_ELSE(TypeInfo *type_info, parse_type(context), NULL); vec_add(types, type_info); - if (context->lex.tok.type != TOKEN_RPAREN && context->lex.tok.type != TOKEN_GREATER) + if (context->tok.type != TOKEN_RPAREN && context->tok.type != TOKEN_GREATER) { TRY_CONSUME_OR(TOKEN_COMMA, "Expected ',' after argument.", NULL); } @@ -1473,9 +1437,9 @@ static inline TypeInfo **parse_generic_parameters(Context *context) return types; } -static inline bool parse_define_optional_path(Context *context, Path **path) +static inline bool parse_define_optional_path(ParseContext *context, Path **path) { - if (context->lex.tok.type != TOKEN_IDENT || context->lex.next_tok.type != TOKEN_SCOPE) + if (context->tok.type != TOKEN_IDENT || context->next_tok.type != TOKEN_SCOPE) { *path = NULL; return true; @@ -1491,17 +1455,17 @@ static inline bool parse_define_optional_path(Context *context, Path **path) * * func_typedef ::= 'func' failable_type parameter_type_list */ -static inline Decl *parse_define_type(Context *context, Visibility visibility) +static inline Decl *parse_define_type(ParseContext *context, Visibility visibility) { - TokenId start = context->lex.tok.id; + TokenId start = context->tok.id; advance_and_verify(context, TOKEN_DEFINE); - TokenId alias_name = context->lex.tok.id; + TokenId alias_name = context->tok.id; DEBUG_LOG("Parse define %s", TOKSTR(alias_name)); advance_and_verify(context, TOKEN_TYPE_IDENT); CONSUME_OR(TOKEN_EQ, poisoned_decl); bool distinct = false; - if (context->lex.tok.type == TOKEN_IDENT && TOKSTR(context->lex.tok) == kw_distinct) + if (context->tok.type == TOKEN_IDENT && TOKSTR(context->tok) == kw_distinct) { distinct = true; advance(context); @@ -1564,31 +1528,31 @@ static inline Decl *parse_define_type(Context *context, Visibility visibility) * * identifier_alias ::= path? (IDENT | CONST_IDENT) */ -static inline Decl *parse_define_ident(Context *context, Visibility visibility) +static inline Decl *parse_define_ident(ParseContext *context, Visibility visibility) { // 1. Store the beginning of the define. - TokenId start = context->lex.tok.id; + TokenId start = context->tok.id; advance_and_verify(context, TOKEN_DEFINE); // 2. At this point we expect an ident or a const token. // since the Type is handled. - TokenType alias_type = context->lex.tok.type; + TokenType alias_type = context->tok.type; if (alias_type != TOKEN_IDENT && alias_type != TOKEN_CONST_IDENT) { if (token_is_any_type(alias_type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "'%s' is the name of a built-in type and can't be used as an alias.", + SEMA_TOKEN_ERROR(context->tok, "'%s' is the name of a built-in type and can't be used as an alias.", token_type_to_string(alias_type)); } else { - SEMA_TOKEN_ERROR(context->lex.tok, "An identifier was expected here."); + SEMA_TOKEN_ERROR(context->tok, "An identifier was expected here."); } return poisoned_decl; } // 3. Set up the define. - Decl *decl = decl_new(DECL_DEFINE, context->lex.tok.id, visibility); + Decl *decl = decl_new(DECL_DEFINE, context->tok.id, visibility); decl->define_decl.define_kind = DEFINE_IDENT_ALIAS; decl->span.loc = start; @@ -1614,24 +1578,24 @@ static inline Decl *parse_define_ident(Context *context, Visibility visibility) decl->define_decl.path = path; // 6. Check that the token after the path is of the same type. - if (context->lex.tok.type != alias_type) + if (context->tok.type != alias_type) { - if (token_is_any_type(context->lex.tok.type) || context->lex.tok.type == TOKEN_TYPE_IDENT) + if (token_is_any_type(context->tok.type) || context->tok.type == TOKEN_TYPE_IDENT) { SEMA_TOKID_ERROR(decl->name_token, "A type alias must start with an upper case letter and contain at least one lower case letter."); return poisoned_decl; } if (alias_type == TOKEN_CONST_IDENT) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a constant name here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a constant name here."); return poisoned_decl; } - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a function or variable name here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a function or variable name here."); return poisoned_decl; } // 7. Consume the identifier - decl->define_decl.identifier = context->lex.tok.id; + decl->define_decl.identifier = context->tok.id; advance(context); if (try_consume(context, TOKEN_LESS)) @@ -1649,26 +1613,26 @@ static inline Decl *parse_define_ident(Context *context, Visibility visibility) /** * define_attribute ::= 'define' '@' IDENT '(' parameter_list ')' ('=' (void | attribute_list))? */ -static inline Decl *parse_define_attribute(Context *context, Visibility visibility) +static inline Decl *parse_define_attribute(ParseContext *context, Visibility visibility) { // 1. Store the beginning of the define. - TokenId start = context->lex.tok.id; + TokenId start = context->tok.id; advance_and_verify(context, TOKEN_DEFINE); advance_and_verify(context, TOKEN_AT); - TokenType alias_type = context->lex.tok.type; + TokenType alias_type = context->tok.type; if (alias_type != TOKEN_TYPE_IDENT) { if (token_is_some_ident(alias_type) || token_is_keyword(alias_type)) { - SEMA_TOKEN_ERROR(context->lex.tok, "A user defined attribute must start with an uppercase character, followed by at least one lower case."); + SEMA_TOKEN_ERROR(context->tok, "A user defined attribute must start with an uppercase character, followed by at least one lower case."); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "The attribute name was expected here."); + SEMA_TOKEN_ERROR(context->tok, "The attribute name was expected here."); return false; } - Decl *decl = decl_new(DECL_DEFINE, context->lex.tok.id, visibility); + Decl *decl = decl_new(DECL_DEFINE, context->tok.id, visibility); advance_and_verify(context, TOKEN_TYPE_IDENT); Decl **parameters = NULL; @@ -1699,14 +1663,14 @@ static inline Decl *parse_define_attribute(Context *context, Visibility visibil /** * define_decl ::= DEFINE define_type_body | */ -static inline Decl *parse_define(Context *context, Visibility visibility) +static inline Decl *parse_define(ParseContext *context, Visibility visibility) { - if (context->lex.next_tok.type == TOKEN_AT) + if (context->next_tok.type == TOKEN_AT) { // define @foo = @inline, @noreturn return parse_define_attribute(context, visibility); } - if (context->lex.next_tok.type == TOKEN_TYPE_IDENT) + if (context->next_tok.type == TOKEN_TYPE_IDENT) { return parse_define_type(context, visibility); } @@ -1719,7 +1683,7 @@ static inline Decl *parse_define(Context *context, Visibility visibility) * macro_header ::= (type '!'?)? (type '.')? IDENT */ static inline bool -parse_func_macro_header(Context *context, bool rtype_is_optional, TypeInfo **rtype_ref, TypeInfo **method_type_ref, +parse_func_macro_header(ParseContext *context, bool rtype_is_optional, TypeInfo **rtype_ref, TypeInfo **method_type_ref, TokenId *name_ref) { TypeInfo *rtype = NULL; @@ -1749,7 +1713,7 @@ parse_func_macro_header(Context *context, bool rtype_is_optional, TypeInfo **rty // 5b. If the rtype is not optional or the return type was a failable, then this is an error. if (!rtype_is_optional || rtype->failable) { - SEMA_TOKID_ERROR(context->lex.prev_tok, + SEMA_TOKID_ERROR(context->prev_tok, "This looks like you are declaring a method without a return type?"); return false; } @@ -1765,7 +1729,7 @@ parse_func_macro_header(Context *context, bool rtype_is_optional, TypeInfo **rty } RESULT: TRY_CONSUME_OR(TOKEN_IDENT, "Expected a name here.", false); - *name_ref = context->lex.prev_tok; + *name_ref = context->prev_tok; *rtype_ref = rtype; *method_type_ref = method_type; return true; @@ -1775,12 +1739,12 @@ parse_func_macro_header(Context *context, bool rtype_is_optional, TypeInfo **rty /** * macro ::= macro_header '(' macro_params ')' compound_statement */ -static inline Decl *parse_macro_declaration(Context *context, Visibility visibility) +static inline Decl *parse_macro_declaration(ParseContext *context, Visibility visibility) { DeclKind kind = try_consume(context, TOKEN_MACRO) ? DECL_MACRO : DECL_GENERIC; if (kind == DECL_GENERIC) advance_and_verify(context, TOKEN_GENERIC); - Decl *decl = decl_new(kind, context->lex.tok.id, visibility); + Decl *decl = decl_new(kind, context->tok.id, visibility); TypeInfo **rtype_ref = &decl->macro_decl.rtype; TypeInfo **method_type_ref = &decl->macro_decl.type_parent; TokenId name; @@ -1792,6 +1756,9 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil TokenId block_parameter = NO_TOKEN_ID; if (!parse_macro_arguments(context, visibility, &decl->macro_decl.parameters, &decl->macro_decl.body_parameters, &block_parameter)) return poisoned_decl; decl->macro_decl.block_parameter = block_parameter; + + if (!parse_attributes(context, &decl->attributes)) return poisoned_decl; + ASSIGN_AST_ELSE(decl->macro_decl.body, parse_stmt(context), poisoned_decl); return decl; } @@ -1803,11 +1770,11 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil * | ERRTYPE TYPE_IDENT '{' error_data '}' * ; */ -static inline Decl *parse_error_declaration(Context *context, Visibility visibility) +static inline Decl *parse_error_declaration(ParseContext *context, Visibility visibility) { advance_and_verify(context, TOKEN_ERRTYPE); - Decl *decl = decl_new_with_type(context->lex.tok.id, DECL_ERRTYPE, visibility); + Decl *decl = decl_new_with_type(context->tok.id, DECL_ERRTYPE, visibility); if (!consume_type_name(context, "error type")) return poisoned_decl; @@ -1818,14 +1785,14 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil decl->enums.type_info = type_info_new_base(type_iptr->canonical, decl->span); while (!try_consume(context, TOKEN_RBRACE)) { - Decl *enum_const = decl_new(DECL_ERRVALUE, context->lex.tok.id, decl->visibility); + Decl *enum_const = decl_new(DECL_ERRVALUE, context->tok.id, decl->visibility); const char *name = enum_const->name; VECEACH(decl->enums.values, i) { Decl *other_constant = decl->enums.values[i]; if (other_constant->name == name) { - SEMA_TOKEN_ERROR(context->lex.tok, "This enum constant is declared twice."); + SEMA_TOKEN_ERROR(context->tok, "This enum constant is declared twice."); SEMA_PREV(other_constant, "The previous declaration was here."); decl_poison(enum_const); break; @@ -1862,7 +1829,7 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil * | type '(' opt_parameter_type_list ')' * ; */ -static inline bool parse_enum_spec(Context *context, TypeInfo **type_ref, Decl*** parameters_ref, Visibility parent_visibility) +static inline bool parse_enum_spec(ParseContext *context, TypeInfo **type_ref, Decl*** parameters_ref, Visibility parent_visibility) { ASSIGN_TYPE_ELSE(*type_ref, parse_type(context), false); @@ -1873,7 +1840,7 @@ static inline bool parse_enum_spec(Context *context, TypeInfo **type_ref, Decl** if (!parse_param_decl(context, parent_visibility, parameters_ref, true)) return false; if (VECLAST(*parameters_ref)->var.vararg) { - SEMA_TOKID_ERROR(context->lex.prev_tok, "Vararg parameters are not allowed as enum parameters."); + SEMA_TOKID_ERROR(context->prev_tok, "Vararg parameters are not allowed as enum parameters."); return false; } if (!try_consume(context, TOKEN_COMMA)) @@ -1906,13 +1873,13 @@ static inline bool parse_enum_spec(Context *context, TypeInfo **type_ref, Decl** * ; * */ -static inline Decl *parse_enum_declaration(Context *context, Visibility visibility) +static inline Decl *parse_enum_declaration(ParseContext *context, Visibility visibility) { advance_and_verify(context, TOKEN_ENUM); if (!consume_type_name(context, "enum")) return poisoned_decl; - Decl *decl = decl_new_with_type(context->lex.prev_tok, DECL_ENUM, visibility); + Decl *decl = decl_new_with_type(context->prev_tok, DECL_ENUM, visibility); TypeInfo *type = NULL; @@ -1926,14 +1893,14 @@ static inline Decl *parse_enum_declaration(Context *context, Visibility visibili decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span); while (!try_consume(context, TOKEN_RBRACE)) { - Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, context->lex.tok.id, decl->visibility); + Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, context->tok.id, decl->visibility); const char *name = enum_const->name; VECEACH(decl->enums.values, i) { Decl *other_constant = decl->enums.values[i]; if (other_constant->name == name) { - SEMA_TOKEN_ERROR(context->lex.tok, "This enum constant is declared twice."); + SEMA_TOKEN_ERROR(context->tok, "This enum constant is declared twice."); SEMA_PREV(other_constant, "The previous declaration was here."); decl_poison(enum_const); break; @@ -1989,9 +1956,9 @@ static inline Decl *parse_enum_declaration(Context *context, Visibility visibili * @param visibility * @return Decl* */ -static inline Decl *parse_func_definition(Context *context, Visibility visibility, bool is_interface) +static inline Decl *parse_func_definition(ParseContext *context, Visibility visibility, bool is_interface) { - Decl *func = decl_new(DECL_FUNC, context->lex.next_tok.id, visibility); + Decl *func = decl_new(DECL_FUNC, context->next_tok.id, visibility); if (TOKEN_IS(TOKEN_FUNC)) { advance_and_verify(context, TOKEN_FUNC); @@ -2018,7 +1985,7 @@ static inline Decl *parse_func_definition(Context *context, Visibility visibilit { if (TOKEN_IS(TOKEN_LBRACE)) { - SEMA_TOKEN_ERROR(context->lex.next_tok, "A function body is not allowed here."); + SEMA_TOKEN_ERROR(context->next_tok, "A function body is not allowed here."); return poisoned_decl; } TRY_CONSUME_OR(TOKEN_EOS, "Expected ';' after function declaration.", poisoned_decl); @@ -2034,15 +2001,15 @@ static inline Decl *parse_func_definition(Context *context, Visibility visibilit } -static inline bool check_no_visibility_before(Context *context, Visibility visibility) +static inline bool check_no_visibility_before(ParseContext *context, Visibility visibility) { switch (visibility) { case VISIBLE_MODULE: - SEMA_TOKEN_ERROR(context->lex.tok, "Unexpected 'static' before '%.*s'.", TOKLEN(context->lex.tok.id), TOKSTR(context->lex.tok.id)); + SEMA_TOKEN_ERROR(context->tok, "Unexpected 'static' before '%.*s'.", TOKLEN(context->tok.id), TOKSTR(context->tok.id)); return false; case VISIBLE_EXTERN: - SEMA_TOKEN_ERROR(context->lex.tok, "Unexpected 'extern' before '%.*s'.", TOKLEN(context->lex.tok.id), TOKSTR(context->lex.tok.id)); + SEMA_TOKEN_ERROR(context->tok, "Unexpected 'extern' before '%.*s'.", TOKLEN(context->tok.id), TOKSTR(context->tok.id)); return false; default: return true; @@ -2057,7 +2024,7 @@ static inline bool check_no_visibility_before(Context *context, Visibility visib * * @return true if import succeeded */ -static inline bool parse_import(Context *context) +static inline bool parse_import(ParseContext *context) { advance_and_verify(context, TOKEN_IMPORT); @@ -2067,15 +2034,15 @@ static inline bool parse_import(Context *context) { if (TOKEN_IS(TOKEN_STRING)) { - SEMA_TOKEN_ERROR(context->lex.tok, "An import should be followed by a plain identifier, not a string. Did you accidentally put the module name between \"\"?"); + SEMA_TOKEN_ERROR(context->tok, "An import should be followed by a plain identifier, not a string. Did you accidentally put the module name between \"\"?"); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "Import statement should be followed by the name of the module to import."); + SEMA_TOKEN_ERROR(context->tok, "Import statement should be followed by the name of the module to import."); return false; } Path *path = parse_module_path(context); - context_add_import(context, path, NO_TOKEN, NO_TOKEN, private); + unit_add_import(context->unit, path, NO_TOKEN, private); TRY_CONSUME_EOS_OR(false); return true; } @@ -2084,7 +2051,7 @@ static inline bool parse_import(Context *context) /** * imports ::= import* */ -void parse_imports(Context *context) +void parse_imports(ParseContext *context) { while (TOKEN_IS(TOKEN_IMPORT)) { @@ -2092,14 +2059,14 @@ void parse_imports(Context *context) } } -static inline TokenId parse_doc_opt_rest_of_line(Context *context) +static inline TokenId parse_doc_opt_rest_of_line(ParseContext *context) { - return try_consume(context, TOKEN_DOCS_LINE) ? context->lex.prev_tok : INVALID_TOKEN_ID; + return try_consume(context, TOKEN_DOCS_LINE) ? context->prev_tok : INVALID_TOKEN_ID; } -static inline bool parse_doc_param(Context *context, Ast *docs) +static inline bool parse_doc_param(ParseContext *context, Ast *docs) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_IDENT: case TOKEN_CT_IDENT: @@ -2112,27 +2079,27 @@ static inline bool parse_doc_param(Context *context, Ast *docs) case TOKEN_HASH_IDENT: break; default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a parameter name here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a parameter name here."); return false; } docs->doc_directive.kind = DOC_DIRECTIVE_PARAM; - docs->doc_directive.param.param = context->lex.tok.id; + docs->doc_directive.param.param = context->tok.id; advance(context); docs->doc_directive.param.rest_of_line = parse_doc_opt_rest_of_line(context); return true; } -static inline bool parse_doc_errors(Context *context, Ast *docs) +static inline bool parse_doc_errors(ParseContext *context, Ast *docs) { TODO while (1) { - if (context->lex.tok.type != TOKEN_TYPE_IDENT) + if (context->tok.type != TOKEN_TYPE_IDENT) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected an error type here."); + SEMA_TOKEN_ERROR(context->tok, "Expected an error type here."); } } - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_TYPE_IDENT: break; @@ -2140,13 +2107,13 @@ static inline bool parse_doc_errors(Context *context, Ast *docs) return false; } docs->doc_directive.kind = DOC_DIRECTIVE_PARAM; - docs->doc_directive.param.param = context->lex.tok.id; + docs->doc_directive.param.param = context->tok.id; advance(context); docs->doc_directive.param.rest_of_line = parse_doc_opt_rest_of_line(context); return true; } -static inline bool parse_doc_contract(Context *context, Ast *docs) +static inline bool parse_doc_contract(ParseContext *context, Ast *docs) { ASSIGN_EXPR_ELSE(docs->doc_directive.contract.decl_exprs, parse_cond(context), false); @@ -2157,12 +2124,12 @@ static inline bool parse_doc_contract(Context *context, Ast *docs) return true; } -static bool parse_docs(Context *context, Ast **docs) +static bool parse_docs(ParseContext *context, Ast **docs) { *docs = NULL; if (!try_consume(context, TOKEN_DOCS_START)) return true; - Ast *ast = new_ast(AST_DOCS, (SourceSpan) { .loc = context->lex.prev_tok, .end_loc = context->lex.prev_tok }); + Ast *ast = new_ast(AST_DOCS, (SourceSpan) { .loc = context->prev_tok, .end_loc = context->prev_tok }); while (!try_consume(context, TOKEN_DOCS_END)) { // Spin past the lines and line ends @@ -2170,8 +2137,8 @@ static bool parse_docs(Context *context, Ast **docs) if (try_consume(context, TOKEN_DOCS_LINE)) continue; CONSUME_OR(TOKEN_DOCS_DIRECTIVE, false); CONSUME_OR(TOKEN_IDENT, false); - const char *directive = TOKSTR(context->lex.prev_tok); - SourceSpan span = { context->lex.prev_tok, context->lex.prev_tok }; + const char *directive = TOKSTR(context->prev_tok); + SourceSpan span = { context->prev_tok, context->prev_tok }; Ast *doc_ast = new_ast(AST_DOC_DIRECTIVE, span); if (directive == kw_param) { @@ -2234,12 +2201,12 @@ LINE_END: * @param visibility * @return Decl* or a poison value if parsing failed */ -Decl *parse_top_level_statement(Context *context) +Decl *parse_top_level_statement(ParseContext *context) { Ast *docs = NULL; if (!parse_docs(context, &docs)) return poisoned_decl; Visibility visibility = VISIBLE_PUBLIC; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_PRIVATE: visibility = VISIBLE_MODULE; @@ -2253,16 +2220,16 @@ Decl *parse_top_level_statement(Context *context) } Decl *decl; - TokenType type = context->lex.tok.type; + TokenType type = context->tok.type; switch (type) { case TOKEN_DOCS_START: if (visibility != VISIBLE_PUBLIC) { - SEMA_TOKEN_ERROR(context->lex.tok, "Did not expect doc comments after visibility."); + SEMA_TOKEN_ERROR(context->tok, "Did not expect doc comments after visibility."); return poisoned_decl; } - SEMA_TOKEN_ERROR(context->lex.tok, "There are more than one doc comment in a row, that is not allowed."); + SEMA_TOKEN_ERROR(context->tok, "There are more than one doc comment in a row, that is not allowed."); return poisoned_decl; case TOKEN_DEFINE: { @@ -2345,21 +2312,21 @@ Decl *parse_top_level_statement(Context *context) case TOKEN_IDENT: return parse_global_declaration(context, visibility); case TOKEN_EOF: - SEMA_TOKID_ERROR(context->lex.prev_tok, "Expected a top level declaration"); + SEMA_TOKID_ERROR(context->prev_tok, "Expected a top level declaration"); return poisoned_decl; case TOKEN_CT_CONST_IDENT: - if (context->lex.next_tok.type == TOKEN_EQ) + if (context->next_tok.type == TOKEN_EQ) { - SEMA_TOKEN_ERROR(context->lex.tok, + SEMA_TOKEN_ERROR(context->tok, "Did you forget a 'const' before the name of this compile time constant?"); } else { - SEMA_TOKEN_ERROR(context->lex.tok, "Compile time constant unexpectedly found."); + SEMA_TOKEN_ERROR(context->tok, "Compile time constant unexpectedly found."); } return poisoned_decl; case TOKEN_IMPORT: - SEMA_TOKEN_ERROR(context->lex.tok, "Imports are only allowed directly after the module declaration."); + SEMA_TOKEN_ERROR(context->tok, "Imports are only allowed directly after the module declaration."); return poisoned_decl; case TOKEN_TLOCAL: case TYPELIKE_TOKENS: @@ -2368,7 +2335,7 @@ Decl *parse_top_level_statement(Context *context) break; } default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a top level declaration here."); + SEMA_TOKEN_ERROR(context->tok, "Expected a top level declaration here."); return poisoned_decl; break; } diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index d43053a95..a0ed40ac9 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -6,9 +6,9 @@ #include "parser_internal.h" -Ast *parse_unreachable_stmt(Context *context); +Ast *parse_unreachable_stmt(ParseContext *context); -Ast *parse_scoping_stmt(Context *context); +Ast *parse_scoping_stmt(ParseContext *context); // --- Internal functions @@ -17,18 +17,18 @@ Ast *parse_scoping_stmt(Context *context); * declaration_stmt * : declaration ';' */ -static inline Ast *parse_declaration_stmt(Context *context) +static inline Ast *parse_declaration_stmt(ParseContext *context) { - Ast *decl_stmt = AST_NEW_TOKEN(AST_DECLARE_STMT, context->lex.tok); + Ast *decl_stmt = AST_NEW_TOKEN(AST_DECLARE_STMT, context->tok); ASSIGN_DECL_ELSE(decl_stmt->declare_stmt, parse_decl(context), poisoned_ast); CONSUME_OR(TOKEN_EOS, poisoned_ast); return decl_stmt; } -static inline Decl *parse_optional_label(Context *context, Ast *parent) +static inline Decl *parse_optional_label(ParseContext *context, Ast *parent) { if (!TOKEN_IS(TOKEN_CONST_IDENT)) return NULL; - Decl *decl = decl_new(DECL_LABEL, context->lex.tok.id, VISIBLE_LOCAL); + Decl *decl = decl_new(DECL_LABEL, context->tok.id, VISIBLE_LOCAL); decl->label.parent = astid(parent); advance_and_verify(context, TOKEN_CONST_IDENT); if (!try_consume(context, TOKEN_COLON)) @@ -39,12 +39,12 @@ static inline Decl *parse_optional_label(Context *context, Ast *parent) return decl; } -static inline void parse_optional_label_target(Context *context, Label *label) +static inline void parse_optional_label_target(ParseContext *context, Label *label) { if (TOKEN_IS(TOKEN_CONST_IDENT)) { - label->span = context->lex.tok.id; - label->name = TOKSTR(context->lex.tok); + label->span = context->tok.id; + label->name = TOKSTR(context->tok); advance_and_verify(context, TOKEN_CONST_IDENT); } } @@ -54,9 +54,9 @@ static inline void parse_optional_label_target(Context *context, Label *label) * @param context * @return */ -static inline Ast* parse_asm_stmt(Context *context) +static inline Ast* parse_asm_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_ASM_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_ASM_STMT, context->tok); advance_and_verify(context, TOKEN_ASM); // TODO use attributes, like volatile CONSUME_OR(TOKEN_LPAREN, poisoned_ast); @@ -73,9 +73,9 @@ static inline Ast* parse_asm_stmt(Context *context) * do_stmt * : DO statement WHILE '(' expression ')' ';' */ -static inline Ast* parse_do_stmt(Context *context) +static inline Ast* parse_do_stmt(ParseContext *context) { - Ast *do_ast = AST_NEW_TOKEN(AST_DO_STMT, context->lex.tok); + Ast *do_ast = AST_NEW_TOKEN(AST_DO_STMT, context->tok); advance_and_verify(context, TOKEN_DO); @@ -98,11 +98,11 @@ static inline bool token_type_ends_case(TokenType type, TokenType case_type, Tok return type == case_type || type == default_type || type == TOKEN_RBRACE || type == TOKEN_CT_ENDSWITCH; } -static inline Ast *parse_case_stmts(Context *context, TokenType case_type, TokenType default_type) +static inline Ast *parse_case_stmts(ParseContext *context, TokenType case_type, TokenType default_type) { - if (token_type_ends_case(context->lex.tok.type, case_type, default_type)) return NULL; - Ast *compound = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->lex.tok); - while (!token_type_ends_case(context->lex.tok.type, case_type, default_type)) + if (token_type_ends_case(context->tok.type, case_type, default_type)) return NULL; + Ast *compound = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->tok); + while (!token_type_ends_case(context->tok.type, case_type, default_type)) { ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast); vec_add(compound->compound_stmt.stmts, stmt); @@ -116,10 +116,10 @@ static inline Ast *parse_case_stmts(Context *context, TokenType case_type, Token * defer_stmt * : DEFER statement */ -static inline Ast* parse_defer_stmt(Context *context) +static inline Ast* parse_defer_stmt(ParseContext *context) { advance_and_verify(context, TOKEN_DEFER); - Ast *defer_stmt = AST_NEW_TOKEN(AST_DEFER_STMT, context->lex.tok); + Ast *defer_stmt = AST_NEW_TOKEN(AST_DEFER_STMT, context->tok); ASSIGN_AST_ELSE(defer_stmt->defer_stmt.body, parse_stmt(context), poisoned_ast); return defer_stmt; } @@ -128,9 +128,9 @@ static inline Ast* parse_defer_stmt(Context *context) * while_stmt * : WHILE '(' control_expression ')' statement */ -static inline Ast* parse_while_stmt(Context *context) +static inline Ast* parse_while_stmt(ParseContext *context) { - Ast *while_ast = AST_NEW_TOKEN(AST_WHILE_STMT, context->lex.tok); + Ast *while_ast = AST_NEW_TOKEN(AST_WHILE_STMT, context->tok); advance_and_verify(context, TOKEN_WHILE); ASSIGN_DECL_ELSE(while_ast->while_stmt.flow.label, parse_optional_label(context, while_ast), poisoned_ast); @@ -161,18 +161,18 @@ static inline Ast* parse_while_stmt(Context *context) * | IF '(' control_expression ')' compound_statement ELSE compound_statement * ; */ -static inline Ast* parse_if_stmt(Context *context) +static inline Ast* parse_if_stmt(ParseContext *context) { - Ast *if_ast = AST_NEW_TOKEN(AST_IF_STMT, context->lex.tok); + Ast *if_ast = AST_NEW_TOKEN(AST_IF_STMT, context->tok); advance_and_verify(context, TOKEN_IF); ASSIGN_DECL_ELSE(if_ast->if_stmt.flow.label, parse_optional_label(context, if_ast), poisoned_ast); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); ASSIGN_EXPR_ELSE(if_ast->if_stmt.cond, parse_cond(context), poisoned_ast); CONSUME_OR(TOKEN_RPAREN, poisoned_ast); // Special case, we might have if ( ) { case ... } - if (tok_is(context, TOKEN_LBRACE) && (context->lex.next_tok.type == TOKEN_CASE || context->lex.next_tok.type == TOKEN_DEFAULT)) + if (tok_is(context, TOKEN_LBRACE) && (context->next_tok.type == TOKEN_CASE || context->next_tok.type == TOKEN_DEFAULT)) { - Ast *stmt = AST_NEW_TOKEN(AST_IF_CATCH_SWITCH_STMT, context->lex.tok); + Ast *stmt = AST_NEW_TOKEN(AST_IF_CATCH_SWITCH_STMT, context->tok); Ast **cases = NULL; if (!parse_switch_body(context, &cases, TOKEN_CASE, TOKEN_DEFAULT, true)) return poisoned_ast; stmt->switch_stmt.cases = cases; @@ -192,7 +192,7 @@ static inline Ast* parse_if_stmt(Context *context) -static bool parse_type_or_expr(Context *context, TypeInfo **type_info, Expr **expr) +static bool parse_type_or_expr(ParseContext *context, TypeInfo **type_info, Expr **expr) { if (parse_next_is_case_type(context)) { @@ -212,9 +212,9 @@ static bool parse_type_or_expr(Context *context, TypeInfo **type_info, Expr **ex * | CAST type ':' cast_stmts * ; */ -static inline Ast *parse_case_stmt(Context *context, TokenType case_type, TokenType default_type) +static inline Ast *parse_case_stmt(ParseContext *context, TokenType case_type, TokenType default_type) { - Ast *ast = AST_NEW_TOKEN(AST_CASE_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CASE_STMT, context->tok); advance(context); ASSIGN_EXPR_ELSE(ast->case_stmt.expr, parse_expr(context), poisoned_ast); // Change type -> type.typeid @@ -236,9 +236,9 @@ static inline Ast *parse_case_stmt(Context *context, TokenType case_type, TokenT * default_stmt * : DEFAULT ':' case_stmts */ -static inline Ast *parse_default_stmt(Context *context, TokenType case_type, TokenType default_type) +static inline Ast *parse_default_stmt(ParseContext *context, TokenType case_type, TokenType default_type) { - Ast *ast = AST_NEW_TOKEN(AST_DEFAULT_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_DEFAULT_STMT, context->tok); advance(context); TRY_CONSUME_OR(TOKEN_COLON, "Expected ':' after 'default'.", poisoned_ast); extend_ast_with_prev_token(context, ast); @@ -255,14 +255,14 @@ static inline Ast *parse_default_stmt(Context *context, TokenType case_type, Tok * | default_stmt switch body * ; */ -bool parse_switch_body(Context *context, Ast ***cases, TokenType case_type, TokenType default_type, +bool parse_switch_body(ParseContext *context, Ast ***cases, TokenType case_type, TokenType default_type, bool allow_multiple_values) { CONSUME_OR(TOKEN_LBRACE, false); while (!try_consume(context, TOKEN_RBRACE)) { Ast *result; - TokenType next = context->lex.tok.type; + TokenType next = context->tok.type; if (next == case_type) { ASSIGN_AST_ELSE(result, parse_case_stmt(context, case_type, default_type), false); @@ -273,7 +273,7 @@ bool parse_switch_body(Context *context, Ast ***cases, TokenType case_type, Toke } else { - SEMA_TOKEN_ERROR(context->lex.tok, "A 'case' or 'default' would be needed here, '%.*s' is not allowed.", TOKLEN(context->lex.tok.id), TOKSTR(context->lex.tok.id)); + SEMA_TOKEN_ERROR(context->tok, "A 'case' or 'default' would be needed here, '%.*s' is not allowed.", TOKLEN(context->tok.id), TOKSTR(context->tok.id)); return false; } vec_add((*cases), result); @@ -286,9 +286,9 @@ bool parse_switch_body(Context *context, Ast ***cases, TokenType case_type, Toke * switch * : SWITCH '(' decl_expr_list ')' '{' switch_body '}' */ -static inline Ast* parse_switch_stmt(Context *context) +static inline Ast* parse_switch_stmt(ParseContext *context) { - Ast *switch_ast = AST_NEW_TOKEN(AST_SWITCH_STMT, context->lex.tok); + Ast *switch_ast = AST_NEW_TOKEN(AST_SWITCH_STMT, context->tok); advance_and_verify(context, TOKEN_SWITCH); ASSIGN_DECL_ELSE(switch_ast->switch_stmt.flow.label, parse_optional_label(context, switch_ast), poisoned_ast); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); @@ -310,9 +310,9 @@ static inline Ast* parse_switch_stmt(Context *context) * | FOR '(' ';' expression ';' expression_list ')' statement * ; */ -static inline Ast* parse_for_stmt(Context *context) +static inline Ast* parse_for_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_FOR_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_FOR_STMT, context->tok); advance_and_verify(context, TOKEN_FOR); ASSIGN_DECL_ELSE(ast->for_stmt.flow.label, parse_optional_label(context, ast), poisoned_ast); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); @@ -347,7 +347,7 @@ static inline Ast* parse_for_stmt(Context *context) return ast; } -static inline bool parse_foreach_var(Context *context, Ast *foreach) +static inline bool parse_foreach_var(ParseContext *context, Ast *foreach) { TypeInfo *type = NULL; @@ -369,13 +369,13 @@ static inline bool parse_foreach_var(Context *context, Ast *foreach) { if (type) { - SEMA_TOKEN_ERROR(context->lex.tok, "Expected an identifier after the type."); + SEMA_TOKEN_ERROR(context->tok, "Expected an identifier after the type."); return false; } - SEMA_TOKEN_ERROR(context->lex.tok, "Expected an identifier or type."); + SEMA_TOKEN_ERROR(context->tok, "Expected an identifier or type."); return false; } - Decl *var = decl_new_var(context->lex.prev_tok, type, VARDECL_LOCAL, VISIBLE_LOCAL); + Decl *var = decl_new_var(context->prev_tok, type, VARDECL_LOCAL, VISIBLE_LOCAL); foreach->foreach_stmt.variable = var; return true; } @@ -384,9 +384,9 @@ static inline bool parse_foreach_var(Context *context, Ast *foreach) * : FOREACH (CONST_IDENT ':')? '(' type? '*'? IDENT (',' type? '*'? IDENT) ':' expression ')' statement * ; */ -static inline Ast* parse_foreach_stmt(Context *context) +static inline Ast* parse_foreach_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_FOREACH_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_FOREACH_STMT, context->tok); advance_and_verify(context, TOKEN_FOREACH); ASSIGN_DECL_ELSE(ast->foreach_stmt.flow.label, parse_optional_label(context, ast), poisoned_ast); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); @@ -421,9 +421,9 @@ static inline Ast* parse_foreach_stmt(Context *context) * continue_stmt * : CONTINUE */ -static inline Ast* parse_continue(Context *context) +static inline Ast* parse_continue(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CONTINUE_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CONTINUE_STMT, context->tok); advance_and_verify(context, TOKEN_CONTINUE); parse_optional_label_target(context, &ast->contbreak_stmt.label); if (ast->contbreak_stmt.label.name) ast->contbreak_stmt.is_label = true; @@ -436,13 +436,13 @@ static inline Ast* parse_continue(Context *context) * : NEXT * | NEXT expr */ -static inline Ast* parse_next(Context *context) +static inline Ast* parse_next(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_NEXT_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_NEXT_STMT, context->tok); advance_and_verify(context, TOKEN_NEXTCASE); if (!TOKEN_IS(TOKEN_EOS)) { - if (TOKEN_IS(TOKEN_CONST_IDENT) && context->lex.next_tok.type == TOKEN_COLON) + if (TOKEN_IS(TOKEN_CONST_IDENT) && context->next_tok.type == TOKEN_COLON) { parse_optional_label_target(context, &ast->next_stmt.label); advance_and_verify(context, TOKEN_COLON); @@ -467,9 +467,9 @@ static inline Ast* parse_next(Context *context) * break * : BREAK */ -static inline Ast* parse_break(Context *context) +static inline Ast* parse_break(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_BREAK_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_BREAK_STMT, context->tok); advance_and_verify(context, TOKEN_BREAK); parse_optional_label_target(context, &ast->contbreak_stmt.label); if (ast->contbreak_stmt.label.name) ast->contbreak_stmt.is_label = true; @@ -481,9 +481,9 @@ static inline Ast* parse_break(Context *context) * : expression EOS * ; */ -static inline Ast *parse_expr_stmt(Context *context) +static inline Ast *parse_expr_stmt(ParseContext *context) { - Ast *stmt = AST_NEW_TOKEN(AST_EXPR_STMT, context->lex.tok); + Ast *stmt = AST_NEW_TOKEN(AST_EXPR_STMT, context->tok); ASSIGN_EXPR_ELSE(stmt->expr_stmt, parse_expr(context), poisoned_ast); TRY_CONSUME_EOS(); return stmt; @@ -491,7 +491,7 @@ static inline Ast *parse_expr_stmt(Context *context) -static inline Ast *parse_decl_or_expr_stmt(Context *context) +static inline Ast *parse_decl_or_expr_stmt(ParseContext *context) { ASSIGN_EXPR_ELSE(Expr *expr, parse_expr(context), poisoned_ast); Ast *ast = ast_calloc(); @@ -524,16 +524,16 @@ static inline Ast *parse_decl_or_expr_stmt(Context *context) * | var CT_TYPE '=' const_expr EOS * ; */ -static inline Ast *parse_var_stmt(Context *context) +static inline Ast *parse_var_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_VAR_STMT, context->lex.tok); - TokenId start = context->lex.tok.id; + Ast *ast = AST_NEW_TOKEN(AST_VAR_STMT, context->tok); + TokenId start = context->tok.id; advance_and_verify(context, TOKEN_VAR); Decl *decl; - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_CT_IDENT: - decl = decl_new_var(context->lex.tok.id, NULL, VARDECL_LOCAL_CT, VISIBLE_LOCAL); + decl = decl_new_var(context->tok.id, NULL, VARDECL_LOCAL_CT, VISIBLE_LOCAL); advance(context); if (try_consume(context, TOKEN_EQ)) { @@ -541,7 +541,7 @@ static inline Ast *parse_var_stmt(Context *context) } break; case TOKEN_CT_TYPE_IDENT: - decl = decl_new_var(context->lex.tok.id, NULL, VARDECL_LOCAL_CT_TYPE, VISIBLE_LOCAL); + decl = decl_new_var(context->tok.id, NULL, VARDECL_LOCAL_CT_TYPE, VISIBLE_LOCAL); advance(context); if (try_consume(context, TOKEN_EQ)) { @@ -549,7 +549,7 @@ static inline Ast *parse_var_stmt(Context *context) } break; default: - SEMA_TOKEN_ERROR(context->lex.tok, "Expected a compile time variable name ('$Foo' or '$foo')."); + SEMA_TOKEN_ERROR(context->tok, "Expected a compile time variable name ('$Foo' or '$foo')."); return poisoned_ast; } decl->span.loc = start; @@ -560,12 +560,12 @@ static inline Ast *parse_var_stmt(Context *context) return ast; } -static inline Ast* parse_ct_compound_stmt(Context *context) +static inline Ast* parse_ct_compound_stmt(ParseContext *context) { - Ast *stmts = AST_NEW_TOKEN(AST_CT_COMPOUND_STMT, context->lex.tok); + Ast *stmts = AST_NEW_TOKEN(AST_CT_COMPOUND_STMT, context->tok); while (1) { - TokenType token = context->lex.tok.type; + TokenType token = context->tok.type; if (token == TOKEN_CT_ELSE || token == TOKEN_CT_ELIF || token == TOKEN_CT_ENDIF) break; ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast); vec_add(stmts->compound_stmt.stmts, stmt); @@ -578,9 +578,9 @@ static inline Ast* parse_ct_compound_stmt(Context *context) * ct_else_stmt * : CT_ELSE ':' ct_compound_stmt */ -static inline Ast* parse_ct_else_stmt(Context *context) +static inline Ast* parse_ct_else_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_ELSE_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_ELSE_STMT, context->tok); advance_and_verify(context, TOKEN_CT_ELSE); TRY_CONSUME(TOKEN_COLON, "$else needs a ':', did you forget it?"); ASSIGN_AST_ELSE(ast->ct_else_stmt, parse_ct_compound_stmt(context), poisoned_ast); @@ -591,9 +591,9 @@ static inline Ast* parse_ct_else_stmt(Context *context) * ct_elif_stmt * : CT_ELIF '(' expression ')' ':' ct_compound_stmt (ct_elif_stmt | ct_else_stmt)? */ -static inline Ast *parse_ct_elif_stmt(Context *context) +static inline Ast *parse_ct_elif_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_ELIF_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_ELIF_STMT, context->tok); advance_and_verify(context, TOKEN_CT_ELIF); ASSIGN_EXPR_ELSE(ast->ct_elif_stmt.expr, parse_const_paren_expr(context), poisoned_ast); TRY_CONSUME(TOKEN_COLON, "$elif needs a ':' after the expression, did you forget it?"); @@ -615,9 +615,9 @@ static inline Ast *parse_ct_elif_stmt(Context *context) * : CT_IF '(' expression ')' ':' ct_compound_stmt (ct_elif_stmt | ct_else_stmt) CT_ENDIF EOS * ; */ -static inline Ast* parse_ct_if_stmt(Context *context) +static inline Ast* parse_ct_if_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_IF_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_IF_STMT, context->tok); advance_and_verify(context, TOKEN_CT_IF); ASSIGN_EXPR_ELSE(ast->ct_if_stmt.expr, parse_const_paren_expr(context), poisoned_ast); TRY_CONSUME(TOKEN_COLON, "$if needs a ':' after the expression, did you forget it?"); @@ -645,10 +645,10 @@ static inline Ast* parse_ct_if_stmt(Context *context) * | RETURN * ; */ -static inline Ast *parse_return(Context *context) +static inline Ast *parse_return(ParseContext *context) { advance_and_verify(context, TOKEN_RETURN); - Ast *ast = AST_NEW_TOKEN(AST_RETURN_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_RETURN_STMT, context->tok); ast->return_stmt.defer = 0; if (!TOKEN_IS(TOKEN_EOS)) { @@ -671,18 +671,18 @@ static inline Ast *parse_return(Context *context) * * @return */ -static inline Ast* parse_ct_for_stmt(Context *context) +static inline Ast* parse_ct_for_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_FOR_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_FOR_STMT, context->tok); advance_and_verify(context, TOKEN_CT_FOR); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); - if (context->lex.next_tok.type == TOKEN_COMMA) + if (context->next_tok.type == TOKEN_COMMA) { - ast->ct_for_stmt.index = context->lex.tok.id; + ast->ct_for_stmt.index = context->tok.id; TRY_CONSUME_OR(TOKEN_CT_IDENT, "Expected a compile time index variable", poisoned_ast); advance_and_verify(context, TOKEN_COMMA); } - ast->ct_for_stmt.value = context->lex.tok.id; + ast->ct_for_stmt.value = context->tok.id; TRY_CONSUME_OR(TOKEN_CT_IDENT, "Expected a compile time variable", poisoned_ast); TRY_CONSUME_OR(TOKEN_COLON, "Expected ':'.", poisoned_ast); ASSIGN_EXPR_ELSE(ast->ct_for_stmt.expr, parse_expr(context), poisoned_ast); @@ -707,9 +707,9 @@ static inline Ast* parse_ct_for_stmt(Context *context) * * @return */ -static inline Ast* parse_ct_switch_stmt(Context *context) +static inline Ast* parse_ct_switch_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_SWITCH_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_SWITCH_STMT, context->tok); advance_and_verify(context, TOKEN_CT_SWITCH); ASSIGN_EXPR_ELSE(ast->ct_switch_stmt.cond, parse_const_paren_expr(context), poisoned_ast); TRY_CONSUME(TOKEN_COLON, "Expected ':' after $switch expression, did you forget it?"); @@ -717,7 +717,7 @@ static inline Ast* parse_ct_switch_stmt(Context *context) while (!try_consume(context, TOKEN_CT_ENDSWITCH)) { Ast *result; - TokenType next = context->lex.tok.type; + TokenType next = context->tok.type; if (next == TOKEN_CT_CASE) { ASSIGN_AST_ELSE(result, parse_case_stmt(context, TOKEN_CT_CASE, TOKEN_CT_DEFAULT), poisoned_ast); @@ -728,7 +728,7 @@ static inline Ast* parse_ct_switch_stmt(Context *context) } else { - SEMA_TOKEN_ERROR(context->lex.tok, "A '$case' or '$default' would be needed here, '%.*s' is not allowed.", TOKLEN(context->lex.tok.id), TOKSTR(context->lex.tok.id)); + SEMA_TOKEN_ERROR(context->tok, "A '$case' or '$default' would be needed here, '%.*s' is not allowed.", TOKLEN(context->tok.id), TOKSTR(context->tok.id)); return poisoned_ast; } vec_add(cases, result); @@ -738,9 +738,9 @@ static inline Ast* parse_ct_switch_stmt(Context *context) return ast; } -static inline Ast *parse_assert_stmt(Context *context) +static inline Ast *parse_assert_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_ASSERT_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_ASSERT_STMT, context->tok); advance_and_verify(context, TOKEN_ASSERT); TRY_CONSUME_OR(TOKEN_LPAREN, "'assert' needs a '(' here, did you forget it?", poisoned_ast); ASSIGN_EXPR_ELSE(ast->assert_stmt.expr, parse_assert_expr(context), poisoned_ast); @@ -761,9 +761,9 @@ static inline Ast *parse_assert_stmt(Context *context) * @param context * @return */ -Ast *parse_ct_assert_stmt(Context *context) +Ast *parse_ct_assert_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_CT_ASSERT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_CT_ASSERT, context->tok); advance_and_verify(context, TOKEN_CT_ASSERT); TRY_CONSUME_OR(TOKEN_LPAREN, "'$assert' needs a '(' here, did you forget it?", poisoned_ast); ASSIGN_EXPR_ELSE(ast->ct_assert_stmt.expr, parse_constant_expr(context), poisoned_ast); @@ -777,9 +777,9 @@ Ast *parse_ct_assert_stmt(Context *context) return ast; } -Ast *parse_stmt(Context *context) +Ast *parse_stmt(ParseContext *context) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_ASM_STRING: case TOKEN_ASM_CONSTRAINT: @@ -829,7 +829,7 @@ Ast *parse_stmt(Context *context) RETURN_AFTER_EOS(ast); } case TOKEN_CASE: - SEMA_TOKEN_ERROR(context->lex.tok, "'case' was found outside of 'switch', did you mismatch a '{ }' pair?"); + SEMA_TOKEN_ERROR(context->tok, "'case' was found outside of 'switch', did you mismatch a '{ }' pair?"); advance(context); return poisoned_ast; case TOKEN_BREAK: @@ -845,7 +845,7 @@ Ast *parse_stmt(Context *context) case TOKEN_ASM: return parse_asm_stmt(context); case TOKEN_DEFAULT: - SEMA_TOKEN_ERROR(context->lex.tok, "'default' was found outside of 'switch', did you mismatch a '{ }' pair?"); + SEMA_TOKEN_ERROR(context->tok, "'default' was found outside of 'switch', did you mismatch a '{ }' pair?"); advance(context); return poisoned_ast; case TOKEN_CT_ASSERT: @@ -967,28 +967,28 @@ Ast *parse_stmt(Context *context) case TOKEN_BITSTRUCT: case TOKEN_LVEC: case TOKEN_RVEC: - SEMA_TOKEN_ERROR(context->lex.tok, "Unexpected '%s' found when expecting a statement.", token_type_to_string(context->lex.tok.type)); + SEMA_TOKEN_ERROR(context->tok, "Unexpected '%s' found when expecting a statement.", token_type_to_string(context->tok.type)); advance(context); return poisoned_ast; case TOKEN_RPAREN: case TOKEN_RBRACE: case TOKEN_RBRACKET: - SEMA_TOKEN_ERROR(context->lex.tok, "Mismatched '%s' found.", token_type_to_string(context->lex.tok.type)); + SEMA_TOKEN_ERROR(context->tok, "Mismatched '%s' found.", token_type_to_string(context->tok.type)); advance(context); return poisoned_ast; case TOKEN_EOS: advance(context); - return AST_NEW_TOKEN(AST_NOP_STMT, context->lex.tok); + return AST_NEW_TOKEN(AST_NOP_STMT, context->tok); case TOKEN_EOF: - SEMA_TOKID_ERROR(context->lex.tok.id, "Reached the end of the file when expecting a statement."); + SEMA_TOKID_ERROR(context->tok.id, "Reached the end of the file when expecting a statement."); return poisoned_ast; } UNREACHABLE } -Ast *parse_scoping_stmt(Context *context) +Ast *parse_scoping_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_SCOPING_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_SCOPING_STMT, context->tok); advance_and_verify(context, TOKEN_SCOPING); CONSUME_OR(TOKEN_LPAREN, poisoned_ast); ASSIGN_EXPR_ELSE(ast->scoping_stmt.scoped, parse_expression_list(context, false), poisoned_ast); @@ -997,17 +997,17 @@ Ast *parse_scoping_stmt(Context *context) return ast; } -Ast *parse_unreachable_stmt(Context *context) +Ast *parse_unreachable_stmt(ParseContext *context) { - Ast *ast = AST_NEW_TOKEN(AST_UNREACHABLE_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_UNREACHABLE_STMT, context->tok); advance_and_verify(context, TOKEN_CT_UNREACHABLE); TRY_CONSUME_EOS_OR(poisoned_ast); return ast; } -Ast *parse_jump_stmt_no_eos(Context *context) +Ast *parse_jump_stmt_no_eos(ParseContext *context) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_NEXTCASE: return parse_next(context); @@ -1036,10 +1036,10 @@ Ast *parse_jump_stmt_no_eos(Context *context) * @param context * @return a compound statement */ -Ast* parse_compound_stmt(Context *context) +Ast* parse_compound_stmt(ParseContext *context) { CONSUME_OR(TOKEN_LBRACE, poisoned_ast); - Ast *ast = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->lex.tok); + Ast *ast = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->tok); while (!try_consume(context, TOKEN_RBRACE)) { ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 78def9d5d..7e8a4f094 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -12,26 +12,26 @@ * * @param context the current context. */ -inline void advance(Context *context) +inline void advance(ParseContext *context) { context->lead_comment = context->next_lead_comment; context->trailing_comment = NULL; context->next_lead_comment = NULL; - context->lex.prev_tok = context->lex.tok.id; - context->lex.tok = context->lex.next_tok; + context->prev_tok = context->tok.id; + context->tok = context->next_tok; while (1) { - if (context->lex.tok.type == TOKEN_EOF) + if (context->tok.type == TOKEN_EOF) { - context->lex.next_tok = context->lex.tok; + context->next_tok = context->tok; return; } - uint32_t index = context->lex.lexer_index++; + uint32_t index = context->lexer_index++; TokenType next_type = (TokenType)(*toktypeptr(index)); - context->lex.next_tok.id.index = index; - context->lex.next_tok.type = next_type; + context->next_tok.id.index = index; + context->next_tok.type = next_type; // At this point we should not have any invalid tokens. assert(next_type != TOKEN_INVALID_TOKEN); @@ -39,7 +39,7 @@ inline void advance(Context *context) // Walk through any regular comments if (next_type == TOKEN_COMMENT) { - vec_add(context->comments, context->lex.next_tok); + vec_add(context->comments, context->next_tok); continue; } @@ -47,14 +47,14 @@ inline void advance(Context *context) if (next_type != TOKEN_DOC_COMMENT) return; { - SourceLocation *curr = TOKLOC(context->lex.tok); - SourceLocation *next = TOKLOC(context->lex.next_tok); - vec_add(context->comments, context->lex.next_tok); + SourceLocation *curr = TOKLOC(context->tok); + SourceLocation *next = TOKLOC(context->next_tok); + vec_add(context->comments, context->next_tok); if (curr->row == next->row) { if (context->trailing_comment) { - SEMA_TOKEN_ERROR(context->lex.next_tok, + SEMA_TOKEN_ERROR(context->next_tok, "You have multiple trailing doc-style comments, should the second one go on the next line?"); } else @@ -66,7 +66,7 @@ inline void advance(Context *context) { if (context->lead_comment) { - SEMA_TOKEN_ERROR(context->lex.next_tok, + SEMA_TOKEN_ERROR(context->next_tok, "You have multiple doc-style comments in a row, are all of them really meant to document the code that follows?"); } else @@ -79,9 +79,9 @@ inline void advance(Context *context) } -bool try_consume(Context *context, TokenType type) +bool try_consume(ParseContext *context, TokenType type) { - if (context->lex.tok.type == type) + if (context->tok.type == type) { advance(context); return true; @@ -89,7 +89,7 @@ bool try_consume(Context *context, TokenType type) return false; } -bool consume(Context *context, TokenType type, const char *message, ...) +bool consume(ParseContext *context, TokenType type, const char *message, ...) { if (try_consume(context, type)) { @@ -98,7 +98,7 @@ bool consume(Context *context, TokenType type, const char *message, ...) va_list args; va_start(args, message); - sema_verror_range(TOKLOC(context->lex.tok), message, args); + sema_verror_range(TOKLOC(context->tok), message, args); va_end(args); return false; } @@ -110,7 +110,7 @@ bool consume(Context *context, TokenType type, const char *message, ...) * module? imports top_level_statement* * @param context */ -static inline void parse_translation_unit(Context *context) +static inline void parse_translation_unit(ParseContext *context) { // Prime everything advance(context); @@ -122,10 +122,9 @@ static inline void parse_translation_unit(Context *context) { if (TOKEN_IS(TOKEN_MODULE)) { - Context *new_context = context_create(context->file); - new_context->lead_comment = context->lead_comment; - new_context->next_lead_comment = context->next_lead_comment; - new_context->lex = context->lex; + ParseContext *new_context = CALLOCS(ParseContext); + *new_context = *context; + new_context->unit = unit_create(context->unit->file); context = new_context; goto NEXT_CONTEXT; } @@ -133,7 +132,7 @@ static inline void parse_translation_unit(Context *context) if (!decl) continue; if (decl_ok(decl)) { - vec_add(context->global_decls, decl); + vec_add(context->unit->global_decls, decl); } else { @@ -154,9 +153,10 @@ bool parse_file(File *file) Lexer lexer = { .file = file }; lexer_lex_file(&lexer); if (global_context.errors_found) return false; - Context *context = context_create(file); - context->lex.lexer_index = lexer.token_start_id; - parse_translation_unit(context); + CompilationUnit *unit = unit_create(file); + ParseContext lex_context = { .lexer_index = lexer.token_start_id, + .unit = unit }; + parse_translation_unit(&lex_context); return !global_context.errors_found; } diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index 116a80264..6ef1cb484 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -4,14 +4,14 @@ // Use of this source code is governed by a LGPLv3.0 // a copy of which can be found in the LICENSE file. -#define TOKEN_IS(_type) (context->lex.tok.type == _type) +#define TOKEN_IS(_type) (context->tok.type == _type) #define EXPECT_IDENT_FOR_OR(_name, _res) do { if (!expect_ident(context, _name)) return _res; } while(0) #define EXPECT_OR(_tok, _res) do { if (!expect(context, _tok)) return _res; } while(0) #define CONSUME_OR(_tok, _res) do { if (!expect(context, _tok)) return _res; advance(context); } while(0) -#define TRY_EXPECT_OR(_tok, _message, _type) do { if (context->lex.tok.type != _tok) { SEMA_TOKEN_ERROR(context->lex.tok, _message); return _type; } } while(0) +#define TRY_EXPECT_OR(_tok, _message, _type) do { if (context->tok.type != _tok) { SEMA_TOKEN_ERROR(context->tok, _message); return _type; } } while(0) #define TRY_CONSUME_OR(_tok, _message, _type) do { if (!consume(context, _tok, _message)) return _type; } while(0) #define TRY_CONSUME(_tok, _message) TRY_CONSUME_OR(_tok, _message, poisoned_ast) -#define TRY_CONSUME_EOS_OR(_res) do { if (!TOKEN_IS(TOKEN_EOS)) { sema_error_at_prev_end(context->lex.tok, "Expected ';'"); return _res; } advance(context); } while(0) +#define TRY_CONSUME_EOS_OR(_res) do { if (!TOKEN_IS(TOKEN_EOS)) { sema_error_at_prev_end(context->tok, "Expected ';'"); return _res; } advance(context); } while(0) #define TRY_CONSUME_EOS() TRY_CONSUME_EOS_OR(poisoned_ast) #define RETURN_AFTER_EOS(_ast) extend_ast_with_prev_token(context, ast); TRY_CONSUME_EOS_OR(poisoned_ast); return _ast @@ -20,59 +20,59 @@ #define COMMA_RPAREN_OR(_res) \ do { if (!try_consume(context, TOKEN_COMMA) && !TOKEN_IS(TOKEN_RPAREN)) { \ -SEMA_TOKEN_ERROR(context->lex.tok, "Expected ',' or ')'"); return _res; } } while(0) +SEMA_TOKEN_ERROR(context->tok, "Expected ',' or ')'"); return _res; } } while(0) -Decl *parse_top_level_statement(Context *context); -Ast *parse_ct_assert_stmt(Context *context); -Ast *parse_stmt(Context *context); -Path *parse_path_prefix(Context *context, bool *had_error); -Expr *parse_type_expression_with_path(Context *context, Path *path); -Expr *parse_expr(Context *context); -bool consume_ident(Context *context, const char* name); -TypeInfo *parse_type(Context *context); -TypeInfo *parse_failable_type(Context *context); -TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info); -Expr* parse_constant_expr(Context *context); -Expr *parse_initializer(Context *context); -void parse_imports(Context *context); -Decl *parse_decl(Context *context); -void recover_top_level(Context *context); -Expr *parse_cond(Context *context); -Expr *parse_assert_expr(Context *context); -Ast* parse_compound_stmt(Context *context); -Ast *parse_jump_stmt_no_eos(Context *context); -bool parse_attributes(Context *context, Attr ***attributes_ref); +Decl *parse_top_level_statement(ParseContext *context); +Ast *parse_ct_assert_stmt(ParseContext *context); +Ast *parse_stmt(ParseContext *context); +Path *parse_path_prefix(ParseContext *context, bool *had_error); +Expr *parse_type_expression_with_path(ParseContext *context, Path *path); +Expr *parse_expr(ParseContext *context); +bool consume_ident(ParseContext *context, const char* name); +TypeInfo *parse_type(ParseContext *context); +TypeInfo *parse_failable_type(ParseContext *context); +TypeInfo *parse_type_with_base(ParseContext *context, TypeInfo *type_info); +Expr* parse_constant_expr(ParseContext *context); +Expr *parse_initializer(ParseContext *context); +void parse_imports(ParseContext *context); +Decl *parse_decl(ParseContext *context); +void recover_top_level(ParseContext *context); +Expr *parse_cond(ParseContext *context); +Expr *parse_assert_expr(ParseContext *context); +Ast* parse_compound_stmt(ParseContext *context); +Ast *parse_jump_stmt_no_eos(ParseContext *context); +bool parse_attributes(ParseContext *context, Attr ***attributes_ref); -bool parse_switch_body(Context *context, Ast ***cases, TokenType case_type, TokenType default_type, +bool parse_switch_body(ParseContext *context, Ast ***cases, TokenType case_type, TokenType default_type, bool allow_multiple_values); -Expr *parse_expression_list(Context *context, bool allow_decls); -Decl *parse_decl_after_type(Context *context, TypeInfo *type); +Expr *parse_expression_list(ParseContext *context, bool allow_decls); +Decl *parse_decl_after_type(ParseContext *context, TypeInfo *type); -bool parse_parameters(Context *context, Visibility visibility, Decl ***params_ref); -bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool *unsplat); -Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *type_info); +bool parse_parameters(ParseContext *context, Visibility visibility, Decl ***params_ref); +bool parse_arg_list(ParseContext *context, Expr ***result, TokenType param_end, bool *unsplat); +Expr *parse_type_compound_literal_expr_after_type(ParseContext *context, TypeInfo *type_info); -bool parse_next_is_decl(Context *context); -bool parse_next_is_case_type(Context *context); -bool parse_next_is_type(Context *context); -bool parse_module(Context *context); +bool parse_next_is_decl(ParseContext *context); +bool parse_next_is_case_type(ParseContext *context); +bool parse_next_is_type(ParseContext *context); +bool parse_module(ParseContext *unit); -bool try_consume(Context *context, TokenType type); -bool consume(Context *context, TokenType type, const char *message, ...); -bool consume_const_name(Context *context, const char* type); -Expr *parse_precedence_with_left_side(Context *context, Expr *left_side, Precedence precedence); +bool try_consume(ParseContext *context, TokenType type); +bool consume(ParseContext *context, TokenType type, const char *message, ...); +bool consume_const_name(ParseContext *context, const char* type); +Expr *parse_precedence_with_left_side(ParseContext *context, Expr *left_side, Precedence precedence); -static inline bool tok_is(Context *context, TokenType type) +static inline bool tok_is(ParseContext *context, TokenType type) { - return context->lex.tok.type == type; + return context->tok.type == type; } -static inline bool expect(Context *context, TokenType token_type) +static inline bool expect(ParseContext *context, TokenType token_type) { - if (token_type == context->lex.tok.type) return true; + if (token_type == context->tok.type) return true; - SEMA_TOKEN_ERROR(context->lex.tok, "Expected '%s'.", token_type_to_string(token_type)); + SEMA_TOKEN_ERROR(context->tok, "Expected '%s'.", token_type_to_string(token_type)); return false; } @@ -96,23 +96,23 @@ static inline bool token_is_keyword(TokenType token_type) return false; } -static inline bool expect_ident(Context *context, const char* name) +static inline bool expect_ident(ParseContext *context, const char* name) { - switch (context->lex.tok.type) + switch (context->tok.type) { case TOKEN_IDENT: return true; case TOKEN_TYPE_IDENT: case TOKEN_CONST_IDENT: - SEMA_TOKEN_ERROR(context->lex.tok, "A %s cannot start with a capital letter.", name); + SEMA_TOKEN_ERROR(context->tok, "A %s cannot start with a capital letter.", name); return false; default: - SEMA_TOKEN_ERROR(context->lex.tok, "A %s was expected.", name); + SEMA_TOKEN_ERROR(context->tok, "A %s was expected.", name); return false; } } -static inline Expr *parse_const_paren_expr(Context *context) +static inline Expr *parse_const_paren_expr(ParseContext *context) { CONSUME_OR(TOKEN_LPAREN, poisoned_expr); ASSIGN_EXPR_ELSE(Expr *expr, parse_constant_expr(context), poisoned_expr); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index e78617487..070771d8f 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -7,9 +7,9 @@ -static bool sema_analyse_struct_union(Context *context, Decl *decl); +static bool sema_analyse_struct_union(SemaContext *context, Decl *decl); -static bool sema_check_section(Context *context, Decl *decl, Attr *attr) +static bool sema_check_section(SemaContext *context, Decl *decl, Attr *attr) { const char *section_string = attr->expr->const_expr.string.chars; decl->section = section_string; @@ -70,7 +70,7 @@ static inline bool sema_check_no_duplicate_parameter(Decl **decls, Decl *current -static inline bool sema_analyse_struct_member(Context *context, Decl *decl) +static inline bool sema_analyse_struct_member(SemaContext *context, Decl *decl) { if (decl->name) { @@ -112,7 +112,7 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl) } } -static bool sema_analyse_union_members(Context *context, Decl *decl, Decl **members) +static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl **members) { AlignSize max_size = 0; MemberIndex max_alignment_element = 0; @@ -209,7 +209,7 @@ static bool sema_analyse_union_members(Context *context, Decl *decl, Decl **memb return true; } -static bool sema_analyse_struct_members(Context *context, Decl *decl, Decl **members) +static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl **members) { // Default alignment is 1 even if it is empty. AlignSize natural_alignment = 1; @@ -351,7 +351,7 @@ static bool sema_analyse_struct_members(Context *context, Decl *decl, Decl **mem return true; } -static bool sema_analyse_struct_union(Context *context, Decl *decl) +static bool sema_analyse_struct_union(SemaContext *context, Decl *decl) { AttributeDomain domain; switch (decl->decl_kind) @@ -444,7 +444,7 @@ static bool sema_analyse_struct_union(Context *context, Decl *decl) return decl_ok(decl); } -static inline bool sema_analyse_bitstruct_member(Context *context, Decl *decl, unsigned index, bool allow_overlap) +static inline bool sema_analyse_bitstruct_member(SemaContext *context, Decl *decl, unsigned index, bool allow_overlap) { Decl **members = decl->strukt.members; Decl *member = members[index]; @@ -536,7 +536,7 @@ static inline bool sema_analyse_bitstruct_member(Context *context, Decl *decl, u return true; } -static bool sema_analyse_bitstruct(Context *context, Decl *decl) +static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl) { VECEACH(decl->attributes, i) { @@ -608,7 +608,7 @@ static bool sema_analyse_bitstruct(Context *context, Decl *decl) } -static inline bool sema_analyse_function_param(Context *context, Decl *param, bool is_function, bool *has_default) +static inline bool sema_analyse_function_param(SemaContext *context, Decl *param, bool is_function, bool *has_default) { *has_default = false; assert(param->decl_kind == DECL_VAR); @@ -656,7 +656,7 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo return true; } -static inline Type *sema_analyse_function_signature(Context *context, FunctionSignature *signature, bool is_real_function) +static inline Type *sema_analyse_function_signature(SemaContext *context, FunctionSignature *signature, bool is_real_function) { bool all_ok = true; all_ok = sema_resolve_type_info(context, signature->rtype) && all_ok; @@ -693,7 +693,7 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi return type_find_function_type(signature); } -static inline bool sema_analyse_typedef(Context *context, Decl *decl) +static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl) { if (decl->typedef_decl.is_func) { @@ -714,7 +714,7 @@ static inline bool sema_analyse_typedef(Context *context, Decl *decl) return true; } -static inline bool sema_analyse_distinct(Context *context, Decl *decl) +static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl) { if (decl->distinct_decl.typedef_decl.is_func) { @@ -767,7 +767,7 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl) return true; } -static inline bool sema_analyse_enum(Context *context, Decl *decl) +static inline bool sema_analyse_enum(SemaContext *context, Decl *decl) { // Resolve the type of the enum. if (!sema_resolve_type_info(context, decl->enums.type_info)) return false; @@ -855,7 +855,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl) return success; } -static inline bool sema_analyse_error(Context *context, Decl *decl) +static inline bool sema_analyse_error(SemaContext *context, Decl *decl) { bool success = true; unsigned enums = vec_size(decl->enums.values); @@ -915,7 +915,7 @@ static inline void find_operator_parameters(Decl *method, TypeInfo **rtype_ptr, } -static bool sema_analyse_operator_common(Context *context, Decl *method, TypeInfo **rtype_ptr, Decl ***params_ptr, uint32_t parameters) +static bool sema_analyse_operator_common(Decl *method, TypeInfo **rtype_ptr, Decl ***params_ptr, uint32_t parameters) { find_operator_parameters(method, rtype_ptr, params_ptr); Decl **params = *params_ptr; @@ -948,11 +948,11 @@ static bool sema_analyse_operator_common(Context *context, Decl *method, TypeInf return true; } -Decl *sema_find_operator(Context *context, Expr *expr, const char *kw) +Decl *sema_find_operator(SemaContext *context, Expr *expr, const char *kw) { Decl *ambiguous = NULL; Decl *private = NULL; - Decl *method = type_may_have_sub_elements(expr->type) ? sema_resolve_method(context, expr->type->decl, kw, &ambiguous, &private) : NULL; + Decl *method = type_may_have_sub_elements(expr->type) ? sema_resolve_method(context->unit, expr->type->decl, kw, &ambiguous, &private) : NULL; if (!decl_ok(method)) return NULL; if (!method) { @@ -975,11 +975,11 @@ Decl *sema_find_operator(Context *context, Expr *expr, const char *kw) return method; } -static inline bool sema_analyse_operator_element_at(Context *context, Decl *method) +static inline bool sema_analyse_operator_element_at(Decl *method) { TypeInfo *rtype; Decl **params; - if (!sema_analyse_operator_common(context, method, &rtype, ¶ms, 2)) return false; + if (!sema_analyse_operator_common(method, &rtype, ¶ms, 2)) return false; if (rtype->type->canonical == type_void) { SEMA_ERROR(rtype, "The return type cannot be 'void'."); @@ -988,11 +988,11 @@ static inline bool sema_analyse_operator_element_at(Context *context, Decl *meth return true; } -static inline bool sema_analyse_operator_len(Context *context, Decl *method) +static inline bool sema_analyse_operator_len(Decl *method) { TypeInfo *rtype; Decl **params; - if (!sema_analyse_operator_common(context, method, &rtype, ¶ms, 1)) return false; + if (!sema_analyse_operator_common(method, &rtype, ¶ms, 1)) return false; if (!type_is_integer(rtype->type)) { SEMA_ERROR(rtype, "The return type must be an integer type."); @@ -1001,25 +1001,25 @@ static inline bool sema_analyse_operator_len(Context *context, Decl *method) return true; } -static bool sema_check_operator_method_validity(Context *context, Decl *method) +static bool sema_check_operator_method_validity(Decl *method) { if (method->name == kw_operator_element_at || method->name == kw_operator_element_at_ref) { - return sema_analyse_operator_element_at(context, method); + return sema_analyse_operator_element_at(method); } if (method->name == kw_operator_len) { - return sema_analyse_operator_len(context, method); + return sema_analyse_operator_len(method); } return true; } -static inline bool sema_add_method_like(Context *context, Type *parent_type, Decl *method_like) +static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type, Decl *method_like) { assert(parent_type->canonical == parent_type); Decl *parent = parent_type->decl; const char *name = method_like->name; - Decl *method = sema_find_extension_method_in_module(context->module, parent_type, name); + Decl *method = sema_find_extension_method_in_module(unit->module, parent_type, name); if (method) { SEMA_TOKID_ERROR(method_like->name_token, "This %s is already defined in this module.", name_by_decl(method_like)); @@ -1028,14 +1028,14 @@ static inline bool sema_add_method_like(Context *context, Type *parent_type, Dec } Decl *ambiguous = NULL; Decl *private = NULL; - method = sema_resolve_method(context, parent, name, &ambiguous, &private); + method = sema_resolve_method(unit, parent, name, &ambiguous, &private); if (method) { SEMA_TOKID_ERROR(method_like->name_token, "This %s is already defined for '%s'.", name_by_decl(method_like), parent_type->name); SEMA_TOKID_PREV(method->name_token, "The previous definition was here."); return false; } - if (!sema_check_operator_method_validity(context, method_like)) return false; + if (!sema_check_operator_method_validity(method_like)) return false; scratch_buffer_clear(); if (method_like->visibility <= VISIBLE_MODULE) { @@ -1051,19 +1051,19 @@ static inline bool sema_add_method_like(Context *context, Type *parent_type, Dec } method_like->external_name = scratch_buffer_interned(); DEBUG_LOG("Method-like '%s.%s' analysed.", parent->name, method_like->name); - if (parent->module == context->module) + if (parent->module == unit->module) { vec_add(parent->methods, method_like); } else { - vec_add(context->module->method_extensions, method_like); + vec_add(unit->module->method_extensions, method_like); } return true; } -static inline bool sema_analyse_method(Context *context, Decl *decl) +static inline bool sema_analyse_method(SemaContext *context, Decl *decl) { TypeInfo *parent_type = decl->func_decl.type_parent; if (!sema_resolve_type_info(context, parent_type)) return false; @@ -1075,7 +1075,7 @@ static inline bool sema_analyse_method(Context *context, Decl *decl) return false; } Type *type = parent_type->type->canonical; - return sema_add_method_like(context, type, decl); + return unit_add_method_like(context->unit, type, decl); } static inline AttributeType attribute_by_name(Attr *attr) @@ -1093,6 +1093,8 @@ static const char *attribute_domain_to_string(AttributeDomain domain) { switch (domain) { + case ATTR_MACRO: + return "macro"; case ATTR_LOCAL: return "local variable"; case ATTR_BITSTRUCT: @@ -1122,7 +1124,7 @@ static const char *attribute_domain_to_string(AttributeDomain domain) } UNREACHABLE } -AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDomain domain) +AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain) { AttributeType type = attribute_by_name(attr); if (type == ATTRIBUTE_NONE) @@ -1132,7 +1134,7 @@ AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDoma } static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = { [ATTRIBUTE_WEAK] = ATTR_FUNC | ATTR_CONST | ATTR_GLOBAL, - [ATTRIBUTE_EXTNAME] = (AttributeDomain)~ATTR_CALL, + [ATTRIBUTE_EXTNAME] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_MACRO), [ATTRIBUTE_SECTION] = ATTR_FUNC | ATTR_CONST | ATTR_GLOBAL, [ATTRIBUTE_PACKED] = ATTR_STRUCT | ATTR_UNION, [ATTRIBUTE_NORETURN] = ATTR_FUNC, @@ -1150,7 +1152,8 @@ AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDoma [ATTRIBUTE_VECCALL] = ATTR_FUNC, [ATTRIBUTE_REGCALL] = ATTR_FUNC, [ATTRIBUTE_FASTCALL] = ATTR_FUNC, - [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT + [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT, + [ATTRIBUTE_NOSCOPE] = ATTR_MACRO, }; if ((attribute_domain[type] & domain) != domain) @@ -1201,7 +1204,7 @@ AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDoma return type; case ATTRIBUTE_SECTION: case ATTRIBUTE_EXTNAME: - if (context->module->is_generic) + if (context->unit->module->is_generic) { SEMA_TOKID_ERROR(attr->name, "'extname' attributes are not allowed in generic modules."); return false; @@ -1262,9 +1265,9 @@ static inline bool sema_update_call_convention(Decl *decl, CallABI abi) return had; } -static inline bool sema_analyse_main_function(Context *context, Decl *decl) +static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl) { - if (decl == context->main_function) return true; + if (decl == context->unit->main_function) return true; if (decl->visibility == VISIBLE_LOCAL) { @@ -1392,10 +1395,10 @@ static inline bool sema_analyse_main_function(Context *context, Decl *decl) } vec_add(body->compound_stmt.stmts, ret_stmt); function->func_decl.body = body; - context->main_function = function; + context->unit->main_function = function; return true; } -static inline bool sema_analyse_func(Context *context, Decl *decl) +static inline bool sema_analyse_func(SemaContext *context, Decl *decl) { DEBUG_LOG("----Analysing function %s", decl->name); @@ -1509,7 +1512,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl) return true; } -static bool sema_analyse_macro_method(Context *context, Decl *decl) +static bool sema_analyse_macro_method(SemaContext *context, Decl *decl) { if (!sema_resolve_type_info(context, decl->macro_decl.type_parent)) return false; Type *parent_type = decl->macro_decl.type_parent->type; @@ -1536,15 +1539,40 @@ static bool sema_analyse_macro_method(Context *context, Decl *decl) SEMA_ERROR(first_param, "The first parameter must be a ref (&) parameter."); return false; } - return sema_add_method_like(context, parent_type, decl); + return unit_add_method_like(context->unit, parent_type, decl); } -static inline bool sema_analyse_macro(Context *context, Decl *decl) +static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) { bool is_generic = decl->decl_kind == DECL_GENERIC; + + VECEACH(decl->attributes, i) + { + Attr *attr = decl->attributes[i]; + + AttributeType attribute = sema_analyse_attribute(context, attr, ATTR_MACRO); + if (attribute == ATTRIBUTE_NONE) return decl_poison(decl); + + bool had = false; + switch (attribute) + { + case ATTRIBUTE_NOSCOPE: + had = decl->no_scope; + decl->no_scope = true; + break; + default: + UNREACHABLE + } + if (had) + { + SEMA_TOKID_ERROR(attr->name, "Attribute occurred twice, please remove one."); + return decl_poison(decl); + } + } + TypeInfo *rtype = decl->macro_decl.rtype; if (decl->macro_decl.rtype && !sema_resolve_type_info(context, rtype)) return decl_poison(decl); - decl->macro_decl.context = context; + decl->macro_decl.unit = context->unit; Decl **parameters = decl->macro_decl.parameters; unsigned param_count = vec_size(parameters); for (unsigned i = 0; i < param_count; i++) @@ -1640,9 +1668,8 @@ static inline bool sema_analyse_macro(Context *context, Decl *decl) } -bool sema_analyse_attributes_for_var(Context *context, Decl *decl) +bool sema_analyse_attributes_for_var(SemaContext *context, Decl *decl) { - AttributeDomain domain; switch (decl->var.kind) { @@ -1694,7 +1721,7 @@ bool sema_analyse_attributes_for_var(Context *context, Decl *decl) return true; } -bool sema_analyse_decl_type(Context *context, Type *type, SourceSpan span) +bool sema_analyse_decl_type(SemaContext *context, Type *type, SourceSpan span) { if (type == type_void) { @@ -1714,7 +1741,7 @@ bool sema_analyse_decl_type(Context *context, Type *type, SourceSpan span) /** * Analyse a regular global or local declaration, e.g. int x = 123 */ -bool sema_analyse_var_decl(Context *context, Decl *decl, bool local) +bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) { assert(decl->decl_kind == DECL_VAR && "Unexpected declaration type"); @@ -1770,7 +1797,7 @@ bool sema_analyse_var_decl(Context *context, Decl *decl, bool local) if (decl->var.is_static) { scratch_buffer_clear(); - scratch_buffer_append(context->active_function_for_analysis->name); + scratch_buffer_append(context->current_function->name); scratch_buffer_append_char('.'); scratch_buffer_append(decl->name); decl->external_name = scratch_buffer_interned(); @@ -1835,26 +1862,26 @@ bool sema_analyse_var_decl(Context *context, Decl *decl, bool local) -static Context *copy_context(Module *module, Context *c) +static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit) { - Context *copy = context_create(c->file); - copy->imports = copy_decl_list(c->imports); - copy->global_decls = copy_decl_list(c->global_decls); + CompilationUnit *copy = unit_create(unit->file); + copy->imports = copy_decl_list(unit->imports); + copy->global_decls = copy_decl_list(unit->global_decls); copy->module = module; - assert(!c->functions && !c->macro_methods && !c->methods && !c->enums && !c->ct_ifs && !c->types && !c->external_symbol_list); + assert(!unit->functions && !unit->macro_methods && !unit->methods && !unit->enums && !unit->ct_ifs && !unit->types && !unit->external_symbol_list); return copy; } -static Module *sema_instantiate_module(Context *context, Module *module, Path *path, TypeInfo **parms) +static Module *module_instantiate_generic(Module *module, Path *path, TypeInfo **parms) { Module *new_module = compiler_find_or_create_module(path, NULL, module->is_private); new_module->is_generic = true; - Context **contexts = module->contexts; - VECEACH(contexts, i) + CompilationUnit **units = module->units; + VECEACH(units, i) { - vec_add(new_module->contexts, copy_context(new_module, contexts[i])); + vec_add(new_module->units, unit_copy(new_module, units[i])); } - Context *first_context = new_module->contexts[0]; + CompilationUnit *first_context = new_module->units[0]; VECEACH(module->parameters, i) { TokenId param = module->parameters[i]; @@ -1870,7 +1897,7 @@ static Module *sema_instantiate_module(Context *context, Module *module, Path *p return new_module; } -static bool sema_analyse_parameterized_define(Context *c, Decl *decl) +static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl) { Path *decl_path; TokenId name; @@ -1897,7 +1924,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl) default: UNREACHABLE } - Decl *alias = sema_resolve_parameterized_symbol(c, name, decl_path); + Decl *alias = unit_resolve_parameterized_symbol(c->unit, name, decl_path); if (!decl_ok(alias)) { return decl_poison(decl); @@ -1933,14 +1960,14 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl) path->module = path_string; path->span = module->name->span; path->len = global_context.scratch_buffer_len; - instantiated_module = sema_instantiate_module(c, module, path, decl->define_decl.generic_params); - sema_analyze_stage(instantiated_module, c->module->stage); + instantiated_module = module_instantiate_generic(module, path, decl->define_decl.generic_params); + sema_analyze_stage(instantiated_module, c->unit->module->stage); } if (global_context.errors_found) return decl_poison(decl); const char *name_str = TOKSTR(name); Decl *symbol = module_find_symbol(instantiated_module, name_str); assert(symbol); - context_register_external_symbol(c, symbol); + unit_register_external_symbol(c->unit, symbol); switch (decl->define_decl.define_kind) { case DEFINE_IDENT_GENERIC: @@ -1961,7 +1988,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl) } } -static inline bool sema_analyse_define(Context *c, Decl *decl) +static inline bool sema_analyse_define(SemaContext *c, Decl *decl) { // 1. The plain define if (decl->define_decl.define_kind == DEFINE_IDENT_ALIAS) @@ -1983,7 +2010,7 @@ static inline bool sema_analyse_define(Context *c, Decl *decl) -bool sema_analyse_decl(Context *context, Decl *decl) +bool sema_analyse_decl(SemaContext *context, Decl *decl) { if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl); @@ -1996,7 +2023,7 @@ bool sema_analyse_decl(Context *context, Decl *decl) } decl->resolve_status = RESOLVE_RUNNING; - decl->module = context->module; + decl->module = context->unit->module; switch (decl->decl_kind) { case DECL_BITSTRUCT: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 6da3be89a..7f03a3944 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -10,14 +10,14 @@ */ static bool sema_take_addr_of(Expr *inner); -static inline bool sema_expr_analyse_binary(Context *context, Expr *expr); -static inline bool sema_cast_rvalue(Context *context, Expr *expr); +static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr); +static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr); static Expr *expr_access_inline_member(Expr *parent, Decl *parent_decl); static inline void expr_set_as_const_list(Expr *expr, ConstInitializer *list); static inline bool is_const(Expr *expr); -static inline bool sema_expr_analyse_builtin(Context *context, Expr *expr, bool throw_error); -static bool sema_check_stmt_compile_time(Context *context, Ast *ast); -static bool binary_arithmetic_promotion(Context *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message); +static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error); +static bool sema_check_stmt_compile_time(SemaContext *context, Ast *ast); +static bool binary_arithmetic_promotion(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message); static inline void expr_set_as_const_list(Expr *expr, ConstInitializer *list) { expr->expr_kind = EXPR_CONST; @@ -494,7 +494,7 @@ static void expr_unify_binary(Expr *expr, Expr *left, Expr *right) expr->type = type_get_opt_fail(left->type, IS_FAILABLE(right)); } -static inline void context_pop_returns(Context *context, Ast **restore) +static inline void context_pop_returns(SemaContext *context, Ast **restore) { if (!context->returns_cache && context->returns) { @@ -503,7 +503,7 @@ static inline void context_pop_returns(Context *context, Ast **restore) context->returns = restore; } -static inline Ast **context_push_returns(Context *context) +static inline Ast **context_push_returns(SemaContext *context) { Ast** old_returns = context->returns; if (context->returns_cache) @@ -519,7 +519,7 @@ static inline Ast **context_push_returns(Context *context) return old_returns; } -int sema_check_comp_time_bool(Context *context, Expr *expr) +int sema_check_comp_time_bool(SemaContext *context, Expr *expr) { if (!sema_analyse_cond_expr(context, expr)) return -1; if (expr->expr_kind != EXPR_CONST) @@ -580,7 +580,7 @@ bool expr_is_ltype(Expr *expr) } } -static inline bool sema_cast_ident_rvalue(Context *context, Expr *expr) +static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) { Decl *decl = expr->identifier_expr.decl; decl = decl_flatten(decl); @@ -664,9 +664,7 @@ static inline bool sema_cast_ident_rvalue(Context *context, Expr *expr) expr_replace(expr, copy_expr(decl->var.init_expr)); return sema_analyse_expr(context, expr); case VARDECL_PARAM_EXPR: - expr_replace(expr, copy_expr(decl->var.init_expr)); - assert(decl->var.init_expr->resolve_status == RESOLVE_DONE); - return true; + UNREACHABLE case VARDECL_PARAM_CT_TYPE: case VARDECL_PARAM_CT: case VARDECL_LOCAL_CT: @@ -736,7 +734,7 @@ static bool expr_cast_to_index(Expr *index) } } -static inline bool sema_expr_analyse_ternary(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr) { Expr *left = expr->ternary_expr.then_expr; Expr *cond = expr->ternary_expr.cond; @@ -857,7 +855,7 @@ static inline bool find_possible_inferred_identifier(Type *to, Expr *expr) -static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr *expr) +static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr) { Decl *ambiguous_decl = NULL; Decl *private_symbol = NULL; @@ -885,7 +883,7 @@ static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr // Already handled if (!decl_ok(decl)) return false; - if (decl->decl_kind == DECL_FUNC && !expr->identifier_expr.path && decl->module != context->module) + if (decl->decl_kind == DECL_FUNC && !expr->identifier_expr.path && decl->module != context->unit->module) { SEMA_ERROR(expr, "Functions from other modules, must be prefixed with the module name"); return false; @@ -928,12 +926,13 @@ static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr return true; } -static inline bool sema_expr_analyse_macro_expansion(Context *context, Expr *expr) +static inline bool sema_expr_analyse_macro_expansion(SemaContext *context, Expr *expr) { Expr *inner = expr->macro_expansion_expr.inner; if (inner->expr_kind == EXPR_IDENTIFIER) { - if (!inner->identifier_expr.path && TOKSTR(inner->identifier_expr.identifier) == context->macro_scope.body_param) + TokenId body = context->current_macro ? context->current_macro->macro_decl.block_parameter : NO_TOKEN_ID ; + if (body.index && !inner->identifier_expr.path && TOKSTR(inner->identifier_expr.identifier) == TOKSTR(body)) { expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; expr->body_expansion_expr.ast = NULL; @@ -966,7 +965,7 @@ static inline bool sema_expr_analyse_macro_expansion(Context *context, Expr *exp return true; } -static inline bool sema_expr_analyse_ct_identifier(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr) { DEBUG_LOG("Now resolving %s", TOKSTR(expr->ct_ident_expr.identifier)); Decl *decl = sema_resolve_normal_symbol(context, @@ -988,7 +987,7 @@ static inline bool sema_expr_analyse_ct_identifier(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_hash_identifier(Context *context, Expr *expr) +static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr *expr) { DEBUG_LOG("Now resolving %s", TOKSTR(expr->hash_ident_expr.identifier)); Decl *decl = sema_resolve_normal_symbol(context, @@ -1003,11 +1002,15 @@ static inline bool sema_expr_analyse_hash_identifier(Context *context, Expr *exp DEBUG_LOG("Resolution successful of %s.", decl->name); assert(decl->decl_kind == DECL_VAR); - assert(decl->resolve_status == RESOLVE_DONE); - assert(decl->var.init_expr->resolve_status == RESOLVE_DONE); expr_replace(expr, copy_expr(decl->var.init_expr)); - return sema_analyse_expr(context, expr); + if (!sema_analyse_expr(decl->var.context, expr)) + { + // Poison the decl so we don't evaluate twice. + decl_poison(decl); + return false; + } + return true; } static inline bool sema_widen_top_down(Expr *expr, Type *type) @@ -1031,19 +1034,19 @@ static inline bool sema_widen_top_down(Expr *expr, Type *type) return cast_implicit(expr, type); } -static inline bool sema_promote_binary_top_down(Context *context, Expr *binary, Expr *left, Expr *right) +static inline bool sema_promote_binary_top_down(SemaContext *context, Expr *binary, Expr *left, Expr *right) { if (!binary->binary_expr.widen) return true; Type *to = binary->type; return sema_widen_top_down(left, to) && sema_widen_top_down(right, to); } -static inline bool sema_expr_analyse_binary_subexpr(Context *context, Expr *binary, Expr *left, Expr *right) +static inline bool sema_expr_analyse_binary_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right) { return (int)sema_analyse_expr(context, left) & (int)sema_analyse_expr(context, right); } -static inline bool sema_expr_analyse_binary_arithmetic_subexpr(Context *context, Expr *expr, const char *error) +static inline bool sema_expr_analyse_binary_arithmetic_subexpr(SemaContext *context, Expr *expr, const char *error) { Expr *left = expr->binary_expr.left; Expr *right = expr->binary_expr.right; @@ -1083,7 +1086,7 @@ static inline int find_index_of_named_parameter(Decl **func_params, Expr *expr) return -1; } -static inline bool sema_expr_analyse_intrinsic_fp_invocation(Context *context, Expr *expr, Decl *decl, bool *failable) +static inline bool sema_expr_analyse_intrinsic_fp_invocation(SemaContext *context, Expr *expr, Decl *decl, bool *failable) { unsigned arguments = vec_size(expr->call_expr.arguments); if (arguments != 1) @@ -1139,7 +1142,7 @@ typedef struct Variadic variadic; } CalledDecl; -static inline bool expr_promote_vararg(Context *context, Expr *arg) +static inline bool expr_promote_vararg(SemaContext *context, Expr *arg) { Type *arg_type = arg->type->canonical; @@ -1156,7 +1159,7 @@ static inline bool expr_promote_vararg(Context *context, Expr *arg) return true; } -static inline bool sema_check_invalid_body_arguments(Context *context, Expr *call, CalledDecl *callee) +static inline bool sema_check_invalid_body_arguments(SemaContext *context, Expr *call, CalledDecl *callee) { Decl **body_arguments = call->call_expr.body_arguments; bool has_body_arguments = vec_size(body_arguments) > 0; @@ -1208,7 +1211,7 @@ static inline bool sema_check_invalid_body_arguments(Context *context, Expr *cal } -static inline bool sema_expand_call_arguments(Context *context, CalledDecl *callee, Expr *call, Decl **params, Expr **args, unsigned func_param_count, bool variadic, bool *failable) +static inline bool sema_expand_call_arguments(SemaContext *context, CalledDecl *callee, Expr *call, Decl **params, Expr **args, unsigned func_param_count, bool variadic, bool *failable) { unsigned num_args = vec_size(args); @@ -1324,7 +1327,7 @@ static inline bool sema_expand_call_arguments(Context *context, CalledDecl *call return true; } -static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *call, CalledDecl callee, bool *failable) +static inline bool sema_expr_analyse_call_invocation(SemaContext *context, Expr *call, CalledDecl callee, bool *failable) { // 1. Check body arguments. if (!sema_check_invalid_body_arguments(context, call, &callee)) return false; @@ -1468,13 +1471,7 @@ static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *cal break; case VARDECL_PARAM_EXPR: // #foo - // We push a scope here as this will prevent the expression from modifying - // compile time variables during evaluation: - assert(callee.macro); - SCOPE_START - if (!sema_analyse_expr_rhs(context, param->type, arg, true)) return SCOPE_POP_ERROR(); - SCOPE_END; - if (IS_FAILABLE(arg)) *failable = true; + param->var.context = context; break; case VARDECL_PARAM_CT: // $foo @@ -1513,8 +1510,8 @@ static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *cal } return true; } -static inline bool sema_expr_analyse_func_invocation(Context *context, FunctionSignature *signature, Expr *expr, Decl *decl, - Expr *struct_var, bool failable) +static inline bool sema_expr_analyse_func_invocation(SemaContext *context, FunctionSignature *signature, Expr *expr, Decl *decl, + Expr *struct_var, bool failable) { CalledDecl callee = { .macro = false, @@ -1532,7 +1529,7 @@ static inline bool sema_expr_analyse_func_invocation(Context *context, FunctionS return true; } -static inline bool sema_expr_analyse_var_call(Context *context, Expr *expr, Type *func_ptr_type, bool failable) +static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool failable) { if (func_ptr_type->type_kind != TYPE_POINTER || func_ptr_type->pointer->type_kind != TYPE_FUNC) { @@ -1548,7 +1545,7 @@ static inline bool sema_expr_analyse_var_call(Context *context, Expr *expr, Type } // Unify returns in a macro or expression block. -static inline Type *unify_returns(Context *context) +static inline Type *unify_returns(SemaContext *context) { bool all_returns_need_casts = false; Type *common_type = NULL; @@ -1607,14 +1604,14 @@ static inline Type *unify_returns(Context *context) return common_type ? common_type : type_void; } -static inline bool sema_expr_analyse_func_call(Context *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable) +static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable) { expr->call_expr.is_pointer_call = false; return sema_expr_analyse_func_invocation(context, &decl->func_decl.function_signature, expr, decl, struct_var, failable); } -static bool sema_check_expr_compile_time(Context *context, Expr *expr) +static bool sema_check_expr_compile_time(SemaContext *context, Expr *expr) { switch (expr->expr_kind) { @@ -1632,7 +1629,7 @@ static bool sema_check_expr_compile_time(Context *context, Expr *expr) UNREACHABLE } -static bool sema_check_stmt_compile_time(Context *context, Ast *ast) +static bool sema_check_stmt_compile_time(SemaContext *context, Ast *ast) { switch (ast->ast_kind) { @@ -1655,16 +1652,10 @@ static bool sema_check_stmt_compile_time(Context *context, Ast *ast) } } -bool sema_expr_analyse_macro_call(Context *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable) +bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable) { assert(decl->decl_kind == DECL_MACRO); - if (context->macro_scope.depth >= MAX_MACRO_NESTING) - { - SEMA_ERROR(call_expr, "Too deep nesting (more than %d levels) when evaluating this macro.", MAX_MACRO_NESTING); - return false; - } - Decl **params = copy_decl_list(decl->macro_decl.parameters); CalledDecl callee = { .macro = true, @@ -1682,14 +1673,15 @@ bool sema_expr_analyse_macro_call(Context *context, Expr *call_expr, Expr *struc param->var.init_expr = args[i]; } - unsigned body_params = vec_size(call_expr->call_expr.body_arguments); + Decl **body_params = call_expr->call_expr.body_arguments; + unsigned body_params_count = vec_size(body_params); unsigned expected_body_params = vec_size(decl->macro_decl.body_parameters); - if (expected_body_params > body_params) + if (expected_body_params > body_params_count) { SEMA_ERROR(call_expr, "Not enough parameters for the macro body, expected %d.", expected_body_params); return false; } - if (expected_body_params < body_params) + if (expected_body_params < body_params_count) { SEMA_ERROR(call_expr, "Too many parameters for the macro body, expected %d.", expected_body_params); return false; @@ -1719,137 +1711,141 @@ bool sema_expr_analyse_macro_call(Context *context, Expr *call_expr, Expr *struc } if (!body_arg->alignment) body_arg->alignment = type_alloca_alignment(body_arg->type); } - Decl **first_local = context->macro_scope.macro ? context->macro_scope.locals_start : context->locals; - MacroScope old_macro_scope = context->macro_scope; + Ast *body = copy_ast(decl->macro_decl.body); - bool ok = true; + bool no_scope = decl->no_scope; + DynamicScope old_scope = context->active_scope; + if (!no_scope) + { + context_change_scope_with_flags(context, SCOPE_NONE); + } - SCOPE_OUTER_START + SemaContext macro_context; - for (unsigned i = 0; i < expected_body_params; i++) + Type *rtype = NULL; + if (no_scope) + { + + macro_context = *context; + macro_context.unit = decl->macro_decl.unit; + } + else + { + sema_context_init(¯o_context, decl->macro_decl.unit); + macro_context.compilation_unit = context->unit; + macro_context.current_function = context->current_function; + rtype = decl->macro_decl.rtype ? decl->macro_decl.rtype->type : NULL; + macro_context.expected_block_type = rtype; + context_change_scope_with_flags(¯o_context, SCOPE_MACRO); + } + macro_context.current_macro = decl; + macro_context.yield_body = call_expr->call_expr.body; + macro_context.yield_params = body_params; + macro_context.yield_context = context; + macro_context.original_inline_line = context->original_inline_line ? context->original_inline_line : TOKLOC(call_expr->span.loc)->row; + + VECEACH(params, i) + { + Decl *param = params[i]; + if (!sema_add_local(¯o_context, param)) goto EXIT_FAIL; + } + + VECEACH(body->compound_stmt.stmts, i) + { + if (!sema_analyse_statement(¯o_context, body->compound_stmt.stmts[i])) goto EXIT_FAIL; + } + + if (no_scope) + { + call_expr->type = type_void; + } + else + { + if (!vec_size(macro_context.returns)) { - Decl *body_arg = call_expr->call_expr.body_arguments[i]; - sema_add_local(context, body_arg); + if (rtype && type_no_fail(rtype) != type_void) + { + SEMA_ERROR(decl, + "Missing return in macro that should evaluate to %s.", + type_quoted_error_string(rtype)); + return SCOPE_POP_ERROR(); + } } - context->macro_scope = (MacroScope){ - .body_param = decl->macro_decl.block_parameter.index ? TOKSTR(decl->macro_decl.block_parameter) : NULL, - .macro = decl, - .inline_line = TOKLOC(call_expr->span.loc)->row, - .original_inline_line = old_macro_scope.depth ? old_macro_scope.original_inline_line : TOKLOC(call_expr->span.loc)->row, - .locals_start = context->active_scope.current_local, - .depth = old_macro_scope.depth + 1, - .yield_symbol_start = first_local, - .yield_body = call_expr->call_expr.body, - .yield_symbol_end = context->active_scope.current_local, - .yield_args = call_expr->call_expr.body_arguments, - }; - - - Ast *body = copy_ast(decl->macro_decl.body); - Type *rtype = decl->macro_decl.rtype ? decl->macro_decl.rtype->type : NULL; - - Ast **saved_returns = context_push_returns(context); - Type *previous_block_type = context->expected_block_type; - context->expected_block_type = rtype; - SCOPE_START_WITH_FLAGS(SCOPE_MACRO); - - - VECEACH(params, i) + if (rtype) + { + VECEACH(macro_context.returns, i) { - Decl *param = params[i]; - sema_add_local(context, param); - } - - VECEACH(body->compound_stmt.stmts, i) - { - if (!sema_analyse_statement(context, body->compound_stmt.stmts[i])) + Ast *return_stmt = macro_context.returns[i]; + Expr *ret_expr = return_stmt->return_stmt.expr; + if (!ret_expr) { - ok = false; + if (rtype == type_void) continue; + SEMA_ERROR(return_stmt, "Expected returning a value of type %s.", type_quoted_error_string(rtype)); + return SCOPE_POP_ERROR(); + } + Type *type = ret_expr->type; + if (!cast_may_implicit(type, rtype, true, true)) + { + SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype), + type_quoted_error_string(type)); + return SCOPE_POP_ERROR(); + } + bool success = cast_implicit(ret_expr, rtype); + assert(success); + } + call_expr->type = type_get_opt_fail(rtype, failable); + } + else + { + Type *sum_returns = unify_returns(¯o_context); + if (!sum_returns) return SCOPE_POP_ERROR(); + call_expr->type = type_get_opt_fail(sum_returns, failable); + } + if (vec_size(macro_context.returns) == 1) + { + Expr *result = macro_context.returns[0]->return_stmt.expr; + if (result && expr_is_constant_eval(result, CONSTANT_EVAL_ANY)) + { + if (sema_check_stmt_compile_time(¯o_context, body)) + { + expr_replace(call_expr, result); goto EXIT; } } + } + } - if (!vec_size(context->returns)) - { - if (rtype && type_no_fail(rtype) != type_void) - { - SEMA_ERROR(decl, "Missing return in macro that should evaluate to %s.", type_quoted_error_string(rtype)); - ok = false; - goto EXIT; - } - } - - if (rtype) - { - VECEACH(context->returns, i) - { - Ast *return_stmt = context->returns[i]; - Expr *ret_expr = return_stmt->return_stmt.expr; - if (!ret_expr) - { - if (rtype == type_void) continue; - SEMA_ERROR(return_stmt, "Expected returning a value of type %s.", type_quoted_error_string(rtype)); - ok = false; - goto EXIT; - } - Type *type = ret_expr->type; - if (!cast_may_implicit(type, rtype, true, true)) - { - SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype), - type_quoted_error_string(type)); - ok = false; - goto EXIT; - } - bool success = cast_implicit(ret_expr, rtype); - assert(success); - } - call_expr->type = type_get_opt_fail(rtype, failable); - } - else - { - Type *sum_returns = unify_returns(context); - if (!sum_returns) - { - ok = false; - goto EXIT; - } - call_expr->type = type_get_opt_fail(sum_returns, failable); - } - if (vec_size(context->returns) == 1) - { - Expr *result = context->returns[0]->return_stmt.expr; - if (result && expr_is_constant_eval(result, CONSTANT_EVAL_ANY)) - { - if (sema_check_stmt_compile_time(context, body)) - { - expr_replace(call_expr, result); - goto EXIT; - } - } - } - call_expr->expr_kind = EXPR_MACRO_BLOCK; - call_expr->macro_block.stmts = body->compound_stmt.stmts; - call_expr->macro_block.params = params; - call_expr->macro_block.args = args; - - EXIT: - SCOPE_END; - context->expected_block_type = previous_block_type; - context_pop_returns(context, saved_returns); - - SCOPE_OUTER_END; - context->macro_scope = old_macro_scope; - return ok; + call_expr->expr_kind = EXPR_MACRO_BLOCK; + call_expr->macro_block.stmts = body->compound_stmt.stmts; + call_expr->macro_block.params = params; + call_expr->macro_block.args = args; + call_expr->macro_block.no_scope = no_scope; +EXIT: + if (no_scope) + { + context->active_scope.jump_end = macro_context.active_scope.jump_end; + context->active_scope.defer_last = macro_context.active_scope.defer_last; + context->active_scope.defer_start = macro_context.active_scope.defer_start; + } + else + { + context_pop_defers_and_replace_expr(¯o_context, call_expr); + assert(context->active_scope.defer_last == context->active_scope.defer_start); + context->active_scope = old_scope; + } + return true; +EXIT_FAIL: + return SCOPE_POP_ERROR(); } -static inline Decl *sema_generate_generic_function(Context *context, Expr *call_expr, Expr *struct_var, Decl *decl, const char *mangled_name) +static inline Decl *sema_generate_generic_function(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, const char *mangled_name) { TODO return NULL; } -static inline bool sema_expr_analyse_generic_call(Context *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable) +static inline bool sema_expr_analyse_generic_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable) { assert(decl->decl_kind == DECL_GENERIC); @@ -1939,9 +1935,9 @@ static inline bool sema_expr_analyse_generic_call(Context *context, Expr *call_e return sema_expr_analyse_func_call(context, call_expr, found, struct_var, failable); } -static bool sema_analyse_body_expansion(Context *context, Expr *call) +static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) { - Decl *macro = context->macro_scope.macro; + Decl *macro = macro_context->current_macro; assert(macro); assert(macro->macro_decl.block_parameter.index); @@ -1964,25 +1960,36 @@ static bool sema_analyse_body_expansion(Context *context, Expr *call) return false; } Expr **args = call_expr->arguments; + + // Evaluate the expressions. TODO hash expressions for (unsigned i = 0; i < expressions; i++) { Expr *expr = args[i]; - Decl *param = context->macro_scope.yield_args[i]; - if (!sema_analyse_expr(context, expr)) return false; + if (!sema_analyse_expr(macro_context, expr)) return false; } + SemaContext *context = macro_context->yield_context; + Decl **params = macro_context->yield_params; + assert(call_expr->function->expr_kind == EXPR_MACRO_BODY_EXPANSION); expr_replace(call, call_expr->function); call->body_expansion_expr.values = args; - call->body_expansion_expr.declarations = context->macro_scope.yield_args; - bool in_yield = context->macro_scope.in_yield; - context->macro_scope.in_yield = true; - call->body_expansion_expr.ast = copy_ast(context->macro_scope.yield_body); - bool success = sema_analyse_statement(context, call->body_expansion_expr.ast); - context->macro_scope.in_yield = in_yield; + call->body_expansion_expr.declarations = macro_context->yield_params; + + bool success; + SCOPE_START + VECEACH(params, i) + { + Decl *param = params[i]; + if (!sema_add_local(context, param)) return SCOPE_POP_ERROR(); + } + call->body_expansion_expr.ast = copy_ast(macro_context->yield_body); + success = sema_analyse_statement(context, call->body_expansion_expr.ast); + + SCOPE_END; return success; } -bool sema_expr_analyse_general_call(Context *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable) +bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable) { int force_inline = -1; VECEACH(expr->call_expr.attributes, i) @@ -2086,7 +2093,7 @@ static inline unsigned builtin_expected_args(BuiltinFunction func) } UNREACHABLE } -static inline bool sema_expr_analyse_builtin_call(Context *context, Expr *expr) +static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr) { expr->call_expr.is_builtin = true; BuiltinFunction func = expr->call_expr.function->builtin_expr.builtin; @@ -2219,7 +2226,7 @@ static inline bool sema_expr_analyse_builtin_call(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_call(Context *context, Expr *expr) +static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr) { Expr *func_expr = expr->call_expr.function; @@ -2296,7 +2303,7 @@ static void sema_deref_array_pointers(Expr *expr) } } -static bool expr_check_index_in_range(Context *context, Type *type, Expr *index_expr, bool end_index, bool from_end) +static bool expr_check_index_in_range(SemaContext *context, Type *type, Expr *index_expr, bool end_index, bool from_end) { assert(type == type->canonical); if (index_expr->expr_kind != EXPR_CONST) return true; @@ -2390,7 +2397,7 @@ static Type *sema_expr_find_indexable_type_recursively(Type **type, Expr **paren } } -static inline bool sema_expr_analyse_subscript(Context *context, Expr *expr, bool is_addr) +static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, bool is_addr) { assert(expr->expr_kind == EXPR_SUBSCRIPT || expr->expr_kind == EXPR_SUBSCRIPT_ADDR); @@ -2521,7 +2528,7 @@ static inline bool sema_expr_analyse_subscript(Context *context, Expr *expr, boo return true; } -static inline bool sema_expr_analyse_slice(Context *context, Expr *expr) +static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) { if (!sema_analyse_expr(context, expr->slice_expr.expr)) return false; bool failable = IS_FAILABLE(expr->slice_expr.expr); @@ -2610,7 +2617,7 @@ static inline bool sema_expr_analyse_slice(Context *context, Expr *expr) } -static inline bool sema_expr_analyse_group(Context *context, Expr *expr) +static inline bool sema_expr_analyse_group(SemaContext *context, Expr *expr) { if (!sema_analyse_expr(context, expr->inner_expr)) return false; *expr = *expr->inner_expr; @@ -2644,7 +2651,7 @@ static inline void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *str -static void add_members_to_context(Context *context, Decl *decl) +static void add_members_to_context(SemaContext *context, Decl *decl) { VECEACH(decl->methods, i) { @@ -2740,7 +2747,7 @@ static TokenId sema_expr_resolve_access_child(Expr *child) return INVALID_TOKEN_ID; } -static inline bool sema_expr_analyse_type_access(Context *context, Expr *expr, TypeInfo *parent, bool was_group, bool is_macro, TokenId identifier_token) +static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, TypeInfo *parent, bool was_group, bool is_macro, TokenId identifier_token) { // 1. Foo*.sizeof is not allowed, it must be (Foo*).sizeof if (!was_group && type_kind_is_derived(parent->type->type_kind)) @@ -2841,7 +2848,7 @@ static inline bool sema_expr_analyse_type_access(Context *context, Expr *expr, T } break; case DECL_ERRTYPE: - context_register_external_symbol(context, decl); + unit_register_external_symbol(context->compilation_unit, decl); if (type == TOKEN_CONST_IDENT) { @@ -2940,7 +2947,7 @@ static inline bool sema_expr_analyse_type_access(Context *context, Expr *expr, T /** * Analyse "x.y" */ -static inline bool sema_expr_analyse_access(Context *context, Expr *expr) +static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) { Expr *parent = expr->access_expr.parent; bool was_group = parent->expr_kind == EXPR_GROUP; @@ -3052,12 +3059,12 @@ CHECK_DEEPER: { Decl *ambiguous = NULL; Decl *private = NULL; - member = sema_resolve_method(context, decl, kw, &ambiguous, &private); + member = sema_resolve_method(context->unit, decl, kw, &ambiguous, &private); } if (member && member->decl_kind == DECL_FUNC) { - context_register_external_symbol(context, member); + unit_register_external_symbol(context->compilation_unit, member); } // 11. If we didn't find a match... @@ -3149,7 +3156,7 @@ static Decl *sema_resolve_element_for_name(Decl** decls, DesignatorElement **ele return NULL; } -static MemberIndex sema_analyse_designator_index(Context *context, Expr *index) +static MemberIndex sema_analyse_designator_index(SemaContext *context, Expr *index) { if (!sema_analyse_expr_lvalue(context, index)) { @@ -3180,7 +3187,7 @@ static MemberIndex sema_analyse_designator_index(Context *context, Expr *index) return (MemberIndex)index_val; } -static Type *sema_find_type_of_element(Context *context, Type *type, DesignatorElement **elements, unsigned *curr_index, bool *is_constant, bool *did_report_error, MemberIndex *max_index, Decl **member_ptr) +static Type *sema_find_type_of_element(SemaContext *context, Type *type, DesignatorElement **elements, unsigned *curr_index, bool *is_constant, bool *did_report_error, MemberIndex *max_index, Decl **member_ptr) { Type *type_flattened = type_flatten(type); DesignatorElement *element = elements[*curr_index]; @@ -3257,7 +3264,7 @@ static Type *sema_find_type_of_element(Context *context, Type *type, DesignatorE return member->type; } -static Type *sema_expr_analyse_designator(Context *context, Type *current, Expr *expr, MemberIndex *max_index, Decl **member_ptr) +static Type *sema_expr_analyse_designator(SemaContext *context, Type *current, Expr *expr, MemberIndex *max_index, Decl **member_ptr) { DesignatorElement **path = expr->designator_expr.path; @@ -3574,7 +3581,7 @@ static void sema_create_const_initializer(ConstInitializer *const_init, Expr *in } } -static bool sema_expr_analyse_designated_initializer(Context *context, Type *assigned, Expr *initializer) +static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Expr *initializer) { Expr **init_expressions = initializer->designated_init_list; Type *original = assigned->canonical; @@ -3644,7 +3651,7 @@ static inline void not_enough_elements(Expr *initializer, int element) * Perform analysis for a plain initializer, that is one initializing all fields. * @return true if analysis succeeds. */ -static inline bool sema_expr_analyse_struct_plain_initializer(Context *context, Decl *assigned, Expr *initializer) +static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer) { Expr **elements = initializer->initializer_list; Decl **members = assigned->strukt.members; @@ -3781,7 +3788,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context, * Perform analysis for a plain initializer, that is one initializing all fields. * @return true if analysis succeeds. */ -static inline bool sema_expr_analyse_array_plain_initializer(Context *context, Type *assigned, Expr *initializer) +static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Expr *initializer) { Expr **elements = initializer->initializer_list; @@ -3848,7 +3855,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T return true; } -static inline bool sema_expr_analyse_untyped_initializer(Context *context, Expr *initializer) +static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer) { Expr **elements = initializer->initializer_list; @@ -3887,7 +3894,7 @@ static inline bool sema_expr_analyse_untyped_initializer(Context *context, Expr return true; } -static inline bool sema_expr_analyse_initializer(Context *context, Type *external_type, Type *assigned, Expr *expr) +static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *external_type, Type *assigned, Expr *expr) { // Note at this point this we either have // EXPR_DESIGNATED_INITIALIZER_LIST @@ -3938,7 +3945,7 @@ static inline bool sema_expr_analyse_initializer(Context *context, Type *externa return sema_expr_analyse_struct_plain_initializer(context, assigned->decl, expr); } -static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to, Expr *expr) +static inline bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr) { if (!to) { @@ -3978,7 +3985,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to -static inline bool sema_expr_analyse_expr_list(Context *context, Expr *expr) +static inline bool sema_expr_analyse_expr_list(SemaContext *context, Expr *expr) { bool success = true; ByteSize last = vec_size(expr->expression_list) - 1; @@ -3991,7 +3998,7 @@ static inline bool sema_expr_analyse_expr_list(Context *context, Expr *expr) return success; } -static inline bool sema_expr_analyse_cast(Context *context, Expr *expr) +static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr) { Expr *inner = expr->cast_expr.expr; bool success = sema_resolve_type_info(context, expr->cast_expr.type_info); @@ -4012,7 +4019,7 @@ static inline bool sema_expr_analyse_cast(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_slice_assign(Context *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped) +static inline bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped) { // 1. Evaluate right side to required type. if (!sema_analyse_expr_rhs(context, left_type->array.base, right, false)) return false; @@ -4026,7 +4033,7 @@ static inline bool sema_expr_analyse_slice_assign(Context *context, Expr *expr, return true; } -bool sema_expr_analyse_assign_right_side(Context *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped) +bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped) { if (expr && expr->binary_expr.left->expr_kind == EXPR_SLICE) { @@ -4068,7 +4075,7 @@ static inline bool sema_expr_begin_analyse(Expr *expr) } -static inline bool sema_expr_analyse_ct_identifier_lvalue(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_identifier_lvalue(SemaContext *context, Expr *expr) { if (!sema_expr_begin_analyse(expr)) return expr_ok(expr); @@ -4099,7 +4106,7 @@ static inline bool sema_expr_analyse_ct_identifier_lvalue(Context *context, Expr } -static bool sema_expr_analyse_ct_identifier_assign(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { if (!sema_expr_analyse_ct_identifier_lvalue(context, left)) return false; @@ -4111,7 +4118,7 @@ static bool sema_expr_analyse_ct_identifier_assign(Context *context, Expr *expr, return true; } -static bool sema_expr_analyse_ct_type_identifier_assign(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { TypeInfo *info = left->type_expr; @@ -4153,7 +4160,7 @@ static bool sema_expr_analyse_ct_type_identifier_assign(Context *context, Expr * * Analyse a = b * @return true if analysis works */ -static bool sema_expr_analyse_assign(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Evaluate left side if (left->expr_kind == EXPR_CT_IDENT) @@ -4199,7 +4206,7 @@ static bool sema_expr_analyse_assign(Context *context, Expr *expr, Expr *left, E * * @return true if analysis worked. */ -static bool sema_expr_analyse_ct_common_assign(Context *context, Expr *expr, Expr *left) +static bool sema_expr_analyse_ct_common_assign(SemaContext *context, Expr *expr, Expr *left) { // 1. Analyse left side. @@ -4233,7 +4240,7 @@ static bool sema_expr_analyse_ct_common_assign(Context *context, Expr *expr, Exp * * @return true if analysis worked. */ -static bool sema_expr_analyse_common_assign(Context *context, Expr *expr, Expr *left, Expr *right, bool int_only) +static bool sema_expr_analyse_common_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right, bool int_only) { if (left->expr_kind == EXPR_CT_IDENT) { @@ -4330,7 +4337,7 @@ static bool sema_expr_analyse_common_assign(Context *context, Expr *expr, Expr * * Handle a += b, a -= b * @return true if analysis succeeded. */ -static bool sema_expr_analyse_add_sub_assign(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { if (left->expr_kind == EXPR_CT_IDENT) { @@ -4420,7 +4427,7 @@ static Type *numeric_arithmetic_promotion(Type *type) } } -static bool binary_arithmetic_promotion(Context *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message) +static bool binary_arithmetic_promotion(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message) { Type *max = numeric_arithmetic_promotion(type_find_max_type(left_type, right_type)); if (!max || !type_underlying_is_numeric(max)) @@ -4471,7 +4478,7 @@ static Type *defer_iptr_cast(Expr *maybe_pointer, Expr *maybe_diff) * Analyse a - b * @return true if analysis succeeded */ -static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_sub(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyse a and b. if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false; @@ -4578,7 +4585,7 @@ static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr * Analyse a + b * @return true if it succeeds. */ -static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_add(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Promote everything to the recipient type – if possible // this is safe in the pointer case actually. @@ -4680,7 +4687,7 @@ static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr * * @return true if analysis worked. */ -static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_mult(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyse the sub expressions and promote to a common type @@ -4714,7 +4721,7 @@ static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Exp * Analyse a / b * @return true if analysis completed ok. */ -static bool sema_expr_analyse_div(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_div(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyse sub expressions and promote to a common type if (!sema_expr_analyse_binary_arithmetic_subexpr(context, expr, "Cannot divide %s by %s.")) return false; @@ -4766,7 +4773,7 @@ static bool sema_expr_analyse_div(Context *context, Expr *expr, Expr *left, Expr * Analyse a % b * @return true if analysis succeeds. */ -static bool sema_expr_analyse_mod(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_mod(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyse both sides and promote to a common type if (!sema_expr_analyse_binary_arithmetic_subexpr(context, expr, NULL)) return false; @@ -4794,7 +4801,7 @@ static bool sema_expr_analyse_mod(Context *context, Expr *expr, Expr *left, Expr * Analyse a ^ b, a | b, a & b * @return true if the analysis succeeded. */ -static bool sema_expr_analyse_bit(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_bit(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Convert to common type if possible. if (!sema_expr_analyse_binary_arithmetic_subexpr(context, expr, NULL)) return false; @@ -4835,7 +4842,7 @@ static bool sema_expr_analyse_bit(Context *context, Expr *expr, Expr *left, Expr * Analyse >> and << operations. * @return true if the analysis succeeded. */ -static bool sema_expr_analyse_shift(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_shift(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyze both sides. if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false; @@ -4897,7 +4904,7 @@ static bool sema_expr_analyse_shift(Context *context, Expr *expr, Expr *left, Ex * Analyse a <<= b a >>= b * @return true is the analysis succeeds, false otherwise. */ -static bool sema_expr_analyse_shift_assign(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyze the two sub lhs & rhs *without coercion* @@ -4945,7 +4952,7 @@ static bool sema_expr_analyse_shift_assign(Context *context, Expr *expr, Expr *l } -static bool sema_expr_analyse_and_or(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_and_or(SemaContext *context, Expr *expr, Expr *left, Expr *right) { if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false; if (!cast_implicit(left, type_bool) || !cast_implicit(right, type_bool)) return false; @@ -4969,7 +4976,7 @@ static bool sema_expr_analyse_and_or(Context *context, Expr *expr, Expr *left, E -static void cast_to_max_bit_size(Context *context, Expr *left, Expr *right, Type *left_type, Type *right_type) +static void cast_to_max_bit_size(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type) { unsigned bit_size_left = left_type->builtin.bitsize; unsigned bit_size_right = right_type->builtin.bitsize; @@ -4991,9 +4998,9 @@ static void cast_to_max_bit_size(Context *context, Expr *left, Expr *right, Type assert(success); } -static bool sema_is_unsigned_always_false_comparison(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_is_unsigned_always_false_comparison(SemaContext *context, Expr *expr, Expr *left, Expr *right) { - if (context->macro_scope.macro) return true; + if (context->active_scope.flags & SCOPE_MACRO) return true; if (!is_const(left) && !is_const(right)) return true; if (!type_is_integer(left->type)) return true; if (is_const(left) && type_is_unsigned(type_flatten_distinct(right->type))) @@ -5046,7 +5053,7 @@ static bool sema_is_unsigned_always_false_comparison(Context *context, Expr *exp * Analyze a == b, a != b, a > b, a < b, a >= b, a <= b * @return */ -static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Expr *right) +static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Analyse left and right side without any conversions. if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false; @@ -5151,7 +5158,7 @@ DONE: * Analyse *a * @return true if analysis succeeds. */ -static bool sema_expr_analyse_deref(Context *context, Expr *expr) +static bool sema_expr_analyse_deref(SemaContext *context, Expr *expr) { // 1. Check the inner expression Expr *inner = expr->unary_expr.expr; @@ -5306,7 +5313,7 @@ static bool sema_take_addr_of(Expr *inner) * Analyse &a * @return true if analysis succeeds. */ -static bool sema_expr_analyse_addr(Context *context, Expr *expr) +static bool sema_expr_analyse_addr(SemaContext *context, Expr *expr) { // 1. Evaluate the expression Expr *inner = expr->unary_expr.expr; @@ -5342,7 +5349,7 @@ static bool sema_expr_analyse_addr(Context *context, Expr *expr) /** * Test -a */ -static bool sema_expr_analyse_neg(Context *context, Expr *expr) +static bool sema_expr_analyse_neg(SemaContext *context, Expr *expr) { // 1. Check the inner expression Expr *inner = expr->unary_expr.expr; @@ -5388,7 +5395,7 @@ static bool sema_expr_analyse_neg(Context *context, Expr *expr) * * @return */ -static bool sema_expr_analyse_bit_not(Context *context, Expr *expr) +static bool sema_expr_analyse_bit_not(SemaContext *context, Expr *expr) { // 1. Analyse the inner expression. Expr *inner = expr->unary_expr.expr; @@ -5431,7 +5438,7 @@ VALID_VEC: /** * Evaluate !a */ -static bool sema_expr_analyse_not(Context *context, Expr *expr) +static bool sema_expr_analyse_not(SemaContext *context, Expr *expr) { // 1. Evaluate inner Expr *inner = expr->unary_expr.expr; @@ -5467,7 +5474,7 @@ static bool sema_expr_analyse_not(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_ct_incdec(Context *context, Expr *expr, Expr *inner) +static inline bool sema_expr_analyse_ct_incdec(SemaContext *context, Expr *expr, Expr *inner) { assert(inner->expr_kind == EXPR_CT_IDENT); @@ -5513,7 +5520,7 @@ static inline bool sema_expr_analyse_ct_incdec(Context *context, Expr *expr, Exp * Analyse foo++ foo-- --foo ++foo * @return false if analysis fails. */ -static inline bool sema_expr_analyse_incdec(Context *context, Expr *expr) +static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr) { // 1. Analyse the lvalue to update Expr *inner = expr->unary_expr.expr; @@ -5552,7 +5559,7 @@ static inline bool sema_expr_analyse_incdec(Context *context, Expr *expr) /** * Take an address of a temporary &&x. */ -static inline bool sema_expr_analyse_taddr(Context *context, Expr *expr) +static inline bool sema_expr_analyse_taddr(SemaContext *context, Expr *expr) { Expr *inner = expr->unary_expr.expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5578,11 +5585,11 @@ static bool unclear_op_precedence(Expr *left_side, Expr * main_expr, Expr *right return false; } -static inline bool sema_expr_analyse_bitassign(Context *context, Expr *expr) +static inline bool sema_expr_analyse_bitassign(SemaContext *context, Expr *expr) { TODO } -static inline bool sema_expr_analyse_binary(Context *context, Expr *expr) +static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr) { assert(expr->resolve_status == RESOLVE_RUNNING); Expr *left = expr->binary_expr.left; @@ -5654,7 +5661,7 @@ static inline bool sema_expr_analyse_binary(Context *context, Expr *expr) * &&x * -x */ -static inline bool sema_expr_analyse_unary(Context *context, Expr *expr) +static inline bool sema_expr_analyse_unary(SemaContext *context, Expr *expr) { assert(expr->resolve_status == RESOLVE_RUNNING); switch (expr->unary_expr.operator) @@ -5681,7 +5688,7 @@ static inline bool sema_expr_analyse_unary(Context *context, Expr *expr) } -static inline bool sema_expr_analyse_try(Context *context, Expr *expr) +static inline bool sema_expr_analyse_try(SemaContext *context, Expr *expr) { Expr *inner = expr->inner_expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5694,7 +5701,7 @@ static inline bool sema_expr_analyse_try(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_catch(Context *context, Expr *expr) +static inline bool sema_expr_analyse_catch(SemaContext *context, Expr *expr) { Expr *inner = expr->inner_expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5707,7 +5714,7 @@ static inline bool sema_expr_analyse_catch(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_or_error(Context *context, Expr *expr) +static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr) { Expr *inner = expr->or_error_expr.expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5759,7 +5766,7 @@ static inline bool sema_expr_analyse_or_error(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_rethrow(Context *context, Expr *expr) +static inline bool sema_expr_analyse_rethrow(SemaContext *context, Expr *expr) { Expr *inner = expr->rethrow_expr.inner; if (!sema_analyse_expr(context, inner)) return false; @@ -5787,7 +5794,7 @@ static inline bool sema_expr_analyse_rethrow(Context *context, Expr *expr) } -static inline bool sema_expr_analyse_force_unwrap(Context *context, Expr *expr) +static inline bool sema_expr_analyse_force_unwrap(SemaContext *context, Expr *expr) { Expr *inner = expr->inner_expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5809,7 +5816,7 @@ static inline bool sema_expr_analyse_force_unwrap(Context *context, Expr *expr) -static inline bool sema_expr_analyse_typeid(Context *context, Expr *expr) +static inline bool sema_expr_analyse_typeid(SemaContext *context, Expr *expr) { if (!sema_resolve_type_info(context, expr->typeid_expr)) return expr_poison(expr); Type *type = expr->type_expr->type; @@ -5821,7 +5828,7 @@ static inline bool sema_expr_analyse_typeid(Context *context, Expr *expr) } -static inline bool sema_expr_analyse_expr_block(Context *context, Expr *expr) +static inline bool sema_expr_analyse_expr_block(SemaContext *context, Expr *expr) { bool success = true; expr->type = type_void; @@ -5873,7 +5880,7 @@ static inline bool sema_expr_analyse_expr_block(Context *context, Expr *expr) } -static inline bool sema_expr_analyse_compound_literal(Context *context, Expr *expr) +static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr) { if (!sema_resolve_type_info(context, expr->expr_compound_literal.type_info)) return false; Type *type = expr->expr_compound_literal.type_info->type; @@ -5890,7 +5897,7 @@ static inline bool sema_expr_analyse_compound_literal(Context *context, Expr *ex -static inline bool sema_expr_analyse_failable(Context *context, Expr *expr) +static inline bool sema_expr_analyse_failable(SemaContext *context, Expr *expr) { Expr *inner = expr->inner_expr; if (!sema_analyse_expr(context, inner)) return false; @@ -5917,22 +5924,22 @@ static inline bool sema_expr_analyse_failable(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_placeholder(Context *context, Expr *expr) +static inline bool sema_expr_analyse_placeholder(SemaContext *context, Expr *expr) { const char *string = TOKSTR(expr->placeholder_expr.identifier); if (string == kw_FILE) { - expr_rewrite_to_string(expr, context->file->name); + expr_rewrite_to_string(expr, context->unit->file->name); return true; } if (string == kw_FUNC) { - if (!context->active_function_for_analysis) + if (!context->current_function) { expr_rewrite_to_string(expr, ""); return true; } - expr_rewrite_to_string(expr, context->active_function_for_analysis->name); + expr_rewrite_to_string(expr, context->current_function->name); return true; } if (string == kw_LINEREAL) @@ -5942,9 +5949,9 @@ static inline bool sema_expr_analyse_placeholder(Context *context, Expr *expr) } if (string == kw_LINE) { - if (context->macro_scope.depth) + if (context->original_inline_line) { - expr_rewrite_to_int_const(expr, type_isize, context->macro_scope.original_inline_line, true); + expr_rewrite_to_int_const(expr, type_isize, context->original_inline_line, true); } else { @@ -6012,7 +6019,7 @@ uint64_t minilex_parse_number(MiniLexer *lexer, uint64_t max) return value; } -static inline bool sema_analyse_idents_string(Context *context, MiniLexer *lexer, ExprFlatElement **elements_ref) +static inline bool sema_analyse_idents_string(SemaContext *context, MiniLexer *lexer, ExprFlatElement **elements_ref) { ExprFlatElement *elements = NULL; @@ -6059,7 +6066,7 @@ static inline bool sema_analyse_idents_string(Context *context, MiniLexer *lexer return true; } -static inline bool sema_analyse_identifier_path_string(Context *context, SourceSpan span, Expr *expr, Decl **decl_ref, Type **type_ref, ExprFlatElement **idents_ref, bool report_missing) +static inline bool sema_analyse_identifier_path_string(SemaContext *context, SourceSpan span, Expr *expr, Decl **decl_ref, Type **type_ref, ExprFlatElement **idents_ref, bool report_missing) { const char *chars = expr->const_expr.string.chars; uint32_t len = expr->const_expr.string.len; @@ -6243,7 +6250,7 @@ static inline bool decl_is_local(Decl *decl) } -static bool sema_expr_analyse_type_var_path(Context *context, Expr *expr, ExprFlatElement **elements, Type **type_ref, +static bool sema_expr_analyse_type_var_path(SemaContext *context, Expr *expr, ExprFlatElement **elements, Type **type_ref, Decl **decl_ref) { if (!sema_analyse_expr_lvalue(context, expr)) return false; @@ -6284,7 +6291,7 @@ RETRY: return true; } -static inline bool sema_expr_analyse_ct_alignof(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr) { Expr *main_var = expr->ct_call_expr.main_var; Type *type = NULL; @@ -6341,7 +6348,7 @@ static inline bool sema_expr_analyse_ct_alignof(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_ct_sizeof(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_sizeof(SemaContext *context, Expr *expr) { Expr *main_var = expr->ct_call_expr.main_var; Type *type = NULL; @@ -6394,7 +6401,7 @@ static inline bool sema_expr_analyse_ct_sizeof(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_ct_nameof(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) { Expr *main_var = expr->ct_call_expr.main_var; @@ -6463,7 +6470,7 @@ static inline bool sema_expr_analyse_ct_nameof(Context *context, Expr *expr) } -static Type *sema_expr_check_type_exists(Context *context, TypeInfo *type_info) +static Type *sema_expr_check_type_exists(SemaContext *context, TypeInfo *type_info) { if (type_info->resolve_status == RESOLVE_DONE) { @@ -6536,7 +6543,7 @@ static Type *sema_expr_check_type_exists(Context *context, TypeInfo *type_info) } UNREACHABLE } -static inline bool sema_expr_analyse_ct_defined(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr) { if (expr->resolve_status == RESOLVE_DONE) return expr_ok(expr); @@ -6630,7 +6637,7 @@ NOT_DEFINED: } -static inline bool sema_expr_analyse_ct_offsetof(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_offsetof(SemaContext *context, Expr *expr) { Expr *main_var = expr->ct_call_expr.main_var; Type *type = NULL; @@ -6690,7 +6697,7 @@ static inline bool sema_expr_analyse_ct_offsetof(Context *context, Expr *expr) return true; } -static inline bool sema_expr_analyse_ct_call(Context *context, Expr *expr) +static inline bool sema_expr_analyse_ct_call(SemaContext *context, Expr *expr) { switch (expr->ct_call_expr.token_type) { @@ -6720,7 +6727,7 @@ static inline BuiltinFunction builtin_by_name(const char *name) return BUILTIN_NONE; } -static inline bool sema_expr_analyse_builtin(Context *context, Expr *expr, bool throw_error) +static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error) { const char *builtin_char = TOKSTR(expr->builtin_expr.identifier); @@ -6736,7 +6743,7 @@ static inline bool sema_expr_analyse_builtin(Context *context, Expr *expr, bool return true; } -static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr) +static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) { switch (expr->expr_kind) { @@ -6842,7 +6849,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr) } -bool sema_analyse_cond_expr(Context *context, Expr *expr) +bool sema_analyse_cond_expr(SemaContext *context, Expr *expr) { if (expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator == BINARYOP_ASSIGN) { @@ -6861,7 +6868,7 @@ bool sema_analyse_cond_expr(Context *context, Expr *expr) } -bool sema_analyse_expr_rhs(Context *context, Type *to, Expr *expr, bool allow_failable) +bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_failable) { if (to && type_is_failable_type(to)) { @@ -6879,7 +6886,7 @@ bool sema_analyse_expr_rhs(Context *context, Type *to, Expr *expr, bool allow_fa } -static inline bool sema_cast_ct_ident_rvalue(Context *context, Expr *expr) +static inline bool sema_cast_ct_ident_rvalue(SemaContext *context, Expr *expr) { Decl *decl = expr->ct_ident_expr.decl; Expr *copy = copy_expr(decl->var.init_expr); @@ -6888,7 +6895,7 @@ static inline bool sema_cast_ct_ident_rvalue(Context *context, Expr *expr) return true; } -static inline bool sema_cast_rvalue(Context *context, Expr *expr) +static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr) { if (!expr_ok(expr)) return false; switch (expr->expr_kind) @@ -6896,7 +6903,7 @@ static inline bool sema_cast_rvalue(Context *context, Expr *expr) case EXPR_MACRO_BODY_EXPANSION: if (!expr->body_expansion_expr.ast) { - SEMA_ERROR(expr, "'@%s' must be followed by ().", context->macro_scope.body_param); + SEMA_ERROR(expr, "'@%s' must be followed by ().", TOKSTR(context->current_macro->macro_decl.block_parameter)); return false; } break; @@ -6934,7 +6941,7 @@ static inline bool sema_cast_rvalue(Context *context, Expr *expr) return true; } -bool sema_analyse_expr_lvalue(Context *context, Expr *expr) +bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr) { switch (expr->resolve_status) { @@ -6953,7 +6960,7 @@ bool sema_analyse_expr_lvalue(Context *context, Expr *expr) } } -MemberIndex sema_get_initializer_const_array_size(Context *context, Expr *initializer, bool *may_be_array, bool *is_const_size) +MemberIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size) { if (initializer->expr_kind == EXPR_CONST) { @@ -7047,7 +7054,7 @@ MemberIndex sema_get_initializer_const_array_size(Context *context, Expr *initia return size; } -bool sema_analyse_expr(Context *context, Expr *expr) +bool sema_analyse_expr(SemaContext *context, Expr *expr) { return sema_analyse_expr_lvalue(context, expr) && sema_cast_rvalue(context, expr); } @@ -7109,7 +7116,7 @@ void insert_widening_type(Expr *expr, Type *infer_type) } UNREACHABLE } -bool sema_analyse_inferred_expr(Context *context, Type *infer_type, Expr *expr) +bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *expr) { infer_type = type_no_fail(infer_type); switch (expr->resolve_status) diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 44266151b..2ec4d64e3 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -7,8 +7,8 @@ #include "compiler_internal.h" -int sema_check_comp_time_bool(Context *context, Expr *expr); -bool sema_analyse_function_body(Context *context, Decl *func); +int sema_check_comp_time_bool(SemaContext *context, Expr *expr); +bool sema_analyse_function_body(SemaContext *context, Decl *func); #define SCOPE_OUTER_START \ do { \ DynamicScope stored_scope = context->active_scope; \ @@ -34,11 +34,12 @@ do { \ #define SCOPE_ERROR_END_OUTER() \ do { context->active_scope = stored_scope; } while(0) -void context_pop_defers_to(Context *context, DeferList *list); -Expr *context_pop_defers_and_wrap_expr(Context *context, Expr *expr); -void context_pop_defers_and_replace_ast(Context *context, Ast *ast); -void context_change_scope_for_label(Context *context, Decl *label); -void context_change_scope_with_flags(Context *context, ScopeFlags flags); +void context_pop_defers_to(SemaContext *context, DeferList *list); +Expr *context_pop_defers_and_wrap_expr(SemaContext *context, Expr *expr); +void context_pop_defers_and_replace_expr(SemaContext *context, Expr *expr); +void context_pop_defers_and_replace_ast(SemaContext *context, Ast *ast); +void context_change_scope_for_label(SemaContext *context, Decl *label); +void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags); #define PUSH_X(ast, X) AstId _old_##X##_defer = context->X##_defer; AstId _old_##X = context->X##_target; context->X##_target = ast ? astid(ast) : 0; context->X##_defer = context->active_scope.defer_last #define POP_X(X) context->X##_target = _old_##X; context->X##_defer = _old_##X##_defer @@ -52,10 +53,21 @@ void context_change_scope_with_flags(Context *context, ScopeFlags flags); #define POP_BREAKCONT() POP_CONTINUE(); POP_BREAK() void c_abi_func_create(FunctionSignature *signature); -AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDomain domain); +AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain); bool expr_is_ltype(Expr *expr); -Decl *sema_find_operator(Context *context, Expr *expr, const char *kw); -bool sema_analyse_expr_lvalue(Context *context, Expr *expr); -bool sema_expr_analyse_macro_call(Context *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable); +void sema_context_init(SemaContext *context, CompilationUnit *unit); +void sema_context_destroy(SemaContext *context); +Decl **global_context_acquire_locals_list(void); +void generic_context_release_locals_list(Decl **); +void sema_analysis_pass_process_imports(Module *module); +void sema_analysis_pass_register_globals(Module *module); +void sema_analysis_pass_conditional_compilation(Module *module); +void sema_analysis_pass_decls(Module *module); +void sema_analysis_pass_ct_assert(Module *module); +void sema_analysis_pass_functions(Module *module); +void sema_analyze_stage(Module *module, AnalysisStage stage); +Decl *sema_find_operator(SemaContext *context, Expr *expr, const char *kw); +bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr); +bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable); void expr_rewrite_to_int_const(Expr *expr_to_rewrite, Type *type, uint64_t value, bool narrowable); \ No newline at end of file diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index daa7fee97..044f630d7 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -29,19 +29,19 @@ static inline bool matches_subpath(Path *path_to_check, Path *path_to_find) return 0 == memcmp(path_to_check->module + compare_start, path_to_find->module, path_to_find->len); } -Decl *sema_resolve_symbol_in_current_dynamic_scope(Context *context, const char *symbol) +Decl *sema_resolve_symbol_in_current_dynamic_scope(SemaContext *context, const char *symbol) { - Decl **first = context->active_scope.local_decl_start; - Decl **current = context->active_scope.current_local; - while (current > first) + Decl **locals = context->locals; + size_t first = context->active_scope.local_decl_start; + for (size_t i = context->active_scope.current_local; i > first; i--) { - current--; - if (current[0]->name == symbol) return current[0]; + Decl *decl = locals[i - 1]; + if (decl->name == symbol) return decl; } return NULL; } -static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path *path, Decl **ambiguous_other_decl, +static Decl *sema_resolve_path_symbol(SemaContext *context, const char *symbol, Path *path, Decl **ambiguous_other_decl, Decl **private_decl, bool *path_found) { assert(path && "Expected path."); @@ -55,19 +55,19 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path return module_find_symbol(&global_context.std_module, symbol); } - Context *real_context = context->macro_scope.macro ? context->macro_scope.macro->macro_decl.context : context; + CompilationUnit *unit = context->unit; // 1. Do we match our own path? - if (matches_subpath(real_context->module->name, path)) + if (matches_subpath(unit->module->name, path)) { // 2. If so just get the symbol. - return module_find_symbol(real_context->module, symbol); + return module_find_symbol(unit->module, symbol); } // 3. Loop over imports. - VECEACH(real_context->imports, i) + VECEACH(unit->imports, i) { - Decl *import = real_context->imports[i]; + Decl *import = unit->imports[i]; if (import->module->is_generic) continue; @@ -108,61 +108,54 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path return decl; } -static Decl *sema_resolve_no_path_symbol(Context *context, const char *symbol, +static Decl *sema_resolve_no_path_symbol(SemaContext *context, const char *symbol, Decl **ambiguous_other_decl, Decl **private_decl) { Decl *decl = NULL; - if (context->active_scope.current_local > &context->locals[0]) + Decl **locals = context->locals; + if (context->active_scope.current_local > 0) { - Decl **first = &context->locals[0]; - Decl **current = context->active_scope.current_local - 1; - if (context->macro_scope.macro) - { - first = context->macro_scope.locals_start; - if (context->macro_scope.in_yield) - { - first = context->macro_scope.yield_symbol_start; - current = context->macro_scope.yield_symbol_end - 1; - } - } + int64_t first = 0; + int64_t current = context->active_scope.current_local - 1; while (current >= first) { - if (current[0]->name == symbol) + Decl *cur = locals[current]; + if (cur->name == symbol) { // We patch special behaviour here. - if (current[0]->decl_kind == DECL_VAR) + if (cur->decl_kind == DECL_VAR) { - VarDeclKind kind = current[0]->var.kind; + VarDeclKind kind = cur->var.kind; // In this case, we erase the value from parent scopes, so it isn't visible here. if (kind == VARDECL_ERASE) goto JUMP_ERASED; - if (kind == VARDECL_REWRAPPED) return current[0]->var.alias; + if (kind == VARDECL_REWRAPPED) return cur->var.alias; } - return current[0]; + return cur; } current--; } } JUMP_ERASED:; - Context *real_context = context->macro_scope.macro ? context->macro_scope.macro->macro_decl.context : context; + CompilationUnit *unit = context->unit; // Search in file scope. - decl = stable_get(&real_context->local_symbols, symbol); + decl = stable_get(&unit->local_symbols, symbol); if (decl) return decl; // Search in the module. - decl = module_find_symbol(real_context->module, symbol); + decl = module_find_symbol(unit->module, symbol); if (decl) return decl; // Search in imports - VECEACH(real_context->imports, i) + VECEACH(unit->imports, i) { - Decl *import = real_context->imports[i]; + Decl *import = unit->imports[i]; if (!decl_ok(import)) continue; // Skip parameterized modules @@ -219,7 +212,7 @@ static void sema_report_error_on_decl(const char *symbol_str, SourceSpan span, D sema_error_range(span, "'%s' could not be found, did you spell it right?", symbol_str); } -static Decl *sema_resolve_symbol(Context *context, const char *symbol_str, SourceSpan span, Path *path, bool report_error) +static Decl *sema_resolve_symbol(SemaContext *context, const char *symbol_str, SourceSpan span, Path *path, bool report_error) { Decl *ambiguous_other_decl = NULL; Decl *private_decl = NULL; @@ -249,9 +242,9 @@ static Decl *sema_resolve_symbol(Context *context, const char *symbol_str, Sourc sema_report_error_on_decl(symbol_str, span, decl, ambiguous_other_decl, private_decl); return poisoned_decl; } - if (decl->module && decl->module != context->module) + if (decl->module && decl->module != context->unit->module) { - context_register_external_symbol(context, decl); + unit_register_external_symbol(context->compilation_unit, decl); } return decl; } @@ -279,7 +272,7 @@ Decl *sema_find_extension_method_in_module(Module *module, Type *type, const cha return NULL; } -Decl *sema_resolve_method(Context *context, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref) +Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref) { // 1. Look at the previously defined ones. VECEACH(type->methods, i) @@ -292,9 +285,9 @@ Decl *sema_resolve_method(Context *context, Decl *type, const char *method_name, Type *actual_type = type->type; Decl *private_type = NULL; Decl *result = NULL; - VECEACH(context->imports, i) + VECEACH(unit->imports, i) { - Decl *import = context->imports[i]; + Decl *import = unit->imports[i]; if (import->module->is_generic) continue; @@ -322,7 +315,7 @@ Decl *sema_resolve_method(Context *context, Decl *type, const char *method_name, return result; } -Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path *path) +Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, TokenId symbol, Path *path) { Decl *ambiguous_other_decl = NULL; Decl *private_decl = NULL; @@ -331,9 +324,9 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path * if (path) { // 3. Loop over imports. - VECEACH(context->imports, i) + VECEACH(unit->imports, i) { - Decl *import = context->imports[i]; + Decl *import = unit->imports[i]; // Skip any without parameters. if (!import->module->is_generic) continue; @@ -378,9 +371,9 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path * return decl; } // 15. Loop over imports. - VECEACH(context->imports, i) + VECEACH(unit->imports, i) { - Decl *import = context->imports[i]; + Decl *import = unit->imports[i]; // Skip any without parameters. if (!import->module->is_generic) continue; @@ -420,42 +413,51 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path * return decl; } -Decl *sema_resolve_normal_symbol(Context *context, TokenId symbol, Path *path, bool handle_error) +Decl *sema_resolve_normal_symbol(SemaContext *context, TokenId symbol, Path *path, bool handle_error) { return sema_resolve_symbol(context, TOKSTR(symbol), source_span_from_token_id(symbol), path, handle_error); } -Decl *sema_resolve_string_symbol(Context *context, const char *symbol, SourceSpan span, Path *path, bool report_error) +Decl *sema_resolve_string_symbol(SemaContext *context, const char *symbol, SourceSpan span, Path *path, bool report_error) { return sema_resolve_symbol(context, symbol, span, path, report_error); } -static inline bool sema_append_local(Context *context, Decl *decl) +static inline bool sema_append_local(SemaContext *context, Decl *decl) { - if (context->active_scope.current_local == &context->locals[MAX_LOCALS - 1]) + Decl ***locals = &context->locals; + size_t locals_size = vec_size(*locals); + size_t current_local = context->active_scope.current_local; + if (locals_size <= current_local) { - SEMA_ERROR(decl, "Reached the maximum number of locals."); - return false; + while (locals_size <= current_local) + { + vec_add(*locals, decl); + locals_size++; + } + } + else + { + (*locals)[current_local] = decl; } - context->active_scope.current_local[0] = decl; context->active_scope.current_local++; return true; } -bool sema_add_member(Context *context, Decl *decl) +bool sema_add_member(SemaContext *context, Decl *decl) { return sema_append_local(context, decl); } -bool sema_add_local(Context *context, Decl *decl) +bool sema_add_local(SemaContext *context, Decl *decl) { - decl->module = context->module; + Module *current_module = decl->module = context->unit->module; // Ignore synthetic locals. if (decl->name_token.index == NO_TOKEN_ID.index) return true; if (decl->decl_kind == DECL_VAR && decl->var.shadow) goto ADD_VAR; Decl *other = sema_resolve_normal_symbol(context, decl->name_token, NULL, false); assert(!other || other->module); - if (other && other->module == context->module) + if (other && other->module == current_module) { sema_shadow_error(decl, other); decl_poison(decl); @@ -463,7 +465,7 @@ bool sema_add_local(Context *context, Decl *decl) return false; } ADD_VAR:; - Decl ***vars = &context->active_function_for_analysis->func_decl.annotations->vars; + Decl ***vars = &context->current_function->func_decl.annotations->vars; unsigned num_vars = vec_size(*vars); if (num_vars == MAX_LOCALS - 1) { @@ -475,7 +477,7 @@ ADD_VAR:; return sema_append_local(context, decl); } -bool sema_unwrap_var(Context *context, Decl *decl) +bool sema_unwrap_var(SemaContext *context, Decl *decl) { Decl *alias = decl_copy(decl); alias->var.kind = VARDECL_UNWRAPPED; @@ -485,13 +487,13 @@ bool sema_unwrap_var(Context *context, Decl *decl) return sema_append_local(context, alias); } -bool sema_rewrap_var(Context *context, Decl *decl) +bool sema_rewrap_var(SemaContext *context, Decl *decl) { assert(decl->decl_kind == DECL_VAR && decl->var.kind == VARDECL_UNWRAPPED && decl->var.alias->type->type_kind == TYPE_FAILABLE); return sema_append_local(context, decl->var.alias); } -bool sema_erase_var(Context *context, Decl *decl) +bool sema_erase_var(SemaContext *context, Decl *decl) { Decl *erased = decl_copy(decl); erased->var.kind = VARDECL_ERASE; @@ -500,7 +502,7 @@ bool sema_erase_var(Context *context, Decl *decl) } -bool sema_erase_unwrapped(Context *context, Decl *decl) +bool sema_erase_unwrapped(SemaContext *context, Decl *decl) { assert(IS_FAILABLE(decl)); Decl *rewrapped = decl_copy(decl); diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index a04871d51..522d09a47 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -10,19 +10,19 @@ void sema_analysis_pass_process_imports(Module *module) DEBUG_LOG("Pass: Importing dependencies for files in module '%s'.", module->name->module); unsigned import_count = 0; - VECEACH(module->contexts, index) + VECEACH(module->units, index) { // 1. Loop through each context in the module. - Context *context = module->contexts[index]; - DEBUG_LOG("Checking imports for %s.", context->file->name); + CompilationUnit *unit = module->units[index]; + DEBUG_LOG("Checking imports for %s.", unit->file->name); // 2. Loop through imports - unsigned imports = vec_size(context->imports); + unsigned imports = vec_size(unit->imports); for (unsigned i = 0; i < imports; i++) { // 3. Begin analysis - Decl *import = context->imports[i]; + Decl *import = unit->imports[i]; assert(import->resolve_status == RESOLVE_NOT_DONE); import->resolve_status = RESOLVE_RUNNING; @@ -60,10 +60,10 @@ void sema_analysis_pass_process_imports(Module *module) for (unsigned j = 0; j < i; j++) { // 9. We might run into multiple imports of the same package. - if (import->module == context->imports[j]->module) + if (import->module == unit->imports[j]->module) { SEMA_ERROR(import, "Module '%s' was imported more than once, please remove the duplicates.", path->module); - SEMA_PREV(context->imports[j], "Previous import was here"); + SEMA_PREV(unit->imports[j], "Previous import was here"); decl_poison(import); break; } @@ -79,38 +79,38 @@ void sema_analysis_pass_register_globals(Module *module) { DEBUG_LOG("Pass: Register globals for module '%s'.", module->name->module); - VECEACH(module->contexts, index) + VECEACH(module->units, index) { - Context *context = module->contexts[index]; - context->module = module; - DEBUG_LOG("Processing %s.", context->file->name); - Decl **decls = context->global_decls; + CompilationUnit *unit = module->units[index]; + unit->module = module; + DEBUG_LOG("Processing %s.", unit->file->name); + Decl **decls = unit->global_decls; VECEACH(decls, i) { - context_register_global_decl(context, decls[i]); + unit_register_global_decl(unit, decls[i]); } - vec_resize(context->global_decls, 0); + vec_resize(unit->global_decls, 0); } DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); } -static inline void sema_append_decls(Context *context, Decl **decls) +static inline void sema_append_decls(CompilationUnit *unit, Decl **decls) { VECEACH(decls, i) { - context_register_global_decl(context, decls[i]); + unit_register_global_decl(unit, decls[i]); } } -static inline bool sema_analyse_top_level_if(Context *context, Decl *ct_if) +static inline bool sema_analyse_top_level_if(SemaContext *context, Decl *ct_if) { int res = sema_check_comp_time_bool(context, ct_if->ct_if_decl.expr); if (res == -1) return false; if (res) { // Append declarations - sema_append_decls(context, ct_if->ct_if_decl.then); + sema_append_decls(context->unit, ct_if->ct_if_decl.then); return true; } @@ -124,7 +124,7 @@ static inline bool sema_analyse_top_level_if(Context *context, Decl *ct_if) if (res == -1) return false; if (res) { - sema_append_decls(context, ct_elif->ct_elif_decl.then); + sema_append_decls(context->unit, ct_elif->ct_elif_decl.then); return true; } ct_elif = ct_elif->ct_elif_decl.elif; @@ -132,7 +132,7 @@ static inline bool sema_analyse_top_level_if(Context *context, Decl *ct_if) else { assert(ct_elif->decl_kind == DECL_CT_ELSE); - sema_append_decls(context, ct_elif->ct_else_decl); + sema_append_decls(context->unit, ct_elif->ct_else_decl); return true; } } @@ -144,13 +144,16 @@ void sema_analysis_pass_conditional_compilation(Module *module) { DEBUG_LOG("Pass: Top level conditionals %s", module->name->module); - VECEACH(module->contexts, index) + VECEACH(module->units, index) { - Context *context = module->contexts[index]; - for (unsigned i = 0; i < vec_size(context->ct_ifs); i++) + CompilationUnit *unit = module->units[index]; + for (unsigned i = 0; i < vec_size(unit->ct_ifs); i++) { // Also handle switch! - sema_analyse_top_level_if(context, context->ct_ifs[i]); + SemaContext context; + sema_context_init(&context, unit); + sema_analyse_top_level_if(&context, unit->ct_ifs[i]); + sema_context_destroy(&context); } } DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); @@ -159,18 +162,21 @@ void sema_analysis_pass_conditional_compilation(Module *module) void sema_analysis_pass_ct_assert(Module *module) { DEBUG_LOG("Pass: $assert checks %s", module->name->module); - VECEACH(module->contexts, index) + VECEACH(module->units, index) { - Context *context = module->contexts[index]; - VECEACH(context->ct_asserts, i) + SemaContext context; + sema_context_init(&context, module->units[index]); + Decl **asserts = context.unit->ct_asserts; + VECEACH(asserts, i) { - sema_analyse_ct_assert_stmt(context, context->ct_asserts[i]->ct_assert_decl); + sema_analyse_ct_assert_stmt(&context, asserts[i]->ct_assert_decl); } + sema_context_destroy(&context); } DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); } -static inline bool analyse_func_body(Context *context, Decl *decl) +static inline bool analyse_func_body(SemaContext *context, Decl *decl) { if (!decl->func_decl.body) return true; if (!sema_analyse_function_body(context, decl)) return decl_poison(decl); @@ -181,57 +187,59 @@ void sema_analysis_pass_decls(Module *module) { DEBUG_LOG("Pass: Decl analysis %s", module->name->module); - VECEACH(module->contexts, index) + VECEACH(module->units, index) { - Context *context = module->contexts[index]; - context->active_scope = (DynamicScope) + CompilationUnit *unit = module->units[index]; + SemaContext context; + sema_context_init(&context, unit); + context.active_scope = (DynamicScope) { .depth = 0, .scope_id = 0, - .local_decl_start = &context->locals[0], - .current_local = &context->locals[0], + .local_decl_start = 0, + .current_local = 0, }; - context->macro_scope = (MacroScope) { 0 }; - VECEACH(context->enums, i) + VECEACH(unit->enums, i) { - sema_analyse_decl(context, context->enums[i]); + sema_analyse_decl(&context, unit->enums[i]); } - VECEACH(context->types, i) + VECEACH(unit->types, i) { - sema_analyse_decl(context, context->types[i]); + sema_analyse_decl(&context, unit->types[i]); } - VECEACH(context->macros, i) + VECEACH(unit->macros, i) { - sema_analyse_decl(context, context->macros[i]); + sema_analyse_decl(&context, unit->macros[i]); } - VECEACH(context->generics, i) + VECEACH(unit->generics, i) { - sema_analyse_decl(context, context->generics[i]); + sema_analyse_decl(&context, unit->generics[i]); } - VECEACH(context->methods, i) + VECEACH(unit->methods, i) { - sema_analyse_decl(context, context->methods[i]); + sema_analyse_decl(&context, unit->methods[i]); } - VECEACH(context->macro_methods, i) + VECEACH(unit->macro_methods, i) { - sema_analyse_decl(context, context->macro_methods[i]); + sema_analyse_decl(&context, unit->macro_methods[i]); } - VECEACH(context->vars, i) + VECEACH(unit->vars, i) { - sema_analyse_decl(context, context->vars[i]); + sema_analyse_decl(&context, unit->vars[i]); } - VECEACH(context->functions, i) + VECEACH(unit->functions, i) { - sema_analyse_decl(context, context->functions[i]); + sema_analyse_decl(&context, unit->functions[i]); } - if (context->main_function) + if (unit->main_function) { - sema_analyse_decl(context, context->main_function); + sema_analyse_decl(&context, unit->main_function); } - VECEACH(context->generic_defines, i) + VECEACH(unit->generic_defines, i) { - sema_analyse_decl(context, context->generic_defines[i]); + sema_analyse_decl(&context, unit->generic_defines[i]); } + sema_context_destroy(&context); } DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); } @@ -240,18 +248,21 @@ void sema_analysis_pass_functions(Module *module) { DEBUG_LOG("Pass: Function analysis %s", module->name->module); - VECEACH(module->contexts, index) + VECEACH(module->units, index) { - Context *context = module->contexts[index]; - VECEACH(context->methods, i) + CompilationUnit *unit = module->units[index]; + SemaContext context; + sema_context_init(&context, unit); + VECEACH(unit->methods, i) { - analyse_func_body(context, context->methods[i]); + analyse_func_body(&context, unit->methods[i]); } - VECEACH(context->functions, i) + VECEACH(unit->functions, i) { - analyse_func_body(context, context->functions[i]); + analyse_func_body(&context, unit->functions[i]); } - if (context->main_function) analyse_func_body(context, context->main_function); + if (unit->main_function) analyse_func_body(&context, unit->main_function); + sema_context_destroy(&context); } diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 06b8d69f3..8bbd1a815 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -6,7 +6,7 @@ // --- Helper functions -static bool sema_analyse_compound_stmt(Context *context, Ast *statement); +static bool sema_analyse_compound_stmt(SemaContext *context, Ast *statement); typedef enum { @@ -15,7 +15,7 @@ typedef enum COND_TYPE_EVALTYPE_VALUE, } CondType; -static void sema_unwrappable_from_catch_in_else(Context *c, Expr *cond) +static void sema_unwrappable_from_catch_in_else(SemaContext *c, Expr *cond) { assert(cond->expr_kind == EXPR_COND); @@ -55,7 +55,7 @@ static void sema_unwrappable_from_catch_in_else(Context *c, Expr *cond) -static inline bool sema_analyse_block_return_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_block_return_stmt(SemaContext *context, Ast *statement) { assert(context->active_scope.flags & (SCOPE_EXPR_BLOCK | SCOPE_MACRO)); context->active_scope.jump_end = true; @@ -82,7 +82,7 @@ static inline bool sema_analyse_block_return_stmt(Context *context, Ast *stateme * @param statement * @return */ -static inline bool sema_analyse_return_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_return_stmt(SemaContext *context, Ast *statement) { // This might be a return in a function block or a macro which must be treated differently. if (context->active_scope.flags & (SCOPE_EXPR_BLOCK | SCOPE_MACRO)) @@ -117,13 +117,13 @@ static inline bool sema_analyse_return_stmt(Context *context, Ast *statement) return true; } -static inline bool sema_analyse_unreachable_stmt(Context *context) +static inline bool sema_analyse_unreachable_stmt(SemaContext *context) { context->active_scope.jump_end = true; return true; } -static inline bool sema_analyse_try_unwrap(Context *context, Expr *expr) +static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) { assert(expr->expr_kind == EXPR_TRY_UNWRAP); Expr *ident = expr->try_unwrap_expr.variable; @@ -285,7 +285,7 @@ static inline bool sema_analyse_try_unwrap(Context *context, Expr *expr) } -static inline bool sema_analyse_try_unwrap_chain(Context *context, Expr *expr, CondType cond_type) +static inline bool sema_analyse_try_unwrap_chain(SemaContext *context, Expr *expr, CondType cond_type) { assert(cond_type == COND_TYPE_UNWRAP_BOOL || cond_type == COND_TYPE_UNWRAP); @@ -307,7 +307,7 @@ static inline bool sema_analyse_try_unwrap_chain(Context *context, Expr *expr, C expr->resolve_status = RESOLVE_DONE; return true; } -static inline bool sema_analyse_catch_unwrap(Context *context, Expr *expr) +static inline bool sema_analyse_catch_unwrap(SemaContext *context, Expr *expr) { Expr *ident = expr->catch_unwrap_expr.variable; @@ -405,7 +405,7 @@ RESOLVE_EXPRS:; return true; } -static void sema_remove_unwraps_from_try(Context *c, Expr *cond) +static void sema_remove_unwraps_from_try(SemaContext *c, Expr *cond) { assert(cond->expr_kind == EXPR_COND); Expr *last = VECLAST(cond->cond_expr); @@ -427,7 +427,7 @@ static void sema_remove_unwraps_from_try(Context *c, Expr *cond) } } -static inline bool sema_analyse_last_cond(Context *context, Expr *expr, CondType cond_type) +static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, CondType cond_type) { switch (expr->expr_kind) { @@ -511,7 +511,7 @@ NORMAL_EXPR: * * In this case the final value is 4.0 and the type is float. */ -static inline bool sema_analyse_cond_list(Context *context, Expr *expr, CondType cond_type) +static inline bool sema_analyse_cond_list(SemaContext *context, Expr *expr, CondType cond_type) { assert(expr->expr_kind == EXPR_COND); @@ -551,7 +551,7 @@ static inline bool sema_analyse_cond_list(Context *context, Expr *expr, CondType * @param cast_to_bool if the result is to be cast to bool after * @return true if it passes analysis. */ -static inline bool sema_analyse_cond(Context *context, Expr *expr, CondType cond_type) +static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType cond_type) { bool cast_to_bool = cond_type == COND_TYPE_UNWRAP_BOOL; assert(expr->expr_kind == EXPR_COND && "Conditional expressions should always be of type EXPR_DECL_LIST"); @@ -626,7 +626,7 @@ static inline bool sema_analyse_stmt_placement(Expr *cond, Ast *stmt) /** * Check "while" statement, including end of line placement of a single statement. */ -static inline bool sema_analyse_while_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_while_stmt(SemaContext *context, Ast *statement) { Expr *cond = statement->while_stmt.cond; Ast *body = statement->while_stmt.body; @@ -679,7 +679,7 @@ static inline bool sema_analyse_while_stmt(Context *context, Ast *statement) /** * Check the do ... while (...) statement. */ -static inline bool sema_analyse_do_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_do_stmt(SemaContext *context, Ast *statement) { Expr *expr = statement->do_stmt.expr; Ast *body = statement->do_stmt.body; @@ -753,7 +753,7 @@ END:; } -static inline bool sema_analyse_declare_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_declare_stmt(SemaContext *context, Ast *statement) { return sema_analyse_var_decl(context, statement->declare_stmt, true); } @@ -761,7 +761,7 @@ static inline bool sema_analyse_declare_stmt(Context *context, Ast *statement) /** * Check "var $foo = ... " and "var $Foo = ..." */ -static inline bool sema_analyse_var_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_var_stmt(SemaContext *context, Ast *statement) { // 1. Pick the declaration. Decl *decl = statement->var_stmt; @@ -842,13 +842,13 @@ static inline bool sema_analyse_var_stmt(Context *context, Ast *statement) return sema_add_local(context, decl); } -static inline bool sema_analyse_expr_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_expr_stmt(SemaContext *context, Ast *statement) { if (!sema_analyse_expr(context, statement->expr_stmt)) return false; return true; } -static inline bool sema_analyse_defer_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_defer_stmt(SemaContext *context, Ast *statement) { // TODO special parsing of "catch" bool success; @@ -882,7 +882,7 @@ static inline bool sema_analyse_defer_stmt(Context *context, Ast *statement) } -static inline bool sema_analyse_for_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) { bool success = true; bool is_infinite; @@ -961,7 +961,7 @@ static inline bool sema_analyse_for_stmt(Context *context, Ast *statement) } -static inline bool sema_inline_default_iterator(Context *context, Expr *expr, Decl *decl) +static inline bool sema_inline_default_iterator(SemaContext *context, Expr *expr, Decl *decl) { Expr *inner = expr_copy(expr); expr_insert_addr(inner); @@ -973,7 +973,7 @@ static inline bool sema_inline_default_iterator(Context *context, Expr *expr, De return sema_expr_analyse_general_call(context, expr, decl, inner, decl->decl_kind == DECL_MACRO, false); } -static Decl *find_iterator(Context *context, Expr *enumerator) +static Decl *find_iterator(SemaContext *context, Expr *enumerator) { if (!type_may_have_sub_elements(enumerator->type)) { @@ -982,7 +982,7 @@ static Decl *find_iterator(Context *context, Expr *enumerator) } Decl *ambiguous = NULL; Decl *private = NULL; - Decl *method = sema_resolve_method(context, enumerator->type->decl, kw_iterator, &ambiguous, &private); + Decl *method = sema_resolve_method(context->unit, enumerator->type->decl, kw_iterator, &ambiguous, &private); if (!decl_ok(method)) return NULL; if (!method) { @@ -1044,13 +1044,13 @@ static Decl *find_iterator(Context *context, Expr *enumerator) return method; } -static Decl *find_iterator_next(Context *context, Expr *enumerator) +static Decl *find_iterator_next(SemaContext *context, Expr *enumerator) { Type *type = enumerator->type->canonical; assert(type->type_kind == TYPE_STRUCT); Decl *ambiguous = NULL; Decl *private = NULL; - Decl *method = sema_resolve_method(context, type->decl, kw_next, &ambiguous, &private); + Decl *method = sema_resolve_method(context->unit, type->decl, kw_next, &ambiguous, &private); if (!decl_ok(method)) return NULL; if (!method) { @@ -1103,7 +1103,7 @@ static Decl *find_iterator_next(Context *context, Expr *enumerator) return method; } -static Expr *sema_insert_method_macro_call(Context *context, SourceSpan span, Decl *macro_decl, Expr *parent, Expr **arguments) +static Expr *sema_insert_method_macro_call(SemaContext *context, SourceSpan span, Decl *macro_decl, Expr *parent, Expr **arguments) { Expr *len_call = expr_new(EXPR_CALL, span); len_call->resolve_status = RESOLVE_RUNNING; @@ -1117,7 +1117,7 @@ static Expr *sema_insert_method_macro_call(Context *context, SourceSpan span, De return len_call; } -static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statement) { // Pull out the relevant data. Decl *index = statement->foreach_stmt.index; @@ -1426,9 +1426,9 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement) } -static bool sema_analyse_switch_stmt(Context *context, Ast *statement); +static bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement); -static inline bool sema_analyse_if_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement) { // IMPROVE // convert @@ -1529,7 +1529,7 @@ static inline bool sema_analyse_if_stmt(Context *context, Ast *statement) -static bool sema_analyse_asm_stmt(Context *context, Ast *stmt) +static bool sema_analyse_asm_stmt(SemaContext *context, Ast *stmt) { if (!sema_analyse_expr(context, stmt->asm_stmt.body)) return false; if (stmt->asm_stmt.body->expr_kind != EXPR_CONST @@ -1541,7 +1541,7 @@ static bool sema_analyse_asm_stmt(Context *context, Ast *stmt) return true; } -static inline Decl *sema_analyse_label(Context *context, Ast *stmt) +static inline Decl *sema_analyse_label(SemaContext *context, Ast *stmt) { Decl *ambiguous; Decl *dummy; @@ -1567,17 +1567,17 @@ static inline Decl *sema_analyse_label(Context *context, Ast *stmt) return target; } -static bool context_labels_exist_in_scope(Context *context) +static bool context_labels_exist_in_scope(SemaContext *context) { - Decl **last = context->active_scope.current_local; - for (Decl **from = &context->locals[0]; from < last; from++) + Decl **locals = context->locals; + for (size_t local = context->active_scope.current_local; local > 0; local--) { - if ((*from)->decl_kind == DECL_LABEL) return true; + if (locals[local - 1]->decl_kind == DECL_LABEL) return true; } return false; } -static bool sema_analyse_break_stmt(Context *context, Ast *statement) +static bool sema_analyse_break_stmt(SemaContext *context, Ast *statement) { context->active_scope.jump_end = true; if (!context->break_target && !statement->contbreak_stmt.is_label) @@ -1610,7 +1610,7 @@ static bool sema_analyse_break_stmt(Context *context, Ast *statement) return true; } -static bool sema_analyse_nextcase_stmt(Context *context, Ast *statement) +static bool sema_analyse_nextcase_stmt(SemaContext *context, Ast *statement) { context->active_scope.jump_end = true; @@ -1751,7 +1751,7 @@ static bool sema_analyse_nextcase_stmt(Context *context, Ast *statement) return true; } -static bool sema_analyse_continue_stmt(Context *context, Ast *statement) +static bool sema_analyse_continue_stmt(SemaContext *context, Ast *statement) { context->active_scope.jump_end = true; statement->contbreak_stmt.defers.start = context->active_scope.defer_last; @@ -1788,7 +1788,7 @@ static bool sema_analyse_continue_stmt(Context *context, Ast *statement) return true; } -static inline bool sema_analyse_then_overwrite(Context *context, Ast *statement, Ast *replacement) +static inline bool sema_analyse_then_overwrite(SemaContext *context, Ast *statement, Ast *replacement) { if (!sema_analyse_statement(context, replacement)) return false; // Overwrite @@ -1797,7 +1797,7 @@ static inline bool sema_analyse_then_overwrite(Context *context, Ast *statement, } -static bool sema_analyse_ct_if_stmt(Context *context, Ast *statement) +static bool sema_analyse_ct_if_stmt(SemaContext *context, Ast *statement) { int res = sema_check_comp_time_bool(context, statement->ct_if_stmt.expr); if (res == -1) return false; @@ -1833,7 +1833,7 @@ static bool sema_analyse_ct_if_stmt(Context *context, Ast *statement) } -static inline bool sema_analyse_compound_statement_no_scope(Context *context, Ast *compound_statement) +static inline bool sema_analyse_compound_statement_no_scope(SemaContext *context, Ast *compound_statement) { bool all_ok = ast_ok(compound_statement); VECEACH(compound_statement->compound_stmt.stmts, i) @@ -1849,7 +1849,7 @@ static inline bool sema_analyse_compound_statement_no_scope(Context *context, As return all_ok; } -static inline bool sema_check_type_case(Context *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index) +static inline bool sema_check_type_case(SemaContext *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index) { Expr *expr = case_stmt->case_stmt.expr; if (!sema_analyse_expr_rhs(context, type_typeid, expr, false)) return false; @@ -1888,7 +1888,7 @@ static inline ExprConst *flatten_enum_const(Expr *expr) } return const_expr; } -static inline bool sema_check_value_case(Context *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index, bool *if_chained, bool *max_ranged) +static inline bool sema_check_value_case(SemaContext *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index, bool *if_chained, bool *max_ranged) { assert(switch_type); Expr *expr = case_stmt->case_stmt.expr; @@ -1931,7 +1931,7 @@ static inline bool sema_check_value_case(Context *context, Type *switch_type, As return true; } -static bool sema_analyse_switch_body(Context *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases, ExprVariantSwitch *variant, Decl *var_holder) +static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases, ExprVariantSwitch *variant, Decl *var_holder) { bool use_type_id = false; if (!type_is_comparable(switch_type)) @@ -2048,7 +2048,7 @@ static bool sema_analyse_switch_body(Context *context, Ast *statement, SourceSpa return success; } -static bool sema_analyse_ct_switch_body(Context *context, Ast *statement) +static bool sema_analyse_ct_switch_body(SemaContext *context, Ast *statement) { Expr *cond = statement->ct_switch_stmt.cond; Type *type = cond->type; @@ -2151,7 +2151,7 @@ static bool sema_analyse_ct_switch_body(Context *context, Ast *statement) return true; } -static bool sema_analyse_ct_switch_stmt(Context *context, Ast *statement) +static bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statement) { Expr *cond = statement->ct_switch_stmt.cond; if (!sema_analyse_expr(context, cond)) return false; @@ -2163,7 +2163,7 @@ static bool sema_analyse_ct_switch_stmt(Context *context, Ast *statement) return sema_analyse_ct_switch_body(context, statement); } -static bool sema_analyse_switch_stmt(Context *context, Ast *statement) +static bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement) { statement->switch_stmt.scope_defer = context->active_scope.in_defer; @@ -2234,7 +2234,7 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement) -bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement) +bool sema_analyse_ct_assert_stmt(SemaContext *context, Ast *statement) { Expr *expr = statement->ct_assert_stmt.expr; Expr *message = statement->ct_assert_stmt.message; @@ -2265,7 +2265,7 @@ bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement) return true; } -static inline bool sema_analyse_scoping_stmt(Context *context, Ast *statement) +static inline bool sema_analyse_scoping_stmt(SemaContext *context, Ast *statement) { Expr **exprs = statement->scoping_stmt.scoped->expression_list; unsigned scoped_count = vec_size(exprs); @@ -2310,7 +2310,7 @@ static inline bool sema_analyse_scoping_stmt(Context *context, Ast *statement) return sema_analyse_compound_stmt(context, statement); } -bool sema_analyse_assert_stmt(Context *context, Ast *statement) +bool sema_analyse_assert_stmt(SemaContext *context, Ast *statement) { Expr *expr = statement->assert_stmt.expr; Expr *message = statement->assert_stmt.message; @@ -2333,7 +2333,7 @@ bool sema_analyse_assert_stmt(Context *context, Ast *statement) return true; } -static bool sema_analyse_compound_stmt(Context *context, Ast *statement) +static bool sema_analyse_compound_stmt(SemaContext *context, Ast *statement) { bool success; bool ends_with_jump; @@ -2345,7 +2345,7 @@ static bool sema_analyse_compound_stmt(Context *context, Ast *statement) return success; } -static bool sema_analyse_ct_compound_stmt(Context *context, Ast *statement) +static bool sema_analyse_ct_compound_stmt(SemaContext *context, Ast *statement) { bool all_ok = ast_ok(statement); Ast **stmts = statement->compound_stmt.stmts; @@ -2361,7 +2361,7 @@ static bool sema_analyse_ct_compound_stmt(Context *context, Ast *statement) } -static inline bool sema_analyse_statement_inner(Context *context, Ast *statement) +static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *statement) { if (statement->ast_kind == AST_POISONED) { @@ -2451,14 +2451,14 @@ static inline bool sema_analyse_statement_inner(Context *context, Ast *statement } -bool sema_analyse_statement(Context *context, Ast *statement) +bool sema_analyse_statement(SemaContext *context, Ast *statement) { if (sema_analyse_statement_inner(context, statement)) return true; return ast_poison(statement); } -static bool sema_analyse_requires(Context *context, Ast *docs, Ast ***asserts) +static bool sema_analyse_requires(SemaContext *context, Ast *docs, Ast ***asserts) { if (!docs) return true; Ast **directives = docs->directives; @@ -2498,19 +2498,18 @@ static bool sema_analyse_requires(Context *context, Ast *docs, Ast ***asserts) return true; } -bool sema_analyse_function_body(Context *context, Decl *func) +bool sema_analyse_function_body(SemaContext *context, Decl *func) { if (!decl_ok(func)) return false; FunctionSignature *signature = &func->func_decl.function_signature; - context->active_function_for_analysis = func; + context->current_function = func; context->rtype = signature->rtype->type; context->active_scope = (DynamicScope) { .scope_id = 0, .depth = 0, - .local_decl_start = &context->locals[0], - .current_local = &context->locals[0] + .local_decl_start = 0, + .current_local = 0 }; - context->macro_scope = (MacroScope) { 0 }; // Clear returns vec_resize(context->returns, 0); diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 2148c39a9..3a49f878a 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -4,7 +4,7 @@ #include "sema_internal.h" -static inline bool sema_resolve_ptr_type(Context *context, TypeInfo *type_info) +static inline bool sema_resolve_ptr_type(SemaContext *context, TypeInfo *type_info) { if (!sema_resolve_type_shallow(context, type_info->pointer, false, true)) { @@ -15,7 +15,7 @@ static inline bool sema_resolve_ptr_type(Context *context, TypeInfo *type_info) return true; } -bool sema_resolve_array_like_len(Context *context, TypeInfo *type_info, ArraySize *len_ref) +bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, ArraySize *len_ref) { Expr *len_expr = type_info->array.len; if (!sema_analyse_expr(context, len_expr)) return type_info_poison(type_info); @@ -62,7 +62,7 @@ bool sema_resolve_array_like_len(Context *context, TypeInfo *type_info, ArraySiz } // TODO cleanup. -static inline bool sema_resolve_array_type(Context *context, TypeInfo *type, bool shallow) +static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type, bool shallow) { if (type->kind == TYPE_INFO_SUBARRAY || shallow) { @@ -119,7 +119,7 @@ static inline bool sema_resolve_array_type(Context *context, TypeInfo *type, boo } -static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info) +static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_info) { Decl *decl = sema_resolve_normal_symbol(context, type_info->unresolved.name_loc, @@ -188,7 +188,7 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info) } -bool sema_resolve_type(Context *context, Type *type) +bool sema_resolve_type(SemaContext *context, Type *type) { switch (type->type_kind) { @@ -228,7 +228,7 @@ bool sema_resolve_type(Context *context, Type *type) return sema_analyse_decl(context, type->decl); } -bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info, bool allow_inferred_type, bool in_shallow) +bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool allow_inferred_type, bool in_shallow) { if (type_info->resolve_status == RESOLVE_DONE) return type_info_ok(type_info); diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 64f00549e..ca1d74869 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -10,7 +10,7 @@ void sema_shadow_error(Decl *decl, Decl *old) SEMA_PREV(old, "The previous use of '%s' was here.", decl->name); } -bool sema_resolve_type_info_maybe_inferred(Context *context, TypeInfo *type_info, bool allow_inferred_type) +bool sema_resolve_type_info_maybe_inferred(SemaContext *context, TypeInfo *type_info, bool allow_inferred_type) { if (!sema_resolve_type_shallow(context, type_info, allow_inferred_type, false)) return false; Type *type = type_no_fail(type_info->type); @@ -20,14 +20,14 @@ bool sema_resolve_type_info_maybe_inferred(Context *context, TypeInfo *type_info return sema_analyse_decl(context, type->decl); } -bool sema_resolve_type_info(Context *context, TypeInfo *type_info) +bool sema_resolve_type_info(SemaContext *context, TypeInfo *type_info) { return sema_resolve_type_info_maybe_inferred(context, type_info, false); } -void context_change_scope_with_flags(Context *context, ScopeFlags flags) +void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags) { unsigned depth = context->active_scope.depth + 1; if (depth > MAX_SCOPE_DEPTH) @@ -37,7 +37,7 @@ void context_change_scope_with_flags(Context *context, ScopeFlags flags) Ast *previous_defer = context->active_scope.in_defer; AstId parent_defer = context->active_scope.defer_last; - Decl **last_local = context->active_scope.current_local; + unsigned last_local = context->active_scope.current_local; assert(parent_defer < 1000000); // Defer and expression blocks introduce their own return/break/continue // otherwise just merge with the old flags. @@ -63,7 +63,7 @@ void context_change_scope_with_flags(Context *context, ScopeFlags flags) } } -void context_change_scope_for_label(Context *context, Decl *label) +void context_change_scope_for_label(SemaContext *context, Decl *label) { context_change_scope_with_flags(context, SCOPE_NONE); @@ -77,7 +77,7 @@ void context_change_scope_for_label(Context *context, Decl *label) -void context_pop_defers_to(Context *context, DeferList *list) +void context_pop_defers_to(SemaContext *context, DeferList *list) { list->end = context->active_scope.defer_start; assert(context->active_scope.defer_last < 10000000); @@ -89,7 +89,7 @@ void context_pop_defers_to(Context *context, DeferList *list) -Expr *context_pop_defers_and_wrap_expr(Context *context, Expr *expr) +Expr *context_pop_defers_and_wrap_expr(SemaContext *context, Expr *expr) { DeferList defers = { 0, 0 }; context_pop_defers_to(context, &defers); @@ -102,7 +102,18 @@ Expr *context_pop_defers_and_wrap_expr(Context *context, Expr *expr) return expr; } -void context_pop_defers_and_replace_ast(Context *context, Ast *ast) +void context_pop_defers_and_replace_expr(SemaContext *context, Expr *expr) +{ + DeferList defers = { 0, 0 }; + context_pop_defers_to(context, &defers); + if (defers.end == defers.start) return; + Expr *inner = expr_copy(expr); + expr->expr_kind = EXPR_SCOPED_EXPR; + expr->expr_scope.expr = inner; + expr->expr_scope.defers = defers; +} + +void context_pop_defers_and_replace_ast(SemaContext *context, Ast *ast) { DeferList defers = { 0, 0 }; context_pop_defers_to(context, &defers); @@ -120,3 +131,233 @@ void context_pop_defers_and_replace_ast(Context *context, Ast *ast) ast->scoped_stmt.defers = defers; } +static inline void halt_on_error(void) +{ + if (global_context.errors_found > 0) exit_compiler(EXIT_FAILURE); +} + + +static void setup_int_define(const char *id, uint64_t i, Type *type) +{ + TokenType token_type = TOKEN_CONST_IDENT; + id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); + Expr *expr = expr_new(EXPR_CONST, INVALID_RANGE); + assert(type_is_integer(type)); + expr_const_set_int(&expr->const_expr, i, type->type_kind); + if (expr_const_will_overflow(&expr->const_expr, type->type_kind)) + { + error_exit("Integer define %s overflow.", id); + } + expr->type = type; + expr->const_expr.narrowable = true; + expr->span = INVALID_RANGE; + expr->resolve_status = RESOLVE_NOT_DONE; + void *previous = stable_set(&global_context.compiler_defines, id, expr); + if (previous) + { + error_exit("Redefined ident %s", id); + } +} + +void sema_analyze_stage(Module *module, AnalysisStage stage) +{ + while (module->stage < stage) + { + module->stage++; + switch (module->stage) + { + case ANALYSIS_NOT_BEGUN: + UNREACHABLE + case ANALYSIS_IMPORTS: + sema_analysis_pass_process_imports(module); + break; + case ANALYSIS_REGISTER_GLOBALS: + sema_analysis_pass_register_globals(module); + break; + case ANALYSIS_CONDITIONAL_COMPILATION: + sema_analysis_pass_conditional_compilation(module); + break; + case ANALYSIS_DECLS: + sema_analysis_pass_decls(module); + break; + case ANALYSIS_CT_ASSERT: + sema_analysis_pass_ct_assert(module); + break; + case ANALYSIS_FUNCTIONS: + sema_analysis_pass_functions(module); + break; + } + if (global_context.errors_found) return; + } +} + +static void register_generic_decls(Module *module, Decl **decls) +{ + VECEACH(decls, i) + { + Decl *decl = decls[i]; + decl->module = module; + switch (decl->decl_kind) + { + case DECL_POISONED: + case DECL_ENUM_CONSTANT: + case DECL_ERRVALUE: + case DECL_IMPORT: + case DECL_LABEL: + case DECL_CT_ASSERT: + continue; + case DECL_ATTRIBUTE: + break; + case DECL_CT_CASE: + register_generic_decls(module, decl->ct_case_decl.body); + continue; + case DECL_CT_ELIF: + register_generic_decls(module, decl->ct_elif_decl.then); + continue; + case DECL_CT_ELSE: + register_generic_decls(module, decl->ct_else_decl); + continue; + case DECL_CT_IF: + register_generic_decls(module, decl->ct_if_decl.then); + continue; + case DECL_CT_SWITCH: + register_generic_decls(module, decl->ct_switch_decl.cases); + continue; + case DECL_MACRO: + case DECL_DEFINE: + case DECL_DISTINCT: + case DECL_ENUM: + case DECL_GENERIC: + case DECL_ERRTYPE: + case DECL_FUNC: + case DECL_STRUCT: + case DECL_TYPEDEF: + case DECL_UNION: + case DECL_VAR: + case DECL_BITSTRUCT: + break; + } + if (decl->visibility > VISIBLE_MODULE) + { + stable_set(&module->public_symbols, decl->name, decl); + } + stable_set(&module->symbols, decl->name, decl); + } + +} + +static void setup_bool_define(const char *id, bool value) +{ + TokenType token_type = TOKEN_CONST_IDENT; + id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); + Expr *expr = expr_new(EXPR_CONST, INVALID_RANGE); + expr_const_set_bool(&expr->const_expr, value); + expr->type = type_bool; + expr->span = INVALID_RANGE; + expr->resolve_status = RESOLVE_NOT_DONE; + void *previous = stable_set(&global_context.compiler_defines, id, expr); + if (previous) + { + error_exit("Redefined ident %s", id); + } +} + +static void analyze_generic_module(Module *module) +{ + assert(module->parameters && module->is_generic); + // TODO maybe do this analysis: sema_analysis_pass_process_imports(module); + VECEACH(module->units, index) + { + register_generic_decls(module, module->units[index]->global_decls); + } +} + +static void analyze_to_stage(AnalysisStage stage) +{ + VECEACH(global_context.module_list, i) + { + sema_analyze_stage(global_context.module_list[i], stage); + } + halt_on_error(); +} + +void sema_analysis_run(void) +{ + setup_int_define("C_SHORT_SIZE", platform_target.width_c_short, type_long); + setup_int_define("C_INT_SIZE", platform_target.width_c_int, type_long); + setup_int_define("C_LONG_SIZE", platform_target.width_c_long, type_long); + setup_int_define("C_LONG_LONG_SIZE", platform_target.width_c_long_long, type_long); + setup_bool_define("C_CHAR_IS_SIGNED", platform_target.signed_c_char); + setup_bool_define("PLATFORM_BIG_ENDIAN", platform_target.big_endian); + setup_bool_define("PLATFORM_I128_SUPPORTED", platform_target.int128); + setup_int_define("COMPILER_OPT_LEVEL", (uint64_t)active_target.optimization_level, type_int); + setup_int_define("COMPILER_SIZE_OPT_LEVEL", (uint64_t)active_target.size_optimization_level, type_int); + setup_bool_define("COMPILER_SAFE_MODE", active_target.feature.safe_mode); + + type_init_cint(); + + global_context_clear_errors(); + + if (global_context.lib_dir) + { + file_add_wildcard_files(&global_context.sources, global_context.lib_dir, true, ".c3", ".c3i"); + } + bool has_error = false; + VECEACH(global_context.sources, i) + { + bool loaded = false; + File *file = source_file_load(global_context.sources[i], &loaded); + if (loaded) continue; + if (!parse_file(file)) has_error = true; + } + + if (has_error) exit_compiler(EXIT_FAILURE); + + global_context.std_module_path = (Path) { .module = kw_std, .span = INVALID_RANGE, .len = (uint32_t) strlen(kw_std) }; + global_context.std_module = (Module){ .name = &global_context.std_module_path }; + global_context.std_module.stage = ANALYSIS_LAST; + global_context.locals_list = NULL; + + stable_init(&global_context.std_module.symbols, 0x10000); + + if (!global_context.module_list) + { + if (global_context.errors_found) exit_compiler(EXIT_FAILURE); + error_exit("No modules to compile."); + } + VECEACH(global_context.generic_module_list, i) + { + analyze_generic_module(global_context.generic_module_list[i]); + } + for (AnalysisStage stage = ANALYSIS_NOT_BEGUN + 1; stage <= ANALYSIS_LAST; stage++) + { + analyze_to_stage(stage); + } + +} + +void sema_context_init(SemaContext *context, CompilationUnit *unit) +{ + *context = (SemaContext) { .unit = unit, .compilation_unit = unit, .locals = global_context_acquire_locals_list() }; +} + +void sema_context_destroy(SemaContext *context) +{ + generic_context_release_locals_list(context->locals); +} + +Decl **global_context_acquire_locals_list(void) +{ + if (!vec_size(global_context.locals_list)) + { + return VECNEW(Decl*, 64); + } + Decl **result = VECLAST(global_context.locals_list); + vec_pop(global_context.locals_list); + return result; +} + +void generic_context_release_locals_list(Decl **list) +{ + vec_add(global_context.locals_list, list); +} diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index a5609a144..d6cd8abc9 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -208,6 +208,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_UNUSED] = KW_DEF("unused"); attribute_list[ATTRIBUTE_USED] = KW_DEF("used"); attribute_list[ATTRIBUTE_NAKED] = KW_DEF("naked"); + attribute_list[ATTRIBUTE_NOSCOPE] = KW_DEF("noscope"); attribute_list[ATTRIBUTE_CDECL] = KW_DEF("cdecl"); attribute_list[ATTRIBUTE_STDCALL] = KW_DEF("stdcall"); attribute_list[ATTRIBUTE_VECCALL] = KW_DEF("veccall"); diff --git a/src/version.h b/src/version.h index e25901307..590077abd 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "PRE.8" \ No newline at end of file +#define COMPILER_VERSION "PRE.9" \ No newline at end of file diff --git a/test/test_suite/macros/macro_defer_noscope.c3t b/test/test_suite/macros/macro_defer_noscope.c3t new file mode 100644 index 000000000..2996962aa --- /dev/null +++ b/test/test_suite/macros/macro_defer_noscope.c3t @@ -0,0 +1,56 @@ +// #target: x64-darwin +module foo; +extern fn void puts(char *); + +fn void foo1() +{ + puts("foo1"); +} + +module foo2; +import foo; +fn void foo2() +{ + foo::puts("foo2"); +} +module bar; +import foo2; +macro bar1(#test) @noscope +{ + defer foo2::foo2(); + #test; + #test; +} + +module baz; +import foo; +import bar; +extern fn void printf(char *, ...); +fn void main() +{ + var $foo = 1; + @bar::bar1(foo::foo1()); + @bar::bar1($foo += 1); + printf("End: %d\n", $foo); +} + +/* #expect: baz.ll + +declare void @foo2.foo2() +declare void @foo.foo1() + +define void @baz.main() #0 { +entry: + call void @foo.foo1() + call void @foo.foo1() + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i32 3) + call void @foo2.foo2() + br label %exit + +exit: ; preds = %entry + call void @foo2.foo2() + br label %exit1 + +exit1: ; preds = %exit + ret void +} diff --git a/test/test_suite/macros/macro_defer_scope.c3t b/test/test_suite/macros/macro_defer_scope.c3t new file mode 100644 index 000000000..5c3f7d35d --- /dev/null +++ b/test/test_suite/macros/macro_defer_scope.c3t @@ -0,0 +1,41 @@ +// #target: x64-darwin +module foo; +macro int cofefe(#a) +{ + int x = 0; + defer printf("Was here\n"); + return #a + #a; +} + +extern fn int printf(char *, ...); + +fn void main() +{ + int x = 0; + @cofefe(x += 1); + printf("%d\n", x); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %x1 = alloca i32, align 4 + store i32 0, i32* %x, align 4 + store i32 0, i32* %x1, align 4 + %0 = load i32, i32* %x, align 4 + %add = add i32 %0, 1 + store i32 %add, i32* %x, align 4 + %1 = load i32, i32* %x, align 4 + %add2 = add i32 %1, 1 + store i32 %add2, i32* %x, align 4 + %add3 = add i32 %add, %add2 + %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0)) + br label %exit + +exit: ; preds = %entry + %3 = load i32, i32* %x, align 4 + %4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 %3) + ret void +} diff --git a/test/test_suite/macros/macro_defer_with_body.c3t b/test/test_suite/macros/macro_defer_with_body.c3t new file mode 100644 index 000000000..7453a7269 --- /dev/null +++ b/test/test_suite/macros/macro_defer_with_body.c3t @@ -0,0 +1,24 @@ +module foo; +macro int cofefe(a; @body(x)) +{ + @body(a); + @body(a); + return 1; +} + +extern fn int printf(char *, ...); + +fn void main() +{ + int x = 0; + @cofefe(1; int y) + { + defer printf("defer: %d\n", x++); + printf("%d\n", x++); + }; + printf("Done!\n"); +} + +/* expect: foo.ll + +feokfef \ No newline at end of file diff --git a/test/test_suite/macros/macro_import_res_private.c3t b/test/test_suite/macros/macro_import_res_private.c3t new file mode 100644 index 000000000..620e3e1b1 --- /dev/null +++ b/test/test_suite/macros/macro_import_res_private.c3t @@ -0,0 +1,26 @@ +// #target: x64-darwin +module foo; +private fn void foo1() +{} + +module bar; +import private foo; +macro bar1() +{ + foo::foo1(); +} + +module baz; +import bar; +fn void test() +{ + @bar1(); +} + +/* #expect: baz.ll + +define void @baz.test() #0 { +entry: + call void @foo.foo1() + ret void +} \ No newline at end of file