public
Description: a ruby-to-pyc compiler
Clone URL: git://github.com/why/unholy.git
Search Repo:
 * lib/unholy/pyasm.rb: got some basic blocks working. slight work on 
 arrays.
why (author)
Thu May 15 00:12:27 -0700 2008
commit  d5266bb310536bd7899e9291bf05ddf1b79827fc
tree    67187c5e507ad5267c9759be21154844c26f1404
parent  d15375b5c542aba81333671d08691bc67153b30b
...
2
3
4
5
6
7
8
 
...
2
3
4
 
 
 
 
5
0
@@ -2,8 +2,5 @@
0
 $: << "./lib"
0
 require 'unholy'
0
 
0
-asm = Pyasm.new(ARGV[0])
0
-asm.import :Kernel
0
-asm.eval IO.read(ARGV[0])
0
-asm.compile(ARGV[0]+".pyc")
0
+unholy(ARGV[0], ARGV[0] + ".pyc")
...
1
2
3
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
0
@@ -1,4 +1,11 @@
0
 require 'unholy/tuple'
0
 require 'unholy/pickle'
0
 require 'unholy/pyasm'
0
+
0
+def unholy(fname, fpyc)
0
+ asm = Pyasm.new(fname)
0
+ asm.import :Kernel
0
+ asm.eval IO.read(fname)
0
+ asm.compile(fpyc)
0
+end
...
8
9
10
11
 
12
13
14
15
 
 
 
16
17
18
19
...
49
50
51
52
53
 
 
54
55
56
 
 
 
 
 
57
58
59
...
95
96
97
98
 
99
100
101
102
...
133
134
135
 
 
 
136
137
138
 
 
 
 
139
140
141
142
...
173
174
175
 
 
 
 
 
 
176
177
178
 
 
 
 
 
 
 
179
180
181
182
...
198
199
200
 
201
202
203
204
205
206
 
 
 
207
208
209
...
226
227
228
 
 
 
 
 
 
 
 
229
230
231
...
255
256
257
258
 
259
260
261
...
297
298
299
300
 
301
302
303
...
332
333
334
335
 
336
337
338
...
8
9
10
 
11
12
 
 
 
13
14
15
16
17
18
19
...
49
50
51
 
 
52
53
54
55
56
57
58
59
60
61
62
63
64
...
100
101
102
 
103
104
105
106
107
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
...
292
293
294
 
295
296
297
298
...
334
335
336
 
337
338
339
340
...
369
370
371
 
372
373
374
375
0
@@ -8,11 +8,11 @@
0
     :== => 2
0
   }
0
 
0
- attr_accessor :argc, :nlocals, :stacksize, :flags, :consts, :bytecode,
0
+ attr_accessor :argc, :, :stacksize, :flags, :consts, :bytecode,
0
     :filename, :lineno, :name, :symbols, :stacknow, :varsyms, :jumps, :labels, :lines
0
- def initialize(fname, type = nil, name = "<module>", lineno = 0)
0
- @argc, @nlocals, @stacksize, @flags, @filename, @lineno, @name, @stack, @nopop, @type =
0
- 0, 0, 1, CO_NOFREE, fname, lineno, name, [], 0, type
0
+ def initialize(fname, type = nil, name = "<module>", lineno = 0, argc = 0)
0
+ @argc, @stacksize, @flags, @filename, @lineno, @name, @stack, @nopop, @type =
0
+ argc, 1, CO_NOFREE, fname, lineno, name, [], 0, type
0
     @flags |= CO_NEWLOCALS if [:class, :method].include?(type)
0
     @consts = [-1, nil]
0
     @symbols = [:Kernel]
0
0
@@ -49,11 +49,16 @@
0
   end
0
 
0
   def pop_top; bc 0x01; dump_stack end
0
- def binary_add
0
- add = bc 0x17
0
+ def infix i
0
+ add = bc i
0
     @stack.pop
0
     add
0
   end
0
+ def binary_add; infix 0x17 end
0
+ def binary_subscr; infix 0x19 end
0
+ def inplace_add; infix 0x37 end
0
+ def print_item; dump_stack; bc 0x47 end
0
+ def print_newline; dump_stack; bc 0x48 end
0
   def load_locals; bc 0x52 end
0
   def ret_val; bc 0x53 end
0
   def build_class; bc 0x59 end
0
@@ -95,7 +100,7 @@
0
     mark_jump n, bc(0x6f, n, 0x0)
0
   end
0
   def load_fast(n)
0
- stack_push Object.new, bc(0x7c, n, 0x0)
0
+ stack_push n, bc(0x7c, n, 0x0)
0
   end
0
   def store_fast(n)
0
     dump_stack
0
0
@@ -133,9 +138,16 @@
0
   def setlocal id
0
     store_fast id - 2
0
   end
0
+ def getdynamic id, lvl
0
+ load_name @varsyms[id - 1]
0
+ end
0
   def getconstant sym
0
     load_name(sym)
0
   end
0
+ def print_obj
0
+ print_item
0
+ print_newline
0
+ end
0
   def import(mod, inner = nil)
0
     load_const(-1)
0
 
0
0
@@ -173,9 +185,22 @@
0
     end
0
     ret_val
0
   end
0
+ def duparray ary
0
+ ary.each do |x|
0
+ load_const x
0
+ end
0
+ build_list ary.length
0
+ end
0
   def newarray size
0
     build_list size
0
   end
0
+ def opt_aref
0
+ binary_subscr
0
+ end
0
+ def opt_ltlt
0
+ build_list 1
0
+ inplace_add
0
+ end
0
   def opt_plus
0
     binary_add
0
   end
0
0
@@ -198,12 +223,16 @@
0
     args = @stack[-op_argc, op_argc].map { |o,_| o }
0
     idx = @bytecode.index { |x| x.object_id == recbytes.object_id }
0
     bytes = []
0
+
0
     if idx
0
       bytes = @bytecode.slice! idx..-1
0
 
0
       unless receiver
0
         unpop
0
         case meth
0
+ when :print
0
+ @bytecode += bytes
0
+ return print_obj
0
         when :import
0
           return import(*args)
0
         when :from
0
@@ -226,6 +255,14 @@
0
       load_attr(meth)
0
     end
0
     @bytecode += bytes
0
+
0
+ if blockiseq
0
+ blk = Pyasm.new(@filename, :block, "<block>", @lines.last[0])
0
+ blk.load_iseq blockiseq
0
+ load_const(blk)
0
+ op_argc += 1
0
+ end
0
+
0
     call_func(op_argc)
0
   end
0
   def unpop
0
@@ -255,7 +292,7 @@
0
     bytes = @bytecode.slice! idx..-1
0
     bytes.shift unless receiver
0
 
0
- asm = Pyasm.new(@filename, type, id.to_s, @lines.last[0]])
0
+ asm = Pyasm.new(@filename, type, id.to_s, @lines.last[0], iseq[5][:arg_size])
0
     if type == :class
0
       asm.load_name(:__name__)
0
       asm.store_name(:__module__)
0
@@ -297,7 +334,7 @@
0
     iseq = iseq.to_a
0
     @varsyms += iseq[8].reverse
0
 
0
- iseq.last.each do |inst|
0
+ iseq[11].each do |inst|
0
       case inst
0
       when Integer # line no
0
         line inst
0
@@ -332,7 +369,7 @@
0
     end
0
 
0
     f = "c"
0
- f << [@argc, @nlocals, @stacksize, @flags].pack("LLLL")
0
+ f << [@argc, @varsyms.length, @stacksize, @flags].pack("LLLL")
0
 
0
     # bytecode
0
     bytes = @bytecode.flatten
...
 
 
 
 
 
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
8
9
10
11
12
0
@@ -1,3 +1,12 @@
0
+class Proc:
0
+ def __init__(self, code):
0
+ self.code = code
0
+ def call(self, *args):
0
+ exec self.code in dict(zip(self.code.co_varnames, args))
0
+
0
+def proc(func):
0
+ return Proc(func)
0
+
0
 def puts(*args):
0
   for x in args: print x
0
   if not args: print
...
 
 
 
 
 
 
...
1
2
3
4
5
6
0
@@ -1 +1,7 @@
0
+# Content-Type: text/plain
0
+#
0
+# Hello, world!
0
+puts "Content-Type: text/plain"
0
+puts
0
+puts "Hello, world!"
...
 
 
 
...
1
2
3
0
@@ -1 +1,4 @@
0
+# [1, 2, 'c', 'd', [3, 4]]
0
+a = [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
0
+print a
...
 
 
 
 
 
...
1
2
3
4
5
0
@@ -1 +1,6 @@
0
+# 4
0
+# 5
0
+a = [1, 2, 3, 4, 5, 6]
0
+print a[3]
0
+print a[-2]
...
 
 
 
...
1
2
3
0
@@ -1 +1,4 @@
0
+# 3
0
+a = proc { |x| print(x + 1) }
0
+a.call(2)
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0
@@ -1 +1,20 @@
0
+#!/usr/bin/env ruby
0
+$: << "./lib"
0
+require 'unholy'
0
+
0
+ENV['PYTHONPATH'] = 'python'
0
+
0
+`rm -rf tests/*.pyc`
0
+Dir["tests/*.rb"].each do |rb|
0
+ unholy(rb, rb + ".pyc")
0
+ expect = File.read(rb).scan(/^# (.+\n)|^#(\n)/).join
0
+ actual = `python #{rb}.pyc`
0
+ puts "#{rb}: #{expect == actual ? "passed" : "FAILED"}"
0
+ unless expect == actual
0
+ puts " expected:"
0
+ puts expect.gsub(/^/, ' ')
0
+ puts " actual:"
0
+ puts actual.gsub(/^/, ' ')
0
+ end
0
+end

Comments

    No one has commented yet.