RubyToC 1.0.0.4 → 1.0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,18 @@
1
+ *** 1.0.0-beta-5 / 2006-05-12
2
+
3
+ + 6 minor enhancements:
4
+ + Split RubyToC to RubyToRubyC and RubyToAnsiC.
5
+ + Extended Environment to be more flexible for various situations.
6
+ + Removed propaganda (bloat) from release.
7
+ + Gemified and reorganized things. Support still needs splitting up.
8
+ + Flipped a lot of internal naming to use Unique.
9
+ + Added ruby_to_c_show (like parse_tree_show).
10
+ + 4(ish) bug fixes:
11
+ + Use ivars instead of cvars so inheritance won't bugger the translator.
12
+ + Corrected unsupported node lists in pipeline.
13
+ + Fixed bugs for splat args, iters, optional args, method name map.
14
+ + Fixed many other bugs.
15
+
1
16
  *** 1.0.0-beta-4 / 2005-07-13
2
17
 
3
18
  + 1 minor enhancements
data/Makefile CHANGED
@@ -1,9 +1,9 @@
1
1
  RUBY?=ruby
2
2
  RUBY_FLAGS?=-w -I.:../../ParseTree/dev/lib:../../ParseTree/dev/test:../../RubyInline/dev
3
- TEST?=
3
+ FILTER?=
4
4
 
5
5
  all test:
6
- $(RUBY) $(RUBY_FLAGS) test_all.rb $(TEST)
6
+ $(RUBY) $(RUBY_FLAGS) test_all.rb $(FILTER)
7
7
 
8
8
  docs:
9
9
  rdoc -d -I png --main RubyToC -x test_\* -x something.rb
@@ -42,6 +42,11 @@ demos: FORCE
42
42
  interp: FORCE
43
43
  for rf in demo/*.rb; do f=$$(basename $$rf .rb); echo $$f; ./interp.rb demo/$$f; done
44
44
 
45
+ sort:
46
+ for f in *.rb; do grep "def " $f > x; sort x > y; echo $f; echo; diff x y; done
47
+ for f in test_*.rb; do grep "def.test_" $f > x; sort x > y; echo $f; echo; diff x y; done
48
+ rm x y
49
+
45
50
  clean:
46
51
  rm -f *~ trouble.* diff.txt demo/*~
47
52
  rm -rf ~/.ruby_inline
@@ -2,97 +2,27 @@ History.txt
2
2
  Makefile
3
3
  Manifest.txt
4
4
  README.txt
5
+ Rakefile
6
+ bin/ruby_to_c_show
7
+ bin/ruby_to_c_validate
5
8
  demo/char.rb
6
9
  demo/factorial.rb
7
10
  demo/hello.rb
8
11
  demo/misc.rb
9
12
  demo/newarray.rb
10
13
  demo/strcat.rb
11
- propaganda/Ruby2C.key/.typeAttributes.dict
12
- propaganda/Ruby2C.key/Contents/PkgInfo
13
- propaganda/Ruby2C.key/pasted.pdf
14
- propaganda/Ruby2C.key/pasted1.pdf
15
- propaganda/Ruby2C.key/pasted10.pdf
16
- propaganda/Ruby2C.key/pasted2.pdf
17
- propaganda/Ruby2C.key/pasted3.pdf
18
- propaganda/Ruby2C.key/pasted4.pdf
19
- propaganda/Ruby2C.key/pasted5.pdf
20
- propaganda/Ruby2C.key/pasted6.pdf
21
- propaganda/Ruby2C.key/pasted7.pdf
22
- propaganda/Ruby2C.key/pasted8.pdf
23
- propaganda/Ruby2C.key/pasted9.pdf
24
- propaganda/Ruby2C.key/presentation.apxl
25
- propaganda/Ruby2C.key/thumbs/.rjsf
26
- propaganda/Ruby2C.key/thumbs/mt0.tiff
27
- propaganda/Ruby2C.key/thumbs/mt1.tiff
28
- propaganda/Ruby2C.key/thumbs/mt10.tiff
29
- propaganda/Ruby2C.key/thumbs/mt11.tiff
30
- propaganda/Ruby2C.key/thumbs/mt12.tiff
31
- propaganda/Ruby2C.key/thumbs/mt13.tiff
32
- propaganda/Ruby2C.key/thumbs/mt14.tiff
33
- propaganda/Ruby2C.key/thumbs/mt15.tiff
34
- propaganda/Ruby2C.key/thumbs/mt2.tiff
35
- propaganda/Ruby2C.key/thumbs/mt3.tiff
36
- propaganda/Ruby2C.key/thumbs/mt4.tiff
37
- propaganda/Ruby2C.key/thumbs/mt5.tiff
38
- propaganda/Ruby2C.key/thumbs/mt6.tiff
39
- propaganda/Ruby2C.key/thumbs/mt7.tiff
40
- propaganda/Ruby2C.key/thumbs/mt8.tiff
41
- propaganda/Ruby2C.key/thumbs/mt9.tiff
42
- propaganda/Ruby2C.key/thumbs/st0.tiff
43
- propaganda/Ruby2C.key/thumbs/st1.tiff
44
- propaganda/Ruby2C.key/thumbs/st10.tiff
45
- propaganda/Ruby2C.key/thumbs/st11.tiff
46
- propaganda/Ruby2C.key/thumbs/st13.tiff
47
- propaganda/Ruby2C.key/thumbs/st131.tiff
48
- propaganda/Ruby2C.key/thumbs/st15.tiff
49
- propaganda/Ruby2C.key/thumbs/st16.tiff
50
- propaganda/Ruby2C.key/thumbs/st161.tiff
51
- propaganda/Ruby2C.key/thumbs/st17.tiff
52
- propaganda/Ruby2C.key/thumbs/st18.tiff
53
- propaganda/Ruby2C.key/thumbs/st19.tiff
54
- propaganda/Ruby2C.key/thumbs/st2.tiff
55
- propaganda/Ruby2C.key/thumbs/st20.tiff
56
- propaganda/Ruby2C.key/thumbs/st201.tiff
57
- propaganda/Ruby2C.key/thumbs/st21.tiff
58
- propaganda/Ruby2C.key/thumbs/st22.tiff
59
- propaganda/Ruby2C.key/thumbs/st23.tiff
60
- propaganda/Ruby2C.key/thumbs/st231.tiff
61
- propaganda/Ruby2C.key/thumbs/st24.tiff
62
- propaganda/Ruby2C.key/thumbs/st25.tiff
63
- propaganda/Ruby2C.key/thumbs/st3.tiff
64
- propaganda/Ruby2C.key/thumbs/st31.tiff
65
- propaganda/Ruby2C.key/thumbs/st4.tiff
66
- propaganda/Ruby2C.key/thumbs/st5.tiff
67
- propaganda/Ruby2C.key/thumbs/st7.tiff
68
- propaganda/Ruby2C.key/thumbs/st8.tiff
69
- propaganda/Ruby2C.key/thumbs/st9.tiff
70
- propaganda/Ruby2C.key/tile_paper_blue.jpg
71
- propaganda/Ruby2C.key/tile_paper_gray.jpg
72
- propaganda/Ruby2C.key/tile_paper_green.jpg
73
- propaganda/Ruby2C.key/tile_paper_purple.jpg
74
- propaganda/Ruby2C.key/tile_paper_red.jpg
75
- propaganda/Ruby2C.key/tile_paper_yellow.jpg
76
- propaganda/Ruby2C.key/tiny/.jrsf
77
- propaganda/Ruby2C.key/tiny/tile_paper_blue.jpg
78
- propaganda/Ruby2C.pdf
79
- propaganda/class diagram.graffle
80
- propaganda/processors.graffle
81
- propaganda/ruby2c architecture.graffle
82
- rewrite.rb
83
- rewriter.rb
84
- ruby_to_c.rb
85
- support.rb
86
- test_all.rb
87
- test_extras.rb
88
- test_rewriter.rb
89
- test_ruby_to_c.rb
90
- test_support.rb
91
- test_type_checker.rb
92
- test_typed_sexp_processor.rb
93
- translate.rb
94
- type.rb
95
- type_checker.rb
96
- typed_sexp_processor.rb
97
- validate.sh
98
- zcomparable.rb
14
+ lib/rewriter.rb
15
+ lib/ruby_to_ansi_c.rb
16
+ lib/ruby_to_ruby_c.rb
17
+ lib/support.rb
18
+ lib/type_checker.rb
19
+ lib/typed_sexp_processor.rb
20
+ test/r2ctestcase.rb
21
+ test/test_all.rb
22
+ test/test_extras.rb
23
+ test/test_rewriter.rb
24
+ test/test_ruby_to_ansi_c.rb
25
+ test/test_ruby_to_ruby_c.rb
26
+ test/test_support.rb
27
+ test/test_type_checker.rb
28
+ test/test_typed_sexp_processor.rb
data/README.txt CHANGED
@@ -17,7 +17,8 @@ RubyToC has the following modules:
17
17
 
18
18
  Rewriter - massages the sexp into a more consistent form.
19
19
  TypeChecker - type inferencer for the above sexps.
20
- RubyToC - converts a ruby (subset) sexp to C.
20
+ RubyToRubyC - converts a ruby (subset) sexp to ruby interals C.
21
+ RubyToAnsiC - converts a ruby (subset) sexp to ANSI C.
21
22
 
22
23
  and the following tools:
23
24
 
@@ -0,0 +1,52 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rake'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/testtask'
7
+ require 'rubygems'
8
+
9
+ task :default => :test
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs.push(*%w( test ../../ParseTree/dev/lib ../../ParseTree/dev/test ../../RubyInline/dev ))
13
+ t.pattern = 'test/test_*.rb'
14
+ t.verbose = true
15
+ end
16
+
17
+ R2C_VERSION = $1 if File.read('./lib/ruby_to_ansi_c.rb') =~ /VERSION = '([^']+)'/
18
+
19
+ spec = Gem::Specification.new do |s|
20
+ s.name = 'RubyToC'
21
+ s.version = R2C_VERSION.sub(/-beta-/, '.')
22
+ s.summary = "Ruby (subset) to C translator."
23
+
24
+ paragraphs = File.read("README.txt").split(/\n\n+/)
25
+ s.description = paragraphs[2]
26
+ puts s.description
27
+
28
+ s.add_dependency('ParseTree')
29
+ s.files = IO.readlines("Manifest.txt").reject { |o| o =~ /propaganda/ }.map {|f| f.chomp }
30
+
31
+ s.require_path = 'lib'
32
+
33
+ s.has_rdoc = true
34
+ s.test_suite_file = "test/test_all.rb"
35
+
36
+ s.author = "Ryan Davis"
37
+ s.email = "ryand-ruby@zenspider.com"
38
+ s.homepage = "http://rubyforge.org/projects/ruby2c/"
39
+ s.rubyforge_project = "ruby2c"
40
+ end
41
+
42
+ Rake::GemPackageTask.new spec do |pkg|
43
+ pkg.need_tar = true
44
+ end
45
+
46
+ task :sort do
47
+ sh 'for f in lib/*.rb; do grep "^ *def " $f | grep -v "def self" > x; sort x > y; echo; echo $f; echo; diff x y; done; true'
48
+ sh 'for f in test/test_*.rb; do grep "def.test_" $f > x; sort x > y; echo; echo $f; echo; diff x y; done; true'
49
+ sh 'rm x y'
50
+ end
51
+
52
+
@@ -0,0 +1,97 @@
1
+ #!/usr/local/bin/ruby -ws
2
+
3
+ $: << "../../ParseTree/dev/lib"
4
+
5
+ require 'pp'
6
+ require 'parse_tree'
7
+ require 'ruby_to_ansi_c'
8
+
9
+ if defined? $h then
10
+ puts "Usage:"
11
+ puts " #{File.basename $0} [options]"
12
+ puts " -h display this help"
13
+ puts " -r display rewriter output only"
14
+ puts " -t display typecherker output only"
15
+ puts " -R display r2c rewriter output only"
16
+ puts " -f fast mode, read from stdin and build class/method around it"
17
+ puts " -c <class> class to process"
18
+ puts " -q quick mode, use regular inspect instead of pp"
19
+ puts " -p print mode, just print instead of p or pp"
20
+ exit 0
21
+ end
22
+
23
+ def discover_new_classes_from
24
+ old_classes = []
25
+ ObjectSpace.each_object(Module) do |klass|
26
+ old_classes << klass
27
+ end
28
+
29
+ yield
30
+
31
+ new_classes = []
32
+ ObjectSpace.each_object(Module) do |klass|
33
+ new_classes << klass
34
+ end
35
+
36
+ new_classes -= old_classes
37
+ new_classes = [ eval($c) ] if defined? $c
38
+ new_classes
39
+ end
40
+
41
+ $f = false unless defined? $f
42
+
43
+ new_classes = discover_new_classes_from do
44
+ ARGV.unshift "-" if ARGV.empty?
45
+ ARGV.each do |name|
46
+ if name == "-" then
47
+ code = $stdin.read
48
+ code = "class Example; def example; #{code}; end; end" if $f
49
+ eval code unless code.nil?
50
+ else
51
+ require name
52
+ end
53
+ end
54
+ end
55
+
56
+ parser = ParseTree.new(false)
57
+ translator = RubyToAnsiC.translator
58
+
59
+ $r ||= false
60
+ $t ||= false
61
+ $R ||= false
62
+
63
+ if $r or $t or $R then
64
+ t = translator.processors
65
+
66
+ t.pop # r2c
67
+ if $r then
68
+ t.pop # r2c rewriter
69
+ t.pop # typechecker
70
+ end
71
+ if $t then
72
+ t.pop # r2c rewriter
73
+ end
74
+ if $R then
75
+ # nothing else to do
76
+ end
77
+ end
78
+
79
+ new_classes.each do |klass|
80
+ sexp = parser.parse_tree klass
81
+ sexp.each do |exp|
82
+ result = translator.process(exp)
83
+
84
+ if defined? $q then
85
+ p result
86
+ next
87
+ end
88
+
89
+ if defined? $p then
90
+ puts result
91
+ next
92
+ end
93
+
94
+ pp result
95
+ end
96
+ end
97
+
File without changes
@@ -157,6 +157,16 @@ class Rewriter < SexpProcessor
157
157
  raise "Unknown :defn format: #{name.inspect} #{args.inspect} #{body.inspect}"
158
158
  end
159
159
 
160
+ if Array === args.last and args.last.first == :block then
161
+ cond = args.pop
162
+ cond.shift # take off :block
163
+ new_code = cond.map do |t, var, val|
164
+ s(:if, s(:call, s(:lvar, var), :nil?), s(:lasgn, var, val), nil)
165
+ end
166
+ body[1].insert 1, *new_code
167
+ end
168
+
169
+
160
170
  return s(:defn, name, args, body)
161
171
  end
162
172
 
@@ -167,7 +177,7 @@ class Rewriter < SexpProcessor
167
177
  def process_fcall(exp)
168
178
  name = exp.shift
169
179
  args = process exp.shift
170
- args[0] = :arglist
180
+ args[0] = :arglist unless args.nil? # for :fcall with block (:iter)
171
181
 
172
182
  return s(:call, nil, name, args)
173
183
  end
@@ -192,9 +202,7 @@ class Rewriter < SexpProcessor
192
202
  var = process exp.shift
193
203
  body = process exp.shift
194
204
 
195
- if var.nil? then
196
- var = s(:lvar, :temp_var1) # HACK Use Unique
197
- end
205
+ var = s(:dasgn_curr, Unique.next) if var.nil?
198
206
 
199
207
  assert_type call, :call
200
208
 
@@ -248,9 +256,14 @@ class Rewriter < SexpProcessor
248
256
  body.find_and_replace_all(:dvar, :lvar)
249
257
  result = s(:block, var, body)
250
258
  else
251
- raise "unknown iter method #{method_name}"
259
+ # HACK we butchered call up top
260
+ result = s(:iter, s(:call, lhs, method_name, call.shift), var, body)
252
261
  end
253
262
  else
263
+ if var.nil? then
264
+ var = s(:lvar, Unique.next)
265
+ end
266
+
254
267
  s(:iter, call, var, body)
255
268
  end
256
269
  end
@@ -354,3 +367,4 @@ class R2CRewriter < SexpProcessor
354
367
  end
355
368
  end
356
369
 
370
+
@@ -10,15 +10,30 @@ require 'rewriter'
10
10
  require 'pp'
11
11
 
12
12
  ##
13
- # Maps a sexp type to a C counterpart.
13
+ # The whole point of this project! RubyToC is an actually very simple
14
+ # SexpProcessor that does the final conversion from Sexp to C code.
15
+ # This class has more unsupported nodes than any other (on
16
+ # purpose--we'd like TypeChecker and friends to be as generally useful
17
+ # as possible), and as a result, supports a very small subset of ruby.
18
+ #
19
+ # NOT SUPPORTED: (keep in sync w/ initialize)
20
+ #
21
+ # :begin, :block_arg, :case, :dstr, :rescue, :self, :super, :when
22
+
23
+ class RubyToAnsiC < SexpProcessor
14
24
 
15
- module TypeMap
25
+ VERSION = '1.0.0-beta-5'
26
+
27
+ # TODO: remove me
28
+ def no(exp) # :nodoc:
29
+ raise "no: #{caller[0].split[1]} #{exp.inspect}"
30
+ end
16
31
 
17
32
  ##
18
33
  # Returns a textual version of a C type that corresponds to a sexp
19
34
  # type.
20
35
 
21
- def c_type(typ)
36
+ def self.c_type(typ)
22
37
  base_type =
23
38
  case typ.type.contents # HACK this is breaking demeter
24
39
  when :float then
@@ -30,13 +45,13 @@ module TypeMap
30
45
  when :symbol then
31
46
  "symbol"
32
47
  when :bool then # TODO: subject to change
33
- "VALUE"
48
+ "bool"
34
49
  when :void then
35
50
  "void"
36
51
  when :homo then
37
52
  "void *" # HACK
38
53
  when :value, :unknown then
39
- "VALUE"
54
+ "void *" # HACK
40
55
  # HACK: uncomment this and fix the above when you want to have good tests
41
56
  # when :unknown then
42
57
  # raise "You should not have unknown types by now!"
@@ -44,37 +59,11 @@ module TypeMap
44
59
  raise "Bug! Unknown type #{typ.inspect} in c_type"
45
60
  end
46
61
 
47
- base_type += "_array" if typ.list?
62
+ base_type += " *" if typ.list? unless typ.unknown?
48
63
 
49
64
  base_type
50
65
  end
51
66
 
52
- module_function :c_type # if $TESTING
53
-
54
- end
55
-
56
- ##
57
- # The whole point of this project! RubyToC is an actually very simple
58
- # SexpProcessor that does the final conversion from Sexp to C code.
59
- # This class has more unsupported nodes than any other (on
60
- # purpose--we'd like TypeChecker and friends to be as generally useful
61
- # as possible), and as a result, supports a very small subset of ruby.
62
- #
63
- # NOT SUPPORTED: (keep in sync w/ initialize)
64
- #
65
- # :begin, :block_arg, :case, :dstr, :rescue, :self, :super, :when
66
-
67
- class RubyToC < SexpProcessor
68
-
69
- VERSION = '1.0.0-beta-4'
70
-
71
- # TODO: remove me
72
- def no(exp) # :nodoc:
73
- raise "no: #{caller[0].split[1]} #{exp.inspect}"
74
- end
75
-
76
- include TypeMap
77
-
78
67
  ##
79
68
  # Provides access to the variable scope.
80
69
 
@@ -96,8 +85,6 @@ class RubyToC < SexpProcessor
96
85
  #include <ruby.h>
97
86
  #define RB_COMPARE(x, y) (x) == (y) ? 0 : (x) < (y) ? -1 : 1
98
87
  typedef char * str;
99
- typedef struct { unsigned long length; long * contents; } long_array;
100
- typedef struct { unsigned long length; str * contents; } str_array;
101
88
  #define case_equal_long(x, y) ((x) == (y))
102
89
  // END METARUBY PREAMBLE
103
90
  " + self.prototypes.join('')
@@ -107,13 +94,13 @@ typedef struct { unsigned long length; str * contents; } str_array;
107
94
  # Lazy initializer for the composite RubytoC translator chain.
108
95
 
109
96
  def self.translator
110
- unless defined? @@translator then
111
- @@translator = CompositeSexpProcessor.new
112
- @@translator << Rewriter.new
113
- @@translator << TypeChecker.new
114
- @@translator << R2CRewriter.new
115
- @@translator << RubyToC.new
116
- @@translator.on_error_in(:defn) do |processor, exp, err|
97
+ unless defined? @translator then
98
+ @translator = CompositeSexpProcessor.new
99
+ @translator << Rewriter.new
100
+ @translator << TypeChecker.new
101
+ @translator << R2CRewriter.new
102
+ @translator << RubyToAnsiC.new
103
+ @translator.on_error_in(:defn) do |processor, exp, err|
117
104
  result = processor.expected.new
118
105
  case result
119
106
  when Array then
@@ -126,7 +113,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
126
113
  result
127
114
  end
128
115
  end
129
- @@translator
116
+ @translator
130
117
  end
131
118
 
132
119
  ##
@@ -174,7 +161,8 @@ typedef struct { unsigned long length; str * contents; } str_array;
174
161
  super
175
162
  @env = Environment.new
176
163
  self.auto_shift_type = true
177
- self.unsupported = [ :begin, :block_arg, :case, :dstr, :rescue, :self, :super, :when, ]
164
+ self.unsupported = [:alias, :alloca, :argscat, :argspush, :attrasgn, :attrset, :back_ref, :begin, :block_arg, :block_pass, :bmethod, :break, :case, :cdecl, :cfunc, :colon2, :colon3, :cref, :cvasgn, :cvdecl, :dasgn, :defined, :defs, :dmethod, :dot2, :dot3, :dregx, :dregx_once, :dstr, :dsym, :dxstr, :ensure, :evstr, :fbody, :fcall, :flip2, :flip3, :for, :gasgn, :ifunc, :last, :masgn, :match, :match2, :match3, :memo, :method, :module, :newline, :next, :nth_ref, :op_asgn1, :op_asgn2, :op_asgn_and, :opt_n, :postexe, :redo, :resbody, :rescue, :retry, :sclass, :self, :splat, :super, :svalue, :to_ary, :undef, :until, :valias, :vcall, :when, :xstr, :yield, :zarray, :zsuper]
165
+
178
166
  self.strict = true
179
167
  self.expected = String
180
168
 
@@ -191,6 +179,13 @@ typedef struct { unsigned long length; str * contents; } str_array;
191
179
  return "#{lhs} && #{rhs}"
192
180
  end
193
181
 
182
+ ##
183
+ # Arglist is used by call arg lists.
184
+
185
+ def process_arglist(exp)
186
+ return process_array(exp)
187
+ end
188
+
194
189
  ##
195
190
  # Argument List including variable types.
196
191
 
@@ -208,19 +203,12 @@ typedef struct { unsigned long length; str * contents; } str_array;
208
203
  # p TypeMap.methods.sort
209
204
  # p c_type(arg.sexp_type)
210
205
 
211
- args << "#{c_type(arg.sexp_type)} #{arg.first}"
206
+ args << "#{self.class.c_type(arg.sexp_type)} #{arg.first}"
212
207
  end
213
208
 
214
209
  return "(#{args.join ', '})"
215
210
  end
216
211
 
217
- ##
218
- # Arglist is used by call arg lists.
219
-
220
- def process_arglist(exp)
221
- return process_array(exp)
222
- end
223
-
224
212
  ##
225
213
  # Array is used as call arg lists and as initializers for variables.
226
214
 
@@ -232,7 +220,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
232
220
  end
233
221
 
234
222
  s = code.join ', '
235
- s = "[]" if s.empty?
223
+ s = "rb_ary_new()" if s.empty? # HACK
236
224
 
237
225
  return s
238
226
  end
@@ -284,17 +272,13 @@ typedef struct { unsigned long length; str * contents; } str_array;
284
272
  args = process exp.shift
285
273
  return "#{receiver} == #{args}" # equal? == address equality
286
274
  when :[]
287
- if receiver_type.list? then
288
- args = process exp.shift
289
- return "#{receiver}.contents[#{args}]"
290
- else
291
- # FIX: not sure about this one... hope for the best.
292
- args = process exp.shift
293
- return "#{receiver}[#{args}]"
294
- end
275
+ args = process exp.shift
276
+ return "#{receiver}[#{args}]"
277
+ when :nil?
278
+ exp.clear
279
+ return receiver.to_s
295
280
  else
296
281
  args = process exp.shift
297
- name = "NIL_P" if name == :nil?
298
282
 
299
283
  if receiver.nil? and args.nil? then
300
284
  args = ""
@@ -364,14 +348,21 @@ typedef struct { unsigned long length; str * contents; } str_array;
364
348
  ##
365
349
  # Function definition
366
350
 
367
- def process_defn(exp)
351
+ METHOD_MAP = {
352
+ :| => "or",
353
+ :& => "and",
354
+ :^ => "xor",
355
+ }
368
356
 
357
+ def process_defn(exp)
369
358
  name = exp.shift
359
+ name = METHOD_MAP[name] if METHOD_MAP.has_key? name
360
+ name = name.to_s.sub(/(.*)\?$/, 'is_\1').intern
370
361
  args = process exp.shift
371
362
  body = process exp.shift
372
363
  function_type = exp.sexp_type
373
364
 
374
- ret_type = c_type function_type.list_type.return_type
365
+ ret_type = self.class.c_type function_type.list_type.return_type
375
366
 
376
367
  @prototypes << "#{ret_type} #{name}#{args};\n"
377
368
  "#{ret_type}\n#{name}#{args} #{body}"
@@ -405,10 +396,10 @@ typedef struct { unsigned long length; str * contents; } str_array;
405
396
  end
406
397
 
407
398
  ##
408
- # False. Pretty straightforward. Currently we output ruby Qfalse
399
+ # False. Pretty straightforward.
409
400
 
410
401
  def process_false(exp)
411
- return "Qfalse"
402
+ return "0"
412
403
  end
413
404
 
414
405
  ##
@@ -489,8 +480,10 @@ typedef struct { unsigned long length; str * contents; } str_array;
489
480
 
490
481
  def process_iter(exp)
491
482
  out = []
483
+ # Only support enums in C-land
484
+ raise UnsupportedNodeError if exp[0][1].nil? # HACK ugly
492
485
  @env.scope do
493
- enum = exp[0][1][1] # HACK ugly
486
+ enum = exp[0][1][1] # HACK ugly t(:iter, t(:call, lhs <-- get lhs
494
487
  call = process exp.shift
495
488
  var = process(exp.shift).intern # semi-HACK-y
496
489
  body = process exp.shift
@@ -500,8 +493,8 @@ typedef struct { unsigned long length; str * contents; } str_array;
500
493
  body.gsub!(/\n\n+/, "\n")
501
494
 
502
495
  out << "unsigned long #{index};"
503
- out << "for (#{index} = 0; #{index} < #{enum}.length; ++#{index}) {"
504
- out << "#{c_type @env.lookup(var)} #{var} = #{enum}.contents[#{index}];"
496
+ out << "for (#{index} = 0; #{enum}[#{index}] != NULL; ++#{index}) {"
497
+ out << "#{self.class.c_type @env.lookup(var)} #{var} = #{enum}[#{index}];"
505
498
  out << body
506
499
  out << "}"
507
500
  end
@@ -534,7 +527,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
534
527
 
535
528
  exp_type = exp.sexp_type
536
529
  @env.add var.to_sym, exp_type
537
- var_type = c_type exp_type
530
+ var_type = self.class.c_type exp_type
538
531
 
539
532
  if exp_type.list? then
540
533
  assert_type args, :array
@@ -543,13 +536,12 @@ typedef struct { unsigned long length; str * contents; } str_array;
543
536
 
544
537
  # HACK: until we figure out properly what to do w/ zarray
545
538
  # before we know what its type is, we will default to long.
546
- array_type = args.sexp_types.empty? ? 'long' : c_type(args.sexp_types.first)
539
+ array_type = args.sexp_types.empty? ? 'void *' : self.class.c_type(args.sexp_types.first)
547
540
 
548
- args.shift
549
- out << "#{var}.length = #{arg_count};\n"
550
- out << "#{var}.contents = (#{array_type}*) malloc(sizeof(#{array_type}) * #{var}.length);\n"
541
+ args.shift # :arglist
542
+ out << "#{var} = (#{array_type}) malloc(sizeof(#{array_type}) * #{args.length});\n"
551
543
  args.each_with_index do |o,i|
552
- out << "#{var}.contents[#{i}] = #{process o};\n"
544
+ out << "#{var}[#{i}] = #{process o};\n"
553
545
  end
554
546
  else
555
547
  out << "#{var} = #{process args}"
@@ -574,7 +566,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
574
566
  when Type.long, Type.float then
575
567
  return value.to_s
576
568
  when Type.symbol then
577
- return ":" + value.to_s
569
+ return value.to_s.inspect
578
570
  else
579
571
  raise "Bug! no: Unknown literal #{value}:#{value.class}"
580
572
  end
@@ -594,7 +586,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
594
586
  # Nil, currently ruby nil, not C NULL (0).
595
587
 
596
588
  def process_nil(exp)
597
- return "Qnil"
589
+ return "NULL"
598
590
  end
599
591
 
600
592
  ##
@@ -642,7 +634,7 @@ typedef struct { unsigned long length; str * contents; } str_array;
642
634
  @env.scope do
643
635
  body = process exp.shift unless exp.empty?
644
636
  @env.current.sort_by { |v,t| v.to_s }.each do |var, var_type|
645
- var_type = c_type var_type
637
+ var_type = self.class.c_type var_type
646
638
  declarations << "#{var_type} #{var};\n"
647
639
  end
648
640
  end
@@ -658,10 +650,10 @@ typedef struct { unsigned long length; str * contents; } str_array;
658
650
  end
659
651
 
660
652
  ##
661
- # Truth... what is truth? In this case, Qtrue.
653
+ # Truth... what is truth?
662
654
 
663
655
  def process_true(exp)
664
- return "Qtrue"
656
+ return "1"
665
657
  end
666
658
 
667
659
  ##
@@ -676,5 +668,4 @@ typedef struct { unsigned long length; str * contents; } str_array;
676
668
  code = "{\n#{body.strip}\n} while (#{cond})" unless is_precondition
677
669
  return code
678
670
  end
679
-
680
671
  end