separate number into float and integer
This commit is contained in:
parent
10f55313b0
commit
daab50d54c
22 changed files with 848 additions and 428 deletions
191
core/compiler.go
191
core/compiler.go
|
|
@ -2,6 +2,7 @@ package core
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -191,9 +192,13 @@ func (c *Compiler) compile(tree Node) error {
|
|||
tree.(*StringNode).value,
|
||||
})
|
||||
|
||||
case NumberNodeType:
|
||||
case FloatNodeType:
|
||||
c.add(InstructionConstant)
|
||||
c.addConstant(&NumberValue{tree.(*NumberNode).value})
|
||||
c.addConstant(&FloatValue{tree.(*FloatNode).value})
|
||||
|
||||
case IntegerNodeType:
|
||||
c.add(InstructionConstant)
|
||||
c.addConstant(&IntegerValue{tree.(*IntegerNode).value})
|
||||
|
||||
case ListNodeType:
|
||||
l := tree.(*ListNode)
|
||||
|
|
@ -243,9 +248,19 @@ func (c *Compiler) compile(tree Node) error {
|
|||
return err
|
||||
}
|
||||
|
||||
vt, err := c.deduceSignature(tree.(*UnaryNode).value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tree.(*UnaryNode).UnaryOperation {
|
||||
case UnaryNegate:
|
||||
c.add(InstructionNegate)
|
||||
if vt.Type() == TypeInteger {
|
||||
c.add(InstructionNegateInt)
|
||||
} else {
|
||||
c.add(InstructionNegateFloat)
|
||||
}
|
||||
|
||||
case UnaryNot:
|
||||
c.add(InstructionNot)
|
||||
}
|
||||
|
|
@ -593,38 +608,72 @@ func (c *Compiler) compileBinary(binary *BinaryNode) error {
|
|||
return err
|
||||
}
|
||||
|
||||
res, err := c.deduceSignature(binary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch binary.BinaryOperation {
|
||||
case BinaryAddition:
|
||||
res, err := c.deduceSignature(binary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if res.Type() == TypeString {
|
||||
c.add(InstructionStringConcatenation)
|
||||
} else if res.Type() == TypeList {
|
||||
c.add(InstructionConcatLists)
|
||||
} else if res.Type() == TypeFloat {
|
||||
c.add(InstructionAddFloat)
|
||||
} else if res.Type() == TypeInteger {
|
||||
c.add(InstructionAddInt)
|
||||
} else {
|
||||
c.add(InstructionAdd)
|
||||
return c.error("unimplemented binary compilation", binary)
|
||||
}
|
||||
case BinarySubtraction:
|
||||
c.add(InstructionSub)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionSubFloat)
|
||||
} else {
|
||||
c.add(InstructionSubInt)
|
||||
}
|
||||
case BinaryMultiplication:
|
||||
c.add(InstructionMul)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionMulFloat)
|
||||
} else {
|
||||
c.add(InstructionMulInt)
|
||||
}
|
||||
case BinaryDivision:
|
||||
c.add(InstructionDiv)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionDivFloat)
|
||||
} else {
|
||||
c.add(InstructionDivInt)
|
||||
}
|
||||
case BinaryEquality:
|
||||
c.add(InstructionEquals)
|
||||
case BinaryInequality:
|
||||
c.add(InstructionNotEqual)
|
||||
|
||||
case BinaryLess:
|
||||
c.add(InstructionLess)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionLessFloat)
|
||||
} else {
|
||||
c.add(InstructionLessInt)
|
||||
}
|
||||
case BinaryGreater:
|
||||
c.add(InstructionGreater)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionGreaterFloat)
|
||||
} else {
|
||||
c.add(InstructionGreaterInt)
|
||||
}
|
||||
case BinaryLessEqual:
|
||||
c.add(InstructionLessOrEqual)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionLessOrEqualFloat)
|
||||
} else {
|
||||
c.add(InstructionLessOrEqualInt)
|
||||
}
|
||||
case BinaryGreaterEqual:
|
||||
c.add(InstructionGreaterOrEqual)
|
||||
if res.Type() == TypeFloat {
|
||||
c.add(InstructionGreaterOrEqualFloat)
|
||||
} else {
|
||||
c.add(InstructionGreaterOrEqualInt)
|
||||
}
|
||||
|
||||
case BinaryAnd:
|
||||
c.add(InstructionAnd)
|
||||
case BinaryOr:
|
||||
|
|
@ -638,8 +687,10 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
|
|||
switch tree.Type() {
|
||||
case StringNodeType:
|
||||
return &StringSignature{}, nil
|
||||
case NumberNodeType:
|
||||
return &NumberSignature{}, nil
|
||||
case FloatNodeType:
|
||||
return &FloatSignature{}, nil
|
||||
case IntegerNodeType:
|
||||
return &IntegerSignature{}, nil
|
||||
case ReferenceNodeType:
|
||||
n := tree.(*ReferenceNode)
|
||||
sig, err := c.getVarSignature(n.name, n)
|
||||
|
|
@ -695,17 +746,23 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
|
|||
|
||||
switch n.BinaryOperation {
|
||||
case BinarySubtraction, BinaryMultiplication, BinaryDivision:
|
||||
if l.Type() != TypeNumber {
|
||||
return nil, c.error(fmt.Sprintf("cannot %s values of non-number type %s", n.BinaryOperation, l), n)
|
||||
if l.Type() == TypeInteger {
|
||||
return &IntegerSignature{}, nil
|
||||
}
|
||||
|
||||
return &NumberSignature{}, nil
|
||||
if l.Type() == TypeFloat {
|
||||
return &FloatSignature{}, nil
|
||||
}
|
||||
|
||||
return nil, c.error(fmt.Sprintf("cannot %s values of non-number type %s", n.BinaryOperation, l), n)
|
||||
case BinaryAddition:
|
||||
switch l.Type() {
|
||||
case TypeString:
|
||||
return &StringSignature{}, nil
|
||||
case TypeNumber:
|
||||
return &NumberSignature{}, nil
|
||||
case TypeInteger:
|
||||
return &IntegerSignature{}, nil
|
||||
case TypeFloat:
|
||||
return &FloatSignature{}, nil
|
||||
case TypeList:
|
||||
return &ListSignature{
|
||||
l.(*ListSignature).Contents,
|
||||
|
|
@ -722,7 +779,7 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
|
|||
case BinaryEquality, BinaryInequality:
|
||||
return &BooleanSignature{}, nil
|
||||
case BinaryLess, BinaryGreater, BinaryLessEqual, BinaryGreaterEqual:
|
||||
if l.Type() != TypeNumber {
|
||||
if l.Type() != TypeInteger && l.Type() != TypeFloat {
|
||||
return nil, c.error(fmt.Sprintf("cannot perform number comparison (%s) on non-number type %s", n.BinaryOperation, l), n)
|
||||
}
|
||||
|
||||
|
|
@ -852,10 +909,13 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
|
|||
|
||||
switch n.UnaryOperation {
|
||||
case UnaryNegate:
|
||||
if sig.Type() != TypeNumber {
|
||||
return nil, c.error(fmt.Sprintf("cannot perform negation on type %s (must be number)", n.UnaryOperation), n)
|
||||
if sig.Type() == TypeFloat {
|
||||
return &FloatSignature{}, nil
|
||||
} else if sig.Type() == TypeInteger {
|
||||
return &IntegerSignature{}, nil
|
||||
}
|
||||
return &NumberSignature{}, nil
|
||||
|
||||
return nil, c.error(fmt.Sprintf("cannot perform negation on type %s (must be number)", n.UnaryOperation), n)
|
||||
case UnaryNot:
|
||||
if sig.Type() != TypeBoolean {
|
||||
return nil, c.error(fmt.Sprintf("cannot perform negation on type %s (must be boolean)", n.UnaryOperation), n)
|
||||
|
|
@ -1040,7 +1100,7 @@ func (c *Compiler) isLocal(name string) bool {
|
|||
// isTreeConstant check if a node tree is constant (predictable)
|
||||
func (c *Compiler) isTreeConstant(tree Node) bool {
|
||||
switch tree.Type() {
|
||||
case StringNodeType, NumberNodeType, BooleanNodeType, NilNodeType:
|
||||
case StringNodeType, FloatNodeType, IntegerNodeType, BooleanNodeType, NilNodeType:
|
||||
return true
|
||||
case ListNodeType:
|
||||
for _, item := range tree.(*ListNode).items {
|
||||
|
|
@ -1076,8 +1136,13 @@ func (c *Compiler) compute(tree Node) (Value, error) {
|
|||
n.value,
|
||||
}, nil
|
||||
|
||||
case *NumberNode:
|
||||
return &NumberValue{
|
||||
case *FloatNode:
|
||||
return &FloatValue{
|
||||
n.value,
|
||||
}, nil
|
||||
|
||||
case *IntegerNode:
|
||||
return &IntegerValue{
|
||||
n.value,
|
||||
}, nil
|
||||
|
||||
|
|
@ -1114,13 +1179,17 @@ func (c *Compiler) compute(tree Node) (Value, error) {
|
|||
|
||||
switch n.UnaryOperation {
|
||||
case UnaryNegate:
|
||||
if v.Type() != NumberValueType {
|
||||
return nil, c.error(fmt.Sprintf("cannot negate %s value (not a number)", v.Type()), n)
|
||||
if v.Type() == FloatValueType {
|
||||
return &FloatValue{
|
||||
-v.(*FloatValue).Number,
|
||||
}, nil
|
||||
} else if v.Type() == IntegerValueType {
|
||||
return &IntegerValue{
|
||||
new(big.Int).Neg(v.(*IntegerValue).Number),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &NumberValue{
|
||||
-v.(*NumberValue).Number,
|
||||
}, nil
|
||||
return nil, c.error(fmt.Sprintf("cannot negate %s value (not a number)", v.Type()), n)
|
||||
case UnaryNot:
|
||||
if v.Type() != BoolValueType {
|
||||
return nil, c.error(fmt.Sprintf("cannot invert %s value (not a boolean)", v.Type()), n)
|
||||
|
|
@ -1180,7 +1249,7 @@ func (c *Compiler) computeBinary(n *BinaryNode) (Value, error) {
|
|||
// perform type check
|
||||
switch n.BinaryOperation {
|
||||
case BinarySubtraction, BinaryMultiplication, BinaryDivision, BinaryLess, BinaryGreater, BinaryLessEqual, BinaryGreaterEqual:
|
||||
if l.Type() != NumberValueType {
|
||||
if l.Type() != FloatValueType && l.Type() != IntegerValueType {
|
||||
return nil, c.error(fmt.Sprintf("cannot %s values of non-number type %s", n.BinaryOperation, l.Type()), n)
|
||||
}
|
||||
case BinaryAnd, BinaryOr:
|
||||
|
|
@ -1196,37 +1265,67 @@ func (c *Compiler) computeBinary(n *BinaryNode) (Value, error) {
|
|||
switch n.BinaryOperation {
|
||||
case BinaryAddition:
|
||||
switch l.Type() {
|
||||
case NumberValueType:
|
||||
v = l.(*NumberValue).Number + r.(*NumberValue).Number
|
||||
case FloatValueType:
|
||||
v = l.(*FloatValue).Number + r.(*FloatValue).Number
|
||||
case StringValueType:
|
||||
v = l.(*StringValue).Text + r.(*StringValue).Text
|
||||
case ListValueType:
|
||||
v = append(l.(*ListValue).Items, r.(*ListValue).Items...)
|
||||
case IntegerValueType:
|
||||
v = new(big.Int).Add(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
|
||||
default:
|
||||
return nil, c.error(fmt.Sprintf("cannot add values of type %s", l.Type()), n)
|
||||
}
|
||||
case BinarySubtraction:
|
||||
v = l.(*NumberValue).Number - r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number - r.(*FloatValue).Number
|
||||
} else {
|
||||
v = new(big.Int).Sub(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
|
||||
}
|
||||
case BinaryMultiplication:
|
||||
v = l.(*NumberValue).Number * r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number * r.(*FloatValue).Number
|
||||
} else {
|
||||
v = new(big.Int).Mul(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
|
||||
}
|
||||
case BinaryDivision:
|
||||
v = l.(*NumberValue).Number / r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number / r.(*FloatValue).Number
|
||||
} else {
|
||||
v = new(big.Int).Div(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
|
||||
}
|
||||
case BinaryAnd:
|
||||
v = l.(*BoolValue).Boolean && r.(*BoolValue).Boolean
|
||||
case BinaryOr:
|
||||
v = l.(*BoolValue).Boolean && r.(*BoolValue).Boolean
|
||||
v = l.(*BoolValue).Boolean || r.(*BoolValue).Boolean
|
||||
case BinaryEquality:
|
||||
v = l.Equals(r)
|
||||
case BinaryInequality:
|
||||
v = !l.Equals(r)
|
||||
case BinaryLess:
|
||||
v = l.(*NumberValue).Number < r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number < r.(*FloatValue).Number
|
||||
} else {
|
||||
v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) == -1
|
||||
}
|
||||
case BinaryGreater:
|
||||
v = l.(*NumberValue).Number > r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number > r.(*FloatValue).Number
|
||||
} else {
|
||||
v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) == 1
|
||||
}
|
||||
case BinaryLessEqual:
|
||||
v = l.(*NumberValue).Number <= r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number <= r.(*FloatValue).Number
|
||||
} else {
|
||||
v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) != 1
|
||||
}
|
||||
case BinaryGreaterEqual:
|
||||
v = l.(*NumberValue).Number >= r.(*NumberValue).Number
|
||||
if l.Type() == FloatValueType {
|
||||
v = l.(*FloatValue).Number >= r.(*FloatValue).Number
|
||||
} else {
|
||||
v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) != 1
|
||||
}
|
||||
}
|
||||
|
||||
return GoToValue(v), nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue