diff options
Diffstat (limited to 'nomnom')
| -rw-r--r-- | nomnom/ast.nom | 90 | ||||
| -rw-r--r-- | nomnom/code_obj.nom | 212 | ||||
| -rw-r--r-- | nomnom/compile.nom | 278 | ||||
| -rw-r--r-- | nomnom/decompile.nom | 348 | ||||
| -rw-r--r-- | nomnom/files.nom | 110 | ||||
| -rw-r--r-- | nomnom/parser.nom | 91 | ||||
| -rw-r--r-- | nomnom/pretty_errors.nom | 85 | ||||
| -rw-r--r-- | nomnom/source.nom | 56 |
8 files changed, 0 insertions, 1270 deletions
diff --git a/nomnom/ast.nom b/nomnom/ast.nom deleted file mode 100644 index 935b0c5..0000000 --- a/nomnom/ast.nom +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -use "lib/object.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# The types are [..] - "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 " ") - if (%me.stub == "Lua Code 1 2"): - lua> "require('ldt').breakpoint()" - - (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] "\ - ..a_Syntax_Tree_with(\(call ({} 's metatable).as_lua with [%me]))" - my action [as nomsu] "\ - ..(a Syntax Tree with \(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 [with %overrides]: - %new = (%k = %v for %k = %v in %me) - for %k = %v in %overrides: %new.%k = %v - return (Syntax Tree %new) - - 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 - diff --git a/nomnom/code_obj.nom b/nomnom/code_obj.nom deleted file mode 100644 index 2c78ace..0000000 --- a/nomnom/code_obj.nom +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# This file contains objects that are used to track code positions and incrementally - build up generated code, while keeping track of where it came from, and managing - indentation levels. -use "lib/things.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -a (Code Buffer) is a thing: - that can (set up) by: - assume %its.source - %old_bits = (%its.bits if (%its.bits is a "List") else [%its.bits]) - %its.bits = [] - if (type of %its.source) is: - "Text": - %its.source = (Source from text %its.source) - "Syntax Tree": - %its.source = %its.source.source - - for % in %old_bits: %its::add % - - whose (text) means: - if (%its._text == (nil)): - %buff = [] - %indent = 0 - for %bit in %its.bits: - if (%bit is text): - %spaces = (%bit::matching "\n([ ]*)[^\n]*$") - if %spaces: %indent = (size of %spaces.1) - ..else: - %bit = (%bit::text) - if (%indent > 0): - %bit = (%bit::with "\n" -> "\n\(" "::* %indent)") - %buff::add %bit - %its._text = (%buff::joined) - return %its._text - - whose (lua code) means "\ - ..a_\(%its.class.name::as lua id)_with{source=\(..) - (%its.source::as lua) if %its.source else "nil" - .., \(%its.bits::as lua)}" - - whose (nomsu code) means "\ - ..(a \(%its.class.name) with {source: \((%its.source::as nomsu) if %its.source else "(nil)"), bits: \(..) - %its.bits::as nomsu - ..})" - - whose (size) means (size of (%its::text)) - - that can (mark as dirty) by: - %its._text = (nil) - %its._trailing_line_len = (nil) - %its._num_lines = (nil) - - that can (add %new_bits) by: - unless (%new_bits is a "List"): - %new_bits = [%new_bits] - for % in %new_bits: - if (% == ""): do next % - #if ((% isn't text) and (% isn't a (Code))): - % = (%::as lua) - %its.bits::add % - %its::mark as dirty - - whose (trailing line length) means: - if (%its._trailing_line_len == (nil)): - %its._trailing_line_len = (size of ((%its::text)::matching "[^\n]*$")) - return %its._trailing_line_len - - whose (number of lines) means: - unless %its._num_lines: - %num_lines = 1 - for % in %its: - if (% is text): - %num_lines += (size of (%::all matches of "\n")) - ..else: - %num_lines += ((%::number of lines) - 1) - - %its._num_lines = %num_lines - - return %its._num_lines - - whose [is multiline, is multi-line] all mean ((%its::number of lines) > 1) - whose [is one line, is single line] all mean ((%its::number of lines) == 1) - that can (add %values joined with %joiner) by: - %its::add %values joined with %joiner or %joiner - that can [add %values joined with %joiner or %wrapping_joiner] by: - %line_len = 0 - %bits = %its.bits - for %value in %values at %i: - if (%i > 1): - if (%line_len > 80): - %bits::add %wrapping_joiner - %line_len = 0 - ..else: %bits::add %joiner - - %bits::add %value - unless (%value is text): - %value = (%value::text) - %line = (%value::matching "\n([^\n]*)$") - if %line: - %line_len = (size of %line) - ..else: - %line_len += (size of %value) - %its::mark as dirty - - that can (prepend %) by: - #if ((% isn't text) and (% isn't a %its.__type)): - % = (%::as lua) - %its.bits::add % at index 1 - %its::mark as dirty - - that can (parenthesize) by: - %its.bits::add "(" at index 1 - %its.bits::add ")" - %its::mark as dirty - -a (Lua Buffer) is a thing: - that has [..] - text, lua code, nomsu code, trailing line length, size, number of lines, - is multiline, is multi-line, is one line, is single line, - ..like a (Code Buffer) - that can [..] - set up, mark as dirty, add %, prepend %, parenthesize, - add % joined with %, add % joined with % or %, - ..like a (Code Buffer) - - that can (add free vars %vars) by: - if ((size of %vars) == 0): return - %seen = (%v = (yes) for %v in %its.free_vars) - for %var in %vars: - assume (%var is text) - unless %seen.%var: - %its.free_vars::add %var - %seen.%var = (yes) - - %its::mark as dirty - - that can (remove free vars %vars) by: - if ((size of %vars) == 0): return - %removals = {} - for %var in %vars: - assume (%var is text) - %removals.%var = (yes) - - %stack = [%its] - repeat while ((size of %stack) > 0): - %lua = (%stack::pop) - for %i in (size of %lua.free_vars) to 1 by -1: - if %removals.(%lua.free_vars.%i): - %lua.free_vars::remove at index %i - - for % in %lua.bits: - unless (% is text): %stack::add % - - %its::mark as dirty - - that can (declare locals) by (%its::declare locals (nil)) - that can (declare locals %to_declare) by: - unless %to_declare: - %to_declare = [] - %seen = {} - for %lua in recursive %its: - for %var in %lua.free_vars: - unless %seen.%var: - %seen.%var = (yes) - %to_declare::add %var - - for % in %lua.bits: - unless (% is text): recurse %lua on % - - if ((size of %to_declare) > 0): - %its::remove free vars %to_declare - %its::prepend "local \(%to_declare::joined with ", ");\n" - return %to_declare - - whose (as statements) means (%its::as statements with "") - whose (as statements with %prefix) means: - unless %its.is_value: return %its - %statements = (a Lua Buffer with {source:%its.source}) - if ((%prefix or "") != ""): - %statements::add %prefix - %statements::add %its - %statements::add ";" - return %statements - - that can (mark as value) by: - %its.is_value = (yes) - - that can (mark as variable) by: - %its.is_variable = (yes) - %its.is_value = (yes) - - that can (variables) by: - %vars = [] - for %code in recursive %its: - if %code.is_variable: - %vars::add (%code::text) - for % in %code.bits: - unless (% is text): recurse %code on % - - return %vars - -a (Nomsu Buffer) is a thing: - that has [..] - text, lua code, nomsu code, trailing line length, size, number of lines, - is multiline, is multi-line, is one line, is single line, - ..like a (Code Buffer) - that can [..] - set up, mark as dirty, add %, prepend %, parenthesize, - add % joined with %, add % joined with % or %, - ..like a (Code Buffer) diff --git a/nomnom/compile.nom b/nomnom/compile.nom deleted file mode 100644 index ad38b69..0000000 --- a/nomnom/compile.nom +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# This file contains the code to convert syntax trees to Lua code -use "nomnom/code_obj.nom" -use "nomnom/parser.nom" -use "nomnom/pretty_errors.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -externally (report compile error at %tree %err) means: - barf (pretty "Compile Error" error at %tree %err) - -externally (report compile error at %pos %err hint %hint) means: - barf (pretty "Compile Error" error at %tree %err hint %hint) - -externally (barf any errors in %t) means: - assume (%t is a "Syntax Tree") - %errs = [] - for % in recursive %t: - if (%.type == "Error"): %errs::add % - for %k = %v in %: - if (%v is a "Syntax Tree"): recurse % on %v - - sort %errs by % -> %.source - %errs = ((% as a pretty error) for % in %errs) - if ((size of %errs) > 0): - if ((size of %errs) > 3): - %n = ((size of %errs) - 3) - for %i in 4 to (size of %errs): %errs.%i = (nil) - %errs::add "\027[31;1m +\%n additional errors...\027[0m\n" - barf (%errs::joined with "\n\n") - -externally (%tree compiled with %compile_actions) means: - assume (%tree is a "Syntax Tree") - if all of [..] - %tree.version, ((Nomsu version)'s meaning) != (nil), %tree.version != (Nomsu version) - ((1 upgraded from 2 to 3)'s meaning) != (nil) - ..then: - %tree = (upgrade %tree from %tree.version to (Nomsu version)) - - if %tree.type is: - "Action": - %stub = %tree.stub - %compile_action = %compile_actions.%stub - - # Don't apply compiler actions to methods - if (%compile_action and (not %tree.target)): - # TODO: restore this: - #%args = [%tree, %compile_actions] - %args = [%nomsu, %tree] - for % in (%tree::arguments): %args::add % - %result = (call %compile_action with %args) - if (%result == (nil)): - report compile error at %tree "\ - ..The compile-time action here (\(%tree.stub)) failed to return any value." - ..hint "\ - ..Look at the implementation of (\(%tree.stub)) and make sure it's returning something." - - if (%result is a "Syntax Tree"): - if (%result == %tree): - report compile error at %tree "\ - ..The compile-time action here (\(%tree.stub)) is producing an endless loop." - ..hint "\ - ..Look at the implementation of (\(%tree.stub)) and make sure it's not just returning the original tree." - - return (%result compiled with %compile_actions) - - return %result - - %lua = (a Lua Buffer with {source:%tree}) - if %tree.target: - # Method call - %target_lua = (%tree.target compiled with %compile_actions) - if (..) - ((%target_lua::text)::matches "^%(.*%)$") or (..) - (%target_lua::text)::matches "^[_a-zA-Z][_a-zA-Z0-9]*$" - ..: - %lua::add [%target_lua, ":"] - ..else: - %lua::add ["(", %target_lua, "):"] - - %lua::add [%stub as lua id, "("] - %args = [] - for %tok in %tree at %i: - if (%tok is text): do next %tok - - # TODO: maybe don't translate Lua comments - #if (%tok.type == "Comment"): do next %tok - if (%tok.type == "Block"): - %values = [] - for %line in %tok: - #unless (%line.type == "Comment"): - %values::add (%line compiled with %compile_actions) - - if all of (%.is_value for % in %values): - if ((size of %values) == 1): - %arg_lua = %values.1 - ..else: - %arg_lua = (a Lua Buffer with {source:%tok, is_value:yes, bits:["("]}) - %arg_lua::add %values joined with " and nil or " - %arg_lua::add ")" - ..else: - %arg_lua = (a Lua Buffer with {source:%tok, is_value:yes, bits:["((function()"]}) - for %v in %values at %i: - if %v.is_value: - %v = (%v::as statements with ("return " if (%i == (size of %values) else ""))) - %arg_lua::add ["\n ", %v] - - %arg_lua::add "\nend)())" - ..else: - %arg_lua = (%tok compiled with %compile_actions) - unless %arg_lua.is_value: - if (%tok.type == "Action"): - report compile error at %tok "\ - ..Can't use this as an argument to (\%stub), since it's not an expression, it produces: \%arg_lua" - ..hint "\ - ..Check the implementation of (\(%tok.stub)) to see if it is actually meant to produce an expression." - ..else: - report compile error at %tok "\ - ..Can't use this as an argument to (\%stub), since it's not an expression, it produces: \%arg_lua" - - assume (%arg_lua != %lua) or barf "Huh? \%tree .\%i = \%tok -> \%arg_lua" - %args::add %arg_lua - - %lua::add %args joined with ", " - %lua::add ")" - return %lua - - "EscapedNomsu": - %lua = (a Lua Buffer with {source:%tree, is_value:yes, bits:["a_Syntax_Tree_with{type=", quote %tree.(1).type]}) - set {%needs_comma:no, %i:1} - (% as shmua) means: - if (% is a "Lua number"): return "\%" - if (% is a "Syntax Tree"): - return (% compiled with %compile_actions) - if (% is text): return (quote %) - return (%::as lua) - - for %k = %v in (((%tree.(1).type == "EscapedNomsu") and %tree) or %tree.1): - %lua::add ", " - if: - (%k == %i): %i += 1 - ((%k is text) and (%k::is a lua identifier)): - %lua::add [%k, "= "] - else: - %lua::add ["[", % as shmua, "]= "] - - if (%k == "source"): - %lua::add (quote "\%v") - ..else: - %lua::add (%v as shmua) - - %lua::add "}" - return %lua - - "Block": - %lua = (a Lua Buffer with {source:%tree}) - %lua::add (..) - ((%line compiled with %compile_actions)::as statements) for %line in %tree - ..joined with "\n" - - return %lua - - "Text": - %lua = (a Lua Buffer with {source:%tree}) - %lua_bits = [] - %string_buffer = "" - for % in %tree: - if (% is text): - %string_buffer = "\%string_buffer\%" - do next % - - if (%string_buffer != ""): - %lua_bits::add (%string_buffer::as lua) - %string_buffer = "" - - %bit_lua = (% compiled with %compile_actions) - unless %bit_lua.is_value: - report compile error at % "\ - ..Can't use this as a string interpolation value, since it doesn't have a value." - - if (%.type != "Text"): - %bit_lua = (a Lua Buffer with {source:%, is_value:yes, bits:["tostring(", %bit_lua, ")"]}) - %lua_bits::add %bit_lua - - if ((%string_buffer != "") or ((size of %lua_bits) == 0)): - %lua_bits::add (%string_buffer::as lua) - %lua::add %lua_bits joined with ".." - if ((size of %lua_bits) > 1): %lua::parenthesize - return %lua - - "List": - %lua = (a Lua Buffer with {source:%tree, is_value:yes, bits:["List{"]}) - %lua::add ((% compiled with %compile_actions) for % in %tree) joined with ", " or ",\n " - %lua::add "}" - return %lua - - "Dict": - %lua = (a Lua Buffer with {source:%tree, is_value:yes, bits:["Dict{"]}) - %lua::add ((% compiled with %compile_actions) for % in %tree) joined with ", " or ",\n " - %lua::add "}" - return %lua - - "DictEntry": - set {%key:%tree.1, %value:%tree.2} - %key_lua = (%key compiled with %compile_actions) - unless %key_lua.is_value: - report compile error at %tree.1 "\ - ..Can't use this as a dict key, since it's not an expression." - - %value_lua = (..) - (%value compiled with %compile_actions) if %value else (..) - a Lua Buffer with {source:%key, is_value:yes, bits:["true"]} - - unless %value_lua.is_value: - report compile error at %tree.2 "\ - ..Can't use this as a dict value, since it's not an expression." - - %key_str = ((%key_lua::text)::matching "^[\"']([a-zA-Z_][a-zA-Z0-9_]*)['\"]$") - if: - %key_str: - return (a Lua Buffer with {source:%tree, bits:[%key_str, "=", %value_lua]}) - ((%key_lua::text).1 == "["): - # NOTE: this *must* use a space after the [ to avoid freaking out - Lua's parser if the inner expression is a long string. Lua - parses x[[[y]]] as x("[y]"), not as x["y"] - return (a Lua Buffer with {source:%tree, bits:["[ ", %key_lua, "]=", %value_lua]}) - - else: - return (a Lua Buffer with {source:%tree, bits:["[", %key_lua, "]=", %value_lua]}) - - "IndexChain": - %lua = (%tree.1 compiled with %compile_actions) - unless %lua.is_value: - report compile error at %tree.1 "\ - ..Can't index into this, since it's not an expression." - - %first_char = (%lua::text).1 - if (any of [%first_char == "{", %first_char == "\"", %first_char == "["]): - %lua::parenthesize - for %i in 2 to (size of %tree): - %key = %tree.%i - %key_lua = (%key compiled with %compile_actions) - unless %key_lua.is_value: - report compile error at %key "\ - ..Can't use this as an index, since it's not an expression." - - %key_lua_str = (%key_lua::text) - %lua_id = (%key_lua_str::matching "^['\"]([a-zA-Z_][a-zA-Z0-9_]*)['\"]$") - if: - %lua_id: - %lua::add [".", %lua_id] - (%key_lua_str.1 == "["): - # NOTE: this *must* use a space after the [ to avoid freaking out - Lua's parser if the inner expression is a long string. Lua - parses x[[[y]]] as x("[y]"), not as x["y"] - %lua::add ["[ ", %key_lua, " ]"] - - else: - %lua::add ["[", %key_lua, "]"] - - return %lua - - "Number": - return (a Lua Buffer with {source:%tree, is_value:yes, bits:["\(%tree.1)"]}) - "Var": - return (a Lua Buffer with {source:%tree, is_value:yes, is_variable:yes, bits:[%tree.1::as lua id]}) - "FileChunks": - barf "\ - ..Can't convert FileChunks to a single block of lua, since each chunk's compilation depends on the earlier chunks" - - "Comment": - # TODO: de-implement? - return (a Lua Buffer with {source:%tree, bits:["-- \(%tree.1::with "\n" -> "\n-- ")"]}) - - "Error": - barf (%tree as a pretty error) - else: - barf "Unknown type: \(%tree.type)" diff --git a/nomnom/decompile.nom b/nomnom/decompile.nom deleted file mode 100644 index c958280..0000000 --- a/nomnom/decompile.nom +++ /dev/null @@ -1,348 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# This file contains the code to convert syntax trees to Nomsu code -use "nomnom/code_obj.nom" -use "nomnom/parser.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# TODO: maybe re-implement the fancy coroutine checker that aborts early if nomsu gets too long -externally (%tree decompiled inline) means: - assume (%tree is a "Syntax Tree") - if %tree.type is: - "Action": - %nomsu = (a Nomsu Buffer with {source: %tree}) - if %tree.target: - %target_nomsu = (%tree.target decompiled inline) - if %tree.target.type is: - "Action" "Block": - %target_nomsu::parenthesize - - %nomsu::add [%target_nomsu, "::"] - - for %bit in %tree at %i: - if (%bit is text): - unless (..) - any of [..] - %i == 1, %tree.(%i - 1) isn't text, (%bit is a nomsu operator) == (%tree.(%i - 1) is a nomsu operator) - ..: %nomsu::add " " - - %nomsu::add %bit - ..else: - %arg_nomsu = (%bit decompiled inline) - unless ((%i == (size of %tree)) and (%bit.type == "Block")): - %nomsu::add " " - if ((%bit.type == "Action") or (%bit.type == "Block")): - %arg_nomsu::parenthesize - - %nomsu::add %arg_nomsu - - return %nomsu - - "EscapedNomsu": - %inner_nomsu = (%tree.1 decompiled inline) - unless (..) - any of [..] - %tree.(1).type == "List", %tree.(1).type == "Dict", %tree.(1).type == "Var" - ..: - %inner_nomsu::parenthesize - - %nomsu = (a Nomsu Buffer with {source: %tree, bits: ["\\", %inner_nomsu]}) - return %nomsu - - "Block": - %nomsu = (a Nomsu Buffer with {source: %tree, bits: [":"]}) - for %line in %tree at %i: - %nomsu::add [" " if (%i == 1) else "; ", %line decompiled inline] - return %nomsu - - "Text": - %nomsu = (a Nomsu Buffer with {source: %tree, bits: []}) - for %text in recursive %tree: - for %bit in %text at %i: - if (%bit is text): %nomsu::add %bit - ..else: - if %bit.type is: - "Text": - recurse %text on %bit - "Var": - %interp_nomsu = (%bit decompiled inline) - - # Make sure "...\(%x)y..." isn't confused with "...\(%xy)..." - # TODO: make this more robust against "...\%x\("y").." - if (..) - (%tree.(%i + 1) is text) and (..) - not (%tree.(%i + 1)::matches "^[ \n\t,.:;#(){}%[%]]") - ..: %interp_nomsu::parenthesize - %nomsu::add ["\\", %interp_nomsu] - - "List" "Dict": - %nomsu::add ["\\", %bit decompiled inline] - else: - %nomsu::add ["\\(", %bit decompiled inline, ")"] - - return (a Nomsu Buffer with {source: %tree, bits: ["\"", %nomsu, "\""]}) - - "List" "Dict": - %nomsu = (a Nomsu Buffer with {source: %tree, bits: ["[" if (%tree.type == "List") else "{"]}) - for %item in %tree at %i: - if (%i > 1): %nomsu::add ", " - %nomsu::add (%item decompiled inline) - - %nomsu::add ("]" if (%tree.type == "List") else "}") - return %nomsu - - "DictEntry": - set {%key:%tree.1, %value:%tree.2} - if (..) - all of [%key.type == "Text", (size of %key) == 1, %key.1 is a nomsu identifier] - ..: - %nomsu = (a Nomsu Buffer with {source: %key, bits: [%key.1]}) - ..else: - %nomsu = (%key decompiled inline) - - if (%key.type == "Action"): - %nomsu::parenthesize - if %value: - %nomsu::add ":" - %nomsu::add (%value decompiled inline) - - return %nomsu - - "IndexChain": - %nomsu = (a Nomsu Buffer with {source: %tree}) - for %bit in %tree at %i: - if (%i > 1): %nomsu::add "." - if (..) - all of [..] - %i > 1, %bit.type == "Text", (size of %bit) == 1, %bit.1 is text, %bit.1 is a nomsu identifier - ..: %nomsu::add %bit.1 - ..else: - %bit_nomsu = (%bit decompiled inline) - if (..) - any of [..] - %bit.type == "Action", %bit.type == "Block", %bit.type == "IndexChain" - (%bit.type == "Number") and (%i < (size of %tree)) - ..: - %bit_nomsu::parenthesize - - %nomsu::add %bit_nomsu - - return %nomsu - - "Number": - return (a Nomsu Buffer with {source: %tree, bits: [(%tree.1 as hex) if %tree.hex else "\(%tree.1)"]}) - "Var": - return (a Nomsu Buffer with {source: %tree, bits: ["%\(%tree.1)"]}) - "Comment": return (nil) - "FileChunks": - barf "Can't inline a FileChunks" - "Error": - barf "Can't compile errors" - else: - barf "Unknown type: \(%tree.type)" - -%MAX_LINE = 90 -externally (%tree decompiled) means: - %nomsu = (a Nomsu Buffer with {source: %tree}) - - # For concision: - (recurse on %t) means: - %space = (%MAX_LINE - (%nomsu::trailing line length)) - if (%space <= 0): - go to (Use Indented) - for %subtree in recursive %tree: - if %subtree.type is: - "Block": - if ((size of %subtree) > 1): - go to (Use Indented) - if ((size of "\(%subtree decompiled inline)") > 20): - go to (Use Indented) - - for %k = %v in %subtree: - if (%v is a "Syntax Tree"): - recurse %subtree on %v - - %inline_nomsu = (%t decompiled inline) - if (%inline_nomsu and ((size of "\%inline_nomsu") <= %space)): - return %inline_nomsu - === (Use Indented) === - %indented = (%t decompiled) - if (%t.type == "Action"): - %indented = (..) - a Nomsu Buffer with {source: %t, bits: ["(..)\n ", %indented]} - - return %indented - - if %tree.type is: - "FileChunks": - (%1 and %2 should clump) means: - if ((%1.type == "Action") and (%2.type == "Action")): - if (%1.stub == "use"): - return (%2.stub == "use") - if (%1.stub == "test"): return (yes) - if (%2.stub == "test"): return (no) - - return (not ((recurse on %1)::is multi-line)) - - for %chunk in %tree at %chunk_no: - if (%chunk_no > 1): - %nomsu::add "\n\n\("~"::* 80)\n\n" - if (%chunk.type == "Block"): - for %line in %chunk at %line_no: - if (%line_no > 1): - if (%chunk.(%line_no - 1) and %line should clump): %nomsu::add "\n" - ..else: %nomsu::add "\n\n" - - %nomsu::add (%line decompiled) - ..else: - %nomsu::add (%chunk decompiled) - - unless ("\%nomsu"::matches "\n$"): %nomsu::add "\n" - return %nomsu - - "Action": - %next_space = "" - if %tree.target: - %target_nomsu = (recurse on %tree.target) - if ((%tree.target.type == "Action") and (%target_nomsu::is one line)): - %target_nomsu::parenthesize - %nomsu::add %target_nomsu - %next_space = ("\n..::" if (%target_nomsu::is multi-line) else "::") - - for %bit in %tree at %i: - if ((%next_space == " ") and ((%nomsu::trailing line length) > %MAX_LINE)): - %next_space = " \\\n" - - %nomsu::add %next_space - if (%bit is text): - unless (..) - all of [..] - %tree.(%i - 1) is text, (%tree.(%i - 1) is a nomsu operator) != (%bit is a nomsu operator) - ..: - %nomsu::add %next_space - - %nomsu::add %bit - %next_space = " " - do next %bit - - %bit_nomsu = (recurse on %bit) - if (%bit.type == "Comment"): %next_space = "\n" - ..else: - %next_space = (" " if (%bit_nomsu::is one line) else "\n..") - if (%bit.type == "Action"): - %bit_nomsu::parenthesize - - return %nomsu - - "EscapedNomsu": - %nomsu::add "\\" - %val_nomsu = (recurse on %tree.1) - if ((%tree.(1).type == "Action") and (%val_nomsu::is one line)): - %val_nomsu::parenthesize - %nomsu::add %val_nomsu - return %nomsu - - "Block": - for %line in %tree at %i: - if ((%i > 1) and (%line.type == "Comment")): %nomsu::add "\n" - %line_nomsu = (recurse on %line) - %nomsu::add - if (%i < (size of %tree)): - if ((%line_nomsu::number of lines) > 2): %nomsu::add "\n\n" - ..else: %nomsu::add "\n" - - return (..) - a Nomsu Buffer with {source: %tree, bits: [":\n ", %nomsu]} - - "Text": - # Multi-line text has more generous wrap margins - %max_line = ((1.5 * %MAX_LINE) rounded down) - %nomsu = (a Nomsu Buffer with {source: %tree}) - (add text from %tree) means: - for %bit in %tree at %i: - if (%bit is text): - # TODO: escape properly? - %bit = (escape text %bit) - for %line in (%bit::lines) at %j: - if: - (%j > 1): %nomsu::add "\n" - (((size of %line) > 10) and ((%nomsu::trailing line length) > %max_line)): - %nomsu::add "\\\n.." - - repeat while ((size of %line) > 0): - %space = (%max_line - (%nomsu::trailing line length)) - %split = (%line::position of "[%p%s]" after %space) - if ((not %split) or (%split > %space + 10)): - %split = (%space + 10) - if ((%line - %split) < 10): - %split = (size of %line) - set {%bite:%line.[1, %split], %line:%line.[%split + 1, -1]} - %nomsu::add %bite - if ((size of %line) > 0): - %nomsu::add "\\\n.." - if (%bit.type == "Text"): - add text from %bit - ..else: - %nomsu::add "\\" - %interp_nomsu = (recurse on %bit) - unless (%interp_nomsu::is multi-line): - if %bit.type is: - "Var": - if ((%tree.(%i+1) is text) and (not (%tree.(%i+1)::matches "^[ \n\t,.:#(){}[%]]"))): - %interp_nomsu::parenthesize - "List" "Dict": - do nothing - else: - %interp_nomsu::parenthesize - - %nomsu::add %interp_nomsu - if (%interp_nomsu::is multi-line): %nomsu::add "\n.." - - add text from %tree - return (..) - a Nomsu Buffer with {source: %tree, bits: ["\"\\\n ..", %nomsu, "\""]} - - "List" "Dict": - if ((size of %tree) == 0): - %nomsu::add ("[]" if (%tree.type == "List") else "{}") - return %nomsu - - for %item in %tree at %i: - %item_nomsu = (%item decompiled inline) - if ((not %item_nomsu) or ((size of "\%item_nomsu") > %MAX_LINE)): - %item_nomsu = (recurse on %item_nomsu) - %nomsu::add %item_nomsu - if (%i < (size of %tree)): - if any of [..] - %item_nomsu::is multi-line, ((%nomsu::trailing line length) + (size of "\%item_nomsu")) >= %MAX_LINE - ..: %nomsu::add "\n" - ..else: %nomsu::add ", " - - return (..) - a Nomsu Buffer with {..} - source: %tree, bits: [..] - "[..]\n " if (%tree.type == "List") else "{..}\n ", %nomsu - - "DictEntry": - set {%key:%tree.1, %value:%tree.2} - if (..) - all of [%key.type == "Text", (size of %key) == 1, %key.1 is a nomsu identifier] - ..: %nomsu::add %key.1 - ..else: - %nomsu::add (%key decompiled inline) - - if ((%key.type == "Action") or (%key.type == "Block")): - %nomsu::parenthesize - %nomsu::add [": ", recurse on %value] - return %nomsu - - "Comment": - %nomsu::add ["#", %tree.1::with "\n" -> "\n "] - return %nomsu - - "IndexChain" "Number" "Var": - return (%tree decompiled inline) - "Error": - barf "Cannot decompile an error" - else: - barf "Unknown type: \(%tree.type)" diff --git a/nomnom/files.nom b/nomnom/files.nom deleted file mode 100644 index 61119c0..0000000 --- a/nomnom/files.nom +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# Some file utilities for searching for files recursively and using package.nomsupath -use "lib/os.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -%_SPOOFED_FILES = {} -%_FILE_CACHE = ({} with fallback % -> %_SPOOFED_FILES.%) -%_BROWSE_CACHE = {} - -# Create a fake file and put it in the cache -externally (spoof file %filename %contents) means: - %_SPOOFED_FILES.%filename = %contents - return %contents - -# Read a file's contents -externally (read file %filename) means: - %contents = %_FILE_CACHE.%filename - if %contents: return %contents - if (%filename == "stdin"): - return (spoof file "stdin" (=lua "io.read('*a')")) - %file = (=lua "io.open(\%filename)") - unless %file: return (nil) - %contents = (call %file.read with [%file, "*a"]) - %file::close - %_FILE_CACHE.%filename = %contents - return %contents - -externally (%path sanitized) means: - %path = (%path::with "\\" -> "\\\\") - %path = (%path::with "`" -> "") - %path = (%path::with "\"" -> "\\\"") - %path = (%path::with "$" -> "") - %path = (%path::with "%.%." -> "\\..") - return %path - -try: - %lfs = (=lua "require('lfs')") -..and if it succeeds: - (filesystem has %filename) means: - %mode = (call %lfs.attributes with [%filename, "mode"]) - if %mode is: - "file" "directory" "link" "char device": return (yes) - else: return (no) - - externally (file %path exists) means: - if (any of [%_SPOOFED_FILES.%path, %path == "stdin", filesystem has %path]): - return (yes) - for %nomsupath in (%package.nomsupath::all matches of "[^;]+"): - if (filesystem has "\(%nomsupath)/\%path"): return (yes) - return (no) - - externally (files in %path) means: - unless %_BROWSE_CACHE.%path: - if (%_SPOOFED_FILES.%path or (%filename == "stdin")): - %_BROWSE_CACHE.%path = [%path] - ..else: - if (call %lfs.attributes with [%filename, "mode"]) is: - "file" "char device": - %_BROWSE_CACHE.%path = [%filename] - "directory" "link": - for %nomsupath in (%package.nomsupath::all matches of "[^;]+"): - %files = [] - for %member in (call %lfs.dir with ["\(%nomsupath)/\%filename"]): - if ((%member == ".") or (%member == "..")): do next %member - for % in (files in %member): %files::add % - - if ((size of %files) > 0): - %_BROWSE_CACHE.%path = %files - go to (Found Files) - - %_BROWSE_CACHE.%path = [] - - else: - %_BROWSE_CACHE.%path = [] - - === (Found Files) === - return %_BROWSE_CACHE.%filename -..or if it barfs: - # LFS not found! Fall back to shell commands, if available. - unless (sh> "find . -maxdepth 0"): - barf "\ - ..Could not find 'luafilesystem' module and couldn't run system command 'find' (this might happen on Windows). Please install \ - ..'luafilesystem' (which can be found at \(..) - "https://github.com/spacewander/luafilesystem" if %jit else "\ - ..https://github.com/keplerproject/luafilesystem" - .. or obtained through `luarocks install luafilesystem`)" - - externally (file %path exists) means: - if (any of [%_SPOOFED_FILES.%path, %path == "stdin", sh> "ls \(%path sanitized)"]) \ - ..: return (yes) - for %nomsupath in (%package.nomsupath::all matches of "[^;]+"): - if (sh> "ls \(%nomsupath)/\%path"): return (yes) - return (no) - - externally (files in %path) means: - unless %_BROWSE_CACHE.%path: - if %_SPOOFED_FILES.%path: - %_BROWSE_CACHE.%path = [%_SPOOFED_FILES.%path] - ..else: - for %nomsupath in (%package.nomsupath::all matches of "[^;]+"): - %files = (sh> "find -L '\(%path)' -not -path '*/\\.*' -type f'") - if %files: - %_BROWSE_CACHE.%path = (%files::lines) - go to (Found Files) - - %_BROWSE_CACHE.%path = [] - - === (Found Files) === - return %_BROWSE_CACHE.%path diff --git a/nomnom/parser.nom b/nomnom/parser.nom deleted file mode 100644 index fe237e8..0000000 --- a/nomnom/parser.nom +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# This file contains the parser, which converts text into abstract syntax trees -#use "nomonom/ast.nom" -%lpeg = (=lua "require('lpeg')") -%re = (=lua "require('re')") -call %lpeg.setmaxstack with [20000] -set {..} - ((P 1)'s meaning):%lpeg.P, ((R 1)'s meaning):%lpeg.R - ((Carg 1)'s meaning):%lpeg.Carg, ((S 1)'s meaning):%lpeg.S - ((Cc 1)'s meaning):%lpeg.Cc, ((lpeg re pattern 1)'s meaning):%re.compile - ((lpeg re pattern 1 using 2)'s meaning):%re.compile - ((lpeg pattern 1's match of 2)'s meaning):%lpeg.match - ((lpeg pattern 1's match of 2 with 3)'s meaning): (..) - [%1, %2, %3] -> (call %lpeg.match with [%1, %2, nil, %3]) - -%source_code_for_tree = {} -%defs = (..) - {..} - nl: (P "\r")^(-1) * (P "\n") - tab: P "\t" - tonumber: %tonumber - tochar: %string.char - unpack: %unpack - nil: Cc (nil) - userdata: Carg 1 - utf8_char: (..) - (R "\194\223")*(R "\128\191") + - ..(R "\224\239")*(R "\128\191")*(R "\128\191") + - ..(R "\240\244")*(R "\128\191")*(R "\128\191")*(R "\128\191") - - Tree: [%t, %userdata] ->: - %source = (..) - Source {filename:%userdata.filename, start:%t.start, stop:%t.stop} - set {%t.start: nil, %t.stop: nil, %t.source: %source} - %t = (a Syntax Tree with %t) - (Syntax Tree).source_code_for_tree.%t = %userdata.source - return %t - ..with fallback %key ->: - if: - (%key::matches "^ascii_(%d+)$"): - %i = (%key::matching "^ascii_(%d+)$") - return (call %string.char with [%i as a number]) - - (%key::matches "^number_(%d+)$"): - %i = (%key::matching "^number_(%d+)$") - return (Cc (%i as a number)) - -%id_patt = (..) - ((P "") - (R "09")) * (..) - (%defs.utf8_char + (R "az") + (R "AZ") + (P "_") + (R "09")) ^ 1 * -1 - -%operator_patt = ((S "'`~!@$^&*+=|<>?/-") ^ 1 * -1) -externally [%text is a nomsu id, %text is a nomsu identifier] all mean (..) - lpeg pattern %id_patt's match of %text - -externally (%text is a nomsu operator) means (..) - lpeg pattern %operator_patt's match of %text - -%peg_tidier = (..) - lpeg re pattern "\ - ..file <- %nl* {~ (def/comment) (%nl+ (def/comment))* %nl* ~} - def <- anon_def / captured_def - anon_def <- - ({ident} (" "*) ":" {[^%nl]* (%nl+ " "+ [^%nl]*)*}) - -> "%1 <- %2" - captured_def <- - ({ident} (" "*) "(" {ident} ")" (" "*) ":" {[^%nl]* (%nl+ " "+ [^%nl]*)*}) - -> "%1 <- ({| {:start:{}:} %3 {:stop:{}:} {:type: (''->'%2') :} |} %%userdata) -> Tree" - ident <- [a-zA-Z_][a-zA-Z0-9_]* - comment <- "--" [^%nl]* - " - -externally (make parser from %peg) means (make parser from %peg using (nil)) -externally (make parser from %peg using %make_tree) means: - %peg = (lpeg pattern %peg_tidier's match of %peg) - %peg = (lpeg re pattern %peg using %defs) - (%input from %filename parsed) means: - %input = "\%input" - %tree_mt = {__index:{source:%input, filename:%filename}} - %userdata = {..} - make_tree:%make_tree or ([%] -> (: set %'s metatable to %tree_mt; return %)) - filename:%filename, source:%input - - %tree = (lpeg pattern %peg's match of %input with %userdata) - assume %tree or barf "\ - ..File \%filename failed to parse: - \%input" - - return %tree - - return ((1 from 2 parsed)'s meaning) diff --git a/nomnom/pretty_errors.nom b/nomnom/pretty_errors.nom deleted file mode 100644 index db4be5a..0000000 --- a/nomnom/pretty_errors.nom +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -# This file has code for converting errors to user-friendly format, with colors, - line numbers, code excerpts, and so on. -(visible size of %text) means: - return (size of (%text::with "\027%[[0-9;]*m" -> "")) - -(%text boxed) means: - %max_line = (max of ((visible size of %line) for %line in (%text::lines))) - %ret = (..) - "\n\%text"::with "\n([^\n]*)" -> (..) - [%] -> (..) - "\n\%\(" "::* (%max_line - (visible size of %))) \027[0m" - return %ret.[2,-1] - -%CONTEXT = 2 -externally (pretty %title error at %tree %err hint %hint) means: - %source_code = (%tree::get source code) - %start = %tree.source.start - %stop = %tree.source.stop - %filename = (%tree.source.filename or "???") - %err_line = (%source_code::line at %start) - %err_linenum = (%source_code::line number at %start) - %err_linepos = (%source_code::line position at %start) - - # TODO: better handle multi-line errors - %err_size = (min of [%stop - %start, (size of %err_line) - %err_linepos + 1]) - %nl_indicator = (" " if (%err_linepos > (size of %err_line)) else "") - %fmt_str = " %\(size of "\(%err_linenum + %CONTEXT)")d|" - (num %i) means (%fmt_str::formatted with %i) - %linenum_size = (size of (num 0)) - %pointer = "\(" "::* (%err_linepos + %linenum_size - 1))" - if (%err_size >= 2): - %pointer += "╚\("═"::* (%err_size - 2))╝" - ..else: %pointer += "⬆" - - %err_msg = "\ - ..\027[33;41;1m\(%title or "Error") at \%filename:\%err_linenum\027[0m" - for %i in (%err_linenum - %CONTEXT) to (%err_linenum - 1): - %line = (%source_code::line %i) - if %line: - %err_msg += "\n\027[2m\(num %i)\027[0m\(%line)\027[0m" - - if %err_line: - %before = %err_line.[1, %err_linepos - 1] - %during = %err_line.[%err_linepos, %err_linepos + %err_size - 1] - %after = %err_line.[%err_linepos + %err_size, -1] - %err_line = "\027[0m\(%before)\027[41;30m\%during\(%nl_indicator)\027[0m\%after" - %err_msg += "\n\027[2m\(num %err_linenum)\(%err_line)\027[0m" - - %err_linenum_end = (%source_code::line number at %stop) - %err_linepos_end = (%source_code::line position at %stop) - %err_linenum_end or= %err_linenum - if (%err_linenum_end == %err_linenum): - %err_msg += "\n\%pointer" - ..else: - for %i in (%err_linenum + 1) to %err_linenum_end: - %line = (%source_code::line %i) - if %line: - if (%i == %err_linenum_end): - %during = %line.[1, %err_linepos_end - 1] - %after = %line.[%err_linepos_end, -1] - %err_msg += "\n\027[2m\(num %i)\027[0;41;30m\(%during)\027[0m\%after" - ..else: - %err_msg += "\n\027[2m\(num %i)\027[0;41;30m\(%line)\027[0m" - - %box_width = 70 - %err_text = "\ - ..\027[47;31;1m\((" \%err"::wrapped to %box_width)::with "\n" -> "\n\027[47;31;1m ")" - if %hint: - %err_text += "\n\027[47;30m\((" Suggestion: \(%hint)"::wrapped to %box_width)::with "\n" -> "\n\027[47;30m ")" - %err_msg += "\n\027[33;1m \((%err_text boxed)::with "\n" -> "\n ")" - - %err_msg += "\n\027[33;1m \((%err_text boxed)::with "\n" -> "\n ")" - for %i in (%err_linenum_end + 1) to (%err_linenum_end + %CONTEXT): - %line = (%source_code::line %i) - if %line: - %err_msg += "\n\027[2m\(num %i)\027[0m\(%line)\027[0m" - - return %err_msg - -externally (pretty %title error at %tree %err) means (..) - pretty %title error at %tree %err (nil) - -externally (%err_tree as a pretty error) means (..) - pretty %err_tree.title error at %err_tree %err_tree.error hint %err_tree.hint diff --git a/nomnom/source.nom b/nomnom/source.nom deleted file mode 100644 index bff8d8d..0000000 --- a/nomnom/source.nom +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env nomsu -V4.8.10 -use "lib/object.nom" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -object (Source): - externally (Source from text %text) means: - %match = (%text::matching groups "^@(.-)%[(%d+):(%d+)%]$") - set {%filename:%match.1, %start:%match.2, %stop:%match.3} - unless %filename: - %match = (%text::matching groups "^@(.-)%[(%d+)%]$") - set {%filename:%match.1, %start:%match.2} - - return (..) - Source {filename:%filename, start:(%start or 1) as number, stop:%stop as number} - - my action [as text] "\ - ..@\(%me.filename)[\(%me.start)\(":\(%me.stop)" if %me.stop else "")]" - my action [as lua] "\ - ..Source{filename=\(%me.filename::as lua), start=\(%me.start)\(..) - ", stop=\(%me.stop)" if %stop else "" - ..}" - - my action [as nomsu] "\ - ..(Source {filename:\(%me.filename::as nomsu), start:\(%me.start)\(..) - ", stop:\(%me.stop)" if %stop else "" - ..})" - - my action [== %other] (..) - all of [..] - (%me's metatable) == (%other's metatable) - %me.filename == %other.filename - %me.start == %other.start - %me.stop == %other.stop - - my action [< %other]: - assume %me.filename == %other.filename - if (%start == %other.start): - return ((%me.stop or %me.start) < (%other.stop or %other.start)) - ..else: - return (%me.start < %other.start) - - my action [<= %other]: - assume %me.filename == %other.filename - if (%start == %other.start): - return ((%me.stop or %me.start) <= (%other.stop or %other.start)) - ..else: - return (%me.start <= %other.start) - - my action [+ %offset]: - if ((type of %me) == "number"): - set {%me:%offset, %offset:%me} - ..else: - assume (type of %offset) == "number" - - return (Source {filename:%me.filename, start:%me.start + %offset, stop:%me.stop}) |
