class ADSL::Parser::ASTTypecheckResolveContext

Attributes

actions[RW]
classes[RW]
invariants[RW]
pre_stmts[RW]
relations[RW]
var_stack[RW]

Public Class Methods

context_vars_that_differ(*contexts) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 517
def self.context_vars_that_differ(*contexts)
  vars_per_context = []
  contexts.each do |context|
    vars_per_context << context.var_stack.inject(ActiveSupport::OrderedHash.new) { |so_far, frame| so_far.merge! frame }
  end
  all_vars = vars_per_context.map{ |c| c.keys }.flatten.uniq
  packed = ActiveSupport::OrderedHash.new
  all_vars.each do |v|
    packed[v] = vars_per_context.map{ |vpc| vpc[v][1] }
  end
  packed.delete_if { |v, vars| vars.uniq.length == 1 }
  packed
end
new() click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 394
def initialize
  # name => [astnode, dsobj]
  @classes = ActiveSupport::OrderedHash.new

  # classname => name => [astnode, dsobj]
  @relations = ActiveSupport::OrderedHash.new{ |hash, key| hash[key] = ActiveSupport::OrderedHash.new }

  # stack of name => [astnode, dsobj]
  @actions = ActiveSupport::OrderedHash.new

  @invariants = []
  @var_stack = []
  @pre_stmts = []
end

Public Instance Methods

define_var(var, node) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 449
def define_var(var, node)
  raise ADSLError, "Defining variables on a stack with no stack frames" if @var_stack.empty?
  prev_var_node, prev_var = lookup_var var.name
  raise ADSLError, "Duplicate identifier '#{var.name}' on line #{node.lineno}; previous definition on line #{prev_var_node.lineno}" unless prev_var.nil?
  @var_stack.last[var.name] = [node, var]
  @var_stack.last.fire_write_event var.name
  return var
end
find_relation(from_type, rel_name, lineno, to_type=nil) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 501
def find_relation(from_type, rel_name, lineno, to_type=nil)
  iter = from_type
  relation_node, relation = @relations[iter.name][rel_name]
  while relation.nil?
    iter = iter.parent
    raise ADSLError, "Unknown relation #{from_type.name}.#{rel_name} on line #{lineno}" if iter.nil?
    relation_node, relation = @relations[iter.name][rel_name]
  end
  
  unless to_type.nil?
    raise ADSLError, "Mismatched right-hand-side type for relation #{from_type.name}.#{rel_name} on line #{lineno}. Expected #{relation.to_class.name} but was #{to_type.name}" unless relation.to_class.superclass_of? to_type
  end

  relation
end
in_stack_frame() { || ... } click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 434
def in_stack_frame
  push_frame
  yield
ensure
  pop_frame
end
initialize_copy(source) click to toggle source
Calls superclass method
# File lib/adsl/parser/ast_nodes.rb, line 409
def initialize_copy(source)
  super
  source.classes.each do |name, value|
    @classes[name] = value.dup
  end
  source.relations.each do |class_name, class_entry|
    entries = @relations[class_name]
    class_entry.each do |name, value|
      entries[name] = value.dup
    end
  end
  @actions = source.actions.dup
  @invariants = source.invariants.dup
  @var_stack = source.var_stack.map{ |frame| frame.dup }
  @pre_stmts = source.pre_stmts.map{ |stmt| stmt.dup }
end
lookup_var(name, fire_read_event=true) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 483
def lookup_var(name, fire_read_event=true)
  @var_stack.length.times do |index|
    frame = @var_stack[index]
    next if frame[name].nil?
    var = frame[name]

    if fire_read_event
      @var_stack[index..-1].reverse.each do |subframe|
        subframe.fire_read_event name
      end
    end

    # handle events here, none defined atm
    return var
  end
  nil
end
on_var_read(&block) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 430
def on_var_read(&block)
  @var_stack.last.on_var_read(&block)
end
on_var_write(&block) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 426
def on_var_write(&block)
  @var_stack.last.on_var_write(&block)
end
pop_frame() click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 445
def pop_frame
  @var_stack.pop
end
push_frame() click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 441
def push_frame
  @var_stack.push ASTStackFrame.new
end
redefine_var(var, node) click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 458
def redefine_var(var, node)
  @var_stack.length.times do |frame_index|
    frame = @var_stack[frame_index]
    next unless frame.include? var.name
    old_var = frame[var.name][1]
  
    if old_var.type.nil?
      # nothing?
    elsif var.type.nil?
      var.type = old_var.type
    elsif var.type != old_var.type
      raise ADSLError, "Unmatched type '#{var.type.name}' for variable '#{var.name}' on line #{node.lineno}"
    end

    frame[var.name][1] = var

    @var_stack[frame_index..-1].reverse.each do |subframe|
      subframe.fire_write_event var.name
    end
    
    return var
  end
  return define_var var, node
end