aboutsummaryrefslogtreecommitdiff
path: root/nomnom/ast.nom
diff options
context:
space:
mode:
Diffstat (limited to 'nomnom/ast.nom')
-rw-r--r--nomnom/ast.nom88
1 files changed, 88 insertions, 0 deletions
diff --git a/nomnom/ast.nom b/nomnom/ast.nom
new file mode 100644
index 0000000..2d5a894
--- /dev/null
+++ b/nomnom/ast.nom
@@ -0,0 +1,88 @@
+use "lib/object.nom"
+
+#%types = [..]
+ "Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry",
+ "IndexChain", "Action", "FileChunks", "Error", "Comment"
+
+object (Syntax Tree):
+ my action [set up]:
+ if (%me.type == "Action"):
+ %stub_bits = []
+ %argnum = 1
+ for %bit in %me:
+ if:
+ (%bit is text): %stub_bits::add %bit
+ (%bit.type != "Comment"):
+ %stub_bits::add "\%argnum"
+ %argnum += 1
+ %me.stub = (%stub_bits::joined with " ")
+
+ (Syntax Tree).source_code_for_tree = (..)
+ {} with fallback % -> (read file %.source.filename)
+
+ my action [children]:
+ %children = []
+ for % in %me:
+ if ((% is a "Syntax Tree") and (%.type != "Comment")):
+ %children::add %
+ if ((%me.type == "Action") and %me.target):
+ %children::add %me.target
+ return %children
+
+ my action [as lua] (..)
+ "Syntax_Tree(\(call ({}'s metatable).as_lua with [%me]))"
+
+ my action [as nomsu] (..)
+ "(Syntax Tree \(call ({}'s metatable).as_nomsu with [%me]))"
+
+ my action [as text] (..)
+ "(Syntax Tree \(call ({}'s metatable).__tostring with [%me]))"
+
+ my action [get source code] (..)
+ (Syntax Tree).source_code_for_tree.%me
+
+ my action [map %fn]:
+ %replacement = (call %fn with [%me])
+ if %replacement:
+ if (%replacement is a "Syntax Tree"):
+ %replacement = (%k = %v for %k = %v in %replacement)
+ %replacement.source = %me.source
+ return (Syntax Tree %replacement)
+ return %replacement
+ ..else:
+ %replacement = {}
+ %changes = (no)
+ for %k = %v in %me:
+ %replacement.%k = %v
+ if (%v is a "Syntax Tree"):
+ %r = (%v::map %fn)
+ if ((%r == %v) or (%r == (nil))):
+ do next %k
+ %changes = (yes)
+ %replacement.%k = %r
+ unless %changes: return %me
+ return (Syntax Tree %replacement)
+
+ my action [== %other]:
+ unless (..)
+ all of [..]
+ (type of %me) == (type of %other)
+ (%me's metatable) == (%other's metatable)
+ (size of %me) == (size of %other)
+ %me.type == %other.type
+ ..: return (no)
+
+ for %item in %me at %i:
+ if (%other.%i != %item): return (no)
+ if (%me.type == "Action"):
+ if (%me.target != %other.target): return (no)
+ return (yes)
+
+ my action [get args]:
+ assume (%me.type == "Action") or barf "Only actions have arguments, not \(%me.type)"
+ %args = []
+ for % in %me:
+ unless ((% is text) or (%.type == "Comment")):
+ %args::add %
+ return %args
+