 declareImported = (ctx, name) ->
   ctx.assignType name, (ctx.tempType name)
   ctx.declareAsFinal name, ctx.currentScopeIndex()
-
-imports = (moduleName, names) ->
-  validModuleName = validIdentifier moduleName
-  for name in names
-    validName = validIdentifier name
-    jsVarDeclaration validName, (jsAccess (jsAccess "Shem", validModuleName), validName)
 
 ms.format = ms_format = (ctx, call) ->
   typeTable =

topLevel = (ctx, form) ->
  definitionList ctx, spaceSeparatedPairs form

topLevelModule = (moduleName, defaultImports) -> (ctx, form) ->
  [(jsAssignStatement (jsAccess "Shem", (validIdentifier moduleName)),
    (exportAll ctx, (join (importAny defaultImports), (topLevel ctx, form))))]

topLevelExpressionInModule = (defaultImports) -> (ctx, expression) ->
  (iife (concat [

compiledModules = newMap()
moduleGraph = newMap()

# TODO: pass this info in through context instead of a direct call
moduleNameToTypedModulePath = (moduleName, currentTypedModulePath) ->
  module = (lookupInMap moduleGraph, moduleName)
  if module
    if violating = moduleAccessViolation (moduleNameToPath moduleName), currentTypedModulePath
      nonExportedLink: violating
  module.typedModulePath

moduleAccessViolation = (toModulePath, fromTypedModulePath) ->
  for i, moduleName in toModulePath
    if fromTypedModulePath.names[i] isnt moduleName
      checkedModuleName = (modulePathToName toModulePath[0..i])
      module = (lookupInMap moduleGraph, checkedModuleName)
      if not module
        throw new Error "missing module #{checkedModuleName}
         that should have been compiled for #{moduleName}"
      if not module.exported
        return checkedModuleName
  false

lookupCompiledModule = (name) ->
  lookupInMap compiledModules, name

compileModule = (source) ->
  compileModuleTopLevel source, (names: ['.'], types: ['commonJs'])

defaultTypedModulePath = (names: ['@unnamed'], types: ['browser'])

compileModuleTopLevel = (source, typedModulePath = defaultTypedModulePath, requiredMap = newMap()) ->
  compileModuleTopLevelAst (astFromSource "(#{source})", -1, -1), typedModulePath, requiredMap

compileModuleTopLevelAst = (ast, typedModulePath = defaultTypedModulePath, requiredMap = newMap()) ->
  # addToMap requiredMap, 'Prelude', yes # TODO: Hardcoded prelude dependency
  moduleName = modulePathToName typedModulePath.names
  removeFromMap requiredMap, moduleName
  for requiredModuleName of values requiredMap
    if not lookupCompiledModule requiredModuleName
      return request: requiredModuleName
  replaceOrAddToMap moduleGraph, moduleName, requires: requiredMap, typedModulePath: typedModulePath
  toInject = requiresFor moduleName
  ctx = injectedContext toInject
  ctx.typedModulePath = typedModulePath
  defaultImports = importsFor newSet()#(subtractSets (newSetWith 'Prelude'), (newSetWith moduleName))
  declareImportedByDefault ctx, defaultImports
  compilationFn = (topLevelModule typedModulePath, defaultImports)
  {request, ir, js} = compileCtxAstToJs compilationFn, ctx, ast
  if request
    if not allInjected request, requiredMap
      return compileModuleTopLevelAst ast, typedModulePath, request
    else
      {js} = compileCtxIrToJs ctx, ir
  errors = checkTypes ctx
