diff --git a/resources/lib/std/mem.c3 b/resources/lib/std/mem.c3 index 885cb977c..8e8e7cb08 100644 --- a/resources/lib/std/mem.c3 +++ b/resources/lib/std/mem.c3 @@ -22,7 +22,7 @@ public error AllocationFailure AllocationFailureKind failureKind; } -public typedef func void!(void *data, void** pointer, usize bytes, usize alignment, AllocationKind kind) as AllocatorFunction; +public define AllocatorFunction = func void!(void *data, void** pointer, usize bytes, usize alignment, AllocationKind kind); public struct Allocator { diff --git a/resources/testproject/foo.c3 b/resources/testproject/foo.c3 index bff7459da..e66e33cee 100644 --- a/resources/testproject/foo.c3 +++ b/resources/testproject/foo.c3 @@ -9,7 +9,7 @@ public struct Foo extern func void printf(char *hello); -local func void ofke() +func void ofke() {} func void exple() {} diff --git a/src/build/build_options.c b/src/build/build_options.c index 16b9c291e..f48fa5c1d 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -107,7 +107,7 @@ static const char* check_dir(const char *path) } if (chdir(path) == -1) error_exit("The path \"%s\" does not point to a valid directory.", path); int err = chdir(original_path); - assert(!err); + if (err) FAIL_WITH_ERR("Failed to change path to %s.", original_path); return path; } diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 169be79b8..471d2af82 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -12,6 +12,9 @@ #define USE_PTHREAD 0 #endif +#define MAX_OUTPUT_FILES 100000000 +#define MAX_MODULES 10000000 + GlobalContext global_context; BuildTarget active_target; @@ -227,6 +230,15 @@ void compiler_compile(void) Module **modules = global_context.module_list; unsigned module_count = vec_size(modules); + if (module_count > MAX_MODULES) + { + error_exit("Too many modules."); + } + if (module_count < 1) + { + error_exit("No module to compile."); + } + if (active_target.output_headers) { for (unsigned i = 0; i < module_count; i++) @@ -246,7 +258,6 @@ void compiler_compile(void) if (result) vec_add(gen_contexts, result); } - printf("-- AST/EXPR INFO -- \n"); printf(" * Ast memory use: %llukb\n", (unsigned long long)ast_arena.allocated / 1024); printf(" * Decl memory use: %llukb\n", (unsigned long long)decl_arena.allocated / 1024); @@ -269,6 +280,10 @@ void compiler_compile(void) bool create_exe = !active_target.test_output && (active_target.type == TARGET_TYPE_EXECUTABLE || active_target.type == TARGET_TYPE_TEST); size_t output_file_count = vec_size(gen_contexts); + if (output_file_count > MAX_OUTPUT_FILES) + { + error_exit("Too many output files."); + } if (!output_file_count) { error_exit("No output files found."); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 32f6c5c88..a3174482c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -452,7 +452,7 @@ typedef struct }; Decl *alias; }; - Expr **params; + TypeInfo **params; } DefineDecl; typedef struct @@ -1697,6 +1697,17 @@ bool token_is_type(TokenType type); bool token_is_any_type(TokenType type); bool token_is_symbol(TokenType type); const char *token_type_to_string(TokenType type); +static inline TokenType advance_token(TokenId *token) +{ + TokenType tok; + while (1) + { + token->index += 1; + tok = TOKTYPE(*token); + if (tok != TOKEN_COMMENT) return tok; + } +} + AlignSize type_abi_alignment(Type *type); AlignSize type_alloca_alignment(Type *type); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 555ea58b5..1f804f2e6 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -24,7 +24,7 @@ static inline void copy_flow(Ast *ast) ast->flow.label = decl_copy_label_from_macro(ast->flow.label, ast); } -static TypeInfo** type_info_copy_list_from_macro(Context *context, TypeInfo **to_copy) +static TypeInfo** type_info_copy_list_from_macro(TypeInfo **to_copy) { TypeInfo **result = NULL; VECEACH(to_copy, i) @@ -561,7 +561,7 @@ Decl *copy_decl(Decl *decl) case DECL_ATTRIBUTE: TODO case DECL_DEFINE: - MACRO_COPY_EXPR_LIST(decl->define_decl.params); + MACRO_COPY_TYPE_LIST(decl->define_decl.params); switch (decl->define_decl.define_kind) { case DEFINE_FUNC: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 113b7c943..746e704a0 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -433,7 +433,6 @@ typedef enum TOKEN_SWITCH, TOKEN_TRUE, TOKEN_TRY, - TOKEN_TYPEDEF, TOKEN_TYPEOF, TOKEN_UNION, TOKEN_VAR, // Reserved diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 601d7c12b..720abc7a9 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -168,7 +168,7 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig LLVMValueRef hi_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 1, "hi"); // Store it in the struct. AlignSize hi_alignment = MIN(llvm_abi_alignment(c, hi), decl_alignment); - llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), decl_alignment); + llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), hi_alignment); return; } case ABI_ARG_DIRECT_COERCE: diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index ed24a39ab..53a7f97d2 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -2,7 +2,7 @@ #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); /** * Walk forward through the token stream to identify a type on the format: foo::bar::Type @@ -20,12 +20,7 @@ static bool context_next_is_type_with_path_prefix(Context *context) TokenType tok; // 1. Step past the '::' and any following comment (doc comments are not allowed here!) - while (1) - { - current.index += 1; - tok = TOKTYPE(current); - if (tok != TOKEN_COMMENT) break; - } + tok = advance_token(¤t); // 2. Check that we have an ident, otherwise if // we see a type token, we're done and return true @@ -34,12 +29,7 @@ static bool context_next_is_type_with_path_prefix(Context *context) // 3. Now we've confirmed that there is an ident, step past it // and any following comments. - while (1) - { - current.index += 1; - tok = TOKTYPE(current); - if (tok != TOKEN_COMMENT) break; - } + tok = advance_token(¤t); // 4. If we don't see '::' after an ident we're done. // And we know it's not a type. @@ -77,7 +67,6 @@ void recover_top_level(Context *context) switch (context->tok.type) { case TOKEN_PUBLIC: - case TOKEN_TYPEDEF: case TOKEN_STRUCT: case TOKEN_INTERFACE: case TOKEN_IMPORT: @@ -849,10 +838,46 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility) return decl; } +/** + * Possibilities: + * foo(...) + * Bar.foo(...) + * foo::baz::bar.foo(...) + * + * @return true if this is a function start. + */ +static inline bool is_function_start(Context *context) +{ + // If it's a ! then it must be function! + if (TOKEN_IS(TOKEN_BANG)) return true; + if (TOKEN_IS(TOKEN_IDENT)) + { + 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->tok.id; + TokenType tok = TOKTYPE(current); + while (1) + { + if (tok != TOKEN_IDENT) break; + tok = advance_token(¤t); + if (tok != TOKEN_SCOPE) break; + tok = advance_token(¤t); + } + if (tok != TOKEN_TYPE_IDENT) return false; + tok = advance_token(¤t); + if (tok != TOKEN_DOT) return false; + tok = advance_token(¤t); + if (tok != TOKEN_IDENT) return false; + tok = advance_token(¤t); + return tok == TOKEN_LPAREN; +} + /** * global_declaration * : failable_type IDENT ';' * | failable_type IDENT '=' expression ';' + * | failable_type func_definition * ; * * @param visibility @@ -864,12 +889,6 @@ static inline Decl *parse_global_declaration(Context *context, Visibility visibi Decl *decl = decl_new_var(context->tok.id, type, VARDECL_GLOBAL, visibility); - if (TOKEN_IS(TOKEN_FUNC)) - { - SEMA_TOKEN_ERROR(context->tok, "'func' can't appear here, maybe you intended to put 'func' the type?"); - advance(context); - return poisoned_decl; - } if (TOKEN_IS(TOKEN_CONST_IDENT)) { @@ -1463,39 +1482,36 @@ static inline Decl *parse_generics_declaration(Context *context, Visibility visi } /** - * define_parameters ::= '(' expr (',' expr)* ')' + * define_parameters ::= type (',' type)* '>' * - * @return NULL if parsing failed, otherwise a list of Expr* + * @return NULL if parsing failed, otherwise a list of Type* */ -static inline Expr **parse_parameterized_define(Context *context, Visibility visibility) +static inline TypeInfo **parse_parameterized_define(Context *context) { - CONSUME_OR(TOKEN_LPAREN, NULL); - Expr **exprs = NULL; - while (!try_consume(context, TOKEN_RPAREN)) + TypeInfo **types = NULL; + while (!try_consume(context, TOKEN_GREATER)) { - Expr *expr = TRY_EXPR_OR(parse_constant_expr(context), NULL); - vec_add(exprs, expr); - if (context->tok.type != TOKEN_RPAREN) + TypeInfo *expr = TRY_TYPE_OR(parse_type(context), NULL); + vec_add(types, expr); + if (context->tok.type != TOKEN_RPAREN && context->tok.type != TOKEN_GREATER) { TRY_CONSUME_OR(TOKEN_COMMA, "Expected ',' after argument.", NULL); } } - return exprs; + return types; } /** * func_define ::= failable_type opt_parameter_type_list */ -static inline bool parse_func_define(Context *context, Decl *decl, Visibility visibility) +static inline bool parse_func_define(Context *context, Decl *decl, Visibility visibility, TypeInfo *return_type) { decl->define_decl.define_kind = DEFINE_FUNC; - advance_and_verify(context, TOKEN_FUNC); - TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), false); if (try_consume(context, TOKEN_BANG)) { decl->define_decl.function_signature.failable = true; } - decl->define_decl.function_signature.rtype = type_info; + decl->define_decl.function_signature.rtype = return_type; if (!parse_opt_parameter_type_list(context, visibility, &(decl->typedef_decl.function_signature), true)) { return false; @@ -1503,87 +1519,199 @@ static inline bool parse_func_define(Context *context, Decl *decl, Visibility vi return true; } -/** - * define_decl ::= DEFINE path? (IDENT | TYPE_IDENT | CONST_IDENT) define_parameters? as (IDENT | TYPE_IDENT | CONST_IDENT) - */ -static inline Decl *parse_define(Context *context, Visibility visibility) + +static inline Decl *parse_typedef_body_function_ptr(Context *context, Decl *decl) { - advance_and_verify(context, TOKEN_DEFINE); - Decl *decl = decl_new(DECL_DEFINE, context->tok.id, visibility); - if (try_consume(context, TOKEN_FUNC)) + decl->typedef_decl.is_func = true; + assert(decl->typedef_decl.type_info); + decl->typedef_decl.function_signature.rtype = decl->typedef_decl.type_info; + if (try_consume(context, TOKEN_BANG)) { - if (!parse_func_define(context, decl, visibility)) return poisoned_decl; + decl->typedef_decl.function_signature.failable = true; } - else if (parse_next_is_type(context)) + if (!parse_opt_parameter_type_list(context, decl->visibility, &(decl->typedef_decl.function_signature), true)) { - decl->define_decl.define_kind = DEFINE_TYPE_ALIAS; - decl->define_decl.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl); - } - else if (TOKEN_IS(TOKEN_IDENT) || TOKEN_IS(TOKEN_CONST_IDENT)) - { - decl->define_decl.path = NULL; - if (context->next_tok.type == TOKEN_SCOPE) - { - bool error; - decl->define_decl.path = parse_path_prefix(context, &error); - if (error) return poisoned_decl; - } - decl->define_decl.identifier = context->tok.id; - if (try_consume(context, TOKEN_CONST_IDENT) || try_consume(context, TOKEN_IDENT)) - { - decl->define_decl.define_kind = DEFINE_IDENT_ALIAS; - } - else - { - SEMA_TOKEN_ERROR(context->tok, "Expected an identifier, constant or type."); - return poisoned_decl; - } - } - else - { - SEMA_TOKEN_ERROR(context->tok, "Expected a constant, type or identifier here."); return poisoned_decl; } + TRY_CONSUME_OR(TOKEN_STAR, "Function pointers must end with a '*'", poisoned_decl); + RANGE_EXTEND_PREV(decl); + TRY_CONSUME_EOS_OR(poisoned_decl); + return decl; +} - Expr **exprs = NULL; - if (TOKEN_IS(TOKEN_LPAREN)) - { - exprs = parse_parameterized_define(context, visibility); - if (!exprs) return poisoned_decl; - TRY_CONSUME_OR(TOKEN_AS, "Expected 'as' after the generic declaration, did you forget it", poisoned_decl); - decl->define_decl.is_parameterized = true; - decl->define_decl.params = exprs; - } - else - { - TRY_CONSUME_OR(TOKEN_AS, "Expected 'as' after the name, did you forget it?", poisoned_decl); - } - // Parse optional "distinct" +/** + * define_type_body ::= + * TYPE_IDENT '=' typedef_body | generic_define (('distinct') type ('!' parameter_type_list '*')?) | (path TYPE_IDENT '(' type_list ')') + * + */ +static inline Decl *parse_define_type(Context *context, Visibility visibility) +{ + TokenId start = context->tok.id; + advance_and_verify(context, TOKEN_DEFINE); + + TokenId alias_name = context->tok.id; + advance_and_verify(context, TOKEN_TYPE_IDENT); + CONSUME_OR(TOKEN_EQ, poisoned_decl); + bool distinct = false; if (context->tok.type == TOKEN_IDENT && TOKSTR(context->tok) == kw_distinct) { - if (decl->define_decl.define_kind != DEFINE_TYPE_ALIAS || decl->define_decl.is_parameterized) - { - SEMA_TOKID_ERROR(context->tok.id, "'distinct' can only be used for regular types."); - return poisoned_decl; - } + distinct = true; advance(context); - decl->define_decl.define_kind = DEFINE_DISTINCT_TYPE; } - decl->name = TOKSTR(context->tok); - decl->name_token = context->tok.id; - if (!token_is_symbol(context->tok.type)) + // 1. Did we have `func`? In that case it's a function pointer. + if (try_consume(context, TOKEN_FUNC)) { - SEMA_TOKEN_ERROR(context->tok, "The aliased name must follow after 'as'."); - return poisoned_decl; + assert(!distinct && "TODO"); + Decl *decl = decl_new_with_type(alias_name, DECL_TYPEDEF, visibility); + decl->span.loc = start; + decl->typedef_decl.is_func = true; + TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl); + decl->typedef_decl.function_signature.rtype = type_info; + if (try_consume(context, TOKEN_BANG)) + { + decl->typedef_decl.function_signature.failable = true; + } + if (!parse_opt_parameter_type_list(context, decl->visibility, &(decl->typedef_decl.function_signature), true)) + { + return poisoned_decl; + } + RANGE_EXTEND_PREV(decl); + TRY_CONSUME_EOS_OR(poisoned_decl); + return decl; + + } + TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl); + + // 2. define Foo = foo::bar::Type; + // this is always a normal typedef / distinct. + if (TOKEN_IS(TOKEN_EOS)) + { + Decl *decl = decl_new_with_type(alias_name, distinct ? DECL_DISTINCT : DECL_TYPEDEF, visibility); + decl->span.loc = start; + decl->typedef_decl.type_info = type_info; + decl->typedef_decl.is_func = false; + if (distinct) + { + decl->distinct_decl.typedef_decl = decl->typedef_decl; + decl->type->type_kind = TYPE_DISTINCT; + decl->decl_kind = DECL_DISTINCT; + } + RANGE_EXTEND_PREV(decl); + advance_and_verify(context, TOKEN_EOS); + return decl; + } + + // 3. Assume we missed a ';' if we don't see '<' + if (!TOKEN_IS(TOKEN_LESS)) + { + SEMA_TOKEN_ERROR(context->tok, "Expected a ';' here"); + return false; } advance(context); - CONSUME_OR(TOKEN_EOS, poisoned_decl); + // 4. We assume parameterization + if (TOKEN_IS(TOKEN_GREATER)) + { + SEMA_TOKEN_ERROR(context->tok, "Expected at least one type as a parameter."); + return poisoned_decl; + } + TypeInfo **types = parse_parameterized_define(context); + if (!types) return poisoned_decl; + Decl *decl = decl_new(DECL_DEFINE, alias_name, visibility); + decl->span.loc = start; + decl->define_decl.is_parameterized = true; + decl->define_decl.params = types; + decl->define_decl.define_kind = DEFINE_TYPE_ALIAS; + decl->define_decl.type_info = type_info; + RANGE_EXTEND_PREV(decl); + TRY_CONSUME_EOS_OR(poisoned_decl); return decl; +} +static inline Decl *parse_define_ident(Context *context, Visibility visibility) +{ + // 1. Store the beginning of the define. + 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->tok.type; + if (alias_type != TOKEN_IDENT && alias_type != TOKEN_CONST_IDENT) + { + SEMA_TOKEN_ERROR(context->tok, "An regular identifier was expected here."); + return poisoned_decl; + } + + // 3. Set up the define. + Decl *decl = decl_new(DECL_DEFINE, context->tok.id, visibility); + decl->define_decl.define_kind = DEFINE_IDENT_ALIAS; + decl->span.loc = start; + + // 4. Advance and consume the '=' + advance(context); + CONSUME_OR(TOKEN_EQ, poisoned_decl); + + // 5. Here we may an (optional) path, we just check if it starts + // with IDENT '::' + decl->define_decl.path = NULL; + if (TOKEN_IS(TOKEN_IDENT) && context->next_tok.type == TOKEN_SCOPE) + { + bool error; + decl->define_decl.path = parse_path_prefix(context, &error); + if (error) return poisoned_decl; + } + + // 6. Check that the token after the path is of the same type. + if (context->tok.type != alias_type) + { + if (alias_type == TOKEN_CONST_IDENT) + { + SEMA_TOKEN_ERROR(context->tok, "Expected a constant name here."); + } + else + { + SEMA_TOKEN_ERROR(context->tok, "Expected a function or variable name here."); + } + return poisoned_decl; + } + + // 7. Consume the identifier + decl->define_decl.identifier = context->tok.id; + advance(context); + + // 8. Is this one parameterized? If so parse the parameters. + if (try_consume(context, TOKEN_LESS)) + { + if (TOKEN_IS(TOKEN_GREATER)) + { + SEMA_TOKEN_ERROR(context->tok, "Expected at least one type as a parameter."); + return poisoned_decl; + } + TypeInfo **types = parse_parameterized_define(context); + if (!types) return poisoned_decl; + decl->define_decl.is_parameterized = true; + decl->define_decl.params = types; + } + + RANGE_EXTEND_PREV(decl); + TRY_CONSUME_EOS_OR(poisoned_decl); + + return decl; +} +/** + * define_decl ::= DEFINE define_type_body | + */ +static inline Decl *parse_define(Context *context, Visibility visibility) +{ + if (context->next_tok.type == TOKEN_TYPE_IDENT) + { + return parse_define_type(context, visibility); + } + return parse_define_ident(context, visibility); } @@ -1595,7 +1723,7 @@ static AttributeDomain TOKEN_TO_ATTR[TOKEN_EOF + 1] = { [TOKEN_INTERFACE] = ATTR_INTERFACE, [TOKEN_UNION] = ATTR_UNION, [TOKEN_CONST] = ATTR_CONST, - [TOKEN_TYPEDEF] = ATTR_TYPEDEF, + [TOKEN_DEFINE] = ATTR_TYPEDEF, [TOKEN_ERR] = ATTR_ERROR, }; @@ -1654,66 +1782,7 @@ static inline Decl *parse_attribute_declaration(Context *context, Visibility vis return decl; } -/** - * func_typedef - * : FUNC failable_type opt_parameter_type_list - * | FUNC failable_type opt_parameter_type_list throw_declaration - * ; - */ -static inline bool parse_func_typedef(Context *context, Decl *decl, Visibility visibility) -{ - decl->typedef_decl.is_func = true; - advance_and_verify(context, TOKEN_FUNC); - TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), false); - if (try_consume(context, TOKEN_BANG)) - { - decl->typedef_decl.function_signature.failable = true; - } - decl->typedef_decl.function_signature.rtype = type_info; - if (!parse_opt_parameter_type_list(context, visibility, &(decl->typedef_decl.function_signature), true)) - { - return false; - } - return true; -} -/** - * typedef_declaration - * : TYPEDEF (func_typedef | type) AS ('distinct')? type_ident - * - * @param context - * @param visibility - * @return - */ -static inline Decl *parse_typedef_declaration(Context *context, Visibility visibility) -{ - advance_and_verify(context, TOKEN_TYPEDEF); - Decl *decl = decl_new_with_type(context->tok.id, DECL_TYPEDEF, visibility); - if (TOKEN_IS(TOKEN_FUNC)) - { - if (!parse_func_typedef(context, decl, visibility)) return poisoned_decl; - } - else - { - decl->typedef_decl.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl); - decl->typedef_decl.is_func = false; - } - CONSUME_OR(TOKEN_AS, poisoned_decl); - - // Parse optional "distinct" - if (context->tok.type == TOKEN_IDENT && TOKSTR(context->tok) == kw_distinct) - { - advance(context); - decl->type->type_kind = TYPE_DISTINCT; - decl->decl_kind = DECL_DISTINCT; - } - decl->name = TOKSTR(context->tok); - decl->type->name = TOKSTR(context->tok); - decl->name_token = context->tok.id; - if (!consume_type_name(context, "typedef")) return poisoned_decl; - CONSUME_OR(TOKEN_EOS, poisoned_decl); - return decl; -} /** * macro ::= MACRO (type '!'?)? identifier '!'? '(' macro_params ')' compound_statement @@ -1916,11 +1985,9 @@ static inline Decl *parse_enum_declaration(Context *context, Visibility visibili */ static inline Decl *parse_func_definition(Context *context, Visibility visibility, bool is_interface) { + Decl *func = decl_new(DECL_FUNC, context->next_tok.id, visibility); advance_and_verify(context, TOKEN_FUNC); - - TypeInfo *return_type = TRY_TYPE_OR(parse_type(context), poisoned_decl); - Decl *func = DECL_NEW(DECL_FUNC, visibility); - func->func.function_signature.rtype = return_type; + func->func.function_signature.rtype = TRY_TYPE_OR(parse_type(context), poisoned_decl); func->func.function_signature.failable = try_consume(context, TOKEN_BANG); SourceSpan start = source_span_from_token_id(context->tok.id); bool had_error = false; @@ -1993,8 +2060,18 @@ static inline Decl *parse_interface_declaration(Context *context, Visibility vis CONSUME_OR(TOKEN_LBRACE, poisoned_decl); - while (TOKEN_IS(TOKEN_FUNC)) + while (!TOKEN_IS(TOKEN_RBRACE)) { + if (TOKEN_IS(TOKEN_PUBLIC)) + { + SEMA_TOKEN_ERROR(context->tok, "Interface functions cannot have visibility."); + return poisoned_decl; + } + if (!TOKEN_IS(TOKEN_FUNC)) + { + SEMA_TOKEN_ERROR(context->tok, "Expected a function here."); + return poisoned_decl; + } Decl *function = TRY_DECL_OR(parse_func_definition(context, visibility, true), poisoned_decl); vec_add(decl->interface_decl.functions, function); } @@ -2303,15 +2380,17 @@ Decl *parse_top_level_statement(Context *context) case TOKEN_ERR: decl = TRY_DECL_OR(parse_error_declaration(context, visibility), poisoned_decl); break; - case TOKEN_TYPEDEF: - decl = TRY_DECL_OR(parse_typedef_declaration(context, visibility), poisoned_decl); - break; case TOKEN_CT_TYPE_IDENT: case TOKEN_TYPE_IDENT: // All of these start type decl = TRY_DECL_OR(parse_global_declaration(context, visibility), poisoned_decl); break; case TOKEN_IDENT: + if (context->next_tok.type == TOKEN_SCOPE) + { + decl = TRY_DECL_OR(parse_global_declaration(context, visibility), poisoned_decl); + break; + } if (!check_no_visibility_before(context, visibility)) return poisoned_decl; decl = TRY_DECL_OR(parse_incremental_array(context), poisoned_decl); if (docs) diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index c39555eea..b05338535 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -1149,7 +1149,6 @@ Ast *parse_stmt(Context *context) case TOKEN_EXTERN: case TOKEN_STRUCT: case TOKEN_INTERFACE: - case TOKEN_TYPEDEF: case TOKEN_UNION: case TOKEN_ATTRIBUTE: case TOKEN_VAR: diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 82948d526..af031ffb5 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1046,7 +1046,7 @@ static Context *copy_context(Module *module, Context *c) return copy; } -static Module *sema_instantiate_module(Context *context, Module *module, Path *path, Expr **parms) +static Module *sema_instantiate_module(Context *context, Module *module, Path *path, TypeInfo **parms) { Module *new_module = compiler_find_or_create_module(path, NULL); new_module->is_generic = true; @@ -1061,12 +1061,11 @@ static Module *sema_instantiate_module(Context *context, Module *module, Path *p TokenId param = module->parameters[i]; Decl *decl = decl_new_with_type(param, DECL_TYPEDEF, VISIBLE_PUBLIC); decl->resolve_status = RESOLVE_DONE; - Expr *type_info_expr = parms[i]; - assert(type_info_expr->expr_kind == EXPR_TYPEINFO); - assert(type_info_expr->type_expr->resolve_status == RESOLVE_DONE); - decl->typedef_decl.type_info = type_info_expr->type_expr; + TypeInfo *type_info = parms[i]; + assert(type_info->resolve_status == RESOLVE_DONE); + decl->typedef_decl.type_info = type_info; decl->type->name = decl->name; - decl->type->canonical = type_info_expr->type_expr->type->canonical; + decl->type->canonical = type_info->type->canonical; vec_add(first_context->global_decls, decl); } return new_module; @@ -1130,7 +1129,7 @@ static Decl *sema_analyse_parameterized_define(Context *c, Decl *decl) } Module *module = import_found->module; - Expr **params = decl->define_decl.params; + TypeInfo **params = decl->define_decl.params; unsigned parameter_count = vec_size(module->parameters); assert(parameter_count > 0); if (parameter_count != vec_size(params)) @@ -1144,15 +1143,10 @@ static Decl *sema_analyse_parameterized_define(Context *c, Decl *decl) scratch_buffer_append_char('.'); VECEACH(decl->define_decl.params, i) { - Expr *expr = decl->define_decl.params[i]; - if (expr->expr_kind != EXPR_TYPEINFO) - { - SEMA_ERROR(expr, "A generic module can only take plain types as arguments."); - return poisoned_decl; - } - if (!sema_resolve_type_info(c, expr->type_expr)) return poisoned_decl; + TypeInfo *type_info = decl->define_decl.params[i]; + if (!sema_resolve_type_info(c, type_info)) return poisoned_decl; if (i != 0) scratch_buffer_append_char('.'); - const char *type_name = expr->type_expr->type->canonical->name; + const char *type_name = type_info->type->canonical->name; scratch_buffer_append(type_name); } TokenType ident_type = TOKEN_IDENT; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 4001c7ef2..ec31b4cdb 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -781,7 +781,6 @@ static inline bool sema_expr_analyse_intrinsic_fp_invocation(Context *context, E static inline bool sema_expr_analyse_intrinsic_invocation(Context *context, Expr *expr, Decl *decl, Type *to) { - unsigned arguments = vec_size(expr->call_expr.arguments); if (decl->name == kw___ceil || decl->name == kw___trunc || decl->name == kw___round || decl->name == kw___sqrt) { return sema_expr_analyse_intrinsic_fp_invocation(context, expr, decl, to); @@ -3488,6 +3487,7 @@ static bool sema_expr_analyse_add(Context *context, Type *to, Expr *expr, Expr * // No need to check the cast we just ensured it was an integer. assert(success && "This should always work"); + (void)success; // 3c. Set the type and other properties. expr_copy_types(expr, left); @@ -4172,8 +4172,6 @@ static bool sema_take_addr_of(Expr *inner, bool *is_constant) */ static bool sema_expr_analyse_addr(Context *context, Type *to, Expr *expr, Expr *inner) { - Type *pointee = to ? to->canonical->pointer : NULL; - // 1. Evaluate the expression REDO: switch (inner->expr_kind) diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index 8382bc357..ca9d8b640 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -250,8 +250,6 @@ const char *token_type_to_string(TokenType type) return "typeid"; case TOKEN_TYPEOF: return "typeof"; - case TOKEN_TYPEDEF: - return "typedef"; case TOKEN_UNION: return "union"; case TOKEN_WHILE: diff --git a/src/compiler_tests/tests.c b/src/compiler_tests/tests.c index 6498956bd..c0aa1c67d 100644 --- a/src/compiler_tests/tests.c +++ b/src/compiler_tests/tests.c @@ -61,10 +61,8 @@ static void test_lexer(void) { for (int i = 1; i < TOKEN_EOF; i++) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-variable" volatile bool t = lexer_scan_ident_test(&lexer, tokens[i]); -#pragma clang diagnostic pop + (void)t; } } diff --git a/src/main.c b/src/main.c index 67ef41b95..d713cd99f 100644 --- a/src/main.c +++ b/src/main.c @@ -21,8 +21,6 @@ int main(int argc, const char *argv[]) // Init the compiler compiler_init(build_options.std_lib_dir); - BuildTarget build_target = { .name = NULL }; - switch (build_options.command) { case COMMAND_INIT: diff --git a/src/utils/lib.h b/src/utils/lib.h index 447fbc205..3d1522a0d 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -288,7 +288,7 @@ static inline _VHeader* _vec_new(size_t element_size, size_t capacity) return header; } -static inline unsigned vec_size(const void*vec) +static inline unsigned vec_size(const void *vec) { return vec ? (((_VHeader *)vec) - 1)->size : 0; } diff --git a/src/utils/stringutils.c b/src/utils/stringutils.c index 353724783..71c60f938 100644 --- a/src/utils/stringutils.c +++ b/src/utils/stringutils.c @@ -20,6 +20,7 @@ char *strformat(const char *var, ...) int new_len = vsnprintf(buffer, len + 1, var, list); va_end(list); assert(len == new_len); + (void)new_len; return buffer; } diff --git a/test/test_suite/distinct/distinct_invalid.c3 b/test/test_suite/distinct/distinct_invalid.c3 index a82c4a9bf..5cfa24c85 100644 --- a/test/test_suite/distinct/distinct_invalid.c3 +++ b/test/test_suite/distinct/distinct_invalid.c3 @@ -1,10 +1,10 @@ error Error {} -typedef Error as distinct Foo1; // #error: You cannot create a distinct type from an error +define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error -typedef error as distinct Foo2; // #error: You cannot create a distinct type from an error union +define Foo2 = distinct error; // #error: You cannot create a distinct type from an error union -typedef void as distinct Foo3; // #error: create a distinct type from 'void' +define Foo3 = distinct void; // #error: create a distinct type from 'void' -typedef typeid as distinct Foo4; // #error: create a distinct type from 'typeid' +define Foo4 = distinct typeid; // #error: create a distinct type from 'typeid' diff --git a/test/test_suite/distinct/distinct_struct.c3 b/test/test_suite/distinct/distinct_struct.c3 index 64d617365..c567ab4ea 100644 --- a/test/test_suite/distinct/distinct_struct.c3 +++ b/test/test_suite/distinct/distinct_struct.c3 @@ -5,7 +5,7 @@ struct Struct double y; } -typedef Struct as distinct Foo; +define Foo = distinct Struct; struct Struct2 { diff --git a/test/test_suite/distinct/distinct_struct_array.c3 b/test/test_suite/distinct/distinct_struct_array.c3 index da6e833b1..867a0bdb3 100644 --- a/test/test_suite/distinct/distinct_struct_array.c3 +++ b/test/test_suite/distinct/distinct_struct_array.c3 @@ -1,6 +1,6 @@ module test; -typedef int as distinct Foo; +define Foo = distinct int; struct Struct { @@ -8,8 +8,8 @@ struct Struct int y; } -typedef Struct as distinct Struct2; -typedef Struct2[3] as distinct StructArr; +define Struct2 = distinct Struct; +define StructArr = distinct Struct2[3]; func void test(int x) { diff --git a/test/test_suite/distinct/distinct_union.c3 b/test/test_suite/distinct/distinct_union.c3 index b430a824c..0ec2798a1 100644 --- a/test/test_suite/distinct/distinct_union.c3 +++ b/test/test_suite/distinct/distinct_union.c3 @@ -6,7 +6,7 @@ union Union double y; } -typedef Union as distinct Foo; +define Foo = distinct Union; union Union2 { @@ -19,9 +19,9 @@ union Union2 } Foo f = { .x = 1 }; -typedef Union2 as distinct Union3; +define Union3 = distinct Union2; -typedef Union3[3] as distinct UnionArr; +define UnionArr = distinct Union3[3]; func void test(int x) { diff --git a/test/test_suite/distinct/test_errors.c3 b/test/test_suite/distinct/test_errors.c3 index 01ff9ee8c..253d567bc 100644 --- a/test/test_suite/distinct/test_errors.c3 +++ b/test/test_suite/distinct/test_errors.c3 @@ -1,6 +1,6 @@ module test; -typedef int as distinct Int2; +define Int2 = distinct int; func void test() { diff --git a/test/test_suite/distinct/test_ops_on_int.c3 b/test/test_suite/distinct/test_ops_on_int.c3 index b5e60b6a4..13b8478de 100644 --- a/test/test_suite/distinct/test_ops_on_int.c3 +++ b/test/test_suite/distinct/test_ops_on_int.c3 @@ -1,6 +1,6 @@ module test; -typedef int as distinct Foo; +define Foo = distinct int; func int test1() { diff --git a/test/test_suite/distinct/test_ops_on_struct.c3 b/test/test_suite/distinct/test_ops_on_struct.c3 index 94fd66590..ee157b92e 100644 --- a/test/test_suite/distinct/test_ops_on_struct.c3 +++ b/test/test_suite/distinct/test_ops_on_struct.c3 @@ -6,7 +6,7 @@ struct Struct double y; } -typedef Struct as distinct Foo; +define Foo = distinct Struct; struct Struct2 { diff --git a/test/test_suite/expressions/assignability.c3 b/test/test_suite/expressions/assignability.c3 index 26aaca86a..98f4e0bf1 100644 --- a/test/test_suite/expressions/assignability.c3 +++ b/test/test_suite/expressions/assignability.c3 @@ -1,4 +1,4 @@ -typedef int as Number; +define Number = int; func void test1() { diff --git a/test/test_suite/expressions/casts/cast_enum_to_various.c3 b/test/test_suite/expressions/casts/cast_enum_to_various.c3 index 93622baf2..fb9e2b346 100644 --- a/test/test_suite/expressions/casts/cast_enum_to_various.c3 +++ b/test/test_suite/expressions/casts/cast_enum_to_various.c3 @@ -16,7 +16,7 @@ enum EnumB : char C, D } -typedef func void(Enum) as Func; +define Func = func void(Enum); func void test1(Enum e) { diff --git a/test/test_suite/expressions/casts/cast_func_to_various.c3 b/test/test_suite/expressions/casts/cast_func_to_various.c3 index c02c80412..e1ba0e1d1 100644 --- a/test/test_suite/expressions/casts/cast_func_to_various.c3 +++ b/test/test_suite/expressions/casts/cast_func_to_various.c3 @@ -8,11 +8,9 @@ enum Enum : uptr A, B } -typedef func void(int) as Func; - -typedef func bool(char*) as FuncOther; - -typedef func void(int) as FuncSame; +define Func = func void(int); +define FuncOther = func bool(char*); +define FuncSame = func void(int); func void test1(Func arg) diff --git a/test/test_suite/expressions/casts/cast_unknown.c3 b/test/test_suite/expressions/casts/cast_unknown.c3 index 218aa2ab5..2bb470156 100644 --- a/test/test_suite/expressions/casts/cast_unknown.c3 +++ b/test/test_suite/expressions/casts/cast_unknown.c3 @@ -1,4 +1,4 @@ -typedef int as Number; +define Number = int; func void test1() { diff --git a/test/test_suite/expressions/casts/explicit_cast.c3 b/test/test_suite/expressions/casts/explicit_cast.c3 index c43db992f..535d9a81f 100644 --- a/test/test_suite/expressions/casts/explicit_cast.c3 +++ b/test/test_suite/expressions/casts/explicit_cast.c3 @@ -1,5 +1,5 @@ -typedef char as Number8; -typedef int as Number32; +define Number8 = char; +define Number32 = int; func void test1() { diff --git a/test/test_suite/statements/default_args.c3 b/test/test_suite/statements/default_args.c3 index 885e2d44c..8f567c437 100644 --- a/test/test_suite/statements/default_args.c3 +++ b/test/test_suite/statements/default_args.c3 @@ -1,2 +1,2 @@ -typedef func void (int a = 10) as Foo; // #error: Function types may not have default arguments. +define Foo = func void(int a = 10); // #error: Function types may not have default arguments. diff --git a/test/test_suite/struct/member_expr.c3 b/test/test_suite/struct/member_expr.c3 index 3ffff0b72..d34a5b29d 100644 --- a/test/test_suite/struct/member_expr.c3 +++ b/test/test_suite/struct/member_expr.c3 @@ -1,7 +1,7 @@ -typedef func int(int) as Func; +define Func = func int(int); -typedef func int(Foo*, int) as Func2; +define Func2 = func int(Foo*, int); struct Foo { diff --git a/test/test_suite/symbols/shadow_struct.c3 b/test/test_suite/symbols/shadow_struct.c3 index 95ea26ba0..72b36f698 100644 --- a/test/test_suite/symbols/shadow_struct.c3 +++ b/test/test_suite/symbols/shadow_struct.c3 @@ -4,7 +4,7 @@ struct Foo int y; } -typedef float as Foo; // #error: shadow a previous declaration +define Foo = float; // #error: shadow a previous declaration enum Bar { @@ -12,4 +12,4 @@ enum Bar TEST2 } -typedef float as Bar; // #error: shadow a previous declaration \ No newline at end of file +define Bar = float; // #error: shadow a previous declaration \ No newline at end of file diff --git a/test/test_suite/symbols/various.c3 b/test/test_suite/symbols/various.c3 index 30438c237..94e22bb18 100644 --- a/test/test_suite/symbols/various.c3 +++ b/test/test_suite/symbols/various.c3 @@ -49,7 +49,7 @@ func void test7() int v = array[1]; } -typedef int as Number; +define Number = int; func void test8() { diff --git a/test/test_suite/types/enum_inference.c3 b/test/test_suite/types/enum_inference.c3 index 35212eb9d..479ee9b89 100644 --- a/test/test_suite/types/enum_inference.c3 +++ b/test/test_suite/types/enum_inference.c3 @@ -13,7 +13,7 @@ enum Inf2 : char C = 129, } -typedef Inf as BooInf; +define BooInf = Inf; func void enumInferenceTest() diff --git a/test/test_suite/types/enum_ok.c3 b/test/test_suite/types/enum_ok.c3 index 9e3b3a46e..318822428 100644 --- a/test/test_suite/types/enum_ok.c3 +++ b/test/test_suite/types/enum_ok.c3 @@ -4,7 +4,7 @@ enum EnumTest : long VALUE2 } -typedef long as Frob; +define Frob = long; enum EnumTestAlias : Frob { diff --git a/test/test_suite/types/recursive_typedef.c3 b/test/test_suite/types/recursive_typedef.c3 index 7470e470c..7d264a9d7 100644 --- a/test/test_suite/types/recursive_typedef.c3 +++ b/test/test_suite/types/recursive_typedef.c3 @@ -1,9 +1,9 @@ -typedef Number1 as Number2; // #error: Recursive definition of 'Number2' -typedef Number2 as Number1; +define Number2 = Number1; // #error: Recursive definition of 'Number2' +define Number1 = Number2; -typedef Number as Number; // #error: Recursive definition of 'Number' +define Number = Number; // #error: Recursive definition of 'Number' -typedef Loop as Loop2; // #error: Recursive definition of 'Loop2' -typedef Loop2 as Loop3; -typedef Loop3 as Loop; +define Loop2 = Loop; // #error: Recursive definition of 'Loop2' +define Loop3 = Loop2; +define Loop = Loop3; diff --git a/test/test_suite/types/redefinition.c3 b/test/test_suite/types/redefinition.c3 index be3b75848..a2e16bd89 100644 --- a/test/test_suite/types/redefinition.c3 +++ b/test/test_suite/types/redefinition.c3 @@ -1,2 +1,2 @@ -typedef int as Number; -typedef uint as Number; // #error: 'Number' would shadow a previous declaration. \ No newline at end of file +define Number = int; +define Number = uint; // #error: 'Number' would shadow a previous declaration. \ No newline at end of file diff --git a/test/test_suite/types/typedefs.c3 b/test/test_suite/types/typedefs.c3 index b3472f928..662b9f82b 100644 --- a/test/test_suite/types/typedefs.c3 +++ b/test/test_suite/types/typedefs.c3 @@ -1,4 +1,4 @@ -typedef int[4] as Arr; +define Arr = int[4]; Arr a = { 3, 4, 5, 6 };