diff --git a/src/conspage.c b/src/conspage.c index 77187b9..22a53e3 100644 --- a/src/conspage.c +++ b/src/conspage.c @@ -152,13 +152,7 @@ struct cons_pointer allocate_cell( char* tag) { if ( strncmp( &cell->tag.bytes[0], FREETAG, TAGLENGTH) == 0) { freelist = cell->payload.free.cdr; - fprintf( stderr, "Before: %c%c%c%c (%d)\n", - cell->tag.bytes[0], cell->tag.bytes[1], cell->tag.bytes[2], - cell->tag.bytes[3], cell->tag.value); strncpy( &cell->tag.bytes[0], tag, 4); - fprintf( stderr, "After: %c%c%c%c (%d)\n", - cell->tag.bytes[0], cell->tag.bytes[1], cell->tag.bytes[2], - cell->tag.bytes[3], cell->tag.value); cell->count = 0; cell->payload.cons.car = NIL; diff --git a/src/init.c b/src/init.c index f3d442d..98ece93 100644 --- a/src/init.c +++ b/src/init.c @@ -18,17 +18,15 @@ #include "read.h" int main (int argc, char *argv[]) { - printf( "Post scarcity software environment version %s\n", VERSION); + // printf( "Post scarcity software environment version %s\n", VERSION); initialise_cons_pages(); - printf( "Ready\n>> "); - struct cons_pointer input = read( stdin); - inc_ref( input); - printf( "\n:: "); + //inc_ref( input); + //printf( "\n:: "); print( stdout, input); - dump_pages(stdout); + // dump_pages(stdout); // printf( "Tag2uint(\"FREE\") = %d\n", tag2uint("FREE")); return(0); diff --git a/src/print.c b/src/print.c index 6e0452e..f26514a 100644 --- a/src/print.c +++ b/src/print.c @@ -39,7 +39,11 @@ void print( FILE* output, struct cons_pointer pointer) { for (struct cons_pointer p = pointer; stringp( p); p = pointer2cell( p).payload.string.cdr) { // TODO: That's potentially a UTF character, needs more handling. - fprintf( output, "%c", (char)pointer2cell( p).payload.string.character); + char c = (char)pointer2cell( p).payload.string.character; + + if ( c != '\0') { + fprintf( output, "%c", c); + } } fputc( '"', output); } else if ( check_tag( pointer, TRUETAG)) { diff --git a/src/read.c b/src/read.c index a5236f1..2354420 100644 --- a/src/read.c +++ b/src/read.c @@ -9,6 +9,7 @@ */ #include +#include #include #include "consspaceobject.h" @@ -21,67 +22,29 @@ lists Can't read atoms because I don't yet know what an atom is or how it's stored. */ -/** - * read a number from this input stream, given this initial character. - */ -struct cons_pointer read_number( FILE* input, char initial) { - int accumulator = 0; - char c; - - for (c = initial; isdigit( c); c = fgetc( input)) { - int digitvalue = (int)c - (int)'0'; - accumulator = accumulator * 10 + digitvalue; - } - - /* push back the character read which was not a digit */ - fputc( c, input); - - return make_integer( accumulator); -} - - -struct cons_pointer read_list( FILE* input) { - struct cons_pointer car = read( input); - struct cons_pointer cdr = NIL; - - char c = fgetc( input); - - if ( c != ')' ) { - cdr = read_list( input); - } - - return make_cons( car, cdr); -} - - -struct cons_pointer read_string( FILE* input) { - struct cons_pointer cdr = NIL; - struct cons_pointer result= NIL; - - char c = fgetc( input); - - if ( c != '"' ) { - result = make_string( c, read_string( input)); - } - - return result; -} +struct cons_pointer read_number( FILE* input, char initial); +struct cons_pointer read_list( FILE* input, char initial); +struct cons_pointer read_string( FILE* input, char initial); /** - * read the next object on this input stream and return a cons_pointer to it. + * Read the next object on this input stream and return a cons_pointer to it, + * treating this initial character as the first character of the object + * representation. */ -struct cons_pointer read( FILE* input) { +struct cons_pointer read_continuation( FILE* input, char initial) { struct cons_pointer result = NIL; char c; - for (c = fgetc( input); isblank( c); c = fgetc( input)); + for (c = initial; c == '\0' || isblank( c); c = fgetc( input)); switch( c) { - case '(' : result = read_list(input); + case '(' : + case ')': + result = read_list(input, fgetc( input)); break; - case '"': result = read_string(input); + case '"': result = read_string(input, fgetc( input)); break; case '0': case '1': @@ -102,6 +65,92 @@ struct cons_pointer read( FILE* input) { return result; } + + +/** + * read a number from this input stream, given this initial character. + */ +struct cons_pointer read_number( FILE* input, char initial) { + int accumulator = 0; + int places_of_decimals = 0; + bool seen_period = false; + char c; + + fprintf( stderr, "read_number starting '%c' (%d)\n", initial, initial); + + for (c = initial; isdigit( c); c = fgetc( input)) { + if ( c == '.') { + seen_period = true; + } else { + accumulator = accumulator * 10 + ((int)c - (int)'0'); + + if ( seen_period) { + places_of_decimals ++; + } + } + } + + /* push back the character read which was not a digit */ + fputc( c, input); + + return make_integer( accumulator); +} + + +/** + * Read a list from this input stream, which no longer contains the opening + * left parenthesis. + */ +struct cons_pointer read_list( FILE* input, char initial) { + struct cons_pointer cdr = NIL; + struct cons_pointer result= NIL; + + fprintf( stderr, "read_list starting '%c' (%d)\n", initial, initial); + + if ( initial != ')' ) { + struct cons_pointer car = read_continuation( input, initial); + cdr = read_list( input, fgetc( input)); + result = make_cons( car, cdr); + } + + return result; +} + + +/** + * Read a string from this input stream, which no longer contains the opening + * double quote. Note that there is (for now) a problem with the list + * representation of a string, which is that there's no obvious representation of + * an empty string. + */ +struct cons_pointer read_string( FILE* input, char initial) { + struct cons_pointer cdr = NIL; + struct cons_pointer result; + + fprintf( stderr, "read_string starting '%c' (%d)\n", initial, initial); + + switch ( initial) { + case '\0': + result = make_string( initial, NIL); + break; + case '"': + result = make_string( '\0', NIL); + break; + default: + result = make_string( initial, read_string( input, fgetc( input))); + break; + } + + return result; +} + + +/** + * Read the next object on this input stream and return a cons_pointer to it. + */ +struct cons_pointer read( FILE* input) { + return read_continuation( input, '\0'); +} diff --git a/unit-tests.sh b/unit-tests.sh new file mode 100755 index 0000000..da99fa6 --- /dev/null +++ b/unit-tests.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Early stage unit test runner for post-scarcity software environment. +# Uses bash to run every file in the unit-tests subdirectory; expects these +# to return 0 on success, anything else on fail. + +# (c) 2017 Simon Brooke +# Licensed under GPL version 2.0, or, at your option, any later version. + +tests=0 +pass=0 +fail=0 + +for file in unit-tests/* +do + echo ${file} + bash ${file} + + if [ $? -eq 0 ] + then + pass=$((${pass} + 1)) + else + fail=$((${fail} + 1)) + fi + + tests=$((${tests} + 1)) +done + +echo +echo "Tested ${tests}, passed ${pass}, failed ${fail}" + +exit ${fail} + diff --git a/unit-tests/empty-string.sh b/unit-tests/empty-string.sh new file mode 100644 index 0000000..c8e947a --- /dev/null +++ b/unit-tests/empty-string.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +expected="\"\"" +actual=`echo '""' | target/psse 2> /dev/null` + +if [ "$expected" = "$actual" ] +then + echo "OK" + exit 0 +else + echo "Expected '$expected', got '$actual'" + exit 1 +fi diff --git a/unit-tests/fred.sh b/unit-tests/fred.sh new file mode 100644 index 0000000..2be3096 --- /dev/null +++ b/unit-tests/fred.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +expected=\"Fred\" +actual=`echo '"Fred"' | target/psse 2> /dev/null` + +if [ "$expected" = "$actual" ] +then + echo "OK" + exit 0 +else + echo "Expected '$expected', got '$actual'" + exit 1 +fi diff --git a/unit-tests/nil.sh b/unit-tests/nil.sh new file mode 100644 index 0000000..249c51b --- /dev/null +++ b/unit-tests/nil.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +expected=NIL +actual=`echo '()' | target/psse 2> /dev/null` + +if [ "${expected}" = "${actual}" ] +then + echo "OK" + exit 0 +else + echo "Expected '${expected}', got '${actual}'" + exit 1 +fi