More comments and helpful explanations
This commit is contained in:
38
alisp.h
38
alisp.h
@@ -22,7 +22,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/// The bare fucking minimum
|
/// Essential macros
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
#define ARRSIZE(A) (sizeof(A) / sizeof((A)[0]))
|
#define ARRSIZE(A) (sizeof(A) / sizeof((A)[0]))
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#define FAIL(MSG) assert(false && "FAIL: " #MSG)
|
#define FAIL(MSG) assert(false && "FAIL: " #MSG)
|
||||||
#define TODO(MSG) assert(false && "TODO: " #MSG)
|
#define TODO(MSG) assert(false && "TODO: " #MSG)
|
||||||
|
|
||||||
|
/// Numeric aliases
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
@@ -40,28 +41,31 @@ typedef int16_t i16;
|
|||||||
typedef int32_t i32;
|
typedef int32_t i32;
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
|
|
||||||
/// String Views for my String Needs
|
/// String Views
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u64 size;
|
u64 size;
|
||||||
char *data;
|
char *data;
|
||||||
} sv_t;
|
} sv_t;
|
||||||
|
|
||||||
|
// String view macro constructor
|
||||||
#define SV(DATA, SIZE) ((sv_t){.data = (DATA), .size = (SIZE)})
|
#define SV(DATA, SIZE) ((sv_t){.data = (DATA), .size = (SIZE)})
|
||||||
|
// Pretty printers
|
||||||
#define SV_FMT(SV) (int)(SV).size, (SV).data
|
#define SV_FMT(SV) (int)(SV).size, (SV).data
|
||||||
#define PR_SV "%.*s"
|
#define PR_SV "%.*s"
|
||||||
#define PRD_SV "%d@%p"
|
#define PRD_SV "%d@%p"
|
||||||
|
|
||||||
|
// String view functions
|
||||||
sv_t sv_copy(sv_t);
|
sv_t sv_copy(sv_t);
|
||||||
|
|
||||||
/// Dynamic arrays
|
/// Dynamic arrays
|
||||||
|
|
||||||
#define VEC_INLINE_CAPACITY 32
|
#define VEC_INLINE_CAPACITY 32
|
||||||
#define VEC_MULT 2
|
#define VEC_MULT 2
|
||||||
|
|
||||||
typedef struct Vector
|
typedef struct Vector
|
||||||
{
|
{
|
||||||
u64 size, capacity;
|
u64 size, capacity;
|
||||||
|
// Small buffer optimisation
|
||||||
u8 is_inlined;
|
u8 is_inlined;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@@ -70,7 +74,7 @@ typedef struct Vector
|
|||||||
};
|
};
|
||||||
} vec_t;
|
} vec_t;
|
||||||
|
|
||||||
static_assert(sizeof(vec_t) == 64, "vec_t has to be 64 bytes");
|
static_assert(sizeof(vec_t) == 64, "vec_t has to be 64 bytes as part of SBO");
|
||||||
|
|
||||||
#define VEC_GET(V, T) ((T *)vec_data(V))
|
#define VEC_GET(V, T) ((T *)vec_data(V))
|
||||||
|
|
||||||
@@ -91,15 +95,16 @@ typedef struct
|
|||||||
|
|
||||||
#define SYM_TABLE_INIT_SIZE (1 << 10)
|
#define SYM_TABLE_INIT_SIZE (1 << 10)
|
||||||
|
|
||||||
u64 djb2(sv_t string);
|
|
||||||
void sym_table_init(sym_table_t *);
|
void sym_table_init(sym_table_t *);
|
||||||
char *sym_table_find(sym_table_t *, sv_t);
|
char *sym_table_find(sym_table_t *, sv_t);
|
||||||
void sym_table_cleanup(sym_table_t *);
|
void sym_table_cleanup(sym_table_t *);
|
||||||
|
// Hashing algorithm
|
||||||
|
u64 djb2(sv_t string);
|
||||||
|
|
||||||
/// Streams
|
/// Streams
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
STREAM_TYPE_STRING,
|
STREAM_TYPE_STRING = 0,
|
||||||
STREAM_TYPE_PIPE,
|
STREAM_TYPE_PIPE,
|
||||||
STREAM_TYPE_FILE,
|
STREAM_TYPE_FILE,
|
||||||
} stream_type_t;
|
} stream_type_t;
|
||||||
@@ -147,15 +152,14 @@ u64 stream_size(stream_t *);
|
|||||||
char stream_next(stream_t *);
|
char stream_next(stream_t *);
|
||||||
// Peek current character, do not push position
|
// Peek current character, do not push position
|
||||||
char stream_peek(stream_t *);
|
char stream_peek(stream_t *);
|
||||||
// Seek forward or backward in the stream, return success
|
// Move forward or backward in the stream, return success of operation
|
||||||
bool stream_seek(stream_t *, i64);
|
bool stream_seek(stream_t *, i64);
|
||||||
bool stream_seek_forward(stream_t *, u64);
|
bool stream_seek_forward(stream_t *, u64);
|
||||||
bool stream_seek_backward(stream_t *, u64);
|
bool stream_seek_backward(stream_t *, u64);
|
||||||
|
|
||||||
// Return a relative substring (using sv_t) of a given size
|
// Return a relative substring of a given size
|
||||||
sv_t stream_substr(stream_t *, u64);
|
sv_t stream_substr(stream_t *, u64);
|
||||||
// Return an absolutely located substring (using sv_t) at given index and of
|
// Return an absolute substring at given index and of given size.
|
||||||
// given size.
|
|
||||||
sv_t stream_substr_abs(stream_t *, u64, u64);
|
sv_t stream_substr_abs(stream_t *, u64, u64);
|
||||||
|
|
||||||
// Skip forward in stream till one of the characters in the given C string is
|
// Skip forward in stream till one of the characters in the given C string is
|
||||||
@@ -168,6 +172,7 @@ sv_t stream_while(stream_t *, const char *);
|
|||||||
/// Lisp type definitions
|
/// Lisp type definitions
|
||||||
#define NIL 0
|
#define NIL 0
|
||||||
|
|
||||||
|
// Opaque object for tagged pointers
|
||||||
typedef struct Obj lisp_t;
|
typedef struct Obj lisp_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -175,10 +180,10 @@ typedef struct
|
|||||||
lisp_t *car, *cdr;
|
lisp_t *car, *cdr;
|
||||||
} cons_t;
|
} cons_t;
|
||||||
|
|
||||||
/// System context - essentially something to help with system management
|
/// System context
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
lisp_t *memory;
|
lisp_t *conses;
|
||||||
sym_table_t symtable;
|
sym_table_t symtable;
|
||||||
} sys_t;
|
} sys_t;
|
||||||
|
|
||||||
@@ -203,8 +208,7 @@ vec_t *as_vec(lisp_t *);
|
|||||||
lisp_t *car(lisp_t *);
|
lisp_t *car(lisp_t *);
|
||||||
lisp_t *cdr(lisp_t *);
|
lisp_t *cdr(lisp_t *);
|
||||||
|
|
||||||
/// Pointer tagging scheme for lisps
|
/// Tagging scheme
|
||||||
|
|
||||||
typedef enum Tag
|
typedef enum Tag
|
||||||
{
|
{
|
||||||
TAG_NIL = 0b00000000, // Start of atomic types
|
TAG_NIL = 0b00000000, // Start of atomic types
|
||||||
@@ -215,6 +219,7 @@ typedef enum Tag
|
|||||||
NUM_TAGS = 5,
|
NUM_TAGS = 5,
|
||||||
} tag_t;
|
} tag_t;
|
||||||
|
|
||||||
|
static_assert(NUM_TAGS == 5, "Expected NUM_TAGS == 5 for enum SHIFT");
|
||||||
enum Shift
|
enum Shift
|
||||||
{
|
{
|
||||||
SHIFT_INT = 1,
|
SHIFT_INT = 1,
|
||||||
@@ -223,6 +228,7 @@ enum Shift
|
|||||||
SHIFT_VEC = 8,
|
SHIFT_VEC = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(NUM_TAGS == 5, "Expected NUM_TAGS == 5 for enum MASK");
|
||||||
enum Mask
|
enum Mask
|
||||||
{
|
{
|
||||||
MASK_INT = 0b00000001,
|
MASK_INT = 0b00000001,
|
||||||
@@ -231,6 +237,7 @@ enum Mask
|
|||||||
MASK_VEC = 0b11111111,
|
MASK_VEC = 0b11111111,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Some helper macros for tagging
|
||||||
#define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE))
|
#define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE))
|
||||||
#define IS_TAG(PTR, TYPE) (((u64)(PTR) & MASK_##TYPE) == TAG_##TYPE)
|
#define IS_TAG(PTR, TYPE) (((u64)(PTR) & MASK_##TYPE) == TAG_##TYPE)
|
||||||
#define UNTAG(PTR, TYPE) (((u64)PTR) >> SHIFT_##TYPE)
|
#define UNTAG(PTR, TYPE) (((u64)PTR) >> SHIFT_##TYPE)
|
||||||
@@ -239,7 +246,6 @@ enum Mask
|
|||||||
#define INT_MIN (-(1L << 62))
|
#define INT_MIN (-(1L << 62))
|
||||||
|
|
||||||
tag_t get_tag(lisp_t *);
|
tag_t get_tag(lisp_t *);
|
||||||
|
|
||||||
lisp_t *tag_int(i64);
|
lisp_t *tag_int(i64);
|
||||||
lisp_t *tag_sym(char *);
|
lisp_t *tag_sym(char *);
|
||||||
lisp_t *tag_cons(cons_t *);
|
lisp_t *tag_cons(cons_t *);
|
||||||
@@ -252,7 +258,7 @@ typedef enum
|
|||||||
} read_err_t;
|
} read_err_t;
|
||||||
|
|
||||||
// Attempt to read an expression from the stream, storing it in a pointer,
|
// Attempt to read an expression from the stream, storing it in a pointer,
|
||||||
// returning any errors if failed
|
// returning any errors if failed.
|
||||||
read_err_t read(sys_t *, stream_t *, lisp_t **);
|
read_err_t read(sys_t *, stream_t *, lisp_t **);
|
||||||
|
|
||||||
// Attempt to read all expressions from a stream till end of content, storing
|
// Attempt to read all expressions from a stream till end of content, storing
|
||||||
|
|||||||
8
sys.c
8
sys.c
@@ -28,8 +28,8 @@ void sys_register(sys_t *sys, lisp_t *ptr)
|
|||||||
// Generate an unmanaged cons
|
// Generate an unmanaged cons
|
||||||
cons_t *cons = calloc(1, sizeof(*cons));
|
cons_t *cons = calloc(1, sizeof(*cons));
|
||||||
cons->car = ptr;
|
cons->car = ptr;
|
||||||
cons->cdr = sys->memory;
|
cons->cdr = sys->conses;
|
||||||
sys->memory = tag_cons(cons);
|
sys->conses = tag_cons(cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_cleanup(sys_t *sys)
|
void sys_cleanup(sys_t *sys)
|
||||||
@@ -38,11 +38,11 @@ void sys_cleanup(sys_t *sys)
|
|||||||
|
|
||||||
sym_table_cleanup(&sys->symtable);
|
sym_table_cleanup(&sys->symtable);
|
||||||
|
|
||||||
if (!sys->memory)
|
if (!sys->conses)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Iterate through each element of memory
|
// Iterate through each element of memory
|
||||||
for (lisp_t *cell = sys->memory, *next = cdr(cell); cell;
|
for (lisp_t *cell = sys->conses, *next = cdr(cell); cell;
|
||||||
cell = next, next = cdr(next))
|
cell = next, next = cdr(next))
|
||||||
{
|
{
|
||||||
// Only reason allocated exists is because we had to allocate memory on the
|
// Only reason allocated exists is because we had to allocate memory on the
|
||||||
|
|||||||
Reference in New Issue
Block a user