@@ -11,11 +11,11 @@ class RubyishClassHOW {
11
11
has % ! methods ;
12
12
13
13
method new_type (: $ name ! , : $ isa ? ) {
14
- nqp ::die(" duplicate class definition: $ name" )
15
- if % CLASSES { $ name };
14
+ nqp ::die(" duplicate class definition: $ name" )
15
+ if % CLASSES { $ name };
16
16
17
- my $ obj := self . new (: $ name , : $ isa );
18
- % CLASSES { $ name } := [$ obj ];
17
+ my $ obj := self . new (: $ name , : $ isa );
18
+ % CLASSES { $ name } := [$ obj ];
19
19
20
20
nqp ::newtype($ obj , ' HashAttrStore' );
21
21
}
@@ -29,24 +29,24 @@ class RubyishClassHOW {
29
29
30
30
method find_method ($ obj , $ name ) {
31
31
32
- my $ method ;
32
+ my $ method ;
33
33
34
- if nqp :: substr ($ name , 0 , 1 ) eq ' ^' {
35
- # '^' prefix indicates a superclass lookup
36
- $ name := nqp :: substr ($ name , 1 );
37
- }
38
- else {
39
- $ method := % ! methods {$ name };
40
- }
34
+ if nqp :: substr ($ name , 0 , 1 ) eq ' ^' {
35
+ # '^' prefix indicates a superclass lookup
36
+ $ name := nqp :: substr ($ name , 1 );
37
+ }
38
+ else {
39
+ $ method := % ! methods {$ name };
40
+ }
41
41
42
- if ! $ method && $ ! isa {
43
- my $ super := % CLASSES { $ ! isa };
44
- nqp ::die(" unresolved super-class: " ~ $ ! isa )
45
- unless $ super ;
46
- $ method := $ super [0 ]. find_method( $ obj , $ name );
47
- }
42
+ if ! $ method && $ ! isa {
43
+ my $ super := % CLASSES { $ ! isa };
44
+ nqp ::die(" unresolved super-class: " ~ $ ! isa )
45
+ unless $ super ;
46
+ $ method := $ super [0 ]. find_method( $ obj , $ name );
47
+ }
48
48
49
- $ method // nqp ::null();
49
+ $ method // nqp ::null();
50
50
}
51
51
}
52
52
@@ -58,7 +58,9 @@ grammar Rubyish::Grammar is HLL::Grammar {
58
58
:my $ * CLASS_BLOCK := $ * CUR_BLOCK ;
59
59
:my $ * IN_TEMPLATE := 0;
60
60
:my $ * IN_PARENS := 0;
61
- :my % * SYM := self. sym-init();
61
+ :my % * SYM ;
62
+ :my % * CLASS_SYMS ;
63
+
62
64
^ ~ $ <stmtlist >
63
65
|| <.panic (' Syntax error' )>
64
66
}
@@ -92,17 +94,22 @@ grammar Rubyish::Grammar is HLL::Grammar {
92
94
proto token stmt {* }
93
95
94
96
token stmt :sym <def > {:s
95
- :my % sym-save := self. hcopy(% * SYM );
96
97
97
- 'def' ~ 'end' <defbody >
98
+ :my % sym-save := nqp::clone (% * SYM );
99
+ :my $ * DEF ;
98
100
99
- { % * SYM := self . hcopy(% sym-save )}
101
+ 'def' ~ 'end' <defbody > {
102
+ % sym-save {$ * DEF } := % * SYM {$ * DEF };
103
+ % * SYM := % sym-save ;
104
+ }
100
105
}
101
106
102
107
rule defbody {
103
108
:my $ * CUR_BLOCK := QAST::Block . new(QAST::Stmts . new());
104
- :my $ * DEF ;
105
- <operation > { $ * DEF := ~ $ < operation > }
109
+ <operation > {
110
+ $ * DEF := ~ $ < operation > ;
111
+ % * SYM {$ * DEF } := $ * IN_CLASS ?? ' method' !! ' func' ;
112
+ }
106
113
['(' ~ ')' <signature >? ]? <separator >?
107
114
<stmtlist >
108
115
}
@@ -116,26 +123,38 @@ grammar Rubyish::Grammar is HLL::Grammar {
116
123
| '&' <func = .param >
117
124
}
118
125
119
- token param { <ident > [:s <hs > '=' <EXPR >]? }
126
+ token param { <ident > [:s <hs > '=' <EXPR >]? {
127
+ % * SYM {~ $ < ident > } := ' var'
128
+ }
129
+ }
120
130
121
131
token stmt :sym <class > {
122
132
:my $ * IN_CLASS := 1;
123
133
:my @ * METHODS ;
124
- :my % sym-save := self . hcopy (% * SYM );
134
+ :my % sym-save := nqp: :clone (% * SYM );
125
135
126
- [<sym > \h + ] ~ [\h * 'end' ] <classbody >
127
-
128
- { % * SYM := self . hcopy( % sym-save ) }
136
+ [<sym > \h + ] ~ [\h * 'end' ] <classbody > {
137
+ % * SYM := % sym-save
138
+ }
129
139
}
130
140
131
141
rule classbody {
132
142
:my $ * CUR_BLOCK := QAST::Block . new(QAST::Stmts . new());
133
143
:my $ * CLASS_BLOCK := $ * CUR_BLOCK ;
134
144
135
145
<ident > { $ * CLASS_BLOCK . name (~ $ < ident > ) }
136
- [ '<' <super = .ident > ]?
146
+ [ '<' <super = .ident > { inherit-syms( ~ $ < super > ) } ]?
137
147
<separator >
138
- <stmtlist >
148
+ <stmtlist > {
149
+ % * CLASS_SYMS {~ $ < ident > } := % * SYM ;
150
+ }
151
+ }
152
+
153
+ sub inherit-syms ($ class ) {
154
+ if my % syms := % * CLASS_SYMS {$ class } {
155
+ % * SYM {$ _ } := % syms {$ _ }
156
+ for % syms ;
157
+ }
139
158
}
140
159
141
160
token stmt :sym <EXPR > { <EXPR > }
@@ -146,15 +165,28 @@ grammar Rubyish::Grammar is HLL::Grammar {
146
165
<closure >
147
166
}
148
167
168
+ my % builtins ;
169
+
170
+ method callable ($ op ) {
171
+ % builtins := self . builtin-init()
172
+ unless % builtins <puts >;
173
+
174
+ my $ type := % * SYM {$ op } || (% builtins {$ op } && ' func' );
175
+
176
+ $ type && ($ type eq ' func' || $ type eq ' method' );
177
+ }
178
+
149
179
token term :sym <call > {
150
180
<!keyword >
151
181
<operation > ['(' ~ ')' <call - args = .paren - args >? <code - block >?
152
- | :s <hs > <call - args >? <?{ % * SYM {~ $ < operation > } eq ' def' }> ]
182
+ | :s <hs > <call - args >? <?{ self . callable(~ $ < operation > )}>
183
+ ]
153
184
}
154
185
155
186
token term :sym <super > {
156
187
'super' ['(' ~ ')' <call - args = .paren - args >? <code - block >?
157
- | :s <call - args >? ]
188
+ | :s <call - args >?
189
+ ]
158
190
}
159
191
160
192
token term :sym <nqp-op > {
@@ -166,7 +198,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
166
198
}
167
199
168
200
token call-args {:s <hs >
169
- [<arg = .hash - args >|| <arg = .EXPR >]+ % ',' [ ',' <arg = .func - ref > ]?
201
+ [ <arg = .hash - args >|| <arg = .EXPR >]+ % ',' [ ',' <arg = .func - ref > ]?
170
202
| <arg = .func - ref >
171
203
}
172
204
@@ -186,7 +218,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
186
218
:my $ * MAYBE_DECL := 0;
187
219
\+?
188
220
$ < sigil > =[ \$ | \@\@? | <!keyword > ]
189
- <ident >
221
+ <ident >< ! before [\! | \ ? | \h * \(]>
190
222
[ <? before \h * '=' [\w | \h + || <.EXPR >] { $ * MAYBE_DECL := 1 }> || <?> ]
191
223
}
192
224
@@ -212,9 +244,9 @@ grammar Rubyish::Grammar is HLL::Grammar {
212
244
\n $ < marker > $$
213
245
}
214
246
215
- token chars {\n ? [<! before ['#{' ]> \N ]+ | \n }
247
+ token heredoc-line {\n ? [<! before ['#{' ]> \N ]+ | \n }
216
248
token heredoc :sym <interp > {\" $ < marker > =<- [ \" \n ] >+? \"\n
217
- [<text = .interp > | <text = .chars > ]*?
249
+ [<text = .interp > | <text = .heredoc - line > ]*?
218
250
\n $ < marker > $$
219
251
}
220
252
@@ -246,6 +278,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
246
278
| begin | else | in | rescue | undef
247
279
| break | elsif | module | retry | unless
248
280
| case | end | next | return | until
281
+ | eq | ne | lt | gt | le | ge | cmp
249
282
] <!ww >
250
283
}
251
284
@@ -380,7 +413,10 @@ grammar Rubyish::Grammar is HLL::Grammar {
380
413
}
381
414
382
415
token stmt :sym <for > {:s
383
- <sym > <ident > 'in' <EXPR > <do - block >
416
+ <sym > <ident > 'in' <EXPR > {
417
+ % * SYM {~ $ < ident > } := ' var'
418
+ }
419
+ <do - block >
384
420
}
385
421
386
422
token do-block { <do > ~ 'end' <stmtlist > }
@@ -414,18 +450,6 @@ grammar Rubyish::Grammar is HLL::Grammar {
414
450
);
415
451
}
416
452
417
- method sym-init () {
418
- my % builtins := self . builtin-init();
419
- my % sym ;
420
- % sym {$ _ } := ' def' for % builtins ;
421
- return % sym ;
422
- }
423
-
424
- method hcopy (% in ) {
425
- my % out ;
426
- % out {$ _ } := % in {$ _ } for % in ;
427
- return % out ;
428
- }
429
453
}
430
454
431
455
class Rubyish::Actions is HLL::Actions {
@@ -482,9 +506,20 @@ class Rubyish::Actions is HLL::Actions {
482
506
unless % builtins <puts >;
483
507
my $ op := % builtins {$ name };
484
508
485
- my $ call := $ op
486
- ?? QAST ::Op. new ( : op($ op ) )
487
- !! QAST ::Op. new ( : op(' call' ), : name($ name ) );
509
+ my $ call ;
510
+
511
+ if $ op {
512
+ $ call := QAST ::Op. new ( : op($ op ) )
513
+ }
514
+ elsif % * SYM {$ name } eq ' method' {
515
+ $ call := QAST ::Op. new ( : op(' callmethod' ),
516
+ QAST ::Var. new ( : name(' self' ), : scope(' lexical' )),
517
+ QAST ::SVal. new ( : value($ name ) ),
518
+ );
519
+ }
520
+ else {
521
+ $ call := QAST ::Op. new ( : op(' call' ), : name($ name ) );
522
+ }
488
523
489
524
if $ < call-args > {
490
525
$ call . push ($ _ )
@@ -501,9 +536,9 @@ class Rubyish::Actions is HLL::Actions {
501
536
my $ name := ~ $ * DEF ;
502
537
503
538
my $ call := QAST ::Op. new ( : op(' callmethod' ),
504
- QAST ::Var. new ( : name(' self' ), : scope(' lexical' )),
505
- QAST ::SVal. new ( : value(' ^' ~ $ name ) ),
506
- );
539
+ QAST ::Var. new ( : name(' self' ), : scope(' lexical' )),
540
+ QAST ::SVal. new ( : value(' ^' ~ $ name ) ),
541
+ );
507
542
508
543
if $ < call-args > {
509
544
$ call . push ($ _ )
@@ -580,15 +615,15 @@ class Rubyish::Actions is HLL::Actions {
580
615
),
581
616
582
617
# call initialize method, if available
583
- ($ < call-args >
584
- ?? $ init-call
585
- !! QAST ::Op. new ( : op<if >,
586
- QAST ::Op. new ( : op<can >,
587
- QAST ::Var. new ( : name($ tmp-sym ), : scope<lexical > ),
588
- QAST ::SVal. new ( : value<initialize > )),
589
- $ init-call ,
590
- )
591
- ),
618
+ ($ < call-args >
619
+ ?? $ init-call
620
+ !! QAST ::Op. new ( : op<if >,
621
+ QAST ::Op. new ( : op<can >,
622
+ QAST ::Var. new ( : name($ tmp-sym ), : scope<lexical > ),
623
+ QAST ::SVal. new ( : value<initialize > )),
624
+ $ init-call ,
625
+ )
626
+ ),
592
627
593
628
# return the new object
594
629
QAST ::Var. new ( : name($ tmp-sym ), : scope<lexical > ),
@@ -653,7 +688,6 @@ class Rubyish::Actions is HLL::Actions {
653
688
QAST ::Var. new ( : name($ install . name ), : scope(' lexical' ), : decl(' var' ) ),
654
689
$ install
655
690
));
656
- % * SYM {$ install . name } := ' def' ;
657
691
if $ * IN_CLASS {
658
692
@ * METHODS . push ($ install );
659
693
}
@@ -678,6 +712,7 @@ class Rubyish::Actions is HLL::Actions {
678
712
my $ var := QAST ::Var. new (
679
713
: name(~ $ < ident > ), : scope(' lexical' ), : decl(' param' )
680
714
);
715
+ $ * CUR_BLOCK . symbol(' self' , : declared(1 ));
681
716
682
717
$ var . default( $ < EXPR > . ast )
683
718
if $ < EXPR > ;
@@ -722,9 +757,9 @@ class Rubyish::Actions is HLL::Actions {
722
757
QAST ::SVal. new ( : value(~ $ < classbody >< ident > ), : named(' name' ) ),
723
758
);
724
759
725
- $ new_type . push (
726
- QAST ::SVal. new ( : value(~ $ < classbody >< super > ), : named(' isa' ) )
727
- ) if ~ $ < classbody >< super > ;
760
+ $ new_type . push (
761
+ QAST ::SVal. new ( : value(~ $ < classbody >< super > ), : named(' isa' ) )
762
+ ) if $ < classbody >< super > ;
728
763
729
764
$ class_stmts . push (QAST ::Op. new (
730
765
: op(' bind' ),
@@ -736,15 +771,15 @@ class Rubyish::Actions is HLL::Actions {
736
771
my $ class_var := QAST ::Var. new ( : name($ ins_name ), : scope(' lexical' ) );
737
772
738
773
for @ * METHODS {
739
- my $ name := $ _ . name ;
774
+ my $ name := $ _ . name ;
740
775
741
776
$ class_stmts . push (QAST ::Op. new (
742
777
: op(' callmethod' ), : name(' add_method' ),
743
778
QAST ::Op. new ( : op(' how' ), $ class_var ),
744
779
$ class_var ,
745
780
QAST ::SVal. new ( : value($ name ) ),
746
781
QAST ::BVal. new ( : value($ _ ) ))
747
- );
782
+ );
748
783
}
749
784
750
785
make $ class_stmts ;
@@ -790,7 +825,7 @@ class Rubyish::Actions is HLL::Actions {
790
825
make QAST ::SVal. new ( : value( ~ $ < text > ) );
791
826
}
792
827
793
- method chars ($/ ) { make QAST ::SVal. new ( : value(~ $/ ) ) }
828
+ method heredoc-line ($/ ) { make QAST ::SVal. new ( : value(~ $/ ) ) }
794
829
795
830
method heredoc :sym <interp >($/ ) {
796
831
my $ list := QAST ::Op. new ( : op<list > );
0 commit comments