WOO YEE Basic polymorphism for untyped values, not working for typed expressions yet
This commit is contained in:
@@ -47,12 +47,16 @@ MakeArray :: (a: *int, count: int): Array(int)
|
|||||||
// @todo: maybe disallow multiple arguments in current form
|
// @todo: maybe disallow multiple arguments in current form
|
||||||
// and use polimorphism. Then we could make var unpacking,
|
// and use polimorphism. Then we could make var unpacking,
|
||||||
// unpack structs making it more powerful
|
// unpack structs making it more powerful
|
||||||
|
// a,b := MultipleArgs() // @todo var unpacking
|
||||||
MultipleArgs :: (): Tuple(int, F32)
|
MultipleArgs :: (): Tuple(int, F32)
|
||||||
return {32, 32}
|
return {32, 32}
|
||||||
|
|
||||||
PolyLambda :: ($T: Type = *int): T
|
PolyLambda :: ($T: Type = *int): T
|
||||||
return 32
|
return 32
|
||||||
|
|
||||||
|
PolyType :: (a: $T): T
|
||||||
|
return a
|
||||||
|
|
||||||
GetCount :: (a: int): int
|
GetCount :: (a: int): int
|
||||||
return a
|
return a
|
||||||
|
|
||||||
@@ -78,7 +82,7 @@ main :: (argc: int, argv: **char): int
|
|||||||
|
|
||||||
// c := MakeArray(buff, GetCount(GetCount(32)))
|
// c := MakeArray(buff, GetCount(GetCount(32)))
|
||||||
|
|
||||||
// a,b := MultipleArgs()
|
|
||||||
a := MultipleArgs()
|
a := MultipleArgs()
|
||||||
|
|
||||||
Test(10)
|
Test(10)
|
||||||
@@ -89,5 +93,10 @@ main :: (argc: int, argv: **char): int
|
|||||||
Test(a = 10, b = 10, c = 20)
|
Test(a = 10, b = 10, c = 20)
|
||||||
|
|
||||||
value := PolyLambda(**int)
|
value := PolyLambda(**int)
|
||||||
|
PolyType_r1 := PolyType(10)
|
||||||
|
PolyType_r2 := PolyType(int)
|
||||||
|
// PolyType_r3 := PolyType(array)
|
||||||
|
// PolyType_r4 := PolyType(seventh)
|
||||||
|
// PolyType_r5 := PolyType(sixth)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -14,6 +14,69 @@ get_unique_name_for_decl(Ast_Decl *decl) {
|
|||||||
return pctx->internf("%c%u_%Q", char_counter++, decl->di, decl->name);
|
return pctx->internf("%c%u_%Q", char_counter++, decl->di, decl->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CORE_Static String core_type_to_string(Ast_Type *type);
|
||||||
|
Ast_Expr *create_typespec_from_type(Token *pos, Ast_Scope *parent_scope, Ast_Type *type) {
|
||||||
|
Ast_Expr *result = 0;
|
||||||
|
switch (type->kind) {
|
||||||
|
case TYPE_NONE:
|
||||||
|
case TYPE_TUPLE:
|
||||||
|
case TYPE_COMPLETING:
|
||||||
|
case TYPE_INCOMPLETE:
|
||||||
|
case TYPE_POLYMORPH:
|
||||||
|
case TYPE_UNTYPED_BOOL:
|
||||||
|
case TYPE_UNTYPED_INT:
|
||||||
|
case TYPE_UNTYPED_FLOAT:
|
||||||
|
case TYPE_UNTYPED_STRING: {
|
||||||
|
invalid_codepath;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TYPE_TYPE:
|
||||||
|
case TYPE_S64:
|
||||||
|
case TYPE_S32:
|
||||||
|
case TYPE_S16:
|
||||||
|
case TYPE_S8:
|
||||||
|
case TYPE_INT:
|
||||||
|
case TYPE_CHAR:
|
||||||
|
case TYPE_U64:
|
||||||
|
case TYPE_U32:
|
||||||
|
case TYPE_U16:
|
||||||
|
case TYPE_U8:
|
||||||
|
case TYPE_F32:
|
||||||
|
case TYPE_F64:
|
||||||
|
case TYPE_BOOL:
|
||||||
|
case TYPE_STRING:
|
||||||
|
case TYPE_VOID: {
|
||||||
|
String s = core_type_to_string(type);
|
||||||
|
result = ast_ident(pos, pctx->intern(s));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TYPE_POINTER: {
|
||||||
|
result = ast_expr_unary(pos, TK_Pointer, create_typespec_from_type(pos, parent_scope, type->base));
|
||||||
|
} break;
|
||||||
|
case TYPE_ARRAY: {
|
||||||
|
Ast_Array *arr = ast_array(pos, create_typespec_from_type(pos, parent_scope, type->arr.base));
|
||||||
|
arr->expr = ast_int(pos, type->arr.size);
|
||||||
|
arr->expr->parent_scope = parent_scope;
|
||||||
|
result = arr;
|
||||||
|
} break;
|
||||||
|
case TYPE_SLICE: {
|
||||||
|
Ast_Array *arr = ast_array(pos, create_typespec_from_type(pos, parent_scope, type->arr.base));
|
||||||
|
result = arr;
|
||||||
|
} break;
|
||||||
|
case TYPE_LAMBDA: {
|
||||||
|
invalid_codepath;
|
||||||
|
} break;
|
||||||
|
case TYPE_STRUCT:
|
||||||
|
case TYPE_UNION:
|
||||||
|
case TYPE_ENUM: {
|
||||||
|
Ast_Decl *decl = (Ast_Decl *)type->ast;
|
||||||
|
result = ast_ident(pos, decl->name);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
result->parent_scope = parent_scope;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#define ast_create_copy(parent_scope, T, ast) (T *)ast__create_copy(parent_scope, sizeof(T), ast)
|
#define ast_create_copy(parent_scope, T, ast) (T *)ast__create_copy(parent_scope, sizeof(T), ast)
|
||||||
Ast *ast__create_copy(Ast_Scope *parent_scope, size_t size, Ast *ast) {
|
Ast *ast__create_copy(Ast_Scope *parent_scope, size_t size, Ast *ast) {
|
||||||
if (ast == 0) return 0;
|
if (ast == 0) return 0;
|
||||||
@@ -57,12 +120,32 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Ast_Decl *> *replace, Arr
|
|||||||
if (replace && with) {
|
if (replace && with) {
|
||||||
// @todo: IF ITS STRUCT we only want to replace TYPESPECS
|
// @todo: IF ITS STRUCT we only want to replace TYPESPECS
|
||||||
For(*replace) {
|
For(*replace) {
|
||||||
assert(it->type == pctx->type_type);
|
if (it->flags & AST_IDENT_POLYMORPH) {
|
||||||
if (it->name == dst->intern_val) {
|
assert(it->type == pctx->type_type);
|
||||||
S64 it_index = replace->get_index(it);
|
if (it->name == dst->intern_val) {
|
||||||
Ast_Call_Item *replacement = with[0][it_index];
|
S64 it_index = replace->get_index(it);
|
||||||
Ast *replacement_v = replacement->item;
|
Ast_Call_Item *replacement = with[0][it_index];
|
||||||
dst = (Ast_Atom *)ast_copy(replacement_v, parent_scope, 0, 0);
|
Ast *replacement_v = replacement->item;
|
||||||
|
dst = (Ast_Atom *)ast_copy(replacement_v, parent_scope, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it->flags & AST_TYPE_POLYMORPH) {
|
||||||
|
Ast_Expr *typespec = it->typespec;
|
||||||
|
assert(typespec);
|
||||||
|
assert(typespec->kind == AST_IDENT);
|
||||||
|
Ast_Atom *t = (Ast_Atom *)typespec;
|
||||||
|
|
||||||
|
if (t->intern_val == dst->intern_val) {
|
||||||
|
S64 it_index = replace->get_index(it);
|
||||||
|
|
||||||
|
// @todo: This probably should be resolved
|
||||||
|
// before calling the ast_copy function
|
||||||
|
// or something
|
||||||
|
Ast_Call_Item *replacement = with[0][it_index];
|
||||||
|
Ast_Type *type_to_replace = replacement->item->resolved_type;
|
||||||
|
dst = (Ast_Atom *)create_typespec_from_type(dst->pos, parent_scope, type_to_replace);
|
||||||
|
// dst = (Ast_Atom *)ast_copy(replacement_v, parent_scope, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,19 +416,30 @@ Ast_Decl *get_or_instantiate_polymorph_type(Token *pos, Ast_Decl *poly, Array<As
|
|||||||
|
|
||||||
Ast_Decl *get_or_instantiate_polymorph_lambda(Token *pos, Ast_Decl *poly, Array<Ast_Call_Item *> params, Ast_Scope *field_access_scope) {
|
Ast_Decl *get_or_instantiate_polymorph_lambda(Token *pos, Ast_Decl *poly, Array<Ast_Call_Item *> params, Ast_Scope *field_access_scope) {
|
||||||
if (params.len != poly->polymorph_parameters.len) compiler_error(pos, "Invalid count of polymorphic arguments");
|
if (params.len != poly->polymorph_parameters.len) compiler_error(pos, "Invalid count of polymorphic arguments");
|
||||||
|
Scoped_Arena scratch(pctx->scratch);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint64_t hash = 91;
|
uint64_t hash = 91;
|
||||||
For(params) {
|
For(params) {
|
||||||
Ast_Decl *poly_decl = poly->polymorph_parameters[i++];
|
Ast_Decl *poly_decl = poly->polymorph_parameters[i++];
|
||||||
resolve_decl(poly_decl);
|
if (poly_decl->flags & AST_IDENT_POLYMORPH) {
|
||||||
if (poly_decl->type != pctx->type_type) compiler_error(poly_decl->pos, "Invalid type of polymorphic struct argument");
|
resolve_decl(poly_decl);
|
||||||
|
if (poly_decl->type != pctx->type_type) compiler_error(poly_decl->pos, "Invalid type of polymorphic struct argument");
|
||||||
|
|
||||||
Operand op = resolve_expr(it->item, AST_CANT_BE_NULL, 0, field_access_scope);
|
Operand op = resolve_expr(it->item, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
if (!op.is_const) compiler_error(it->pos, "Argument is required to be compile time known");
|
if (!op.is_const) compiler_error(it->pos, "Argument is required to be compile time known");
|
||||||
if (op.type != pctx->type_type) compiler_error(it->pos, "Struct argument required to be a type");
|
if (op.type != pctx->type_type) compiler_error(it->pos, "Struct argument required to be a type");
|
||||||
|
|
||||||
hash = hash_mix(hash, hash_ptr(op.type_val));
|
hash = hash_mix(hash, hash_ptr(op.type_val));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Operand op = resolve_expr(it->item, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
|
try_converting_untyped_to_default_type(&op);
|
||||||
|
try_propagating_resolved_type_to_untyped_literals(it->item, op.type);
|
||||||
|
assert(it->item->resolved_type == op.type);
|
||||||
|
|
||||||
|
hash = hash_mix(hash, hash_ptr(op.type));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Decl *result = 0;
|
Ast_Decl *result = 0;
|
||||||
|
|||||||
@@ -625,7 +625,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl) {
|
|||||||
// need to propagate int to untyped_int
|
// need to propagate int to untyped_int
|
||||||
//
|
//
|
||||||
CORE_Static void
|
CORE_Static void
|
||||||
try_propagating_resolved_type_to_untyped_literals(Ast *ast, Ast_Type *type, Ast_Type *additional_not_bool_type = 0) {
|
try_propagating_resolved_type_to_untyped_literals(Ast *ast, Ast_Type *type, Ast_Type *additional_not_bool_type) {
|
||||||
if (!type) compiler_error(ast->pos, "Internal compiler error: Type passed to try_propagating_resolved_type_to_untyped_literals is null");
|
if (!type) compiler_error(ast->pos, "Internal compiler error: Type passed to try_propagating_resolved_type_to_untyped_literals is null");
|
||||||
if (!ast) return;
|
if (!ast) return;
|
||||||
if (is_untyped(type)) return;
|
if (is_untyped(type)) return;
|
||||||
@@ -1699,11 +1699,8 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
Array<Ast_Call_Item *> replacements = {scratch.arena};
|
Array<Ast_Call_Item *> replacements = {scratch.arena};
|
||||||
ForArrayRemovable(matches) {
|
ForArrayRemovable(matches) {
|
||||||
ForArrayRemovablePrepare(matches);
|
ForArrayRemovablePrepare(matches);
|
||||||
|
if (it.lambda_arg->flags & AST_POLYMORPH) replacements.add(it.call_arg);
|
||||||
if (it.lambda_arg->flags & AST_POLYMORPH) {
|
if (it.lambda_arg->flags & AST_IDENT_POLYMORPH) ForArrayRemovableDeclare();
|
||||||
replacements.add(it.call_arg);
|
|
||||||
ForArrayRemovableDeclare();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Decl *poly = name.resolved_decl;
|
Ast_Decl *poly = name.resolved_decl;
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ enum {
|
|||||||
RESOLVE_NAME_MAKE_SURE_OPERATOR_OVERLOAD_IS_NOT_EVER_CALLED = bit_flag(2),
|
RESOLVE_NAME_MAKE_SURE_OPERATOR_OVERLOAD_IS_NOT_EVER_CALLED = bit_flag(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CORE_Static void try_converting_untyped_to_default_type(Operand *op);
|
||||||
|
CORE_Static void try_propagating_resolved_type_to_untyped_literals(Ast *ast, Ast_Type *type, Ast_Type *additional_not_bool_type = 0);
|
||||||
|
|
||||||
CORE_Static Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_Scope *field_access_scope);
|
CORE_Static Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_Scope *field_access_scope);
|
||||||
CORE_Static void resolve_decl(Ast_Decl *ast);
|
CORE_Static void resolve_decl(Ast_Decl *ast);
|
||||||
CORE_Static Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
|
CORE_Static Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user