Working on casts
This commit is contained in:
@@ -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);
|
||||
|
||||
46
ccodegen.cpp
46
ccodegen.cpp
@@ -292,7 +292,25 @@ gen_ast(Ast *ast){
|
||||
CASE(CONST, Const){
|
||||
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){
|
||||
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
||||
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
|
||||
@@ -317,24 +335,9 @@ gen_ast(Ast *ast){
|
||||
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){
|
||||
}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){
|
||||
@@ -382,9 +385,8 @@ gen_ast(Ast *ast){
|
||||
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();
|
||||
|
||||
2
main.cpp
2
main.cpp
@@ -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
|
||||
|
||||
@@ -87,8 +87,6 @@ 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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
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_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]",
|
||||
|
||||
Reference in New Issue
Block a user