module Macros::Sexp
Public Instance Methods
node?(node)
click to toggle source
# File lib/macros/sexp.rb, line 50 def node?(node) node.is_a?(AST::Node) end
s(type, *children)
click to toggle source
# File lib/macros/sexp.rb, line 6 def s(type, *children) Parser::AST::Node.new(type, children) end
seval(ast)
click to toggle source
# File lib/macros/sexp.rb, line 54 def seval(ast) eval(Unparser.unparse(ast)) end
sfind(sexp, specs)
click to toggle source
Traverse into sexp by type and child position
# File lib/macros/sexp.rb, line 11 def sfind(sexp, specs) specs.inject(sexp) do |node, spec| return NotFound if node.nil? if spec.is_a?(Symbol) && node.type == spec node elsif spec.is_a?(Integer) && node.children.length > spec node.children[spec] elsif spec.is_a?(Array) node.children.grep(AST::Node) .flat_map { |child| sfind(child, spec) } .reject { |child| child == NotFound } else return NotFound end end end
smatch?(node, pattern)
click to toggle source
# File lib/macros/sexp.rb, line 43 def smatch?(node, pattern) return false unless node.type == pattern.type pattern.children.zip(node.children).all? do |a, b| a == b || node?(a) && smatch?(b, a) end end
treefilter(node, &block)
click to toggle source
# File lib/macros/sexp.rb, line 36 def treefilter(node, &block) acc = [] acc << node if block.call(node) treemap(node) { |n| acc << n if block.call(n) ; n} acc.freeze end
treemap(node, &block)
click to toggle source
# File lib/macros/sexp.rb, line 29 def treemap(node, &block) block.call(s(node.type, *node.children.map do |child| next child unless child.is_a? AST::Node block.call(treemap(child, &block)) end)) end