Skip to content

Commit a7c5369

Browse files
committed
implemented rubyish lambda, etc - nqp::makeclosure++
1 parent 45b52fd commit a7c5369

File tree

7 files changed

+84
-26
lines changed

7 files changed

+84
-26
lines changed

examples/rubyish/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ Features:
2727
- basic arrays and hashes
2828
- for loops on arrays: `for val in [10,20,30] do puts val end`
2929
- for loops on hash keys: `h = {'a'=>10, 'b'=>20}; for k in h do puts h{k} end`
30+
- lambda blocks: `def make_counter(n,incr) ; n-=incr; lambda { n += incr }; end`
31+
end
32+
3033
- lightweight eRuby like templating, see [template.rbi](rubyish-examples/template.rbi)
3134

3235
Notes:
@@ -53,7 +56,7 @@ curly brackets `puts fruit{'bannanas'}`
5356

5457
- nqp op-codes can be called like regular functions. E.g.
5558
```
56-
puts nqp:if(2+2 == 4, 'yup', 'nope' )
59+
puts nqp::if(2+2 == 4, 'yup', 'nope' )
5760
```
5861
- this includes nqp control-flow functions:
5962
```

examples/rubyish/rubyish-examples/pi.rbi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# naive approximation: pi = 4 * (1 - /1/3 + 1/5 ...)
22

33
limit = 2500000
4-
def time ; nqp:time_i() ; end
4+
def time ; nqp::time_i() ; end
55

66
n = 1;
77
pi_over_4 = 0.0

examples/rubyish/rubyish-examples/template.rbi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Any arbritrary code can appear before the template. Output to stdout
88
# is appended to the template, both before and within the template body
99

10-
puts "<?xml version='1.0' encoding='utf-8'?>"
10+
puts %q{<?xml version='1.0' encoding='utf-8'?>}
1111

1212
<?rbi?>
1313
<html>

examples/rubyish/rubyish.nqp

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
4141
token template-chunk { [<tmpl-unesc>|<tmpl-hdr>] ~ [<tmpl-esc>|$] <template-nibble>* }
4242
proto token template-nibble {*}
4343
token template-nibble:sym<interp> { <interp> }
44+
token template-nibble:sym<stray-tag> { [<.tmpl-unesc>|<.tmpl-hdr>] <.panic("Stray tag, e.g. '%>' or '<?rbi?>'")> }
4445
token template-nibble:sym<plain-text> { [<!before [<tmpl-esc>|'#{'|$]> .]+ }
4546

4647
token tmpl-hdr {'<?rbi?>' \h* \n? <?{$*IN_TEMPLATE := 1}>}
@@ -73,14 +74,14 @@ grammar Rubyish::Grammar is HLL::Grammar {
7374

7475
rule defbody {
7576
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
76-
<operation> <signature>? <separator>?
77+
<operation> ['(' ~ ')' <signature>]? <separator>?
7778
<stmtlist>
7879
}
7980

8081
token comma { :s [','|'=>'] :s }
8182

8283
rule signature {
83-
'(' ~ ')' [:my $*LINE_SPAN := 1; <param>* %% <comma>]
84+
:my $*LINE_SPAN := 1; <param>* %% <comma>
8485
}
8586

8687
token param { <ident> }
@@ -128,6 +129,10 @@ grammar Rubyish::Grammar is HLL::Grammar {
128129
['new' \h+ :s <ident> | <ident> '.' 'new'] ['(' ~ ')' <call-args=.paren-args>?]?
129130
}
130131

132+
token term:sym<lambda-call> {
133+
<ident> '.' 'call' ['(' ~ ')' <call-args=.paren-args>?]?
134+
}
135+
131136
token var {
132137
:my $*MAYBE_DECL := 0;
133138
[$<sigil>=[\$|\@\@?]|<!keyword>]
@@ -183,7 +188,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
183188
proto token comment {*}
184189
token comment:sym<line> { '#' [<?{!$*IN_TEMPLATE}> \N* || [<!before <tmpl-unesc>>\N]*] }
185190
token comment:sym<podish> {[^^'=begin'\n] ~ [^^'=end'\n ] .*?}
186-
token ws { <!ww>[\h | <.comment> | <.continuation> | <?{$*LINE_SPAN}> \n]* }
191+
token ws { <!ww> [\h | <.comment> | <.continuation> | <?{$*LINE_SPAN}> \n]* }
187192

188193
# Operator precedence levels
189194
INIT {
@@ -288,7 +293,10 @@ grammar Rubyish::Grammar is HLL::Grammar {
288293

289294
token term:sym<code> {
290295
'begin' ~ 'end' <stmtlist>
291-
| '{' ~ '}' <stmtlist>
296+
}
297+
298+
token term:sym<lambda> {
299+
'lambda' :s ['{' ['|' ~ '|' <signature>]?] ~ '}' <stmtlist>
292300
}
293301

294302
method builtin-init() {
@@ -442,6 +450,17 @@ class Rubyish::Actions is HLL::Actions {
442450
);
443451
}
444452

453+
method term:sym<lambda-call>($/) {
454+
my $call := QAST::Op.new( :op<call>,
455+
:name(~$<ident>),
456+
);
457+
if $<call-args> {
458+
$call.push($_)
459+
for $<call-args>.ast;
460+
}
461+
make $call;
462+
}
463+
445464
method var($/) {
446465
my $sigil := ~$<sigil>//'';
447466
my $name := $sigil ~ $<ident>;
@@ -507,6 +526,12 @@ class Rubyish::Actions is HLL::Actions {
507526

508527
method defbody($/) {
509528
$*CUR_BLOCK.name(~$<operation>);
529+
if $<signature> {
530+
for $<signature>.ast {
531+
$*CUR_BLOCK[0].push($_);
532+
$*CUR_BLOCK.symbol($_.name, :declared(1));
533+
}
534+
}
510535
$*CUR_BLOCK.push($<stmtlist>.ast);
511536
if $*IN_CLASS {
512537
# it's a method, self will be automatically passed
@@ -520,12 +545,13 @@ class Rubyish::Actions is HLL::Actions {
520545
}
521546

522547
method signature($/) {
548+
my @params;
523549
for $<param> {
524-
$*CUR_BLOCK[0].push(QAST::Var.new(
550+
@params.push(QAST::Var.new(
525551
:name(~$_), :scope('lexical'), :decl('param')
526552
));
527-
$*CUR_BLOCK.symbol(~$_, :declared(1));
528553
}
554+
make @params;
529555
}
530556

531557
method stmt:sym<class>($/) {
@@ -566,7 +592,6 @@ class Rubyish::Actions is HLL::Actions {
566592
method stmt:sym<EXPR>($/) { make $<EXPR>.ast; }
567593

568594
method term:sym<assign>($/) {
569-
my $sym := ~$<OPER>;
570595
my $op := $<OPER><O><op>;
571596
make QAST::Op.new( :op('bind'),
572597
$<var>.ast,
@@ -621,6 +646,7 @@ class Rubyish::Actions is HLL::Actions {
621646
$hash.push($_) for $<paren-list>.ast;
622647
make $hash;
623648
}
649+
624650
method value:sym<nil>($/) {
625651
make QAST::Op.new( :op<null> );
626652
}
@@ -630,7 +656,7 @@ class Rubyish::Actions is HLL::Actions {
630656
}
631657

632658
method value:sym<false>($/) {
633-
make QAST::IVal.new(0);
659+
make QAST::IVal.new( :value<0> );
634660
}
635661

636662
method interp($/) { make $<stmt>.ast }
@@ -699,6 +725,21 @@ class Rubyish::Actions is HLL::Actions {
699725
make $<stmtlist>.ast;
700726
}
701727

728+
method term:sym<lambda>($/) {
729+
my $block := QAST::Block.new();
730+
if $<signature> {
731+
for $<signature>.ast {
732+
$block.push($_);
733+
$block.symbol($_.name, :declared(1));
734+
}
735+
}
736+
$block.push($<stmtlist>.ast);
737+
738+
make QAST::Op.new(:op<takeclosure>,
739+
$block,
740+
);
741+
}
742+
702743
}
703744

704745
class Rubyish::Compiler is HLL::Compiler {

examples/rubyish/t/00hello-worldish.t

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
puts "1..4"
22

33
def capitalize(s)
4-
nqp:uc(nqp:substr(s, 0, 1)) ~ nqp:lc(nqp:substr(s, 1));
4+
nqp::uc(nqp::substr(s, 0, 1)) ~ nqp::lc(nqp::substr(s, 1));
55
end
66

77
class HelloWorld
@@ -15,7 +15,7 @@ class HelloWorld
1515
end
1616

1717
hello = HelloWorld.new("worldish")
18-
puts "#{nqp:can(hello, 'sayHi')? 'ok' : 'nok'} 2 - can say Hi"
19-
puts "#{nqp:can(hello, 'sayBye')? 'nok' : 'ok'} 3 - can't say Bye"
18+
puts "#{nqp::can(hello, 'sayHi')? 'ok' : 'nok'} 2 - can say Hi"
19+
puts "#{nqp::can(hello, 'sayBye')? 'nok' : 'ok'} 3 - can't say Bye"
2020
hello.sayHi
2121

examples/rubyish/t/lamba.t

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
puts "1..5"
2+
def make_iterator(n)
3+
lambda { |incr,desc| n += incr; puts "ok #{n} - #{desc}"}
4+
end
5+
6+
it1 = make_iterator(-1)
7+
it2 = make_iterator(3)
8+
9+
it1.call(2,"iterator 1")
10+
it1.call(1,"iterator 1")
11+
it2.call(0,"iterator 2")
12+
it2.call(1,"iterator 2")
13+
it1.call(3,"iterator 1")
14+

examples/rubyish/t/nqp-ops.t

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
puts "1..11"
2-
nqp:say("ok 1 - nqp:say")
3-
nqp:print("ok 2 - nqp:print with new-line\n")
4-
puts nqp:concat("ok ", '3 - nqp:concat')
5-
puts nqp:substr("nok 4 - nqp:substr", 1)
6-
puts nqp:lc("OK 5 - nqp:lC")
7-
nqp:print nqp:chr(nqp:ord('o')); puts 'k 6 - nqp:ord and nqp:chr'
2+
nqp::say("ok 1 - nqp::say")
3+
nqp::print("ok 2 - nqp::print with new-line\n")
4+
puts nqp::concat("ok ", '3 - nqp::concat')
5+
puts nqp::substr("nok 4 - nqp::substr", 1)
6+
puts nqp::lc("OK 5 - nqp::lC")
7+
nqp::print nqp::chr(nqp::ord('o')); puts 'k 6 - nqp::ord and nqp::chr'
88

99
def ok(i,msg)
10-
nqp:say("ok #{i} - #{msg}");
10+
nqp::say("ok #{i} - #{msg}");
1111
end
1212
def nok(i,msg)
13-
nqp:say("nok #{i} - #{msg}");
13+
nqp::say("nok #{i} - #{msg}");
1414
end
1515

16-
nqp:if(2+2 == 4, ok(7, "nqp:if (true)"), nok(7, "nqp:if (true)"))
17-
nqp:if(2+2 == 5, nok(8, "nqp:if (true)"), ok(8, "nqp:if (false)"))
16+
nqp::if(2+2 == 4, ok(7, "nqp::if (true)"), nok(7, "nqp::if (true)"))
17+
nqp::if(2+2 == 5, nok(8, "nqp::if (true)"), ok(8, "nqp::if (false)"))
1818

1919
n = 9
2020

21-
nqp:while n <= 11, begin
22-
ok(n, "nqp:while (#{n})")
21+
nqp::while n <= 11, begin
22+
ok(n, "nqp::while (#{n})")
2323
n += 1
2424
end

0 commit comments

Comments
 (0)