fix unary compilation and add tests

This commit is contained in:
Neemek 2025-09-16 19:59:58 +02:00
parent f53ab30dbe
commit 4a0c315ccb
2 changed files with 81 additions and 7 deletions

View file

@ -991,6 +991,8 @@ func (c *Compiler) isTreeConstant(tree Node) bool {
} }
return true return true
case UnaryNodeType:
return c.isTreeConstant(tree.(*UnaryNode).value)
case BinaryNodeType: case BinaryNodeType:
return c.isTreeConstant(tree.(*BinaryNode).Left) && c.isTreeConstant(tree.(*BinaryNode).Right) return c.isTreeConstant(tree.(*BinaryNode).Left) && c.isTreeConstant(tree.(*BinaryNode).Right)
case CallNodeType: case CallNodeType:
@ -1051,9 +1053,26 @@ func (c *Compiler) compute(tree Node) (Value, error) {
return nil, err return nil, err
} }
return &NumberValue{ switch n.UnaryOperation {
-v.(*NumberValue).Number, case UnaryNegate:
}, nil if v.Type() != NumberValueType {
return nil, c.error(fmt.Sprintf("cannot negate %s value (not a number)", v.Type()), n)
}
return &NumberValue{
-v.(*NumberValue).Number,
}, nil
case UnaryNot:
if v.Type() != BoolValueType {
return nil, c.error(fmt.Sprintf("cannot invert %s value (not a boolean)", v.Type()), n)
}
return &BoolValue{
!v.(*BoolValue).Boolean,
}, nil
}
return nil, c.error(fmt.Sprintf("unimplemented unary %s", v.Type()), n)
case *CallNode: case *CallNode:
source, err := c.compute(n.source) source, err := c.compute(n.source)
@ -1101,10 +1120,6 @@ func (c *Compiler) computeBinary(n *BinaryNode) (Value, error) {
// perform type check // perform type check
switch n.BinaryOperation { switch n.BinaryOperation {
case BinaryAddition:
if l.Type() != StringValueType && l.Type() != NumberValueType && l.Type() != ListValueType {
return nil, c.error(fmt.Sprintf("cannot add values of type %s", l.Type()), n)
}
case BinarySubtraction, BinaryMultiplication, BinaryDivision, BinaryLess, BinaryGreater, BinaryLessEqual, BinaryGreaterEqual: case BinarySubtraction, BinaryMultiplication, BinaryDivision, BinaryLess, BinaryGreater, BinaryLessEqual, BinaryGreaterEqual:
if l.Type() != NumberValueType { if l.Type() != NumberValueType {
return nil, c.error(fmt.Sprintf("cannot do binary %s on non-number type %s", n.BinaryOperation, l.Type()), n) return nil, c.error(fmt.Sprintf("cannot do binary %s on non-number type %s", n.BinaryOperation, l.Type()), n)

View file

@ -534,6 +534,65 @@ func GetCompileTestData() map[string]CompileTestData {
}, },
}, },
}, },
"unary/negate": {
program: &Program{
[]string{},
&BlockNode{
[]Node{
&AssignNode{
name: "a",
value: &UnaryNode{
UnaryNegate,
&NumberNode{
1,
0, 0,
},
0, 0,
},
declare: true,
},
},
0, 0,
},
"",
},
expectedStack: []Value{
&VariableValue{
name: "a",
value: &NumberValue{-1},
scope: 0,
},
},
},
"unary/not": {
program: &Program{
[]string{},
&BlockNode{
[]Node{
&AssignNode{
name: "a",
value: &UnaryNode{
UnaryNot,
&BooleanNode{
value: true,
},
0, 0,
},
declare: true,
},
},
0, 0,
},
"",
},
expectedStack: []Value{
&VariableValue{
name: "a",
value: &BoolValue{false},
scope: 0,
},
},
},
} }
} }