diff --git a/nomnom/ast.nom b/nomnom/ast.nom
index 377f4ae..816554c 100644
--- a/nomnom/ast.nom
+++ b/nomnom/ast.nom
@@ -64,6 +64,11 @@ object (Syntax Tree):
                     %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 (..)
diff --git a/nomnom/code_obj.nom b/nomnom/code_obj.nom
index f573599..363713c 100644
--- a/nomnom/code_obj.nom
+++ b/nomnom/code_obj.nom
@@ -4,10 +4,27 @@
 
 use "lib/object.nom"
 
+object (Hole):
+    action [Hole from %lua]:
+        return (Hole {lua:%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]:
         assume %me.source
-        %old_bits = %me.bits
+        %old_bits = (%me.bits if (%me.bits is a "List") else [%me.bits])
         %me.bits = []
         if (%me.source is text):
             %me.source = (Source from text %me.source)
@@ -34,10 +51,10 @@ object (Code):
 
     my action [as lua]:
         barf
-        return "\(%me.class.name::as lua id)_from_1_2(\(%me.source::as lua), \(%me.bits::as lua))"
+        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) \(%me.bits::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))
     
@@ -170,20 +187,42 @@ object (Lua Code) extends (Code):
         if (%suffix != ""):
             %statements::add (%suffix or ";")
         return %statements
+    
+    my action [variables]:
+        %vars = []
+        for %code in recursive %me:
+            if %code.is_variable:
+                %vars::add (%code::as smext)
+            for % in %code.bits:
+                unless (% is text):
+                    recurse %code on %
+        return %vars
 
     action [Lua Code from %source %bits]:
-        if (%bits is text): %bits = [%bits]
+        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:[]}
+            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 (%bits is text): %bits = [%bits]
+        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:[]}
+            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]:
+        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, 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
@@ -196,3 +235,5 @@ object (Nomsu Code) extends (Code):
         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) [])
diff --git a/nomnom/compile.nom b/nomnom/compile.nom
index 3d7c5b0..989bc04 100644
--- a/nomnom/compile.nom
+++ b/nomnom/compile.nom
@@ -4,14 +4,31 @@ use "nomnom/code_obj.nom"
 use "nomnom/parser.nom"
 use "nomnom/pretty_errors.nom"
 
-# TODO: use pretty_errors
 local action [report compile error at %tree %err]:
     barf (pretty "Compile Error" error at %tree %err)
 
 local action [report compile error at %pos %err hint %hint]:
     barf (pretty "Compile Error" error at %tree %err hint %hint)
 
-action [compile %tree using %compile_actions]:
+action [barf any errors in %t]:
+    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")
+
+action [%tree compiled with %compile_actions]:
     assume (%tree is a "Syntax Tree")
     if all of [..]
         %tree.version, action (Nomsu version)
@@ -40,12 +57,12 @@ action [compile %tree using %compile_actions]:
                             ..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 (compile %result using %compile_actions)
+                    return (%result compiled with %compile_actions)
                 return %result
 
             %lua = (Lua Value from %tree)
             if %tree.target: # Method call
-                %target_lua = (compile %tree.target using %compile_actions)
+                %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]*$")):
                     %lua::add [%target_lua, ":"]
                 ..else:
@@ -60,7 +77,7 @@ action [compile %tree using %compile_actions]:
                     %values = []
                     for %line in %tok:
                         #unless (%line.type == "Comment"):
-                        %values::add (compile %line using %compile_actions)
+                        %values::add (%line compiled with %compile_actions)
                     if all of (%.is_value for % in %values):
                         if ((size of %values) == 1):
                             %arg_lua = %values.1
@@ -76,7 +93,7 @@ action [compile %tree using %compile_actions]:
                             %arg_lua::add ["\n    ", %v]
                         %arg_lua::add "\nend)())"
                 ..else:
-                    %arg_lua = (compile %tok using %compile_actions)
+                    %arg_lua = (%tok compiled with %compile_actions)
                     unless %arg_lua.is_value:
                         if (%tok.type == "Action"):
                             report compile error at %tok "\
@@ -96,12 +113,39 @@ action [compile %tree using %compile_actions]:
             return %lua
 
         "EscapedNomsu":
-            return (Lua Value from %tree ((%tree.1)::as nomsu))
+            #return (Lua Value from %tree ((%tree.1)::as lua))
+
+            %lua = (Lua Value from %tree ["Syntax_Tree_1{type=", quote %tree.1.type])
+            set {%needs_comma:no, %i:1}
+            local action [% as shmua]:
+                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 = (Lua Code from %tree)
             %lua::add (..)
-                ((compile %line using %compile_actions)::as statements)
+                ((%line compiled with %compile_actions)::as statements)
                 ..for %line in %tree
             ..joined with "\n"
             return %lua
@@ -117,7 +161,7 @@ action [compile %tree using %compile_actions]:
                 if (%string_buffer != ""):
                     %lua_bits::add (%string_buffer::as lua)
                     %string_buffer = ""
-                %bit_lua = (compile % using %compile_actions)
+                %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."
@@ -135,24 +179,24 @@ action [compile %tree using %compile_actions]:
 
         "List":
             %lua = (Lua Value from %tree ["List{"])
-            %lua::add ((compile % using %compile_actions) for % in %tree) joined with ", " or ",\n  "
+            %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 ((compile % using %compile_actions) for % in %tree) joined with ", " or ",\n  "
+            %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 = (compile %key using %compile_actions)
+            %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 = (..)
-                (compile %value using %compile_actions) if %value
+                (%value compiled with %compile_actions) if %value
                 ..else (Lua Value from %key ["true"])
             unless %value_lua.is_value:
                 report compile error at %tree.2 "\
@@ -170,7 +214,7 @@ action [compile %tree using %compile_actions]:
                     return (Lua Code from %tree ["[", %key_lua, "]=", %value_lua])
         
         "IndexChain":
-            %lua = (compile %tree.1 using %compile_actions)
+            %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."
@@ -180,7 +224,7 @@ action [compile %tree using %compile_actions]:
 
             for %i in 2 to (size of %tree):
                 %key = %tree.%i
-                %key_lua = (compile %key using %compile_actions)
+                %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."
@@ -202,7 +246,7 @@ action [compile %tree using %compile_actions]:
             return (Lua Value from %tree ["\(%tree.1)"])
 
         "Var":
-            return (Lua Value from %tree [%tree.1::as lua id])
+            return (Lua Variable from %tree [%tree.1::as lua id])
 
         "FileChunks":
             barf "\
@@ -214,7 +258,7 @@ action [compile %tree using %compile_actions]:
             return (Lua Code from %tree "-- \(%tree.1::with "\n" -> "\n-- ")")
         
         "Error":
-            barf "Can't compile errors"
+            barf (%tree as a pretty error)
 
         else:
             barf "Unknown type: \(%tree.type)"
diff --git a/nomnom/decompile.nom b/nomnom/decompile.nom
index 58679a2..54afb08 100644
--- a/nomnom/decompile.nom
+++ b/nomnom/decompile.nom
@@ -3,13 +3,13 @@ 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 [decompile %tree inline]:
+action [%tree decompiled inline]:
     assume (%tree is a "Syntax Tree")
     if %tree.type is:
         "Action":
             %nomsu = (Nomsu Code from %tree)
             if %tree.target:
-                %target_nomsu = (decompile %tree.target inline)
+                %target_nomsu = (%tree.target decompiled inline)
                 if %tree.target.type is:
                     ("Action", "Block"):
                         %target_nomsu::parenthesize
@@ -25,7 +25,7 @@ action [decompile %tree inline]:
                     ..: %nomsu::add " "
                     %nomsu::add %bit
                 ..else:
-                    %arg_nomsu = (decompile %bit inline)
+                    %arg_nomsu = (%bit decompiled inline)
                     unless ((%i == (size of %tree)) and (%bit.type == "Block")):
                         %nomsu::add " "
                         if ((%bit.type == "Action") or (%bit.type == "Block")):
@@ -34,7 +34,7 @@ action [decompile %tree inline]:
             return %nomsu
 
         "EscapedNomsu":
-            %inner_nomsu = (decompile %tree.1 inline)
+            %inner_nomsu = (%tree.1 decompiled inline)
             unless (..)
                 any of [..]
                     %tree.1.type == "List", %tree.1.type == "Dict",
@@ -48,7 +48,7 @@ action [decompile %tree inline]:
             for %line in %tree at %i:
                 %nomsu::add [..]
                     " " if (%i == 1) else "; "
-                    decompile %line inline
+                    %line decompiled inline
             return %nomsu
 
         "Text":
@@ -62,7 +62,7 @@ action [decompile %tree inline]:
                             "Text":
                                 recurse %text on %bit
                             "Var":
-                                %interp_nomsu = (decompile %bit inline)
+                                %interp_nomsu = (%bit decompiled inline)
                                 # Make sure "...\(%x)y..." isn't confused with "...\(%xy)..."
                                 # TODO: make this more robust against "...\%x\("y").."
                                 if (..)
@@ -71,16 +71,16 @@ action [decompile %tree inline]:
                                 ..: %interp_nomsu::parenthesize
                                 %nomsu::add ["\\", %interp_nomsu]
                             ("List", "Dict"):
-                                %nomsu::add ["\\", decompile %bit inline]
+                                %nomsu::add ["\\", %bit decompiled inline]
                             else:
-                                %nomsu::add ["\\(", decompile %bit inline, ")"]
+                                %nomsu::add ["\\(", %bit decompiled inline, ")"]
             return (Nomsu Code from %tree ["\"", %nomsu, "\""])
 
         ("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 (decompile %item inline)
+                %nomsu::add (%item decompiled inline)
             %nomsu::add ("]" if (%tree.type == "List") else "}")
             return %nomsu
         
@@ -89,13 +89,13 @@ action [decompile %tree inline]:
             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 = (decompile %key inline)
+                %nomsu = (%key decompiled inline)
 
             if (%key.type == "Action"):
                 %nomsu::parenthesize
             %nomsu::add ":"
             if %value:
-                %nomsu::add (decompile %value inline)
+                %nomsu::add (%value decompiled inline)
             return %nomsu
         
         "IndexChain":
@@ -108,7 +108,7 @@ action [decompile %tree inline]:
                         %bit.1 is a nomsu identifier
                 ..:%nomsu::add %bit.1
                 ..else:
-                    %bit_nomsu = (decompile %bit inline)
+                    %bit_nomsu = (%bit decompiled inline)
                     if (..)
                         any of [..]
                             %bit.type == "Action"
@@ -138,7 +138,7 @@ action [decompile %tree inline]:
             barf "Unknown type: \(%tree.type)"
 
 %MAX_LINE = 90
-action [decompile %tree]:
+action [%tree decompiled]:
     %nomsu = (Nomsu Code from %tree)
     # For concision:
     local action [recurse on %t]:
@@ -149,18 +149,18 @@ action [decompile %tree]:
                 "Block":
                     if ((size of %subtree) > 1):
                         go to (Use Indented)
-                    if ((size of "\(decompile %subtree inline)") > 20):
+                    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 = (decompile %t inline)
+        %inline_nomsu = (%t decompiled inline)
         if (%inline_nomsu and ((size of "\%inline_nomsu") <= %space)):
             return %inline_nomsu
 
         === (Use Indented) ===
-        %indented = (decompile %t)
+        %indented = (%t decompiled)
         if (%t.type == "Action"):
             %indented = (Nomsu Code from %t ["(..)\n    ", %indented])
         return %indented
@@ -176,19 +176,16 @@ action [decompile %tree]:
             for %chunk in %tree at %chunk_no:
                 if (%chunk_no > 1):
                     %nomsu::add "\n\n\("~"::* 80)\n\n"
-                %nomsu::add (pop comments at %chunk.source.start)
                 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", pop comments at %line.source.start "\n"]
+                                %nomsu::add "\n"
                             ..else:
-                                %nomsu::add ["\n\n", pop comments at %line.source.start]
-                        %nomsu::add (decompile %line %pop_comments)
-                    %nomsu::add (pop comments at %chunk.source.stop "\n")
+                                %nomsu::add "\n\n"
+                        %nomsu::add (%line decompiled)
                 ..else:
-                    %nomsu::add (decompile %chunk %pop_comments)
-            %nomsu::add (pop comments at %tree.source.stop "\n")
+                    %nomsu::add (%chunk decompiled)
             unless ("\%nomsu"::matches "\n$"):
                 %nomsu::add "\n"
             return %nomsu
@@ -300,7 +297,7 @@ action [decompile %tree]:
                 %nomsu::add ("[]" if (%tree.type == "List") else "{}")
                 return %nomsu
             for %item in %tree at %i:
-                %item_nomsu = (decompile %item inline)
+                %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
@@ -320,7 +317,7 @@ action [decompile %tree]:
             if (all of [%key.type == "Text", (size of %key) == 1, %key.1 is a nomsu identifier]):
                 %nomsu::add %key.1
             ..else:
-                %nomsu::add (decompile %key inline)
+                %nomsu::add (%key decompiled inline)
             if ((%key.type == "Action") or (%key.type == "Block")):
                 %nomsu::parenthesize
             %nomsu::add [": ", recurse on %value]
@@ -331,7 +328,7 @@ action [decompile %tree]:
             return %nomsu
         
         ("IndexChain", "Number", "Var"):
-            return (decompile %tree inline)
+            return (%tree decompiled inline)
         
         "Error":
             barf "Cannot decompile an error"
diff --git a/nomnom/parser.nom b/nomnom/parser.nom
index 0be394c..dfd5253 100644
--- a/nomnom/parser.nom
+++ b/nomnom/parser.nom
@@ -72,7 +72,7 @@ action [make parser from %peg] (make parser from %peg using (nil))
 action [make parser from %peg using %make_tree]:
     %peg = (lpeg pattern %peg_tidier's match of %peg)
     %peg = (lpeg re pattern %peg using %defs)
-    local action [parse %input from %filename]:
+    local action [%input from %filename parsed]:
         %input = "\%input"
         %tree_mt = {__index: {source:%input, filename:%filename}}
         %userdata = {..}
@@ -81,4 +81,4 @@ action [make parser from %peg using %make_tree]:
         %tree = (lpeg pattern %peg's match of %input with %userdata)
         assume %tree or barf "File \%filename failed to parse:\n\%input"
         return %tree
-    return (action (parse 1 from 2))
+    return (action (1 from 2 parsed))
diff --git a/string2.lua b/string2.lua
index ae0e49d..1cb89ba 100644
--- a/string2.lua
+++ b/string2.lua
@@ -189,5 +189,4 @@ for _index_0 = 1, #_list_0 do
   local roundtrip = string2.from_lua_id(lua_id)
   assert(roundtrip == test, "Failed lua_id roundtrip: '" .. tostring(test) .. "' -> " .. tostring(lua_id) .. " -> " .. tostring(roundtrip))
 end
-assert(string2.as_lua_id('') == '_')
 return string2
diff --git a/string2.moon b/string2.moon
index 8d2f3f9..d70abe6 100644
--- a/string2.moon
+++ b/string2.moon
@@ -96,6 +96,6 @@ for test in *{"", "_", " ", "return", "asdf", "one two", "one_two", "Hex2Dec", "
     lua_id = string2.as_lua_id(test)
     assert is_lua_id(lua_id), "failed to convert '#{test}' to a valid Lua identifier (got '#{lua_id}')"
     roundtrip = string2.from_lua_id(lua_id)
-    assert roundtrip == test, "Failed lua_id roundtrip: '#{test}' -> #{lua_id} -> #{roundtrip}"
+    assert roundtrip == test, "Failed lua_id roundtrip: '#{test}' -> '#{lua_id}' -> '#{roundtrip}'"
 
 return string2
diff --git a/syntax_tree.lua b/syntax_tree.lua
index 851711a..63c24ee 100644
--- a/syntax_tree.lua
+++ b/syntax_tree.lua
@@ -196,8 +196,6 @@ for _index_0 = 1, #types do
     __call = function(self, t)
       if type(t.source) == 'string' then
         t.source = Source:from_string(t.source)
-      else
-        assert(Source:is_instance(t.source))
       end
       setmetatable(t, self)
       do
diff --git a/syntax_tree.moon b/syntax_tree.moon
index 926ea09..f3d3aee 100644
--- a/syntax_tree.moon
+++ b/syntax_tree.moon
@@ -82,8 +82,8 @@ for name in *types
         __call: (t)=>
             if type(t.source) == 'string'
                 t.source = Source\from_string(t.source)
-            else
-                assert(Source\is_instance(t.source))
+            --else
+            --    assert(Source\is_instance(t.source))
             setmetatable(t, @)
             if init = t.__init then init(t)
             return t