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.
struct Token;
global S64 bigint_allocation_count;
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 FATAL_ERROR(x) parsing_error(0, x)
@@ -18,7 +19,6 @@ struct BigInt
};
};
#include <inttypes.h>
enum CmpRes
{
@@ -74,14 +74,14 @@ size_t bigint_popcount_unsigned(const BigInt *big_int);
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static BigInt
function BigInt
bigint_u64(U64 value){
BigInt result;
bigint_init_unsigned(&result, value);
return result;
}
static BigInt
function BigInt
bigint_s64(S64 value){
BigInt result;
bigint_init_signed(&result, value);

View File

@@ -292,99 +292,101 @@ gen_ast(Ast *ast){
CASE(CONST, Const){
Sym *sym = resolved_get(node);
if(sym->type->kind == TYPE_LAMBDA){
if(node->value->kind == AST_LAMBDA){
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
gen_simple_decl(ret, node->name);
gen("(");
For(lambda->args){
assert(it->kind == AST_LAMBDA_ARG);
Ast_Resolved_Type *type = resolved_type_get(it->typespec);
gen_simple_decl(type, it->name);
if(&it != (lambda->args.end() - 1)) gen(", ");
}
gen(")");
switch(sym->type->kind){
CASE_FLOAT:{
gen("// F64 %s = ", node->name.str);
gen_value(sym->value);
} break;
CASE_INT:{
gen("// constant int %s = ", node->name.str);
gen_value(sym->value);
}break;
CASE_STRING:{
gen("// const String %s = ", node->name.str);
gen_value(sym->value);
}break;
CASE_BOOL:{
gen("// const Bool %s = ", node->name.str);
gen_value(sym->value);
}break;
if(lambda->block) {
gen_block(lambda->block);
}
else gen(";");
}
else{
gen_simple_decl(sym->type, node->name);
gen(" = ");
gen_expr((Ast_Expr *)node->value);
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);
case TYPE_LAMBDA:{
if(node->value->kind == AST_LAMBDA){
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
gen_simple_decl(ret, node->name);
gen("(");
For(lambda->args){
assert(it->kind == AST_LAMBDA_ARG);
Ast_Resolved_Type *type = resolved_type_get(it->typespec);
gen_simple_decl(type, it->name);
if(&it != (lambda->args.end() - 1)) gen(", ");
}
gen(")");
For(agg->const_members){
genln("");
gen_ast(it);
if(lambda->block) {
gen_block(lambda->block);
}
global_indent--;
genln("};");
else gen(";");
}
else{
// Type alias
gen_simple_decl(sym->type, node->name);
gen(" = ");
gen_expr((Ast_Expr *)node->value);
gen(";");
}
}
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(",");
}break;
case 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);
}
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{
// Type alias
gen("// typedef ");
gen_simple_decl(sym->type_val, node->name);
gen(";");
}
}
else{
gen("// typedef ");
gen_simple_decl(sym->type_val, node->name);
gen(";");
}
}
else{
parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression");
}break;
default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
}
BREAK();

View File

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

View File

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

View File

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

View File

@@ -71,21 +71,25 @@ value_float(BigInt a){
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
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
assert(new_type);
if(a.type == 0) 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);
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))
a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint
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));
a.type = new_type;
check_value_boundaries(pos, &a);
return a;
}
function void
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))
*a = value_float(a->big_int_val);
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){
Operand expr = resolve_expr(node->expr);
Ast_Resolved_Type *type = resolve_typespec(node->typespec);
unused(expr);
// @todo
return operand_rvalue(type);
Ast_Resolved_Type *original_type = expr.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();
}

View File

@@ -46,6 +46,7 @@ enum Ast_Resolved_Type_Kind{
#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_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[] = {
"[Invalid Ast_Resolved_Type]",