 # certain AST nodes with metadata. It would also probably rely on a symbol
 # table. But this one does nonee such thing.
 
+
 class JSCodeGenerator
-  constructor: -> # Do nothing
-  compile: (astRoot) ->
-    @ident = '  ' # I guess I should have an indent or something.
+  constructor: ->
+    @indentAmount = '  '
+
+  compile: (ast) ->
+    # I guess I should initialize the indent or something.
+    @indent = '  '
+
     # I don't know what else to do other than visit the node.
     # Regardless... here it is:
-    @visit astRoot
+    @visit ast
+
+  # Returns an action for a JS binary operator.
+  @makeBinOp: (binop) -> (node) ->
+    ['(', @visit(node.left), binop, @visit(node.right), ')']
 
   # Here's the big array of ast nodes and the actions that should be called
   # when they are visited. Each each action should return either a list or a
-  # string of JavaScript code. 
+  # string of JavaScript code.
   @actions =
     program: (node) ->
       [

      params = []

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

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

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

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

      subroutineName =
        if node.name is 'writeln' then '_output' else '_' + node.name

      # TODO: Handle builtins.
      "#{subroutineName}(#{paramList})"

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

    # I'll get around to making these later.
    binary_plus: (node) -> @makeSimpleBinOp '+'

  # Creates a basic action for a JS binary operator.
  @makeSimpleBinOp: (binop) -> (node)->
    [visit(node.left), binop, 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) ->

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

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

      # Need to expliclty defined these in this scope.
      body = undefined
      subroutines = undefined

      @indentThis =>
        # Compile all of the subroutines.
        subroutines =
          @visit sub for sub in node.subroutines

        # Compile every statment that makes up the body
        body = @visit node.body, '$stmt'

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

    # Compiles a single statement. Basically indent it and place a semi-colon
    # and newline at the end. Only creates output for statments that are
    # defined.
    $stmt: (node) ->
      if node
        [@indent, @visit(node), ';\n']
      else
        ''

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

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

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

        @indent
        "}"
      ]

