         argName = freshName nameIndex
         param = definedParams[0]
         context = concat context, newMapWith param.token, argName
-        [s1, nextIndex, A] = infer context, body, nameIndex + 1
-        [s1, nextIndex, (subExp s1, [argName, A])]
+        [s1, nextIndex, body] = infer context, body, nameIndex + 1
+        expression.tea = (subExp s1, [argName, body.tea])
+        [s1, nextIndex, expression]
 
       # Call
       else if Array.isArray expression
         [op, arg] = inside expression
         # assume call.length is 2
         returnName = freshName nameIndex
-        [s1, nextIndex, A] = infer context, op, nameIndex + 1
-        [s2, nextIndex, B] = infer (subContext s1, context), arg, nextIndex
-        log "op", s2, A, (subExp s2, A)
-        log "operand", [B, returnName]
-        s3 = unify (subExp s2, A), [B, returnName]
-        [(concat s3, s2, s1), nextIndex, (subExp s3, returnName)]
+        [s1, nextIndex, op] = infer context, op, nameIndex + 1
+        [s2, nextIndex, arg] = infer (subContext s1, context), arg, nextIndex
+        s3 = unify (subExp s2, op.tea), [arg.tea, returnName]
+        expression.tea = (subExp s3, returnName)
+        [(concat s3, s2, s1), nextIndex, expression]
 
 unify = (t1, t2) ->
   unifyWith newMap(), [[t1, t2]]


# Type inference and checker

infer = (context, expression, nameIndex) ->
  switch expression.label
    when 'numerical' then [newMap(), nameIndex, 'Num']
    when 'string' then [newMap(), nameIndex, 'Text']
    else
      # Reference
      if isReference expression

  else
    cb ast, ast.token
  return

crouch = (ast, cb) ->
  if Array.isArray ast
    for node in ast
      crouch node, cb
  else
    cb ast
  ast

inside = (node) -> node[1...-1]

