Polymorphic procedure, with passed in compile time type but without removing the type in params etc.
This commit is contained in:
@@ -54,6 +54,24 @@ struct Array {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void insert(T item, int index) {
|
||||||
|
if (index == len) {
|
||||||
|
add(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(index < len);
|
||||||
|
assert(index >= 0);
|
||||||
|
|
||||||
|
grow(1);
|
||||||
|
int right_len = len - index;
|
||||||
|
memmove(data + index + 1, data + index, sizeof(T) * right_len);
|
||||||
|
data[index] = item;
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void add(T item) {
|
void add(T item) {
|
||||||
grow(1);
|
grow(1);
|
||||||
data[len++] = item;
|
data[len++] = item;
|
||||||
@@ -113,14 +131,6 @@ struct Array {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
|
||||||
CORE_Static Array<T>
|
|
||||||
array_make(Allocator *a, S64 size = 16) {
|
|
||||||
Array<T> result = {};
|
|
||||||
result.init(a, size);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Map
|
// Map
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
12
core_ast.cpp
12
core_ast.cpp
@@ -116,7 +116,14 @@ ast_lambda(Token *pos, Array<Ast_Decl *> params, Array<Ast_Expr *> ret, Ast_Scop
|
|||||||
result->args = params.tight_copy(pctx->perm);
|
result->args = params.tight_copy(pctx->perm);
|
||||||
result->ret = ret.tight_copy(pctx->perm);
|
result->ret = ret.tight_copy(pctx->perm);
|
||||||
result->scope = scope;
|
result->scope = scope;
|
||||||
For(params) if (is_flag_set(it->flags, AST_POLYMORPH)) set_flag(result->flags, AST_POLYMORPH);
|
|
||||||
|
For(params) {
|
||||||
|
if (is_flag_set(it->flags, AST_POLYMORPH)) {
|
||||||
|
set_flag(result->flags, AST_POLYMORPH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +231,6 @@ ast_struct(Token *pos, Ast_Scope *scope, Ast_Kind kind, Array<Ast_Decl *> polymo
|
|||||||
result->polymorph_parameters = polymorph_parameters;
|
result->polymorph_parameters = polymorph_parameters;
|
||||||
set_flag(result->flags, AST_POLYMORPH);
|
set_flag(result->flags, AST_POLYMORPH);
|
||||||
set_flag(result->flags, AST_PARENT_POLYMORPH);
|
set_flag(result->flags, AST_PARENT_POLYMORPH);
|
||||||
result->polymorphs.allocator = pctx->heap;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -627,7 +633,6 @@ end_of_switch:
|
|||||||
CORE_Static void
|
CORE_Static void
|
||||||
set_flag_typespec(Ast_Expr *expr) {
|
set_flag_typespec(Ast_Expr *expr) {
|
||||||
for (Ast_Iter iter = iterate_depth_first(pctx->heap, expr, true); iter.ast; next(&iter)) {
|
for (Ast_Iter iter = iterate_depth_first(pctx->heap, expr, true); iter.ast; next(&iter)) {
|
||||||
assert(iter.kind == AST_UNARY || iter.kind == AST_ARRAY || iter.kind == AST_CALL || iter.kind == AST_CALL_ITEM || iter.kind == AST_IDENT);
|
|
||||||
set_flag(iter.ast->flags, AST_TYPESPEC);
|
set_flag(iter.ast->flags, AST_TYPESPEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,7 +647,6 @@ unset_polymorph(Ast *ast) {
|
|||||||
CORE_Static bool
|
CORE_Static bool
|
||||||
is_typespec_polymorphic(Ast *ast) {
|
is_typespec_polymorphic(Ast *ast) {
|
||||||
for (Ast_Iter iter = iterate_depth_first(pctx->heap, ast, true); iter.ast; next(&iter)) {
|
for (Ast_Iter iter = iterate_depth_first(pctx->heap, ast, true); iter.ast; next(&iter)) {
|
||||||
assert(iter.kind == AST_UNARY || iter.kind == AST_ARRAY || iter.kind == AST_CALL || iter.kind == AST_CALL_ITEM || iter.kind == AST_IDENT);
|
|
||||||
if (is_flag_set(iter.ast->flags, AST_POLYMORPH)) {
|
if (is_flag_set(iter.ast->flags, AST_POLYMORPH)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,18 +421,17 @@ typedef uint32_t Ast_Call_Item_Flag;
|
|||||||
enum {
|
enum {
|
||||||
CALL_INDEX = 1ull << 1,
|
CALL_INDEX = 1ull << 1,
|
||||||
CALL_NAME = 1ull << 2,
|
CALL_NAME = 1ull << 2,
|
||||||
CALL_INCLUDED = 1ull << 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Call_Item : Ast_Expr {
|
struct Ast_Call_Item : Ast_Expr {
|
||||||
Ast_Call_Item_Flag call_flags;
|
Ast_Call_Item_Flag call_flags;
|
||||||
int32_t resolved_index;
|
int32_t resolved_index; // This is probably for compound array
|
||||||
Ast_Expr *item;
|
Ast_Expr *item;
|
||||||
union {
|
union {
|
||||||
Ast_Atom *name;
|
Ast_Atom *name;
|
||||||
Ast_Expr *index;
|
Ast_Expr *index;
|
||||||
};
|
};
|
||||||
Intern_String resolved_name;
|
Intern_String resolved_name; // This is probably for compound struct
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Call : Ast_Expr {
|
struct Ast_Call : Ast_Expr {
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ parse_expr(S64 min_bp) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case TK_OpenParen: {
|
case TK_OpenParen: {
|
||||||
if (token_is(TK_CloseParen) || (token_is(TK_Identifier) && token_is(TK_Colon, 1)) || token_is(TK_ThreeDots))
|
if (token_is(TK_CloseParen) || (token_is(TK_Identifier) && token_is(TK_Colon, 1)) || (token_is(TK_Polymorph) && token_is(TK_Colon, 1)) || token_is(TK_ThreeDots))
|
||||||
left = parse_lambda(token);
|
left = parse_lambda(token);
|
||||||
else {
|
else {
|
||||||
left = parse_expr(0);
|
left = parse_expr(0);
|
||||||
@@ -930,6 +930,20 @@ parse_decl(B32 is_global) {
|
|||||||
if (is_flag_set(a->flags, AST_POLYMORPH)) {
|
if (is_flag_set(a->flags, AST_POLYMORPH)) {
|
||||||
set_flag(result->flags, AST_POLYMORPH);
|
set_flag(result->flags, AST_POLYMORPH);
|
||||||
set_flag(result->flags, AST_PARENT_POLYMORPH);
|
set_flag(result->flags, AST_PARENT_POLYMORPH);
|
||||||
|
|
||||||
|
int polymorph_count = 0;
|
||||||
|
For(a->args) {
|
||||||
|
if (it->flags & AST_POLYMORPH) {
|
||||||
|
polymorph_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result->polymorph_parameters.init(pctx->perm, polymorph_count);
|
||||||
|
For(a->args) {
|
||||||
|
if (it->flags & AST_POLYMORPH) {
|
||||||
|
result->polymorph_parameters.add(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (is_flag_set(flags, AST_FOREIGN))
|
if (is_flag_set(flags, AST_FOREIGN))
|
||||||
set_flag(expr->flags, flags);
|
set_flag(expr->flags, flags);
|
||||||
|
|||||||
@@ -306,16 +306,26 @@ Ast_Decl *get_or_instantiate_polymorph_type(Token *pos, Ast_Decl *poly, Array<As
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (poly->kind == AST_LAMBDA) Breakpoint;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = (Ast_Decl *)ast_copy(poly, poly->parent_scope, &poly->polymorph_parameters, ¶ms);
|
result = (Ast_Decl *)ast_copy(poly, poly->parent_scope, &poly->polymorph_parameters, ¶ms);
|
||||||
unset_flag(result->flags, AST_POLYMORPH);
|
unset_flag(result->flags, AST_POLYMORPH);
|
||||||
result->type_val = type_incomplete(result);
|
unset_flag(result->flags, AST_PARENT_POLYMORPH);
|
||||||
|
if (poly->kind == AST_STRUCT || poly->kind == AST_UNION) result->type_val = type_incomplete(result);
|
||||||
result->polymorph_hash = hash;
|
result->polymorph_hash = hash;
|
||||||
|
|
||||||
assert(result->di != poly->di);
|
assert(result->di != poly->di);
|
||||||
result->name = get_unique_name_for_decl(result);
|
result->name = get_unique_name_for_decl(result);
|
||||||
|
|
||||||
|
poly->polymorphs.allocator = pctx->heap;
|
||||||
poly->polymorphs.add(result);
|
poly->polymorphs.add(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolve_decl(result);
|
||||||
|
if (poly->kind == AST_STRUCT || poly->kind == AST_UNION) type_complete(result->type_val);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ast_Decl *get_or_instantiate_polymorph_lambda(Token *pos, Ast_Decl *poly, Array<Ast_Call_Item *> params, Ast_Scope *field_access_scope) {
|
||||||
|
// }
|
||||||
@@ -1565,24 +1565,12 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
else {
|
else {
|
||||||
Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
|
|
||||||
// @cleanup: polymorphic structs probably shouldnt have types, not sure?
|
|
||||||
if (name.type == pctx->type_type) {
|
|
||||||
if (name.type_val->kind != TYPE_POLYMORPH) {
|
|
||||||
compiler_error(node->pos, "Parenthesis are not valid for types that are not polymorphic");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.resolved_decl->flags & AST_POLYMORPH) {
|
if (name.resolved_decl->flags & AST_POLYMORPH) {
|
||||||
assert(name.resolved_decl->flags & AST_PARENT_POLYMORPH);
|
assert(name.resolved_decl->flags & AST_PARENT_POLYMORPH);
|
||||||
Ast_Decl *poly = name.resolved_decl;
|
Ast_Decl *poly = name.resolved_decl;
|
||||||
|
|
||||||
if (poly->kind == AST_LAMBDA) {
|
if (poly->kind == AST_STRUCT || poly->kind == AST_UNION) {
|
||||||
// Ast_Decl *instance = get_or_instantiate_polymorph_type(node->pos, poly, node->exprs, field_access_scope);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Ast_Decl *instance = get_or_instantiate_polymorph_type(node->pos, poly, node->exprs, field_access_scope);
|
Ast_Decl *instance = get_or_instantiate_polymorph_type(node->pos, poly, node->exprs, field_access_scope);
|
||||||
resolve_decl(instance);
|
|
||||||
type_complete(instance->type_val);
|
|
||||||
return operand_type(instance->type_val);
|
return operand_type(instance->type_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1623,18 +1611,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
//
|
//
|
||||||
// Regular call
|
// Regular call
|
||||||
//
|
//
|
||||||
if (name.type->kind != TYPE_LAMBDA) {
|
|
||||||
compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
|
|
||||||
}
|
|
||||||
if (!name.resolved_decl) {
|
if (!name.resolved_decl) {
|
||||||
compiler_error(node->pos, "Internal compiler error: Failed to propagate a resolved lambda declaration from atom resolution");
|
compiler_error(node->pos, "Internal compiler error: Failed to propagate a resolved lambda declaration from atom resolution");
|
||||||
}
|
}
|
||||||
|
if (name.resolved_decl->kind != AST_LAMBDA) {
|
||||||
|
compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
|
||||||
|
}
|
||||||
node->resolved_decl = name.resolved_decl;
|
node->resolved_decl = name.resolved_decl;
|
||||||
|
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
|
||||||
Array<Ast_Call_Item *> items = {scratch.arena};
|
|
||||||
S64 default_iter = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@warning
|
@warning
|
||||||
We only have one instance of a given Lambda type for example (a: Vec3): Vec3.
|
We only have one instance of a given Lambda type for example (a: Vec3): Vec3.
|
||||||
@@ -1642,67 +1626,105 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
This creates a problem cause sometimes we might refer to the wrong Ast.
|
This creates a problem cause sometimes we might refer to the wrong Ast.
|
||||||
Need to be careful!!!
|
Need to be careful!!!
|
||||||
*/
|
*/
|
||||||
Ast_Lambda *lambda = (Ast_Lambda *)name.type->ast;
|
|
||||||
|
Scoped_Arena scratch(pctx->scratch);
|
||||||
|
Ast_Lambda *lambda = name.resolved_decl->lambda;
|
||||||
|
struct Match {
|
||||||
|
Ast_Decl *lambda_arg;
|
||||||
|
Ast_Call_Item *call_arg;
|
||||||
|
};
|
||||||
|
Array<Match> matches = {scratch.arena};
|
||||||
|
S64 default_iter = 0;
|
||||||
|
|
||||||
|
// For every defined argument in the lambda we seek for
|
||||||
|
// a corresponding item in the call expression.
|
||||||
|
//
|
||||||
|
// This algorithm is cool because it results in correct argument order.
|
||||||
|
// It's kind of complicated, especially the default_iter stuff is kind
|
||||||
|
// of weird but it works very well. The default_iter is only incremented
|
||||||
|
// on successful match because we are iterating through entire call expression
|
||||||
|
// every time.
|
||||||
|
// Might be wise to revise it later but the approach of starting with
|
||||||
|
// lambda_args seems correct.
|
||||||
For_Named(lambda->args, lambda_arg) {
|
For_Named(lambda->args, lambda_arg) {
|
||||||
assert(lambda_arg->type);
|
// assert(lambda_arg->type); // @todo: maybe add this check at the end
|
||||||
|
|
||||||
Ast_Call_Item *item = 0;
|
Ast_Call_Item *item = 0;
|
||||||
For(node->exprs) {
|
For(node->exprs) {
|
||||||
assert(!is_flag_set(it->call_flags, CALL_INDEX));
|
int it_index = node->exprs.get_index(&it);
|
||||||
if (is_flag_set(it->call_flags, CALL_NAME)) {
|
|
||||||
|
bool named_argument = is_flag_set(it->call_flags, CALL_NAME);
|
||||||
|
bool named_argument_already_appeared = it_index > default_iter;
|
||||||
|
if (named_argument) {
|
||||||
Ast_Atom *name = it->name;
|
Ast_Atom *name = it->name;
|
||||||
assert(name->kind == AST_IDENT);
|
assert(name->kind == AST_IDENT);
|
||||||
if (name->intern_val.str == lambda_arg->name.str)
|
if (name->intern_val.str == lambda_arg->name.str) item = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (it_index == default_iter) {
|
||||||
|
default_iter += 1;
|
||||||
item = it;
|
item = it;
|
||||||
}
|
}
|
||||||
else if (node->exprs.get_index(&it) == default_iter) {
|
|
||||||
default_iter++;
|
else if (named_argument_already_appeared) compiler_error(it->pos, "Positional argument after named argument is not permitted");
|
||||||
item = it;
|
|
||||||
}
|
|
||||||
else if (node->exprs.get_index(&it) > default_iter) {
|
|
||||||
compiler_error(it->pos, "Positional argument after named argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item) break;
|
if (item) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item) {
|
// If we couldn't find corresponding call item we should seek
|
||||||
set_flag(item->call_flags, CALL_INCLUDED);
|
// for a default value inside the lambda declaration
|
||||||
|
if (!item) {
|
||||||
|
if (!lambda_arg->expr) compiler_error(node->pos, node->resolved_decl->pos, "Required value: %Q in lambda call was not passed", lambda_arg->name);
|
||||||
|
item = ast_call_item(lambda_arg->expr->pos, 0, 0, lambda_arg->expr);
|
||||||
|
item->resolved_type = lambda_arg->expr->resolved_type;
|
||||||
|
}
|
||||||
|
matches.add({lambda_arg, item});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we found every item.
|
||||||
|
For_Named(node->exprs, call_it) {
|
||||||
|
bool included = false;
|
||||||
|
For_Named(matches, match_it) {
|
||||||
|
if (call_it == match_it.call_arg) {
|
||||||
|
included = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!included) compiler_error(call_it->pos, "Unknown argument to a function call, couldn't match it with any of the declared arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the polymorph
|
||||||
|
if (lambda->flags & AST_POLYMORPH) {
|
||||||
|
Array<Ast_Call_Item *> replacements = {scratch.arena};
|
||||||
|
For(matches) {
|
||||||
|
if (it.lambda_arg->flags & AST_POLYMORPH) {
|
||||||
|
replacements.add(it.call_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Decl *poly = name.resolved_decl;
|
||||||
|
assert(replacements.len == poly->polymorph_parameters.len);
|
||||||
|
Ast_Decl *instance = get_or_instantiate_polymorph_type(node->pos, poly, replacements, field_access_scope);
|
||||||
|
lambda = instance->lambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typecheck the arguments and produce properly ordered list of arguments for codegeneration
|
||||||
|
Array<Ast_Call_Item *> items = {scratch.arena};
|
||||||
|
For(matches) {
|
||||||
|
Ast_Call_Item *item = it.call_arg;
|
||||||
|
Ast_Decl *lambda_arg = it.lambda_arg;
|
||||||
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
|
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
|
||||||
|
|
||||||
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
|
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
|
||||||
item->resolved_type = lambda_arg->type;
|
item->resolved_type = lambda_arg->type;
|
||||||
|
|
||||||
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
||||||
item->resolved_index = lambda->args.get_index(&lambda_arg);
|
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
|
||||||
if (!lambda_arg->expr) {
|
|
||||||
compiler_error(node->pos, node->resolved_decl->pos, "Required value: %Q in lambda call was not passed", lambda_arg->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// default values are typechecked when they get resolved
|
|
||||||
Ast_Call_Item *call_item = ast_call_item(lambda_arg->expr->pos, 0, 0, lambda_arg->expr);
|
|
||||||
call_item->resolved_type = lambda_arg->expr->resolved_type;
|
|
||||||
call_item->resolved_index = lambda->args.get_index(&lambda_arg);
|
|
||||||
set_flag(call_item->call_flags, CALL_INCLUDED);
|
|
||||||
items.add(call_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if all arguments are included and cleanup
|
|
||||||
For(node->exprs) {
|
|
||||||
if (!is_flag_set(it->call_flags, CALL_INCLUDED))
|
|
||||||
compiler_error(it->pos, "Unknown argument to a function call, couldn't match it with any of the declared arguments");
|
|
||||||
else unset_flag(it->call_flags, CALL_INCLUDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->exprs = items.tight_copy(pctx->perm);
|
node->exprs = items.tight_copy(pctx->perm);
|
||||||
node->resolved_type = name.type->func.ret;
|
|
||||||
|
|
||||||
return operand_rvalue(name.type->func.ret);
|
node->resolved_type = lambda->resolved_type->func.ret;
|
||||||
|
return operand_rvalue(node->resolved_type);
|
||||||
//
|
//
|
||||||
// CALL End
|
// CALL End
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ type_try_tupling(Array<Ast_Type *> types, Ast *ast) {
|
|||||||
|
|
||||||
// @todo alignment, offsets
|
// @todo alignment, offsets
|
||||||
result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align);
|
result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align);
|
||||||
result->agg.members = array_make<Ast_Resolved_Member>(pctx->perm, types.len);
|
result->agg.members.init(pctx->perm, types.len);
|
||||||
For(types) {
|
For(types) {
|
||||||
Ast_Resolved_Member m = {};
|
Ast_Resolved_Member m = {};
|
||||||
m.type = it;
|
m.type = it;
|
||||||
@@ -219,8 +219,8 @@ type_enum(Ast_Decl *ast, Ast_Type *type) {
|
|||||||
|
|
||||||
CORE_Static Ast_Type *
|
CORE_Static Ast_Type *
|
||||||
type_incomplete(Ast *ast) {
|
type_incomplete(Ast *ast) {
|
||||||
|
if (is_flag_set(ast->flags, AST_POLYMORPH)) return 0;
|
||||||
Ast_Type_Kind kind = TYPE_INCOMPLETE;
|
Ast_Type_Kind kind = TYPE_INCOMPLETE;
|
||||||
if (is_flag_set(ast->flags, AST_POLYMORPH)) kind = TYPE_POLYMORPH;
|
|
||||||
Ast_Type *result = type_new(pctx->perm, kind, 0, 0);
|
Ast_Type *result = type_new(pctx->perm, kind, 0, 0);
|
||||||
result->ast = ast;
|
result->ast = ast;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ Triple :: struct($A: Type, $B: Type, $C: Type)
|
|||||||
a: A
|
a: A
|
||||||
b: B
|
b: B
|
||||||
c: C
|
c: C
|
||||||
|
Variant :: union($A: Type, $B: Type, $C: Type)
|
||||||
|
a: A
|
||||||
|
b: B
|
||||||
|
c: C
|
||||||
|
|
||||||
MakeArray :: (a: *int, count: int): Array(int)
|
MakeArray :: (a: *int, count: int): Array(int)
|
||||||
result := Array(int) {
|
result := Array(int) {
|
||||||
@@ -46,13 +50,19 @@ MakeArray :: (a: *int, count: int): Array(int)
|
|||||||
MultipleArgs :: (): Tuple(int, F32)
|
MultipleArgs :: (): Tuple(int, F32)
|
||||||
return {32, 32}
|
return {32, 32}
|
||||||
|
|
||||||
PolyLambda :: (value: $T): T
|
PolyLambda :: ($T: Type): T
|
||||||
return value
|
return 32
|
||||||
|
|
||||||
|
|
||||||
GetCount :: (a: int): int
|
GetCount :: (a: int): int
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
// @todo: this is allowed, shouldn't be
|
||||||
|
// Test :: (a: int, b: int = 10, c: int???)
|
||||||
|
|
||||||
|
Test :: (a: int, b: int = 10, c: int = 20)
|
||||||
|
pass
|
||||||
|
|
||||||
main :: (argc: int, argv: **char): int
|
main :: (argc: int, argv: **char): int
|
||||||
buff: *int
|
buff: *int
|
||||||
array: Array(int) = {len = 10, cap = 10, data = buff}
|
array: Array(int) = {len = 10, cap = 10, data = buff}
|
||||||
@@ -61,12 +71,21 @@ main :: (argc: int, argv: **char): int
|
|||||||
fourth: Array(F32)
|
fourth: Array(F32)
|
||||||
fifth: Array(F32)
|
fifth: Array(F32)
|
||||||
sixth: Array(Array(F32))
|
sixth: Array(Array(F32))
|
||||||
|
seventh: Variant(int, F32, S64)
|
||||||
|
// d: int(32)
|
||||||
|
|
||||||
// c := MakeArray(buff, GetCount(GetCount(32)))
|
// c := MakeArray(buff, GetCount(GetCount(32)))
|
||||||
|
|
||||||
// a,b := MultipleArgs()
|
// a,b := MultipleArgs()
|
||||||
a := MultipleArgs()
|
a := MultipleArgs()
|
||||||
|
|
||||||
// value := PolyLambda(32)
|
Test(10)
|
||||||
|
Test(10, 20)
|
||||||
|
Test(10, 20, 30)
|
||||||
|
Test(10, b = 10)
|
||||||
|
Test(10, b = 10, c = 20)
|
||||||
|
Test(a = 10, b = 10, c = 20)
|
||||||
|
|
||||||
|
value := PolyLambda(int)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
Reference in New Issue
Block a user