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:
parent
655526afac
commit
2e77d2beb6
23
Makefile
Normal file
23
Makefile
Normal 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
156
src/conspage.c
Normal 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
36
src/conspage.h
Normal 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
14
src/consspaceobject.c
Normal 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
116
src/consspaceobject.h
Normal 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
22
src/init.c
Normal 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
19
src/quickbool.h
Normal 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
12
src/version.h
Normal 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"
|
Loading…
Reference in a new issue