   if hasName
     macroName = ctx.definitionName()
     if ctx.macros()[macroName]
-      malformed call, "Macro with this name already defined"
+      return malformed call, "Macro with this name already defined"
+    if not isTypeAnnotation type
+      return malformed call, "Type annotation required"
 
     # Register type
     ctx.declare macroName,
       arity: (map _symbol, _terms paramTuple)
-      type: quantifyUnbound ctx, typeConstrainedCompile type
+      type: quantifyUnbound ctx, typeConstrainedCompile ctx, type
 
     #macroFn = transform call
     compiledMacro = translateToJs translateIr ctx,

binaryMathOpType = '(Fn Num Num Num)'
comparatorOpType = '(Fn a a Bool)'

builtInContext = ->
  concatMaps (mapMap desiplifyTypeAndArity, newMapWith 'True', 'Bool',
    'False', 'Bool'
    '&', '(Fn a b b)' # TODO: replace with actual type
    'show-list', '(Fn a b)' # TODO: replace with actual type
    'from-nullable', '(Fn a b)' # TODO: replace with actual type JS -> Maybe a

    # TODO match

    # 'if', '(Fn Bool a a a)'
    # TODO JS interop

    # 'sqrt', '(Fn Num Num)'
    # 'not', '(Fn Bool Bool)'

    # '^', binaryMathOpType

    # '~', '(Fn Num Num)'

    # '+', binaryMathOpType
    # '*', binaryMathOpType
    '==', comparatorOpType
    # '!=', comparatorOpType
    # 'and', '(Fn Bool Bool Bool)'
    # 'or', '(Fn Bool Bool Bool)'

    # '-', binaryMathOpType
    # '/', binaryMathOpType
    # 'rem', binaryMathOpType
    # '<', comparatorOpType
    # '>', comparatorOpType
    # '<=', comparatorOpType
    # '>=', comparatorOpType
    ),
    newMapWith 'empty-array', (type: (parseUnConstrainedType '(Fn (Array a))'), arity: [])
      'cons-array', (type: (parseUnConstrainedType '(Fn a (Array a) (Array a))'), arity: ['what', 'onto'])

desiplifyTypeAndArity = (simple) ->
  type = parseUnConstrainedType simple


kindsEq = (k1, k2) ->
  k1 is k2 or
    k1.from and k2.from and
    (kindsEq k1.from, k2.from) and
    (kindsEq k1.to, k2.to)

