From 7ce3871a9e88c6db7e8f62cf3adb56ce0f23c79b Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 29 Sep 2022 14:16:44 +0200 Subject: [PATCH] Parsing operator overloads --- core_ast.cpp | 25 ++++++++-------- core_compiler.cpp | 70 +++++++++++++++++++++++++++++-------------- core_compiler.h | 3 ++ core_globals.cpp | 24 +++++++++++++++ core_lexing.cpp | 7 ++++- core_parsing.cpp | 19 +++++++++++- core_typechecking.cpp | 3 +- modules/math.kl | 3 +- 8 files changed, 114 insertions(+), 40 deletions(-) diff --git a/core_ast.cpp b/core_ast.cpp index 71471b4..e9837bc 100644 --- a/core_ast.cpp +++ b/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{ diff --git a/core_compiler.cpp b/core_compiler.cpp index 37dcfea..3db3768 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -15,32 +15,56 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ l->tokens = array_make(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 diff --git a/core_compiler.h b/core_compiler.h index 90dfbd2..78df2e3 100644 --- a/core_compiler.h +++ b/core_compiler.h @@ -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); } diff --git a/core_globals.cpp b/core_globals.cpp index 19e37bb..72f989e 100644 --- a/core_globals.cpp +++ b/core_globals.cpp @@ -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 //----------------------------------------------------------------------------- diff --git a/core_lexing.cpp b/core_lexing.cpp index 8e4966a..c3f7fb3 100644 --- a/core_lexing.cpp +++ b/core_lexing.cpp @@ -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; diff --git a/core_parsing.cpp b/core_parsing.cpp index c1c3904..97fb240 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -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(); diff --git a/core_typechecking.cpp b/core_typechecking.cpp index cae2db6..9466d3a 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -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); diff --git a/modules/math.kl b/modules/math.kl index da81c21..00591b4 100644 --- a/modules/math.kl +++ b/modules/math.kl @@ -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{