RubyToC 1.0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +69 -0
- data/Makefile +49 -0
- data/Manifest.txt +98 -0
- data/README.txt +75 -0
- data/demo/char.rb +13 -0
- data/demo/factorial.rb +11 -0
- data/demo/hello.rb +11 -0
- data/demo/misc.rb +25 -0
- data/demo/newarray.rb +11 -0
- data/demo/strcat.rb +12 -0
- data/rewrite.rb +32 -0
- data/rewriter.rb +356 -0
- data/ruby_to_c.rb +680 -0
- data/support.rb +317 -0
- data/test_all.rb +9 -0
- data/test_extras.rb +143 -0
- data/test_rewriter.rb +292 -0
- data/test_ruby_to_c.rb +533 -0
- data/test_support.rb +525 -0
- data/test_type_checker.rb +838 -0
- data/test_typed_sexp_processor.rb +134 -0
- data/translate.rb +31 -0
- data/type.rb +33 -0
- data/type_checker.rb +922 -0
- data/typed_sexp_processor.rb +88 -0
- data/validate.sh +49 -0
- data/zcomparable.rb +300 -0
- metadata +74 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
begin require 'rubygems' rescue LoadError end
|
3
|
+
require 'sexp_processor'
|
4
|
+
require 'support'
|
5
|
+
|
6
|
+
$TESTING = false unless defined? $TESTING
|
7
|
+
|
8
|
+
class TypedSexp < Sexp
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
# TODO: should probably be Type.unknown
|
12
|
+
@sexp_type = Type === args.last ? args.pop : nil
|
13
|
+
super(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def sexp_type
|
17
|
+
unless array_type? then
|
18
|
+
@sexp_type
|
19
|
+
else
|
20
|
+
types = self.sexp_types.flatten.uniq
|
21
|
+
|
22
|
+
if types.size > 1 then
|
23
|
+
Type.hetero
|
24
|
+
else
|
25
|
+
Type.homo
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def _set_sexp_type(o)
|
31
|
+
@sexp_type = o
|
32
|
+
end
|
33
|
+
|
34
|
+
def sexp_type=(o)
|
35
|
+
raise "You shouldn't call this on an #{first}" if array_type?
|
36
|
+
raise "You shouldn't call this a second time, ever" unless
|
37
|
+
@sexp_type.nil? or @sexp_type == Type.unknown
|
38
|
+
_set_sexp_type(o)
|
39
|
+
end
|
40
|
+
|
41
|
+
def sexp_types
|
42
|
+
raise "You shouldn't call this if not an #{@@array_types.join(' or ')}, was #{first} (#{self.inspect})" unless array_type?
|
43
|
+
self.grep(Sexp).map { |x| x.sexp_type }
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(obj)
|
47
|
+
case obj
|
48
|
+
when TypedSexp
|
49
|
+
super && sexp_type == obj.sexp_type
|
50
|
+
else
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_a
|
56
|
+
result = super
|
57
|
+
if defined?(@sexp_type) and not @sexp_type.nil? then
|
58
|
+
result += [ @sexp_type ]
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
def inspect
|
64
|
+
sexp_str = self.map {|x|x.inspect}.join(', ')
|
65
|
+
sexp_type_str = (sexp_str.empty? ? "" : ", ") + "#{array_type? ? sexp_types.inspect : sexp_type}" unless sexp_type.nil?
|
66
|
+
return "t(#{sexp_str}#{sexp_type_str})"
|
67
|
+
end
|
68
|
+
|
69
|
+
def pretty_print(q)
|
70
|
+
q.group(1, 't(', ')') do
|
71
|
+
q.seplist(self) {|v| q.pp v }
|
72
|
+
unless @sexp_type.nil? then
|
73
|
+
q.text ", " unless self.empty?
|
74
|
+
q.pp @sexp_type
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
inspect
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def t(*args) # stupid shortcut to make indentation much cleaner
|
86
|
+
TypedSexp.new(*args)
|
87
|
+
end
|
88
|
+
|
data/validate.sh
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# set -xv
|
4
|
+
|
5
|
+
trap "exit 1" 1 2 3 15
|
6
|
+
|
7
|
+
DIRS="-I../../metaruby/dev/tests/builtin:../../metaruby/dev/tests:../../ParseTree/dev/test:../../ParseTree/dev/lib"
|
8
|
+
for d in $(ls -d ../../*/dev | grep -v ruby_to_c); do
|
9
|
+
DIRS="-I$d $DIRS"
|
10
|
+
done
|
11
|
+
|
12
|
+
if [ -z "$1" ]; then
|
13
|
+
if [ -f rb.bad.txt ]; then
|
14
|
+
mv rb.bad.txt rb.files.txt
|
15
|
+
else
|
16
|
+
find ../../*/dev /usr/local/lib/ruby/1.8/ -name \*.rb | grep -v tk | xargs egrep -l "^(class|module)" > rb.files.txt
|
17
|
+
fi
|
18
|
+
|
19
|
+
total_count=$(wc -l rb.files.txt | awk '{print $1}')
|
20
|
+
curr_count=0
|
21
|
+
good_count=0
|
22
|
+
for f in $(cat rb.files.txt); do
|
23
|
+
curr_count=$(($curr_count + 1))
|
24
|
+
if ruby $DIRS ./translate.rb $f &> /tmp/r2c.$$ < /dev/null; then
|
25
|
+
echo $f >> rb.good.txt
|
26
|
+
status=pass
|
27
|
+
good_count=$(($good_count + 1))
|
28
|
+
else
|
29
|
+
echo $f >> rb.bad.txt
|
30
|
+
cat /tmp/r2c.$$ >> rb.err.txt
|
31
|
+
status=fail
|
32
|
+
fi
|
33
|
+
fname=`basename $f`
|
34
|
+
pct=$(echo "$good_count / $curr_count * 100.0" | bc -l)
|
35
|
+
printf "%4d/%4d (%6.2f%%): %s %s\n" $curr_count $total_count $pct $status $fname
|
36
|
+
done
|
37
|
+
else
|
38
|
+
if [ "$1" == "-q" ]; then
|
39
|
+
ruby $DIRS ./translate.rb "$2" 2>&1 | egrep "(ERROR|no:)" | perl -pe '
|
40
|
+
s/ in .*//;
|
41
|
+
s/(translating \S+):/$1/;
|
42
|
+
s/(is not an Array \w+):.*/$1/;
|
43
|
+
s/.* (is not a supported node type)/blah $1/;
|
44
|
+
s/(Unable to unify).*/$1/;
|
45
|
+
s/(Unknown literal) \S+/$1/;' | occur
|
46
|
+
else
|
47
|
+
ruby $DIRS ./translate.rb "$1"
|
48
|
+
fi
|
49
|
+
fi
|
data/zcomparable.rb
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
|
2
|
+
class ZComparable
|
3
|
+
|
4
|
+
# int
|
5
|
+
# rb_cmpint(val, a, b)
|
6
|
+
# VALUE val, a, b;
|
7
|
+
# {
|
8
|
+
# if (NIL_P(val)) {
|
9
|
+
# zrb_cmperr(a, b);
|
10
|
+
# }
|
11
|
+
# if (FIXNUM_P(val)) return FIX2INT(val);
|
12
|
+
# if (TYPE(val) == T_BIGNUM) {
|
13
|
+
# if (RBIGNUM(val)->sign) return 1;
|
14
|
+
# return -1;
|
15
|
+
# }
|
16
|
+
# if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
|
17
|
+
# if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
|
18
|
+
# return 0;
|
19
|
+
# }
|
20
|
+
|
21
|
+
def zrb_cmpint(val, a, b)
|
22
|
+
return val.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
# void
|
26
|
+
# rb_cmperr(x, y)
|
27
|
+
# VALUE x, y;
|
28
|
+
# {
|
29
|
+
# const char *classname;
|
30
|
+
#
|
31
|
+
# if (SPECIAL_CONST_P(y)) {
|
32
|
+
# y = rb_inspect(y);
|
33
|
+
# classname = StringValuePtr(y);
|
34
|
+
# }
|
35
|
+
# else {
|
36
|
+
# classname = rb_obj_classname(y);
|
37
|
+
# }
|
38
|
+
# rb_raise(rb_eArgError, "comparison of %s with %s failed",
|
39
|
+
# rb_obj_classname(x), classname);
|
40
|
+
# }
|
41
|
+
|
42
|
+
def zrb_cmperr(x, y)
|
43
|
+
$stderr.puts("comparison of " + x.class.to_s + " with " + y.class.to_s + " failed")
|
44
|
+
exit 1
|
45
|
+
# raise ArgumentError, "comparison of #{x.class} with #{y.class} failed"
|
46
|
+
end
|
47
|
+
|
48
|
+
# #define cmperr() (rb_cmperr(x, y), Qnil)
|
49
|
+
|
50
|
+
# static VALUE
|
51
|
+
# cmp_eq(a)
|
52
|
+
# VALUE *a;
|
53
|
+
# {
|
54
|
+
# VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
|
55
|
+
|
56
|
+
# if (NIL_P(c)) return Qnil;
|
57
|
+
# if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
|
58
|
+
# return Qfalse;
|
59
|
+
# }
|
60
|
+
|
61
|
+
def zcmp_eq(a, b)
|
62
|
+
c = a <=> b
|
63
|
+
return false if c.nil?
|
64
|
+
return c.to_i == 0
|
65
|
+
end
|
66
|
+
|
67
|
+
# static VALUE
|
68
|
+
# cmp_failed()
|
69
|
+
# {
|
70
|
+
# return Qnil;
|
71
|
+
# }
|
72
|
+
|
73
|
+
# TODO RETIRE me
|
74
|
+
def zcmp_failed
|
75
|
+
return nil
|
76
|
+
end
|
77
|
+
|
78
|
+
# /*
|
79
|
+
# * call-seq:
|
80
|
+
# * obj == other => true or false
|
81
|
+
# *
|
82
|
+
# * Compares two objects based on the receiver's <code><=></code>
|
83
|
+
# * method, returning true if it returns 0. Also returns true if
|
84
|
+
# * _obj_ and _other_ are the same object.
|
85
|
+
# */
|
86
|
+
|
87
|
+
# static VALUE
|
88
|
+
# cmp_equal(x, y)
|
89
|
+
# VALUE x, y;
|
90
|
+
# {
|
91
|
+
# VALUE a[2];
|
92
|
+
#
|
93
|
+
# if (x == y) return Qtrue;
|
94
|
+
#
|
95
|
+
# a[0] = x; a[1] = y;
|
96
|
+
# return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
|
97
|
+
# }
|
98
|
+
|
99
|
+
def zcmp_equal(x, y)
|
100
|
+
|
101
|
+
if x.equal? y then
|
102
|
+
return true
|
103
|
+
else
|
104
|
+
return zcmp_eq(x, y) # HACK rescue false
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# /*
|
110
|
+
# * call-seq:
|
111
|
+
# * obj > other => true or false
|
112
|
+
# *
|
113
|
+
# * Compares two objects based on the receiver's <code><=></code>
|
114
|
+
# * method, returning true if it returns 1.
|
115
|
+
# */
|
116
|
+
|
117
|
+
# static VALUE
|
118
|
+
# cmp_gt(x, y)
|
119
|
+
# VALUE x, y;
|
120
|
+
# {
|
121
|
+
# VALUE c = rb_funcall(x, cmp, 1, y);
|
122
|
+
|
123
|
+
# if (NIL_P(c)) return cmperr();
|
124
|
+
# if (rb_cmpint(c, x, y) > 0) return Qtrue;
|
125
|
+
# return Qfalse;
|
126
|
+
# }
|
127
|
+
|
128
|
+
def zcmp_gt(x, y)
|
129
|
+
c = x <=> y
|
130
|
+
|
131
|
+
zrb_cmperr(x, y) if c.nil?
|
132
|
+
|
133
|
+
return c.to_i > 0
|
134
|
+
end
|
135
|
+
|
136
|
+
# /*
|
137
|
+
# * call-seq:
|
138
|
+
# * obj >= other => true or false
|
139
|
+
# *
|
140
|
+
# * Compares two objects based on the receiver's <code><=></code>
|
141
|
+
# * method, returning true if it returns 0 or 1.
|
142
|
+
# */
|
143
|
+
|
144
|
+
# static VALUE
|
145
|
+
# cmp_ge(x, y)
|
146
|
+
# VALUE x, y;
|
147
|
+
# {
|
148
|
+
# VALUE c = rb_funcall(x, cmp, 1, y);
|
149
|
+
|
150
|
+
# if (NIL_P(c)) return cmperr();
|
151
|
+
# if (rb_cmpint(c, x, y) >= 0) return Qtrue;
|
152
|
+
# return Qfalse;
|
153
|
+
# }
|
154
|
+
|
155
|
+
def zcmp_ge(x, y)
|
156
|
+
c = x <=> y
|
157
|
+
|
158
|
+
zrb_cmperr(x, y) if c.nil?
|
159
|
+
|
160
|
+
return c.to_i >= 0
|
161
|
+
end
|
162
|
+
|
163
|
+
# /*
|
164
|
+
# * call-seq:
|
165
|
+
# * obj < other => true or false
|
166
|
+
# *
|
167
|
+
# * Compares two objects based on the receiver's <code><=></code>
|
168
|
+
# * method, returning true if it returns -1.
|
169
|
+
# */
|
170
|
+
|
171
|
+
# static VALUE
|
172
|
+
# cmp_lt(x, y)
|
173
|
+
# VALUE x, y;
|
174
|
+
# {
|
175
|
+
# VALUE c = rb_funcall(x, cmp, 1, y);
|
176
|
+
#
|
177
|
+
# if (NIL_P(c)) return cmperr();
|
178
|
+
# if (rb_cmpint(c, x, y) < 0) return Qtrue;
|
179
|
+
# return Qfalse;
|
180
|
+
# }
|
181
|
+
|
182
|
+
def zcmp_lt(x, y)
|
183
|
+
c = x <=> y
|
184
|
+
|
185
|
+
zrb_cmperr(x, y) if c.nil?
|
186
|
+
|
187
|
+
return c.to_i < 0
|
188
|
+
end
|
189
|
+
|
190
|
+
# /*
|
191
|
+
# * call-seq:
|
192
|
+
# * obj <= other => true or false
|
193
|
+
# *
|
194
|
+
# * Compares two objects based on the receiver's <code><=></code>
|
195
|
+
# * method, returning true if it returns -1 or 0.
|
196
|
+
# */
|
197
|
+
|
198
|
+
# static VALUE
|
199
|
+
# cmp_le(x, y)
|
200
|
+
# VALUE x, y;
|
201
|
+
# {
|
202
|
+
# VALUE c = rb_funcall(x, cmp, 1, y);
|
203
|
+
|
204
|
+
# if (NIL_P(c)) return cmperr();
|
205
|
+
# if (rb_cmpint(c, x, y) <= 0) return Qtrue;
|
206
|
+
# return Qfalse;
|
207
|
+
# }
|
208
|
+
|
209
|
+
def zcmp_le(x, y)
|
210
|
+
c = x <=> y
|
211
|
+
|
212
|
+
zrb_cmperr(x, y) if c.nil?
|
213
|
+
|
214
|
+
return c.to_i <= 0
|
215
|
+
end
|
216
|
+
|
217
|
+
# /*
|
218
|
+
# * call-seq:
|
219
|
+
# * obj.between?(min, max) => true or false
|
220
|
+
# *
|
221
|
+
# * Returns <code>false</code> if <i>obj</i> <code><=></code>
|
222
|
+
# * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
|
223
|
+
# * <i>max</i> is greater than zero, <code>true</code> otherwise.
|
224
|
+
# *
|
225
|
+
# * 3.between?(1, 5) #=> true
|
226
|
+
# * 6.between?(1, 5) #=> false
|
227
|
+
# * 'cat'.between?('ant', 'dog') #=> true
|
228
|
+
# * 'gnu'.between?('ant', 'dog') #=> false
|
229
|
+
# *
|
230
|
+
# */
|
231
|
+
|
232
|
+
# static VALUE
|
233
|
+
# cmp_between(x, min, max)
|
234
|
+
# VALUE x, min, max;
|
235
|
+
# {
|
236
|
+
# if (RTEST(cmp_lt(x, min))) return Qfalse;
|
237
|
+
# if (RTEST(cmp_gt(x, max))) return Qfalse;
|
238
|
+
# return Qtrue;
|
239
|
+
# }
|
240
|
+
|
241
|
+
def zcmp_between(x, min, max)
|
242
|
+
|
243
|
+
return false if zcmp_lt(x, min)
|
244
|
+
return false if zcmp_gt(x, max)
|
245
|
+
return true
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
# /*
|
250
|
+
# * The <code>Comparable</code> mixin is used by classes whose objects
|
251
|
+
# * may be ordered. The class must define the <code><=></code> operator,
|
252
|
+
# * which compares the receiver against another object, returning -1, 0,
|
253
|
+
# * or +1 depending on whether the receiver is less than, equal to, or
|
254
|
+
# * greater than the other object. <code>Comparable</code> uses
|
255
|
+
# * <code><=></code> to implement the conventional comparison operators
|
256
|
+
# * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
|
257
|
+
# * and <code>></code>) and the method <code>between?</code>.
|
258
|
+
# *
|
259
|
+
# * class SizeMatters
|
260
|
+
# * include Comparable
|
261
|
+
# * attr :str
|
262
|
+
# * def <=>(anOther)
|
263
|
+
# * str.size <=> anOther.str.size
|
264
|
+
# * end
|
265
|
+
# * def initialize(str)
|
266
|
+
# * @str = str
|
267
|
+
# * end
|
268
|
+
# * def inspect
|
269
|
+
# * @str
|
270
|
+
# * end
|
271
|
+
# * end
|
272
|
+
# *
|
273
|
+
# * s1 = SizeMatters.new("Z")
|
274
|
+
# * s2 = SizeMatters.new("YY")
|
275
|
+
# * s3 = SizeMatters.new("XXX")
|
276
|
+
# * s4 = SizeMatters.new("WWWW")
|
277
|
+
# * s5 = SizeMatters.new("VVVVV")
|
278
|
+
# *
|
279
|
+
# * s1 < s2 #=> true
|
280
|
+
# * s4.between?(s1, s3) #=> false
|
281
|
+
# * s4.between?(s3, s5) #=> true
|
282
|
+
# * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
|
283
|
+
# *
|
284
|
+
# */
|
285
|
+
|
286
|
+
# void
|
287
|
+
# Init_Comparable()
|
288
|
+
# {
|
289
|
+
# rb_mComparable = rb_define_module("Comparable");
|
290
|
+
# rb_define_method(rb_mComparable, "==", cmp_equal, 1);
|
291
|
+
# rb_define_method(rb_mComparable, ">", cmp_gt, 1);
|
292
|
+
# rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
|
293
|
+
# rb_define_method(rb_mComparable, "<", cmp_lt, 1);
|
294
|
+
# rb_define_method(rb_mComparable, "<=", cmp_le, 1);
|
295
|
+
# rb_define_method(rb_mComparable, "between?", cmp_between, 2);
|
296
|
+
|
297
|
+
# cmp = rb_intern("<=>");
|
298
|
+
# }
|
299
|
+
|
300
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10.1
|
3
|
+
specification_version: 1
|
4
|
+
name: RubyToC
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0.4
|
7
|
+
date: 2005-07-13
|
8
|
+
summary: Ruby (subset) to C translator.
|
9
|
+
require_paths:
|
10
|
+
- "."
|
11
|
+
email: ryand-ruby@zenspider.com
|
12
|
+
homepage: http://rubyforge.org/projects/ruby2c/
|
13
|
+
rubyforge_project: ruby2c
|
14
|
+
description: ruby_to_c translates a static ruby subset to C. Hopefully it works.
|
15
|
+
autorequire: ruby_to_c
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Ryan Davis
|
29
|
+
files:
|
30
|
+
- History.txt
|
31
|
+
- Makefile
|
32
|
+
- Manifest.txt
|
33
|
+
- README.txt
|
34
|
+
- demo/char.rb
|
35
|
+
- demo/factorial.rb
|
36
|
+
- demo/hello.rb
|
37
|
+
- demo/misc.rb
|
38
|
+
- demo/newarray.rb
|
39
|
+
- demo/strcat.rb
|
40
|
+
- rewrite.rb
|
41
|
+
- rewriter.rb
|
42
|
+
- ruby_to_c.rb
|
43
|
+
- support.rb
|
44
|
+
- test_all.rb
|
45
|
+
- test_extras.rb
|
46
|
+
- test_rewriter.rb
|
47
|
+
- test_ruby_to_c.rb
|
48
|
+
- test_support.rb
|
49
|
+
- test_type_checker.rb
|
50
|
+
- test_typed_sexp_processor.rb
|
51
|
+
- translate.rb
|
52
|
+
- type.rb
|
53
|
+
- type_checker.rb
|
54
|
+
- typed_sexp_processor.rb
|
55
|
+
- validate.sh
|
56
|
+
- zcomparable.rb
|
57
|
+
test_files:
|
58
|
+
- test_all.rb
|
59
|
+
rdoc_options: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
requirements: []
|
64
|
+
dependencies:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: ParseTree
|
67
|
+
version_requirement:
|
68
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
69
|
+
requirements:
|
70
|
+
-
|
71
|
+
- ">"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.0.0
|
74
|
+
version:
|