began to work on docs

This commit is contained in:
2025-02-12 12:08:41 -05:00
parent 99097b765a
commit 1fad37ad90
12 changed files with 444 additions and 198 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Metadesk (RADDBG Standalone Fork)
# Metadesk: RAD Debugger's Standalone Fork
**Note: This repo is under heavy WIP. I'm currently getting the code from RAD's (Epic Games) Debugger over to a standalone state while at the same time studying it.**
**Note: This repo is under heavy WIP. Currently getting the code from RAD's (Epic Games) Debugger over to a standalone state while at the same time studying it.**
This is a fork that aims to make the latest version of metadesk available from the [RAD Debugger](https://github.com/EpicGamesExt/raddebugger) accessible as a standalone library.
+60 -5
View File
@@ -44,6 +44,8 @@ $release = $null
[bool] $compile_sanity = $false
[bool] $gen_c11 = $false
[bool] $tests = $false
[bool] $c11_sanity = $false
[bool] $sanity_tests = $false
[array] $vendors = @( "clang", "msvc" )
@@ -59,6 +61,8 @@ if ( $args ) { $args | ForEach-Object {
"compile_sanity" { $compile_sanity = $true }
"gen_c11" { $gen_c11 = $true }
"tests" { $tests = $true }
"c11_sanity" { $c11_sanity = $true }
"sanity_tests" { $sanity_tests = $true }
}
}
}
@@ -89,6 +93,8 @@ $cannot_build = $code_sanity -eq $false
$cannot_build = $cannot_build -and $compile_sanity -eq $false
$cannot_build = $cannot_build -and $gen_c11 -eq $false
$cannot_build = $cannot_build -and $test -eq $false
$cannot_build = $cannot_build -and $c11_sanity -eq $false
$cannot_build = $cannot_build -and $sanity_tests -eq $false
if ( $cannot_build ) {
Pop-Location
throw "No build target specified. One must be specified, this script will not assume one"
@@ -183,7 +189,7 @@ if ($gen_c11)
Push-Location $path_root
if ( Test-Path( $executable ) ) {
write-host "`nRunninggen_c11/gen_c11.exe"
write-host "`nRunning gen_c11/gen_c11.exe"
$time_taken = Measure-Command { & $executable
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
@@ -194,10 +200,9 @@ if ($gen_c11)
Pop-Location
}
if ($tests)
if ($c11_sanity)
{
write-host " Bulding tests/c11_sanity.c"
write-host " Building tests/c11_sanity.c"
$compiler_args = @()
$compiler_args += $flag_all_c
@@ -241,7 +246,57 @@ if ($tests)
}
write-host "`ntest/code_sanity completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
Pop-Location
}
if ($cpp17_sanity)
{
}
if ($sanity_tests)
{
write-host " Building tests/sanity_tests.c"
$compiler_args = @()
$compiler_args += $flag_all_c
$compiler_args += $flag_updated_cpp_macro
$compiler_args += $flag_c11
$linker_args = @()
$linker_args += $flag_link_win_subsystem_console
$path_gen = join-path $path_gen_c11 'gen'
$includes = @( $path_gen, $path_root )
$unit = join-path $path_tests 'sanity_tests.c'
$executable = join-path $path_build 'sanity_tests.exe'
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_root
if ( Test-Path( $executable ) ) {
write-host "`nRunning gen_c11/sanity_tests.exe"
$time_taken = Measure-Command { & $executable
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
write-host "`ntest/sanity_tests completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
}
if ($unicode_test)
{
}
if ($expression_tests)
{
}
Pop-Location # $path_root
View File
+3 -3
View File
@@ -48,10 +48,10 @@ struct ArenaParams
typedef struct Arena Arena;
struct Arena
{
Arena* prev; // previous arena in chain
Arena* current; // current arena in chain
Arena* prev; // Previous arena in chain
Arena* current; // Current arena in chain
AllocatorInfo backing;
SSIZE base_pos;
SSIZE base_pos; // Tracks how main arenas have been chained
SSIZE pos;
SSIZE block_size;
ArenaFlags flags;
+3 -4
View File
@@ -65,10 +65,9 @@ os_string_from_file_range__arena(Arena* arena, OS_Handle file, Rng1U64 range)
U64 pre_pos = arena_pos(arena);
String8 result;
result.size = dim_1u64(range);
result.str = push_array_no_zero(arena, U8, result.size);
result.str = push_array_no_zero(arena, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size)
{
if(actual_read_size < result.size) {
arena_pop_to(arena, pre_pos + actual_read_size);
result.size = actual_read_size;
}
@@ -82,7 +81,7 @@ os_string_from_file_range__ainfo(AllocatorInfo ainfo, OS_Handle file, Rng1U64 ra
result.str = alloc_array_no_zero(ainfo, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if ((allocator_query_support(ainfo) & AllocatorQuery_ResizeShrink) && actual_read_size < result.size) {
resize(ainfo, result.str, result.size, scast(U64, result.str) + actual_read_size);
resize(ainfo, result.str, result.size, actual_read_size);
result.size = actual_read_size;
}
return result;
+200 -1
View File
@@ -1,4 +1,203 @@
# docs
Haven't done yet...
**NOTE: metagen has not been reviewed yet.**
## Notable Changes: Original -> RAD Debugger
Metadesk's original implementation recieved an overhaul with its use within the RAD debugger.
`TODO`
## Notable Changes: RAD Debugger -> Standalone Library
For ergonomic usage and ability for the user to generate the library tailor made for their code base, the library has been heavily modified further while preserving the original indended design or interface for the user.
The metagen's base and os library's have been lifted to [code/base](../code/base/) & [code/os](../code/os/).
* `base` was splintered further into more files.
* `os` was adjusted so that includes for the target platform are in separate headers.
`MD_` and `md_` perfixes were removed, they are added back when generating variants of the library for user usage. The [gen_c11/c11.refactor](../gen_c11/c11.refactor) script has the refactoring mappings.
At the top of each head or source file in [code](../code/) the following pattern will be observed:
```c
#ifdef INTELLISENSE_DIRECTIVES
....
#endif
```
This provides a while for editors to provide syntatical or semantic information of the library's files without affecting how they are built. They are removed with [gencpp_c11.h](../third_party/gencpp_c11/gencpp_c11.h)'s `gen_scan_file` or manually while traversing the file's ast after `parse_global_body` via iterating through the tree during codegen.
Metadesk had a contrictive use of only one allocator scheme with Arenas, `memory_substrate.h` was introduced to absolve this.
It defines a generic Allocator interface of the style seen in [GB Headers](https://github.com/gingerBill/gb/blob/52a3a542ef6d398d541d5083aa878598189425ef/gb.h#L1078) and [ZPL-C](https://github.com/zpl-c/zpl/blob/master/code/header/essentials/memory_custom.h) libraries, or the [Jai](https://github.com/Ivo-Balbaert/The_Way_to_Jai/blob/main/book/21A_Memory_Allocators_and_Temporary_Storage.md) and [Odin](https://github.com/odin-lang/Odin/blob/4c4b481ccc0d6ff98e91801517b23ef78c624bdb/base/runtime/core.odin#L355) programming languages:
```c
typedef void*(AllocatorProc)(
void* allocator_data,
AllocatorMode type,
SSIZE size,
SSIZE alignment,
void* old_memory,
SSIZE old_size,
U64 flags
);
typedef struct AllocatorInfo AllocatorInfo;
struct AllocatorInfo
{
AllocatorProc* proc;
void* data;
};
```
This allows the original `Arena` used by the RaD Debugger version to now be backed by an abitrary block/s of memory:
```c
typedef U32 ArenaFlags;
enum
{
// Don't chain this arena
ArenaFlag_NoChain = (1 << 0),
// Only relevant if backing is virtual memory, will prevent allocating a new backing VArena when the current block exhausts
// Will assume backing can chain multiple block_size arenas however. If there is an allocation failure it will assert.
ArenaFlag_NoChainVirtual = (1 << 1),
// Backing allocator identified as VArena during initialization
ArenaFlag_Virtual = (1 << 2),
};
typedef struct ArenaParams ArenaParams;
struct ArenaParams
{
AllocatorInfo backing;
ArenaFlags flags;
U64 block_size; // If chaining VArenas set this to the reserve size
};
#define ARENA_DEFAULT_BLOCK_SIZE VARENA_DEFAULT_RESERVE - align_pow2(size_of(VArena), MD_DEFAULT_MEMORY_ALIGNMENT)
typedef struct Arena Arena;
struct Arena
{
Arena* prev; // Previous arena in chain
Arena* current; // Current arena in chain
AllocatorInfo backing;
SSIZE base_pos; // Tracks how main arenas have been chained
SSIZE pos;
SSIZE block_size;
ArenaFlags flags;
};
```
`generic_macros.h` was addded for use of _Generic expressions from C11.
`_Generic` is utilized mainly for creating a unified interface for procedures that take either the `Arena*` as they originally did or the new `AllocatorInfo` equivalents:
```c
MD_API String8List debug_string_list_from_tree__arena(Arena* arena, Node* root);
MD_API String8List debug_string_list_from_tree__ainfo(AllocatorInfo ainfo, Node* root);
#define debug_string_list_from_tree(allocator, string) _Generic( \
(allocator), \
Arena*: debug_string_list_from_tree__arena, \
AllocatorInfo: debug_string_list_from_tree__ainfo, \
default: assert_generic_sel_fail \
) generic_call(allocator, string)
force_inline String8List
debug_string_list_from_tree__arena(Arena* arena, Node* root) {
return debug_string_list_from_tree__ainfo(arena_allocator(arena), root);
}
```
As shown above, many of the `__arena` functions now collapse to the `__ainfo` equivalents as they do not do anything unique that the general allocator scheme cannot do.
There are however exceptions if the thread scratch allocator or essentially the `Arena`'s ability to pop/rewind its position is utilized. In those cases the distinct code path is preserved:
```c
String8
os_string_from_file_range__arena(Arena* arena, OS_Handle file, Rng1U64 range)
{
U64 pre_pos = arena_pos(arena);
String8 result;
result.size = dim_1u64(range);
result.str = push_array_no_zero(arena, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size) {
arena_pop_to(arena, pre_pos + actual_read_size);
result.size = actual_read_size;
}
return result;
}
```
The generic allocator an technically handle it though just not as ergonomnically:
```c
String8
os_string_from_file_range__ainfo(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range) {
String8 result;
result.size = dim_1u64(range);
result.str = alloc_array_no_zero(ainfo, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if ((allocator_query_support(ainfo) & AllocatorQuery_ResizeShrink) && actual_read_size < result.size) {
resize(ainfo, result.str, result.size, actual_read_size);
result.size = actual_read_size;
}
return result;
}
```
The above resize-shrink pattern could be used or the allocator made need to be wrapped in a nested arena allocator then have the resize shrink back to zero.
Natrually the allocator passed must support ths and thus the need for the query, as such any allocator that doesn't support it would not be able to shrink but this deferred to the discretion of the user now.
The following was introduced into [os.h](../code/os/os.h):
```c
typedef struct OS_Context OS_Context;
struct OS_Context
{
Arena* state_arena;
Arena* entity_arena;
B32 enable_large_pages;
};
// OS layer initialization
MD_API void os_init(OS_Context* ctx, TCTX* thread_ctx);
```
This allows for os platform functionality from the original entry_point abstraction (which is still available), to be lifted to a regular procedure that the user may manually call.
The following was introduced into [mdesk.h](../code/mdesk/mdesk.h):
```c
typedef struct Context Context;
struct Context
{
TCTX thread_ctx;
OS_Context os_ctx;
B32 dont_init_os;
};
MD_API void init(Context* ctx);
MD_API void deinit(Context* ctx); // Does nothing for now.
```
This provides the user a way to control startup of the libary.
[code/metadesk.h](../code/metadesk.h) & [code/metadesk.c](../code//metadesk.c) outline the usual intended resolved outline of how the library should be constructed for use. Its tested for vaildity using [tests/code_sanity.c](../tests/code_sanity.c).
### Additional Info
* [Zig's Allocator Interface](https://github.com/ziglang/zig/blob/master/lib/std/mem/Allocator.zig) is similar but not exactly the same.
## Notes
[Handmade Network Project Page](https://metadesk.handmade.network)
[Original Repo](https://github.com/ryanfleury/metadesk)
[Dion Systems Page](https://web.archive.org/web/20231126220529/https://dion.systems/metadesk)
[Dion Systems Reference](https://web.archive.org/web/20211205200037/https://dion.systems/metadesk_reference)
BIN
View File
Binary file not shown.
+4 -4
View File
@@ -11,9 +11,9 @@
│ 88 `8' 88 `"Ybbd8"' "Y888 `"8bbdP"Y8 `"8bbdP"Y8 `"Ybbd8"' `"YbbdP"' 88 `Y8a │
│ │
╚────────────────────────────────────────────────────────────────────────────────────────────────────────────╝
/ \-------------------------,
\_,| |
| Segregated C11 |
/ \-------------------------, Metadesk: RAD Debugger's Standalone Fork (https://github.com/Ed94/metadesk)
\_,| | This is a fork that aims to make the latest version of metadesk available
| Segregated C11 | from the RAD Debugger accessible as a standalone library.
| ,-----------------------
\_/______________________/
\_/______________________/ VERSION: 0.0.0
*/
+5 -5
View File
@@ -11,9 +11,9 @@
│ 88 `8' 88 `"Ybbd8"' "Y888 `"8bbdP"Y8 `"8bbdP"Y8 `"Ybbd8"' `"YbbdP"' 88 `Y8a │
│ │
╚────────────────────────────────────────────────────────────────────────────────────────────────────────────╝
/ \-------------------------,
\_,| |
| Single-header C11 |
| ,-----------------------
\_/______________________/
/ \-------------------------, Metadesk: RAD Debugger's Standalone Fork (https://github.com/Ed94/metadesk)
\_,| | This is a fork that aims to make the latest version of metadesk available
| Single-header C11 | from the RAD Debugger accessible as a standalone library.
| ,-----------------------
\_/______________________/ VERSION: 0.0.0
*/
+3
View File
@@ -0,0 +1,3 @@
# Old Source
This is the original metadesk that resided in the [first published repository](https://github.com/ryanfleury/metadesk).
+161 -173
View File
@@ -12,7 +12,7 @@ static struct
test_ctx;
static void
BeginTest(char* name)
begin_test(char* name)
{
MD_U64 length = md_cstring_length((MD_U8*)name);
MD_U64 spaces = 25 - length;
@@ -26,7 +26,7 @@ BeginTest(char* name)
}
static void
TestResult(MD_B32 result)
test_result(MD_B32 result)
{
test_ctx.number_of_tests += 1;
test_ctx.number_passed += !!result;
@@ -41,7 +41,7 @@ TestResult(MD_B32 result)
}
static void
EndTest(void)
end_test(void)
{
int spaces = 20 - test_ctx.number_of_tests;
if(spaces < 0) { spaces = 0; }
@@ -60,246 +60,234 @@ EndTest(void)
printf("\n");
}
#define Test(name) for(int _i_ = (BeginTest(name), 0); !_i_; _i_ += 1, EndTest())
#define test(name) for(int _i_ = (begin_test(name), 0); !_i_; _i_ += 1, end_test())
static MD_Node*
MakeTestNode(MD_NodeKind kind, MD_String8 string)
make_test_node(MD_NodeKind kind, MD_String8 string)
{
return MD_MakeNode(arena, kind, string, string, 0);
}
static MD_B32
MatchParsedWithNode(MD_Arena* arena, MD_String8 string, MD_Node* tree)
match_parsed_with_node(MD_Arena* arena, MD_String8 string, MD_Node* tree)
{
MD_TokenizeResult lexed = md_tokenize_from_text(arena, string);
MD_ParseResult parsed = md_parse_from_text_tokens(arena, str8_lit("MatchParsedWithNode"), string, lexed.tokens);
MD_ParseResult parsed = md_parse_from_text_tokens(arena, md_str8_lit("match_parsed_with_node"), string, lexed.tokens);
return md_node_match(tree, parsed.root, 0);
}
static MD_B32
TokenMatch(MD_Token token, MD_String8 string, MD_TokenFlags flags)
token_match(MD_String8 text, MD_Token token, MD_String8 string, MD_TokenFlags flags)
{
return md_str8_match(string, md_token, 0) &&& token.flags == flags
return MD_S8Match(string, token.string, 0) && token.kind == kind;
return md_str8_match(string, md_str8_substr(text, token.range), 0) &&& token.flags == flags
// return MD_S8Match(string, token.string, 0) && token.kind == kind;
}
int main(void)
{
arena = MD_ArenaAlloc();
arena = md_arena_alloc(0);
Test("Lexer")
test("Lexer")
{
MD_String8 string = md_str8_lit("abc def 123 456 123_456 abc123 123abc +-*");
MD_String8 text = md_str8_lit("abc def 123 456 123_456 abc123 123abc +-*");
MD_Token tokens[100];
MD_Token* token = tokens;
MD_Token* token_opl = md_token;
MD_U64 pos = 0;
for (; pos < string.size && token < token_opl; )
{
*token = MD_TokenFromString(MD_S8Skip(string, pos));
pos += md_dim_1u64(token->range);
token += 1;
}
MD_TokenizeResult lexed = md_tokenize_from_text(arena, text);
TestResult(TokenMatch(tokens[0], MD_S8Lit("abc"), MD_TokenKind_Identifier));
TestResult(TokenMatch(tokens[1], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[2], MD_S8Lit("def"), MD_TokenKind_Identifier));
TestResult(TokenMatch(tokens[3], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[4], MD_S8Lit("123"), MD_TokenKind_Numeric));
TestResult(TokenMatch(tokens[5], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[6], MD_S8Lit("456"), MD_TokenKind_Numeric));
TestResult(TokenMatch(tokens[7], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[8], MD_S8Lit("123_456"), MD_TokenKind_Numeric));
TestResult(TokenMatch(tokens[9], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[10], MD_S8Lit("abc123"), MD_TokenKind_Identifier));
TestResult(TokenMatch(tokens[11], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[12], MD_S8Lit("123abc"), MD_TokenKind_Numeric));
TestResult(TokenMatch(tokens[13], MD_S8Lit(" "), MD_TokenKind_Whitespace));
TestResult(TokenMatch(tokens[14], MD_S8Lit("+-*"), MD_TokenKind_Symbol));
test_result(token_match(text, tokens[0], md_str8_lit("abc"), MD_TokenFlag_Identifier));
test_result(token_match(text, tokens[1], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[2], md_str8_lit("def"), MD_TokenFlag_Identifier));
test_result(token_match(text, tokens[3], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[4], md_str8_lit("123"), MD_TokenFlag_Numeric));
test_result(token_match(text, tokens[5], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[6], md_str8_lit("456"), MD_TokenFlag_Numeric));
test_result(token_match(text, tokens[7], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[8], md_str8_lit("123_456"), MD_TokenFlag_Numeric));
test_result(token_match(text, tokens[9], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[10], md_str8_lit("abc123"), MD_TokenFlag_Identifier));
test_result(token_match(text, tokens[11], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[12], md_str8_lit("123abc"), MD_TokenFlag_Numeric));
test_result(token_match(text, tokens[13], md_str8_lit(" "), MD_TokenFlag_Whitespace));
test_result(token_match(text, tokens[14], md_str8_lit("+-*"), MD_TokenFlag_Symbol));
}
Test("Empty Sets")
test("Empty Sets")
{
TestResult(MatchParsedWithNode(MD_S8Lit("{}"), MakeTestNode(NodeKind_Main, MD_S8Lit(""))));
TestResult(MatchParsedWithNode(MD_S8Lit("()"), MakeTestNode(NodeKind_Main, MD_S8Lit(""))));
TestResult(MatchParsedWithNode(MD_S8Lit("[]"), MakeTestNode(NodeKind_Main, MD_S8Lit(""))));
TestResult(MatchParsedWithNode(MD_S8Lit("[)"), MakeTestNode(NodeKind_Main, MD_S8Lit(""))));
TestResult(MatchParsedWithNode(MD_S8Lit("(]"), MakeTestNode(NodeKind_Main, MD_S8Lit(""))));
test_result(matched_parsed_with_node(md_str8_lit("{}"), make_test_node(MD_NodeKind_Main, md_str8_lit(""))));
test_result(matched_parsed_with_node(md_str8_lit("()"), make_test_node(MD_NodeKind_Main, md_str8_lit(""))));
test_result(matched_parsed_with_node(md_str8_lit("[]"), make_test_node(MD_NodeKind_Main, md_str8_lit(""))));
test_result(matched_parsed_with_node(md_str8_lit("[)"), make_test_node(MD_NodeKind_Main, md_str8_lit(""))));
test_result(matched_parsed_with_node(md_str8_lit("(]"), make_test_node(MD_NodeKind_Main, md_str8_lit(""))));
}
Test("Simple Unnamed Sets")
test("Simple Unnamed Sets")
{
{
MD_String8 string = MD_S8Lit("{a, b, c}");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit(""));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("a")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("b")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("c")));
TestResult(MatchParsedWithNode(string, tree));
MD_String8 string = md_str8_lit("{a, b, c}");
MD_Node* tree = make_test_node(MD_NodeKind_Main, md_str8_lit(""));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("a")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("b")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("c")));
test_result(matched_parsed_with_node(string, tree));
}
{
MD_String8 string = MD_S8Lit("(1 2 3 4 5)");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit(""));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("1")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("2")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("3")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("4")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("5")));
TestResult(MatchParsedWithNode(string, tree));
MD_String8 string = md_str8_lit("(1 2 3 4 5)");
MD_Node *tree = make_test_node(MD_NodeKind_Main, md_str8_lit(""));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("1")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("2")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("3")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("4")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("5")));
test_result(matched_parsed_with_node(string, tree));
}
{
MD_String8 string = MD_S8Lit("{a}");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit(""));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("a")));
TestResult(MatchParsedWithNode(string, tree));
MD_String8 string = md_str8_lit("{a}");
MD_Node* tree = make_test_node(MD_NodeKind_Main, md_str8_lit(""));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("a")));
test_result(matched_parsed_with_node(string, tree));
}
}
Test("Simple Named Sets")
test("Simple Named Sets")
{
MD_String8 string = MD_S8Lit("simple_set: {a, b, c}");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit("simple_set"));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("a")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("b")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("c")));
TestResult(MatchParsedWithNode(string, tree));
MD_String8 string = md_str8_lit("simple_set: {a, b, c}");
MD_Node* tree = make_test_node(MD_NodeKind_Main, md_str8_lit("simple_set"));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("a")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("b")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("c")));
test_result(matched_parsed_with_node(string, tree));
}
Test("Nested Sets")
test("Nested Sets")
{
{
MD_String8 string = MD_S8Lit("{a b:{1 2 3} c}");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit(""));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("a")));
MD_String8 string = md_str8_lit("{a b:{1 2 3} c}");
MD_Node* tree = make_test_node(MD_NodeKind_Main, md_str8_lit(""));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("a")));
{
Node *sub = MakeTestNode(NodeKind_Main, MD_S8Lit("b"));
MD_PushChild(sub, MakeTestNode(NodeKind_Main, MD_S8Lit("1")));
MD_PushChild(sub, MakeTestNode(NodeKind_Main, MD_S8Lit("2")));
MD_PushChild(sub, MakeTestNode(NodeKind_Main, MD_S8Lit("3")));
MD_PushChild(tree, sub);
MD_Node* sub = make_test_node(MD_NodeKind_Main, md_str8_lit("b"));
md_node_push_child(sub, make_test_node(MD_NodeKind_Main, md_str8_lit("1")));
md_node_push_child(sub, make_test_node(MD_NodeKind_Main, md_str8_lit("2")));
md_node_push_child(sub, make_test_node(MD_NodeKind_Main, md_str8_lit("3")));
md_node_push_child(tree, sub);
}
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("c")));
TestResult(MatchParsedWithNode(string, tree));
MD_PushChild(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("c")));
test_result(matched_parsed_with_node(string, tree));
}
{
MD_String8 string = MD_S8Lit("foo: { (size: u64) -> *void }");
Node *tree = MakeTestNode(NodeKind_Main, MD_S8Lit("foo"));
Node *params = MakeTestNode(NodeKind_Main, MD_S8Lit(""));
Node *size = MakeTestNode(NodeKind_Main, MD_S8Lit("size"));
MD_PushChild(size, MakeTestNode(NodeKind_Main, MD_S8Lit("u64")));
MD_PushChild(params, size);
MD_PushChild(tree, params);
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("->")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("*")));
MD_PushChild(tree, MakeTestNode(NodeKind_Main, MD_S8Lit("void")));
TestResult(MatchParsedWithNode(string, tree));
MD_String8 string = md_str8_lit("foo: { (size: u64) -> *void }");
MD_Node* tree = make_test_node(MD_NodeKind_Main, md_str8_lit("foo"));
MD_Node* params = make_test_node(MD_NodeKind_Main, md_str8_lit(""));
MD_Node* size = make_test_node(MD_NodeKind_Main, md_str8_lit("size"));
md_node_push_child(size, make_test_node(MD_NodeKind_Main, md_str8_lit("u64")));
md_node_push_child(params, size);
md_node_push_child(tree, params);
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("->")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("*")));
md_node_push_child(tree, make_test_node(MD_NodeKind_Main, md_str8_lit("void")));
test_result(matched_parsed_with_node(string, tree));
}
}
Test("Non-Sets")
test("Non-Sets")
{
TestResult(MatchParsedWithNode(MD_S8Lit("foo"), MakeTestNode(NodeKind_Main, MD_S8Lit("foo"))));
TestResult(MatchParsedWithNode(MD_S8Lit("123"), MakeTestNode(NodeKind_Main, MD_S8Lit("123"))));
TestResult(MatchParsedWithNode(MD_S8Lit("+"), MakeTestNode(NodeKind_Main, MD_S8Lit("+"))));
test_result(matched_parsed_with_node(md_str8_lit("foo"), make_test_node(MD_NodeKind_Main, md_str8_lit("foo"))));
test_result(matched_parsed_with_node(md_str8_lit("123"), make_test_node(MD_NodeKind_Main, md_str8_lit("123"))));
test_result(matched_parsed_with_node(md_str8_lit("+"), make_test_node(MD_NodeKind_Main, md_str8_lit("+"))));
}
Test("Set Border Flags")
test("Set Border Flags")
{
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("(0, 100)"), 0);
TestResult(parse.node->flags & NodeFlag_HasParenLeft &&
parse.node->flags & NodeFlag_HasParenRight);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("(0, 100)"), 0);
test_result(parse.root->flags & MD_NodeFlag_HasParenLeft &&
parse.root->flags & MD_NodeFlag_HasParenRight);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("(0, 100]"), 0);
TestResult(parse.node->flags & NodeFlag_HasParenLeft &&
parse.node->flags & NodeFlag_HasBracketRight);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("(0, 100]"), 0);
test_result(parse.root->flags & MD_NodeFlag_HasParenLeft &&
parse.root->flags & MD_NodeFlag_HasBracketRight);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("[0, 100)"), 0);
TestResult(parse.node->flags & NodeFlag_HasBracketLeft &&
parse.node->flags & NodeFlag_HasParenRight);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("[0, 100)"), 0);
test_result(parse.root->flags & MD_NodeFlag_HasBracketLeft &&
parse.root->flags & MD_NodeFlag_HasParenRight);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("[0, 100]"), 0);
TestResult(parse.node->flags & NodeFlag_HasBracketLeft &&
parse.node->flags & NodeFlag_HasBracketRight);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("[0, 100]"), 0);
test_result(parse.root->flags & MD_NodeFlag_HasBracketLeft &&
parse.root->flags & MD_NodeFlag_HasBracketRight);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("{0, 100}"), 0);
TestResult(parse.node->flags & NodeFlag_HasBraceLeft &&
parse.node->flags & NodeFlag_HasBraceRight);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("{0, 100}"), 0);
test_result(parse.root->flags & MD_NodeFlag_HasBraceLeft &&
parse.root->flags & MD_NodeFlag_HasBraceRight);
}
}
Test("Node Separator Flags")
test("Node Separator Flags")
{
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("(a, b)"), 0);
TestResult(parse.node->first_child->flags & NodeFlag_IsBeforeComma);
TestResult(parse.node->first_child->next->flags & NodeFlag_IsAfterComma);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("(a, b)"), 0);
test_result(parse.root->first_child->flags & MD_NodeFlag_IsBeforeComma);
test_result(parse.root->first_child->next->flags & MD_NodeFlag_IsAfterComma);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("(a; b)"), 0);
TestResult(parse.node->first_child->flags & NodeFlag_IsBeforeSemicolon);
TestResult(parse.node->first_child->next->flags & NodeFlag_IsAfterSemicolon);
MD_ParseResult parse = MD_ParseOneNode(arena, md_str8_lit("(a; b)"), 0);
test_result(parse.root->first_child->flags & MD_NodeFlag_IsBeforeSemicolon);
test_result(parse.root->first_child->next->flags & MD_NodeFlag_IsAfterSemicolon);
}
}
Test("Node Text Flags")
test("Node Text Flags")
{
TestResult(MD_ParseOneNode(arena, MD_S8Lit("123"), 0).node->flags &
NodeFlag_Numeric);
TestResult(MD_ParseOneNode(arena, MD_S8Lit("123_456_789"), 0).node->flags &
NodeFlag_Numeric);
TestResult(MD_ParseOneNode(arena, MD_S8Lit("abc"), 0).node->flags &
NodeFlag_Identifier);
TestResult(MD_ParseOneNode(arena, md_str8_lit("123"), 0).node->flags &MD_NodeFlag_Numeric);
TestResult(MD_ParseOneNode(arena, md_str8_lit("123_456_789"), 0).node->flags &MD_NodeFlag_Numeric);
TestResult(MD_ParseOneNode(arena, md_str8_lit("abc"), 0).node->flags &MD_NodeFlag_Identifier);
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("\"foo\""), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringDoubleQuote);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("\"foo\""), 0);
TestResult(parse.root->flags & MD_NodeFlag_StringLiteral &&
parse.root->flags & MD_NodeFlag_StringDoubleQuote);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("'foo'"), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringSingleQuote);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("'foo'"), 0);
TestResult(parse.root->flags & NodeFlag_StringLiteral &&
parse.root->flags & NodeFlag_StringSingleQuote);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("`foo`"), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringTick);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("`foo`"), 0);
TestResult(parse.root->flags & NodeFlag_StringLiteral &&
parse.root->flags & NodeFlag_StringTick);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("\"\"\"foo\"\"\""), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringDoubleQuote &&
parse.node->flags & NodeFlag_StringTriplet);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("\"\"\"foo\"\"\""), 0);
TestResult(parse.root->flags & NodeFlag_StringLiteral &&
parse.root->flags & NodeFlag_StringDoubleQuote &&
parse.root->flags & NodeFlag_StringTriplet);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("'''foo'''"), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringSingleQuote &&
parse.node->flags & NodeFlag_StringTriplet);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("'''foo'''"), 0);
TestResult(parse.root->flags & NodeFlag_StringLiteral &&
parse.root->flags & NodeFlag_StringSingleQuote &&
parse.root->flags & NodeFlag_StringTriplet);
}
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("```foo```"), 0);
TestResult(parse.node->flags & NodeFlag_StringLiteral &&
parse.node->flags & NodeFlag_StringTick &&
parse.node->flags & NodeFlag_StringTriplet);
MD_ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("```foo```"), 0);
TestResult(parse.root->flags & NodeFlag_StringLiteral &&
parse.root->flags & NodeFlag_StringTick &&
parse.root->flags & NodeFlag_StringTriplet);
}
}
Test("Style Strings")
test("Style Strings")
{
{
MD_String8 str = MD_S8Stylize(arena, MD_S8Lit("THIS_IS_A_TEST"),
MD_String8 str = md_str8_style(arena, MD_S8Lit("THIS_IS_A_TEST"),
MD_IdentifierStyle_UpperCamelCase, MD_S8Lit(" "));
TestResult(MD_S8Match(str, MD_S8Lit("This Is A Test"), 0));
}
@@ -320,20 +308,20 @@ int main(void)
}
}
Test("Enum Strings")
test("Enum Strings")
{
TestResult(MD_S8Match(MD_StringFromNodeKind(NodeKind_Main), MD_S8Lit("Main"), 0));
TestResult(MD_S8Match(MD_StringFromNodeKind(NodeKind_Main), MD_S8Lit("Main"), 0));
TestResult(MD_S8Match(MD_StringFromNodeKind(MD_NodeKind_Main), MD_S8Lit("Main"), 0));
TestResult(MD_S8Match(MD_StringFromNodeKind(MD_NodeKind_Main), MD_S8Lit("Main"), 0));
MD_String8List list = MD_StringListFromNodeFlags(arena,
NodeFlag_StringLiteral |
NodeFlag_HasParenLeft |
NodeFlag_IsBeforeSemicolon);
MD_b32 match = 1;
MD_NodeFlag_StringLiteral |
MD_NodeFlag_HasParenLeft |
MD_NodeFlag_IsBeforeSemicolon);
MD_B32 match = 1;
for(MD_String8Node *node = list.first; node; node = node->next)
{
if(!MD_S8Match(node->string, MD_S8Lit("StringLiteral"), 0) &&
!MD_S8Match(node->string, MD_S8Lit("HasParenLeft"), 0) &&
!MD_S8Match(node->string, MD_S8Lit("IsBeforeSemicolon"), 0))
md_str8_lit
if(!md_str8_match(node->string, md_str8_lit("StringLiteral"), 0) &&
!md_str8_match(node->string, md_str8_lit("HasParenLeft"), 0) &&
!md_str8_match(node->string, md_str8_lit("IsBeforeSemicolon"), 0))
{
match = 0;
break;
@@ -342,7 +330,7 @@ int main(void)
TestResult(match);
}
Test("Node Comments")
test("Node Comments")
{
// NOTE(rjf): Pre-Comments:
@@ -389,7 +377,7 @@ int main(void)
}
}
Test("Errors")
test("Errors")
{
struct { char *s; MD_u64 columns[2]; } tests[] = {
{"{", {1}},
@@ -436,7 +424,7 @@ int main(void)
}
Test("Hash maps")
test("Hash maps")
{
MD_String8 key_strings[] =
{
@@ -478,7 +466,7 @@ int main(void)
}
}
Test("String Inner & Outer")
test("String Inner & Outer")
{
MD_String8 samples[6] = {
MD_S8LitComp("'foo-bar'"),
@@ -511,7 +499,7 @@ int main(void)
TestResult(MD_S8Match(nodes[5]->raw_string, samples[5], 0));
}
Test("String escaping")
test("String escaping")
{
{
ParseResult parse = MD_ParseOneNode(arena, MD_S8Lit("`\\``"), 0);
@@ -553,7 +541,7 @@ int main(void)
}
}
Test("Node-With-Flags Seeking")
test("Node-With-Flags Seeking")
{
{
@@ -606,7 +594,7 @@ int main(void)
}
Test("Unscoped Subtleties")
test("Unscoped Subtleties")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -678,7 +666,7 @@ int main(void)
}
}
Test("Tags")
test("Tags")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -700,7 +688,7 @@ int main(void)
}
}
Test("Tagged & Unlabeled")
test("Tagged & Unlabeled")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -731,7 +719,7 @@ int main(void)
}
}
Test("Integer Lexing")
test("Integer Lexing")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -752,7 +740,7 @@ int main(void)
}
}
Test("Float Lexing")
test("Float Lexing")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -778,7 +766,7 @@ int main(void)
}
}
Test("Labels are Not Reserved")
test("Labels are Not Reserved")
{
MD_String8 file_name = MD_S8Lit("raw_text");
@@ -808,7 +796,7 @@ int main(void)
}
}
Test("Debug Strings")
test("Debug Strings")
{
{
MD_String8 code = MD_S8Lit("@foo @bar @baz a: { b c d e f }");
+3 -1
View File
@@ -229,7 +229,7 @@ STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri
#ifdef STB_SPRINTF_IMPLEMENTATION
// NOTE(Ed): Modifying because I don't want to introduce this kind of mess to the gencpp parser
// NOTE(Ed): Modifying these typedef defines to typedefs because I don't want to introduce this kind of mess to the gencpp parser
// #define stbsp__uint32 unsigned int
// #define stbsp__int32 signed int
@@ -260,6 +260,8 @@ typedef unsigned short stbsp__uint16;
# endif
#endif
// NOTE(Ed) - END OF: Modifying these typedef defines to typedefs because I don't want to introduce this kind of mess to the gencpp parser
#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC)
# if defined(_MSC_VER) && (_MSC_VER < 1900)
# define STB_SPRINTF_MSVC_MODE