def replace_with_value(node, var, value): if node.value == "with" and node.args[0].value == var: return LLLnode(node.value, [ node.args[0], replace_with_value(node.args[1], var, value), node.args[2] ], node.typ, node.location, node.annotation) elif node.value == var: return LLLnode(value, [], node.typ, node.location, node.annotation) else: return LLLnode( node.value, [replace_with_value(arg, var, value) for arg in node.args], node.typ, node.location, node.annotation)
def as_num256(expr, args, kwargs, context): if isinstance(args[0], int): if not(0 <= args[0] <= 2**256 - 1): raise InvalidLiteralException("Number out of range: " + str(expr.args[0].n), expr.args[0]) return LLLnode.from_list(args[0], typ=BaseType('num256', None), pos=getpos(expr)) elif isinstance(args[0], LLLnode): if args[0].value == "sub" and args[0].args[0].value == 0 and args[0].args[1].value > 0: raise InvalidLiteralException("Negative numbers cannot be num256 literals") return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType('num256'), pos=getpos(expr)) else: raise InvalidLiteralException("Invalid input for num256: %r" % args[0], expr)
def as_num256(expr, args, kwargs, context): if isinstance(args[0], int): if not (0 <= args[0] <= 2**256 - 1): raise InvalidLiteralException( "Number out of range: " + str(expr.args[0].n), expr.args[0]) return LLLnode.from_list(args[0], typ=BaseType('num256'), pos=getpos(expr)) elif isinstance( args[0], LLLnode) and args[0].typ.typ in ('num', 'num_literal', 'address'): return LLLnode.from_list(['clampge', args[0], 0], typ=BaseType('num256'), pos=getpos(expr)) elif isinstance(args[0], LLLnode): return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType('num256'), pos=getpos(expr)) else: raise InvalidLiteralException("Invalid input for num256: %r" % args[0], expr)
def method_id(expr, args, kwargs, context): method_id = fourbytes_to_int(sha3(args[0])[:4]) return LLLnode(method_id, typ=BaseType('method_id'), pos=getpos(expr))
def as_bytes32(expr, args, kwargs, context): return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType('bytes32'), pos=getpos(expr))
def as_unitless_number(expr, args, kwargs, context): return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType(args[0].typ.typ, {}), pos=getpos(expr))
def optimize(node): argz = [optimize(arg) for arg in node.args] if node.value in arith and int_at(argz, 0) and int_at(argz, 1): left, right = get_int_at(argz, 0), get_int_at(argz, 1) calcer, symb = arith[node.value] new_value = calcer(left, right) if argz[0].annotation and argz[1].annotation: annotation = argz[0].annotation + symb + argz[1].annotation elif argz[0].annotation or argz[1].annotation: annotation = (argz[0].annotation or str(left)) + symb + ( argz[1].annotation or str(right)) else: annotation = '' return LLLnode(new_value, [], node.typ, None, node.pos, annotation) elif node.value == "add" and int_at( argz, 0) and argz[1].value == "add" and int_at(argz[1].args, 0): calcer, symb = arith[node.value] if argz[0].annotation and argz[1].args[0].annotation: annotation = argz[0].annotation + symb + argz[1].args[0].annotation elif argz[0].annotation or argz[1].args[0].annotation: annotation = (argz[0].annotation or str(argz[0].value)) + symb + ( argz[1].args[0].annotation or str(argz[1].args[0].value)) else: annotation = '' return LLLnode("add", [ LLLnode(argz[0].value + argz[1].args[0].value, annotation=annotation), argz[1].args[1] ], node.typ, None, node.annotation) elif node.value == "add" and get_int_at(argz, 0) == 0: return LLLnode(argz[1].value, argz[1].args, node.typ, node.location, node.pos, argz[1].annotation) elif node.value == "add" and get_int_at(argz, 1) == 0: return LLLnode(argz[0].value, argz[0].args, node.typ, node.location, node.pos, argz[0].annotation) elif node.value == "clamp" and int_at(argz, 0) and int_at( argz, 1) and int_at(argz, 2): if get_int_at(argz, 0, True) > get_int_at(argz, 1, True): raise Exception("Clamp always fails") elif get_int_at(argz, 1, True) > get_int_at(argz, 2, True): raise Exception("Clamp always fails") else: return argz[1] elif node.value == "clamp" and int_at(argz, 0) and int_at(argz, 1): if get_int_at(argz, 0, True) > get_int_at(argz, 1, True): raise Exception("Clamp always fails") else: return LLLnode("clample", [argz[1], argz[2]], node.typ, node.location, node.pos, node.annotation) elif node.value == "clamp_nonzero" and int_at(argz, 0): if get_int_at(argz, 0) != 0: return LLLnode(argz[0].value, [], node.typ, node.location, node.pos, node.annotation) else: raise Exception("Clamp always fails") # Turns out this is actually not such a good optimization after all elif node.value == "with" and int_at( argz, 1) and not search_for_set(argz[2], argz[0].value) and False: o = replace_with_value(argz[2], argz[0].value, argz[1].value) return o elif node.value == "seq": o = [] for arg in argz: if arg.value == "seq": o.extend(arg.args) elif arg.value != "pass": o.append(arg) return LLLnode(node.value, o, node.typ, node.location, node.pos, node.annotation, add_gas_estimate=node.add_gas_estimate) elif hasattr(node, 'total_gas'): o = LLLnode(node.value, argz, node.typ, node.location, node.pos, node.annotation, add_gas_estimate=node.add_gas_estimate) o.total_gas = node.total_gas - node.gas + o.gas o.func_name = node.func_name return o else: return LLLnode(node.value, argz, node.typ, node.location, node.pos, node.annotation, add_gas_estimate=node.add_gas_estimate)