 
                 @changed = true
 
+        setDesiredType: (ast, ty) ->
+                #console.warn "setting desired type of #{ty}"
+                ast._ejs_desiredtype = ty
+                @changed = true
+
 class TypeInfer
         constructor: ->
                 @defaultGlobalEnvironment = [

dump = (tree)->
        dumpvisitor = new DumpInferredTypesVisitor
        dumpvisitor.visit tree
###
dump run esprima.parse "5;"
dump run esprima.parse "4 + 5;"
dump run esprima.parse "function () { return 5; }"
###

        visitCallExpression: (exp) ->
                super
                # If we have a type for the callee in our environment,
                # try to look up a matching signature for
                # parameters/arguments.
                # 
                # If we find one, then use the return type of that
                # signature as exp's inferred type.
                #
                # If we don't find one, we need to re-traverse the
                # function using the inferred argument types to see
                # what the return type could be.
                exp

        visitFunctionBody: (exp) ->
                @function_stack.push exp
                exp.body = @visit exp.body
                @function_stack.pop()
                exp

        visitFunctionExpression: (exp) ->
                @visitFunctionBody exp

        visitFunctionDeclaration: (exp) ->
                @visitFunctionBody exp

        visitReturn: (exp) ->
                super
                debug.log "visitReturn"
                @assignType @function_stack.top, new FunctionType (@getType exp.argument), []
                exp

        visitBinaryExpression: (exp) ->
                super
                switch exp.operator
                        when "+"
                                if StringType.is @getType exp.left
                                        @assignType exp, new StringType
                                        @setDesiredType exp.right, new StringType
                                else if StringType.is @getType exp.right
                                        @assignType exp, new StringType
                                        @setDesiredType exp.left, new StringType
                                else
                                        @assignType exp, new NumberType
                                        @setDesiredType exp.left, new NumberType
                                        @setDesiredType exp.right, new NumberType
                        when "-"
                                @assignType exp, new NumberType
                                @setDesiredType exp.left, new NumberType
                                @setDesiredType exp.right, new NumberType
                        when "*"
                                @assignType exp, new NumberType
                                @setDesiredType exp.left, new NumberType
                                @setDesiredType exp.right, new NumberType
                        when "/"
                                @assignType exp, new NumberType
                                @setDesiredType exp.left, new NumberType
                                @setDesiredType exp.right, new NumberType
                exp
        visitVariableDeclarator: (exp) ->
                super
