atduskgreg-rad 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/History.txt +104 -0
  2. data/License.txt +282 -0
  3. data/Manifest.txt +142 -0
  4. data/README.rdoc +55 -0
  5. data/Rakefile +142 -0
  6. data/bin/hello_world_test/Makefile +436 -0
  7. data/bin/hello_world_test/hello_world.cpp +23 -0
  8. data/bin/rad +302 -0
  9. data/lib/examples/add_hysteresis.rb +13 -0
  10. data/lib/examples/basic_blink.rb +10 -0
  11. data/lib/examples/blink_m_address_assignment.rb +104 -0
  12. data/lib/examples/blink_m_hello.rb +14 -0
  13. data/lib/examples/blink_m_multi.rb +61 -0
  14. data/lib/examples/blink_with_serial.rb +16 -0
  15. data/lib/examples/configure_pa_lcd_boot.rb +91 -0
  16. data/lib/examples/debounce_methods.rb +49 -0
  17. data/lib/examples/external_variable_fu.rb +26 -0
  18. data/lib/examples/external_variables.rb +32 -0
  19. data/lib/examples/first_sound.rb +23 -0
  20. data/lib/examples/frequency_generator.rb +30 -0
  21. data/lib/examples/hello_array.rb +48 -0
  22. data/lib/examples/hello_array2.rb +79 -0
  23. data/lib/examples/hello_array_eeprom.rb +59 -0
  24. data/lib/examples/hello_clock.rb +84 -0
  25. data/lib/examples/hello_eeprom.rb +51 -0
  26. data/lib/examples/hello_eeprom_lcdpa.rb +81 -0
  27. data/lib/examples/hello_format_print.rb +94 -0
  28. data/lib/examples/hello_lcd_charset.rb +75 -0
  29. data/lib/examples/hello_pa_lcd.rb +59 -0
  30. data/lib/examples/hello_servos.rb +88 -0
  31. data/lib/examples/hello_spectra_sound.rb +38 -0
  32. data/lib/examples/hello_world.rb +11 -0
  33. data/lib/examples/hello_xbee.rb +12 -0
  34. data/lib/examples/hysteresis_duel.rb +39 -0
  35. data/lib/examples/i2c_with_clock_chip.rb +124 -0
  36. data/lib/examples/midi_beat_box.rb +86 -0
  37. data/lib/examples/midi_scales.rb +94 -0
  38. data/lib/examples/motor_knob.rb +30 -0
  39. data/lib/examples/servo_buttons.rb +23 -0
  40. data/lib/examples/servo_calibrate_continuous.rb +92 -0
  41. data/lib/examples/servo_throttle.rb +40 -0
  42. data/lib/examples/software_serial.rb +10 -0
  43. data/lib/examples/sparkfun_lcd.rb +48 -0
  44. data/lib/examples/spectra_soft_pot.rb +34 -0
  45. data/lib/examples/times_method.rb +8 -0
  46. data/lib/examples/toggle.rb +10 -0
  47. data/lib/examples/twitter.rb +57 -0
  48. data/lib/examples/two_wire.rb +14 -0
  49. data/lib/libraries/AFSoftSerial/AFSoftSerial.cpp +321 -0
  50. data/lib/libraries/AFSoftSerial/AFSoftSerial.h +61 -0
  51. data/lib/libraries/AFSoftSerial/keywords.txt +18 -0
  52. data/lib/libraries/AF_XPort/AF_XPort.cpp +166 -0
  53. data/lib/libraries/AF_XPort/AF_XPort.h +48 -0
  54. data/lib/libraries/DS1307/DS1307.cpp +162 -0
  55. data/lib/libraries/DS1307/DS1307.h +66 -0
  56. data/lib/libraries/DS1307/keywords.txt +18 -0
  57. data/lib/libraries/FrequencyTimer2/FrequencyTimer2.cpp +144 -0
  58. data/lib/libraries/FrequencyTimer2/FrequencyTimer2.h +42 -0
  59. data/lib/libraries/FrequencyTimer2/keywords.txt +22 -0
  60. data/lib/libraries/I2CEEPROM/I2CEEPROM.cpp +120 -0
  61. data/lib/libraries/I2CEEPROM/I2CEEPROM.h +70 -0
  62. data/lib/libraries/I2CEEPROM/keywords.txt +21 -0
  63. data/lib/libraries/LoopTimer/LoopTimer.cpp +35 -0
  64. data/lib/libraries/LoopTimer/LoopTimer.h +34 -0
  65. data/lib/libraries/LoopTimer/keywords.txt +27 -0
  66. data/lib/libraries/OneWire/OneWire.cpp +194 -0
  67. data/lib/libraries/OneWire/OneWire.h +63 -0
  68. data/lib/libraries/OneWire/keywords.txt +35 -0
  69. data/lib/libraries/OneWire/readme.txt +13 -0
  70. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +296 -0
  71. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +69 -0
  72. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +311 -0
  73. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +67 -0
  74. data/lib/libraries/Servo/Servo.cpp +192 -0
  75. data/lib/libraries/Servo/Servo.h +61 -0
  76. data/lib/libraries/Stepper/Stepper.cpp +220 -0
  77. data/lib/libraries/Stepper/Stepper.h +86 -0
  78. data/lib/libraries/Stepper/keywords.txt +28 -0
  79. data/lib/libraries/Wire/Wire.cpp +262 -0
  80. data/lib/libraries/Wire/Wire.h +67 -0
  81. data/lib/libraries/Wire/keywords.txt +31 -0
  82. data/lib/libraries/Wire/twi.h +57 -0
  83. data/lib/libraries/Wire/utility/twi.c +449 -0
  84. data/lib/libraries/Wire/utility/twi.h +57 -0
  85. data/lib/plugins/bitwise_ops.rb +54 -0
  86. data/lib/plugins/blink.rb +25 -0
  87. data/lib/plugins/blink_m.rb +356 -0
  88. data/lib/plugins/debounce.rb +138 -0
  89. data/lib/plugins/debug_output_to_lcd.rb +71 -0
  90. data/lib/plugins/hysteresis.rb +52 -0
  91. data/lib/plugins/input_output_state.rb +84 -0
  92. data/lib/plugins/lcd_padding.rb +58 -0
  93. data/lib/plugins/mem_test.rb +37 -0
  94. data/lib/plugins/midi.rb +60 -0
  95. data/lib/plugins/parallax_ping.rb +50 -0
  96. data/lib/plugins/servo_pulse.rb +31 -0
  97. data/lib/plugins/servo_setup.rb +86 -0
  98. data/lib/plugins/smoother.rb +54 -0
  99. data/lib/plugins/spark_fun_serial_lcd.rb +100 -0
  100. data/lib/plugins/spectra_symbol.rb +79 -0
  101. data/lib/plugins/twitter_connect.rb +145 -0
  102. data/lib/rad.rb +5 -0
  103. data/lib/rad/README.rdoc +5 -0
  104. data/lib/rad/arduino_plugin.rb +246 -0
  105. data/lib/rad/arduino_sketch.rb +627 -0
  106. data/lib/rad/generators/makefile/makefile.erb +243 -0
  107. data/lib/rad/generators/makefile/makefile.rb +38 -0
  108. data/lib/rad/hardware_library.rb +813 -0
  109. data/lib/rad/init.rb +14 -0
  110. data/lib/rad/progressbar.rb +236 -0
  111. data/lib/rad/rad_processor.rb +128 -0
  112. data/lib/rad/rad_rewriter.rb +94 -0
  113. data/lib/rad/rad_type_checker.rb +26 -0
  114. data/lib/rad/sim/arduino_sketch.rb +57 -0
  115. data/lib/rad/sketch_compiler.rb +47 -0
  116. data/lib/rad/tasks/build_and_make.rake +210 -0
  117. data/lib/rad/tasks/rad.rb +2 -0
  118. data/lib/rad/todo.txt +13 -0
  119. data/lib/rad/variable_processing.rb +153 -0
  120. data/lib/rad/version.rb +9 -0
  121. data/scripts/txt2html +67 -0
  122. data/setup.rb +1585 -0
  123. data/spec/examples/hello_world.rb +11 -0
  124. data/spec/examples/serial_motor.rb +12 -0
  125. data/spec/models/arduino_sketch_spec.rb +82 -0
  126. data/spec/models/sketch_compiler_spec.rb +96 -0
  127. data/spec/models/spec_helper.rb +2 -0
  128. data/spec/sim/hello_world_spec.rb +42 -0
  129. data/spec/spec.opts +1 -0
  130. data/test/test_array_processing.rb +179 -0
  131. data/test/test_plugin_loading.rb +151 -0
  132. data/test/test_translation_post_processing.rb +185 -0
  133. data/test/test_variable_processing.rb +238 -0
  134. data/website/examples/assembler_test.rb.html +73 -0
  135. data/website/examples/gps_reader.rb.html +39 -0
  136. data/website/examples/hello_world.rb.html +38 -0
  137. data/website/examples/serial_motor.rb.html +41 -0
  138. data/website/index.html +178 -0
  139. data/website/index.txt +64 -0
  140. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  141. data/website/stylesheets/screen.css +169 -0
  142. data/website/template.rhtml +48 -0
  143. metadata +217 -0
@@ -0,0 +1,26 @@
1
+ require 'ruby_to_ansi_c'
2
+
3
+ class RADTypeChecker < TypeChecker
4
+
5
+ def process_const(exp)
6
+ c = exp.shift
7
+ if c.to_s =~ /^[A-Z]/ then
8
+ # TODO: validate that it really is a const?
9
+ # uber hackery
10
+ # since constants are defined in the arduino_sketch define method and
11
+ # we can't inject them into the methods
12
+ # transport them here with a $define_types hash
13
+
14
+ $define_types.each do |k,v|
15
+ if k == c.to_s
16
+ @const_type = eval "Type.#{v}"
17
+ end
18
+ end
19
+ return t(:const, c, @const_type)
20
+ else
21
+ raise "I don't know what to do with const #{c.inspect}. It doesn't look like a class."
22
+ end
23
+ raise "need to finish process_const in #{self.class}"
24
+ end
25
+
26
+ end
@@ -0,0 +1,57 @@
1
+ ON = true
2
+ OFF = !ON
3
+ HIGH = ON
4
+ LOW = !HIGH
5
+
6
+ class ArduinoSketch
7
+ attr_accessor :pins
8
+
9
+ def initialize
10
+ @pins = self.class.instance_variable_get("@pins")
11
+ end
12
+
13
+ def self.output_pin(num, opts)
14
+ module_eval "@pins ||= []"
15
+ module_eval do
16
+ @pins << Pin.new( num, :type => :output )
17
+ end
18
+
19
+ if opts[:as]
20
+ module_eval <<-CODE
21
+ def #{opts[:as]}
22
+ pins.select{|p| p.num == #{num}}.first
23
+ end
24
+ CODE
25
+ end
26
+ end
27
+
28
+ def loop
29
+ end
30
+
31
+ def digitalWrite( pin, value )
32
+ to_change = pins.select{|p| p.num == pin.num}.first
33
+ to_change.value = value
34
+ end
35
+
36
+ def delay( millis )
37
+ end
38
+
39
+ # def serial_read
40
+ # end
41
+
42
+ # def serial_available
43
+ # end
44
+
45
+ # def blink
46
+ # end
47
+ end
48
+
49
+ class Pin
50
+ attr_accessor :num, :type, :value
51
+
52
+ def initialize num, opts
53
+ @num = num
54
+ @type = opts[:type]
55
+ @value = opts[:value] || false
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+ # TODO:
2
+ # compilation
3
+ # gather pieces of code we need as strings
4
+ # translate non-loop methods
5
+ # do plugin stuff
6
+ # deal with examples/ exception
7
+ # manage upload process
8
+ # compose_setup should move in here entirely
9
+
10
+ # require 'arduino_sketch'
11
+
12
+ class SketchCompiler
13
+ attr_accessor :path, :body, :klass, :target_dir, :name
14
+
15
+ def initialize path_to_sketch
16
+ @path = File.expand_path(path_to_sketch)
17
+ @body = open(@path).read
18
+ @name = @path.split("/").last.split(".").first
19
+ @klass = @name.split(".").first.split("_").collect{|c| c.capitalize}.join("")
20
+ @target_dir = parent_dir
21
+ end
22
+
23
+ def parent_dir
24
+ self.path.split("/")[0..@path.split("/").length-2].join("/")
25
+ end
26
+
27
+ def build_dir
28
+ "#{self.target_dir}/#{self.name}"
29
+ end
30
+
31
+ def create_build_dir! optional_path_prefix=nil
32
+ self.target_dir = optional_path_prefix if optional_path_prefix
33
+ mkdir_p build_dir
34
+ end
35
+
36
+ def process_constants
37
+ self.body.gsub!("HIGH", "1")
38
+ self.body.gsub!("LOW", "0")
39
+ self.body.gsub!("ON", "1")
40
+ self.body.gsub!("OFF", "0")
41
+ end
42
+
43
+ def sketch_methods
44
+ self.body.scan(/^\s*def\s.\w*/).collect{ |m| m.gsub(/\s*def\s*/, "") }
45
+ end
46
+
47
+ end
@@ -0,0 +1,210 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../init.rb")
2
+ require 'ruby_to_ansi_c'
3
+
4
+ C_VAR_TYPES = "unsigned|int|long|double|str|char|byte|bool"
5
+
6
+ # incredibly primitive tests
7
+ # rake test:compile or rake test:upload
8
+ # runs through all sketches in the example directory
9
+
10
+ def run_tests(sketch, type)
11
+ sh %{rake make:#{type} sketch=examples/#{sketch}}
12
+ end
13
+
14
+ namespace :test do
15
+
16
+ desc "iterate through all the sketches in the example directory"
17
+ task :upload => :gather do
18
+ @examples.each {|e| run_tests(e, "upload")}
19
+ end
20
+
21
+ task :compile => :gather do
22
+
23
+ @examples.each {|e| run_tests(e, "compile")}
24
+ end
25
+
26
+ desc "gather all tests"
27
+ task :gather do # => "make:upload" do
28
+ @examples = []
29
+ if ENV['sketch']
30
+ @examples << ENV['sketch']
31
+ else
32
+ Dir.entries( File.expand_path("#{RAD_ROOT}/examples/") ).each do |f|
33
+ @examples << f.split('.').first if (f =~ /\.rb$/)
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+
41
+ namespace :make do
42
+
43
+ desc "compile the sketch and then upload it to your Arduino board"
44
+ task :upload => :compile do
45
+ if Makefile.hardware_params['physical_reset']
46
+ puts "Reset the Arduino and hit enter.\n==If your board doesn't need it, you can turn off this prompt in config/software.yml=="
47
+ STDIN.gets.chomp
48
+ end
49
+ sh %{cd #{@sketch.build_dir}; make upload}
50
+ end
51
+
52
+ desc "generate a makefile and use it to compile the .cpp"
53
+ task :compile => [:clean_sketch_dir, "build:sketch"] do # should also depend on "build:sketch"
54
+ Makefile.compose_for_sketch( @sketch.build_dir )
55
+
56
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
57
+ sh %{cd #{@sketch.build_dir}; make depend; make}
58
+ end
59
+
60
+ desc "generate a makefile and use it to compile the .cpp using the current .cpp file"
61
+ task :compile_cpp => ["build:sketch_dir", "build:gather_required_plugins", "build:plugin_setup", "build:setup", :clean_sketch_dir] do # should also depend on "build:sketch"
62
+ Makefile.compose_for_sketch( @sketch.build_dir )
63
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
64
+ sh %{cd #{@sketch.build_dir}; make depend; make}
65
+ end
66
+
67
+ desc "generate a makefile and use it to compile the .cpp and upload it using current .cpp file"
68
+ task :upload_cpp => ["build:sketch_dir", "build:gather_required_plugins", "build:plugin_setup", "build:setup", :clean_sketch_dir] do # should also depend on "build:sketch"
69
+ Makefile.compose_for_sketch( @sketch.build_dir )
70
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
71
+ sh %{cd #{@sketch.build_dir}; make depend; make upload}
72
+ end
73
+
74
+ task :clean_sketch_dir => ["build:file_list", "build:sketch_dir"] do
75
+ FileList.new(Dir.entries("#{@sketch.build_dir}")).exclude("#{@sketch.name}.cpp").exclude(/^\./).each do |f|
76
+ sh %{rm #{@sketch.build_dir}/#{f}}
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ namespace :build do
83
+
84
+ desc "actually build the sketch"
85
+ task :sketch => [:file_list, :sketch_dir, :gather_required_plugins, :plugin_setup, :setup] do
86
+ c_methods = []
87
+ sketch_signatures = []
88
+ # until we better understand RubyToC let's see what's happening on errors
89
+ @sketch.sketch_methods.each do |meth|
90
+ raw_rtc_meth = RADProcessor.translate(constantize(@sketch.klass), meth)
91
+ puts "Translator Error: #{raw_rtc_meth.inspect}" if raw_rtc_meth =~ /\/\/ ERROR:/
92
+ c_methods << raw_rtc_meth unless meth == "setup"
93
+ # treat the setup method differently
94
+ @additional_setup = [] if meth == "setup"
95
+ raw_rtc_meth.each {|m| @additional_setup << ArduinoSketch.add_to_setup(m) } if meth == "setup"
96
+ end
97
+ c_methods.each {|meth| sketch_signatures << "#{meth.scan(/^\w*\s?\*?\n.*\)/)[0].gsub("\n", " ")};" }
98
+ clean_c_methods = []
99
+ # remove external variables that were previously injected
100
+ c_methods.join("\n").each { |meth| clean_c_methods << ArduinoSketch.post_process_ruby_to_c_methods(meth) }
101
+ c_methods_with_timer = clean_c_methods.join.gsub(/loop\(\)\s\{/,"loop() {")
102
+ # last chance to add/change setup
103
+ @setup[2] << sketch_signatures.join("\n") unless sketch_signatures.empty?
104
+ # add special setup method to existing setup if present
105
+ if @additional_setup
106
+ @setup[2] << "void additional_setup();" # declaration
107
+ @setup[4] << "\tadditional_setup();" # call from setup
108
+ @setup[5] << @additional_setup.join("") #
109
+ end
110
+ result = "#{@setup.join( "\n" )}\n#{c_methods_with_timer}\n"
111
+ File.open("#{@sketch.build_dir}/#{@sketch.name}.cpp", "w"){|f| f << result}
112
+ end
113
+
114
+ # needs to write the library include and the method signatures
115
+ desc "build setup function"
116
+ task :setup do
117
+ eval "class #{@sketch.klass} < ArduinoSketch; end;"
118
+
119
+ @@as = HardwareLibrary.new
120
+
121
+ delegate_methods = @@as.methods - Object.new.methods
122
+ delegate_methods.reject!{|m| m == "compose_setup"}
123
+
124
+ delegate_methods.each do |meth|
125
+ constantize(@sketch.klass).module_eval <<-CODE
126
+ def self.#{meth}(*args)
127
+ @@as.#{meth}(*args)
128
+ end
129
+ CODE
130
+ end
131
+ # allow variable declaration without quotes: @foo = int
132
+ ["long","unsigned","int","byte","short"].each do |type|
133
+ constantize(@sketch.klass).module_eval <<-CODE
134
+ def self.#{type}
135
+ return "#{type}"
136
+ end
137
+ CODE
138
+ end
139
+
140
+ @sketch.process_constants
141
+
142
+ eval ArduinoSketch.pre_process(@sketch.body)
143
+ @@as.process_external_vars(constantize(@sketch.klass))
144
+ @setup = @@as.compose_setup
145
+ end
146
+
147
+ desc "add plugin methods"
148
+ task :plugin_setup do
149
+ $plugins_to_load.each do |name|
150
+ klass = name.split(".").first.split("_").collect{|c| c.capitalize}.join("")
151
+ eval "class #{klass} < ArduinoPlugin; end;"
152
+
153
+ @@ps = ArduinoPlugin.new
154
+ plugin_delegate_methods = @@ps.methods - Object.new.methods
155
+ plugin_delegate_methods.reject!{|m| m == "compose_setup"}
156
+
157
+ plugin_delegate_methods.each do |meth|
158
+ constantize(klass).module_eval <<-CODE
159
+ def self.#{meth}(*args)
160
+ @@ps.#{meth}(*args)
161
+ end
162
+ CODE
163
+ end
164
+
165
+ eval ArduinoPlugin.process(File.read("vendor/plugins/#{name}"))
166
+
167
+ end
168
+ @@no_plugins = ArduinoPlugin.new if @plugin_names.empty?
169
+ end
170
+
171
+ desc "determine which plugins to load based on use of methods in sketch"
172
+ task :gather_required_plugins do
173
+ @plugin_names.each do |name|
174
+ ArduinoPlugin.check_for_plugin_use(@sketch.body, File.read("vendor/plugins/#{name}"), name )
175
+ end
176
+ puts "#{$plugins_to_load.length} of #{$plugin_methods_hash.length} plugins are being loaded: #{$plugins_to_load.join(", ")}"
177
+ end
178
+
179
+ desc "setup target directory named after your sketch class"
180
+ task :sketch_dir => [:file_list] do
181
+ @sketch.create_build_dir!
182
+ end
183
+
184
+ task :file_list do
185
+ # take another look at this, since if the root directory name is changed, everything breaks
186
+ # perhaps we generate a constant when the project is generated an pop it here or in the init file
187
+ if ENV['sketch']
188
+ @sketch = SketchCompiler.new File.expand_path("#{ENV['sketch']}.rb")
189
+ else
190
+ # assume the only .rb file in the sketch dir is the sketch:
191
+ @sketch = SketchCompiler.new Dir.glob("#{File.expand_path(File.dirname(__FILE__))}/../../../*.rb").first
192
+ end
193
+
194
+ @plugin_names = []
195
+ Dir.entries( File.expand_path("#{RAD_ROOT}/vendor/plugins/") ).each do |f|
196
+ if (f =~ /\.rb$/)
197
+ @plugin_names << f
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ #yoinked from Rails
204
+ def constantize(camel_cased_word)
205
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
206
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
207
+ end
208
+
209
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
210
+ end
@@ -0,0 +1,2 @@
1
+ require 'rake'
2
+ Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
data/lib/rad/todo.txt ADDED
@@ -0,0 +1,13 @@
1
+ TODO:
2
+ =====
3
+
4
+ Future:
5
+ - complete library system: script/install library some_library
6
+ - bin/rad:
7
+ - setup and use a ~/.rad for new project defaults
8
+ - put repository on git
9
+ - project gallery (examples with movies)
10
+ - testing framework
11
+ - implement wire lib
12
+ - subclasses of ArduinoSketch (should just work, but what are they for?)
13
+ - simulator
@@ -0,0 +1,153 @@
1
+ module ExternalVariableProcessing
2
+ # issues
3
+ # testing
4
+ # add checking for colon
5
+
6
+
7
+ ## need to clean this up
8
+ ## need to test
9
+ def process_external_vars(klass)
10
+ vars = eval "#{klass}.instance_variables"
11
+ local_vars = []
12
+ vars.each { |v| local_vars << ":#{v.gsub("@", "")}" }
13
+ loc_vars = local_vars.join(", ")
14
+ # add accessors 
15
+ klass.module_eval "class << self; attr_accessor #{loc_vars} end"
16
+ local_vars.each do |symbol|
17
+ name = symbol.gsub(":","")
18
+ t_var = eval "#{klass}.#{name}"
19
+ pre_process_vars(name, t_var)
20
+ end
21
+ end
22
+
23
+
24
+ def pre_process_vars(name, var)
25
+ # puts
26
+ # puts
27
+ case var
28
+ when Integer
29
+ # puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} 29"
30
+ value = var
31
+ type = "int"
32
+ post_process_vars(name, type, value)
33
+ when Float
34
+ # puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} 34"
35
+ value = var
36
+ type = "float"
37
+ post_process_vars(name, type, value)
38
+ when String
39
+ # puts "pre_process: #{name}, #{var.inspect} got #{var.class} on 39"
40
+ if var.match(",").nil? && var =~ /long|byte|unsigned|int|short/
41
+ # puts "pre_process #{name}, #{var.inspect} got #{var.class} level three sublevel"
42
+ type = var
43
+ value = nil
44
+ post_process_vars(name, type, value)
45
+ else
46
+ value = var.split(",").first.lstrip
47
+ type = var.split(",")[1].nil? ? nil : var.split(",")[1].lstrip
48
+ translate_variables( name , type, value )
49
+ end
50
+ when TrueClass
51
+ # puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} on 50"
52
+ value = 1
53
+ type = "bool"
54
+ post_process_vars(name, type, value)
55
+ when FalseClass
56
+ # puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} on 55"
57
+ value = 0
58
+ type = "bool"
59
+ post_process_vars(name, type, value)
60
+ when Array
61
+ post_process_arrays(name, var)
62
+ else
63
+ raise ArgumentError, "not sure what to do here... got #{name} with value #{var} which is a #{var.class}"
64
+ end
65
+ end
66
+
67
+
68
+ def translate_variables(name, type = nil, value = nil)
69
+
70
+ unless type.nil?
71
+ check_variable_type(type)
72
+ end
73
+
74
+ # classify the values
75
+ if value.class == Fixnum
76
+ # puts "translate_variables: #{name}, #{value}, #{type} is a fixnum, got #{value.class} on 74"
77
+ elsif value.class == Float
78
+ # puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 76"
79
+ elsif value =~ /^-(\d|x)*$/
80
+ value = value.to_i
81
+ type = "int" if type.nil?
82
+ elsif value =~ /^-(\d|\.|x)*$/
83
+ value = value.to_f
84
+ unless type.nil?
85
+ raise ArgumentError, "#{value} should be a float got #{type}" unless type == "float"
86
+ end
87
+ type = "float" if type.nil?
88
+
89
+ elsif value[0,1] !~ /\d/
90
+ # puts value[0,1]
91
+ # puts "translate_variables: #{name}, #{value}, #{type} is a number of some type, got #{value.class} on 79"
92
+ type = "char*"
93
+ value = "\"#{value}\""
94
+ elsif value !~ /(\.|x)/
95
+ # puts "translate_variables: #{name}, #{value}, #{type} is an integer, got #{value.class} on 83"
96
+ value = value.to_i
97
+ type = "int" if type.nil?
98
+ elsif value =~ /(\d*\.\d*)/ # and no
99
+ # puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 87"
100
+ value = value.to_f
101
+ type = "float"
102
+ elsif value =~ /0x\d\d/
103
+ # puts "translate_variables: #{name}, #{value}, #{type} is a byte, got #{value.class} on 91"
104
+ type = "byte"
105
+ else
106
+ raise ArgumentError, "not sure what to do with a value of #{value} with a type like #{type}"
107
+ end
108
+
109
+ post_process_vars(name, type, value)
110
+ end
111
+
112
+
113
+
114
+ def post_process_vars(name, type, value = nil)
115
+ value = " = #{value}" if value
116
+ $external_var_identifiers << "__#{name}" unless $external_var_identifiers.include?("__#{name}")
117
+ $external_vars << "#{type} __#{name}#{value};"
118
+ end
119
+
120
+ def post_process_arrays(name, var)
121
+ type = c_type(var[0])
122
+ $array_types[name] = type
123
+ assignment = var.inspect.gsub("[","{").gsub("]","}")
124
+ c_style_array = "#{type} __#{name}[] = #{assignment};"
125
+ $external_var_identifiers << "__#{name}" unless $external_var_identifiers.include?("__#{name}")
126
+ $external_array_vars << c_style_array unless $external_array_vars.include?(c_style_array)
127
+ end
128
+
129
+ def check_variable_type(type)
130
+ unless type =~ /#{C_VAR_TYPES}/
131
+ raise ArgumentError, "the following variable types are supported \n #{C_VAR_TYPES.gsub("|",", ")} got #{type}"
132
+ end
133
+ end
134
+
135
+ def c_type(typ)
136
+ type =
137
+ case typ
138
+ when Integer
139
+ "int"
140
+ when String
141
+ "char*"
142
+ when TrueClass
143
+ "bool"
144
+ when FalseClass
145
+ "bool"
146
+ else
147
+ raise "Bug! Unknown type #{typ.inspect} in c_type"
148
+ end
149
+
150
+ type
151
+ end
152
+
153
+ end