class Pione::Lang::StructuralContext

StructuralContext is a basic context for all contexts.

Public Class Methods

accept(elt) click to toggle source

Trun the element to be accepted in the context.

# File lib/pione/lang/context.rb, line 18
def accept(elt)
  acceptances << elt

  # define the accessor by snakecase
  define_method(elt.to_s.snake_case) do
    elements.select{|e| e.kind_of?(elt)}
  end
end
acceptances() click to toggle source

Return all accepted declaration types in the context.

# File lib/pione/lang/context.rb, line 13
def acceptances
  @acceptances ||= []
end
inherited(subclass) click to toggle source
# File lib/pione/lang/context.rb, line 27
def inherited(subclass)
  acceptances.each {|acceptance| subclass.accept acceptance}
  members.each {|member_name| subclass.member(member_name, default: default_values[member_name])}
end
new(*args) click to toggle source

Initialize and validate the context.

Calls superclass method
# File lib/pione/lang/context.rb, line 37
def initialize(*args)
  super(*args)
  raise ArgumentError.new(args) unless elements
  validate(acceptances)
end

Public Instance Methods

+(other) click to toggle source
# File lib/pione/lang/context.rb, line 101
def +(other)
  if self.class == other.class
    set(elements: elements + other.elements)
  else
    raise ContextError.new(other, self)
  end
end
eval(env) click to toggle source

Evaluete each element in the context. Pione permit declarations to be in arbitray order, so the strategy of evaluation is try and error.

# File lib/pione/lang/context.rb, line 62
def eval(env)
  try_to_eval(env, elements)
end
pos() click to toggle source

Return the position of first element in the context.

# File lib/pione/lang/context.rb, line 95
def pos
  if elements.size > 0
    elements.first.pos
  end
end
try_to_eval(env, elts) click to toggle source

Make trial loop for evaluation.

# File lib/pione/lang/context.rb, line 67
def try_to_eval(env, elts)
  return if elts.empty?

  exception = nil
  next_elts = []

  # trial
  elts.each do |elt|
    begin
      elt.eval(env).tap {|res| next_elts << res if res.is_a?(Context)}
    rescue UnboundError => e
      exception = e
      next_elts << elt
    end
  end if elts

  # stop endless loop
  if elts == next_elts
    raise exception
  end

  # go next trial
  unless next_elts.empty?
    return try_to_eval(env, next_elts)
  end
end
validate(acceptances) click to toggle source

Validate that the element type is accepted or not. This validation applies same criteria to conditional branches recursively.

# File lib/pione/lang/context.rb, line 45
def validate(acceptances)
  elements.each do |elt|
    # check the type
    accepted = acceptances.any? {|type| type == :all or elt.kind_of?(type)}

    # raise a context error if the type is not accepted
    raise ContextError.new(elt, self) if not(accepted)

    # check for inner branches recursively
    if elt.kind_of?(ConditionalBranch)
      elt.validate(acceptances)
    end
  end
end