def visit_bool_literal(self, node, target, *args): if target == ir.EXPR: return ir.Const(int(node.value), args[0]) else: if node.value: return ir.Jump(args[0]) else: return ir.Jump(args[1])
def remove_constant_reads(ir_list): next_step = _next_step_list(ir_list) prev_step = [[] for i in ir_list] for i, n in enumerate(next_step): for j in n: prev_step[j].append(i) prev_step[0].append(-1) new_list = [] for i, op in enumerate(ir_list): if not isinstance(op, (ir.Local, ir.Param)): new_list.append(op) continue q = deque([i]) reachable = {i} sources = [] while q: x = q.popleft() for n in prev_step[x]: if n not in reachable: reachable.add(n) if n == -1: if isinstance(op, ir.Param): src = 0 else: continue # uninitialized locals are UB else: src = _get_op_source(ir_list[n], op) if src is not None: sources.append(src) if isinstance(src, int): q.clear() break else: q.append(n) if any(isinstance(i, int) for i in sources) or len({i.value for i in sources}) > 1: new_list.append(op) elif sources: new_list.append(ir.Const(sources.pop().value, op.trg)) else: # uninitialized locals are UB new_list.append(ir.Const(0, op.trg)) return new_list
def factor(self, symtab): if self.accept('ident'): var = symtab.find(self.value) offs = self.array_offset(symtab) if offs is None: return ir.Var(var=var, symtab=symtab) else: return ir.ArrayElement(var=var, offset=offs, symtab=symtab) if self.accept('number'): return ir.Const(value=int(self.value), symtab=symtab) elif self.accept('lparen'): expr = self.expression() self.expect('rparen') return expr else: self.error("factor: syntax error") self.getsym()
def linearize_multid_vector(explist, target, symtab): offset = None for i in range(0, len(target.stype.dims)): if i + 1 < len(target.stype.dims): planedisp = reduce(lambda x, y: x * y, target.stype.dims[i + 1:]) else: planedisp = 1 idx = explist[i] esize = (target.stype.basetype.size // 8) * planedisp planed = ir.BinExpr( children=['times', idx, ir.Const(value=esize, symtab=symtab)], symtab=symtab) if offset is None: offset = planed else: offset = ir.BinExpr(children=['plus', offset, planed], symtab=symtab) return offset
def visit_bin_op(self, node, target, *args): if node.op in ['+', '-', '*', '%'] or (node.op == '<' and target == ir.EXPR): assert target == ir.EXPR lhs = self.get_id() rhs = self.get_id() arg1, arg2 = self.reorder_for_bin_op(node.left, node.right, lhs, rhs) return [ arg1, arg2, ir.BinOp(node.op, lhs, rhs, args[0]), ] if node.op == '<': assert target == ir.COND lhs = self.get_id() rhs = self.get_id() arg1, arg2 = self.reorder_for_bin_op(node.left, node.right, lhs, rhs) return [ arg1, arg2, ir.CJumpLess(lhs, rhs, args[0], args[1]), ] if node.op == '&&': if target == ir.COND: lbl_second_arg = self.get_id() return [ self.visit(node.left, ir.COND, lbl_second_arg, args[1]), ir.Label(lbl_second_arg), self.visit(node.right, ir.COND, args[0], args[1]), ] else: lbl_second_arg = self.get_id() lbl_false = self.get_id() lbl_true = self.get_id() lbl_end = self.get_id() return [ self.visit(node.left, ir.COND, lbl_second_arg, lbl_false), ir.Label(lbl_second_arg), self.visit(node.right, ir.COND, lbl_true, lbl_false), ir.Label(lbl_true), ir.Const(1, args[0]), ir.Jump(lbl_end), ir.Label(lbl_false), ir.Const(0, args[0]), ir.Label(lbl_end), ] if node.op == '||': if target == ir.COND: lbl_second_arg = self.get_id() return [ self.visit(node.left, ir.COND, args[0], lbl_second_arg), ir.Label(lbl_second_arg), self.visit(node.right, ir.COND, args[0], args[1]), ] else: lbl_second_arg = self.get_id() lbl_false = self.get_id() lbl_true = self.get_id() lbl_end = self.get_id() return [ self.visit(node.left, ir.COND, lbl_true, lbl_second_arg), ir.Label(lbl_second_arg), self.visit(node.right, ir.COND, lbl_true, lbl_false), ir.Label(lbl_false), ir.Const(0, args[0]), ir.Jump(lbl_end), ir.Label(lbl_true), ir.Const(1, args[0]), ir.Label(lbl_end), ] assert False
def visit_int_literal(self, node, target, *args): assert target == ir.EXPR return ir.Const(node.value, args[0])
def createDefaultDict(): d = { "^": OverloadList([Func([Float, Float], Float, "pow"), Func([Complex, Float], Complex, "pow"), Func([Complex, Complex], Complex, "pow")], operator=True, doc='''Exponentiation operator. Computes x to the power y.'''), "t__neg": efl("neg", "[_], _", [Int, Float, Complex, Hyper]), # logical ops "&&": OverloadList( [ Func([Bool, Bool], Bool, None) ], doc="Logical AND.", operator=True), "||": OverloadList( [ Func([Bool, Bool], Bool, None) ], doc="Logical OR.", operator=True), "t__not" : OverloadList( [ Func([Bool],Bool, "not") ], doc="Logical NOT.", operator=True), # predefined magic variables "t__h_pi" : Alias("pi"), "t__h_rand" : Alias("rand"), "t__h_random" : Alias("rand"), "t__h_magn" : Var(Float,doc="The magnification factor of the image. This is the number of times the image size has doubled, or ln(4.0/size)"), "t__h_center" : Var(Complex,doc="Where the center of the image is located on the complex plane"), "rand" : OverloadList( [ Func([], Complex, "rand") ], doc="Each time this is accessed, it returns a new pseudo-random complex number. This is primarily for backwards compatibility with Fractint formulas - use the random() function in new formulas."), "t__h_pixel": Alias("pixel"), "t__h_xypixel": Alias("pixel"), "pixel" : Var(Complex,doc="The (X,Y) coordinates of the current point. When viewing the Mandelbrot set, this has a different value for each pixel. When viewing the Julia set, it remains constant for each pixel."), "pi": Var(Float), "t__h_z" : Alias("z"), "z" : Var(Complex), "t__h_index": Var(Float,doc="The point in the gradient to use for the color of this point."), "t__h_numiter": Var(Int,doc="The number of iterations performed."), "t__h_maxiter": Alias("maxiter"), "t__h_maxit" : Alias("maxiter"), "maxit" : Alias("maxiter"), "maxiter" : Var(Int, "The maximum number of iterations set by the user."), "pi" : Var(Float,math.pi, doc="The constant pi, 3.14159..."), "t__h_tolerance" : Var(Float, doc="10% of the distance between adjacent pixels."), "t__h_zwpixel" : Var(Complex,doc="The (Z,W) coordinates of the current point. (See #pixel for the other two coordinates.) When viewing the Mandelbrot set, this remains constant for each pixel on the screen; when viewing the Julia set, it's different for each pixel. Initialize z to some function of this to take advantage of 4D drawing."), "t__h_solid" : Var(Bool,doc="Set this to true in a coloring function to use the solid color rather than the color map."), "t__h_color" : Var(Color,doc="Set this from a coloring function to directly set the color instead of using a gradient"), "t__h_fate" : Var(Int,doc="The fate of a point can be used to distinguish between different basins of attraction or whatever you like. Set this to a number from 2 to 128 to indicate that a different 'fate' has befallen this point. 0 indicates the point has diverged, 1 that it has been trapped, >1 whatever you like. Can only be usefully updated in the #final section."), "t__h_inside" : Var(Bool,doc="Set this in the final section of a formula to override whether a point is colored with the inside or outside coloring algorithm. This is mainly useful in conjuction with #fate.") } # extra shorthand to make things as short as possible def f(name, list, **kwds): mkfl(d,name,list,**kwds) # standard functions f("bool", [[Bool], Bool], doc="""Construct a boolean. It's not really required (bool x = bool(true) is just the same as bool x = true) but is included for consistency.""") f("int", [[Int], Int], doc="""Construct an integer. To convert a float to an int, use floor, ceil, round or trunc instead.""") f("float", [[Float], Float], doc="""Construct a floating-point number.""") f("color", [[Float, Float, Float, Float], Color], doc="""Constructs a new color from floating point red, green, blue and alpha components. Equivalent to rgba.""") f("complex", [[Float, Float], Complex], doc='''Construct a complex number from two real parts. complex(a,b) is equivalent to (a,b).''') f("hyper", [[[Float, Float, Float, Float], Hyper], [[Complex, Complex], Hyper]], doc='''Construct a hypercomplex number with a real and 3 imaginary parts. Can be passed either 2 complex numbers or 4 floating-point numbers. hyper(a,b,c,d) is equivalent to the shorthand (a,b,c,d).''') f("sqr", cfl("[_] , _", [Int, Float, Complex, Hyper]), doc="Square the argument. sqr(x) is equivalent to x*x or x^2.") #f("cube", # cfl("[_] , _", [Int, Float, Complex]), # doc="Cube the argument. cube(x) is equivalent to x*x*x or x^3.") f("ident", cfl("[_] , _", [Int, Float, Complex, Bool, Hyper]), doc='''Do nothing. ident(x) is equivalent to x. This function is useless in normal formulas but comes in useful as a value for a function parameter to a formula. For example, a general formula like z = @fn1(z*z)+c can be set back to a plain Mandelbrot by setting fn1 to ident. Note: ident() is compiled out so there\'s no speed penalty involved.''') f("conj", cfl("[_] , _", [Complex, Hyper]), doc="The complex conjugate. conj(a,b) is equivalent to (a,-b).") f("flip", cfl("[_] , _", [Complex, Hyper]), doc='''Swap the real and imaginary parts of a complex number. flip(a,b) = (b,a).''') f("real", [[[Complex], Float], [[Hyper], Float]], doc='''Extract the real part of a complex or hypercomplex number. real(a,b) = a. real() is unusual in that it can be assigned to: real(z) = 7 changes the real part of z.''') f("real2", [[Complex], Float], doc='''The square of the real part of a complex number. real2(a,b) = a*a. While not a generally useful function, this is provided to ease porting of files from older Gnofract 4D versions.''') f("imag", [[[Complex], Float], [[Hyper], Float]], doc='''Extract the imaginary part of a complex or hypercomplex number. imag(a,b) = b. imag() is unusual in that it can be assigned to: imag(z) = 7 changes the imag part of z.''') f("imag2", [[Complex], Float], doc='''The square of the imaginary part of a complex number. real2(a,b) = b*b. While not a generally useful function, this is provided to ease porting of files from older Gnofract 4D versions.''') f("hyper_ri", [[Hyper], Complex], doc='''The real and imaginary parts of a hypercomplex number. Can be assigned to. hyper_ri(a,b,c,d) = (a,b).''') f("hyper_jk", [[Hyper], Complex], doc='''The 3rd and 4th parts of a hypercomplex number. Can be assigned to. hyper_jk(a,b,c,d) = (c,d).''') f("hyper_j", [[Hyper], Float], doc='''The 3rd component of a hypercomplex number. Can be assigned to. hyper_j(a,b,c,d) = c.''') f("hyper_k", [[Hyper], Float], doc='''The 4th component of a hypercomplex number. Can be assigned to. hyper_k(a,b,c,d) = d.''') f("red", [[Color], Float], doc='''The red component of a color. Can be assigned to.''') f("green", [[Color], Float], doc='''The green component of a color. Can be assigned to.''') f("blue", [[Color], Float], doc='''The blue component of a color. Can be assigned to.''') f("alpha", [[Color], Float], doc='''The alpha component of a color. Can be assigned to.''') f("hue", [[Color], Float], doc='''The hue of a color.''') f("sat", [[Color], Float], doc='''The saturation of a color.''') f("lum", [[Color], Float], doc='''The luminance (or brightness) of a color.''') f("gradient", [[Float], Color], doc='''Look up a color from the default gradient.''') f("recip", cfl("[_] , _", [Float, Complex, Hyper]), doc='''The reciprocal of a number. recip(x) is equivalent to 1/x. Note that not all hypercomplex numbers have a proper reciprocal.''') f("trunc", [[[Float], Int], [[Complex], Complex]], doc='''Round towards zero.''') f("round", [[[Float], Int], [[Complex], Complex]], doc='''Round to the nearest number (0.5 rounds up).''') f("floor", [[[Float], Int], [[Complex], Complex]], doc='''Round down to the next lowest number.''') f("ceil", [[[Float], Int], [[Complex], Complex]], doc='''Round up to the next highest number.''') f("zero", cfl("[_], _ ", [Int, Float, Complex]), doc='''Returns zero.''') f("abs", cfl("[_], _", [Int,Float, Complex]), doc='''The absolute value of a number. abs(3) = abs(-3) = 3. abs() of a complex number is a complex number consisting of the absolute values of the real and imaginary parts, i.e. abs(a,b) = (abs(a),abs(b)).''') f("cabs", [[Complex], Float], doc='''The complex modulus of a complex number z. cabs(a,b) is equivalent to sqrt(a*a+b*b). This is also the same as sqrt(|z|)''') f("cmag", [[[Complex], Float], [[Hyper], Float]], doc='''The squared modulus of a complex or hypercomplex number z. cmag(a,b) is equivalent to a*a+b*b. This is the same as |z|.''') f("log", cfl("[_], _", [Float, Complex, Hyper]), doc='The natural log.') f("sqrt", cfl("[_], _", [Float, Complex, Hyper]), doc='''The square root. The square root of a negative float number is NaN (ie it is NOT converted to complex). Thus sqrt((-3,0)) != sqrt(-3).''' ) f("exp", cfl("[_], _", [Float, Complex, Hyper]), doc='exp(x) is equivalent to e^x') f("manhattan", [[Complex], Float], doc='''The Manhattan distance between the origin and complex number z. manhattan(a,b) is equivalent to abs(a) + abs(b).''') f("manhattanish", [[Complex], Float], doc='''A variant on Manhattan distance provided for backwards compatibility. manhattanish(a,b) is equivalent to a+b.''') f("manhattanish2", [[Complex], Float], doc='''A variant on Manhattan distance provided for backwards compatibility. manhattanish2(a,b) is equivalent to (a*a + b*b)^2.''') f("min", [[Float, Float], Float], doc='''Returns the smaller of its two arguments.''') f("max", [[Float, Float], Float], doc='''Returns the larger of its two arguments.''') f("max2", [[Complex], Float], doc='''max2(a,b) returns the larger of a*a or b*b. Provided for backwards compatibility.''') f("min2", [[Complex], Float], doc='''min2(a,b) returns the smaller of a*a or b*b. Provided for backwards compatibility.''') f("sin", cfl( "[_], _", [Float, Complex, Hyper]), doc='trigonometric sine function.') f("cos", cfl( "[_], _", [Float, Complex, Hyper]), doc='trigonometric sine function.') f("cosxx", cfl( "[_], _", [Complex, Hyper]), doc='''Incorrect version of cosine function. Provided for backwards compatibility with equivalent wrong function in Fractint.''') f("tan", cfl( "[_], _", [Float, Complex, Hyper]), doc='trigonometric sine function.') f("cotan", cfl("[_], _", [Float, Complex, Hyper]), doc="Trigonometric cotangent function.") f("sinh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Hyperbolic sine function.') f("cosh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Hyperbolic cosine function.') f("tanh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Hyperbolic tangent function.') f("cotanh", cfl("[_], _", [Float, Complex, Hyper]), doc='Hyperbolic cotangent function.') f("asin", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse sine function.') f("acos", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse cosine function.') f("atan", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse tangent function.') f("atan2", [[Complex], Float], doc='''The angle between this complex number and the real line, aka the complex argument.''') f("asinh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse hyperbolic sine function.') f("acosh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse hyperbolic cosine function.') f("atanh", cfl( "[_], _", [Float, Complex, Hyper]), doc='Inverse hyperbolic tangent function.') # color functions f("blend", [ [Color, Color, Float], Color], doc='Blend two colors together in the ratio given by the 3rd parameter.') f("compose", [ [Color, Color, Float], Color], doc='''Composite the second color on top of the first, with opacity given by the 3rd parameter.''') f("mergenormal", [ [Color, Color], Color], doc='''Returns second color, ignoring first.''') f("mergemultiply", [ [Color, Color], Color], doc='''Multiplies colors together. Result is always darker than either input.''') f("rgb", [ [Float, Float, Float], Color], doc='''Create a color from three color components. The alpha channel is set to to 1.0 (=100%).''') f("rgba", [ [Float, Float, Float, Float], Color], doc='Create a color from three color components and an alpha channel.') f("hsl", [ [Float, Float, Float], Color], doc='''Create a color from hue, saturation and lightness components. The alpha channel is set to to 1.0 (=100%).''') f("hsla", [ [Float, Float, Float,Float], Color], doc='''Create a color from hue, saturation and lightness components and an alpha channel.''') f("hsv", [ [Float, Float, Float], Color], doc='''Create a color from hue, saturation and value components. HSV is a similar color model to HSL but has a different valid range for brightness.''') f("_image", [ [Image, Complex], Color], doc='''Look up a color from a 2D array of colors.''') f("_alloc", [ [ [VoidArray, Int, Int], VoidArray], [ [VoidArray, Int, Int, Int], VoidArray], [ [VoidArray, Int, Int, Int, Int], VoidArray], [ [VoidArray, Int, Int, Int, Int, Int], VoidArray]], doc='''Allocate an array. First argument is element size in bytes, subsequent args are array sizes''') f("_write_lookup", # args are array, indexes, value. returns false if index is out of bounds [ [ [IntArray, Int, Int], Bool], [ [IntArray, Int, Int, Int], Bool], [ [IntArray, Int, Int, Int, Int], Bool], [ [IntArray, Int, Int, Int, Int, Int], Bool], [ [FloatArray, Int, Float], Bool], [ [FloatArray, Int, Int, Float], Bool], [ [FloatArray, Int, Int, Int, Float], Bool], [ [FloatArray, Int, Int, Int, Int, Float], Bool], [ [ComplexArray, Int, Complex], Bool], [ [ComplexArray, Int, Int, Complex], Bool], [ [ComplexArray, Int, Int, Int, Complex], Bool], [ [ComplexArray, Int, Int, Int, Int, Complex], Bool], ], doc='''Write a value into an array''') f("_read_lookup", # args are array, indexes, value [ [ [IntArray, Int], Int], [ [IntArray, Int, Int], Int], [ [IntArray, Int, Int, Int], Int], [ [IntArray, Int, Int, Int, Int], Int], [ [FloatArray, Int], Float], [ [FloatArray, Int, Int], Float], [ [FloatArray, Int, Int, Int], Float], [ [FloatArray, Int, Int, Int, Int], Float], [ [ComplexArray, Int], Complex], [ [ComplexArray, Int, Int], Complex], [ [ComplexArray, Int, Int, Int], Complex], [ [ComplexArray, Int, Int, Int, Int], Complex], ], doc='''Read a value out of an array''') # operators f("+", cfl("[_,_] , _", [Int, Float, Complex, Hyper, Color]), fname="add", operator=True, doc='Adds two numbers together.') f("-", cfl("[_,_] , _", [Int, Float, Complex, Hyper, Color]), fname="sub", operator=True, doc='Subtracts two numbers') f("*", cfl("[_,_] , _", [Int, Float, Complex, Hyper]) + cfl("[_, Float], _", [Hyper, Color]), fname="mul", operator=True, doc='''Multiplication operator.''') f("/", [ [[Float, Float], Float], [[Complex, Float], Complex], [[Complex, Complex], Complex], [[Hyper, Float], Hyper], [[Color, Float], Color] ], fname="div", operator=True, doc='''Division operator''') f("!=", cfl("[_,_] , Bool", [Int, Float, Complex, Bool]), fname="noteq", operator=True, precedence=3, doc='''Inequality operator. Compare two values and return true if they are different.''') f("==", cfl("[_,_] , Bool", [Int, Float, Complex, Bool]), fname="eq", operator=True, precedence=3, doc='''Equality operator. Compare two values and return true if they are the same.''') # fixme - issue a warning for complex compares f(">", cfl("[_,_], Bool", [Int, Float, Complex]), fname="gt", operator=True, precedence=3, doc='''Greater-than operator. Compare two values and return true if the first is greater than the second.''') f(">=", cfl("[_,_], Bool", [Int, Float, Complex]), fname="gte", operator=True, precedence=3, doc='''Greater-than-or-equal operator. Compare two values and return true if the first is greater than or equal to the second.''') f("<", cfl("[_,_], Bool", [Int, Float, Complex]), fname="lt", operator=True, precedence=3, doc='''Less-than operator. Compare two values and return true if the first is less than the second.''') f("<=", cfl("[_,_], Bool", [Int, Float, Complex]), fname="lte", operator=True, precedence=3, doc='''Less-than-or-equal operator. Compare two values and return true if the first is less than or equal to the second.''') f("%", cfl("[_,_] , _", [Int, Float]), fname="mod", operator=True, doc='''Modulus operator. Computes the remainder when x is divided by y. Not to be confused with the complex modulus.'''), # predefined parameters for p in xrange(1,7): name = "p%d" % p d[name] = Alias("t__a_" + name) d["t__a_" + name] = Var(Complex,doc="Predefined parameter used by Fractint formulas") # predefined functions for p in xrange(1,5): name = "fn%d" % p d[name] = Alias("t__a_" + name) d["t__a_" + name ] = OverloadList( [Func([Complex],Complex, "ident") ], doc="Predefined function parameter used by Fractint formulas") # predefined gradient-related vars and functions tfunc = Func([Float],Float, "ident") tfunc.caption = ir.Const("Transfer Function", None, String) transfer = OverloadList([tfunc]) d["t__a__transfer"] = transfer d["t__a__gradient"] = Var(Gradient) for (k,v) in d.items(): if hasattr(v,"cname") and v.cname == None: v.cname = k return d
def const(self, value=0): return ir.Const(value, self.fakeNode, Int)