Added first cut of reader and writer, but nothing working at this stage.

This commit is contained in:
Simon Brooke 2017-01-06 22:49:04 +00:00
parent 0e693d4360
commit 5920b0d04f
12 changed files with 413 additions and 36 deletions

View file

@ -27,7 +27,13 @@
bool conspageinitihasbeencalled = false;
/**
* The (global) pointer to the (global) freelist. Not sure whether this ultimately belongs in this file.
* the number of cons pages which have thus far been initialised.
*/
int initialisedconspages = 0;
/**
* The (global) pointer to the (global) freelist. Not sure whether this ultimately
* belongs in this file.
*/
struct cons_pointer freelist = NIL;
@ -36,11 +42,6 @@ struct cons_pointer freelist = NIL;
*/
struct cons_page* conspages[NCONSPAGES];
/**
* the number of cons pages which have thus far been initialised.
*/
int initialisedconspages = 0;
/**
* Make a cons page whose serial number (i.e. index in the conspages directory) is pageno.
@ -55,21 +56,21 @@ void makeconspage() {
if ( initialisedconspages == 0 && i < 2) {
if ( i == 0) {
/* initialise cell as NIL */
strncpy( result->cell[i].tag, NILTAG, 4);
result->cell[i].count = (2 ^ 32) - 1; // should be max value of unsigned 32 bit integer
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;
} else if ( i == 1) {
/* initialise cell as T */
strncpy( result->cell[i].tag, TRUETAG, 4);
result->cell[i].count = (2 ^ 32) - 1; // should be max value of unsigned 32 bit integer
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};
}
}
/* otherwise, standard initialisation */
strncpy( result->cell[i].tag, FREETAG, 4);
strncpy( result->cell[i].tag, FREETAG, TAGLENGTH);
result->cell[i].payload.free.car = NIL;
result->cell[i].payload.free.cdr = freelist;
freelist.page = initialisedconspages;
@ -85,6 +86,20 @@ void makeconspage() {
}
/**
* dump the allocated pages to this output stream.
*/
void dumppages( FILE* output) {
for ( int i = 0; i < initialisedconspages; i++) {
fprintf( output, "\nDUMPING PAGE %d\n", i);
for ( int j = 0; j < CONSPAGESIZE; j++) {
dump_object( output, (struct cons_pointer){i, j});
}
}
}
/**
* Frees the cell at the specified pointer. Dangerous, primitive, low
* level.
@ -129,10 +144,17 @@ struct cons_pointer allocatecell( char* tag) {
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]);
cell.count = 1;
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);
}
return result;

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 256
#define CONSPAGESIZE 64
/**
* 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 256
#define NCONSPAGES 64
/**
* a cons page is essentially just an array of cons space objects. It might later have a local
@ -28,9 +28,45 @@ struct cons_page {
};
/**
* The (global) pointer to the (global) freelist. Not sure whether this ultimately
* belongs in this file.
*/
extern struct cons_pointer freelist;
/**
* An array of pointers to cons pages.
*/
extern struct cons_page* conspages[NCONSPAGES];
/**
* Frees the cell at the specified pointer. Dangerous, primitive, low
* level.
*
* @pointer the cell to free
*/
void free_cell(struct cons_pointer pointer);
/**
* Allocates a cell with the specified tag. Dangerous, primitive, low
* level.
*
* @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);
/**
* initialise the cons page system; to be called exactly once during startup.
*/
void conspagesinit();
/**
* dump the allocated pages to this output stream.
*/
void dumppages( FILE* output);
#endif

View file

@ -8,7 +8,76 @@
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "conspage.h"
#include "consspaceobject.h"
/**
* increment the reference count of the object at this cons pointer.
*
* 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);
if (cell.count < MAXREFERENCE) {
cell.count ++;
}
}
/**
* Decrement the reference count of the object at this cons 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);
if (cell.count < MAXREFERENCE) {
cell.count --;
if (cell.count == 0) {
free_cell( 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",
pointer.page,
pointer.offset,
tag,
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) {
fprintf( output, "\t\tInteger cell: value %ld\n", cell.payload.integer.value);
} else if ( strncmp( tag, FREETAG, TAGLENGTH) == 0) {
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) {
fprintf( output, "\t\tReal cell: value %Lf\n", cell.payload.real.value);
} else if ( strncmp( tag, STRINGTAG, TAGLENGTH) == 0) {
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);
};
}

View file

@ -8,8 +8,8 @@
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdint.h>
#include <stdio.h>
#ifndef __consspaceobject_h
#define __consspaceobject_h
@ -38,11 +38,33 @@
*/
#define NIL (struct cons_pointer){ 0, 0}
/**
* the maximum possible value of a reference count
*/
#define MAXREFERENCE ((2 ^ 32) - 1)
/**
* a macro to convert a tag into a number
*/
#define tag2uint(tag) ((uint32_t)*tag)
#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)
/**
* true if conspointer points to a cons cell, else false
*/
#define consp(conspoint) (strncmp(pointer2cell(conspoint).tag, CONSTAG, TAGLENGTH)==0)
/**
* true if conspointer points to a string cell, else false
*/
#define stringp(conspoint) (strncmp(pointer2cell(conspoint).tag, STRINGTAG, TAGLENGTH)==0)
/**
* An indirect pointer to a cons cell
@ -76,7 +98,7 @@ struct free_payload {
* optional bignum object.
*/
struct integer_payload {
long int integer;
long int value;
};
@ -85,7 +107,7 @@ struct integer_payload {
* precision, but I'm not sure of the detail.
*/
struct real_payload {
long double real;
long double value;
};
/**
@ -123,4 +145,21 @@ struct cons_space_object {
};
/**
* increment the reference count of the object at this cons pointer
*/
void incref( struct cons_pointer pointer);
/**
* decrement the reference count of the object at this cons pointer
*/
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);
#endif

View file

@ -14,11 +14,21 @@
#include "version.h"
#include "conspage.h"
#include "consspaceobject.h"
#include "print.h"
#include "read.h"
int main (int argc, char *argv[]) {
printf( "Post scarcity software environment version %s\n", VERSION);
conspagesinit();
printf( "Ready\n>>");
struct cons_pointer input = read( stdin);
incref( input);
printf( "\n");
print( stdout, input);
dumppages(stdout);
// printf( "Tag2uint(\"FREE\") = %d\n", tag2uint("FREE"));
return(0);

24
src/integer.c Normal file
View file

@ -0,0 +1,24 @@
/**
* integer.c
*
* functions for integer cells.
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "conspage.h"
#include "consspaceobject.h"
#include "read.h"
/**
* 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;
return result;
}

19
src/integer.h Normal file
View file

@ -0,0 +1,19 @@
/**
* integer.h
*
* functions for integer cells.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __integer_h
#define __integer_h
/**
* Allocate an integer cell representing this value and return a cons pointer to it.
*/
struct cons_pointer makeinteger( int value);
#endif

47
src/print.c Normal file
View file

@ -0,0 +1,47 @@
/**
* print.c
*
* First pass at a printer, for bootstrapping.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "conspage.h"
#include "consspaceobject.h"
#include "integer.h"
#include "print.h"
void print( FILE* output, struct cons_pointer pointer) {
struct cons_space_object cell = pointer2cell( pointer);
if ( strncmp( cell.tag, CONSTAG, TAGLENGTH) == 0) {
fputc( '(', output);
for (struct cons_pointer p = pointer; consp( p);
p = pointer2cell( p).payload.cons.cdr) {
print( output, p);
fputc( ' ', output);
}
fputc( ')', output);
} else if ( strncmp( cell.tag, INTEGERTAG, TAGLENGTH) == 0) {
fprintf( output, " %ld", cell.payload.integer.value);
} else if ( strncmp( cell.tag, NILTAG, TAGLENGTH) == 0) {
fprintf( output, "NIL");
} else if ( strncmp( cell.tag, REALTAG, TAGLENGTH) == 0) {
fprintf( output, "%Lf", cell.payload.real.value);
} else if ( strncmp( cell.tag, STRINGTAG, TAGLENGTH) == 0) {
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);
}
fputc( '"', output);
} else if ( strncmp( cell.tag, TRUETAG, TAGLENGTH) == 0) {
fprintf( output, "T");
}
}

19
src/print.h Normal file
View file

@ -0,0 +1,19 @@
/**
* print.h
*
* First pass at a printer, for bootstrapping.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <ctype.h>
#include <stdio.h>
#ifndef __print_h
#define __print_h
void print( FILE* output, struct cons_pointer pointer);
#endif

View file

@ -1,19 +0,0 @@
/**
* quickbool.h
*
* Currently, just a macro to test whether a cons_pointer is the
* special NIL cons_pointer.
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "consspaceobject.h"
#ifndef __quickbool_h
#define __quickbool_h
/* true if conspointer points to the special cell NIL, else false */
#define nilp(conspoint) ((((struct cons_pointer)conspoint).page == NIL.page) && ((struct conspoint).offser == NIL.offset))
#endif

92
src/read.c Normal file
View file

@ -0,0 +1,92 @@
/**
* read.c
*
* First pass at a reader, for bootstrapping.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <ctype.h>
#include <stdio.h>
#include "consspaceobject.h"
#include "integer.h"
#include "read.h"
/* for the time being things which may be read are:
strings
numbers - either integer or real, but not yet including ratios or bignums
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 readnumber( 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 makeinteger( accumulator);
}
struct cons_pointer readlist( FILE* input) {
return NIL;
}
struct cons_pointer readstring( FILE* input) {
return NIL;
}
/**
* read the next object on this input stream and return a cons_pointer to it.
*/
struct cons_pointer read( FILE* input) {
struct cons_pointer result = NIL;
char c = fgetc( input);
while ( isblank( c)) {
c = fgetc( input);
}
switch( c) {
case '(' : result = readlist(input);
break;
case '"': result = readstring(input);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// case '.':
result = readnumber( input, c);
break;
default:
fprintf( stderr, "Unrecognised start of input character %c\n", c);
}
return result;
}

19
src/read.h Normal file
View file

@ -0,0 +1,19 @@
/**
* read.c
*
* First pass at a reader, for bootstrapping.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __read_h
#define __read_h
/**
* read the next object on this input stream and return a cons_pointer to it.
*/
struct cons_pointer read( FILE* input);
#endif