       console.warn 'No action for', node
       ''
 
-    
+  # Executes the function, but must indent all its output.
+  indentThis: (func) ->
+      # Increment the indent.
+      oldIdent = @indent
+      @indent += @indentAmount
+      func()
+      @indent = oldIdent
+
+

      # TODO: visit the var declarations.
      vars = []

      # Compile all of the subroutines. This is the only place where we
      # increment the indent.
      oldIdent = @ident
      @ident += '  '
      subroutines =
        @visit sub for sub in node.subroutines
      @ident = oldIdent

      # Compile every statment that makes up the body...
      body =
        # Some statements are undefined... skip those.
        for stmt in node.body when stmt?
          @ident + @visit(stmt) + ';\n'

      # ...and concatenate all of the above categories.
      [].concat(vars, subroutines, body)

    'procedure': (node) ->
      # Get the names of the parameters...
      # TODO:
      params = []

      [
        @ident
        "function #{name}(#{parms.join(', ')}) {"

        # Visit this node as a generic "body" node.
        @visit node, '$body'

        @ident
        "}"
      ]


      params = []

      [
        @indent
        "function #{name}(#{params.join(', ')}) {"
        "#{@indent}  var _ret;"

        # Visit this node as a generic "body" node.
        @visit node, '$body'

        # Put the return
        "#{@indent}  return _ret;"
        @indent
        "}"
      ]

    'if': (node) ->
      condition =
        ['if (', @visit(node.condition), ') {\n']

      # Compile the list of statements
      body = undefined
      @indentThis =>
        body = @visit node.consequent, '$stmt'

      elsePart =
        if node.alternative?
          topElse = [@indent, '} else {\n']
          elseBody = undefined
          @indentThis =>
            elseBody = @visit node.alternative, '$stmt'
          topElse.concat(elseBody)
        else
          []

      # The final statement should be the condition, the body, the else part
      # (optional) and finally the close brace.
      condition.concat(body, elsePart, @indent, '}')

    'while': (node) ->
      condition =
        ['while (', @visit(node.condition), ') {\n']

      # Compile the list of statements
      body = undefined
      @indentThis =>
        body = @visit node.body, '$stmt'

      condition.concat [body, @indent, '}']

    sub_invocation: (node) ->
      params =
        @visit param for param in node.params
      paramList = params.join ', '

      # Hack! I should have a table of builtins, but instead, I have only
      # implemented this one and only method.
      subroutineName =
        # TODO: Handle builtins.
        if node.name is 'writeln' then '_output' else '_' + node.name

      "#{subroutineName}(#{paramList})"

    # Got to place strings in quotes and escape characters.
    string: (node) ->
      original = node.val
      # Replace \, ', " with its backslash escape and add quotes around it.
      # And voila, a JavaScript string literal!
      "'#{original.replace /[\\'"]/, '//$&'}'"

    # For integers and reals, do nothing more than explicitly convert these to
    # strings.
    integer: (node) -> node.val.toString()
    real: (node) -> node.val.toString()

    binary_equal:  @makeBinOp '==='
    binary_nequal: @makeBinOp '!=='
    binary_gequal: @makeBinOp '>='
    binary_lequal: @makeBinOp '<='
    binary_great:  @makeBinOp '>'
    binary_less:   @makeBinOp '<'

    binary_plus:   @makeBinOp '+'
    binary_sub:    @makeBinOp '-'
    binary_or:     @makeBinOp '||'

    binary_mul:    @makeBinOp '*'
    binary_rdiv:   @makeBinOp '/'
    binary_mod:    @makeBinOp '%'
    binary_and:    @makeBinOp '&&'

    # To ensure integer division, implicitly coerce the result to integer by
    # doing a compliment operation on it, and compliment it again to get the
    # actual result. This works regardless of the operands' sign.
    binary_idiv: (node) ->
      ['(~~(', @visit(node.left), '/', @visit(node.right), '))']

    unary_pos: (node) -> @visit(node.right)
    unary_neg: (node) -> ['(-', @visit(node.right), ')']
    unary_not: (node) -> ['(!', @visit(node.right), ')']


  # General function that generates code. This calls the appropriate node
  # action or the 'explicitAction', if given. The return should be a string.
  # Probably.
  visit: (node, explicitAction=null) ->

    # Node could potentially be a node list:
    if Array.isArray node
      return (@visit n, explicitAction for n in node).join('')

    # Use either the explictly given action or the AST node kind.
    kind = explicitAction or node.ast
