Having found rust wasn't going to work, I've hacked up a rough core of the

cons space in C. None of this is tested.
This commit is contained in:
simon 2017-01-06 15:25:16 +00:00
parent 655526afac
commit 2e77d2beb6
8 changed files with 398 additions and 0 deletions

23
Makefile Normal file
View file

@ -0,0 +1,23 @@
TARGET ?= target/psse
SRC_DIRS ?= ./src
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
OBJS := $(addsuffix .o,$(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
INC_DIRS := $(shell find $(SRC_DIRS) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
VERSION := "0.0.0"
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -DVERSION=$(VERSION) -o $@ $(LOADLIBES) $(LDLIBS)
.PHONY: clean
clean:
$(RM) $(TARGET) $(OBJS) $(DEPS)
-include $(DEPS)

156
src/conspage.c Normal file
View file

@ -0,0 +1,156 @@
/**
* conspage.c
*
* Setup and tear down cons pages, and (FOR NOW) do primitive
* allocation/deallocation of cells.
* NOTE THAT before we go multi-threaded, these functions must be
* aggressively
* thread safe.
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "consspaceobject.h"
#include "conspage.h"
/**
* Flag indicating whether conspage initialisation has been done.
*/
bool conspageinitihasbeencalled = false;
/**
* The (global) pointer to the (global) freelist. Not sure whether this ultimately belongs in this file.
*/
struct cons_pointer freelist = NIL;
/**
* An array of pointers to cons pages.
*/
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.
* 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() {
struct cons_page* result = malloc( sizeof( struct cons_page));
if ( result != NULL) {
for (int i = 0; i < CONSPAGESIZE; i++) {
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
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
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);
result->cell[i].payload.free.car = NIL;
result->cell[i].payload.free.cdr = freelist;
freelist.page = initialisedconspages;
freelist.offset = i;
}
} else {
fprintf( stderr, "FATAL: Failed to allocate memory for cons page %d\n", initialisedconspages);
exit(1);
}
conspages[initialisedconspages] = result;
initialisedconspages++;
}
/**
* Frees the cell at the specified pointer. Dangerous, primitive, low
* level.
*
* @pointer the cell to free
*/
void free_cell(struct cons_pointer pointer) {
struct cons_space_object cell = conspages[pointer.page]->cell[pointer.offset];
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;
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);
}
} else {
fprintf( stderr, "Attempt to free cell which is already FREE at page %d, offset %d\n",
pointer.page, pointer.offset);
}
}
/**
* 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) {
struct cons_pointer result = freelist;
if ( result.page == NIL.page && result.offset == NIL.offset) {
makeconspage();
result = allocatecell( tag);
} else {
struct cons_space_object cell = conspages[result.page]->cell[result.offset];
freelist = cell.payload.free.cdr;
strncpy( cell.tag, tag, 4);
cell.count = 1;
cell.payload.cons.car = NIL;
cell.payload.cons.cdr = NIL;
}
return result;
}
/**
* initialise the cons page system; to be called exactly once during startup.
*/
void conspagesinit() {
if ( conspageinitihasbeencalled == false) {
for (int i = 0; i < NCONSPAGES; i++) {
conspages[i] = (struct cons_page *) NULL;
}
makeconspage();
conspageinitihasbeencalled = true;
} else {
fprintf( stderr, "WARNING: conspageinit() called a second or subsequent time\n");
}
}

36
src/conspage.h Normal file
View file

@ -0,0 +1,36 @@
#include "consspaceobject.h"
#ifndef __conspage_h
#define __conspage_h
/**
* the number of cons cells on a cons page. The maximum value this can be (and consequently,
* 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
/**
* 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
/**
* a cons page is essentially just an array of cons space objects. It might later have a local
* free list (i.e. list of free cells on this page) and a pointer to the next cons page, but
* my current view is that that's probably unneccessary.
*/
struct cons_page {
struct cons_space_object cell[CONSPAGESIZE];
};
/**
* initialise the cons page system; to be called exactly once during startup.
*/
void conspagesinit();
#endif

14
src/consspaceobject.c Normal file
View file

@ -0,0 +1,14 @@
/**
* consspaceobject.c
*
* Structures common to all cons space objects.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdint.h>
#include "consspaceobject.h"

116
src/consspaceobject.h Normal file
View file

@ -0,0 +1,116 @@
/**
* consspaceobject.h
*
* Declarations common to all cons space objects.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdint.h>
#ifndef __consspaceobject_h
#define __consspaceobject_h
/**
* The length of a tag, in bytes.
*/
#define TAGLENGTH 4
/**
* tag values, all of which must be 4 bytes. Must not collide with vector space tag values
*/
#define CONSTAG "CONS"
#define FREETAG "FREE"
#define INTEGERTAG "INTR"
#define NILTAG "NIL "
#define READTAG "READ"
#define REALTAG "REAL"
#define STRINGTAG "STRG"
#define TRUETAG "TRUE"
#define VECTORPOINTTAG "VECP"
#define WRITETAG "WRIT"
/**
* a cons pointer which points to the special NIL cell
*/
#define NIL (struct cons_pointer){ 0, 0}
/**
* An indirect pointer to a cons cell
*/
struct cons_pointer {
uint32_t page; /* the index of the page on which this cell resides */
uint32_t offset; /* the index of the cell within the page */
};
/**
* payload of a cons cell.
*/
struct cons_payload {
struct cons_pointer car;
struct cons_pointer cdr;
};
/**
* payload of a free cell. For the time being identical to a cons cell,
* but it may not be so in future.
*/
struct free_payload {
struct cons_pointer car;
struct cons_pointer cdr;
};
/**
* payload of an integer cell. For the time being just a signed integer;
* later might be a signed 128 bit integer, or might have some flag to point to an
* optional bignum object.
*/
struct integer_payload {
long int integer;
};
/**
* payload for a real number cell. Internals of this liable to change to give 128 bits
* precision, but I'm not sure of the detail.
*/
struct real_payload {
long double real;
};
/**
* payload of a string cell. At least at first, only one UTF character will be stored in each cell.
*/
struct string_payload {
uint32_t character; /* the actual character stored in this cell */
uint32_t padding; /* unused padding to word-align the cdr */
struct cons_pointer cdr;
};
/**
* an object in cons space.
*/
struct cons_space_object {
char tag[TAGLENGTH]; /* the tag (type) of this cons cell */
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 {
/* if tag == CONSTAG */
struct cons_payload cons;
/* if tag == FREETAG */
struct free_payload free;
struct integer_payload integer;
struct cons_payload nil;
struct real_payload real;
struct string_payload string;
struct cons_payload t;
} payload;
};
#endif

22
src/init.c Normal file
View file

@ -0,0 +1,22 @@
/**
* init.c
*
* Start up and initialise the environement - just enough to get working and (ultimately)
* hand off to the executive.
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include "version.h"
#include "conspage.h"
int main (int argc, char *argv[]) {
printf( "Post scarcity software environment version %s\n", VERSION);
conspagesinit();
return(0);
}

19
src/quickbool.h Normal file
View file

@ -0,0 +1,19 @@
/**
* 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

12
src/version.h Normal file
View file

@ -0,0 +1,12 @@
/**
* version.h
*
* Just the version number. There's DEFINITELY a better way to do this!
*
*
* (c) 2017 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#define VERSION "0.0.0"