aboutsummaryrefslogtreecommitdiff
path: root/nomsu_tree.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-06-12 15:12:27 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-06-12 15:14:07 -0700
commitb5fb8933af283d2b873a03ded085e8b69f374e81 (patch)
tree5cf00c528eb339d5a9f4491652f8a9a0601d943b /nomsu_tree.moon
parent0c9973ff0363e400d3d284339b77197c40c3f60c (diff)
Removed dependency on 'immutable' library. This lets LuaJIT do more
aggressive optimizations and generally helps performance. Some safety is lost, but I think the performance gains, reduced complexity, and reduced dependencies are worth it.
Diffstat (limited to 'nomsu_tree.moon')
-rw-r--r--nomsu_tree.moon96
1 files changed, 40 insertions, 56 deletions
diff --git a/nomsu_tree.moon b/nomsu_tree.moon
index 3339606..fe1c4f4 100644
--- a/nomsu_tree.moon
+++ b/nomsu_tree.moon
@@ -1,69 +1,53 @@
-- This file contains the datastructures used to represent parsed Nomsu syntax trees,
-- as well as the logic for converting them to Lua code.
-utils = require 'utils'
-{:repr, :stringify, :min, :max, :equivalent, :set, :is_list, :sum} = utils
-immutable = require 'immutable'
+{:repr} = require 'utils'
{:insert, :remove, :concat} = table
-{:Lua, :Nomsu, :Source} = require "code_obj"
+{:Source} = require "code_obj"
-MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
-
-Types = {}
-Types.is_node = (n)->
- type(n) == 'userdata' and getmetatable(n) and Types[n.type] == getmetatable(n)
+AST = {}
+AST.is_syntax_tree = (n)->
+ type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n)
-- Helper method:
-Tree = (name, fields, methods)->
- methods or= {}
- is_multi = true
- for f in *fields do is_multi and= (f != "value")
- with methods
+Tree = (name, leaf_or_branch, methods)->
+ cls = methods or {}
+ is_multi = leaf_or_branch == 'branch'
+ with cls
.type = name
- .name = name
- .__new or= (source, ...)=>
- assert source
+ .is_instance = (x)=> getmetatable(x) == @
+ .__index = cls
+ .__tostring = => "#{@name}(#{@value and repr(@value) or table.concat([repr(v) for v in *@]), ', '})"
+ .map = (fn)=>
+ if replacement = fn(@) then return replacement
+ if @value then return @
+ new_vals = [v.map and v\map(fn) or v for v in *@]
+ return getmetatable(self)(@source, unpack(new_vals))
+
+ AST[name] = setmetatable cls,
+ __tostring: => @name
+ __call: (source, ...)=>
if type(source) == 'string'
source = Source\from_string(source)
- --assert Source\is_instance(source)
- return source, ...
- .is_multi = is_multi
- if is_multi
- .__tostring = => "#{@name}(#{table.concat [repr(v) for v in *@], ', '})"
- .map = (fn)=>
- if replacement = fn(@)
- return replacement
- new_vals = [v.map and v\map(fn) or v for v in *@]
- return getmetatable(self)(@source, unpack(new_vals))
- else
- .__tostring = => "#{@name}(#{repr(@value)})"
- .map = (fn)=>
- fn(@) or @
-
- Types[name] = immutable fields, methods
-
-Tree "Block", {"source"}
-Tree "EscapedNomsu", {"source"}
-Tree "Text", {"source"}
-Tree "List", {"source"}
-Tree "Dict", {"source"}
-Tree "DictEntry", {"source"}
-Tree "IndexChain", {"source"}
-Tree "Number", {"source", "value"}
-Tree "Var", {"source", "value"}
+ assert(Source\is_instance(source))
+ inst = if is_multi then {:source, ...} else {:source, value:...}
+ setmetatable(inst, @)
+ if inst.__init then inst\__init!
+ return inst
-Tree "Action", {"source", "stub"},
- __new: (source, ...)=>
- assert source
- if type(source) == 'string'
- source = Source\from_string(source)
- --assert Source\is_instance(source)
- stub_bits = {}
- for i=1,select("#",...)
- a = select(i, ...)
- stub_bits[i] = type(a) == 'string' and a or "%"
- stub = concat stub_bits, " "
- return source, stub, ...
+Tree "Number", 'leaf'
+Tree "Var", 'leaf'
+Tree "Block", 'branch'
+Tree "EscapedNomsu", 'branch'
+Tree "Text", 'branch'
+Tree "List", 'branch'
+Tree "Dict", 'branch'
+Tree "DictEntry", 'branch'
+Tree "IndexChain", 'branch'
+Tree "Action", 'branch',
+ __init: =>
+ stub_bits = [type(a) == 'string' and a or '%' for a in *@]
+ @stub = concat stub_bits, " "
get_spec: =>
concat [type(a) == "string" and a or "%#{a.value}" for a in *@], " "
-return Types
+return AST