lib/furnace/ast/node.rb in furnace-0.0.1 vs lib/furnace/ast/node.rb in furnace-0.0.2

- old
+ new

@@ -1,70 +1,96 @@ -module Furnace - module AST - class Node - attr_accessor :type, :parent, :children, :metadata +module Furnace::AST + class Node + attr_accessor :type, :parent, :children, :metadata - def initialize(type, children=[], metadata={}) - @type, @children, @metadata = type.to_sym, children, metadata - end + def initialize(type, children=[], metadata={}) + @type, @children, @metadata = type.to_sym, children, metadata + end - def update(type, children=nil, metadata={}) - @type = type - @children = children || @children - - # If something non-nil is passed, including default value, then merge. - # Else, clear metadata store. - if metadata - @metadata.merge!(metadata) - else - @metadata = {} + def normalize_hierarchy! + @children.each do |child| + if child.respond_to? :parent= + child.parent = self end - self + if child.respond_to? :normalize_hierarchy! + child.normalize_hierarchy! + end end - def index - parent.children.find_index(self) - end + self + end - def next - parent.children[index + 1] - end + def update(type, children=nil, metadata={}) + @type = type + @children = children || @children - def prev - parent.children[index - 1] + # If something non-nil is passed, including default value, then merge. + # Else, clear metadata store. + if metadata + @metadata.merge!(metadata) + else + @metadata = {} end - def to_s - "(#{fancy_type} ...)" - end + self + end - def to_sexp(indent=0) - str = "#{" " * indent}(#{fancy_type}" + def dup + node = super + node.children = @children.dup + node.metadata = @metadata.dup + node + end - children.each do |child| - if child.is_a? Node - str << "\n#{child.to_sexp(indent + 1)}" - else - str << " #{child.inspect}" - end - end + def index + parent.children.find_index(self) + end - str << ")" + def next + parent.children[index + 1] + end - str - end - alias :inspect :to_sexp + def prev + parent.children[index - 1] + end - protected + def to_s + "(#{fancy_type} ...)" + end - def fancy_type - dasherized = @type.to_s.gsub('_', '-') - if @metadata[:label] - "#{@metadata[:label]}:#{dasherized}" + def to_sexp(indent=0) + str = "#{" " * indent}(#{fancy_type}" + + children.each do |child| + if (!children[0].is_a?(Node) && child.is_a?(Node)) || + (children[0].is_a?(Node) && child.is_a?(Node) && + child.children.any? { |c| c.is_a?(Node) || c.is_a?(Array) }) || + (child.is_a?(Node) && child.metadata[:label]) + str << "\n#{child.to_sexp(indent + 1)}" else - dasherized + str << " #{child.inspect}" end + end + + str << ")" + + str + end + alias :inspect :to_sexp + + def to_astlet + self + end + + protected + + def fancy_type + dasherized = @type.to_s.gsub('_', '-') + if @metadata[:label] + "#{@metadata[:label]}:#{dasherized}" + else + dasherized end end end end \ No newline at end of file