aboutsummaryrefslogtreecommitdiff
path: root/syntax_tree.moon
diff options
context:
space:
mode:
Diffstat (limited to 'syntax_tree.moon')
-rw-r--r--syntax_tree.moon164
1 files changed, 79 insertions, 85 deletions
diff --git a/syntax_tree.moon b/syntax_tree.moon
index f3d3aee..228f560 100644
--- a/syntax_tree.moon
+++ b/syntax_tree.moon
@@ -4,10 +4,6 @@
{:Source} = require "code_obj"
unpack or= table.unpack
-AST = {}
-AST.is_syntax_tree = (n, t=nil)->
- type(n) == 'table' and getmetatable(n) and getmetatable(n).__type == "Syntax Tree" and (t == nil or n.type == t)
-
as_lua = =>
if type(@) == 'number'
return tostring(@)
@@ -16,90 +12,88 @@ as_lua = =>
return _as_lua(@)
error("Not supported: #{@}")
-types = {"Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry",
- "IndexChain", "Action", "FileChunks", "Error", "Comment"}
-for name in *types
- cls = {}
- with cls
- .__class = cls
- .__index = cls
- .__name = name
- .type = name
- .__type = "Syntax Tree"
- .is_instance = (x)=> getmetatable(x) == @
- .__tostring = =>
- bits = [tostring(b) for b in *@]
- for k,v in pairs(@)
- unless bits[k]
- table.insert(bits, "[ #{tostring(k)}]=#{tostring(v)}")
- return "#{@type}{#{table.concat(bits, ", ")}}"
- .as_lua = =>
- bits = [as_lua(b) for b in *@]
+--types = {"Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry",
+-- "IndexChain", "Action", "FileChunks", "Error", "Comment"}
+class SyntaxTree
+ @__type: "Syntax Tree"
+
+ __tostring: =>
+ bits = [tostring(b) for b in *@]
+ for k,v in pairs(@)
+ unless bits[k]
+ table.insert(bits, "[ #{tostring(k)}]=#{tostring(v)}")
+ return "SyntaxTree{#{table.concat(bits, ", ")}}"
+
+ __eq: (other)=>
+ return false if type(@) != type(other) or #@ != #other or getmetatable(@) != getmetatable(other)
+ for i=1,#@
+ return false if @[i] != other[i]
+ return false if @target != other.target
+ return true
+
+ as_lua: =>
+ bits = [as_lua(b) for b in *@]
+ for k,v in pairs(@)
+ unless bits[k]
+ table.insert(bits, "[ #{as_lua(k)}]=#{as_lua(v)}")
+ return "SyntaxTree{#{table.concat(bits, ", ")}}"
+
+ @source_code_for_tree: setmetatable({}, {__index:(t)=>
+ s = t.source
+ Files = require 'files'
+ f = Files.read(s.filename)
+ return f
+ })
+ get_source_code: => @@source_code_for_tree[@]
+ map: (fn)=>
+ replacement = fn(@)
+ if replacement == false then return nil
+ if replacement
+ -- Clone the replacement, so we can give it a proper source/comments
+ if SyntaxTree\is_instance(replacement)
+ replacement = {k,v for k,v in pairs replacement}
+ replacement.source = @source
+ replacement.comments = {unpack(@comments)} if @comments
+ replacement = SyntaxTree(replacement)
+ else
+ replacement = {source:@source, comments:@comments and {unpack(@comments)}}
+ changes = false
for k,v in pairs(@)
- unless bits[k]
- table.insert(bits, "[ #{as_lua(k)}]=#{as_lua(v)}")
- return "#{@type}{#{table.concat(bits, ", ")}}"
- .source_code_for_tree = setmetatable({}, {__index:(t)=>
- s = t.source
- Files = require 'files'
- f = Files.read(s.filename)
- return f
- })
- .get_source_code = => @source_code_for_tree[@]
- .map = (fn)=>
- replacement = fn(@)
- if replacement == false then return nil
- if replacement
- -- Clone the replacement, so we can give it a proper source/comments
- if AST.is_syntax_tree(replacement)
- replacement = setmetatable {k,v for k,v in pairs replacement}, getmetatable(replacement)
- replacement.source = @source
- replacement.comments = {unpack(@comments)} if @comments
- if init = replacement.__init then init(replacement)
+ replacement[k] = v
+ if SyntaxTree\is_instance(v)
+ r = v\map(fn)
+ continue if r == v or r == nil
+ changes = true
+ replacement[k] = r
+ return @ unless changes
+ replacement = SyntaxTree(replacement)
+ return replacement
+
+ get_args: =>
+ assert(@type == "Action", "Only actions have arguments")
+ return [tok for tok in *@ when type(tok) != 'string']
+
+ get_stub: =>
+ stub_bits = {}
+ arg_i = 1
+ for a in *@
+ if type(a) == 'string'
+ stub_bits[#stub_bits+1] = a
else
- replacement = {source:@source, comments:@comments and {unpack(@comments)}}
- changes = false
- for k,v in pairs(@)
- replacement[k] = v
- if AST.is_syntax_tree(v)
- r = v\map(fn)
- continue if r == v or r == nil
- changes = true
- replacement[k] = r
- return @ unless changes
- replacement = setmetatable replacement, getmetatable(@)
- if init = replacement.__init then init(replacement)
- return replacement
- .__eq = (other)=>
- return false if type(@) != type(other) or #@ != #other or getmetatable(@) != getmetatable(other)
- for i=1,#@
- return false if @[i] != other[i]
- return false if @target != other.target
- return true
+ stub_bits[#stub_bits+1] = tostring(arg_i)
+ arg_i += 1
+ return concat stub_bits, " "
- AST[name] = setmetatable cls,
- __tostring: => @__name
- __call: (t)=>
- if type(t.source) == 'string'
- t.source = Source\from_string(t.source)
- --else
- -- assert(Source\is_instance(t.source))
- setmetatable(t, @)
- if init = t.__init then init(t)
- return t
+ @is_instance: (t)=>
+ type(t) == 'table' and getmetatable(t) == @__base
-AST.Action.__init = =>
- stub_bits = {}
- arg_i = 1
- for a in *@
- if type(a) == 'string'
- stub_bits[#stub_bits+1] = a
- else
- stub_bits[#stub_bits+1] = tostring(arg_i)
- arg_i += 1
- @stub = concat stub_bits, " "
-AST.Action.get_args = =>
- [tok for tok in *@ when type(tok) != 'string']
+getmetatable(SyntaxTree).__call = (t)=>
+ if type(t.source) == 'string'
+ t.source = Source\from_string(t.source)
+ setmetatable(t, @__base)
+ if t.type == 'Action'
+ t.stub = t\get_stub!
+ return t
-return AST
+return SyntaxTree