Skip to content

Commit 77caca1

Browse files
committed
fix: refactored grammar of prefix negation
1 parent 06a7199 commit 77caca1

18 files changed

+609
-400
lines changed

Lexer.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ PERCENTAGE_PORTION_LITERAL: [0-9]+ ('.' [0-9]+)? '%';
3838
STRING: '"' ('\\"' | ~[\r\n"])* '"';
3939
4040
IDENTIFIER: [a-z]+ [a-z_]*;
41-
NUMBER: MINUS? [0-9]+ ('_' [0-9]+)*;
41+
NUMBER: [0-9]+ ('_' [0-9]+)*;
4242
ASSET: [A-Z][A-Z0-9]* ('/' [0-9]+)?;
4343
4444
ACCOUNT_START: '@' -> pushMode(ACCOUNT_MODE);

Numscript.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ valueExpr:
1919
| NUMBER # numberLiteral
2020
| PERCENTAGE_PORTION_LITERAL # percentagePortionLiteral
2121
| monetaryLit # monetaryLiteral
22+
| op=MINUS valueExpr # prefixExpr
2223
| left = valueExpr op = DIV right = valueExpr # infixExpr
2324
| left = valueExpr op = (PLUS | MINUS) right = valueExpr # infixExpr
2425
| LPARENS valueExpr RPARENS # parenthesizedExpr

internal/analysis/hover.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ func hoverOnExpression(lit parser.ValueExpr, position parser.Position) Hover {
183183
return hover
184184
}
185185

186+
case *parser.Prefix:
187+
return hoverOnExpression(lit.Expr, position)
188+
186189
case *parser.FnCall:
187190
return hoverOnFnCall(*lit, position)
188191
}

internal/interpreter/evaluate_expr.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ func (st *programState) evaluateExpr(expr parser.ValueExpr) (Value, InterpreterE
6969
return value, nil
7070

7171
case *parser.BinaryInfix:
72-
7372
switch expr.Operator {
7473
case parser.InfixOperatorPlus:
7574
return st.plusOp(expr.Left, expr.Right)
@@ -85,6 +84,16 @@ func (st *programState) evaluateExpr(expr parser.ValueExpr) (Value, InterpreterE
8584
return nil, nil
8685
}
8786

87+
case *parser.Prefix:
88+
switch expr.Operator {
89+
case parser.PrefixOperator(parser.PrefixOperatorMinus):
90+
return st.unaryNegOp(expr.Expr)
91+
92+
default:
93+
utils.NonExhaustiveMatchPanic[any](expr.Operator)
94+
return nil, nil
95+
}
96+
8897
case *parser.FnCall:
8998
if !st.varOriginPosition {
9099
err := st.checkFeatureFlag(flags.ExperimentalMidScriptFunctionCall)
@@ -214,6 +223,25 @@ func (st *programState) divOp(rng parser.Range, left parser.ValueExpr, right par
214223
return Portion(*rat), nil
215224
}
216225

226+
func (st *programState) unaryNegOp(expr parser.ValueExpr) (Value, InterpreterError) {
227+
evExpr, err := evaluateExprAs(st, expr, expectOneOf(
228+
expectMapped(expectMonetary, func(m Monetary) opNeg {
229+
return m
230+
}),
231+
232+
// while "x.map(identity)" is the same as "x", just writing "expectNumber" would't typecheck
233+
expectMapped(expectNumber, func(bi big.Int) opNeg {
234+
return MonetaryInt(bi)
235+
}),
236+
))
237+
238+
if err != nil {
239+
return nil, err
240+
}
241+
242+
return (*evExpr).evalNeg(st)
243+
}
244+
217245
func castToString(v Value, rng parser.Range) (string, InterpreterError) {
218246
switch v := v.(type) {
219247
case AccountAddress:

internal/interpreter/infix_overloads.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,26 @@ func (m Monetary) evalSub(st *programState, other parser.ValueExpr) (Value, Inte
8080
}, nil
8181

8282
}
83+
84+
type opNeg interface {
85+
evalNeg(st *programState) (Value, InterpreterError)
86+
}
87+
88+
var _ opNeg = (*MonetaryInt)(nil)
89+
var _ opNeg = (*Monetary)(nil)
90+
91+
func (m MonetaryInt) evalNeg(st *programState) (Value, InterpreterError) {
92+
m1 := big.Int(m)
93+
neg := new(big.Int).Neg(&m1)
94+
return MonetaryInt(*neg), nil
95+
}
96+
97+
func (m Monetary) evalNeg(st *programState) (Value, InterpreterError) {
98+
m1 := big.Int(m.Amount)
99+
neg := new(big.Int).Neg(&m1)
100+
return Monetary{
101+
Asset: m.Asset,
102+
Amount: MonetaryInt(*neg),
103+
}, nil
104+
105+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
send [EUR/2 100] - [EUR/2 1] (
2+
source = @world
3+
destination = @dest
4+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/formancehq/numscript/main/specs.schema.json",
3+
"testCases": [
4+
{
5+
"it": "should subtract the monetaries",
6+
"expect.postings": [
7+
{
8+
"source": "world",
9+
"destination": "dest",
10+
"amount": 99,
11+
"asset": "EUR/2"
12+
}
13+
]
14+
}
15+
]
16+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
send [EUR/2 100-1] (
2+
source = @world
3+
destination = @dest
4+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/formancehq/numscript/main/specs.schema.json",
3+
"testCases": [
4+
{
5+
"it": "should subtract the numbers",
6+
"expect.postings": [
7+
{
8+
"source": "world",
9+
"destination": "dest",
10+
"amount": 99,
11+
"asset": "EUR/2"
12+
}
13+
]
14+
}
15+
]
16+
}

internal/parser/__snapshots__/parser_test.snap

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,12 +2173,19 @@ parser.Program{
21732173
},
21742174
Asset: "EUR/2",
21752175
},
2176-
Amount: &parser.NumberLiteral{
2176+
Amount: &parser.Prefix{
21772177
Range: parser.Range{
21782178
Start: parser.Position{Character:12, Line:0},
21792179
End: parser.Position{Character:16, Line:0},
21802180
},
2181-
Number: -100,
2181+
Operator: "-",
2182+
Expr: &parser.NumberLiteral{
2183+
Range: parser.Range{
2184+
Start: parser.Position{Character:13, Line:0},
2185+
End: parser.Position{Character:16, Line:0},
2186+
},
2187+
Number: 100,
2188+
},
21822189
},
21832190
},
21842191
},

0 commit comments

Comments
 (0)