Add ## and ##= operators

This commit is contained in:
gingerBill
2025-03-31 16:32:55 +01:00
parent 70ddb74e40
commit c1333d75ef
4 changed files with 54 additions and 2 deletions

View File

@@ -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)) {

View File

@@ -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;

View File

@@ -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");

View File

@@ -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 == '+') {