formatter: handle multi-quoted expressions

This commit is contained in:
Tyler Wilding
2024-05-25 13:25:39 -04:00
parent e67a3ea4c3
commit 005fd46a96
5 changed files with 99 additions and 21 deletions
+42 -14
View File
@@ -79,19 +79,18 @@ FormatterTree::FormatterTree(const std::string& source, const TSNode& root_node)
}
const std::unordered_map<std::string, std::vector<std::string>> 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<std::string> 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<std::string> 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);
}
}
+2 -2
View File
@@ -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) '())))
+3 -3
View File
@@ -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)))))
+41 -1
View File
@@ -100,4 +100,44 @@ Retain quoted empty lists
---
(or (= '() lst))
(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)
+11 -1
View File
@@ -36,4 +36,14 @@ vector-rad<-vector-deg/2!
---
vector-rad<-vector-deg/2!
vector-rad<-vector-deg/2!
===
Double Quoted Symbols
===
''something
---
''something