Reads, stores and prints numbers correctly. Reads and stores lists and

strings, but they don't print correctly.
This commit is contained in:
Simon Brooke 2017-01-07 02:17:54 +00:00
parent 5920b0d04f
commit 85cc542d74
9 changed files with 226 additions and 125 deletions

View file

@ -29,7 +29,7 @@ bool conspageinitihasbeencalled = false;
/**
* the number of cons pages which have thus far been initialised.
*/
int initialisedconspages = 0;
int initialised_cons_pages = 0;
/**
* The (global) pointer to the (global) freelist. Not sure whether this ultimately
@ -48,49 +48,54 @@ struct cons_page* conspages[NCONSPAGES];
* Initialise all cells and prepend each to the freelist; if pageno is zero, do not prepend
* cells 0 and 1 to the freelist but initialise them as NIL and T respectively.
*/
void makeconspage() {
void make_cons_page() {
struct cons_page* result = malloc( sizeof( struct cons_page));
if ( result != NULL) {
conspages[initialised_cons_pages] = result;
for (int i = 0; i < CONSPAGESIZE; i++) {
if ( initialisedconspages == 0 && i < 2) {
struct cons_space_object * cell = &conspages[initialised_cons_pages]->cell[i];
if ( initialised_cons_pages == 0 && i < 2) {
if ( i == 0) {
/* initialise cell as NIL */
strncpy( result->cell[i].tag, NILTAG, TAGLENGTH);
result->cell[i].count = MAXREFERENCE;
result->cell[i].payload.free.car = NIL;
result->cell[i].payload.free.cdr = NIL;
strncpy( &cell->tag.bytes[0], NILTAG, TAGLENGTH);
cell->count = MAXREFERENCE;
cell->payload.free.car = NIL;
cell->payload.free.cdr = NIL;
fprintf( stderr, "Allocated special cell NIL\n");
} else if ( i == 1) {
/* initialise cell as T */
strncpy( result->cell[i].tag, TRUETAG, TAGLENGTH);
result->cell[i].count = MAXREFERENCE;
result->cell[i].payload.free.car = (struct cons_pointer){ 0, 1};
result->cell[i].payload.free.cdr = (struct cons_pointer){ 0, 1};
strncpy( &cell->tag.bytes[0], TRUETAG, TAGLENGTH);
cell->count = MAXREFERENCE;
cell->payload.free.car = (struct cons_pointer){ 0, 1};
cell->payload.free.cdr = (struct cons_pointer){ 0, 1};
fprintf( stderr, "Allocated special cell T\n");
}
} else {
/* otherwise, standard initialisation */
strncpy( &cell->tag.bytes[0], FREETAG, TAGLENGTH);
cell->payload.free.car = NIL;
cell->payload.free.cdr = freelist;
freelist.page = initialised_cons_pages;
freelist.offset = i;
}
}
/* otherwise, standard initialisation */
strncpy( result->cell[i].tag, FREETAG, TAGLENGTH);
result->cell[i].payload.free.car = NIL;
result->cell[i].payload.free.cdr = freelist;
freelist.page = initialisedconspages;
freelist.offset = i;
}
initialised_cons_pages ++;
} else {
fprintf( stderr, "FATAL: Failed to allocate memory for cons page %d\n", initialisedconspages);
fprintf( stderr, "FATAL: Failed to allocate memory for cons page %d\n", initialised_cons_pages);
exit(1);
}
conspages[initialisedconspages] = result;
initialisedconspages++;
}
/**
* dump the allocated pages to this output stream.
*/
void dumppages( FILE* output) {
for ( int i = 0; i < initialisedconspages; i++) {
void dump_pages( FILE* output) {
for ( int i = 0; i < initialised_cons_pages; i++) {
fprintf( output, "\nDUMPING PAGE %d\n", i);
for ( int j = 0; j < CONSPAGESIZE; j++) {
@ -107,20 +112,22 @@ void dumppages( FILE* output) {
* @pointer the cell to free
*/
void free_cell(struct cons_pointer pointer) {
struct cons_space_object cell = conspages[pointer.page]->cell[pointer.offset];
struct cons_space_object* cell = &pointer2cell( pointer);
if ( strncmp( cell.tag, FREETAG, 4) != 0) {
if ( cell.count == 0) {
strncpy( cell.tag, FREETAG, 4);
cell.payload.free.car = NIL;
cell.payload.free.cdr = freelist;
if ( !check_tag(pointer, FREETAG)) {
if ( cell->count == 0) {
strncpy( &cell->tag.bytes[0], FREETAG, 4);
cell->payload.free.car = NIL;
cell->payload.free.cdr = freelist;
freelist = pointer;
} else {
fprintf( stderr, "Attempt to free cell with %d dangling references at page %d, offset %d\n",
cell.count, pointer.page, pointer.offset);
fprintf( stderr,
"Attempt to free cell with %d dangling references at page %d, offset %d\n",
cell->count, pointer.page, pointer.offset);
}
} else {
fprintf( stderr, "Attempt to free cell which is already FREE at page %d, offset %d\n",
fprintf( stderr,
"Attempt to free cell which is already FREE at page %d, offset %d\n",
pointer.page, pointer.offset);
}
}
@ -133,28 +140,36 @@ void free_cell(struct cons_pointer pointer) {
* @param tag the tag of the cell to allocate - must be a valid cons space tag.
* @return the cons pointer which refers to the cell allocated.
*/
struct cons_pointer allocatecell( char* tag) {
struct cons_pointer allocate_cell( char* tag) {
struct cons_pointer result = freelist;
if ( result.page == NIL.page && result.offset == NIL.offset) {
makeconspage();
result = allocatecell( tag);
make_cons_page();
result = allocate_cell( tag);
} else {
struct cons_space_object cell = conspages[result.page]->cell[result.offset];
struct cons_space_object* cell = &pointer2cell(result);
freelist = cell.payload.free.cdr;
if ( strncmp( &cell->tag.bytes[0], FREETAG, TAGLENGTH) == 0) {
freelist = cell->payload.free.cdr;
fprintf( stderr, "Before: %c\n", cell.tag[0]);
strncpy( cell.tag, tag, 4);
fprintf( stderr, "After: %c\n", cell.tag[0]);
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 = 1;
cell.payload.cons.car = NIL;
cell.payload.cons.cdr = NIL;
cell->count = 0;
cell->payload.cons.car = NIL;
cell->payload.cons.cdr = NIL;
fprintf( stderr, "Allocated cell of type '%s' at %d, %d \n",
tag, result.page, result.offset);
dump_object( stderr, result);
} else {
fprintf( stderr, "WARNING: Allocating non-free cell!");
}
}
return result;
@ -164,13 +179,13 @@ struct cons_pointer allocatecell( char* tag) {
/**
* initialise the cons page system; to be called exactly once during startup.
*/
void conspagesinit() {
void initialise_cons_pages() {
if ( conspageinitihasbeencalled == false) {
for (int i = 0; i < NCONSPAGES; i++) {
conspages[i] = (struct cons_page *) NULL;
}
makeconspage();
make_cons_page();
conspageinitihasbeencalled = true;
} else {
fprintf( stderr, "WARNING: conspageinit() called a second or subsequent time\n");

View file

@ -9,14 +9,14 @@
* the size which, by version 1, it will default to) is the maximum value of an unsigned 32
* bit integer, which is to say 4294967296. However, we'll start small.
*/
#define CONSPAGESIZE 64
#define CONSPAGESIZE 8
/**
* the number of cons pages we will initially allow for. For convenience we'll set up an array
* of cons pages this big; however, later we will want a mechanism for this to be able to grow
* dynamically to the maximum we can currently allow, which is 4294967296.
*/
#define NCONSPAGES 64
#define NCONSPAGES 8
/**
* a cons page is essentially just an array of cons space objects. It might later have a local
@ -56,17 +56,17 @@ void free_cell(struct cons_pointer pointer);
* @param tag the tag of the cell to allocate - must be a valid cons space tag.
* @return the cons pointer which refers to the cell allocated.
*/
struct cons_pointer allocatecell( char* tag);
struct cons_pointer allocate_cell( char* tag);
/**
* initialise the cons page system; to be called exactly once during startup.
*/
void conspagesinit();
void initialise_cons_pages();
/**
* dump the allocated pages to this output stream.
*/
void dumppages( FILE* output);
void dump_pages( FILE* output);
#endif

View file

@ -15,6 +15,14 @@
#include "conspage.h"
#include "consspaceobject.h"
/**
* Check that the tag on the cell at this pointer is this tag
*/
int check_tag( struct cons_pointer pointer, char* tag) {
struct cons_space_object cell = pointer2cell(pointer);
return strncmp( &cell.tag.bytes[0], tag, TAGLENGTH) == 0;
}
/**
* increment the reference count of the object at this cons pointer.
@ -22,11 +30,11 @@
* You can't roll over the reference count. Once it hits the maximum
* value you cannot increment further.
*/
void incref( struct cons_pointer pointer) {
struct cons_space_object cell = pointer2cell( pointer);
void inc_ref( struct cons_pointer pointer) {
struct cons_space_object* cell = &pointer2cell( pointer);
if (cell.count < MAXREFERENCE) {
cell.count ++;
if (cell->count < MAXREFERENCE) {
cell->count ++;
}
}
@ -37,13 +45,13 @@ void incref( struct cons_pointer pointer) {
* If a count has reached MAXREFERENCE it cannot be decremented.
* If a count is decremented to zero the cell should be freed.
*/
void decref( struct cons_pointer pointer) {
struct cons_space_object cell = pointer2cell( pointer);
void dec_ref( struct cons_pointer pointer) {
struct cons_space_object* cell = &pointer2cell( pointer);
if (cell.count < MAXREFERENCE) {
cell.count --;
if (cell->count <= MAXREFERENCE) {
cell->count --;
if (cell.count == 0) {
if (cell->count == 0) {
free_cell( pointer);
}
}
@ -54,30 +62,73 @@ void decref( struct cons_pointer pointer) {
* dump the object at this cons_pointer to this output stream.
*/
void dump_object( FILE* output, struct cons_pointer pointer) {
struct cons_space_object cell = conspages[pointer.page]->cell[pointer.offset];
char * tag = malloc( TAGLENGTH + 1);
memset( tag, 0, TAGLENGTH + 1);
strncpy( tag, cell.tag, TAGLENGTH);
fprintf( output, "\tDumping object at page %d, offset %d with tag %s, count %d\n",
struct cons_space_object cell = pointer2cell(pointer);
fprintf( output,
"\tDumping object at page %d, offset %d with tag %c%c%c%c (%d), count %u\n",
pointer.page,
pointer.offset,
tag,
cell.tag.bytes[0],
cell.tag.bytes[1],
cell.tag.bytes[2],
cell.tag.bytes[3],
cell.tag.value,
cell.count);
if ( strncmp( tag, CONSTAG, TAGLENGTH) == 0) {
fprintf( output, "\tCons cell: car at page %d offset %d, cdr at page %d offset %d\n",
cell.payload.cons.car.page, cell.payload.cons.car.offset, cell.payload.cons.cdr.page, cell.payload.cons.cdr.offset);
} else if ( strncmp( tag, INTEGERTAG, TAGLENGTH) == 0) {
if ( check_tag(pointer, CONSTAG)) {
fprintf( output,
"\tCons cell: car at page %d offset %d, cdr at page %d offset %d\n",
cell.payload.cons.car.page, cell.payload.cons.car.offset,
cell.payload.cons.cdr.page, cell.payload.cons.cdr.offset);
} else if ( check_tag(pointer, INTEGERTAG)) {
fprintf( output, "\t\tInteger cell: value %ld\n", cell.payload.integer.value);
} else if ( strncmp( tag, FREETAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, FREETAG)) {
fprintf( output, "\t\tFree cell: next at page %d offset %d\n",
cell.payload.cons.cdr.page, cell.payload.cons.cdr.offset);
} else if ( strncmp( tag, REALTAG, TAGLENGTH) == 0) {
} else if ( check_tag(pointer, REALTAG)) {
fprintf( output, "\t\tReal cell: value %Lf\n", cell.payload.real.value);
} else if ( strncmp( tag, STRINGTAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, STRINGTAG)) {
fprintf( output, "\t\tString cell: character '%c' next at page %d offset %d\n",
cell.payload.string.character, cell.payload.string.cdr.page,
cell.payload.string.cdr.offset);
};
}
/**
* Construct a cons cell from this pair of pointers.
*/
struct cons_pointer make_cons( struct cons_pointer car, struct cons_pointer cdr) {
struct cons_pointer pointer = allocate_cell( CONSTAG);
struct cons_space_object* cell = &conspages[pointer.page]->cell[pointer.offset];
inc_ref(car);
inc_ref(cdr);
cell->payload.cons.car = car;
cell->payload.cons.cdr = cdr;
return pointer;
}
/**
* Construct a string from this character (which later will be UTF) and
* this tail. A string is implemented as a flat list of cells each of which
* has one character and a pointer to the next; in the last cell the
* pointer to next is NIL.
*/
struct cons_pointer make_string( char c, struct cons_pointer tail) {
struct cons_pointer pointer = NIL;
if ( check_tag( tail, STRINGTAG) || check_tag( tail, NILTAG)) {
pointer = allocate_cell( STRINGTAG);
struct cons_space_object* cell = &conspages[pointer.page]->cell[pointer.offset];
inc_ref(tail);
cell->payload.string.character = (uint32_t) c;
cell->payload.string.cdr = tail;
} else {
fprintf( stderr, "Warning: only NIL and STRING can be appended to STRING\n");
}
return pointer;
}

View file

@ -41,7 +41,7 @@
/**
* the maximum possible value of a reference count
*/
#define MAXREFERENCE ((2 ^ 32) - 1)
#define MAXREFERENCE 4294967295
/**
* a macro to convert a tag into a number
@ -50,21 +50,20 @@
#define pointer2cell(pointer) ((conspages[pointer.page]->cell[pointer.offset]))
/**
* true if conspointer points to the special cell NIL, else false
*/
#define nilp(conspoint) (strncmp(pointer2cell(conspoint).tag, NILTAG, TAGLENGTH)==0)
#define nilp(conspoint) (check_tag(conspoint,NILTAG)==0)
/**
* true if conspointer points to a cons cell, else false
*/
#define consp(conspoint) (strncmp(pointer2cell(conspoint).tag, CONSTAG, TAGLENGTH)==0)
#define consp(conspoint) (check_tag(conspoint,CONSTAG)==0)
/**
* true if conspointer points to a string cell, else false
*/
#define stringp(conspoint) (strncmp(pointer2cell(conspoint).tag, STRINGTAG, TAGLENGTH)==0)
#define stringp(conspoint) (check_tag(conspoint,STRINGTAG)==0)
/**
* An indirect pointer to a cons cell
@ -123,7 +122,10 @@ struct string_payload {
* an object in cons space.
*/
struct cons_space_object {
char tag[TAGLENGTH]; /* the tag (type) of this cell */
union {
char bytes[TAGLENGTH]; /* the tag (type) of this cell, considered as bytes */
uint32_t value; /* the tag considered as a number */
} tag;
uint32_t count; /* the count of the number of references to this cell */
struct cons_pointer access; /* cons pointer to the access control list of this cell */
union {
@ -145,16 +147,22 @@ struct cons_space_object {
};
/**
* Check that the tag on the cell at this pointer is this tag
*/
int check_tag( struct cons_pointer pointer, char* tag);
/**
* increment the reference count of the object at this cons pointer
*/
void incref( struct cons_pointer pointer);
void inc_ref( struct cons_pointer pointer);
/**
* decrement the reference count of the object at this cons pointer
*/
void decref( struct cons_pointer pointer);
void dec_ref( struct cons_pointer pointer);
/**
@ -162,4 +170,14 @@ void decref( struct cons_pointer pointer);
*/
void dump_object( FILE* output, struct cons_pointer pointer);
struct cons_pointer make_cons( struct cons_pointer car, struct cons_pointer cdr);
/**
* Construct a string from this character (which later will be UTF) and
* this tail. A string is implemented as a flat list of cells each of which
* has one character and a pointer to the next; in the last cell the
* pointer to next is NIL.
*/
struct cons_pointer make_string( char c, struct cons_pointer tail);
#endif

View file

@ -19,16 +19,16 @@
int main (int argc, char *argv[]) {
printf( "Post scarcity software environment version %s\n", VERSION);
conspagesinit();
initialise_cons_pages();
printf( "Ready\n>> ");
struct cons_pointer input = read( stdin);
incref( input);
printf( "\n");
inc_ref( input);
printf( "\n:: ");
print( stdout, input);
dumppages(stdout);
dump_pages(stdout);
// printf( "Tag2uint(\"FREE\") = %d\n", tag2uint("FREE"));
return(0);

View file

@ -14,10 +14,10 @@
/**
* Allocate an integer cell representing this value and return a cons pointer to it.
*/
struct cons_pointer makeinteger( int value) {
struct cons_pointer result = allocatecell( INTEGERTAG);
struct cons_space_object cell = conspages[result.page]->cell[result.offset];
cell.payload.integer.value = value;
struct cons_pointer make_integer( int value) {
struct cons_pointer result = allocate_cell( INTEGERTAG);
struct cons_space_object* cell = &conspages[result.page]->cell[result.offset];
cell->payload.integer.value = value;
return result;
}

View file

@ -14,6 +14,6 @@
/**
* Allocate an integer cell representing this value and return a cons pointer to it.
*/
struct cons_pointer makeinteger( int value);
struct cons_pointer make_integer( int value);
#endif

View file

@ -20,7 +20,7 @@
void print( FILE* output, struct cons_pointer pointer) {
struct cons_space_object cell = pointer2cell( pointer);
if ( strncmp( cell.tag, CONSTAG, TAGLENGTH) == 0) {
if ( check_tag( pointer, CONSTAG)) {
fputc( '(', output);
for (struct cons_pointer p = pointer; consp( p);
p = pointer2cell( p).payload.cons.cdr) {
@ -28,20 +28,21 @@ void print( FILE* output, struct cons_pointer pointer) {
fputc( ' ', output);
}
fputc( ')', output);
} else if ( strncmp( cell.tag, INTEGERTAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, INTEGERTAG)) {
fprintf( output, " %ld", cell.payload.integer.value);
} else if ( strncmp( cell.tag, NILTAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, NILTAG)) {
fprintf( output, "NIL");
} else if ( strncmp( cell.tag, REALTAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, REALTAG)) {
fprintf( output, "%Lf", cell.payload.real.value);
} else if ( strncmp( cell.tag, STRINGTAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, STRINGTAG)) {
fputc( '"', output);
for (struct cons_pointer p = pointer; stringp( p);
p = pointer2cell( p).payload.string.cdr) {
fprintf( output, '%c', (char)pointer2cell( p).payload.string.character);
// TODO: That's potentially a UTF character, needs more handling.
fprintf( output, "%c", (char)pointer2cell( p).payload.string.character);
}
fputc( '"', output);
} else if ( strncmp( cell.tag, TRUETAG, TAGLENGTH) == 0) {
} else if ( check_tag( pointer, TRUETAG)) {
fprintf( output, "T");
}
}

View file

@ -24,7 +24,7 @@
/**
* read a number from this input stream, given this initial character.
*/
struct cons_pointer readnumber( FILE* input, char initial) {
struct cons_pointer read_number( FILE* input, char initial) {
int accumulator = 0;
char c;
@ -36,17 +36,35 @@ struct cons_pointer readnumber( FILE* input, char initial) {
/* push back the character read which was not a digit */
fputc( c, input);
return makeinteger( accumulator);
return make_integer( accumulator);
}
struct cons_pointer readlist( FILE* input) {
return NIL;
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 readstring( FILE* input) {
return NIL;
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;
}
@ -56,16 +74,14 @@ struct cons_pointer readstring( FILE* input) {
struct cons_pointer read( FILE* input) {
struct cons_pointer result = NIL;
char c = fgetc( input);
char c;
while ( isblank( c)) {
c = fgetc( input);
}
for (c = fgetc( input); isblank( c); c = fgetc( input));
switch( c) {
case '(' : result = readlist(input);
case '(' : result = read_list(input);
break;
case '"': result = readstring(input);
case '"': result = read_string(input);
break;
case '0':
case '1':
@ -78,7 +94,7 @@ struct cons_pointer read( FILE* input) {
case '8':
case '9':
// case '.':
result = readnumber( input, c);
result = read_number( input, c);
break;
default:
fprintf( stderr, "Unrecognised start of input character %c\n", c);