Fixing bugs, pointer arithmetic checking, better for, working on first program

This commit is contained in:
Krzosa Karol
2022-06-06 23:50:38 +02:00
parent 729e7aee86
commit f852a23fcb
8 changed files with 127 additions and 50 deletions

View File

@@ -66,7 +66,7 @@ gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
function void
gen_value(Value a){
gen("%s", docname(a.type));
// gen("%s", docname(a.type));
switch(a.type->kind){
CASE_INT: {
Scratch scratch;
@@ -94,10 +94,12 @@ gen_expr(Ast_Expr *ast){
}
CASE(INDEX, Index){
gen("(");
gen_expr(node->expr);
gen("[");
gen_expr(node->index);
gen("]");
gen(")");
BREAK();
}
@@ -335,7 +337,7 @@ gen_ast(Ast *ast){
if(sym->type_val->kind == TYPE_STRUCT){
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
if(node->value->kind == AST_STRUCT){
gen("struct %s{", node->name.str);
gen("typedef struct %s{", node->name.str);
global_indent++;
For(agg->members){
genln("");
@@ -347,7 +349,7 @@ gen_ast(Ast *ast){
gen_ast(it);
}
global_indent--;
genln("};");
genln("}%s;", node->name.str);
}
else{
// Type alias
@@ -428,12 +430,18 @@ typedef U64 SizeU;
typedef S64 SizeS;
typedef float F32;
typedef double F64;
typedef S32 Bool;
typedef struct String{
U8 *str;
S64 len;
}String;
#define LIT(x) (String){.str=(U8 *)x, .len=sizeof(x)-1}
void entry();
int main(){
entry();
}
)==");
F64 resolve_begin = os_time();

View File

@@ -77,7 +77,6 @@ Expr:
@todo
[ ] - Fix casting
[ ] - Make sure pointer arithmetic works
[ ] - Passing down program to compile through command line
[ ] - More for loop variations
@@ -108,10 +107,12 @@ Expr:
[ ] - Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {}
@donzo
[x] - We are parsing wrong here: (t.str=(&string_to_lex.str)[i]);
[x] - Test new operators, add constant eval for them
[x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
[x] - More basic types
[x] - Implementing required operations int128
[x] - Fix casting
[x] - Add basic support for floats
[x] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need big int
[x] - Add basic setup for new type system
@@ -167,7 +168,7 @@ int main(){
String result = {};
#if 1
#if 0
result = compile_file("globals.kl"_s);
printf("%s", result.str);
result = compile_file("enums.kl"_s);
@@ -178,12 +179,12 @@ int main(){
printf("%s", result.str);
result = compile_file("lambdas.kl"_s);
printf("%s", result.str);
#endif
result = compile_file("new_types.kl"_s);
printf("%s", result.str);
#endif
#if 0
#if 1
result = compile_file("program.kl"_s);
FILE *f = fopen("program.c", "w");
assert(f);

View File

@@ -118,7 +118,9 @@ function Ast_Expr *parse_expr(S64 minbp = 0);
function Ast_Expr *
parse_init_stmt(Ast_Expr *expr){
Token *token = token_get();
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) parsing_error(expr->pos, "Binding with [:=] to something that is not an identifier");
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
parsing_error(expr->pos, "Binding with [:=] to something that is not an identifier");
if(token_is_assign(token)){
token_next();
Ast_Expr *value = parse_expr();
@@ -359,7 +361,7 @@ binding_power(Binding binding, Token_Kind kind){
Postfix: switch(kind){
case TK_OpenBracket:
case TK_OpenParen:
return {20, -2};
return {21, -2};
default: return{-1,-1};
}
}

View File

@@ -18,6 +18,9 @@ unary_test :: ()
var2: S64 = 20
var_bool: Bool = !var1 == !var2
pointer: *S64
pointer += 10
// pointer = pointer + pointer
// uns: U64 = -int_val
// int_float: S64 = float_val

View File

@@ -16,6 +16,7 @@ typedef U64 SizeU;
typedef S64 SizeS;
typedef float F32;
typedef double F64;
typedef S32 Bool;
typedef struct String{
U8 *str;
@@ -23,13 +24,28 @@ typedef struct String{
}String;
#define LIT(x) (String){.str=(U8 *)x, .len=sizeof(x)-1}
struct Lex_Stream{
U8 *stream;
U8 *end;
};
void entry();
int main(){
entry();
}
typedef struct Token{
U8 *str;
S64 len;
}Token;
Bool is_numeric(U8 c){
Bool result = ((c>=48)&&(c<=57));
return result;
}
void entry(){
String string_to_lex = LIT("Identifier 2425525 Not_Number");
Token t;
for(S64 i = 0;(i<string_to_lex.len);(i+=1)){
(string_to_lex.str[0]=64);
if(is_numeric((string_to_lex.str[i]))){
(t.str=(&(string_to_lex.str[i])));
for(;is_numeric((string_to_lex.str[i]));){
(i+=1);
}
}
}
}

View File

@@ -1,11 +1,21 @@
Lex_Stream :: struct
stream: *U8
end : *U8
Token :: struct
str: *U8
len: S64
main :: (): int
is_numeric :: (c: U8): Bool
result := c >= '0 && c <= '9
return result
entry :: ()
string_to_lex := "Identifier 2425525 Not_Number"
t: Token
for i := 0, i < string_to_lex.len, i+=1
string_to_lex.str[0] = 64
if is_numeric(string_to_lex.str[i])
t.str = &string_to_lex.str[i]
for is_numeric(string_to_lex.str[i])
i+=1

View File

@@ -52,6 +52,8 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){
assert(a.type == untyped_int);
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_int(a.type) && is_pointer(new_type))
;
else if(is_float(a.type) && is_float(new_type))
; // nothing to do
else if(is_bool(a.type) && is_bool(new_type))
@@ -67,11 +69,18 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){
function void
make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
if(is_typed(a->type) && is_typed(b->type)){
if((is_pointer(a->type) && is_int(b->type)) || (is_pointer(b->type) && is_int(a->type))){
return;
}
else if(is_pointer(a->type) && is_pointer(b->type)){
goto fail;
}
else if(is_typed(a->type) && is_typed(b->type)){
if(a->type != b->type){
parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type));
fail: parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type));
}
}
if(is_untyped(a->type) && is_typed(b->type)){
assert(is_typed(b->type));
*a = convert_untyped_to_typed(pos, *a, b->type);
@@ -80,7 +89,6 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
assert(is_typed(a->type));
*b = convert_untyped_to_typed(pos, *b, a->type);
}
else if(is_int(a->type) && is_float(b->type)){
*a = value_float(a->big_int_val);
}
@@ -92,7 +100,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
function Value
compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
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", name(op), docname(a.type), docname(a.type));
parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
make_sure_types_are_compatible(pos, &a, &b);
@@ -146,7 +154,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
return compare_values(pos, op, a, b, is_const);
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", name(op), docname(a.type), docname(a.type));
parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
make_sure_types_are_compatible(pos, &a, &b);
@@ -261,30 +269,45 @@ eval_unary(Token *pos, Token_Kind op, Value *a, bool is_const){
}
function void
convert_untyped_to_typed_default(Operand *op){
if(!op) return;
try_converting_untyped_to_typed(Operand *op){
if(is_untyped(op->type)){
if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_s64;
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;
switch(op->type->kind){
case TYPE_UNTYPED_INT: op->type = type_s64; break;
case TYPE_UNTYPED_BOOL: op->type = type_bool; break;
case TYPE_UNTYPED_STRING: op->type = type_string; break;
case TYPE_UNTYPED_FLOAT: op->type = type_f64; break;
default: invalid_codepath;
}
}
}
enum{
TYPE_AND_EXPR_REQUIRED = 0,
TYPE_CAN_BE_NULL = 1,
EXPR_CAN_BE_NULL = 2
};
function void
make_sure_types_are_compatible_for_assignment(Token *pos, Operand *expr, Ast_Resolved_Type *type = 0){
make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_Type *type, U64 debug_flag){
if(type == expr->type){
assert(type);
assert(expr->type);
return;
}
if(!type)
convert_untyped_to_typed_default(expr);
else if(!expr->type)
if(!type){
assert(is_flag_set(debug_flag, TYPE_CAN_BE_NULL));
assert(expr->type);
try_converting_untyped_to_typed(expr);
}
else if(!expr->type){
assert(is_flag_set(debug_flag, EXPR_CAN_BE_NULL));
assert(type);
expr->type = type;
else if(is_untyped(expr->type))
}
else if(is_untyped(expr->type)){
expr->value = convert_untyped_to_typed(pos, expr->value, type);
}
if(type && expr->type != type){
parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type));
@@ -362,10 +385,16 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
}
CASE(FOR, For){
if(node->init && node->cond == 0 && node->iter == 0){
if(!is_flag_set(node->init->flags, AST_STMT)){
node->cond = node->init;
node->init = 0;
}
}
resolve_expr(node->init, ret);
Operand cond = resolve_expr(node->cond); // @todo: typechecking
resolve_expr(node->cond, ret);
resolve_expr(node->iter, ret);
unused(cond);
resolve_stmt_block(node->block, ret);
BREAK();
}
@@ -392,10 +421,16 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
function Operand
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
Operand op = resolve_expr(expr);
if(expr == 0 && ast_can_be_null) return op;
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(!is_int(op.type)) parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
if(expr == 0 && ast_can_be_null)
return op;
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(!is_int(op.type))
parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
return op;
}
@@ -410,7 +445,7 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
Ast_Resolved_Type *type =
resolve_typespec(it->typespec, AST_CANT_BE_NULL);
Operand default_value = resolve_expr(it->default_value, type);
make_sure_types_are_compatible_for_assignment(it->pos, &default_value, type);
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
args.add(type);
}
@@ -700,7 +735,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
}
else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
}break;
case TK_Dereference:{return operand_lvalue(type_pointer(value.type));}break;
case TK_Dereference:{
return operand_lvalue(type_pointer(value.type));
}break;
case TK_Neg:case TK_Not:case TK_Add:case TK_Sub:{
Operand op = resolve_expr(node->expr);
eval_unary(node->pos, node->op, &op.value, op.is_const);
@@ -724,7 +761,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
assert(node->left->kind == AST_IDENT);
Operand right = resolve_expr(node->right);
make_sure_types_are_compatible_for_assignment(node->pos, &right);
make_sure_value_is_compatible_with_type(node->pos, &right, 0, TYPE_CAN_BE_NULL);
assert(right.type);
auto atom = (Ast_Atom *)node->left;
@@ -840,7 +877,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
rewrite_into_const(node, Ast_Binary, value);
result = operand_const_rvalue(value);
}
else result = operand_rvalue(left.type);
else result = operand_rvalue(value.type);
}
//-----------------------------------------------------------------------------
@@ -903,7 +940,7 @@ resolve_binding(Ast *ast, Sym *sym){
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
Operand expr = resolve_expr(node->expr, type);
assert(expr.type != 0 || type != 0);
make_sure_types_are_compatible_for_assignment(node->pos, &expr, type);
make_sure_value_is_compatible_with_type(node->pos, &expr, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL);
assert(expr.type);
return expr;
BREAK();

View File

@@ -19,10 +19,10 @@ enum Ast_Resolved_Type_Kind{
TYPE_U8 ,
TYPE_F32,
TYPE_F64,
TYPE_POINTER,
TYPE_BOOL, // LAST_NUMERIC
TYPE_STRING,
TYPE_VOID,
TYPE_POINTER,
TYPE_ARRAY,
TYPE_LAMBDA,
TYPE_STRUCT,