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