Types, Fixed personal arena
This commit is contained in:
55
main.cpp
55
main.cpp
@@ -29,11 +29,10 @@ typedef double F64;
|
|||||||
#define mib(x) (kib(x)*1024llu)
|
#define mib(x) (kib(x)*1024llu)
|
||||||
#define gib(x) (mib(x)*1024llu)
|
#define gib(x) (mib(x)*1024llu)
|
||||||
struct String{U8 *str;S64 len;};
|
struct String{U8 *str;S64 len;};
|
||||||
union Intern_String{
|
union Intern_String{ String s; struct{ U8 *str; S64 len; }; }; // Basically just String
|
||||||
String s;
|
|
||||||
struct{ U8 *str; S64 len; };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#define JOIN1(X,Y) X##Y // helper macro
|
||||||
|
#define JOIN(X,Y) JOIN1(X,Y)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Utilities
|
// Utilities
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -287,6 +286,11 @@ struct Arena:Allocator{
|
|||||||
OS_Memory memory;
|
OS_Memory memory;
|
||||||
SizeU alignment;
|
SizeU alignment;
|
||||||
SizeU len;
|
SizeU len;
|
||||||
|
|
||||||
|
// Personal arena memes so we can compute correct size when resizing
|
||||||
|
// Also a pointer so that we can make sure it didn't change
|
||||||
|
SizeU old_size;
|
||||||
|
void *debug_prev_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
function void arena_init(Arena *arena, String debug_name);
|
function void arena_init(Arena *arena, String debug_name);
|
||||||
@@ -347,7 +351,24 @@ force_inline void *
|
|||||||
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
||||||
Arena *arena = (Arena *)a;
|
Arena *arena = (Arena *)a;
|
||||||
arena->alignment = 1;
|
arena->alignment = 1;
|
||||||
return arena_allocator_proc(a, kind, old_pointer, size);
|
|
||||||
|
void *result = 0;
|
||||||
|
switch(kind){
|
||||||
|
case Allocation_Resize: {
|
||||||
|
assert(arena->old_size);
|
||||||
|
assert(arena->old_size < size);
|
||||||
|
assert(arena->debug_prev_pointer == old_pointer);
|
||||||
|
result = arena_push_size(arena, size - arena->old_size);
|
||||||
|
result = old_pointer;
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
result = arena_allocator_proc(a, kind, old_pointer, size);
|
||||||
|
arena->debug_prev_pointer = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arena->old_size = size;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -447,8 +468,8 @@ report__file_and_line(const char *file, int line){
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Implicit scratch stack
|
// Implicit scratch stack
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define Set_Scratch() Scoped_Scratch scratch_##__LINE__
|
#define Set_Scratch() Scoped_Scratch JOIN(scratch, __LINE__)
|
||||||
#define Set_Backup_Scratch() Scoped_Scratch scratch_##__LINE__(true)
|
#define Set_Backup_Scratch() Scoped_Scratch JOIN(scratch, __LINE__)(true)
|
||||||
struct Scoped_Scratch{
|
struct Scoped_Scratch{
|
||||||
SizeU saved_pos;
|
SizeU saved_pos;
|
||||||
Allocator *saved_allocator;
|
Allocator *saved_allocator;
|
||||||
@@ -470,7 +491,7 @@ struct Scoped_Scratch{
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Implicit allocator stack
|
// Implicit allocator stack
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define Set_Allocator(a) Scoped_Allocator scoped_##__LINE__(a)
|
#define Set_Allocator(a) Scoped_Allocator JOIN(scoped,__LINE__)(a)
|
||||||
struct Scoped_Allocator{
|
struct Scoped_Allocator{
|
||||||
Allocator *allocator;
|
Allocator *allocator;
|
||||||
Scoped_Allocator(Allocator *a){
|
Scoped_Allocator(Allocator *a){
|
||||||
@@ -492,7 +513,7 @@ thread_ctx_get_user_ctx(U64 id){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define Get_Ctx(T) T *ctx = (T *)thread_ctx_get_user_ctx(T##_ID)
|
#define Get_Ctx(T) T *ctx = (T *)thread_ctx_get_user_ctx(T##_ID)
|
||||||
#define Set_Ctx(ctx, id) Scoped_Ctx scoped_ctx_##__LINE__((void *)ctx, id)
|
#define Set_Ctx(ctx, id) Scoped_Ctx JOIN(scoped_ctx, __LINE__)((void *)ctx, id)
|
||||||
struct Scoped_Ctx{
|
struct Scoped_Ctx{
|
||||||
void *prev_ctx;
|
void *prev_ctx;
|
||||||
U64 prev_id;
|
U64 prev_id;
|
||||||
@@ -699,7 +720,6 @@ test_custom_context(){
|
|||||||
assert(thread_ctx.ctx == 0);
|
assert(thread_ctx.ctx == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Defer
|
// Defer
|
||||||
// http://www.gingerbill.org/article/2015/08/19/defer-in-cpp/
|
// http://www.gingerbill.org/article/2015/08/19/defer-in-cpp/
|
||||||
@@ -757,6 +777,16 @@ struct Array{
|
|||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<T> copy(Allocator *a){
|
||||||
|
Array<T> result = {};
|
||||||
|
result.len = len;
|
||||||
|
result.cap = len;
|
||||||
|
result.allocator = 0;
|
||||||
|
result.data = exp_alloc_array(a, T, len);
|
||||||
|
memory_copy(result.data, data, sizeof(T)*len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
T *begin(){ return data; }
|
T *begin(){ return data; }
|
||||||
T *end (){ return data + len; }
|
T *end (){ return data + len; }
|
||||||
T &operator[](S64 i){ return data[i]; }
|
T &operator[](S64 i){ return data[i]; }
|
||||||
@@ -1089,17 +1119,18 @@ test_intern_table(){ Set_Scratch();
|
|||||||
#include "new_lex.cpp"
|
#include "new_lex.cpp"
|
||||||
#include "new_ast.cpp"
|
#include "new_ast.cpp"
|
||||||
#include "new_parse.cpp"
|
#include "new_parse.cpp"
|
||||||
|
#include "new_type.cpp"
|
||||||
int main(){
|
int main(){
|
||||||
test_custom_context();
|
test_custom_context();
|
||||||
test_heap_allocator();
|
test_heap_allocator();
|
||||||
test_os_memory();
|
test_os_memory();
|
||||||
|
|
||||||
thread_ctx_init();
|
thread_ctx_init();
|
||||||
map_test();
|
test_types();
|
||||||
|
|
||||||
test_parse_decl();
|
test_parse_decl();
|
||||||
test_parse_expr();
|
test_parse_expr();
|
||||||
|
|
||||||
|
map_test();
|
||||||
test_array();
|
test_array();
|
||||||
test_string_builder();
|
test_string_builder();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ struct Parse_Ctx:Lexer{
|
|||||||
Token empty_token;
|
Token empty_token;
|
||||||
S64 indent;
|
S64 indent;
|
||||||
S64 pt[256]; // precedence table
|
S64 pt[256]; // precedence table
|
||||||
|
Map type_map;
|
||||||
|
|
||||||
void init(){
|
void init(){
|
||||||
const S64 addp = 1;
|
const S64 addp = 1;
|
||||||
|
|||||||
@@ -244,4 +244,3 @@ test_parse_decl(){
|
|||||||
lex_restream(&ctx, "thing := 24252\nanother_thing := \"string\"\n\nref := thing"_s, "test_parse_decl"_s);
|
lex_restream(&ctx, "thing := 24252\nanother_thing := \"string\"\n\nref := thing"_s, "test_parse_decl"_s);
|
||||||
Ast_Package *result = parse_file();
|
Ast_Package *result = parse_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
153
new_type.cpp
Normal file
153
new_type.cpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
|
||||||
|
enum Type_Kind{
|
||||||
|
TYPE_None,
|
||||||
|
TYPE_Int,
|
||||||
|
TYPE_String,
|
||||||
|
TYPE_Void,
|
||||||
|
TYPE_Pointer,
|
||||||
|
TYPE_Array,
|
||||||
|
TYPE_Func,
|
||||||
|
TYPE_Struct,
|
||||||
|
TYPE_Union,
|
||||||
|
TYPE_Enum,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Type{
|
||||||
|
Type_Kind kind;
|
||||||
|
SizeU size;
|
||||||
|
SizeU align;
|
||||||
|
union{
|
||||||
|
Type *base;
|
||||||
|
struct{
|
||||||
|
Type *base;
|
||||||
|
SizeU size;
|
||||||
|
}arr;
|
||||||
|
struct{
|
||||||
|
Type *ret;
|
||||||
|
Array<Type*> args;
|
||||||
|
}func;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const SizeU pointer_size = sizeof(SizeU);
|
||||||
|
const SizeU pointer_align = __alignof(SizeU);
|
||||||
|
|
||||||
|
global Type type__void = {TYPE_Void};
|
||||||
|
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
||||||
|
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
||||||
|
|
||||||
|
global Type *type_void = &type__void;
|
||||||
|
global Type *type_int = &type__int;
|
||||||
|
global Type *type_string = &type__string;
|
||||||
|
|
||||||
|
function Type *
|
||||||
|
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
|
||||||
|
Type *result = exp_alloc_type(allocator, Type);
|
||||||
|
result->kind = kind;
|
||||||
|
result->size = size;
|
||||||
|
result->align = align;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Type *
|
||||||
|
type_copy(Allocator *a, Type *type){
|
||||||
|
Type *result = exp_alloc_type(a, Type);
|
||||||
|
memory_copy(result, type, sizeof(Type));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Type *
|
||||||
|
type_pointer(Type *base){
|
||||||
|
Get_Ctx(Parse_Ctx);
|
||||||
|
Type *result = (Type *)map_get(&ctx->type_map, (void *)base);
|
||||||
|
if(!result){
|
||||||
|
result = type_new(&ctx->ast_arena, TYPE_Pointer, pointer_size, pointer_align);
|
||||||
|
result->base = base;
|
||||||
|
map_insert(&ctx->type_map, base, result);
|
||||||
|
}
|
||||||
|
assert(result->kind == TYPE_Pointer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Type *
|
||||||
|
type_array(Type *base, SizeU size){
|
||||||
|
Get_Ctx(Parse_Ctx);
|
||||||
|
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
||||||
|
Type *result = (Type *)map_get_u64(&ctx->type_map, hash);
|
||||||
|
if(result){
|
||||||
|
assert(result->kind == TYPE_Array);
|
||||||
|
assert(result->arr.size == size);
|
||||||
|
assert(result->arr.base == base);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = type_new(&ctx->ast_arena, TYPE_Array, pointer_size, pointer_align);
|
||||||
|
result->arr.base = base;
|
||||||
|
result->arr.size = size;
|
||||||
|
map_insert_u64(&ctx->type_map, hash, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Type *
|
||||||
|
type_function(Type *ret, Array<Type *> args){
|
||||||
|
Get_Ctx(Parse_Ctx);
|
||||||
|
|
||||||
|
U64 hash = hash_ptr(ret);
|
||||||
|
IFor(args){
|
||||||
|
hash = hash_mix(hash, hash_ptr(*it));
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *result = (Type *)map_get_u64(&ctx->type_map, hash);
|
||||||
|
if(result){
|
||||||
|
assert(result->kind == TYPE_Func);
|
||||||
|
assert(result->func.ret == ret);
|
||||||
|
assert(result->func.args.len == args.len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = type_new(&ctx->ast_arena, TYPE_Func, pointer_size, pointer_align);
|
||||||
|
result->func.ret = ret;
|
||||||
|
result->func.args = args.copy(&ctx->ast_arena);
|
||||||
|
map_insert_u64(&ctx->type_map, hash, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
test_types(){
|
||||||
|
Set_Backup_Scratch();
|
||||||
|
Set_Scratch();
|
||||||
|
Parse_Ctx ctx = {};
|
||||||
|
Set_Ctx(&ctx, Parse_Ctx_ID);
|
||||||
|
ctx.ast_arena = thread_ctx.scratch[1];
|
||||||
|
|
||||||
|
Type *array_type1 = type_array(type_int, 32);
|
||||||
|
Type *array_type2 = type_array(type_int, 32);
|
||||||
|
Type *array_type3 = type_array(type_int, 48);
|
||||||
|
assert(array_type1 == array_type2);
|
||||||
|
assert(array_type2 != array_type3);
|
||||||
|
Type *pointer_type1 = type_pointer(type_int);
|
||||||
|
Type *pointer_type2 = type_pointer(type_int);
|
||||||
|
assert(pointer_type2 == pointer_type1);
|
||||||
|
Type *pointer_type3 = type_pointer(pointer_type1);
|
||||||
|
Type *pointer_type4 = type_pointer(pointer_type2);
|
||||||
|
assert(pointer_type3 != pointer_type1);
|
||||||
|
assert(pointer_type3 == pointer_type4);
|
||||||
|
|
||||||
|
Array<Type*> types = {};
|
||||||
|
types.add(type_array(type_int, 32));
|
||||||
|
Type *func_type1 = type_function(types[0], types);
|
||||||
|
Type *func_type2 = type_function(types[0], types);
|
||||||
|
assert(func_type1 == func_type2);
|
||||||
|
|
||||||
|
Array<Type*> types2 = {};
|
||||||
|
{
|
||||||
|
types2.add(type_array(type_int, 32));
|
||||||
|
types2.add(type_int);
|
||||||
|
}
|
||||||
|
types.add(type_int);
|
||||||
|
Type *func_type3 = type_function(types[0], types);
|
||||||
|
Type *func_type4 = type_function(types[0], types2);
|
||||||
|
assert(func_type1 != func_type3);
|
||||||
|
assert(func_type3 == func_type4);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user