From 005fd46a96e69a8901fe59194c0b84df30ee3883 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 25 May 2024 13:25:39 -0400 Subject: [PATCH] formatter: handle multi-quoted expressions --- common/formatter/formatter_tree.cpp | 56 +++++++++++++++----- goal_src/jak1/engine/ps2/vu1-macros.gc | 4 +- goal_src/jak1/pc/debug/default-menu-pc.gc | 6 +-- test/common/formatter/corpus/lists.test.gc | 42 ++++++++++++++- test/common/formatter/corpus/symbols.test.gc | 12 ++++- 5 files changed, 99 insertions(+), 21 deletions(-) diff --git a/common/formatter/formatter_tree.cpp b/common/formatter/formatter_tree.cpp index 96e49517dc..b03f7c3e66 100644 --- a/common/formatter/formatter_tree.cpp +++ b/common/formatter/formatter_tree.cpp @@ -79,19 +79,18 @@ FormatterTree::FormatterTree(const std::string& source, const TSNode& root_node) } const std::unordered_map> node_type_ignorable_contents = { - {"list_lit", {"(", ")"}}, - {"quoting_lit", {"'"}}, - {"unquoting_lit", {","}}, - {"quasi_quoting_lit", {"`"}}, - {"unquote_splicing_lit", {",@"}}}; + {"list_lit", {"(", ")"}}}; // TODO make an imperative version eventually +// TODO - cleanup duplication void FormatterTree::construct_formatter_tree_recursive(const std::string& source, TSNode curr_node, FormatterTreeNode& tree_node, std::optional node_prefix) { if (ts_node_child_count(curr_node) == 0) { - tree_node.refs.push_back(FormatterTreeNode(source, curr_node)); + auto new_node = FormatterTreeNode(source, curr_node); + new_node.node_prefix = node_prefix; + tree_node.refs.push_back(new_node); return; } const std::string curr_node_type = ts_node_type(curr_node); @@ -106,13 +105,37 @@ void FormatterTree::construct_formatter_tree_recursive(const std::string& source tree_node.refs.push_back(FormatterTreeNode(source, curr_node)); return; } else if (curr_node_type == "quoting_lit") { - next_node_prefix = "'"; + if (node_prefix) { + node_prefix.value() += "'"; + } else { + node_prefix = "'"; + } + construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix); + return; } else if (curr_node_type == "unquoting_lit") { - next_node_prefix = ","; + if (node_prefix) { + node_prefix.value() += ","; + } else { + node_prefix = ","; + } + construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix); + return; } else if (curr_node_type == "quasi_quoting_lit") { - next_node_prefix = "`"; + if (node_prefix) { + node_prefix.value() += "`"; + } else { + node_prefix = "`"; + } + construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix); + return; } else if (curr_node_type == "unquote_splicing_lit") { - next_node_prefix = ",@"; + if (node_prefix) { + node_prefix.value() += ",@"; + } else { + node_prefix = ",@"; + } + construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix); + return; } std::vector skippable_nodes = {}; if (node_type_ignorable_contents.find(curr_node_type) != node_type_ignorable_contents.end()) { @@ -120,6 +143,7 @@ void FormatterTree::construct_formatter_tree_recursive(const std::string& source } for (size_t i = 0; i < ts_node_child_count(curr_node); i++) { const auto child_node = ts_node_child(curr_node, i); + auto debug_child = ts_node_string(child_node); const auto contents = get_source_code(source, child_node); bool skip_node = false; for (const auto& skippable_content : skippable_nodes) { @@ -132,18 +156,22 @@ void FormatterTree::construct_formatter_tree_recursive(const std::string& source continue; } if (curr_node_type == "list_lit") { - construct_formatter_tree_recursive(source, child_node, list_node, next_node_prefix); + construct_formatter_tree_recursive(source, child_node, list_node, {}); if (node_prefix) { list_node.node_prefix = node_prefix; } } else { - construct_formatter_tree_recursive(source, child_node, tree_node, next_node_prefix); - if (next_node_prefix && !tree_node.refs.empty()) { - tree_node.refs.at(tree_node.refs.size() - 1).node_prefix = next_node_prefix; + construct_formatter_tree_recursive(source, child_node, tree_node, node_prefix); + if (node_prefix && !tree_node.refs.empty()) { + tree_node.refs.at(tree_node.refs.size() - 1).node_prefix = node_prefix; } } } if (curr_node_type == "list_lit") { + // special case for empty lists + if (node_prefix && !list_node.node_prefix) { + list_node.node_prefix = node_prefix; + } tree_node.refs.push_back(list_node); } } diff --git a/goal_src/jak1/engine/ps2/vu1-macros.gc b/goal_src/jak1/engine/ps2/vu1-macros.gc index a7a7d20533..a50c9aa752 100644 --- a/goal_src/jak1/engine/ps2/vu1-macros.gc +++ b/goal_src/jak1/engine/ps2/vu1-macros.gc @@ -154,7 +154,7 @@ 'readwrite (or 'rw) means both #f means neither, turning this into a fancy macro around rlet." `(rlet (,@(apply (lambda (x) `(,x :class vf)) regs)) - ,@(if (or (eq? rw 'read) (eq? rw 'readwrite) (eq? rw 'rw)) (apply (lambda (y) `(load-vf ,y)) regs) '()) + ,@(if (or (eq? rw ''read) (eq? rw ''readwrite) (eq? rw ''rw)) (apply (lambda (y) `(load-vf ,y)) regs) '()) ,@body ;; this will mess up the return value! - ,@(if (or (eq? rw 'write) (eq? rw 'readwrite) (eq? rw 'rw)) (apply (lambda (y) `(save-vf ,y)) regs) '()))) + ,@(if (or (eq? rw ''write) (eq? rw ''readwrite) (eq? rw ''rw)) (apply (lambda (y) `(save-vf ,y)) regs) '()))) diff --git a/goal_src/jak1/pc/debug/default-menu-pc.gc b/goal_src/jak1/pc/debug/default-menu-pc.gc index f7a13331e9..648be74180 100644 --- a/goal_src/jak1/pc/debug/default-menu-pc.gc +++ b/goal_src/jak1/pc/debug/default-menu-pc.gc @@ -197,13 +197,13 @@ (defmacro dm-lambda-boolean-flag (val) "helper macro for making boolean buttons that don't just access symbols directly" - `(lambda (arg (msg debug-menu-msg)) + `,(lambda (arg (msg debug-menu-msg)) (if (= msg (debug-menu-msg press)) (not! ,val)) ,val)) (defmacro dm-lambda-int-var (val) "helper macro for making int buttons" - `(lambda (arg (msg debug-menu-msg) (newval int)) + `,(lambda (arg (msg debug-menu-msg) (newval int)) (cond ((= msg (debug-menu-msg press)) (set! ,val newval)) (else ,val)))) @@ -217,7 +217,7 @@ (defmacro dm-lambda-meters-var (val) "helper macro for making meters buttons" - `(lambda (arg (msg debug-menu-msg) (newval float)) + `,(lambda (arg (msg debug-menu-msg) (newval float)) (cond ((= msg (debug-menu-msg press)) (set! ,val (meters newval))) (else (* (1/ METER_LENGTH) ,val))))) diff --git a/test/common/formatter/corpus/lists.test.gc b/test/common/formatter/corpus/lists.test.gc index ca97026ea7..0cdaef03a9 100644 --- a/test/common/formatter/corpus/lists.test.gc +++ b/test/common/formatter/corpus/lists.test.gc @@ -100,4 +100,44 @@ Retain quoted empty lists --- -(or (= '() lst)) \ No newline at end of file +(or (= '() lst)) + +=== +Quasi-quoted unquoted List +=== + +`,(something here) + +--- + +`,(something here) + +=== +Empty Quoted List +=== + +'() + +--- + +'() + +=== +Non-empty Quoted List +=== + +'(1 2 3) + +--- + +'(1 2 3) + +=== +Non-empty Quoted List with quoted symbols inside +=== + +'('3) + +--- + +'('3) \ No newline at end of file diff --git a/test/common/formatter/corpus/symbols.test.gc b/test/common/formatter/corpus/symbols.test.gc index 2931e91ff8..d1192503c0 100644 --- a/test/common/formatter/corpus/symbols.test.gc +++ b/test/common/formatter/corpus/symbols.test.gc @@ -36,4 +36,14 @@ vector-rad<-vector-deg/2! --- -vector-rad<-vector-deg/2! \ No newline at end of file +vector-rad<-vector-deg/2! + +=== +Double Quoted Symbols +=== + +''something + +--- + +''something