@@ -10,6 +10,7 @@ class RubyishClassHOW {
10
10
has $ ! isa ;
11
11
has % ! methods ;
12
12
13
+ # | define a new class
13
14
method new_type (: $ name ! , : $ isa ? ) {
14
15
nqp ::die(" duplicate class definition: $ name" )
15
16
if % CLASSES { $ name };
@@ -20,18 +21,20 @@ class RubyishClassHOW {
20
21
nqp ::newtype($ obj , ' HashAttrStore' );
21
22
}
22
23
24
+ # | add a named method to a class
23
25
method add_method ($ obj , $ name , $ code ) {
24
26
nqp ::die(" This class already has a method named " ~ $ name )
25
27
if nqp ::existskey(% ! methods , $ name );
26
28
27
29
% ! methods {$ name } := $ code ;
28
30
}
29
31
32
+ # | find a named method in a class or its parents
33
+ # | a '^' prefix, skips the current class, starting at the parent
30
34
method find_method ($ obj , $ name ) {
31
35
my $ method ;
32
36
33
37
if nqp :: substr ($ name , 0 , 1 ) eq ' ^' {
34
- # '^' prefix indicates a superclass lookup
35
38
$ name := nqp :: substr ($ name , 1 );
36
39
}
37
40
else {
@@ -53,10 +56,10 @@ grammar Rubyish::Grammar is HLL::Grammar {
53
56
54
57
token TOP {
55
58
:my $ * CUR_BLOCK := QAST::Block . new(QAST::Stmts . new());
56
- :my $ * TOP_BLOCK := $ * CUR_BLOCK ;
57
- :my $ * CLASS_BLOCK := $ * CUR_BLOCK ;
58
- :my $ * IN_TEMPLATE := 0;
59
- :my $ * IN_PARENS := 0;
59
+ :my $ * TOP_BLOCK := $ * CUR_BLOCK ; # global top-level block
60
+ :my $ * CLASS_BLOCK := $ * CUR_BLOCK ; # out class block
61
+ :my $ * IN_TEMPLATE := 0; # true, if in a template
62
+ :my $ * IN_PARENS := 0; # true, if in a parentheised list (signature etc)
60
63
:my % * SYM ; # symbols in current scope
61
64
:my % * SYM-GBL ; # globals and package variables
62
65
:my % * SYM-CLASS ; # class-inherited methods
@@ -68,10 +71,12 @@ grammar Rubyish::Grammar is HLL::Grammar {
68
71
rule separator { ';' | \n <! after continuation> }
69
72
token continuation { \\ \n }
70
73
74
+ # | a list of statements and/or template expressions
71
75
rule stmtlist {
72
76
[ <stmt = .stmtish >? ] *%% [<.separator >| <stmt = .template - chunk >]
73
77
}
74
78
79
+ # | a single statement, plus optional modifier
75
80
token stmtish {:s <hs >
76
81
<stmt > [ <modifier > <EXPR >]?
77
82
}
@@ -80,6 +85,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
80
85
81
86
proto token stmt {* }
82
87
88
+ # | function, or method definition
83
89
token stmt :sym <def > {:s
84
90
:my % * inner-sym := nqp::clone (% * SYM );
85
91
:my $ * DEF ;
@@ -95,10 +101,12 @@ grammar Rubyish::Grammar is HLL::Grammar {
95
101
<operation > {
96
102
$ * DEF := ~ $ < operation > ;
97
103
if $ * IN_CLASS {
104
+ # if we're in a class, we're defining a method ...
98
105
% * SYM {$ * DEF } := ' method' ;
99
106
% * SYM <self > := ' var' ;
100
107
}
101
108
else {
109
+ # ... otherwise it's a function
102
110
% * SYM {$ * DEF } := ' func' ;
103
111
}
104
112
}
@@ -108,6 +116,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
108
116
109
117
rule comma { [',' | '=>' ] }
110
118
119
+ # | a signature; for a method, function or closure
111
120
rule signature {
112
121
:my $ * IN_PARENS := 1;
113
122
[ <param > | '*' <slurpy = .param > | '&' <func = .param > ] +% ','
@@ -119,6 +128,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
119
128
}
120
129
}
121
130
131
+ # | a class definition
122
132
token stmt :sym <class > {
123
133
:my $ * IN_CLASS := 1;
124
134
:my @ * METHODS ;
@@ -148,7 +158,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
148
158
<closure >
149
159
}
150
160
151
- our % builtins ;
161
+ our % builtins ; # | functions that map directly to nqp ops
152
162
BEGIN {
153
163
% builtins := nqp ::hash(
154
164
' abort' , ' die' ,
@@ -162,13 +172,15 @@ grammar Rubyish::Grammar is HLL::Grammar {
162
172
);
163
173
}
164
174
175
+ # | a call to a function or method
165
176
token term :sym <call > {
166
177
<!keyword >
167
178
<operation > ['(' ~ ')' <call - args = .paren - args >? <code - block >?
168
179
| :s <hs > <?{ callable(~ $ < operation > )}> <call - args >?
169
180
]
170
181
}
171
182
183
+ # | a call to the super-method (aka callsame)
172
184
token term :sym <super > {
173
185
'super' ['(' ~ ')' <call - args = .paren - args >? <code - block >?
174
186
| :s <call - args >?
@@ -179,10 +191,12 @@ grammar Rubyish::Grammar is HLL::Grammar {
179
191
]
180
192
}
181
193
194
+ # | call to an nqp operation
182
195
token term :sym <nqp-op > {
183
196
'nqp::' <ident > ['(' ~ ')' <call - args = .paren - args >? | <call - args >? ]
184
197
}
185
198
199
+ # | quoted words, e.g.: %w<a b c>
186
200
token term :sym <quote-words > {
187
201
\% w <? before [. ]> <quote_EXPR : ':q' , ':w' >
188
202
}
@@ -206,6 +220,8 @@ grammar Rubyish::Grammar is HLL::Grammar {
206
220
['new' \h + <ident > | <ident > '.' 'new' ] ['(' ~ ')' <call - args = .paren - args >? ]?
207
221
}
208
222
223
+ # process a variable name, e.g.: localvar $global @attr Pkg::Var
224
+ # the first reference to a local or global variable must be an assignment
209
225
token var {
210
226
:my $ * MAYBE_DECL := 0;
211
227
\+?
@@ -226,26 +242,34 @@ grammar Rubyish::Grammar is HLL::Grammar {
226
242
proto token value {* }
227
243
token value :sym <string > {<strings >}
228
244
token strings {:s <hs > <string > <strings >? }
229
- token string { <?[ ' ] > <quote_EXPR : ':q' >
230
- | <?[ " ] > <quote_EXPR : ':qq' >
231
- | \% [ q <? before [. ]> <quote_EXPR : ':q' >
232
- | Q <? before [. ]> <quote_EXPR : ':qq' >
245
+ token string { <?[ ' ] > <quote_EXPR : ':q' > # 'non-interpolating'
246
+ | <?[ " ] > <quote_EXPR : ':qq' > # "interpolating#{42}"
247
+ | \% [ q <? before [. ]> <quote_EXPR : ':q' > # %q<non-interpolating>
248
+ | Q <? before [. ]> <quote_EXPR : ':qq' > # %Q<interpolating#{42}>
233
249
]
234
250
}
235
251
236
252
token value :sym <heredoc > {'<<' <heredoc >}
237
253
238
254
proto token heredoc {* }
255
+ # | non-interpolating heredoc
239
256
token heredoc :sym <literal > {[$ < marker > =<.ident > | \' $ < marker > =<- [ \' \n ] >+? \' ]\n
240
257
$ < text > =.*?
241
258
\n $ < marker > $$
242
259
}
243
260
244
- token heredoc-line { \n ? [< ! before [ '#{' ]> \N ] + | \n }
261
+ # | interpolating heredoc
245
262
token heredoc :sym <interp > {\" $ < marker > =<- [ \" \n ] >+? \"\n
246
263
[<text = .interp > | <text = .heredoc - line > ]*?
247
264
\n $ < marker > $$
248
265
}
266
+ token heredoc-line {\n ? [<! before ['#{' ]> \N ]+ | \n }
267
+
268
+ # | Interpolation
269
+ token interp { '#{' ~ '}' [ [:s <hs > <stmtlist > ]
270
+ || <panic (' string interpolation error' )> ]
271
+ }
272
+ token quote_escape :sym <#{ } > { <?quotemod_check (' s' )> <interp > }
249
273
250
274
token paren-list {
251
275
:my $ * IN_PARENS := 1;
@@ -260,12 +284,6 @@ grammar Rubyish::Grammar is HLL::Grammar {
260
284
token value :sym <true > { <sym > }
261
285
token value :sym <false > { <sym > }
262
286
263
- # Interpolation
264
- token interp { '#{' ~ '}' [ [:s <hs > <stmtlist > ]
265
- || <panic (' string interpolation error' )> ]
266
- }
267
- token quote_escape :sym <#{ } > { <?quotemod_check (' s' )> <interp > }
268
-
269
287
# Reserved words.
270
288
token keyword {
271
289
[ BEGIN | class | ensure | nil | new | when
0 commit comments