root/v6/v6-KindaPerl6/docs/ruby_backend.txt

Revision 19680, 5.9 kB (checked in by putter, 11 months ago)

[kp6] ruby backend: instance variables fleshed out. run_tests thru t/kp6/28 pass.

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1kp6 ruby backend
2
3MISSION
4
5As of January 2008, kp6 is the most-advanced actively-developed
6non-parrot perl6 implementation.  It is written in a subset of
7perl6, and runs on the more limited, but faster, mp6.
8
9kp6 is designed to be capable of running on itself.  But the
10performance of kp6 on kp6 is currently too slow to be usable.
11By a couple of orders of magnitude.
12
13This performance obstacle has severely hampered using bootstrapped
14kp6 as a development path towards the implementation of perl6.
15
16The objective of this kp6 ruby backend is to provide sufficient
17performance for bootstrapped kp6 to be usable, thus unblocking
18the development path.
19
20
21DEVELOPMENT TIPS
22
23 perl script/kp6 -Cruby -e 'say 3'  # show the emitted ruby code
24 perl script/kp6 -Bruby -e 'say 3'  # run the emitted ruby code
25
26 perl script/kp6 -Cast -e 'say 3'   # show the AST
27 perl script/kp6 -Cperl5 -e 'say 3' # show the emitted perl5
28
29 ./script/run_tests.pl --backend=ruby
30
31
32If you change Emit/Ruby.pm,
33  # get svn file timestamps correct
34  rm -rf v6-KindaPerl6/compiled
35  svn up
36  # make
37  perl Makefile.PL
38  make kp6_mp6
39
40make kp6_mp6 runs
41 perl script/mp6.pl \
42  -o compiled/perl5-kp6-mp6/lib/KindaPerl6/Visitor/Emit/Ruby.pm \
43  src/KindaPerl6/Visitor/Emit/Ruby.pm
44
45
46Files:
47 docs/ruby_backend.txt
48 src/KindaPerl6/Visitor/Emit/Ruby.pm
49 compiled/ruby-kp6-mp6/kp6_runtime.rb
50 compiled/ruby-kp6-mp6
51 src/KindaPerl6/Runtime/Ruby
52
53
54SCOPE OF OBJECTIVES
55
56Performance.  Obj: kp6 on kp6 should run with at least the speed of
57kp6 on mp6, and ideally of pugs.  Non-obj: performance on anything
58other than kp6, eg, numerics.
59
60Ability to run kp6 without significant mofication.
61
62Simplicity.  Obj: simplicity for reducing development cost and risk.
63Non-obj: simplicity for elegance, long-term maintainability, or
64anything else.
65
66Correctness.  Just enough correctness to make kp6 happy, and support
67it's near term further development.  While stronger correctness will
68likely exist, it's not a project objective.
69Non-obj: Unneeded p6 spec-wise correctness, either short or long term.
70
71Readable emitted ruby code.  Obj: easily readable for debugging.
72Non-obj: easily hand writiable.  No hairy ruby games.
73
74
75DESIGN
76
77Calling convention:
78 ->(cap){
79   ->(the,formal,arguments) {
80     ...inline argment processing...
81     ...body...
82   }.(nil,nil,nil)
83 }
84 cap is a Ruddy::Capture.
85
86Name encoding
87 base type - a prefix.  $x -> s_x, @%& -> a_ h_ c_
88 characters - follow kp6.
89 categories - follow kp6?
90   but kp6's including <> in the encoding of infix:<x> seems unfortunate.
91
92Variables
93 Lookup is done using normal ruby lookup on zero-ary accessors which
94 return p6 Containers.
95
96 $x
97 $x = v
98 $x := v
99 s_x
100 s_x._(v)
101 s_x = v       # for binding lexical variables
102 self.s_x = v  # for binding package variables
103
104 f(...)
105 c_f.(...)
106
107Lexical vars
108 ->(x1,x2){...}.(v1,v2)  === (let ((x1 v1) (x2 v2)) ...)
109 The absence of a real lambda in ruby 1.8 is what forces us to use 1.9.
110
111Package vars
112 Done with class vars.
113
114 our $.x
115 ===
116 our :s_x
117 ==>
118 def s_x; @@x ||= ...; end  where ... is the optional default, or undef.
119 def s_x=(v); @@x = v; end 
120
121OO
122 p6 classes are similarly named ruby classes.
123 p6 modules and packages are ruby modules.(?)
124 methods:
125
126   $o.m()
127   s_o.c_m.(...)
128
129   current_class.def_pkg_var(:c_m, ...)
130   where ... is
131     ->(c){
132       ->(s_self,...){
133         ...
134       } 
135     }
136
137
138
139Examples:
140 my sub f(x) { 42 * x }
141 ==>
142 ->(c_f){
143   c_f =
144     ->(cap){
145       ->(s_x){
146         cap.mumble(1)
147         s_x._(cap.frotz(0))
148         42 * s_x
149       }.(Scalar.new)
150     }
151   }.()
152 }.(nil)
153
154 sub g() { 42 }
155 ==>
156 our :c_g, ->(c){
157   ...
158   }
159
160
161
162DESIGN DISCUSSION
163
164A high-level alternate approach would be to more closely mimic the
165perl5 backend.  Just do a transliteration.  Speedup would come from
166running more or less directly on fast ruby oo, instead of the p5
167backend's running on an oo layer (Moose) sitting on top of slow p5 oo.
168This approach would in some ways be simpler.  And the performance gain
169may well be sufficient to achieve a usably fast bootstrapped kp6.  I
170didn't take this path because it required greater understanding of the
171perl5 backend, and the assorted libraries it uses.  Which seemed a
172higher cost and risk approach, for me, than reusing the architecture
173from redsix.  Someone else might pursue it, if the current approach
174bogs down, of if keeping the ruby and p5 backends synced becomes
175burdensome at some future time.
176
177Regards signature architecture.  The p6 signature language is, even
178more so than usual, a non-trivial language.  Options:
179(1) pass to the runtime, a p6 sig string '$x,$y', then parse in the
180runtime.  Even if the parse/emit was used to cannonicallize the form,
181there's still such richness as would be a pain to duplicate.
182(2) pass to the runtime, an ast instead.
183(2a) an ast composed of runtime objects, which are not p6 objects.
184(2b) an ast composed of p6 objects.  Facilitates p6 reflection.
185(3) at compile-time, generate inline code for parameter processing.
186Currently the backend is using (3), but there is unfinished code for (2a).
187
188Here's the unused (2a) convention:
189 sig = Ruddy::Signature.new(...)
190 ->(cap){
191   ->(the,formal,arguments) {
192     sig.bind(cap,binding)
193     ...body...
194   }.(nil,nil,nil)
195 }
196 cap may be an array (positional args only), a hash (named args only),
197 or a Ruddy::Capture.
198
199 my sub f(x) { 42 * x }
200 ==>
201 ->(c_f){
202   c_f = ->(){
203     sig = Ruddy::Signature.new(...)
204     ->(cap){
205       ->(s_x){
206         sig.bind(cap,binding)
207         42 * s_x
208       }.(nil)
209     }
210   }.()
211 }.(nil)
212
213
214
215
216Note to self: don't forget Method .receiver and .owner. :)
217
218
219TODO:
220- continue to work through failing tests
221- try compilation of kp6 p6 files
222
223- start creating mp6_runtime.rb.
224
225- flesh out todos
226
227OLD FUZZY TODO LIST:
228- walk though Emit/Ruby.pm, deciding, creating, and documenting runtime apis.
229- do Runtime/Ruby.  Should be much simpler and smaller than Runtime/Perl5/.
230
231LATER:
232- create script/kp6.pl? a p6 version of the p5 script/kp6.
233- rename ruby backend to ruddy (after acceptance).
Note: See TracBrowser for help on using the browser.