# New Ticket Created by  Jürgen Bömmels 
# Please include the string:  [perl #17109]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=17109 >


Hi,

the next patch to languages/scheme. It implements the quote and a
first cut of define and set!. They work only for values at the Moment,
functions are next.

In order to get quote working I had to change the Parser in a
fundamentel way: The tree now monitors exaktly the structure of the
parens, and not special-casing the first argument. I think this is
also neccessary to get things like ((if (= 1 0) + -) 1 2) running.
It leads to an off by one in the node children, but thats rather
trivial to fix. Anyway all tests pass.

define and set! use find_lex and store_lex to read and store its
values. As there are no functions ATM they only work for values.

bye
b.



-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/37055/29973/418c30/scheme.diff

Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.216
diff -u -r1.216 MANIFEST
--- MANIFEST	9 Sep 2002 07:21:48 -0000	1.216
+++ MANIFEST	9 Sep 2002 22:48:14 -0000
@@ -514,6 +514,7 @@
 languages/scheme/t/harness
 languages/scheme/t/io/basic.t
 languages/scheme/t/logic/basic.t
+languages/scheme/t/logic/defines.t
 languages/scheme/t/logic/lists.t
 lib/Class/Struct.pm
 lib/Make.pm
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	9 Sep 2002 22:48:15 -0000
@@ -60,10 +60,25 @@
 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 $children).\n"
-    if ($children != $expected);
+  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;
+
+  my @args = @{$node->{children}};
+  splice @args, 0, $num;
+
+  return @args;
 }
 
 #------------------------------------
@@ -78,26 +93,90 @@
 
 #------------------------------------
 
-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 = _save_1 ('I');
+    $self->_add_inst ('', 'set', [$return,$value]);
+  }
+  elsif ($value =~ /^[-+]?((\d+\.\d*)|(\.d+))([eE][-+]?\d+)?$/) {
+    $return = _save_1 ('N');
+    $self->_add_inst ('', 'set', [$return,$value]);
+  }
+  else {
+    $return = _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 = _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 = _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]);
+      _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 {
@@ -108,23 +187,73 @@
   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]);
+  _restore($cond);
+  $return = _save_1 ('P');
+
+  my $true = $self->_generate(_get_arg($node,2));
+  $self->_morph($return,$true);
   $self->_add_inst('','branch',["DONE_$label"]);
-  $self->_add_inst("FALSE_$label");
   _restore($true);
-  _restore($cond);
-  my $false = $self->_generate($node->{children}[2]);
-  $self->_add_inst('','set',[$return,$false]);
+
+  $self->_add_inst("FALSE_$label");
+  my $false = $self->_generate(_get_arg($node,3));
+  $self->_morph($return,$false);
   _restore($false);
+
   $self->_add_inst("DONE_$label");
   return $return;
 }
 
+sub _op_define {
+  my ($self, $node) = @_;
+
+  _num_arg ($node, 2, 'define');
+
+  if (!exists _get_arg($node,1)->{value}) {
+    die "define: function defines not yet implemented";
+  }
+  my $symbol = _get_arg($node,1)->{value};
+
+  if (exists $self->{scope}->{$symbol}) {
+    die "define: $symbol is already defined\n";
+  }
+
+  my $temp = $self->_generate (_get_arg($node,2));
+
+  if ($temp !~ /^P/) {
+    my $pmc = _save_1 ('P');
+    $self->_morph ($pmc, $temp);
+    _restore ($temp);
+    $temp = $pmc;
+  }
+
+  $self->{scope}->{$symbol} = 1;
+  $self->_add_inst ('', 'store_lex', ["\"$symbol\"",$temp]);
+
+  return $temp;
+}
+
 sub _op_set_bang {
+  my ($self, $node) = @_;
+
+  _num_arg ($node, 2, 'set!');
+
+  my $symbol = _get_arg ($node, 1)->{value};
+  if (!exists $self->{scope}->{$symbol}) {
+    die "set!: $symbol not in current scope!";
+  }
+  my $temp = $self->_generate(_get_arg($node,2));
+  if ($temp !~ /^P/) {
+    my $pmc = _save_1 ('P');
+    $self->_morph ($pmc, $temp);
+    _restore ($temp);
+    $temp = $pmc;
+  }
+  $self->_add_inst ('', 'store_lex', ["\"$symbol\"",$temp]);
+  
+  return $temp;
 }
 
 sub _op_cond {
@@ -139,7 +268,7 @@
   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);
@@ -155,7 +284,7 @@
   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);
@@ -175,6 +304,16 @@
 }
 
 sub _op_begin {
+  my ($self, $node) = @_;
+  my $temp = _save_1('I');
+
+  my @args = _get_args ($node);
+
+  for (@args) {
+    _restore ($temp);
+    $temp = $self->_generate ($_);
+  }
+  return $temp;
 }
 
 sub _op_do {
@@ -189,13 +328,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 = _save_1 ('I');
+  $self->_generate(_get_arg($node,1));
+  $self->_add_inst('','not',[$return,$return]);
+  
+  $return;
 }
 
 sub _op_boolean_p {
@@ -217,7 +356,7 @@
 
   _num_arg ($node, 1, 'pair?');
 
-  my $item = $self->_generate($node->{children}->[0]);
+  my $item = $self->_generate(_get_arg($node,1));
 
   $return = _save_1 ('I');
 
@@ -244,7 +383,7 @@
 
   _num_arg ($node, 2, 'cons');
   
-  my $car = $self->_generate($node->{children}->[0]);
+  my $car = $self->_generate(_get_arg($node,1));
   $return = _save_1('P');
 
   $self->_add_inst ('', 'new', [$return,'.Array']);
@@ -252,7 +391,7 @@
   $self->_add_inst ('', 'set', [$return.'[0]',$car]);
   _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);
 
@@ -264,7 +403,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 +415,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,9 +427,9 @@
 
   _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);
 
@@ -302,16 +441,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);
 
   return $return;
 }
 
-sub _op_null {
+sub _op_null_p {
+  my ($self, $node) = @_;
+  my $return = _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");
+  _restore ($temp);
+
+  return $return;
 }
 
 sub _op_list_p {
@@ -324,9 +479,9 @@
 
   $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');
 
@@ -349,7 +504,7 @@
 
   _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');
@@ -430,9 +585,9 @@
   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('','ne',[$temp_0,$temp_1,"DONE_$label"]);
     _restore($temp_1);
   }
@@ -448,9 +603,9 @@
   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);
   }
@@ -466,9 +621,9 @@
   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);
   }
@@ -484,9 +639,9 @@
   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);
   }
@@ -502,9 +657,9 @@
   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);
   }
@@ -520,10 +675,9 @@
   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->_add_inst(''           ,'set'   ,[$return,0]);
@@ -537,7 +691,7 @@
   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->_add_inst(''           ,'set'   ,[$return,0]);
@@ -551,7 +705,7 @@
   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->_add_inst(''           ,'set'   ,[$return,0]);
@@ -564,7 +718,7 @@
   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]);
@@ -580,7 +734,7 @@
   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]);
@@ -596,8 +750,8 @@
   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"]);
@@ -613,8 +767,8 @@
   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"]);
@@ -628,14 +782,14 @@
 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]);
   } else {
-    $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}[$_]);
       $self->_add_inst('','add',[$return,$return,$temp]);
       _restore($temp);
@@ -647,18 +801,18 @@
 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]);
     my $temp   = $self->_constant(0);
     $self->_add_inst('','sub',[$return,$temp,$return]);
     _restore($temp);
   } else {
-     $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}[$_]);
        $self->_add_inst('','sub',[$return,$return,$temp]);
        _restore($temp);
@@ -670,15 +824,15 @@
 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]);
   } else {
-    $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}[$_]);
       $self->_add_inst('','mul',[$return,$return,$temp]);
       _restore($temp);
@@ -690,18 +844,18 @@
 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]);
     my $temp = $self->_constant(1);
     $self->_add_inst('','div',[$return,$temp,$return]);
     _restore($temp);
   } else {
-    $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}[$_]);
       $self->_add_inst('','div',[$return,$return,$temp]);
       _restore($temp);
@@ -715,7 +869,7 @@
   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]);
@@ -1044,8 +1198,11 @@
 
 sub _op_write {
   my ($self,$node) = @_;
-  for(@{$node->{children}}) {
-    my $temp = $self->_generate($_);
+  my $temp = _save_1 ('I');
+
+  for(_get_args($node)) {
+    _restore ($temp); # ugly trick 
+    $temp = $self->_generate($_);
     if ($temp =~ /[INS]/) {
       $self->_add_inst('','print',[$temp]);
     }
@@ -1060,8 +1217,8 @@
 	$self->_add_inst('', 'restore', ['P5']);
       }
     }
-    _restore($temp);
   }
+  return $temp; # We need to return something
 }
 
 sub _op_display {
@@ -1122,8 +1279,6 @@
 
 my %global_ops = (
 
-  'CONSTANT'   => \&_op_constant,
-
 #----------------------
 #
 # Section 4 Expressions
@@ -1133,6 +1288,7 @@
   'quote'      => \&_op_quote,
   'lambda'     => \&_op_lambda,
   'if'         => \&_op_if,
+  'define'     => \&_op_define,
   'set!'       => \&_op_set_bang,
   'cond'       => \&_op_cond,
   'case'       => \&_op_case,
@@ -1424,7 +1580,7 @@
   my ($self, $name) = @_;
 
   push @{$self->{functions}}, $name 
-    unless grep { $_ eq $name } @{$self->{functitons}};
+    unless grep { $_ eq $name } @{$self->{functions}};
 }
 
 sub _format_columns {
@@ -1475,15 +1631,29 @@
   my ($self,$node) = @_;
   my $return;
 
-  if($node->{value} =~ /\d/) {
-    $return = $global_ops{CONSTANT}->($self,$node);
-  } else {
-    $return = $global_ops{$node->{value}}->($self,$node);
+  if (exists $node->{children}) {
+    my $func = $node->{children}->[0]->{value};
+    if (exists $global_ops{$func}) {
+      $return = $global_ops{$func}->($self, $node);
+    }
+    else {
+      print STDERR "Error: $func not defined\n";
+    }
+  } 
+  else {
+    my $value = $node->{value};
+    if (exists $self->{scope}->{$value}) {
+      $return = _save_1 ('P');
+      $self->_add_inst ('', 'find_lex',[$return,"\"$value\""]);
+    }
+    else {
+      $return = $self->_constant($node->{value});
+    }
   }
-  $return;
+  return $return;
 }
 
-sub _link_buildins {
+sub _link_builtins {
   my ($self) = @_;
 
   for (@{$self->{functions}}) {
@@ -1493,12 +1663,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');
+
+  $temp = $self->_generate($self->{tree});
+
+  $self->_add_inst ('', 'pop_pad');
 #die Dumper($self->{tree});
-  _restore(@temp);
+  _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	9 Sep 2002 22:48:15 -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	9 Sep 2002 22:48:15 -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	9 Sep 2002 22:48:15 -0000
@@ -0,0 +1,30 @@
+#! perl -w
+
+use Scheme::Test tests => 5;
+
+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
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	9 Sep 2002 22:48:15 -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

Reply via email to