Core: Remove AST_Tuple, repurpose VAR_UNPACK (buggy probably)
This commit is contained in:
@@ -3,7 +3,8 @@ call "..\misc\compile_setup.bat"
|
|||||||
|
|
||||||
bld --dont_compile_core
|
bld --dont_compile_core
|
||||||
cd build
|
cd build
|
||||||
core_main.exe rtsgame/main.core
|
rem core_main.exe rtsgame/main.core
|
||||||
|
core_main.exe examples/unions.core
|
||||||
bld --dont_compile_core --link=vendor/raylib/windows/raylibdll.lib
|
bld --dont_compile_core --link=vendor/raylib/windows/raylibdll.lib
|
||||||
rem build\generated_main.exe
|
rem build\generated_main.exe
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ QuestionMark16 :: 0x003f
|
|||||||
String32 :: struct;; str: *U32; len: int
|
String32 :: struct;; str: *U32; len: int
|
||||||
String16 :: struct;; str: *U16; len: int
|
String16 :: struct;; str: *U16; len: int
|
||||||
|
|
||||||
Utf8ToUtf32 :: (c: *U8, max_advance: int): U32, int
|
Utf8ToUtf32 :: (c: *U8, max_advance: int): Two(U32, int)
|
||||||
out_str: U32
|
out_str: U32
|
||||||
advance: int
|
advance: int
|
||||||
if (c[0] & 0b10000000) == 0
|
if (c[0] & 0b10000000) == 0
|
||||||
@@ -60,21 +60,19 @@ Utf8ToUtf32 :: (c: *U8, max_advance: int): U32, int
|
|||||||
out_str = (c0 & 0b00001111) << 18 | (c1 & 0b00111111) << 12 | (c2 & 0b00111111) << 6 | (c3 & 0b00111111)
|
out_str = (c0 & 0b00001111) << 18 | (c1 & 0b00111111) << 12 | (c2 & 0b00111111) << 6 | (c3 & 0b00111111)
|
||||||
advance = 4
|
advance = 4
|
||||||
|
|
||||||
return out_str, advance
|
return {out_str, advance}
|
||||||
|
|
||||||
Utf32ToUtf16 :: (codepoint: U32): [2]U16, int
|
Utf32ToUtf16 :: (codepoint: U32): Two([2]U16, int)
|
||||||
str: [2]U16
|
result: Two([2]U16, int)
|
||||||
len := 0
|
|
||||||
if codepoint < 0x10000
|
if codepoint < 0x10000
|
||||||
str[0] = codepoint->U16
|
result.a[0] = codepoint->U16
|
||||||
len = 1
|
result.b = 1
|
||||||
elif codepoint <= 0x10FFFF
|
elif codepoint <= 0x10FFFF
|
||||||
code: U32 = (codepoint - 0x10000)
|
code: U32 = (codepoint - 0x10000)
|
||||||
str[0] = (0xD800 | (code >> 10))->U16
|
result.a[0] = (0xD800 | (code >> 10))->U16
|
||||||
str[1] = (0xDC00 | (code & 0x3FF))->U16
|
result.a[1] = (0xDC00 | (code & 0x3FF))->U16
|
||||||
len = 2
|
result.b = 2
|
||||||
|
return result
|
||||||
return str, len
|
|
||||||
|
|
||||||
StringToString16 :: (arena: *Arena, in: String): String16
|
StringToString16 :: (arena: *Arena, in: String): String16
|
||||||
in_str := &in[0]
|
in_str := &in[0]
|
||||||
@@ -82,7 +80,9 @@ StringToString16 :: (arena: *Arena, in: String): String16
|
|||||||
alloc_size := (Len(in)*2)+1
|
alloc_size := (Len(in)*2)+1
|
||||||
result := String16{str = PushSize(arena, alloc_size->U64)}
|
result := String16{str = PushSize(arena, alloc_size->U64)}
|
||||||
for i := 0, i < Len(in)
|
for i := 0, i < Len(in)
|
||||||
s32, s32_len := Utf8ToUtf32(in_str + i, Len(in) - i)
|
a := Utf8ToUtf32(in_str + i, Len(in) - i)
|
||||||
|
s32 := a.a
|
||||||
|
s32_len := a.b
|
||||||
if s32_len != 0
|
if s32_len != 0
|
||||||
i += s32_len
|
i += s32_len
|
||||||
s16, s16_len := Utf32ToUtf16(s32)
|
s16, s16_len := Utf32ToUtf16(s32)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ AdjustWindowRectEx :: #foreign (lpRect: *RECT, dwStyle: DWORD, bMenu: BOOL, dwEx
|
|||||||
SetWindowPos :: #foreign (hWnd: HWND, hWndInsertAfter: HWND, X: int, Y: int, cx: int, cy: int, uFlags: UINT): BOOL
|
SetWindowPos :: #foreign (hWnd: HWND, hWndInsertAfter: HWND, X: int, Y: int, cx: int, cy: int, uFlags: UINT): BOOL
|
||||||
GetClientRect :: #foreign (hWnd: HWND, lpRect: LPRECT): BOOL
|
GetClientRect :: #foreign (hWnd: HWND, lpRect: LPRECT): BOOL
|
||||||
|
|
||||||
CW_USEDEFAULT :: -2147483648//0x80000000
|
CW_USEDEFAULT :: 0x80000000-1 // -2147483648
|
||||||
|
|
||||||
|
|
||||||
WS_CAPTION :: 0x00C00000
|
WS_CAPTION :: 0x00C00000
|
||||||
|
|||||||
15
core_ast.cpp
15
core_ast.cpp
@@ -110,11 +110,11 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static Ast_Lambda *
|
CORE_Static Ast_Lambda *
|
||||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, Array<Ast_Expr *> ret, Ast_Scope *scope) {
|
ast_lambda(Token *pos, Array<Ast_Decl *> params, 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->ret = ret;
|
||||||
result->scope = scope;
|
result->scope = scope;
|
||||||
if (scope) scope->parent_ast = result;
|
if (scope) scope->parent_ast = result;
|
||||||
|
|
||||||
@@ -171,12 +171,9 @@ ast_continue(Token *pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static Ast_Return *
|
CORE_Static Ast_Return *
|
||||||
ast_return(Token *pos, Array<Ast_Expr *> expr) {
|
ast_return(Token *pos, Ast_Expr *expr) {
|
||||||
AST_NEW(Return, RETURN, pos, AST_STMT);
|
AST_NEW(Return, RETURN, pos, AST_STMT);
|
||||||
if (expr.len) {
|
result->expr = expr;
|
||||||
For(expr) assert(is_flag_set(it->flags, AST_EXPR));
|
|
||||||
result->expr = expr.tight_copy(pctx->perm);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,14 +620,14 @@ void next(Ast_Iter *iter) {
|
|||||||
case AST_RETURN: {
|
case AST_RETURN: {
|
||||||
Ast_Return *node = (Ast_Return *)ast;
|
Ast_Return *node = (Ast_Return *)ast;
|
||||||
if (!iter->skip_end_blocks) iter->stack.add(node);
|
if (!iter->skip_end_blocks) iter->stack.add(node);
|
||||||
For(node->expr) iter->stack.add(it);
|
if (node->expr) iter->stack.add(node->expr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case AST_LAMBDA_EXPR: {
|
case AST_LAMBDA_EXPR: {
|
||||||
Ast_Lambda *node = (Ast_Lambda *)ast;
|
Ast_Lambda *node = (Ast_Lambda *)ast;
|
||||||
if (!iter->skip_end_blocks) iter->stack.add(node);
|
if (!iter->skip_end_blocks) iter->stack.add(node);
|
||||||
if (node->scope) iter->stack.add(node->scope);
|
if (node->scope) iter->stack.add(node->scope);
|
||||||
For(node->ret) iter->stack.add(it);
|
iter->stack.add(node->ret);
|
||||||
For(node->args) iter->stack.add(it);
|
For(node->args) iter->stack.add(it);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ get_ctype_name_for_type(Ast_Type *type) {
|
|||||||
case TYPE_U16: return "uint16_t";
|
case TYPE_U16: return "uint16_t";
|
||||||
case TYPE_U32: return "uint32_t";
|
case TYPE_U32: return "uint32_t";
|
||||||
case TYPE_U64: return "uint64_t";
|
case TYPE_U64: return "uint64_t";
|
||||||
case TYPE_TUPLE: return "Tuple";
|
|
||||||
case TYPE_TYPE: return "int64_t";
|
case TYPE_TYPE: return "int64_t";
|
||||||
|
|
||||||
case TYPE_INCOMPLETE: {
|
case TYPE_INCOMPLETE: {
|
||||||
@@ -105,10 +104,6 @@ string_simple_decl_prefix(Ast_Type *ast) {
|
|||||||
string = pctx->fmt("Slice%llu ", ast->type_id);
|
string = pctx->fmt("Slice%llu ", ast->type_id);
|
||||||
return string;
|
return string;
|
||||||
} break;
|
} break;
|
||||||
case TYPE_TUPLE: {
|
|
||||||
String string = pctx->fmt("Tuple%llu ", ast->type_id);
|
|
||||||
return string;
|
|
||||||
} break;
|
|
||||||
case TYPE_UNION:
|
case TYPE_UNION:
|
||||||
case TYPE_STRUCT: {
|
case TYPE_STRUCT: {
|
||||||
auto constant = (Ast_Decl *)ast->ast;
|
auto constant = (Ast_Decl *)ast->ast;
|
||||||
@@ -189,6 +184,7 @@ get_type_postfix(Ast_Type *type) {
|
|||||||
case TYPE_U8:
|
case TYPE_U8:
|
||||||
case TYPE_UCHAR:
|
case TYPE_UCHAR:
|
||||||
case TYPE_U16:
|
case TYPE_U16:
|
||||||
|
case TYPE_UINT:
|
||||||
case TYPE_U32: return "U"_s; break;
|
case TYPE_U32: return "U"_s; break;
|
||||||
|
|
||||||
case TYPE_SHORT:
|
case TYPE_SHORT:
|
||||||
@@ -585,39 +581,8 @@ gen_ast(Ast *ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(RETURN, Return) {
|
CASE(RETURN, Return) {
|
||||||
if (is_tuple(node->resolved_type)) {
|
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
|
||||||
|
|
||||||
Intern_String tuple_name = get_unique_name();
|
|
||||||
gen_simple_decl(node->resolved_type, tuple_name);
|
|
||||||
gen(";");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
For(node->expr) {
|
|
||||||
|
|
||||||
// We cant assign to array in C so we need a special case
|
|
||||||
if (is_array(it->resolved_type)) {
|
|
||||||
genln("MemoryCopy(&%Q.m%d, ", tuple_name, i);
|
|
||||||
gen_expr(it);
|
|
||||||
gen(", sizeof(%Q.m%d));", tuple_name, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
genln("%Q.m%d = ", tuple_name, i);
|
|
||||||
gen_expr(it);
|
|
||||||
gen(";");
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
gen_line(node);
|
|
||||||
genln("return %Q;", tuple_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(node->expr.len <= 1);
|
|
||||||
gen("return ");
|
gen("return ");
|
||||||
For(node->expr) gen_expr(it);
|
gen_expr(node->expr);
|
||||||
gen(";");
|
gen(";");
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -814,10 +779,10 @@ gen_ast(Ast *ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR_UNPACK, Var_Unpack) {
|
CASE(VAR_UNPACK, Var_Unpack) {
|
||||||
For(node->vars)
|
Ast_Type *t = node->resolved_type;
|
||||||
|
For(node->vars) {
|
||||||
gen_ast(it);
|
gen_ast(it);
|
||||||
|
}
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
|
||||||
|
|
||||||
Intern_String var_name = get_unique_name();
|
Intern_String var_name = get_unique_name();
|
||||||
gen_simple_decl(node->resolved_type, var_name);
|
gen_simple_decl(node->resolved_type, var_name);
|
||||||
@@ -827,7 +792,12 @@ gen_ast(Ast *ast) {
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
For(node->vars) {
|
For(node->vars) {
|
||||||
gen("MemoryCopy((void *)&%Q, (void *)&%Q.m%d, sizeof(%Q));", it->name, var_name, i++, it->name);
|
Ast_Resolved_Member &m = t->agg.members[i];
|
||||||
|
char *p = "&";
|
||||||
|
if (is_array(m.type)) p = "";
|
||||||
|
|
||||||
|
gen("MemoryCopy((void *)%s%Q, (void *)%s%Q.%Q, sizeof(%Q));", p, it->name, p, var_name, m.name, it->name);
|
||||||
|
i = +1;
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -926,10 +896,8 @@ int printf(const char *format, ...);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate slice and tuple types
|
// Generate slice types
|
||||||
For2(pctx->all_types, type) {
|
For2(pctx->all_types, type) {
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
|
||||||
|
|
||||||
if (type->kind == TYPE_SLICE) {
|
if (type->kind == TYPE_SLICE) {
|
||||||
genln("typedef struct Slice%llu{", type->type_id);
|
genln("typedef struct Slice%llu{", type->type_id);
|
||||||
global_indent++;
|
global_indent++;
|
||||||
@@ -940,20 +908,6 @@ int printf(const char *format, ...);
|
|||||||
global_indent--;
|
global_indent--;
|
||||||
genln("} Slice%llu;", type->type_id);
|
genln("} Slice%llu;", type->type_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (type->kind == TYPE_TUPLE) {
|
|
||||||
genln("typedef struct Tuple%llu{", type->type_id);
|
|
||||||
global_indent++;
|
|
||||||
For(type->agg.members) {
|
|
||||||
genln("");
|
|
||||||
// @todo remove intern from gen
|
|
||||||
Intern_String name = pctx->internf("m%llu", type->agg.members.get_index(it));
|
|
||||||
gen_simple_decl(it.type, name);
|
|
||||||
gen(";");
|
|
||||||
}
|
|
||||||
global_indent--;
|
|
||||||
genln("} Tuple%llu;", type->type_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Intern_String intern_main = pctx->intern("main"_s);
|
Intern_String intern_main = pctx->intern("main"_s);
|
||||||
@@ -994,12 +948,15 @@ int printf(const char *format, ...);
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate type info
|
// Generate type info
|
||||||
genln("int64_t type_infos_len = %d;", length(&pctx->all_types));
|
genln("int type_infos_len = %d;", length(&pctx->all_types));
|
||||||
genln("Type_Info *type_infos = (Type_Info[]){");
|
genln("Type_Info *type_infos = (Type_Info[]){");
|
||||||
global_indent++;
|
global_indent++;
|
||||||
|
int i = 0;
|
||||||
For2(pctx->all_types, t) {
|
For2(pctx->all_types, t) {
|
||||||
if (t->kind == TYPE_POLYMORPH) continue;
|
if (t->kind == TYPE_POLYMORPH) continue;
|
||||||
// if (t->kind == TYPE_VARGS) continue;
|
if (i++ != t->type_id) {
|
||||||
|
compiler_error(0, "Internal compiler error: type info array is inconsistent");
|
||||||
|
}
|
||||||
|
|
||||||
genln("{/*%Q*/", typestring(t));
|
genln("{/*%Q*/", typestring(t));
|
||||||
global_indent += 1;
|
global_indent += 1;
|
||||||
@@ -1042,9 +999,11 @@ int printf(const char *format, ...);
|
|||||||
global_indent -= 1;
|
global_indent -= 1;
|
||||||
genln("}");
|
genln("}");
|
||||||
} break;
|
} break;
|
||||||
|
case AST_ENUM: {
|
||||||
|
// todo;
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
}
|
}
|
||||||
// invalid_default_case;
|
|
||||||
}
|
}
|
||||||
end_of_switch:;
|
end_of_switch:;
|
||||||
global_indent -= 1;
|
global_indent -= 1;
|
||||||
|
|||||||
@@ -335,7 +335,11 @@ Any :: struct
|
|||||||
|
|
||||||
String :: struct
|
String :: struct
|
||||||
data: *U8
|
data: *U8
|
||||||
len: S64
|
len: int
|
||||||
|
|
||||||
|
Two :: struct($A: Type, $B: Type)
|
||||||
|
a: A
|
||||||
|
b: B
|
||||||
|
|
||||||
Type_Info_Kind :: enum
|
Type_Info_Kind :: enum
|
||||||
S64 // FIRST_NUMERIC
|
S64 // FIRST_NUMERIC
|
||||||
@@ -366,26 +370,26 @@ Type_Info_Kind :: enum
|
|||||||
Type_Info_Struct_Member :: struct
|
Type_Info_Struct_Member :: struct
|
||||||
name: String
|
name: String
|
||||||
type: Type
|
type: Type
|
||||||
offset: S64
|
offset: int
|
||||||
|
|
||||||
Type_Info :: struct
|
Type_Info :: struct
|
||||||
kind: Type_Info_Kind
|
kind: Type_Info_Kind
|
||||||
size: S64
|
size: int
|
||||||
align: S64
|
align: int
|
||||||
is_unsigned: bool
|
is_unsigned: bool
|
||||||
type: Type
|
type: Type
|
||||||
|
|
||||||
base_type: Type
|
base_type: Type
|
||||||
array_size: S64
|
array_size: int
|
||||||
struct_members: []Type_Info_Struct_Member
|
struct_members: []Type_Info_Struct_Member
|
||||||
lambda_arguments: []Type_Info
|
lambda_arguments: []Type_Info
|
||||||
lambda_return: Type
|
lambda_return: Type
|
||||||
|
|
||||||
type_infos_len: S64 #foreign
|
type_infos_len: int #foreign
|
||||||
type_infos : *Type_Info #foreign
|
type_infos : *Type_Info #foreign
|
||||||
|
|
||||||
GetTypeInfo :: (type: Type): *Type_Info
|
GetTypeInfo :: (type: Type): *Type_Info
|
||||||
id := type->S64
|
id := type->int
|
||||||
if id >= type_infos_len
|
if id >= type_infos_len
|
||||||
return 0
|
return 0
|
||||||
return type_infos + id
|
return type_infos + id
|
||||||
|
|||||||
@@ -218,7 +218,6 @@ enum Ast_Type_Kind {
|
|||||||
TYPE_ENUM,
|
TYPE_ENUM,
|
||||||
TYPE_TYPE,
|
TYPE_TYPE,
|
||||||
TYPE_SLICE,
|
TYPE_SLICE,
|
||||||
TYPE_TUPLE,
|
|
||||||
|
|
||||||
TYPE_COMPLETING,
|
TYPE_COMPLETING,
|
||||||
TYPE_INCOMPLETE,
|
TYPE_INCOMPLETE,
|
||||||
@@ -509,7 +508,7 @@ struct Ast_Builtin : Ast_Expr {
|
|||||||
|
|
||||||
struct Ast_Return : Ast {
|
struct Ast_Return : Ast {
|
||||||
Ast_Type *resolved_type;
|
Ast_Type *resolved_type;
|
||||||
Array<Ast_Expr *> expr;
|
Ast_Expr *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_If_Node : Ast {
|
struct Ast_If_Node : Ast {
|
||||||
@@ -538,16 +537,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;
|
||||||
// :Multiple arguments
|
|
||||||
// @todo: maybe disallow multiple arguments in current form
|
|
||||||
// and use polimorphism. Then we could make var unpacking,
|
|
||||||
// unpack structs making it more powerful
|
|
||||||
|
|
||||||
// @cleanup @refactor: return value shouldn't be a array of expressions.
|
|
||||||
// It should be a single expression. So probably need a special type
|
|
||||||
// for that.
|
|
||||||
Array<Ast_Expr *> ret;
|
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -284,13 +284,8 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) {
|
|||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
|
|
||||||
if (token_match_keyword(pctx->keyword_return)) {
|
if (token_match_keyword(pctx->keyword_return)) {
|
||||||
Array<Ast_Expr *> expr = {scratch.arena};
|
Ast_Expr *expr = 0;
|
||||||
if (!token_is_scope()) {
|
if (!token_is_scope()) expr = parse_expr();
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,17 +513,7 @@ parse_lambda(Token *token) {
|
|||||||
Scoped_Arena scratch(pctx->scratch);
|
Scoped_Arena scratch(pctx->scratch);
|
||||||
|
|
||||||
Array<Ast_Decl *> params = parse_parameter_list(scratch.arena);
|
Array<Ast_Decl *> params = parse_parameter_list(scratch.arena);
|
||||||
Array<Ast_Expr *> ret = {scratch.arena};
|
Ast_Expr *ret = parse_optional_type();
|
||||||
if (token_match(TK_Colon)) {
|
|
||||||
do {
|
|
||||||
Ast_Expr *typespec = parse_expr();
|
|
||||||
set_flag_typespec(typespec);
|
|
||||||
|
|
||||||
ret.add(typespec);
|
|
||||||
} while (token_match(TK_Comma));
|
|
||||||
}
|
|
||||||
else ret.add(ast_ident(token, pctx->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;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ Ast_Expr *create_typespec_from_type(Token *pos, Ast_Scope *parent_scope, Ast_Typ
|
|||||||
Ast_Expr *result = 0;
|
Ast_Expr *result = 0;
|
||||||
switch (type->kind) {
|
switch (type->kind) {
|
||||||
case TYPE_NONE:
|
case TYPE_NONE:
|
||||||
case TYPE_TUPLE:
|
|
||||||
case TYPE_COMPLETING:
|
case TYPE_COMPLETING:
|
||||||
case TYPE_INCOMPLETE:
|
case TYPE_INCOMPLETE:
|
||||||
case TYPE_POLYMORPH:
|
case TYPE_POLYMORPH:
|
||||||
@@ -394,11 +393,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
|
|||||||
Ast_Return *src = (Ast_Return *)ast;
|
Ast_Return *src = (Ast_Return *)ast;
|
||||||
Ast_Return *dst = ast_create_copy(parent_scope, Ast_Return, ast);
|
Ast_Return *dst = ast_create_copy(parent_scope, Ast_Return, ast);
|
||||||
|
|
||||||
dst->expr.init(pctx->perm, src->expr.len);
|
dst->expr = (Ast_Expr *)ast_copy(src->expr, parent_scope, repl);
|
||||||
For(src->expr) {
|
|
||||||
auto copy = (Ast_Expr *)ast_copy(it, parent_scope, repl);
|
|
||||||
dst->expr.add(copy);
|
|
||||||
}
|
|
||||||
result = dst;
|
result = dst;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -413,11 +408,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
|
|||||||
dst->args.add(copy);
|
dst->args.add(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->ret.init(pctx->perm, src->ret.len);
|
dst->ret = (Ast_Expr *)ast_copy(src->ret, parent_scope, repl);
|
||||||
For(src->ret) {
|
|
||||||
auto copy = (Ast_Expr *)ast_copy(it, parent_scope, repl);
|
|
||||||
dst->ret.add(copy);
|
|
||||||
}
|
|
||||||
dst->scope = (Ast_Scope *)ast_copy(src->scope, parent_scope, repl);
|
dst->scope = (Ast_Scope *)ast_copy(src->scope, parent_scope, repl);
|
||||||
result = dst;
|
result = dst;
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -77,9 +77,6 @@ core_type_to_string(Ast_Type *type) {
|
|||||||
String base = core_type_to_string(type->base);
|
String base = core_type_to_string(type->base);
|
||||||
return pctx->fmt("[]%Q", base);
|
return pctx->fmt("[]%Q", base);
|
||||||
} break;
|
} break;
|
||||||
case TYPE_TUPLE: {
|
|
||||||
invalid_codepath;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TYPE_TYPE: return "Type"_s; break;
|
case TYPE_TYPE: return "Type"_s; break;
|
||||||
case TYPE_UNTYPED_BOOL: return "UntypedBool"_s; break;
|
case TYPE_UNTYPED_BOOL: return "UntypedBool"_s; break;
|
||||||
@@ -342,10 +339,7 @@ void core__stringify(Ast *ast) {
|
|||||||
case AST_RETURN: {
|
case AST_RETURN: {
|
||||||
Ast_Return *n = (Ast_Return *)ast;
|
Ast_Return *n = (Ast_Return *)ast;
|
||||||
gen("return ");
|
gen("return ");
|
||||||
For(n->expr) {
|
core__stringify(n->expr);
|
||||||
core__stringify(it);
|
|
||||||
if (!n->expr.is_last(it)) gen(", ");
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case AST_LAMBDA_EXPR: {
|
case AST_LAMBDA_EXPR: {
|
||||||
@@ -358,12 +352,8 @@ void core__stringify(Ast *ast) {
|
|||||||
}
|
}
|
||||||
gen(")");
|
gen(")");
|
||||||
|
|
||||||
if (n->ret.len) gen(": ");
|
if (n->ret) gen(": ");
|
||||||
For(n->ret) {
|
core__stringify(n->ret);
|
||||||
core__stringify(it);
|
|
||||||
if (!n->ret.is_last(it)) gen(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
core__stringify(n->scope);
|
core__stringify(n->scope);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
@@ -723,48 +723,25 @@ require_const_int(Ast_Expr *expr, Resolve_Flag flags) {
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note: Ret is return value of CORE_Static passed down the stack
|
// ret is return value passed down the stack to check if type matches
|
||||||
// to check if type matches
|
CORE_Static void resolve_stmt(Ast *ast, Ast_Type *ret) {
|
||||||
CORE_Static void
|
|
||||||
resolve_stmt(Ast *ast, Ast_Type *ret) {
|
|
||||||
if (!ast) return;
|
if (!ast) return;
|
||||||
assert(ast->parent_scope->kind == AST_SCOPE);
|
assert(ast->parent_scope->kind == AST_SCOPE);
|
||||||
if (ast->flags & AST_COMPILER_BREAKPOINT) Breakpoint;
|
if (ast->flags & AST_COMPILER_BREAKPOINT) Breakpoint;
|
||||||
|
|
||||||
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
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
Ast_Type *value_type = pctx->type_void;
|
||||||
Array<Ast_Type *> types = {scratch.arena};
|
if (node->expr) {
|
||||||
|
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, ret, 0);
|
||||||
int i = 0;
|
|
||||||
For(node->expr) {
|
|
||||||
Operand op;
|
|
||||||
if (is_tuple(ret)) {
|
|
||||||
Ast_Type *sub_type = ret->agg.members[i].type;
|
|
||||||
op = resolve_expr(it, AST_CAN_BE_NULL, sub_type, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
op = resolve_expr(it, AST_CAN_BE_NULL, ret, 0);
|
|
||||||
convert_untyped_to_typed(node->pos, &op.value, ret);
|
convert_untyped_to_typed(node->pos, &op.value, ret);
|
||||||
|
value_type = op.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
types.add(op.type);
|
if (value_type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %Q got instead %Q", typestring(ret), typestring(value_type));
|
||||||
i += 1;
|
node->resolved_type = ret;
|
||||||
}
|
|
||||||
|
|
||||||
Ast_Type *type = type_try_tupling(types, node);
|
if (node->expr) try_propagating_resolved_type_to_untyped_literals(node->expr, ret);
|
||||||
if (type && type != ret)
|
|
||||||
compiler_error(node->pos, "Return statement has different type then returned value, expecting: %Q got instead %Q", typestring(ret), typestring(type));
|
|
||||||
node->resolved_type = type;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
For(node->expr) {
|
|
||||||
Ast_Type *sub_type = type;
|
|
||||||
if (is_tuple(type)) sub_type = type->agg.members[i].type;
|
|
||||||
|
|
||||||
try_propagating_resolved_type_to_untyped_literals(it, sub_type);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -877,8 +854,8 @@ resolve_stmt(Ast *ast, Ast_Type *ret) {
|
|||||||
|
|
||||||
CASE(VAR_UNPACK, Var_Unpack) {
|
CASE(VAR_UNPACK, Var_Unpack) {
|
||||||
Operand expr_op = resolve_expr(node->expr, AST_CANT_BE_NULL, 0, 0);
|
Operand expr_op = resolve_expr(node->expr, AST_CANT_BE_NULL, 0, 0);
|
||||||
if (!is_tuple(expr_op.type))
|
if (!is_struct_union(expr_op.type))
|
||||||
compiler_error(node->pos, "Expected expression to be of type [Tuple]");
|
compiler_error(node->pos, "Expected expression to have either [Struct] or [Union] type");
|
||||||
if (expr_op.type->agg.members.len != node->vars.len)
|
if (expr_op.type->agg.members.len != node->vars.len)
|
||||||
compiler_error(node->pos, "Different count of return values and assigning values");
|
compiler_error(node->pos, "Different count of return values and assigning values");
|
||||||
node->resolved_type = expr_op.type;
|
node->resolved_type = expr_op.type;
|
||||||
@@ -907,11 +884,8 @@ CORE_Static Ast_Type *
|
|||||||
resolve_lambda_type(Ast_Lambda *lambda) {
|
resolve_lambda_type(Ast_Lambda *lambda) {
|
||||||
Scoped_Arena scratch(pctx->scratch);
|
Scoped_Arena scratch(pctx->scratch);
|
||||||
Array<Ast_Type *> args = {scratch.arena};
|
Array<Ast_Type *> args = {scratch.arena};
|
||||||
Array<Ast_Type *> ret = {scratch.arena};
|
Ast_Type *ret = resolve_typespec(lambda->ret, AST_CAN_BE_NULL);
|
||||||
For(lambda->ret) {
|
if (!ret) ret = pctx->type_void;
|
||||||
Ast_Type *type = resolve_typespec(it, AST_CANT_BE_NULL);
|
|
||||||
ret.add(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
For(lambda->args) {
|
For(lambda->args) {
|
||||||
if (it->name == pctx->intern("..."_s)) {
|
if (it->name == pctx->intern("..."_s)) {
|
||||||
@@ -1343,7 +1317,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
if (is_pointer(type)) type = type->base;
|
if (is_pointer(type)) type = type->base;
|
||||||
type_complete(type);
|
type_complete(type);
|
||||||
|
|
||||||
bool is_dottable_type = type->kind == TYPE_STRUCT || type->kind == TYPE_UNION;
|
bool is_dottable_type = type->kind == TYPE_ENUM || type->kind == TYPE_STRUCT || type->kind == TYPE_UNION;
|
||||||
if (is_dottable_type == false) compiler_error(node->pos, "Type %Q doesn't have anything to access using '.' operator", typestring(type));
|
if (is_dottable_type == false) compiler_error(node->pos, "Type %Q doesn't have anything to access using '.' operator", typestring(type));
|
||||||
|
|
||||||
scope = ((Ast_Decl *)type->ast)->scope;
|
scope = ((Ast_Decl *)type->ast)->scope;
|
||||||
@@ -1377,10 +1351,6 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
|
|
||||||
if (operator_overload) {
|
if (operator_overload) {
|
||||||
proceed_to_default_operator_handler = false;
|
proceed_to_default_operator_handler = false;
|
||||||
if (operator_overload->lambda->ret.len != 1) {
|
|
||||||
compiler_error(operator_overload->pos, "Operator overload is required to have exactly 1 return value");
|
|
||||||
}
|
|
||||||
|
|
||||||
left.value = left_copy;
|
left.value = left_copy;
|
||||||
right.value = right_copy;
|
right.value = right_copy;
|
||||||
// @warning: might be buggy, added after a long break
|
// @warning: might be buggy, added after a long break
|
||||||
@@ -1468,10 +1438,6 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
|||||||
Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, value.type, 0, node->pos, node->op, hash);
|
Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, value.type, 0, node->pos, node->op, hash);
|
||||||
if (operator_overload) {
|
if (operator_overload) {
|
||||||
proceed_to_default_operator_handler = false;
|
proceed_to_default_operator_handler = false;
|
||||||
if (operator_overload->lambda->ret.len != 1) {
|
|
||||||
compiler_error(operator_overload->pos, "Operator overload is required to have exactly 1 return value");
|
|
||||||
}
|
|
||||||
|
|
||||||
node->resolved_type = operator_overload->type->func.ret;
|
node->resolved_type = operator_overload->type->func.ret;
|
||||||
node->resolved_operator_overload = operator_overload;
|
node->resolved_operator_overload = operator_overload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ get_name_of_type(Ast_Type *type) {
|
|||||||
case TYPE_U16: return "U16";
|
case TYPE_U16: return "U16";
|
||||||
case TYPE_U32: return "U32";
|
case TYPE_U32: return "U32";
|
||||||
case TYPE_U64: return "U64";
|
case TYPE_U64: return "U64";
|
||||||
case TYPE_TUPLE: return "Tuple";
|
|
||||||
case TYPE_TYPE:
|
case TYPE_TYPE:
|
||||||
return "Type";
|
return "Type";
|
||||||
case TYPE_POLYMORPH:
|
case TYPE_POLYMORPH:
|
||||||
@@ -42,10 +41,10 @@ get_name_of_type(Ast_Type *type) {
|
|||||||
force_inline B32 is_any(Ast_Type *a) { return a == pctx->type_any; }
|
force_inline B32 is_any(Ast_Type *a) { return a == pctx->type_any; }
|
||||||
force_inline B32 is_struct(Ast_Type *a) { return a->kind == TYPE_STRUCT; }
|
force_inline B32 is_struct(Ast_Type *a) { return a->kind == TYPE_STRUCT; }
|
||||||
force_inline B32 is_union(Ast_Type *a) { return a->kind == TYPE_UNION; }
|
force_inline B32 is_union(Ast_Type *a) { return a->kind == TYPE_UNION; }
|
||||||
|
force_inline B32 is_struct_union(Ast_Type *a) { return a->kind == TYPE_UNION || a->kind == TYPE_STRUCT; }
|
||||||
force_inline B32 is_lambda(Ast_Type *a) { return a->kind == TYPE_LAMBDA; }
|
force_inline B32 is_lambda(Ast_Type *a) { return a->kind == TYPE_LAMBDA; }
|
||||||
force_inline B32 is_array(Ast_Type *a) { return a->kind == TYPE_ARRAY; }
|
force_inline B32 is_array(Ast_Type *a) { return a->kind == TYPE_ARRAY; }
|
||||||
force_inline B32 is_slice(Ast_Type *a) { return a->kind == TYPE_SLICE; }
|
force_inline B32 is_slice(Ast_Type *a) { return a->kind == TYPE_SLICE; }
|
||||||
force_inline B32 is_tuple(Ast_Type *a) { return a->kind == TYPE_TUPLE; }
|
|
||||||
force_inline B32 is_enum(Ast_Type *a) { return a->kind == TYPE_ENUM; }
|
force_inline B32 is_enum(Ast_Type *a) { return a->kind == TYPE_ENUM; }
|
||||||
force_inline B32 is_pointer(Ast_Type *a) { return a->kind == TYPE_POINTER; }
|
force_inline B32 is_pointer(Ast_Type *a) { return a->kind == TYPE_POINTER; }
|
||||||
force_inline B32 is_void(Ast_Type *a) { return a->kind == TYPE_VOID; }
|
force_inline B32 is_void(Ast_Type *a) { return a->kind == TYPE_VOID; }
|
||||||
@@ -71,12 +70,12 @@ force_inline B32 is_numeric(Ast_Type *type) {
|
|||||||
// Hash consed types
|
// Hash consed types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CORE_Static Ast_Type *
|
CORE_Static Ast_Type *
|
||||||
type_new(Allocator *allocator, Ast_Type_Kind kind, int32_t size, int32_t align) {
|
type_new(Allocator *allocator, Ast_Type_Kind kind, int32_t size, int32_t align, bool generate_type_id = true) {
|
||||||
Ast_Type *result = allocate_struct(allocator, Ast_Type, true);
|
Ast_Type *result = allocate_struct(allocator, Ast_Type, true);
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->size = size;
|
result->size = size;
|
||||||
result->align = align;
|
result->align = align;
|
||||||
result->type_id = pctx->type_ids++;
|
if (generate_type_id) result->type_id = pctx->type_ids++;
|
||||||
add(pctx->perm, &pctx->all_types, result);
|
add(pctx->perm, &pctx->all_types, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -127,37 +126,6 @@ type_slice(Ast_Type *base, Ast *ast) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static Ast_Type *
|
|
||||||
type_try_tupling(Array<Ast_Type *> types, Ast *ast) {
|
|
||||||
if (types.len == 0) return pctx->type_void;
|
|
||||||
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);
|
|
||||||
if (result) {
|
|
||||||
assert(result->kind == TYPE_TUPLE);
|
|
||||||
assert(result->agg.members.len == types.len);
|
|
||||||
assert(result->agg.members.len > 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo alignment, offsets
|
|
||||||
result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align);
|
|
||||||
result->agg.members.init(pctx->perm, types.len);
|
|
||||||
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);
|
|
||||||
assert(result->agg.members.len > 1);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CORE_Static Ast_Type *
|
CORE_Static Ast_Type *
|
||||||
type_array(Ast_Type *base, S32 size) {
|
type_array(Ast_Type *base, S32 size) {
|
||||||
U64 hash_base = hash_ptr(base);
|
U64 hash_base = hash_ptr(base);
|
||||||
@@ -178,24 +146,21 @@ type_array(Ast_Type *base, S32 size) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline U64
|
inline U64 calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b) {
|
||||||
calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b) {
|
|
||||||
U64 result = 13;
|
U64 result = 13;
|
||||||
result = hash_mix(result, hash_ptr(a));
|
result = hash_mix(result, hash_ptr(a));
|
||||||
result = hash_mix(result, hash_ptr(b));
|
result = hash_mix(result, hash_ptr(b));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline U64
|
inline U64 calculate_hash_for_arguments(Ast_Type *a) {
|
||||||
calculate_hash_for_arguments(Ast_Type *a) {
|
|
||||||
U64 result = 13;
|
U64 result = 13;
|
||||||
result = hash_mix(result, hash_ptr(a));
|
result = hash_mix(result, hash_ptr(a));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static Ast_Type *
|
CORE_Static Ast_Type *
|
||||||
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args) {
|
type_lambda(Ast *ast, Ast_Type *ret, Array<Ast_Type *> args) {
|
||||||
Ast_Type *ret = type_try_tupling(return_vals, ast);
|
|
||||||
U64 hash_without_ret = 13;
|
U64 hash_without_ret = 13;
|
||||||
For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
|
For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
|
||||||
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
|
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
|
||||||
@@ -232,8 +197,14 @@ type_enum(Ast_Decl *ast, Ast_Type *type) {
|
|||||||
CORE_Static Ast_Type *
|
CORE_Static Ast_Type *
|
||||||
type_incomplete(Ast *ast) {
|
type_incomplete(Ast *ast) {
|
||||||
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);
|
bool generate_type_id = true;
|
||||||
|
if (is_flag_set(ast->flags, AST_POLYMORPH)) {
|
||||||
|
kind = TYPE_POLYMORPH;
|
||||||
|
generate_type_id = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Type *result = type_new(pctx->perm, kind, 0, 0, generate_type_id);
|
||||||
result->ast = ast;
|
result->ast = ast;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user