       params = []
 
       [
-        @ident
+        @indent
         "function #{name}(#{params.join(', ')}) {"
-        "#{@ident}  var _ret;"
+        "#{@indent}  var _ret;"
 
         # Visit this node as a generic "body" node.
         @visit node, '$body'
 
         # Put the return
-        "#{@ident}  return _ret;"
-        @ident
+        "#{@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
 
-      # TODO: Handle builtins.
       "#{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 /[\\'"]/, '//$&'}'"
 
-    # 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)]
+    # 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

# 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.
    # I don't know what else to do other than visit the node.
    # Regardless... here it is:
    @visit astRoot

  # 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. 
  @actions =
    program: (node) ->
      [

      # 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
        "}"
      ]

