Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.223
diff -u -r1.223 MANIFEST
--- MANIFEST 23 Sep 2002 00:11:18 -0000 1.223
+++ MANIFEST 23 Sep 2002 23:19:34 -0000
@@ -35,6 +35,7 @@
classes/perlundef.pmc
classes/pmc2c.pl
classes/pointer.pmc
+classes/scratchpad.pmc
classes/sub.pmc
config/auto/alignptrs.pl
config/auto/alignptrs/test_c.in
@@ -516,6 +517,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: classes/scratchpad.pmc
===================================================================
RCS file: classes/scratchpad.pmc
diff -N classes/scratchpad.pmc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ classes/scratchpad.pmc 23 Sep 2002 23:19:34 -0000
@@ -0,0 +1,475 @@
+
+/* Scratchpad.pmc
+ * Copyright: (When this is determined...it will go here)
+ * CVS Info
+ * $Id$
+ * Overview:
+ * These are the vtable functions for the Scratchpad base class.
+ * It implements an array of nested lexical scopes, each of which
+ * is currently a PerlHash. Scratchpads are currently intended to
+ * be manipulated only by the scratchpad-handling functions
+ * defined in sub.c and by the lexical operations in core.ops, and
+ * not by the user.
+ * History: Initial revision Mon Sep 16 2002 by Sean O'Rourke
+ * Notes:
+ * References: Most compiler books, e.g. Aho, Sethi, and Ullman,
+ * "Compilers: Principles, tools, and techniques."
+ */
+
+#include "parrot/parrot.h"
+
+#define NO_DEPTH (-100000)
+
+static PMC * pad_keys(struct Parrot_Interp *, PMC *, INTVAL * , STRING ** );
+static PMC * pad_index_pmc(struct Parrot_Interp *, PMC *, INTVAL, STRING *,
+ int);
+static HASH_ENTRY * pad_find (struct Parrot_Interp *, PMC *, STRING *);
+static PMC * pad_copy (struct Parrot_Interp *, PMC *, INTVAL);
+static HASH_ENTRY * pad_index (struct Parrot_Interp *, PMC *, INTVAL,
+ STRING *, int);
+static INTVAL pad_offset (PMC *, INTVAL);
+
+/*
+ * rest_of_key = pad_keys(interp, key, &ix, &sx)
+ *
+ * Get pad-relevant elements from a key, returning the remainder of
+ * the key.
+ *
+ * { string, ... } -> [NO_DEPTH, string] (lexical name without depth)
+ * { int } -> [int, NULL] (lexical depth without name)
+ * { int, string, ... } -> [int, string] (lexical name at depth)
+ */
+static PMC *
+pad_keys(struct Parrot_Interp * interp, PMC * key, INTVAL * ix, STRING ** sx)
+{
+ if (key_type(interp, key) & KEY_string_FLAG) {
+ /* need to do a pad_find */
+ *ix = NO_DEPTH;
+ *sx = key_string(interp, key);
+ return key_next(interp, key);
+ }
+
+ *ix = key_integer(interp, key);
+ key = key_next(interp, key);
+ if (key) {
+ *sx = key_string(interp, key);
+ key = key_next(interp, key);
+ }
+ else {
+ *sx = NULL;
+ }
+ return key;
+}
+
+/*
+ * pmc = pad_index_pmc(interp, pad, depth, name, create)
+ *
+ * If depth is NO_DEPTH, find lexical name (or die).
+ * Else get name at depth.
+ * If create is true, create a new PerlUndef PMC
+ * Else, die.
+ */
+static PMC *
+pad_index_pmc(struct Parrot_Interp * interp, PMC * self, INTVAL ix,
+ STRING * sx, int create)
+{
+ HASH_ENTRY * e;
+
+ /* XXX: should this auto-insert? */
+ if (ix == NO_DEPTH)
+ e = pad_find(interp, self, sx);
+ else
+ e = pad_index(interp, self, ix, sx, create);
+ if (e == NULL)
+ internal_exception(-1, "No such variable\n");
+
+ if (e->val.pmc_val == NULL) {
+ /* XXX: perl-specificity... */
+ e->type = enum_hash_pmc;
+ e->val.pmc_val = pmc_new(interp, enum_class_PerlUndef);
+ }
+ return e->val.pmc_val;
+}
+
+/* Just to make it compile */
+INTVAL
+pad_offset (PMC *pmc, INTVAL ix)
+{
+ internal_exception (0, "pad_offset not implemented");
+ return 0;
+}
+
+HASH_ENTRY *
+pad_find (struct Parrot_Interp *interpreter, PMC *pmc, STRING *sx)
+{
+ HASH_ENTRY *e = NULL;
+ PMC *pad;
+ INTVAL i;
+
+ i = pmc->cache.int_val;
+ while (e == NULL && i--) {
+ pad = ((PMC**)pmc->data)[i];
+ e = hash_get (interpreter, (HASH *)pad->data, sx);
+ }
+
+ return e;
+}
+
+HASH_ENTRY *
+pad_index (struct Parrot_Interp *interpreter, PMC *pmc,
+ INTVAL ix, STRING *sx, int create)
+{
+ HASH_ENTRY * e;
+ PMC* pad;
+
+ if (ix < -pmc->cache.int_val || ix >= pmc->cache.int_val) {
+ internal_exception (OUT_OF_BOUNDS, "Scrachpad: index out of bounds");
+ return NULL;
+ }
+ if (ix < 0) ix += pmc->cache.int_val;
+
+ pad = ((PMC **)pmc->data)[ix];
+ e = hash_get (interpreter, (HASH *)pad->data, sx);
+
+ if (e == NULL && create) {
+ HASH_ENTRY new_entry;
+ new_entry.type = enum_hash_pmc;
+ new_entry.val.pmc_val = pmc_new (interpreter, enum_class_PerlUndef);
+ hash_put (interpreter, (HASH *)pad->data, sx, &new_entry);
+ e = hash_get (interpreter, (HASH *)pad->data, sx);
+ }
+
+ return e;
+}
+
+PMC *
+pad_copy (struct Parrot_Interp *interpreter, PMC *pmc, INTVAL depth)
+{
+ PMC *self = pmc_new (interpreter, enum_class_Scratchpad);
+
+ self->data = mem_sys_allocate (depth * sizeof (PMC *));
+ mem_sys_memcopy (self->data, pmc->data, depth * sizeof (PMC *));
+
+ self->cache.int_val = depth;
+
+ return self;
+}
+
+pmclass Scratchpad {
+
+ void init () {
+ SELF->cache.int_val = 0;
+ SELF->data = NULL;
+ SELF->flags |= PMC_custom_mark_FLAG | PMC_active_destroy_FLAG;
+ }
+
+ PMC* mark (PMC* last) {
+ int j;
+ for (j = 0; j < SELF->cache.int_val; j++)
+ last = mark_used(((PMC **)SELF->data)[j], last);
+ return last;
+ }
+
+ void destroy () {
+ fprintf(stderr, "Freed pad at %p\n", SELF);
+ mem_sys_free(SELF->data);
+ }
+
+ INTVAL type () {
+ return enum_class_Scratchpad;
+ }
+
+ INTVAL type_keyed (PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ return enum_class_PerlHash;
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 0);
+ if (key)
+ return p->vtable->type_keyed(INTERP, p, key);
+ return p->vtable->type(INTERP, p);
+ }
+
+ INTVAL type_keyed_int (INTVAL* key) {
+ return enum_class_PerlHash;
+ }
+
+ STRING* name () {
+ return whoami;
+ }
+
+ PMC* clone () {
+ return pad_copy(INTERP, SELF, SELF->cache.int_val);
+ }
+
+ PMC* clone_keyed (PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL) {
+ ix = pad_offset(SELF, ix);
+ p = ((PMC **)SELF->data)[pad_offset(SELF, ix)];
+ return p->vtable->clone(INTERP, p);
+ }
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 0);
+ if (key)
+ return p->vtable->clone_keyed(INTERP, p, key);
+ return p->vtable->clone(INTERP, p);
+ }
+
+ PMC* clone_keyed_int (INTVAL* key) {
+ return pad_copy(INTERP, SELF, *key);
+ }
+
+ INTVAL get_integer () {
+ return SELF->cache.int_val;
+ }
+
+ void set_integer_native (INTVAL depth) {
+ if (depth < 0) {
+ depth += SELF->cache.int_val;
+ if (depth < 0)
+ internal_exception(-1, "index too negative\n");
+ }
+ if (depth > SELF->cache.int_val) {
+ int i;
+ PMC ** p;
+ SELF->data = mem_sys_realloc(SELF->data, depth * sizeof(PMC *));
+ p = (PMC**)SELF->data;
+ for (i = SELF->cache.int_val; i < depth; i++)
+ p[i] = pmc_new(INTERP, enum_class_PerlHash);
+ }
+ SELF->cache.int_val = depth;
+ }
+
+ void set_integer (PMC * p) {
+ INTVAL i = p->vtable->get_integer(INTERP, p);
+ SELF.set_integer_native(i);
+ }
+
+/* INTVAL get_integer_keyed (PMC* key) { */
+/* } */
+
+/* XXX: not sure how these will be used, so they're currently unavailable. */
+/* INTVAL elements () { */
+/* return SELF->cache.int_val; */
+/* } */
+
+/* INTVAL elements_keyed (PMC* key) { */
+/* } */
+
+/* INTVAL elements_keyed_int (INTVAL* key) { */
+/* PMC * thing = SELF.get_pmc_keyed_int(key); */
+/* if (thing) */
+/* return thing->vtable->elements(INTERP, thing); */
+/* return 0; */
+/* } */
+
+ PMC* get_pmc () {
+ return SELF;
+ }
+
+ PMC* get_pmc_keyed (PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ return ((PMC **)SELF->data)[pad_offset(SELF, ix)];
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 0);
+ if (key)
+ return p->vtable->get_pmc_keyed(INTERP, p, key);
+ return p->vtable->get_pmc(INTERP, p);
+ }
+
+ PMC* get_pmc_keyed_int (INTVAL* key) {
+ INTVAL k = pad_offset(SELF, *key);
+ return ((PMC **)SELF->data)[k];
+ }
+
+ void set_integer_keyed (PMC* key, INTVAL value) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ if (key == NULL) {
+ SELF.set_integer_native(value);
+ return;
+ }
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ internal_exception(-1, "Can't set a lexical scope level\n");
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 1);
+ if (key)
+ return p->vtable->set_integer_keyed(INTERP, p, key, value);
+ return p->vtable->set_integer_native(INTERP, p, value);
+ }
+
+ void set_number_keyed (PMC* key, FLOATVAL value) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ internal_exception(-1, "Can't set a lexical scope level\n");
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 1);
+ if (key)
+ return p->vtable->set_number_keyed(INTERP, p, key, value);
+ return p->vtable->set_number_native(INTERP, p, value);
+ }
+
+ void set_string_keyed (PMC* key, STRING* value) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ internal_exception(-1, "Can't set a lexical scope level\n");
+ p = pad_index_pmc(INTERP, SELF, ix, sx, 1);
+ if (key)
+ return p->vtable->set_string_keyed(INTERP, p, key, value);
+ return p->vtable->set_string_native(INTERP, p, value);
+ }
+
+ void set_pmc_keyed (PMC* key, PMC* value, PMC* value_key) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p, * val;
+ HASH_ENTRY * e;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (sx == NULL)
+ internal_exception(-1, "Can't set a lexical scope level\n");
+
+ /* XXX: should this auto-insert? */
+ if (ix == NO_DEPTH)
+ e = pad_find(INTERP, SELF, sx);
+ else
+ e = pad_index(INTERP, SELF, ix, sx, 1);
+ if (key == NULL) {
+ /* Special case -- make this just like "set Py, Px" if
+ * there are no more keys. */
+ if (value_key)
+ e->val.pmc_val
+ = value->vtable->get_pmc_keyed(INTERP, value, value_key);
+ else
+ e->val.pmc_val = value->vtable->get_pmc(INTERP, value);
+ }
+ else {
+ p = e->val.pmc_val;
+ p->vtable->set_pmc_keyed(INTERP, p, key, value, value_key);
+ }
+ }
+
+/* void set_pmc_keyed_int (INTVAL* key, PMC* value, INTVAL* value_key) { */
+/* } */
+
+ void set_same (PMC* value) {
+ SELF->cache.int_val = value->cache.int_val;
+ mem_sys_free(SELF->data);
+ SELF->data = mem_sys_allocate(value->cache.int_val * sizeof(PMC *));
+ mem_sys_memcopy(SELF->data, value->data,
+ value->cache.int_val * sizeof(PMC *));
+ }
+
+/* void set_same_keyed (PMC* key, PMC* value, PMC* value_key) { */
+/* } */
+
+/* void set_same_keyed_int (INTVAL* key, PMC* value, INTVAL* value_key) { */
+/* } */
+
+ PMC* pop_pmc () {
+ PMC * ret;
+ if (SELF->cache.int_val == 0)
+ internal_exception(OUT_OF_BOUNDS, "No nested scopes\n");
+ return ((PMC **)SELF->data)[--(SELF->cache.int_val)];
+ }
+
+ void push_pmc (PMC* value) {
+ if (value->vtable != &Parrot_base_vtables[enum_class_PerlHash])
+ internal_exception(-1, "Wrong type for scope stack\n");
+ SELF->data = mem_sys_realloc(SELF->data, ++SELF->cache.int_val);
+ ((PMC **)SELF->data)[SELF->cache.int_val - 1] = value;
+ }
+
+ INTVAL defined () {
+ return 1;
+ }
+
+ INTVAL defined_keyed (PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ PMC * p;
+ HASH_ENTRY * e;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (ix == NO_DEPTH)
+ e = pad_find(INTERP, SELF, sx);
+ else
+ e = pad_index(INTERP, SELF, ix, sx, 0);
+ if (e == NULL)
+ return 0;
+
+ p = e->val.pmc_val;
+ if (key)
+ return p->vtable->defined_keyed(INTERP, p, key);
+ return p->vtable->defined(INTERP, p);
+ }
+
+ INTVAL defined_keyed_int (INTVAL* key) {
+ return *key < SELF->cache.int_val && *key >= -SELF->cache.int_val;
+ }
+
+ void delete_keyed (PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ HASH_ENTRY * e;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (ix == NO_DEPTH)
+ e = pad_find(INTERP, SELF, sx);
+ else
+ e = pad_index(INTERP, SELF, ix, sx, 0);
+ if (e == NULL)
+ return;
+
+ if (key == NULL) {
+ /* delete pad entry */
+ HASH * hash;
+ ix = pad_offset(SELF, ix);
+ hash = (HASH *)((PMC **)SELF->data)[ix]->data;
+ hash_delete(INTERP, hash, sx);
+ }
+ else {
+ /* forward to whatever's inside */
+ PMC * p = e->val.pmc_val;
+ p->vtable->delete_keyed(INTERP, p, key);
+ }
+ }
+
+ INTVAL exists_keyed(PMC* key) {
+ INTVAL ix;
+ STRING * sx;
+ HASH_ENTRY * e;
+ key = pad_keys(INTERP, key, &ix, &sx);
+ if (ix == NO_DEPTH)
+ e = pad_find(INTERP, SELF, sx);
+ else
+ e = pad_index(INTERP, SELF, ix, sx, 0);
+ if (e == NULL)
+ return 0;
+
+ if (key == NULL) {
+ /* lexical entry exists */
+ return 1;
+ }
+ else {
+ /* forward to whatever's inside */
+ PMC * p = e->val.pmc_val;
+ return p->vtable->exists_keyed(INTERP, p, key);
+ }
+ }
+
+ INTVAL exists_keyed_int(INTVAL* key) {
+ return *key < SELF->cache.int_val && *key >= -SELF->cache.int_val;
+ }
+}
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 23 Sep 2002 23:19:34 -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,28 @@
['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]'],
+ ['', 'set', 'I0', 'P7'],
+ ['', 'clone', 'P31', 'P7'],
+ ['', 'add', 'I0', '1'],
+ ['', 'set', 'P31', 'I0'],
+ ['', 'set', 'P7', 'P5[2]'],
+ ['apply_NEXT', 'typeof', 'I0', 'P6'],
+ ['', 'eq', 'I0', '.PerlUndef', 'apply_LAST'],
+ ['', 'set', 'S0', 'P7[0]'],
+# ['', 'set', 'P31[-1;S0]', 'P6[0]'], # not working yet
+ ['', 'set', 'P8', 'P6[0]'],
+ ['', 'set', 'P31[-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 23 Sep 2002 23:19:35 -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 => { 31 => -1, map { $_ => 0 } (0..30) },
+ };
};
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 ('','set',[$return,"P31[\"$symbol\"]"]);
+ return $return;
+}
+
+sub _store_lex {
+ my ($self, $symbol,$value) = @_;
+ $self->_add_inst ('','set',["P31[\"$symbol\"]",$value]);
+}
+
+sub _new_lex {
+ my ($self, $symbol, $value) = @_;
+ $self->_add_inst ('','set',["P31[-1;\"$symbol\"]",$value]);
}
#------------------------------------
@@ -78,29 +143,133 @@
#------------------------------------
-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();
+
+ $return = $self->_save_1 ('P');
+
+ $self->_add_inst ('', 'new',[$return,'.Array']);
+ $self->_add_inst ('', 'set',[$return,3]);
+ $self->_add_inst ('', 'set',[$return.'[0]','P31']);
+
+ my $addr = $self->_save_1 ('I');
+ $self->_add_inst ('', 'set_addr',[$addr,"LAMBDA_$label"]);
+ $self->_add_inst ('', 'set',[$return.'[1]',$addr]);
+ $self->_restore ($addr);
+
+ my $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('', 'ret');
+ $self->_add_inst("DONE_$label");
+
+ $self->{regs} = pop @{$self->{frames}};
+
+ return $return;
}
sub _op_if {
@@ -108,23 +277,84 @@
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->_add_inst ('', 'store_lex', ["\"$symbol\"",$temp]);
+ $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};
+# 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 = $self->_save_1 ('P');
+ $self->_morph ($pmc, $temp);
+ $self->_restore ($temp);
+ $temp = $pmc;
+ }
+# $self->_add_inst ('', 'store_lex', ["\"$symbol\"",$temp]);
+ $self->_store_lex ($symbol,$temp);
+
+ return $temp;
}
sub _op_cond {
@@ -139,10 +369,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 +385,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 +396,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 +427,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 +451,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 +479,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 +506,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 +526,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 +538,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 +550,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 +564,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 +598,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 +614,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 +623,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 +708,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 +732,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 +750,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 +768,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 +786,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 +804,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 +820,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 +834,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 +847,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 +863,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 +879,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 +896,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 +911,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 +942,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 +977,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 +1009,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 +1046,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 +1305,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 +1407,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 +1480,6 @@
my %global_ops = (
- 'CONSTANT' => \&_op_constant,
-
#----------------------
#
# Section 4 Expressions
@@ -1133,6 +1489,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 +1777,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
- push @{$self->{functions}}, $name
- unless grep { $_ eq $name } @{$self->{functitons}};
+ $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;
+
+ return $return;
}
sub _format_columns {
@@ -1451,7 +1844,8 @@
my $tree = shift;
my $self = {
tree => $tree,
- register => [(0) x 32],
+ regs => _new_regs,
+ frames => [],
gensym => 0,
functions=> [],
};
@@ -1475,15 +1869,39 @@
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->_save_1('P');
+# $self->_add_inst('', 'find_lex',[$func_obj,"\"$func_sym\""]);
+ 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 +1911,20 @@
sub generate {
my $self = shift;
- my @temp = _save(1);
- $self->_generate($self->{tree},$temp[0]);
+ my $temp;
+
+ $self->{scope} = {};
+# $self->_add_inst ('', 'new_pad');
+ $self->_add_inst ('', 'new',['P31','.Scratchpad']);
+ $self->_add_inst ('', 'set',['P31',1]);
+
+ $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 23 Sep 2002 23:19:36 -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 23 Sep 2002 23:19:36 -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 23 Sep 2002 23:19:36 -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 23 Sep 2002 23:19:36 -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