Cleanup
This commit is contained in:
2
main.cpp
2
main.cpp
@@ -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)
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -551,6 +551,3 @@ parse_named(B32 is_global){
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
new_types.kl
20
new_types.kl
@@ -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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
178
typecheck.cpp
178
typecheck.cpp
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user