Skip to content

Commit

Permalink
canonicalize module names, generate unambiguous names in JS
Browse files Browse the repository at this point in the history
Begging to address #826
  • Loading branch information
process-bot committed Aug 28, 2015
1 parent 5943865 commit 31545d1
Show file tree
Hide file tree
Showing 23 changed files with 360 additions and 405 deletions.
1 change: 1 addition & 0 deletions elm-compiler.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Library
AST.Helpers,
AST.Literal,
AST.Module,
AST.Module.Name,
AST.Pattern,
AST.Type,
AST.Variable,
Expand Down
55 changes: 15 additions & 40 deletions src/AST/Module.hs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
module AST.Module
( Interfaces, CanonicalInterfaces
( Interfaces
, Types, Aliases, ADTs
, AdtInfo, CanonicalAdt
, SourceModule, ValidModule, CanonicalModule, Optimized
, Module(..), Body(..)
, Header(..)
, Name, nameToString, nameIsNative
, CanonicalName(..), canonPkg, canonModul
, Interface(..), toInterface
, UserImport, DefaultImport, ImportMethod(..)
) where

import Control.Applicative ((<$>),(<*>))
import Data.Binary
import qualified Data.List as List
import qualified Data.Map as Map

import qualified AST.Declaration as Decl
import qualified AST.Expression.Canonical as Canonical
import qualified AST.Expression.Optimized as Optimized
import qualified AST.Module.Name as Name
import qualified AST.Type as Type
import qualified AST.Variable as Var
import qualified Docs.AST as Docs
Expand All @@ -29,8 +27,7 @@ import qualified Reporting.Annotation as A

-- HELPFUL TYPE ALIASES

type Interfaces = Map.Map Name Interface
type CanonicalInterfaces = Map.Map CanonicalName Interface
type Interfaces = Map.Map Name.Canonical Interface

type Types = Map.Map String Type.Canonical
type Aliases = Map.Map String ([String], Type.Canonical)
Expand Down Expand Up @@ -59,15 +56,15 @@ type ValidModule =


type CanonicalModule =
Module Docs.Centralized [Name] [Var.Value] (Body Canonical.Expr)
Module Docs.Centralized [Name.Raw] [Var.Value] (Body Canonical.Expr)


type Optimized =
Module Docs.Centralized [Name] [Var.Value] (Body Optimized.Expr)
Module Docs.Centralized [Name.Raw] [Var.Value] (Body Optimized.Expr)


data Module docs imports exports body = Module
{ names :: Name
{ name :: Name.Canonical
, path :: FilePath
, docs :: A.Located (Maybe docs)
, exports :: exports
Expand All @@ -90,41 +87,19 @@ data Body expr = Body

{-| Basic info needed to identify modules and determine dependencies. -}
data Header imports = Header
{ _names :: Name
{ _name :: Name.Raw
, _docs :: A.Located (Maybe String)
, _exports :: Var.Listing (A.Located Var.Value)
, _imports :: imports
}


type Name = [String] -- must be non-empty


data CanonicalName =
CanonicalName
{ canonPkg :: Package.Name
, canonModul :: Name
}


nameToString :: Name -> String
nameToString =
List.intercalate "."


nameIsNative :: Name -> Bool
nameIsNative name =
case name of
"Native" : _ -> True
_ -> False


-- IMPORTs

type UserImport = A.Located (Name, ImportMethod)
type UserImport = A.Located (Name.Raw, ImportMethod)


type DefaultImport = (Name, ImportMethod)
type DefaultImport = (Name.Raw, ImportMethod)


data ImportMethod = ImportMethod
Expand All @@ -137,43 +112,43 @@ data ImportMethod = ImportMethod

{-| Key facts about a module, used when reading info from .elmi files. -}
data Interface = Interface
{ iVersion :: String
{ iVersion :: Package.Version
, iPackage :: Package.Name
, iExports :: [Var.Value]
, iTypes :: Types
, iImports :: [Name]
, iImports :: [Name.Raw]
, iAdts :: ADTs
, iAliases :: Aliases
, iFixities :: [(Decl.Assoc, Int, String)]
, iPorts :: [String]
, iPackage :: Package.Name
}


toInterface :: Package.Name -> CanonicalModule -> Interface
toInterface pkgName modul =
let body' = body modul in
Interface
{ iVersion = Package.versionToString Compiler.version
{ iVersion = Compiler.version
, iPackage = pkgName
, iExports = exports modul
, iTypes = types body'
, iImports = imports modul
, iAdts = datatypes body'
, iAliases = aliases body'
, iFixities = fixities body'
, iPorts = ports body'
, iPackage = pkgName
}


instance Binary Interface where
get = Interface <$> get <*> get <*> get <*> get <*> get <*> get <*> get <*> get <*> get
put modul = do
put (iVersion modul)
put (iPackage modul)
put (iExports modul)
put (iTypes modul)
put (iImports modul)
put (iAdts modul)
put (iAliases modul)
put (iFixities modul)
put (iPorts modul)
put (iPackage modul)
50 changes: 50 additions & 0 deletions src/AST/Module/Name.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module AST.Module.Name where

import Control.Applicative ((<$>),(<*>))
import Data.Binary
import qualified Data.List as List

import qualified Elm.Package as Package


type Raw = [String] -- must be non-empty


data Canonical = Canonical
{ _package :: Package.Name
, _module :: Raw
}
deriving (Eq, Ord, Show)


inCore :: Raw -> Canonical
inCore raw =
Canonical Package.coreName raw


toString :: Raw -> String
toString rawName =
List.intercalate "." rawName


canonicalToString :: Canonical -> String
canonicalToString (Canonical _ rawName) =
toString rawName


isNative :: Raw -> Bool
isNative name =
case name of
"Native" : _ ->
True

_ ->
False


instance Binary Canonical where
put (Canonical home name) =
put home >> put name

get =
Canonical <$> get <*> get
27 changes: 16 additions & 11 deletions src/AST/Variable.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ module AST.Variable where

import Control.Applicative ((<$>), (<*>))
import Data.Binary
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Maybe as Maybe
import Text.PrettyPrint as P

import qualified AST.Helpers as Help
import qualified AST.Module.Name as ModuleName
import qualified Reporting.PrettyPrint as P


Expand All @@ -19,8 +19,8 @@ newtype Raw = Raw String

data Home
= BuiltIn
| Module [String]
| TopLevel [String]
| Module ModuleName.Canonical
| TopLevel ModuleName.Canonical
| Local
deriving (Eq, Ord, Show)

Expand All @@ -37,26 +37,31 @@ local x =
Canonical Local x


topLevel :: [String] -> String -> Canonical
topLevel names x =
Canonical (TopLevel names) x
topLevel :: ModuleName.Canonical -> String -> Canonical
topLevel home x =
Canonical (TopLevel home) x


builtin :: String -> Canonical
builtin x =
Canonical BuiltIn x


fromModule :: [String] -> String -> Canonical
fromModule :: ModuleName.Canonical -> String -> Canonical
fromModule home name =
Canonical (Module home) name


inCore :: ModuleName.Raw -> String -> Canonical
inCore home name =
Canonical (Module (ModuleName.inCore home)) name


-- VARIABLE RECOGNIZERS

is :: [String] -> String -> Canonical -> Bool
is :: ModuleName.Raw -> String -> Canonical -> Bool
is home name var =
var == Canonical (Module home) name
var == inCore home name


isJson :: Canonical -> Bool
Expand Down Expand Up @@ -133,8 +138,8 @@ instance ToString Canonical where
BuiltIn ->
name

Module path ->
List.intercalate "." (path ++ [name])
Module moduleName ->
ModuleName.canonicalToString moduleName ++ "." ++ name

TopLevel _ ->
name
Expand Down
25 changes: 17 additions & 8 deletions src/Canonicalize.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import qualified Data.Foldable as T

import AST.Expression.General (Expr'(..), dummyLet)
import AST.Module (Body(..))
import Elm.Utils ((|>))

import qualified AST.Declaration as D
import qualified AST.Expression.General as E
import qualified AST.Expression.Valid as Valid
import qualified AST.Expression.Canonical as Canonical
import qualified AST.Module as Module
import qualified AST.Module.Name as ModuleName
import qualified AST.Pattern as P
import qualified AST.Type as Type
import qualified AST.Variable as Var
Expand All @@ -41,13 +43,19 @@ import qualified Canonicalize.Variable as Canonicalize
-- MODULES

module'
:: Module.Interfaces
:: [ModuleName.Canonical]
-> Module.Interfaces
-> Module.ValidModule
-> R.Result Warning.Warning Error.Error Module.CanonicalModule
module' interfaces modul =
module' canonicalImports interfaces modul =
let
importDict =
canonicalImports
|> map (\cName -> (ModuleName._module cName, cName))
|> Map.fromList

(Result.Result uses rawResults) =
moduleHelp interfaces modul
moduleHelp importDict interfaces modul
in
case rawResults of
Result.Ok (env, almostCanonicalModule) ->
Expand All @@ -67,10 +75,11 @@ type AlmostCanonicalModule =


moduleHelp
:: Module.Interfaces
:: Map.Map ModuleName.Raw ModuleName.Canonical
-> Module.Interfaces
-> Module.ValidModule
-> Result.ResultErr (Env.Environment, AlmostCanonicalModule)
moduleHelp interfaces modul@(Module.Module _ _ comment exports _ decls) =
moduleHelp importDict interfaces modul@(Module.Module _ _ comment exports _ decls) =
canonicalModule
<$> canonicalDeclsResult
<*> resolveExports locals exports
Expand All @@ -88,7 +97,7 @@ moduleHelp interfaces modul@(Module.Module _ _ comment exports _ decls) =
concatMap declToValue decls

canonicalDeclsResult =
Setup.environment interfaces modul
Setup.environment importDict interfaces modul
`Result.andThen` \env -> (,) env <$> T.traverse (declaration env) decls

body :: [D.CanonicalDecl] -> Module.Body Canonical.Expr
Expand All @@ -97,7 +106,7 @@ moduleHelp interfaces modul@(Module.Module _ _ comment exports _ decls) =
in
Module.Body
{ program =
let expr = Decls.toExpr (Module.names modul) decls
let expr = Decls.toExpr (Module.name modul) decls
in
Sort.definitions (dummyLet expr)

Expand All @@ -121,7 +130,7 @@ moduleHelp interfaces modul@(Module.Module _ _ comment exports _ decls) =
-- IMPORTS

filterImports
:: Set.Set Module.Name
:: Set.Set ModuleName.Raw
-> AlmostCanonicalModule
-> R.Result Warning.Warning e Module.CanonicalModule
filterImports uses modul@(Module.Module _ _ _ _ (defaults, imports) _) =
Expand Down
6 changes: 3 additions & 3 deletions src/Canonicalize/Declaration.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ module Canonicalize.Declaration (toExpr) where
import qualified AST.Declaration as D
import qualified AST.Expression.General as E
import qualified AST.Expression.Canonical as Canonical
import qualified AST.Module as Module
import qualified AST.Module.Name as ModuleName
import qualified AST.Pattern as P
import qualified AST.Type as T
import qualified AST.Variable as Var
import qualified Reporting.Annotation as A
import qualified Reporting.Region as R


toExpr :: Module.Name -> [D.CanonicalDecl] -> [Canonical.Def]
toExpr :: ModuleName.Canonical -> [D.CanonicalDecl] -> [Canonical.Def]
toExpr moduleName decls =
concatMap (toDefs moduleName) decls


toDefs :: Module.Name -> D.CanonicalDecl -> [Canonical.Def]
toDefs :: ModuleName.Canonical -> D.CanonicalDecl -> [Canonical.Def]
toDefs moduleName (A.A (region,_) decl) =
let typeVar = Var.fromModule moduleName

Expand Down
Loading

0 comments on commit 31545d1

Please sign in to comment.