Class: ADSL::Parser::ASTTypecheckResolveContext

Inherits:
Object
  • Object
show all
Defined in:
lib/adsl/parser/ast_nodes.rb

Defined Under Namespace

Classes: ASTStackFrame

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeASTTypecheckResolveContext

Returns a new instance of ASTTypecheckResolveContext.



394
395
396
397
398
399
400
401
402
403
404
405
406
407
# 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

Instance Attribute Details

#actionsObject

Returns the value of attribute actions.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def actions
  @actions
end

#classesObject

Returns the value of attribute classes.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def classes
  @classes
end

#invariantsObject

Returns the value of attribute invariants.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def invariants
  @invariants
end

#pre_stmtsObject

Returns the value of attribute pre_stmts.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def pre_stmts
  @pre_stmts
end

#relationsObject

Returns the value of attribute relations.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def relations
  @relations
end

#var_stackObject

Returns the value of attribute var_stack.



343
344
345
# File 'lib/adsl/parser/ast_nodes.rb', line 343

def var_stack
  @var_stack
end

Class Method Details

.context_vars_that_differ(*contexts) ⇒ Object



517
518
519
520
521
522
523
524
525
526
527
528
529
# 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

Instance Method Details

#define_var(var, node) ⇒ Object

Raises:



449
450
451
452
453
454
455
456
# 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) ⇒ Object



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# 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_frameObject



434
435
436
437
438
439
# File 'lib/adsl/parser/ast_nodes.rb', line 434

def in_stack_frame
  push_frame
  yield
ensure
  pop_frame
end

#initialize_copy(source) ⇒ Object



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# 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) ⇒ Object



483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
# 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) ⇒ Object



430
431
432
# 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) ⇒ Object



426
427
428
# File 'lib/adsl/parser/ast_nodes.rb', line 426

def on_var_write(&block)
  @var_stack.last.on_var_write(&block)
end

#pop_frameObject



445
446
447
# File 'lib/adsl/parser/ast_nodes.rb', line 445

def pop_frame
  @var_stack.pop
end

#push_frameObject



441
442
443
# File 'lib/adsl/parser/ast_nodes.rb', line 441

def push_frame
  @var_stack.push ASTStackFrame.new
end

#redefine_var(var, node) ⇒ Object



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
# 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