예제 #1
0
    def __init__(self,
                 key_domain: Type[KeyWrapper],
                 precursory: FularaState,
                 scalar_vars: Set[VariableIdentifier] = None,
                 map_vars: Set[VariableIdentifier] = None,
                 k_pre_k_conv: Callable[[KeyWrapper],
                                        KeyWrapper] = lambda x: x):
        """
        :param key_domain: domain for abstraction of dictionary keys,
            ranges over the scalar variables and the special key variable v_k,
            should support backward assignments with _substitute
        :param precursory: Forward analysis (Fulara analysis) result above the current statement
        :param scalar_vars: list of scalar variables, whose liveness should be abstracted
        :param map_vars: list of map variables, whose usage should be abstracted
        :param k_pre_k_conv: Conversion function to convert from key domain elements of the
                             precursory analysis to key domain elements of this analysis
                             (if the domains differ)"""

        arguments = {
            'key_domain': key_domain,
            'scalar_vars': scalar_vars,
            'map_vars': map_vars
        }
        super().__init__(FularaUsageLattice, arguments)  # Stack
        State.__init__(self, precursory)

        # self._s_vars = scalar_vars
        self._k_pre_k_conv = k_pre_k_conv
예제 #2
0
 def range_call_semantics(self, stmt: Call, state: State) -> State:
     result = set()
     if len(stmt.arguments) == 1:
         start = Literal(IntegerLyraType(), "0")
         stops = self.semantics(stmt.arguments[0], state).result
         step = Literal(IntegerLyraType(), "1")
         for stop in stops:
             range = Range(stmt.typ, start, stop, step)
             result.add(range)
         state.result = result
         return state
     elif len(stmt.arguments) == 2:
         starts = self.semantics(stmt.arguments[0], state).result
         stops = self.semantics(stmt.arguments[1], state).result
         step = Literal(IntegerLyraType(), "1")
         for start in starts:
             for stop in stops:
                 range = Range(stmt.typ, start, stop, step)
                 result.add(range)
         state.result = result
         return state
     elif len(stmt.arguments) == 3:
         starts = self.semantics(stmt.arguments[0], state).result
         stops = self.semantics(stmt.arguments[1], state).result
         steps = self.semantics(stmt.arguments[2], state).result
         for start in starts:
             for stop in stops:
                 for step in steps:
                     range = Range(stmt.typ, start, stop, step)
                     result.add(range)
         state.result = result
         return state
     error = f"Call to {stmt.name} with unexpected number of arguments!"
     raise ValueError(error)
예제 #3
0
    def __init__(self, variables: Set[VariableIdentifier], precursory: State = None):
        """Map each program variable to the interval representing its value.

        :param variables: set of program variables
        """
        lattices = defaultdict(lambda: IntervalLattice)
        super().__init__(variables, lattices)
        State.__init__(self, precursory)
예제 #4
0
    def __init__(self, variables: Set[VariableIdentifier], precursory: State = None):
        """Map each program variable to its liveness status.

        :param variables: set of program variables
        """
        lattices = defaultdict(lambda: LivenessLattice)
        super().__init__(variables, lattices)
        State.__init__(self, precursory)
예제 #5
0
    def list_call_semantics(self, stmt: Call, state: State) -> State:
        """Semantics of a call to 'list'.

        :param stmt: call to 'list' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        def do(variable):
            if isinstance(variable.typ, StringLyraType):
                typ = ListLyraType(variable.typ)
                state.result = {VariableIdentifier(typ, variable.name)}
                return state
            elif isinstance(variable.typ, ListLyraType):
                state.result = {variable}
                return state
            elif isinstance(variable.typ, TupleLyraType):
                raise NotImplementedError(f"Conversion to list of {variable.typ} is not yet implemented!")
            elif isinstance(variable.typ, SetLyraType):
                typ = ListLyraType(variable.typ.typ)
                state.result = {VariableIdentifier(typ, variable.name)}
                return state
            elif isinstance(variable.typ, DictLyraType):
                typ = ListLyraType(variable.typ.key_typ)
                state.result = {VariableIdentifier(typ, variable.name)}
                return state
            raise TypeError(f"Unexpected type {variable.typ} for list conversion!")
        if not stmt.arguments:
            state.result = {ListDisplay(stmt.typ, list())}
            return state
        assert len(stmt.arguments) == 1  # exactly one argument is expected
        argument = stmt.arguments[0]
        if isinstance(argument, VariableAccess):
            return do(argument.variable)
        # elif isinstance(argument, SubscriptionAccess):
        #     target = argument.target
        #     if isinstance(target, VariableAccess):
        #         return do(target.variable)
        elif isinstance(argument, Call):
            if isinstance(argument.typ, StringLyraType):
                typ = ListLyraType(argument.typ)
                call = Call(argument.pp, argument.name, argument.arguments, typ)
                state.result = self.semantics(call, state).result
                return state
            elif isinstance(argument.typ, ListLyraType):
                state.result = self.semantics(argument, state).result
                return state
            elif isinstance(argument.typ, SetLyraType):
                typ = ListLyraType(argument.typ.typ)
                call = Call(argument.pp, argument.name, argument.arguments, typ)
                state.result = self.semantics(call, state).result
                return state
            elif isinstance(argument.typ, DictLyraType):
                typ = ListLyraType(argument.typ.key_typ)
                call = Call(argument.pp, argument.name, argument.arguments, typ)
                state.result = self.semantics(call, state).result
                return state
        raise NotImplementedError(f"Semantics for {stmt} is not yet implemented!")
예제 #6
0
    def tuple_call_semantics(self, stmt: Call, state: State,
                             interpreter: Interpreter) -> State:
        """Semantics of a call to 'tuple'.

        :param stmt: call to 'tuple' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        if not stmt.arguments:
            state.result = {TupleDisplay(stmt.typ, list())}
            return state
        assert len(stmt.arguments) == 1  # exactly one argument is expected
        argument = self.semantics(stmt.arguments[0], state, interpreter).result
        result = set()
        for expression in argument:
            if isinstance(expression.typ, StringLyraType):
                if isinstance(expression, Literal):
                    typs = [
                        deepcopy(expression.typ)
                        for _ in range(len(expression.val))
                    ]
                    typ = TupleLyraType(typs)
                    result.add(CastOperation(typ, expression))
                else:
                    error = f"Cast to tuple of {expression} is not yet implemented!"
                    raise NotImplementedError(error)
            elif isinstance(expression.typ, (ListLyraType, SetLyraType)):
                if isinstance(expression, ListDisplay):
                    typs = [
                        deepcopy(expression.typ.typ)
                        for _ in range(len(expression.items))
                    ]
                    typ = TupleLyraType(typs)
                    result.add(CastOperation(typ, expression))
                else:
                    error = f"Cast to tuple of {expression} is not yet implemented!"
                    raise NotImplementedError(error)
            elif isinstance(expression.typ, TupleLyraType):
                result.add(expression)
            elif isinstance(expression.typ, DictLyraType):
                if isinstance(expression, DictDisplay):
                    typs = [
                        deepcopy(expression.typ.key_typ)
                        for _ in range(len(expression.keys))
                    ]
                    typ = TupleLyraType(typs)
                    result.add(CastOperation(typ, expression))
                else:
                    error = f"Cast to tuple of {expression} is not yet implemented!"
                    raise NotImplementedError(error)
            else:
                error = f"Cast to list of expression {expression} with unexpected type!"
                raise ValueError(error)
        state.result = result
        return state
예제 #7
0
    def user_defined_call_semantics(self, stmt: Call, state: State,
                                    interpreter: Interpreter):
        """Forward semantics of a user-defined function/method call.

        :param stmt: call statement to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        fname, fcfg = stmt.name, interpreter.cfgs[stmt.name]
        # add formal function parameters to the state and assign their actual values
        formal_args = interpreter.fargs[fname]
        for formal, actual in zip(formal_args, stmt.arguments):

            rhs = self.semantics(actual, state, interpreter).result
            state = state.add_variable(formal).forget_variable(formal)
            state = state.assign({formal}, rhs)

            if isinstance(actual, Call) and actual.name in interpreter.cfgs:
                _ret = VariableIdentifier(formal.typ,
                                          '{}#return'.format(actual.name))
                state = state.remove_variable(_ret)
        # add local function variables to the state
        _formal_args = set()
        for formal in formal_args:
            _formal_args.add(formal)
            # if isinstance(formal.typ, (SequenceLyraType, ContainerLyraType)):
            #     _formal_args.add(LengthIdentifier(formal))
            #     if isinstance(formal.typ, DictLyraType):
            #         _formal_args.add(KeysIdentifier(formal))
            #         _formal_args.add(ValuesIdentifier(formal))
        local_vars = set(fcfg.variables).difference(_formal_args)
        for local in local_vars:
            state = state.add_variable(local).forget_variable(local)

        fresult = interpreter.analyze(fcfg, state)  # analyze the function
        fstate = fresult.get_node_result(fcfg.out_node)[state][-1]
        state = state.bottom().join(deepcopy(fstate))

        # assign return variable
        if state.result:
            ret = VariableIdentifier(stmt.typ, '{}#return'.format(fname))
            state = state.add_variable(ret).forget_variable(ret)
            state = state.assign({ret}, state.result)
            state.result = {ret}

        # remove local function variables and formal function parameters
        for local in local_vars:
            if not local.special:
                state = state.remove_variable(local)
        for formal in formal_args:
            state = state.remove_variable(formal)

        return state
예제 #8
0
    def subscription_access_semantics(self, stmt: SubscriptionAccess, state: State) -> State:
        """Semantics of a subscription access.

        :param stmt: subscription access statement to be executed
        :param state: state before executing the subscription access
        :return: state modified by the subscription access
        """
        target = self.semantics(stmt.target, state).result
        key = self.semantics(stmt.key, state).result
        result = set()
        for primary, index in itertools.product(target, key):
            if isinstance(primary.typ, StringLyraType):
                subscription = Subscription(primary.typ, primary, index)
                result.add(subscription)
            elif isinstance(primary.typ, (ListLyraType, SetLyraType)):
                subscription = Subscription(primary.typ.typ, primary, index)
                result.add(subscription)
            elif isinstance(primary.typ, DictLyraType):
                subscription = Subscription(primary.typ.key_typ, primary, index)
                result.add(subscription)
            else:
                error = f"Semantics for subscription of {primary} is not yet implemented!"
                raise NotImplementedError(error)
        state.result = result
        return state
예제 #9
0
    def _binary_operation(self, stmt: Call, operator: BinaryOperation.Operator,
                          state: State):
        """Semantics of a call to a binary operation.

        :param stmt: call to binary operation to be executed
        :param operator: binary operator
        :param state: state before executing the call statements
        :return: state modified by the call statement
        """
        assert len(stmt.arguments
                   ) == 2  # binary operations have exactly two arguments
        argument1 = self.semantics(stmt.arguments[0], state).result
        argument2 = self.semantics(stmt.arguments[1], state).result
        result = set()
        if isinstance(operator, BinaryArithmeticOperation.Operator):
            for left, right in itertools.product(argument1, argument2):
                operation = BinaryArithmeticOperation(stmt.typ, left, operator,
                                                      right)
                result.add(operation)
        elif isinstance(operator, BinaryComparisonOperation.Operator):
            for left, right in itertools.product(argument1, argument2):
                operation = BinaryComparisonOperation(stmt.typ, left, operator,
                                                      right)
                result.add(operation)
        elif isinstance(operator, BinaryBooleanOperation.Operator):
            for left, right in itertools.product(argument1, argument2):
                operation = BinaryBooleanOperation(stmt.typ, left, operator,
                                                   right)
                result.add(operation)
        else:
            error = f"Semantics for binary operator {operator} is not yet implemented!"
            raise NotImplementedError(error)
        state.result = result
        return state
예제 #10
0
파일: semantics.py 프로젝트: ELowis/Lyra
    def dict_display_access_semantics(self, stmt: DictDisplayAccess,
                                      state: State) -> State:
        """Semantics of a list display access.

        :param stmt: dictionary display access statement to be executed
        :param state: state before executing the dictionary display access
        :return: state modified by the dictionary display access
        """
        k_exprs = [self.semantics(k, state).result
                   for k in stmt.keys]  # List[Set[Expression]]
        v_exprs = [self.semantics(v, state).result for v in stmt.values]

        result = set()

        if k_exprs:  # not empty
            # One "Set" of Tuples of possible key-value pairs per actual k-v-pair
            k_v_tuples = map(itertools.product, k_exprs, v_exprs)

            k_typ = next(iter(k_exprs[0])
                         ).typ  # Is there a better way to retrieve the types?
            v_typ = next(iter(v_exprs[0])).typ

            for combination in itertools.product(*k_v_tuples):
                unzip = list(
                    zip(*combination
                        ))  # to create two separate lists for keys and values
                display = DictDisplay(DictLyraType(k_typ, v_typ),
                                      list(unzip[0]), list(unzip[1]))
                result.add(display)
        else:
            # empty dict of generic type TODO: way to get specific type?
            result.add(DictDisplay(DictLyraType(LyraType(), LyraType())))
        state.result = result
        return state
예제 #11
0
    def _cast_call_semantics(self, stmt: Call, state: State,
                             typ: LyraType) -> State:
        """Semantics of a call to 'int' or 'bool'.

        :param stmt: call to 'int' or 'bool' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        if len(stmt.arguments) != 1:
            error = f"Semantics for multiple arguments of {stmt.name} is not yet implemented!"
            raise NotImplementedError(error)
        argument = self.semantics(stmt.arguments[0], state).result
        result = set()
        for expression in argument:
            if isinstance(expression, Input):
                result.add(Input(typ))
            elif isinstance(expression, Literal):
                result.add(Literal(typ, expression.val))
            elif isinstance(expression, VariableIdentifier):
                result.add(VariableIdentifier(typ, expression.name))
            elif isinstance(expression, Subscription):
                pass  # TODO
            else:
                error = f"Argument of type {expression.typ} of {stmt.name} is not yet supported!"
                raise NotImplementedError(error)
        state.result = result
        return state
예제 #12
0
 def strip_call_semantics(self, stmt: Call, state: State,
                          interpreter: Interpreter) -> State:
     if len(stmt.arguments) != 1:
         error = f"Semantics for multiple arguments of {stmt.name} is not yet implemented!"
         raise NotImplementedError(error)
     argument = self.semantics(stmt.arguments[0], state, interpreter).result
     result = set()
     for arg in argument:
         assert isinstance(arg, Expression)
         if not isinstance(arg.typ, StringLyraType):
             error = f"Call to {stmt.name} of argument with unexpected type!"
             raise ValueError(error)
         typ = StringLyraType()
         if isinstance(arg, Input):  # input().strip()
             result.add(Input(typ))
             continue
         elif isinstance(arg, VariableIdentifier):  # x.strip()
             result.add(VariableIdentifier(typ, arg.name))
             continue
         elif isinstance(arg, Subscription):  # x[i].strip()
             result.add(Subscription(typ, arg.target, arg.key))
             continue
         error = f"Call to {stmt.name} of unexpected argument {arg}!"
         raise ValueError(error)
     state.result = result
     return state
예제 #13
0
 def split_call_semantics(self, stmt: Call, state: State) -> State:
     if len(stmt.arguments) != 1:
         error = f"Semantics for multiple arguments of {stmt.name} is not yet implemented!"
         raise NotImplementedError(error)
     argument = self.semantics(stmt.arguments[0], state).result
     result = set()
     for arg in argument:
         assert isinstance(arg, Expression)
         if not isinstance(arg.typ, StringLyraType):
             error = f"Call to {stmt.name} of argument with unexpected type!"
             raise ValueError(error)
         typ = ListLyraType(StringLyraType())
         if isinstance(arg, Literal):  # "a b c".split() -> ["a", "b", "c"]
             items = [
                 Literal(StringLyraType(), val) for val in arg.val.split()
             ]
             result.add(ListDisplay(typ, items))
             continue
         elif isinstance(arg, VariableIdentifier):  # x.split()
             result.add(VariableIdentifier(typ, arg.name))
             continue
         elif isinstance(arg, Input):  # input().split()
             result.add(Input(typ))
             continue
         error = f"Call to {stmt.name} of unexpected argument!"
         raise ValueError(error)
     state.result = result
     return state
예제 #14
0
    def _unary_operation(self, stmt: Call, operator: UnaryOperation.Operator,
                         state: State):
        """Semantics of a call to a unary operation.

        :param stmt: call to unary operation to be executed
        :param operator: unary operator
        :param state: state before executing the call statements
        :return: state modified by the call statement
        """
        assert len(
            stmt.arguments) == 1  # unary operations have exactly one argument
        argument = self.semantics(stmt.arguments[0], state).result
        result = set()
        if isinstance(operator, UnaryArithmeticOperation.Operator):
            for expression in argument:
                operation = UnaryArithmeticOperation(stmt.typ, operator,
                                                     expression)
                result.add(operation)
        elif isinstance(operator, UnaryBooleanOperation.Operator):
            for expression in argument:
                operation = UnaryBooleanOperation(stmt.typ, operator,
                                                  expression)
                result.add(operation)
        else:
            error = f"Semantics for unary operation {operator} is not yet implemented!"
            raise NotImplementedError(error)
        state.result = result
        return state
예제 #15
0
    def raise_semantics(self, stmt: Raise, state: State) -> State:
        """Semantics of raising an Error.

        :param stmt: raise statement to be executed
        :param state: state before executing the raise Error
        :return: state modified by the raise
        """
        return state.raise_error()
예제 #16
0
    def raise_semantics(self, _, state: State,
                        interpreter: Interpreter) -> State:
        """Semantics of raising an Error.

        :param _: raise statement to be executed
        :param state: state before executing the raise Error
        :return: state modified by the raise
        """
        return state.raise_error()
예제 #17
0
    def input_call_semantics(self, stmt: Call, state: State) -> State:
        """Semantics of a calls to 'input'.

        :param stmt: call to 'input' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        state.result = {Input(stmt.typ)}
        return state
예제 #18
0
    def literal_evaluation_semantics(self, stmt: LiteralEvaluation, state: State) -> State:
        """Semantics of a literal evaluation.

        :param stmt: literal evaluation statement to be executed
        :param state: state before executing the literal evaluation
        :return: stated modified by the literal evaluation
        """
        state.result = {stmt.literal}
        return state
예제 #19
0
    def variable_access_semantics(self, stmt: VariableAccess, state: State) -> State:
        """Semantics of a variable access.

        :param stmt: variable access statement to be executed
        :param state: state before executing the variable access
        :return: state modified by the variable access
        """
        state.result = {stmt.variable}
        return state
예제 #20
0
    def assignment_semantics(self, stmt: Assignment, state: State) -> State:
        """Backward semantics of an assignment.

        :param stmt: assignment statement to be executed
        :param state: state before executing the assignment
        :return: state modified by the assignment
        """
        lhs = self.semantics(stmt.left, state).result  # lhs evaluation
        rhs = self.semantics(stmt.right, state).result  # rhs evaluation
        return state.substitute(lhs, rhs)
예제 #21
0
 def update_call_semantics(self, stmt: Call, state: State, interpreter: Interpreter) -> State:
     assert len(stmt.arguments) == 2
     targets = self.semantics(stmt.arguments[0], state, interpreter).result
     op = BinarySequenceOperation.Operator.Concat
     values = self.semantics(stmt.arguments[1], state, interpreter).result
     rhs = set()
     for target in targets:
         for value in values:
             display = SetDisplay(SetLyraType(value.typ), [value])
             rhs.add(BinarySequenceOperation(target.typ, target, op, display))
     return state.substitute(targets, rhs)
예제 #22
0
    def dict_call_semantics(self, stmt: Call, state: State) -> State:
        """Semantics of a call to 'dict'.

        :param stmt: call to 'dict' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        if not stmt.arguments:
            state.result = {SetDisplay(stmt.typ, list())}
            return state
        raise NotImplementedError(f"Semantics for {stmt} is not yet implemented!")
예제 #23
0
 def print_call_semantics(self, stmt: Call, state: State) -> State:
     """Semantics of a call to 'print'.
     
     :param stmt: call to 'print' to be executed
     :param state: state before executing the call statement
     :return: state modified by the call statement
     """
     if len(stmt.arguments) != 1:
         error = f"Semantics for multiple arguments of {stmt.name} is not yet implemented!"
         raise NotImplementedError(error)
     argument = self.semantics(stmt.arguments[0], state).result
     return state.output(argument)
예제 #24
0
 def append_call_semantics(self, stmt: Call, state: State) -> State:
     assert len(stmt.arguments) == 2
     targets = self.semantics(stmt.arguments[0], state).result
     op = BinarySequenceOperation.Operator.Concat
     values = self.semantics(stmt.arguments[1], state).result
     rhs = set()
     for target in targets:
         for value in values:
             display = ListDisplay(ListLyraType(value.typ), [value])
             rhs.add(
                 BinarySequenceOperation(target.typ, target, op, display))
     return state.assign(targets, rhs)
예제 #25
0
    def __init__(self,
                 key_domain: Type[KeyWrapper],
                 scalar_vars: Set[VariableIdentifier] = None,
                 dict_vars: Set[VariableIdentifier] = None,
                 k_k_pre_conv: Callable[[KeyWrapper],
                                        KeyWrapper] = lambda x: x,
                 k_pre_k_conv: Callable[[KeyWrapper],
                                        KeyWrapper] = lambda x: x,
                 precursory: FularaState = None):
        arguments = {
            'key_domain': key_domain,
            'scalar_vars': scalar_vars,
            'dict_vars': dict_vars
        }
        super().__init__(FularaUsageLattice, arguments)  # Stack
        State.__init__(self, precursory)

        # self._s_vars = scalar_vars
        self._k_k_pre_conv = k_k_pre_conv
        self._k_pre_k_conv = k_pre_k_conv

        self._loop_flag = False
예제 #26
0
    def set_call_semantics(self, stmt: Call, state: State,
                           interpreter: Interpreter) -> State:
        """Semantics of a call to 'set'.

        :param stmt: call to 'set' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        if not stmt.arguments:
            state.result = {SetDisplay(stmt.typ, list())}
            return state
        assert len(stmt.arguments) == 1  # exactly one argument is expected
        argument = self.semantics(stmt.arguments[0], state, interpreter).result
        result = set()
        for expression in argument:
            if isinstance(expression.typ, StringLyraType):
                typ = SetLyraType(expression.typ)
                result.add(CastOperation(typ, expression))
            elif isinstance(expression.typ, ListLyraType):
                typ = SetLyraType(expression.typ.typ)
                result.add(CastOperation(typ, expression))
            elif isinstance(expression.typ, TupleLyraType):
                if all(typ == expression.typ.typs[0]
                       for typ in expression.typ.typs):
                    typ = SetLyraType(expression.typ.typs[0])
                    result.add(CastOperation(typ, expression))
                else:
                    error = f"Cast to list of {expression} is not yet implemented!"
                    raise NotImplementedError(error)
            elif isinstance(expression.typ, SetLyraType):
                result.add(expression)
            elif isinstance(expression.typ, DictLyraType):
                typ = SetLyraType(expression.typ.key_typ)
                result.add(CastOperation(typ, expression))
            else:
                error = f"Cast to list of expression {expression} with unexpected type!"
                raise ValueError(error)
        state.result = result
        return state
예제 #27
0
    def user_defined_call_semantics(self, stmt: Call, state: State, interpreter: Interpreter):
        """Backward semantics of a user-defined function/method call.

        :param stmt: call statement to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        fname, fcfg, _ = stmt.name, interpreter.cfgs[stmt.name], deepcopy(state)
        # analyze the function
        fresult = interpreter.analyze(fcfg, state)
        fstate = fresult.get_node_result(fcfg.in_node)[state][-1]
        state = state.bottom().join(deepcopy(fstate))
        # substitute function actual to formal parameters
        for formal, actual in zip(interpreter.fargs[fname], stmt.arguments):
            if isinstance(actual, Call) and actual.name in interpreter.cfgs:
            # TODO: right might not be a Call but just contain a Call
                state.result = {formal}
                state = self.semantics(actual, state, interpreter)
            else:
                rhs = self.semantics(actual, state, interpreter).result
                state = state.substitute({formal}, rhs)
        return state
예제 #28
0
    def return_semantics(self, stmt: Return, state: State, interpreter: Interpreter):
        """Backward semantics of an return statement.

        :param stmt: return statement to be executed
        :param state: state before executing the return statement
        :return: state modified by the return statement
        """
        if len(stmt.values) != 1:
            error = f"Semantics for multiple arguments of {stmt} is not yet implemented!"
            raise NotImplementedError(error)
        lhs = state.result
        rhs = self.semantics(stmt.values[0], state, interpreter).result
        return state.substitute(lhs, rhs)
예제 #29
0
    def bitxor_call_semantics(self, stmt: Call, state: State,
                              interpreter: Interpreter) -> State:
        """Semantics of calls to '^' (bitwise xor).

        :param stmt: call to '^' (bitwise xor) to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        argument = self.semantics(stmt.arguments[0], state, interpreter).result
        result = set()
        for arg in argument:
            result.add(VariableIdentifier(stmt.typ, arg.name))
        state.result = result
        return state
예제 #30
0
파일: semantics.py 프로젝트: ELowis/Lyra
    def values_call_semantics(self, stmt: Call, state: State) -> State:
        """Semantics of calls to 'values'.

                        :param stmt: call to 'values' to be executed
                        :param state: state before executing the call statement
                        :return: state modified by the call statement
                        """
        if isinstance(stmt.arguments[0], VariableAccess):  # target
            state.result = {Values(stmt.typ, stmt.arguments[0].variable)}
        else:
            error = f"Semantics for values() call on non-variable {stmt.arguments[0]} is not yet "\
                    f"implemented!"
            raise NotImplementedError(error)
        return state