Got all programs working, now adding unary not and neg
This commit is contained in:
@@ -405,10 +405,7 @@ compile_string(String filecontent, String filename = "default_name"_s){
|
|||||||
|
|
||||||
|
|
||||||
gen(R"==(
|
gen(R"==(
|
||||||
//-------------------------------
|
// Generated
|
||||||
#define NULL_POINTER 0
|
|
||||||
#define NULL_LAMBDA 0
|
|
||||||
//-------------------------------
|
|
||||||
)==");
|
)==");
|
||||||
|
|
||||||
F64 resolve_begin = os_time();
|
F64 resolve_begin = os_time();
|
||||||
|
|||||||
24
main.cpp
24
main.cpp
@@ -32,10 +32,9 @@ For now I don't thing it should be overloadable.
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@todo
|
@todo
|
||||||
[ ] - in new typesystem: Fix calls, fix other example programs
|
[ ] - Operators: Bit negation, Not
|
||||||
[ ] - 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
|
||||||
[ ] - 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
|
||||||
@@ -66,6 +65,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] - in new typesystem: Fix calls, fix all example programs
|
||||||
[x] - Fix arithmetic operations in new type system
|
[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
|
||||||
@@ -104,20 +104,20 @@ int main(){
|
|||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|
||||||
String result = {};
|
String result = {};
|
||||||
#if 1
|
#if 0
|
||||||
// result = compile_file("globals.kl"_s);
|
result = compile_file("globals.kl"_s);
|
||||||
// printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
// result = compile_file("enums.kl"_s);
|
result = compile_file("enums.kl"_s);
|
||||||
// printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
// result = compile_file("order1.kl"_s);
|
result = compile_file("order1.kl"_s);
|
||||||
// printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
// result = compile_file("lambdas.kl"_s);
|
|
||||||
// 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("lambdas.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
#endif
|
#endif
|
||||||
|
result = compile_file("new_types.kl"_s);
|
||||||
|
printf("%s", result.str);
|
||||||
|
|
||||||
// result = compile_file("lexer.kl"_s);
|
// result = compile_file("lexer.kl"_s);
|
||||||
// FILE *f = fopen("program.c", "w");
|
// FILE *f = fopen("program.c", "w");
|
||||||
|
|||||||
@@ -315,6 +315,8 @@ binding_power(Binding binding, Token_Kind kind){
|
|||||||
case TK_OpenParen:
|
case TK_OpenParen:
|
||||||
case TK_Sub:
|
case TK_Sub:
|
||||||
case TK_Add:
|
case TK_Add:
|
||||||
|
case TK_Neg:
|
||||||
|
case TK_Not:
|
||||||
return{-2, 20};
|
return{-2, 20};
|
||||||
default: return {-1, -1};
|
default: return {-1, -1};
|
||||||
}
|
}
|
||||||
@@ -370,6 +372,8 @@ parse_expr(S64 min_bp){
|
|||||||
case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break;
|
case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break;
|
||||||
case TK_Sub : left = ast_expr_unary(token, TK_Sub, parse_expr(prefix_bp.right)); break;
|
case TK_Sub : left = ast_expr_unary(token, TK_Sub, parse_expr(prefix_bp.right)); break;
|
||||||
case TK_Add : left = ast_expr_unary(token, TK_Add, parse_expr(prefix_bp.right)); break;
|
case TK_Add : left = ast_expr_unary(token, TK_Add, parse_expr(prefix_bp.right)); break;
|
||||||
|
case TK_Not : left = ast_expr_unary(token, TK_Not, parse_expr(prefix_bp.right)); break;
|
||||||
|
case TK_Neg : left = ast_expr_unary(token, TK_Neg, parse_expr(prefix_bp.right)); break;
|
||||||
|
|
||||||
case TK_OpenBracket: {
|
case TK_OpenBracket: {
|
||||||
Ast_Array *result = ast_array(token, parse_expr(0));
|
Ast_Array *result = ast_array(token, parse_expr(0));
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ unary_test :: ()
|
|||||||
float2 := -float_val
|
float2 := -float_val
|
||||||
unsigned: Int = -+-+-int_val
|
unsigned: Int = -+-+-int_val
|
||||||
|
|
||||||
|
not: Bool = !int_val
|
||||||
|
neg: S64 = ~int_val
|
||||||
|
|
||||||
// uns: U64 = -int_val
|
// uns: U64 = -int_val
|
||||||
// int_float: S64 = float_val
|
// int_float: S64 = float_val
|
||||||
// string :: -"Thing"
|
// string :: -"Thing"
|
||||||
|
|||||||
100
typecheck.cpp
100
typecheck.cpp
@@ -1,6 +1,33 @@
|
|||||||
#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
|
||||||
|
|
||||||
|
function void
|
||||||
|
type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual, const char *str, ...){
|
||||||
|
Scratch scratch;
|
||||||
|
STRING_FMT(scratch, str, string);
|
||||||
|
|
||||||
|
// @Note(Krzosa): Print nice error message
|
||||||
|
printf("\nType error :: %s :: ", string.str);
|
||||||
|
printf("Expected %s, got instead %s", docname(expected), docname(actual));
|
||||||
|
if(token){
|
||||||
|
printf(" :: %s:%d\n", token->file.str, (S32)token->line + 1);
|
||||||
|
|
||||||
|
// @Note(Krzosa): Print error line
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||||
|
printf("%.*s\n", i, token->line_begin);
|
||||||
|
|
||||||
|
// @Note(Krzosa): Print error marker
|
||||||
|
int token_i = token->str - token->line_begin;
|
||||||
|
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||||
|
printf("^^^^^^\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Evaluating constant expressions
|
// Evaluating constant expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -13,8 +40,10 @@
|
|||||||
|
|
||||||
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(is_untyped(a.type));
|
// assert(a.type);
|
||||||
assert(new_type);
|
assert(new_type);
|
||||||
|
if(a.type == 0) return a;
|
||||||
|
if(is_typed(a.type)) return a;
|
||||||
|
|
||||||
assert(a.int_val <= S64MAX);
|
assert(a.int_val <= S64MAX);
|
||||||
if(is_int(a.type) && is_int(new_type)){
|
if(is_int(a.type) && is_int(new_type)){
|
||||||
@@ -315,28 +344,6 @@ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
|
|||||||
return resolved.type_val;
|
return resolved.type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
|
||||||
resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
|
||||||
Ast_Resolved_Type *result = 0;
|
|
||||||
if(!a && b) result = b;
|
|
||||||
else if(a && !b) result = a;
|
|
||||||
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
|
|
||||||
else{ // a && b
|
|
||||||
if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
|
|
||||||
else result = a; // Types are the same
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Operand
|
|
||||||
resolve_operand_pair(Token *pos, Operand a, Operand b){
|
|
||||||
Operand result = {};
|
|
||||||
result.is_const = a.is_const && b.is_const;
|
|
||||||
result.type = resolve_type_pair(pos, a.type, b.type);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function void resolve_stmt(Ast *ast, Ast_Resolved_Type *ret);
|
function void resolve_stmt(Ast *ast, Ast_Resolved_Type *ret);
|
||||||
function void
|
function void
|
||||||
resolve_stmt_block(Ast_Block *block, Ast_Resolved_Type *ret){
|
resolve_stmt_block(Ast_Block *block, Ast_Resolved_Type *ret){
|
||||||
@@ -354,8 +361,9 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
||||||
Operand op = resolve_expr(node->expr);
|
Operand op = resolve_expr(node->expr);
|
||||||
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [%s]", type_names[op.type->kind]);
|
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
||||||
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
op.value = convert_untyped(node->pos, op.value, ret);
|
||||||
|
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,12 +417,11 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
|||||||
if(expr == 0 && ast_can_be_null) return op;
|
if(expr == 0 && ast_can_be_null) return op;
|
||||||
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
|
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
|
||||||
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
|
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
|
||||||
if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer");
|
if(!is_int(op.type)) parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
|
||||||
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -422,11 +429,15 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
|||||||
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret);
|
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret);
|
||||||
Array<Ast_Resolved_Type *> args = {scratch};
|
Array<Ast_Resolved_Type *> args = {scratch};
|
||||||
For(lambda->args){
|
For(lambda->args){
|
||||||
Operand type = resolve_expr(it->typespec);
|
Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||||
if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]");
|
Operand default_value = resolve_expr(it->default_value, type);
|
||||||
Operand default_value = resolve_expr(it->default_value, type.type_val);
|
|
||||||
if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ");
|
if(default_value.type){
|
||||||
args.add(type.type_val);
|
default_value.value = convert_untyped(it->pos, default_value.value, type);
|
||||||
|
if(default_value.type != type) parsing_error(it->pos, "Default value type and type declaration differ, expected %s got instead %s", docname(type), docname(default_value.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
args.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
lambda_type = type_lambda(lambda, ret_type, args);
|
lambda_type = type_lambda(lambda, ret_type, args);
|
||||||
@@ -507,8 +518,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
CASE(INDEX, Index){
|
CASE(INDEX, Index){
|
||||||
Operand left = resolve_expr(node->expr);
|
Operand left = resolve_expr(node->expr);
|
||||||
Operand index = resolve_expr(node->index);
|
Operand index = resolve_expr(node->index);
|
||||||
if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array");
|
if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array, it's of type %s instead", docname(left.type));
|
||||||
if(index.type != type_int) parsing_error(node->pos, "Trying to index the array with invalid type, expected int");
|
if(!is_int(index.type)) type_error(node->pos, type_int, index.type,"Trying to index the array with invalid type, expected int");
|
||||||
return operand_lvalue(left.type->arr.base);
|
return operand_lvalue(left.type->arr.base);
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -536,7 +547,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = resolve_expr(i->item, item_type);
|
Operand expr = resolve_expr(i->item, item_type);
|
||||||
resolve_type_pair(i->pos, expr.type, item_type);
|
expr.value = convert_untyped(i->pos, expr.value, item_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(type->kind == TYPE_STRUCT){
|
else if(type->kind == TYPE_STRUCT){
|
||||||
@@ -571,10 +582,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
|
|
||||||
if(!found) parsing_error(expr->pos, "Invalid argument in compound constructor");
|
if(!found) parsing_error(expr->pos, "Invalid argument in compound constructor");
|
||||||
if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor");
|
if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor");
|
||||||
|
|
||||||
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);
|
||||||
try_untyping(&op);
|
op.value = convert_untyped(node->pos, op.value, 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[found_type->type->kind], type_names[op.type->kind]);
|
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,7 +626,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(item){
|
if(item){
|
||||||
item->flags = set_flag(item->flags, AST_ITEM_INCLUDED);
|
item->flags = set_flag(item->flags, AST_ITEM_INCLUDED);
|
||||||
Operand expr = resolve_expr(item->item);
|
Operand expr = resolve_expr(item->item);
|
||||||
if(expr.type != resolved) parsing_error(item->pos, "Type is not matching function definition");
|
expr.value = convert_untyped(node->pos, expr.value, resolved);
|
||||||
|
|
||||||
|
if(expr.type != resolved) type_error(item->pos, resolved, expr.type, "Type is not matching function definition");
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -809,6 +822,16 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
result = operand_const_rvalue(value);
|
result = operand_const_rvalue(value);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
if(is_untyped(left.type)){
|
||||||
|
assert(is_typed(right.type));
|
||||||
|
left.value = convert_untyped(node->pos, left.value, right.type);
|
||||||
|
}
|
||||||
|
else if(is_untyped(right.type)){
|
||||||
|
assert(is_typed(left.type));
|
||||||
|
right.value = convert_untyped(node->pos, right.value, left.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(left.type != right.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));
|
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));
|
||||||
}
|
}
|
||||||
@@ -879,7 +902,6 @@ 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) try_untyping(&expr);
|
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);
|
||||||
|
|||||||
@@ -400,6 +400,9 @@ type_struct(Ast_Struct *agg){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
type_complete(Ast_Resolved_Type *type){
|
type_complete(Ast_Resolved_Type *type){
|
||||||
|
if(!type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(type->kind == TYPE_COMPLETING){
|
if(type->kind == TYPE_COMPLETING){
|
||||||
parsing_error(type->ast->pos, "Cyclic type dependency");
|
parsing_error(type->ast->pos, "Cyclic type dependency");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user