def _make_accessors(self, info): """Build get() and set() function based on info. """ name = self._array_name(info) fname = self._make_getter_name(info) size = info.sizeof() params = [("int", f"x{i}") for i in range(len(info.size))] mults = [ BinaryOp("*", a, ID(b[1])) for a, b in zip(info.size[1:], params[:-1]) ] offset = ID(params[-1][1]) for m in mults: offset = BinaryOp("+", m, offset) cases = [ Case(Constant("int", str(i)), [Return(ID(f"{name}_{i}"))]) for i in range(size) ] body = Compound([Switch(offset, Compound(cases))]) self.accessors.add(make_function(info.type, fname, params, body)) cases = [ Case(Constant("int", str(i)), [Assignment("=", ID(f"{name}_{i}"), ID("value")), Break()]) for i in range(size) ] body = Compound([Switch(offset, Compound(cases))]) type_ = (info.type.name if type(info.type) == Struct else info.type.names[0]) setter = make_function(IdentifierType(["void"]), fname.replace("get", "set", 1), params + [(type_, "value")], body) self.accessors.add(setter)
def visit_UnaryOp(self, pyc_unary_op: UnaryOp): # convert pyc_unary operator to pyc_assignment op = pyc_unary_op.op if op == '++' or op == 'p++': op = '+' elif op == '--' or op == 'p--': op = '-' elif op == '+' or op == '-': bin_op = BinaryOp(op, Constant('int', '0', pyc_unary_op.coord), pyc_unary_op.expr, pyc_unary_op.coord) return self.visit(bin_op) # else: # raise NotImplementedError('op=', op) right = BinaryOp(op, pyc_unary_op.expr, Constant('int', '1', pyc_unary_op.coord), pyc_unary_op.coord) pyc_assign = Assignment('=', pyc_unary_op.expr, right, pyc_unary_op.coord) return self.visit(pyc_assign)
def cached_provider_call(self): provider = self.provider entity_flag = self.memo_flag_name return If(cond=UnaryOp(op='!', expr=ID(name=entity_flag)), iftrue=Compound(block_items=[ FuncCall(name=ID(name=provider), args=None), Assignment(op='=', lvalue=ID(name=entity_flag), rvalue=Constant(type='bool', value='true'))]), iffalse=None)
def visit_UnaryOp(self, node): _ops = { "!": lambda x: 1 if x == 0 else 0, "+": lambda x: x, "-": lambda x: -x } self.generic_visit(node) if is_const(node.expr) and node.op in _ops: val = str(_ops[node.op](parse_int(node.expr.value))) new_node = Constant("int", val) self.replace(node, new_node)
def visit_Enum(self, node): if not node.values: return generator = c_generator.CGenerator() for i, elem in enumerate(node.values.enumerators): if not elem.value: continue try: raw_val = generator.visit(elem.value) for item in node.values.enumerators: try: if item.value and item.value.type == 'int': raw_val = raw_val.replace(item.name, item.value.value) except: pass cooked_value = eval(raw_val) elem.value = Constant(type='int', value=str(cooked_value)) except: pass
def make_int_constant(value): return Constant(type='int', value=str(value))
def visit_BinaryOp(self, node): """C99-Section 6.5 """ _ops = { "+": lambda x, y: x + y, "-": lambda x, y: x - y, "*": lambda x, y: x * y, "/": lambda x, y: x // y, "%": lambda x, y: abs(x) % abs(y) * (1 - 2 * (x < 0)), "<<": lambda x, y: x << y, ">>": lambda x, y: x >> y, "&": lambda x, y: x & y, "|": lambda x, y: x | y, "&&": lambda x, y: 0 if not bool(x) else int(bool(x & y)), "||": lambda x, y: 1 if bool(x) else int(bool(x | y)) } self.generic_visit(node) # Commutative axioms for n1, n2 in ((node.left, node.right), (node.right, node.left)): if self.is_int_const(n1): v1 = parse_int(n1.value) if v1 == 0: if node.op in ("+", "-"): self.replace(node, n2) # 0+x = 0-x = 0 elif node.op == "*": self.replace(node, n1) # 0*x = 0 elif v1 == 1 and node.op == "*": self.replace(node, n2) # 1*x = x elif v1 == -1 and node.op == "*": self.replace(node, UnaryOp("-", n2)) # -1*x = -x # Non-commutative axioms if self.is_int_const(node.left): v = parse_int(node.left.value) if v == 0 and node.op in (">>", "<<", "/", "%"): self.replace(node, node.left) # 0<<x = 0>>x = 0/x = 0%x = 0 if self.is_int_const(node.right): v = parse_int(node.right.value) if v == 0 and node.op in ("<<", ">>"): self.replace(node, node.left) # x<<0 = x>>0 = x elif v == 1 and node.op == "/": self.replace(node, node.left) # x/1 = x elif v == -1 and node.op == "/": self.replace(node, UnaryOp("-", node.left)) # x/-1 = -x elif abs(v) == 1 and node.op == "%": node.right.value = "0" self.replace(node, node.right) # x%1 = 0 # Generic folding ULLONG_MAX = 18446744073709551615 if self.is_int_const(node.left) and self.is_int_const(node.right): if node.op in _ops: try: val = _ops[node.op]( parse_int(node.left.value), parse_int(node.right.value)) # print(">>>",val) if abs(val) <= ULLONG_MAX: new_node = Constant("int", str(val)) self.replace(node, new_node) except ZeroDivisionError: pass