Compare commits

..

9 Commits

Author SHA1 Message Date
Aryadev Chavali
698b2b96b1 vec: switch to pointer to u8 instead of void pointer for vec_data
No issues with indexing this by byte, right?
2026-02-03 18:55:46 +00:00
Aryadev Chavali
0162dcc709 Switch to Makefile for build system 2026-02-03 18:55:13 +00:00
Aryadev Chavali
6ec0108566 vec: is_inlined -> not_inlined
If you allocate a vector on the stack and default initialise
it (i.e. {0}), then by default "is_inlined" = 0.  This is bad, as
technically speaking we should expect the vector to attempt to use
it's small inline buffer for vector operations before going onto the
heap - this will mess up our functions.  So here I adjust the name to
make default stack based allocation a bit easier.
2026-01-22 16:37:58 +00:00
Aryadev Chavali
865ab22fdc Make VEC_GET take an index along with the type
Since most use cases require indexing the data directly, and the macro
implies you're retrieving data from it, may as well take the index.

If you wanted a pointer to that data, &VEC_GET(vec, index, type) works
just fine.
2026-01-21 09:48:29 +00:00
Aryadev Chavali
8c190e955d Make conses a vector, add VEC_SIZE macro
Easier to iterate through, O(1) amortized registering just like the
Linked List.

VEC_SIZE just makes it easier to iterate through a vector of specially
typed elements.
2026-01-21 09:45:36 +00:00
Aryadev Chavali
2ec1dfa083 Move some stuff around for cleanliness 2026-01-21 09:33:35 +00:00
Aryadev Chavali
bb55895e94 Test program to read all whitespace delimited tokens in a text file 2026-01-21 09:27:59 +00:00
Aryadev Chavali
eda23c8278 More comments and helpful explanations 2026-01-21 09:27:43 +00:00
Aryadev Chavali
dae6382f4b Added stream_till and stream_while helpers
Allows more abstract movement around the stream.
2026-01-21 09:27:12 +00:00
14 changed files with 176 additions and 114 deletions

View File

@@ -1,6 +1,6 @@
;;; Directory Local Variables -*- no-byte-compile: t -*- ;;; Directory Local Variables -*- no-byte-compile: t -*-
;;; For more information see (info "(emacs) Directory Variables") ;;; For more information see (info "(emacs) Directory Variables")
((nil . ((compile-command . "sh build.sh") ((nil . ((compile-command . "make MODE=debug")
(+license/license-choice . "Unlicense"))) (+license/license-choice . "Unlicense")))
(c-mode . ((mode . clang-format)))) (c-mode . ((mode . clang-format))))

5
.gitignore vendored
View File

@@ -1,5 +1,4 @@
*.o build/
*.out
.cache/ .cache/
compile_commands.json compile_commands.json
TAGS TAGS

51
Makefile Normal file
View File

@@ -0,0 +1,51 @@
CC=cc
DIST=build
OUT=$(DIST)/alisp.out
UNITS=main.c $(shell find ./runtime -type 'f')
OBJECTS:=$(patsubst %.c, $(DIST)/%.o, $(UNITS))
LDFLAGS=
GFLAGS=-Wall -Wextra -Wpedantic -std=c23 -I./
DFLAGS=-ggdb -fsanitize=address -fsanitize=undefined
RFLAGS=-O3
MODE=release
ifeq ($(MODE), release)
CFLAGS=$(GFLAGS) $(RFLAGS)
else
CFLAGS=$(GFLAGS) $(DFLAGS)
endif
# Dependency generation
DEPFLAGS=-MT $@ -MMD -MP -MF
DEPDIR=$(DIST)/deps
$(OUT): $(OBJECTS) | $(DIST)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
$(DIST)/%.o: %.c | $(DIST) $(DEPDIR)
$(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c -o $@ $<
$(DIST):
mkdir -p $(DIST) $(DIST)/runtime
$(DEPDIR):
mkdir -p $(DEPDIR)
mkdir -p $(DEPDIR)/runtime
clangd: compile_commands.json
compile_commands.json: Makefile
bear -- $(MAKE) -B MODE=debug
.PHONY: run clean examples
ARGS=
run: $(OUT)
./$^ $(ARGS)
clean:
rm -rf $(DIST)
DEPS:=$(patsubst %.c,$(DEPDIR)/%.d, $(UNITS))
include $(wildcard $(DEPS))

60
alisp.h
View File

@@ -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,29 +41,32 @@ 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)})
#define SV_FMT(SV) (int)(SV).size, (SV).data // Pretty printers
#define PR_SV "%.*s" #define SV_FMT(SV) (int)(SV).size, (SV).data
#define PRD_SV "%d@%p" #define PR_SV "%.*s"
#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;
u8 is_inlined; // Small buffer optimisation
u8 not_inlined;
union union
{ {
void *ptr; void *ptr;
@@ -70,13 +74,14 @@ 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, I, T) (((T *)vec_data(V))[I])
#define VEC_SIZE(V, T) ((V)->size / (sizeof(T)))
void vec_init(vec_t *, u64); void vec_init(vec_t *, u64);
void vec_free(vec_t *); void vec_free(vec_t *);
void *vec_data(vec_t *); u8 *vec_data(vec_t *);
void vec_ensure_free(vec_t *, u64); void vec_ensure_free(vec_t *, u64);
void vec_append(vec_t *, const void *const, u64); void vec_append(vec_t *, const void *const, u64);
void vec_clone(vec_t *, vec_t *); void vec_clone(vec_t *, vec_t *);
@@ -91,15 +96,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,20 +153,27 @@ 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);
/// Basic defintions for a Lisp // Skip forward in stream till one of the characters in the given C string is
// encountered.
sv_t stream_till(stream_t *, const char *);
// Skip forward in stream while one of the characters in the given C string is
// present.
sv_t stream_while(stream_t *, const char *);
/// 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
@@ -168,10 +181,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; vec_t memory;
sym_table_t symtable; sym_table_t symtable;
} sys_t; } sys_t;
@@ -196,8 +209,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
@@ -208,6 +220,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,
@@ -216,6 +229,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,
@@ -224,6 +238,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)
@@ -232,7 +247,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 *);
@@ -245,7 +259,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

View File

@@ -1,38 +0,0 @@
#!/usr/bin/env sh
set -xe
CFLAGS="-Wall -Wextra -std=c11 -ggdb -fsanitize=address -fsanitize=undefined -Wswitch -Wswitch-enum"
LINK="-I."
LIB=$(find "./" -name "*.c" -not -name "main.c" -not -name "test.c")
OUT="alisp.out"
build() {
cc $LINK $CFLAGS -o $OUT $LIB main.c;
cc $LINK $CFLAGS -o test.out $LIB test.c;
}
clean() {
rm -v $OUT test.out;
}
run() {
./$OUT;
}
test() {
./test.out
}
build
if [ "$1" = "run" ]
then
run
elif [ "$1" = "test" ]
then
test
elif [ "$1" = "clean" ]
then
clean
fi

19
main.c
View File

@@ -18,12 +18,25 @@
#include "./alisp.h" #include "./alisp.h"
const char *TOKEN_DELIM = "\n ";
int main(void) int main(void)
{ {
char filename[] = "./lorem.txt";
FILE *fp = fopen(filename, "r");
stream_t stream = {0}; stream_t stream = {0};
stream_init_pipe(&stream, "<stdin>", stdin); stream_init_file(&stream, filename, fp);
sv_t sv = stream_substr(&stream, 10);
printf("=> `" PR_SV "`\n", SV_FMT(sv)); for (u64 token_no = 1; !stream_eoc(&stream); ++token_no)
{
// Skip forward any delimiters
stream_while(&stream, TOKEN_DELIM);
// Get the token (up until delimiter)
sv_t token = stream_till(&stream, TOKEN_DELIM);
printf("%s[%lu] => `" PR_SV "`\n", stream.name, token_no, SV_FMT(token));
}
stream_stop(&stream); stream_stop(&stream);
fclose(fp);
return 0; return 0;
} }

View File

@@ -14,7 +14,7 @@
#include <malloc.h> #include <malloc.h>
#include "./alisp.h" #include "../alisp.h"
lisp_t *make_int(i64 i) lisp_t *make_int(i64 i)
{ {

View File

@@ -15,7 +15,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "./alisp.h" #include "../alisp.h"
stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents) stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents)
{ {
@@ -191,7 +191,7 @@ char stream_peek(stream_t *stream)
// Cached already? We are done. // Cached already? We are done.
if (stream->position < stream->pipe.cache.size) if (stream->position < stream->pipe.cache.size)
{ {
const char *const str = vec_data(&stream->pipe.cache); const char *const str = (char *)vec_data(&stream->pipe.cache);
return str[stream->position]; return str[stream->position];
} }
@@ -301,7 +301,7 @@ sv_t stream_substr(stream_t *stream, u64 size)
break; break;
case STREAM_TYPE_PIPE: case STREAM_TYPE_PIPE:
case STREAM_TYPE_FILE: case STREAM_TYPE_FILE:
ptr = vec_data(&stream->pipe.cache); ptr = (char *)vec_data(&stream->pipe.cache);
break; break;
default: default:
FAIL("Unreachable"); FAIL("Unreachable");
@@ -323,7 +323,7 @@ sv_t stream_substr_abs(stream_t *stream, u64 index, u64 size)
case STREAM_TYPE_FILE: case STREAM_TYPE_FILE:
{ {
if (index + size <= stream_size(stream)) if (index + size <= stream_size(stream))
return SV(vec_data(&stream->pipe.cache) + index, size); return SV((char *)vec_data(&stream->pipe.cache) + index, size);
// (index + size > stream_size(stream)) => try reading chunks // (index + size > stream_size(stream)) => try reading chunks
for (bool read_chunk = stream_chunk(stream); for (bool read_chunk = stream_chunk(stream);
read_chunk && index + size >= stream->pipe.cache.size; read_chunk && index + size >= stream->pipe.cache.size;
@@ -332,10 +332,38 @@ sv_t stream_substr_abs(stream_t *stream, u64 index, u64 size)
if (index + size > stream_size(stream)) if (index + size > stream_size(stream))
return SV(NULL, 0); return SV(NULL, 0);
return SV(vec_data(&stream->pipe.cache) + index, size); return SV((char *)vec_data(&stream->pipe.cache) + index, size);
} }
default: default:
assert("Unreachable"); assert("Unreachable");
return SV(NULL, 0); return SV(NULL, 0);
} }
} }
sv_t stream_till(stream_t *stream, const char *str)
{
if (stream_eoc(stream))
return SV(NULL, 0);
u64 current_position = stream->position;
for (char c = stream_peek(stream); c != '\0' && strchr(str, c) == NULL;
c = stream_next(stream))
continue;
u64 size = stream->position - current_position;
if (size == 0)
return SV(NULL, 0);
return stream_substr_abs(stream, current_position, size - 1);
}
sv_t stream_while(stream_t *stream, const char *str)
{
if (stream_eoc(stream))
return SV(NULL, 0);
u64 current_position = stream->position;
for (char c = stream_peek(stream); c != '\0' && strchr(str, c);
c = stream_next(stream))
continue;
u64 size = stream->position - current_position;
if (size == 0)
return SV(NULL, 0);
return stream_substr_abs(stream, current_position, size - 1);
}

View File

@@ -16,7 +16,7 @@
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include "./alisp.h" #include "../alisp.h"
sv_t sv_copy(sv_t old) sv_t sv_copy(sv_t old)
{ {

View File

@@ -12,7 +12,7 @@
* Description: Symbol Table implementation * Description: Symbol Table implementation
*/ */
#include "./alisp.h" #include "../alisp.h"
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@@ -41,22 +41,22 @@ char *sym_table_find(sym_table_t *table, sv_t sv)
// TODO: Deal with resizing this when table->count > table->size / 2 // TODO: Deal with resizing this when table->count > table->size / 2
u64 index = djb2(sv) & (table->capacity - 1); u64 index = djb2(sv) & (table->capacity - 1);
for (sv_t comp = VEC_GET(&table->entries, sv_t)[index]; comp.data; index += 1, for (sv_t comp = VEC_GET(&table->entries, index, sv_t); comp.data; index += 1,
index = index & (table->capacity - 1), index = index & (table->capacity - 1),
comp = VEC_GET(&table->entries, sv_t)[index]) comp = VEC_GET(&table->entries, index, sv_t))
// Is it present in the table? // Is it present in the table?
if (sv.size == comp.size && strncmp(sv.data, comp.data, sv.size) == 0) if (sv.size == comp.size && strncmp(sv.data, comp.data, sv.size) == 0)
break; break;
// we couldn't find it in our linear search (worst case scenario) // we couldn't find it in our linear search (worst case scenario)
if (!VEC_GET(&table->entries, sv_t)[index].data) if (!VEC_GET(&table->entries, index, sv_t).data)
{ {
sv_t newsv = sv_copy(sv); sv_t newsv = sv_copy(sv);
VEC_GET(&table->entries, sv_t)[index] = newsv; VEC_GET(&table->entries, index, sv_t) = newsv;
++table->count; ++table->count;
} }
return VEC_GET(&table->entries, sv_t)[index].data; return VEC_GET(&table->entries, index, sv_t).data;
} }
void sym_table_cleanup(sym_table_t *table) void sym_table_cleanup(sym_table_t *table)
@@ -65,7 +65,7 @@ void sym_table_cleanup(sym_table_t *table)
sv_t current = {0}; sv_t current = {0};
for (u64 i = 0; i < table->capacity; ++i) for (u64 i = 0; i < table->capacity; ++i)
{ {
current = VEC_GET(&table->entries, sv_t)[i]; current = VEC_GET(&table->entries, i, sv_t);
if (current.data) if (current.data)
free(current.data); free(current.data);
} }

View File

@@ -12,7 +12,7 @@
* Description: System management * Description: System management
*/ */
#include "./alisp.h" #include "../alisp.h"
#include <assert.h> #include <assert.h>
#include <malloc.h> #include <malloc.h>
@@ -21,15 +21,13 @@
void sys_init(sys_t *sys) void sys_init(sys_t *sys)
{ {
memset(sys, 0, sizeof(*sys)); memset(sys, 0, sizeof(*sys));
vec_init(&sys->conses, 0);
} }
void sys_register(sys_t *sys, lisp_t *ptr) void sys_register(sys_t *sys, lisp_t *ptr)
{ {
// Generate an unmanaged cons // Simply append it to the list of currently active conses
cons_t *cons = calloc(1, sizeof(*cons)); vec_append(&sys->conses, &ptr, sizeof(&ptr));
cons->car = ptr;
cons->cdr = sys->memory;
sys->memory = tag_cons(cons);
} }
void sys_cleanup(sys_t *sys) void sys_cleanup(sys_t *sys)
@@ -37,18 +35,13 @@ void sys_cleanup(sys_t *sys)
static_assert(NUM_TAGS == 5); static_assert(NUM_TAGS == 5);
sym_table_cleanup(&sys->symtable); sym_table_cleanup(&sys->symtable);
if (sys->conses.size == 0)
if (!sys->memory)
return; return;
// Iterate through each element of memory // Iterate through each cons currently allocated and free them
for (lisp_t *cell = sys->memory, *next = cdr(cell); cell; for (size_t i = 0; i < VEC_SIZE(&sys->conses, lisp_t **); ++i)
cell = next, next = cdr(next))
{ {
// Only reason allocated exists is because we had to allocate memory on the lisp_t *allocated = VEC_GET(&sys->conses, i, lisp_t *);
// heap for it. It's therefore enough to deal with only the allocated
// types.
lisp_t *allocated = car(cell);
switch (get_tag(allocated)) switch (get_tag(allocated))
{ {
case TAG_CONS: case TAG_CONS:
@@ -69,9 +62,11 @@ void sys_cleanup(sys_t *sys)
// shouldn't be dealt with (either constant or dealt with elsewhere) // shouldn't be dealt with (either constant or dealt with elsewhere)
break; break;
} }
// Then free the current cell
free(as_cons(cell));
} }
// Free the container
vec_free(&sys->conses);
// Ensure no one treats this as active in any sense
memset(sys, 0, sizeof(*sys)); memset(sys, 0, sizeof(*sys));
} }

View File

@@ -15,7 +15,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include "./alisp.h" #include "../alisp.h"
lisp_t *tag_int(i64 i) lisp_t *tag_int(i64 i)
{ {

View File

@@ -16,7 +16,7 @@
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include "./alisp.h" #include "../alisp.h"
void vec_init(vec_t *vec, u64 size) void vec_init(vec_t *vec, u64 size)
{ {
@@ -25,15 +25,15 @@ void vec_init(vec_t *vec, u64 size)
return; return;
else if (size <= VEC_INLINE_CAPACITY) else if (size <= VEC_INLINE_CAPACITY)
{ {
vec->is_inlined = 1; vec->not_inlined = 0;
vec->capacity = VEC_INLINE_CAPACITY; vec->capacity = VEC_INLINE_CAPACITY;
vec->ptr = NULL; vec->ptr = NULL;
} }
else else
{ {
vec->is_inlined = 0; vec->not_inlined = 1;
vec->capacity = size; vec->capacity = size;
vec->ptr = calloc(1, vec->capacity); vec->ptr = calloc(1, vec->capacity);
} }
} }
@@ -41,14 +41,14 @@ void vec_free(vec_t *vec)
{ {
if (!vec) if (!vec)
return; return;
if (!vec->is_inlined && vec->ptr) if (vec->not_inlined && vec->ptr)
free(vec->ptr); free(vec->ptr);
memset(vec, 0, sizeof(*vec)); memset(vec, 0, sizeof(*vec));
} }
void *vec_data(vec_t *vec) u8 *vec_data(vec_t *vec)
{ {
return vec->is_inlined ? vec->inlined : vec->ptr; return vec->not_inlined ? vec->ptr : vec->inlined;
} }
void vec_ensure_free(vec_t *vec, u64 size) void vec_ensure_free(vec_t *vec, u64 size)
@@ -58,7 +58,7 @@ void vec_ensure_free(vec_t *vec, u64 size)
if (vec->capacity - vec->size < size) if (vec->capacity - vec->size < size)
{ {
vec->capacity = MAX(vec->capacity * VEC_MULT, vec->size + size); vec->capacity = MAX(vec->capacity * VEC_MULT, vec->size + size);
if (vec->is_inlined) if (!vec->not_inlined)
{ {
// If we're inlined, we need to allocate on the heap now. So let's copy // If we're inlined, we need to allocate on the heap now. So let's copy
// vec->inlined over to vec->ptr, then turn off inlining. // vec->inlined over to vec->ptr, then turn off inlining.
@@ -69,7 +69,7 @@ void vec_ensure_free(vec_t *vec, u64 size)
memcpy(buffer, vec->inlined, vec->size); memcpy(buffer, vec->inlined, vec->size);
vec->ptr = calloc(1, vec->capacity); vec->ptr = calloc(1, vec->capacity);
memcpy(vec->ptr, buffer, vec->size); memcpy(vec->ptr, buffer, vec->size);
vec->is_inlined = 0; vec->not_inlined = 1;
} }
else else
vec->ptr = realloc(vec->ptr, vec->capacity); vec->ptr = realloc(vec->ptr, vec->capacity);

View File

@@ -16,7 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "./alisp.h" #include "../alisp.h"
#define TEST_PASSED() printf("[%s]: Pass\n", __func__) #define TEST_PASSED() printf("[%s]: Pass\n", __func__)
#define TEST(NAME, COND) \ #define TEST(NAME, COND) \