Parsing operator overloads
This commit is contained in:
@@ -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{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
Reference in New Issue
Block a user