Class: StyleScript::Node

Inherits:
Object
  • Object
show all
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.

Constant Summary collapse

TAB =

Tabs are two spaces for pretty-printing.

'  '

Class Method Summary collapse

Instance Method Summary collapse

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

.statementObject

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_onlyObject

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_sensitiveObject

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

#childrenObject



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?

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


82
# File 'lib/style_script/nodes.rb', line 82

def statement?;       false;  end

#statement_only?Boolean

Returns:

  • (Boolean)


83
# File 'lib/style_script/nodes.rb', line 83

def statement_only?;  false;  end

#top_sensitive?Boolean

Returns:

  • (Boolean)


84
# File 'lib/style_script/nodes.rb', line 84

def top_sensitive?;   false;  end

#unwrapObject

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