Here's a patch to fix logical ops in the Parrot Scheme compiler. The
patch:
- Implements (min) and (max) which had stubs and some =pod'd out code
which I couldn't understand.
- Fixes (=), (<), (>), (<=) and (>=) to work with more than 2 operands.
Added tests where they were missing and fixed tests that were
incorrectly passing.
After this patch "make test" has no failures on my box. Question:
- Why does Scheme::Generator::_save(2) return an array of three
elements? I tried to "fix" _save() and that just broke things...
I must be missing something!
-sam
PS: Can we get this into languages/scheme?
diff -ru scheme.orig/Scheme/Generator.pm scheme/Scheme/Generator.pm
--- scheme.orig/Scheme/Generator.pm Thu Oct 18 15:44:43 2001
+++ scheme/Scheme/Generator.pm Sat Oct 20 17:36:19 2001
@@ -244,8 +244,9 @@
$self->_add_inst('','set',["I$return",0]);
$self->_generate($node->{children}[0],$temp[0]);
for(1..$#{$node->{children}}) {
- $self->_generate($node->{children}[1],$temp[1]);
+ $self->_generate($node->{children}[$_],$temp[1]);
$self->_add_inst('','ne',["I$temp[0]","I$temp[1]","DONE_$label"]);
+ ($temp[0], $temp[1]) = ($temp[1], $temp[0]);
}
$self->_add_inst('','set',["I$return",1]);
$self->_add_inst("DONE_$label");
@@ -260,8 +261,9 @@
$self->_add_inst('','set',["I$return",0]);
$self->_generate($node->{children}[0],$temp[0]);
for(1..$#{$node->{children}}) {
- $self->_generate($node->{children}[1],$temp[1]);
+ $self->_generate($node->{children}[$_],$temp[1]);
$self->_add_inst('','ge',["I$temp[0]","I$temp[1]","DONE_$label"]);
+ ($temp[0], $temp[1]) = ($temp[1], $temp[0]);
}
$self->_add_inst('','set',["I$return",1]);
$self->_add_inst("DONE_$label");
@@ -276,8 +278,9 @@
$self->_add_inst('','set',["I$return",0]);
$self->_generate($node->{children}[0],$temp[0]);
for(1..$#{$node->{children}}) {
- $self->_generate($node->{children}[1],$temp[1]);
+ $self->_generate($node->{children}[$_],$temp[1]);
$self->_add_inst('','le',["I$temp[0]","I$temp[1]","DONE_$label"]);
+ ($temp[0], $temp[1]) = ($temp[1], $temp[0]);
}
$self->_add_inst('','set',["I$return",1]);
$self->_add_inst("DONE_$label");
@@ -292,8 +295,9 @@
$self->_add_inst('','set',["I$return",0]);
$self->_generate($node->{children}[0],$temp[0]);
for(1..$#{$node->{children}}) {
- $self->_generate($node->{children}[1],$temp[1]);
+ $self->_generate($node->{children}[$_],$temp[1]);
$self->_add_inst('','gt',["I$temp[0]","I$temp[1]","DONE_$label"]);
+ ($temp[0], $temp[1]) = ($temp[1], $temp[0]);
}
$self->_add_inst('','set',["I$return",1]);
$self->_add_inst("DONE_$label");
@@ -308,8 +312,9 @@
$self->_add_inst('','set',["I$return",0]);
$self->_generate($node->{children}[0],$temp[0]);
for(1..$#{$node->{children}}) {
- $self->_generate($node->{children}[1],$temp[1]);
+ $self->_generate($node->{children}[$_],$temp[1]);
$self->_add_inst('','lt',["I$temp[0]","I$temp[1]","DONE_$label"]);
+ ($temp[0], $temp[1]) = ($temp[1], $temp[0]);
}
$self->_add_inst('','set',["I$return",1]);
$self->_add_inst("DONE_$label");
@@ -385,59 +390,32 @@
sub _op_max {
my ($self,$node,$return) = @_;
- my $label = $self->_gensym();
-
- my @temp = _save(1);
- $self->_generate($node->{children}[0],$return);
-
- _restore(@temp);
+ my ($targ) = _save(1);
-=pod
-
- $self->__build_children($node);
-
- $self->_add_inst('','set',[$return,$registers[0]]);
-
- $self->_add_inst('', 'lt', [$registers[0],$return,$label]);
- $self->_add_inst('', 'set',[$return,$registers[0]]);
- for(1..$#registers) {
- my $tmp_label = "NEXT_".$self->_gensym();
- $self->_add_inst($label,'lt' ,[$registers[$_],$return,$tmp_label]);
- $self->_add_inst('', 'set',[$return,$registers[$_]]);
- $label = $tmp_label;
+ $self->_generate($node->{children}[0], $return);
+ for (1 .. $#{$node->{children}}) {
+ my $label = $self->_gensym();
+ $self->_generate($node->{children}[$_], $targ);
+ $self->_add_inst('','le',["I$targ","I$return","SKIP_$label"]);
+ $self->_add_inst('','set',["I$return","I$targ"]);
+ $self->_add_inst("SKIP_$label");
}
- $self->_add_inst($label);
-
-=cut
-
+ _restore($targ);
}
sub _op_min {
+ my ($self,$node,$return) = @_;
+ my ($targ) = _save(1);
-=pod
-
- my $self = shift;
- my $node = shift;
- my $return = "I$node->{register}";
-
- $self->__build_children($node);
- my @registers = map { "I$_->{register}" } @{$node->{children}};
-
- $self->_add_inst('','set',[$return,$registers[0]]);
-
- my $label = "NEXT_".$self->_gensym();
- $self->_add_inst('', 'gt', [$registers[0],$return,$label]);
- $self->_add_inst('', 'set',[$return,$registers[0]]);
- for(1..$#registers) {
- my $tmp_label = "NEXT_".$self->_gensym();
- $self->_add_inst($label,'gt' ,[$registers[$_],$return,$tmp_label]);
- $self->_add_inst('', 'set',[$return,$registers[$_]]);
- $label = $tmp_label;
+ $self->_generate($node->{children}[0], $return);
+ foreach (1 .. $#{$node->{children}}) {
+ my $label = $self->_gensym();
+ $self->_generate($node->{children}[$_], $targ);
+ $self->_add_inst('','ge',["I$targ","I$return","SKIP_$label"]);
+ $self->_add_inst('','set',["I$return","I$targ"]);
+ $self->_add_inst("SKIP_$label");
}
- $self->_add_inst($label);
-
-=cut
-
+ _restore($targ);
}
sub _op_plus {
diff -ru scheme.orig/t/arith/logic.t scheme/t/arith/logic.t
--- scheme.orig/t/arith/logic.t Mon Oct 15 19:36:46 2001
+++ scheme/t/arith/logic.t Sat Oct 20 17:29:01 2001
@@ -1,6 +1,6 @@
#! perl -w
-use Scheme::Test tests => 43;
+use Scheme::Test tests => 54;
###
### Zero?
@@ -143,15 +143,19 @@
CODE
output_is(<<'CODE', 1, 'write (= 0 0 0))');
-(write (= 0 0))
+(write (= 0 0 0))
+CODE
+
+output_is(<<'CODE', 0, 'write (= 0 0 1))');
+(write (= 0 0 1))
CODE
output_is(<<'CODE', 0, 'write (= 1 2 3))');
-(write (= 1 0))
+(write (= 1 2 3))
CODE
output_is(<<'CODE', 0, 'write (= 0 1 1))');
-(write (= 0 1))
+(write (= 0 1 1))
CODE
###
@@ -174,6 +178,10 @@
(write (< 1 1 1))
CODE
+output_is(<<'CODE', 0, 'write (< 1 2 1))');
+(write (< 1 2 1))
+CODE
+
###
### Greater (>)
###
@@ -218,6 +226,42 @@
(write (<= 2 1 1))
CODE
+output_is(<<'CODE', 0, 'write (<= 2 1 2))');
+(write (<= 2 1 2))
+CODE
+
+output_is(<<'CODE', 0, 'write (<= 1 2 1))');
+(write (<= 1 2 1))
+CODE
+
###
### GEQ (>=)
###
+
+output_is(<<'CODE', 1, 'write (>= 0 0))');
+(write (>= 0 0))
+CODE
+
+output_is(<<'CODE', 1, 'write (>= 1 0))');
+(write (>= 1 0))
+CODE
+
+output_is(<<'CODE', 0, 'write (>= 1 2))');
+(write (>= 1 2))
+CODE
+
+output_is(<<'CODE', 1, 'write (>= 2 1 0))');
+(write (>= 2 1 0))
+CODE
+
+output_is(<<'CODE', 1, 'write (>= 2 1 1))');
+(write (>= 2 1 1))
+CODE
+
+output_is(<<'CODE', 0, 'write (>= 2 1 2))');
+(write (>= 2 1 2))
+CODE
+
+output_is(<<'CODE', 0, 'write (>= 1 2 1))');
+(write (>= 1 2 1))
+CODE