diff --git a/compatibility/2.3.nom b/compatibility/2.3.nom index fb137b8..7de353e 100644 --- a/compatibility/2.3.nom +++ b/compatibility/2.3.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <2.3 to Nomsu 2.3 diff --git a/compatibility/2.4.nom b/compatibility/2.4.nom index b770840..1a7c9c3 100644 --- a/compatibility/2.4.nom +++ b/compatibility/2.4.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <2.4 to Nomsu 2.4 diff --git a/compatibility/2.5.5.5.nom b/compatibility/2.5.5.5.nom index a3f8b27..efed78d 100644 --- a/compatibility/2.5.5.5.nom +++ b/compatibility/2.5.5.5.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <2.5.5.5 to Nomsu 2.5.5.5 diff --git a/compatibility/2.5.nom b/compatibility/2.5.nom index fe17dfb..b1e01b0 100644 --- a/compatibility/2.5.nom +++ b/compatibility/2.5.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <2.5 to Nomsu 2.5 diff --git a/compatibility/2.nom b/compatibility/2.nom index 2364f56..d7a1489 100644 --- a/compatibility/2.nom +++ b/compatibility/2.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu 1 to Nomsu 2 diff --git a/compatibility/3.5.5.6.nom b/compatibility/3.5.5.6.nom index 068e65d..89fbc8a 100644 --- a/compatibility/3.5.5.6.nom +++ b/compatibility/3.5.5.6.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <3.5.5.6 to Nomsu 3.5.5.6 diff --git a/compatibility/3.6.nom b/compatibility/3.6.nom index eec97eb..7cd5c64 100644 --- a/compatibility/3.6.nom +++ b/compatibility/3.6.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <3.6 to 3.6 diff --git a/compatibility/3.7.nom b/compatibility/3.7.nom index 5b458de..599e0d5 100644 --- a/compatibility/3.7.nom +++ b/compatibility/3.7.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <3.7 to 3.7 diff --git a/compatibility/3.8.nom b/compatibility/3.8.nom index 9538770..0709688 100644 --- a/compatibility/3.8.nom +++ b/compatibility/3.8.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <3.8 to 3.8 (Text method changes) diff --git a/compatibility/3.nom b/compatibility/3.nom index 36df17d..5156aa8 100644 --- a/compatibility/3.nom +++ b/compatibility/3.nom @@ -1,4 +1,4 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # This file defines upgrades from Nomsu <=2 to Nomsu 3 diff --git a/compatibility/4.8.10.nom b/compatibility/4.8.10.nom index 58fd376..d20448e 100644 --- a/compatibility/4.8.10.nom +++ b/compatibility/4.8.10.nom @@ -56,4 +56,4 @@ upgrade action "parse 1 as 2" to "4.8.10" via (..) return \(%spec parse as %body) upgrade action (compile as %) to "4.8.10" as (what % compiles to) - +upgrade action (action %) to "4.8.10" as (%'s meaning) diff --git a/compatibility/compatibility.nom b/compatibility/compatibility.nom index 6da7063..c61b5a9 100644 --- a/compatibility/compatibility.nom +++ b/compatibility/compatibility.nom @@ -80,16 +80,15 @@ externally [..] %tree with % -> (..) if ((% is "Action" syntax tree) and %ACTION_UPGRADES.%ver.(%.stub)): %with_upgraded_args = (..) - %k = (%v upgraded from %start_version to %end_version) \ - ..for %k = %v in % - set %with_upgraded_args's metatable to (%'s metatable) - return (call %ACTION_UPGRADES.%ver.(%.stub) with [%with_upgraded_args, %end_version]) + %k = (%v upgraded from %start_version to %end_version) for %k = %v in % + set %with_upgraded_args 's metatable to (% 's metatable) + return (..) + call %ACTION_UPGRADES.%ver.(%.stub) with [%with_upgraded_args, %end_version] if %UPGRADES.%ver: %with_upgraded_args = (..) - %k = (%v upgraded from %start_version to %end_version) \ - ..for %k = %v in %tree - set %with_upgraded_args's metatable to (%tree's metatable) + %k = (%v upgraded from %start_version to %end_version) for %k = %v in %tree + set %with_upgraded_args 's metatable to (%tree 's metatable) %tree = (call %UPGRADES.%ver with [%with_upgraded_args, %end_version]) return %tree diff --git a/core/control_flow.nom b/core/control_flow.nom index 2b53ce7..0cabf95 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -406,7 +406,7 @@ test: ..hint "If you want the code in this block to always execute, you don't \ ..need a conditional block around it. Otherwise, make sure the 'else' \ ..block comes last." - + %code::append "\nelse\n " %code::append (%action as lua statements) %else_allowed = (no) diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index a2f15a1..c999191 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -102,7 +102,7 @@ lua> "\ test: (foo %x) means (return "outer") - with local [action (foo %)]: + with local [(foo %)'s meaning]: (foo %x) means: %y = (%x + 1) return %y @@ -151,8 +151,8 @@ test: return lua" test: - assume ((action (say %)) == (=lua "say_1")) -(action %action) compiles to (Lua value (%action.stub as lua id)) + assume (((say %)'s meaning) == (=lua "say_1")) +(%action's meaning) compiles to (Lua value (%action.stub as lua id)) test: (swap %x and %y) parses as (..) diff --git a/core/scopes.nom b/core/scopes.nom index 715409c..2d86ca4 100644 --- a/core/scopes.nom +++ b/core/scopes.nom @@ -15,7 +15,7 @@ test: assume (%x == "outer") externally (foo) means "outer foo" - with local [action (foo)]: + with local [(foo)'s meaning]: externally (foo) means "inner foo" assume ((foo) == "inner foo") diff --git a/examples/how_do_i.nom b/examples/how_do_i.nom index e8e838b..ec75596 100644 --- a/examples/how_do_i.nom +++ b/examples/how_do_i.nom @@ -247,7 +247,7 @@ say both (my favorite number) and also "foo" # Macros: # The "lua> %" and "=lua %" macros can be used to write raw lua code: -(say the time) means (..) +(say the time) means: lua> "io.write(\"The OS time is: \", os.time(), \"\\n\");" say the time diff --git a/nomnom/ast.nom b/nomnom/ast.nom index 816554c..4d261aa 100644 --- a/nomnom/ast.nom +++ b/nomnom/ast.nom @@ -1,9 +1,9 @@ +#!/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"): @@ -11,38 +11,33 @@ object (Syntax Tree): %argnum = 1 for %bit in %me: if: - (%bit is text): %stub_bits::add %bit + (%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 ((% 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] (..) - "Syntax_Tree(\(call ({}'s metatable).as_lua with [%me]))" - - my action [as nomsu] (..) - "(Syntax Tree \(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 [as lua] "\ + ..a_Syntax_Tree_with_1(\(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: @@ -58,25 +53,23 @@ object (Syntax Tree): %replacement.%k = %v if (%v is a "Syntax Tree"): %r = (%v::map %fn) - if ((%r == %v) or (%r == (nil))): - do next %k + 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 + (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: @@ -86,11 +79,11 @@ object (Syntax Tree): return (yes) my action [get args]: - assume (%me.type == "Action") or barf "Only actions have arguments, not \(%me.type)" + 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 % + unless ((% is text) or (%.type == "Comment")): %args::add % return %args (Syntax Tree).map = (Syntax Tree).map_1 diff --git a/nomnom/code_obj.nom b/nomnom/code_obj.nom index 363713c..8379f36 100644 --- a/nomnom/code_obj.nom +++ b/nomnom/code_obj.nom @@ -1,25 +1,19 @@ +#!/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/object.nom" object (Hole): - action [Hole from %lua]: + externally (Hole from %lua) means: return (Hole {lua:%lua}) - - my action [as lua]: - return %me.lua - + my action [as lua]: return %me.lua my action [as nomsu]: return "(Hole {lua:\(%me.lua)})" - my action [as text]: barf "Not implemented" - my action [as smext]: barf "Must fill in holes before smexting" - object (Code): my action [set up]: @@ -28,12 +22,10 @@ object (Code): %me.bits = [] if (%me.source is text): %me.source = (Source from text %me.source) - for % in %old_bits: - %me::add % - + for % in %old_bits: %me::add % + my action [as text]: barf "Not implemented" - my action [as smext]: if (%me.__str == (nil)): set {%buff:[], %indent:0} @@ -45,32 +37,41 @@ object (Code): %bit = (%bit::as smext) if (%indent > 0): %bit = (%bit::with "\n" -> "\n\(" "::* %indent)") + %buff::add %bit + %me.__str = (%buff::joined) + return %me.__str - + my action [as lua]: barf - return "\(%me.class.name::as lua id)_from_1_2(\((%me.source::as lua) if %me.source else "nil"), \(%me.bits::as lua))" - - my action [as nomsu] (..) - "(\(%me.class.name) \((%me.source::as nomsu) if %me.source else "(nil)") \(%me.bits::as nomsu))" - - my action [size] (size of (%me::as smext)) + return "\ + ..\(%me.class.name::as lua id)_from_1_2(\(..) + (%me.source::as lua) if %me.source else "nil" + .., \(%me.bits::as lua))" + my action [as nomsu] "\ + ..(\(%me.class.name) \((%me.source::as nomsu) if %me.source else "(nil)") \(..) + %me.bits::as nomsu + ..)" + + my action [size] (size of (%me::as smext)) my action [mark as dirty]: %me.__str = (nil) %me._trailing_line_len = (nil) %me._num_lines = (nil) - + my action [add %new_bits]: 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) %me.bits::add % + %me::mark as dirty my action [trailing line length]: @@ -86,15 +87,15 @@ object (Code): %num_lines += (size of (%::all matches of "\n")) ..else: %num_lines += ((%::number of lines) - 1) + %me._num_lines = %num_lines + return %me._num_lines - + my action [is multiline, is multi-line] ((%me::number of lines) > 1) my action [is one line, is single line] ((%me::number of lines) == 1) - my action [add %values joined with %joiner]: %me::add %values joined with %joiner or %joiner - my action [add %values joined with %joiner or %wrapping_joiner]: %line_len = 0 %bits = %me.bits @@ -103,8 +104,8 @@ object (Code): if (%line_len > 80): %bits::add %wrapping_joiner %line_len = 0 - ..else: - %bits::add %joiner + ..else: %bits::add %joiner + %bits::add %value unless (%value is text): %value = (%value::as smext) @@ -113,6 +114,7 @@ object (Code): %line_len = (size of %line) ..else: %line_len += (size of %value) + %me::mark as dirty my action [prepend %]: @@ -120,13 +122,12 @@ object (Code): % = (%::as lua) %me.bits::add % at index 1 %me::mark as dirty - + my action [parenthesize]: %me.bits::add "(" at index 1 %me.bits::add ")" %me::mark as dirty - object (Lua Code) extends (Code): my action [add free vars %vars]: if ((size of %vars) == 0): return @@ -136,6 +137,7 @@ object (Lua Code) extends (Code): unless %seen.%var: %me.free_vars::add %var %seen.%var = (yes) + %me::mark as dirty my action [remove free vars %vars]: @@ -153,11 +155,13 @@ object (Lua Code) extends (Code): lua> "table.remove(\%lua.free_vars, \%i)" #TODO: reinstate this #%lua.free_vars::remove at index %i + + for % in %lua.bits: - unless (% is text): - %stack::add % + unless (% is text): %stack::add % + %me::mark as dirty - + my action [declare locals] (%me::declare locals (nil)) my action [declare locals %to_declare]: unless %to_declare: @@ -167,19 +171,19 @@ object (Lua Code) extends (Code): unless %seen.%var: %seen.%var = (yes) %to_declare::add %var + for % in %lua.bits: - unless (% is text): - recurse %lua on % + unless (% is text): recurse %lua on % + if ((size of %to_declare) > 0): %me::remove free vars %to_declare %me::prepend "local \(%to_declare::joined with ", ");\n" return %to_declare - + my action [as statements] (%me::as statements "" ";") my action [as statements %prefix] (%me::as statements %prefix ";") my action [as statements %prefix %suffix]: - unless %me.is_value: - return %me + unless %me.is_value: return %me %statements = (Lua Code from %me.source []) if ((%prefix or "") != ""): %statements::add %prefix @@ -194,46 +198,48 @@ object (Lua Code) extends (Code): if %code.is_variable: %vars::add (%code::as smext) for % in %code.bits: - unless (% is text): - recurse %code on % + unless (% is text): recurse %code on % + return %vars - - action [Lua Code from %source %bits]: + + externally (Lua Code from %source %bits) means: assume %source unless (%bits is a "List"): %bits = [%bits] - if (%source is a "Syntax Tree"): %source = %source.source - return (..) - Lua Code {source:%source, bits:%bits, is_value: no, free_vars:[]} - action [Lua Code from %source] (Lua Code from %source []) - - action [Lua Value from %source %bits]: + if (%source is a "Syntax Tree"): + %source = %source.source + return (Lua Code {source:%source, bits:%bits, is_value:no, free_vars:[]}) + + externally (Lua Code from %source) means (Lua Code from %source []) + externally (Lua Value from %source %bits) means: assume %source unless (%bits is a "List"): %bits = [%bits] - if (%source is a "Syntax Tree"): %source = %source.source - return (..) - Lua Code {source:%source, bits:%bits, is_value: yes, free_vars:[]} - action [Lua Value from %source] (Lua Value from %source []) - - action [Lua Variable from %source] (Lua Variable from %source []) - action [Lua Variable from %source %bits]: + if (%source is a "Syntax Tree"): + %source = %source.source + return (Lua Code {source:%source, bits:%bits, is_value:yes, free_vars:[]}) + + externally (Lua Value from %source) means (Lua Value from %source []) + externally (Lua Variable from %source) means (Lua Variable from %source []) + externally (Lua Variable from %source %bits) means: assume %source unless (%bits is a "List"): %bits = [%bits] - if (%source is a "Syntax Tree"): %source = %source.source + if (%source is a "Syntax Tree"): + %source = %source.source return (..) - Lua Code {source:%source, bits:%bits, is_value: yes, is_variable: yes, free_vars:[]} + Lua Code {..} + source:%source, bits:%bits, is_value:yes, is_variable:yes, free_vars:[] # TODO: remove this shim (Lua Code).add_free_vars = (Lua Code).add_free_vars_1 (Lua Code).remove_free_vars = (Lua Code).remove_free_vars_1 (Lua Code).declare_locals = (Lua Code).declare_locals_1 (Lua Code).as_statements = (Lua Code).as_statements_1_2 - object (Nomsu Code) extends (Code): - action [Nomsu Code from %source %bits]: + externally (Nomsu Code from %source %bits) means: if (%bits is text): %bits = [%bits] - if (%source is a "Syntax Tree"): %source = %source.source - return (..) - Nomsu Code {source:%source, bits:%bits} - action [Nomsu Code from %source] (Nomsu Code from %source []) - action [Nomsu Code %bits] (Nomsu Code from (nil) %bits) - action [Nomsu Code] (Nomsu Code from (nil) []) + if (%source is a "Syntax Tree"): + %source = %source.source + return (Nomsu Code {source:%source, bits:%bits}) + + externally (Nomsu Code from %source) means (Nomsu Code from %source []) + externally (Nomsu Code %bits) means (Nomsu Code from (nil) %bits) + externally (Nomsu Code) means (Nomsu Code from (nil) []) diff --git a/nomnom/compile.nom b/nomnom/compile.nom index 989bc04..18afe3c 100644 --- a/nomnom/compile.nom +++ b/nomnom/compile.nom @@ -1,24 +1,23 @@ +#!/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" -local action [report compile error at %tree %err]: +externally (report compile error at %tree %err) means: barf (pretty "Compile Error" error at %tree %err) -local action [report compile error at %pos %err hint %hint]: +externally (report compile error at %pos %err hint %hint) means: barf (pretty "Compile Error" error at %tree %err hint %hint) -action [barf any errors in %t]: +externally (barf any errors in %t) means: assume (%t is a "Syntax Tree") %errs = [] for % in recursive %t: - if (%.type == "Error"): - %errs::add % + if (%.type == "Error"): %errs::add % for %k = %v in %: - if (%v is a "Syntax Tree"): - recurse % on %v + 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): @@ -28,17 +27,19 @@ action [barf any errors in %t]: %errs::add "\027[31;1m +\%n additional errors...\027[0m\n" barf (%errs::joined with "\n\n") -action [%tree compiled with %compile_actions]: +externally (%tree compiled with %compile_actions) means: assume (%tree is a "Syntax Tree") if all of [..] - %tree.version, action (Nomsu version) - %tree.version != (Nomsu version) - action (1 upgraded from 2 to 3) - ..then: %tree = (upgrade %tree from %tree.version to (Nomsu version)) + %tree.version, (Nomsu version)'s meaning, %tree.version != (Nomsu version) + (1 upgraded from 2 to 3)'s meaning + ..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: @@ -51,26 +52,35 @@ action [%tree compiled with %compile_actions]: ..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 = (Lua Value from %tree) - if %tree.target: # Method call + if %tree.target: + # Method call %target_lua = (%tree.target compiled with %compile_actions) - if (((%target_lua::as smext)::matches "^%(.*%)$") or ((%target_lua::as smext)::matches "^[_a-zA-Z][_a-zA-Z0-9]*$")): + if (..) + ((%target_lua::as smext)::matches "^%(.*%)$") or (..) + (%target_lua::as smext)::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"): @@ -78,6 +88,7 @@ action [%tree compiled with %compile_actions]: 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 @@ -91,65 +102,63 @@ action [%tree compiled with %compile_actions]: if %v.is_value: %v = (%v::as statements ("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" + ..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." + ..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" + ..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": #return (Lua Value from %tree ((%tree.1)::as lua)) - - %lua = (Lua Value from %tree ["Syntax_Tree_1{type=", quote %tree.1.type]) + %lua = (Lua Value from %tree ["a_Syntax_Tree_with_1{type=", quote %tree.(1).type]) set {%needs_comma:no, %i:1} - local action [% as shmua]: - if (% is a "Lua number"): - return "\%" + (% as shmua) means: + if (% is a "Lua number"): return "\%" if (% is a "Syntax Tree"): return (% compiled with %compile_actions) - if (% is text): - return (quote %) + if (% is text): return (quote %) return (%::as lua) - - for %k = %v in (((%tree.1.type == "EscapedNomsu") and %tree) or %tree.1): + + for %k = %v in (((%tree.(1).type == "EscapedNomsu") and %tree) or %tree.1): %lua::add ", " if: - (%k == %i): - %i += 1 + (%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 = (Lua Code from %tree) %lua::add (..) - ((%line compiled with %compile_actions)::as statements) - ..for %line in %tree + ((%line compiled with %compile_actions)::as statements) for %line in %tree ..joined with "\n" + return %lua - + "Text": %lua = (Lua Value from %tree) %lua_bits = [] @@ -158,49 +167,53 @@ action [%tree compiled with %compile_actions]: 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 = (Lua Value from % ["tostring(",%bit_lua,")"]) + %bit_lua = (Lua Value from % ["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 + %lua::add %lua_bits joined with ".." + if ((size of %lua_bits) > 1): %lua::parenthesize return %lua - + "List": %lua = (Lua Value from %tree ["List{"]) %lua::add ((% compiled with %compile_actions) for % in %tree) joined with ", " or ",\n " %lua::add "}" return %lua - + "Dict": %lua = (Lua Value from %tree ["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 (Lua Value from %key ["true"]) + (%value compiled with %compile_actions) if %value else (..) + Lua Value from %key ["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::as smext)::matching "^[\"']([a-zA-Z_][a-zA-Z0-9_]*)['\"]$") if: %key_str: @@ -210,6 +223,7 @@ action [%tree compiled with %compile_actions]: Lua's parser if the inner expression is a long string. Lua parses x[[[y]]] as x("[y]"), not as x["y"] return (Lua Code from %tree ["[ ", %key_lua, "]=", %value_lua]) + else: return (Lua Code from %tree ["[", %key_lua, "]=", %value_lua]) @@ -218,16 +232,17 @@ action [%tree 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::as smext).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::as smext) %lua_id = (%key_lua_str::matching "^['\"]([a-zA-Z_][a-zA-Z0-9_]*)['\"]$") if: @@ -238,20 +253,19 @@ action [%tree compiled with %compile_actions]: 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 (Lua Value from %tree ["\(%tree.1)"]) - "Var": return (Lua Variable from %tree [%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" + ..Can't convert FileChunks to a single block of lua, since each chunk's compilation depends on the earlier chunks" "Comment": # TODO: de-implement? @@ -259,7 +273,5 @@ action [%tree compiled with %compile_actions]: "Error": barf (%tree as a pretty error) - else: barf "Unknown type: \(%tree.type)" - diff --git a/nomnom/decompile.nom b/nomnom/decompile.nom index fb64f7c..7db61c8 100644 --- a/nomnom/decompile.nom +++ b/nomnom/decompile.nom @@ -1,9 +1,10 @@ +#!/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 -action [%tree decompiled inline]: +externally (%tree decompiled inline) means: assume (%tree is a "Syntax Tree") if %tree.type is: "Action": @@ -11,18 +12,18 @@ action [%tree decompiled inline]: if %tree.target: %target_nomsu = (%tree.target decompiled inline) if %tree.target.type is: - ("Action", "Block"): + "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) + %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) @@ -30,39 +31,40 @@ action [%tree decompiled inline]: %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 + %tree.(1).type == "List", %tree.(1).type == "Dict", %tree.(1).type == "Var" + ..: + %inner_nomsu::parenthesize + %nomsu = (Nomsu Code from %tree ["\\", %inner_nomsu]) return %nomsu - + "Block": %nomsu = (Nomsu Code from %tree [":"]) for %line in %tree at %i: - %nomsu::add [..] - " " if (%i == 1) else "; " - %line decompiled inline + %nomsu::add [" " if (%i == 1) else "; ", %line decompiled inline] return %nomsu - + "Text": %nomsu = (Nomsu Code from %tree []) for %text in recursive %tree: for %bit in %text at %i: - if (%bit is text): - %nomsu::add %bit + 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 (..) @@ -70,32 +72,38 @@ action [%tree decompiled inline]: not (%tree.(%i + 1)::matches "^[ \n\t,.:;#(){}%[%]]") ..: %interp_nomsu::parenthesize %nomsu::add ["\\", %interp_nomsu] - ("List", "Dict"): + + "List" "Dict": %nomsu::add ["\\", %bit decompiled inline] else: %nomsu::add ["\\(", %bit decompiled inline, ")"] + return (Nomsu Code from %tree ["\"", %nomsu, "\""]) - - ("List", "Dict"): + + "List" "Dict": %nomsu = (Nomsu Code from %tree ["[" 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]): + if (..) + all of [%key.type == "Text", (size of %key) == 1, %key.1 is a nomsu identifier] + ..: %nomsu = (Nomsu Code from %key [%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": @@ -104,46 +112,42 @@ action [%tree decompiled inline]: 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 + %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 == "Action", %bit.type == "Block", %bit.type == "IndexChain" (%bit.type == "Number") and (%i < (size of %tree)) - ..: %bit_nomsu::parenthesize + ..: + %bit_nomsu::parenthesize + %nomsu::add %bit_nomsu + return %nomsu "Number": return (Nomsu Code from %tree [(%tree.1 as hex) if %tree.hex else "\(%tree.1)"]) - "Var": return (Nomsu Code from %tree ["%\(%tree.1)"]) - - "Comment": - return (nil) - + "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 -action [%tree decompiled]: +externally (%tree decompiled) means: %nomsu = (Nomsu Code from %tree) + # For concision: - local action [recurse on %t]: + (recurse on %t) means: %space = (%MAX_LINE - (%nomsu::trailing line length)) - if (%space <= 0): go to (Use Indented) + if (%space <= 0): + go to (Use Indented) for %subtree in recursive %tree: if %subtree.type is: "Block": @@ -151,45 +155,50 @@ action [%tree decompiled]: 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 = (Nomsu Code from %t ["(..)\n ", %indented]) + %indented = (..) + Nomsu Code from %t [..] + "(..)\n ", %indented + return %indented - + if %tree.type is: "FileChunks": - local action [%1 and %2 should clump]: + (%1 and %2 should clump) means: if ((%1.type == "Action") and (%2.type == "Action")): - if (%1.stub == "use 1"): return (%2.stub == "use 1") + if (%1.stub == "use 1"): + return (%2.stub == "use 1") if (%1.stub == "test 1"): return (yes) if (%2.stub == "test 1"): 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" + 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" + + unless ("\%nomsu"::matches "\n$"): %nomsu::add "\n" return %nomsu - + "Action": %pos = %tree.source.start %next_space = "" @@ -200,33 +209,32 @@ action [%tree decompiled]: %nomsu::add %target_nomsu %pos = %tree.target.source.stop %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 + %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" + 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) @@ -234,25 +242,25 @@ action [%tree decompiled]: %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" + 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 (Nomsu Code from %tree [":\n ", %nomsu]) - + if ((%line_nomsu::number of lines) > 2): %nomsu::add "\n\n" + ..else: %nomsu::add "\n" + + return (..) + Nomsu Code from %tree [..] + ":\n ", %nomsu + "Text": # Multi-line text has more generous wrap margins %max_line = ((1.5 * %MAX_LINE) rounded down) %nomsu = (Nomsu Code from %tree) - local action [add text from %tree]: + (add text from %tree) means: for %bit in %tree at %i: if (%bit is text): # TODO: escape properly? @@ -262,7 +270,7 @@ action [%tree decompiled]: (%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) @@ -284,18 +292,23 @@ action [%tree decompiled]: "Var": if ((%tree.(%i+1) is text) and (not (%tree.(%i+1)::matches "^[ \n\t,.:#(){}[%]]"))): %interp_nomsu::parenthesize - ("List", "Dict"): + + "List" "Dict": %interp_nomsu::parenthesize + %nomsu::add %interp_nomsu - if (%interp_nomsu::is multi-line): - %nomsu::add "\n.." + if (%interp_nomsu::is multi-line): %nomsu::add "\n.." + add text from %tree - return (Nomsu Code from %tree ["\"\\\n ..", %nomsu, "\""]) - - ("List", "Dict"): + return (..) + Nomsu Code from %tree [..] + "\"\\\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)): @@ -303,10 +316,10 @@ action [%tree decompiled]: %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 + %item_nomsu::is multi-line, ((%nomsu::trailing line length) + (size of "\%item_nomsu")) >= %MAX_LINE ..: %nomsu::add "\n" ..else: %nomsu::add ", " + return (..) Nomsu Code from %tree [..] "[..]\n " if (%tree.type == "List") else "{..}\n " @@ -314,10 +327,12 @@ action [%tree decompiled]: "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 + 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] @@ -327,11 +342,9 @@ action [%tree decompiled]: %nomsu::add ["#", %tree.1::with "\n" -> "\n "] return %nomsu - ("IndexChain", "Number", "Var"): + "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 index e4b5aa2..352ddfa 100644 --- a/nomnom/files.nom +++ b/nomnom/files.nom @@ -1,3 +1,4 @@ +#!/usr/bin/env nomsu -V4.8.10 # Some file utilities for searching for files recursively and using package.nomsupath use "lib/os.nom" @@ -6,12 +7,12 @@ use "lib/os.nom" %_BROWSE_CACHE = {} # Create a fake file and put it in the cache -action [spoof file %filename %contents]: +externally (spoof file %filename %contents) means: %_SPOOFED_FILES.%filename = %contents return %contents # Read a file's contents -action [read file %filename]: +externally (read file %filename) means: %contents = %_FILE_CACHE.%filename if %contents: return %contents if (%filename == "stdin"): @@ -23,7 +24,7 @@ action [read file %filename]: %_FILE_CACHE.%filename = %contents return %contents -action [%path sanitized]: +externally (%path sanitized) means: %path = (%path::with "\\" -> "\\\\") %path = (%path::with "`" -> "") %path = (%path::with "\"" -> "\\\"") @@ -34,87 +35,74 @@ action [%path sanitized]: try: %lfs = (=lua "require('lfs')") ..and if it succeeds: - local action [filesystem has %filename]: + (filesystem has %filename) means: %mode = (call %lfs.attributes with [%filename, "mode"]) if %mode is: - ("file", "directory", "link", "char device"): - return (yes) + "file" "directory" "link" "char device": return (yes) else: return (no) - action [file %path exists]: - if (..) - any of [..] - %_SPOOFED_FILES.%path - %path == "stdin" - filesystem has %path - ..: return (yes) + 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) + if (filesystem has "\(%nomsupath)/\%path"): return (yes) return (no) - - action [files in %path]: + + 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"): + "file" "char device": %_BROWSE_CACHE.%path = [%filename] - ("directory", "link"): + "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 %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" + ..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`)" - - - action [file %path exists]: - if (..) - any of [..] - %_SPOOFED_FILES.%path - %path == "stdin" - sh> "ls \(%path sanitized)" + + 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) + if (sh> "ls \(%nomsupath)/\%path"): return (yes) return (no) - - action [files in %path]: + + 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'") + %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 index dfd5253..13d6112 100644 --- a/nomnom/parser.nom +++ b/nomnom/parser.nom @@ -1,16 +1,17 @@ +#!/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 {..} - (action (P 1)): %lpeg.P, (action (R 1)): %lpeg.R, (action (Carg 1)): %lpeg.Carg, - (action (S 1)): %lpeg.S, - (action (Cc 1)): %lpeg.Cc, (action (lpeg re pattern 1)): %re.compile, - (action (lpeg re pattern 1 using 2)): %re.compile - (action (lpeg pattern 1's match of 2)): %lpeg.match - (action (lpeg pattern 1's match of 2 with 3)): [%1, %2, %3] -> (call %lpeg.match with [%1, %2, nil, %3]) + ((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 = (..) @@ -34,28 +35,30 @@ set {..} %t = (Syntax Tree %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) +%id_patt = (..) + ((P "") - (R "09")) * (..) + (%defs.utf8_char + (R "az") + (R "AZ") + (P "_") + (R "09")) ^ 1 * -1 -action [%text is a nomsu id, %text is a nomsu identifier] (..) +%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 -action [%text is a nomsu operator] (..) +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* ~} + ..file <- %nl* {~ (def/comment) (%nl+ (def/comment))* %nl* ~} def <- anon_def / captured_def anon_def <- ({ident} (" "*) ":" {[^%nl]* (%nl+ " "+ [^%nl]*)*}) @@ -67,18 +70,22 @@ action [%text is a nomsu operator] (..) comment <- "--" [^%nl]* " -action [make parser from %peg] (make parser from %peg using (nil)) - -action [make parser from %peg using %make_tree]: +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) - local action [%input from %filename parsed]: + (%input from %filename parsed) means: %input = "\%input" - %tree_mt = {__index: {source:%input, filename:%filename}} + %tree_mt = {__index:{source:%input, filename:%filename}} %userdata = {..} - make_tree: %make_tree or ([%]-> (: set %'s metatable to %tree_mt; return %)) + 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:\n\%input" + assume %tree or barf "\ + ..File \%filename failed to parse: + \%input" + return %tree - return (action (1 from 2 parsed)) + + return ((1 from 2 parsed)'s meaning) diff --git a/nomnom/pretty_errors.nom b/nomnom/pretty_errors.nom index f32b849..db4be5a 100644 --- a/nomnom/pretty_errors.nom +++ b/nomnom/pretty_errors.nom @@ -1,12 +1,11 @@ +#!/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. - -local action [visible size of %text]: +(visible size of %text) means: return (size of (%text::with "\027%[[0-9;]*m" -> "")) -local action [%text boxed]: - %max_line = (..) - max of ((visible size of %line) for %line in (%text::lines)) +(%text boxed) means: + %max_line = (max of ((visible size of %line) for %line in (%text::lines))) %ret = (..) "\n\%text"::with "\n([^\n]*)" -> (..) [%] -> (..) @@ -14,47 +13,45 @@ local action [%text boxed]: return %ret.[2,-1] %CONTEXT = 2 -action [pretty %title error at %tree %err hint %hint]: +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 + %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|" - local action [num %i] (%fmt_str::formatted with %i) + (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" + ..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_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)" + %err_msg += "\n\%pointer" ..else: for %i in (%err_linenum + 1) to %err_linenum_end: %line = (%source_code::line %i) @@ -62,24 +59,27 @@ action [pretty %title error at %tree %err hint %hint]: 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)" + %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 ")" + ..\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 -action [pretty %title error at %tree %err] (pretty %title error at %tree %err (nil)) +externally (pretty %title error at %tree %err) means (..) + pretty %title error at %tree %err (nil) -action [%err_tree as a pretty error] (..) +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 index e05b314..c36216f 100644 --- a/nomnom/source.nom +++ b/nomnom/source.nom @@ -1,24 +1,28 @@ +#!/usr/bin/env nomsu -V4.8.10 use "lib/object.nom" object (Source): - action [Source from text %text]: + 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}) - + + 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 "")}" - + ..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 "")})" + ..(Source {filename:\(%me.filename::as nomsu), start:\(%me.start)\(..) + ", stop:\(%me.stop)" if %stop else "" + ..})" my action [== %other] (..) all of [..] @@ -26,24 +30,25 @@ object (Source): %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}) diff --git a/tools/autoformat.nom b/tools/autoformat.nom index a915fa4..13f54ef 100755 --- a/tools/autoformat.nom +++ b/tools/autoformat.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # Auto-format Nomsu code. Usage: - nomsu tools/autoformat.nom [-i] file1 file2 directory1 ... + nomsu tools/autoformat.nom [-i] file1 file2 directory1 ... If the first argument is "-i", modifications will be performed in-place. Otherwise, the formatted code will be printed. diff --git a/tools/find_action.nom b/tools/find_action.nom index e30f155..e7e3f49 100755 --- a/tools/find_action.nom +++ b/tools/find_action.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # Find an action by its stub. Usage: - nomsu tools/find_action.nom "foo %" file1 file2 directory1 ... + nomsu tools/find_action.nom "foo %" file1 file2 directory1 ... Will print all the code locations and code that uses the stub. use "lib/os.nom" @@ -28,6 +28,6 @@ for %path in %files: if (%t is syntax tree): for %sub in %t: recurse %t on %sub + sort %results by % -> %.line - for % in %results: - say %.text + for % in %results: say %.text diff --git a/tools/parse.nom b/tools/parse.nom index 9d728e8..de6aff4 100755 --- a/tools/parse.nom +++ b/tools/parse.nom @@ -1,11 +1,11 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # Tool to print out a parse tree of files in an easy-to-read format. Usage: - nomsu tools/parse.nom file1 file2 directory1 ... + nomsu tools/parse.nom file1 file2 directory1 ... use "lib/os.nom" -action [print tree %t at indent %indent]: +externally (print tree %t at indent %indent) means: if %t.type is: "Action": say "\(%indent)Action (\(%t.stub)):" diff --git a/tools/replace.nom b/tools/replace.nom index c55793a..25ae0ae 100755 --- a/tools/replace.nom +++ b/tools/replace.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # Tool to find and replace one tree with another. - nomsu tools/replace.nom [-i] tree_to_replace replacement file1 file2 directory1 ... + nomsu tools/replace.nom [-i] tree_to_replace replacement file1 file2 directory1 ... If "-i" is the first argument, replacements will be performed in-place. Otherwise, the upgraded code will be printed. diff --git a/tools/test.nom b/tools/test.nom index 6d557ea..fb70d1c 100755 --- a/tools/test.nom +++ b/tools/test.nom @@ -1,7 +1,7 @@ -#!/usr/bin/env nomsu -V4.8.8.6 +#!/usr/bin/env nomsu -V4.8.10 # Tool to run all tests in a file (i.e. the code block inside a call to 'test %'). Usage: - nomsu tools/test.nom file1 file2 directory1 ... + nomsu tools/test.nom file1 file2 directory1 ... use "lib/os.nom" use "lib/consolecolor.nom" @@ -17,7 +17,6 @@ for %path in (command line args): if (%filename::matches "%.nom$"): use %filename for %path in (command line args): use %path - %tests = ((=lua "Source:from_string(\%s)") = %t for %s = %t in (tests)) for %path in (command line args): for file %filename in %path: diff --git a/tools/upgrade.nom b/tools/upgrade.nom index 7d36793..575646e 100755 --- a/tools/upgrade.nom +++ b/tools/upgrade.nom @@ -1,7 +1,7 @@ #!/usr/bin/env nomsu -V4.8.10 # Tool to automatically update code from old versions of Nomsu. Usage: - nomsu tools/upgrade.nom [-i] file1 file2 directory1 ... + nomsu tools/upgrade.nom [-i] file1 file2 directory1 ... If "-i" is the first argument, upgrades will be performed in-place. Otherwise, the upgraded code will be printed. @@ -10,27 +10,37 @@ use "lib/os.nom" %args = (command line args) %inplace = (no) +%start_version = (nil) %version = (Nomsu version) repeat: if %args.1 is: "-i": %inplace = (yes) %args::remove index 1 + "-t": use "lib/consolecolor.nom" %test = (yes) %args::remove index 1 + "-V": %version = %args.2 %args::remove index 1 %args::remove index 1 + + "-S": + %start_version = %args.2 + %args::remove index 1 + %args::remove index 1 + else: stop for %path in %args: for file %filename in %path: unless (%filename::matches "%.nom$"): do next %filename %tree = (parse (read file %filename) from %filename) - %uptree = (%tree upgraded to %version) + %uptree = (..) + %tree upgraded from (%start_version or (%tree.version or (Nomsu version))) to %version %text = "\ ..#!/usr/bin/env nomsu -V\%version \(%uptree as nomsu)"