Module: Red

Defined in:
lib/red/executable.rb,
lib/red.rb,
lib/red/errors.rb,
lib/red/plugin.rb,
lib/red/version.rb,
lib/red/call_nodes.rb,
lib/red/control_nodes.rb,
lib/red/illegal_nodes.rb,
lib/red/constant_nodes.rb,
lib/red/variable_nodes.rb,
lib/red/assignment_nodes.rb,
lib/red/definition_nodes.rb,
lib/red/conditional_nodes.rb,
lib/red/conjunction_nodes.rb

Overview

:nodoc:

Defined Under Namespace

Modules: RailsBase, VERSION Classes: AssignmentNode, BuildError, CallNode, ConditionalNode, ConjunctionNode, ConstantNode, ControlNode, DefinitionNode, IllegalNode, VariableNode

Constant Summary collapse

ARRAY_NODES =
{
  :and          => ConjunctionNode::AndNode,
  :argscat      => IllegalNode::MultipleAssignmentNode,
  :argspush     => IllegalNode::MultipleAssignmentNode,
  :array        => LiteralNode::ArrayNode,
  :attrasgn     => AssignmentNode::AttributeNode,
  :begin        => ControlNode::BeginNode,
  :block        => LiteralNode::MultilineNode,
  :block_arg    => IllegalNode::BlockArgument,
  :block_pass   => IllegalNode::BlockArgument,
  :break        => ConstantNode::BreakNode,
  :call         => CallNode::MethodNode::ExplicitNode,
  :case         => ConditionalNode::CaseNode,
  :class        => DefinitionNode::ClassNode,
  :cdecl        => AssignmentNode::GlobalVariableNode,
  :colon2       => LiteralNode::NamespaceNode,
  :colon3       => ControlNode::LibraryNode,
  :const        => VariableNode::OtherVariableNode,
  :cvar         => VariableNode::ClassVariableNode,
  :cvasgn       => AssignmentNode::ClassVariableNode,
  :cvdecl       => AssignmentNode::ClassVariableNode,
  :dasgn        => AssignmentNode::LocalVariableNode,
  :dasgn_curr   => AssignmentNode::LocalVariableNode,
  :defined      => WrapNode::DefinedNode,
  :defn         => DefinitionNode::InstanceMethodNode,
  :defs         => DefinitionNode::ClassMethodNode,
  :dot2         => LiteralNode::RangeNode,
  :dot3         => LiteralNode::RangeNode::ExclusiveNode,
  :dregx        => IllegalNode::RegexEvaluationNode,
  :dregx_once   => IllegalNode::RegexEvaluationNode,
  :dstr         => LiteralNode::StringNode,
  :dsym         => IllegalNode::SymbolEvaluationNode,
  :dvar         => VariableNode::OtherVariableNode,
  :dxstr        => LiteralNode::StringNode,
  :ensure       => ControlNode::EnsureNode,
  :evstr        => LiteralNode::StringNode,
  :false        => ConstantNode::FalseNode,
  :fcall        => CallNode::MethodNode::ImplicitNode,
  :flip2        => IllegalNode::FlipflopNode,
  :flip3        => IllegalNode::FlipflopNode,
  :for          => ControlNode::ForNode,
  :gasgn        => AssignmentNode::GlobalVariableNode,
  :gvar         => VariableNode::GlobalVariableNode,
  :hash         => LiteralNode::HashNode,
  :iasgn        => AssignmentNode::InstanceVariableNode,
  :if           => ConditionalNode::IfNode,
  :iter         => CallNode::BlockNode,
  :ivar         => VariableNode::InstanceVariableNode,
  :lasgn        => AssignmentNode::LocalVariableNode,
  :lvar         => VariableNode::OtherVariableNode,
  :lit          => LiteralNode::OtherNode,
  :match        => IllegalNode::MatchNode,
  :match2       => CallNode::MatchNode,
  :match3       => CallNode::MatchNode::ReverseNode,
  :masgn        => IllegalNode::MultipleAssignmentNode,
  :module       => DefinitionNode::ModuleNode,
  :next         => ConstantNode::NextNode,
  :nil          => ConstantNode::NilNode,
  :not          => WrapNode::NotNode,
  :op_asgn1     => AssignmentNode::OperatorNode::BracketNode,
  :op_asgn2     => AssignmentNode::OperatorNode::DotNode,
  :op_asgn_and  => AssignmentNode::OperatorNode::AndNode,
  :op_asgn_or   => AssignmentNode::OperatorNode::OrNode,
  :or           => ConjunctionNode::OrNode,
  :postexe      => IllegalNode::PostexeNode,
  :redo         => IllegalNode::RedoNode,
  :rescue       => ControlNode::RescueNode,
  :retry        => IllegalNode::RetryNode,
  :return       => WrapNode::ReturnNode,
  :sclass       => DefinitionNode::ObjectLiteralNode,
  :scope        => LiteralNode::OtherNode,
  :self         => ConstantNode::SelfNode,
  :splat        => LiteralNode::SplatNode,
  :super        => WrapNode::SuperNode,
  :svalue       => LiteralNode::OtherNode,
  :str          => LiteralNode::StringNode,
  :true         => ConstantNode::TrueNode,
  :undef        => IllegalNode::UndefNode,
  :until        => ControlNode::UntilNode,
  :vcall        => VariableNode::OtherVariableNode,
  :when         => ConditionalNode::WhenNode,
  :while        => ControlNode::WhileNode,
  :xstr         => LiteralNode::StringNode,
  :yield        => WrapNode::YieldNode,
  :zarray       => LiteralNode::ArrayNode,
  :zsuper       => WrapNode::SuperNode
}
DATA_NODES =
{
  Bignum        => DataNode::OtherNode,
  Fixnum        => DataNode::OtherNode,
  Float         => DataNode::OtherNode,
  Range         => DataNode::RangeNode,
  Regexp        => DataNode::OtherNode,
  Symbol        => DataNode::SymbolNode,
  String        => DataNode::StringNode,
  NilClass      => DataNode::NilNode
}
RAILS_LOADED =
true
RED_MESSAGES =
{}
@@red_library =
nil
@@red_module =
nil
@@red_class =
nil
@@rescue_is_safe =
false
@@exception_index =
0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.already_updated?Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/red/plugin.rb', line 3

def already_updated?
  @@red_updated ||= false
end

.railsObject



163
164
165
# File 'lib/red.rb', line 163

def self.rails
  require 'red/plugin'
end

.update_javascriptsObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/red/plugin.rb', line 7

def update_javascripts
  @@red_updated = true
  red_dir = 'public/javascripts/red/'
  Dir.glob("#{red_dir}**/*[.rb|.red]").each do |filepath|
    if self.update_javascripts?(filename = filepath.gsub(red_dir,'').gsub(/.[rb|red]+$/,'')) || RAILS_ENV != 'production'
      js_output = (File.read(filepath).string_to_node.compile_node || '') << (@@red_errors ||= '')
      
      filename.split('/')[0...-1].inject('public/javascripts') do |string,dir|
        new_dir = string << '/' << dir
        Dir.mkdir(new_dir) unless File.exists?(new_dir)
        string
      end
      
      File.open("public/javascripts/#{filename}.js", 'w') { |f| f.write(js_output) }
      
      @@red_errors = ''
    end
  end
end

.update_javascripts?(filename) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
31
32
33
# File 'lib/red/plugin.rb', line 27

def update_javascripts?(filename)
  if File.exists?("public/javascripts/#{filename}.js")
    (File.mtime("public/javascripts/red/#{filename}.red") rescue File.mtime("public/javascripts/red/#{filename}.rb")) > File.mtime("public/javascripts/#{filename}.js")
  else
    return true
  end
end

Instance Method Details

#build_nodeObject

:nodoc:



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/red.rb', line 126

def build_node # :nodoc:
  case self
  when Array
    raise(BuildError::UnknownNode, "Don't know how to handle sexp type :#{self.first}") unless ARRAY_NODES[self.first]
    return ARRAY_NODES[self.first].new(*self[1..-1])
  else
    return DATA_NODES[self.class].new(self)
  end
rescue => e
  self.handle_red_error(e)
end

#build_nodesObject

:nodoc:



138
139
140
# File 'lib/red.rb', line 138

def build_nodes  # :nodoc:
  self.map {|node| node.build_node}
end

#build_red_plugin_for_railsObject



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/red/executable.rb', line 2

def build_red_plugin_for_rails
  unless File.exists?('vendor/plugins')
    puts "Directory vendor/plugins does not exist."
    exit
  end
  
  begin
    Dir.mkdir('vendor/plugins/red') unless File.exists?('vendor/plugins/red')
  rescue SystemCallError
    puts "Unable to create directory in vendor/plugins"
    exit
  end
  
  File.open('vendor/plugins/red/init.rb', 'w') { |f| f.write("require 'rubygems'\nrequire 'red'\n\nRed.rails\n") }
  
  puts "Red plugin added to project."
  exit
end

#compile_nodes(options = {}) ⇒ Object

:nodoc:



142
143
144
# File 'lib/red.rb', line 142

def compile_nodes(options = {}) # :nodoc:
  self.map {|node| node.compile_node(options)}
end

#compile_red_to_js(filename) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/red/executable.rb', line 41

def compile_red_to_js(filename)
  unless File.exists?(file = "%s.red" % [filename]) || File.exists?(file = "%sred/%s.red" % [(dir = "public/javascripts/"), filename])
    puts "File #{filename}.red does not exist."
    exit
  end
  
  source = File.read(file)
  js_output = hush_warnings { source.string_to_node }.compile_node
  
  File.open("%s%s.js" % [dir, filename], 'w') {|f| f.write(js_output)} unless filename == 'test'
  
  print_js(js_output, filename)
end

#direct_translate(string) ⇒ Object



21
22
23
24
25
# File 'lib/red/executable.rb', line 21

def direct_translate(string)
  js_output = hush_warnings { string.string_to_node }.compile_node
  print_js(js_output, 'test')
  exit
end

#handle_red_error(error) ⇒ Object

:nodoc:



157
158
159
160
161
# File 'lib/red.rb', line 157

def handle_red_error(error) # :nodoc:
  @@red_errors ||= "\n// Errors"
  @@red_errors << "\n// %s: %s" % [@@exception_index += 1, error]
  return DataNode::ErrorNode.new(@@exception_index)
end

#hush_warningsObject



27
28
29
30
31
32
33
34
35
# File 'lib/red/executable.rb', line 27

def hush_warnings
  $stderr = File.open('spew', 'w')
  output = yield
  $stderr = $>
  
  File.delete('spew')
  
  return output
end

:nodoc:



37
38
39
# File 'lib/red/executable.rb', line 37

def print_js(js_output, filename) # :nodoc:
  puts RED_MESSAGES[:output] % [("- #{filename}.js" unless filename == 'test'), js_output, @@red_errors ||= '']
end

#string_to_nodeObject

:nodoc:



146
147
148
149
150
# File 'lib/red.rb', line 146

def string_to_node # :nodoc:
  self.translate_to_sexp_array.build_node
rescue SyntaxError => e
  self.handle_red_error(e)
end

#translate_to_sexp_arrayObject

:nodoc:

Raises:

  • (TypeError)


152
153
154
155
# File 'lib/red.rb', line 152

def translate_to_sexp_array # :nodoc:
  raise TypeError, "Can only translate Strings" unless self.is_a?(String)
  ParseTree.translate("::Standard\n" + self)
end