-> Operator has very low precedence, size_of, align_of, length_of expressions
This commit is contained in:
34
ast.cpp
34
ast.cpp
@@ -20,6 +20,10 @@ enum Ast_Kind: U32{
|
||||
AST_CALL_ITEM,
|
||||
AST_CALL,
|
||||
|
||||
AST_SIZE_OF,
|
||||
AST_LENGTH_OF,
|
||||
AST_ALIGN_OF,
|
||||
|
||||
AST_COMPOUND,
|
||||
AST_TYPE,
|
||||
AST_VAR,
|
||||
@@ -56,7 +60,7 @@ enum{
|
||||
};
|
||||
|
||||
struct Ast{
|
||||
U64 id;
|
||||
U64 di; // Debug id, shouldn't ever be used in the program
|
||||
Token *pos;
|
||||
|
||||
Ast_Kind kind;
|
||||
@@ -119,13 +123,12 @@ struct Ast_Binary: Ast_Expr{
|
||||
Token_Kind op;
|
||||
Ast_Expr *left;
|
||||
Ast_Expr *right;
|
||||
|
||||
// Ast_Type *type; // For casts after_type
|
||||
Ast_Type *before_type;
|
||||
};
|
||||
|
||||
struct Ast_Len: Ast_Expr{
|
||||
struct Ast_Builtin: Ast_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
|
||||
@@ -236,7 +239,7 @@ struct Ast_Decl: Ast{
|
||||
result->kind = AST_##ikind; \
|
||||
result->parent_scope = pctx->currently_parsed_scope; \
|
||||
result->pos = ipos; \
|
||||
result->id = ++pctx->unique_ids
|
||||
result->di = ++pctx->unique_ids
|
||||
|
||||
function Ast_Atom *
|
||||
ast_str(Token *pos, Intern_String string){
|
||||
@@ -513,6 +516,27 @@ ast_module(Intern_String filename){
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
26
ccodegen.cpp
26
ccodegen.cpp
@@ -256,6 +256,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
|
||||
CASE(INDEX, Index){
|
||||
gen("(");
|
||||
gen_expr(node->expr);
|
||||
if(node->expr->resolved_type == type_string) gen(".str");
|
||||
gen("[");
|
||||
gen_expr(node->index);
|
||||
gen("]");
|
||||
@@ -310,19 +311,15 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CALL, Call){
|
||||
if(node->name->kind == AST_IDENT){
|
||||
auto ident = (Ast_Atom *)node->name;
|
||||
if(ident->intern_val == pctx->intern("len"_s)){
|
||||
if(is_slice(ident->type)){
|
||||
Ast_Call_Item *arg = node->exprs[0];
|
||||
gen_expr(arg->item);
|
||||
gen(".len");
|
||||
return true;
|
||||
} else invalid_codepath;
|
||||
}
|
||||
}
|
||||
CASE(LENGTH_OF, Builtin){
|
||||
gen_expr(node->expr);
|
||||
if(is_pointer(node->expr->resolved_type))
|
||||
gen("->len");
|
||||
else gen(".len");
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CALL, Call){
|
||||
gen_expr(node->name);
|
||||
gen("(");
|
||||
For(node->exprs){
|
||||
@@ -680,10 +677,7 @@ typedef struct String{
|
||||
#endif
|
||||
For(pctx->ordered_decls){
|
||||
if(it->kind == AST_STRUCT){
|
||||
genln("typedef struct struct %s;", it->name.str);
|
||||
} else if(it->kind == AST_LAMBDA){
|
||||
genln("");
|
||||
gen_lambda(it->name, it->lambda, false);
|
||||
genln("typedef struct %s %s;", it->name.str, it->name.str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,9 @@ Intern_String keyword_true;
|
||||
Intern_String keyword_false;
|
||||
Intern_String keyword_for;
|
||||
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 intern_void;
|
||||
@@ -202,7 +204,9 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
||||
|
||||
keyword_struct= l->intern("struct"_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_false = l->intern("false"_s);
|
||||
keyword_return = l->intern("return"_s);
|
||||
|
||||
14
main.kl
14
main.kl
@@ -1,16 +1,10 @@
|
||||
#import "base.kl"
|
||||
|
||||
test_arrays :: ()
|
||||
array := [4]int{1,2,3,4}
|
||||
item := array[0]
|
||||
length := len(array)
|
||||
slice: []int = array
|
||||
slice_length := len(slice)
|
||||
print :: (string: String)
|
||||
handle := Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE)
|
||||
Windows.WriteConsoleA(handle, &string[0]->*void, length_of(string)->Windows.DWORD, 0, 0)
|
||||
|
||||
main :: (argc: int, argv: **char): int
|
||||
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)
|
||||
|
||||
26
parsing.cpp
26
parsing.cpp
@@ -404,7 +404,7 @@ binding_power(Binding binding, Token_Kind kind){
|
||||
case TK_Dot:
|
||||
return {31,30};
|
||||
case TK_Arrow:
|
||||
return {29,28};
|
||||
return {2,1};
|
||||
default: return {};
|
||||
}
|
||||
Postfix: switch(kind){
|
||||
@@ -457,8 +457,28 @@ parse_expr(S64 min_bp){
|
||||
}break;
|
||||
|
||||
case TK_Keyword: {
|
||||
if(token->intern_val == keyword_true) left = ast_bool(token, 1);
|
||||
else if(token->intern_val == keyword_false) left = ast_bool(token, 0);
|
||||
if(token->intern_val == keyword_true)
|
||||
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);
|
||||
}break;
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
||||
set_flag(ast->flags, AST_ATOM);
|
||||
ast->kind = AST_VALUE;
|
||||
ast->value = value;
|
||||
ast->resolved_type = value.type;
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
@@ -682,6 +683,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
|
||||
CASE(IDENT, Atom){
|
||||
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);
|
||||
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)){
|
||||
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));
|
||||
}
|
||||
|
||||
node->index_original_type = left.type;
|
||||
return operand_lvalue(left.type->arr.base);
|
||||
BREAK();
|
||||
}
|
||||
@@ -858,28 +864,49 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CALL, Call){
|
||||
// Handle builtin calls
|
||||
if(node->name->kind == AST_IDENT){
|
||||
auto ident = (Ast_Atom *)node->name;
|
||||
if(ident->intern_val == pctx->intern("len"_s)){
|
||||
if(node->exprs.len > 1) compiler_error(node->pos, "Expected 1 argument");
|
||||
Ast_Call_Item *arg = node->exprs[0];
|
||||
if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected");
|
||||
Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL);
|
||||
ident->type = op.type;
|
||||
CASE(ALIGN_OF, Builtin){
|
||||
Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
if(!name.is_const) compiler_error(node->pos, "align_of requires a constant value");
|
||||
Ast_Type *type = name.type == type_type ? name.type_val : name.type;
|
||||
Value v = value_int(type->align);
|
||||
rewrite_into_const(node, Ast_Builtin, v);
|
||||
return operand_const_rvalue(v);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
if(is_array(op.type)){
|
||||
Value val = value_int(op.type->arr.size);
|
||||
rewrite_into_const(node, Ast_Call, val);
|
||||
return operand_const_rvalue(val);
|
||||
} else if(is_slice(op.type)){
|
||||
return operand_rvalue(type_s64);
|
||||
} else compiler_error(node->pos, "Invalid argument");
|
||||
CASE(SIZE_OF, Builtin){
|
||||
Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
if(!name.is_const) compiler_error(node->pos, "size_of requires a constant value");
|
||||
Ast_Type *type = name.type == type_type ? name.type_val : name.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);
|
||||
}
|
||||
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);
|
||||
if(name.type->kind != TYPE_LAMBDA)
|
||||
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){
|
||||
set_flag(item->flags, AST_ITEM_INCLUDED);
|
||||
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);
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -164,7 +164,7 @@ type_array(Ast_Type *base, S64 size){
|
||||
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.size = size;
|
||||
result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||
|
||||
Reference in New Issue
Block a user