Parsing operator overloads

This commit is contained in:
Krzosa Karol
2022-09-29 14:16:44 +02:00
parent a447d66015
commit 7ce3871a9e
8 changed files with 114 additions and 40 deletions

View File

@@ -64,6 +64,7 @@ enum{
AST_GLOBAL = bit_flag(10), AST_GLOBAL = bit_flag(10),
AST_FLAG = bit_flag(11), AST_FLAG = bit_flag(11),
AST_VAR_IS_CONST = bit_flag(12), AST_VAR_IS_CONST = bit_flag(12),
AST_OPERATOR_OVERLOAD = bit_flag(13),
}; };
struct Ast{ struct Ast{

View File

@@ -15,7 +15,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
l->tokens = array_make<Token>(token_string_arena, 1024*2); l->tokens = array_make<Token>(token_string_arena, 1024*2);
l->interns= intern_table_make(token_string_arena, map_allocator, 1024); l->interns= intern_table_make(token_string_arena, map_allocator, 1024);
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_true = l->intern("true"_s); keyword_true = l->intern("true"_s);
keyword_default = l->intern("default"_s); keyword_default = l->intern("default"_s);
@@ -36,11 +36,35 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
intern_sizeof = l->intern("SizeOf"_s); intern_sizeof = l->intern("SizeOf"_s);
intern_lengthof = l->intern("Length"_s); intern_lengthof = l->intern("Length"_s);
intern_alignof = l->intern("AlignOf"_s); intern_alignof = l->intern("AlignOf"_s);
intern_foreign = intern_string(&l->interns, "foreign"_s); intern_foreign = l->intern("foreign"_s);
intern_strict = intern_string(&l->interns, "strict"_s); intern_strict = l->intern("strict"_s);
intern_void = intern_string(&l->interns, "void"_s); intern_void = l->intern("void"_s);
intern_flag = intern_string(&l->interns, "flag"_s); intern_flag = l->intern("flag"_s);
intern_it = intern_string(&l->interns, "it"_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 function void

View File

@@ -142,6 +142,9 @@ struct Lexer{
S64 token_iter; S64 token_iter;
U32 token_debug_ids; U32 token_debug_ids;
Intern_String first_op;
Intern_String last_op ;
Intern_String intern(String string){ Intern_String intern(String string){
return intern_string(&interns, string); return intern_string(&interns, string);
} }

View File

@@ -4,6 +4,8 @@ thread_local B32 emit_line_directives;
Allocator *bigint_allocator; Allocator *bigint_allocator;
global S64 bigint_allocation_count; global S64 bigint_allocation_count;
global Token token_null = {SAME_SCOPE};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Interns / keywords // Interns / keywords
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -32,6 +34,28 @@ Intern_String intern_it;
Intern_String intern_strict; Intern_String intern_strict;
Intern_String intern_flag; 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 // Type globals
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -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_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_Kind token){return token >= TK_FirstCompare && token <= TK_LastCompare;}
force_inline B32 token_is_compare(Token *token){return token_is_compare(token->kind);} force_inline B32 token_is_compare(Token *token){return token_is_compare(token->kind);}
global Token token_null = {SAME_SCOPE};
function U8 function U8
lexc(Lex_Stream *s){ lexc(Lex_Stream *s){
@@ -73,6 +72,12 @@ lex_is_keyword(Intern_Table *lexer, Intern_String keyword){
return result; 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 function void
token_error(Token *t, String error_val){ token_error(Token *t, String error_val){
t->kind = TK_Error; t->kind = TK_Error;

View File

@@ -834,12 +834,29 @@ parse_decl(B32 is_global){
if(expr->kind == AST_LAMBDA_EXPR){ if(expr->kind == AST_LAMBDA_EXPR){
auto a = (Ast_Lambda *)expr; auto a = (Ast_Lambda *)expr;
if(a->scope || is_flag_set(flags, AST_FOREIGN)){ if(a->scope || is_flag_set(flags, AST_FOREIGN)){
result->kind = AST_LAMBDA;
if(is_flag_set(flags, AST_FOREIGN)) if(is_flag_set(flags, AST_FOREIGN))
set_flag(expr->flags, flags); set_flag(expr->flags, flags);
}
}
}
}
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->kind = AST_LAMBDA;
} result->flags = set_flag(result->flags, AST_OPERATOR_OVERLOAD);
}
}
} }
else if(token_match(TK_Identifier, TK_Colon)){ else if(token_match(TK_Identifier, TK_Colon)){
Ast_Expr *typespec = parse_expr(); Ast_Expr *typespec = parse_expr();

View File

@@ -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) #define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s)
function void function void _rewrite_into_const(Ast *node, U64 ast_size, Value value){
_rewrite_into_const(Ast *node, U64 ast_size, Value value){
auto ast = (Ast_Atom *)node; auto ast = (Ast_Atom *)node;
assert(ast_size >= sizeof(Ast_Atom)); assert(ast_size >= sizeof(Ast_Atom));
set_flag(ast->flags, AST_ATOM); set_flag(ast->flags, AST_ATOM);

View File

@@ -6,7 +6,8 @@ Vec2I :: struct;; x: S64; y: S64
Vec2 :: struct;; x: F32; y: F32 Vec2 :: struct;; x: F32; y: F32
Vec3 :: struct;; x: F32; y: F32; z: 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 Vec3_Cross :: (a: Vec3, b: Vec3): Vec3
result := Vec3{ result := Vec3{