diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-04-11 20:05:12 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-04-11 20:05:18 -0700 |
| commit | b9827b1745e3b633666483ed0a8df35714a7fc4f (patch) | |
| tree | fcec8f6fef4cfa11e32e6483087d0bdc8f0591ab /lua_obj.moon | |
| parent | ab8ccf4e274d7a4fbb5d95e0fc20b71bafbc98dc (diff) | |
Work in progress...
Diffstat (limited to 'lua_obj.moon')
| -rw-r--r-- | lua_obj.moon | 133 |
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} |
