Compare commits
9 Commits
88c9d01677
...
698b2b96b1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
698b2b96b1 | ||
|
|
0162dcc709 | ||
|
|
6ec0108566 | ||
|
|
865ab22fdc | ||
|
|
8c190e955d | ||
|
|
2ec1dfa083 | ||
|
|
bb55895e94 | ||
|
|
eda23c8278 | ||
|
|
dae6382f4b |
@@ -1,6 +1,6 @@
|
||||
;;; Directory Local Variables -*- no-byte-compile: t -*-
|
||||
;;; For more information see (info "(emacs) Directory Variables")
|
||||
|
||||
((nil . ((compile-command . "sh build.sh")
|
||||
((nil . ((compile-command . "make MODE=debug")
|
||||
(+license/license-choice . "Unlicense")))
|
||||
(c-mode . ((mode . clang-format))))
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
*.o
|
||||
*.out
|
||||
build/
|
||||
.cache/
|
||||
compile_commands.json
|
||||
TAGS
|
||||
51
Makefile
Normal file
51
Makefile
Normal 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))
|
||||
54
alisp.h
54
alisp.h
@@ -22,7 +22,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/// The bare fucking minimum
|
||||
/// Essential macros
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define ARRSIZE(A) (sizeof(A) / sizeof((A)[0]))
|
||||
@@ -30,6 +30,7 @@
|
||||
#define FAIL(MSG) assert(false && "FAIL: " #MSG)
|
||||
#define TODO(MSG) assert(false && "TODO: " #MSG)
|
||||
|
||||
/// Numeric aliases
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
@@ -40,29 +41,32 @@ typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
/// String Views for my String Needs
|
||||
/// String Views
|
||||
typedef struct
|
||||
{
|
||||
u64 size;
|
||||
char *data;
|
||||
} sv_t;
|
||||
|
||||
// String view macro constructor
|
||||
#define SV(DATA, SIZE) ((sv_t){.data = (DATA), .size = (SIZE)})
|
||||
// Pretty printers
|
||||
#define SV_FMT(SV) (int)(SV).size, (SV).data
|
||||
#define PR_SV "%.*s"
|
||||
#define PRD_SV "%d@%p"
|
||||
|
||||
// String view functions
|
||||
sv_t sv_copy(sv_t);
|
||||
|
||||
/// Dynamic arrays
|
||||
|
||||
#define VEC_INLINE_CAPACITY 32
|
||||
#define VEC_MULT 2
|
||||
|
||||
typedef struct Vector
|
||||
{
|
||||
u64 size, capacity;
|
||||
u8 is_inlined;
|
||||
// Small buffer optimisation
|
||||
u8 not_inlined;
|
||||
union
|
||||
{
|
||||
void *ptr;
|
||||
@@ -70,13 +74,14 @@ typedef struct Vector
|
||||
};
|
||||
} 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_free(vec_t *);
|
||||
void *vec_data(vec_t *);
|
||||
u8 *vec_data(vec_t *);
|
||||
void vec_ensure_free(vec_t *, u64);
|
||||
void vec_append(vec_t *, const void *const, u64);
|
||||
void vec_clone(vec_t *, vec_t *);
|
||||
@@ -91,15 +96,16 @@ typedef struct
|
||||
|
||||
#define SYM_TABLE_INIT_SIZE (1 << 10)
|
||||
|
||||
u64 djb2(sv_t string);
|
||||
void sym_table_init(sym_table_t *);
|
||||
char *sym_table_find(sym_table_t *, sv_t);
|
||||
void sym_table_cleanup(sym_table_t *);
|
||||
// Hashing algorithm
|
||||
u64 djb2(sv_t string);
|
||||
|
||||
/// Streams
|
||||
typedef enum
|
||||
{
|
||||
STREAM_TYPE_STRING,
|
||||
STREAM_TYPE_STRING = 0,
|
||||
STREAM_TYPE_PIPE,
|
||||
STREAM_TYPE_FILE,
|
||||
} stream_type_t;
|
||||
@@ -147,20 +153,27 @@ u64 stream_size(stream_t *);
|
||||
char stream_next(stream_t *);
|
||||
// Peek current character, do not push position
|
||||
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_forward(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);
|
||||
// Return an absolutely located substring (using sv_t) at given index and of
|
||||
// given size.
|
||||
// Return an absolute substring at given index and of given size.
|
||||
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
|
||||
|
||||
// Opaque object for tagged pointers
|
||||
typedef struct Obj lisp_t;
|
||||
|
||||
typedef struct
|
||||
@@ -168,10 +181,10 @@ typedef struct
|
||||
lisp_t *car, *cdr;
|
||||
} cons_t;
|
||||
|
||||
/// System context - essentially something to help with system management
|
||||
/// System context
|
||||
typedef struct
|
||||
{
|
||||
lisp_t *memory;
|
||||
vec_t memory;
|
||||
sym_table_t symtable;
|
||||
} sys_t;
|
||||
|
||||
@@ -196,8 +209,7 @@ vec_t *as_vec(lisp_t *);
|
||||
lisp_t *car(lisp_t *);
|
||||
lisp_t *cdr(lisp_t *);
|
||||
|
||||
/// Pointer tagging scheme for lisps
|
||||
|
||||
/// Tagging scheme
|
||||
typedef enum Tag
|
||||
{
|
||||
TAG_NIL = 0b00000000, // Start of atomic types
|
||||
@@ -208,6 +220,7 @@ typedef enum Tag
|
||||
NUM_TAGS = 5,
|
||||
} tag_t;
|
||||
|
||||
static_assert(NUM_TAGS == 5, "Expected NUM_TAGS == 5 for enum SHIFT");
|
||||
enum Shift
|
||||
{
|
||||
SHIFT_INT = 1,
|
||||
@@ -216,6 +229,7 @@ enum Shift
|
||||
SHIFT_VEC = 8,
|
||||
};
|
||||
|
||||
static_assert(NUM_TAGS == 5, "Expected NUM_TAGS == 5 for enum MASK");
|
||||
enum Mask
|
||||
{
|
||||
MASK_INT = 0b00000001,
|
||||
@@ -224,6 +238,7 @@ enum Mask
|
||||
MASK_VEC = 0b11111111,
|
||||
};
|
||||
|
||||
// Some helper macros for tagging
|
||||
#define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE))
|
||||
#define IS_TAG(PTR, TYPE) (((u64)(PTR) & MASK_##TYPE) == TAG_##TYPE)
|
||||
#define UNTAG(PTR, TYPE) (((u64)PTR) >> SHIFT_##TYPE)
|
||||
@@ -232,7 +247,6 @@ enum Mask
|
||||
#define INT_MIN (-(1L << 62))
|
||||
|
||||
tag_t get_tag(lisp_t *);
|
||||
|
||||
lisp_t *tag_int(i64);
|
||||
lisp_t *tag_sym(char *);
|
||||
lisp_t *tag_cons(cons_t *);
|
||||
@@ -245,7 +259,7 @@ typedef enum
|
||||
} read_err_t;
|
||||
|
||||
// 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 **);
|
||||
|
||||
// Attempt to read all expressions from a stream till end of content, storing
|
||||
|
||||
38
build.sh
38
build.sh
@@ -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
19
main.c
@@ -18,12 +18,25 @@
|
||||
|
||||
#include "./alisp.h"
|
||||
|
||||
const char *TOKEN_DELIM = "\n ";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char filename[] = "./lorem.txt";
|
||||
FILE *fp = fopen(filename, "r");
|
||||
stream_t stream = {0};
|
||||
stream_init_pipe(&stream, "<stdin>", stdin);
|
||||
sv_t sv = stream_substr(&stream, 10);
|
||||
printf("=> `" PR_SV "`\n", SV_FMT(sv));
|
||||
stream_init_file(&stream, filename, fp);
|
||||
|
||||
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);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
lisp_t *make_int(i64 i)
|
||||
{
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
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.
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ sv_t stream_substr(stream_t *stream, u64 size)
|
||||
break;
|
||||
case STREAM_TYPE_PIPE:
|
||||
case STREAM_TYPE_FILE:
|
||||
ptr = vec_data(&stream->pipe.cache);
|
||||
ptr = (char *)vec_data(&stream->pipe.cache);
|
||||
break;
|
||||
default:
|
||||
FAIL("Unreachable");
|
||||
@@ -323,7 +323,7 @@ sv_t stream_substr_abs(stream_t *stream, u64 index, u64 size)
|
||||
case STREAM_TYPE_FILE:
|
||||
{
|
||||
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
|
||||
for (bool read_chunk = stream_chunk(stream);
|
||||
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))
|
||||
return SV(NULL, 0);
|
||||
return SV(vec_data(&stream->pipe.cache) + index, size);
|
||||
return SV((char *)vec_data(&stream->pipe.cache) + index, size);
|
||||
}
|
||||
default:
|
||||
assert("Unreachable");
|
||||
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);
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
sv_t sv_copy(sv_t old)
|
||||
{
|
||||
@@ -12,7 +12,7 @@
|
||||
* Description: Symbol Table implementation
|
||||
*/
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
#include <malloc.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
|
||||
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),
|
||||
comp = VEC_GET(&table->entries, sv_t)[index])
|
||||
comp = VEC_GET(&table->entries, index, sv_t))
|
||||
// Is it present in the table?
|
||||
if (sv.size == comp.size && strncmp(sv.data, comp.data, sv.size) == 0)
|
||||
break;
|
||||
|
||||
// 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);
|
||||
VEC_GET(&table->entries, sv_t)[index] = newsv;
|
||||
VEC_GET(&table->entries, index, sv_t) = newsv;
|
||||
++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)
|
||||
@@ -65,7 +65,7 @@ void sym_table_cleanup(sym_table_t *table)
|
||||
sv_t current = {0};
|
||||
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)
|
||||
free(current.data);
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
* Description: System management
|
||||
*/
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
@@ -21,15 +21,13 @@
|
||||
void sys_init(sys_t *sys)
|
||||
{
|
||||
memset(sys, 0, sizeof(*sys));
|
||||
vec_init(&sys->conses, 0);
|
||||
}
|
||||
|
||||
void sys_register(sys_t *sys, lisp_t *ptr)
|
||||
{
|
||||
// Generate an unmanaged cons
|
||||
cons_t *cons = calloc(1, sizeof(*cons));
|
||||
cons->car = ptr;
|
||||
cons->cdr = sys->memory;
|
||||
sys->memory = tag_cons(cons);
|
||||
// Simply append it to the list of currently active conses
|
||||
vec_append(&sys->conses, &ptr, sizeof(&ptr));
|
||||
}
|
||||
|
||||
void sys_cleanup(sys_t *sys)
|
||||
@@ -37,18 +35,13 @@ void sys_cleanup(sys_t *sys)
|
||||
static_assert(NUM_TAGS == 5);
|
||||
|
||||
sym_table_cleanup(&sys->symtable);
|
||||
|
||||
if (!sys->memory)
|
||||
if (sys->conses.size == 0)
|
||||
return;
|
||||
|
||||
// Iterate through each element of memory
|
||||
for (lisp_t *cell = sys->memory, *next = cdr(cell); cell;
|
||||
cell = next, next = cdr(next))
|
||||
// Iterate through each cons currently allocated and free them
|
||||
for (size_t i = 0; i < VEC_SIZE(&sys->conses, lisp_t **); ++i)
|
||||
{
|
||||
// Only reason allocated exists is because we had to allocate memory on the
|
||||
// heap for it. It's therefore enough to deal with only the allocated
|
||||
// types.
|
||||
lisp_t *allocated = car(cell);
|
||||
lisp_t *allocated = VEC_GET(&sys->conses, i, lisp_t *);
|
||||
switch (get_tag(allocated))
|
||||
{
|
||||
case TAG_CONS:
|
||||
@@ -69,9 +62,11 @@ void sys_cleanup(sys_t *sys)
|
||||
// shouldn't be dealt with (either constant or dealt with elsewhere)
|
||||
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));
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
lisp_t *tag_int(i64 i)
|
||||
{
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
void vec_init(vec_t *vec, u64 size)
|
||||
{
|
||||
@@ -25,13 +25,13 @@ void vec_init(vec_t *vec, u64 size)
|
||||
return;
|
||||
else if (size <= VEC_INLINE_CAPACITY)
|
||||
{
|
||||
vec->is_inlined = 1;
|
||||
vec->not_inlined = 0;
|
||||
vec->capacity = VEC_INLINE_CAPACITY;
|
||||
vec->ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec->is_inlined = 0;
|
||||
vec->not_inlined = 1;
|
||||
vec->capacity = size;
|
||||
vec->ptr = calloc(1, vec->capacity);
|
||||
}
|
||||
@@ -41,14 +41,14 @@ void vec_free(vec_t *vec)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
if (!vec->is_inlined && vec->ptr)
|
||||
if (vec->not_inlined && vec->ptr)
|
||||
free(vec->ptr);
|
||||
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)
|
||||
@@ -58,7 +58,7 @@ void vec_ensure_free(vec_t *vec, u64 size)
|
||||
if (vec->capacity - 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
|
||||
// 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);
|
||||
vec->ptr = calloc(1, vec->capacity);
|
||||
memcpy(vec->ptr, buffer, vec->size);
|
||||
vec->is_inlined = 0;
|
||||
vec->not_inlined = 1;
|
||||
}
|
||||
else
|
||||
vec->ptr = realloc(vec->ptr, vec->capacity);
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./alisp.h"
|
||||
#include "../alisp.h"
|
||||
|
||||
#define TEST_PASSED() printf("[%s]: Pass\n", __func__)
|
||||
#define TEST(NAME, COND) \
|
||||
Reference in New Issue
Block a user