Class: UnsafeFuncRewriter

Inherits:
SexpProcessor
  • Object
show all
Defined in:
lib/bud/rewrite.rb

Overview

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.

Constant Summary

SAFE_FUNC_LIST =
[:int_ip_port, :ip_port, :ip, :port].to_set

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (UnsafeFuncRewriter) initialize(bud_instance)

Returns a new instance of UnsafeFuncRewriter



357
358
359
360
361
362
363
364
# File 'lib/bud/rewrite.rb', line 357

def initialize(bud_instance)
  super()
  self.require_empty = false
  self.expected = Sexp
  @bud_instance = bud_instance
  @unsafe_func_called = false
  @elem_stack = []
end

Instance Attribute Details

- (Object) unsafe_func_called (readonly)

Returns the value of attribute unsafe_func_called



355
356
357
# File 'lib/bud/rewrite.rb', line 355

def unsafe_func_called
  @unsafe_func_called
end

Instance Method Details

- (Boolean) is_collection_name?(op)

Returns:

  • (Boolean)


394
395
396
# File 'lib/bud/rewrite.rb', line 394

def is_collection_name?(op)
  @bud_instance.tables.has_key?(op.to_sym) || @bud_instance.lattices.has_key?(op.to_sym)
end

- (Object) is_safe_func(op)



398
399
400
# File 'lib/bud/rewrite.rb', line 398

def is_safe_func(op)
  SAFE_FUNC_LIST.include? op
end

- (Object) process_call(exp)



366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/bud/rewrite.rb', line 366

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

- (Object) process_iter(exp)



380
381
382
383
384
# File 'lib/bud/rewrite.rb', line 380

def process_iter(exp)
  tag, recv, iter_args, body = exp
  new_body = push_and_process(body)
  return s(tag, process(recv), process(iter_args), new_body)
end

- (Object) push_and_process(exp)

Raises:



386
387
388
389
390
391
392
# File 'lib/bud/rewrite.rb', line 386

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