Clang format
This commit is contained in:
506
base.cpp
506
base.cpp
@@ -1,117 +1,117 @@
|
||||
#define CORE_BASE
|
||||
|
||||
#if defined(__clang__)
|
||||
# define COMPILER_CLANG 1
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# else
|
||||
# error Couldnt figure out the platform automatically
|
||||
# endif
|
||||
#define COMPILER_CLANG 1
|
||||
#if defined(_WIN32)
|
||||
#define OS_WINDOWS 1
|
||||
#elif defined(__linux__)
|
||||
#define OS_LINUX 1
|
||||
#else
|
||||
#error Couldnt figure out the platform automatically
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define COMPILER_MSVC 1
|
||||
# define OS_WINDOWS 1
|
||||
#define COMPILER_MSVC 1
|
||||
#define OS_WINDOWS 1
|
||||
#elif defined(__GNUC__)
|
||||
# define COMPILER_GCC 1
|
||||
# if defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# endif
|
||||
#define COMPILER_GCC 1
|
||||
#if defined(__linux__)
|
||||
#define OS_LINUX 1
|
||||
#endif
|
||||
#else
|
||||
# error Couldnt figure out the compiler
|
||||
#error Couldnt figure out the compiler
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#define OS_UNIX 1
|
||||
#define OS_UNIX 1
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
#define OS_UNIX 1
|
||||
#define OS_UNIX 1
|
||||
#endif
|
||||
|
||||
#if !defined(COMPILER_MSVC)
|
||||
# define COMPILER_MSVC 0
|
||||
#define COMPILER_MSVC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_GCC)
|
||||
# define COMPILER_GCC 0
|
||||
#define COMPILER_GCC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_CLANG)
|
||||
# define COMPILER_CLANG 0
|
||||
#define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(OS_WINDOWS)
|
||||
# define OS_WINDOWS 0
|
||||
#define OS_WINDOWS 0
|
||||
#endif
|
||||
#if !defined(OS_LINUX)
|
||||
# define OS_LINUX 0
|
||||
#define OS_LINUX 0
|
||||
#endif
|
||||
#if !defined(OS_MAC)
|
||||
# define OS_MAC 0
|
||||
#define OS_MAC 0
|
||||
#endif
|
||||
#if !defined(OS_UNIX)
|
||||
# define OS_UNIX 0
|
||||
#define OS_UNIX 0
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
#define OS_EXE ".exe"
|
||||
#define OS_NAME "Win32"_s
|
||||
#define OS_NAME_LOWER "win32"_s
|
||||
#define OS_EXE ".exe"
|
||||
#define OS_NAME "Win32"_s
|
||||
#define OS_NAME_LOWER "win32"_s
|
||||
#elif OS_LINUX
|
||||
#define OS_EXE ".out"
|
||||
#define OS_NAME "Linux"_s
|
||||
#define OS_NAME_LOWER "linux"_s
|
||||
#define OS_EXE ".out"
|
||||
#define OS_NAME "Linux"_s
|
||||
#define OS_NAME_LOWER "linux"_s
|
||||
#elif OS_MAC
|
||||
#define OS_EXE ".out"
|
||||
#define OS_NAME "Mac"_s
|
||||
#define OS_NAME_LOWER "mac"_s
|
||||
#define OS_EXE ".out"
|
||||
#define OS_NAME "Mac"_s
|
||||
#define OS_NAME_LOWER "mac"_s
|
||||
#else
|
||||
#error Couldnt figure out the OS with C macros!
|
||||
#error Couldnt figure out the OS with C macros!
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
#define NOMINMAX
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#define Breakpoint __debugbreak()
|
||||
#define force_inline __forceinline
|
||||
#define NOMINMAX
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#define Breakpoint __debugbreak()
|
||||
#define force_inline __forceinline
|
||||
#else
|
||||
#define Breakpoint (*(volatile int *)0 = 0)
|
||||
#define force_inline inline
|
||||
#define Breakpoint (*(volatile int *)0 = 0)
|
||||
#define force_inline inline
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
typedef uint8_t U8;
|
||||
typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef uint64_t U64;
|
||||
typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
typedef S64 B64;
|
||||
typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
typedef S64 B64;
|
||||
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
|
||||
#define U64MAX UINT64_MAX
|
||||
#define U32MAX UINT32_MAX
|
||||
#define U16MAX UINT16_MAX
|
||||
#define U8MAX UINT8_MAX
|
||||
#define U8MAX UINT8_MAX
|
||||
#define U64MIN 0
|
||||
#define U32MIN 0
|
||||
#define U16MIN 0
|
||||
#define U8MIN 0
|
||||
#define U8MIN 0
|
||||
#define S64MAX INT64_MAX
|
||||
#define S64MIN INT64_MIN
|
||||
#define S32MAX INT32_MAX
|
||||
#define S32MIN INT32_MIN
|
||||
#define S16MAX INT16_MAX
|
||||
#define S16MIN INT16_MIN
|
||||
#define S8MAX INT8_MAX
|
||||
#define S8MIN INT8_MIN
|
||||
#define S8MAX INT8_MAX
|
||||
#define S8MIN INT8_MIN
|
||||
#define F32MAX FLT_MAX
|
||||
#define F32MIN FLT_MIN
|
||||
#define F64MAX DBL_MAX
|
||||
@@ -120,305 +120,323 @@ typedef double F64;
|
||||
#define api
|
||||
#define CORE_Static static
|
||||
#define global static
|
||||
#define assert(x) do{if(!(x))Breakpoint;}while(0)
|
||||
#define assert_message(x,...) assert(x)
|
||||
#define assert(x) \
|
||||
do { \
|
||||
if (!(x)) Breakpoint; \
|
||||
} while (0)
|
||||
#define assert_message(x, ...) assert(x)
|
||||
#define invalid_codepath assert_message(0, "Invalid codepath")
|
||||
#define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0)
|
||||
#define invalid_default_case default: invalid_codepath
|
||||
#define invalid_return \
|
||||
do { \
|
||||
assert_message(0, "Invalid codepath"); \
|
||||
return {}; \
|
||||
} while (0)
|
||||
#define invalid_default_case \
|
||||
default: \
|
||||
invalid_codepath
|
||||
#define not_implemented assert_message(0, "Not implemented")
|
||||
#define unused(x) ((void)x)
|
||||
#define buff_cap(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define is_flag_set(val,flag) ((val) & (flag))
|
||||
#define set_flag(val,flag) ((val) |= (flag))
|
||||
#define unset_flag(val,flag) ((val) &= (~(flag)))
|
||||
#define buff_cap(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define is_flag_set(val, flag) ((val) & (flag))
|
||||
#define set_flag(val, flag) ((val) |= (flag))
|
||||
#define unset_flag(val, flag) ((val) &= (~(flag)))
|
||||
#define bit_flag(x) (1ull << (x))
|
||||
#define kib(x) ((x)*1024llu)
|
||||
#define mib(x) (kib(x)*1024llu)
|
||||
#define gib(x) (mib(x)*1024llu)
|
||||
#define JOIN1(X,Y) X##Y
|
||||
#define JOIN(X,Y) JOIN1(X,Y)
|
||||
#define mib(x) (kib(x) * 1024llu)
|
||||
#define gib(x) (mib(x) * 1024llu)
|
||||
#define JOIN1(X, Y) X##Y
|
||||
#define JOIN(X, Y) JOIN1(X, Y)
|
||||
#define string_expand(x) (int)x.len, x.str
|
||||
|
||||
struct String{
|
||||
U8 *str;
|
||||
S64 len;
|
||||
struct String {
|
||||
U8 *str;
|
||||
S64 len;
|
||||
};
|
||||
global String string_null = {(U8 *)"null", 4};
|
||||
|
||||
union Intern_String{ // Basically just String
|
||||
String s;
|
||||
struct{ U8 *str; S64 len; };
|
||||
union Intern_String { // Basically just String
|
||||
String s;
|
||||
struct {
|
||||
U8 *str;
|
||||
S64 len;
|
||||
};
|
||||
};
|
||||
|
||||
struct Allocator {
|
||||
typedef void *Allocate(Allocator *, size_t);
|
||||
typedef void Deallocate(Allocator *, void *p);
|
||||
typedef void *Allocate(Allocator *, size_t);
|
||||
typedef void Deallocate(Allocator *, void *p);
|
||||
|
||||
Allocate *allocate;
|
||||
Deallocate *deallocate;
|
||||
Allocate *allocate;
|
||||
Deallocate *deallocate;
|
||||
};
|
||||
|
||||
CORE_Static void memory_zero(void *p, size_t size);
|
||||
CORE_Static void deallocate_stub(Allocator *, void *) {}
|
||||
|
||||
#define allocate_array(a, T, size,...) (T *)allocate_size(a, sizeof(T)*(size),##__VA_ARGS__)
|
||||
#define allocate_struct(a, T, ...) allocate_array(a, T, 1,##__VA_ARGS__)
|
||||
#define allocate_array(a, T, size, ...) (T *)allocate_size(a, sizeof(T) * (size), ##__VA_ARGS__)
|
||||
#define allocate_struct(a, T, ...) allocate_array(a, T, 1, ##__VA_ARGS__)
|
||||
CORE_Static void *allocate_size(Allocator *allocator, size_t size, bool zero_memory = true) {
|
||||
void *result = allocator->allocate(allocator, size);
|
||||
if (zero_memory) {
|
||||
memory_zero(result, size);
|
||||
}
|
||||
return result;
|
||||
void *result = allocator->allocate(allocator, size);
|
||||
if (zero_memory) {
|
||||
memory_zero(result, size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void deallocate(Allocator *allocator, void *p) {
|
||||
assert(p);
|
||||
allocator->deallocate(allocator, p);
|
||||
assert(p);
|
||||
allocator->deallocate(allocator, p);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
CORE_Static size_t
|
||||
get_align_offset(size_t size, size_t align){
|
||||
size_t mask = align - 1;
|
||||
size_t val = size & mask;
|
||||
if(val){
|
||||
val = align - val;
|
||||
}
|
||||
return val;
|
||||
get_align_offset(size_t size, size_t align) {
|
||||
size_t mask = align - 1;
|
||||
size_t val = size & mask;
|
||||
if (val) {
|
||||
val = align - val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
CORE_Static size_t
|
||||
align_up(size_t size, size_t align){
|
||||
size_t result = size + get_align_offset(size, align);
|
||||
return result;
|
||||
align_up(size_t size, size_t align) {
|
||||
size_t result = size + get_align_offset(size, align);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static size_t
|
||||
align_down(size_t size, size_t align){
|
||||
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
|
||||
size_t result = size - (align - get_align_offset(size, align));
|
||||
return result;
|
||||
align_down(size_t size, size_t align) {
|
||||
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
|
||||
size_t result = size - (align - get_align_offset(size, align));
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
memory_copy(void *dst, const void *src, size_t size){
|
||||
U8 *d = (U8*)dst;
|
||||
U8 *s = (U8*)src;
|
||||
for(size_t i = 0; i < size; i++){
|
||||
d[i] = s[i];
|
||||
}
|
||||
memory_copy(void *dst, const void *src, size_t size) {
|
||||
U8 *d = (U8 *)dst;
|
||||
U8 *s = (U8 *)src;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
memory_zero(void *p, size_t size){
|
||||
U8 *pp = (U8 *)p;
|
||||
for(size_t i = 0; i < size; i++)
|
||||
pp[i] = 0;
|
||||
memory_zero(void *p, size_t size) {
|
||||
U8 *pp = (U8 *)p;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
pp[i] = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void swap(T &a, T &b){
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
template <class T>
|
||||
void swap(T &a, T &b) {
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T max(T a, T b){
|
||||
if(a > b) return a;
|
||||
return b;
|
||||
template <class T>
|
||||
T max(T a, T b) {
|
||||
if (a > b) return a;
|
||||
return b;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T min(T a, T b){
|
||||
if(a > b) return b;
|
||||
return a;
|
||||
template <class T>
|
||||
T min(T a, T b) {
|
||||
if (a > b) return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T clamp_top(T val, T max){
|
||||
if(val > max) val = max;
|
||||
return val;
|
||||
template <class T>
|
||||
T clamp_top(T val, T max) {
|
||||
if (val > max) val = max;
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T clamp_bot(T bot, T val){
|
||||
if(val < bot) val = bot;
|
||||
return val;
|
||||
template <class T>
|
||||
T clamp_bot(T bot, T val) {
|
||||
if (val < bot) val = bot;
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T clamp(T min, T val, T max){
|
||||
if(val > max) val = max;
|
||||
if(val < min) val = min;
|
||||
return val;
|
||||
template <class T>
|
||||
T clamp(T min, T val, T max) {
|
||||
if (val > max) val = max;
|
||||
if (val < min) val = min;
|
||||
return val;
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
hash_string(String string) {
|
||||
U64 hash = (U64)14695981039346656037ULL;
|
||||
for (S64 i = 0; i < string.len; i++) {
|
||||
hash = hash ^ (U64)(string.str[i]);
|
||||
hash = hash * (U64)1099511628211ULL;
|
||||
}
|
||||
return hash;
|
||||
U64 hash = (U64)14695981039346656037ULL;
|
||||
for (S64 i = 0; i < string.len; i++) {
|
||||
hash = hash ^ (U64)(string.str[i]);
|
||||
hash = hash * (U64)1099511628211ULL;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
hash_u64(U64 x) {
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= x >> 32;
|
||||
return x;
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= x >> 32;
|
||||
return x;
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
hash_ptr(const void *ptr) {
|
||||
return hash_u64((uintptr_t)ptr);
|
||||
return hash_u64((uintptr_t)ptr);
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
hash_mix(U64 x, U64 y) {
|
||||
// @note: murmur hash 3 mixer but I add the 'y'
|
||||
// which means it's probably bad, hopefully better
|
||||
// then some random scribble I could do
|
||||
x ^= (y >> 33);
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= (x >> 33);
|
||||
x *= 0xc4ceb9fe1a85ec53;
|
||||
x ^= (y >> 33);
|
||||
return x;
|
||||
// @note: murmur hash 3 mixer but I add the 'y'
|
||||
// which means it's probably bad, hopefully better
|
||||
// then some random scribble I could do
|
||||
x ^= (y >> 33);
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= (x >> 33);
|
||||
x *= 0xc4ceb9fe1a85ec53;
|
||||
x ^= (y >> 33);
|
||||
return x;
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
is_pow2(U64 x) {
|
||||
assert(x != 0);
|
||||
B32 result = (x & (x - 1llu)) == 0;
|
||||
return result;
|
||||
assert(x != 0);
|
||||
B32 result = (x & (x - 1llu)) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
wrap_around_pow2(U64 x, U64 power_of_2) {
|
||||
assert(is_pow2(power_of_2));
|
||||
U64 r = (((x)&((power_of_2)-1llu)));
|
||||
return r;
|
||||
assert(is_pow2(power_of_2));
|
||||
U64 r = (((x) & ((power_of_2)-1llu)));
|
||||
return r;
|
||||
}
|
||||
|
||||
force_inline String
|
||||
operator""_s(const char *str, size_t size){
|
||||
return String{(U8 *)str, (S64)size};
|
||||
operator""_s(const char *str, size_t size) {
|
||||
return String{(U8 *)str, (S64)size};
|
||||
}
|
||||
|
||||
force_inline B32
|
||||
operator==(Intern_String a, Intern_String b){
|
||||
return a.str == b.str;
|
||||
operator==(Intern_String a, Intern_String b) {
|
||||
return a.str == b.str;
|
||||
}
|
||||
|
||||
force_inline B32
|
||||
operator!=(Intern_String a, Intern_String b){
|
||||
B32 result = a.str == b.str;
|
||||
return !result;
|
||||
operator!=(Intern_String a, Intern_String b) {
|
||||
B32 result = a.str == b.str;
|
||||
return !result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Very cool macros. Since these are macros it's recommended to wrap them
|
||||
// in a function and not use directly
|
||||
//----- -----------------------------------------------------------------------
|
||||
#define SLL_QUEUE_ADD_MOD(f, l, n, next) \
|
||||
do { \
|
||||
if ((f) == 0) { \
|
||||
(f) = (l) = (n); \
|
||||
} else { \
|
||||
(l) = (l)->next = (n); \
|
||||
} \
|
||||
#define SLL_QUEUE_ADD_MOD(f, l, n, next) \
|
||||
do { \
|
||||
if ((f) == 0) { \
|
||||
(f) = (l) = (n); \
|
||||
} \
|
||||
else { \
|
||||
(l) = (l)->next = (n); \
|
||||
} \
|
||||
} while (0)
|
||||
#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next)
|
||||
|
||||
#define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \
|
||||
do { \
|
||||
if ((f) == (l)) { \
|
||||
(f) = (l) = 0; \
|
||||
} else { \
|
||||
(f) = (f)->next; \
|
||||
} \
|
||||
#define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \
|
||||
do { \
|
||||
if ((f) == (l)) { \
|
||||
(f) = (l) = 0; \
|
||||
} \
|
||||
else { \
|
||||
(f) = (f)->next; \
|
||||
} \
|
||||
} while (0)
|
||||
#define SLL_QUEUE_POP_FIRST(f, l) SLL_QUEUE_POP_FIRST_MOD(f, l, next)
|
||||
|
||||
#define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \
|
||||
do { \
|
||||
(new_stack_base)->next = (stack_base); \
|
||||
(stack_base) = (new_stack_base); \
|
||||
#define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \
|
||||
do { \
|
||||
(new_stack_base)->next = (stack_base); \
|
||||
(stack_base) = (new_stack_base); \
|
||||
} while (0)
|
||||
#define SLL_STACK_ADD(stack_base, new_stack_base) SLL_STACK_ADD_MOD(stack_base, new_stack_base, next)
|
||||
|
||||
#define SLL_STACK_POP(stack_base) \
|
||||
do { \
|
||||
if (stack_base) { \
|
||||
auto(N) = (stack_base); \
|
||||
(stack_base) = (stack_base)->next; \
|
||||
(N)->next = 0; \
|
||||
} \
|
||||
#define SLL_STACK_POP(stack_base) \
|
||||
do { \
|
||||
if (stack_base) { \
|
||||
auto(N) = (stack_base); \
|
||||
(stack_base) = (stack_base)->next; \
|
||||
(N)->next = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev) \
|
||||
do { \
|
||||
if ((f) == 0) { \
|
||||
(f) = (l) = (node); \
|
||||
(node)->prev = 0; \
|
||||
(node)->next = 0; \
|
||||
} else { \
|
||||
(l)->next = (node); \
|
||||
(node)->prev = (l); \
|
||||
(node)->next = 0; \
|
||||
(l) = (node); \
|
||||
} \
|
||||
#define DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev) \
|
||||
do { \
|
||||
if ((f) == 0) { \
|
||||
(f) = (l) = (node); \
|
||||
(node)->prev = 0; \
|
||||
(node)->next = 0; \
|
||||
} \
|
||||
else { \
|
||||
(l)->next = (node); \
|
||||
(node)->prev = (l); \
|
||||
(node)->next = 0; \
|
||||
(l) = (node); \
|
||||
} \
|
||||
} while (0)
|
||||
#define DLL_QUEUE_ADD_LAST(f, l, node) DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev)
|
||||
#define DLL_QUEUE_ADD(f, l, node) DLL_QUEUE_ADD_LAST(f, l, node)
|
||||
#define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \
|
||||
do { \
|
||||
if ((first) == (last)) { \
|
||||
assert_message((node) == (first), "Macro assert failed"); \
|
||||
(first) = (last) = 0; \
|
||||
} else if ((last) == (node)) { \
|
||||
(last) = (last)->prev; \
|
||||
(last)->next = 0; \
|
||||
} else if ((first) == (node)) { \
|
||||
(first) = (first)->next; \
|
||||
(first)->prev = 0; \
|
||||
} else { \
|
||||
(node)->prev->next = (node)->next; \
|
||||
(node)->next->prev = (node)->prev; \
|
||||
} \
|
||||
#define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \
|
||||
do { \
|
||||
if ((first) == (last)) { \
|
||||
assert_message((node) == (first), "Macro assert failed"); \
|
||||
(first) = (last) = 0; \
|
||||
} \
|
||||
else if ((last) == (node)) { \
|
||||
(last) = (last)->prev; \
|
||||
(last)->next = 0; \
|
||||
} \
|
||||
else if ((first) == (node)) { \
|
||||
(first) = (first)->next; \
|
||||
(first)->prev = 0; \
|
||||
} \
|
||||
else { \
|
||||
(node)->prev->next = (node)->next; \
|
||||
(node)->next->prev = (node)->prev; \
|
||||
} \
|
||||
} while (0)
|
||||
#define DLL_QUEUE_REMOVE(first, last, node) DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev)
|
||||
|
||||
#define DLL_STACK_ADD_MOD(first, node, next, prev) \
|
||||
do { \
|
||||
(node)->next = (first); \
|
||||
if ((first)) \
|
||||
(first)->prev = (node); \
|
||||
(first) = (node); \
|
||||
(node)->prev = 0; \
|
||||
#define DLL_STACK_ADD_MOD(first, node, next, prev) \
|
||||
do { \
|
||||
(node)->next = (first); \
|
||||
if ((first)) \
|
||||
(first)->prev = (node); \
|
||||
(first) = (node); \
|
||||
(node)->prev = 0; \
|
||||
} while (0)
|
||||
#define DLL_STACK_ADD(first, node) DLL_STACK_ADD_MOD(first, node, next, prev)
|
||||
#define DLL_STACK_REMOVE_MOD(first, node, next, prev) \
|
||||
do { \
|
||||
if ((node) == (first)) { \
|
||||
(first) = (first)->next; \
|
||||
if ((first)) \
|
||||
(first)->prev = 0; \
|
||||
} else { \
|
||||
(node)->prev->next = (node)->next; \
|
||||
if ((node)->next) \
|
||||
(node)->next->prev = (node)->prev; \
|
||||
} \
|
||||
#define DLL_STACK_REMOVE_MOD(first, node, next, prev) \
|
||||
do { \
|
||||
if ((node) == (first)) { \
|
||||
(first) = (first)->next; \
|
||||
if ((first)) \
|
||||
(first)->prev = 0; \
|
||||
} \
|
||||
else { \
|
||||
(node)->prev->next = (node)->next; \
|
||||
if ((node)->next) \
|
||||
(node)->next->prev = (node)->prev; \
|
||||
} \
|
||||
} while (0)
|
||||
#define DLL_STACK_REMOVE(first, node) DLL_STACK_REMOVE_MOD(first, node, next, prev)
|
||||
|
||||
#define For_Linked_List_Named(a,it) for(auto *it = (a); it; it=it->next) // @todo: reference?
|
||||
#define For_Linked_List(a) For_Linked_List_Named(a,it)
|
||||
#define For_Named(a,it) for(auto &it : (a))
|
||||
#define For(a) For_Named((a),it)
|
||||
#define For_Linked_List_Named(a, it) for (auto *it = (a); it; it = it->next) // @todo: reference?
|
||||
#define For_Linked_List(a) For_Linked_List_Named(a, it)
|
||||
#define For_Named(a, it) for (auto &it : (a))
|
||||
#define For(a) For_Named((a), it)
|
||||
|
||||
147
base_arena.cpp
147
base_arena.cpp
@@ -5,18 +5,18 @@ struct CRT_Heap : Allocator {};
|
||||
static void *crt_allocate(Allocator *allocator, size_t size) { return malloc(size); }
|
||||
static void crt_deallocate(Allocator *allocator, void *p) { return free(p); }
|
||||
static CRT_Heap make_crt_heap() {
|
||||
CRT_Heap result = {};
|
||||
result.allocate = crt_allocate;
|
||||
result.deallocate = crt_deallocate;
|
||||
return result;
|
||||
CRT_Heap result = {};
|
||||
result.allocate = crt_allocate;
|
||||
result.deallocate = crt_deallocate;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory OS
|
||||
//-----------------------------------------------------------------------------
|
||||
struct OS_Memory{
|
||||
size_t commit, reserve;
|
||||
U8 *data;
|
||||
struct OS_Memory {
|
||||
size_t commit, reserve;
|
||||
U8 *data;
|
||||
};
|
||||
CORE_Static OS_Memory os_reserve(size_t size);
|
||||
CORE_Static B32 os_commit(OS_Memory *m, size_t size);
|
||||
@@ -26,104 +26,107 @@ CORE_Static B32 os_decommit_pos(OS_Memory *m, size_t pos);
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory arenas
|
||||
//-----------------------------------------------------------------------------
|
||||
global const size_t default_reserve_size = gib(4);
|
||||
global const size_t default_alignment = 8;
|
||||
global const size_t default_reserve_size = gib(4);
|
||||
global const size_t default_alignment = 8;
|
||||
global const size_t additional_commit_size = mib(1);
|
||||
struct Arena : Allocator {
|
||||
OS_Memory memory;
|
||||
size_t alignment;
|
||||
size_t len;
|
||||
String debug_string;
|
||||
OS_Memory memory;
|
||||
size_t alignment;
|
||||
size_t len;
|
||||
String debug_string;
|
||||
};
|
||||
|
||||
CORE_Static void
|
||||
arena_pop_pos(Arena *arena, size_t pos){
|
||||
pos = clamp_top(pos, arena->len);
|
||||
arena->len = pos;
|
||||
arena_pop_pos(Arena *arena, size_t pos) {
|
||||
pos = clamp_top(pos, arena->len);
|
||||
arena->len = pos;
|
||||
}
|
||||
|
||||
CORE_Static void *
|
||||
arena_pop(Arena *arena, size_t size){
|
||||
size = clamp_top(size, arena->len);
|
||||
arena->len -= size;
|
||||
return arena->memory.data + arena->len;
|
||||
arena_pop(Arena *arena, size_t size) {
|
||||
size = clamp_top(size, arena->len);
|
||||
arena->len -= size;
|
||||
return arena->memory.data + arena->len;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
arena_release(Arena *arena){
|
||||
os_release(&arena->memory);
|
||||
arena_release(Arena *arena) {
|
||||
os_release(&arena->memory);
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
arena_clear(Arena *arena){
|
||||
arena_pop_pos(arena, 0);
|
||||
arena_clear(Arena *arena) {
|
||||
arena_pop_pos(arena, 0);
|
||||
}
|
||||
|
||||
CORE_Static void *
|
||||
arena_push_size(Arena *a, size_t size){
|
||||
size_t generous_size = size + a->alignment;
|
||||
if(a->len+generous_size>a->memory.commit){
|
||||
assert(a->memory.reserve > 0);
|
||||
B32 result = os_commit(&a->memory, generous_size+additional_commit_size);
|
||||
assert(result);
|
||||
}
|
||||
arena_push_size(Arena *a, size_t size) {
|
||||
size_t generous_size = size + a->alignment;
|
||||
if (a->len + generous_size > a->memory.commit) {
|
||||
assert(a->memory.reserve > 0);
|
||||
B32 result = os_commit(&a->memory, generous_size + additional_commit_size);
|
||||
assert(result);
|
||||
}
|
||||
|
||||
a->len = align_up(a->len, a->alignment);
|
||||
assert(a->memory.reserve > a->len + size);
|
||||
void *result = (U8*)a->memory.data + a->len;
|
||||
a->len += size;
|
||||
a->len = align_up(a->len, a->alignment);
|
||||
assert(a->memory.reserve > a->len + size);
|
||||
void *result = (U8 *)a->memory.data + a->len;
|
||||
a->len += size;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Arena
|
||||
push_arena(Allocator *allocator, size_t size, String debug_name) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)allocate_size(allocator, size);
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.debug_string = debug_name;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
push_arena(Allocator *allocator, size_t size, String debug_name) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)allocate_size(allocator, size);
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.debug_string = debug_name;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
arena_init(Arena *a, String debug_name){
|
||||
a->memory = os_reserve(default_reserve_size);
|
||||
a->alignment = default_alignment;
|
||||
a->debug_string = debug_name;
|
||||
a->allocate = (Allocator::Allocate *)arena_push_size;
|
||||
a->deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
arena_init(Arena *a, String debug_name) {
|
||||
a->memory = os_reserve(default_reserve_size);
|
||||
a->alignment = default_alignment;
|
||||
a->debug_string = debug_name;
|
||||
a->allocate = (Allocator::Allocate *)arena_push_size;
|
||||
a->deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
}
|
||||
|
||||
CORE_Static Arena
|
||||
arena_sub(Arena *base, size_t size, String debug_name) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)arena_push_size(base, size);
|
||||
result.memory.commit = size;
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate= (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
arena_sub(Arena *base, size_t size, String debug_name) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)arena_push_size(base, size);
|
||||
result.memory.commit = size;
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Arena
|
||||
arena_from_buffer(void *buffer, size_t size) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)buffer;
|
||||
result.memory.commit = size;
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate= (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)buffer;
|
||||
result.memory.commit = size;
|
||||
result.memory.reserve = size;
|
||||
result.alignment = default_alignment;
|
||||
result.allocate = (Allocator::Allocate *)arena_push_size;
|
||||
result.deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct Scratch_Scope {
|
||||
Arena *arena;
|
||||
int pos;
|
||||
Scratch_Scope(Arena *arena) { this->arena = arena; this->pos = arena->len; }
|
||||
~Scratch_Scope() { this->arena->len = this->pos; }
|
||||
Arena *arena;
|
||||
int pos;
|
||||
Scratch_Scope(Arena *arena) {
|
||||
this->arena = arena;
|
||||
this->pos = arena->len;
|
||||
}
|
||||
~Scratch_Scope() { this->arena->len = this->pos; }
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
584
base_string.cpp
584
base_string.cpp
@@ -1,233 +1,234 @@
|
||||
|
||||
CORE_Static U8
|
||||
to_lower_case(U8 a) {
|
||||
if (a >= 'A' && a <= 'Z')
|
||||
a += 32;
|
||||
return a;
|
||||
if (a >= 'A' && a <= 'Z')
|
||||
a += 32;
|
||||
return a;
|
||||
}
|
||||
|
||||
CORE_Static U8
|
||||
to_upper_case(U8 a) {
|
||||
if (a >= 'a' && a <= 'z')
|
||||
a -= 32;
|
||||
return a;
|
||||
if (a >= 'a' && a <= 'z')
|
||||
a -= 32;
|
||||
return a;
|
||||
}
|
||||
|
||||
CORE_Static U8
|
||||
char_to_lower(U8 c){
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
c += 32;
|
||||
return c;
|
||||
char_to_lower(U8 c) {
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c += 32;
|
||||
return c;
|
||||
}
|
||||
|
||||
CORE_Static U8
|
||||
char_to_upper(U8 c){
|
||||
if(c >= 'a' && c <= 'z')
|
||||
c -= 32;
|
||||
return c;
|
||||
char_to_upper(U8 c) {
|
||||
if (c >= 'a' && c <= 'z')
|
||||
c -= 32;
|
||||
return c;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_whitespace(U8 w) {
|
||||
bool result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
|
||||
return result;
|
||||
bool result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_alphabetic(U8 a) {
|
||||
if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_number(U8 a) {
|
||||
B32 result = a >= '0' && a <= '9';
|
||||
return result;
|
||||
B32 result = a >= '0' && a <= '9';
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_alphanumeric(U8 a) {
|
||||
B32 result = is_number(a) || is_alphabetic(a);
|
||||
return result;
|
||||
B32 result = is_number(a) || is_alphabetic(a);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
string_compare(String a, String b, B32 ignore_case = false) {
|
||||
if (a.len != b.len)
|
||||
return false;
|
||||
for (S64 i = 0; i < a.len; i++) {
|
||||
U8 A = a.str[i];
|
||||
U8 B = b.str[i];
|
||||
if (ignore_case) {
|
||||
A = to_lower_case(A);
|
||||
B = to_lower_case(B);
|
||||
if (a.len != b.len)
|
||||
return false;
|
||||
for (S64 i = 0; i < a.len; i++) {
|
||||
U8 A = a.str[i];
|
||||
U8 B = b.str[i];
|
||||
if (ignore_case) {
|
||||
A = to_lower_case(A);
|
||||
B = to_lower_case(B);
|
||||
}
|
||||
if (A != B)
|
||||
return false;
|
||||
}
|
||||
if (A != B)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
operator==(String a, String b){
|
||||
return string_compare(a,b);
|
||||
operator==(String a, String b) {
|
||||
return string_compare(a, b);
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_copy(Allocator *a, String string){
|
||||
U8 *copy = allocate_array(a, U8, string.len+1);
|
||||
memory_copy(copy, string.str, string.len);
|
||||
copy[string.len] = 0;
|
||||
return String{copy, string.len};
|
||||
string_copy(Allocator *a, String string) {
|
||||
U8 *copy = allocate_array(a, U8, string.len + 1);
|
||||
memory_copy(copy, string.str, string.len);
|
||||
copy[string.len] = 0;
|
||||
return String{copy, string.len};
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_fmtv(Allocator *a, const char *str, va_list args1) {
|
||||
va_list args2;
|
||||
va_copy(args2, args1);
|
||||
S64 len = stbsp_vsnprintf(0, 0, str, args2);
|
||||
va_end(args2);
|
||||
va_list args2;
|
||||
va_copy(args2, args1);
|
||||
S64 len = stbsp_vsnprintf(0, 0, str, args2);
|
||||
va_end(args2);
|
||||
|
||||
char *result = allocate_array(a, char, len + 1);
|
||||
stbsp_vsnprintf(result, (int)(len + 1), str, args1);
|
||||
char *result = allocate_array(a, char, len + 1);
|
||||
stbsp_vsnprintf(result, (int)(len + 1), str, args1);
|
||||
|
||||
String res = {(U8 *)result, len};
|
||||
return res;
|
||||
String res = {(U8 *)result, len};
|
||||
return res;
|
||||
}
|
||||
|
||||
#define STRING_FMT(alloc, str, result) \
|
||||
va_list args1; \
|
||||
va_start(args1, str); \
|
||||
String result = string_fmtv(alloc, str, args1); \
|
||||
va_end(args1)
|
||||
va_list args1; \
|
||||
va_start(args1, str); \
|
||||
String result = string_fmtv(alloc, str, args1); \
|
||||
va_end(args1)
|
||||
|
||||
CORE_Static String
|
||||
string_fmt(Allocator *a, const char *str, ...) {
|
||||
STRING_FMT(a, str, result);
|
||||
return result;
|
||||
STRING_FMT(a, str, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// String builder
|
||||
//-----------------------------------------------------------------------------
|
||||
struct String_Builder_Block{
|
||||
String_Builder_Block *next;
|
||||
S64 cap;
|
||||
S64 len;
|
||||
U8 data[0];
|
||||
struct String_Builder_Block {
|
||||
String_Builder_Block *next;
|
||||
S64 cap;
|
||||
S64 len;
|
||||
U8 data[0];
|
||||
};
|
||||
|
||||
struct String_Builder{
|
||||
Allocator *allocator;
|
||||
String_Builder_Block *first_free;
|
||||
String_Builder_Block *first;
|
||||
String_Builder_Block *last;
|
||||
U64 di;
|
||||
struct String_Builder {
|
||||
Allocator *allocator;
|
||||
String_Builder_Block *first_free;
|
||||
String_Builder_Block *first;
|
||||
String_Builder_Block *last;
|
||||
U64 di;
|
||||
|
||||
void reset(){
|
||||
for(;;){
|
||||
auto *block = first;
|
||||
first = first->next;
|
||||
void reset() {
|
||||
for (;;) {
|
||||
auto *block = first;
|
||||
first = first->next;
|
||||
|
||||
block->next = first_free;
|
||||
first_free = block;
|
||||
block->next = first_free;
|
||||
first_free = block;
|
||||
|
||||
if(!first) break;
|
||||
if (!first) break;
|
||||
}
|
||||
|
||||
last = 0;
|
||||
assert(!last && !first);
|
||||
}
|
||||
|
||||
last = 0;
|
||||
assert(!last && !first);
|
||||
}
|
||||
|
||||
void push_block(size_t size){
|
||||
String_Builder_Block *block = 0;
|
||||
if(first_free){
|
||||
block = first_free;
|
||||
first_free = first_free->next;
|
||||
} else{
|
||||
block = (String_Builder_Block *)allocate_size(allocator, sizeof(String_Builder_Block) + size, false);
|
||||
}
|
||||
memory_zero(block, sizeof(String_Builder_Block)+1); // Also clear first byte of character data
|
||||
block->cap = size;
|
||||
SLL_QUEUE_ADD(first, last, block);
|
||||
}
|
||||
|
||||
void init(S64 size = 4096){
|
||||
assert(allocator);
|
||||
push_block(size);
|
||||
}
|
||||
|
||||
void append_data(void *data, S64 size){
|
||||
if(first == 0){
|
||||
init();
|
||||
void push_block(size_t size) {
|
||||
String_Builder_Block *block = 0;
|
||||
if (first_free) {
|
||||
block = first_free;
|
||||
first_free = first_free->next;
|
||||
}
|
||||
else {
|
||||
block = (String_Builder_Block *)allocate_size(allocator, sizeof(String_Builder_Block) + size, false);
|
||||
}
|
||||
memory_zero(block, sizeof(String_Builder_Block) + 1); // Also clear first byte of character data
|
||||
block->cap = size;
|
||||
SLL_QUEUE_ADD(first, last, block);
|
||||
}
|
||||
|
||||
S64 remaining_cap = last->cap - last->len;
|
||||
if(size > remaining_cap){
|
||||
S64 new_block_size = max(last->cap*2, size*2);
|
||||
push_block(new_block_size);
|
||||
void init(S64 size = 4096) {
|
||||
assert(allocator);
|
||||
push_block(size);
|
||||
}
|
||||
|
||||
U8 *write_address = last->data + last->len;
|
||||
last->len += size;
|
||||
memory_copy(write_address, data, size);
|
||||
}
|
||||
void append_data(void *data, S64 size) {
|
||||
if (first == 0) {
|
||||
init();
|
||||
}
|
||||
|
||||
void addf(const char *str, ...){
|
||||
if(first == 0){
|
||||
init();
|
||||
S64 remaining_cap = last->cap - last->len;
|
||||
if (size > remaining_cap) {
|
||||
S64 new_block_size = max(last->cap * 2, size * 2);
|
||||
push_block(new_block_size);
|
||||
}
|
||||
|
||||
U8 *write_address = last->data + last->len;
|
||||
last->len += size;
|
||||
memory_copy(write_address, data, size);
|
||||
}
|
||||
va_list args, args2;
|
||||
va_start(args, str);
|
||||
retry:{
|
||||
String_Builder_Block *block = last;
|
||||
S64 block_size = block->cap - block->len;
|
||||
char *write_address = (char *)block->data + block->len;
|
||||
|
||||
va_copy(args2, args);
|
||||
int written = stbsp_vsnprintf(write_address, (int)block_size, str, args2);
|
||||
va_end(args2);
|
||||
void addf(const char *str, ...) {
|
||||
if (first == 0) {
|
||||
init();
|
||||
}
|
||||
va_list args, args2;
|
||||
va_start(args, str);
|
||||
retry : {
|
||||
String_Builder_Block *block = last;
|
||||
S64 block_size = block->cap - block->len;
|
||||
char *write_address = (char *)block->data + block->len;
|
||||
|
||||
if(written > (block_size-1)){
|
||||
S64 new_block_size = max(4096, (written+1)*2);
|
||||
push_block(new_block_size);
|
||||
goto retry;
|
||||
}
|
||||
block->len += written;
|
||||
va_copy(args2, args);
|
||||
int written = stbsp_vsnprintf(write_address, (int)block_size, str, args2);
|
||||
va_end(args2);
|
||||
|
||||
if (written > (block_size - 1)) {
|
||||
S64 new_block_size = max(4096, (written + 1) * 2);
|
||||
push_block(new_block_size);
|
||||
goto retry;
|
||||
}
|
||||
block->len += written;
|
||||
}
|
||||
va_end(args);
|
||||
di++;
|
||||
}
|
||||
va_end(args);
|
||||
di++;
|
||||
}
|
||||
};
|
||||
|
||||
CORE_Static String_Builder
|
||||
string_builder_make(Allocator *a, S64 first_block_size = 4096){
|
||||
String_Builder sb = {a};
|
||||
sb.init(first_block_size);
|
||||
return sb;
|
||||
string_builder_make(Allocator *a, S64 first_block_size = 4096) {
|
||||
String_Builder sb = {a};
|
||||
sb.init(first_block_size);
|
||||
return sb;
|
||||
}
|
||||
|
||||
// @! Make string_flatten a method
|
||||
static String string_flatten(Allocator *a, String_Builder *b){
|
||||
// @Note(Krzosa): Compute size to allocate
|
||||
S64 size = 1;
|
||||
For_Linked_List(b->first){
|
||||
size += it->len;
|
||||
}
|
||||
static String string_flatten(Allocator *a, String_Builder *b) {
|
||||
// @Note(Krzosa): Compute size to allocate
|
||||
S64 size = 1;
|
||||
For_Linked_List(b->first) {
|
||||
size += it->len;
|
||||
}
|
||||
|
||||
String result = {};
|
||||
result.str = (U8 *)allocate_size(a, size, false);
|
||||
String result = {};
|
||||
result.str = (U8 *)allocate_size(a, size, false);
|
||||
|
||||
// @Note(Krzosa): Copy the content of each block into the string
|
||||
For_Linked_List(b->first){
|
||||
memory_copy(result.str + result.len, it->data, it->len);
|
||||
result.len += it->len;
|
||||
}
|
||||
// @Note(Krzosa): Copy the content of each block into the string
|
||||
For_Linked_List(b->first) {
|
||||
memory_copy(result.str + result.len, it->data, it->len);
|
||||
result.len += it->len;
|
||||
}
|
||||
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -235,241 +236,240 @@ static String string_flatten(Allocator *a, String_Builder *b){
|
||||
//-----------------------------------------------------------------------------
|
||||
CORE_Static void
|
||||
string_path_normalize(String s) {
|
||||
for (S64 i = 0; i < s.len; i++) {
|
||||
if (s.str[i] == '\\')
|
||||
s.str[i] = '/';
|
||||
}
|
||||
for (S64 i = 0; i < s.len; i++) {
|
||||
if (s.str[i] == '\\')
|
||||
s.str[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_make(char *str, S64 len) {
|
||||
String result;
|
||||
result.str = (U8 *)str;
|
||||
result.len = len;
|
||||
return result;
|
||||
String result;
|
||||
result.str = (U8 *)str;
|
||||
result.len = len;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_make(U8 *str, S64 len) {
|
||||
return string_make((char*)str, len);
|
||||
return string_make((char *)str, len);
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_chop(String string, S64 len) {
|
||||
len = clamp_top(len, string.len);
|
||||
String result = string_make(string.str, string.len - len);
|
||||
return result;
|
||||
len = clamp_top(len, string.len);
|
||||
String result = string_make(string.str, string.len - len);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_skip(String string, S64 len) {
|
||||
len = clamp_top(len, string.len);
|
||||
S64 remain = string.len - len;
|
||||
String result = string_make(string.str + len, remain);
|
||||
return result;
|
||||
len = clamp_top(len, string.len);
|
||||
S64 remain = string.len - len;
|
||||
String result = string_make(string.str + len, remain);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_get_postfix(String string, S64 len) {
|
||||
len = clamp_top(len, string.len);
|
||||
S64 remain_len = string.len - len;
|
||||
String result = string_make(string.str + remain_len, len);
|
||||
return result;
|
||||
len = clamp_top(len, string.len);
|
||||
S64 remain_len = string.len - len;
|
||||
String result = string_make(string.str + remain_len, len);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_get_prefix(String string, S64 len) {
|
||||
len = clamp_top(len, string.len);
|
||||
String result = string_make(string.str, len);
|
||||
return result;
|
||||
len = clamp_top(len, string.len);
|
||||
String result = string_make(string.str, len);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_slice(String string, S64 first_index, S64 one_past_last_index) {
|
||||
assert_message(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index");
|
||||
assert_message(string.len > 0, "Slicing string of length 0! Might be an error!");
|
||||
String result = string;
|
||||
if (string.len > 0) {
|
||||
if (one_past_last_index > first_index) {
|
||||
first_index = clamp_top(first_index, string.len - 1);
|
||||
one_past_last_index = clamp_top(one_past_last_index, string.len);
|
||||
result.str += first_index;
|
||||
result.len = one_past_last_index - first_index;
|
||||
assert_message(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index");
|
||||
assert_message(string.len > 0, "Slicing string of length 0! Might be an error!");
|
||||
String result = string;
|
||||
if (string.len > 0) {
|
||||
if (one_past_last_index > first_index) {
|
||||
first_index = clamp_top(first_index, string.len - 1);
|
||||
one_past_last_index = clamp_top(one_past_last_index, string.len);
|
||||
result.str += first_index;
|
||||
result.len = one_past_last_index - first_index;
|
||||
}
|
||||
else {
|
||||
result.len = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.len = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_trim(String string) {
|
||||
if (string.len == 0) return string;
|
||||
if (string.len == 0) return string;
|
||||
|
||||
|
||||
S64 whitespace_begin = 0;
|
||||
for (; whitespace_begin < string.len; whitespace_begin++) {
|
||||
if (!is_whitespace(string.str[whitespace_begin])) {
|
||||
break;
|
||||
S64 whitespace_begin = 0;
|
||||
for (; whitespace_begin < string.len; whitespace_begin++) {
|
||||
if (!is_whitespace(string.str[whitespace_begin])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S64 whitespace_end = string.len;
|
||||
for (; whitespace_end != whitespace_begin; whitespace_end--) {
|
||||
if (!is_whitespace(string.str[whitespace_end - 1])) {
|
||||
break;
|
||||
S64 whitespace_end = string.len;
|
||||
for (; whitespace_end != whitespace_begin; whitespace_end--) {
|
||||
if (!is_whitespace(string.str[whitespace_end - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (whitespace_begin == whitespace_end) {
|
||||
string.len = 0;
|
||||
}
|
||||
else {
|
||||
string = string_slice(string, whitespace_begin, whitespace_end);
|
||||
}
|
||||
if (whitespace_begin == whitespace_end) {
|
||||
string.len = 0;
|
||||
}
|
||||
else {
|
||||
string = string_slice(string, whitespace_begin, whitespace_end);
|
||||
}
|
||||
|
||||
return string;
|
||||
return string;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_trim_end(String string) {
|
||||
S64 whitespace_end = string.len;
|
||||
for (; whitespace_end != 0; whitespace_end--) {
|
||||
if (!is_whitespace(string.str[whitespace_end - 1])) {
|
||||
break;
|
||||
S64 whitespace_end = string.len;
|
||||
for (; whitespace_end != 0; whitespace_end--) {
|
||||
if (!is_whitespace(string.str[whitespace_end - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String result = string_get_prefix(string, whitespace_end);
|
||||
return result;
|
||||
String result = string_get_prefix(string, whitespace_end);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_to_lower_case(Allocator *arena, String s) {
|
||||
String copy = string_copy(arena, s);
|
||||
for (S64 i = 0; i < copy.len; i++) {
|
||||
copy.str[i] = to_lower_case(copy.str[i]);
|
||||
}
|
||||
return copy;
|
||||
String copy = string_copy(arena, s);
|
||||
for (S64 i = 0; i < copy.len; i++) {
|
||||
copy.str[i] = to_lower_case(copy.str[i]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_to_upper_case(Allocator *arena, String s) {
|
||||
String copy = string_copy(arena, s);
|
||||
for (S64 i = 0; i < copy.len; i++) {
|
||||
copy.str[i] = to_upper_case(copy.str[i]);
|
||||
}
|
||||
return copy;
|
||||
String copy = string_copy(arena, s);
|
||||
for (S64 i = 0; i < copy.len; i++) {
|
||||
copy.str[i] = to_upper_case(copy.str[i]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
typedef U32 MatchFlag;
|
||||
enum {
|
||||
MatchFlag_None=0,
|
||||
MatchFlag_FindLast=1,
|
||||
MatchFlag_IgnoreCase=2,
|
||||
MatchFlag_None = 0,
|
||||
MatchFlag_FindLast = 1,
|
||||
MatchFlag_IgnoreCase = 2,
|
||||
};
|
||||
|
||||
CORE_Static B32
|
||||
string_find(String string, String find, MatchFlag flags, S64 *index_out) {
|
||||
B32 result = false;
|
||||
if (flags & MatchFlag_FindLast) {
|
||||
for (S64 i = string.len; i != 0; i--) {
|
||||
S64 index = i - 1;
|
||||
String substring = string_slice(string, index, index + find.len);
|
||||
if (string_compare(substring, find, flags & MatchFlag_IgnoreCase)) {
|
||||
if (index_out)
|
||||
*index_out = index;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
B32 result = false;
|
||||
if (flags & MatchFlag_FindLast) {
|
||||
for (S64 i = string.len; i != 0; i--) {
|
||||
S64 index = i - 1;
|
||||
String substring = string_slice(string, index, index + find.len);
|
||||
if (string_compare(substring, find, flags & MatchFlag_IgnoreCase)) {
|
||||
if (index_out)
|
||||
*index_out = index;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (S64 i = 0; i < string.len; i++) {
|
||||
String substring = string_slice(string, i, i + find.len);
|
||||
if (string_compare(substring, find, flags & MatchFlag_IgnoreCase)) {
|
||||
if (index_out)
|
||||
*index_out = i;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
for (S64 i = 0; i < string.len; i++) {
|
||||
String substring = string_slice(string, i, i + find.len);
|
||||
if (string_compare(substring, find, flags & MatchFlag_IgnoreCase)) {
|
||||
if (index_out)
|
||||
*index_out = i;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_chop_last_slash(String s) {
|
||||
String result = s;
|
||||
string_find(s, "/"_s, MatchFlag_FindLast, &result.len);
|
||||
return result;
|
||||
String result = s;
|
||||
string_find(s, "/"_s, MatchFlag_FindLast, &result.len);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_chop_last_period(String s) {
|
||||
String result = s;
|
||||
string_find(s, "."_s, MatchFlag_FindLast, &result.len);
|
||||
return result;
|
||||
String result = s;
|
||||
string_find(s, "."_s, MatchFlag_FindLast, &result.len);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_skip_to_last_slash(String s) {
|
||||
S64 pos;
|
||||
String result = s;
|
||||
if (string_find(s, "/"_s, MatchFlag_FindLast, &pos)) {
|
||||
result = string_skip(result, pos + 1);
|
||||
}
|
||||
return result;
|
||||
S64 pos;
|
||||
String result = s;
|
||||
if (string_find(s, "/"_s, MatchFlag_FindLast, &pos)) {
|
||||
result = string_skip(result, pos + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_skip_to_last_period(String s) {
|
||||
S64 pos;
|
||||
String result = s;
|
||||
if (string_find(s, "."_s, MatchFlag_FindLast, &pos)) {
|
||||
result = string_skip(result, pos + 1);
|
||||
}
|
||||
return result;
|
||||
S64 pos;
|
||||
String result = s;
|
||||
if (string_find(s, "."_s, MatchFlag_FindLast, &pos)) {
|
||||
result = string_skip(result, pos + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static S64
|
||||
string_len(char *string){
|
||||
S64 len = 0;
|
||||
while(*string++!=0)len++;
|
||||
return len;
|
||||
string_len(char *string) {
|
||||
S64 len = 0;
|
||||
while (*string++ != 0) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string_from_cstring(char *string){
|
||||
String result;
|
||||
result.str = (U8 *)string;
|
||||
result.len = string_len(string);
|
||||
return result;
|
||||
string_from_cstring(char *string) {
|
||||
String result;
|
||||
result.str = (U8 *)string;
|
||||
result.len = string_len(string);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct String_Replace {
|
||||
String find;
|
||||
String replace;
|
||||
String find;
|
||||
String replace;
|
||||
};
|
||||
|
||||
CORE_Static String
|
||||
string_replace(Arena *scratch, Allocator *allocator, String string, Array<String_Replace> pairs){
|
||||
Scratch_Scope _scope(scratch);
|
||||
String_Builder builder = {scratch};
|
||||
for(S64 i = 0; i < string.len; i++){
|
||||
For(pairs){
|
||||
String current = string_skip(string, i);
|
||||
current = string_get_prefix(current, it.find.len);
|
||||
if(current == it.find){
|
||||
builder.append_data(it.replace.str, it.replace.len);
|
||||
i += it.find.len;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
string_replace(Arena *scratch, Allocator *allocator, String string, Array<String_Replace> pairs) {
|
||||
Scratch_Scope _scope(scratch);
|
||||
String_Builder builder = {scratch};
|
||||
for (S64 i = 0; i < string.len; i++) {
|
||||
For(pairs) {
|
||||
String current = string_skip(string, i);
|
||||
current = string_get_prefix(current, it.find.len);
|
||||
if (current == it.find) {
|
||||
builder.append_data(it.replace.str, it.replace.len);
|
||||
i += it.find.len;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
builder.append_data(string.str + i, 1);
|
||||
}
|
||||
return string_flatten(allocator, &builder);
|
||||
builder.append_data(string.str + i, 1);
|
||||
}
|
||||
return string_flatten(allocator, &builder);
|
||||
}
|
||||
394
base_unicode.cpp
394
base_unicode.cpp
@@ -1,274 +1,274 @@
|
||||
global U32 question_mark32 = '?';
|
||||
global U16 question_mark16 = 0x003f;
|
||||
global U8 question_mark8 = '?';
|
||||
global U8 question_mark8 = '?';
|
||||
|
||||
struct String32{
|
||||
U32 *str;
|
||||
S64 len;
|
||||
struct String32 {
|
||||
U32 *str;
|
||||
S64 len;
|
||||
};
|
||||
|
||||
struct UTF32_Result{
|
||||
U32 out_str;
|
||||
S64 advance;
|
||||
B32 error;
|
||||
struct UTF32_Result {
|
||||
U32 out_str;
|
||||
S64 advance;
|
||||
B32 error;
|
||||
};
|
||||
|
||||
CORE_Static UTF32_Result
|
||||
utf8_to_utf32(U8 *c, S64 max_advance) {
|
||||
UTF32_Result result = {};
|
||||
UTF32_Result result = {};
|
||||
|
||||
if ((c[0] & 0b10000000) == 0) { // Check if leftmost zero of first byte is unset
|
||||
if(max_advance >= 1){
|
||||
result.out_str = c[0];
|
||||
result.advance = 1;
|
||||
if ((c[0] & 0b10000000) == 0) { // Check if leftmost zero of first byte is unset
|
||||
if (max_advance >= 1) {
|
||||
result.out_str = c[0];
|
||||
result.advance = 1;
|
||||
}
|
||||
else result.error = 1;
|
||||
}
|
||||
else result.error = 1;
|
||||
}
|
||||
|
||||
else if ((c[0] & 0b11100000) == 0b11000000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000) { // Continuation byte required
|
||||
if(max_advance >= 2){
|
||||
result.out_str = (U32)(c[0] & 0b00011111) << 6u | (c[1] & 0b00111111);
|
||||
result.advance = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
else if ((c[0] & 0b11100000) == 0b11000000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000) { // Continuation byte required
|
||||
if (max_advance >= 2) {
|
||||
result.out_str = (U32)(c[0] & 0b00011111) << 6u | (c[1] & 0b00111111);
|
||||
result.advance = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
}
|
||||
|
||||
else if ((c[0] & 0b11110000) == 0b11100000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000 && (c[2] & 0b11000000) == 0b10000000) { // Two continuation bytes required
|
||||
if(max_advance >= 3){
|
||||
result.out_str = (U32)(c[0] & 0b00001111) << 12u | (U32)(c[1] & 0b00111111) << 6u | (c[2] & 0b00111111);
|
||||
result.advance = 3;
|
||||
}
|
||||
else result.error = 3;
|
||||
else if ((c[0] & 0b11110000) == 0b11100000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000 && (c[2] & 0b11000000) == 0b10000000) { // Two continuation bytes required
|
||||
if (max_advance >= 3) {
|
||||
result.out_str = (U32)(c[0] & 0b00001111) << 12u | (U32)(c[1] & 0b00111111) << 6u | (c[2] & 0b00111111);
|
||||
result.advance = 3;
|
||||
}
|
||||
else result.error = 3;
|
||||
}
|
||||
else result.error = 3;
|
||||
}
|
||||
else result.error = 3;
|
||||
}
|
||||
|
||||
else if ((c[0] & 0b11111000) == 0b11110000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000 && (c[2] & 0b11000000) == 0b10000000 && (c[3] & 0b11000000) == 0b10000000) { // Three continuation bytes required
|
||||
if(max_advance >= 4){
|
||||
result.out_str = (U32)(c[0] & 0b00001111) << 18u | (U32)(c[1] & 0b00111111) << 12u | (U32)(c[2] & 0b00111111) << 6u | (U32)(c[3] & 0b00111111);
|
||||
result.advance = 4;
|
||||
}
|
||||
else result.error = 4;
|
||||
else if ((c[0] & 0b11111000) == 0b11110000) {
|
||||
if ((c[1] & 0b11000000) == 0b10000000 && (c[2] & 0b11000000) == 0b10000000 && (c[3] & 0b11000000) == 0b10000000) { // Three continuation bytes required
|
||||
if (max_advance >= 4) {
|
||||
result.out_str = (U32)(c[0] & 0b00001111) << 18u | (U32)(c[1] & 0b00111111) << 12u | (U32)(c[2] & 0b00111111) << 6u | (U32)(c[3] & 0b00111111);
|
||||
result.advance = 4;
|
||||
}
|
||||
else result.error = 4;
|
||||
}
|
||||
else result.error = 4;
|
||||
}
|
||||
else result.error = 4;
|
||||
}
|
||||
else result.error = 4;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct String16{
|
||||
U16 *str;
|
||||
S64 len;
|
||||
struct String16 {
|
||||
U16 *str;
|
||||
S64 len;
|
||||
};
|
||||
|
||||
struct UTF16_Result{
|
||||
U16 out_str[2];
|
||||
S32 len;
|
||||
B32 error;
|
||||
struct UTF16_Result {
|
||||
U16 out_str[2];
|
||||
S32 len;
|
||||
B32 error;
|
||||
};
|
||||
|
||||
CORE_Static UTF16_Result
|
||||
utf32_to_utf16(U32 codepoint){
|
||||
UTF16_Result result = {};
|
||||
if (codepoint < 0x10000) {
|
||||
result.out_str[0] = (U16)codepoint;
|
||||
result.out_str[1] = 0;
|
||||
result.len = 1;
|
||||
}
|
||||
else if (codepoint <= 0x10FFFF) {
|
||||
U32 code = (codepoint - 0x10000);
|
||||
result.out_str[0] = (U16)(0xD800 | (code >> 10));
|
||||
result.out_str[1] = (U16)(0xDC00 | (code & 0x3FF));
|
||||
result.len = 2;
|
||||
}
|
||||
else{
|
||||
result.error = 1;
|
||||
}
|
||||
utf32_to_utf16(U32 codepoint) {
|
||||
UTF16_Result result = {};
|
||||
if (codepoint < 0x10000) {
|
||||
result.out_str[0] = (U16)codepoint;
|
||||
result.out_str[1] = 0;
|
||||
result.len = 1;
|
||||
}
|
||||
else if (codepoint <= 0x10FFFF) {
|
||||
U32 code = (codepoint - 0x10000);
|
||||
result.out_str[0] = (U16)(0xD800 | (code >> 10));
|
||||
result.out_str[1] = (U16)(0xDC00 | (code & 0x3FF));
|
||||
result.len = 2;
|
||||
}
|
||||
else {
|
||||
result.error = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct UTF8_Result{
|
||||
U8 out_str[4];
|
||||
S32 len;
|
||||
B32 error;
|
||||
struct UTF8_Result {
|
||||
U8 out_str[4];
|
||||
S32 len;
|
||||
B32 error;
|
||||
};
|
||||
|
||||
CORE_Static UTF8_Result
|
||||
utf32_to_utf8(U32 codepoint) {
|
||||
UTF8_Result result = {};
|
||||
if (codepoint <= 0x7F) {
|
||||
result.len = 1;
|
||||
result.out_str[0] = (U8)codepoint;
|
||||
}
|
||||
else if (codepoint <= 0x7FF) {
|
||||
result.len= 2;
|
||||
result.out_str[0] = 0b11000000 | (0b00011111 & (codepoint >> 6));
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & codepoint);
|
||||
}
|
||||
else if (codepoint <= 0xFFFF) { // 16 bit word
|
||||
result.len= 3;
|
||||
result.out_str[0] = 0b11100000 | (0b00001111 & (codepoint >> 12)); // 4 bits
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & (codepoint >> 6)); // 6 bits
|
||||
result.out_str[2] = 0b10000000 | (0b00111111 & codepoint); // 6 bits
|
||||
}
|
||||
else if (codepoint <= 0x10FFFF) { // 21 bit word
|
||||
result.len= 4;
|
||||
result.out_str[0] = 0b11110000 | (0b00000111 & (codepoint >> 18)); // 3 bits
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & (codepoint >> 12)); // 6 bits
|
||||
result.out_str[2] = 0b10000000 | (0b00111111 & (codepoint >> 6)); // 6 bits
|
||||
result.out_str[3] = 0b10000000 | (0b00111111 & codepoint); // 6 bits
|
||||
}
|
||||
else{
|
||||
result.error = true;
|
||||
}
|
||||
UTF8_Result result = {};
|
||||
if (codepoint <= 0x7F) {
|
||||
result.len = 1;
|
||||
result.out_str[0] = (U8)codepoint;
|
||||
}
|
||||
else if (codepoint <= 0x7FF) {
|
||||
result.len = 2;
|
||||
result.out_str[0] = 0b11000000 | (0b00011111 & (codepoint >> 6));
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & codepoint);
|
||||
}
|
||||
else if (codepoint <= 0xFFFF) { // 16 bit word
|
||||
result.len = 3;
|
||||
result.out_str[0] = 0b11100000 | (0b00001111 & (codepoint >> 12)); // 4 bits
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & (codepoint >> 6)); // 6 bits
|
||||
result.out_str[2] = 0b10000000 | (0b00111111 & codepoint); // 6 bits
|
||||
}
|
||||
else if (codepoint <= 0x10FFFF) { // 21 bit word
|
||||
result.len = 4;
|
||||
result.out_str[0] = 0b11110000 | (0b00000111 & (codepoint >> 18)); // 3 bits
|
||||
result.out_str[1] = 0b10000000 | (0b00111111 & (codepoint >> 12)); // 6 bits
|
||||
result.out_str[2] = 0b10000000 | (0b00111111 & (codepoint >> 6)); // 6 bits
|
||||
result.out_str[3] = 0b10000000 | (0b00111111 & codepoint); // 6 bits
|
||||
}
|
||||
else {
|
||||
result.error = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static UTF32_Result
|
||||
utf16_to_utf32(U16 *c, S32 max_advance) {
|
||||
UTF32_Result result = {};
|
||||
if(max_advance >= 1){
|
||||
result.advance = 1;
|
||||
result.out_str = c[0];
|
||||
if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) {
|
||||
if(max_advance >= 2){
|
||||
result.out_str = 0x10000;
|
||||
result.out_str += (U32)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF);
|
||||
result.advance = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
UTF32_Result result = {};
|
||||
if (max_advance >= 1) {
|
||||
result.advance = 1;
|
||||
result.out_str = c[0];
|
||||
if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) {
|
||||
if (max_advance >= 2) {
|
||||
result.out_str = 0x10000;
|
||||
result.out_str += (U32)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF);
|
||||
result.advance = 2;
|
||||
}
|
||||
else result.error = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else result.error = 1;
|
||||
else result.error = 1;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
#define unicode_error(question_mark) \
|
||||
{ \
|
||||
result.str[result.len++] = question_mark; \
|
||||
break; \
|
||||
}
|
||||
#define unicode_error(question_mark) \
|
||||
{ \
|
||||
result.str[result.len++] = question_mark; \
|
||||
break; \
|
||||
}
|
||||
|
||||
CORE_Static String32
|
||||
string16_to_string32(Allocator *allocator, String16 string){
|
||||
String32 result = {allocate_array(allocator, U32, string.len+1)};
|
||||
for(S64 i = 0; i < string.len;){
|
||||
UTF32_Result decode = utf16_to_utf32(string.str + i, (S32)(string.len - i));
|
||||
if(!decode.error){
|
||||
i += decode.advance;
|
||||
result.str[result.len++] = decode.out_str;
|
||||
string16_to_string32(Allocator *allocator, String16 string) {
|
||||
String32 result = {allocate_array(allocator, U32, string.len + 1)};
|
||||
for (S64 i = 0; i < string.len;) {
|
||||
UTF32_Result decode = utf16_to_utf32(string.str + i, (S32)(string.len - i));
|
||||
if (!decode.error) {
|
||||
i += decode.advance;
|
||||
result.str[result.len++] = decode.out_str;
|
||||
}
|
||||
else unicode_error(question_mark32);
|
||||
}
|
||||
else unicode_error(question_mark32);
|
||||
}
|
||||
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String32
|
||||
string8_to_string32(Allocator *allocator, String string){
|
||||
String32 result = {allocate_array(allocator, U32, string.len+1)};
|
||||
for(S64 i = 0; i < string.len;){
|
||||
UTF32_Result decode = utf8_to_utf32(string.str + i, string.len - i);
|
||||
if(!decode.error){
|
||||
i += decode.advance;
|
||||
result.str[result.len++] = decode.out_str;
|
||||
string8_to_string32(Allocator *allocator, String string) {
|
||||
String32 result = {allocate_array(allocator, U32, string.len + 1)};
|
||||
for (S64 i = 0; i < string.len;) {
|
||||
UTF32_Result decode = utf8_to_utf32(string.str + i, string.len - i);
|
||||
if (!decode.error) {
|
||||
i += decode.advance;
|
||||
result.str[result.len++] = decode.out_str;
|
||||
}
|
||||
else unicode_error(question_mark32);
|
||||
}
|
||||
else unicode_error(question_mark32);
|
||||
}
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String16
|
||||
string8_to_string16(Allocator *allocator, String in){
|
||||
String16 result = {allocate_array(allocator, U16, (in.len*2)+1)}; // @Note(Krzosa): Should be more then enough space
|
||||
for(S64 i = 0; i < in.len;){
|
||||
UTF32_Result decode = utf8_to_utf32(in.str + i, in.len - i);
|
||||
if(!decode.error){
|
||||
i += decode.advance;
|
||||
UTF16_Result encode = utf32_to_utf16(decode.out_str);
|
||||
if(!encode.error){
|
||||
for(S32 j = 0; j < encode.len; j++){
|
||||
result.str[result.len++] = encode.out_str[j];
|
||||
string8_to_string16(Allocator *allocator, String in) {
|
||||
String16 result = {allocate_array(allocator, U16, (in.len * 2) + 1)}; // @Note(Krzosa): Should be more then enough space
|
||||
for (S64 i = 0; i < in.len;) {
|
||||
UTF32_Result decode = utf8_to_utf32(in.str + i, in.len - i);
|
||||
if (!decode.error) {
|
||||
i += decode.advance;
|
||||
UTF16_Result encode = utf32_to_utf16(decode.out_str);
|
||||
if (!encode.error) {
|
||||
for (S32 j = 0; j < encode.len; j++) {
|
||||
result.str[result.len++] = encode.out_str[j];
|
||||
}
|
||||
}
|
||||
else unicode_error(question_mark16);
|
||||
}
|
||||
}
|
||||
else unicode_error(question_mark16);
|
||||
else unicode_error(question_mark16);
|
||||
}
|
||||
else unicode_error(question_mark16);
|
||||
}
|
||||
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string16_to_string8(Allocator *allocator, String16 in){
|
||||
String result = {allocate_array(allocator, U8, in.len*4+1)};
|
||||
for(S64 i = 0; i < in.len;){
|
||||
UTF32_Result decode = utf16_to_utf32(in.str + i, (S32)(in.len - i));
|
||||
if(!decode.error){
|
||||
i += decode.advance;
|
||||
UTF8_Result encode = utf32_to_utf8(decode.out_str);
|
||||
if(!encode.error){
|
||||
for(S32 j = 0; j < encode.len; j++)
|
||||
result.str[result.len++] = encode.out_str[j];
|
||||
}
|
||||
else unicode_error(question_mark8);
|
||||
string16_to_string8(Allocator *allocator, String16 in) {
|
||||
String result = {allocate_array(allocator, U8, in.len * 4 + 1)};
|
||||
for (S64 i = 0; i < in.len;) {
|
||||
UTF32_Result decode = utf16_to_utf32(in.str + i, (S32)(in.len - i));
|
||||
if (!decode.error) {
|
||||
i += decode.advance;
|
||||
UTF8_Result encode = utf32_to_utf8(decode.out_str);
|
||||
if (!encode.error) {
|
||||
for (S32 j = 0; j < encode.len; j++)
|
||||
result.str[result.len++] = encode.out_str[j];
|
||||
}
|
||||
else unicode_error(question_mark8);
|
||||
}
|
||||
else unicode_error(question_mark8);
|
||||
}
|
||||
else unicode_error(question_mark8);
|
||||
}
|
||||
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
string_compare(String16 a, String16 b){
|
||||
if(a.len != b.len) return false;
|
||||
for(S64 i = 0; i < a.len; i++){
|
||||
if(a.str[i] != b.str[i]) return false;
|
||||
}
|
||||
return true;
|
||||
string_compare(String16 a, String16 b) {
|
||||
if (a.len != b.len) return false;
|
||||
for (S64 i = 0; i < a.len; i++) {
|
||||
if (a.str[i] != b.str[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
string_compare(String32 a, String32 b){
|
||||
if(a.len != b.len) return false;
|
||||
for(S64 i = 0; i < a.len; i++){
|
||||
if(a.str[i] != b.str[i]) return false;
|
||||
}
|
||||
return true;
|
||||
string_compare(String32 a, String32 b) {
|
||||
if (a.len != b.len) return false;
|
||||
for (S64 i = 0; i < a.len; i++) {
|
||||
if (a.str[i] != b.str[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CORE_Static S64
|
||||
widechar_len(wchar_t *string){
|
||||
S64 len = 0;
|
||||
while(*string++!=0)len++;
|
||||
return len;
|
||||
widechar_len(wchar_t *string) {
|
||||
S64 len = 0;
|
||||
while (*string++ != 0) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
CORE_Static String16
|
||||
string16_from_widechar(wchar_t *string){
|
||||
String16 result;
|
||||
result.str = (U16 *)string;
|
||||
result.len = widechar_len(string);
|
||||
return result;
|
||||
string16_from_widechar(wchar_t *string) {
|
||||
String16 result;
|
||||
result.str = (U16 *)string;
|
||||
result.len = widechar_len(string);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
string16_copy(Allocator *a, String string){
|
||||
U8 *copy = allocate_array(a, U8, string.len+1);
|
||||
memory_copy(copy, string.str, string.len);
|
||||
copy[string.len] = 0;
|
||||
return String{copy, string.len};
|
||||
string16_copy(Allocator *a, String string) {
|
||||
U8 *copy = allocate_array(a, U8, string.len + 1);
|
||||
memory_copy(copy, string.str, string.len);
|
||||
copy[string.len] = 0;
|
||||
return String{copy, string.len};
|
||||
}
|
||||
|
||||
3465
c3_big_int.cpp
3465
c3_big_int.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,10 @@
|
||||
struct Token;
|
||||
|
||||
#include <inttypes.h>
|
||||
enum CmpRes
|
||||
{
|
||||
CMP_LT,
|
||||
CMP_GT,
|
||||
CMP_EQ,
|
||||
enum CmpRes {
|
||||
CMP_LT,
|
||||
CMP_GT,
|
||||
CMP_EQ,
|
||||
};
|
||||
|
||||
#define malloc_arena(x) allocate_size(bigint_allocator, x)
|
||||
|
||||
486
core_ast.cpp
486
core_ast.cpp
@@ -1,387 +1,387 @@
|
||||
|
||||
|
||||
#define AST_NEW(T,ikind,ipos,iflags) \
|
||||
Ast_##T *result = allocate_struct(pctx->perm, Ast_##T); \
|
||||
result->flags = iflags; \
|
||||
result->kind = AST_##ikind; \
|
||||
result->parent_scope = pctx->currently_parsed_scope; \
|
||||
result->pos = ipos; \
|
||||
result->di = ++pctx->unique_ids
|
||||
#define AST_NEW(T, ikind, ipos, iflags) \
|
||||
Ast_##T *result = allocate_struct(pctx->perm, Ast_##T); \
|
||||
result->flags = iflags; \
|
||||
result->kind = AST_##ikind; \
|
||||
result->parent_scope = pctx->currently_parsed_scope; \
|
||||
result->pos = ipos; \
|
||||
result->di = ++pctx->unique_ids
|
||||
|
||||
#define ast_new(T,kind,pos,flags) (T *)_ast_new(sizeof(T), kind, pos, flags)
|
||||
#define ast_new(T, kind, pos, flags) (T *)_ast_new(sizeof(T), kind, pos, flags)
|
||||
CORE_Static Ast *
|
||||
_ast_new(size_t size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){
|
||||
Ast *result = (Ast *)allocate_size(pctx->perm, size);
|
||||
result->flags = flags;
|
||||
result->kind = kind;
|
||||
result->parent_scope = pctx->currently_parsed_scope;
|
||||
result->pos = pos;
|
||||
result->di = ++pctx->unique_ids;
|
||||
return result;
|
||||
_ast_new(size_t size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0) {
|
||||
Ast *result = (Ast *)allocate_size(pctx->perm, size);
|
||||
result->flags = flags;
|
||||
result->kind = kind;
|
||||
result->parent_scope = pctx->currently_parsed_scope;
|
||||
result->pos = pos;
|
||||
result->di = ++pctx->unique_ids;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_str(Token *pos, Intern_String string){
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_string;
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
ast_str(Token *pos, Intern_String string) {
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_string;
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_ident(Token *pos, Intern_String string){
|
||||
AST_NEW(Atom, IDENT, pos, AST_EXPR | AST_ATOM);
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
ast_ident(Token *pos, Intern_String string) {
|
||||
AST_NEW(Atom, IDENT, pos, AST_EXPR | AST_ATOM);
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_bool(Token *pos, B32 bool_val){
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->bool_val = bool_val;
|
||||
result->type = pctx->untyped_bool;
|
||||
return result;
|
||||
ast_bool(Token *pos, B32 bool_val) {
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->bool_val = bool_val;
|
||||
result->type = pctx->untyped_bool;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_float(Token *pos, F64 value){
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_float;
|
||||
result->f64_val = value;
|
||||
return result;
|
||||
ast_float(Token *pos, F64 value) {
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_float;
|
||||
result->f64_val = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_int(Token *pos, BigInt val){
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_int;
|
||||
result->big_int_val = bigint_copy(pctx->perm, &val);
|
||||
return result;
|
||||
ast_int(Token *pos, BigInt val) {
|
||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||
result->type = pctx->untyped_int;
|
||||
result->big_int_val = bigint_copy(pctx->perm, &val);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Atom *
|
||||
ast_int(Token *pos, U64 value){
|
||||
return ast_int(pos, bigint_u64(value));
|
||||
ast_int(Token *pos, U64 value) {
|
||||
return ast_int(pos, bigint_u64(value));
|
||||
}
|
||||
|
||||
CORE_Static Ast_Expr *
|
||||
ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
|
||||
AST_NEW(Binary, BINARY, op, AST_EXPR);
|
||||
result->op = op->kind;
|
||||
result->left = left;
|
||||
result->right = right;
|
||||
return result;
|
||||
ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op) {
|
||||
AST_NEW(Binary, BINARY, op, AST_EXPR);
|
||||
result->op = op->kind;
|
||||
result->left = left;
|
||||
result->right = right;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Call *
|
||||
ast_call(Token *pos, Ast_Expr *name, Array<Ast_Call_Item *> exprs){
|
||||
// name here specifies also typespec for compound expressions !
|
||||
AST_NEW(Call, CALL, pos, AST_EXPR);
|
||||
result->name = name;
|
||||
result->exprs = exprs.tight_copy(pctx->perm);
|
||||
return result;
|
||||
ast_call(Token *pos, Ast_Expr *name, Array<Ast_Call_Item *> exprs) {
|
||||
// name here specifies also typespec for compound expressions !
|
||||
AST_NEW(Call, CALL, pos, AST_EXPR);
|
||||
result->name = name;
|
||||
result->exprs = exprs.tight_copy(pctx->perm);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Call_Item *
|
||||
ast_call_item(Token *pos, Ast_Atom *name, Ast_Expr *index, Ast_Expr *item){
|
||||
AST_NEW(Call_Item, CALL_ITEM, pos, AST_EXPR);
|
||||
result->name = name;
|
||||
result->item = item;
|
||||
result->index = index;
|
||||
return result;
|
||||
ast_call_item(Token *pos, Ast_Atom *name, Ast_Expr *index, Ast_Expr *item) {
|
||||
AST_NEW(Call_Item, CALL_ITEM, pos, AST_EXPR);
|
||||
result->name = name;
|
||||
result->item = item;
|
||||
result->index = index;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Expr *
|
||||
ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){
|
||||
AST_NEW(Unary, UNARY, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->expr = expr;
|
||||
result->op = op;
|
||||
return result;
|
||||
ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr) {
|
||||
AST_NEW(Unary, UNARY, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->expr = expr;
|
||||
result->op = op;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Expr *
|
||||
ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
||||
AST_NEW(Index, INDEX, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->expr = expr;
|
||||
result->index = index;
|
||||
return result;
|
||||
ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index) {
|
||||
AST_NEW(Index, INDEX, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->expr = expr;
|
||||
result->index = index;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Lambda *
|
||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, Array<Ast_Expr *> ret, Ast_Scope *scope){
|
||||
AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->args = params.tight_copy(pctx->perm);
|
||||
result->ret = ret.tight_copy(pctx->perm);
|
||||
result->scope = scope;
|
||||
return result;
|
||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, Array<Ast_Expr *> ret, Ast_Scope *scope) {
|
||||
AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->args = params.tight_copy(pctx->perm);
|
||||
result->ret = ret.tight_copy(pctx->perm);
|
||||
result->scope = scope;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_If *
|
||||
ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
||||
AST_NEW(If, IF, pos, AST_STMT);
|
||||
result->ifs = ifs.tight_copy(pctx->perm);
|
||||
return result;
|
||||
ast_if(Token *pos, Array<Ast_If_Node *> ifs) {
|
||||
AST_NEW(If, IF, pos, AST_STMT);
|
||||
result->ifs = ifs.tight_copy(pctx->perm);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_For *
|
||||
ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Scope *scope){
|
||||
AST_NEW(For, FOR, pos, AST_STMT);
|
||||
result->init = init;
|
||||
result->cond = cond;
|
||||
result->iter = iter;
|
||||
result->scope = scope;
|
||||
return result;
|
||||
ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Scope *scope) {
|
||||
AST_NEW(For, FOR, pos, AST_STMT);
|
||||
result->init = init;
|
||||
result->cond = cond;
|
||||
result->iter = iter;
|
||||
result->scope = scope;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Pass *
|
||||
ast_pass(Token *pos){
|
||||
AST_NEW(Pass, PASS, pos, AST_STMT);
|
||||
return result;
|
||||
ast_pass(Token *pos) {
|
||||
AST_NEW(Pass, PASS, pos, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Break *
|
||||
ast_break(Token *pos){
|
||||
AST_NEW(Break, BREAK, pos, AST_STMT);
|
||||
return result;
|
||||
ast_break(Token *pos) {
|
||||
AST_NEW(Break, BREAK, pos, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Return *
|
||||
ast_return(Token *pos, Array<Ast_Expr *> expr){
|
||||
AST_NEW(Return, RETURN, pos, AST_STMT);
|
||||
if(expr.len){
|
||||
For(expr) assert(is_flag_set(it->flags, AST_EXPR));
|
||||
result->expr = expr.tight_copy(pctx->perm);
|
||||
}
|
||||
return result;
|
||||
ast_return(Token *pos, Array<Ast_Expr *> expr) {
|
||||
AST_NEW(Return, RETURN, pos, AST_STMT);
|
||||
if (expr.len) {
|
||||
For(expr) assert(is_flag_set(it->flags, AST_EXPR));
|
||||
result->expr = expr.tight_copy(pctx->perm);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_If_Node *
|
||||
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope){
|
||||
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
||||
result->scope = scope;
|
||||
result->expr = expr;
|
||||
result->init = (Ast_Binary *)init;
|
||||
if(result->init) {
|
||||
assert(init->kind == AST_VAR);
|
||||
}
|
||||
return result;
|
||||
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope) {
|
||||
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
||||
result->scope = scope;
|
||||
result->expr = expr;
|
||||
result->init = (Ast_Binary *)init;
|
||||
if (result->init) {
|
||||
assert(init->kind == AST_VAR);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Array *
|
||||
ast_array(Token *pos, Ast_Expr *expr){
|
||||
AST_NEW(Array, ARRAY, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_array(Token *pos, Ast_Expr *expr) {
|
||||
AST_NEW(Array, ARRAY, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Scope *
|
||||
begin_decl_scope(Allocator *scratch, Token *pos){
|
||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||
result->file = pctx->currently_parsed_file;
|
||||
result->module = pctx->currently_parsed_file->module;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
result->debug_name = pos->string;
|
||||
assert(result->file);
|
||||
pctx->currently_parsed_scope = result;
|
||||
return result;
|
||||
begin_decl_scope(Allocator *scratch, Token *pos) {
|
||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||
result->file = pctx->currently_parsed_file;
|
||||
result->module = pctx->currently_parsed_file->module;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
result->debug_name = pos->string;
|
||||
assert(result->file);
|
||||
pctx->currently_parsed_scope = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
finalize_decl_scope(Ast_Scope *scope){
|
||||
pctx->currently_parsed_scope = scope->parent_scope;
|
||||
finalize_decl_scope(Ast_Scope *scope) {
|
||||
pctx->currently_parsed_scope = scope->parent_scope;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Scope *
|
||||
begin_stmt_scope(Allocator *scratch, Token *pos){
|
||||
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||
result->stmts = {scratch};
|
||||
result->file = pctx->currently_parsed_file;
|
||||
result->module = pctx->currently_parsed_file->module;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
result->debug_name = pos->string;
|
||||
assert(result->file);
|
||||
pctx->currently_parsed_scope = result;
|
||||
return result;
|
||||
begin_stmt_scope(Allocator *scratch, Token *pos) {
|
||||
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||
result->stmts = {scratch};
|
||||
result->file = pctx->currently_parsed_file;
|
||||
result->module = pctx->currently_parsed_file->module;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
result->debug_name = pos->string;
|
||||
assert(result->file);
|
||||
pctx->currently_parsed_scope = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
finalize_stmt_scope(Ast_Scope *scope){
|
||||
scope->stmts = scope->stmts.tight_copy(pctx->perm);
|
||||
pctx->currently_parsed_scope = scope->parent_scope;
|
||||
finalize_stmt_scope(Ast_Scope *scope) {
|
||||
scope->stmts = scope->stmts.tight_copy(pctx->perm);
|
||||
pctx->currently_parsed_scope = scope->parent_scope;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_struct(Token *pos, Ast_Scope *scope){
|
||||
AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE);
|
||||
result->scope = scope;
|
||||
return result;
|
||||
ast_struct(Token *pos, Ast_Scope *scope) {
|
||||
AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE);
|
||||
result->scope = scope;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_enum(Token *pos, Ast_Expr *typespec, Ast_Scope *scope){
|
||||
AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE);
|
||||
result->scope = scope;
|
||||
result->typespec = typespec;
|
||||
return result;
|
||||
ast_enum(Token *pos, Ast_Expr *typespec, Ast_Scope *scope) {
|
||||
AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE);
|
||||
result->scope = scope;
|
||||
result->typespec = typespec;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
|
||||
AST_NEW(Decl, VAR, pos, AST_DECL);
|
||||
result->name = name;
|
||||
result->typespec = typespec;
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr) {
|
||||
AST_NEW(Decl, VAR, pos, AST_DECL);
|
||||
result->name = name;
|
||||
result->typespec = typespec;
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_const(Token *pos, Intern_String name, Value value){
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->value = value;
|
||||
result->name = name;
|
||||
return result;
|
||||
ast_const(Token *pos, Intern_String name, Value value) {
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->value = value;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->expr = expr;
|
||||
result->name = name;
|
||||
return result;
|
||||
ast_const(Token *pos, Intern_String name, Ast_Expr *expr) {
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->expr = expr;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_type(Token *pos, Intern_String name, Ast_Type *type){
|
||||
AST_NEW(Decl, TYPE, pos, AST_DECL);
|
||||
result->type = pctx->type_type;
|
||||
result->type_val = type;
|
||||
result->name = name;
|
||||
return result;
|
||||
ast_type(Token *pos, Intern_String name, Ast_Type *type) {
|
||||
AST_NEW(Decl, TYPE, pos, AST_DECL);
|
||||
result->type = pctx->type_type;
|
||||
result->type_val = type;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Scope *
|
||||
ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){
|
||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||
result->file = file;
|
||||
ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file) {
|
||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||
result->file = file;
|
||||
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
assert(result->file);
|
||||
return result;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
assert(result->file);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Decl *
|
||||
ast_namespace(Token *pos, Ast_Scope *module, Intern_String name){
|
||||
AST_NEW(Decl, NAMESPACE, pos, AST_DECL);
|
||||
result->scope = module;
|
||||
result->name = name;
|
||||
return result;
|
||||
ast_namespace(Token *pos, Ast_Scope *module, Intern_String name) {
|
||||
AST_NEW(Decl, NAMESPACE, pos, AST_DECL);
|
||||
result->scope = module;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Builtin *
|
||||
ast_runtime_assert(Token *pos, Ast_Expr *expr, Intern_String message){
|
||||
AST_NEW(Builtin, RUNTIME_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
ast_runtime_assert(Token *pos, Ast_Expr *expr, Intern_String message) {
|
||||
AST_NEW(Builtin, RUNTIME_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Builtin *
|
||||
ast_constant_assert(Token *pos, Ast_Expr *expr, Intern_String message){
|
||||
AST_NEW(Builtin, CONSTANT_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
ast_constant_assert(Token *pos, Ast_Expr *expr, Intern_String message) {
|
||||
AST_NEW(Builtin, CONSTANT_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Builtin *
|
||||
ast_sizeof(Token *pos, Ast_Expr *expr){
|
||||
AST_NEW(Builtin, SIZE_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_sizeof(Token *pos, Ast_Expr *expr) {
|
||||
AST_NEW(Builtin, SIZE_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Builtin *
|
||||
ast_len(Token *pos, Ast_Expr *expr){
|
||||
AST_NEW(Builtin, LENGTH_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_len(Token *pos, Ast_Expr *expr) {
|
||||
AST_NEW(Builtin, LENGTH_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Builtin *
|
||||
ast_alignof(Token *pos, Ast_Expr *expr){
|
||||
AST_NEW(Builtin, ALIGN_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_alignof(Token *pos, Ast_Expr *expr) {
|
||||
AST_NEW(Builtin, ALIGN_OF, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Var_Unpack *
|
||||
ast_var_unpack(Token *pos, Array<Ast_Decl *> vars, Ast_Expr *expr){
|
||||
AST_NEW(Var_Unpack, VAR_UNPACK, pos, AST_STMT);
|
||||
result->vars = vars.tight_copy(pctx->perm);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
ast_var_unpack(Token *pos, Array<Ast_Decl *> vars, Ast_Expr *expr) {
|
||||
AST_NEW(Var_Unpack, VAR_UNPACK, pos, AST_STMT);
|
||||
result->vars = vars.tight_copy(pctx->perm);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Value
|
||||
//-----------------------------------------------------------------------------
|
||||
CORE_Static Value
|
||||
value_bool(B32 v){
|
||||
Value value;
|
||||
value.bool_val = v;
|
||||
value.type = pctx->untyped_bool;
|
||||
return value;
|
||||
value_bool(B32 v) {
|
||||
Value value;
|
||||
value.bool_val = v;
|
||||
value.type = pctx->untyped_bool;
|
||||
return value;
|
||||
}
|
||||
|
||||
CORE_Static Value
|
||||
value_int(BigInt b){
|
||||
Value value;
|
||||
value.big_int_val = b;
|
||||
value.type = pctx->untyped_int;
|
||||
return value;
|
||||
value_int(BigInt b) {
|
||||
Value value;
|
||||
value.big_int_val = b;
|
||||
value.type = pctx->untyped_int;
|
||||
return value;
|
||||
}
|
||||
|
||||
CORE_Static Value
|
||||
value_int(S64 s64){
|
||||
Value value;
|
||||
value.type = pctx->untyped_int;
|
||||
bigint_init_signed(&value.big_int_val, s64);
|
||||
return value;
|
||||
value_int(S64 s64) {
|
||||
Value value;
|
||||
value.type = pctx->untyped_int;
|
||||
bigint_init_signed(&value.big_int_val, s64);
|
||||
return value;
|
||||
}
|
||||
|
||||
CORE_Static Value
|
||||
value_float(F64 b){
|
||||
Value value;
|
||||
value.f64_val = b;
|
||||
value.type = pctx->untyped_float;
|
||||
return value;
|
||||
value_float(F64 b) {
|
||||
Value value;
|
||||
value.f64_val = b;
|
||||
value.type = pctx->untyped_float;
|
||||
return value;
|
||||
}
|
||||
|
||||
CORE_Static Value
|
||||
value_float(BigInt a){
|
||||
Value value;
|
||||
value.f64_val = bigint_as_float(&a);
|
||||
value.type = pctx->untyped_float;
|
||||
return value;
|
||||
value_float(BigInt a) {
|
||||
Value value;
|
||||
value.f64_val = bigint_as_float(&a);
|
||||
value.type = pctx->untyped_float;
|
||||
return value;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_ident(Ast *ast){
|
||||
B32 result = ast->kind == AST_IDENT;
|
||||
return result;
|
||||
is_ident(Ast *ast) {
|
||||
B32 result = ast->kind == AST_IDENT;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_binary(Ast *ast){
|
||||
B32 result = ast->kind == AST_BINARY;
|
||||
return result;
|
||||
is_binary(Ast *ast) {
|
||||
B32 result = ast->kind == AST_BINARY;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
is_atom(Ast *ast){
|
||||
B32 result = is_flag_set(ast->flags, AST_ATOM);
|
||||
return result;
|
||||
is_atom(Ast *ast) {
|
||||
B32 result = is_flag_set(ast->flags, AST_ATOM);
|
||||
return result;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,312 +1,312 @@
|
||||
|
||||
//apifn
|
||||
// apifn
|
||||
static void core_free_compiler() {
|
||||
deallocate(pctx->heap, pctx->type_map.data);
|
||||
deallocate(pctx->heap, pctx->interns.map.data);
|
||||
arena_release(pctx->stage_arena);
|
||||
arena_release(pctx->scratch);
|
||||
arena_release(pctx->perm);
|
||||
deallocate(pctx->heap, pctx->type_map.data);
|
||||
deallocate(pctx->heap, pctx->interns.map.data);
|
||||
arena_release(pctx->stage_arena);
|
||||
arena_release(pctx->scratch);
|
||||
arena_release(pctx->perm);
|
||||
}
|
||||
|
||||
//apifn
|
||||
// apifn
|
||||
static void core_init_compiler(Core_Ctx *ctx, Allocator *allocator) {
|
||||
ctx->time.init_context = os_time();
|
||||
pctx = ctx;
|
||||
ctx->time.init_context = os_time();
|
||||
pctx = ctx;
|
||||
|
||||
ctx->emit_type_info = true;
|
||||
ctx->emit_line_directives = true;
|
||||
ctx->debugger_break_on_compiler_error = true;
|
||||
ctx->color_codes_enabled = true;
|
||||
ctx->same_scope_token = { SAME_SCOPE };
|
||||
ctx->emit_type_info = true;
|
||||
ctx->emit_line_directives = true;
|
||||
ctx->debugger_break_on_compiler_error = true;
|
||||
ctx->color_codes_enabled = true;
|
||||
ctx->same_scope_token = {SAME_SCOPE};
|
||||
|
||||
arena_init(&ctx->perm_push_only, "Perm Push Only"_s);
|
||||
arena_init(&ctx->scratch_, "Scratch"_s);
|
||||
arena_init(&ctx->stage_arena_, "Stage Arena"_s);
|
||||
ctx->scratch = &ctx->scratch_;
|
||||
ctx->stage_arena = &ctx->stage_arena_;
|
||||
ctx->perm = &ctx->perm_push_only;
|
||||
ctx->heap = allocator;
|
||||
ctx->type_map = map_make(ctx->heap, 2048);
|
||||
ctx->gen = {ctx->perm};
|
||||
ctx->helper_builder = {ctx->perm};
|
||||
ctx->scope_ids = 1;
|
||||
bigint_allocator = ctx->perm;
|
||||
arena_init(&ctx->perm_push_only, "Perm Push Only"_s);
|
||||
arena_init(&ctx->scratch_, "Scratch"_s);
|
||||
arena_init(&ctx->stage_arena_, "Stage Arena"_s);
|
||||
ctx->scratch = &ctx->scratch_;
|
||||
ctx->stage_arena = &ctx->stage_arena_;
|
||||
ctx->perm = &ctx->perm_push_only;
|
||||
ctx->heap = allocator;
|
||||
ctx->type_map = map_make(ctx->heap, 2048);
|
||||
ctx->gen = {ctx->perm};
|
||||
ctx->helper_builder = {ctx->perm};
|
||||
ctx->scope_ids = 1;
|
||||
bigint_allocator = ctx->perm;
|
||||
|
||||
ctx->interns = intern_table_make(ctx->perm, ctx->heap, 2048);
|
||||
ctx->interns = intern_table_make(ctx->perm, ctx->heap, 2048);
|
||||
|
||||
/*#import meta
|
||||
for i in meta.keywords:
|
||||
print(f'pctx->keyword_{i.lower()} = pctx->intern("{i}"_s);')
|
||||
print(f'pctx->interns.first_keyword = pctx->keyword_{meta.keywords[0].lower()}.str;')
|
||||
print(f'pctx->interns.last_keyword = pctx->keyword_{meta.keywords[-1].lower()}.str;')
|
||||
/*#import meta
|
||||
for i in meta.keywords:
|
||||
print(f'pctx->keyword_{i.lower()} = pctx->intern("{i}"_s);')
|
||||
print(f'pctx->interns.first_keyword = pctx->keyword_{meta.keywords[0].lower()}.str;')
|
||||
print(f'pctx->interns.last_keyword = pctx->keyword_{meta.keywords[-1].lower()}.str;')
|
||||
|
||||
for i in meta.interns:
|
||||
print(f'pctx->intern_{i.lower()} = pctx->intern("{i}"_s);')
|
||||
for i in meta.interns:
|
||||
print(f'pctx->intern_{i.lower()} = pctx->intern("{i}"_s);')
|
||||
|
||||
index = 0
|
||||
for i in meta.token_simple_expr:
|
||||
if i[1] != "SPECIAL":
|
||||
print(f'pctx->op_info_table[{index}] = {{pctx->intern("{i[1]}"_s), "{i[0].upper()}"_s, TK_{i[0]}, {int(i[2]&meta.BINARY_EXPR>0)}, {int(i[2]&meta.UNARY_EXPR>0)}}};')
|
||||
index += 1
|
||||
index = 0
|
||||
for i in meta.token_simple_expr:
|
||||
if i[1] != "SPECIAL":
|
||||
print(f'pctx->op_info_table[{index}] = {{pctx->intern("{i[1]}"_s), "{i[0].upper()}"_s, TK_{i[0]}, {int(i[2]&meta.BINARY_EXPR>0)}, {int(i[2]&meta.UNARY_EXPR>0)}}};')
|
||||
index += 1
|
||||
|
||||
*/
|
||||
pctx->keyword_struct = pctx->intern("struct"_s);
|
||||
pctx->keyword_union = pctx->intern("union"_s);
|
||||
pctx->keyword_true = pctx->intern("true"_s);
|
||||
pctx->keyword_default = pctx->intern("default"_s);
|
||||
pctx->keyword_break = pctx->intern("break"_s);
|
||||
pctx->keyword_false = pctx->intern("false"_s);
|
||||
pctx->keyword_return = pctx->intern("return"_s);
|
||||
pctx->keyword_switch = pctx->intern("switch"_s);
|
||||
pctx->keyword_assert = pctx->intern("Assert"_s);
|
||||
pctx->keyword_if = pctx->intern("if"_s);
|
||||
pctx->keyword_elif = pctx->intern("elif"_s);
|
||||
pctx->keyword_pass = pctx->intern("pass"_s);
|
||||
pctx->keyword_else = pctx->intern("else"_s);
|
||||
pctx->keyword_for = pctx->intern("for"_s);
|
||||
pctx->keyword_enum = pctx->intern("enum"_s);
|
||||
pctx->interns.first_keyword = pctx->keyword_struct.str;
|
||||
pctx->interns.last_keyword = pctx->keyword_enum.str;
|
||||
pctx->intern_typeof = pctx->intern("TypeOf"_s);
|
||||
pctx->intern_sizeof = pctx->intern("SizeOf"_s);
|
||||
pctx->intern_len = pctx->intern("Len"_s);
|
||||
pctx->intern_alignof = pctx->intern("AlignOf"_s);
|
||||
pctx->intern_foreign = pctx->intern("foreign"_s);
|
||||
pctx->intern_strict = pctx->intern("strict"_s);
|
||||
pctx->intern_void = pctx->intern("void"_s);
|
||||
pctx->intern_flag = pctx->intern("flag"_s);
|
||||
pctx->intern_it = pctx->intern("it"_s);
|
||||
pctx->intern_load = pctx->intern("load"_s);
|
||||
pctx->intern_import = pctx->intern("import"_s);
|
||||
pctx->intern_link = pctx->intern("link"_s);
|
||||
pctx->op_info_table[0] = {pctx->intern("*"_s), "MUL"_s, TK_Mul, 1, 0};
|
||||
pctx->op_info_table[1] = {pctx->intern("/"_s), "DIV"_s, TK_Div, 1, 0};
|
||||
pctx->op_info_table[2] = {pctx->intern("%"_s), "MOD"_s, TK_Mod, 1, 0};
|
||||
pctx->op_info_table[3] = {pctx->intern("<<"_s), "LEFTSHIFT"_s, TK_LeftShift, 1, 0};
|
||||
pctx->op_info_table[4] = {pctx->intern(">>"_s), "RIGHTSHIFT"_s, TK_RightShift, 1, 0};
|
||||
pctx->op_info_table[5] = {pctx->intern("+"_s), "ADD"_s, TK_Add, 1, 1};
|
||||
pctx->op_info_table[6] = {pctx->intern("-"_s), "SUB"_s, TK_Sub, 1, 1};
|
||||
pctx->op_info_table[7] = {pctx->intern("=="_s), "EQUALS"_s, TK_Equals, 1, 0};
|
||||
pctx->op_info_table[8] = {pctx->intern("<="_s), "LESSERTHENOREQUAL"_s, TK_LesserThenOrEqual, 1, 0};
|
||||
pctx->op_info_table[9] = {pctx->intern(">="_s), "GREATERTHENOREQUAL"_s, TK_GreaterThenOrEqual, 1, 0};
|
||||
pctx->op_info_table[10] = {pctx->intern("<"_s), "LESSERTHEN"_s, TK_LesserThen, 1, 0};
|
||||
pctx->op_info_table[11] = {pctx->intern(">"_s), "GREATERTHEN"_s, TK_GreaterThen, 1, 0};
|
||||
pctx->op_info_table[12] = {pctx->intern("!="_s), "NOTEQUALS"_s, TK_NotEquals, 1, 0};
|
||||
pctx->op_info_table[13] = {pctx->intern("&"_s), "BITAND"_s, TK_BitAnd, 1, 0};
|
||||
pctx->op_info_table[14] = {pctx->intern("|"_s), "BITOR"_s, TK_BitOr, 1, 0};
|
||||
pctx->op_info_table[15] = {pctx->intern("^"_s), "BITXOR"_s, TK_BitXor, 1, 0};
|
||||
pctx->op_info_table[16] = {pctx->intern("&&"_s), "AND"_s, TK_And, 1, 0};
|
||||
pctx->op_info_table[17] = {pctx->intern("||"_s), "OR"_s, TK_Or, 1, 0};
|
||||
pctx->op_info_table[18] = {pctx->intern("~"_s), "NEG"_s, TK_Neg, 0, 1};
|
||||
pctx->op_info_table[19] = {pctx->intern("!"_s), "NOT"_s, TK_Not, 0, 1};
|
||||
/*END*/
|
||||
*/
|
||||
pctx->keyword_struct = pctx->intern("struct"_s);
|
||||
pctx->keyword_union = pctx->intern("union"_s);
|
||||
pctx->keyword_true = pctx->intern("true"_s);
|
||||
pctx->keyword_default = pctx->intern("default"_s);
|
||||
pctx->keyword_break = pctx->intern("break"_s);
|
||||
pctx->keyword_false = pctx->intern("false"_s);
|
||||
pctx->keyword_return = pctx->intern("return"_s);
|
||||
pctx->keyword_switch = pctx->intern("switch"_s);
|
||||
pctx->keyword_assert = pctx->intern("Assert"_s);
|
||||
pctx->keyword_if = pctx->intern("if"_s);
|
||||
pctx->keyword_elif = pctx->intern("elif"_s);
|
||||
pctx->keyword_pass = pctx->intern("pass"_s);
|
||||
pctx->keyword_else = pctx->intern("else"_s);
|
||||
pctx->keyword_for = pctx->intern("for"_s);
|
||||
pctx->keyword_enum = pctx->intern("enum"_s);
|
||||
pctx->interns.first_keyword = pctx->keyword_struct.str;
|
||||
pctx->interns.last_keyword = pctx->keyword_enum.str;
|
||||
pctx->intern_typeof = pctx->intern("TypeOf"_s);
|
||||
pctx->intern_sizeof = pctx->intern("SizeOf"_s);
|
||||
pctx->intern_len = pctx->intern("Len"_s);
|
||||
pctx->intern_alignof = pctx->intern("AlignOf"_s);
|
||||
pctx->intern_foreign = pctx->intern("foreign"_s);
|
||||
pctx->intern_strict = pctx->intern("strict"_s);
|
||||
pctx->intern_void = pctx->intern("void"_s);
|
||||
pctx->intern_flag = pctx->intern("flag"_s);
|
||||
pctx->intern_it = pctx->intern("it"_s);
|
||||
pctx->intern_load = pctx->intern("load"_s);
|
||||
pctx->intern_import = pctx->intern("import"_s);
|
||||
pctx->intern_link = pctx->intern("link"_s);
|
||||
pctx->op_info_table[0] = {pctx->intern("*"_s), "MUL"_s, TK_Mul, 1, 0};
|
||||
pctx->op_info_table[1] = {pctx->intern("/"_s), "DIV"_s, TK_Div, 1, 0};
|
||||
pctx->op_info_table[2] = {pctx->intern("%"_s), "MOD"_s, TK_Mod, 1, 0};
|
||||
pctx->op_info_table[3] = {pctx->intern("<<"_s), "LEFTSHIFT"_s, TK_LeftShift, 1, 0};
|
||||
pctx->op_info_table[4] = {pctx->intern(">>"_s), "RIGHTSHIFT"_s, TK_RightShift, 1, 0};
|
||||
pctx->op_info_table[5] = {pctx->intern("+"_s), "ADD"_s, TK_Add, 1, 1};
|
||||
pctx->op_info_table[6] = {pctx->intern("-"_s), "SUB"_s, TK_Sub, 1, 1};
|
||||
pctx->op_info_table[7] = {pctx->intern("=="_s), "EQUALS"_s, TK_Equals, 1, 0};
|
||||
pctx->op_info_table[8] = {pctx->intern("<="_s), "LESSERTHENOREQUAL"_s, TK_LesserThenOrEqual, 1, 0};
|
||||
pctx->op_info_table[9] = {pctx->intern(">="_s), "GREATERTHENOREQUAL"_s, TK_GreaterThenOrEqual, 1, 0};
|
||||
pctx->op_info_table[10] = {pctx->intern("<"_s), "LESSERTHEN"_s, TK_LesserThen, 1, 0};
|
||||
pctx->op_info_table[11] = {pctx->intern(">"_s), "GREATERTHEN"_s, TK_GreaterThen, 1, 0};
|
||||
pctx->op_info_table[12] = {pctx->intern("!="_s), "NOTEQUALS"_s, TK_NotEquals, 1, 0};
|
||||
pctx->op_info_table[13] = {pctx->intern("&"_s), "BITAND"_s, TK_BitAnd, 1, 0};
|
||||
pctx->op_info_table[14] = {pctx->intern("|"_s), "BITOR"_s, TK_BitOr, 1, 0};
|
||||
pctx->op_info_table[15] = {pctx->intern("^"_s), "BITXOR"_s, TK_BitXor, 1, 0};
|
||||
pctx->op_info_table[16] = {pctx->intern("&&"_s), "AND"_s, TK_And, 1, 0};
|
||||
pctx->op_info_table[17] = {pctx->intern("||"_s), "OR"_s, TK_Or, 1, 0};
|
||||
pctx->op_info_table[18] = {pctx->intern("~"_s), "NEG"_s, TK_Neg, 0, 1};
|
||||
pctx->op_info_table[19] = {pctx->intern("!"_s), "NOT"_s, TK_Not, 0, 1};
|
||||
/*END*/
|
||||
|
||||
// Init types
|
||||
pctx->type__void = {TYPE_VOID};
|
||||
// pctx->type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
|
||||
pctx->type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
|
||||
pctx->type__type = {TYPE_TYPE, sizeof(S64), __alignof(S64)};
|
||||
// Init types
|
||||
pctx->type__void = {TYPE_VOID};
|
||||
// pctx->type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
|
||||
pctx->type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
|
||||
pctx->type__type = {TYPE_TYPE, sizeof(S64), __alignof(S64)};
|
||||
|
||||
pctx->type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)};
|
||||
pctx->type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)};
|
||||
pctx->type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)};
|
||||
pctx->type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)};
|
||||
|
||||
pctx->type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)};
|
||||
pctx->type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)};
|
||||
pctx->type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)};
|
||||
pctx->type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)};
|
||||
pctx->type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)};
|
||||
pctx->type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)};
|
||||
pctx->type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)};
|
||||
pctx->type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)};
|
||||
|
||||
pctx->type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8), true};
|
||||
pctx->type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16), true};
|
||||
pctx->type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32), true};
|
||||
pctx->type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64), true};
|
||||
pctx->type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8), true};
|
||||
pctx->type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16), true};
|
||||
pctx->type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32), true};
|
||||
pctx->type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64), true};
|
||||
|
||||
pctx->type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)};
|
||||
pctx->type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)};
|
||||
pctx->type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)};
|
||||
pctx->type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)};
|
||||
pctx->type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)};
|
||||
pctx->type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)};
|
||||
pctx->type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)};
|
||||
pctx->type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)};
|
||||
|
||||
pctx->type__char = {TYPE_CHAR, sizeof(char), __alignof(char)};
|
||||
pctx->type__int = {TYPE_INT, sizeof(int), __alignof(int)};
|
||||
pctx->type__char = {TYPE_CHAR, sizeof(char), __alignof(char)};
|
||||
pctx->type__int = {TYPE_INT, sizeof(int), __alignof(int)};
|
||||
|
||||
pctx->type_char = &pctx->type__char;
|
||||
pctx->type_int = &pctx->type__int;
|
||||
pctx->type_void = &pctx->type__void;
|
||||
pctx->type_char = &pctx->type__char;
|
||||
pctx->type_int = &pctx->type__int;
|
||||
pctx->type_void = &pctx->type__void;
|
||||
|
||||
//pctx->type_any; // Needs to be inited at runtime
|
||||
// pctx->type_any; // Needs to be inited at runtime
|
||||
|
||||
pctx->type_type = &pctx->type__type;
|
||||
// pctx->type_string = &pctx->type__string;
|
||||
pctx->type_bool = &pctx->type__bool;
|
||||
pctx->type_type = &pctx->type__type;
|
||||
// pctx->type_string = &pctx->type__string;
|
||||
pctx->type_bool = &pctx->type__bool;
|
||||
|
||||
pctx->type_f32 = &pctx->type__f32;
|
||||
pctx->type_f64 = &pctx->type__f64;
|
||||
pctx->type_f32 = &pctx->type__f32;
|
||||
pctx->type_f64 = &pctx->type__f64;
|
||||
|
||||
pctx->type_s8 = &pctx->type__s8 ;
|
||||
pctx->type_s16 = &pctx->type__s16;
|
||||
pctx->type_s32 = &pctx->type__s32;
|
||||
pctx->type_s64 = &pctx->type__s64;
|
||||
pctx->type_s8 = &pctx->type__s8;
|
||||
pctx->type_s16 = &pctx->type__s16;
|
||||
pctx->type_s32 = &pctx->type__s32;
|
||||
pctx->type_s64 = &pctx->type__s64;
|
||||
|
||||
pctx->type_u8 = &pctx->type__u8 ;
|
||||
pctx->type_u16 = &pctx->type__u16;
|
||||
pctx->type_u32 = &pctx->type__u32;
|
||||
pctx->type_u64 = &pctx->type__u64;
|
||||
pctx->type_u8 = &pctx->type__u8;
|
||||
pctx->type_u16 = &pctx->type__u16;
|
||||
pctx->type_u32 = &pctx->type__u32;
|
||||
pctx->type_u64 = &pctx->type__u64;
|
||||
|
||||
pctx->untyped_string = &pctx->type__untyped_string;
|
||||
pctx->untyped_bool = &pctx->type__untyped_bool;
|
||||
pctx->untyped_int = &pctx->type__untyped_int;
|
||||
pctx->untyped_float = &pctx->type__untyped_float;
|
||||
pctx->untyped_string = &pctx->type__untyped_string;
|
||||
pctx->untyped_bool = &pctx->type__untyped_bool;
|
||||
pctx->untyped_int = &pctx->type__untyped_int;
|
||||
pctx->untyped_float = &pctx->type__untyped_float;
|
||||
|
||||
pctx->type_pointer_to_char = type_pointer(pctx->type_char);
|
||||
pctx->type_pointer_to_void = type_pointer(pctx->type_void);
|
||||
pctx->type_pointer_to_char = type_pointer(pctx->type_char);
|
||||
pctx->type_pointer_to_void = type_pointer(pctx->type_void);
|
||||
|
||||
// Init paths
|
||||
ctx->exe_folder = os_get_exe_dir(ctx->perm);
|
||||
ctx->working_folder = os_get_working_dir(ctx->perm);
|
||||
// Init paths
|
||||
ctx->exe_folder = os_get_exe_dir(ctx->perm);
|
||||
ctx->working_folder = os_get_working_dir(ctx->perm);
|
||||
|
||||
String main_module = string_fmt(ctx->perm, "%Q/modules", ctx->exe_folder);
|
||||
add(ctx->perm, &ctx->module_folders, main_module);
|
||||
ctx->time.init_context = os_time() - ctx->time.init_context;
|
||||
String main_module = string_fmt(ctx->perm, "%Q/modules", ctx->exe_folder);
|
||||
add(ctx->perm, &ctx->module_folders, main_module);
|
||||
ctx->time.init_context = os_time() - ctx->time.init_context;
|
||||
}
|
||||
|
||||
//apifn
|
||||
// apifn
|
||||
CORE_Static void
|
||||
core_bootstrap_compiler(Allocator *allocator) {
|
||||
Core_Ctx *ctx = allocate_struct(allocator, Core_Ctx);
|
||||
core_init_compiler(ctx, allocator);
|
||||
Core_Ctx *ctx = allocate_struct(allocator, Core_Ctx);
|
||||
core_init_compiler(ctx, allocator);
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
insert_builtin_type_into_scope(Ast_Scope *p, String name, Ast_Type *type) {
|
||||
Intern_String string = pctx->intern(name);
|
||||
Ast_Decl * decl = ast_type(0, string, type);
|
||||
type->type_id = pctx->type_ids++;
|
||||
decl->parent_scope = p;
|
||||
decl->state = DECL_RESOLVED;
|
||||
insert_into_scope(p, decl);
|
||||
add(pctx->perm, &pctx->all_types, type);
|
||||
Intern_String string = pctx->intern(name);
|
||||
Ast_Decl *decl = ast_type(0, string, type);
|
||||
type->type_id = pctx->type_ids++;
|
||||
decl->parent_scope = p;
|
||||
decl->state = DECL_RESOLVED;
|
||||
insert_into_scope(p, decl);
|
||||
add(pctx->perm, &pctx->all_types, type);
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
parse_all_modules() {
|
||||
pctx->time.parsing = os_time();
|
||||
pctx->time.parsing = os_time();
|
||||
|
||||
For_Named(pctx->modules, module) {
|
||||
if (module->state != MODULE_REGISTERED)
|
||||
continue;
|
||||
For_Named(pctx->modules, module) {
|
||||
if (module->state != MODULE_REGISTERED)
|
||||
continue;
|
||||
|
||||
For(module->all_loaded_files) {
|
||||
parse_file(it);
|
||||
For(module->all_loaded_files) {
|
||||
parse_file(it);
|
||||
}
|
||||
|
||||
if (module != pctx->language_base_module) {
|
||||
add(pctx->perm, &module->implicit_imports, (Ast_Scope *)pctx->language_base_module);
|
||||
}
|
||||
|
||||
module->state = MODULE_PARSED;
|
||||
}
|
||||
|
||||
if (module != pctx->language_base_module) {
|
||||
add(pctx->perm, &module->implicit_imports, (Ast_Scope *)pctx->language_base_module);
|
||||
}
|
||||
|
||||
module->state = MODULE_PARSED;
|
||||
}
|
||||
pctx->time.parsing = os_time() - pctx->time.parsing;
|
||||
pctx->time.parsing = os_time() - pctx->time.parsing;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Module *
|
||||
add_module(Token *pos, Intern_String filename, B32 command_line_module, bool string_only_module) {
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope _scope(scratch);
|
||||
String absolute_file_path = {};
|
||||
String absolute_base_folder = {};
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope _scope(scratch);
|
||||
String absolute_file_path = {};
|
||||
String absolute_base_folder = {};
|
||||
|
||||
if (string_only_module) {
|
||||
absolute_file_path = filename.s;
|
||||
absolute_base_folder = filename.s;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Find in working directory
|
||||
//
|
||||
if (command_line_module) {
|
||||
if (os_does_file_exist(filename.s)) {
|
||||
String path = os_get_absolute_path(scratch, filename.s);
|
||||
string_path_normalize(path);
|
||||
absolute_file_path = string_copy(scratch, path);
|
||||
absolute_base_folder = string_chop_last_slash(path);
|
||||
}
|
||||
if (string_only_module) {
|
||||
absolute_file_path = filename.s;
|
||||
absolute_base_folder = filename.s;
|
||||
}
|
||||
|
||||
//
|
||||
// Find in module folder
|
||||
//
|
||||
else {
|
||||
For(pctx->module_folders) {
|
||||
String path = string_fmt(scratch, "%Q/%Q", it, filename);
|
||||
if (os_does_file_exist(path)) {
|
||||
absolute_file_path = path;
|
||||
absolute_base_folder = string_chop_last_slash(path);
|
||||
break;
|
||||
//
|
||||
// Find in working directory
|
||||
//
|
||||
if (command_line_module) {
|
||||
if (os_does_file_exist(filename.s)) {
|
||||
String path = os_get_absolute_path(scratch, filename.s);
|
||||
string_path_normalize(path);
|
||||
absolute_file_path = string_copy(scratch, path);
|
||||
absolute_base_folder = string_chop_last_slash(path);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Find in module folder
|
||||
//
|
||||
else {
|
||||
For(pctx->module_folders) {
|
||||
String path = string_fmt(scratch, "%Q/%Q", it, filename);
|
||||
if (os_does_file_exist(path)) {
|
||||
absolute_file_path = path;
|
||||
absolute_base_folder = string_chop_last_slash(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (absolute_file_path.len == 0) {
|
||||
compiler_error(pos, "Couldn't find the module with name %Q", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (absolute_file_path.len == 0) {
|
||||
compiler_error(pos, "Couldn't find the module with name %Q", filename);
|
||||
For(pctx->modules) {
|
||||
if (string_compare(it->absolute_file_path, absolute_file_path)) {
|
||||
log_trace("Returning registered module: %Q\n", absolute_file_path);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
For(pctx->modules) {
|
||||
if (string_compare(it->absolute_file_path, absolute_file_path)) {
|
||||
log_trace("Returning registered module: %Q\n", absolute_file_path);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
log_trace("Adding module: %Q\n", filename);
|
||||
Ast_Module *result = ast_new(Ast_Module, AST_MODULE, pos, 0);
|
||||
result->absolute_file_path = string_copy(pctx->perm, absolute_file_path);
|
||||
result->absolute_base_folder = string_copy(pctx->perm, absolute_base_folder);
|
||||
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
||||
result->module = result; // @warning: self referential
|
||||
result->file = result; // @warning: self referential
|
||||
result->parent_scope = 0;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
|
||||
log_trace("Adding module: %Q\n", filename);
|
||||
Ast_Module *result = ast_new(Ast_Module, AST_MODULE, pos, 0);
|
||||
result->absolute_file_path = string_copy(pctx->perm, absolute_file_path);
|
||||
result->absolute_base_folder = string_copy(pctx->perm, absolute_base_folder);
|
||||
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
||||
result->module = result; // @warning: self referential
|
||||
result->file = result; // @warning: self referential
|
||||
result->parent_scope = 0;
|
||||
result->scope_id = pctx->scope_ids++;
|
||||
|
||||
register_ast_file(pos, result->absolute_file_path, result, GLOBAL_IMPLICIT_LOAD);
|
||||
add(pctx->perm, &pctx->modules, result);
|
||||
return result;
|
||||
register_ast_file(pos, result->absolute_file_path, result, GLOBAL_IMPLICIT_LOAD);
|
||||
add(pctx->perm, &pctx->modules, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_File *
|
||||
custom_parse_string(String string) {
|
||||
Ast_Module *module = pctx->custom_module;
|
||||
Ast_File *file = get(&module->all_loaded_files, 0);
|
||||
file->filecontent = string;
|
||||
parse_file(file);
|
||||
return file;
|
||||
Ast_Module *module = pctx->custom_module;
|
||||
Ast_File *file = get(&module->all_loaded_files, 0);
|
||||
file->filecontent = string;
|
||||
parse_file(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
resolve_everything_in_module(Ast_Module *module) {
|
||||
if (module->state == MODULE_RESOLVED)
|
||||
return;
|
||||
pctx->time.typechecking = os_time();
|
||||
For_Named(module->all_loaded_files, file) {
|
||||
For_Named(file->decls, decl) {
|
||||
resolve_name(file, decl->pos, decl->name);
|
||||
if (module->state == MODULE_RESOLVED)
|
||||
return;
|
||||
pctx->time.typechecking = os_time();
|
||||
For_Named(module->all_loaded_files, file) {
|
||||
For_Named(file->decls, decl) {
|
||||
resolve_name(file, decl->pos, decl->name);
|
||||
|
||||
if (decl->kind == AST_STRUCT) {
|
||||
type_complete(decl->type_val);
|
||||
}
|
||||
if (decl->kind == AST_STRUCT) {
|
||||
type_complete(decl->type_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
module->state = MODULE_RESOLVED;
|
||||
pctx->time.typechecking = os_time() - pctx->time.typechecking;
|
||||
module->state = MODULE_RESOLVED;
|
||||
pctx->time.typechecking = os_time() - pctx->time.typechecking;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
init_language_core() {
|
||||
pctx->custom_module = add_module(0, pctx->intern("Custom.core"_s), false, true);
|
||||
pctx->custom_module->state = MODULE_RESOLVED;
|
||||
pctx->custom_module = add_module(0, pctx->intern("Custom.core"_s), false, true);
|
||||
pctx->custom_module->state = MODULE_RESOLVED;
|
||||
|
||||
Ast_Module *module = add_module(0, pctx->intern("Language.core"_s), false, true);
|
||||
get(&module->all_loaded_files, 0)->filecontent =
|
||||
R"(
|
||||
Ast_Module *module = add_module(0, pctx->intern("Language.core"_s), false, true);
|
||||
get(&module->all_loaded_files, 0)->filecontent =
|
||||
R"(
|
||||
Any :: struct
|
||||
data: *void
|
||||
type: Type
|
||||
@@ -371,80 +371,80 @@ GetTypeInfo :: (type: Type): *Type_Info
|
||||
return type_infos + id
|
||||
)"_s;
|
||||
|
||||
{
|
||||
insert_builtin_type_into_scope(module, "S64"_s, pctx->type_s64);
|
||||
insert_builtin_type_into_scope(module, "S32"_s, pctx->type_s32);
|
||||
insert_builtin_type_into_scope(module, "S16"_s, pctx->type_s16);
|
||||
insert_builtin_type_into_scope(module, "S8"_s, pctx->type_s8);
|
||||
insert_builtin_type_into_scope(module, "int"_s, pctx->type_int);
|
||||
insert_builtin_type_into_scope(module, "char"_s, pctx->type_char);
|
||||
insert_builtin_type_into_scope(module, "U64"_s, pctx->type_u64);
|
||||
insert_builtin_type_into_scope(module, "U32"_s, pctx->type_u32);
|
||||
insert_builtin_type_into_scope(module, "U16"_s, pctx->type_u16);
|
||||
insert_builtin_type_into_scope(module, "U8"_s, pctx->type_u8);
|
||||
insert_builtin_type_into_scope(module, "F64"_s, pctx->type_f64);
|
||||
insert_builtin_type_into_scope(module, "F32"_s, pctx->type_f32);
|
||||
insert_builtin_type_into_scope(module, "void"_s, pctx->type_void);
|
||||
insert_builtin_type_into_scope(module, "Bool"_s, pctx->type_bool);
|
||||
// insert_builtin_type_into_scope(module, "String"_s, pctx->type_string);
|
||||
insert_builtin_type_into_scope(module, "Type"_s, pctx->type_type);
|
||||
}
|
||||
{
|
||||
insert_builtin_type_into_scope(module, "S64"_s, pctx->type_s64);
|
||||
insert_builtin_type_into_scope(module, "S32"_s, pctx->type_s32);
|
||||
insert_builtin_type_into_scope(module, "S16"_s, pctx->type_s16);
|
||||
insert_builtin_type_into_scope(module, "S8"_s, pctx->type_s8);
|
||||
insert_builtin_type_into_scope(module, "int"_s, pctx->type_int);
|
||||
insert_builtin_type_into_scope(module, "char"_s, pctx->type_char);
|
||||
insert_builtin_type_into_scope(module, "U64"_s, pctx->type_u64);
|
||||
insert_builtin_type_into_scope(module, "U32"_s, pctx->type_u32);
|
||||
insert_builtin_type_into_scope(module, "U16"_s, pctx->type_u16);
|
||||
insert_builtin_type_into_scope(module, "U8"_s, pctx->type_u8);
|
||||
insert_builtin_type_into_scope(module, "F64"_s, pctx->type_f64);
|
||||
insert_builtin_type_into_scope(module, "F32"_s, pctx->type_f32);
|
||||
insert_builtin_type_into_scope(module, "void"_s, pctx->type_void);
|
||||
insert_builtin_type_into_scope(module, "Bool"_s, pctx->type_bool);
|
||||
// insert_builtin_type_into_scope(module, "String"_s, pctx->type_string);
|
||||
insert_builtin_type_into_scope(module, "Type"_s, pctx->type_type);
|
||||
}
|
||||
|
||||
{
|
||||
Ast_Scope *scope = ast_decl_scope(&pctx->null_token, pctx->perm, get(&module->all_loaded_files, 0));
|
||||
Ast_Decl * decl = ast_namespace(&pctx->null_token, scope, pctx->intern("Const"_s));
|
||||
decl->state = DECL_RESOLVED;
|
||||
{
|
||||
Ast_Scope *scope = ast_decl_scope(&pctx->null_token, pctx->perm, get(&module->all_loaded_files, 0));
|
||||
Ast_Decl *decl = ast_namespace(&pctx->null_token, scope, pctx->intern("Const"_s));
|
||||
decl->state = DECL_RESOLVED;
|
||||
|
||||
Value v1 = {};
|
||||
v1.type = pctx->untyped_string;
|
||||
v1.intern_val = pctx->intern(OS_NAME);
|
||||
Ast_Decl *const_os1 = ast_const(&pctx->null_token, pctx->intern("OSName"_s), v1);
|
||||
const_os1->state = DECL_RESOLVED;
|
||||
insert_into_scope(scope, const_os1);
|
||||
Value v1 = {};
|
||||
v1.type = pctx->untyped_string;
|
||||
v1.intern_val = pctx->intern(OS_NAME);
|
||||
Ast_Decl *const_os1 = ast_const(&pctx->null_token, pctx->intern("OSName"_s), v1);
|
||||
const_os1->state = DECL_RESOLVED;
|
||||
insert_into_scope(scope, const_os1);
|
||||
|
||||
Value v2 = {};
|
||||
v1.type = pctx->untyped_string;
|
||||
v1.intern_val = pctx->intern(OS_NAME_LOWER);
|
||||
Ast_Decl *const_os2 = ast_const(&pctx->null_token, pctx->intern("OSNameLower"_s), v2);
|
||||
const_os2->state = DECL_RESOLVED;
|
||||
insert_into_scope(scope, const_os2);
|
||||
Value v2 = {};
|
||||
v1.type = pctx->untyped_string;
|
||||
v1.intern_val = pctx->intern(OS_NAME_LOWER);
|
||||
Ast_Decl *const_os2 = ast_const(&pctx->null_token, pctx->intern("OSNameLower"_s), v2);
|
||||
const_os2->state = DECL_RESOLVED;
|
||||
insert_into_scope(scope, const_os2);
|
||||
|
||||
insert_into_scope(module, decl);
|
||||
}
|
||||
insert_into_scope(module, decl);
|
||||
}
|
||||
|
||||
pctx->language_base_module = module;
|
||||
pctx->language_base_module = module;
|
||||
|
||||
parse_all_modules();
|
||||
resolve_everything_in_module(module);
|
||||
parse_all_modules();
|
||||
resolve_everything_in_module(module);
|
||||
|
||||
// @note: language stuff needs to be declared before type_info data
|
||||
// so we mark where it ends
|
||||
pctx->base_language_ordered_decl_len = length(&pctx->ordered_decls);
|
||||
Ast_Decl *any_decl = search_for_single_decl(module, pctx->intern("Any"_s));
|
||||
assert(any_decl->type == pctx->type_type);
|
||||
pctx->type_any = any_decl->type_val;
|
||||
// @note: language stuff needs to be declared before type_info data
|
||||
// so we mark where it ends
|
||||
pctx->base_language_ordered_decl_len = length(&pctx->ordered_decls);
|
||||
Ast_Decl *any_decl = search_for_single_decl(module, pctx->intern("Any"_s));
|
||||
assert(any_decl->type == pctx->type_type);
|
||||
pctx->type_any = any_decl->type_val;
|
||||
|
||||
Ast_Decl *string_decl = search_for_single_decl(module, pctx->intern("String"_s));
|
||||
assert(string_decl->type == pctx->type_type);
|
||||
pctx->type_string = string_decl->type_val;
|
||||
Ast_Decl *string_decl = search_for_single_decl(module, pctx->intern("String"_s));
|
||||
assert(string_decl->type == pctx->type_type);
|
||||
pctx->type_string = string_decl->type_val;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
compile_file_to_string(Allocator *allocator, String filename) {
|
||||
F64 total_time = os_time();
|
||||
core_bootstrap_compiler(allocator);
|
||||
pctx->time.total = total_time;
|
||||
pctx->time.start = total_time;
|
||||
init_language_core();
|
||||
F64 total_time = os_time();
|
||||
core_bootstrap_compiler(allocator);
|
||||
pctx->time.total = total_time;
|
||||
pctx->time.start = total_time;
|
||||
init_language_core();
|
||||
|
||||
Ast_Module *module = add_module(0, pctx->intern(filename), true);
|
||||
parse_all_modules();
|
||||
assert(module);
|
||||
Ast_Module *module = add_module(0, pctx->intern(filename), true);
|
||||
parse_all_modules();
|
||||
assert(module);
|
||||
|
||||
resolve_everything_in_module(module);
|
||||
resolve_everything_in_module(module);
|
||||
|
||||
String result = compile_to_c_code();
|
||||
String result = compile_to_c_code();
|
||||
|
||||
pctx->time.total = os_time() - pctx->time.total;
|
||||
return result;
|
||||
pctx->time.total = os_time() - pctx->time.total;
|
||||
return result;
|
||||
}
|
||||
|
||||
314
core_compiler.h
314
core_compiler.h
@@ -1,195 +1,195 @@
|
||||
|
||||
struct Lex_Stream{
|
||||
String stream;
|
||||
S64 iter;
|
||||
struct Lex_Stream {
|
||||
String stream;
|
||||
S64 iter;
|
||||
|
||||
U8 *line_begin;
|
||||
Intern_String file;
|
||||
S32 line;
|
||||
S32 inside_brace_paren;
|
||||
Array<Token *> indent_stack; // @scratch_allocated
|
||||
U8 *line_begin;
|
||||
Intern_String file;
|
||||
S32 line;
|
||||
S32 inside_brace_paren;
|
||||
Array<Token *> indent_stack; // @scratch_allocated
|
||||
};
|
||||
|
||||
struct Core_Ctx{
|
||||
Allocator *heap;
|
||||
struct Core_Ctx {
|
||||
Allocator *heap;
|
||||
|
||||
Arena perm_push_only;
|
||||
Arena *perm; // Stores: AST, tokens, interns
|
||||
Arena perm_push_only;
|
||||
Arena *perm; // Stores: AST, tokens, interns
|
||||
|
||||
Arena *scratch;
|
||||
Arena scratch_;
|
||||
Arena stage_arena_;
|
||||
Arena *stage_arena;
|
||||
String_Builder helper_builder;
|
||||
Arena *scratch;
|
||||
Arena scratch_;
|
||||
Arena stage_arena_;
|
||||
Arena *stage_arena;
|
||||
String_Builder helper_builder;
|
||||
|
||||
int errors_occured;
|
||||
int warnings_occured;
|
||||
Core_Message *first_message;
|
||||
Core_Message *last_message;
|
||||
int errors_occured;
|
||||
int warnings_occured;
|
||||
Core_Message *first_message;
|
||||
Core_Message *last_message;
|
||||
|
||||
// Lexer stuff
|
||||
Lex_Stream stream;
|
||||
Array<Token> tokens;
|
||||
Intern_Table interns;
|
||||
S64 token_iter;
|
||||
U32 token_debug_ids;
|
||||
// Lexer stuff
|
||||
Lex_Stream stream;
|
||||
Array<Token> tokens;
|
||||
Intern_Table interns;
|
||||
S64 token_iter;
|
||||
U32 token_debug_ids;
|
||||
|
||||
// Types
|
||||
List<Ast_Type *> all_types;
|
||||
S32 type_ids;
|
||||
int lambda_ids;
|
||||
U64 unique_ids; // @Debug
|
||||
Map type_map;
|
||||
// Types
|
||||
List<Ast_Type *> all_types;
|
||||
S32 type_ids;
|
||||
int lambda_ids;
|
||||
U64 unique_ids; // @Debug
|
||||
Map type_map;
|
||||
|
||||
Ast_Module *custom_module;
|
||||
Ast_Module *language_base_module;
|
||||
Ast_Module *custom_module;
|
||||
Ast_Module *language_base_module;
|
||||
|
||||
List<Ast_File *> files;
|
||||
List<Ast_Module *> modules;
|
||||
List<Ast_Decl *> ordered_decls;
|
||||
S32 base_language_ordered_decl_len;
|
||||
List<Ast_File *> files;
|
||||
List<Ast_Module *> modules;
|
||||
List<Ast_Decl *> ordered_decls;
|
||||
S32 base_language_ordered_decl_len;
|
||||
|
||||
Ast_Scope *currently_parsed_scope;
|
||||
Ast_File *currently_parsed_file;
|
||||
U32 scope_ids;
|
||||
U32 scope_visit_id;
|
||||
Ast_Scope *currently_parsed_scope;
|
||||
Ast_File *currently_parsed_file;
|
||||
U32 scope_ids;
|
||||
U32 scope_visit_id;
|
||||
|
||||
List<String> module_folders;
|
||||
String module_folder;
|
||||
String exe_folder;
|
||||
String working_folder;
|
||||
List<Token *> files_to_link;
|
||||
List<String> module_folders;
|
||||
String module_folder;
|
||||
String exe_folder;
|
||||
String working_folder;
|
||||
List<Token *> files_to_link;
|
||||
|
||||
struct {
|
||||
F64 typechecking;
|
||||
F64 code_generation;
|
||||
F64 total;
|
||||
F64 init_context;
|
||||
F64 parsing;
|
||||
struct {
|
||||
F64 typechecking;
|
||||
F64 code_generation;
|
||||
F64 total;
|
||||
F64 init_context;
|
||||
F64 parsing;
|
||||
|
||||
F64 start;
|
||||
} time;
|
||||
F64 start;
|
||||
} time;
|
||||
|
||||
bool color_codes_enabled;
|
||||
bool debugger_break_on_compiler_error;
|
||||
bool color_codes_enabled;
|
||||
bool debugger_break_on_compiler_error;
|
||||
|
||||
// Codegen stage mostly
|
||||
S64 indent;
|
||||
String_Builder gen;
|
||||
// Codegen stage mostly
|
||||
S64 indent;
|
||||
String_Builder gen;
|
||||
|
||||
// Codegen stage configurables
|
||||
bool emit_line_directives;
|
||||
bool emit_type_info;
|
||||
String symbol_prefix;
|
||||
bool single_header_library_mode;
|
||||
String single_header_library_name;
|
||||
// Codegen stage configurables
|
||||
bool emit_line_directives;
|
||||
bool emit_type_info;
|
||||
String symbol_prefix;
|
||||
bool single_header_library_mode;
|
||||
String single_header_library_name;
|
||||
|
||||
Token same_scope_token;
|
||||
Token null_token;
|
||||
Token same_scope_token;
|
||||
Token null_token;
|
||||
|
||||
/*#import meta
|
||||
for i in meta.keywords: print(f'Intern_String keyword_{i.lower()};')
|
||||
for i in meta.interns: print(f'Intern_String intern_{i.lower()};')
|
||||
*/
|
||||
Intern_String keyword_struct;
|
||||
Intern_String keyword_union;
|
||||
Intern_String keyword_true;
|
||||
Intern_String keyword_default;
|
||||
Intern_String keyword_break;
|
||||
Intern_String keyword_false;
|
||||
Intern_String keyword_return;
|
||||
Intern_String keyword_switch;
|
||||
Intern_String keyword_assert;
|
||||
Intern_String keyword_if;
|
||||
Intern_String keyword_elif;
|
||||
Intern_String keyword_pass;
|
||||
Intern_String keyword_else;
|
||||
Intern_String keyword_for;
|
||||
Intern_String keyword_enum;
|
||||
Intern_String intern_typeof;
|
||||
Intern_String intern_sizeof;
|
||||
Intern_String intern_len;
|
||||
Intern_String intern_alignof;
|
||||
Intern_String intern_foreign;
|
||||
Intern_String intern_strict;
|
||||
Intern_String intern_void;
|
||||
Intern_String intern_flag;
|
||||
Intern_String intern_it;
|
||||
Intern_String intern_load;
|
||||
Intern_String intern_import;
|
||||
Intern_String intern_link;
|
||||
/*END*/
|
||||
/*#import meta
|
||||
for i in meta.keywords: print(f'Intern_String keyword_{i.lower()};')
|
||||
for i in meta.interns: print(f'Intern_String intern_{i.lower()};')
|
||||
*/
|
||||
Intern_String keyword_struct;
|
||||
Intern_String keyword_union;
|
||||
Intern_String keyword_true;
|
||||
Intern_String keyword_default;
|
||||
Intern_String keyword_break;
|
||||
Intern_String keyword_false;
|
||||
Intern_String keyword_return;
|
||||
Intern_String keyword_switch;
|
||||
Intern_String keyword_assert;
|
||||
Intern_String keyword_if;
|
||||
Intern_String keyword_elif;
|
||||
Intern_String keyword_pass;
|
||||
Intern_String keyword_else;
|
||||
Intern_String keyword_for;
|
||||
Intern_String keyword_enum;
|
||||
Intern_String intern_typeof;
|
||||
Intern_String intern_sizeof;
|
||||
Intern_String intern_len;
|
||||
Intern_String intern_alignof;
|
||||
Intern_String intern_foreign;
|
||||
Intern_String intern_strict;
|
||||
Intern_String intern_void;
|
||||
Intern_String intern_flag;
|
||||
Intern_String intern_it;
|
||||
Intern_String intern_load;
|
||||
Intern_String intern_import;
|
||||
Intern_String intern_link;
|
||||
/*END*/
|
||||
|
||||
/*#import meta
|
||||
size = 0
|
||||
for i in meta.token_simple_expr:
|
||||
if i[1] != "SPECIAL":
|
||||
size += 1
|
||||
print(f"Ast_Operator_Info op_info_table[{size}];")
|
||||
*/
|
||||
Ast_Operator_Info op_info_table[20];
|
||||
/*END*/
|
||||
/*#import meta
|
||||
size = 0
|
||||
for i in meta.token_simple_expr:
|
||||
if i[1] != "SPECIAL":
|
||||
size += 1
|
||||
print(f"Ast_Operator_Info op_info_table[{size}];")
|
||||
*/
|
||||
Ast_Operator_Info op_info_table[20];
|
||||
/*END*/
|
||||
|
||||
Ast_Type type__void;
|
||||
Ast_Type type__string;
|
||||
Ast_Type type__bool;
|
||||
Ast_Type type__type;
|
||||
Ast_Type type__void;
|
||||
Ast_Type type__string;
|
||||
Ast_Type type__bool;
|
||||
Ast_Type type__type;
|
||||
|
||||
Ast_Type type__f32;
|
||||
Ast_Type type__f64;
|
||||
Ast_Type type__f32;
|
||||
Ast_Type type__f64;
|
||||
|
||||
Ast_Type type__s8 ;
|
||||
Ast_Type type__s16;
|
||||
Ast_Type type__s32;
|
||||
Ast_Type type__s64;
|
||||
Ast_Type type__s8;
|
||||
Ast_Type type__s16;
|
||||
Ast_Type type__s32;
|
||||
Ast_Type type__s64;
|
||||
|
||||
Ast_Type type__u8 ;
|
||||
Ast_Type type__u16;
|
||||
Ast_Type type__u32;
|
||||
Ast_Type type__u64;
|
||||
Ast_Type type__u8;
|
||||
Ast_Type type__u16;
|
||||
Ast_Type type__u32;
|
||||
Ast_Type type__u64;
|
||||
|
||||
Ast_Type type__untyped_bool;
|
||||
Ast_Type type__untyped_int;
|
||||
Ast_Type type__untyped_string;
|
||||
Ast_Type type__untyped_float;
|
||||
Ast_Type type__untyped_bool;
|
||||
Ast_Type type__untyped_int;
|
||||
Ast_Type type__untyped_string;
|
||||
Ast_Type type__untyped_float;
|
||||
|
||||
Ast_Type type__char;
|
||||
Ast_Type type__int;
|
||||
Ast_Type type__char;
|
||||
Ast_Type type__int;
|
||||
|
||||
Ast_Type *type_char = &type__char;
|
||||
Ast_Type *type_int = &type__int;
|
||||
Ast_Type *type_void = &type__void;
|
||||
Ast_Type *type_char = &type__char;
|
||||
Ast_Type *type_int = &type__int;
|
||||
Ast_Type *type_void = &type__void;
|
||||
|
||||
Ast_Type *type_pointer_to_char;
|
||||
Ast_Type *type_pointer_to_void;
|
||||
Ast_Type *type_any; // Needs to be inited at runtime
|
||||
Ast_Type *type_pointer_to_char;
|
||||
Ast_Type *type_pointer_to_void;
|
||||
Ast_Type *type_any; // Needs to be inited at runtime
|
||||
|
||||
Ast_Type *type_type = &type__type;
|
||||
Ast_Type *type_string = &type__string;
|
||||
Ast_Type *type_bool = &type__bool;
|
||||
Ast_Type *type_type = &type__type;
|
||||
Ast_Type *type_string = &type__string;
|
||||
Ast_Type *type_bool = &type__bool;
|
||||
|
||||
Ast_Type *type_f32 = &type__f32;
|
||||
Ast_Type *type_f64 = &type__f64;
|
||||
Ast_Type *type_f32 = &type__f32;
|
||||
Ast_Type *type_f64 = &type__f64;
|
||||
|
||||
Ast_Type *type_s8 = &type__s8 ;
|
||||
Ast_Type *type_s16 = &type__s16;
|
||||
Ast_Type *type_s32 = &type__s32;
|
||||
Ast_Type *type_s64 = &type__s64;
|
||||
Ast_Type *type_s8 = &type__s8;
|
||||
Ast_Type *type_s16 = &type__s16;
|
||||
Ast_Type *type_s32 = &type__s32;
|
||||
Ast_Type *type_s64 = &type__s64;
|
||||
|
||||
Ast_Type *type_u8 = &type__u8 ;
|
||||
Ast_Type *type_u16 = &type__u16;
|
||||
Ast_Type *type_u32 = &type__u32;
|
||||
Ast_Type *type_u64 = &type__u64;
|
||||
Ast_Type *type_u8 = &type__u8;
|
||||
Ast_Type *type_u16 = &type__u16;
|
||||
Ast_Type *type_u32 = &type__u32;
|
||||
Ast_Type *type_u64 = &type__u64;
|
||||
|
||||
Ast_Type *untyped_string = &type__untyped_string;
|
||||
Ast_Type *untyped_bool = &type__untyped_bool;
|
||||
Ast_Type *untyped_int = &type__untyped_int;
|
||||
Ast_Type *untyped_float = &type__untyped_float;
|
||||
Ast_Type *untyped_string = &type__untyped_string;
|
||||
Ast_Type *untyped_bool = &type__untyped_bool;
|
||||
Ast_Type *untyped_int = &type__untyped_int;
|
||||
Ast_Type *untyped_float = &type__untyped_float;
|
||||
|
||||
Intern_String intern(String string){
|
||||
assert(string.len > 0);
|
||||
return intern_string(&interns, string);
|
||||
}
|
||||
Intern_String intern(String string) {
|
||||
assert(string.len > 0);
|
||||
return intern_string(&interns, string);
|
||||
}
|
||||
};
|
||||
|
||||
CORE_Static String compile_to_c_code();
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
#include "os.h"
|
||||
#if OS_WINDOWS
|
||||
#include "os_windows.cpp"
|
||||
#include "os_windows.cpp"
|
||||
#elif OS_LINUX
|
||||
#include "os_linux.cpp"
|
||||
#include "os_linux.cpp"
|
||||
#else
|
||||
#error Couldnt figure out OS using macros
|
||||
#error Couldnt figure out OS using macros
|
||||
#endif
|
||||
|
||||
#include "core_compiler_interface.hpp"
|
||||
|
||||
@@ -26,55 +26,57 @@ print(" return 0;\n}")
|
||||
|
||||
*/
|
||||
CORE_Static Ast_Operator_Info *
|
||||
get_operator_info(Token_Kind op){
|
||||
switch(op){
|
||||
case TK_Mul: return pctx->op_info_table + 0;
|
||||
case TK_Div: return pctx->op_info_table + 1;
|
||||
case TK_Mod: return pctx->op_info_table + 2;
|
||||
case TK_LeftShift: return pctx->op_info_table + 3;
|
||||
case TK_RightShift: return pctx->op_info_table + 4;
|
||||
case TK_Add: return pctx->op_info_table + 5;
|
||||
case TK_Sub: return pctx->op_info_table + 6;
|
||||
case TK_Equals: return pctx->op_info_table + 7;
|
||||
case TK_LesserThenOrEqual: return pctx->op_info_table + 8;
|
||||
case TK_GreaterThenOrEqual: return pctx->op_info_table + 9;
|
||||
case TK_LesserThen: return pctx->op_info_table + 10;
|
||||
case TK_GreaterThen: return pctx->op_info_table + 11;
|
||||
case TK_NotEquals: return pctx->op_info_table + 12;
|
||||
case TK_BitAnd: return pctx->op_info_table + 13;
|
||||
case TK_BitOr: return pctx->op_info_table + 14;
|
||||
case TK_BitXor: return pctx->op_info_table + 15;
|
||||
case TK_And: return pctx->op_info_table + 16;
|
||||
case TK_Or: return pctx->op_info_table + 17;
|
||||
case TK_Neg: return pctx->op_info_table + 18;
|
||||
case TK_Not: return pctx->op_info_table + 19;
|
||||
default: {}
|
||||
}
|
||||
return 0;
|
||||
get_operator_info(Token_Kind op) {
|
||||
switch (op) {
|
||||
case TK_Mul: return pctx->op_info_table + 0;
|
||||
case TK_Div: return pctx->op_info_table + 1;
|
||||
case TK_Mod: return pctx->op_info_table + 2;
|
||||
case TK_LeftShift: return pctx->op_info_table + 3;
|
||||
case TK_RightShift: return pctx->op_info_table + 4;
|
||||
case TK_Add: return pctx->op_info_table + 5;
|
||||
case TK_Sub: return pctx->op_info_table + 6;
|
||||
case TK_Equals: return pctx->op_info_table + 7;
|
||||
case TK_LesserThenOrEqual: return pctx->op_info_table + 8;
|
||||
case TK_GreaterThenOrEqual: return pctx->op_info_table + 9;
|
||||
case TK_LesserThen: return pctx->op_info_table + 10;
|
||||
case TK_GreaterThen: return pctx->op_info_table + 11;
|
||||
case TK_NotEquals: return pctx->op_info_table + 12;
|
||||
case TK_BitAnd: return pctx->op_info_table + 13;
|
||||
case TK_BitOr: return pctx->op_info_table + 14;
|
||||
case TK_BitXor: return pctx->op_info_table + 15;
|
||||
case TK_And: return pctx->op_info_table + 16;
|
||||
case TK_Or: return pctx->op_info_table + 17;
|
||||
case TK_Neg: return pctx->op_info_table + 18;
|
||||
case TK_Not: return pctx->op_info_table + 19;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
CORE_Static Ast_Operator_Info *
|
||||
get_operator_info(Intern_String op){
|
||||
if(0){}
|
||||
else if(pctx->op_info_table[0].op.str == op.str) return pctx->op_info_table + 0;
|
||||
else if(pctx->op_info_table[1].op.str == op.str) return pctx->op_info_table + 1;
|
||||
else if(pctx->op_info_table[2].op.str == op.str) return pctx->op_info_table + 2;
|
||||
else if(pctx->op_info_table[3].op.str == op.str) return pctx->op_info_table + 3;
|
||||
else if(pctx->op_info_table[4].op.str == op.str) return pctx->op_info_table + 4;
|
||||
else if(pctx->op_info_table[5].op.str == op.str) return pctx->op_info_table + 5;
|
||||
else if(pctx->op_info_table[6].op.str == op.str) return pctx->op_info_table + 6;
|
||||
else if(pctx->op_info_table[7].op.str == op.str) return pctx->op_info_table + 7;
|
||||
else if(pctx->op_info_table[8].op.str == op.str) return pctx->op_info_table + 8;
|
||||
else if(pctx->op_info_table[9].op.str == op.str) return pctx->op_info_table + 9;
|
||||
else if(pctx->op_info_table[10].op.str == op.str) return pctx->op_info_table + 10;
|
||||
else if(pctx->op_info_table[11].op.str == op.str) return pctx->op_info_table + 11;
|
||||
else if(pctx->op_info_table[12].op.str == op.str) return pctx->op_info_table + 12;
|
||||
else if(pctx->op_info_table[13].op.str == op.str) return pctx->op_info_table + 13;
|
||||
else if(pctx->op_info_table[14].op.str == op.str) return pctx->op_info_table + 14;
|
||||
else if(pctx->op_info_table[15].op.str == op.str) return pctx->op_info_table + 15;
|
||||
else if(pctx->op_info_table[16].op.str == op.str) return pctx->op_info_table + 16;
|
||||
else if(pctx->op_info_table[17].op.str == op.str) return pctx->op_info_table + 17;
|
||||
else if(pctx->op_info_table[18].op.str == op.str) return pctx->op_info_table + 18;
|
||||
else if(pctx->op_info_table[19].op.str == op.str) return pctx->op_info_table + 19;
|
||||
return 0;
|
||||
get_operator_info(Intern_String op) {
|
||||
if (0) {
|
||||
}
|
||||
else if (pctx->op_info_table[0].op.str == op.str) return pctx->op_info_table + 0;
|
||||
else if (pctx->op_info_table[1].op.str == op.str) return pctx->op_info_table + 1;
|
||||
else if (pctx->op_info_table[2].op.str == op.str) return pctx->op_info_table + 2;
|
||||
else if (pctx->op_info_table[3].op.str == op.str) return pctx->op_info_table + 3;
|
||||
else if (pctx->op_info_table[4].op.str == op.str) return pctx->op_info_table + 4;
|
||||
else if (pctx->op_info_table[5].op.str == op.str) return pctx->op_info_table + 5;
|
||||
else if (pctx->op_info_table[6].op.str == op.str) return pctx->op_info_table + 6;
|
||||
else if (pctx->op_info_table[7].op.str == op.str) return pctx->op_info_table + 7;
|
||||
else if (pctx->op_info_table[8].op.str == op.str) return pctx->op_info_table + 8;
|
||||
else if (pctx->op_info_table[9].op.str == op.str) return pctx->op_info_table + 9;
|
||||
else if (pctx->op_info_table[10].op.str == op.str) return pctx->op_info_table + 10;
|
||||
else if (pctx->op_info_table[11].op.str == op.str) return pctx->op_info_table + 11;
|
||||
else if (pctx->op_info_table[12].op.str == op.str) return pctx->op_info_table + 12;
|
||||
else if (pctx->op_info_table[13].op.str == op.str) return pctx->op_info_table + 13;
|
||||
else if (pctx->op_info_table[14].op.str == op.str) return pctx->op_info_table + 14;
|
||||
else if (pctx->op_info_table[15].op.str == op.str) return pctx->op_info_table + 15;
|
||||
else if (pctx->op_info_table[16].op.str == op.str) return pctx->op_info_table + 16;
|
||||
else if (pctx->op_info_table[17].op.str == op.str) return pctx->op_info_table + 17;
|
||||
else if (pctx->op_info_table[18].op.str == op.str) return pctx->op_info_table + 18;
|
||||
else if (pctx->op_info_table[19].op.str == op.str) return pctx->op_info_table + 19;
|
||||
return 0;
|
||||
}
|
||||
/*END*/
|
||||
|
||||
@@ -3,8 +3,5 @@ thread_local Core_Ctx *pctx;
|
||||
Allocator *bigint_allocator;
|
||||
global S64 bigint_allocation_count;
|
||||
|
||||
const uintptr_t pointer_size = sizeof(uintptr_t);
|
||||
const uintptr_t pointer_size = sizeof(uintptr_t);
|
||||
const uintptr_t pointer_align = __alignof(uintptr_t);
|
||||
|
||||
|
||||
|
||||
|
||||
1324
core_lexing.cpp
1324
core_lexing.cpp
File diff suppressed because it is too large
Load Diff
209
core_main.cpp
209
core_main.cpp
@@ -93,138 +93,137 @@ Ideas
|
||||
|
||||
#include "core_compiler_includes.cpp"
|
||||
|
||||
const U32 COMPILE_NULL = 0x0;
|
||||
const U32 COMPILE_PRINT_STATS = 0x1;
|
||||
const U32 COMPILE_NULL = 0x0;
|
||||
const U32 COMPILE_PRINT_STATS = 0x1;
|
||||
const U32 COMPILE_PRINT_ALLOCATOR_STATS_BEFORE_DESTROY = 0x2;
|
||||
const U32 COMPILE_AND_RUN = 0x4;
|
||||
const U32 COMPILE_TESTING = 0x8;
|
||||
const U32 COMPILE_AND_RUN = 0x4;
|
||||
const U32 COMPILE_TESTING = 0x8;
|
||||
|
||||
static void compile_file(Allocator *allocator, String filename, U32 compile_flags = COMPILE_NULL) {
|
||||
if (is_flag_set(compile_flags, COMPILE_AND_RUN)) {
|
||||
printf("%s - ", filename.str);
|
||||
}
|
||||
String result = compile_file_to_string(allocator, filename);
|
||||
if (is_flag_set(compile_flags, COMPILE_AND_RUN)) {
|
||||
printf("%s - ", filename.str);
|
||||
}
|
||||
String result = compile_file_to_string(allocator, filename);
|
||||
|
||||
B32 r = os_write_file("program.c"_s, result);
|
||||
assert(r);
|
||||
F64 total_compiler_time = os_time() - pctx->time.start;
|
||||
printf("%f - ", total_compiler_time);
|
||||
B32 r = os_write_file("program.c"_s, result);
|
||||
assert(r);
|
||||
F64 total_compiler_time = os_time() - pctx->time.start;
|
||||
printf("%f - ", total_compiler_time);
|
||||
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope _scope(scratch);
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope _scope(scratch);
|
||||
|
||||
F64 begin = os_time();
|
||||
String_Builder builder = {scratch};
|
||||
builder.addf("clang program.c -Wall -Wno-unused-function -Wno-parentheses-equality -g -o a" OS_EXE " ");
|
||||
For(pctx->files_to_link) {
|
||||
builder.addf("-l%Q ", it->intern_val);
|
||||
}
|
||||
String compiler_call = string_flatten(scratch, &builder);
|
||||
F64 begin = os_time();
|
||||
String_Builder builder = {scratch};
|
||||
builder.addf("clang program.c -Wall -Wno-unused-function -Wno-parentheses-equality -g -o a" OS_EXE " ");
|
||||
For(pctx->files_to_link) {
|
||||
builder.addf("-l%Q ", it->intern_val);
|
||||
}
|
||||
String compiler_call = string_flatten(scratch, &builder);
|
||||
|
||||
system((const char *)compiler_call.str);
|
||||
F64 end = os_time();
|
||||
system((const char *)compiler_call.str);
|
||||
F64 end = os_time();
|
||||
|
||||
if (is_flag_set(compile_flags, COMPILE_PRINT_STATS)) {
|
||||
printf("total = %f\n", os_time() - pctx->time.start);
|
||||
printf("core_total = %f\n", pctx->time.total);
|
||||
printf("clang = %f\n", end - begin);
|
||||
printf("parsing = %f\n", pctx->time.parsing);
|
||||
printf("typecheck = %f\n", pctx->time.typechecking);
|
||||
printf("generatin = %f\n", pctx->time.code_generation);
|
||||
}
|
||||
if (is_flag_set(compile_flags, COMPILE_PRINT_STATS)) {
|
||||
printf("total = %f\n", os_time() - pctx->time.start);
|
||||
printf("core_total = %f\n", pctx->time.total);
|
||||
printf("clang = %f\n", end - begin);
|
||||
printf("parsing = %f\n", pctx->time.parsing);
|
||||
printf("typecheck = %f\n", pctx->time.typechecking);
|
||||
printf("generatin = %f\n", pctx->time.code_generation);
|
||||
}
|
||||
|
||||
if (is_flag_set(compile_flags, COMPILE_PRINT_ALLOCATOR_STATS_BEFORE_DESTROY)) {
|
||||
// @! Allocator stats
|
||||
}
|
||||
if (is_flag_set(compile_flags, COMPILE_PRINT_ALLOCATOR_STATS_BEFORE_DESTROY)) {
|
||||
// @! Allocator stats
|
||||
}
|
||||
|
||||
if (is_flag_set(compile_flags, COMPILE_AND_RUN)) {
|
||||
String testing = compile_flags & COMPILE_TESTING ? "testing"_s : ""_s;
|
||||
if (is_flag_set(compile_flags, COMPILE_AND_RUN)) {
|
||||
String testing = compile_flags & COMPILE_TESTING ? "testing"_s : ""_s;
|
||||
#if OS_WINDOWS
|
||||
String sys = string_fmt(scratch, "a.exe %Q", testing);
|
||||
String sys = string_fmt(scratch, "a.exe %Q", testing);
|
||||
#else
|
||||
String sys = string_fmt(scratch, "./a.out %Q", testing);
|
||||
String sys = string_fmt(scratch, "./a.out %Q", testing);
|
||||
#endif
|
||||
int result = system((char *)sys.str);
|
||||
assert(result != -1);
|
||||
if (result == 0) {
|
||||
printf(PRINTF_GREEN "OK!" PRINTF_RESET);
|
||||
int result = system((char *)sys.str);
|
||||
assert(result != -1);
|
||||
if (result == 0) {
|
||||
printf(PRINTF_GREEN "OK!" PRINTF_RESET);
|
||||
}
|
||||
if (result != 0) {
|
||||
printf(PRINTF_RED "ERROR!" PRINTF_RESET);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
if (result != 0) {
|
||||
printf(PRINTF_RED "ERROR!" PRINTF_RESET);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argument_count, char **arguments){
|
||||
Arena arena = {};
|
||||
Arena scratch = {};
|
||||
arena_init(&arena, "Pernament arena"_s);
|
||||
arena_init(&scratch, "Pernament scratch arena"_s);
|
||||
int main(int argument_count, char **arguments) {
|
||||
Arena arena = {};
|
||||
Arena scratch = {};
|
||||
arena_init(&arena, "Pernament arena"_s);
|
||||
arena_init(&scratch, "Pernament scratch arena"_s);
|
||||
|
||||
Array<String> args = {&scratch};
|
||||
for(int i = 1; i < argument_count; i+=1){
|
||||
String arg = string_from_cstring(arguments[i]);
|
||||
args.add(arg);
|
||||
}
|
||||
Array<String> args = {&scratch};
|
||||
for (int i = 1; i < argument_count; i += 1) {
|
||||
String arg = string_from_cstring(arguments[i]);
|
||||
args.add(arg);
|
||||
}
|
||||
|
||||
if(!args.len){
|
||||
printf("Please specify a file to compile!");
|
||||
return 0;
|
||||
}
|
||||
if (!args.len) {
|
||||
printf("Please specify a file to compile!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool enable_color_codes = false;
|
||||
bool enable_color_codes = false;
|
||||
#if OS_UNIX
|
||||
enable_color_codes = true;
|
||||
enable_color_codes = true;
|
||||
#endif
|
||||
#if OS_WINDOWS
|
||||
// Set output mode to handle virtual terminal sequences
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hOut, &dwMode)) {
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (SetConsoleMode(hOut, dwMode)) {
|
||||
enable_color_codes = true;
|
||||
}
|
||||
else{
|
||||
printf("Failed to enable colored terminal output C\n");
|
||||
}
|
||||
// Set output mode to handle virtual terminal sequences
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hOut, &dwMode)) {
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (SetConsoleMode(hOut, dwMode)) {
|
||||
enable_color_codes = true;
|
||||
}
|
||||
else {
|
||||
printf("Failed to enable colored terminal output C\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Failed to enable colored terminal output B\n");
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("Failed to enable colored terminal output B\n");
|
||||
else {
|
||||
printf("Failed to enable colored terminal output A\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Failed to enable colored terminal output A\n");
|
||||
}
|
||||
|
||||
test_os_memory();
|
||||
test_os_memory();
|
||||
#endif
|
||||
|
||||
(void)enable_color_codes;
|
||||
For(args){
|
||||
(void)enable_color_codes;
|
||||
For(args) {
|
||||
|
||||
if(it == "-testing"_s){
|
||||
Scratch_Scope _scope(&scratch);
|
||||
Array<OS_File_Info> examples = os_list_dir(&scratch, &scratch, "examples"_s);
|
||||
Array<OS_File_Info> tests = os_list_dir(&scratch, &scratch, "tests"_s);
|
||||
For(examples){
|
||||
if(it.is_directory) continue;
|
||||
compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
||||
}
|
||||
For(tests){
|
||||
if(it.is_directory) continue;
|
||||
compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
||||
}
|
||||
if (it == "-testing"_s) {
|
||||
Scratch_Scope _scope(&scratch);
|
||||
Array<OS_File_Info> examples = os_list_dir(&scratch, &scratch, "examples"_s);
|
||||
Array<OS_File_Info> tests = os_list_dir(&scratch, &scratch, "tests"_s);
|
||||
For(examples) {
|
||||
if (it.is_directory) continue;
|
||||
compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
||||
}
|
||||
For(tests) {
|
||||
if (it.is_directory) continue;
|
||||
compile_file(&arena, it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
String program_name = string_from_cstring(arguments[1]);
|
||||
compile_file(&arena, program_name, COMPILE_PRINT_STATS);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
String program_name = string_from_cstring(arguments[1]);
|
||||
compile_file(&arena, program_name, COMPILE_PRINT_STATS);
|
||||
}
|
||||
|
||||
}
|
||||
printf("End of program\n");
|
||||
return 0;
|
||||
printf("End of program\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
1619
core_parsing.cpp
1619
core_parsing.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,64 +1,68 @@
|
||||
|
||||
|
||||
struct Operand{
|
||||
/*#import meta
|
||||
meta.inline_value_fields()
|
||||
*/
|
||||
union {
|
||||
Value value;
|
||||
struct {
|
||||
Ast_Type *type;
|
||||
Ast_Decl *resolved_decl;
|
||||
union {
|
||||
bool bool_val;
|
||||
double f64_val;
|
||||
Intern_String intern_val;
|
||||
BigInt big_int_val;
|
||||
Ast_Type *type_val;
|
||||
};
|
||||
struct Operand {
|
||||
/*#import meta
|
||||
meta.inline_value_fields()
|
||||
*/
|
||||
union {
|
||||
Value value;
|
||||
struct {
|
||||
Ast_Type *type;
|
||||
Ast_Decl *resolved_decl;
|
||||
union {
|
||||
bool bool_val;
|
||||
double f64_val;
|
||||
Intern_String intern_val;
|
||||
BigInt big_int_val;
|
||||
Ast_Type *type_val;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/*END*/
|
||||
// is_const is used to rewrite the tree and bound
|
||||
// something to the const name at the end
|
||||
U8 is_const : 1;
|
||||
U8 is_lvalue : 1;
|
||||
U8 pound_strict: 1;
|
||||
/*END*/
|
||||
// is_const is used to rewrite the tree and bound
|
||||
// something to the const name at the end
|
||||
U8 is_const : 1;
|
||||
U8 is_lvalue : 1;
|
||||
U8 pound_strict : 1;
|
||||
};
|
||||
|
||||
struct Scope_Search {
|
||||
Array<Ast_Decl *> results;
|
||||
Intern_String name;
|
||||
Array<Ast_Scope *> scopes;
|
||||
Array<Ast_Decl *> results;
|
||||
Intern_String name;
|
||||
Array<Ast_Scope *> scopes;
|
||||
|
||||
bool exit_on_find;
|
||||
bool search_only_current_scope;
|
||||
U32 scope_visit_id;
|
||||
bool exit_on_find;
|
||||
bool search_only_current_scope;
|
||||
U32 scope_visit_id;
|
||||
};
|
||||
|
||||
typedef U32 Typecheck_Flag;
|
||||
enum {
|
||||
TYPE_AND_EXPR_REQUIRED = 0,
|
||||
TYPE_CAN_BE_NULL = 1,
|
||||
EXPR_CAN_BE_NULL = 2
|
||||
TYPE_AND_EXPR_REQUIRED = 0,
|
||||
TYPE_CAN_BE_NULL = 1,
|
||||
EXPR_CAN_BE_NULL = 2
|
||||
};
|
||||
|
||||
typedef U32 Resolve_Flag;
|
||||
enum{
|
||||
AST_CANT_BE_NULL = bit_flag(0),
|
||||
AST_CAN_BE_NULL = bit_flag(1),
|
||||
RESOLVE_TYPESPEC_COMPLETE = bit_flag(2),
|
||||
RESOLVE_TYPESPEC = bit_flag(3),
|
||||
enum {
|
||||
AST_CANT_BE_NULL = bit_flag(0),
|
||||
AST_CAN_BE_NULL = bit_flag(1),
|
||||
RESOLVE_TYPESPEC_COMPLETE = bit_flag(2),
|
||||
RESOLVE_TYPESPEC = bit_flag(3),
|
||||
};
|
||||
|
||||
typedef U32 Search_Flag;
|
||||
enum{
|
||||
SEARCH_ONLY_CURRENT_SCOPE = bit_flag(1),
|
||||
RESOLVE_NAME_MAKE_SURE_OPERATOR_OVERLOAD_IS_NOT_EVER_CALLED = bit_flag(2),
|
||||
enum {
|
||||
SEARCH_ONLY_CURRENT_SCOPE = bit_flag(1),
|
||||
RESOLVE_NAME_MAKE_SURE_OPERATOR_OVERLOAD_IS_NOT_EVER_CALLED = bit_flag(2),
|
||||
};
|
||||
|
||||
CORE_Static Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_Scope *field_access_scope);
|
||||
CORE_Static void resolve_decl(Ast_Decl *ast);
|
||||
CORE_Static Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
|
||||
#define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
|
||||
#define BREAK() } break
|
||||
#define CASE(kind, type) \
|
||||
case AST_##kind: { \
|
||||
Ast_##type *node = (Ast_##type *)ast;
|
||||
#define BREAK() \
|
||||
} \
|
||||
break
|
||||
|
||||
544
core_types.cpp
544
core_types.cpp
@@ -1,331 +1,335 @@
|
||||
|
||||
CORE_Static const char *
|
||||
get_name_of_type(Ast_Type *type){
|
||||
switch(type->kind){
|
||||
case TYPE_VOID: return "void";
|
||||
case TYPE_BOOL: return "Bool";
|
||||
case TYPE_CHAR: return "char";
|
||||
case TYPE_F32: return "F32";
|
||||
case TYPE_F64: return "F64";
|
||||
case TYPE_S8: return "S8";
|
||||
case TYPE_INT: return "int";
|
||||
case TYPE_S16: return "S16";
|
||||
case TYPE_S32: return "S32";
|
||||
case TYPE_S64: return "S64";
|
||||
case TYPE_U8: return "U8";
|
||||
case TYPE_U16: return "U16";
|
||||
case TYPE_U32: return "U32";
|
||||
case TYPE_U64: return "U64";
|
||||
case TYPE_TUPLE: return "Tuple";
|
||||
case TYPE_TYPE: return "Type";
|
||||
invalid_default_case;
|
||||
}
|
||||
return "<unknown_type>";
|
||||
get_name_of_type(Ast_Type *type) {
|
||||
switch (type->kind) {
|
||||
case TYPE_VOID: return "void";
|
||||
case TYPE_BOOL: return "Bool";
|
||||
case TYPE_CHAR: return "char";
|
||||
case TYPE_F32: return "F32";
|
||||
case TYPE_F64: return "F64";
|
||||
case TYPE_S8: return "S8";
|
||||
case TYPE_INT: return "int";
|
||||
case TYPE_S16: return "S16";
|
||||
case TYPE_S32: return "S32";
|
||||
case TYPE_S64: return "S64";
|
||||
case TYPE_U8: return "U8";
|
||||
case TYPE_U16: return "U16";
|
||||
case TYPE_U32: return "U32";
|
||||
case TYPE_U64: return "U64";
|
||||
case TYPE_TUPLE: return "Tuple";
|
||||
case TYPE_TYPE:
|
||||
return "Type";
|
||||
invalid_default_case;
|
||||
}
|
||||
return "<unknown_type>";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type constructors and utillities
|
||||
//-----------------------------------------------------------------------------
|
||||
force_inline B32 is_any(Ast_Type *a){return a == pctx->type_any;}
|
||||
force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;}
|
||||
force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;}
|
||||
force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;}
|
||||
force_inline B32 is_slice(Ast_Type *a){return a->kind == TYPE_SLICE;}
|
||||
force_inline B32 is_tuple(Ast_Type *a){return a->kind == TYPE_TUPLE;}
|
||||
force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;}
|
||||
force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;}
|
||||
force_inline B32 is_void(Ast_Type *a){return a->kind == TYPE_VOID;}
|
||||
force_inline B32 is_void_pointer(Ast_Type *a){return a == pctx->type_pointer_to_void;}
|
||||
force_inline B32 is_string(Ast_Type *a){return a == pctx->type_string || a->kind == TYPE_UNTYPED_STRING || a == pctx->type_pointer_to_char;}
|
||||
force_inline B32 is_untyped_int(Ast_Type *a){return a->kind == TYPE_UNTYPED_INT;}
|
||||
force_inline B32 is_typed_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8);}
|
||||
force_inline B32 is_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;}
|
||||
force_inline B32 is_signed_int(Ast_Type *a){return !a->is_unsigned;}
|
||||
force_inline B32 is_unsigned_int(Ast_Type *a){return a->is_unsigned;}
|
||||
force_inline B32 is_float(Ast_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;}
|
||||
force_inline B32 is_f32(Ast_Type *a){return a->kind == TYPE_F32;}
|
||||
force_inline B32 is_f64(Ast_Type *a){return a->kind == TYPE_F64;}
|
||||
force_inline B32 is_bool(Ast_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;}
|
||||
force_inline B32 is_untyped(Ast_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;}
|
||||
force_inline B32 is_typed(Ast_Type *a){return !is_untyped(a);}
|
||||
force_inline B32 is_numeric(Ast_Type *type){
|
||||
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
|
||||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
|
||||
force_inline B32 is_any(Ast_Type *a) { return a == pctx->type_any; }
|
||||
force_inline B32 is_struct(Ast_Type *a) { return a->kind == TYPE_STRUCT; }
|
||||
force_inline B32 is_lambda(Ast_Type *a) { return a->kind == TYPE_LAMBDA; }
|
||||
force_inline B32 is_array(Ast_Type *a) { return a->kind == TYPE_ARRAY; }
|
||||
force_inline B32 is_slice(Ast_Type *a) { return a->kind == TYPE_SLICE; }
|
||||
force_inline B32 is_tuple(Ast_Type *a) { return a->kind == TYPE_TUPLE; }
|
||||
force_inline B32 is_enum(Ast_Type *a) { return a->kind == TYPE_ENUM; }
|
||||
force_inline B32 is_pointer(Ast_Type *a) { return a->kind == TYPE_POINTER; }
|
||||
force_inline B32 is_void(Ast_Type *a) { return a->kind == TYPE_VOID; }
|
||||
force_inline B32 is_void_pointer(Ast_Type *a) { return a == pctx->type_pointer_to_void; }
|
||||
force_inline B32 is_string(Ast_Type *a) { return a == pctx->type_string || a->kind == TYPE_UNTYPED_STRING || a == pctx->type_pointer_to_char; }
|
||||
force_inline B32 is_untyped_int(Ast_Type *a) { return a->kind == TYPE_UNTYPED_INT; }
|
||||
force_inline B32 is_typed_int(Ast_Type *a) { return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8); }
|
||||
force_inline B32 is_int(Ast_Type *a) { return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT; }
|
||||
force_inline B32 is_signed_int(Ast_Type *a) { return !a->is_unsigned; }
|
||||
force_inline B32 is_unsigned_int(Ast_Type *a) { return a->is_unsigned; }
|
||||
force_inline B32 is_float(Ast_Type *a) { return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT; }
|
||||
force_inline B32 is_f32(Ast_Type *a) { return a->kind == TYPE_F32; }
|
||||
force_inline B32 is_f64(Ast_Type *a) { return a->kind == TYPE_F64; }
|
||||
force_inline B32 is_bool(Ast_Type *a) { return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL; }
|
||||
force_inline B32 is_untyped(Ast_Type *a) { return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST; }
|
||||
force_inline B32 is_typed(Ast_Type *a) { return !is_untyped(a); }
|
||||
force_inline B32 is_numeric(Ast_Type *type) {
|
||||
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
|
||||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hash consed types
|
||||
//-----------------------------------------------------------------------------
|
||||
CORE_Static Ast_Type *
|
||||
type_new(Allocator *allocator, Ast_Type_Kind kind, size_t size, size_t align){
|
||||
Ast_Type *result = allocate_struct(allocator, Ast_Type, true);
|
||||
result->kind = kind;
|
||||
result->size = size;
|
||||
result->align = align;
|
||||
result->type_id = pctx->type_ids++;
|
||||
add(pctx->perm, &pctx->all_types, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_copy(Allocator *a, Ast_Type *type){
|
||||
// @warning: This changes type id !!!!
|
||||
Ast_Type *result = allocate_struct(a, Ast_Type);
|
||||
memory_copy(result, type, sizeof(Ast_Type));
|
||||
result->type_id = pctx->type_ids++;
|
||||
add(pctx->perm, &pctx->all_types, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_pointer(Ast_Type *base){
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, (void *)base);
|
||||
if(!result){
|
||||
result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align);
|
||||
result->base = base;
|
||||
result->is_unsigned = true;
|
||||
map_insert(&pctx->type_map, base, result);
|
||||
}
|
||||
assert(result->kind == TYPE_POINTER);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_slice(Ast_Type *base, Ast *ast){
|
||||
U64 hash_base = hash_ptr(base);
|
||||
U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
if(result){
|
||||
assert(result->kind == TYPE_SLICE);
|
||||
assert(result->arr.base == base);
|
||||
type_new(Allocator *allocator, Ast_Type_Kind kind, size_t size, size_t align) {
|
||||
Ast_Type *result = allocate_struct(allocator, Ast_Type, true);
|
||||
result->kind = kind;
|
||||
result->size = size;
|
||||
result->align = align;
|
||||
result->type_id = pctx->type_ids++;
|
||||
add(pctx->perm, &pctx->all_types, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct Slice{void *p; S64 len;};
|
||||
result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice));
|
||||
result->arr.base = base;
|
||||
result->arr.slice_hash = hash;
|
||||
result->ast = ast;
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_try_tupling(Array<Ast_Type *> types, Ast *ast){
|
||||
if(types.len == 0) return pctx->type_void;
|
||||
if(types.len == 1) return types[0];
|
||||
type_copy(Allocator *a, Ast_Type *type) {
|
||||
// @warning: This changes type id !!!!
|
||||
Ast_Type *result = allocate_struct(a, Ast_Type);
|
||||
memory_copy(result, type, sizeof(Ast_Type));
|
||||
result->type_id = pctx->type_ids++;
|
||||
add(pctx->perm, &pctx->all_types, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
U64 hash = 13;
|
||||
For(types) hash = hash_mix(hash, hash_ptr(it));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
if(result){
|
||||
assert(result->kind == TYPE_TUPLE);
|
||||
assert(result->agg.members.len == types.len);
|
||||
CORE_Static Ast_Type *
|
||||
type_pointer(Ast_Type *base) {
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, (void *)base);
|
||||
if (!result) {
|
||||
result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align);
|
||||
result->base = base;
|
||||
result->is_unsigned = true;
|
||||
map_insert(&pctx->type_map, base, result);
|
||||
}
|
||||
assert(result->kind == TYPE_POINTER);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_slice(Ast_Type *base, Ast *ast) {
|
||||
U64 hash_base = hash_ptr(base);
|
||||
U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
if (result) {
|
||||
assert(result->kind == TYPE_SLICE);
|
||||
assert(result->arr.base == base);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct Slice {
|
||||
void *p;
|
||||
S64 len;
|
||||
};
|
||||
result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice));
|
||||
result->arr.base = base;
|
||||
result->arr.slice_hash = hash;
|
||||
result->ast = ast;
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_try_tupling(Array<Ast_Type *> types, Ast *ast) {
|
||||
if (types.len == 0) return pctx->type_void;
|
||||
if (types.len == 1) return types[0];
|
||||
|
||||
U64 hash = 13;
|
||||
For(types) hash = hash_mix(hash, hash_ptr(it));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
if (result) {
|
||||
assert(result->kind == TYPE_TUPLE);
|
||||
assert(result->agg.members.len == types.len);
|
||||
assert(result->agg.members.len > 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
// @todo alignment, offsets
|
||||
result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align);
|
||||
result->agg.members = array_make<Ast_Resolved_Member>(pctx->perm, types.len);
|
||||
For(types) {
|
||||
Ast_Resolved_Member m = {};
|
||||
m.type = it;
|
||||
m.offset = 0; // @todo
|
||||
result->size += it->size;
|
||||
result->agg.members.add(m);
|
||||
}
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
assert(result->agg.members.len > 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// @todo alignment, offsets
|
||||
result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align);
|
||||
result->agg.members = array_make<Ast_Resolved_Member>(pctx->perm, types.len);
|
||||
For(types){
|
||||
Ast_Resolved_Member m = {};
|
||||
m.type = it;
|
||||
m.offset = 0; // @todo
|
||||
result->size += it->size;
|
||||
result->agg.members.add(m);
|
||||
}
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
assert(result->agg.members.len > 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_array(Ast_Type *base, S64 size){
|
||||
U64 hash_base = hash_ptr(base);
|
||||
U64 hash = hash_mix(hash_base, hash_u64(size));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
if(result){
|
||||
assert(result->kind == TYPE_ARRAY);
|
||||
assert(result->arr.size == size);
|
||||
assert(result->arr.base == base);
|
||||
return result;
|
||||
}
|
||||
type_array(Ast_Type *base, S64 size) {
|
||||
U64 hash_base = hash_ptr(base);
|
||||
U64 hash = hash_mix(hash_base, hash_u64(size));
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->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(pctx->perm, TYPE_ARRAY, size*base->size, pointer_align);
|
||||
result->arr.base = base;
|
||||
result->arr.size = size;
|
||||
result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
return result;
|
||||
result = type_new(pctx->perm, TYPE_ARRAY, size * base->size, pointer_align);
|
||||
result->arr.base = base;
|
||||
result->arr.size = size;
|
||||
result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline U64
|
||||
calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b){
|
||||
U64 result = 13;
|
||||
result = hash_mix(result, hash_ptr(a));
|
||||
result = hash_mix(result, hash_ptr(b));
|
||||
return result;
|
||||
calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b) {
|
||||
U64 result = 13;
|
||||
result = hash_mix(result, hash_ptr(a));
|
||||
result = hash_mix(result, hash_ptr(b));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline U64
|
||||
calculate_hash_for_arguments(Ast_Type *a){
|
||||
U64 result = 13;
|
||||
result = hash_mix(result, hash_ptr(a));
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){
|
||||
Ast_Type *ret = type_try_tupling(return_vals, ast);
|
||||
U64 hash_without_ret = 13;
|
||||
For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
|
||||
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
|
||||
if(result){
|
||||
assert(result->kind == TYPE_LAMBDA);
|
||||
assert(result->func.args.len == args.len);
|
||||
calculate_hash_for_arguments(Ast_Type *a) {
|
||||
U64 result = 13;
|
||||
result = hash_mix(result, hash_ptr(a));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align);
|
||||
result->ast = ast;
|
||||
result->func.ret = ret;
|
||||
result->func.args = args.tight_copy(pctx->perm);
|
||||
result->func.hash_without_ret = hash_without_ret;
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_enum(Ast_Decl *ast, Ast_Type *type){
|
||||
if(!type){
|
||||
type = pctx->type_s64;
|
||||
}
|
||||
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args) {
|
||||
Ast_Type *ret = type_try_tupling(return_vals, ast);
|
||||
U64 hash_without_ret = 13;
|
||||
For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
|
||||
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
|
||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||
|
||||
Ast_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align);
|
||||
result->base = type;
|
||||
result->ast = ast;
|
||||
return result;
|
||||
if (result) {
|
||||
assert(result->kind == TYPE_LAMBDA);
|
||||
assert(result->func.args.len == args.len);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align);
|
||||
result->ast = ast;
|
||||
result->func.ret = ret;
|
||||
result->func.args = args.tight_copy(pctx->perm);
|
||||
result->func.hash_without_ret = hash_without_ret;
|
||||
map_insert(&pctx->type_map, hash, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_incomplete(Ast *ast){
|
||||
Ast_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
|
||||
result->ast = ast;
|
||||
return result;
|
||||
type_enum(Ast_Decl *ast, Ast_Type *type) {
|
||||
if (!type) {
|
||||
type = pctx->type_s64;
|
||||
}
|
||||
|
||||
Ast_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align);
|
||||
result->base = type;
|
||||
result->ast = ast;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Ast_Type *
|
||||
type_incomplete(Ast *ast) {
|
||||
Ast_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
|
||||
result->ast = ast;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void type_complete(Ast_Type *type);
|
||||
CORE_Static void
|
||||
type_struct_complete(Ast_Type *type, Ast_Decl *node){
|
||||
assert(node->kind == AST_STRUCT);
|
||||
// @todo: compute size, alignement, offset !!!
|
||||
// @note: resolve all the struct members first
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope __scope(scratch);
|
||||
type_struct_complete(Ast_Type *type, Ast_Decl *node) {
|
||||
assert(node->kind == AST_STRUCT);
|
||||
// @todo: compute size, alignement, offset !!!
|
||||
// @note: resolve all the struct members first
|
||||
Arena *scratch = pctx->scratch;
|
||||
Scratch_Scope __scope(scratch);
|
||||
|
||||
Array<Ast_Resolved_Member> members = {scratch};
|
||||
type->kind = TYPE_COMPLETING;
|
||||
size_t members_size = 0;
|
||||
For_Named(node->scope->decls, decl){
|
||||
resolve_decl(decl);
|
||||
assert(decl->type->kind != TYPE_INCOMPLETE);
|
||||
assert(is_pow2(decl->type->align));
|
||||
Array<Ast_Resolved_Member> members = {scratch};
|
||||
type->kind = TYPE_COMPLETING;
|
||||
size_t members_size = 0;
|
||||
For_Named(node->scope->decls, decl) {
|
||||
resolve_decl(decl);
|
||||
assert(decl->type->kind != TYPE_INCOMPLETE);
|
||||
assert(is_pow2(decl->type->align));
|
||||
|
||||
Ast_Resolved_Member m = {};
|
||||
m.offset = type->size;
|
||||
members_size += decl->type->size;
|
||||
type->align = max(type->align, decl->type->align);
|
||||
type->size = decl->type->size + align_up(type->size, decl->type->align);
|
||||
Ast_Resolved_Member m = {};
|
||||
m.offset = type->size;
|
||||
members_size += decl->type->size;
|
||||
type->align = max(type->align, decl->type->align);
|
||||
type->size = decl->type->size + align_up(type->size, decl->type->align);
|
||||
|
||||
m.name = decl->name;
|
||||
m.value = decl->value;
|
||||
members.add(m);
|
||||
}
|
||||
type->size = align_up(type->size, type->align);
|
||||
type->padding = type->size - members_size;
|
||||
type->agg.members = members.tight_copy(pctx->perm);
|
||||
type->kind = TYPE_STRUCT;
|
||||
node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", pctx->symbol_prefix, node->name));
|
||||
m.name = decl->name;
|
||||
m.value = decl->value;
|
||||
members.add(m);
|
||||
}
|
||||
type->size = align_up(type->size, type->align);
|
||||
type->padding = type->size - members_size;
|
||||
type->agg.members = members.tight_copy(pctx->perm);
|
||||
type->kind = TYPE_STRUCT;
|
||||
node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", pctx->symbol_prefix, node->name));
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
type_complete(Ast_Type *type){
|
||||
if(!type) {
|
||||
return;
|
||||
}
|
||||
if(type->kind == TYPE_COMPLETING){
|
||||
compiler_error(type->ast->pos, "Cyclic type dependency");
|
||||
}
|
||||
else if(type->kind != TYPE_INCOMPLETE){
|
||||
return;
|
||||
}
|
||||
type_complete(Ast_Type *type) {
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
if (type->kind == TYPE_COMPLETING) {
|
||||
compiler_error(type->ast->pos, "Cyclic type dependency");
|
||||
}
|
||||
else if (type->kind != TYPE_INCOMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
type_struct_complete(type, (Ast_Decl *)type->ast);
|
||||
add(pctx->perm, &pctx->ordered_decls, (Ast_Decl *)type->ast);
|
||||
type_struct_complete(type, (Ast_Decl *)type->ast);
|
||||
add(pctx->perm, &pctx->ordered_decls, (Ast_Decl *)type->ast);
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
typename_base(String_Builder *sb, Ast_Type *type){
|
||||
switch(type->kind){
|
||||
case TYPE_INCOMPLETE: sb->addf("INCOMPLETE"); break;
|
||||
case TYPE_COMPLETING: sb->addf("COMPLETING"); break;
|
||||
case TYPE_TYPE: sb->addf("TYPE"); break;
|
||||
case TYPE_POINTER:
|
||||
sb->addf("*");
|
||||
typename_base(sb, type->base);
|
||||
break;
|
||||
case TYPE_LAMBDA:
|
||||
sb->addf("(");
|
||||
For(type->func.args) {
|
||||
typename_base(sb, it);
|
||||
if(!type->func.args.is_last(&it)) sb->addf(", ");
|
||||
}
|
||||
typename_base(String_Builder *sb, Ast_Type *type) {
|
||||
switch (type->kind) {
|
||||
case TYPE_INCOMPLETE: sb->addf("INCOMPLETE"); break;
|
||||
case TYPE_COMPLETING: sb->addf("COMPLETING"); break;
|
||||
case TYPE_TYPE: sb->addf("TYPE"); break;
|
||||
case TYPE_POINTER:
|
||||
sb->addf("*");
|
||||
typename_base(sb, type->base);
|
||||
break;
|
||||
case TYPE_LAMBDA:
|
||||
sb->addf("(");
|
||||
For(type->func.args) {
|
||||
typename_base(sb, it);
|
||||
if (!type->func.args.is_last(&it)) sb->addf(", ");
|
||||
}
|
||||
|
||||
sb->addf("):");
|
||||
typename_base(sb, type->func.ret);
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
sb->addf("[%d]", (int)type->arr.size);
|
||||
typename_base(sb, type->arr.base);
|
||||
break;
|
||||
case TYPE_SLICE:
|
||||
sb->addf("[]");
|
||||
typename_base(sb, type->base);
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_ENUM:{
|
||||
// @todo direct access
|
||||
auto constant = (Ast_Decl *)type->ast;
|
||||
auto name = constant->name;
|
||||
sb->addf("%Q", name);
|
||||
break;
|
||||
sb->addf("):");
|
||||
typename_base(sb, type->func.ret);
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
sb->addf("[%d]", (int)type->arr.size);
|
||||
typename_base(sb, type->arr.base);
|
||||
break;
|
||||
case TYPE_SLICE:
|
||||
sb->addf("[]");
|
||||
typename_base(sb, type->base);
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_ENUM: {
|
||||
// @todo direct access
|
||||
auto constant = (Ast_Decl *)type->ast;
|
||||
auto name = constant->name;
|
||||
sb->addf("%Q", name);
|
||||
break;
|
||||
}
|
||||
case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break;
|
||||
case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break;
|
||||
case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break;
|
||||
case TYPE_UNTYPED_STRING: sb->addf("Untyped_String"); break;
|
||||
default: {
|
||||
sb->addf("%s", get_name_of_type(type));
|
||||
}
|
||||
}
|
||||
case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break;
|
||||
case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break;
|
||||
case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break;
|
||||
case TYPE_UNTYPED_STRING: sb->addf("Untyped_String"); break;
|
||||
default: {
|
||||
sb->addf("%s", get_name_of_type(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
get_typename(Allocator *a, Ast_Type *type){
|
||||
pctx->helper_builder.addf("[");
|
||||
typename_base(&pctx->helper_builder, type);
|
||||
pctx->helper_builder.addf("]");
|
||||
String result = string_flatten(a, &pctx->helper_builder);
|
||||
pctx->helper_builder.reset();
|
||||
return result;
|
||||
get_typename(Allocator *a, Ast_Type *type) {
|
||||
pctx->helper_builder.addf("[");
|
||||
typename_base(&pctx->helper_builder, type);
|
||||
pctx->helper_builder.addf("]");
|
||||
String result = string_flatten(a, &pctx->helper_builder);
|
||||
pctx->helper_builder.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
typestring(Ast_Type *type){
|
||||
return get_typename(pctx->stage_arena, type);
|
||||
typestring(Ast_Type *type) {
|
||||
return get_typename(pctx->stage_arena, type);
|
||||
}
|
||||
|
||||
40
core_types.h
40
core_types.h
@@ -2,12 +2,36 @@
|
||||
// Resolved Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#define CASE_SINT case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64: case TYPE_CHAR: case TYPE_INT
|
||||
#define CASE_UINT case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64
|
||||
#define CASE_INT case TYPE_UNTYPED_INT: CASE_SINT: CASE_UINT
|
||||
#define CASE_BOOL case TYPE_UNTYPED_BOOL: case TYPE_BOOL
|
||||
#define CASE_FLOAT case TYPE_UNTYPED_FLOAT: case TYPE_F32: case TYPE_F64
|
||||
#define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRUCT: case TYPE_POINTER
|
||||
#define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING
|
||||
#define CASE_SINT \
|
||||
case TYPE_S8: \
|
||||
case TYPE_S16: \
|
||||
case TYPE_S32: \
|
||||
case TYPE_S64: \
|
||||
case TYPE_CHAR: \
|
||||
case TYPE_INT
|
||||
#define CASE_UINT \
|
||||
case TYPE_U8: \
|
||||
case TYPE_U16: \
|
||||
case TYPE_U32: \
|
||||
case TYPE_U64
|
||||
#define CASE_INT \
|
||||
case TYPE_UNTYPED_INT: \
|
||||
CASE_SINT: \
|
||||
CASE_UINT
|
||||
#define CASE_BOOL \
|
||||
case TYPE_UNTYPED_BOOL: \
|
||||
case TYPE_BOOL
|
||||
#define CASE_FLOAT \
|
||||
case TYPE_UNTYPED_FLOAT: \
|
||||
case TYPE_F32: \
|
||||
case TYPE_F64
|
||||
#define CASE_STRING \
|
||||
case TYPE_UNTYPED_STRING: \
|
||||
case TYPE_STRUCT: \
|
||||
case TYPE_POINTER
|
||||
#define CASE_UNTYPED \
|
||||
case TYPE_UNTYPED_INT: \
|
||||
case TYPE_UNTYPED_BOOL: \
|
||||
case TYPE_UNTYPED_FLOAT: \
|
||||
case TYPE_UNTYPED_STRING
|
||||
#define ARRAY_SIZE_SLICE (-1)
|
||||
|
||||
12
os.h
12
os.h
@@ -1,9 +1,9 @@
|
||||
|
||||
const U32 LIST_NO_FLAGS = 0;
|
||||
const U32 LIST_RECURSE_INTO_DIRS = 1;
|
||||
const U32 LIST_NO_FLAGS = 0;
|
||||
const U32 LIST_RECURSE_INTO_DIRS = 1;
|
||||
|
||||
struct OS_File_Info{
|
||||
String relative_path;
|
||||
String absolute_path;
|
||||
B32 is_directory;
|
||||
struct OS_File_Info {
|
||||
String relative_path;
|
||||
String absolute_path;
|
||||
B32 is_directory;
|
||||
};
|
||||
|
||||
260
os_linux.cpp
260
os_linux.cpp
@@ -11,184 +11,184 @@
|
||||
#define POSIX_PAGE_SIZE 4096
|
||||
|
||||
CORE_Static B32
|
||||
os_write_file(String filename, String filecontent){
|
||||
FILE *f = fopen((const char *)filename.str, "w");
|
||||
if(f){
|
||||
fwrite(filecontent.str, 1, filecontent.len, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
os_write_file(String filename, String filecontent) {
|
||||
FILE *f = fopen((const char *)filename.str, "w");
|
||||
if (f) {
|
||||
fwrite(filecontent.str, 1, filecontent.len, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_read_file(Alloator *a, String name){
|
||||
String result = {0};
|
||||
FILE *f = fopen((char *)name.str, "rb");
|
||||
if(f){
|
||||
fseek(f, 0, SEEK_END);
|
||||
result.len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
result.str = (U8 *)allocate_size(a, result.len + 1, false);
|
||||
fread(result.str, result.len, 1, f);
|
||||
fclose(f);
|
||||
result.str[result.len] = 0;
|
||||
}
|
||||
os_read_file(Alloator *a, String name) {
|
||||
String result = {0};
|
||||
FILE *f = fopen((char *)name.str, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
result.len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
result.str = (U8 *)allocate_size(a, result.len + 1, false);
|
||||
fread(result.str, result.len, 1, f);
|
||||
fclose(f);
|
||||
result.str[result.len] = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_exe_dir(Allocator *a){
|
||||
char buffer[PATH_MAX] = {};
|
||||
if (readlink("/proc/self/exe", buffer, PATH_MAX) == -1) {
|
||||
log_info("Failed to retrieve the path of the executable, the method used is fetching /proc/self/exe, very likely you are using an OS that doesn't follow this convention and as such it is currently not supported");
|
||||
}
|
||||
String exe = string_from_cstring(buffer);
|
||||
exe = string_chop_last_slash(exe);
|
||||
String result = string_copy(a, exe);
|
||||
os_get_exe_dir(Allocator *a) {
|
||||
char buffer[PATH_MAX] = {};
|
||||
if (readlink("/proc/self/exe", buffer, PATH_MAX) == -1) {
|
||||
log_info("Failed to retrieve the path of the executable, the method used is fetching /proc/self/exe, very likely you are using an OS that doesn't follow this convention and as such it is currently not supported");
|
||||
}
|
||||
String exe = string_from_cstring(buffer);
|
||||
exe = string_chop_last_slash(exe);
|
||||
String result = string_copy(a, exe);
|
||||
|
||||
log_trace("Retrieved executable path %Q", result);
|
||||
return result;
|
||||
log_trace("Retrieved executable path %Q", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_absolute_path(Allocator *a, String path){
|
||||
assert(path.str[path.len] == 0);
|
||||
char buffer[PATH_MAX] = {};
|
||||
realpath((char *)path.str, buffer);
|
||||
String abs = string_from_cstring(buffer);
|
||||
String result = string_copy(a, abs);
|
||||
return result;
|
||||
os_get_absolute_path(Allocator *a, String path) {
|
||||
assert(path.str[path.len] == 0);
|
||||
char buffer[PATH_MAX] = {};
|
||||
realpath((char *)path.str, buffer);
|
||||
String abs = string_from_cstring(buffer);
|
||||
String result = string_copy(a, abs);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
os_does_file_exist(String path){
|
||||
B32 result = false;
|
||||
assert(path.str[path.len] == 0);
|
||||
if (access((char *)path.str, F_OK) == 0) {
|
||||
result = true;
|
||||
}
|
||||
log_trace("Does file exist? %Q %d", path, result);
|
||||
return result;
|
||||
os_does_file_exist(String path) {
|
||||
B32 result = false;
|
||||
assert(path.str[path.len] == 0);
|
||||
if (access((char *)path.str, F_OK) == 0) {
|
||||
result = true;
|
||||
}
|
||||
log_trace("Does file exist? %Q %d", path, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_working_dir(Allocator *allocator){
|
||||
char *buffer = allocate_array(allocator, char, PATH_MAX, false);
|
||||
char *result = getcwd(buffer, PATH_MAX);
|
||||
return string_from_cstring(result);
|
||||
os_get_working_dir(Allocator *allocator) {
|
||||
char *buffer = allocate_array(allocator, char, PATH_MAX, false);
|
||||
char *result = getcwd(buffer, PATH_MAX);
|
||||
return string_from_cstring(result);
|
||||
}
|
||||
|
||||
CORE_Static Array<OS_File_Info>
|
||||
os_list_dir(Scratch_Arena *scratch, Allocator *a, String dir, U32 flags = LIST_RECURSE_INTO_DIRS){
|
||||
Scratch_Scope _scope(scratch);
|
||||
Array<String> dirs_to_read = {scratch};
|
||||
dirs_to_read.add(dir);
|
||||
os_list_dir(Scratch_Arena *scratch, Allocator *a, String dir, U32 flags = LIST_RECURSE_INTO_DIRS) {
|
||||
Scratch_Scope _scope(scratch);
|
||||
Array<String> dirs_to_read = {scratch};
|
||||
dirs_to_read.add(dir);
|
||||
|
||||
Array<OS_File_Info> result = {a};
|
||||
for(auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++){
|
||||
assert(it->str[it->len] == 0);
|
||||
dirent *dir;
|
||||
DIR *d = opendir((char *)it->str);
|
||||
if(d){
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
if(dir->d_name[0] == '.'){
|
||||
if(dir->d_name[1] == '.'){
|
||||
if(dir->d_name[2] == 0)
|
||||
continue;
|
||||
}
|
||||
Array<OS_File_Info> result = {a};
|
||||
for (auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++) {
|
||||
assert(it->str[it->len] == 0);
|
||||
dirent *dir;
|
||||
DIR *d = opendir((char *)it->str);
|
||||
if (d) {
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
if (dir->d_name[0] == '.') {
|
||||
if (dir->d_name[1] == '.') {
|
||||
if (dir->d_name[2] == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(dir->d_name[1] == 0)
|
||||
continue;
|
||||
if (dir->d_name[1] == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
OS_File_Info entry = {};
|
||||
entry.relative_path = string_fmt(a, "%Q/%s", *it, dir->d_name);
|
||||
entry.absolute_path = os_get_absolute_path(a, entry.relative_path);
|
||||
|
||||
if (dir->d_type == DT_DIR) {
|
||||
entry.is_directory = true;
|
||||
|
||||
if (flags & LIST_RECURSE_INTO_DIRS) {
|
||||
dirs_to_read.add(entry.absolute_path);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(entry);
|
||||
log_trace("%Q %d", entry.absolute_path, entry.is_directory);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
OS_File_Info entry = {};
|
||||
entry.relative_path = string_fmt(a, "%Q/%s", *it, dir->d_name);
|
||||
entry.absolute_path = os_get_absolute_path(a, entry.relative_path);
|
||||
|
||||
if(dir->d_type == DT_DIR){
|
||||
entry.is_directory = true;
|
||||
|
||||
if(flags & LIST_RECURSE_INTO_DIRS){
|
||||
dirs_to_read.add(entry.absolute_path);
|
||||
}
|
||||
else {
|
||||
log_info("ERROR Failed to read dir: %Q, errno: %s", *it, strerror(errno));
|
||||
}
|
||||
|
||||
result.add(entry);
|
||||
log_trace("%Q %d", entry.absolute_path, entry.is_directory);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
else{
|
||||
log_info("ERROR Failed to read dir: %Q, errno: %s", *it, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static U8 *
|
||||
os_advance_commit(OS_Memory *m, size_t *commit_size, size_t page_size) {
|
||||
size_t aligned_up_commit = align_up(*commit_size, page_size);
|
||||
size_t to_be_total_commited_size = aligned_up_commit + m->commit;
|
||||
size_t to_be_total_commited_size_clamped_to_reserve = clamp_top(to_be_total_commited_size, m->reserve);
|
||||
size_t adjusted_to_boundary_commit = to_be_total_commited_size_clamped_to_reserve - m->commit;
|
||||
assert_message(adjusted_to_boundary_commit, "Debug WIN32 Error: Reached the virtual memory reserved boundary");
|
||||
U8 *result = m->data + m->commit;
|
||||
if (adjusted_to_boundary_commit == 0)
|
||||
result = 0;
|
||||
*commit_size = adjusted_to_boundary_commit;
|
||||
return result;
|
||||
size_t aligned_up_commit = align_up(*commit_size, page_size);
|
||||
size_t to_be_total_commited_size = aligned_up_commit + m->commit;
|
||||
size_t to_be_total_commited_size_clamped_to_reserve = clamp_top(to_be_total_commited_size, m->reserve);
|
||||
size_t adjusted_to_boundary_commit = to_be_total_commited_size_clamped_to_reserve - m->commit;
|
||||
assert_message(adjusted_to_boundary_commit, "Debug WIN32 Error: Reached the virtual memory reserved boundary");
|
||||
U8 *result = m->data + m->commit;
|
||||
if (adjusted_to_boundary_commit == 0)
|
||||
result = 0;
|
||||
*commit_size = adjusted_to_boundary_commit;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static OS_Memory
|
||||
os_reserve(size_t size) {
|
||||
OS_Memory result = {};
|
||||
size_t size_aligned = align_up(size, POSIX_PAGE_SIZE);
|
||||
result.data = (U8 *)mmap(0, size_aligned, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
assert_message(result.data, POSIX_ERROR "Failed to reserve memory using mmap!!");
|
||||
if (result.data) {
|
||||
result.reserve = size_aligned;
|
||||
}
|
||||
return result;
|
||||
OS_Memory result = {};
|
||||
size_t size_aligned = align_up(size, POSIX_PAGE_SIZE);
|
||||
result.data = (U8 *)mmap(0, size_aligned, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
assert_message(result.data, POSIX_ERROR "Failed to reserve memory using mmap!!");
|
||||
if (result.data) {
|
||||
result.reserve = size_aligned;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
os_commit(OS_Memory *m, size_t commit) {
|
||||
B32 result = false;
|
||||
U8 * pointer = os_advance_commit(m, &commit, POSIX_PAGE_SIZE);
|
||||
if (pointer) {
|
||||
int mprotect_result = mprotect(pointer, commit, PROT_READ | PROT_WRITE);
|
||||
assert_message(mprotect_result == 0, "OS1 POSIX Debug Error: Failed to commit more memory using mmap");
|
||||
if (mprotect_result == 0) {
|
||||
m->commit += commit;
|
||||
result = true;
|
||||
B32 result = false;
|
||||
U8 *pointer = os_advance_commit(m, &commit, POSIX_PAGE_SIZE);
|
||||
if (pointer) {
|
||||
int mprotect_result = mprotect(pointer, commit, PROT_READ | PROT_WRITE);
|
||||
assert_message(mprotect_result == 0, "OS1 POSIX Debug Error: Failed to commit more memory using mmap");
|
||||
if (mprotect_result == 0) {
|
||||
m->commit += commit;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
os_release(OS_Memory *m) {
|
||||
int result = munmap(m->data, m->reserve);
|
||||
assert_message(result == 0, "OS1 POSIX Debug Error: Failed to release virtual memory using munmap");
|
||||
if (result == 0) {
|
||||
memory_zero(m, sizeof(*m));
|
||||
}
|
||||
int result = munmap(m->data, m->reserve);
|
||||
assert_message(result == 0, "OS1 POSIX Debug Error: Failed to release virtual memory using munmap");
|
||||
if (result == 0) {
|
||||
memory_zero(m, sizeof(*m));
|
||||
}
|
||||
}
|
||||
|
||||
CORE_Static U64
|
||||
os_get_microseconds() {
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
U64 result = (((U64)ts.tv_sec) * 1000000ull) + ((U64)ts.tv_nsec) / 1000ull;
|
||||
return result;
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
U64 result = (((U64)ts.tv_sec) * 1000000ull) + ((U64)ts.tv_nsec) / 1000ull;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static F64
|
||||
os_time(){
|
||||
F64 time = (F64)os_get_microseconds();
|
||||
F64 result = time / 1000000.0; // Microseconds to seconds
|
||||
return result;
|
||||
os_time() {
|
||||
F64 time = (F64)os_get_microseconds();
|
||||
F64 result = time / 1000000.0; // Microseconds to seconds
|
||||
return result;
|
||||
}
|
||||
|
||||
363
os_windows.cpp
363
os_windows.cpp
@@ -6,82 +6,82 @@
|
||||
const size_t os_page_size = 4096;
|
||||
|
||||
CORE_Static OS_Memory
|
||||
os_reserve(size_t size){
|
||||
OS_Memory result = {};
|
||||
size_t adjusted_size = align_up(size, os_page_size);
|
||||
result.data = (U8*)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE);
|
||||
assert_message(result.data, "Failed to reserve virtual memory");
|
||||
result.reserve = adjusted_size;
|
||||
return result;
|
||||
os_reserve(size_t size) {
|
||||
OS_Memory result = {};
|
||||
size_t adjusted_size = align_up(size, os_page_size);
|
||||
result.data = (U8 *)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE);
|
||||
assert_message(result.data, "Failed to reserve virtual memory");
|
||||
result.reserve = adjusted_size;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
os_commit(OS_Memory *m, size_t size){
|
||||
size_t commit = align_up(size, os_page_size);
|
||||
size_t total_commit = m->commit + commit;
|
||||
total_commit = clamp_top(total_commit, m->reserve);
|
||||
size_t adjusted_commit = total_commit - m->commit;
|
||||
if(adjusted_commit != 0){
|
||||
void *result = VirtualAlloc((U8*)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE);
|
||||
assert_message(result, "Failed to commit more memory");
|
||||
m->commit += adjusted_commit;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
os_release(OS_Memory *m){
|
||||
BOOL result = VirtualFree(m->data, 0, MEM_RELEASE);
|
||||
assert_message(result != 0, "Failed to release OS_Memory");
|
||||
if(result){
|
||||
m->data = 0;
|
||||
m->commit = 0;
|
||||
m->reserve = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
os_decommit_pos(OS_Memory *m, size_t pos){
|
||||
size_t aligned = align_down(pos, os_page_size);
|
||||
size_t adjusted_pos = clamp_top(aligned, m->commit);
|
||||
size_t size_to_decommit = m->commit - adjusted_pos;
|
||||
if(size_to_decommit){
|
||||
U8 *base_address = m->data + adjusted_pos;
|
||||
BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT);
|
||||
if(result){
|
||||
m->commit -= size_to_decommit;
|
||||
return true;
|
||||
os_commit(OS_Memory *m, size_t size) {
|
||||
size_t commit = align_up(size, os_page_size);
|
||||
size_t total_commit = m->commit + commit;
|
||||
total_commit = clamp_top(total_commit, m->reserve);
|
||||
size_t adjusted_commit = total_commit - m->commit;
|
||||
if (adjusted_commit != 0) {
|
||||
void *result = VirtualAlloc((U8 *)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE);
|
||||
assert_message(result, "Failed to commit more memory");
|
||||
m->commit += adjusted_commit;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
CORE_Static void
|
||||
test_os_memory(){
|
||||
assert(align_down(4096, 4096) == 4096);
|
||||
assert(align_down(4095, 4096) == 0);
|
||||
os_release(OS_Memory *m) {
|
||||
BOOL result = VirtualFree(m->data, 0, MEM_RELEASE);
|
||||
assert_message(result != 0, "Failed to release OS_Memory");
|
||||
if (result) {
|
||||
m->data = 0;
|
||||
m->commit = 0;
|
||||
m->reserve = 0;
|
||||
}
|
||||
}
|
||||
|
||||
OS_Memory memory = os_reserve(9000);
|
||||
assert(memory.reserve == 4096*3 && memory.data && memory.commit == 0);
|
||||
os_commit(&memory, 100);
|
||||
assert(memory.commit == 4096);
|
||||
os_commit(&memory, 100);
|
||||
assert(memory.commit == 4096*2);
|
||||
os_commit(&memory, 9000);
|
||||
assert(memory.commit == 4096*3);
|
||||
os_commit(&memory, 9000);
|
||||
assert(memory.commit == 4096*3);
|
||||
CORE_Static B32
|
||||
os_decommit_pos(OS_Memory *m, size_t pos) {
|
||||
size_t aligned = align_down(pos, os_page_size);
|
||||
size_t adjusted_pos = clamp_top(aligned, m->commit);
|
||||
size_t size_to_decommit = m->commit - adjusted_pos;
|
||||
if (size_to_decommit) {
|
||||
U8 *base_address = m->data + adjusted_pos;
|
||||
BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT);
|
||||
if (result) {
|
||||
m->commit -= size_to_decommit;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
os_decommit_pos(&memory, 4096);
|
||||
assert(memory.commit == 4096);
|
||||
os_decommit_pos(&memory, 4096);
|
||||
assert(memory.commit == 4096);
|
||||
os_decommit_pos(&memory, 0);
|
||||
assert(memory.commit == 0);
|
||||
CORE_Static void
|
||||
test_os_memory() {
|
||||
assert(align_down(4096, 4096) == 4096);
|
||||
assert(align_down(4095, 4096) == 0);
|
||||
|
||||
os_release(&memory);
|
||||
assert(memory.data == 0);
|
||||
OS_Memory memory = os_reserve(9000);
|
||||
assert(memory.reserve == 4096 * 3 && memory.data && memory.commit == 0);
|
||||
os_commit(&memory, 100);
|
||||
assert(memory.commit == 4096);
|
||||
os_commit(&memory, 100);
|
||||
assert(memory.commit == 4096 * 2);
|
||||
os_commit(&memory, 9000);
|
||||
assert(memory.commit == 4096 * 3);
|
||||
os_commit(&memory, 9000);
|
||||
assert(memory.commit == 4096 * 3);
|
||||
|
||||
os_decommit_pos(&memory, 4096);
|
||||
assert(memory.commit == 4096);
|
||||
os_decommit_pos(&memory, 4096);
|
||||
assert(memory.commit == 4096);
|
||||
os_decommit_pos(&memory, 0);
|
||||
assert(memory.commit == 0);
|
||||
|
||||
os_release(&memory);
|
||||
assert(memory.data == 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -89,156 +89,155 @@ test_os_memory(){
|
||||
//-----------------------------------------------------------------------------
|
||||
global S64 Global_counts_per_second;
|
||||
api F64 os_time() {
|
||||
if (Global_counts_per_second == 0) {
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
Global_counts_per_second = freq.QuadPart;
|
||||
}
|
||||
if (Global_counts_per_second == 0) {
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
Global_counts_per_second = freq.QuadPart;
|
||||
}
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
F64 result = (F64)time.QuadPart / (F64)Global_counts_per_second;
|
||||
return result;
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
F64 result = (F64)time.QuadPart / (F64)Global_counts_per_second;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Filesystem
|
||||
//-----------------------------------------------------------------------------
|
||||
CORE_Static B32
|
||||
os_write_file(String filename, String filecontent){
|
||||
FILE *f = fopen((const char *)filename.str, "w");
|
||||
if(f){
|
||||
fwrite(filecontent.str, 1, filecontent.len, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
os_write_file(String filename, String filecontent) {
|
||||
FILE *f = fopen((const char *)filename.str, "w");
|
||||
if (f) {
|
||||
fwrite(filecontent.str, 1, filecontent.len, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_read_file(Allocator *a, String name){
|
||||
String result = {0};
|
||||
FILE *f = fopen((char *)name.str, "rb");
|
||||
if(f){
|
||||
fseek(f, 0, SEEK_END);
|
||||
result.len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
result.str = (U8 *)allocate_size(a, result.len + 1, false);
|
||||
fread(result.str, result.len, 1, f);
|
||||
fclose(f);
|
||||
result.str[result.len] = 0;
|
||||
}
|
||||
os_read_file(Allocator *a, String name) {
|
||||
String result = {0};
|
||||
FILE *f = fopen((char *)name.str, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
result.len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
result.str = (U8 *)allocate_size(a, result.len + 1, false);
|
||||
fread(result.str, result.len, 1, f);
|
||||
fclose(f);
|
||||
result.str[result.len] = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_working_dir(Allocator *a){
|
||||
wchar_t buffer[2048];
|
||||
DWORD written = GetCurrentDirectoryW(2048, buffer);
|
||||
assert(written != 0);
|
||||
String16 string16 = string16_from_widechar(buffer);
|
||||
String result = string16_to_string8(a, string16);
|
||||
string_path_normalize(result);
|
||||
return result;
|
||||
os_get_working_dir(Allocator *a) {
|
||||
wchar_t buffer[2048];
|
||||
DWORD written = GetCurrentDirectoryW(2048, buffer);
|
||||
assert(written != 0);
|
||||
String16 string16 = string16_from_widechar(buffer);
|
||||
String result = string16_to_string8(a, string16);
|
||||
string_path_normalize(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_exe_dir(Allocator *a){
|
||||
wchar_t buffer[2048];
|
||||
DWORD written = GetModuleFileNameW(0, buffer, 2048);
|
||||
assert(written != 0);
|
||||
String16 string16 = string16_from_widechar(buffer);
|
||||
String result = string16_to_string8(a, string16);
|
||||
string_path_normalize(result);
|
||||
result = string_chop_last_slash(result);
|
||||
os_get_exe_dir(Allocator *a) {
|
||||
wchar_t buffer[2048];
|
||||
DWORD written = GetModuleFileNameW(0, buffer, 2048);
|
||||
assert(written != 0);
|
||||
String16 string16 = string16_from_widechar(buffer);
|
||||
String result = string16_to_string8(a, string16);
|
||||
string_path_normalize(result);
|
||||
result = string_chop_last_slash(result);
|
||||
|
||||
if(string16.len > result.len) result.str[result.len] = 0;
|
||||
string_path_normalize(result);
|
||||
return result;
|
||||
if (string16.len > result.len) result.str[result.len] = 0;
|
||||
string_path_normalize(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static String
|
||||
os_get_absolute_path(Allocator *a, String path){
|
||||
char buff[2048];
|
||||
Arena scratch = arena_from_buffer(buff, 2048);
|
||||
String16 path16 = string8_to_string16(&scratch, path);
|
||||
os_get_absolute_path(Allocator *a, String path) {
|
||||
char buff[2048];
|
||||
Arena scratch = arena_from_buffer(buff, 2048);
|
||||
String16 path16 = string8_to_string16(&scratch, path);
|
||||
|
||||
wchar_t *buffer = allocate_array(&scratch, wchar_t, 512);
|
||||
DWORD written = GetFullPathNameW((wchar_t *)path16.str, 512, buffer, 0);
|
||||
if(written == 0) return {};
|
||||
wchar_t *buffer = allocate_array(&scratch, wchar_t, 512);
|
||||
DWORD written = GetFullPathNameW((wchar_t *)path16.str, 512, buffer, 0);
|
||||
if (written == 0) return {};
|
||||
|
||||
String16 absolute16 = string16_from_widechar(buffer);
|
||||
String absolute = string16_to_string8(a, absolute16);
|
||||
string_path_normalize(absolute);
|
||||
return absolute;
|
||||
String16 absolute16 = string16_from_widechar(buffer);
|
||||
String absolute = string16_to_string8(a, absolute16);
|
||||
string_path_normalize(absolute);
|
||||
return absolute;
|
||||
}
|
||||
|
||||
CORE_Static B32
|
||||
os_does_file_exist(String path){
|
||||
char buff[2048];
|
||||
Arena scratch = arena_from_buffer(buff, buff_cap(buff));
|
||||
String16 path16 = string8_to_string16(&scratch, path);
|
||||
DWORD attribs = GetFileAttributesW((wchar_t *)path16.str);
|
||||
B32 result = attribs == INVALID_FILE_ATTRIBUTES ? false : true;
|
||||
return result;
|
||||
os_does_file_exist(String path) {
|
||||
char buff[2048];
|
||||
Arena scratch = arena_from_buffer(buff, buff_cap(buff));
|
||||
String16 path16 = string8_to_string16(&scratch, path);
|
||||
DWORD attribs = GetFileAttributesW((wchar_t *)path16.str);
|
||||
B32 result = attribs == INVALID_FILE_ATTRIBUTES ? false : true;
|
||||
return result;
|
||||
}
|
||||
|
||||
CORE_Static Array<OS_File_Info>
|
||||
os_list_dir(Arena *scratch, Allocator *a, String dir, U32 flags = LIST_NO_FLAGS){
|
||||
Scratch_Scope _scope(scratch);
|
||||
Array<String> dirs_to_read = {scratch};
|
||||
dirs_to_read.add(dir);
|
||||
os_list_dir(Arena *scratch, Allocator *a, String dir, U32 flags = LIST_NO_FLAGS) {
|
||||
Scratch_Scope _scope(scratch);
|
||||
Array<String> dirs_to_read = {scratch};
|
||||
dirs_to_read.add(dir);
|
||||
|
||||
Array<OS_File_Info> result = {a};
|
||||
for(auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++){
|
||||
String modified_path = string_fmt(scratch, "%Q\\*", it);
|
||||
String16 path16 = string8_to_string16(scratch, modified_path);
|
||||
Array<OS_File_Info> result = {a};
|
||||
for (auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++) {
|
||||
String modified_path = string_fmt(scratch, "%Q\\*", it);
|
||||
String16 path16 = string8_to_string16(scratch, modified_path);
|
||||
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE handle = FindFirstFileW((wchar_t *)path16.str, &ffd);
|
||||
if(handle == INVALID_HANDLE_VALUE) continue;
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE handle = FindFirstFileW((wchar_t *)path16.str, &ffd);
|
||||
if (handle == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
do{
|
||||
do {
|
||||
|
||||
//
|
||||
// Skip '.' and '..'
|
||||
//
|
||||
if(ffd.cFileName[0] == '.'){
|
||||
if(ffd.cFileName[1] == '.'){
|
||||
if(ffd.cFileName[2] == 0)
|
||||
continue;
|
||||
//
|
||||
// Skip '.' and '..'
|
||||
//
|
||||
if (ffd.cFileName[0] == '.') {
|
||||
if (ffd.cFileName[1] == '.') {
|
||||
if (ffd.cFileName[2] == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffd.cFileName[1] == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
String16 filename16 = string16_from_widechar(ffd.cFileName);
|
||||
String filename = string16_to_string8(scratch, filename16);
|
||||
|
||||
String full_file_path = string_fmt(a, "%Q/%Q", dir, filename);
|
||||
OS_File_Info listing = {full_file_path, os_get_absolute_path(a, full_file_path)};
|
||||
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
listing.is_directory = true;
|
||||
|
||||
if (flags & LIST_RECURSE_INTO_DIRS) {
|
||||
dirs_to_read.add(full_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(listing);
|
||||
|
||||
} while (FindNextFileW(handle, &ffd) != 0);
|
||||
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_NO_MORE_FILES) {
|
||||
// Not sure what to do here hmmm
|
||||
}
|
||||
|
||||
if(ffd.cFileName[1] == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
String16 filename16 = string16_from_widechar(ffd.cFileName);
|
||||
String filename = string16_to_string8(scratch, filename16);
|
||||
|
||||
String full_file_path = string_fmt(a, "%Q/%Q", dir, filename);
|
||||
OS_File_Info listing = {full_file_path, os_get_absolute_path(a, full_file_path)};
|
||||
|
||||
|
||||
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
|
||||
listing.is_directory = true;
|
||||
|
||||
if(flags & LIST_RECURSE_INTO_DIRS){
|
||||
dirs_to_read.add(full_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(listing);
|
||||
|
||||
}while(FindNextFileW(handle, &ffd) != 0);
|
||||
|
||||
DWORD error = GetLastError();
|
||||
if(error != ERROR_NO_MORE_FILES){
|
||||
// Not sure what to do here hmmm
|
||||
FindClose(handle);
|
||||
}
|
||||
FindClose(handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
3172
stb_sprintf.h
3172
stb_sprintf.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user