From 7e4b9777e6aa2912162c5a88ee93178b85b28425 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 3 Jun 2022 12:07:17 +0200 Subject: [PATCH] Cleanup --- main.cpp | 2 +- new_ast.cpp | 9 +++ new_parse.cpp | 3 - new_types.kl | 20 ++++-- typecheck.cpp | 178 +++++++++++++++++++++++++++++++------------------- 5 files changed, 138 insertions(+), 74 deletions(-) diff --git a/main.cpp b/main.cpp index d55384a..63d0c55 100644 --- a/main.cpp +++ b/main.cpp @@ -46,7 +46,7 @@ For now I don't thing it should be overloadable. [ ] - Add single line lambda expressions [ ] - Ternary operator [ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix -[ ] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need the big int stuff +[ ] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need [ ] - Order independent constants in structs [ ] - Can you even have recursive lambdas in structs, other recursive stuff [ ] - Casting to basic types by call S64(x) diff --git a/new_ast.cpp b/new_ast.cpp index 5f63db1..34314eb 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -142,6 +142,14 @@ union{ \ bool bool_val; \ F64 f64_val; \ F32 f32_val; \ + S8 s8_val; \ + S16 s16_val; \ + S32 s32_val; \ + S64 s64_val; \ + U8 u8_val; \ + U16 u16_val; \ + U32 u32_val; \ + U64 u64_val; \ S64 int_val; \ U64 uint_val; \ Intern_String intern_val; \ @@ -169,6 +177,7 @@ struct Ast_Call: Ast_Expr{ struct Ast_Unary: Ast_Expr{ Token_Kind op; Ast_Expr *expr; + U64 padding[3]; // For folding constants into atoms }; struct Ast_Cast: Ast_Expr{ diff --git a/new_parse.cpp b/new_parse.cpp index f23a49f..dd5b56a 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -551,6 +551,3 @@ parse_named(B32 is_global){ return result; } - - - diff --git a/new_types.kl b/new_types.kl index a95217f..dc5b981 100644 --- a/new_types.kl +++ b/new_types.kl @@ -1,14 +1,26 @@ +unary_test :: () + int_val :: 1251525 + float_val :: 124.42 + conversion: F64 = -+int_val + float2 := -float_val + unsigned: Int = -+-+-int_val + + // int_float: S64 = float_val + // string :: -"Thing" + // boolean :: -true + // var := -true + // var := +true + + basic_type_assignment :: () custom_data: Custom_Data some_constant :: true thing: Bool = some_constant float_val :: 325.42 float_var := float_val - int_val :: 1251525 - int_var: Int = int_val - conversion: F64 = +int_val - unsigned: Int = ++-int_val + + diff --git a/typecheck.cpp b/typecheck.cpp index 3901340..67b0328 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -1,6 +1,105 @@ #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define BREAK() } break + +#define CASE_CONVERT(pos, int_val, kind_val, new_val, TYPE, min, max) \ + case TYPE:{ \ + if(int_val > max) parsing_error(pos, "Overflow when converting from %s constant to %s, value out of range: %d, max is: %d", type_names[kind_val], type_names[TYPE], int_val, max); \ + if(int_val < min) parsing_error(pos, "Underflow when converting from %s constant to %s, value out of range: %d, min is: %d", type_names[kind_val], type_names[TYPE], int_val, min);\ + new_val = int_val;\ + }break; + +function Value +from_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ + assert(is_untyped(a.type)); + assert(new_type); + + if(is_int(a.type) && is_int(new_type)){ + assert(a.type == untyped_int); + switch(new_type->kind){ + CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_INT, TYPE_INT_MIN, TYPE_INT_MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_UINT, TYPE_UINT_MIN, TYPE_INT_MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.s8_val , TYPE_S8 , S8MIN, S8MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.s16_val, TYPE_S16, S16MIN, S16MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.s32_val, TYPE_S32, S32MIN, S32MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_S64, S64MIN, S64MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.u8_val , TYPE_U8 , U8MIN, U8MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.u16_val, TYPE_U16, U16MIN, U16MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.u32_val, TYPE_U32, U32MIN, U32MAX) + CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_U64, U64MIN, U64MAX) + invalid_default_case; + } + } + else if(is_int(a.type) && is_float(new_type)){ + assert(a.type == untyped_int); + switch(new_type->kind){ + case TYPE_F32: {a.f32_val = a.int_val;}break; + case TYPE_UNTYPED_FLOAT:{a.f64_val = a.int_val;}break; + case TYPE_F64: {a.f64_val = a.int_val;}break; + invalid_default_case; + } + } + else if(is_float(a.type) && is_float(new_type)){ + assert(a.type == untyped_float); + if(new_type == type_f32) a.f32_val = a.f64_val; + } + else if(is_bool(a.type) && is_bool(new_type)) + ; // nothing to do + else if(is_string(a.type) && is_string(new_type)) + ; // nothing to do + else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); + + a.type = new_type; + return a; +} + +function Value +eval_unary(Token *pos, Token_Kind op, Value v){ + switch(op){ + case TK_Sub:{ + switch(v.type->kind){ + case TYPE_UNTYPED_INT: v.int_val = -v.int_val;break; + case TYPE_UNTYPED_FLOAT: v.f64_val = -v.f64_val;break; + case TYPE_INT: v.int_val = -v.int_val;break; + case TYPE_S64: v.s64_val = -v.s64_val;break; // @todo Check bounds + case TYPE_S32: v.s32_val = -v.s32_val;break; + case TYPE_S16: v.s16_val = -v.s16_val;break; + case TYPE_S8: v.s8_val = -v.s8_val; break; + case TYPE_F32: v.f32_val = -v.f32_val;break; + case TYPE_F64: v.f64_val = -v.f64_val;break; + case TYPE_U64: + case TYPE_U32: + case TYPE_U16: + case TYPE_U8: + case TYPE_UINT: parsing_error(pos, "Application of unary [-] on type %s results in overflow", docname(v.type));break; + default: parsing_error(pos, "Constant application of unary [-] on type of %s is unsupported", docname(v.type));break; + } + }break; + case TK_Add:{ + switch(v.type->kind){ + case TYPE_UNTYPED_INT: v.int_val = +v.int_val;break; + case TYPE_UNTYPED_FLOAT: v.f64_val = +v.f64_val;break; + case TYPE_INT: v.int_val = +v.int_val;break; + case TYPE_S64: v.int_val = +v.int_val;break; // @todo Check bounds + case TYPE_S32: v.int_val = +v.int_val;break; + case TYPE_S16: v.int_val = +v.int_val;break; + case TYPE_S8: v.int_val = +v.int_val;break; + case TYPE_F32: v.f32_val = +v.f32_val;break; + case TYPE_F64: v.f64_val = +v.f64_val;break; + case TYPE_U64: v.u64_val = +v.u64_val;break; + case TYPE_U32: v.u32_val = +v.u32_val;break; + case TYPE_U16: v.u16_val = +v.u16_val;break; + case TYPE_U8: v.u8_val = +v.u8_val;break; + case TYPE_UINT: v.u64_val = +v.u64_val;break; + default: parsing_error(pos, "Constant application of unary [+] on type of %s is unsupported", docname(v.type));break; + } + }break; + default: invalid_codepath; + } + + return v; +} + function Ast_Resolved_Type * resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ if(ast_can_be_null && ast == 0) return 0; @@ -108,14 +207,21 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ return op; } +#define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s) function void -_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ +_rewrite_into_const(Ast *node, U64 ast_size, Value value){ auto ast = (Ast_Atom *)node; assert(ast_size >= sizeof(Ast_Atom)); + ast->flags = set_flag(ast->flags, AST_ATOM); ast->kind = AST_VALUE; - ast->value = sym->value; + ast->value = value; } -#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym) + +function void +_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ + _rewrite_into_const(node, ast_size, sym->value); +} + function Operand resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ @@ -373,28 +479,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Operand op = resolve_expr(node->expr); if(!is_numeric(op.type)) parsing_error(node->pos, "Unary [-] cant be applied to value of type %s", docname(op.type)); if(op.is_const){ - switch(op.type->kind){ - case TYPE_UNTYPED_INT: op.int_val = -op.int_val;break; - case TYPE_UNTYPED_FLOAT: op.f64_val = -op.f64_val;break; - case TYPE_INT: op.int_val = -op.int_val;break; - case TYPE_S64: op.int_val = -op.int_val;break; // @todo Check bounds - case TYPE_S32: op.int_val = -op.int_val;break; - case TYPE_S16: op.int_val = -op.int_val;break; - case TYPE_S8: op.int_val = -op.int_val;break; - case TYPE_F32: op.f32_val = -op.f32_val;break; - case TYPE_F64: op.f64_val = -op.f64_val;break; - case TYPE_U64: - case TYPE_U32: - case TYPE_U16: - case TYPE_U8: - case TYPE_UINT: parsing_error(node->pos, "Application of unary [-] on type %s results in overflow", docname(op.type));break; - default: parsing_error(node->pos, "Constant application of unary [-] on type of %s is unsupported", docname(op.type));break; - } - - auto atom = (Ast_Atom *)node; - atom->kind = AST_VALUE; - atom->flags |= AST_ATOM; - atom->value = op.value; + rewrite_into_const(node, Ast_Unary, eval_unary(node->pos, node->op, op.value)); } return op; }break; @@ -402,10 +487,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Operand op = resolve_expr(node->expr); if(!is_numeric(op.type)) parsing_error(node->pos, "Unary [+] cant be applied to value of type %s", docname(op.type)); if(op.is_const){ - auto atom = (Ast_Atom *)node; - atom->kind = AST_VALUE; - atom->flags |= AST_ATOM; - atom->value = op.value; + rewrite_into_const(node, Ast_Unary, eval_unary(node->pos, node->op, op.value)); } return op; }break; @@ -612,12 +694,6 @@ resolve_const(Ast_Expr *ast, Sym *sym){ } } -#define CASE_OVERFLOW(pos, int_val, kind_val, TYPE, min, max) \ - case TYPE:{ \ - if(int_val > max) parsing_error(pos, "Overflow when converting from %s constant to %s, value out of range: %d, max is: %d", type_names[kind_val], type_names[TYPE], int_val, max); \ - if(int_val < min) parsing_error(pos, "Underflow when converting from %s constant to %s, value out of range: %d, min is: %d", type_names[kind_val], type_names[TYPE], int_val, min);\ - }break; - function Operand resolve_binding(Ast *ast, Sym *sym){ switch(ast->kind){ @@ -629,37 +705,7 @@ resolve_binding(Ast *ast, Sym *sym){ else if(!expr.type) expr.type = type; else if(type == expr.type); else if(is_untyped(expr.type)){ - Ast_Resolved_Type *untyped = expr.type; - if(is_int(type) && is_int(untyped)){ - switch(type->kind){ - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_INT, TYPE_INT_MIN, TYPE_INT_MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_UINT, TYPE_UINT_MIN, TYPE_INT_MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_S8 , S8MIN, S8MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_S16, S16MIN, S16MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_S32, S32MIN, S32MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_S64, S64MIN, S64MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_U8 , U8MIN, U8MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_U16, U16MIN, U16MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_U32, U32MIN, U32MAX) - CASE_OVERFLOW(node->pos, expr.int_val, untyped->kind, TYPE_U64, U64MIN, U64MAX) - invalid_default_case; - } - } - else if(is_float(type) && is_int(untyped)){ - switch(type->kind){ - case TYPE_F32:{expr.f32_val = expr.int_val;}break; - case TYPE_F64:{expr.f64_val = expr.int_val;}break; - invalid_default_case; - } - } - else if(is_float(type) && is_float(untyped)){ - if(type == type_f32) expr.f32_val = expr.f64_val; - } - else if(is_bool(type) && is_bool(untyped)); - else if(is_string(type) && is_string(untyped)); - else parsing_error(node->pos, "Type mismatch when converting from %s to %s", type_names[untyped->kind], type_names[type->kind]); - - expr.type = type; + expr.value = from_untyped_to_typed(node->pos, expr.value, type); } type_complete(expr.type);