Class: StyleScript::Node
- Inherits:
-
Object
- Object
- StyleScript::Node
- Defined in:
- lib/style_script/nodes.rb
Overview
The abstract base class for all StyleScript nodes. All nodes are implement a “compile_node” method, which performs the code generation for that node. To compile a node, call the “compile” method, which wraps “compile_node” in some extra smarts, to know when the generated code should be wrapped up in a closure. An options hash is passed and cloned throughout, containing messages from higher in the AST, information about the current scope, and indentation level.
Direct Known Subclasses
AccessorNode, ArrayNode, AssignNode, CallNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, RangeNode, ReturnNode, SliceNode, SplatNode, ThisNode, ThrowNode, TryNode, UntilNode, ValueNode, WhileNode
Constant Summary collapse
- TAB =
Tabs are two spaces for pretty-printing.
' '
Class Method Summary collapse
-
.children(*attributes) ⇒ Object
Provide a quick implementation of a children method.
-
.statement ⇒ Object
Tag this node as a statement, meaning that it can’t be used directly as the result of an expression.
-
.statement_only ⇒ Object
Tag this node as a statement that cannot be transformed into an expression.
-
.top_sensitive ⇒ Object
This node needs to know if it’s being compiled as a top-level statement, in order to compile without special expression conversion.
Instance Method Summary collapse
- #children ⇒ Object
-
#compile(o = {}) ⇒ Object
This is extremely important – we convert JS statements into expressions by wrapping them in a closure, only if it’s possible, and we’re not at the top level of a block (which would be unnecessary), and we haven’t already been asked to return the result.
-
#compile_closure(o = {}) ⇒ Object
Statements converted into expressions share scope with their parent closure, to preserve JavaScript-style lexical scope.
-
#contains?(&block) ⇒ Boolean
Does this node, or any of its children, contain a node of a certain kind?.
-
#idt(tabs = 0) ⇒ Object
Quick short method for the current indentation level, plus tabbing in.
- #statement? ⇒ Boolean
- #statement_only? ⇒ Boolean
- #top_sensitive? ⇒ Boolean
-
#unwrap ⇒ Object
Default implementations of the common node methods.
- #write(code) ⇒ Object
Class Method Details
.children(*attributes) ⇒ Object
Provide a quick implementation of a children method.
34 35 36 37 38 |
# File 'lib/style_script/nodes.rb', line 34 def self.children(*attributes) attr_reader(*attributes) attrs = attributes.map {|a| "[@#{a}]" }.join(', ') class_eval "def children; [#{attrs}].flatten.compact; end" end |
.statement ⇒ Object
Tag this node as a statement, meaning that it can’t be used directly as the result of an expression.
16 17 18 |
# File 'lib/style_script/nodes.rb', line 16 def self.statement class_eval "def statement?; true; end" end |
.statement_only ⇒ Object
Tag this node as a statement that cannot be transformed into an expression. (break, continue, etc.) It doesn’t make sense to try to transform it.
22 23 24 25 |
# File 'lib/style_script/nodes.rb', line 22 def self.statement_only statement class_eval "def statement_only?; true; end" end |
.top_sensitive ⇒ Object
This node needs to know if it’s being compiled as a top-level statement, in order to compile without special expression conversion.
29 30 31 |
# File 'lib/style_script/nodes.rb', line 29 def self.top_sensitive class_eval "def top_sensitive?; true; end" end |
Instance Method Details
#children ⇒ Object
81 |
# File 'lib/style_script/nodes.rb', line 81 def children; []; end |
#compile(o = {}) ⇒ Object
This is extremely important – we convert JS statements into expressions by wrapping them in a closure, only if it’s possible, and we’re not at the top level of a block (which would be unnecessary), and we haven’t already been asked to return the result.
49 50 51 52 53 54 55 56 |
# File 'lib/style_script/nodes.rb', line 49 def compile(o={}) @options = o.dup @indent = o[:indent] top = self.top_sensitive? ? @options[:top] : @options.delete(:top) closure = statement? && !statement_only? && !top && !@options[:return] && !self.is_a?(CommentNode) closure &&= !contains? {|n| n.statement_only? } closure ? compile_closure(@options) : compile_node(@options) end |
#compile_closure(o = {}) ⇒ Object
Statements converted into expressions share scope with their parent closure, to preserve JavaScript-style lexical scope.
60 61 62 63 |
# File 'lib/style_script/nodes.rb', line 60 def compile_closure(o={}) @indent = o[:indent] ClosureNode.wrap(self).compile(o.merge(:shared_scope => o[:scope])) end |
#contains?(&block) ⇒ Boolean
Does this node, or any of its children, contain a node of a certain kind?
71 72 73 74 75 76 77 |
# File 'lib/style_script/nodes.rb', line 71 def contains?(&block) children.each do |node| return true if yield(node) return true if node.is_a?(Node) && node.contains?(&block) end false end |
#idt(tabs = 0) ⇒ Object
Quick short method for the current indentation level, plus tabbing in.
66 67 68 |
# File 'lib/style_script/nodes.rb', line 66 def idt(tabs=0) @indent + (TAB * tabs) end |
#statement? ⇒ Boolean
82 |
# File 'lib/style_script/nodes.rb', line 82 def statement?; false; end |
#statement_only? ⇒ Boolean
83 |
# File 'lib/style_script/nodes.rb', line 83 def statement_only?; false; end |
#top_sensitive? ⇒ Boolean
84 |
# File 'lib/style_script/nodes.rb', line 84 def top_sensitive?; false; end |
#unwrap ⇒ Object
Default implementations of the common node methods.
80 |
# File 'lib/style_script/nodes.rb', line 80 def unwrap; self; end |
#write(code) ⇒ Object
40 41 42 43 |
# File 'lib/style_script/nodes.rb', line 40 def write(code) puts "#{self.class.to_s}:\n#{@options.inspect}\n#{code}\n\n" if ENV['VERBOSE'] code end |