Working on casts
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
46
ccodegen.cpp
46
ccodegen.cpp
@@ -292,7 +292,25 @@ 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){
|
||||||
|
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;
|
||||||
|
|
||||||
|
case TYPE_LAMBDA:{
|
||||||
if(node->value->kind == AST_LAMBDA){
|
if(node->value->kind == AST_LAMBDA){
|
||||||
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
||||||
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
|
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
|
||||||
@@ -317,24 +335,9 @@ gen_ast(Ast *ast){
|
|||||||
gen_expr((Ast_Expr *)node->value);
|
gen_expr((Ast_Expr *)node->value);
|
||||||
gen(";");
|
gen(";");
|
||||||
}
|
}
|
||||||
}
|
}break;
|
||||||
else if(sym->type == untyped_float){
|
|
||||||
gen("// F64 %s = ", node->name.str);
|
case TYPE_TYPE:{
|
||||||
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){
|
if(sym->type_val->kind == TYPE_STRUCT){
|
||||||
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
|
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
|
||||||
if(node->value->kind == AST_STRUCT){
|
if(node->value->kind == AST_STRUCT){
|
||||||
@@ -382,9 +385,8 @@ gen_ast(Ast *ast){
|
|||||||
gen_simple_decl(sym->type_val, node->name);
|
gen_simple_decl(sym->type_val, node->name);
|
||||||
gen(";");
|
gen(";");
|
||||||
}
|
}
|
||||||
}
|
}break;
|
||||||
else{
|
default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
|
||||||
parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BREAK();
|
BREAK();
|
||||||
|
|||||||
2
main.cpp
2
main.cpp
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
types.h
1
types.h
@@ -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]",
|
||||||
|
|||||||
Reference in New Issue
Block a user