Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fixed rubyish object attribute scoping. adding recursion tests
  • Loading branch information
dwarring committed Nov 20, 2013
1 parent bdbb63a commit d959560
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 60 deletions.
50 changes: 28 additions & 22 deletions examples/rubyish/rubyish.nqp
@@ -1,4 +1,3 @@
# -*- coding: iso-8859-1 -*-
use NQPHLL;

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

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

'def' ~ 'end' <defbody>

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

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

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

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

rule classbody {
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
:my $*CLASS_BLOCK := $*CUR_BLOCK;
<ident> <separator>

<ident> { $*CLASS_BLOCK.name(~$<ident>) }
<separator>
<stmtlist>
}

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

token code-block {:s<hs>
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
<closure>
<closure>
}

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

token term:sym<var> { <var> }
token term:sym<var> { <var> }

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

Expand Down Expand Up @@ -187,8 +188,8 @@ grammar Rubyish::Grammar is HLL::Grammar {
<EXPR> *%% <comma>
}

token value:sym<integer> { \+? \d+ }
token value:sym<float> { \+? \d* '.' \d+ }
token value:sym<integer> { \d+ }
token value:sym<float> { \d* '.' \d+ }
token value:sym<array> {'[' ~ ']' <paren-list> }
token value:sym<hash> {'{' ~ '}' <paren-list> }
token value:sym<nil> { <sym> }
Expand Down Expand Up @@ -364,8 +365,8 @@ grammar Rubyish::Grammar is HLL::Grammar {
token term:sym<lambda> {:s
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
['lambda' <closure>
| '->' <closure=.closure2>
]
| '->' <closure=.closure2>
]
}

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

if $sigil eq '@' && $*IN_CLASS {
# instance variable, bound to self
make QAST::Var.new( :scope('attribute'),
my $package-name := $*CLASS_BLOCK.name;
make QAST::Var.new( :name($name), :scope('attribute'),
QAST::Var.new( :name('self'), :scope('lexical')),
QAST::SVal.new( :value($name) )
QAST::SVal.new( :value($package-name) )
);
}
else {
Expand Down Expand Up @@ -645,9 +647,9 @@ class Rubyish::Actions is HLL::Actions {
}

for @params {
$*CUR_BLOCK[0].push($_);
$*CUR_BLOCK.symbol($_.name, :declared(1));
}
$*CUR_BLOCK[0].push($_);
$*CUR_BLOCK.symbol($_.name, :declared(1));
}
}

method stmt:sym<class>($/) {
Expand All @@ -656,14 +658,18 @@ class Rubyish::Actions is HLL::Actions {
# Generate code to create the class.
my $class_stmts := QAST::Stmts.new( $body_block );
my $ins_name := '::' ~ $<classbody><ident>;
$class_stmts.push(QAST::Op.new(
:op('bind'),
QAST::Var.new( :name($ins_name), :scope('lexical'), :decl('var') ),
QAST::Op.new(

my $new_type := QAST::Op.new(
:op('callmethod'), :name('new_type'),
QAST::WVal.new( :value(RubyishClassHOW) ),
QAST::SVal.new( :value(~$<classbody><ident>), :named('name') ) )
));
QAST::SVal.new( :value(~$<classbody><ident>), :named('name') ),
);

$class_stmts.push(QAST::Op.new(
:op('bind'),
QAST::Var.new( :name($ins_name), :scope('lexical'), :decl('var') ),
$new_type,
));

# Add methods.
my $class_var := QAST::Var.new( :name($ins_name), :scope('lexical') );
Expand Down
22 changes: 13 additions & 9 deletions examples/rubyish/t/functional.t
@@ -1,29 +1,28 @@
# implement and test functional primitives: map, grep and sort.
puts '1..8'
puts '1..9'

test_counter = 0

def is(result, expected, description)
test_num = (test_counter += 1)
passed = result eq expected
puts "#{passed ? 'ok' : 'nok'} #{test_num} - #{description}"
puts "# expected:'#{expected}' got:'#{result}'" unless passed
puts "# expected:'#{expected}' got:'#{result}'" \
unless passed
end

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

# ------------
def grep(array_inp, &filter)
def grep(array_inp, &selector)
array_out = []
n = -1
selector = lambda {|elem| !elem.nil? && elem} \
if selector.nil?

for elem in array_inp ;
keep = (filter.nil?
? (!elem.nil? && elem)
: filter.call(elem))

array_out[ n+=1 ] = elem \
if keep
if selector.call(elem)
end

array_out
Expand Down Expand Up @@ -108,7 +107,12 @@ is dump(num_sort), '0,1,2,4,5,10,13,18,27', 'sort [numeric]'
# ------------
# put it all together
odd = lambda {|n| n % 2 == 1}

combined = map(sort grep(arr,&odd)) {|str| nqp::flip(str)}
is dump(combined), '1,31,72,5', 'combined map sort grep'
is dump(arr), '0,2,10,1,13,27,5,4,18', 'array unscathed'

splitter = lambda {|n| nqp::split('',n)}
is dump( map(combined, &splitter) ), '1,3,1,7,2,5', 'map [flattening]'

is dump(arr), '0,2,10,1,13,27,5,4,18', 'array readonly'

17 changes: 3 additions & 14 deletions examples/rubyish/t/if-then-else.t
Expand Up @@ -34,22 +34,11 @@ puts "ok 10"; end
if 2 >= 1 && 1 <= 2 && "b" gt "a" && "a" lt "b" && (2 != 1) ; puts "ok 11"
else puts "nok 11"; end

def fact!(n)
if n <= 1 then
1
else
n * fact!(n - 1)
end
def one_liner(i)
if i == 42 then 'nok' elsif i == 12 then 'ok' else 'nok' end
end

result = fact!(6)
expected = 6*5*4*3*2

if result == expected then
puts "ok 12 - recursion: 6! == #{expected}"
else
puts "nok 12 - recursion: 6! == #{expected}"
end
puts "#{one_liner(12)} 12 - single line statement"

def iffy(n)
if n == 10
Expand Down
33 changes: 33 additions & 0 deletions examples/rubyish/t/recursion.t
@@ -0,0 +1,33 @@
puts "1..2"

def fact!(n)
if n <= 1 then
1
else
n * fact!(n - 1)
end
end

result = fact!(6)
expected = 6*5*4*3*2

puts "#{result == expected ? 'ok' : 'nok'} 1 - sub recursion: 6! == #{expected}"

# ----------

class MethodRecursion
def fibonacci(n)
n <= 1 \
? n \
: self.fibonacci( n - 1 ) + self.fibonacci(n - 2 )
## todo: -- dereferencing of self should be optional. both of the
## -- following recursive calls are valid Ruby
## self.fibonacci( n - 1 ) + fibonacci(n - 2 )
end
end

fib = MethodRecursion.new.fibonacci(9)
expected2 = 34

puts "# todo - automatic passing of self"
puts "#{fib == expected2 ? 'ok' : 'nok'} 2 - method recursion: (#{expected2})"
33 changes: 21 additions & 12 deletions examples/rubyish/t/scoping.t
@@ -1,4 +1,4 @@
puts "1..13"
puts "1..17"

a = "ok 1"
b = "ok 2"
Expand All @@ -13,20 +13,24 @@ end
some_sub()

class MyClass
@@final_test = 13
@@final_test = 17

def set_class(v); @@c = v; b = 'wtf'; end
def get_class; @@c; end
def set_inst(v); @i = v; end
def get_inst; @i; end
def class_const; @@final_test ; end
def tickle_f(f); @f = f ; end
def set_class(v); @@c = v; b = 'wtf'; end
def get_class; @@c; end
def set_inst(v1,v2); @i1 = v1; @i2= v2 end
def get_inst1; @i1; end
def get_inst2; @i2; end
def class_const; @@final_test ; end
def tickle_f(f); @f = f ; end

end

class OtherClass
def set_class(v); @@c = v; end
def get_class; @@c; end
def set_inst(v1,v2); @i1 = v1; @i2= v2 end
def get_inst1; @i1; end
def get_inst2; @i2; end
end

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

obj1.set_inst(11)
obj2.set_inst(12)
obj1.set_inst(11,12)
obj2.set_inst(13,14)
obj3.set_inst(15,16)

puts "ok #{obj1.get_inst} - @instance access"
puts "ok #{obj2.get_inst} - @instance access"
puts "ok #{obj1.get_inst1} - @instance access"
puts "ok #{obj1.get_inst2} - @instance access"
puts "ok #{obj2.get_inst1} - @instance access"
puts "ok #{obj2.get_inst2} - @instance access"
puts "ok #{obj3.get_inst1} - @instance access"
puts "ok #{obj3.get_inst2} - @instance access"
puts "ok #{obj2.class_const} - @@class constant"
7 changes: 4 additions & 3 deletions examples/rubyish/t/template.t
Expand Up @@ -16,7 +16,8 @@ ok 5 - text between statements
<%elsif n == 20 %>nok 7 - elsif block (false)
<%else %>ok 7 - else block (false)
<% end %>
<%for test in [8, 9] do %>ok #{test} - for loop test
<%for test in [8, 9] do %>ok #{test} - for loop test
<%end%>
<%#puts "nok 10 - commented out directive" %>
ok 10 - final template text
<%n = 9 %>
<%#puts "nok #{n += 1} - commented out directive" %>
ok #{n += 1} - final template text

0 comments on commit d959560

Please sign in to comment.