vm + code split

This commit is contained in:
SimonFJ20 2023-07-31 02:32:29 +02:00
parent 50cd63aa38
commit 1af1fa5d16
14 changed files with 535 additions and 402 deletions

View File

@ -36,7 +36,7 @@ build_folder:
mkdir $(BUILD_FOLDER) -p
compile_flags.txt:
echo -xc $(CPP_FLAGS) | sed 's/\s\+/\n/g' > compile_flags.txt
echo -xc $(C_FLAGS) | sed 's/\s\+/\n/g' > compile_flags.txt
clean:
rm -rf $(BUILD_FOLDER) compile_flags.txt

179
src/allocator.c Normal file
View File

@ -0,0 +1,179 @@
#include "allocator.h"
#include "panic.h"
#include <stdlib.h>
#include <string.h>
size_t align_size(size_t size)
{
const size_t word_size = sizeof(size_t);
return (size + word_size) / word_size * word_size;
}
void gc_buffer_construct(GCBuffer* buffer, size_t capacity)
{
void* data = malloc(capacity);
ASSERT(buffer != NULL);
*buffer = (GCBuffer) {
.data = data,
.index = 0,
.capacity = capacity,
};
}
void gc_buffer_destroy(GCBuffer* buffer) { free(buffer->data); }
void gc_buffer_reset(GCBuffer* buffer) { buffer->index = 0; }
void* gc_buffer_alloc(GCBuffer* buffer, size_t size)
{
size_t aligned_size = align_size(size);
if (buffer->capacity - buffer->index < aligned_size) {
return NULL;
}
void* ptr = &((size_t*)buffer->data)[buffer->index];
buffer->index += aligned_size;
return ptr;
}
void gc_buffer_resize(GCBuffer* buffer, size_t minimum_capacity)
{
size_t aligned_min_cap = align_size(minimum_capacity);
if (buffer->capacity >= aligned_min_cap) {
return;
}
while (buffer->capacity < minimum_capacity) {
buffer->capacity *= 2;
}
void* new_buffer = realloc(buffer->data, buffer->capacity);
ASSERT(new_buffer);
buffer->data = new_buffer;
}
void gc_construct(GC* allocator, size_t start_capacity)
{
GCBuffer buffer_a;
gc_buffer_construct(&buffer_a, start_capacity);
GCBuffer buffer_b;
gc_buffer_construct(&buffer_b, start_capacity);
*allocator = (GC) {
.alloc = gc_alloc,
.realloc = gc_realloc,
.buffer_a = buffer_a,
.buffer_b = buffer_b,
.select = GCBufferA,
};
}
bool gc_buffer_contains(GCBuffer* buffer, void* address)
{
return (size_t)address >= (size_t)buffer->data
&& (size_t)address < (size_t)buffer->data + (size_t)buffer->index;
}
void gc_destroy(GC* allocator)
{
gc_buffer_destroy(&allocator->buffer_a);
gc_buffer_destroy(&allocator->buffer_b);
}
void* gc_alloc(GC* allocator, size_t size)
{
size_t full_size = size + sizeof(size_t);
GCBuffer* buffer = gc_selected_buffer(allocator);
void* ptr = gc_buffer_alloc(buffer, full_size);
if (ptr == NULL) {
return NULL;
}
size_t* alloc_size = (size_t*)ptr;
*alloc_size = size;
return &((size_t*)ptr)[1];
}
void* gc_realloc(GC* allocator, void* data, size_t size)
{
size_t old_size = ((size_t*)data)[-1];
void* new_ptr = gc_alloc(allocator, size);
if (new_ptr == NULL) {
return NULL;
}
memcpy(new_ptr, (size_t*)data - sizeof(size_t), old_size + sizeof(size_t));
size_t* size_ptr = (size_t*)new_ptr;
*size_ptr = size;
return &((size_t*)new_ptr)[1];
}
void gc_collect(GC* allocator, void* entries, size_t entries_size)
{
gc_select_other(allocator);
GCBuffer* source = gc_other_buffer(allocator);
gc_relocate_branches_buffer(allocator, entries, entries_size);
gc_buffer_reset(source);
}
void gc_relocate_branches(GC* allocator, void* allocation)
{
size_t size = ((size_t*)allocation)[-1];
gc_relocate_branches_buffer(allocator, allocation, size);
}
void gc_relocate_branches_buffer(
GC* allocator, void* branches, size_t branches_size
)
{
GCBuffer* source = gc_other_buffer(allocator);
for (size_t i = 0; i < branches_size; ++i) {
if (gc_buffer_contains(source, &((size_t*)branches)[i])) {
gc_relocate_allocation(allocator, branches);
gc_relocate_branches(allocator, branches);
}
}
}
void gc_relocate_allocation(GC* allocator, void* allocation)
{
GCBuffer* dest = gc_selected_buffer(allocator);
void* ptr = &((size_t*)allocation)[-1];
size_t size = ((size_t*)ptr)[0];
size_t full_size = size + sizeof(size_t);
void* new_ptr = gc_buffer_alloc(dest, full_size);
if (new_ptr == NULL) {
gc_buffer_resize(dest, dest->capacity + full_size);
new_ptr = gc_buffer_alloc(dest, full_size);
ASSERT(new_ptr != NULL);
}
size_t* selected_size_ptr = &((size_t*)new_ptr)[0];
*selected_size_ptr = size;
memcpy(&((size_t*)new_ptr)[1], allocation, size);
}
GCBuffer* gc_selected_buffer(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
return &allocator->buffer_a;
case GCBufferB:
return &allocator->buffer_b;
}
}
GCBuffer* gc_other_buffer(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
return &allocator->buffer_b;
case GCBufferB:
return &allocator->buffer_a;
}
}
void gc_select_other(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
allocator->select = GCBufferB;
break;
case GCBufferB:
allocator->select = GCBufferA;
break;
}
}

57
src/allocator.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <stdbool.h>
#include <stddef.h>
typedef struct Allocator Allocator;
struct Allocator {
void* (*alloc)(Allocator* allocator, size_t size);
void* (*realloc)(Allocator* allocator, void* data, size_t size);
};
size_t align_size(size_t size);
typedef struct {
void* data;
size_t index;
size_t capacity;
} GCBuffer;
void gc_buffer_construct(GCBuffer* buffer, size_t capacity);
void gc_buffer_destroy(GCBuffer* buffer);
void gc_buffer_reset(GCBuffer* buffer);
void* gc_buffer_alloc(GCBuffer* buffer, size_t size);
void gc_buffer_resize(GCBuffer* buffer, size_t minimum_capacity);
bool gc_buffer_contains(GCBuffer* buffer, void* address);
typedef enum {
GCBufferA,
GCBufferB,
} SelectedGCBuffer;
typedef struct GC GC;
struct GC {
void* (*alloc)(GC* allocator, size_t size);
void* (*realloc)(GC* allocator, void* data, size_t size);
GCBuffer buffer_a;
GCBuffer buffer_b;
SelectedGCBuffer select;
};
void gc_construct(GC* allocator, size_t start_capacity);
void gc_destroy(GC* allocator);
void* gc_alloc(GC* allocator, size_t size);
void* gc_realloc(GC* allocator, void* data, size_t size);
void gc_collect(GC* allocator, void* entries, size_t entries_size);
void gc_relocate_branches(GC* allocator, void* allocation);
void gc_relocate_branches_buffer(
GC* allocator, void* branches, size_t branches_size
);
void gc_relocate_allocation(GC* allocator, void* allocation);
GCBuffer* gc_selected_buffer(GC* allocator);
GCBuffer* gc_other_buffer(GC* allocator);
void gc_select_other(GC* allocator);
#endif

43
src/char_reader.c Normal file
View File

@ -0,0 +1,43 @@
#include "char_reader.h"
#include "panic.h"
#include "vec.h"
#include <stddef.h>
#include <stdio.h>
void file_char_reader_construct(FileCharReader* reader, FILE* file)
{
*reader = (FileCharReader) {
.next = file_char_reader_next,
.value = file_char_reader_value,
.file = file,
.buffer = { 0 },
};
string_construct(&reader->buffer);
}
void file_char_reader_destroy(FileCharReader* reader)
{
string_destroy(&reader->buffer);
}
char file_char_reader_next(FileCharReader* reader)
{
int read_maybe_char = fgetc(reader->file);
if (read_maybe_char == EOF) {
return '\0';
}
char read_char = (char)read_maybe_char;
string_append_char(&reader->buffer, read_char);
return (char)read_char;
}
StringSlice file_char_reader_value(
const FileCharReader* reader, size_t index, size_t length
)
{
ASSERT(index + length <= reader->buffer.length);
return (StringSlice) {
.data = &reader->buffer.data[index],
.length = length,
};
}

31
src/char_reader.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef CHAR_READER_H
#define CHAR_READER_H
#include "vec.h"
#include <stddef.h>
#include <stdio.h>
typedef struct CharReader CharReader;
struct CharReader {
char (*next)(CharReader* reader);
StringSlice (*value)(const CharReader* reader, size_t index, size_t length);
};
typedef struct FileCharReader FileCharReader;
struct FileCharReader {
char (*next)(FileCharReader* reader);
StringSlice (*value)(
const FileCharReader* reader, size_t index, size_t length
);
FILE* file;
String buffer;
};
void file_char_reader_construct(FileCharReader* reader, FILE* file);
void file_char_reader_destroy(FileCharReader* reader);
char file_char_reader_next(FileCharReader* reader);
StringSlice file_char_reader_value(
const FileCharReader* reader, size_t index, size_t length
);
#endif

View File

@ -1,180 +1,10 @@
#include "lexer.h"
#include "panic.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool string_slice_equal(StringSlice slice, const char* data)
{
if (strlen(data) != slice.length) {
return false;
}
return strncmp(data, slice.data, slice.length) == 0;
}
void string_construct(String* string)
{
*string = (String) {
.data = NULL,
.length = 0,
.capacity = 0,
};
}
void string_destroy(String* string)
{
if (string->data) {
free(string->data);
}
}
const size_t string_starting_alloc_size = 8;
void string_from_cstr(String* string, const char* value)
{
string_construct(string);
string_append_cstr(string, value);
}
void string_from_slice(String* string, StringSlice slice)
{
string_construct(string);
for (size_t i = 0; i < slice.length; ++i) {
string_append_char(string, slice.data[i]);
}
}
void string_append(String* string, const String* value)
{
string_append_cstr(string, value->data);
}
void string_append_char(String* string, char value)
{
if (string->length + 1 >= string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
} else {
string->capacity *= 2;
}
if (string->data == NULL) {
string->data = malloc(string->capacity * sizeof(char));
ASSERT(string->data);
} else {
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
}
string->data[string->length] = value;
string->length += 1;
string->data[string->length] = '\0';
}
void string_append_cstr(String* string, const char* value)
{
size_t value_length = strlen(value);
if (string->length + value_length + 1 > string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
}
while (string->length + value_length + 1 > string->capacity) {
string->capacity *= 2;
}
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
memcpy(&string->data[string->length], value, value_length);
string->length += value_length;
string->data[string->length] = '\0';
}
void string_append_format(String* string, const char* format, ...)
{
va_list varargs;
va_start(varargs, format);
size_t format_length = (size_t)vsnprintf(NULL, 0, format, varargs);
va_end(varargs);
va_start(varargs, format);
if (string->length + format_length + 1 > string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
} else {
string->capacity *= 2;
}
while (string->length + format_length + 1 > string->capacity) {
string->capacity *= 2;
}
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
size_t written = (size_t)vsnprintf(
&string->data[string->length],
string->capacity - string->length,
format,
varargs
);
string->length += written;
string->data[string->length] = '\0';
va_end(varargs);
}
bool string_equal(const String* string, const char* value)
{
return strncmp(value, string->data, string->length + 1);
}
void file_char_reader_construct(FileCharReader* reader, FILE* file)
{
*reader = (FileCharReader) {
.next = file_char_reader_next,
.value = file_char_reader_value,
.file = file,
.buffer = { 0 },
};
string_construct(&reader->buffer);
}
void file_char_reader_destroy(FileCharReader* reader)
{
string_destroy(&reader->buffer);
}
char file_char_reader_next(FileCharReader* reader)
{
int read_maybe_char = fgetc(reader->file);
if (read_maybe_char == EOF) {
return '\0';
}
char read_char = (char)read_maybe_char;
string_append_char(&reader->buffer, read_char);
return (char)read_char;
}
StringSlice file_char_reader_value(
const FileCharReader* reader, size_t index, size_t length
)
{
ASSERT(index + length <= reader->buffer.length);
return (StringSlice) {
.data = &reader->buffer.data[index],
.length = length,
};
}
void error_construct(Error* error, Pos pos, String message)
{
*error = (Error) {

View File

@ -1,79 +1,13 @@
#ifndef LEXER_H
#define LEXER_H
#include "char_reader.h"
#include "vec.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define PANIC(...) \
(fprintf(stderr, "panic: "), \
fprintf(stderr, __VA_ARGS__), \
fprintf(stderr, ", at %s:%d in %s()\n", __FILE__, __LINE__, __func__), \
exit(1));
#define ASSERT(CONDITION) \
{ \
if (!(CONDITION)) { \
(fprintf(stderr, "assertion failed: "), \
fprintf( \
stderr, \
"(%s), at %s:%d in %s()\n", \
#CONDITION, \
__FILE__, \
__LINE__, \
__func__ \
), \
exit(1)); \
} \
};
typedef struct {
const char* data;
size_t length;
} StringSlice;
bool string_slice_equal(StringSlice slice, const char* data);
typedef struct {
char* data;
size_t length;
size_t capacity;
} String;
void string_construct(String* string);
void string_destroy(String* string);
void string_from_cstr(String* string, const char* value);
void string_from_slice(String* string, StringSlice slice);
void string_append(String* string, const String* value);
void string_append_char(String* string, char value);
void string_append_cstr(String* string, const char* value);
void string_append_format(String* string, const char* format, ...);
bool string_equal(const String* string, const char* value);
typedef struct CharReader CharReader;
struct CharReader {
char (*next)(CharReader* reader);
StringSlice (*value)(const CharReader* reader, size_t index, size_t length);
};
typedef struct FileCharReader FileCharReader;
struct FileCharReader {
char (*next)(FileCharReader* reader);
StringSlice (*value)(
const FileCharReader* reader, size_t index, size_t length
);
FILE* file;
String buffer;
};
void file_char_reader_construct(FileCharReader* reader, FILE* file);
void file_char_reader_destroy(FileCharReader* reader);
char file_char_reader_next(FileCharReader* reader);
StringSlice file_char_reader_value(
const FileCharReader* reader, size_t index, size_t length
);
typedef struct {
size_t index;
size_t line;

29
src/panic.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef PANIC_H
#define PANIC_H
#include <stdio.h>
#include <stdlib.h>
#define PANIC(...) \
(fprintf(stderr, "panic: "), \
fprintf(stderr, __VA_ARGS__), \
fprintf(stderr, ", at %s:%d in %s()\n", __FILE__, __LINE__, __func__), \
exit(1));
#define ASSERT(CONDITION) \
{ \
if (!(CONDITION)) { \
(fprintf(stderr, "assertion failed: "), \
fprintf( \
stderr, \
"(%s), at %s:%d in %s()\n", \
#CONDITION, \
__FILE__, \
__LINE__, \
__func__ \
), \
exit(1)); \
} \
};
#endif

View File

@ -1,5 +1,6 @@
#include "parser.h"
#include "lexer.h"
#include "panic.h"
#include <stdio.h>
#include <stdlib.h>
@ -7,29 +8,29 @@ void expr_vec_construct(ExprVec* vec)
{
const size_t starting_capacity = 8;
*vec = (ExprVec) {
.exprs = malloc(starting_capacity * sizeof(Expr)),
.data = malloc(starting_capacity * sizeof(Expr)),
.length = 0,
.capacity = starting_capacity,
};
ASSERT(vec->exprs);
ASSERT(vec->data);
}
void expr_vec_destroy(ExprVec* vec)
{
for (size_t i = 0; i < vec->length; ++i) {
expr_destroy(&vec->exprs[i]);
expr_destroy(&vec->data[i]);
}
free(vec->exprs);
free(vec->data);
}
void expr_vec_push(ExprVec* vec, Expr expr)
{
if (vec->length >= vec->capacity) {
vec->capacity *= 2;
Expr* new_buffer = realloc(vec->exprs, vec->capacity * sizeof(Expr));
Expr* new_buffer = realloc(vec->data, vec->capacity * sizeof(Expr));
ASSERT(new_buffer);
vec->exprs = new_buffer;
vec->data = new_buffer;
}
vec->exprs[vec->length] = expr;
vec->data[vec->length] = expr;
vec->length += 1;
}
@ -37,10 +38,10 @@ void expr_vec_stringify(const ExprVec* vec, String* acc)
{
string_append_cstr(acc, "[");
if (vec->length > 0) {
expr_stringify(&vec->exprs[0], acc);
expr_stringify(&vec->data[0], acc);
for (size_t i = 1; i < vec->length; ++i) {
string_append_cstr(acc, ", ");
expr_stringify(&vec->exprs[i], acc);
expr_stringify(&vec->data[i], acc);
}
}
string_append_cstr(acc, "]");
@ -125,10 +126,10 @@ void expr_stringify(const Expr* expr, String* acc)
case ExprTypeList:
string_append_cstr(acc, "[");
if (expr->list.length > 0) {
expr_stringify(&expr->list.exprs[0], acc);
expr_stringify(&expr->list.data[0], acc);
for (size_t i = 1; i < expr->list.length; ++i) {
string_append_cstr(acc, " ");
expr_stringify(&expr->list.exprs[i], acc);
expr_stringify(&expr->list.data[i], acc);
}
}
string_append_cstr(acc, "]");
@ -136,10 +137,10 @@ void expr_stringify(const Expr* expr, String* acc)
case ExprTypeS:
string_append_cstr(acc, "(");
if (expr->s.length > 0) {
expr_stringify(&expr->s.exprs[0], acc);
expr_stringify(&expr->s.data[0], acc);
for (size_t i = 1; i < expr->s.length; ++i) {
string_append_cstr(acc, " ");
expr_stringify(&expr->s.exprs[i], acc);
expr_stringify(&expr->s.data[i], acc);
}
}
string_append_cstr(acc, ")");

View File

@ -19,7 +19,7 @@ typedef enum {
typedef struct Expr Expr;
typedef struct {
Expr* exprs;
Expr* data;
size_t length;
size_t capacity;
} ExprVec;

View File

@ -1,5 +1,8 @@
#include "runtime.h"
#include "lexer.h"
#include "panic.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -27,7 +30,7 @@ Value* value_vec_at(const ValueVec* vec, int64_t index)
if (index < 0) {
return value_vec_at(vec, -index);
}
if (index >= vec->length) {
if (index >= (int64_t)vec->length) {
return NULL;
}
return &vec->data[index];
@ -135,117 +138,13 @@ void value_stringify(const Value* value, String* acc)
}
}
void gc_buffer_construct(GCBuffer* buffer, size_t capacity)
{
void* data = malloc(capacity);
ASSERT(buffer != NULL);
*buffer = (GCBuffer) {
.data = data,
.capacity = capacity,
};
}
void gc_buffer_destroy(GCBuffer* buffer) { free(buffer->data); }
void gc_buffer_resize(GCBuffer* buffer, size_t minimum_capacity)
{
if (buffer->capacity >= minimum_capacity) {
return;
}
while (buffer->capacity < minimum_capacity) {
buffer->capacity *= 2;
}
void* new_buffer = realloc(buffer->data, buffer->capacity);
ASSERT(new_buffer);
buffer->data = new_buffer;
}
void gc_construct(GC* allocator, size_t start_capacity)
{
GCBuffer buffer_a;
gc_buffer_construct(&buffer_a, start_capacity);
GCBuffer buffer_b;
gc_buffer_construct(&buffer_b, start_capacity);
*allocator = (GC) {
.alloc = gc_alloc,
.realloc = gc_realloc,
.buffer_a = buffer_a,
.buffer_b = buffer_b,
.select = GCBufferA,
.index = 0,
};
}
void gc_destroy(GC* allocator)
{
gc_buffer_destroy(&allocator->buffer_a);
gc_buffer_destroy(&allocator->buffer_b);
}
void* gc_alloc(GC* allocator, size_t size)
{
GCBuffer* buffer = gc_selected_buffer(allocator);
if (buffer->capacity < allocator->index + size) {
return NULL;
}
void* ptr = &buffer->data[allocator->index];
allocator->index += size;
return ptr;
}
void* gc_realloc(GC* allocator, void* data, size_t size)
{
void* new_ptr = gc_alloc(allocator, size);
if (new_ptr == NULL) {
return NULL;
}
memcpy(new_ptr, data, size);
return new_ptr;
}
void* gc_collect(GC* allocator, ValueVec* stack, size_t to_be_allocated)
{
GCBuffer* selected = gc_selected_buffer(allocator);
GCBuffer* other = gc_other_buffer(allocator);
}
GCBuffer* gc_selected_buffer(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
return &allocator->buffer_a;
case GCBufferB:
return &allocator->buffer_b;
}
}
GCBuffer* gc_other_buffer(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
return &allocator->buffer_b;
case GCBufferB:
return &allocator->buffer_a;
}
}
void gc_select_other(GC* allocator)
{
switch (allocator->select) {
case GCBufferA:
allocator->select = GCBufferB;
break;
case GCBufferB:
allocator->select = GCBufferA;
break;
}
}
void runtime_construct(Runtime* runtime, Allocator* allocator)
{
*runtime = (Runtime) {
.allocator = allocator,
.stack = { 0 },
};
value_vec_construct(&runtime->stack, allocator);
}
void runtime_destroy(Runtime* runtime) { }
void runtime_destroy(Runtime* runtime) { value_vec_destroy(&runtime->stack); }

View File

@ -1,16 +1,11 @@
#ifndef RUNTIME_H
#define RUNTIME_H
#include "allocator.h"
#include "lexer.h"
#include <stdbool.h>
#include <stdint.h>
typedef struct Allocator Allocator;
struct Allocator {
void* (*alloc)(Allocator* allocator, size_t size);
void* (*realloc)(Allocator* allocator, void* data, size_t size);
};
typedef enum {
ValueTypeSymbol,
ValueTypeInt,
@ -52,42 +47,9 @@ struct Value {
void value_destroy(Value* value);
void value_stringify(const Value* value, String* acc);
typedef struct {
void* data;
size_t capacity;
} GCBuffer;
void gc_buffer_construct(GCBuffer* buffer, size_t capacity);
void gc_buffer_destroy(GCBuffer* buffer);
void gc_buffer_resize(GCBuffer* buffer, size_t minimum_capacity);
typedef enum {
GCBufferA,
GCBufferB,
} SelectedGCBuffer;
typedef struct GC GC;
struct GC {
void* (*alloc)(GC* allocator, size_t size);
void* (*realloc)(GC* allocator, void* data, size_t size);
GCBuffer buffer_a;
GCBuffer buffer_b;
SelectedGCBuffer select;
size_t index;
};
void gc_construct(GC* allocator, size_t start_capacity);
void gc_destroy(GC* allocator);
void* gc_alloc(GC* allocator, size_t size);
void* gc_realloc(GC* allocator, void* data, size_t size);
void* gc_collect(GC* allocator, ValueVec* stack, size_t to_be_allocated);
GCBuffer* gc_selected_buffer(GC* allocator);
GCBuffer* gc_other_buffer(GC* allocator);
void gc_select_other(GC* allocator);
typedef struct {
Allocator* allocator;
ValueVec stack;
} Runtime;
void runtime_construct(Runtime* runtime, Allocator* allocator);

138
src/vec.c Normal file
View File

@ -0,0 +1,138 @@
#include "vec.h"
#include "panic.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
bool string_slice_equal(StringSlice slice, const char* data)
{
if (strlen(data) != slice.length) {
return false;
}
return strncmp(data, slice.data, slice.length) == 0;
}
void string_construct(String* string)
{
*string = (String) {
.data = NULL,
.length = 0,
.capacity = 0,
};
}
void string_destroy(String* string)
{
if (string->data) {
free(string->data);
}
}
const size_t string_starting_alloc_size = 8;
void string_from_cstr(String* string, const char* value)
{
string_construct(string);
string_append_cstr(string, value);
}
void string_from_slice(String* string, StringSlice slice)
{
string_construct(string);
for (size_t i = 0; i < slice.length; ++i) {
string_append_char(string, slice.data[i]);
}
}
void string_append(String* string, const String* value)
{
string_append_cstr(string, value->data);
}
void string_append_char(String* string, char value)
{
if (string->length + 1 >= string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
} else {
string->capacity *= 2;
}
if (string->data == NULL) {
string->data = malloc(string->capacity * sizeof(char));
ASSERT(string->data);
} else {
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
}
string->data[string->length] = value;
string->length += 1;
string->data[string->length] = '\0';
}
void string_append_cstr(String* string, const char* value)
{
size_t value_length = strlen(value);
if (string->length + value_length + 1 > string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
}
while (string->length + value_length + 1 > string->capacity) {
string->capacity *= 2;
}
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
memcpy(&string->data[string->length], value, value_length);
string->length += value_length;
string->data[string->length] = '\0';
}
void string_append_format(String* string, const char* format, ...)
{
va_list varargs;
va_start(varargs, format);
size_t format_length = (size_t)vsnprintf(NULL, 0, format, varargs);
va_end(varargs);
va_start(varargs, format);
if (string->length + format_length + 1 > string->capacity) {
if (string->capacity == 0) {
string->capacity = string_starting_alloc_size;
} else {
string->capacity *= 2;
}
while (string->length + format_length + 1 > string->capacity) {
string->capacity *= 2;
}
char* new_buffer
= realloc(string->data, string->capacity * sizeof(char));
ASSERT(new_buffer);
string->data = new_buffer;
}
size_t written = (size_t)vsnprintf(
&string->data[string->length],
string->capacity - string->length,
format,
varargs
);
string->length += written;
string->data[string->length] = '\0';
va_end(varargs);
}
bool string_equal(const String* string, const char* value)
{
return strncmp(value, string->data, string->length + 1);
}

30
src/vec.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef VEC_H
#define VEC_H
#include <stdbool.h>
#include <stddef.h>
typedef struct {
const char* data;
size_t length;
} StringSlice;
bool string_slice_equal(StringSlice slice, const char* data);
typedef struct {
char* data;
size_t length;
size_t capacity;
} String;
void string_construct(String* string);
void string_destroy(String* string);
void string_from_cstr(String* string, const char* value);
void string_from_slice(String* string, StringSlice slice);
void string_append(String* string, const String* value);
void string_append_char(String* string, char value);
void string_append_cstr(String* string, const char* value);
void string_append_format(String* string, const char* format, ...);
bool string_equal(const String* string, const char* value);
#endif