示例#1
0
    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 not left.type in supportedTypes:
            raise RuntimeException(
                f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type",
                node.left.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)

        if node.operator.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)

            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")
示例#2
0
def getValueAccordingToType(value, type):
    try:
        if type.value == Type.STRING:
            return Type.string(value)

        if type.value == Type.INTEGER:
            return Type.integer(int(value))

        if type.value == Type.BOOL:
            consumedChars, token = boolTokenizer(value, 0, 0)
            if consumedChars > 0:
                return Type.bool(token.value)

            return ValueError()

        if type.value == Type.NOTE:
            consumedChars, token = noteTokenizer(value, 0, 0)
            if consumedChars > 0:
                return Type.note(token.value)

            raise ValueError()

        raise RuntimeException(
            f"Type {type.value.name.lower()} is not supported", None)

    except ValueError:
        raise RuntimeException(
            f"Invalid value '{value}' for type {type.value.name.lower()}",
            None)
示例#3
0
    def mapEvaluator(cls, node, environment, evaluatedIterator, parameters,
                     filter):
        output = []

        if len(parameters) > 3:
            raise RuntimeException(
                f"Loop with map iterator can handle only three parameters",
                node.parameters.pos)

        i = 0
        for key, value in evaluatedIterator.value.items():
            if len(parameters) == 1:
                environment.scopes[-1][parameters[0]] = value
            if len(parameters) == 2:
                environment.scopes[-1][parameters[0]] = key
                environment.scopes[-1][parameters[1]] = value
            if len(parameters) == 3:
                environment.scopes[-1][parameters[0]] = Type.integer(i)
                environment.scopes[-1][parameters[1]] = key
                environment.scopes[-1][parameters[2]] = value
                i += 1

            if cls.doFilter(filter, environment):
                output.append(evaluate(node.right, environment).value)

        return output
示例#4
0
    def evaluator(cls, node, environment):
        value = expressionEvaluator(doAssert=True)(node.value, environment).value

        if value.type != Type.BOOL:
            raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {Type.BOOL.name.lower()} type", node.value.pos)

        return Type.bool(not value.value)
示例#5
0
def evaluate(node, environment):
    from smnp.runtime.evaluators.program import ProgramEvaluator
    from smnp.runtime.evaluators.expression import expressionEvaluator
    from smnp.runtime.evaluators.condition import IfElseStatementEvaluator
    from smnp.runtime.evaluators.block import BlockEvaluator
    from smnp.runtime.evaluators.imports import ImportEvaluator
    from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
    from smnp.runtime.evaluators.function import ReturnEvaluator
    from smnp.runtime.evaluators.extend import ExtendEvaluator
    from smnp.runtime.evaluators.throw import ThrowEvaluator

    result = Evaluator.oneOf(
        Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
        Evaluator.forNodes(IfElseStatementEvaluator.evaluate, IfElse),
        Evaluator.forNodes(BlockEvaluator.evaluate, Block),
        Evaluator.forNodes(ImportEvaluator.evaluate, Import),
        Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate,
                           FunctionDefinition),
        Evaluator.forNodes(ReturnEvaluator.evaluate, Return),
        Evaluator.forNodes(ExtendEvaluator.evaluate, Extend),
        Evaluator.forNodes(ThrowEvaluator.evaluate, Throw),
        #Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
        #Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
        #Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
        #Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
        #Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
        expressionEvaluator())(node, environment)

    if not result.result:
        raise RuntimeException("Cannot evaluate program", node.pos)

    return result
示例#6
0
def getTuning(config):
    key = Type.string("tuning")
    if key in config.value:
        tuning = config.value[key]
        if not tuning.type in [Type.INTEGER, Type.FLOAT] or tuning.value < 0:
            raise RuntimeException("The 'tuning' property must be non-negative integer or float", None)

        return tuning.value

    return DEFAULT_TUNING
示例#7
0
def getAttack(config):
    key = Type.string("attack")
    if key in config.value:
        attack = config.value[key]
        if not attack.type in [Type.INTEGER, Type.FLOAT] or attack.value < 0:
            raise RuntimeException("The 'attack' property must be non-negative integer or float", None)

        return attack.value

    return DEFAULT_ATTACK
示例#8
0
def getDecay(config):
    key = Type.string("decay")
    if key in config.value:
        decay = config.value[key]
        if not decay.type in [Type.INTEGER, Type.FLOAT] or decay.value < 0:
            raise RuntimeException("The 'decay' property must be non-negative integer or float", None)

        return decay.value

    return DEFAULT_DECAY
示例#9
0
def getBpm(config):
    key = Type.string("bpm")
    if key in config.value:
        bpm = config.value[key]
        if bpm.type != Type.INTEGER or bpm.value <= 0:
            raise RuntimeException("The 'bpm' property must be positive integer", None)

        return bpm.value

    return DEFAULT_BPM
示例#10
0
    def addCustomFunction(self, name, signature, arguments, body,
                          defaultArguments):
        if len([
                fun for fun in self.functions + self.customFunctions
                if fun.name == name
        ]) > 0:
            raise RuntimeException(f"Cannot redeclare function '{name}'", None)

        self.customFunctions.append(
            CustomFunction(name, signature, arguments, body, defaultArguments))
示例#11
0
    def evaluator(cls, node, environment):
        string = expressionEvaluator(doAssert=True)(node.value,
                                                    environment).value

        if string.type != Type.STRING:
            raise RuntimeException(
                f"Only {Type.STRING.name.lower()} types can be thrown",
                node.value.pos)

        raise CustomException(string.value, node.pos)
示例#12
0
    def mapEvaluator(cls, left, operator, right):
        if operator.value == "+":
            return Type.map({**left.value, **right.value})

        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")
示例#13
0
    def listEvaluator(cls, left, operator, right):
        if operator.value == "+":
            return Type.list(left.value + right.value)

        if operator.value == "-":
            raise RuntimeException(
                f"Operator {operator.value} is not supported by list types",
                operator.pos)

        raise RuntimeError("This line should never be reached")
示例#14
0
def getOvertones(config):
    key = Type.string("overtones")
    if key in config.value:
        overtones = config.value[key]
        rawOvertones = [overtone.value for overtone in overtones.value]
        if overtones.type != Type.LIST or not all(overtone.type in [Type.FLOAT, Type.INTEGER] for overtone in overtones.value):
            raise RuntimeException("The 'overtones' property must be list of floats", None)

        if len(rawOvertones) < 1:
            raise RuntimeException("The 'overtones' property must contain one overtone at least", None)

        if any(overtone < 0 for overtone in rawOvertones):
            raise RuntimeException("The 'overtones' property mustn't contain negative values", None)

        if sum(rawOvertones) > 1.0:
            raise RuntimeException("The 'overtones' property must contain overtones which sum is not greater than 1.0", None)

        return rawOvertones

    return DEFAULT_OVERTONES
示例#15
0
 def findVariable(self, name, type=None, pos=None):
     for scope in reversed(self.scopes):
         if name in scope:
             value = scope[name]
             if type is not None:
                 if isinstance(value, type):
                     return value
             else:
                 return value
     raise RuntimeException(
         f"Variable '{name}' is not declared" +
         ("" if type is None else f" (expected type: {type})"), pos)
示例#16
0
    def doFilter(cls, filter, environment):
        if type(filter) is not NoneNode:
            evaluation = expressionEvaluator(doAssert=True)(filter,
                                                            environment).value
            if evaluation.type != Type.BOOL:
                raise RuntimeException(
                    f"Expected {Type.BOOL.name.lower()} as filter expression, found {evaluation.type.name.lower()}",
                    filter.pos)

            return evaluation.value

        return True
示例#17
0
    def addCustomMethod(self, typeSignature, alias, name, signature, arguments,
                        body, defaultArguments):
        if len([
                m for m in self.methods if m.name == name
                and m.signature.matchers[0] == typeSignature.matchers[0]
        ]) > 0:
            raise RuntimeException(
                f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'",
                None)

        if len([
                m for m in self.customMethods if m.name == name
                and m.typeSignature.matchers[0] == typeSignature.matchers[0]
        ]) > 0:
            raise RuntimeException(
                f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'",
                None)

        self.customMethods.append(
            CustomMethod(typeSignature, alias, name, signature, arguments,
                         body, defaultArguments))
示例#18
0
 def evaluator(cls, node, environment):
     value = evaluate(node.value, environment).value
     try:
         return {
             Type.INTEGER: cls.evaluateForInteger,
             Type.FLOAT: cls.evaluateForFloat,
             Type.STRING: cls.evaluateForString,
             Type.LIST: cls.evaluateForList
         }[value.type](value.value)
     except KeyError:
         raise RuntimeException(
             f"Type {value.type.name.lower()} does not support '{node.operator.value}' operator",
             node.pos)
示例#19
0
    def evaluator(cls, node, environment):
        map = {}
        keyEvaluator = Evaluator.oneOf(
            Evaluator.forNodes(lambda node, environment: EvaluationResult.OK(Type.string(node.value)), Identifier),
            expressionEvaluator(doAssert=True)
        )
        for entry in node.children:
            key = keyEvaluator(entry.key, environment).value
            if key in map:
                raise RuntimeException(f"Duplicated key '{key.stringify()}' found in map", entry.pos)
            map[key] = expressionEvaluator(doAssert=True)(entry.value, environment).value

        return Type.map(map)
示例#20
0
    def evaluator(cls, node, environment):
        condition = expressionEvaluator(doAssert=True)(node.condition,
                                                       environment).value

        if condition.type != Type.BOOL:
            raise RuntimeException(
                f"Only {Type.BOOL.name.lower()} types can be used as conditions in conditional expression",
                node.condition.pos)

        if condition.value:
            evaluate(node.ifNode, environment)
        else:
            evaluate(node.elseNode, environment)
示例#21
0
 def evaluator(cls, node, environment):
     if len(environment.callStack) > 0:
         returnValue = expressionEvaluator()(node.value, environment).value
         raise Return(returnValue)
         # Disclaimer
         # Exception system usage to control program execution flow is really bad idea.
         # However because of lack of 'goto' instruction equivalent in Python
         # there is a need to use some mechanism to break function execution on 'return' statement
         # and immediately go to Environment's method 'invokeFunction()' or 'invokeMethod()',
         # which can handle value that came with exception and return it to code being executed.
     else:
         raise RuntimeException(
             "Cannot use 'return' statement outside a function or method",
             node.pos, environment)
示例#22
0
    def boolEvaluator(cls, node, environment, evaluatedIterator, parameters,
                      filter):
        output = []

        if len(parameters) > 0:
            raise RuntimeException(
                f"Loop with logic iterator can't' handle any parameters",
                node.parameters.pos)

        condition = evaluatedIterator
        while condition.value:
            if cls.doFilter(filter, environment):
                output.append(evaluate(node.right, environment).value)
            condition = expressionEvaluator(doAssert=True)(node.left,
                                                           environment).value

        return output
示例#23
0
    def numberEvaluator(cls, node, environment, evaluatedIterator, parameters,
                        filter):
        output = []

        if len(parameters) > 1:
            raise RuntimeException(
                f"Loop with numeric iterator can handle only one parameter",
                node.parameters.pos)

        for i in range(evaluatedIterator.value):
            if len(parameters) > 0:
                environment.scopes[-1][parameters[0]] = Type.integer(i)

            if cls.doFilter(filter, environment):
                output.append(evaluate(node.right, environment).value)

        return output
示例#24
0
    def otherRelationOperatorsEvaluator(cls, left, operator, right):
        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)

            if operator.value == ">=":
                return Type.bool(left.value >= right.value)

            if operator.value == "<":
                return Type.bool(left.value < right.value)

            if operator.value == "<=":
                return Type.bool(left.value <= right.value)

        raise RuntimeException(
            f"Operator {operator.value} is not supported by {left.type.name.lower()} and {right.type.name.lower()} types",
            operator.pos)
示例#25
0
    def listEvaluator(cls, node, environment, evaluatedIterator, parameters,
                      filter):
        output = []

        if len(parameters) > 2:
            raise RuntimeException(
                f"Loop with list iterator can handle only two parameters",
                node.parameters.pos)

        for i, value in enumerate(evaluatedIterator.value):
            if len(parameters) == 1:
                environment.scopes[-1][parameters[0]] = value
            if len(parameters) == 2:
                environment.scopes[-1][parameters[0]] = Type.integer(i)
                environment.scopes[-1][parameters[1]] = value

            if cls.doFilter(filter, environment):
                output.append(evaluate(node.right, environment).value)

        return output
示例#26
0
    def evaluator(cls, node, environment):
        left = expressionEvaluator(doAssert=True)(node.left, environment).value
        right = expressionEvaluator(doAssert=True)(node.right,
                                                   environment).value

        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)

        if left.type == right.type == Type.LIST:
            return cls.listEvaluator(left, node.operator, right)

        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)
示例#27
0
    def evaluator(cls, node, environment):
        left = expressionEvaluator(doAssert=True)(
            node.left, environment
        ).value  #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
        right = node.right

        if type(right) == Identifier:
            try:
                return left.properties[right.value]
            except KeyError:
                raise RuntimeException(
                    f"Unknown property '{right.value}' of type '{left.type.name.lower()}'",
                    right.pos)

        if type(right) == FunctionCall:
            try:
                arguments = abstractIterableEvaluator(
                    expressionEvaluator(doAssert=True))(right.arguments,
                                                        environment)
                return environment.invokeMethod(left, right.name.value,
                                                arguments)
            except RuntimeException as e:
                raise updatePos(e, right)
示例#28
0
    def evaluator(cls, node, environment):
        iterator = expressionEvaluator(doAssert=True)(node.left,
                                                      environment).value
        parameters = [identifier.value for identifier in node.parameters
                      ] if type(node.parameters) != NoneNode() else []

        try:
            environment.appendScope()

            output = {
                Type.INTEGER: cls.numberEvaluator,
                Type.BOOL: cls.boolEvaluator,
                Type.LIST: cls.listEvaluator,
                Type.MAP: cls.mapEvaluator
            }[iterator.type](node, environment, iterator, parameters,
                             node.filter)

            environment.popScope()
        except KeyError:
            raise RuntimeException(
                f"The {iterator.type.name.lower()} type cannot stand as an iterator for loop statement",
                node.left.pos)

        return Type.list(output)
示例#29
0
    def evaluateExpression(node, environment):
        from smnp.runtime.evaluators.function import FunctionCallEvaluator
        from smnp.runtime.evaluators.minus import MinusEvaluator
        from smnp.runtime.evaluators.atom import AtomEvaluator
        from smnp.runtime.evaluators.access import AccessEvaluator
        from smnp.runtime.evaluators.negation import NotEvaluator
        from smnp.runtime.evaluators.power import PowerEvaluator
        from smnp.runtime.evaluators.loop import LoopEvaluator
        from smnp.runtime.evaluators.assignment import AssignmentEvaluator
        from smnp.runtime.evaluators.product import ProductEvaluator

        from smnp.runtime.evaluators.sum import SumEvaluator
        from smnp.runtime.evaluators.relation import RelationEvaluator
        from smnp.runtime.evaluators.condition import IfElseEvaluator
        from smnp.runtime.evaluators.logic import AndEvaluator
        from smnp.runtime.evaluators.logic import OrEvaluator
        result = Evaluator.oneOf(
            Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
            Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
            Evaluator.forNodes(AccessEvaluator.evaluate, Access),
            Evaluator.forNodes(NotEvaluator.evaluate, NotOperator),
            Evaluator.forNodes(PowerEvaluator.evaluate, Power),
            Evaluator.forNodes(LoopEvaluator.evaluate, Loop),
            Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment),
            Evaluator.forNodes(ProductEvaluator.evaluate, Product),
            Evaluator.forNodes(SumEvaluator.evaluate, Sum),
            Evaluator.forNodes(RelationEvaluator.evaluate, Relation),
            Evaluator.forNodes(IfElseEvaluator.evaluate, IfElse),
            Evaluator.forNodes(AndEvaluator.evaluate, And),
            Evaluator.forNodes(OrEvaluator.evaluate, Or),
            AtomEvaluator.evaluate)(node, environment)

        if doAssert and result.result and result.value.type == Type.VOID:
            raise RuntimeException(f"Expected expression", node.pos)

        return result
示例#30
0
def _failStringify(t):
    raise RuntimeException(f"Not able to interpret {t.name}'", None)