Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
implement while/until/repeat_while/repeat_until without using labels/…
…gotos :/
  • Loading branch information
diakopter committed Nov 1, 2011
1 parent 0496bb8 commit 37485f2
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 32 deletions.
37 changes: 37 additions & 0 deletions lua/compiler/LST.pm
Expand Up @@ -299,6 +299,43 @@ class LST::If is LST::Node {
}
}

class LST::While is LST::Node {
has $!type;
has $!bool;
has $!result;
has $!repeat;

method bool($set?) {
if $set { $!bool := $set }
$!bool
}

method type($set?) {
if $set { $!type := $set }
$!type
}

method result($set?) {
if $set { $!result := $set }
$!result
}

method repeat($set?) {
if pir::defined($set) { $!repeat := $set }
$!repeat
}

method new(:$bool, :$type, :$result, :$repeat, *@children) {
my $obj := self.CREATE;
$obj.set_children(@children);
$obj.bool($bool);
$obj.repeat($repeat);
$obj.type(pir::defined($type) ?? $type !! 'RakudoObject');
$obj.result(pir::defined($result) ?? $result !! 1);
$obj;
}
}

class LST::Return is LST::Node {
has $!target;

Expand Down
33 changes: 33 additions & 0 deletions lua/compiler/LST2Lua.pm
Expand Up @@ -212,6 +212,39 @@ our multi sub cs_for(LST::If $if) {
return $code;
}

our multi sub cs_for(LST::While $while) {
unless +@($while) == 3 { pir::die('A LST::While node must have 3 children') }

# Need a variable to put the final result in.
my $while_result := get_unique_id('while_result') if $while.result;

# Get the conditional and emit while.
my $cond_code := cs_for((@($while))[0]) ~ cs_for((@($while))[1]);
# $*LAST_TEMP is set by the condition result cs_for regardless of
# whether the condition code is emitted at the beginning of the loop

my $code := $while.repeat ?? "" !! $cond_code;

$code := $code ~
" $while_result = nil;\n" if $while.result;
if ($while.repeat) {
$code := $code ~
" $*LAST_TEMP = " ~ ($while.bool ?? "true" !! 1) ~ ";\n";
}
$code := $code ~
" while ($*LAST_TEMP" ~ ($while.bool ?? "" !! " ~= 0") ~ ") do\n";

# Compile branch.
$*LAST_TEMP := 'nil';
$code := $code ~ cs_for((@($while))[2]);
$code := $code ~ " $while_result = $*LAST_TEMP;\n" if $while.result;
$code := $code ~ $cond_code;
$code := $code ~ " end\n";

$*LAST_TEMP := $while_result if $while.result;
return $code;
}

our multi sub cs_for(LST::Return $ret) {
return cs_for($ret.target) ~ " return " ~ $*LAST_TEMP ~ ";\n";
}
Expand Down
36 changes: 8 additions & 28 deletions lua/compiler/PAST2LSTCompiler.pm
Expand Up @@ -692,9 +692,6 @@ our multi sub lst_for(PAST::Op $op) {
}

elsif $op.pasttype eq 'while' || $op.pasttype eq 'until' {
# Need labels for start and end.
my $test_label := get_unique_id('while_lab');
my $end_label := get_unique_id('while_end_lab');
my $cond_result := LST::Local.new( :name(get_unique_id('cond')) );

# Compile the condition.
Expand All @@ -716,26 +713,15 @@ our multi sub lst_for(PAST::Op $op) {
my $body := lst_for((@($op))[1]);

# Build up result.
return LST::Stmts.new(
LST::Label.new( :name($test_label) ),
return LST::While.new(
:repeat(0),
$cond,
LST::If.new(
unbox('int', $cond_result),
$body,
LST::Stmts.new(
$cond_result,
LST::Goto.new( :label($end_label) )
)
),
LST::Goto.new( :label($test_label) ),
LST::Label.new( :name($end_label) )
unbox('int', $cond_result),
$body
);
}

elsif $op.pasttype eq 'repeat_while' || $op.pasttype eq 'repeat_until' {
# Need labels for start and end.
my $test_label := get_unique_id('while_lab');
my $block_label := get_unique_id('block_lab');
my $cond_result := LST::Local.new( :name(get_unique_id('cond')) );

# Compile the condition.
Expand All @@ -757,17 +743,11 @@ our multi sub lst_for(PAST::Op $op) {
my $body := lst_for((@($op))[1]);

# Build up result.
return LST::Stmts.new(
LST::Label.new( :name($block_label) ),
$body,
return LST::While.new(
:repeat(1),
$cond,
LST::If.new(
unbox('int', $cond_result),
LST::Stmts.new(
$cond_result,
LST::Goto.new( :label($block_label) )
)
)
unbox('int', $cond_result),
$body
);
}

Expand Down
10 changes: 6 additions & 4 deletions lua/compiler/try.bat
@@ -1,8 +1,10 @@
@if exist x.exe del /Q x.exe
@if exist x.cs del /Q x.cs
@nmake /nologo P6Objects.dll >NUL
@parrot compile.pir %1 > x.cs
@csc /nologo x.cs /reference:RakudoRuntime.dll /debug /warn:0
echo --> x.lua
rem @type RakudoRuntime.lua > x.lua
rem @type NQPSetting.lua >> x.lua
rem @type P6Objects.lua >> x.lua
@parrot compile.pir %1 >> x.lua
@echo ---
@x

@luajit x.lua

0 comments on commit 37485f2

Please sign in to comment.