mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-27 16:53:55 +00:00
Add ## and ##= operators
This commit is contained in:
@@ -1995,6 +1995,12 @@ gb_internal bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Token_Concat:
|
||||
case Token_ConcatEq:
|
||||
if (!is_type_integer(type)) {
|
||||
error(op, "Operator '%.*s' is only allowed with integer expressions", LIT(op.string));
|
||||
}
|
||||
break;
|
||||
|
||||
case Token_Add:
|
||||
if (is_type_string(type)) {
|
||||
|
||||
@@ -1427,6 +1427,38 @@ handle_op:;
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case Token_Concat:
|
||||
{
|
||||
lbValue left = lb_emit_conv(p, lhs, type);
|
||||
lbValue right = lb_emit_conv(p, rhs, type);
|
||||
|
||||
lbValue ten = lb_const_int(p->module, type, 10);
|
||||
lbAddr pow = lb_add_local_generated(p, type, false);
|
||||
lb_addr_store(p, pow, ten);
|
||||
|
||||
lbBlock *loop = lb_create_block(p, "concat.loop");
|
||||
lbBlock *body = lb_create_block(p, "concat.body");
|
||||
lbBlock *done = lb_create_block(p, "concat.done");
|
||||
|
||||
lb_emit_jump(p, loop);
|
||||
lb_start_block(p, loop);
|
||||
|
||||
lbValue cond = lb_emit_comp(p, Token_GtEq, right, lb_addr_load(p, pow));
|
||||
|
||||
lb_emit_if(p, cond, body, done);
|
||||
lb_start_block(p, body);
|
||||
|
||||
lbValue pow_10 = lb_emit_arith(p, Token_Mul, lb_addr_load(p, pow), ten, type);
|
||||
lb_addr_store(p, pow, pow_10);
|
||||
|
||||
lb_emit_jump(p, loop);
|
||||
lb_start_block(p, done);
|
||||
|
||||
lbValue x = lb_emit_arith(p, Token_Mul, left, lb_addr_load(p, pow), type);
|
||||
return lb_emit_arith(p, Token_Add, x, right, type);
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("unhandled operator of lb_emit_arith");
|
||||
@@ -1517,7 +1549,9 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
|
||||
case Token_And:
|
||||
case Token_Or:
|
||||
case Token_Xor:
|
||||
case Token_AndNot: {
|
||||
case Token_AndNot:
|
||||
case Token_Concat:
|
||||
case Token_ConcatEq: {
|
||||
Type *type = default_type(tv.type);
|
||||
lbValue left = lb_build_expr(p, be->left);
|
||||
lbValue right = lb_build_expr(p, be->right);
|
||||
@@ -1604,6 +1638,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
|
||||
lbValue right = lb_build_expr(p, be->right);
|
||||
return lb_build_binary_in(p, left, right, be->op.kind);
|
||||
}
|
||||
|
||||
default:
|
||||
GB_PANIC("Invalid binary expression");
|
||||
break;
|
||||
|
||||
@@ -3490,6 +3490,7 @@ gb_internal i32 token_precedence(AstFile *f, TokenKind t) {
|
||||
case Token_AndNot:
|
||||
case Token_Shl:
|
||||
case Token_Shr:
|
||||
case Token_Concat:
|
||||
return 7;
|
||||
}
|
||||
return 0;
|
||||
@@ -3778,6 +3779,7 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
|
||||
case Token_AndNotEq:
|
||||
case Token_CmpAndEq:
|
||||
case Token_CmpOrEq:
|
||||
case Token_ConcatEq:
|
||||
{
|
||||
if (f->curr_proc == nullptr) {
|
||||
syntax_error(f->curr_token, "You cannot use a simple statement in the file scope");
|
||||
|
||||
@@ -33,6 +33,7 @@ TOKEN_KIND(Token__OperatorBegin, ""), \
|
||||
TOKEN_KIND(Token_AndNot, "&~"), \
|
||||
TOKEN_KIND(Token_Shl, "<<"), \
|
||||
TOKEN_KIND(Token_Shr, ">>"), \
|
||||
TOKEN_KIND(Token_Concat, "##"), \
|
||||
TOKEN_KIND(Token_CmpAnd, "&&"), \
|
||||
TOKEN_KIND(Token_CmpOr, "||"), \
|
||||
\
|
||||
@@ -49,6 +50,7 @@ TOKEN_KIND(Token__AssignOpBegin, ""), \
|
||||
TOKEN_KIND(Token_AndNotEq, "&~="), \
|
||||
TOKEN_KIND(Token_ShlEq, "<<="), \
|
||||
TOKEN_KIND(Token_ShrEq, ">>="), \
|
||||
TOKEN_KIND(Token_ConcatEq, "##="), \
|
||||
TOKEN_KIND(Token_CmpAndEq, "&&="), \
|
||||
TOKEN_KIND(Token_CmpOrEq, "||="), \
|
||||
TOKEN_KIND(Token__AssignOpEnd, ""), \
|
||||
@@ -937,7 +939,14 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) {
|
||||
break;
|
||||
case '#':
|
||||
token->kind = Token_Hash;
|
||||
if (t->curr_rune == '!') {
|
||||
if (t->curr_rune == '#') {
|
||||
advance_to_next_rune(t);
|
||||
token->kind = Token_Concat;
|
||||
if (t->curr_rune == '=') {
|
||||
advance_to_next_rune(t);
|
||||
token->kind = Token_ConcatEq;
|
||||
}
|
||||
} else if (t->curr_rune == '!') {
|
||||
token->kind = Token_Comment;
|
||||
tokenizer_skip_line(t);
|
||||
} else if (t->curr_rune == '+') {
|
||||
|
||||
Reference in New Issue
Block a user