More work on types
This commit is contained in:
10
main.cpp
10
main.cpp
@@ -32,10 +32,10 @@ For now I don't thing it should be overloadable.
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@todo
|
@todo
|
||||||
[ ] - Test new operators, add constant eval for them
|
[ ] - in new typesystem: Fix calls, fix other example programs
|
||||||
[ ] - Compiling and running a program
|
[ ] - Compiling and running a program
|
||||||
[ ] - Passing down program to compile through command line
|
[ ] - Passing down program to compile through command line
|
||||||
[ ] - More operators
|
[ ] - Operators: Bit negation, Not
|
||||||
[ ] - More for loop variations
|
[ ] - More for loop variations
|
||||||
[ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree
|
[ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree
|
||||||
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
||||||
@@ -58,6 +58,7 @@ For now I don't thing it should be overloadable.
|
|||||||
[ ] - Rust like enum where you associate values(other structs) with keys
|
[ ] - Rust like enum where you associate values(other structs) with keys
|
||||||
|
|
||||||
@donzo
|
@donzo
|
||||||
|
[x] - Test new operators, add constant eval for them
|
||||||
[x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
[x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
||||||
[x] - Add basic support for floats
|
[x] - Add basic support for floats
|
||||||
[x] - Add basic setup for new type system
|
[x] - Add basic setup for new type system
|
||||||
@@ -65,6 +66,7 @@ For now I don't thing it should be overloadable.
|
|||||||
[x] - Enums
|
[x] - Enums
|
||||||
[x] - Initial for loop
|
[x] - Initial for loop
|
||||||
[x] - Enum . access to values
|
[x] - Enum . access to values
|
||||||
|
[x] - Fix arithmetic operations in new type system
|
||||||
[x] - Init statements, different kinds [+=] [-=] etc.
|
[x] - Init statements, different kinds [+=] [-=] etc.
|
||||||
[x] - Struct calls
|
[x] - Struct calls
|
||||||
[x] - Default values in calls
|
[x] - Default values in calls
|
||||||
@@ -111,8 +113,8 @@ int main(){
|
|||||||
// printf("%s", result.str);
|
// printf("%s", result.str);
|
||||||
// result = compile_file("lambdas.kl"_s);
|
// result = compile_file("lambdas.kl"_s);
|
||||||
// printf("%s", result.str);
|
// printf("%s", result.str);
|
||||||
// result = compile_file("order2.kl"_s);
|
result = compile_file("order2.kl"_s);
|
||||||
// printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
result = compile_file("new_types.kl"_s);
|
result = compile_file("new_types.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Arena :: struct
|
|||||||
// arena: Arena
|
// arena: Arena
|
||||||
next: *Arena
|
next: *Arena
|
||||||
data: *Int
|
data: *Int
|
||||||
len : Int
|
len : S64
|
||||||
cap : Int
|
cap : Int
|
||||||
|
|
||||||
Sub :: struct
|
Sub :: struct
|
||||||
@@ -26,7 +26,7 @@ Arena :: struct
|
|||||||
Sub_Sub :: struct
|
Sub_Sub :: struct
|
||||||
len: Int
|
len: Int
|
||||||
|
|
||||||
get_len :: (s: *Arena): Int // @todo
|
get_len :: (s: *Arena): S64 // @todo
|
||||||
return s.next.len
|
return s.next.len
|
||||||
|
|
||||||
constant_inside :: 10000
|
constant_inside :: 10000
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#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
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Evaluating constant expressions
|
// Evaluating constant expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -33,6 +34,7 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
|||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(is_int(a.type) && is_float(new_type)){
|
else if(is_int(a.type) && is_float(new_type)){
|
||||||
assert(a.type == untyped_int);
|
assert(a.type == untyped_int);
|
||||||
switch(new_type->kind){
|
switch(new_type->kind){
|
||||||
@@ -92,7 +94,7 @@ value_get_float(Value value){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h> // fmod
|
||||||
function Value
|
function Value
|
||||||
eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
||||||
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", token_kind_string(op).str, docname(a.type), docname(a.type));
|
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", token_kind_string(op).str, docname(a.type), docname(a.type));
|
||||||
@@ -142,55 +144,56 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
|||||||
S64 right_int = value_get_int(b);
|
S64 right_int = value_get_int(b);
|
||||||
F64 left_float = value_get_float(a);
|
F64 left_float = value_get_float(a);
|
||||||
F64 right_float = value_get_float(b);
|
F64 right_float = value_get_float(b);
|
||||||
// @WARNING: When introducing big ints & | ^ will be problematic
|
|
||||||
|
|
||||||
Value c;
|
assert(before_conversion.type == untyped_float || before_conversion.type == untyped_int);
|
||||||
c.type = untyped_bool;
|
// @note: for returning early with bools
|
||||||
|
Value c; c.type = untyped_bool;
|
||||||
switch(op){
|
switch(op){
|
||||||
|
|
||||||
// @note: These return early, they don't need type evaluation
|
// @note: These return early, they don't need type evaluation
|
||||||
// always should return untyped bool
|
// always should return untyped bool
|
||||||
case TK_And: {
|
case TK_And: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int && right_int;
|
if(final_type == untyped_int) c.bool_val = left_int && right_int;
|
||||||
else c.bool_val = left_float && right_float;
|
else c.bool_val = left_float && right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_Or: {
|
case TK_Or: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int || right_int;
|
if(final_type == untyped_int) c.bool_val = left_int || right_int;
|
||||||
else c.bool_val = left_float || right_float;
|
else c.bool_val = left_float || right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_GreaterThen: {
|
case TK_GreaterThen: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int > right_int;
|
if(final_type == untyped_int) c.bool_val = left_int > right_int;
|
||||||
else c.bool_val = left_float > right_float;
|
else c.bool_val = left_float > right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_GreaterThenOrEqual: {
|
case TK_GreaterThenOrEqual: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int >= right_int;
|
if(final_type == untyped_int) c.bool_val = left_int >= right_int;
|
||||||
else c.bool_val = left_float >= right_float;
|
else c.bool_val = left_float >= right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_LesserThen: {
|
case TK_LesserThen: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int < right_int;
|
if(final_type == untyped_int) c.bool_val = left_int < right_int;
|
||||||
else c.bool_val = left_float < right_float;
|
else c.bool_val = left_float < right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_LesserThenOrEqual: {
|
case TK_LesserThenOrEqual: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int <= right_int;
|
if(final_type == untyped_int) c.bool_val = left_int <= right_int;
|
||||||
else c.bool_val = left_float <= right_float;
|
else c.bool_val = left_float <= right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_Equals: {
|
case TK_Equals: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int == right_int;
|
if(final_type == untyped_int) c.bool_val = left_int == right_int;
|
||||||
else c.bool_val = left_float == right_float;
|
else c.bool_val = left_float == right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
case TK_NotEquals: {
|
case TK_NotEquals: {
|
||||||
if(final_type == untyped_int) c.bool_val = left_int != right_int;
|
if(final_type == untyped_int) c.bool_val = left_int != right_int;
|
||||||
else c.bool_val = left_float != right_float;
|
else c.bool_val = left_float != right_float;
|
||||||
return c;
|
return c;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
// @note: These return at the end cause need type evaluation
|
||||||
case TK_Add: {
|
case TK_Add: {
|
||||||
left_int = left_int + right_int;
|
left_int = left_int + right_int;
|
||||||
left_float = left_float + right_float;
|
left_float = left_float + right_float;
|
||||||
@@ -211,6 +214,8 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
|||||||
left_int = left_int % right_int;
|
left_int = left_int % right_int;
|
||||||
left_float = fmod(left_float, right_float);
|
left_float = fmod(left_float, right_float);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
// @WARNING: When introducing big ints & | ^ will be problematic
|
||||||
case TK_BitAnd: {
|
case TK_BitAnd: {
|
||||||
left_int = left_int & right_int;
|
left_int = left_int & right_int;
|
||||||
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
|
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
|
||||||
@@ -223,6 +228,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
|||||||
left_int = left_int ^ right_int;
|
left_int = left_int ^ right_int;
|
||||||
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
|
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: parsing_error(pos, "Binary operation %s is not allowed on types: left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type));
|
default: parsing_error(pos, "Binary operation %s is not allowed on types: left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,6 +243,18 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
try_untyping(Operand *op){
|
||||||
|
if(!op) return;
|
||||||
|
if(is_untyped(op->type)){
|
||||||
|
if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_int;
|
||||||
|
else if(op->type->kind == TYPE_UNTYPED_BOOL) op->type = type_bool;
|
||||||
|
else if(op->type->kind == TYPE_UNTYPED_STRING) op->type = type_string;
|
||||||
|
else if(op->type->kind == TYPE_UNTYPED_FLOAT) op->type = type_f64;
|
||||||
|
else invalid_codepath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Value
|
function Value
|
||||||
eval_unary(Token *pos, Token_Kind op, Value a){
|
eval_unary(Token *pos, Token_Kind op, Value a){
|
||||||
if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type));
|
if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type));
|
||||||
@@ -556,7 +574,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
|
|
||||||
found->flags = set_flag(found->flags, AST_ITEM_INCLUDED);
|
found->flags = set_flag(found->flags, AST_ITEM_INCLUDED);
|
||||||
Operand op = resolve_expr(expr->item, found_type->type);
|
Operand op = resolve_expr(expr->item, found_type->type);
|
||||||
if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[op.type->kind], type_names[found_type->type->kind]);
|
try_untyping(&op);
|
||||||
|
if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note: cleanup, required?
|
// @note: cleanup, required?
|
||||||
@@ -601,7 +620,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(arg->default_value){
|
if(arg->default_value){
|
||||||
// @todo make sure default values have valid types but in lambda definition
|
|
||||||
Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value);
|
Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value);
|
||||||
items.add(item_default);
|
items.add(item_default);
|
||||||
}
|
}
|
||||||
@@ -683,6 +701,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
assert(node->left->kind == AST_IDENT);
|
assert(node->left->kind == AST_IDENT);
|
||||||
|
|
||||||
Operand right = resolve_expr(node->right);
|
Operand right = resolve_expr(node->right);
|
||||||
|
try_untyping(&right);
|
||||||
|
|
||||||
Ast_Atom *atom = (Ast_Atom *)node->left;
|
Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||||
sym_var(atom->intern_val, right, node, INSERT_INTO_SCOPE);
|
sym_var(atom->intern_val, right, node, INSERT_INTO_SCOPE);
|
||||||
}
|
}
|
||||||
@@ -694,7 +714,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
Operand left = resolve_expr(node->left);
|
Operand left = resolve_expr(node->left);
|
||||||
if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue");
|
if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue");
|
||||||
Operand right = resolve_expr(node->right);
|
Operand right = resolve_expr(node->right);
|
||||||
if(left.type != right.type) parsing_error(node->pos, "Different types");
|
try_untyping(&right);
|
||||||
|
if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type));
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -787,12 +808,15 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
rewrite_into_const(node, Ast_Binary, value);
|
rewrite_into_const(node, Ast_Binary, value);
|
||||||
result = operand_const_rvalue(value);
|
result = operand_const_rvalue(value);
|
||||||
}
|
}
|
||||||
else if(left.type != right.type){
|
|
||||||
parsing_error(node->pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(node->op).str, docname(left.type), docname(right.type));
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
result = operand_rvalue(left.type);
|
if(left.type != right.type){
|
||||||
|
parsing_error(node->pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(node->op).str, docname(left.type), docname(right.type));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = operand_rvalue(left.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -855,7 +879,8 @@ resolve_binding(Ast *ast, Sym *sym){
|
|||||||
Operand expr = resolve_expr(node->expr, type);
|
Operand expr = resolve_expr(node->expr, type);
|
||||||
assert(expr.type != 0 || type != 0);
|
assert(expr.type != 0 || type != 0);
|
||||||
|
|
||||||
if(!type) expr.type = if_untyped_get_default_conversion(expr.type);
|
|
||||||
|
if(!type) try_untyping(&expr);
|
||||||
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)) expr.value = convert_untyped(node->pos, expr.value, type);
|
else if(is_untyped(expr.type)) expr.value = convert_untyped(node->pos, expr.value, type);
|
||||||
|
|||||||
12
types.h
12
types.h
@@ -251,15 +251,3 @@ is_numeric(Ast_Resolved_Type *type){
|
|||||||
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
|
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
|
||||||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
|
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
|
||||||
if_untyped_get_default_conversion(Ast_Resolved_Type *type){
|
|
||||||
if(is_untyped(type)){
|
|
||||||
if(type->kind == TYPE_UNTYPED_INT) return type_int;
|
|
||||||
else if(type->kind == TYPE_UNTYPED_BOOL) return type_bool;
|
|
||||||
else if(type->kind == TYPE_UNTYPED_STRING) return type_string;
|
|
||||||
else if(type->kind == TYPE_UNTYPED_FLOAT) return type_f64;
|
|
||||||
invalid_return;
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user