# New Ticket Created by J�rgen B�mmels
# Please include the string: [perl #18379]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=18379 >
Hello,
I used Jonathan Sillito's patch [#18170] to implement functions in
scheme. It has lambda expressions, function defines, and basic let
functionality. Testcases are included. (New file defines.t)
One thing I'm not very happy about that I need 2 pop_pads at function
return, one cleaning up the newly generated pad from new_pad, and one
for cleaning up the stored scope of function definition. I have no
idea how to solve this.
This patch obsoletes #17109 (which isn't applied yet).
bye
b.
DEPENDS ON #18170
-- attachment 1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/41631/33455/33b0f8/scheme.diff
-- attachment 2 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/41631/33456/41cd7b/new_pad.diff
Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.249
diff -u -r1.249 MANIFEST
--- MANIFEST 9 Nov 2002 12:42:54 -0000 1.249
+++ MANIFEST 13 Nov 2002 21:36:24 -0000
@@ -36,6 +36,7 @@
classes/pmc2c.pl
classes/pointer.pmc
classes/scalar.pmc
+classes/scratchpad.pmc
classes/sub.pmc
config/auto/alignptrs.pl
config/auto/alignptrs/test_c.in
@@ -1534,6 +1535,7 @@
languages/scheme/t/io/basic.t
languages/scheme/t/logic/basic.t
languages/scheme/t/logic/lists.t
+languages/scheme/t/logic/defines.t
lib/Class/Struct.pm
lib/Digest/Perl/MD5.pm
lib/Make.pm
Index: languages/scheme/Scheme/Builtins.pm
===================================================================
RCS file: /cvs/public/parrot/languages/scheme/Scheme/Builtins.pm,v
retrieving revision 1.1
diff -u -r1.1 Builtins.pm
--- languages/scheme/Scheme/Builtins.pm 5 Sep 2002 19:54:42 -0000 1.1
+++ languages/scheme/Scheme/Builtins.pm 13 Nov 2002 21:36:24 -0000
@@ -6,20 +6,22 @@
(
write =>
[['# Write function', ''],
- ['write_ENTRY', 'save', 'I0'],
- ['', 'typeof', 'I0', 'P5'],
+ ['write_ENTRY', 'typeof', 'I0', 'P5'],
['', 'ne', 'I0', '.PerlUndef', 'write_N_UNDEF'],
['', 'print', '"()"'],
- ['', 'branch', 'write_RET0'],
- ['write_N_UNDEF','eq', 'I0', '.Array', 'write_ARRAY'],
+ ['', 'branch', 'write_RET'],
+ ['write_N_UNDEF','ne', 'I0', '.Scratchpad', 'write_N_LAMBDA'],
+ ['', 'print', '"lambda"'],
+ ['', 'branch', 'write_RET'],
+ ['write_N_LAMBDA','eq', 'I0', '.Array', 'write_ARRAY'],
['', 'print', 'P5'],
- ['', 'branch', 'write_RET0'],
- ['write_ARRAY', 'save', 'P5'],
- ['', 'save', 'P6'],
- ['', 'print', '"("'],
+ ['', 'branch', 'write_RET'],
+ ['write_ARRAY', 'print', '"("'],
['write_NEXT', 'set', 'P6', 'P5'],
['', 'set', 'P5', 'P6[0]'],
+ ['', 'save', 'P6'],
['', 'bsr', 'write_ENTRY'],
+ ['', 'restore', 'P6'],
['', 'set', 'P5', 'P6[1]'],
['', 'typeof', 'I0', 'P5'],
['', 'eq', 'I0', '.PerlUndef', 'write_KET'],
@@ -29,10 +31,24 @@
['write_DOT', 'print', '" . "'],
['', 'bsr', 'write_ENTRY'],
['write_KET', 'print', '")"'],
- ['', 'restore', 'P6'],
- ['', 'restore', 'P5'],
- ['write_RET0', 'restore', 'I0'],
- ['', 'ret'],
+ ['write_RET', 'ret'],
+ ],
+ apply =>
+ [['# apply Function',''],
+ ['apply_ENTRY', 'set', 'P7', 'P5[0]'],
+ ['', 'push_pad', 'P7'],
+ ['', 'new_pad', '-1'],
+ ['', 'set', 'P7', 'P5[2]'],
+ ['apply_NEXT', 'typeof', 'I0', 'P6'],
+ ['', 'eq', 'I0', '.PerlUndef', 'apply_LAST'],
+ ['', 'set', 'S0', 'P7[0]'],
+ ['', 'set', 'P8', 'P6[0]'],
+ ['', 'store_lex', '-1', 'S0', 'P8'],
+ ['', 'set', 'P6', 'P6[1]'],
+ ['', 'set', 'P7', 'P7[1]'],
+ ['', 'branch', 'apply_NEXT'],
+ ['apply_LAST', 'set', 'I0', 'P5[1]'],
+ ['', 'jump', 'I0'],
]
);
Index: languages/scheme/Scheme/Generator.pm
===================================================================
RCS file: /cvs/public/parrot/languages/scheme/Scheme/Generator.pm,v
retrieving revision 1.3
diff -u -r1.3 Generator.pm
--- languages/scheme/Scheme/Generator.pm 5 Sep 2002 15:03:55 -0000 1.3
+++ languages/scheme/Scheme/Generator.pm 13 Nov 2002 21:36:25 -0000
@@ -15,14 +15,17 @@
#------------------------------------
-my $regs = {
- I => { map { $_ => 0 } (0..31) },
- N => { map { $_ => 0 } (0..31) },
- S => { map { $_ => 0 } (0..31) },
- P => { map { $_ => 0 } (0..31) },
+sub _new_regs {
+ {
+ I => { map { $_ => 0 } (0..31) },
+ N => { map { $_ => 0 } (0..31) },
+ S => { map { $_ => 0 } (0..31) },
+ P => { map { $_ => 0 } (0..31) },
+ };
};
sub _save {
+ my $self = shift;
my $count = shift;
my $type = shift || 'I';
die "No registers to save"
@@ -31,39 +34,101 @@
unless $type and $type=~/^[INPS]$/;
my @temp;
for(0..31) {
- next if $regs->{$type}{$_} == 1;
+ next if $self->{regs}->{$type}{$_} == 1;
last if $count<=0;
push @temp,"$type$_";
- $regs->{$type}{$_}=1;
+ $self->{regs}->{$type}{$_}=1;
$count--;
}
@temp;
}
+sub _save_set {
+ my $self = shift;
+ my %regs = %{$self->{regs}};
+ for my $type (keys %regs) {
+ for my $count (0..31) {
+ $self->_add_inst ('', 'save', ["$type$count"])
+ if $regs{$type}->{$count};
+ }
+ }
+}
+
sub _save_1 {
+ my $self = shift;
my $type = shift || 'I';
- my @temp = _save 1, $type;
+ my @temp = $self->_save(1, $type);
$temp[0];
}
sub _restore {
+ my $self = shift;
+
die "Nothing to restore"
unless defined @_;
- for(@_) {
- s/^(\w)//;
+ foreach my $reg (@_) {
+ next if grep { $_ eq $reg } qw (none);
+ $reg =~ /^(\w)(\d+)/;
die "Missing register type"
unless defined $1;
- $regs->{$1}{$_}=0;
+ if ($self->{regs}->{$1}{$2}) {
+ $self->{regs}->{$1}{$2} = 0;
+ }
+ }
+}
+
+sub _restore_set {
+ my $self = shift;
+ my %regs = %{$self->{regs}};
+
+ for my $type (reverse keys %regs) {
+ for (my $count=31; $count>=0; $count--) {
+ $self->_add_inst ('','restore',["$type$count"])
+ if $regs{$type}->{$count};
+ }
}
}
sub _num_arg {
my ($node, $expected, $name) = @_;
- my $children = scalar @{$node->{children}};
+ my $args = scalar @{$node->{children}} - 1;
+
+ die "$name: Wrong number of arguments (expected $expected, got $args).\n"
+ if ($args != $expected);
+}
+
+sub _get_arg {
+ my ($node, $num) = @_;
+ $node->{children}->[$num];
+}
+
+sub _get_args {
+ my ($node, $num) = @_;
+ $num = 1 unless defined $num;
- die "$name: Wrong number of arguments (expected $expected, got $children).\n"
- if ($children != $expected);
+ my @args = @{$node->{children}};
+ splice @args, 0, $num;
+
+ return @args;
+}
+
+# until there is a working find_lex/store_lex
+sub _find_lex {
+ my ($self, $symbol) = @_;
+ my $return = $self->_save_1 ('P');
+ $self->_add_inst ('','find_lex',[$return,"\"$symbol\""]);
+ return $return;
+}
+
+sub _store_lex {
+ my ($self, $symbol,$value) = @_;
+ $self->_add_inst ('','store_lex',["\"$symbol\"",$value]);
+}
+
+sub _new_lex {
+ my ($self, $symbol, $value) = @_;
+ $self->_add_inst ('','store_lex',[-1,"\"$symbol\"",$value]);
}
#------------------------------------
@@ -78,29 +143,141 @@
#------------------------------------
-sub _op_constant {
- my ($self,$node) = @_;
- my ($num_registers,$type) = @{$type_map->{$node->{type}}};
- my @register = _save($num_registers,$type);
- for(@register) {
- $self->_add_inst('','set',[$_,$node->{value}]);
+sub _constant {
+ my ($self, $value) = @_;
+ my $return;
+
+ if ($value =~ /^[-+]?\d+$/) {
+ $return = $self->_save_1 ('I');
+ $self->_add_inst ('', 'set', [$return,$value]);
+ }
+ elsif ($value =~ /^[-+]?((\d+\.\d*)|(\.d+))([eE][-+]?\d+)?$/) {
+ $return = $self->_save_1 ('N');
+ $self->_add_inst ('', 'set', [$return,$value]);
+ }
+ else {
+ $return = $self->_save_1 ('I');
+ $self->_add_inst ('', 'set', [$return,0]);
}
- return $register[0];
-}
-sub _constant {
- my ($self,$value) = @_;
- return $self->_generate({value=>$value,type=>'INTEGER'});
+ return $return;
}
-#------------------------------------
+sub _morph {
+ my ($self, $to, $from) = @_;
+
+ if ($to =~ /P/) {
+ if ($from =~ /P/) {
+ $self->_add_inst ('', 'clone',[$to,$from]);
+ } elsif ($from =~ /I/) {
+ $self->_add_inst ('', 'new',[$to,'.PerlInt']);
+ $self->_add_inst ('', 'set',[$to,$from]);
+ } elsif ($from =~ /N/) {
+ $self->_add_inst ('', 'new',[$to,'.PerlNum']);
+ $self->_add_inst ('', 'set',[$to,$from]);
+ }
+ }
+}
#---- Section 4 ----
+sub __quoted {
+ my ($self, $node) = @_;
+ my $return = $self->_save_1 ('P');
+
+ if (exists $node->{value}) {
+ my $value = $node->{value};
+ if ($value =~ /^[-+]?\d+$/) {
+ $self->_add_inst ('', 'new',[$return,'.PerlInt']);
+ $self->_add_inst ('', 'set',[$return,$value]);
+ }
+ elsif ($value =~ /^[-+]?((\d+\.\d*)|(\.d+))([eE][-+]?\d+)?$/) {
+ $self->_add_inst ('', 'new',[$return,'.PerlNum']);
+ $self->_add_inst ('', 'set',[$return,$value]);
+ }
+ else { # assume its a symbol
+ $self->_add_inst ('', 'new',[$return,'.PerlString']);
+ $self->_add_inst ('', 'set',[$return,"\"$value\""]);
+ }
+ }
+ elsif (exists $node->{children}) {
+ $self->_add_inst ('', 'new', [$return,'.PerlUndef']);
+ for (reverse @{$node->{children}}) {
+
+ my $item = __quoted ($self, $_);
+ my $pair = $self->_save_1 ('P');
+ $self->_add_inst ('', 'new', [$pair,'.Array']);
+ $self->_add_inst ('', 'set', [$pair,2]);
+ $self->_add_inst ('', 'set', [$pair.'[0]',$item]);
+ $self->_add_inst ('', 'set', [$pair.'[1]',$return]);
+ $self->_add_inst ('', 'set', [$return,$pair]);
+ $self->_restore ($item, $pair);
+ }
+ }
+
+ return $return;
+}
+
sub _op_quote {
+ my ($self, $node) = @_;
+ my $return;
+
+ _num_arg ($node, 1, 'quote');
+
+ my $item = _get_arg($node,1);
+
+ return __quoted ($self, $item);
}
sub _op_lambda {
+ my ($self,$node) = @_;
+ my $return;
+ my $label = $self->_gensym();
+ my $temp;
+
+ $return = $self->_save_1 ('P');
+
+ $self->_add_inst ('', 'new',[$return,'.Array']);
+ $self->_add_inst ('', 'set',[$return,3]);
+
+ $temp = $self->_save_1 ('P');
+ $self->_add_inst ('', 'peek_pad', [$temp]);
+ $self->_add_inst ('', 'set',[$return.'[0]',$temp]);
+ $self->_restore($temp);
+
+ my $addr = $self->_save_1 ('I');
+ $self->_add_inst ('', 'set_addr',[$addr,"LAMBDA_$label"]);
+ $self->_add_inst ('', 'set',[$return.'[1]',$addr]);
+ $self->_restore ($addr);
+
+ $temp = __quoted ($self,_get_arg($node,1));
+ $self->_add_inst ('', 'set',[$return.'[2]',$temp]);
+ $self->_restore ($temp);
+
+ $self->_add_inst ('', 'branch',["DONE_$label"]);
+ $self->_add_inst ("LAMBDA_$label");
+
+ # caller saved => start a new frame
+ push @{$self->{frames}}, $self->{regs};
+ $self->{regs} = _new_regs;
+
+ $temp = 'none';
+ for (_get_args($node,2)) {
+ $self->_restore ($temp);
+ $temp = $self->_generate($_);
+ }
+
+ $self->_add_inst('', 'set', ['P5', $temp]);
+
+ $self->_add_inst('', 'pop_pad');
+ # XXX: new_pad is the only way to create a new scope
+ $self->_add_inst('', 'pop_pad');
+ $self->_add_inst('', 'ret');
+ $self->_add_inst("DONE_$label");
+
+ $self->{regs} = pop @{$self->{frames}};
+
+ return $return;
}
sub _op_if {
@@ -108,23 +285,79 @@
my $return;
my $label = $self->_gensym();
- $return = "I"._save(1,'I');
- my $cond = $self->_generate($node->{children}[0]);
+ my $cond = $self->_generate(_get_arg($node,1));
$self->_add_inst('','eq',[$cond,0,"FALSE_$label"]);
- my $true = $self->_generate($node->{children}[1]);
- $self->_add_inst('','set',[$return,$true]);
+ $self->_restore($cond);
+ $return = $self->_save_1 ('P');
+
+ my $true = $self->_generate(_get_arg($node,2));
+ $self->_morph($return,$true);
$self->_add_inst('','branch',["DONE_$label"]);
+ $self->_restore($true);
+
$self->_add_inst("FALSE_$label");
- _restore($true);
- _restore($cond);
- my $false = $self->_generate($node->{children}[2]);
- $self->_add_inst('','set',[$return,$false]);
- _restore($false);
+ my $false = $self->_generate(_get_arg($node,3));
+ $self->_morph($return,$false);
+ $self->_restore($false);
+
$self->_add_inst("DONE_$label");
return $return;
}
+sub _op_define {
+ my ($self, $node) = @_;
+
+ _num_arg ($node, 2, 'define');
+
+ my ($symbol, $value);
+
+ if (exists _get_arg($node,1)->{children}) {
+ my @formals;
+ ($symbol, @formals) = @{_get_arg($node,1)->{children}};
+ $symbol = $symbol->{value};
+ my $lambda = { children => [ { value => 'lambda' },
+ { children => [ @formals ] },
+ _get_args ($node, 2) ] };
+ $value = $self->_generate($lambda);
+ }
+ else {
+ $symbol = _get_arg($node,1)->{value};
+ $value = $self->_generate (_get_arg($node,2));
+ }
+
+ if (exists $self->{scope}->{$symbol}) {
+ die "define: $symbol is already defined\n";
+ }
+
+ if ($value !~ /^P/) {
+ my $pmc = $self->_save_1 ('P');
+ $self->_morph ($pmc, $value);
+ $self->_restore ($value);
+ $value = $pmc;
+ }
+
+ $self->{scope}->{$symbol} = 1;
+ $self->_new_lex ($symbol,$value);
+
+ return $value;
+}
+
sub _op_set_bang {
+ my ($self, $node) = @_;
+
+ _num_arg ($node, 2, 'set!');
+
+ my $symbol = _get_arg ($node, 1)->{value};
+ my $temp = $self->_generate(_get_arg($node,2));
+ if ($temp !~ /^P/) {
+ my $pmc = $self->_save_1 ('P');
+ $self->_morph ($pmc, $temp);
+ $self->_restore ($temp);
+ $temp = $pmc;
+ }
+ $self->_store_lex ($symbol,$temp);
+
+ return $temp;
}
sub _op_cond {
@@ -139,10 +372,10 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- for(@{$node->{children}}) {
+ for(_get_args($node)) {
my $temp = $self->_generate($_);
$self->_add_inst('' ,'eq' ,[$temp,0,"DONE_$label"]);
- _restore($temp);
+ $self->_restore($temp);
}
$self->_add_inst('' ,'set',[$return,1]);
$self->_add_inst("DONE_$label");
@@ -155,10 +388,10 @@
my $label = $self->_gensym();
$return = $self->_constant(1);
- for(@{$node->{children}}) {
+ for(_get_args($node)) {
my $temp = $self->_generate($_);
$self->_add_inst('' ,'eq' ,[$temp,1,"DONE_$label"]);
- _restore($temp);
+ $self->_restore($temp);
}
$self->_add_inst('' ,'set',[$return,0]);
$self->_add_inst("DONE_$label");
@@ -166,6 +399,28 @@
}
sub _op_let {
+ my ($self, $node) = @_;
+ my $return;
+
+ my ($locals, @body) = _get_args ($node,1);
+ my (@variables, @values);
+ for (@{$locals->{children}}) {
+ _num_arg ($_, 1, 'let locals');
+ my ($var, $val) = _get_args ($_, 0);
+ push @variables, $var;
+ push @values, $val;
+ }
+
+ my $let = { children => [
+ { children => [ { value => 'lambda' },
+ { children => [ @variables ] },
+ @body ]},
+ @values
+ ]};
+
+ $return = $self->_generate($let);
+
+ return $return;
}
sub _op_let_star {
@@ -175,6 +430,16 @@
}
sub _op_begin {
+ my ($self, $node) = @_;
+ my $temp = 'none';
+
+ my @args = _get_args ($node);
+
+ for (@args) {
+ $self->_restore ($temp);
+ $temp = $self->_generate ($_);
+ }
+ return $temp;
}
sub _op_do {
@@ -189,13 +454,13 @@
#---- Section 6 ----
sub _op_not {
- my ($self,$node,$return) = @_;
+ my ($self,$node) = @_;
- my @temp = _save(1);
- $self->_generate($node->{children}[0],$temp[0]);
- $self->_add_inst('','not',[$temp[0],$temp[0]]);
- $self->_add_inst('','and',[$return,$temp[0],1]);
- _restore(@temp);
+ my $return = $self->_save_1 ('I');
+ $self->_generate(_get_arg($node,1));
+ $self->_add_inst('','not',[$return,$return]);
+
+ $return;
}
sub _op_boolean_p {
@@ -217,9 +482,9 @@
_num_arg ($node, 1, 'pair?');
- my $item = $self->_generate($node->{children}->[0]);
+ my $item = $self->_generate(_get_arg($node,1));
- $return = _save_1 ('I');
+ $return = $self->_save_1 ('I');
if ($item =~ /^[INS]/) {
$self->_add_inst ('', 'set', [$return,0]);
@@ -244,17 +509,17 @@
_num_arg ($node, 2, 'cons');
- my $car = $self->_generate($node->{children}->[0]);
- $return = _save_1('P');
+ my $car = $self->_generate(_get_arg($node,1));
+ $return = $self->_save_1('P');
$self->_add_inst ('', 'new', [$return,'.Array']);
$self->_add_inst ('', 'set', [$return,2]);
$self->_add_inst ('', 'set', [$return.'[0]',$car]);
- _restore ($car);
+ $self->_restore ($car);
- my $cdr = $self->_generate($node->{children}->[1]);
+ my $cdr = $self->_generate(_get_arg($node,2));
$self->_add_inst ('', 'set', [$return.'[1]', $cdr]);
- _restore ($cdr);
+ $self->_restore ($cdr);
return $return;
}
@@ -264,7 +529,7 @@
_num_arg ($node, 1, 'car');
- my $return = $self->_generate ($node->{children}->[0]);
+ my $return = $self->_generate (_get_arg($node,1));
die "car: Element not pair\n" unless $return =~ /^P/;
$self->_add_inst ('', 'set', [$return,$return.'[0]']);
@@ -276,7 +541,7 @@
_num_arg ($node, 1, 'cdr');
- my $return = $self->_generate ($node->{children}->[0]);
+ my $return = $self->_generate (_get_arg($node,1));
die "cdr: Element not pair\n" unless $return =~ /^P/;
$self->_add_inst ('', 'set', [$return,$return.'[1]']);
@@ -288,11 +553,11 @@
_num_arg ($node, 2, 'set-car!');
- my $return = $self->_generate ($node->{children}->[0]);
+ my $return = $self->_generate (_get_arg($node,1));
die "set-car!: Element not pair\n" unless $return =~ /^P/;
- my $value = $self->_generate ($node->{children}->[1]);
+ my $value = $self->_generate (_get_arg($node,2));
$self->_add_inst ('', 'set', [$return.'[0]',$value]);
- _restore ($value);
+ $self->_restore ($value);
return $return;
}
@@ -302,16 +567,32 @@
_num_arg ($node, 2, 'set-cdr!');
- my $return = $self->_generate ($node->{children}->[0]);
+ my $return = $self->_generate (_get_arg($node,1));
die "set-cdr!: Element not pair\n" unless $return =~ /^P/;
- my $value = $self->_generate ($node->{children}->[1]);
+ my $value = $self->_generate (_get_arg($node,2));
$self->_add_inst ('', 'set', [$return.'[1]',$value]);
- _restore ($value);
+ $self->_restore ($value);
return $return;
}
-sub _op_null {
+sub _op_null_p {
+ my ($self, $node) = @_;
+ my $return = $self->_save_1 ('I');
+ my $label = $self->_gensym();
+
+ _num_arg ($node, 1, 'null?');
+
+ my $temp = $self->_generate(_get_arg($node,1));
+ $self->_add_inst ('', 'typeof',[$return,$temp]);
+ $self->_add_inst ('', 'ne', [$return,'.PerlUndef',"FAIL_$label"]);
+ $self->_add_inst ('', 'set', [$return,1]);
+ $self->_add_inst ('', 'branch', ["DONE_$label"]);
+ $self->_add_inst ("FAIL_$label", 'set', [$return,0]);
+ $self->_add_inst ("DONE_$label");
+ $self->_restore ($temp);
+
+ return $return;
}
sub _op_list_p {
@@ -320,15 +601,15 @@
sub _op_list {
my ($self, $node) = @_;
my $label = $self->_gensym ();
- my $return = _save_1 ('P');
+ my $return = $self->_save_1 ('P');
$self->_add_inst ('', 'new',[$return,'.PerlUndef']);
- return $return unless exists $node->{children};
+ my @reverse = reverse _get_args($node);
- for (reverse @{$node->{children}}) {
+ for (@reverse) {
my $item = $self->_generate($_);
- my $pair = _save_1 ('P');
+ my $pair = $self->_save_1 ('P');
$self->_add_inst ('', 'new',[$pair,'.Array']);
$self->_add_inst ('', 'set',[$pair,2]);
@@ -336,7 +617,7 @@
$self->_add_inst ('', 'set',[$pair.'[1]',$return]);
$self->_add_inst ('', 'set',[$return,$pair]);
- _restore($item, $pair);
+ $self->_restore($item, $pair);
}
return $return;
@@ -345,14 +626,14 @@
sub _op_length {
my ($self, $node) = @_;
my $label = $self->_gensym ();
- my $return = _save_1 ('I');
+ my $return = $self->_save_1 ('I');
_num_arg ($node, 1, 'length');
- my $list = $self->_generate($node->{children}->[0]);
+ my $list = $self->_generate(_get_arg($node,1));
$self->_add_inst ('', 'set',[$return,'0']);
- my $type = _save_1 ('I');
+ my $type = $self->_save_1 ('I');
$self->_add_inst ("NEXT_$label", 'typeof',[$type,$list]);
$self->_add_inst ('', 'eq',[$type,'.PerlUndef', "DONE_$label"]);
$self->_add_inst ('', 'ne',[$type,'.Array', "ERR_$label"]);
@@ -430,15 +711,21 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my $temp_0 = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp_1 = $self->_generate($node->{children}[1]);
- $self->_add_inst('','ne',[$temp_0,$temp_1,"DONE_$label"]);
- _restore($temp_1);
+ my $temp_0 = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
+ my $temp_1 = $self->_generate($node->{children}[$_]);
+ if (substr ($temp_0, 0, 1) ne substr ($temp_1, 0, 1)) {
+ my $temp_2 = $self->_save_1(substr ($temp_0, 0, 1));
+ $self->_morph($temp_2, $temp_1);
+ $self->_restore ($temp_1);
+ $temp_1 = $temp_2;
+ }
+ $self->_add_inst ('', 'ne', [$temp_0,$temp_1,"DONE_$label"]);
+ $self->_restore($temp_1);
}
$self->_add_inst('','set',[$return,1]);
$self->_add_inst("DONE_$label");
- _restore($temp_0);
+ $self->_restore($temp_0);
return $return;
}
@@ -448,15 +735,15 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my $temp_0 = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp_1 = $self->_generate($node->{children}[1]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
+ my $temp_1 = $self->_generate($node->{children}[$_]);
$self->_add_inst('','ge',[$temp_0,$temp_1,"DONE_$label"]);
- _restore($temp_1);
+ $self->_restore($temp_1);
}
$self->_add_inst('','set',[$return,1]);
$self->_add_inst("DONE_$label");
- _restore($temp_0);
+ $self->_restore($temp_0);
return $return;
}
@@ -466,15 +753,15 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my $temp_0 = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp_1 = $self->_generate($node->{children}[1]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
+ my $temp_1 = $self->_generate($node->{children}[$_]);
$self->_add_inst('','le',[$temp_0,$temp_1,"DONE_$label"]);
- _restore($temp_1);
+ $self->_restore($temp_1);
}
$self->_add_inst('','set',[$return,1]);
$self->_add_inst("DONE_$label");
- _restore($temp_0);
+ $self->_restore($temp_0);
return $return;
}
@@ -484,15 +771,15 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my $temp_0 = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp_1 = $self->_generate($node->{children}[1]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
+ my $temp_1 = $self->_generate($node->{children}[$_]);
$self->_add_inst('','gt',[$temp_0,$temp_1,"DONE_$label"]);
- _restore($temp_1);
+ $self->_restore($temp_1);
}
$self->_add_inst('','set',[$return,1]);
$self->_add_inst("DONE_$label");
- _restore($temp_0);
+ $self->_restore($temp_0);
return $return;
}
@@ -502,15 +789,15 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my $temp_0 = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp_1 = $self->_generate($node->{children}[1]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
+ my $temp_1 = $self->_generate($node->{children}[$1]);
$self->_add_inst('','lt',[$temp_0,$temp_1,"DONE_$label"]);
- _restore($temp_1);
+ $self->_restore($temp_1);
}
$self->_add_inst('','set',[$return,1]);
$self->_add_inst("DONE_$label");
- _restore($temp_0);
+ $self->_restore($temp_0);
return $return;
}
@@ -520,12 +807,11 @@
my $label = $self->_gensym();
$return = $self->_constant(0);
- my @temp = _save(1);
$self->_add_inst('' ,'set' ,[$return,1]);
- my $temp = $self->_generate($node->{children}[0]);
+ my $temp = $self->_generate($node->{children}[1]);
$self->_add_inst('' ,'eq' ,[$temp,0,"DONE_$label"]);
- _restore($temp);
+ $self->_restore($temp);
$self->_add_inst('' ,'set' ,[$return,0]);
$self->_add_inst("DONE_$label");
return $return;
@@ -537,9 +823,9 @@
my $label = $self->_gensym();
$return = $self->_constant(1);
- my $temp = $self->_generate($node->{children}[0]);
+ my $temp = $self->_generate($node->{children}[1]);
$self->_add_inst('' ,'gt' ,[$temp,0,"DONE_$label"]);
- _restore($temp);
+ $self->_restore($temp);
$self->_add_inst('' ,'set' ,[$return,0]);
$self->_add_inst("DONE_$label");
return $return;
@@ -551,9 +837,9 @@
my $label = $self->_gensym();
$return = $self->_constant(1);
- my $temp = $self->_generate($node->{children}[0]);
+ my $temp = $self->_generate($node->{children}[1]);
$self->_add_inst('' ,'lt' ,[$temp,0,"DONE_$label"]);
- _restore($temp);
+ $self->_restore($temp);
$self->_add_inst('' ,'set' ,[$return,0]);
$self->_add_inst("DONE_$label");
return $return;
@@ -564,14 +850,14 @@
my $return;
my $label = $self->_gensym();
- my $temp_0 = $self->_generate($node->{children}[0]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
$return = $self->_constant(1);
my $temp_1 = $self->_constant(2);
$self->_add_inst('' ,'mod' ,[$temp_0,$temp_0,$temp_1]);
$self->_add_inst('' ,'eq' ,[$temp_0,1,"DONE_$label"]);
$self->_add_inst('' ,'set' ,[$return,0]);
$self->_add_inst("DONE_$label");
- _restore($temp_0,$temp_1);
+ $self->_restore($temp_0,$temp_1);
return $return;
}
@@ -580,14 +866,14 @@
my $return;
my $label = $self->_gensym();
- my $temp_0 = $self->_generate($node->{children}[0]);
+ my $temp_0 = $self->_generate($node->{children}[1]);
$return = $self->_constant(1);
my $temp_1 = $self->_constant(2);
$self->_add_inst('' ,'mod' ,[$temp_0,$temp_0,$temp_1]);
$self->_add_inst('' ,'eq' ,[$temp_0,0,"DONE_$label"]);
$self->_add_inst('' ,'set' ,[$return,0]);
$self->_add_inst("DONE_$label");
- _restore($temp_0,$temp_1);
+ $self->_restore($temp_0,$temp_1);
return $return;
}
@@ -596,14 +882,14 @@
my $return;
my $label = $self->_gensym();
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
+ $return = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
my $temp = $self->_generate($node->{children}[$_]);
my $label = $self->_gensym();
$self->_add_inst('','gt', [$return,$temp,"NEXT_$label"]);
$self->_add_inst('','set',[$return,$temp]);
$self->_add_inst("NEXT_$label");
- _restore($temp);
+ $self->_restore($temp);
}
return $return;
}
@@ -613,14 +899,14 @@
my $return;
my $label = $self->_gensym();
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
+ $return = $self->_generate($node->{children}[1]);
+ for(2..$#{$node->{children}}) {
my $temp = $self->_generate($node->{children}[$_]);
my $label = $self->_gensym();
$self->_add_inst('','lt', [$return,$temp,"NEXT_$label"]);
$self->_add_inst('','set',[$return,$temp]);
$self->_add_inst("NEXT_$label");
- _restore($temp);
+ $self->_restore($temp);
}
return $return;
}
@@ -628,17 +914,29 @@
sub _op_plus {
my ($self,$node) = @_;
my $return;
- my $num_children = defined $node->{children} ? @{$node->{children}} : 0;
+ my $num_children = defined $node->{children} ? @{$node->{children}} - 1 : 0;
if($num_children==0) {
$return = $self->_constant(0);
} elsif($num_children==1) {
- $return = $self->_generate($node->{children}[0]);
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
} else {
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
+ for(2..$#{$node->{children}}) {
my $temp = $self->_generate($node->{children}[$_]);
$self->_add_inst('','add',[$return,$return,$temp]);
- _restore($temp);
+ $self->_restore($temp);
}
}
return $return;
@@ -647,22 +945,34 @@
sub _op_minus {
my ($self,$node) = @_;
my $return;
- my $num_children = defined $node->{children} ? @{$node->{children}} : 0;
+ my $num_children = defined $node->{children} ? @{$node->{children}} - 1 : 0;
if($num_children==0) {
$return = $self->_constant(0);
} elsif($num_children==1) {
- $return = $self->_generate($node->{children}[0]);
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
my $temp = $self->_constant(0);
$self->_add_inst('','sub',[$return,$temp,$return]);
- _restore($temp);
+ $self->_restore($temp);
} else {
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
- my $temp = $self->_generate($node->{children}[$_]);
- $self->_add_inst('','sub',[$return,$return,$temp]);
- _restore($temp);
- }
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
+ for(2..$#{$node->{children}}) {
+ my $temp = $self->_generate($node->{children}[$_]);
+ $self->_add_inst('','sub',[$return,$return,$temp]);
+ $self->_restore($temp);
+ }
}
return $return;
}
@@ -670,18 +980,30 @@
sub _op_times {
my ($self,$node) = @_;
my $return;
- my $num_children = defined $node->{children} ? @{$node->{children}} : 0;
+ my $num_children = defined $node->{children} ? @{$node->{children}} - 1: 0;
if($num_children==0) {
$return = $self->_constant(0);
} elsif($num_children==1) {
- $return = $self->_generate($node->{children}[0]);
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
} else {
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
+ for(2..$#{$node->{children}}) {
my $temp = $self->_generate($node->{children}[$_]);
$self->_add_inst('','mul',[$return,$return,$temp]);
- _restore($temp);
+ $self->_restore($temp);
}
}
return $return;
@@ -690,21 +1012,33 @@
sub _op_divide {
my ($self,$node) = @_;
my $return;
- my $num_children = defined $node->{children} ? @{$node->{children}} : 0;
+ my $num_children = defined $node->{children} ? @{$node->{children}} - 1 : 0;
if($num_children==0) {
$return = $self->_constant(0);
} elsif($num_children==1) {
- $return = $self->_generate($node->{children}[0]);
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
my $temp = $self->_constant(1);
$self->_add_inst('','div',[$return,$temp,$return]);
- _restore($temp);
+ $self->_restore($temp);
} else {
- $return = $self->_generate($node->{children}[0]);
- for(1..$#{$node->{children}}) {
+ $return = $self->_generate($node->{children}[1]);
+ if ($return =~ /^P/) {
+ my $temp = $self->_save_1 ('P');
+ $self->_morph ($temp, $return);
+ $self->_restore ($return);
+ $return = $temp;
+ }
+ for(2..$#{$node->{children}}) {
my $temp = $self->_generate($node->{children}[$_]);
$self->_add_inst('','div',[$return,$return,$temp]);
- _restore($temp);
+ $self->_restore($temp);
}
}
return $return;
@@ -715,11 +1049,11 @@
my $return;
my $label = $self->_gensym();
- $return = $self->_generate($node->{children}[0]);
+ $return = $self->_generate($node->{children}[1]);
$self->_add_inst('', 'gt', [$return,0,"DONE_$label"]);
my $temp = $self->_constant(-1);
$self->_add_inst('', 'mul',[$return,$return,$temp]);
- _restore($temp);
+ $self->_restore($temp);
$self->_add_inst("DONE_$label");
return $return;
}
@@ -974,9 +1308,41 @@
}
sub _op_procedure_p {
+ my ($self, $node) = @_;
+ my $return;
+
+ _check_num_arg ($node, 1, 'procedure?');
+
+ $return = self->_constant(0);
+
+ my $temp = $self->_generate(_get_arg($node,1));
+ if ($temp =~ /^P/) {
+ }
+
+ return $return;
}
sub _op_apply {
+ my ($self, $node) = @_;
+ my $return;
+
+ my $func = $self->_generate(_get_arg ($node, 1));
+ my @args = _get_args ($node, 2);
+ die "apply: wrong number of args\n" unless @args;
+
+ my $argl = $self->_generate(pop @args);
+ while (@args) {
+ my $elem = $self->_generate(pop @args);
+ my $pair = _save_1('P');
+ $self->_add_inst ('','new',[$pair,'.Array']);
+ $self->_add_inst ('','set',[$pair,2]);
+ $self->_add_inst ('','set',[$pair.'[0]',$elem]);
+ $self->_add_inst ('','set',[$pair.'[1]',$argl]);
+ }
+
+ $return = $self->_call_function ('apply');
+
+ return $return;
}
sub _op_map {
@@ -1044,24 +1410,19 @@
sub _op_write {
my ($self,$node) = @_;
- for(@{$node->{children}}) {
- my $temp = $self->_generate($_);
+ my $temp = 'none';
+
+ for(_get_args($node)) {
+ $self->_restore ($temp);
+ $temp = $self->_generate($_);
if ($temp =~ /[INS]/) {
$self->_add_inst('','print',[$temp]);
}
else {
- $self->_use_function ('write');
- if ($temp ne 'P5') {
- $self->_add_inst('', 'save', ['P5']) if $regs->{P}{5};
- $self->_add_inst('', 'set', ['P5',$temp]);
- }
- $self->_add_inst('', 'bsr', ['write_ENTRY']);
- if ($temp ne 'P5' && $regs->{P}{5}) {
- $self->_add_inst('', 'restore', ['P5']);
- }
+ $self->_call_function ('write',$temp);
}
- _restore($temp);
}
+ return $temp; # We need to return something
}
sub _op_display {
@@ -1122,8 +1483,6 @@
my %global_ops = (
- 'CONSTANT' => \&_op_constant,
-
#----------------------
#
# Section 4 Expressions
@@ -1133,6 +1492,7 @@
'quote' => \&_op_quote,
'lambda' => \&_op_lambda,
'if' => \&_op_if,
+ 'define' => \&_op_define,
'set!' => \&_op_set_bang,
'cond' => \&_op_cond,
'case' => \&_op_case,
@@ -1420,11 +1780,47 @@
@max_len;
}
-sub _use_function {
- my ($self, $name) = @_;
+sub _call_function {
+ my $self = shift;
+ my $func = shift;
+
+ push @{$self->{functions}}, $func
+ unless grep { $_ eq $func } @{$self->{functions}};
+
+ my $return = $self->_save_1 ('P');
+ $self->_restore ($return); # dont need to save this
+
+ $self->_save_set;
+
+ my $count = 5;
+ my $empty = $return;
+ while (my $arg = shift) {
+ if ($arg ne "P$count") {
+ # Check if any later argument needs the old value of P$count
+ my $moved;
+ for (@_) {
+ if ($_ eq "P$count") {
+ $moved = $_;
+ $_ = $empty;
+ }
+ }
+ if ($moved) {
+ $self->_add_inst ('', 'set',[$empty,"P$count"]);
+ $empty = $moved;
+ }
+ $self->_add_inst ('','set',["P$count",$arg]);
+ }
+ $count++;
+ }
+
+ $self->_add_inst ('', 'bsr', [$func.'_ENTRY']);
+ $self->_add_inst ('', 'set', [$return,'P5']) unless $return eq 'P5';
+ $self->_restore_set;
+
+ $return =~ /(\w)(\d+)/;
+ $self->{regs}->{$1}->{$2} = 1;
- push @{$self->{functions}}, $name
- unless grep { $_ eq $name } @{$self->{functitons}};
+ return $return;
}
sub _format_columns {
@@ -1451,7 +1847,8 @@
my $tree = shift;
my $self = {
tree => $tree,
- register => [(0) x 32],
+ regs => _new_regs,
+ frames => [],
gensym => 0,
functions=> [],
};
@@ -1475,15 +1872,37 @@
my ($self,$node) = @_;
my $return;
- if($node->{value} =~ /\d/) {
- $return = $global_ops{CONSTANT}->($self,$node);
+ if (exists $node->{children}) {
+ my $func = _get_arg ($node, 0);
+ if (exists $func->{value}) {
+ my $symbol = $func->{value};
+ if (exists $global_ops{$symbol}) {
+ $return = $global_ops{$symbol}->($self, $node);
+ } else {
+ my $func_obj = $self->_find_lex ($symbol);
+ my $argl = $self->_op_list ($node);
+ $return = $self->_call_function('apply', $func_obj, $argl);
+ $self->_restore ($func_obj, $argl);
+ }
+ } else {
+ my $func_obj = $self->_generate ($func);
+ my $argl = $self->_op_list ($node);
+ $return = $self->_call_function('apply', $func_obj, $argl);
+ $self->_restore ($func_obj, $argl);
+ }
} else {
- $return = $global_ops{$node->{value}}->($self,$node);
+ my $value = $node->{value};
+ if ($value =~ /^[a-zA-Z]/) {
+ $return = $self->_find_lex($value);
+ }
+ else {
+ $return = $self->_constant($node->{value});
+ }
}
- $return;
+ return $return;
}
-sub _link_buildins {
+sub _link_builtins {
my ($self) = @_;
for (@{$self->{functions}}) {
@@ -1493,12 +1912,18 @@
sub generate {
my $self = shift;
- my @temp = _save(1);
- $self->_generate($self->{tree},$temp[0]);
+ my $temp;
+
+ $self->{scope} = {};
+ $self->_add_inst ('', 'new_pad',[0]);
+
+ $temp = $self->_generate($self->{tree});
+
+ $self->_add_inst ('', 'pop_pad');
#die Dumper($self->{tree});
- _restore(@temp);
+ $self->_restore($temp);
$self->_add_inst('',"end");
- $self->_link_buildins();
+ $self->_link_builtins();
$self->_format_columns();
}
Index: languages/scheme/Scheme/Parser.pm
===================================================================
RCS file: /cvs/public/parrot/languages/scheme/Scheme/Parser.pm,v
retrieving revision 1.2
diff -u -r1.2 Parser.pm
--- languages/scheme/Scheme/Parser.pm 24 Mar 2002 23:42:38 -0000 1.2
+++ languages/scheme/Scheme/Parser.pm 13 Nov 2002 21:36:25 -0000
@@ -9,27 +9,34 @@
use Data::Dumper;
+my $ind = 0;
sub _build_tree {
my ($tokens,$count) = @_;
my $temp = {};
- $count++;
+ die "EOF reached" if $count >= $#$tokens;
- while($tokens->[$count] ne ')') {
- if($tokens->[$count] eq '(') {
- my ($lcount,$ltemp) = _build_tree($tokens,$count);
- $count = $lcount;
- push @{$temp->{children}},$ltemp;
- } else {
- if(exists $temp->{value} or exists $temp->{children}) {
- push @{$temp->{children}},{value=>$tokens->[$count]};
- } else {
- $temp->{value} = $tokens->[$count];
- }
+ if ($tokens->[$count] eq '(') {
+ $temp->{children} = [];
+ $count++;
+ while($tokens->[$count] ne ')') {
+ my $expr;
+ ($count, $expr) = _build_tree ($tokens, $count);
+ push @{$temp->{children}}, $expr;
}
$count++;
}
-
+ elsif ($tokens->[$count] eq "'") {
+ $temp = { children => [{ value => 'quote' }] };
+ my $expr;
+ $count++;
+ ($count, $expr) = _build_tree ($tokens, $count);
+ push @{$temp->{children}}, $expr;
+ }
+ else {
+ $temp->{value} = $tokens->[$count++];
+ }
+
return ($count,$temp);
}
@@ -57,9 +64,23 @@
sub parse {
my $tokens = shift;
- my (undef,$tree) = _build_tree($tokens,0);
- _dataflow($tree);
+ my @tree;
+ my $tree;
+ my $count = 0;
+
+ while ($count < scalar @$tokens) {
+ #print Dumper $tokens;
+ ($count,$tree) = _build_tree($tokens,$count);
+ #_dataflow($tree);
+ #print Data::Dumper->Dump ([$count, $tree]);
+ push @tree, $tree;
+ }
+
+ # Implicit begin at toplevel
+ if (@tree > 1) {
+ $tree = { children => [ { value => 'begin' }, @tree ] };
+ }
return $tree;
}
Index: languages/scheme/Scheme/Tokenizer.pm
===================================================================
RCS file: /cvs/public/parrot/languages/scheme/Scheme/Tokenizer.pm,v
retrieving revision 1.3
diff -u -r1.3 Tokenizer.pm
--- languages/scheme/Scheme/Tokenizer.pm 5 Sep 2002 15:03:55 -0000 1.3
+++ languages/scheme/Scheme/Tokenizer.pm 13 Nov 2002 21:36:25 -0000
@@ -18,6 +18,7 @@
open SOURCE,"<$file";
while(<SOURCE>) {
next if /^\s*;/;
+ s/;.*$//;
$text .= $_;
}
close SOURCE;
Index: languages/scheme/t/logic/defines.t
===================================================================
RCS file: languages/scheme/t/logic/defines.t
diff -N languages/scheme/t/logic/defines.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ languages/scheme/t/logic/defines.t 13 Nov 2002 21:36:26 -0000
@@ -0,0 +1,100 @@
+#! perl -w
+
+use Scheme::Test tests => 12;
+
+output_is (<<'CODE', 'a', 'a symbol');
+(write 'a) ; for emacs ')
+CODE
+
+output_is (<<'CODE', '5', 'define');
+(define a 5)
+(write a)
+CODE
+
+output_is (<<'CODE', '5', 'define II');
+(define a 4)
+(define b (+ a 1))
+(write b)
+CODE
+
+output_is (<<'CODE', '8', 'set!');
+(define a 5)
+(set! a 8)
+(write a)
+CODE
+
+output_is (<<'CODE', '13', 'set! II');
+(define a 5)
+(set! a (+ a 8))
+(write a)
+CODE
+
+output_is (<<'CODE', '(2 1)', 'define function');
+(define (f a b) (list b a))
+(write (f 1 2))
+CODE
+
+output_is (<<'CODE', '3', 'define via lambda');
+(define sum (lambda (a b) (+ a b)))
+(write (sum 1 2))
+CODE
+
+output_is (<<'CODE', '101', 'let');
+(let ((a 1))
+ (write a)
+ (let ((a 0)
+ (b 0))
+ (write a))
+ (write a))
+CODE
+
+output_is (<<'CODE', '321', 'counter');
+(define (make-counter val)
+ (lambda ()
+ (set! val (- val 1))
+ val)
+)
+(define counter (make-counter 4))
+(write (counter))
+(write (counter))
+(write (counter))
+CODE
+
+output_is (<<'CODE', '9837', '2 counter');
+(define (make-counter val)
+ (lambda ()
+ (set! val (- val 1))
+ val)
+)
+(define ci (make-counter 10))
+(write (ci))
+(define cii (make-counter 4))
+(write (ci))
+(write (cii))
+(write (ci))
+CODE
+
+output_is (<<'CODE', '012023', 'yet another counter');
+(define (make-counter incr)
+ (let ((val 0))
+ (lambda ()
+ (let ((ret val))
+ (set! val (+ incr val))
+ ret))))
+(define ci (make-counter 1))
+(write (ci))
+(write (ci))
+(define cii (make-counter 2))
+(write (ci))
+(write (cii))
+(write (cii))
+(write (ci))
+CODE
+
+output_is (<<'CODE','120','fakultaet');
+(define (fak n)
+ (if (= n 0)
+ 1
+ (* n (fak (- n 1)))))
+(write (fak 5))
+CODE
Index: languages/scheme/t/logic/lists.t
===================================================================
RCS file: /cvs/public/parrot/languages/scheme/t/logic/lists.t,v
retrieving revision 1.1
diff -u -r1.1 lists.t
--- languages/scheme/t/logic/lists.t 5 Sep 2002 19:55:13 -0000 1.1
+++ languages/scheme/t/logic/lists.t 13 Nov 2002 21:36:26 -0000
@@ -1,10 +1,6 @@
#! perl -w
-use Scheme::Test tests => 15;
-
-###
-### Add
-###
+use Scheme::Test tests => 21;
output_is(<<'CODE', '(2 . 5)', 'cons');
(write (cons 2 5))
@@ -81,4 +77,32 @@
output_is(<<'CODE', '(1 4 2)', 'set-cdr!');
(write
(set-cdr! (list 1 2 3) (list 4 2)))
+CODE
+
+output_is(<<'CODE', '(1 2 3 4)', 'quoted list');
+(write '(1 2 3 4)) ; for emacs ')
+CODE
+
+output_is(<<'CODE', '1', 'null?');
+(write
+ (null? (list)))
+CODE
+
+output_is (<<'CODE', '()', "'()");
+(write '()) ; for emacs ')
+CODE
+
+output_is (<<'CODE', '0', 'failed null?');
+(write
+ (null? (list 1)))
+CODE
+
+output_is (<<'CODE', '(1 2 (3 4))', 'complex list');
+(write
+ '(1 2 (3 4))) ; for emacs ')
+CODE
+
+output_is (<<'CODE', '(1 2 (3 4))', 'complex list II');
+(write
+ (list 1 2 (list 3 4)))
CODE
--- sub.c.orig
+++ sub.c Thu Nov 7 23:15:06 2002
@@ -139,7 +139,13 @@
PMC * pad_pmc = pmc_new(interp, enum_class_Scratchpad);
pad_pmc->cache.int_val = 0;
- if ((base && depth > base->cache.int_val) || (!base && depth != 0)) {
+ if (base && depth < 0) {
+ depth = base->cache.int_val + depth + 1;
+ }
+
+ if ((depth < 0)
+ || (base && depth > base->cache.int_val)
+ || (!base && depth != 0)) {
internal_exception(-1, "-scratch_pad: too deep\n");
return NULL;
}