Working on casts

This commit is contained in:
Krzosa Karol
2022-06-06 13:24:01 +02:00
parent 4f876a36a4
commit 06d6ec7525
8 changed files with 145 additions and 100 deletions

View File

@@ -3,8 +3,9 @@
// a copy of which can be found in the LICENSE file. // a copy of which can be found in the LICENSE file.
struct Token; struct Token;
global S64 bigint_allocation_count;
function void parsing_error(Token *token, const char *str, ...); function void parsing_error(Token *token, const char *str, ...);
#define malloc_arena(x) exp_alloc(&pernament_arena, x) #define malloc_arena(x) (bigint_allocation_count++, exp_alloc(&pernament_arena, x))
#define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL) #define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL)
#define FATAL_ERROR(x) parsing_error(0, x) #define FATAL_ERROR(x) parsing_error(0, x)
@@ -18,7 +19,6 @@ struct BigInt
}; };
}; };
#include <inttypes.h> #include <inttypes.h>
enum CmpRes enum CmpRes
{ {
@@ -74,14 +74,14 @@ size_t bigint_popcount_unsigned(const BigInt *big_int);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static BigInt function BigInt
bigint_u64(U64 value){ bigint_u64(U64 value){
BigInt result; BigInt result;
bigint_init_unsigned(&result, value); bigint_init_unsigned(&result, value);
return result; return result;
} }
static BigInt function BigInt
bigint_s64(S64 value){ bigint_s64(S64 value){
BigInt result; BigInt result;
bigint_init_signed(&result, value); bigint_init_signed(&result, value);

View File

@@ -292,99 +292,101 @@ gen_ast(Ast *ast){
CASE(CONST, Const){ CASE(CONST, Const){
Sym *sym = resolved_get(node); Sym *sym = resolved_get(node);
if(sym->type->kind == TYPE_LAMBDA){ switch(sym->type->kind){
if(node->value->kind == AST_LAMBDA){ CASE_FLOAT:{
Ast_Lambda *lambda = (Ast_Lambda *)node->value; gen("// F64 %s = ", node->name.str);
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); gen_value(sym->value);
gen_simple_decl(ret, node->name); } break;
gen("("); CASE_INT:{
For(lambda->args){ gen("// constant int %s = ", node->name.str);
assert(it->kind == AST_LAMBDA_ARG); gen_value(sym->value);
Ast_Resolved_Type *type = resolved_type_get(it->typespec); }break;
gen_simple_decl(type, it->name); CASE_STRING:{
if(&it != (lambda->args.end() - 1)) gen(", "); gen("// const String %s = ", node->name.str);
} gen_value(sym->value);
gen(")"); }break;
CASE_BOOL:{
gen("// const Bool %s = ", node->name.str);
gen_value(sym->value);
}break;
if(lambda->block) { case TYPE_LAMBDA:{
gen_block(lambda->block); if(node->value->kind == AST_LAMBDA){
} Ast_Lambda *lambda = (Ast_Lambda *)node->value;
else gen(";"); Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
} gen_simple_decl(ret, node->name);
else{ gen("(");
gen_simple_decl(sym->type, node->name); For(lambda->args){
gen(" = "); assert(it->kind == AST_LAMBDA_ARG);
gen_expr((Ast_Expr *)node->value); Ast_Resolved_Type *type = resolved_type_get(it->typespec);
gen(";"); gen_simple_decl(type, it->name);
} if(&it != (lambda->args.end() - 1)) gen(", ");
}
else if(sym->type == untyped_float){
gen("// F64 %s = ", node->name.str);
gen_value(sym->value);
}
else if(sym->type == untyped_int){
gen("// constant int %s = ", node->name.str);
gen_value(sym->value);
}
else if(sym->type == untyped_string){
gen("// const String %s = ", node->name.str);
gen_value(sym->value);
}
else if(sym->type == untyped_bool){
gen("// const Bool %s = ", node->name.str);
gen_value(sym->value);
}
else if(sym->type == type_type){
if(sym->type_val->kind == TYPE_STRUCT){
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
if(node->value->kind == AST_STRUCT){
gen("struct %s{", node->name.str);
global_indent++;
For(agg->members){
genln("");
gen_ast(it);
} }
gen(")");
For(agg->const_members){ if(lambda->block) {
genln(""); gen_block(lambda->block);
gen_ast(it);
} }
global_indent--; else gen(";");
genln("};");
} }
else{ else{
// Type alias gen_simple_decl(sym->type, node->name);
gen(" = ");
gen_expr((Ast_Expr *)node->value);
gen(";");
} }
} }break;
else if(sym->type_val->kind == TYPE_ENUM){
Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; case TYPE_TYPE:{
assert(enu->kind == AST_ENUM); if(sym->type_val->kind == TYPE_STRUCT){
if(node->value->kind == AST_ENUM){ Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
gen("/*enum %s{", node->name.str); if(node->value->kind == AST_STRUCT){
// @todo add typespec gen("struct %s{", node->name.str);
global_indent++; global_indent++;
For(enu->members){ For(agg->members){
genln("%s", it->name.str); genln("");
gen(" = "); gen_ast(it);
Sym *value_sym = resolved_get(it); }
gen("%d", bigint_as_signed(&value_sym->big_int_val));
gen(","); For(agg->const_members){
genln("");
gen_ast(it);
}
global_indent--;
genln("};");
}
else{
// Type alias
}
}
else if(sym->type_val->kind == TYPE_ENUM){
Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast;
assert(enu->kind == AST_ENUM);
if(node->value->kind == AST_ENUM){
gen("/*enum %s{", node->name.str);
// @todo add typespec
global_indent++;
For(enu->members){
genln("%s", it->name.str);
gen(" = ");
Sym *value_sym = resolved_get(it);
gen("%d", bigint_as_signed(&value_sym->big_int_val));
gen(",");
}
global_indent--;
genln("};*/");
}
else{
// Type alias
} }
global_indent--;
genln("};*/");
} }
else{ else{
// Type alias gen("// typedef ");
gen_simple_decl(sym->type_val, node->name);
gen(";");
} }
} }break;
else{ default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
gen("// typedef ");
gen_simple_decl(sym->type_val, node->name);
gen(";");
}
}
else{
parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression");
} }
BREAK(); BREAK();

View File

@@ -32,6 +32,7 @@ For now I don't thing it should be overloadable.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@todo @todo
[ ] - Fix casting
[ ] - Passing down program to compile through command line [ ] - Passing down program to compile through command line
[ ] - More for loop variations [ ] - More for loop variations
[ ] - Write up on order independent declarations [ ] - Write up on order independent declarations
@@ -43,6 +44,7 @@ For now I don't thing it should be overloadable.
[ ] - Ternary operator [ ] - Ternary operator
[ ] - Remodel compound from call to {} [ ] - Remodel compound from call to {}
[ ] - Scope
[ ] - Field access rewrite [ ] - Field access rewrite
[ ] - 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
[ ] - Order independent constants in structs [ ] - Order independent constants in structs

View File

@@ -87,8 +87,6 @@ enum Token_Kind{
TK_Pointer = TK_Mul, TK_Pointer = TK_Mul,
TK_Dereference = TK_BitAnd, TK_Dereference = TK_BitAnd,
// These are not produced by lexer
// but identified by parser
OPEN_SCOPE = 128, OPEN_SCOPE = 128,
CLOSE_SCOPE, CLOSE_SCOPE,
SAME_SCOPE, SAME_SCOPE,

View File

@@ -33,6 +33,8 @@ binary_test :: ()
boolean_equals :: true == false boolean_equals :: true == false
boolean_var: Bool = boolean_equals boolean_var: Bool = boolean_equals
cast_value :: cast(4242: S32)
bvar2 := int_val > 1 bvar2 := int_val > 1
if int_val < 1 if int_val < 1
if int_val > 1 if int_val > 1

View File

@@ -71,21 +71,25 @@ value_float(BigInt a){
return value; return value;
} }
function void
check_value_boundaries(Token *pos, Value *a){
if(!is_int(a->type)) return;
Scratch scratch;
if(!bigint_fits_in_bits(&a->big_int_val, a->type->size*8, is_signed_int(a->type))){
const char *string = bigint_to_error_string(scratch, &a->big_int_val, 10);
parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type));
}
}
function Value function Value
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
assert(new_type); assert(new_type);
if(a.type == 0) return a; if(a.type == 0) return a;
if(is_typed(a.type)) return a; if(is_typed(a.type)) return a;
if(is_int(a.type) && is_int(new_type)){ if(is_int(a.type) && is_int(new_type))
assert(a.type == untyped_int); assert(a.type == untyped_int);
if(!bigint_fits_in_bits(&a.big_int_val, new_type->size*8, is_signed_int(new_type))){
Scratch scratch;
const char *string = bigint_to_error_string(scratch, &a.big_int_val, 10);
parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(new_type));
}
}
else if(is_int(a.type) && is_float(new_type)) else if(is_int(a.type) && is_float(new_type))
a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint
else if(is_float(a.type) && is_float(new_type)) else if(is_float(a.type) && is_float(new_type))
@@ -97,11 +101,15 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type));
a.type = new_type; a.type = new_type;
check_value_boundaries(pos, &a);
return a; return a;
} }
function void function void
match_values(Value *a, Value *b){ match_values(Value *a, Value *b){
// @todo: We want match values to convert when int and float => float
// but also we want to unify types when one of them is typed and other untyped???
// Lastly maybe check if typed types are the same
if(is_int(a->type) && is_float(b->type)) if(is_int(a->type) && is_float(b->type))
*a = value_float(a->big_int_val); *a = value_float(a->big_int_val);
else if(is_float(a->type) && is_int(b->type)) else if(is_float(a->type) && is_int(b->type))
@@ -630,9 +638,41 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
CASE(CAST, Cast){ CASE(CAST, Cast){
Operand expr = resolve_expr(node->expr); Operand expr = resolve_expr(node->expr);
Ast_Resolved_Type *type = resolve_typespec(node->typespec); Ast_Resolved_Type *type = resolve_typespec(node->typespec);
unused(expr); Ast_Resolved_Type *original_type = expr.type;
// @todo
return operand_rvalue(type); switch(expr.type->kind){
case TYPE_POINTER:{
if(is_pointer(type))
expr = operand_rvalue(type);
else goto failure;
} break;
CASE_UNTYPED: {
expr.value = convert_untyped(node->pos, expr.value, type);
} break;
CASE_UINT:
CASE_SINT:{
if(is_int(type))
expr.type = type;
else if(is_float(type)){
expr.value.type = type;
expr.value.f64_val = bigint_as_float(&expr.big_int_val); // @leak
} else goto failure;
} break;
case TYPE_F32: case TYPE_F64: {
if(is_float(type)){
expr.type = type;
}
else if(is_int(type)){
expr.value.big_int_val = bigint_s64((S64)expr.value.f64_val); // @todo: What to do here???
expr.type = type;
} else goto failure;
}
default: failure: parsing_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));;
}
if(original_type != type) assert(expr.type == type);
check_value_boundaries(node->pos, &expr.value);
return expr;
BREAK(); BREAK();
} }

View File

@@ -46,6 +46,7 @@ enum Ast_Resolved_Type_Kind{
#define CASE_BOOL case TYPE_UNTYPED_BOOL: case TYPE_BOOL #define CASE_BOOL case TYPE_UNTYPED_BOOL: case TYPE_BOOL
#define CASE_FLOAT case TYPE_UNTYPED_FLOAT: case TYPE_F32: case TYPE_F64 #define CASE_FLOAT case TYPE_UNTYPED_FLOAT: case TYPE_F32: case TYPE_F64
#define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING #define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING
#define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING
const char *type_names[] = { const char *type_names[] = {
"[Invalid Ast_Resolved_Type]", "[Invalid Ast_Resolved_Type]",