-> Operator has very low precedence, size_of, align_of, length_of expressions

This commit is contained in:
Krzosa Karol
2022-06-14 13:50:59 +02:00
parent 17e342c4da
commit f885abe3f5
7 changed files with 121 additions and 58 deletions

34
ast.cpp
View File

@@ -20,6 +20,10 @@ enum Ast_Kind: U32{
AST_CALL_ITEM, AST_CALL_ITEM,
AST_CALL, AST_CALL,
AST_SIZE_OF,
AST_LENGTH_OF,
AST_ALIGN_OF,
AST_COMPOUND, AST_COMPOUND,
AST_TYPE, AST_TYPE,
AST_VAR, AST_VAR,
@@ -56,7 +60,7 @@ enum{
}; };
struct Ast{ struct Ast{
U64 id; U64 di; // Debug id, shouldn't ever be used in the program
Token *pos; Token *pos;
Ast_Kind kind; Ast_Kind kind;
@@ -119,13 +123,12 @@ struct Ast_Binary: Ast_Expr{
Token_Kind op; Token_Kind op;
Ast_Expr *left; Ast_Expr *left;
Ast_Expr *right; Ast_Expr *right;
// Ast_Type *type; // For casts after_type
Ast_Type *before_type; Ast_Type *before_type;
}; };
struct Ast_Len: Ast_Expr{ struct Ast_Builtin: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
U64 padding[3]; // For folding constants into atoms
}; };
// Problem: We are parsing out of order, in the middle of parsing a function // Problem: We are parsing out of order, in the middle of parsing a function
@@ -236,7 +239,7 @@ struct Ast_Decl: Ast{
result->kind = AST_##ikind; \ result->kind = AST_##ikind; \
result->parent_scope = pctx->currently_parsed_scope; \ result->parent_scope = pctx->currently_parsed_scope; \
result->pos = ipos; \ result->pos = ipos; \
result->id = ++pctx->unique_ids result->di = ++pctx->unique_ids
function Ast_Atom * function Ast_Atom *
ast_str(Token *pos, Intern_String string){ ast_str(Token *pos, Intern_String string){
@@ -513,6 +516,27 @@ ast_module(Intern_String filename){
return result; return result;
} }
function Ast_Builtin *
ast_sizeof(Token *pos, Ast_Expr *expr){
AST_NEW(Builtin, SIZE_OF, pos, AST_EXPR);
result->expr = expr;
return result;
}
function Ast_Builtin *
ast_len(Token *pos, Ast_Expr *expr){
AST_NEW(Builtin, LENGTH_OF, pos, AST_EXPR);
result->expr = expr;
return result;
}
function Ast_Builtin *
ast_alignof(Token *pos, Ast_Expr *expr){
AST_NEW(Builtin, ALIGN_OF, pos, AST_EXPR);
result->expr = expr;
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Value // Value
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -256,6 +256,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
CASE(INDEX, Index){ CASE(INDEX, Index){
gen("("); gen("(");
gen_expr(node->expr); gen_expr(node->expr);
if(node->expr->resolved_type == type_string) gen(".str");
gen("["); gen("[");
gen_expr(node->index); gen_expr(node->index);
gen("]"); gen("]");
@@ -310,19 +311,15 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
BREAK(); BREAK();
} }
CASE(CALL, Call){ CASE(LENGTH_OF, Builtin){
if(node->name->kind == AST_IDENT){ gen_expr(node->expr);
auto ident = (Ast_Atom *)node->name; if(is_pointer(node->expr->resolved_type))
if(ident->intern_val == pctx->intern("len"_s)){ gen("->len");
if(is_slice(ident->type)){ else gen(".len");
Ast_Call_Item *arg = node->exprs[0]; BREAK();
gen_expr(arg->item);
gen(".len");
return true;
} else invalid_codepath;
}
} }
CASE(CALL, Call){
gen_expr(node->name); gen_expr(node->name);
gen("("); gen("(");
For(node->exprs){ For(node->exprs){
@@ -680,10 +677,7 @@ typedef struct String{
#endif #endif
For(pctx->ordered_decls){ For(pctx->ordered_decls){
if(it->kind == AST_STRUCT){ if(it->kind == AST_STRUCT){
genln("typedef struct struct %s;", it->name.str); genln("typedef struct %s %s;", it->name.str, it->name.str);
} else if(it->kind == AST_LAMBDA){
genln("");
gen_lambda(it->name, it->lambda, false);
} }
} }

View File

@@ -163,7 +163,9 @@ Intern_String keyword_true;
Intern_String keyword_false; Intern_String keyword_false;
Intern_String keyword_for; Intern_String keyword_for;
Intern_String keyword_pass; Intern_String keyword_pass;
Intern_String keyword_cast; Intern_String keyword_sizeof;
Intern_String keyword_alignof;
Intern_String keyword_lengthof;
Intern_String keyword_enum; Intern_String keyword_enum;
Intern_String intern_void; Intern_String intern_void;
@@ -202,7 +204,9 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
keyword_struct= l->intern("struct"_s); keyword_struct= l->intern("struct"_s);
keyword_union = l->intern("union"_s); keyword_union = l->intern("union"_s);
keyword_cast = l->intern("cast"_s); keyword_sizeof = l->intern("size_of"_s);
keyword_lengthof = l->intern("length_of"_s);
keyword_alignof = l->intern("align_of"_s);
keyword_true = l->intern("true"_s); keyword_true = l->intern("true"_s);
keyword_false = l->intern("false"_s); keyword_false = l->intern("false"_s);
keyword_return = l->intern("return"_s); keyword_return = l->intern("return"_s);

14
main.kl
View File

@@ -1,16 +1,10 @@
#import "base.kl" #import "base.kl"
test_arrays :: () print :: (string: String)
array := [4]int{1,2,3,4} handle := Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE)
item := array[0] Windows.WriteConsoleA(handle, &string[0]->*void, length_of(string)->Windows.DWORD, 0, 0)
length := len(array)
slice: []int = array
slice_length := len(slice)
main :: (argc: int, argv: **char): int main :: (argc: int, argv: **char): int
memory := reserve(size = 10000) memory := reserve(size = 10000)
handle := Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE) print("Hello world")
string: *char = "hello world"
Windows.WriteConsoleA(handle, string->*void, 11, 0, 0)

View File

@@ -404,7 +404,7 @@ binding_power(Binding binding, Token_Kind kind){
case TK_Dot: case TK_Dot:
return {31,30}; return {31,30};
case TK_Arrow: case TK_Arrow:
return {29,28}; return {2,1};
default: return {}; default: return {};
} }
Postfix: switch(kind){ Postfix: switch(kind){
@@ -457,8 +457,28 @@ parse_expr(S64 min_bp){
}break; }break;
case TK_Keyword: { case TK_Keyword: {
if(token->intern_val == keyword_true) left = ast_bool(token, 1); if(token->intern_val == keyword_true)
else if(token->intern_val == keyword_false) left = ast_bool(token, 0); left = ast_bool(token, 1);
else if(token->intern_val == keyword_false)
left = ast_bool(token, 0);
else if(token->intern_val == keyword_sizeof){
token_expect(TK_OpenParen);
Ast_Expr *expr = parse_expr();
token_expect(TK_CloseParen);
left = ast_sizeof(token, expr);
}
else if(token->intern_val == keyword_alignof){
token_expect(TK_OpenParen);
Ast_Expr *expr = parse_expr();
token_expect(TK_CloseParen);
left = ast_alignof(token, expr);
}
else if(token->intern_val == keyword_lengthof){
token_expect(TK_OpenParen);
Ast_Expr *expr = parse_expr();
token_expect(TK_CloseParen);
left = ast_len(token, expr);
}
else compiler_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); else compiler_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
}break; }break;

View File

@@ -311,6 +311,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
set_flag(ast->flags, AST_ATOM); set_flag(ast->flags, AST_ATOM);
ast->kind = AST_VALUE; ast->kind = AST_VALUE;
ast->value = value; ast->value = value;
ast->resolved_type = value.type;
} }
function Ast_Decl * function Ast_Decl *
@@ -682,6 +683,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
CASE(IDENT, Atom){ CASE(IDENT, Atom){
node->resolved_decl = resolve_name(node->parent_scope, node->pos, node->intern_val); node->resolved_decl = resolve_name(node->parent_scope, node->pos, node->intern_val);
node->resolved_type = node->resolved_decl->type;
Operand result = operand(node->resolved_decl); Operand result = operand(node->resolved_decl);
if(result.is_const){ if(result.is_const){
@@ -749,11 +751,15 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
if(!is_int(index.type)){ if(!is_int(index.type)){
compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type)); compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type));
} }
if(!is_array(left.type) && !is_pointer(left.type)){
node->index_original_type = left.type;
if(is_string(left.type)){
return operand_lvalue(type_u8);
}
else if(!is_array(left.type) && !is_pointer(left.type)){
compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type));
} }
node->index_original_type = left.type;
return operand_lvalue(left.type->arr.base); return operand_lvalue(left.type->arr.base);
BREAK(); BREAK();
} }
@@ -858,28 +864,49 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
BREAK(); BREAK();
} }
CASE(CALL, Call){ CASE(ALIGN_OF, Builtin){
// Handle builtin calls Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL);
if(node->name->kind == AST_IDENT){ if(!name.is_const) compiler_error(node->pos, "align_of requires a constant value");
auto ident = (Ast_Atom *)node->name; Ast_Type *type = name.type == type_type ? name.type_val : name.type;
if(ident->intern_val == pctx->intern("len"_s)){ Value v = value_int(type->align);
if(node->exprs.len > 1) compiler_error(node->pos, "Expected 1 argument"); rewrite_into_const(node, Ast_Builtin, v);
Ast_Call_Item *arg = node->exprs[0]; return operand_const_rvalue(v);
if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected"); BREAK();
Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL); }
ident->type = op.type;
if(is_array(op.type)){ CASE(SIZE_OF, Builtin){
Value val = value_int(op.type->arr.size); Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL);
rewrite_into_const(node, Ast_Call, val); if(!name.is_const) compiler_error(node->pos, "size_of requires a constant value");
return operand_const_rvalue(val); Ast_Type *type = name.type == type_type ? name.type_val : name.type;
} else if(is_slice(op.type)){ Value v = value_int(type->size);
rewrite_into_const(node, Ast_Builtin, v);
return operand_const_rvalue(v);
BREAK();
}
CASE(LENGTH_OF, Builtin){
Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL);
if(name.type == type_type){
if(is_array(name.type_val)){
Value value = value_int(name.type_val->arr.size);
rewrite_into_const(node, Ast_Builtin, value);
return operand_const_rvalue(value);
}
else compiler_error(node->pos, "Can't get length of type %s", docname(name.type_val));
}
else if(name.type->kind == TYPE_UNTYPED_STRING){
Value value = value_int(name.intern_val.len);
rewrite_into_const(node, Ast_Builtin, value);
return operand_const_rvalue(value);
}
else if(is_array(name.type) || is_slice(name.type) || is_string(name.type)){
return operand_rvalue(type_s64); return operand_rvalue(type_s64);
} else compiler_error(node->pos, "Invalid argument");
} }
else compiler_error(node->pos, "Can't get length of type %s", docname(name.type));
BREAK();
} }
// Handle calls CASE(CALL, Call){
Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); Operand name = resolve_expr(node->name, AST_CANT_BE_NULL);
if(name.type->kind != TYPE_LAMBDA) if(name.type->kind != TYPE_LAMBDA)
compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type)); compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type));
@@ -918,7 +945,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
if(item){ if(item){
set_flag(item->flags, AST_ITEM_INCLUDED); set_flag(item->flags, AST_ITEM_INCLUDED);
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type); Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type);
make_sure_value_is_compatible_with_type(node->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED); make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
items.add(item); items.add(item);
} }
else{ else{

View File

@@ -164,7 +164,7 @@ type_array(Ast_Type *base, S64 size){
return result; return result;
} }
result = type_new(pctx->perm, TYPE_ARRAY, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_ARRAY, size*base->size, pointer_align);
result->arr.base = base; result->arr.base = base;
result->arr.size = size; result->arr.size = size;
result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));