Enable basic support for evaluating float types

This commit is contained in:
Bartłomiej Pluta
2019-07-25 13:37:31 +02:00
parent 6dc503ba86
commit b126f83824
8 changed files with 64 additions and 20 deletions

View File

@@ -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),

View 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)

View File

@@ -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])

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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, {