This commit is contained in:
Krzosa Karol
2022-06-03 12:07:17 +02:00
parent 71d0abf122
commit 7e4b9777e6
5 changed files with 138 additions and 74 deletions

View File

@@ -46,7 +46,7 @@ For now I don't thing it should be overloadable.
[ ] - Add single line lambda expressions [ ] - Add single line lambda expressions
[ ] - Ternary operator [ ] - Ternary operator
[ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix [ ] - 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 [ ] - Order independent constants in structs
[ ] - Can you even have recursive lambdas in structs, other recursive stuff [ ] - Can you even have recursive lambdas in structs, other recursive stuff
[ ] - Casting to basic types by call S64(x) [ ] - Casting to basic types by call S64(x)

View File

@@ -142,6 +142,14 @@ union{ \
bool bool_val; \ bool bool_val; \
F64 f64_val; \ F64 f64_val; \
F32 f32_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; \ S64 int_val; \
U64 uint_val; \ U64 uint_val; \
Intern_String intern_val; \ Intern_String intern_val; \
@@ -169,6 +177,7 @@ struct Ast_Call: Ast_Expr{
struct Ast_Unary: Ast_Expr{ struct Ast_Unary: Ast_Expr{
Token_Kind op; Token_Kind op;
Ast_Expr *expr; Ast_Expr *expr;
U64 padding[3]; // For folding constants into atoms
}; };
struct Ast_Cast: Ast_Expr{ struct Ast_Cast: Ast_Expr{

View File

@@ -551,6 +551,3 @@ parse_named(B32 is_global){
return result; return result;
} }

View File

@@ -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 :: () basic_type_assignment :: ()
custom_data: Custom_Data custom_data: Custom_Data
some_constant :: true some_constant :: true
thing: Bool = some_constant thing: Bool = some_constant
float_val :: 325.42 float_val :: 325.42
float_var := float_val float_var := float_val
int_val :: 1251525
int_var: Int = int_val
conversion: F64 = +int_val
unsigned: Int = ++-int_val

View File

@@ -1,6 +1,105 @@
#define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
#define BREAK() } break #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 * function Ast_Resolved_Type *
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
if(ast_can_be_null && ast == 0) return 0; 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; return op;
} }
#define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s)
function void 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; auto ast = (Ast_Atom *)node;
assert(ast_size >= sizeof(Ast_Atom)); assert(ast_size >= sizeof(Ast_Atom));
ast->flags = set_flag(ast->flags, AST_ATOM);
ast->kind = AST_VALUE; 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 function Operand
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ 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); 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(!is_numeric(op.type)) parsing_error(node->pos, "Unary [-] cant be applied to value of type %s", docname(op.type));
if(op.is_const){ if(op.is_const){
switch(op.type->kind){ rewrite_into_const(node, Ast_Unary, eval_unary(node->pos, node->op, op.value));
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;
} }
return op; return op;
}break; }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); 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(!is_numeric(op.type)) parsing_error(node->pos, "Unary [+] cant be applied to value of type %s", docname(op.type));
if(op.is_const){ if(op.is_const){
auto atom = (Ast_Atom *)node; rewrite_into_const(node, Ast_Unary, eval_unary(node->pos, node->op, op.value));
atom->kind = AST_VALUE;
atom->flags |= AST_ATOM;
atom->value = op.value;
} }
return op; return op;
}break; }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 function Operand
resolve_binding(Ast *ast, Sym *sym){ resolve_binding(Ast *ast, Sym *sym){
switch(ast->kind){ switch(ast->kind){
@@ -629,37 +705,7 @@ resolve_binding(Ast *ast, Sym *sym){
else if(!expr.type) expr.type = type; else if(!expr.type) expr.type = type;
else if(type == expr.type); else if(type == expr.type);
else if(is_untyped(expr.type)){ else if(is_untyped(expr.type)){
Ast_Resolved_Type *untyped = expr.type; expr.value = from_untyped_to_typed(node->pos, expr.value, 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;
} }
type_complete(expr.type); type_complete(expr.type);