 # exp followed by list of definitions
 compiled = (source) ->
   variableCounter = 1
-  compileTop parentize typifyTop astize tokenize "(#{source})"
+  compileTop preCompileTop source
 
 # single exp
 compiledExp = (source) ->
   variableCounter = 1
-  "(#{compileImpl parentize typify astize tokenize source})"
+  "(#{compileImpl preCompileExp source})"
 
 # list of definitions
 compileDefinitions = (source) ->
   variableCounter = 1
-  compileWheres parentize typifyDefinitions astize tokenize "(#{source})"
+  compileWheres preCompileDefs source
 
 # exported list of definitions
 compileDefinitionsInModule = (source) ->
   variableCounter = 1
-  compileWheresInModule parentize typifyDefinitions astize tokenize "(#{source})"
-
-pushScope = ({parent, ids, children}) ->
-  child =
-    parent:
-      parent: parent
-      ids: ids
-    ids: []
-    children: []
-  child.parent.children = children.concat [child]
-  child
-
-topScope = ->
-  parent: null
-  ids: []
-  children: []
-
-addIdToScope = ({parent, ids, children}, addedIds...) ->
-  parent: parent
-  ids: ids.concat addIds
-  children: children
+  compileWheresInModule preCompileDefs source
+
+preCompileExp = (source) ->
+  parentize typify astize tokenize source
+
+preCompileTop = (source) ->
+  parentize typifyTop astize tokenize "(#{source})"
+
+preCompileDefs = (source) ->
+  parentize typifyDefinitions astize tokenize "(#{source})"
 
 compileTop = (ast) ->
   ast.scope = {}



trueMacros =
  'match': (onwhat, cases...) ->
    varNames = []
    if not onwhat
      throw new Error 'match `onwhat` missing'

  else
    compileDef [name, def]

compileImpl = (node, hoistableWheres = []) ->
  # For now special case match to allow definition hoisting up one level
  if Array.isArray(node) and node.length > 0
    [op, args...] = inside node
    if op.type is 'operator' and op.token is 'match'
      return trueMacros[op.token] hoistableWheres, args...

    ###
    if hoistableWheres.length > 0
      allNames = []
      for [_, _, names] in hoistableWheres
        allNames.push names...
      throw new Error "#{allNames.join ','} used but not defined yet"###

  switch node.type
    when 'comment' then 'null'
    when 'data' then 'null'
    when 'type' then 'null'
    when 'function'
      compileFn node
    else
      if Array.isArray node
        exps = inside node
