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