Ejemplo n.º 1
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
Ejemplo n.º 2
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!")
Ejemplo n.º 3
0
 def append_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 = ListDisplay(ListLyraType(value.typ), [value])
             rhs.add(BinarySequenceOperation(target.typ, target, op, display))
     return state.substitute(targets, rhs)
Ejemplo n.º 4
0
    def list_display_access_semantics(self, stmt: ListDisplayAccess,
                                      state: State) -> State:
        """Semantics of a list display access.

        :param stmt: list display access statement to be executed
        :param state: state before executing the list display access
        :return: state modified by the list display access
        """
        items = [self.semantics(item, state).result for item in stmt.items]
        result = set()
        if items:  # not empty
            for combination in itertools.product(*items):
                display = ListDisplay(ListLyraType(combination[0].typ),
                                      list(combination))
                result.add(display)
        else:
            result.add(ListDisplay(ListLyraType(
                LyraType())))  # empty list of generic type
            # TODO: way to get specific type? -> add type to display statements?
        state.result = result
        return state
Ejemplo n.º 5
0
    def list_display_access_semantics(self, stmt: ListDisplayAccess, state: State) -> State:
        """Semantics of a list display access.

        :param stmt: list display access statement to be executed
        :param state: state before executing the list display access
        :return: state modified by the list display access
        """
        items = [self.semantics(item, state).result for item in stmt.items]
        result = set()
        for combination in itertools.product(*items):
            display = ListDisplay(stmt.typ, list(combination))
            result.add(display)
        state.result = result
        return state
Ejemplo n.º 6
0
    def list_call_semantics(self, stmt: Call, state: State,
                            interpreter: Interpreter) -> 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
        """
        if not stmt.arguments:
            state.result = {ListDisplay(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 = ListLyraType(expression.typ)
                result.add(CastOperation(typ, expression))
            elif isinstance(expression.typ, ListLyraType):
                result.add(expression)
            elif isinstance(expression.typ, TupleLyraType):
                if all(typ == expression.typ.typs[0]
                       for typ in expression.typ.typs):
                    typ = ListLyraType(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):
                typ = ListLyraType(expression.typ.typ)
                result.add(CastOperation(typ, expression))
            elif isinstance(expression.typ, DictLyraType):
                typ = ListLyraType(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
Ejemplo n.º 7
0
 def visit_ListDisplay(self, expr: ListDisplay):
     items = [self.visit(item) for item in expr.items]
     return ListDisplay(expr.typ, items)
Ejemplo n.º 8
0
    def len_call_semantics(self, stmt: Call, state: State,
                           interpreter: Interpreter) -> State:
        """Semantics of a call to 'len'.

        :param stmt: call to 'len' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        assert len(
            stmt.arguments) == 1  # unary operations have exactly one argument
        argument = stmt.arguments[0]
        if isinstance(argument, VariableAccess):
            variable = argument.variable
            state.result = {LengthIdentifier(variable)}
            return state
        elif isinstance(argument, ListDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = ListDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, TupleDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = TupleDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, SetDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = SetDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, DictDisplayAccess):
            keys = [
                self.semantics(k, state, interpreter).result
                for k in argument.keys
            ]
            values = [
                self.semantics(v, state, interpreter).result
                for v in argument.values
            ]
            result = set()
            if keys:  # not empty List[Set[Expression]]
                for combination in itertools.product(
                        *map(itertools.product, keys, values)):
                    unzip = list(zip(*combination))
                    display = DictDisplay(argument.typ, list(unzip[0]),
                                          list(unzip[1]))
                    result.add(LengthIdentifier(display))
            else:
                result.add(
                    LengthIdentifier(DictDisplay(argument.typ, list(),
                                                 list())))
            state.result = result
            return state
        error = f"Semantics for length of {argument} is not yet implemented!"
        raise NotImplementedError(error)