Compound assign

This commit is contained in:
allexanderbergmns
2026-08-24 20:05:19 +02:00
parent 4b7a2f4c67
commit 7c7f4a69ff
3 changed files with 102 additions and 18 deletions
+20
View File
@@ -27,6 +27,10 @@ pub enum TokKind {
gt gt
ge ge
assign assign
plus_eq
minus_eq
star_eq
slash_eq
dotdot dotdot
dotdotdot dotdotdot
kw_fn kw_fn
@@ -172,18 +176,34 @@ fn (mut l Lexer) next() !Tok {
} }
`+` { `+` {
l.advance() l.advance()
if l.peek() == `=` {
l.advance()
return Tok{ kind: .plus_eq, lit: '+=', line: line }
}
return Tok{ kind: .plus, lit: '+', line: line } return Tok{ kind: .plus, lit: '+', line: line }
} }
`-` { `-` {
l.advance() l.advance()
if l.peek() == `=` {
l.advance()
return Tok{ kind: .minus_eq, lit: '-=', line: line }
}
return Tok{ kind: .minus, lit: '-', line: line } return Tok{ kind: .minus, lit: '-', line: line }
} }
`*` { `*` {
l.advance() l.advance()
if l.peek() == `=` {
l.advance()
return Tok{ kind: .star_eq, lit: '*=', line: line }
}
return Tok{ kind: .star, lit: '*', line: line } return Tok{ kind: .star, lit: '*', line: line }
} }
`/` { `/` {
l.advance() l.advance()
if l.peek() == `=` {
l.advance()
return Tok{ kind: .slash_eq, lit: '/=', line: line }
}
return Tok{ kind: .slash, lit: '/', line: line } return Tok{ kind: .slash, lit: '/', line: line }
} }
`%` { `%` {
+48 -18
View File
@@ -435,26 +435,56 @@ fn (mut p Parser) parse_stmt() !Stmt {
} else { } else {
e = p.parse_postfix_tail(Expr{ kind: .ident, name: t.lit, line: t.line })! e = p.parse_postfix_tail(Expr{ kind: .ident, name: t.lit, line: t.line })!
} }
if p.cur().kind == .assign { if p.cur().kind == .assign {
// assignment to an ident, an index, or a field // assignment to an ident, an index, or a field
p.advance() p.advance()
rhs := p.parse_expr()! rhs := p.parse_expr()!
match e.kind { match e.kind {
.ident { .ident {
return Stmt{ kind: .assign_stmt, target: e.name, expr: rhs, line: t.line } return Stmt{ kind: .assign_stmt, target: e.name, expr: rhs, line: t.line }
} }
.index { .index {
return Stmt{ kind: .index_assign, base: *e.left, idx: *e.right, expr: rhs, line: t.line } return Stmt{ kind: .index_assign, base: *e.left, idx: *e.right, expr: rhs, line: t.line }
} }
.field { .field {
return Stmt{ kind: .field_assign, base: *e.left, target: e.name, expr: rhs, line: t.line } return Stmt{ kind: .field_assign, base: *e.left, target: e.name, expr: rhs, line: t.line }
} }
else { else {
return error('cannot assign to this expression (line ${t.line})') return error('cannot assign to this expression (line ${t.line})')
}
} }
} }
return Stmt{ kind: .expr_stmt, expr: e, line: t.line } }
// compound assignment: x += expr, a[i] += expr, a.b += expr
if p.cur().kind == .plus_eq || p.cur().kind == .minus_eq || p.cur().kind == .star_eq || p.cur().kind == .slash_eq {
op_tok := p.advance()
rhs := p.parse_expr()!
bin_op := match op_tok.kind {
.plus_eq { TokKind.plus }
.minus_eq { TokKind.minus }
.star_eq { TokKind.star }
.slash_eq { TokKind.slash }
else { return error('unexpected compound operator (line ${t.line})') }
}
// desugar: LHS op= RHS → LHS = LHS op RHS
match e.kind {
.ident {
full_rhs := bin_node(bin_op, e, rhs, op_tok.line)
return Stmt{ kind: .assign_stmt, target: e.name, expr: full_rhs, line: t.line }
}
.index {
full_rhs := bin_node(bin_op, e, rhs, op_tok.line)
return Stmt{ kind: .index_assign, base: *e.left, idx: *e.right, expr: full_rhs, line: t.line }
}
.field {
full_rhs := bin_node(bin_op, e, rhs, op_tok.line)
return Stmt{ kind: .field_assign, base: *e.left, target: e.name, expr: full_rhs, line: t.line }
}
else {
return error('cannot use compound assignment on this expression (line ${t.line})')
}
}
}
return Stmt{ kind: .expr_stmt, expr: e, line: t.line }
} }
.kw_print, .kw_println { .kw_print, .kw_println {
p.advance() p.advance()
+34
View File
@@ -0,0 +1,34 @@
// compound assignment operators: +=, -=, *=, /=
fn main() {
let x = 10
println(x)
x += 5
println(x) // 15
x -= 3
println(x) // 12
x *= 2
println(x) // 24
x /= 4
println(x) // 6
// compound assignment on arrays (field access for structs/maps)
let m = { "count": 0 }
m["count"] += 1
println(m["count"]) // 1
m["count"] += 10
println(m["count"]) // 11
// compound assignment on array index
let arr = [10, 20, 30]
arr[1] += 5
println(arr[1]) // 25
arr[2] *= 3
println(arr[2]) // 90
}