Parsing operator overloads
This commit is contained in:
25
core_ast.cpp
25
core_ast.cpp
@@ -52,18 +52,19 @@ enum Ast_Kind: U32{
|
||||
|
||||
typedef U32 Ast_Flag;
|
||||
enum{
|
||||
AST_EXPR = bit_flag(1),
|
||||
AST_STMT = bit_flag(2),
|
||||
AST_STRICT = bit_flag(3),
|
||||
AST_AGGREGATE = bit_flag(4),
|
||||
AST_AGGREGATE_CHILD = bit_flag(5),
|
||||
AST_ANY_VARGS = bit_flag(6),
|
||||
AST_ATOM = bit_flag(7),
|
||||
AST_FOREIGN = bit_flag(8),
|
||||
AST_DECL = bit_flag(9),
|
||||
AST_GLOBAL = bit_flag(10),
|
||||
AST_FLAG = bit_flag(11),
|
||||
AST_VAR_IS_CONST = bit_flag(12),
|
||||
AST_EXPR = bit_flag(1),
|
||||
AST_STMT = bit_flag(2),
|
||||
AST_STRICT = bit_flag(3),
|
||||
AST_AGGREGATE = bit_flag(4),
|
||||
AST_AGGREGATE_CHILD = bit_flag(5),
|
||||
AST_ANY_VARGS = bit_flag(6),
|
||||
AST_ATOM = bit_flag(7),
|
||||
AST_FOREIGN = bit_flag(8),
|
||||
AST_DECL = bit_flag(9),
|
||||
AST_GLOBAL = bit_flag(10),
|
||||
AST_FLAG = bit_flag(11),
|
||||
AST_VAR_IS_CONST = bit_flag(12),
|
||||
AST_OPERATOR_OVERLOAD = bit_flag(13),
|
||||
};
|
||||
|
||||
struct Ast{
|
||||
|
||||
@@ -15,32 +15,56 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
||||
l->tokens = array_make<Token>(token_string_arena, 1024*2);
|
||||
l->interns= intern_table_make(token_string_arena, map_allocator, 1024);
|
||||
|
||||
keyword_struct= l->intern("struct"_s);
|
||||
keyword_union = l->intern("union"_s);
|
||||
keyword_true = l->intern("true"_s);
|
||||
keyword_default = l->intern("default"_s);
|
||||
keyword_break = l->intern("break"_s);
|
||||
keyword_false = l->intern("false"_s);
|
||||
keyword_return = l->intern("return"_s);
|
||||
keyword_switch = l->intern("switch"_s);
|
||||
keyword_assert = l->intern("Assert"_s);
|
||||
keyword_if = l->intern("if"_s);
|
||||
keyword_elif = l->intern("elif"_s);
|
||||
keyword_pass = l->intern("pass"_s);
|
||||
keyword_else = l->intern("else"_s);
|
||||
keyword_for = l->intern("for"_s);
|
||||
keyword_enum = intern_string(&l->interns, "enum"_s);
|
||||
keyword_struct = l->intern("struct"_s);
|
||||
keyword_union = l->intern("union"_s);
|
||||
keyword_true = l->intern("true"_s);
|
||||
keyword_default = l->intern("default"_s);
|
||||
keyword_break = l->intern("break"_s);
|
||||
keyword_false = l->intern("false"_s);
|
||||
keyword_return = l->intern("return"_s);
|
||||
keyword_switch = l->intern("switch"_s);
|
||||
keyword_assert = l->intern("Assert"_s);
|
||||
keyword_if = l->intern("if"_s);
|
||||
keyword_elif = l->intern("elif"_s);
|
||||
keyword_pass = l->intern("pass"_s);
|
||||
keyword_else = l->intern("else"_s);
|
||||
keyword_for = l->intern("for"_s);
|
||||
keyword_enum = intern_string(&l->interns, "enum"_s);
|
||||
l->interns.first_keyword = keyword_struct.str;
|
||||
l->interns.last_keyword = keyword_enum.str;
|
||||
|
||||
intern_sizeof = l->intern("SizeOf"_s);
|
||||
intern_lengthof = l->intern("Length"_s);
|
||||
intern_alignof = l->intern("AlignOf"_s);
|
||||
intern_foreign = intern_string(&l->interns, "foreign"_s);
|
||||
intern_strict = intern_string(&l->interns, "strict"_s);
|
||||
intern_void = intern_string(&l->interns, "void"_s);
|
||||
intern_flag = intern_string(&l->interns, "flag"_s);
|
||||
intern_it = intern_string(&l->interns, "it"_s);
|
||||
intern_sizeof = l->intern("SizeOf"_s);
|
||||
intern_lengthof = l->intern("Length"_s);
|
||||
intern_alignof = l->intern("AlignOf"_s);
|
||||
intern_foreign = l->intern("foreign"_s);
|
||||
intern_strict = l->intern("strict"_s);
|
||||
intern_void = l->intern("void"_s);
|
||||
intern_flag = l->intern("flag"_s);
|
||||
intern_it = l->intern("it"_s);
|
||||
|
||||
op_add = l->intern("+"_s);
|
||||
op_mul = l->intern("*"_s);
|
||||
op_div = l->intern("/"_s);
|
||||
op_sub = l->intern("-"_s);
|
||||
op_and = l->intern("&&"_s);
|
||||
op_bitand = l->intern("&"_s);
|
||||
op_or = l->intern("||"_s);
|
||||
op_bitor = l->intern("|"_s);
|
||||
op_xor = l->intern("^"_s);
|
||||
op_equals = l->intern("=="_s);
|
||||
op_not_equals = l->intern("!="_s);
|
||||
op_lesser_then_or_equal = l->intern("<="_s);
|
||||
op_greater_then_or_equal = l->intern(">="_s);
|
||||
op_lesser_then = l->intern("<"_s);
|
||||
op_greater_then = l->intern(">"_s);
|
||||
op_left_shift = l->intern("<<"_s);
|
||||
op_right_shift = l->intern(">>"_s);
|
||||
op_not = l->intern("!"_s);
|
||||
op_neg = l->intern("~"_s);
|
||||
op_decrement = l->intern("--"_s);
|
||||
op_increment = l->intern("++"_s);
|
||||
l->first_op = op_add;
|
||||
l->last_op = op_increment;
|
||||
}
|
||||
|
||||
function void
|
||||
|
||||
@@ -142,6 +142,9 @@ struct Lexer{
|
||||
S64 token_iter;
|
||||
U32 token_debug_ids;
|
||||
|
||||
Intern_String first_op;
|
||||
Intern_String last_op ;
|
||||
|
||||
Intern_String intern(String string){
|
||||
return intern_string(&interns, string);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ thread_local B32 emit_line_directives;
|
||||
Allocator *bigint_allocator;
|
||||
global S64 bigint_allocation_count;
|
||||
|
||||
global Token token_null = {SAME_SCOPE};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Interns / keywords
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -32,6 +34,28 @@ Intern_String intern_it;
|
||||
Intern_String intern_strict;
|
||||
Intern_String intern_flag;
|
||||
|
||||
Intern_String op_add;
|
||||
Intern_String op_mul;
|
||||
Intern_String op_div;
|
||||
Intern_String op_sub;
|
||||
Intern_String op_and;
|
||||
Intern_String op_bitand;
|
||||
Intern_String op_or;
|
||||
Intern_String op_bitor;
|
||||
Intern_String op_xor;
|
||||
Intern_String op_equals;
|
||||
Intern_String op_not_equals;
|
||||
Intern_String op_lesser_then_or_equal;
|
||||
Intern_String op_greater_then_or_equal;
|
||||
Intern_String op_lesser_then;
|
||||
Intern_String op_greater_then;
|
||||
Intern_String op_left_shift;
|
||||
Intern_String op_right_shift;
|
||||
Intern_String op_not;
|
||||
Intern_String op_neg;
|
||||
Intern_String op_decrement;
|
||||
Intern_String op_increment;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type globals
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -2,7 +2,6 @@ force_inline B32 token_is_assign(Token_Kind token){return token >= TK_FirstAssig
|
||||
force_inline B32 token_is_assign(Token *token){return token_is_assign(token->kind);}
|
||||
force_inline B32 token_is_compare(Token_Kind token){return token >= TK_FirstCompare && token <= TK_LastCompare;}
|
||||
force_inline B32 token_is_compare(Token *token){return token_is_compare(token->kind);}
|
||||
global Token token_null = {SAME_SCOPE};
|
||||
|
||||
function U8
|
||||
lexc(Lex_Stream *s){
|
||||
@@ -73,6 +72,12 @@ lex_is_keyword(Intern_Table *lexer, Intern_String keyword){
|
||||
return result;
|
||||
}
|
||||
|
||||
function B32
|
||||
is_valid_operator_overload(Lexer *lexer, Intern_String op){
|
||||
B32 result = op.str >= lexer->first_op.str && op.str <= lexer->last_op.str;
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
token_error(Token *t, String error_val){
|
||||
t->kind = TK_Error;
|
||||
|
||||
@@ -834,13 +834,30 @@ parse_decl(B32 is_global){
|
||||
if(expr->kind == AST_LAMBDA_EXPR){
|
||||
auto a = (Ast_Lambda *)expr;
|
||||
if(a->scope || is_flag_set(flags, AST_FOREIGN)){
|
||||
result->kind = AST_LAMBDA;
|
||||
if(is_flag_set(flags, AST_FOREIGN))
|
||||
set_flag(expr->flags, flags);
|
||||
result->kind = AST_LAMBDA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(token_match(TK_StringLit, TK_DoubleColon)){
|
||||
Ast_Lambda *expr = (Ast_Lambda *)parse_expr();
|
||||
if(expr->kind != AST_LAMBDA_EXPR){
|
||||
compiler_error(tname, "Operator overload is required to be a lambda function");
|
||||
}
|
||||
if(!expr->scope){
|
||||
compiler_error(tname, "Operator overload doesn't have body");
|
||||
}
|
||||
|
||||
if(!is_valid_operator_overload(pctx, tname->intern_val)){
|
||||
compiler_error(tname, "This operator cannot be overloaded");
|
||||
}
|
||||
|
||||
result = ast_const(tname, tname->intern_val, expr);
|
||||
result->kind = AST_LAMBDA;
|
||||
result->flags = set_flag(result->flags, AST_OPERATOR_OVERLOAD);
|
||||
}
|
||||
else if(token_match(TK_Identifier, TK_Colon)){
|
||||
Ast_Expr *typespec = parse_expr();
|
||||
Ast_Expr *expr = parse_assign_expr();
|
||||
|
||||
@@ -737,8 +737,7 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
|
||||
}
|
||||
|
||||
#define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s)
|
||||
function void
|
||||
_rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
||||
function void _rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
||||
auto ast = (Ast_Atom *)node;
|
||||
assert(ast_size >= sizeof(Ast_Atom));
|
||||
set_flag(ast->flags, AST_ATOM);
|
||||
|
||||
@@ -6,7 +6,8 @@ Vec2I :: struct;; x: S64; y: S64
|
||||
Vec2 :: struct;; x: F32; y: F32
|
||||
Vec3 :: struct;; x: F32; y: F32; z: F32
|
||||
|
||||
|
||||
"+" :: (a: Vec3, b: Vec3): Vec3
|
||||
return Vec3_Add(a,b)
|
||||
|
||||
Vec3_Cross :: (a: Vec3, b: Vec3): Vec3
|
||||
result := Vec3{
|
||||
|
||||
Reference in New Issue
Block a user