 clone = (obj) ->
   JSON.parse JSON.stringify obj
 
+# ----------------------------------------------------------------------------
+
+###**
+# ScopeTransformer:
+# Yep
+###
+
+class ScopeTransformer extends TransformerBase
+  run: (@body) ->
+    @prebody = []
+    @recurse @ast
+
+    if @prebody.length
+      @body.body = @prebody.concat(@body.body)
+
+    @ast
+
+  FunctionDeclaration: (node) ->
+    @skip()
+    @prebody.push @buildFunctionDeclaration(node)
+    { type: 'EmptyStatement' }
+
+  FunctionExpression: (node) ->
+    return unless node.id?
+    @skip()
+    @prebody.push @buildFunctionDeclaration(node)
+    { type: 'Identifier', name: node.id.name }
+
+  ###
+  # Returns a `a = -> ...` statement out of a FunctionDeclaration node.
+  ###
+
+  buildFunctionDeclaration: (node) ->
+    type: 'ExpressionStatement'
+    expression:
+      type: 'AssignmentExpression'
+      operator: '='
+      left: node.id
+      right:
+        type: 'FunctionExpression'
+        params: node.params
+        body: node.body
+
+# ----------------------------------------------------------------------------
+
 ###*
 # Builder : new Builder(ast, [options])
 # Generates output based on a JavaScript AST.

    @warnAboutLabeledStatements node, parent
  WithStatement: (node) ->
    @syntaxError node, "'with' is not supported in CoffeeScript"
  VariableDeclarator: (node, parent, skip) ->
    @addShadowingIfNeeded(node)
    @addExplicitUndefinedInitializer node, parent, skip

  fixScope: (root, scope) ->
    prebody = []
    self = this

    @estraverse().replace root,
      enter: (node, parent) ->
        if node is root
          return node

        else if node.type is 'FunctionDeclaration'
          @skip()
          prebody.push self.buildFunctionDeclaration(node)
          { type: 'EmptyStatement' }

        else if node.type is 'FunctionExpression' and node.id?
          @skip()
          prebody.push self.buildFunctionDeclaration(node)
          { type: 'Identifier', name: node.id.name }

        else
          node

    if prebody.length
      scope.body = prebody.concat(scope.body)

    root

  ###
  # Returns a `a = -> ...` statement out of a FunctionDeclaration node.
  ###

  buildFunctionDeclaration: (node) ->
    type: 'ExpressionStatement'
    expression:
      type: 'AssignmentExpression'
      operator: '='
      left: node.id
      right:
        type: 'FunctionExpression'
        params: node.params
        body: node.body

  ###
  # Remove `{type: 'EmptyStatement'}` from the body.

  FunctionExpression: (node, parent) ->
    throw new Error("NamedFnExpr: Not supposed to happen") if node.id # fixScope should've gotten this case
    @pushStack node.body
    @removeUndefinedParameter node
    new ScopeTransformer(node, @options).run(node.body)
  FunctionExpressionExit: (node) ->
    @popStack()
  SwitchStatement: (node) ->
