Class: MixPrecompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby/precompiler.rb

Constant Summary collapse

GEM_INCLUDES_DIR =
File.expand_path("../../includes", __FILE__)
JS_BASE_FILES =
%w{
  env eval ie object
  array false function
  null number string true }
.each_with_object({}) do |x,h|
  filename = File.expand_path("../../javascript/#{x}.js", __FILE__)
  h[filename] = File.read(filename)
end
JS_OBJECT_TYPES =
%w=
ARRAY ELEMENT EVENT
FALSE FUNCTION NULL
NUMBER OBJECT STRING
TEXT TRUE =

Instance Method Summary collapse

Instance Method Details

#build_js_string(js_files) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ruby/precompiler.rb', line 25

def build_js_string (js_files)
  native_js = js_files.map {|*,script| script }.join ?\n
  
  replace_type_variables!(native_js)
  replace_case_markers!(native_js)
  minify!(native_js)
  
<<-JAVASCRIPT
mix_result_should_be_undefined=function(){var SYMBOLS='...Replace with symbol table...';#{native_js};
window.onload=function(){startup();evaluate('...Replace with AST nodes...');}}();
JAVASCRIPT
end

#locate_file(path) ⇒ Object



38
39
40
41
42
43
44
45
46
47
# File 'lib/ruby/precompiler.rb', line 38

def locate_file (path)
  absolute_path_local = File.expand_path(path, @local_mix_dir)
  absolute_path_gem = File.expand_path(path, GEM_INCLUDES_DIR)
  
  return absolute_path_local if File.exists?(absolute_path_local)
  return absolute_path_gem if File.exists?(absolute_path_gem)
  
  puts "could not locate file #{path} in local directory or in gem includes"
  exit
end

#minify!(string) ⇒ Object



49
50
51
52
53
54
# File 'lib/ruby/precompiler.rb', line 49

def minify! (string)
  string.gsub!(/\s*\/\*.*?\*\/\s*/m, ?\n)
  string.gsub!(/\s*\n\s*/, ?\n)
  string.gsub!(/\s*([{;:,=])\s*/, '\1')
  string.gsub!("\n}", ?})
end

#precompile(absolute_mix_path) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'lib/ruby/precompiler.rb', line 56

def precompile (absolute_mix_path)
  @local_mix_dir = File.dirname(absolute_mix_path)
  @paths_seen = []
  @files = {"mix" => {}, "js" => {}.merge(JS_BASE_FILES)}
  
  @files["mix"][absolute_mix_path] = read_file(absolute_mix_path)
  js_string = build_js_string(@files["js"])
  
  return @files["mix"], js_string
end

#read_file(absolute_path) ⇒ Object



67
68
69
70
71
72
# File 'lib/ruby/precompiler.rb', line 67

def read_file (absolute_path)
  script = File.read(absolute_path) + ?\n
  scan_includes(script)
  
  return script
end

#replace_case_markers!(string) ⇒ Object



74
75
76
77
78
# File 'lib/ruby/precompiler.rb', line 74

def replace_case_markers! (string)
  MixTranslator::NODE_TYPES.each do |k,v|
    string.gsub!("case #{k}:","case #{v}:")
  end
end

#replace_type_variables!(string) ⇒ Object



80
81
82
83
84
# File 'lib/ruby/precompiler.rb', line 80

def replace_type_variables! (string)
  JS_OBJECT_TYPES.each_with_index do |t,i|
    string.gsub!("#{t}_TYPE", i.to_s)
  end
end

#scan_includes(script) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ruby/precompiler.rb', line 86

def scan_includes (script)
  ss = StringScanner.new(script)
  
  while ss.scan(/^\/\*\s*(.*)\.(js)\s*\*\/\s*\n/) || ss.scan(/^~~\s*(.*)\.(js|mix)\s*\n/)
    path, ext = ss[1], ss[2]
    absolute_path = locate_file("#{path}.#{ext}")
    
    @paths_seen.include?(absolute_path) ? next : (@paths_seen << absolute_path)
    
    @files[ext][absolute_path] = read_file(absolute_path)
  end
end