From feafba93f327c988325355288ff0712e85047561 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 13 Sep 2021 17:21:12 -0700 Subject: [PATCH] tidy up the reference macro, rename dereference function; [examples] tidy up the commentary about for loop macros --- .../metaprograms/datadesk_like_template.c | 2 +- examples/metaprograms/node_errors.c | 2 +- examples/metaprograms/parse_check.c | 29 +-- source/md.c | 12 +- source/md.h | 6 +- tests/expression_tests.c | 172 +++++++++--------- 6 files changed, 111 insertions(+), 112 deletions(-) diff --git a/examples/metaprograms/datadesk_like_template.c b/examples/metaprograms/datadesk_like_template.c index 17b0916..4c4f0a7 100644 --- a/examples/metaprograms/datadesk_like_template.c +++ b/examples/metaprograms/datadesk_like_template.c @@ -73,7 +73,7 @@ int main(int argument_count, char **arguments) Initialize(); for(MD_EachNode(ref, list->first_child)) { - MD_Node *root = MD_NodeFromReference(ref); + MD_Node *root = MD_ResolveNodeFromReference(ref); for(MD_EachNode(node, root->first_child)) { TopLevel(node); diff --git a/examples/metaprograms/node_errors.c b/examples/metaprograms/node_errors.c index 142b4da..018ffa4 100644 --- a/examples/metaprograms/node_errors.c +++ b/examples/metaprograms/node_errors.c @@ -22,7 +22,7 @@ int main(int argument_count, char **arguments) // NOTE(rjf): Print errors on every single node. for(MD_EachNode(ref, list->first_child)) { - MD_Node *root = MD_NodeFromReference(ref); + MD_Node *root = MD_ResolveNodeFromReference(ref); for(MD_EachNode(node, root->first_child)) { MD_PrintNodeMessageFmt(stderr, node, MD_MessageKind_Error, "This node has an error!"); diff --git a/examples/metaprograms/parse_check.c b/examples/metaprograms/parse_check.c index 35c6804..4a76902 100644 --- a/examples/metaprograms/parse_check.c +++ b/examples/metaprograms/parse_check.c @@ -73,20 +73,23 @@ int main(int argument_count, char **arguments) } // print the verbose parse results - // @notes The Metadesk library provides a few macros for iterating MD_Node - // lists as shown here. The first parameter to the macro becomes an - // MD_Node pointer in the scope of the for loop that visits each node in - // the list in order. The second parameter is a pointer to the first node - // in the list. Generally we past the `first_child` of a list or parent - // MD_Node, but we don't always have to. - // - // MD_EachNode is used to iterate a list of children. - // MD_EachNodeRef is used to iterate a list of references like the list - // of roots from the parses we have built. Underneath the surface this - // macro automatically resolves the reference at the beginning of each - // loop step. - for (MD_EachNodeRef(root, list->first_child)) + // @notes The Metadesk library provides a macros for iterating chains of + // MD_Node as shown here. The first parameter to the macro names an + // 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. + for (MD_EachNode(root_it, list->first_child)) { + + // @notes The `list` we have been building does not contain a normal + // MD_Node chain like in the trees returned from the parser. Instead + // it contains a chain of 'reference' nodes, which can point to any + // metadesk node from a previous parse. So our `root_it` is iterating + // a list of reference nodes. Here we resolve the reference node to + // get the root of the parse tree. + MD_Node *root = MD_ResolveNodeFromReference(root_it); + for (MD_EachNode(node, root->first_child)) { // @notes The Metadesk library likes to use MD_String8List for diff --git a/source/md.c b/source/md.c index 92a80d8..c72e1e7 100644 --- a/source/md.c +++ b/source/md.c @@ -2837,7 +2837,7 @@ MD_TagCountFromNode(MD_Node *node) } MD_FUNCTION_IMPL MD_Node * -MD_NodeFromReference(MD_Node *node) +MD_ResolveNodeFromReference(MD_Node *node) { MD_u64 safety = 100; for(; safety > 0 && node->kind == MD_NodeKind_Reference; @@ -3078,7 +3078,7 @@ struct _MD_ExprParseCtx MD_Node *original_first; MD_Node *first; MD_Node *one_past_last; - + struct{ MD_ExprOperator *call_op; MD_ExprOperator *subscript_op; @@ -3139,12 +3139,12 @@ _MD_ExprParse_MakeContext(MD_ExprOperatorTable *op_table, MD_Node *first, MD_Nod result.original_first = first; result.first = first; result.one_past_last = one_past_last; - + result.accel.bracket_set_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Prefix, MD_S8Lit("[]")); result.accel.brace_set_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Prefix, MD_S8Lit("{}")); result.accel.call_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Postfix, MD_S8Lit("()")); result.accel.subscript_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Binary, MD_S8Lit("[]")); - + return result; } @@ -3170,7 +3170,7 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx) MD_Node *node = ctx->first; MD_ExprOperator *op = 0; - + if(MD_NodeIsNil(node)) { MD_Node *last_non_null = ctx->original_first; @@ -3178,7 +3178,7 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx) { last_non_null = last_non_null->next; } - + MD_String8 error_str = MD_S8Lit("Unexpected end of expression."); MD_u64 error_offset = last_non_null->offset + last_non_null->raw_string.size - ctx->original_first->offset; MD_Message *error = MD_MakeExprParseError(arena, error_str, error_offset); diff --git a/source/md.h b/source/md.h index caaf018..6d955d7 100644 --- a/source/md.h +++ b/source/md.h @@ -1087,17 +1087,13 @@ MD_FUNCTION MD_Node * MD_TagArgFromString(MD_Node *node, MD_String8 tag_string, MD_FUNCTION MD_b32 MD_NodeHasTag(MD_Node *node, MD_String8 tag_string, MD_MatchFlags flags); MD_FUNCTION MD_i64 MD_ChildCountFromNode(MD_Node *node); MD_FUNCTION MD_i64 MD_TagCountFromNode(MD_Node *node); -MD_FUNCTION MD_Node * MD_NodeFromReference(MD_Node *node); +MD_FUNCTION MD_Node * MD_ResolveNodeFromReference(MD_Node *node); MD_FUNCTION MD_String8 MD_PrevCommentFromNode(MD_Node *node); MD_FUNCTION MD_String8 MD_NextCommentFromNode(MD_Node *node); // NOTE(rjf): For-Loop Helpers #define MD_EachNode(it, first) MD_Node *it = (first); !MD_NodeIsNil(it); it = it->next -#define MD_EachNodeRef(it, first) \ -MD_Node *it##_r = (first), *it = MD_NodeFromReference(it##_r); \ -!MD_NodeIsNil(it##_r); \ -it##_r = it##_r->next, it = MD_NodeFromReference(it##_r) //~ Error/Warning Helpers diff --git a/tests/expression_tests.c b/tests/expression_tests.c index 425f4f5..14b1101 100644 --- a/tests/expression_tests.c +++ b/tests/expression_tests.c @@ -29,71 +29,71 @@ struct OperatorDescription{ // NOTE(mal): Based on https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence 2021-09-05 // Precedences are flipped. The ones listed here are 20-x where x is the precedence on the wikipedia table #define OPERATORS \ - X(PostFixIncrement, "++", Postfix, 18) \ - X(PostFixDecrement, "--", Postfix, 18) \ - X(Call, "()", Postfix, 18) \ - X(ArraySubscript, "[]", Binary, 18) \ - X(Member, ".", Binary, 18) \ - X(PointerMember, "->", Binary, 18) \ - X(PreFixIncrement, "++", Prefix, 17) \ - X(PreFixDecrement, "--", Prefix, 17) \ - X(UnaryPlus, "+", Prefix, 17) \ - X(UnaryMinus, "-", Prefix, 17) \ - X(LogicalNot, "!", Prefix, 17) \ - X(BitwiseNot, "~", Prefix, 17) \ - X(Dereference, "*", Prefix, 17) \ - X(AddressOf, "&", Prefix, 17) \ - X(SizeOf, "sizeof", Prefix, 17) /* NOTE(mal); Just for fun*/ \ - X(Multiplication, "*", Binary, 15) \ - X(Division, "/", Binary, 15) \ - X(Modulo, "%", Binary, 15) \ - X(Addition, "+", Binary, 14) \ - X(Subtraction, "-", Binary, 14) \ - X(LeftShift, "<<", Binary, 13) \ - X(RightShift, ">>", Binary, 13) \ - X(LessThan, "<", Binary, 11) \ - X(LessThanOrEqual, "<=", Binary, 11) \ - X(GreaterThan, ">", Binary, 11) \ - X(GreaterThanOrEqual, ">=", Binary, 11) \ - X(Equal, "==", Binary, 10) \ - X(NotEqual, "!=", Binary, 10) \ - X(BitwiseAnd, "&", Binary, 9) \ - X(BitwiseXor, "^", Binary, 8) \ - X(BitwiseOr, "|", Binary, 7) \ - X(LogicalAnd, "&&", Binary, 6) \ - X(LogicalOr, "||", Binary, 5) \ - X(Assign, "=", BinaryRightAssociative, 4) \ - X(AssignAddition, "+=", BinaryRightAssociative, 4) \ - X(AssignSubtraction, "-=", BinaryRightAssociative, 4) \ - X(AssignMultiplication,"*=", BinaryRightAssociative, 4) \ - X(AssignDivision, "/=", BinaryRightAssociative, 4) \ - X(AssignModulo, "%=", BinaryRightAssociative, 4) \ - X(AssignLeftShift, "<<=", BinaryRightAssociative, 4) \ - X(AssignRightShift, ">>=", BinaryRightAssociative, 4) \ - X(AssignBitwiseAnd, "&=", BinaryRightAssociative, 4) \ - X(AssignBitwiseXor, "^=", BinaryRightAssociative, 4) \ - X(AssignBitwiseOr, "|=", BinaryRightAssociative, 4) \ - X(BracketSet, "[]", Prefix, 3) \ - X(BraceSet, "{}", Prefix, 3) - // X(Cast "()", Prefix, 17) - // X(Comma, ",", Binary, 3) +X(PostFixIncrement, "++", Postfix, 18) \ +X(PostFixDecrement, "--", Postfix, 18) \ +X(Call, "()", Postfix, 18) \ +X(ArraySubscript, "[]", Binary, 18) \ +X(Member, ".", Binary, 18) \ +X(PointerMember, "->", Binary, 18) \ +X(PreFixIncrement, "++", Prefix, 17) \ +X(PreFixDecrement, "--", Prefix, 17) \ +X(UnaryPlus, "+", Prefix, 17) \ +X(UnaryMinus, "-", Prefix, 17) \ +X(LogicalNot, "!", Prefix, 17) \ +X(BitwiseNot, "~", Prefix, 17) \ +X(Dereference, "*", Prefix, 17) \ +X(AddressOf, "&", Prefix, 17) \ +X(SizeOf, "sizeof", Prefix, 17) /* NOTE(mal); Just for fun*/ \ +X(Multiplication, "*", Binary, 15) \ +X(Division, "/", Binary, 15) \ +X(Modulo, "%", Binary, 15) \ +X(Addition, "+", Binary, 14) \ +X(Subtraction, "-", Binary, 14) \ +X(LeftShift, "<<", Binary, 13) \ +X(RightShift, ">>", Binary, 13) \ +X(LessThan, "<", Binary, 11) \ +X(LessThanOrEqual, "<=", Binary, 11) \ +X(GreaterThan, ">", Binary, 11) \ +X(GreaterThanOrEqual, ">=", Binary, 11) \ +X(Equal, "==", Binary, 10) \ +X(NotEqual, "!=", Binary, 10) \ +X(BitwiseAnd, "&", Binary, 9) \ +X(BitwiseXor, "^", Binary, 8) \ +X(BitwiseOr, "|", Binary, 7) \ +X(LogicalAnd, "&&", Binary, 6) \ +X(LogicalOr, "||", Binary, 5) \ +X(Assign, "=", BinaryRightAssociative, 4) \ +X(AssignAddition, "+=", BinaryRightAssociative, 4) \ +X(AssignSubtraction, "-=", BinaryRightAssociative, 4) \ +X(AssignMultiplication,"*=", BinaryRightAssociative, 4) \ +X(AssignDivision, "/=", BinaryRightAssociative, 4) \ +X(AssignModulo, "%=", BinaryRightAssociative, 4) \ +X(AssignLeftShift, "<<=", BinaryRightAssociative, 4) \ +X(AssignRightShift, ">>=", BinaryRightAssociative, 4) \ +X(AssignBitwiseAnd, "&=", BinaryRightAssociative, 4) \ +X(AssignBitwiseXor, "^=", BinaryRightAssociative, 4) \ +X(AssignBitwiseOr, "|=", BinaryRightAssociative, 4) \ +X(BracketSet, "[]", Prefix, 3) \ +X(BraceSet, "{}", Prefix, 3) +// X(Cast "()", Prefix, 17) +// X(Comma, ",", Binary, 3) #define X(name, token, kind, prec) Op_##name, typedef enum{ Op_Null, OPERATORS - Op_COUNT + Op_COUNT } Op; #undef X static MD_String8 node_raw_contents(MD_Node *node, MD_b32 exclude_outer){ MD_String8 result = {0}; - + MD_u64 beg = node->offset; if(exclude_outer && !MD_NodeIsNil(node->first_child)){ beg = node->first_child->offset; } - + MD_u64 end = beg; { MD_Node *last_descendant = node; while(!MD_NodeIsNil(last_descendant->last_child)){ @@ -101,12 +101,12 @@ static MD_String8 node_raw_contents(MD_Node *node, MD_b32 exclude_outer){ } end = last_descendant->offset + last_descendant->raw_string.size; } - + MD_Node *root = node; while(!MD_NodeIsNil(root->parent)){ root = root->parent; } - + result = MD_S8Substring(root->raw_string, beg, end); return result; } @@ -117,12 +117,12 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des if(!exclude_outer_parens){ MD_S8ListPush(arena, l, MD_S8Lit("(")); } - + MD_ExprOperator *op = &descs[node->op_id].op; if(op->kind == MD_ExprOperatorKind_Binary || op->kind == MD_ExprOperatorKind_BinaryRightAssociative){ - + parenthesize_exclude_outer(arena, descs, l, node->left, 0); - + MD_b32 is_subscript = (node->op_id == Op_ArraySubscript); if(is_subscript){ MD_S8ListPush(arena, l, MD_S8Lit("[")); @@ -139,16 +139,16 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des else if(op->kind == MD_ExprOperatorKind_Prefix){ MD_S8ListPush(arena, l, node->md_node->string); MD_u8 last_op_c = MD_S8Suffix(node->md_node->string, 1).str[0]; - + if(MD_CharIsAlpha(last_op_c) || MD_CharIsDigit(last_op_c)){ // NOTE: Keyword prefix operator (e.g. sizeof) MD_S8ListPush(arena, l, MD_S8Lit(" ")); } - + parenthesize_exclude_outer(arena, descs, l, node->left, 0); } else if(op->kind == MD_ExprOperatorKind_Postfix){ parenthesize_exclude_outer(arena, descs, l, node->left, 0); - + MD_b32 is_call = (node->op_id == Op_Call); if(is_call){ MD_S8ListPush(arena, l, MD_S8Lit("(...)")); @@ -160,7 +160,7 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des else{ MD_S8ListPush(arena, l, MD_S8Lit("--- Can't print expression ---")); } - + if(!exclude_outer_parens){ MD_S8ListPush(arena, l, MD_S8Lit(")")); } @@ -175,7 +175,7 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des MD_S8ListPush(arena, l, MD_S8Lit("[...]")); } else if(node->md_node->flags & MD_NodeFlag_HasBraceLeft && - node->md_node->flags & MD_NodeFlag_HasBraceRight){ + node->md_node->flags & MD_NodeFlag_HasBraceRight){ MD_S8ListPush(arena, l, MD_S8Lit("{...}")); } else{ @@ -196,30 +196,30 @@ static MD_String8 parenthesize(MD_Arena *arena, OperatorDescription *descs, MD_E int main(void){ OperatorDescription operator_array[Op_COUNT] = {0}; #define X(name, token, kind_, prec) \ - operator_array[Op_##name].s = MD_S8Lit(token); \ - operator_array[Op_##name].op = (MD_ExprOperator){ .op_id = Op_##name, .kind = MD_ExprOperatorKind_##kind_, .precedence = prec }; +operator_array[Op_##name].s = MD_S8Lit(token); \ +operator_array[Op_##name].op = (MD_ExprOperator){ .op_id = Op_##name, .kind = MD_ExprOperatorKind_##kind_, .precedence = prec }; OPERATORS #undef X - + arena = MD_ArenaAlloc(1ull << 40); - + /* NOTE: Operator table bake errors */ { MD_ExprOperatorList operator_list = {0}; MD_ExprOperatorTable op_table = {0}; - + MD_String8 plus = MD_S8Lit("+"); MD_String8 minus = MD_S8Lit("-"); MD_Node *plus_node = MD_MakeNode(arena, MD_NodeKind_Main, plus, plus, 0); MD_Node *minus_node = MD_MakeNode(arena, MD_NodeKind_Main, minus, minus, 0); MD_Node *plus_node_bis = MD_MakeNode(arena, MD_NodeKind_Main, plus, plus, 0); - + // NOTE: Wrong operator kind operator_list = (MD_ExprOperatorList){0}; MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Null, 1, plus_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 && op_table.errors.first->node == plus_node); - + // NOTE: Repeat operator operator_list = (MD_ExprOperatorList){0}; MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node); @@ -227,7 +227,7 @@ int main(void){ op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 && op_table.errors.first->node == plus_node_bis); - + operator_list = (MD_ExprOperatorList){0}; // NOTE: Binary-postfix operator conflict MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node); @@ -235,7 +235,7 @@ int main(void){ op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 && op_table.errors.first->node == plus_node_bis); - + operator_list = (MD_ExprOperatorList){0}; // NOTE: Same precedence difference associativity conflict MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node); @@ -244,19 +244,19 @@ int main(void){ op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 && op_table.errors.first->node == minus_node); - + } - + MD_ExprOperatorList operator_list = {0}; - + for(Op op = Op_Null+1; op < Op_COUNT; ++op){ OperatorDescription *desc = operator_array + op; MD_Node *node = MD_MakeNode(arena, MD_NodeKind_Main, desc->s, desc->s, 0); MD_ExprOperatorPush(arena, &operator_list, op, desc->op.kind, desc->op.precedence, node); } - + MD_ExprOperatorTable op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - + // NOTE(mal): I'm trying something different for expression parser tests. Normally one would take the // output of MD_ExprParse and compare it against the expected output expression tree. // If instead of that we take the output of MD_ExprParse and translate it back to text while @@ -284,30 +284,30 @@ int main(void){ { .q = "a*(b.x)+c", .a = "(a * (b . x)) + c" }, { .q = "a.b*c+d", .a = "((a . b) * c) + d" }, { .q = "a.b+c*d", .a = "(a . b) + (c * d)" }, - + { .q = "a + +b", .a = "a + (+b)" }, { .q = "a + + +b", .a = "a + (+(+b))" }, { .q = "+ a - -b", .a = "(+a) - (-b)" }, - + { .q = "!a", .a = "!a" }, { .q = "!a + b", .a = "(!a) + b" }, { .q = "~a", .a = "~a" }, - + { .q = "*a+b", .a = "(*a) + b" }, { .q = "* + +a", .a = "*(+(+a))" }, { .q = "+ + *a", .a = "+(+(*a))" }, { .q = "!a", .a = "!a" }, { .q = "*f()[10]", .a = "*((f(...))[10])" }, - + { .q = "a >> b << c", .a = "(a >> b) << c" }, { .q = "a < b <= c", .a = "(a < b) <= c" }, { .q = "a > b >= c", .a = "(a > b) >= c" }, { .q = "a == b >= c", .a = "a == (b >= c)" }, { .q = "a != b == c", .a = "(a != b) == c" }, { .q = "a & &b", .a = "a & (&b)" }, - + { .q = "\"a\" + b + c", .a = "(\"a\" + b) + c" }, - + { .q = "(a", .a = "", ExpressionErrorKind_MD, 0}, { .q = "a)", .a = "", ExpressionErrorKind_MD, 1}, { .q = "/a", .a = "", ExpressionErrorKind_Expr, 0}, @@ -315,12 +315,12 @@ int main(void){ { .q = "a+", .a = "", ExpressionErrorKind_Expr, 2}, { .q = "a 1", .a = "", ExpressionErrorKind_Expr, 2}, }; - + for(MD_u32 i_test = 0; i_test < MD_ArrayCount(tests); i_test+=1){ Expression_QA test = tests[i_test]; MD_String8 q = MD_S8CString(test.q); MD_String8 a = MD_S8CString(test.a); - + MD_ParseResult parse = MD_ParseWholeString(arena, MD_S8Lit("test"), q); if(parse.errors.max_message_kind == MD_MessageKind_Null){ MD_ExprParseResult expr_parse = MD_ExprParse(arena, &op_table, parse.node->first_child, MD_NilNode()); @@ -336,7 +336,7 @@ int main(void){ for(MD_Message *message = expr_parse.errors.first; message; message = message->next){ if(message->node->offset != test.error_offset){ printf("Example %d : \"%.*s\". Expected error on character %d; got character %ld instead\n", - i_test, MD_S8VArg(q), test.error_offset, message->node->offset); + i_test, MD_S8VArg(q), test.error_offset, (long)message->node->offset); } } } @@ -352,7 +352,7 @@ int main(void){ for(MD_Message *message = parse.errors.first; message; message = message->next){ if(message->node->offset != test.error_offset){ printf("Example %d : \"%.*s\". Expected error on character %d; got character %ld instead\n", - i_test, MD_S8VArg(q), test.error_offset, message->node->offset); + i_test, MD_S8VArg(q), test.error_offset, (long)message->node->offset); } } } @@ -361,6 +361,6 @@ int main(void){ } } } - + return 0; }