Skip to content

Commit 1f0228e

Browse files
committed
Address multiline header and floor division reviews
1 parent 89d3491 commit 1f0228e

3 files changed

Lines changed: 59 additions & 3 deletions

File tree

vibes/execution_values_arithmetic.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func divideValues(left, right Value) (Value, error) {
125125
if right.Int() == 0 {
126126
return NewNil(), errors.New("division by zero")
127127
}
128-
return NewInt(left.Int() / right.Int()), nil
128+
return NewInt(floorDivInt(left.Int(), right.Int())), nil
129129
case (left.Kind() == KindInt || left.Kind() == KindFloat) && (right.Kind() == KindInt || right.Kind() == KindFloat):
130130
if right.Float() == 0 {
131131
return NewNil(), errors.New("division by zero")
@@ -161,7 +161,7 @@ func moduloValues(left, right Value) (Value, error) {
161161
if right.Int() == 0 {
162162
return NewNil(), errors.New("modulo by zero")
163163
}
164-
return NewInt(left.Int() % right.Int()), nil
164+
return NewInt(floorModInt(left.Int(), right.Int())), nil
165165
}
166166
if left.Kind() == KindDuration && right.Kind() == KindDuration {
167167
if right.Duration().Seconds() == 0 {
@@ -172,6 +172,23 @@ func moduloValues(left, right Value) (Value, error) {
172172
return NewNil(), fmt.Errorf("unsupported modulo operands")
173173
}
174174

175+
func floorDivInt(left, right int64) int64 {
176+
quotient := left / right
177+
remainder := left % right
178+
if remainder != 0 && ((remainder < 0) != (right < 0)) {
179+
quotient--
180+
}
181+
return quotient
182+
}
183+
184+
func floorModInt(left, right int64) int64 {
185+
remainder := left % right
186+
if remainder != 0 && ((remainder < 0) != (right < 0)) {
187+
remainder += right
188+
}
189+
return remainder
190+
}
191+
175192
func compareValues(expr *BinaryExpr, left, right Value, cmp func(int) bool) (Value, error) {
176193
switch {
177194
case left.Kind() == KindInt && right.Kind() == KindInt:

vibes/parser_expressions.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (p *parser) parseExpressionWithLineLimit(precedence int, limitLine int, lin
2828
}
2929

3030
for p.peekToken.Type != tokenEOF && precedence < p.peekPrecedence() {
31-
if lineLimited && p.peekToken.Pos.Line > limitLine {
31+
if lineLimited && p.peekToken.Pos.Line > limitLine && !lineLimitedContinuationToken(p.peekToken.Type) {
3232
return left
3333
}
3434
infix := p.infixFns[p.peekToken.Type]
@@ -40,7 +40,19 @@ func (p *parser) parseExpressionWithLineLimit(precedence int, limitLine int, lin
4040
if left == nil {
4141
return nil
4242
}
43+
if lineLimited {
44+
limitLine = p.curToken.Pos.Line
45+
}
4346
}
4447

4548
return left
4649
}
50+
51+
func lineLimitedContinuationToken(tt TokenType) bool {
52+
switch tt {
53+
case tokenDot, tokenScope, tokenPlus, tokenSlash, tokenAsterisk, tokenPercent, tokenRange, tokenEQ, tokenNotEQ, tokenLT, tokenLTE, tokenGT, tokenGTE, tokenAnd, tokenOr:
54+
return true
55+
default:
56+
return false
57+
}
58+
}

vibes/runtime_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,8 +723,13 @@ func TestIntegerDivisionAndModulo(t *testing.T) {
723723
def arithmetic
724724
{
725725
int_div: 7 / 2,
726+
neg_div_left: -7 / 2,
727+
neg_div_right: 7 / -2,
728+
neg_div_both: -7 / -2,
726729
float_div: 7.0 / 2,
727730
mod_chain: 10 / 2 % 3,
731+
neg_mod_left: -7 % 2,
732+
neg_mod_right: 7 % -2,
728733
gcd: gcd(54, 24),
729734
hailstone: hailstone(7)
730735
}
@@ -739,12 +744,18 @@ func TestIntegerDivisionAndModulo(t *testing.T) {
739744
if !got["int_div"].Equal(NewInt(3)) {
740745
t.Fatalf("int_div mismatch: %v", got["int_div"])
741746
}
747+
if !got["neg_div_left"].Equal(NewInt(-4)) || !got["neg_div_right"].Equal(NewInt(-4)) || !got["neg_div_both"].Equal(NewInt(3)) {
748+
t.Fatalf("negative division mismatch: left=%v right=%v both=%v", got["neg_div_left"], got["neg_div_right"], got["neg_div_both"])
749+
}
742750
if got["float_div"].Kind() != KindFloat || got["float_div"].Float() != 3.5 {
743751
t.Fatalf("float_div mismatch: %v", got["float_div"])
744752
}
745753
if !got["mod_chain"].Equal(NewInt(2)) {
746754
t.Fatalf("mod_chain mismatch: %v", got["mod_chain"])
747755
}
756+
if !got["neg_mod_left"].Equal(NewInt(1)) || !got["neg_mod_right"].Equal(NewInt(-1)) {
757+
t.Fatalf("negative modulo mismatch: left=%v right=%v", got["neg_mod_left"], got["neg_mod_right"])
758+
}
748759
if !got["gcd"].Equal(NewInt(6)) {
749760
t.Fatalf("gcd mismatch: %v", got["gcd"])
750761
}
@@ -1134,6 +1145,16 @@ func TestLineTerminatedHeadersAndStatements(t *testing.T) {
11341145
end
11351146
end
11361147
1148+
def if_chain(values)
1149+
if values
1150+
.reverse
1151+
.include?(1)
1152+
"hit"
1153+
else
1154+
"miss"
1155+
end
1156+
end
1157+
11371158
def while_body
11381159
seen = []
11391160
i = 0
@@ -1191,6 +1212,12 @@ func TestLineTerminatedHeadersAndStatements(t *testing.T) {
11911212
t.Fatalf("if_hash expected hash, got %v", hashResult.Kind())
11921213
}
11931214
compareHash(t, hashResult.Hash(), map[string]Value{"a": NewInt(1)})
1215+
if got := callFunc(t, script, "if_chain", []Value{NewArray([]Value{NewInt(2), NewInt(1)})}); !got.Equal(NewString("hit")) {
1216+
t.Fatalf("if_chain hit mismatch: %v", got)
1217+
}
1218+
if got := callFunc(t, script, "if_chain", []Value{NewArray([]Value{NewInt(2)})}); !got.Equal(NewString("miss")) {
1219+
t.Fatalf("if_chain miss mismatch: %v", got)
1220+
}
11941221

11951222
compareArrays(t, callFunc(t, script, "while_body", nil), []Value{NewInt(0)})
11961223
compareArrays(t, callFunc(t, script, "until_body", nil), []Value{NewInt(0)})

0 commit comments

Comments
 (0)