aboutsummaryrefslogtreecommitdiff
path: root/lua_obj.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-04-11 20:05:12 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-04-11 20:05:18 -0700
commitb9827b1745e3b633666483ed0a8df35714a7fc4f (patch)
treefcec8f6fef4cfa11e32e6483087d0bdc8f0591ab /lua_obj.moon
parentab8ccf4e274d7a4fbb5d95e0fc20b71bafbc98dc (diff)
Work in progress...
Diffstat (limited to 'lua_obj.moon')
-rw-r--r--lua_obj.moon133
1 files changed, 133 insertions, 0 deletions
diff --git a/lua_obj.moon b/lua_obj.moon
new file mode 100644
index 0000000..ba2d0bb
--- /dev/null
+++ b/lua_obj.moon
@@ -0,0 +1,133 @@
+{:insert, :remove, :concat} = table
+immutable = require 'immutable'
+local Lua, LuaValue, Location
+
+Location = immutable {"text_name","text","start","stop"}, {
+ __new: (text_name, text, start, stop)-> text_name, text, start, stop or start
+ __tostring: "#{text_name}[#{start}:#{stop}]"
+ __lt: (other)=>
+ assert(@text == other.text, "Cannot compare sources from different texts")
+ return if @start == other.start
+ @stop < other.stop
+ else @start < other.start
+ __le: (other)=>
+ assert(@text == other.text, "Cannot compare sources from different texts")
+ return if @start == other.start
+ @stop <= other.stop
+ else @start <= other.start
+ get_text: => @text\sub(@start,@stop)
+ get_line_number: =>
+ -- TODO: do a binary search if this is actually slow, which I doubt
+ line_starts = LINE_STARTS[@text]
+ start_line = 1
+ while start_line < #line_starts and line_starts[start_line+1] <= @start
+ start_line += 1
+ stop_line = start_line
+ while stop_line < #line_starts and line_starts[stop_line+1] <= @stop
+ stop_line += 1
+ return start_line, stop_line
+ get_line: => "#{@text_name}:#{@get_line_number}"
+ get_line_range: =>
+ start_line, stop_line = @get_line_number
+ return if stop_line == start_line
+ "#{text_name}:#{start_line}"
+ else "#{text_name}:#{start_line}-#{stop_line}"
+}
+
+class Lua
+ is_statement: true
+ is_value: false
+
+ __new: (@source, ...)=>
+ @bits = {...}
+ @free_vars = {}
+
+ add_free_vars: (free_vars)=>
+ seen = {[v]:true for v in *@free_vars}
+ for var in *free_vars
+ unless seen[var]
+ @free_vars[#@free_vars+1] = var
+ seen[var] = true
+
+ as_statements: => self
+
+ declare_locals: (skip={})=>
+ if next(skip) == 1
+ skip = {[s]:true for s in *skip}
+ @prepend "local #{concat @free_vars, ", "};\n"
+ for var in *@free_vars do skip[var] = true
+ for bit in *@bits
+ if type(bit) == Lua
+ bit\declare_locals(skip)
+
+ __tostring: =>
+ buff = {}
+ for b in *@bits
+ if type(b) == 'string'
+ buff[#buff+1] = b
+ else
+ for sub in *b\render!
+ buff[#buff+1] = sub
+ return concat(buff, "")
+
+ __len: =>
+ len = 0
+ for b in *@bits
+ len += #b
+ return len
+
+ append: (...)=>
+ n = select("#",...)
+ bits = @bits
+ for i=1,n
+ bits[#bits+1] = select(i, ...)
+
+ prepend: (...)=>
+ n = select("#",...)
+ bits = @bits
+ for i=#bits+n,n+1,-1
+ bits[i] = bits[i-n]
+ for i=1,n
+ bits[i] = select(i, ...)
+
+ make_offset_table: (lua_chunkname)=>
+ -- Return a mapping from output (lua) character number to input (nomsu) character number
+ lua_str = tostring(self)
+ metadata = {
+ nomsu_filename:@source.text_name, nomsu_file:@source.text,
+ lua_filename:lua_chunkname, lua_file:lua_str
+ lua_to_nomsu: {}, nomsu_to_lua: {}
+ }
+ metadata, lua_offset = {}, 1
+ lua_offset = 1
+ walk = (lua)->
+ if type(lua) == 'string'
+ lua_offset += #lua
+ else
+ lua_start = lua_offset
+ for b in lua.bits
+ walk b
+ lua_stop = lua_offset
+ nomsu_src, lua_src = lua.souce, Location(lua_chunkname, lua_str, lua_start, lua_stop)
+ metadata.lua_to_nomsu[lua_src] = nomsu_src
+ metadata.nomsu_to_lua[nomsu_src] = lua_src
+ walk self
+ return lua_str, metadata
+
+class LuaValue extends Lua
+ is_statement: false
+ is_value: true
+
+ __new: (@source, ...)=>
+ @bits = {...}
+
+ as_statements: =>
+ bits = {unpack @bits}
+ bits[#bits+1] = ";"
+ return Lua(@source, bits)
+
+ parenthesize: =>
+ @prepend "("
+ @append ")"
+
+return {:Lua, :LuaValue}