diff --git a/base_data_structures.cpp b/base_data_structures.cpp index e6193dd..3dfcb12 100644 --- a/base_data_structures.cpp +++ b/base_data_structures.cpp @@ -302,7 +302,7 @@ intern_string(Intern_Table *t, String string) { //----------------------------------------------------------------------------- // Array List //----------------------------------------------------------------------------- -const int LIST_DEFAULT_BLOCK_SIZE = 32; +const int LIST_DEFAULT_BLOCK_SIZE = 16; const int LIST_DEFAULT_ALLOCATION_MUL = 2; template diff --git a/core_ast.cpp b/core_ast.cpp index 0369402..6d6090f 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -20,6 +20,17 @@ _ast_new(size_t size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0) { return result; } +CORE_Static void +propagate_polymorphic(Ast *to, Ast *from) { + if (is_flag_set(from->flags, AST_IDENT_POLYMORPH)) set_flag(to->flags, AST_IDENT_POLYMORPH); + if (is_flag_set(from->flags, AST_TYPE_POLYMORPH)) set_flag(to->flags, AST_TYPE_POLYMORPH); +} + +CORE_Static void +propagate_polymorphic(Ast *to, Token *from) { + if (from->kind == TK_Polymorph) set_flag(to->flags, AST_IDENT_POLYMORPH); +} + CORE_Static Ast_Atom * ast_str(Token *pos, Intern_String string) { AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM); @@ -214,11 +225,13 @@ finalize_stmt_scope(Ast_Scope *scope) { } CORE_Static Ast_Decl * -ast_struct(Token *pos, Ast_Scope *scope, Ast_Kind kind = AST_STRUCT) { +ast_struct(Token *pos, Ast_Scope *scope, Ast_Kind kind, Array polymorph_parameters) { assert(kind == AST_STRUCT || kind == AST_UNION); AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE); result->kind = kind; result->scope = scope; + result->polymorph_parameters = polymorph_parameters; + if (polymorph_parameters.len) set_flag(result->flags, AST_POLYMORPH); return result; } diff --git a/core_compiler_interface.hpp b/core_compiler_interface.hpp index 4de6999..c31fdad 100644 --- a/core_compiler_interface.hpp +++ b/core_compiler_interface.hpp @@ -348,19 +348,22 @@ enum Ast_Kind : uint32_t { typedef uint32_t Ast_Flag; enum { - AST_EXPR = 1ull << 1, - AST_STMT = 1ull << 2, - AST_STRICT = 1ull << 3, - AST_AGGREGATE = 1ull << 4, - AST_AGGREGATE_CHILD = 1ull << 5, - AST_ATOM = 1ull << 7, - AST_FOREIGN = 1ull << 8, - AST_DECL = 1ull << 9, - AST_GLOBAL = 1ull << 10, - AST_FLAG = 1ull << 11, - AST_VAR_IS_CONST = 1ull << 12, - AST_OPERATOR_OVERLOAD = 1ull << 13, - AST_IS_LVALUE = 1ull << 14, + AST_EXPR = 1 << 1, + AST_STMT = 1 << 2, + AST_STRICT = 1 << 3, + AST_AGGREGATE = 1 << 4, + AST_AGGREGATE_CHILD = 1 << 5, + AST_ATOM = 1 << 7, + AST_FOREIGN = 1 << 8, + AST_DECL = 1 << 9, + AST_GLOBAL = 1 << 10, + AST_FLAG = 1 << 11, + AST_VAR_IS_CONST = 1 << 12, + AST_OPERATOR_OVERLOAD = 1 << 13, + AST_IS_LVALUE = 1 << 14, + AST_IDENT_POLYMORPH = 1 << 15, + AST_TYPE_POLYMORPH = 1 << 16, + AST_POLYMORPH = AST_IDENT_POLYMORPH | AST_TYPE_POLYMORPH, }; struct Ast { @@ -599,6 +602,7 @@ struct Ast_Decl : Ast { uint64_t operator_overload_arguments_hash; Ast_Operator_Info *overload_op_info; + Array polymorph_parameters; Ast_Scope *scope; Ast_Expr *typespec; diff --git a/core_parsing.cpp b/core_parsing.cpp index 6e6c5e1..39f04e8 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -457,22 +457,26 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) { return scope; } -CORE_Static Ast_Lambda * -parse_lambda(Token *token) { - Scratch_Scope scratch(pctx->scratch); - - Array params = {scratch.arena}; +CORE_Static Array +parse_parameter_list(Arena *arena) { + Array params = {arena}; if (!token_is(TK_CloseParen)) { for (;;) { Token *name = token_get(); - if (token_match(TK_Identifier)) { + if (name->kind == TK_Identifier || name->kind == TK_Polymorph) { + token_next(); token_expect(TK_Colon); + Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL); param->name = name->intern_val; - param->typespec = parse_expr(); - if (token_match(TK_Assign)) + + propagate_polymorphic(param, param->typespec); + propagate_polymorphic(param, name); + + if (token_match(TK_Assign)) { param->expr = parse_expr(); + } params.add(param); } @@ -483,7 +487,14 @@ parse_lambda(Token *token) { } } token_expect(TK_CloseParen); + return params; +} +CORE_Static Ast_Lambda * +parse_lambda(Token *token) { + Scratch_Scope scratch(pctx->scratch); + + Array params = parse_parameter_list(scratch.arena); Array ret = {scratch.arena}; if (token_match(TK_Colon)) { do { @@ -588,18 +599,26 @@ parse_expr(S64 min_bp) { switch (token->kind) { case TK_StringLit: left = ast_str(token, token->intern_val); break; case TK_Identifier: left = ast_ident(token, token->intern_val); break; + case TK_Polymorph: left = ast_ident(token, token->intern_val); break; case TK_Integer: left = ast_int(token, token->int_val); break; case TK_UnicodeLit: left = ast_int(token, token->unicode); break; case TK_Float: left = ast_float(token, token->f64_val); break; - case TK_Pointer: left = ast_expr_unary(token, TK_Pointer, parse_expr(prefix_bp.right)); break; - case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break; case TK_Sub: left = ast_expr_unary(token, TK_Sub, parse_expr(prefix_bp.right)); break; case TK_Add: left = ast_expr_unary(token, TK_Add, parse_expr(prefix_bp.right)); break; case TK_Not: left = ast_expr_unary(token, TK_Not, parse_expr(prefix_bp.right)); break; case TK_Neg: left = ast_expr_unary(token, TK_Neg, parse_expr(prefix_bp.right)); break; case TK_Increment: left = ast_expr_unary(token, TK_Increment, parse_expr(prefix_bp.right)); break; case TK_Decrement: left = ast_expr_unary(token, TK_Decrement, parse_expr(prefix_bp.right)); break; + case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break; + // Pointer typespec + case TK_Pointer: { + left = ast_expr_unary(token, TK_Pointer, parse_expr(prefix_bp.right)); + auto unary = (Ast_Unary *)left; + propagate_polymorphic(unary, unary->expr); + } break; + + // Array typespec case TK_OpenBracket: { Ast_Expr *expr = 0; if (!token_is(TK_CloseBracket)) @@ -608,14 +627,17 @@ parse_expr(S64 min_bp) { Ast_Array *result = ast_array(token, expr); token_expect(TK_CloseBracket); result->base = parse_expr(prefix_bp.right); + propagate_polymorphic(result, result->base); left = result; } break; + // Compound expression case TK_OpenBrace: { left = parse_expr_call(0, TK_CloseBrace); left->kind = AST_COMPOUND; } break; + // True, False case TK_Keyword: { if (token->intern_val == pctx->keyword_true) left = ast_bool(token, 1); @@ -695,8 +717,18 @@ CORE_Static Ast_Decl * parse_struct(Token *pos, Ast_Kind kind) { Scratch_Scope scratch(pctx->scratch); - token_match(OPEN_SCOPE); + Array params = {}; + if (token_match(TK_OpenParen)) { + params = parse_parameter_list(scratch.arena); + For(params) { + if (!is_flag_set(it->flags, AST_POLYMORPH)) { + compiler_error(it->pos, "All struct arguments are required to be polymorphic"); + } + } + } + Ast_Scope *scope = begin_decl_scope(scratch.arena, token_get()); + token_match(OPEN_SCOPE); do { Token *token = token_expect(TK_Identifier); token_expect(TK_Colon); @@ -711,7 +743,7 @@ parse_struct(Token *pos, Ast_Kind kind) { token_expect(CLOSE_SCOPE); finalize_decl_scope(scope); - Ast_Decl *result = ast_struct(pos, scope, kind); + Ast_Decl *result = ast_struct(pos, scope, kind, params); return result; } diff --git a/core_typechecking.cpp b/core_typechecking.cpp index f10547b..efc2b90 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -1141,6 +1141,10 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str Ast_Scope *scope = field_access_scope ? field_access_scope : node->parent_scope; Search_Flag flag = field_access_scope ? SEARCH_ONLY_CURRENT_SCOPE : 0; + if (!string_compare(ast->pos->file.s, "Language.core"_s)) { // @debug + int a = 10; + } + Ast_Decl *decl = resolve_name(scope, node->pos, node->intern_val, flag | RESOLVE_NAME_MAKE_SURE_OPERATOR_OVERLOAD_IS_NOT_EVER_CALLED); // Substitute lambda alias diff --git a/examples/polymorphism.core b/examples/polymorphism.core index 11e9eb5..2694134 100644 --- a/examples/polymorphism.core +++ b/examples/polymorphism.core @@ -5,11 +5,6 @@ PushStruct :: (a: *MA.Arena, $T: Type): *$T result := PushSize(a, size) return result -Array :: struct($T: Type) - data: *T - len: int - cap: int - Array(int) QueueAddSLL(list: $List, node: $Node, first: #Identifier = first, last: #Identifier = last, next: #Identifier = next) @@ -24,6 +19,10 @@ QueueAddSLL(list: $List, node: $Node, $first = first, $last = last, $next = next */ +Array :: struct($T: Type) + data: *T + len: int + cap: int + main :: (argc: int, argv: **char): int - $i := 10 return 0 \ No newline at end of file