Slowly adding multiple return values
This commit is contained in:
18
ast.cpp
18
ast.cpp
@@ -139,7 +139,7 @@ struct Ast_Builtin: Ast_Expr{
|
|||||||
//
|
//
|
||||||
|
|
||||||
struct Ast_Return: Ast{
|
struct Ast_Return: Ast{
|
||||||
Ast_Expr *expr;
|
Array<Ast_Expr *> expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_If_Node: Ast{
|
struct Ast_If_Node: Ast{
|
||||||
@@ -164,7 +164,7 @@ struct Ast_For: Ast{
|
|||||||
|
|
||||||
struct Ast_Lambda : Ast_Expr {
|
struct Ast_Lambda : Ast_Expr {
|
||||||
Array<Ast_Decl *> args;
|
Array<Ast_Decl *> args;
|
||||||
Ast_Expr *ret;
|
Array<Ast_Expr *> ret;
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -331,14 +331,12 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Lambda *
|
function Ast_Lambda *
|
||||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, Ast_Expr *ret, Ast_Scope *scope){
|
ast_lambda(Token *pos, Array<Ast_Decl *> params, Array<Ast_Expr *> ret, Ast_Scope *scope){
|
||||||
AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR);
|
AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR);
|
||||||
result->flags = AST_EXPR;
|
result->flags = AST_EXPR;
|
||||||
result->args = params.tight_copy(pctx->perm);
|
result->args = params.tight_copy(pctx->perm);
|
||||||
|
result->ret = ret.tight_copy(pctx->perm);
|
||||||
result->scope = scope;
|
result->scope = scope;
|
||||||
result->ret = ret;
|
|
||||||
if(!ret) result->ret = ast_ident(result->pos, intern_void);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,11 +370,11 @@ ast_break(Token *pos){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Return *
|
function Ast_Return *
|
||||||
ast_return(Token *pos, Ast_Expr *expr){
|
ast_return(Token *pos, Array<Ast_Expr *> expr){
|
||||||
AST_NEW(Return, RETURN, pos, AST_STMT);
|
AST_NEW(Return, RETURN, pos, AST_STMT);
|
||||||
if(expr){
|
if(expr.len){
|
||||||
assert(is_flag_set(expr->flags, AST_EXPR));
|
For(expr) assert(is_flag_set(it->flags, AST_EXPR));
|
||||||
result->expr = expr;
|
result->expr = expr.tight_copy(pctx->perm);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
19
ccodegen.cpp
19
ccodegen.cpp
@@ -213,7 +213,10 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){
|
|||||||
if(name == pctx->intern("main"_s) || name == pctx->intern("WinMain"_s)){
|
if(name == pctx->intern("main"_s) || name == pctx->intern("WinMain"_s)){
|
||||||
is_foreign = true;
|
is_foreign = true;
|
||||||
}
|
}
|
||||||
gen_simple_decl(lambda->resolved_type->func.ret, name, lambda->parent_scope, !is_foreign);
|
if(lambda->resolved_type->func.ret->kind == TYPE_TUPLE){
|
||||||
|
gen("TUPLE ");
|
||||||
|
}
|
||||||
|
else gen_simple_decl(lambda->resolved_type->func.ret, name, lambda->parent_scope, !is_foreign);
|
||||||
gen("(");
|
gen("(");
|
||||||
For(lambda->args){
|
For(lambda->args){
|
||||||
gen_var(it, DONT_EMIT_VALUE, true);
|
gen_var(it, DONT_EMIT_VALUE, true);
|
||||||
@@ -379,9 +382,9 @@ gen_ast(Ast *ast){
|
|||||||
|
|
||||||
CASE(RETURN, Return){
|
CASE(RETURN, Return){
|
||||||
gen("return");
|
gen("return");
|
||||||
if(node->expr){
|
For(node->expr){
|
||||||
gen(" ");
|
gen(" ");
|
||||||
gen_expr(node->expr);
|
gen_expr(it); // @todo multiple_returns
|
||||||
}
|
}
|
||||||
gen(";");
|
gen(";");
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -524,6 +527,15 @@ gen_ast(Ast *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(VAR_UNPACK, Var_Unpack){
|
||||||
|
For(node->vars) {
|
||||||
|
gen_ast(it);
|
||||||
|
}
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr(node->expr);
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
case AST_CONSTANT_ASSERT:
|
case AST_CONSTANT_ASSERT:
|
||||||
case AST_MODULE_NAMESPACE:
|
case AST_MODULE_NAMESPACE:
|
||||||
CASE(FILE_NAMESPACE, File_Namespace){unused(node); BREAK();}
|
CASE(FILE_NAMESPACE, File_Namespace){unused(node); BREAK();}
|
||||||
@@ -707,6 +719,7 @@ typedef struct String{
|
|||||||
#define assert_msg(x,...) assert(x)
|
#define assert_msg(x,...) assert(x)
|
||||||
|
|
||||||
)==");
|
)==");
|
||||||
|
//*(volatile int *)0 = 0;
|
||||||
#endif
|
#endif
|
||||||
For(pctx->ordered_decls){
|
For(pctx->ordered_decls){
|
||||||
if(it->kind == AST_STRUCT){
|
if(it->kind == AST_STRUCT){
|
||||||
|
|||||||
23
parsing.cpp
23
parsing.cpp
@@ -214,9 +214,15 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0){
|
|||||||
if(!scope_defined_outside) scope = begin_stmt_scope(scratch, token_block);
|
if(!scope_defined_outside) scope = begin_stmt_scope(scratch, token_block);
|
||||||
do{
|
do{
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
|
|
||||||
if(token_match_keyword(keyword_return)){
|
if(token_match_keyword(keyword_return)){
|
||||||
Ast_Expr *expr = 0;
|
Array<Ast_Expr *> expr = {scratch};
|
||||||
if(!token_is_scope()) expr = parse_expr();
|
if(!token_is_scope()) {
|
||||||
|
do{
|
||||||
|
Ast_Expr *subexpr = parse_expr();
|
||||||
|
expr.add(subexpr);
|
||||||
|
} while(token_match(TK_Comma));
|
||||||
|
}
|
||||||
scope->stmts.add(ast_return(token, expr));
|
scope->stmts.add(ast_return(token, expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +329,7 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0){
|
|||||||
decls.add(decl);
|
decls.add(decl);
|
||||||
}while(token_match(TK_Comma));
|
}while(token_match(TK_Comma));
|
||||||
|
|
||||||
token_expect(TK_Assign);
|
token_expect(TK_ColonAssign);
|
||||||
Ast_Expr *expr = parse_expr();
|
Ast_Expr *expr = parse_expr();
|
||||||
Ast_Var_Unpack *vars = ast_var_unpack(token, decls, expr);
|
Ast_Var_Unpack *vars = ast_var_unpack(token, decls, expr);
|
||||||
scope->stmts.add(vars);
|
scope->stmts.add(vars);
|
||||||
@@ -384,7 +390,16 @@ parse_lambda(Token *token){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
Ast_Expr *ret = parse_optional_type();
|
|
||||||
|
Array<Ast_Expr *> ret = {scratch};
|
||||||
|
if(token_match(TK_Colon)){
|
||||||
|
do{
|
||||||
|
Ast_Expr *typespec = parse_expr();
|
||||||
|
ret.add(typespec);
|
||||||
|
}while(token_match(TK_Comma));
|
||||||
|
}
|
||||||
|
else ret.add(ast_ident(token, intern_void));
|
||||||
|
|
||||||
Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0;
|
Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0;
|
||||||
Ast_Lambda *result = ast_lambda(token, params, ret, scope);
|
Ast_Lambda *result = ast_lambda(token, params, ret, scope);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -100,6 +100,20 @@ string_to_string16 :: (in: String): String16
|
|||||||
result.str[result.len] = 0
|
result.str[result.len] = 0
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
test_unicode :: ()
|
||||||
|
string := " 豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ..."
|
||||||
|
string_result := string_to_string16(string)
|
||||||
|
print(string_result)
|
||||||
|
|
||||||
|
result := utf8_to_utf32(&"A"[0], 1)
|
||||||
|
assert(result.out_str == 'A, "Invalid decode") // '
|
||||||
|
|
||||||
|
result = utf8_to_utf32(&"ć"[0], 2)
|
||||||
|
assert(result.out_str == 0x107, "Invalid decode")
|
||||||
|
|
||||||
|
result = utf8_to_utf32(&"ó"[0], 2)
|
||||||
|
assert(result.out_str == 0xF3, "Invalid decode")
|
||||||
|
|
||||||
Vec2I :: struct;; x: S64; y: S64
|
Vec2I :: struct;; x: S64; y: S64
|
||||||
Vec2 :: struct;; x: F32; y: F32
|
Vec2 :: struct;; x: F32; y: F32
|
||||||
Windows_Bitmap :: struct
|
Windows_Bitmap :: struct
|
||||||
@@ -128,7 +142,6 @@ create_bitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap
|
|||||||
|
|
||||||
hdc := GetDC(0)
|
hdc := GetDC(0)
|
||||||
result.dib = CreateDIBSection(hdc, &bminfo, DIB_RGB_COLORS, (&result.data)->**void, 0, 0)
|
result.dib = CreateDIBSection(hdc, &bminfo, DIB_RGB_COLORS, (&result.data)->**void, 0, 0)
|
||||||
error := GetLastError()
|
|
||||||
result.hdc = CreateCompatibleDC(hdc)
|
result.hdc = CreateCompatibleDC(hdc)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -140,21 +153,11 @@ window_procedure :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRE
|
|||||||
return 0
|
return 0
|
||||||
else;; return DefWindowProcW(hwnd, msg, wparam, lparam)
|
else;; return DefWindowProcW(hwnd, msg, wparam, lparam)
|
||||||
|
|
||||||
test_unicode :: ()
|
multiple_return_values :: (i: int): int, int
|
||||||
string := " 豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ..."
|
return i, i*2
|
||||||
string_result := string_to_string16(string)
|
|
||||||
print(string_result)
|
|
||||||
|
|
||||||
result := utf8_to_utf32(&"A"[0], 1)
|
|
||||||
assert(result.out_str == 'A, "Invalid decode") // '
|
|
||||||
|
|
||||||
result = utf8_to_utf32(&"ć"[0], 2)
|
|
||||||
assert(result.out_str == 0x107, "Invalid decode")
|
|
||||||
|
|
||||||
result = utf8_to_utf32(&"ó"[0], 2)
|
|
||||||
assert(result.out_str == 0xF3, "Invalid decode")
|
|
||||||
|
|
||||||
WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nShowCmd: int): int
|
WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nShowCmd: int): int
|
||||||
|
a, b := multiple_return_values(10)
|
||||||
window_name := string_to_string16("Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ")
|
window_name := string_to_string16("Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ")
|
||||||
w := WNDCLASSW{
|
w := WNDCLASSW{
|
||||||
lpfnWndProc = window_procedure,
|
lpfnWndProc = window_procedure,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ test_types(){
|
|||||||
Ast_Type *pointer_type4 = type_pointer(pointer_type2);
|
Ast_Type *pointer_type4 = type_pointer(pointer_type2);
|
||||||
assert(pointer_type3 != pointer_type1);
|
assert(pointer_type3 != pointer_type1);
|
||||||
assert(pointer_type3 == pointer_type4);
|
assert(pointer_type3 == pointer_type4);
|
||||||
|
#if 0
|
||||||
Array<Ast_Type*> types = {scratch};
|
Array<Ast_Type*> types = {scratch};
|
||||||
types.add(type_array(type_s64, 32));
|
types.add(type_array(type_s64, 32));
|
||||||
Ast_Type *func_type1 = type_lambda(0, types[0], types);
|
Ast_Type *func_type1 = type_lambda(0, types[0], types);
|
||||||
@@ -34,4 +34,5 @@ test_types(){
|
|||||||
Ast_Type *func_type4 = type_lambda(0, types[0], types2);
|
Ast_Type *func_type4 = type_lambda(0, types[0], types2);
|
||||||
assert(func_type1 != func_type3);
|
assert(func_type1 != func_type3);
|
||||||
assert(func_type3 == func_type4);
|
assert(func_type3 == func_type4);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
@@ -422,10 +422,20 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
||||||
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL);
|
Scratch scratch;
|
||||||
if(!op.type && ret != type_void) compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
Array<Ast_Type *> types = {scratch};
|
||||||
op.value = convert_untyped_to_typed(node->pos, op.value, ret);
|
For(node->expr){
|
||||||
if(op.type && op.type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
Operand op = resolve_expr(it, AST_CAN_BE_NULL);
|
||||||
|
types.add(op.type);
|
||||||
|
}
|
||||||
|
Ast_Type *type = type_try_tupling(types, node);
|
||||||
|
if(!type && ret != type_void)
|
||||||
|
compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(type));
|
||||||
|
|
||||||
|
Value value = {}; value.type = type;
|
||||||
|
value = convert_untyped_to_typed(node->pos, value, ret);
|
||||||
|
if(value.type && value.type != ret)
|
||||||
|
compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(type));
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,6 +494,24 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(VAR_UNPACK, Var_Unpack){
|
||||||
|
Operand expr_op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||||
|
if(!is_tuple(expr_op.type))
|
||||||
|
compiler_error(node->pos, "Expected expression to be of type [Tuple]");
|
||||||
|
if(expr_op.type->agg.members.len != node->vars.len)
|
||||||
|
compiler_error(node->pos, "Different count of return values and assigning values");
|
||||||
|
node->resolved_type = expr_op.type;
|
||||||
|
|
||||||
|
For(node->vars){
|
||||||
|
S64 index = node->vars.get_index(&it);
|
||||||
|
Ast_Resolved_Member *type = expr_op.type->agg.members.data + index;
|
||||||
|
it->type = type->type;
|
||||||
|
resolve_decl(it);
|
||||||
|
insert_into_scope(node->parent_scope, it);
|
||||||
|
}
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
default:{
|
default:{
|
||||||
if(is_flag_set(ast->flags, AST_EXPR)){
|
if(is_flag_set(ast->flags, AST_EXPR)){
|
||||||
assert(is_flag_set(ast->flags, AST_STMT));
|
assert(is_flag_set(ast->flags, AST_STMT));
|
||||||
@@ -497,8 +525,12 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
resolve_lambda_type(Ast_Lambda *lambda){
|
resolve_lambda_type(Ast_Lambda *lambda){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Ast_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL);
|
|
||||||
Array<Ast_Type *> args = {scratch};
|
Array<Ast_Type *> args = {scratch};
|
||||||
|
Array<Ast_Type *> ret = {scratch};
|
||||||
|
For(lambda->ret) {
|
||||||
|
Ast_Type *type = resolve_typespec(it, AST_CANT_BE_NULL);
|
||||||
|
ret.add(type);
|
||||||
|
}
|
||||||
|
|
||||||
For(lambda->args){
|
For(lambda->args){
|
||||||
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||||
@@ -508,7 +540,7 @@ resolve_lambda_type(Ast_Lambda *lambda){
|
|||||||
args.add(type);
|
args.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_lambda(lambda, ret_type, args);
|
return type_lambda(lambda, ret, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -1070,7 +1102,8 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR, Decl){
|
CASE(VAR, Decl){
|
||||||
Ast_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
|
Ast_Type *type = node->type;
|
||||||
|
if(!type) type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
|
||||||
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, type);
|
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, type);
|
||||||
assert(op.type != 0 || type != 0);
|
assert(op.type != 0 || type != 0);
|
||||||
|
|
||||||
|
|||||||
@@ -153,21 +153,32 @@ type_slice(Ast_Type *base, Ast *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
type_tuple(Array<Ast_Resolved_Member> types, Ast *ast){
|
type_try_tupling(Array<Ast_Type *> types, Ast *ast){
|
||||||
U64 hash = 1234;
|
assert(types.len != 0);
|
||||||
For(types) hash = hash_mix(hash, hash_ptr(it.type));
|
if(types.len == 1) return types[0];
|
||||||
|
|
||||||
|
U64 hash = 13;
|
||||||
|
For(types) hash = hash_mix(hash, hash_ptr(it));
|
||||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_TUPLE);
|
assert(result->kind == TYPE_TUPLE);
|
||||||
assert(result->agg.members.len == types.len);
|
assert(result->agg.members.len == types.len);
|
||||||
|
assert(result->agg.members.len > 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// @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);
|
||||||
For(types) result->size += it.type->size;
|
result->agg.members = array_make<Ast_Resolved_Member>(pctx->perm, types.len);
|
||||||
result->agg.members = types.tight_copy(pctx->perm);
|
For(types){
|
||||||
|
Ast_Resolved_Member m = {};
|
||||||
|
m.type = it;
|
||||||
|
m.offset = 0; // @todo
|
||||||
|
result->size += it->size;
|
||||||
|
result->agg.members.add(m);
|
||||||
|
}
|
||||||
map_insert(&pctx->type_map, hash, result);
|
map_insert(&pctx->type_map, hash, result);
|
||||||
|
assert(result->agg.members.len > 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,14 +203,14 @@ type_array(Ast_Type *base, S64 size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
type_lambda(Ast *ast, Ast_Type *ret, Array<Ast_Type *> args){
|
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){
|
||||||
|
Ast_Type *ret = type_try_tupling(return_vals, ast);
|
||||||
U64 hash = hash_ptr(ret);
|
U64 hash = hash_ptr(ret);
|
||||||
For(args) hash = hash_mix(hash, hash_ptr(it));
|
For(args) hash = hash_mix(hash, hash_ptr(it));
|
||||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_LAMBDA);
|
assert(result->kind == TYPE_LAMBDA);
|
||||||
assert(result->func.ret == ret);
|
|
||||||
assert(result->func.args.len == args.len);
|
assert(result->func.args.len == args.len);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user