From 5d51cf478ca8977be222114c3f399ec1073ebc7e Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 7 Oct 2021 22:35:31 -0700 Subject: [PATCH] [examples] write overrides example; tidy up overrides overrview comment; tidy up misc notes files --- bin/build_examples.sh | 1 + bin/build_tests.sh | 5 +- examples/advanced_usages/overrides.c | 170 +++++++++++++++++++++++++++ examples/intro/parse_check.c | 2 +- intro_notes.txt => examples_todo.txt | 8 +- expression_parsing_notes.txt | 37 ------ source/md.c | 78 ++++++------ 7 files changed, 213 insertions(+), 88 deletions(-) create mode 100644 examples/advanced_usages/overrides.c rename intro_notes.txt => examples_todo.txt (88%) delete mode 100644 expression_parsing_notes.txt diff --git a/bin/build_examples.sh b/bin/build_examples.sh index ab7b9cd..d8e3e10 100755 --- a/bin/build_examples.sh +++ b/bin/build_examples.sh @@ -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 diff --git a/bin/build_tests.sh b/bin/build_tests.sh index 161afd3..65d48be 100755 --- a/bin/build_tests.sh +++ b/bin/build_tests.sh @@ -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 diff --git a/examples/advanced_usages/overrides.c b/examples/advanced_usages/overrides.c new file mode 100644 index 0000000..cf72b30 --- /dev/null +++ b/examples/advanced_usages/overrides.c @@ -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 +#include + +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); +} + diff --git a/examples/intro/parse_check.c b/examples/intro/parse_check.c index 15a952d..9bc7d16 100644 --- a/examples/intro/parse_check.c +++ b/examples/intro/parse_check.c @@ -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)) { diff --git a/intro_notes.txt b/examples_todo.txt similarity index 88% rename from intro_notes.txt rename to examples_todo.txt index 267da97..f232eb2 100644 --- a/intro_notes.txt +++ b/examples_todo.txt @@ -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 diff --git a/expression_parsing_notes.txt b/expression_parsing_notes.txt deleted file mode 100644 index 74938cc..0000000 --- a/expression_parsing_notes.txt +++ /dev/null @@ -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. - - - diff --git a/source/md.c b/source/md.c index 19f25b2..fc031ee 100644 --- a/source/md.c +++ b/source/md.c @@ -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 ** #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 } } - + } }