class UnsafeFuncRewriter
Check for whether the rule invokes any “unsafe” functions (functions that might return a different value every time they are called, e.g., budtime). The test for “unsafe” functions is pretty naive: any function call with a nil receiver is treated as unsafe unless it is belongs to a list of “safe” functions (below) or it denotes a lattice identifier. In the latter case, the rule is akin to an implicit join with the lattice, so we only rescan it on deltas to the lattice (see “rescan_on_merge” in LatticeWrapper).
Although this is called a rewriter, it doesn't modify the input AST.
Constants
- SAFE_FUNC_LIST
Attributes
unsafe_func_called[R]
Public Class Methods
new(bud_instance)
click to toggle source
Calls superclass method
# File lib/bud/rewrite.rb, line 359 def initialize(bud_instance) super() self.require_empty = false self.expected = Sexp @bud_instance = bud_instance @unsafe_func_called = false @elem_stack = [] end
Public Instance Methods
is_collection_name?(op)
click to toggle source
# File lib/bud/rewrite.rb, line 399 def is_collection_name?(op) @bud_instance.tables.has_key?(op.to_sym) || @bud_instance.lattices.has_key?(op.to_sym) end
is_safe_func(op)
click to toggle source
# File lib/bud/rewrite.rb, line 403 def is_safe_func(op) SAFE_FUNC_LIST.include? op end
process_call(exp)
click to toggle source
# File lib/bud/rewrite.rb, line 368 def process_call(exp) tag, recv, op, *args = exp # We assume that unsafe funcs have a nil receiver (Bud instance is implicit # receiver). if recv.nil? and @elem_stack.size > 0 unless is_safe_func(op) || is_collection_name?(op) @unsafe_func_called = true end end return s(tag, process(recv), op, *(args.map{|a| process(a)})) end
process_iter(exp)
click to toggle source
# File lib/bud/rewrite.rb, line 382 def process_iter(exp) tag, recv, iter_args, body = exp if (iter_args == 0) iter_args = s(:args) end new_body = push_and_process(body) return s(tag, process(recv), process(iter_args), new_body) end
push_and_process(exp)
click to toggle source
# File lib/bud/rewrite.rb, line 391 def push_and_process(exp) obj_id = exp.object_id @elem_stack.push(obj_id) rv = process(exp) raise Bud::Error unless @elem_stack.pop == obj_id return rv end