Hello, This weekend I played a little bit with Parrot, and in order to learn more about vtables I just implemented Scheme Pairs
Here are the changes: * MANIFEST, Makefile.in, global_setup.c, classes/Makefile.in include/parrot/pmc.h: Added SchemePair as described in vtable.pod * core.ops: * added new operation set_p_p for copying the pmc-pointer * added new operations set_p_i_p and set_p_p_i for indirect setting and getting of pmc values * added new operation get_type_s_p and get_type_i_p to get the type-information at runtime and not only at compiletime * vtable.tbl: Added new methods for indirect setting and getting of pmc-values * classes/default.pmc default (non-)implementations of the above methods * classes/schemepair.pmc: New File. Implementation of the new indirect PMC get and set methods. Implementation of a stringfication method. * classes/perlint.pmc, classes/perlnum.pmc, classes/perlstring.pmc, classes/perlundef.pmc: type () returns the korrekt type and not 0 * languages/scheme/Scheme/Generator.pm Implementation of the following methods: cons, car, cdr, set-car!, set-cdr!, pair?, null?, list, length * languages/scheme/Scheme/Tokenizer.pm Exclamation marks are valid identifiers * languages/scheme/t/harness use directory lists * languages/scheme/t/lists/basic.t Some basic list tests Have fun, Jürgen Index: classes/schemepair.pmc =================================================================== diff -u /dev/null classes/schemepair.pmc --- /dev/null Fri Nov 12 22:31:31 1999 +++ classes/schemepair.pmc Sun Jan 6 17:41:15 2002 @@ -0,0 +1,473 @@ +/* SchemePair.pmc -*- C -*- + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id: not yet $ + * Overview: + * These are the vtable functions for the SchemePair base class + * Data Structure and Algorithms: + * History: + * Notes: + * References: + */ + +#include "parrot/parrot.h" + +static STRING* +_stringify_key_pair (struct Parrot_Interp* INTERP, KEY_PAIR* key_pair) { + STRING* s; + + s = string_make (INTERP, NULL, 80, NULL, 0, NULL); + + switch (key_pair->type) { + case enum_key_int: + s->bufused = sprintf (s->bufstart, "%ld", key_pair->cache.int_val); + string_compute_strlen(s); + break; + case enum_key_num: + s->bufused = sprintf (s->bufstart, "%g", key_pair->cache.struct_val); + string_compute_strlen(s); + break; + case enum_key_string: + string_destroy (s); + s = key_pair->cache.struct_val; + break; + default: + fprintf (stderr, "*** unknown key_type(%d)\n", key_pair->type); + } + + return s; +} + +pmclass SchemePair { + + INTVAL type () { + return enum_class_SchemePair; + } + + STRING* name () { + return whoami; + } + + void init () { + KEY *key; + + key = key_new (INTERP); + key_set_size (INTERP, key, 2); + SELF->cache.struct_val = key; + } + + void clone (PMC* dest) { + KEY *key; + KEY *old = SELF->cache.struct_val; + + dest->vtable = SELF->vtable; + key = key_new (INTERP); + key_set_size (INTERP, key, 2); + memcpy (key->keys, old->keys, 2*sizeof(KEY_PAIR)); + dest->cache.struct_val = key; + } + + void morph (INTVAL type) { + } + + BOOLVAL move_to (void * destination) { + return 0; /* You can't move me, I don't have anything to move! */ + } + + INTVAL real_size () { + return 0; /* ->data is unused */ + } + + void destroy () { + key_destroy(INTERP,SELF->cache.struct_val); + } + + INTVAL get_integer () { + } + + INTVAL get_integer_index (INTVAL index) { + } + + FLOATVAL get_number () { + } + + FLOATVAL get_number_index (INTVAL index) { + } + + STRING* get_string () { + KEY *key = SELF->cache.struct_val; + KEY_PAIR *car, *cdr; + + STRING *ret = string_make (INTERP, "(", 1, NULL, 0, NULL); + + do { + car = key_element_value_i (INTERP, key, 0); + cdr = key_element_value_i (INTERP, key, 1); + + if (car->type == enum_key_pmc) { + PMC *pmc = car->cache.pmc_val; + VTABLE *vtable = pmc->vtable; + INTVAL type = vtable->type (INTERP, pmc); + + if (type == enum_class_PerlUndef) { + /* empty list */ + ret = string_concat (INTERP, ret, + string_make (INTERP, "()", 2, NULL, 0, NULL), + 0); + } + else { + ret = string_concat (INTERP, ret, + vtable->get_string (INTERP, pmc), + 0); + } + } + else { + ret = string_concat (INTERP, ret, + _stringify_key_pair (INTERP, car), + 0); + } + + if (cdr->type == enum_key_pmc) { + PMC *pmc = cdr->cache.pmc_val; + VTABLE *vtable = pmc->vtable; + INTVAL type = vtable->type (INTERP, pmc); + + if (type == enum_class_PerlUndef) { + /* end of list */ + break; + } + else if (type == enum_class_SchemePair) { + /* next element of list */ + ret = string_concat (INTERP, ret, + string_make (INTERP, " ", 1, NULL, 0, NULL), + 0); + key = pmc->cache.struct_val; + } + else { + /* improper lists */ + ret = string_concat (INTERP, ret, + string_make (INTERP, " . ", 3, NULL, 0, NULL), + 0); + ret = string_concat (INTERP, ret, + vtable->get_string (INTERP, pmc), + 0); + break; + } + } + else { + ret = string_concat (INTERP, ret, + string_make (INTERP, " . ", 3, NULL, 0, NULL), + 0); + ret = string_concat (INTERP, ret, + _stringify_key_pair (INTERP, cdr), + 0); + break; + } + } while (1); + + ret = string_concat (INTERP, ret, + string_make (INTERP, ")", 1, NULL, 0, NULL), + 0); + + return ret; + } + + STRING* get_string_index (INTVAL index) { + } + + BOOLVAL get_bool () { + } + + void* get_value () { + } + + BOOLVAL is_same (PMC* pmc2) { + } + + void set_integer (PMC * value) { + } + + void set_integer_native (INTVAL value) { + } + + void set_integer_bigint (BIGINT value) { + } + + void set_integer_same (PMC * value) { + } + + void set_integer_index (INTVAL value, INTVAL index) { + if (index >= 0 && index < 2) { + KEY *key = SELF->cache.struct_val; + KEY_PAIR key_pair; + + key_pair.type = enum_key_int; + key_pair.cache.int_val = value; + key_set_element_value_i (INTERP, key, index, &key_pair); + } + else { + fprintf (stderr, "*** set_integer_index index(%d) out of range\n", + index); + } + } + + + void set_number (PMC * value) { + } + + void set_number_native (FLOATVAL value) { + } + + void set_number_bigfloat (BIGFLOAT value) { + } + + void set_number_same (PMC * value) { + } + + void set_number_index (FLOATVAL value, INTVAL index) { + if (index >= 0 && index < 2) { + KEY *key = SELF->cache.struct_val; + KEY_PAIR key_pair; + + key_pair.type = enum_key_num; + key_pair.cache.num_val = value; + key_set_element_value_i (INTERP, key, index, &key_pair); + } + else { + fprintf (stderr, "*** set_pmc_index index(%d) out of range\n", + index); + } + } + + void set_string (PMC * value) { + } + + void set_string_native (STRING * value) { + } + + void set_string_unicode (STRING * value) { + } + + void set_string_other (STRING * value) { + } + + void set_string_same (PMC * value) { + } + + void set_string_index (STRING* value, INTVAL index) { + } + + void set_value (void* value) { + } + + void add (PMC * value, PMC* dest) { + } + + void add_int (INTVAL value, PMC* dest) { + } + + void add_bigint (BIGINT value, PMC* dest) { + } + + void add_float (FLOATVAL value, PMC* dest) { + } + + void add_bigfloat (BIGFLOAT value, PMC* dest) { + } + + void add_same (PMC * value, PMC* dest) { + } + + void subtract (PMC * value, PMC* dest) { + } + + void subtract_int (INTVAL value, PMC* dest) { + } + + void subtract_bigint (BIGINT value, PMC* dest) { + } + + void subtract_float (FLOATVAL value, PMC* dest) { + } + + void subtract_bigfloat (BIGFLOAT value, PMC* dest) { + } + + void subtract_same (PMC * value, PMC* dest) { + } + + void multiply (PMC * value, PMC* dest) { + } + + void multiply_int (INTVAL value, PMC* dest) { + } + + void multiply_bigint (BIGINT value, PMC* dest) { + } + + void multiply_float (FLOATVAL value, PMC* dest) { + } + + void multiply_bigfloat (BIGFLOAT value, PMC* dest) { + } + + void multiply_same (PMC * value, PMC* dest) { + } + + void divide (PMC * value, PMC* dest) { + } + + void divide_int (INTVAL value, PMC* dest) { + } + + void divide_bigint (BIGINT value, PMC* dest) { + } + + void divide_float (FLOATVAL value, PMC* dest) { + } + + void divide_bigfloat (BIGFLOAT value, PMC* dest) { + } + + void divide_same (PMC * value, PMC* dest) { + } + + void modulus (PMC * value, PMC* dest) { + } + + void modulus_int (INTVAL value, PMC* dest) { + } + + void modulus_bigint (BIGINT value, PMC* dest) { + } + + void modulus_float (FLOATVAL value, PMC* dest) { + } + + void modulus_bigfloat (BIGFLOAT value, PMC* dest) { + } + + void modulus_same (PMC * value, PMC* dest) { + } + + void concatenate (PMC * value, PMC* dest) { + } + + void concatenate_native (STRING * value, PMC* dest) { + } + + void concatenate_unicode (STRING * value, PMC* dest) { + } + + void concatenate_other (STRING * value, PMC* dest) { + } + + void concatenate_same (PMC * value, PMC* dest) { + } + + BOOLVAL is_equal (PMC* value) { + } + + void logical_or (PMC* value, PMC* dest) { + } + + void logical_and (PMC* value, PMC* dest) { + } + + void logical_not (PMC* value) { + } + + void match (PMC * value, REGEX* re) { + } + + void match_native (STRING * value, REGEX* re) { + } + + void match_unicode (STRING * value, REGEX* re) { + } + + void match_other (STRING * value, REGEX* re) { + } + + void match_same (PMC * value, REGEX* re) { + } + + void repeat (PMC * value, PMC* dest) { + } + + void repeat_native (STRING * value, PMC* dest) { + } + + void repeat_unicode (STRING * value, PMC* dest) { + } + + void repeat_other (STRING * value, PMC* dest) { + } + + void repeat_same (PMC * value, PMC* dest) { + } + + void set_pmc_index (PMC *value, INTVAL index) { + if (index >= 0 && index < 2) { + KEY *key = SELF->cache.struct_val; + KEY_PAIR key_pair; + + key_pair.type = enum_key_pmc; + key_pair.cache.pmc_val = value; + key_set_element_value_i (INTERP, key, index, &key_pair); + } + else { + fprintf (stderr, "*** set_pmc_index index(%d) out of range\n", + index); + } + } + + PMC* get_pmc_index (INTVAL index) { + if (index >= 0 && index < 2) { + KEY *key = SELF->cache.struct_val; + KEY_PAIR *key_pair = key_element_value_i (INTERP, key, index); + + if (key_pair->type == enum_key_pmc) { + return key_pair->cache.pmc_val; + } + else { + PMC* new_pmc = NULL; + switch (key_pair->type) { + case enum_key_int: + new_pmc = pmc_new (INTERP, enum_class_PerlInt); + Parrot_PerlInt_set_integer_native (INTERP, new_pmc, + key_pair->cache.int_val); + break; + case enum_key_num: + new_pmc = pmc_new (INTERP, enum_class_PerlNum); + Parrot_PerlNum_set_number_native (INTERP, new_pmc, + key_pair->cache.num_val); + break; + case enum_key_string: + new_pmc = pmc_new (INTERP, enum_class_PerlString); + Parrot_PerlString_set_string_native (INTERP, new_pmc, + key_pair->cache.struct_val); + default: + fprintf (stderr, "*** get_pmc_index: unknown type (%d)\n", + key_pair->type); + } + return new_pmc; + } + } + else { + fprintf (stderr, "*** get_pmc_index index(%d) out of range\n", + index); + } + } + return NULL; +} + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ Index: languages/scheme/t/lists/basic.t =================================================================== diff -u /dev/null languages/scheme/t/lists/basic.t --- /dev/null Fri Nov 12 22:31:31 1999 +++ languages/scheme/t/lists/basic.t Sun Jan 6 17:21:18 2002 @@ -0,0 +1,84 @@ +#! perl -w + +use Scheme::Test tests => 15; + +### +### Add +### + +output_is(<<'CODE', '(2 . 5)', 'cons'); +(write (cons 2 5)) +CODE + +output_is(<<'CODE', '((2 . 3) . 4)', 'cons car'); +(write (cons (cons 2 3) 4)) +CODE + +output_is(<<'CODE', '(2 3 . 4)', 'cons cdr'); +(write (cons 2 (cons 3 4))) +CODE + +output_is(<<'CODE', '((1 . 2) 3 . 4)', 'complex cons'); +(write + (cons + (cons 1 2) + (cons 3 4))) +CODE + +output_is(<<'CODE', '1', 'pair?'); +(write + (pair? (cons 1 3))) +CODE + +output_is(<<'CODE', '0', 'false pair?'); +(write + (pair? 12)) +CODE + +output_is(<<'CODE', '(3 2 1 0)', 'list'); +(write + (list 3 2 1 0)) +CODE + +output_is(<<'CODE', '1', 'pair? list'); +(write + (pair? (list 3 2 1))) +CODE + +output_is(<<'CODE', '(1 2 3)', 'lists the hard way'); +(write + (cons 1 + (cons 2 + (cons 3 + (list))))) +CODE + +output_is(<<'CODE', '4', 'length'); +(write + (length (list 3 2 1 0))) +CODE + +output_is(<<'CODE', '2', 'car'); +(write + (car (list 2 1 0))) +CODE + +output_is(<<'CODE', '(1 0)', 'cdr'); +(write + (cdr (list 2 1 0))) +CODE + +output_is(<<'CODE', '(4 2 3)', 'set-car!'); +(write + (set-car! (list 1 2 3) 4)) +CODE + +output_is(<<'CODE', '((4 . 2) 2 3)', 'set-car! II'); +(write + (set-car! (list 1 2 3) (cons 4 2))) +CODE + +output_is(<<'CODE', '(1 4 2)', 'set-cdr!'); +(write + (set-cdr! (list 1 2 3) (list 4 2))) +CODE Index: MANIFEST =================================================================== RCS file: /cvs/public/parrot/MANIFEST,v retrieving revision 1.84 diff -u -r1.84 MANIFEST --- MANIFEST 4 Jan 2002 03:57:37 -0000 1.84 +++ MANIFEST 6 Jan 2002 19:17:54 -0000 @@ -43,6 +43,7 @@ classes/perlstring.pmc classes/perlundef.pmc classes/pmc2c.pl +classes/schemepair.pmc config_h.in core.ops disassemble.pl @@ -161,6 +162,7 @@ languages/scheme/t/arith/nested.t languages/scheme/t/harness languages/scheme/t/io/basic.t +languages/scheme/t/lists/basic.t languages/scheme/t/logic/basic.t make.pl make_vtable_ops.pl Index: Makefile.in =================================================================== RCS file: /cvs/public/parrot/Makefile.in,v retrieving revision 1.101 diff -u -r1.101 Makefile.in --- Makefile.in 4 Jan 2002 16:44:44 -0000 1.101 +++ Makefile.in 6 Jan 2002 19:17:54 -0000 @@ -66,7 +66,8 @@ $(INC)/interp_guts.h ${jit_h} ${jit_struct_h} CLASS_O_FILES = classes/default$(O) classes/perlint$(O) classes/perlstring$(O) \ -classes/perlnum$(O) classes/perlarray$(O) classes/perlundef$(O) +classes/perlnum$(O) classes/perlarray$(O) classes/perlundef$(O) \ +classes/schemepair$(O) ENCODING_O_FILES = encodings/singlebyte$(O) encodings/utf8$(O) encodings/utf16$(O) \ encodings/utf32$(O) Index: core.ops =================================================================== RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.68 diff -u -r1.68 core.ops --- core.ops 4 Jan 2002 02:36:25 -0000 1.68 +++ core.ops 6 Jan 2002 19:17:55 -0000 @@ -554,8 +554,15 @@ Set $1 to $2. -=cut +=item B<set>(p, i|ic, p) + +Set $1[$2] to $3 +=item B<set>(p, p, i|ic) + +Set $1 to $2[$3] + +=cut inline op set(i, i|ic) { $1 = $2; @@ -614,6 +621,11 @@ goto NEXT(); } +inline op set(p, p) { + $1 = $2; + goto NEXT(); +} + inline op set(p, i|ic, i|ic) { $1->vtable->set_integer_index(interpreter, $1, $2, $3); goto NEXT(); @@ -644,6 +656,16 @@ goto NEXT(); } +inline op set(p, i|ic, p) { /* FIXME: Order of arguments diffrent from above */ + $1->vtable->set_pmc_index (interpreter, $1, $3, $2); + goto NEXT(); +} + +inline op set(p, p, i|ic) { + $1 = $2->vtable->get_pmc_index (interpreter, $2, $3); + goto NEXT(); +} + =back =cut @@ -2581,6 +2603,28 @@ } newpmc = pmc_new(interpreter, $2); $1 = newpmc; + goto NEXT(); +} + +=item B<get_type>(i, p) + +get the type of the PMC C<p> and store it in C<i> + +=cut + +op get_type (i, p) { + $1 = $2->vtable->type(interpreter, $2); + goto NEXT(); +} + +=item B<get_type>(s, p) + +get the typename of the PMC C<p> and store it in C<s> + +=cut + +op get_type (s, p) { + $1 = $2->vtable->name(interpreter, $2); goto NEXT(); } Index: global_setup.c =================================================================== RCS file: /cvs/public/parrot/global_setup.c,v retrieving revision 1.12 diff -u -r1.12 global_setup.c --- global_setup.c 1 Jan 2002 03:46:40 -0000 1.12 +++ global_setup.c 6 Jan 2002 19:17:55 -0000 @@ -15,20 +15,24 @@ #include "parrot/parrot.h" /* Needed because this might get compiled before pmcs have been built */ +void Parrot_PerlUndef_class_init(void); void Parrot_PerlInt_class_init(void); void Parrot_PerlNum_class_init(void); void Parrot_PerlString_class_init(void); void Parrot_PerlArray_class_init(void); +void Parrot_SchemePair_class_init(void); void init_world(void) { string_init(); /* Set up the string subsystem */ /* Call base vtable class constructor methods! */ + Parrot_PerlUndef_class_init(); Parrot_PerlInt_class_init(); Parrot_PerlNum_class_init(); Parrot_PerlString_class_init(); Parrot_PerlArray_class_init(); + Parrot_SchemePair_class_init(); } /* Index: vtable.tbl =================================================================== RCS file: /cvs/public/parrot/vtable.tbl,v retrieving revision 1.10 diff -u -r1.10 vtable.tbl --- vtable.tbl 18 Dec 2001 07:05:00 -0000 1.10 +++ vtable.tbl 6 Jan 2002 19:17:55 -0000 @@ -51,3 +51,7 @@ unique void logical_not PMC* value str void match PMC* value REGEX* re str void repeat PMC* value PMC* dest + +unique void set_pmc_index PMC* value INTVAL index +unique PMC* get_pmc_index INTVAL index + Index: classes/.cvsignore =================================================================== RCS file: /cvs/public/parrot/classes/.cvsignore,v retrieving revision 1.2 diff -u -r1.2 .cvsignore --- classes/.cvsignore 11 Dec 2001 12:03:23 -0000 1.2 +++ classes/.cvsignore 6 Jan 2002 19:17:55 -0000 @@ -1,3 +1,4 @@ Makefile *.c default.h +*.h Index: classes/Makefile.in =================================================================== RCS file: /cvs/public/parrot/classes/Makefile.in,v retrieving revision 1.12 diff -u -r1.12 Makefile.in --- classes/Makefile.in 4 Jan 2002 02:29:18 -0000 1.12 +++ classes/Makefile.in 6 Jan 2002 19:17:55 -0000 @@ -5,7 +5,7 @@ H_FILES = $(INC)/parrot.h default.h -O_FILES = default$(O) perlint$(O) perlstring$(O) perlnum$(O) perlarray$(O) perlundef$(O) +O_FILES = default$(O) perlint$(O) perlstring$(O) perlnum$(O) perlarray$(O) +perlundef$(O) schemepair$(O) #DO NOT ADD C COMPILER FLAGS HERE #Add them in Configure.pl--look for the @@ -52,6 +52,11 @@ $(PERL) pmc2c.pl perlundef.pmc perlundef$(O): $(H_FILES) + +schemepair.c schemepair.h: schemepair.pmc + $(PERL) pmc2c.pl schemepair.pmc + +schemepair$(O): $(H_FILES) clean: $(RM_F) *.c *$(O) default.h Index: classes/default.pmc =================================================================== RCS file: /cvs/public/parrot/classes/default.pmc,v retrieving revision 1.5 diff -u -r1.5 default.pmc --- classes/default.pmc 1 Jan 2002 22:55:47 -0000 1.5 +++ classes/default.pmc 6 Jan 2002 19:17:56 -0000 @@ -544,4 +544,10 @@ value->vtable->get_integer(INTERP, value), NULL) ); } + void set_pmc_index (PMC * value, INTVAL index) { + } + + PMC* get_pmc_index (INTVAL index) { + } + } Index: classes/perlarray.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlarray.pmc,v retrieving revision 1.2 diff -u -r1.2 perlarray.pmc --- classes/perlarray.pmc 4 Jan 2002 16:09:01 -0000 1.2 +++ classes/perlarray.pmc 6 Jan 2002 19:17:56 -0000 @@ -15,7 +15,7 @@ pmclass PerlArray { INTVAL type () { - return 0; + return enum_class_PerlArray; } STRING* name() { Index: classes/perlint.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlint.pmc,v retrieving revision 1.12 diff -u -r1.12 perlint.pmc --- classes/perlint.pmc 4 Jan 2002 16:09:01 -0000 1.12 +++ classes/perlint.pmc 6 Jan 2002 19:17:56 -0000 @@ -15,7 +15,7 @@ pmclass PerlInt { INTVAL type () { - return 0; + return enum_class_PerlInt; } STRING* name() { Index: classes/perlnum.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlnum.pmc,v retrieving revision 1.13 diff -u -r1.13 perlnum.pmc --- classes/perlnum.pmc 4 Jan 2002 16:09:01 -0000 1.13 +++ classes/perlnum.pmc 6 Jan 2002 19:17:56 -0000 @@ -15,7 +15,7 @@ pmclass PerlNum { INTVAL type () { - return 0; + return enum_class_PerlNum; } STRING* name() { Index: classes/perlstring.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlstring.pmc,v retrieving revision 1.13 diff -u -r1.13 perlstring.pmc --- classes/perlstring.pmc 4 Jan 2002 16:09:01 -0000 1.13 +++ classes/perlstring.pmc 6 Jan 2002 19:17:56 -0000 @@ -15,7 +15,7 @@ pmclass PerlString { INTVAL type () { - return 0; + return enum_class_PerlString; } STRING* name() { Index: classes/perlundef.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlundef.pmc,v retrieving revision 1.3 diff -u -r1.3 perlundef.pmc --- classes/perlundef.pmc 4 Jan 2002 16:09:01 -0000 1.3 +++ classes/perlundef.pmc 6 Jan 2002 19:17:57 -0000 @@ -15,6 +15,7 @@ pmclass PerlUndef { INTVAL type () { + return enum_class_PerlUndef; } STRING* name () { Index: include/parrot/pmc.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/pmc.h,v retrieving revision 1.9 diff -u -r1.9 pmc.h --- include/parrot/pmc.h 18 Dec 2001 07:05:01 -0000 1.9 +++ include/parrot/pmc.h 6 Jan 2002 19:17:57 -0000 @@ -19,6 +19,7 @@ enum_class_PerlNum, enum_class_PerlString, enum_class_PerlArray, + enum_class_SchemePair, enum_class_max }; VAR_SCOPE VTABLE Parrot_base_vtables[enum_class_max]; Index: languages/scheme/Scheme/Generator.pm =================================================================== RCS file: /cvs/public/parrot/languages/scheme/Scheme/Generator.pm,v retrieving revision 1.1 diff -u -r1.1 Generator.pm --- languages/scheme/Scheme/Generator.pm 24 Oct 2001 19:27:20 -0000 1.1 +++ languages/scheme/Scheme/Generator.pm 6 Jan 2002 19:17:58 -0000 @@ -3,6 +3,9 @@ use strict; use Data::Dumper; +sub PerlUndef { 0 } +sub SchemePair { 5 } + sub _gensym { return sprintf "G%04d",shift->{gensym}++; } @@ -11,7 +14,6 @@ my $self = shift; push @{$self->{instruction}},[@_]; } - #------------------------------------ my $regs = { @@ -39,6 +41,12 @@ @temp; } +sub _save_1 { + my $type = shift || 'I'; + my @temp = _save 1, $type; + $temp[0]; +} + sub _restore { die "Nothing to restore" unless defined @_; @@ -92,7 +100,7 @@ my $return; my $label = $self->_gensym(); - $return = "I"._save(1,'I'); + $return = "I"._save(1,'I'); my $cond = $self->_generate($node->{children}[0]); $self->_add_inst('','eq',[$cond,0,"FALSE_$label"]); my $true = $self->_generate($node->{children}[1]); @@ -194,34 +202,206 @@ sub _op_equal_p { } -sub _op_pair { +sub _op_pair_p { + my ($self,$node) = @_; + my $return; + + print STDERR "pair?: wrong number of arguments\n" + unless $#{$node->{children}} == 0; + + $return = $self->_constant(0); + + my $temp = $self->_generate($node->{children}->[0]); + if ($temp =~ m/^P/) { + my $type = _save_1('I'); + my $label = $self->_gensym(); + + $self->_add_inst ('', 'get_type', [$type,$temp]); + $self->_add_inst ('', 'ne', [SchemePair,$type,"DONE_$label"]); + $self->_add_inst ('', 'set', [$return,'1']); + $self->_add_inst("DONE_$label"); + _restore ($type); + } + + _restore($temp); + return $return; } sub _op_cons { + my ($self, $node) = @_; + my $return; + + print STDERR "cons: wrong number of arguments\n" + unless $#{$node->{children}} == 1; + + my $car = $self->_generate($node->{children}->[0]); + $return = _save_1('P'); + $self->_add_inst ('', 'new', [$return,'SchemePair']); + if ($car =~ m/^P/) { # FIXME: This is for the strange order index in set + $self->_add_inst ('', 'set', [$return,'0',$car]); + } + else { + $self->_add_inst ('', 'set', [$return,$car,'0']); + } + _restore ($car); + + my $cdr = $self->_generate($node->{children}->[1]); + if ($cdr =~ m/^P/) { + $self->_add_inst ('', 'set', [$return,'1',$cdr]); + } + else { + $self->_add_inst ('', 'set', [$return,$cdr,'1']); + } + _restore ($cdr); + + return $return; } sub _op_car { + my ($self, $node) = @_; + my $return; + + print STDERR "car: wrong number of arguments\n" + unless $#{$node->{children}} == 0; + + my $temp = $self->_generate($node->{children}->[0]); + $return = _save_1('P'); + $self->_add_inst ('', 'set', [$return,$temp,'0']); + _restore ($temp); + + return $return; } sub _op_cdr { + my ($self, $node) = @_; + my $return; + + print STDERR "cdr: wrong number of arguments\n" + unless $#{$node->{children}} == 0; + + my $temp = $self->_generate($node->{children}->[0]); + $return = _save_1('P'); + $self->_add_inst ('', 'set', [$return,$temp,'1']); + _restore ($temp); + + return $return; } sub _op_set_car { + my ($self, $node) = @_; + + print STDERR "set-cdr!: wrong number of arguments\n" + unless $#{$node->{children}} == 1; + + my $pair = $self->_generate($node->{children}->[0]); + my $value = $self->_generate($node->{children}->[1]); + + if ($value =~ m/^P/) { + $self->_add_inst ('', 'set', [$pair, '0', $value]); + } + else { + $self->_add_inst ('', 'set', [$pair, $value, '0']); + } + _restore ($value); + + return $pair; # FIXME: This value should be unspecified } sub _op_set_cdr { + my ($self, $node) = @_; + + print STDERR "set-cdr!: wrong number of arguments\n" + unless $#{$node->{children}} == 1; + + my $pair = $self->_generate($node->{children}->[0]); + my $value = $self->_generate($node->{children}->[1]); + + if ($value =~ m/^P/) { + $self->_add_inst ('', 'set', [$pair, '1', $value]); + } + else { + $self->_add_inst ('', 'set', [$pair, $value, '1']); + } + _restore ($value); + + return $pair; # FIXME: This value should be unspecified } -sub _op_null { +sub _op_null_p { + my ($self, $node) = @_; + my $return; + + print STDERR "null?: wrong number of arguments\n" + unless $#{$node->{children}} == 0; + + my $temp = $self->_generate($self->{children}->[0]); + $return = $self->constant(0); + if ( $temp =~ m/^P/) { + my $label = $self->_gensym(); + my $type = _save_1('1'); + + $self->_add_inst ('', 'get_type', [$type, $temp]); + $self->_add_inst ('', 'ne', [$type, PerlUndef, "DONE_$label"]); + $self->_add_inst ('', 'set', [$return, '1']); + _restore ($type); + } + + _restore ($temp); + + return $return; } sub _op_list_p { } sub _op_list { + my ($self, $node) = @_; + my $return = _save_1 ('P'); + + $self->_add_inst ('', 'new', [$return, 'PerlUndef']); + + if ($node->{children}) { + my $item; + my $lastitem; + for (my $i = $#{$node->{children}}; $i >= 0; $i--) { + $item = $self->_generate ($node->{children}->[$i]); + $lastitem = _save_1 ('P'); + $self->_add_inst ('', 'new', [$lastitem, 'SchemePair']); + $self->_add_inst ('', 'set', [$lastitem, '1', $return]); + if ($item =~ m/^P/) { + $self->_add_inst ('', 'set', [$lastitem, '0', $item]); + } else { + $self->_add_inst ('', 'set', [$lastitem, $item, '0']); + } + $self->_add_inst ('', 'set', [$return, $lastitem]); + _restore ($item, $lastitem); + } + } + + return $return; } sub _op_length { + my ($self,$node) = @_; + my $return; + my $label = $self->_gensym(); + + print STDERR "length: wrong number of arguments\n" + unless $#{$node->{children}} == 0; + + $return = $self->_constant(0); + + my $list = $self->_generate($node->{children}->[0]); + my $type = _save_1('I'); + $self->_add_inst("LOOP_$label", 'get_type', [$type,$list]); + $self->_add_inst('', 'ne', [$type,SchemePair,"DONE_$label"]); + $self->_add_inst('', 'inc', [$return]); + $self->_add_inst('', 'set', [$list,$list,'1']); + $self->_add_inst('', 'branch', ["LOOP_$label"]); + $self->_add_inst("DONE_$label"); + _restore ($list, $type); + + return $return } sub _op_append { @@ -1019,8 +1199,8 @@ 'cons' => \&_op_cons, 'car' => \&_op_car, 'cdr' => \&_op_cdr, - 'set-car!' => \&_op_set_car_bang, - 'set-cdr!' => \&_op_set_cdr_bang, + 'set-car!' => \&_op_set_car, + 'set-cdr!' => \&_op_set_cdr, # Not adding caar/cadr/cdar/whatever 'null?' => \&_op_null_p, 'list?' => \&_op_list_p, @@ -1322,10 +1502,11 @@ sub generate { my $self = shift; my @temp = _save(1); - $self->_generate($self->{tree},$temp[0]); #die Dumper($self->{tree}); + $self->_generate($self->{tree},$temp[0]); _restore(@temp); $self->_add_inst('',"end"); +# print STDERR Dumper $self->{instruction}; $self->_format_columns(); } Index: languages/scheme/Scheme/Tokenizer.pm =================================================================== RCS file: /cvs/public/parrot/languages/scheme/Scheme/Tokenizer.pm,v retrieving revision 1.1 diff -u -r1.1 Tokenizer.pm --- languages/scheme/Scheme/Tokenizer.pm 24 Oct 2001 19:27:20 -0000 1.1 +++ languages/scheme/Scheme/Tokenizer.pm 6 Jan 2002 19:17:58 -0000 @@ -34,6 +34,9 @@ } elsif($ch eq '?' and $token =~ /^[a-z]/) { # Question marks can follow an identifier $token .= $ch; + } elsif($ch eq '!' and + $token =~ /^[a-z]/) { # Exclamaition marks can follow an identifier + $token .= $ch; } elsif($ch eq '=' and $token =~ /^[<>]/) { # Equal sign can follow '<','>' $token .= $ch; Index: languages/scheme/t/harness =================================================================== RCS file: /cvs/public/parrot/languages/scheme/t/harness,v retrieving revision 1.1 diff -u -r1.1 harness --- languages/scheme/t/harness 24 Oct 2001 19:27:20 -0000 1.1 +++ languages/scheme/t/harness 6 Jan 2002 19:17:58 -0000 @@ -4,5 +4,5 @@ use Test::Harness qw(runtests); use lib '../..'; -my @tests = map { glob( "t/$_/*.t" ) } ( qw(io arith logic) ); +my @tests = map { glob( "t/$_/*.t" ) } ( qw(io arith logic lists) ); runtests( @tests );