mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 15:17:19 +00:00
Compound assign
This commit is contained in:
@@ -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
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user