mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-13 07:52:22 -07:00
[examples] write overrides example; tidy up overrides overrview comment; tidy up misc notes files
This commit is contained in:
@@ -21,6 +21,7 @@ if [ -d $examps/type_metadata/generated/type_info_meta.h ]; then
|
||||
bin/bld_core.sh unit type_info $examps/type_metadata/type_info_final_program.c
|
||||
fi
|
||||
|
||||
bin/bld_core.sh unit overrides $examps/advanced_usages/overrides.c
|
||||
|
||||
echo
|
||||
|
||||
|
||||
+1
-4
@@ -9,13 +9,10 @@ cd ..
|
||||
echo "~~~ Build All Tests ~~~"
|
||||
bin/bld_core.sh show_ctx
|
||||
|
||||
bin/bld_core.sh unit expression_tests tests/expression_tests.c
|
||||
|
||||
exit
|
||||
|
||||
bin/bld_core.sh unit sanity_tests tests/sanity_tests.c
|
||||
bin/bld_core.sh unit unicode_test tests/unicode_test.c
|
||||
bin/bld_core.sh unit cpp_build_test tests/cpp_build_test.cpp
|
||||
bin/bld_core.sh unit expression_tests tests/expression_tests.c
|
||||
|
||||
echo
|
||||
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
** Example: overrides
|
||||
**
|
||||
** TODO full commentary
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
//~ example allocator /////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct ExampleAllocatorNode{
|
||||
struct ExampleAllocatorNode *next;
|
||||
struct ExampleAllocatorNode *prev;
|
||||
int size_after_node;
|
||||
} ExampleAllocatorNode;
|
||||
|
||||
typedef struct ExampleAllocator{
|
||||
ExampleAllocatorNode *first;
|
||||
ExampleAllocatorNode *last;
|
||||
} ExampleAllocator;
|
||||
|
||||
void* examp_alloc(ExampleAllocator *a, int size);
|
||||
void examp_free(ExampleAllocator *a, void *ptr);
|
||||
|
||||
|
||||
//~ include metadesk header ///////////////////////////////////////////////////
|
||||
|
||||
#include "md.h"
|
||||
|
||||
|
||||
//~ set metadesk overrides ////////////////////////////////////////////////////
|
||||
|
||||
// override memory to use malloc/free
|
||||
|
||||
ExampleAllocator* md_example_allocator = 0;
|
||||
|
||||
void* md_reserve_by_example_allocator(unsigned long long size);
|
||||
void md_release_by_example_allocator(void *ptr, unsigned long long ignore);
|
||||
|
||||
#define MD_IMPL_Reserve md_reserve_by_example_allocator
|
||||
#define MD_IMPL_Commit(p,z) (1)
|
||||
#define MD_IMPL_Decommit(p,z) ((void)0)
|
||||
#define MD_IMPL_Release(p,z) md_release_by_example_allocator
|
||||
|
||||
|
||||
// override file loading
|
||||
|
||||
MD_String8 md_load_entire_file_by_stdio(MD_Arena *arena, MD_String8 filename);
|
||||
|
||||
#define MD_IMPL_LoadEntireFile md_load_entire_file_by_stdio
|
||||
|
||||
|
||||
//~ metadesk source, global arena /////////////////////////////////////////////
|
||||
|
||||
#include "md.c"
|
||||
static MD_Arena *arena = 0;
|
||||
|
||||
|
||||
//~ implement overrides ///////////////////////////////////////////////////////
|
||||
|
||||
// override memory to use malloc/free
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
void*
|
||||
md_reserve_by_example_allocator(unsigned long long size)
|
||||
{
|
||||
assert(md_example_allocator != 0);
|
||||
void *result = examp_alloc(md_example_allocator, (int)size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
md_release_by_example_allocator(void *ptr, unsigned long long ignore)
|
||||
{
|
||||
assert(md_example_allocator != 0);
|
||||
examp_free(md_example_allocator, ptr);
|
||||
}
|
||||
|
||||
// override file loading
|
||||
|
||||
MD_String8
|
||||
md_load_entire_file_by_stdio(MD_Arena *arena, MD_String8 filename)
|
||||
{
|
||||
MD_String8 result = {0};
|
||||
MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
|
||||
MD_String8 filename_copy = MD_S8Copy(scratch.arena, filename);
|
||||
char *filename_cstr = (char*)filename_copy.str;
|
||||
FILE *file = fopen(filename_cstr, "rb");
|
||||
if (file != 0)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
result.size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(result.str, result.size, 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
MD_ReleaseScratch(scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
//~ main //////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// initialize the example allocator
|
||||
ExampleAllocator allocator = {0};
|
||||
|
||||
// configure the allocator context
|
||||
md_example_allocator = &allocator;
|
||||
|
||||
|
||||
// setup the global arena
|
||||
arena = MD_ArenaAlloc();
|
||||
// ... any normal metadesk usage may go here ...
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//~ implement the example allocator ///////////////////////////////////////////
|
||||
|
||||
void*
|
||||
examp_alloc(ExampleAllocator *a, int size)
|
||||
{
|
||||
ExampleAllocatorNode *node = (ExampleAllocatorNode*)malloc(size + sizeof(*node));
|
||||
node->size_after_node = size;
|
||||
if (a->first == 0)
|
||||
{
|
||||
a->first = a->last = node;
|
||||
node->next = node->prev = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->prev = a->last;
|
||||
node->next = 0;
|
||||
a->last->next = node;
|
||||
a->last = node;
|
||||
}
|
||||
|
||||
void *result = (node + 1);
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
examp_free(ExampleAllocator *a, void *ptr)
|
||||
{
|
||||
ExampleAllocatorNode *node = ((ExampleAllocatorNode*)ptr) - 1;
|
||||
if (node->next != 0)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
if (node->prev != 0)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
if (a->first == node)
|
||||
{
|
||||
a->first = node->next;
|
||||
}
|
||||
if (a->last == node)
|
||||
{
|
||||
a->last = node->prev;
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ int main(int argc, char **argv)
|
||||
// MD_Node pointer in the for loop that iterates through each node in the
|
||||
// list. The second parameter is a pointer to the first node of the list.
|
||||
// Generally we past the `first_child` of a list or parent MD_Node, but we
|
||||
// don't always have to.
|
||||
// don't always have to.
|
||||
for (MD_EachNode(root_it, list->first_child))
|
||||
{
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
Intro Materials Should Cover:
|
||||
arena
|
||||
string helpers
|
||||
immutable tree model
|
||||
nil
|
||||
|
||||
Example Programs:
|
||||
[x] Metadesk hello world
|
||||
[x] Metadesk parse checker
|
||||
@@ -16,6 +10,8 @@ Example Programs:
|
||||
[ ] Example of simple expression parser
|
||||
[ ] Example of C-like expression parser (with value and type expressions)
|
||||
[ ] Example(s) of using overrides
|
||||
[x] Write
|
||||
[ ] Commentary
|
||||
[ ] Example memory clearing in long-running program
|
||||
[ ] Example multi-threaded parsing
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
It looks like there was some confusion around the [] and {} handling.
|
||||
|
||||
1. I don't think these should be allowed as prefix operators at all.
|
||||
Here for example I find it weird and ambiguous `[1, 100] * n`
|
||||
Is this two prefix operators on `n` or is `*` a binary operator?
|
||||
I want to read it as a binary operator, which makes `[1, 100]` a leaf
|
||||
not a prefix. Yet the test sets up "[]" as a prefix and if I remove
|
||||
the "[]" prefix operator the test fails
|
||||
'Example 12 : "[1, 100] * n". Unexpected Expr parsing error: "Unexpected set."'
|
||||
This is a good test but I think it should work *all the time*. Any set
|
||||
with "[]" "{}" "[)" or "(]" should just always be allowed.
|
||||
|
||||
I would like to:
|
||||
a. Always accept the kinds of sets I just listed as leafs when they appear
|
||||
in a location expecting a leaf
|
||||
b. Emit an error when the user tries to create a binary or prefix operator with
|
||||
"[]" "()" or any other set type; allowing "[]" and "()" should be a special
|
||||
case of postfix operators only
|
||||
|
||||
2. When a set type is allowed as a postfix operator, let's do the same thing no
|
||||
matter what kind of set it is. Right now the "[]" postfix has it's children
|
||||
parsed but the "()" does not. I think we should just treat all sets-as-postfix
|
||||
operators the way we're doing "()". Then it's just a matter of checking if a
|
||||
node is a particular set type that matches an existing postfix set.
|
||||
|
||||
3. We should emit errors whenever an operator string does not parse to a single
|
||||
metadesk token - with the exception of the special cases for sets "()" and
|
||||
"[]" Also they should be restricted to the "label" making tokens:
|
||||
identifiers, numbers, string literals and symbols. We could make this easier
|
||||
by allowing even fewer kinds. At the limit it could be just symbols, but
|
||||
that cuts out the clever 'sizeof' from the test... Maybe symbols and
|
||||
identifers only? If that's not too difficult to pull off let's go with that.
|
||||
If an issue comes up with this one we can discuss more because it's not
|
||||
exactly clear to me what's best.
|
||||
|
||||
|
||||
|
||||
+38
-40
@@ -3,44 +3,44 @@
|
||||
#if !defined(MD_C)
|
||||
#define MD_C
|
||||
|
||||
/* NOTE(allen): Notes on overrides/macro options:
|
||||
/* NOTE(allen): Overrides & Options Macros:
|
||||
**
|
||||
** Overridable :
|
||||
** "memset" ** REQUIRED (default crt-based implementation available)
|
||||
** #define MD_IMPL_Memset (void*, int, MD_u64) -> void*
|
||||
** #define MD_IMPL_Memmove (void*, void*, MD_u64) -> void*
|
||||
** Overridable
|
||||
** "memset" ** REQUIRED (default crt-based implementation)
|
||||
** #define MD_IMPL_Memset (void*, int, uint64) -> void*
|
||||
** #define MD_IMPL_Memmove (void*, void*, uint64) -> void*
|
||||
**
|
||||
** "file iteration" ** OPTIONAL
|
||||
** #define MD_IMPL_FileIterBegin (MD_FileIter*, MD_String8) -> MD_b32
|
||||
** "file iteration" ** OPTIONAL (default for win32 and linux)
|
||||
** #define MD_IMPL_FileIterBegin (MD_FileIter*, MD_String8) -> Boolean
|
||||
** #define MD_IMPL_FileIterNext (MD_Arena*, MD_FileIter*) -> MD_FileInfo
|
||||
** #define MD_IMPL_FileIterEnd (MD_FileIter*) -> void
|
||||
**
|
||||
** "file load" ** OPTIONAL
|
||||
** "file load" ** OPTIONAL (default for win32 and linux)
|
||||
** #define MD_IMPL_LoadEntireFile (MD_Arena*, MD_String8 filename) -> MD_String8
|
||||
**
|
||||
** "low level memory" ** OPTIONAL (required for default arena)
|
||||
** #define MD_IMPL_Reserve (MD_u64) -> void*
|
||||
** #define MD_IMPL_Commit (void*, MD_u64) -> MD_b32
|
||||
** #define MD_IMPL_Decommit (void*, MD_u64) -> void
|
||||
** #define MD_IMPL_Release (void*, MD_u64) -> void
|
||||
** "low level memory" ** OPTIONAL (required for default arena) (default for win32 and linux)
|
||||
** #define MD_IMPL_Reserve (uint64) -> void*
|
||||
** #define MD_IMPL_Commit (void*, uint64) -> MD_b32
|
||||
** #define MD_IMPL_Decommit (void*, uint64) -> void
|
||||
** #define MD_IMPL_Release (void*, uint64) -> void
|
||||
**
|
||||
** "arena" ** REQUIRED (default implementation available)
|
||||
** "arena" ** REQUIRED (default available)
|
||||
** #define MD_IMPL_Arena <type>
|
||||
** #define MD_IMPL_ArenaAlloc () -> MD_IMPL_Arena*
|
||||
** #define MD_IMPL_ArenaRelease (MD_IMPL_Arena*) -> void
|
||||
** #define MD_IMPL_ArenaGetPos (MD_IMPL_Arena*) -> MD_u64
|
||||
** #define MD_IMPL_ArenaPush (MD_IMPL_Arena*, MD_u64) -> void*
|
||||
** #define MD_IMPL_ArenaPopTo (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaSetAutoAlign (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaHeaderSize MD_u64
|
||||
** #define MD_IMPL_ArenaGetPos (MD_IMPL_Arena*) -> uint64
|
||||
** #define MD_IMPL_ArenaPush (MD_IMPL_Arena*, uint64) -> void*
|
||||
** #define MD_IMPL_ArenaPopTo (MD_IMPL_Arena*, uint64) -> void
|
||||
** #define MD_IMPL_ArenaSetAutoAlign (MD_IMPL_Arena*, uint64) -> void
|
||||
** #define MD_IMPL_ArenaHeaderSize uint64
|
||||
**
|
||||
** "scratch" ** REQUIRED (default implementation available)
|
||||
** #define MD_IMPL_GetScratch (MD_IMPL_Arena**, MD_u64) -> MD_IMPL_Arena*
|
||||
** "scratch" ** REQUIRED (default available)
|
||||
** #define MD_IMPL_GetScratch (MD_IMPL_Arena**, uint64) -> MD_IMPL_Arena*
|
||||
** "scratch constants" ** OPTIONAL (required for default scratch)
|
||||
** #define MD_IMPL_ScratchCount MD_u64 / default 2
|
||||
** #define MD_IMPL_ScratchCount uint64 [default 2]
|
||||
**
|
||||
** "sprintf" ** OPTIONAL (default implementation available)
|
||||
** #define MD_IMPL_Vsnprintf (char * buf, int count, char const * fmt, va_list va) -> int
|
||||
** "sprintf" ** OPTIONAL (default available)
|
||||
** #define MD_IMPL_Vsnprintf (char*, uint64, char const*, va_list) -> uint64
|
||||
**
|
||||
** Default Implementation Controls
|
||||
** These controls default to '1' i.e. 'enabled'
|
||||
@@ -667,8 +667,6 @@ MD_GetScratchDefault(MD_Arena **conflicts, MD_u64 count)
|
||||
//////////////////////// MD Library Implementation /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MD_UNTERMINATED_TOKEN_LEN_CAP 20
|
||||
|
||||
#if MD_DEFAULT_SPRINTF
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#define STB_SPRINTF_DECORATE(name) md_stbsp_##name
|
||||
@@ -3372,14 +3370,14 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list)
|
||||
|
||||
// error checking
|
||||
MD_String8 error_str = MD_ZERO_STRUCT;
|
||||
|
||||
|
||||
MD_Token op_token = MD_TokenFromString(op_s);
|
||||
MD_b32 is_setlike_op =
|
||||
(op_s.size == 2 &&
|
||||
(MD_S8Match(op_s, MD_S8Lit("[]"), 0) || MD_S8Match(op_s, MD_S8Lit("()"), 0) ||
|
||||
MD_S8Match(op_s, MD_S8Lit("[)"), 0) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) ||
|
||||
MD_S8Match(op_s, MD_S8Lit("{}"), 0)));
|
||||
|
||||
(op_s.size == 2 &&
|
||||
(MD_S8Match(op_s, MD_S8Lit("[]"), 0) || MD_S8Match(op_s, MD_S8Lit("()"), 0) ||
|
||||
MD_S8Match(op_s, MD_S8Lit("[)"), 0) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) ||
|
||||
MD_S8Match(op_s, MD_S8Lit("{}"), 0)));
|
||||
|
||||
if(op_kind != MD_ExprOprKind_Prefix && op_kind != MD_ExprOprKind_Postfix &&
|
||||
op_kind != MD_ExprOprKind_Binary && op_kind != MD_ExprOprKind_BinaryRightAssociative)
|
||||
{
|
||||
@@ -3545,19 +3543,19 @@ MD_ExprParse_MakeContext(MD_ExprOprTable *op_table)
|
||||
{
|
||||
MD_ExprParseCtx result = MD_ZERO_STRUCT;
|
||||
result.op_table = op_table;
|
||||
|
||||
|
||||
result.accel.postfix_set_ops[0] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("()"));
|
||||
result.accel.postfix_set_flags[0] = MD_NodeFlag_HasParenLeft | MD_NodeFlag_HasParenRight;
|
||||
|
||||
|
||||
result.accel.postfix_set_ops[1] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("[]"));
|
||||
result.accel.postfix_set_flags[1] = MD_NodeFlag_HasBracketLeft | MD_NodeFlag_HasBracketRight;
|
||||
|
||||
|
||||
result.accel.postfix_set_ops[2] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("{}"));
|
||||
result.accel.postfix_set_flags[2] = MD_NodeFlag_HasBraceLeft | MD_NodeFlag_HasBraceRight;
|
||||
|
||||
|
||||
result.accel.postfix_set_ops[3] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("[)"));
|
||||
result.accel.postfix_set_flags[3] = MD_NodeFlag_HasBracketLeft | MD_NodeFlag_HasParenRight;
|
||||
|
||||
|
||||
result.accel.postfix_set_ops[4] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("(]"));
|
||||
result.accel.postfix_set_flags[4] = MD_NodeFlag_HasParenLeft | MD_NodeFlag_HasBracketRight;
|
||||
|
||||
@@ -3713,7 +3711,7 @@ MD_ExprParse_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
MD_b32 found_postfix_setlike_operator = 0;
|
||||
@@ -3731,7 +3729,7 @@ MD_ExprParse_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!found_postfix_setlike_operator)
|
||||
{
|
||||
if(MD_ExprParse_OprConsume(ctx, iter, opl, MD_ExprOprKind_Postfix,
|
||||
@@ -3744,7 +3742,7 @@ MD_ExprParse_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx,
|
||||
break; // NOTE: Due to lack of progress
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user