Skip to content

Commit d959560

Browse files
committed
fixed rubyish object attribute scoping. adding recursion tests
1 parent bdbb63a commit d959560

File tree

6 files changed

+102
-60
lines changed

6 files changed

+102
-60
lines changed

examples/rubyish/rubyish.nqp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: iso-8859-1 -*-
21
use NQPHLL;
32

43
# Ruby subset extended from the `rubyish` example, as introduced in the
@@ -45,7 +44,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
4544
token template-nibble:sym<stray-tag> { [<.tmpl-unesc>|<.tmpl-hdr>] <.panic("Stray tag, e.g. '%>' or '<?rbi?>'")> }
4645
token template-nibble:sym<literal> { [<!before [<tmpl-esc>|'#{'|$]> .]+ }
4746

48-
token tmpl-hdr {'<?rbi?>' \h* \n? <?{$*IN_TEMPLATE := 1}>}
47+
token tmpl-hdr {'<?rbi?>' \h* \n? {$*IN_TEMPLATE := 1} }
4948
token tmpl-esc {\h* '<%'
5049
[<?{$*IN_TEMPLATE}> || <.panic('Template directive precedes "<?rbi?>"')>]
5150
}
@@ -70,7 +69,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
7069

7170
'def' ~ 'end' <defbody>
7271

73-
<?{%*SYM := self.hcopy(%sym-save);1}>
72+
{%*SYM := self.hcopy(%sym-save)}
7473
}
7574

7675
rule defbody {
@@ -97,13 +96,15 @@ grammar Rubyish::Grammar is HLL::Grammar {
9796

9897
[<sym> \h+] ~ [\h* 'end'] <classbody>
9998

100-
<?{%*SYM := self.hcopy(%sym-save);1}>
99+
{%*SYM := self.hcopy(%sym-save);1}
101100
}
102101

103102
rule classbody {
104103
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
105104
:my $*CLASS_BLOCK := $*CUR_BLOCK;
106-
<ident> <separator>
105+
106+
<ident> { $*CLASS_BLOCK.name(~$<ident>) }
107+
<separator>
107108
<stmtlist>
108109
}
109110

@@ -112,7 +113,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
112113

113114
token code-block {:s<hs>
114115
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
115-
<closure>
116+
<closure>
116117
}
117118

118119
token term:sym<call> {
@@ -154,7 +155,7 @@ grammar Rubyish::Grammar is HLL::Grammar {
154155
[ <?before \h* '=' [\w | \h+ || <.EXPR>] { $*MAYBE_DECL := 1 }> || <?> ]
155156
}
156157

157-
token term:sym<var> { <var> }
158+
token term:sym<var> { <var> }
158159

159160
token term:sym<value> { \+? <value> }
160161

@@ -187,8 +188,8 @@ grammar Rubyish::Grammar is HLL::Grammar {
187188
<EXPR> *%% <comma>
188189
}
189190

190-
token value:sym<integer> { \+? \d+ }
191-
token value:sym<float> { \+? \d* '.' \d+ }
191+
token value:sym<integer> { \d+ }
192+
token value:sym<float> { \d* '.' \d+ }
192193
token value:sym<array> {'[' ~ ']' <paren-list> }
193194
token value:sym<hash> {'{' ~ '}' <paren-list> }
194195
token value:sym<nil> { <sym> }
@@ -364,8 +365,8 @@ grammar Rubyish::Grammar is HLL::Grammar {
364365
token term:sym<lambda> {:s
365366
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
366367
['lambda' <closure>
367-
| '->' <closure=.closure2>
368-
]
368+
| '->' <closure=.closure2>
369+
]
369370
}
370371

371372
method builtin-init() {
@@ -543,9 +544,10 @@ class Rubyish::Actions is HLL::Actions {
543544

544545
if $sigil eq '@' && $*IN_CLASS {
545546
# instance variable, bound to self
546-
make QAST::Var.new( :scope('attribute'),
547+
my $package-name := $*CLASS_BLOCK.name;
548+
make QAST::Var.new( :name($name), :scope('attribute'),
547549
QAST::Var.new( :name('self'), :scope('lexical')),
548-
QAST::SVal.new( :value($name) )
550+
QAST::SVal.new( :value($package-name) )
549551
);
550552
}
551553
else {
@@ -645,9 +647,9 @@ class Rubyish::Actions is HLL::Actions {
645647
}
646648

647649
for @params {
648-
$*CUR_BLOCK[0].push($_);
649-
$*CUR_BLOCK.symbol($_.name, :declared(1));
650-
}
650+
$*CUR_BLOCK[0].push($_);
651+
$*CUR_BLOCK.symbol($_.name, :declared(1));
652+
}
651653
}
652654

653655
method stmt:sym<class>($/) {
@@ -656,14 +658,18 @@ class Rubyish::Actions is HLL::Actions {
656658
# Generate code to create the class.
657659
my $class_stmts := QAST::Stmts.new( $body_block );
658660
my $ins_name := '::' ~ $<classbody><ident>;
659-
$class_stmts.push(QAST::Op.new(
660-
:op('bind'),
661-
QAST::Var.new( :name($ins_name), :scope('lexical'), :decl('var') ),
662-
QAST::Op.new(
661+
662+
my $new_type := QAST::Op.new(
663663
:op('callmethod'), :name('new_type'),
664664
QAST::WVal.new( :value(RubyishClassHOW) ),
665-
QAST::SVal.new( :value(~$<classbody><ident>), :named('name') ) )
666-
));
665+
QAST::SVal.new( :value(~$<classbody><ident>), :named('name') ),
666+
);
667+
668+
$class_stmts.push(QAST::Op.new(
669+
:op('bind'),
670+
QAST::Var.new( :name($ins_name), :scope('lexical'), :decl('var') ),
671+
$new_type,
672+
));
667673

668674
# Add methods.
669675
my $class_var := QAST::Var.new( :name($ins_name), :scope('lexical') );

examples/rubyish/t/functional.t

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
# implement and test functional primitives: map, grep and sort.
2-
puts '1..8'
2+
puts '1..9'
33

44
test_counter = 0
55

66
def is(result, expected, description)
77
test_num = (test_counter += 1)
88
passed = result eq expected
99
puts "#{passed ? 'ok' : 'nok'} #{test_num} - #{description}"
10-
puts "# expected:'#{expected}' got:'#{result}'" unless passed
10+
puts "# expected:'#{expected}' got:'#{result}'" \
11+
unless passed
1112
end
1213

1314
def dump(arr) ; nqp::join(',', arr); end
1415

1516
# ------------
16-
def grep(array_inp, &filter)
17+
def grep(array_inp, &selector)
1718
array_out = []
1819
n = -1
20+
selector = lambda {|elem| !elem.nil? && elem} \
21+
if selector.nil?
1922

2023
for elem in array_inp ;
21-
keep = (filter.nil?
22-
? (!elem.nil? && elem)
23-
: filter.call(elem))
24-
2524
array_out[ n+=1 ] = elem \
26-
if keep
25+
if selector.call(elem)
2726
end
2827

2928
array_out
@@ -108,7 +107,12 @@ is dump(num_sort), '0,1,2,4,5,10,13,18,27', 'sort [numeric]'
108107
# ------------
109108
# put it all together
110109
odd = lambda {|n| n % 2 == 1}
110+
111111
combined = map(sort grep(arr,&odd)) {|str| nqp::flip(str)}
112112
is dump(combined), '1,31,72,5', 'combined map sort grep'
113-
is dump(arr), '0,2,10,1,13,27,5,4,18', 'array unscathed'
113+
114+
splitter = lambda {|n| nqp::split('',n)}
115+
is dump( map(combined, &splitter) ), '1,3,1,7,2,5', 'map [flattening]'
116+
117+
is dump(arr), '0,2,10,1,13,27,5,4,18', 'array readonly'
114118

examples/rubyish/t/if-then-else.t

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,11 @@ puts "ok 10"; end
3434
if 2 >= 1 && 1 <= 2 && "b" gt "a" && "a" lt "b" && (2 != 1) ; puts "ok 11"
3535
else puts "nok 11"; end
3636

37-
def fact!(n)
38-
if n <= 1 then
39-
1
40-
else
41-
n * fact!(n - 1)
42-
end
37+
def one_liner(i)
38+
if i == 42 then 'nok' elsif i == 12 then 'ok' else 'nok' end
4339
end
4440

45-
result = fact!(6)
46-
expected = 6*5*4*3*2
47-
48-
if result == expected then
49-
puts "ok 12 - recursion: 6! == #{expected}"
50-
else
51-
puts "nok 12 - recursion: 6! == #{expected}"
52-
end
41+
puts "#{one_liner(12)} 12 - single line statement"
5342

5443
def iffy(n)
5544
if n == 10

examples/rubyish/t/recursion.t

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
puts "1..2"
2+
3+
def fact!(n)
4+
if n <= 1 then
5+
1
6+
else
7+
n * fact!(n - 1)
8+
end
9+
end
10+
11+
result = fact!(6)
12+
expected = 6*5*4*3*2
13+
14+
puts "#{result == expected ? 'ok' : 'nok'} 1 - sub recursion: 6! == #{expected}"
15+
16+
# ----------
17+
18+
class MethodRecursion
19+
def fibonacci(n)
20+
n <= 1 \
21+
? n \
22+
: self.fibonacci( n - 1 ) + self.fibonacci(n - 2 )
23+
## todo: -- dereferencing of self should be optional. both of the
24+
## -- following recursive calls are valid Ruby
25+
## self.fibonacci( n - 1 ) + fibonacci(n - 2 )
26+
end
27+
end
28+
29+
fib = MethodRecursion.new.fibonacci(9)
30+
expected2 = 34
31+
32+
puts "# todo - automatic passing of self"
33+
puts "#{fib == expected2 ? 'ok' : 'nok'} 2 - method recursion: (#{expected2})"

examples/rubyish/t/scoping.t

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
puts "1..13"
1+
puts "1..17"
22

33
a = "ok 1"
44
b = "ok 2"
@@ -13,20 +13,24 @@ end
1313
some_sub()
1414

1515
class MyClass
16-
@@final_test = 13
16+
@@final_test = 17
1717

18-
def set_class(v); @@c = v; b = 'wtf'; end
19-
def get_class; @@c; end
20-
def set_inst(v); @i = v; end
21-
def get_inst; @i; end
22-
def class_const; @@final_test ; end
23-
def tickle_f(f); @f = f ; end
18+
def set_class(v); @@c = v; b = 'wtf'; end
19+
def get_class; @@c; end
20+
def set_inst(v1,v2); @i1 = v1; @i2= v2 end
21+
def get_inst1; @i1; end
22+
def get_inst2; @i2; end
23+
def class_const; @@final_test ; end
24+
def tickle_f(f); @f = f ; end
2425

2526
end
2627

2728
class OtherClass
2829
def set_class(v); @@c = v; end
2930
def get_class; @@c; end
31+
def set_inst(v1,v2); @i1 = v1; @i2= v2 end
32+
def get_inst1; @i1; end
33+
def get_inst2; @i2; end
3034
end
3135

3236
obj1 = MyClass.new;
@@ -52,9 +56,14 @@ puts "ok #{obj1.get_class} - @@class access"
5256
puts "ok #{obj2.get_class() + 1} - @@class access"
5357
puts "ok #{obj3.get_class} - @@class variable"
5458

55-
obj1.set_inst(11)
56-
obj2.set_inst(12)
59+
obj1.set_inst(11,12)
60+
obj2.set_inst(13,14)
61+
obj3.set_inst(15,16)
5762

58-
puts "ok #{obj1.get_inst} - @instance access"
59-
puts "ok #{obj2.get_inst} - @instance access"
63+
puts "ok #{obj1.get_inst1} - @instance access"
64+
puts "ok #{obj1.get_inst2} - @instance access"
65+
puts "ok #{obj2.get_inst1} - @instance access"
66+
puts "ok #{obj2.get_inst2} - @instance access"
67+
puts "ok #{obj3.get_inst1} - @instance access"
68+
puts "ok #{obj3.get_inst2} - @instance access"
6069
puts "ok #{obj2.class_const} - @@class constant"

examples/rubyish/t/template.t

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ ok 5 - text between statements
1616
<%elsif n == 20 %>nok 7 - elsif block (false)
1717
<%else %>ok 7 - else block (false)
1818
<% end %>
19-
<%for test in [8, 9] do %>ok #{test} - for loop test
19+
<%for test in [8, 9] do %>ok #{test} - for loop test
2020
<%end%>
21-
<%#puts "nok 10 - commented out directive" %>
22-
ok 10 - final template text
21+
<%n = 9 %>
22+
<%#puts "nok #{n += 1} - commented out directive" %>
23+
ok #{n += 1} - final template text

0 commit comments

Comments
 (0)