 
 infer = (context, expression, nameIndex) ->
   switch expression.label
-    when 'numerical' then [newMap(), 'Num']
-    when 'string' then [newMap(), 'Text']
+    when 'numerical' then [newMap(), nameIndex, 'Num']
+    when 'string' then [newMap(), nameIndex, 'Text']
     else
       # Reference
       if isReference expression
         # TODO: replace free type variables with new unused names
-        [newMap(), lookupInMap context, expression.token]
+        concreteType = lookupInMap context, expression.token
+        unless concreteType
+          throw new Error "Unbound variable #{expression.token}"
+        [newMap(), nameIndex, concreteType]
       # Lambda
       else if expression.type is 'function'
         {params, body, wheres} = fnDefinition expression

subContext = (subs, context) ->
  newContext = newMap()
  for name, t of context.values
    setInMap newContext, name, (subExp subs, t)
  newContext

isTypeVariable = (name) ->
  name.charCodeAt(0) >= 97

freshName = (nameIndex) ->
  # TODO: handle more than 27 variables


subPairs = (subs, pairs) ->
  for [t1, t2] in pairs
    [(subExp subs, t1), (subExp subs, t2)]

subExp = (subs, type) ->
  if Array.isArray type
