Skip to content

Commit c3dc48c

Browse files
authored
perf: implement custom value to reduce memory allocation (#32)
* perf: value bool, int64 or float64 is no longer allocate * perf: reduce alloc by not concating prefix and suffix on value lookup * fix: misspell * tests: update unit tests
1 parent 1197f8e commit c3dc48c

19 files changed

+661
-528
lines changed

arithmetic.go

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ import (
2424

2525
func arithmetic(v, vx, vy *Visitor, binaryExpr *ast.BinaryExpr) {
2626
// numeric guards:
27-
if vx.kind <= numeric_beg || vx.kind >= numeric_end {
27+
if vx.value.Kind() <= numeric_beg || vx.value.Kind() >= numeric_end {
2828
v.err = newArithmeticNonNumericError(vx, binaryExpr.X)
2929
return
3030
}
31-
if vy.kind <= numeric_beg || vy.kind >= numeric_end {
31+
if vy.value.Kind() <= numeric_beg || vy.value.Kind() >= numeric_end {
3232
v.err = newArithmeticNonNumericError(vy, binaryExpr.Y)
3333
return
3434
}
3535

3636
switch v.options.numericType {
3737
case NumericTypeAuto:
38-
if vx.kind == KindImag || vy.kind == KindImag {
38+
if vx.value.Kind() == KindImag || vy.value.Kind() == KindImag {
3939
calculateComplex(v, parseComplex(vx.value), parseComplex(vy.value), binaryExpr.Op, binaryExpr.OpPos)
4040
return
4141
}
@@ -56,24 +56,25 @@ func arithmetic(v, vx, vy *Visitor, binaryExpr *ast.BinaryExpr) {
5656
func newArithmeticNonNumericError(v *Visitor, e ast.Expr) error {
5757
s := conv.FormatExpr(e)
5858
return &SyntaxError{
59-
Msg: "result of \"" + s + "\" is \"" + fmt.Sprintf("%v", v.value) + "\" which is not a number",
59+
Msg: "result of \"" + s + "\" is \"" + fmt.Sprintf("%v", v.value.Any()) + "\" which is not a number",
6060
Pos: v.pos,
6161
Err: ErrArithmeticOperation,
6262
}
6363
}
6464

6565
func calculateComplex(v *Visitor, x, y complex128, op token.Token, opPos token.Pos) {
66-
v.kind = KindImag
66+
v.value.SetKind(KindImag)
6767
switch op {
6868
case token.ADD:
69-
v.value = x + y
69+
v.value = complex128Value(x + y)
7070
case token.SUB:
71-
v.value = x - y
71+
v.value = complex128Value(x - y)
7272
case token.MUL:
73-
v.value = x * y
73+
v.value = complex128Value(x * y)
7474
case token.QUO:
75-
v.value = x / y
75+
v.value = complex128Value(x / y)
7676
case token.REM:
77+
v.value = value{}
7778
v.err = &SyntaxError{
7879
Msg: "operator \"" + op.String() + "\" is not supported to do arithmetic on complex number",
7980
Pos: int(opPos),
@@ -83,81 +84,82 @@ func calculateComplex(v *Visitor, x, y complex128, op token.Token, opPos token.P
8384
}
8485

8586
func calculateFloat(v *Visitor, x, y float64, op token.Token) {
86-
v.kind = KindFloat
87+
v.value.SetKind(KindFloat)
8788
switch op {
8889
case token.ADD:
89-
v.value = x + y
90+
v.value = float64Value(x + y)
9091
case token.SUB:
91-
v.value = x - y
92+
v.value = float64Value(x - y)
9293
case token.MUL:
93-
v.value = x * y
94+
v.value = float64Value(x * y)
9495
case token.QUO:
95-
v.value = x / y
96+
v.value = float64Value(x / y)
9697
case token.REM:
97-
v.value = math.Mod(x, y)
98+
v.value = float64Value(math.Mod(x, y))
9899
}
99100
}
100101

101102
func calculateInt(v *Visitor, x, y int64, yPos int, op token.Token) {
102-
v.kind = KindInt
103+
v.value.SetKind(KindInt)
103104
switch op {
104105
case token.ADD:
105-
v.value = x + y
106+
v.value = int64Value(x + y)
106107
case token.SUB:
107-
v.value = x - y
108+
v.value = int64Value(x - y)
108109
case token.MUL:
109-
v.value = x * y
110+
v.value = int64Value(x * y)
110111
case token.QUO:
111112
if y == 0 {
112113
if v.options.allowIntegerDividedByZero {
113-
v.value = int64(0)
114+
v.value = int64Value(0)
114115
return
115116
}
117+
v.value = value{}
116118
v.err = &SyntaxError{
117119
Msg: "could not divide x with zero y, allowIntegerDividedByZero == false",
118120
Pos: yPos,
119121
Err: ErrIntegerDividedByZero,
120122
}
121123
return
122124
}
123-
v.value = x / y
125+
v.value = int64Value(x / y)
124126
case token.REM:
125-
v.value = x % y
127+
v.value = int64Value(x % y)
126128
}
127129
}
128130

129-
func parseComplex(value interface{}) complex128 { // kind must be numeric
130-
switch val := value.(type) {
131-
case complex128:
132-
return val
133-
case float64:
134-
return complex(val, 0)
135-
case int64:
136-
return complex(float64(val), 0)
131+
func parseComplex(val value) complex128 { // kind must be numeric
132+
switch val.Kind() {
133+
case KindImag:
134+
return val.Complex128()
135+
case KindFloat:
136+
return complex(val.Float64(), 0)
137+
case KindInt:
138+
return complex(float64(val.Int64()), 0)
137139
}
138140
return 0
139141
}
140142

141-
func parseFloat(value interface{}) float64 {
142-
switch val := value.(type) {
143-
case complex128:
144-
return real(val)
145-
case float64:
146-
return val
147-
case int64:
148-
return float64(val)
143+
func parseFloat(val value) float64 {
144+
switch val.Kind() {
145+
case KindImag:
146+
return real(val.Complex128())
147+
case KindFloat:
148+
return val.Float64()
149+
case KindInt:
150+
return float64(val.Int64())
149151
}
150152
return 0
151153
}
152154

153-
func parseInt(value interface{}) int64 {
154-
switch val := value.(type) {
155-
case complex128:
156-
return int64(real(val))
157-
case float64:
158-
return int64(val)
159-
case int64:
160-
return val
155+
func parseInt(val value) int64 {
156+
switch val.Kind() {
157+
case KindImag:
158+
return int64(real(val.Complex128()))
159+
case KindFloat:
160+
return int64(val.Float64())
161+
case KindInt:
162+
return val.Int64()
161163
}
162164
return 0
163165
}

0 commit comments

Comments
 (0)