Enable basic support for evaluating float types
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
from smnp.ast.node.atom import StringLiteral, IntegerLiteral, NoteLiteral, BoolLiteral, TypeLiteral
|
||||
from smnp.ast.node.atom import StringLiteral, IntegerLiteral, NoteLiteral, BoolLiteral, TypeLiteral, FloatLiteral
|
||||
from smnp.ast.node.identifier import Identifier
|
||||
from smnp.ast.node.list import List
|
||||
from smnp.ast.node.map import Map
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
from smnp.runtime.evaluators.float import FloatEvaluator
|
||||
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
|
||||
from smnp.runtime.tools.error import updatePos
|
||||
from smnp.type.model import Type
|
||||
@@ -85,6 +86,7 @@ class AtomEvaluator(Evaluator):
|
||||
return Evaluator.oneOf(
|
||||
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteral),
|
||||
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteral),
|
||||
Evaluator.forNodes(FloatEvaluator.evaluate, FloatLiteral),
|
||||
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteral),
|
||||
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteral),
|
||||
Evaluator.forNodes(TypeEvaluator.evaluate, TypeLiteral),
|
||||
|
||||
9
smnp/runtime/evaluators/float.py
Normal file
9
smnp/runtime/evaluators/float.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
from smnp.type.model import Type
|
||||
|
||||
|
||||
class FloatEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
return Type.float(node.value)
|
||||
@@ -11,6 +11,7 @@ class MinusEvaluator(Evaluator):
|
||||
try:
|
||||
return {
|
||||
Type.INTEGER: cls.evaluateForInteger,
|
||||
Type.FLOAT: cls.evaluateForFloat,
|
||||
Type.STRING: cls.evaluateForString,
|
||||
Type.LIST: cls.evaluateForList
|
||||
}[value.type](value.value)
|
||||
@@ -19,9 +20,12 @@ class MinusEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluateForInteger(cls, value):
|
||||
|
||||
return Type.integer(-value)
|
||||
|
||||
@classmethod
|
||||
def evaluateForFloat(cls, value):
|
||||
return Type.float(-value)
|
||||
|
||||
@classmethod
|
||||
def evaluateForString(cls, value):
|
||||
return Type.string(value[::-1])
|
||||
|
||||
@@ -10,11 +10,12 @@ class PowerEvaluator(Evaluator):
|
||||
def evaluator(cls, node, environment):
|
||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
||||
supportedTypes = [Type.INTEGER, Type.FLOAT]
|
||||
|
||||
if left.type != Type.INTEGER:
|
||||
raise RuntimeException( f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.left.pos)
|
||||
if not left.type in supportedTypes:
|
||||
raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.left.pos)
|
||||
|
||||
if right.type != Type.INTEGER:
|
||||
raise RuntimeException( f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.right.pos)
|
||||
if not right.type in supportedTypes:
|
||||
raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type", node.right.pos)
|
||||
|
||||
return Type.integer(int(left.value ** right.value))
|
||||
@@ -10,22 +10,36 @@ class ProductEvaluator(Evaluator):
|
||||
def evaluator(cls, node, environment):
|
||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
||||
supportedTypes = [Type.INTEGER, Type.FLOAT]
|
||||
|
||||
if left.type != Type.INTEGER:
|
||||
if not left.type in supportedTypes:
|
||||
raise RuntimeException(
|
||||
f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.left.pos)
|
||||
f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type", node.left.pos)
|
||||
|
||||
if right.type != Type.INTEGER:
|
||||
if not right.type in supportedTypes:
|
||||
raise RuntimeException(
|
||||
f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.right.pos)
|
||||
f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type", node.right.pos)
|
||||
|
||||
if node.operator.value == "*":
|
||||
return Type.integer(int(left.value * right.value))
|
||||
return getProperTypeProvider(left.value * right.value)
|
||||
|
||||
if node.operator.value == "/":
|
||||
if right.value == 0:
|
||||
raise RuntimeException("Attempt to divide by 0", node.right.pos)
|
||||
return Type.integer(int(left.value / right.value))
|
||||
|
||||
value = left.value / right.value
|
||||
|
||||
if left.type == right.type == Type.INTEGER and int(value) == value:
|
||||
return Type.integer(int(value))
|
||||
|
||||
return getProperTypeProvider(value)
|
||||
|
||||
raise RuntimeError("This line should never be reached")
|
||||
|
||||
|
||||
def getProperTypeProvider(value):
|
||||
return {
|
||||
int: lambda v: Type.integer(v),
|
||||
float: lambda v: Type.float(v)
|
||||
}[type(value)](value)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class RelationEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def otherRelationOperatorsEvaluator(cls, left, operator, right):
|
||||
if left.type == right.type == Type.INTEGER:
|
||||
if left.type in [Type.INTEGER, Type.FLOAT] and right.type in [Type.INTEGER, Type.FLOAT]:
|
||||
if operator.value == ">":
|
||||
return Type.bool(left.value > right.value)
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ class SumEvaluator(Evaluator):
|
||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
||||
|
||||
if left.type == right.type == Type.INTEGER:
|
||||
return cls.integerEvaluator(left, node.operator, right)
|
||||
if left.type in [Type.INTEGER, Type.FLOAT] and right.type in [Type.INTEGER, Type.FLOAT]:
|
||||
return cls.numberEvaluator(left, node.operator, right)
|
||||
|
||||
if left.type == right.type == Type.STRING:
|
||||
return cls.stringEvaluator(left, node.operator, right)
|
||||
@@ -23,15 +23,17 @@ class SumEvaluator(Evaluator):
|
||||
if left.type == right.type == Type.MAP:
|
||||
return cls.mapEvaluator(left, node.operator, right)
|
||||
|
||||
raise RuntimeException(f"Operator {node.operator.value} is not supported by {left.type.name.lower()} and {right.type.name.lower()} types", node.operator.pos)
|
||||
raise RuntimeException(
|
||||
f"Operator {node.operator.value} is not supported by {left.type.name.lower()} and {right.type.name.lower()} types",
|
||||
node.operator.pos)
|
||||
|
||||
@classmethod
|
||||
def integerEvaluator(cls, left, operator, right):
|
||||
def numberEvaluator(cls, left, operator, right):
|
||||
if operator.value == "+":
|
||||
return Type.integer(left.value + right.value)
|
||||
return getProperTypeProvider(left.value + right.value)
|
||||
|
||||
if operator.value == "-":
|
||||
return Type.integer(left.value - right.value)
|
||||
return getProperTypeProvider(left.value - right.value)
|
||||
|
||||
raise RuntimeError("This line should never be reached")
|
||||
|
||||
@@ -63,4 +65,11 @@ class SumEvaluator(Evaluator):
|
||||
if operator.value == "-":
|
||||
raise RuntimeException(f"Operator {operator.value} is not supported by map types", operator.pos)
|
||||
|
||||
raise RuntimeError("This line should never be reached")
|
||||
raise RuntimeError("This line should never be reached")
|
||||
|
||||
|
||||
def getProperTypeProvider(value):
|
||||
return {
|
||||
int: lambda v: Type.integer(v),
|
||||
float: lambda v: Type.float(v)
|
||||
}[type(value)](value)
|
||||
|
||||
@@ -8,6 +8,7 @@ from smnp.type.value import Value
|
||||
|
||||
class Type(Enum):
|
||||
INTEGER = (int, lambda x: str(x))
|
||||
FLOAT = (float, lambda x: str(x))
|
||||
STRING = (str, lambda x: x)
|
||||
LIST = (list, lambda x: f"[{', '.join([e.stringify() for e in x])}]")
|
||||
MAP = (dict, lambda x: '{' + ', '.join(f"'{k.stringify()}' -> '{v.stringify()}'" for k, v in x.items()) + '}')
|
||||
@@ -25,6 +26,10 @@ class Type(Enum):
|
||||
def integer(value):
|
||||
return Value(Type.INTEGER, value, {})
|
||||
|
||||
@staticmethod
|
||||
def float(value):
|
||||
return Value(Type.FLOAT, value, {})
|
||||
|
||||
@staticmethod
|
||||
def string(value):
|
||||
return Value(Type.STRING, value, {
|
||||
|
||||
Reference in New Issue
Block a user