cut namespaces

This commit is contained in:
Allen Webster
2021-06-12 10:17:14 -07:00
parent f54f1771b9
commit 0832e601b7
9 changed files with 0 additions and 641 deletions
-10
View File
@@ -13,7 +13,6 @@ cl %compile_flags% ..\samples\static_site_generator\static_site_generator.c
cl %compile_flags% ..\samples\output_parse\output_parse.c
cl %compile_flags% ..\samples\c_code_generation.c
cl %compile_flags% ..\samples\node_errors\node_errors.c
cl %compile_flags% ..\samples\namespaced_types\namespaced_types.c
echo.
echo ~~~ Build All Tests ~~~
cl %compile_flags% ..\tests\sanity_tests.c
@@ -66,12 +65,3 @@ pushd build
node_errors.exe %~dp0\samples\node_errors\node_errors.md
popd
echo.
echo ~~~ Running Namespace Type Versioning Sample ~~~
pushd build
if not exist ..\samples\namespaced_types\generated mkdir ..\samples\namespaced_types\generated
namespaced_types.exe ..\samples\namespaced_types\spec.md ..\samples\namespaced_types\generated\converter.c
cl %compile_flags% ..\samples\namespaced_types\conversion_test.c
conversion_test.exe
popd
-9
View File
@@ -24,7 +24,6 @@ $CC $compile_flags ../samples/static_site_generator/static_site_generator.c -o s
$CC $compile_flags ../samples/output_parse/output_parse.c -o output_parse
$CC $compile_flags ../samples/c_code_generation.c -o c_code_generation
$CC $compile_flags ../samples/node_errors/node_errors.c -o node_errors
$CC $compile_flags ../samples/namespaced_types/namespaced_types.c -o namespaced_types
echo
echo ~~~ Build All Tests ~~~
$CC $compile_flags ../tests/sanity_tests.c -o sanity_tests
@@ -65,11 +64,3 @@ pushd build
./node_errors ../samples/node_errors/node_errors.md
popd
echo
echo ~~~ Running Namespace Type Versioning Sample ~~~
pushd build
./namespaced_types ../samples/namespaced_types/spec.md ../samples/namespaced_types/generated/converter.c
$CC $compile_flags ../samples/namespaced_types/conversion_test.c -o conversion_test
./conversion_test
popd
-9
View File
@@ -14,7 +14,6 @@ clang %compile_flags% ..\samples\static_site_generator\static_site_generator.c -
clang %compile_flags% ..\samples\output_parse\output_parse.c -o output_parse.exe
clang %compile_flags% ..\samples\c_code_generation.c -o c_code_generation.exe
clang %compile_flags% ..\samples\node_errors\node_errors.c -o node_errors.exe
clang %compile_flags% ..\samples\namespaced_types\namespaced_types.c -o namespaced_types.exe
echo.
echo ~~~ Build All Tests ~~~
clang %compile_flags% ..\tests\sanity_tests.c -o sanity_tests.exe
@@ -67,12 +66,4 @@ pushd build
node_errors.exe %~dp0\samples\node_errors\node_errors.md
popd
echo.
echo ~~~ Running Namespace Type Versioning Sample ~~~
pushd build
namespaced_types.exe ..\samples\namespaced_types\spec.md ..\samples\namespaced_types\generated\converter.c
clang %compile_flags% ..\samples\namespaced_types\conversion_test.c -o conversion_test.exe
conversion_test.exe
popd
-5
View File
@@ -194,9 +194,6 @@ main:
@doc("A Reference node is an indirection to another node. The node field @code 'ref_target' contains a pointer to the referenced node. These nodes are typically used for creating externally chained linked lists that gather nodes from a parse tree.")
Reference,
@doc("A Namespace node represents a namespace created by the @code '#namespace' reserved keyword.")
Namespace,
@doc("A Label node represents the main structure of the metadesk abstract syntax tree. Some labels have children which will also be labels. Labels can be given their text by identifiers, numerics, string and character literals, and operator symbols.")
@see(MD_TokenKind)
Label,
@@ -435,8 +432,6 @@ main:
at: *MD_u8,
filename: MD_String8,
file_contents: MD_String8,
namespace_table: MD_Map,
selected_namespace: *MD_Node,
catastrophic_error: MD_b32,
};
-374
View File
@@ -1,374 +0,0 @@
#include "md.h"
#include "md_c_helpers.h"
#include "md.c"
#include "md_c_helpers.c"
static MD_Map MapFromChildren(MD_Node *node)
{
MD_Map result = MD_MapMake();
for(MD_EachNodeRef(child, node->first_child))
{
MD_MapInsert(&result, MD_MapKeyStr(child->string), child);
}
return result;
}
static void
OutputType_C_LHS_Namespace(FILE *file, MD_Map *user_defined_types, MD_String8 prefix, MD_C_Expr *type)
{
switch (type->kind)
{
case MD_C_ExprKind_Atom:
{
MD_Node *node = type->node;
if(MD_MapLookup(user_defined_types, MD_MapKeyStr(node->string)))
{
fprintf(file, "%.*s", MD_StringExpand(prefix));
}
fprintf(file, "%.*s", MD_StringExpand(node->whole_string));
}break;
case MD_C_ExprKind_Pointer:
{
OutputType_C_LHS_Namespace(file, user_defined_types, prefix, type->sub[0]);
if (_MD_OutputType_C_NeedsParens(type))
{
fprintf(file, "(");
}
fprintf(file, "*");
}break;
case MD_C_ExprKind_Array:
{
OutputType_C_LHS_Namespace(file, user_defined_types, prefix, type->sub[0]);
if (_MD_OutputType_C_NeedsParens(type))
{
fprintf(file, "(");
}
}break;
case MD_C_ExprKind_Volatile: { fprintf(file, "volatile "); }break;
case MD_C_ExprKind_Const: { fprintf(file, "const "); }break;
default:
{
fprintf(file, "{ unexpected MD_ExprKind (%i) in type info for node \"%.*s\" }",
type->kind,
MD_StringExpand(type->node->whole_string));
}break;
}
}
static void OutputPrefixedType(FILE *f, MD_Map *user_defined_types, MD_String8 prefix, MD_Node *node, MD_u32 depth)
{
#define I() fprintf(f, "%*s", 4*depth, "");
if(MD_NodeHasTag(node, MD_S8Lit("enum")))
{
I(); fprintf(f, "typedef enum\n");
I(); fprintf(f, "{\n");
for(MD_EachNode(enumerand, node->first_child))
{
I(); fprintf(f, " %.*s%.*s_%.*s,\n", MD_StringExpand(prefix),
MD_StringExpand(node->string), MD_StringExpand(enumerand->string));
}
I(); fprintf(f, "} %.*s%.*s;\n\n", MD_StringExpand(prefix), MD_StringExpand(node->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("flags")))
{
I(); fprintf(f, "typedef enum\n");
I(); fprintf(f, "{\n");
MD_String8 singular_flag_type_name = node->string;
if(MD_StringMatch(MD_StringSuffix(singular_flag_type_name, 5), MD_S8Lit("Flags"),
MD_MatchFlag_CaseInsensitive))
{
singular_flag_type_name = MD_StringChop(singular_flag_type_name, 1);
}
MD_u32 v = 0;
for(MD_EachNode(enumerand, node->first_child))
{
I(); fprintf(f, " %.*s%.*s_%.*s = (1<<%d),\n", MD_StringExpand(prefix),
MD_StringExpand(singular_flag_type_name), MD_StringExpand(enumerand->string), v);
v += 1;
}
I(); fprintf(f, "} %.*s%.*s;\n\n", MD_StringExpand(prefix), MD_StringExpand(node->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("union")) || MD_NodeHasTag(node, MD_S8Lit("struct")))
{
MD_String8 aggregate_kind = MD_NodeHasTag(node, MD_S8Lit("union")) ? MD_S8Lit("union") : MD_S8Lit("struct");
if(depth == 0)
{
fprintf(f, "typedef %.*s %.*s%.*s %.*s%.*s;\n",
MD_StringExpand(aggregate_kind),
MD_StringExpand(prefix), MD_StringExpand(node->string),
MD_StringExpand(prefix), MD_StringExpand(node->string));
}
if(depth == 0)
{
I(); fprintf(f, "%.*s %.*s%.*s\n", MD_StringExpand(aggregate_kind),
MD_StringExpand(prefix), MD_StringExpand(node->string));
}
else
{
I(); fprintf(f, "%.*s\n", MD_StringExpand(aggregate_kind));
}
I(); fprintf(f, "{\n");
for(MD_EachNode(member, node->first_child))
{
OutputPrefixedType(f, user_defined_types, prefix, member, depth+1);
}
if(depth == 0)
{
I(); fprintf(f, "};\n\n");
}
else
{
I(); fprintf(f, "} %.*s;\n", MD_StringExpand(node->string));
}
}
else
{
MD_C_Expr *type = MD_C_ParseAsType(node->first_child, node->last_child);
I();
OutputType_C_LHS_Namespace(f, user_defined_types, prefix, type);
fprintf(f, " %.*s", MD_StringExpand(node->string));
MD_C_Generate_TypeRHS(f, type);
fprintf(f, ";\n");
}
#undef I
}
static void AppendConversionCode(FILE *f, MD_Map *user_defined_types, MD_Node *new_element, MD_Node *old_element, MD_String8 member_path)
{
MD_Map new_element_map = MapFromChildren(new_element);
if(MD_NodeHasTag(new_element, MD_S8Lit("struct")))
{
MD_String8 extended_member_path = MD_PushStringF("%.*s.%.*s", MD_StringExpand(member_path),
MD_StringExpand(old_element->string));
for(MD_EachNode(member, old_element->first_child))
{
MD_MapSlot *slot = MD_MapLookup(&new_element_map, MD_MapKeyStr(member->string));
if(slot)
{
AppendConversionCode(f, user_defined_types, member, slot->val, extended_member_path);
}
else
{
fprintf(f, " // TODO: What to do with %.*s\n", MD_StringExpand(old_element->string));
}
}
}
else if(MD_NodeIsNil(new_element->first_tag))
{
if(MD_ChildCountFromNode(new_element) == 1)
{
MD_String8 type_name = new_element->first_child->string;
if(MD_NodeDeepMatch(new_element, old_element, 0))
{
MD_String8 extended_member_path = MD_PushStringF("%.*s.%.*s", MD_StringExpand(member_path),
MD_StringExpand(old_element->string));
if(MD_MapLookup(user_defined_types, MD_MapKeyStr(type_name)))
{
fprintf(f, " result%.*s = %.*sFromV1(v%.*s);\n",
MD_StringExpand(extended_member_path), MD_StringExpand(type_name),
MD_StringExpand(extended_member_path));
}
else
{ // NOTE(mal): Assumes unknown types are base types
fprintf(f, " result%.*s = v%.*s;\n",
MD_StringExpand(extended_member_path), MD_StringExpand(extended_member_path));
}
}
else
{
fprintf(f, " // TODO: What to do with %.*s %.*s\n",
MD_StringExpand(old_element->string), MD_StringExpand(type_name));
}
}
else
{
fprintf(f, " // TODO: What to do with %.*s\n", MD_StringExpand(old_element->string));
}
}
else
{
fprintf(stderr, "Missing code to process tag @%.*s\n", MD_StringExpand(new_element->first_tag->string));
exit(1);
}
}
int main(int argument_count, char **arguments)
{
if(argument_count != 3)
{
fprintf(stderr, "USAGE: %s spec_file_name.md out_file_name.c\n", arguments[0]);
return -1;
}
MD_ParseResult spec = MD_ParseWholeFile(MD_S8CString(arguments[1]));
if(spec.first_error)
{
for(MD_Error *error = spec.first_error; error; error = error->next)
{
MD_NodeMessage(stderr, error->node, error->kind, error->string);
}
return -1;
}
FILE *f = fopen(arguments[2], "wb");
if(f == 0)
{
fprintf(stderr, "Unable to open destination file \"%s\"\n", arguments[2]);
return -1;
}
MD_Map ns_map = MapFromChildren(spec.namespaces);
// NOTE(mal): Old types get "v1_" as a prefix
fprintf(f, "// V1\n");
MD_Node *v1 = MD_MapLookup(&ns_map, MD_MapKeyStr(MD_S8Lit("v1")))->val;
MD_Map v1_map = MapFromChildren(v1);
for(MD_EachNodeRef(node, v1->first_child))
{
OutputPrefixedType(f, &v1_map, MD_S8Lit("v1_"), node, 0);
}
// NOTE(mal): New types don't get a prefix
fprintf(f, "// V2\n");
MD_Map empty_map = {0};
MD_Node *v2 = MD_MapLookup(&ns_map, MD_MapKeyStr(MD_S8Lit("v2")))->val;
for(MD_EachNodeRef(node, v2->first_child))
{
OutputPrefixedType(f, &empty_map, MD_S8Lit(""), node, 0);
}
// NOTE(mal): Routines that map old into new
fprintf(f, "// V1->V2\n");
MD_Map v2_map = MapFromChildren(v2);
for(MD_EachNodeRef(node, v1->first_child))
{
MD_MapSlot *slot = MD_MapLookup(&v2_map, MD_MapKeyStr(node->string));
MD_Node *v2_type = slot->val;
MD_Map children_map = MapFromChildren(v2_type);
fprintf(f, "static %.*s %.*sFromV1(v1_%.*s v)\n{\n",
MD_StringExpand(node->string), MD_StringExpand(node->string), MD_StringExpand(node->string));
if(MD_NodeHasTag(node, MD_S8Lit("enum")))
{
fprintf(f, " %.*s result = 0;\n", MD_StringExpand(node->string));
fprintf(f, " switch(v)\n {\n");
for(MD_EachNode(enumerand, node->first_child))
{
fprintf(f, " case v1_%.*s_%.*s: ",
MD_StringExpand(node->string), MD_StringExpand(enumerand->string));
MD_MapSlot *slot = MD_MapLookup(&children_map, MD_MapKeyStr(enumerand->string));
if(slot)
{
MD_Node *v2_enumerand = slot->val;
fprintf(f, "result = %.*s_%.*s; break;\n",
MD_StringExpand(node->string), MD_StringExpand(v2_enumerand->string));
}
else
{
fprintf(f, "assert(!\"Enumerand v1_%.*s_%.*s is no longer allowed\\n\");\n",
MD_StringExpand(node->string), MD_StringExpand(enumerand->string));
}
}
fprintf(f, " default: assert(!\"Illegal value for enum v1_%.*s\\n\"); break;\n", MD_StringExpand(node->string));
fprintf(f, " }\n");
}
else if(MD_NodeHasTag(node, MD_S8Lit("flags")))
{
fprintf(f, " %.*s result = 0;\n", MD_StringExpand(node->string));
MD_String8 singular_flag_type_name = node->string;
if(MD_StringMatch(MD_StringSuffix(singular_flag_type_name, 5), MD_S8Lit("Flags"),
MD_MatchFlag_CaseInsensitive))
{
singular_flag_type_name = MD_StringChop(singular_flag_type_name, 1);
}
for(MD_EachNode(flag, node->first_child))
{
fprintf(f, " if(v & v1_%.*s_%.*s) ",
MD_StringExpand(singular_flag_type_name), MD_StringExpand(flag->string));
MD_MapSlot *slot = MD_MapLookup(&children_map, MD_MapKeyStr(flag->string));
if(slot)
{
fprintf(f, "result |= %.*s_%.*s;\n",
MD_StringExpand(singular_flag_type_name), MD_StringExpand(flag->string));
}
else
{
fprintf(f, "assert(!\"Flag v1_%.*s is no longer allowed\\n\");\n", MD_StringExpand(flag->string));
}
}
}
else if(MD_NodeHasTag(node, MD_S8Lit("union")))
{
fprintf(f, " %.*s result = {0};\n", MD_StringExpand(node->string));
MD_Node *authoritative_member = v2_type->first_child;
for(MD_EachNode(member, v2_type->first_child))
{
if(MD_NodeHasTag(member, MD_S8Lit("authoritative")))
{
authoritative_member = member;
break;
}
}
MD_Map v1_children_map = MapFromChildren(node);
MD_MapSlot *v1_member_slot = MD_MapLookup(&v1_children_map, MD_MapKeyStr(authoritative_member->string));
if(v1_member_slot)
{
AppendConversionCode(f, &v2_map, authoritative_member, v1_member_slot->val, MD_S8Lit(""));
}
else
{
fprintf(stderr, "Can't generate conversion for union %.*s", MD_StringExpand(node->string));
}
}
else if(MD_NodeHasTag(node, MD_S8Lit("struct")))
{
fprintf(f, " %.*s result = {0};\n", MD_StringExpand(node->string));
MD_Map v1_children_map = MapFromChildren(node);
for(MD_EachNode(member, v2_type->first_child))
{
MD_MapSlot *v1_member_slot = MD_MapLookup(&v1_children_map, MD_MapKeyStr(member->string));
if(v1_member_slot)
{
AppendConversionCode(f, &v2_map, member, v1_member_slot->val, MD_S8Lit(""));
}
else
{
fprintf(stderr, "Can't generate conversion for struct member %.*s", MD_StringExpand(node->string));
}
}
}
else
{
fprintf(stderr, "Missing code to process tag @%.*s\n", MD_StringExpand(node->first_tag->string));
return -1;
}
fprintf(f, " return result;\n");
fprintf(f, "}\n\n");
fflush(f);
}
fclose(f);
return 0;
}
-52
View File
@@ -1,52 +0,0 @@
#namespace v1
@enum EntryKind : { A, B, C, E, }
@flags EntryFlags : { A, B, C, }
@union Color : {
@struct components : {
r : uint8_t;
g : uint8_t;
b : uint8_t;
a : uint8_t;
};
raw : ([4]uint8_t);
}
@struct Entry : {
to_remove : uint16_t;
kind : EntryKind;
flags : EntryFlags;
color : Color;
@struct p : {
x : float;
y : float;
}
}
#namespace v2
@enum EntryKind : { A, B, B2, C, }
@flags EntryFlags : { B, C, D, }
@union Color : {
// NOTE(mal): In the general case, it's impossible to decide automatically which member should be used
// to port data across versions of a union. That's why I've introduced @authoritative here
@authoritative
@struct components : {
b : uint8_t;
g : uint8_t;
r : uint8_t;
a : uint8_t;
}
raw : ([4]uint8_t);
}
@struct Entry : {
kind : EntryKind;
color : Color;
@struct p : {
x : float;
y : float;
z : float;
};
flags : EntryFlags;
}
-1
View File
@@ -526,7 +526,6 @@ struct MD_ParseResult
MD_Node *node;
MD_Error *first_error;
MD_u64 bytes_parsed;
MD_Node *namespaces;
};
//~ Command line parsing helper types.
-130
View File
@@ -2006,83 +2006,10 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
// NOTE(allen): setup parse context
MD_ParseCtx ctx = MD_Parse_InitializeCtx(filename, contents);
// NOTE(allen): setup namespace structure
MD_Node *namespaces = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
MD_S8Lit(""), MD_S8Lit(""), ctx.at);
MD_Map namespace_table = MD_MapMake();
// NOTE(allen): setup default namespace
MD_Node *default_ns = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
MD_S8Lit(""), MD_S8Lit(""), ctx.at);
MD_PushChild(namespaces, default_ns);
MD_MapInsert(&namespace_table, MD_MapKeyStr(default_ns->string), default_ns);
// NOTE(allen): parse loop
MD_NodeFlags next_child_flags = 0;
MD_Node *selected_namespace = default_ns;
for(;;)
{
// TODO(allen): I don't get it... this can only happen once between
// each normal node?
// It feels to me like the picture of "ParseOneNode" and the full
// parse loop is underdeveloped all around. Namespaces can be in
// the full loop but not the single case. Why? What is the
// justification for that? If a new feature is added to the grammar
// how will we determine if it is or isn't in the "single" case?
// Are we sure there is no way to make sense of a namespace in the
// "single" case?
// If it turns out there really isn't a good way to
// namespace in the "single" case, we still need to think through
// how features that only appear in the full loop will be
// expressed. Right now the answer appears to just be "the loop
// will grow more gnarly with each feature".
// It might be useful to figure out an example of a second feature
// that would make sense outside of the "single" case (if this is
// indeed the right direction for namespaces to begin with).
// Suppose, finally, that there are reasons why we specifically
// want to disallow this in the single case *and* we want to
// disallow back-to-back namespaces, that still doesn't mean we
// want to disallow back-to-back `#` cases, right? And we'd want an
// actual error detection path for that rule too, right? Sorting
// these out "later" makes me nervous.
// NOTE(allen): I've brain stormed some ideas on what it might look
// like to address some of these concerns. Ideas in the comments.
// Search for `Allen's Namespace Ideas`
// NOTE(rjf): #-things (just namespaces right now, but can be used for other such
// 'directives' in the future maybe)
if(MD_Parse_Require(&ctx, MD_S8Lit("#"), MD_TokenKind_Symbol))
{
// NOTE(rjf): Namespaces
if(MD_Parse_Require(&ctx, MD_S8Lit("namespace"), MD_TokenKind_Identifier))
{
MD_Token token = MD_ZERO_STRUCT;
if(MD_Parse_RequireKind(&ctx, MD_TokenKind_Identifier, &token))
{
MD_MapKey ns_key = MD_MapKeyStr(token.string);
MD_MapSlot *ns_slot = MD_MapLookup(&namespace_table, ns_key);
if (ns_slot == 0){
MD_Node *ns = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
token.string, token.string, token.outer_string.str);
MD_PushChild(namespaces, ns);
ns_slot = MD_MapInsert(&namespace_table, ns_key, ns);
}
selected_namespace = (MD_Node *)ns_slot->val;
}
else
{
selected_namespace = default_ns;
}
}
// NOTE(rjf): Not a valid hash thing
else
{
MD_Token token = MD_Parse_PeekSkipSome(&ctx, 0);
MD_PushTokenErrorF(&ctx, token, MD_MessageKind_Error, "Invalid '#' directive \"%.*s\"",
MD_StringExpand(token.outer_string));
}
}
// NOTE(allen): parse the next node
MD_ParseResult parse = MD_ParseOneNodeFromCtx(&ctx);
MD_Node *child = parse.node;
@@ -2093,7 +2020,6 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
// connect node into graph
MD_PushChild(root, child);
MD_PushReference(selected_namespace, child);
// check trailing symbol
MD_u32 symbol_flags = 0;
@@ -2112,7 +2038,6 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
// setup next_child_flags
next_child_flags = MD_NodeFlag_AfterFromBefore(symbol_flags);
}
result.namespaces = namespaces;
result.bytes_parsed = (MD_u64)(ctx.at - contents.str);
result.first_error = ctx.first_error;
}
@@ -2747,61 +2672,6 @@ MD_FileIterIncrement(MD_FileIter *it, MD_String8 path, MD_FileInfo *out_info)
#endif
}
// NOTE(allen): Allen's Namespace Ideas
// 1. > '#' handling goes into 'ParseOneNode'.
// > 'ParseResult' from 'ParseOneNode' can indicate that a node is a 'namespace'.
// > The parse loop does all parsing through 'ParseOneNode' first and then
// packages the results into the larger structure in different ways based on
// what came from from 'ParseOneNode'.
//
// Strength: + unify what counts as "valid metadesk"
// + simplify the 'ParseWholeString' loop by driving it with
// 'ParseOneNode' entirely
// Weakness: - boxes us in; we're now committed to all '#' meaning a single node
// - lacks discussion of the difference between '#' at top-level and
// anywhere else
//
// 2. > '#' handling goes into 'ParseOneNode'.
// > Until a non-'#' is consumed, 'ParseOneNode' keeps parsing, and combines all the
// '#' effects it sees along the way.
// > The parse loop does all parsing through 'ParseOneNode' and does not special
// handling of it's own.
//
// Strength: + unify what counts as "valid metadesk"
// + simplify the 'ParseWholeString' loop by driving it with
// 'ParseOneNode' entirely
// + simplify the 'ParseWholeString' loop by taking away any
// responsibility for constructing the result
// Weakness: - boxes us in; we're now committed to all '#' being processed in
// one go without a chance in the API for intervention from the user
// - lots of state handled between calls of 'ParseOneNode' getting
// carried through the context -> likely hard to provide simple APIs,
// more lock in of systems hurting long term maintenance, higher
// likelihood of bugs.
//
// 3. > '#' handling stays where it is
// (except maybe with helper functions involved if that helps anything)
// > We fix the bugs that are there and make things work as they are
//
// Strength: + not a lot of work in the short term
// + no possibility of hidden change in the way namespaces work
// Weakness: - there is no unification between what is "valid metadesk"
// between 'ParseOneNode' and 'ParseWholeString'
// - lacks discussion of the long term maintenance plan for '#' features.
//
// 4. > cut '#' and namespace, reserve '#' as a character for future expansion
//
// Strength: + end up with less code, easy
// + not boxed into any particular direction for '#'
// Weakness: - *may* just be throwing away something we actually want only to
// force ourselves to face this issue again later
// - may have to track down and modify some existing code? (I couldn't
// find much besides our samples, but who knows?)
// Observation: The reasons I wanted namespaces in Datadesk are actually less
// relevant in Metadesk. There is no restriction against name collision.
// I can easily create my own namespace concept if I really need it with
// `@namespace foo;`
/*
Copyright 2021 Dion Systems LLC
-51
View File
@@ -656,57 +656,6 @@ int main(void)
}
Test("Namespace")
{
char raw_text[] =
"Node;\n"
"#namespace foo\n"
"Node;\n"
"#namespace bar\n"
"Node;\n"
"#namespace foo\n"
"Object;\n"
"#namespace fiz\n"
"#namespace bar\n"
"Object;\n"
;
MD_String8 text = MD_S8Lit(raw_text);
MD_String8 file_name = MD_S8Lit("namespace_raw_text");
MD_ParseResult result = MD_ParseWholeString(file_name, text);
MD_Node *namespaces = result.namespaces;
MD_Node *ns_default = MD_ChildFromString(namespaces, MD_S8Lit(""));
MD_Node *ns_foo = MD_ChildFromString(namespaces, MD_S8Lit("foo"));
MD_Node *ns_bar = MD_ChildFromString(namespaces, MD_S8Lit("bar"));
MD_Node *ns_fiz = MD_ChildFromString(namespaces, MD_S8Lit("fiz"));
TestResult(!MD_NodeIsNil(ns_foo));
TestResult(!MD_NodeIsNil(ns_bar));
TestResult(!MD_NodeIsNil(ns_fiz));
{
MD_Node *c0 = MD_ChildFromIndex(ns_default, 0);
TestResult(MD_StringMatch(c0->string, MD_S8Lit("Node"), 0));
}
{
MD_Node *c0 = MD_ChildFromIndex(ns_foo, 0);
MD_Node *c1 = MD_ChildFromIndex(ns_foo, 1);
TestResult(MD_StringMatch(c0->string, MD_S8Lit("Node"), 0));
TestResult(MD_StringMatch(c1->string, MD_S8Lit("Object"), 0));
}
{
MD_Node *c0 = MD_ChildFromIndex(ns_bar, 0);
MD_Node *c1 = MD_ChildFromIndex(ns_bar, 1);
TestResult(MD_StringMatch(c0->string, MD_S8Lit("Node"), 0));
TestResult(MD_StringMatch(c1->string, MD_S8Lit("Object"), 0));
}
{
TestResult(MD_NodeIsNil(ns_fiz->first_child));
}
}
Test("Scoped in Unscoped")
{
// TODO(allen): This test is to reveal a strange phenomenon in the current