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 gib(x) (mib(x)*1024llu)
|
||||
struct String{U8 *str;S64 len;};
|
||||
union Intern_String{
|
||||
String s;
|
||||
struct{ U8 *str; S64 len; };
|
||||
};
|
||||
union Intern_String{ String s; struct{ U8 *str; S64 len; }; }; // Basically just String
|
||||
|
||||
#define JOIN1(X,Y) X##Y // helper macro
|
||||
#define JOIN(X,Y) JOIN1(X,Y)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -287,6 +286,11 @@ struct Arena:Allocator{
|
||||
OS_Memory memory;
|
||||
SizeU alignment;
|
||||
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);
|
||||
@@ -347,7 +351,24 @@ force_inline void *
|
||||
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
||||
Arena *arena = (Arena *)a;
|
||||
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
|
||||
@@ -447,8 +468,8 @@ report__file_and_line(const char *file, int line){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Implicit scratch stack
|
||||
//-----------------------------------------------------------------------------
|
||||
#define Set_Scratch() Scoped_Scratch scratch_##__LINE__
|
||||
#define Set_Backup_Scratch() Scoped_Scratch scratch_##__LINE__(true)
|
||||
#define Set_Scratch() Scoped_Scratch JOIN(scratch, __LINE__)
|
||||
#define Set_Backup_Scratch() Scoped_Scratch JOIN(scratch, __LINE__)(true)
|
||||
struct Scoped_Scratch{
|
||||
SizeU saved_pos;
|
||||
Allocator *saved_allocator;
|
||||
@@ -470,7 +491,7 @@ struct Scoped_Scratch{
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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{
|
||||
Allocator *allocator;
|
||||
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 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{
|
||||
void *prev_ctx;
|
||||
U64 prev_id;
|
||||
@@ -699,7 +720,6 @@ test_custom_context(){
|
||||
assert(thread_ctx.ctx == 0);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defer
|
||||
// http://www.gingerbill.org/article/2015/08/19/defer-in-cpp/
|
||||
@@ -757,6 +777,16 @@ struct Array{
|
||||
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 *end (){ return data + len; }
|
||||
T &operator[](S64 i){ return data[i]; }
|
||||
@@ -1089,17 +1119,18 @@ test_intern_table(){ Set_Scratch();
|
||||
#include "new_lex.cpp"
|
||||
#include "new_ast.cpp"
|
||||
#include "new_parse.cpp"
|
||||
#include "new_type.cpp"
|
||||
int main(){
|
||||
test_custom_context();
|
||||
test_heap_allocator();
|
||||
test_os_memory();
|
||||
|
||||
thread_ctx_init();
|
||||
map_test();
|
||||
|
||||
test_types();
|
||||
test_parse_decl();
|
||||
test_parse_expr();
|
||||
|
||||
map_test();
|
||||
test_array();
|
||||
test_string_builder();
|
||||
test_intern_table();
|
||||
|
||||
@@ -16,6 +16,7 @@ struct Parse_Ctx:Lexer{
|
||||
Token empty_token;
|
||||
S64 indent;
|
||||
S64 pt[256]; // precedence table
|
||||
Map type_map;
|
||||
|
||||
void init(){
|
||||
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);
|
||||
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