class ADSL::Parser::ASTSpec
Public Instance Methods
adsl_ast_size(options = {})
click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 266 def adsl_ast_size(options = {}) sum = 1 @classes.each do |c| sum += c.adsl_ast_size end actions = options[:action_name].nil? ? @actions : @actions.select{ |a| a.name.text == options[:action_name] } actions.each do |a| sum += options[:pre_optimize] ? a.pre_optimize_adsl_ast_size : a.adsl_ast_size end invs = options[:invariant_name].nil? ? @invariants : @invariants.select{ |a| a.name.text == options[:invariant_name] } invs.each do |i| sum += i.adsl_ast_size end sum end
to_adsl()
click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 262 def to_adsl "#{ @classes.map(&:to_adsl).join }\n#{ @actions.map(&:to_adsl).join }\n#{ @invariants.map(&:to_adsl).join }" end
typecheck_and_resolve()
click to toggle source
# File lib/adsl/parser/ast_nodes.rb, line 180 def typecheck_and_resolve context = ASTTypecheckResolveContext.new # make sure class names are unique @classes.each do |class_node| if context.classes.include? class_node.name.text raise ADSLError, "Duplicate class name '#{class_node.name.text}' on line #{class_node.name.lineno} (first definition on line #{context.classes[class_node.name.text][0].name.lineno}" end klass = ADSL::DS::DSClass.new :name => class_node.name.text context.classes[klass.name] = [class_node, klass] end # make sure the parent classes are declared properly and that the inheritance graph is non-cyclic parents = Hash.new{} context.classes.values.select{ |v| v[0].parent_name }.each do |class_node, klass| parent_node, parent = context.classes[class_node.parent_name.text] raise ADSLError, "Unknown parent class name #{class_node.parent_name.text} for class #{class_node.name.text} on line #{class_node.parent_name}" if parent.nil? klass.parent = parent parents[klass] = parent parent_chain = [klass] while parent != nil do if parent_chain.include? parent cyclic_chain = parent_chain.slice(parent_chain.index(parent), parent_chain.length) + [parent] raise ADSLError, "Cyclic inheritance detected: #{cyclic_chain.map{ |c| c.name }.join ' -> '}" end parent_chain << parent parent = parents[parent] end end # make sure relations are valid and refer to existing classes context.classes.values.each do |class_node, klass| class_node.relations.each do |rel_node| iter = klass while iter != nil if context.relations[iter.name].include? rel_node.name.text raise ADSLError, "Duplicate relation name '#{class_node.name.text}' under class '#{klass.name}' on line #{rel_node.lineno} (first definition on line #{context.relations[iter.name][rel_node.name.text][0].lineno}" end iter = iter.parent end rel = ADSL::DS::DSRelation.new :name => rel_node.name.text, :from_class => klass context.relations[klass.name][rel.name] = [rel_node, rel] end end # now that classes and rels are initialized, check them @classes.each do |class_node| class_node.typecheck_and_resolve context end @actions.each do |action_node| action_node.typecheck_and_resolve context end # make sure invariants have unique names; add names to unnamed invariants names = Set.new @invariants.each do |invariant_node| invariant = invariant_node.typecheck_and_resolve context if invariant.name && names.include?(invariant.name) raise ADSLError, "Duplicate invariant name #{invariant.name} on line #{invariant_node.lineno}" end name = invariant.name || "unnamed_line_#{invariant_node.lineno}" while names.include? name name = name.increment_suffix end invariant.name = name context.invariants << invariant names << name end @invariants.each do |invariant_node| invariant = invariant_node.typecheck_and_resolve context end ADSL::DS::DSSpec.new( :classes => context.classes.map{ |a, b| b[1] }, :actions => context.actions.map{ |a, b| b[1] }, :invariants => context.invariants.dup ) end