diff --git a/src/AST.hs b/src/AST.hs index 168a327a..636362a9 100644 --- a/src/AST.hs +++ b/src/AST.hs @@ -54,7 +54,8 @@ module AST ( emptyInterface, emptyImplementation, getParams, getPrimParams, getDetism, getProcDef, getProcPrimProto, mkTempName, updateProcDef, updateProcDefM, - ModSpec, maybeModPrefix, ProcImpln(..), ProcDef(..), procInline, procCallCount, + ModSpec, validModuleName, maybeModPrefix, + ProcImpln(..), ProcDef(..), procInline, procCallCount, transformModuleProcs, getProcGlobalFlows, primImpurity, flagsImpurity, flagsDetism, @@ -1699,6 +1700,12 @@ instance Show TypeVarName where type ModSpec = [Ident] +-- |Check that a module name component is valid (ie, does not contain invalid +-- characters). Currently only period (.) and hash (#) are considered invalid. +validModuleName :: Ident -> Bool +validModuleName = not . any (`elem` ['.','#']) + + -- |The uses one module makes of another; first the public imports, -- then the privates. Each is either Nothing, meaning all exported -- names are imported, or Just a set of the specific names to import. diff --git a/src/Normalise.hs b/src/Normalise.hs index facc6627..b0827225 100644 --- a/src/Normalise.hs +++ b/src/Normalise.hs @@ -55,15 +55,18 @@ normalise items = do normaliseItem :: Item -> Compiler () normaliseItem (TypeDecl vis (TypeProto name params) mods (TypeRepresentation rep) items pos) = do + validateModuleName "type" pos name let items' = RepresentationDecl params mods rep pos : items unless (List.null params) $ errmsg pos "types defined by representation cannot have type parameters" normaliseSubmodule name vis pos items' normaliseItem (TypeDecl vis (TypeProto name params) mods (TypeCtors ctorVis ctors) items pos) = do + validateModuleName "type" pos name let items' = ConstructorDecl ctorVis params mods ctors pos : items normaliseSubmodule name vis pos items' -normaliseItem (ModuleDecl vis name items pos) = +normaliseItem (ModuleDecl vis name items pos) = do + validateModuleName "module" pos name normaliseSubmodule name vis pos items normaliseItem (RepresentationDecl params mods rep pos) = do updateTypeModifiers mods @@ -76,9 +79,12 @@ normaliseItem (ConstructorDecl vis params mods ctors pos) = do Public -> mapM_ (addConstructor Public . snd) ctors Private -> mapM_ (uncurry addConstructor) ctors normaliseItem (ImportMods vis modspecs pos) = - mapM_ (\spec -> addImport spec (importSpec Nothing vis)) modspecs + mapM_ (\spec -> validateModSpec pos spec >> + addImport spec (importSpec Nothing vis) + ) modspecs normaliseItem (ImportItems vis modspec imports pos) = - addImport modspec (importSpec (Just imports) vis) + validateModSpec pos modspec + >> addImport modspec (importSpec (Just imports) vis) normaliseItem (ImportForeign files _) = mapM_ addForeignImport files normaliseItem (ImportForeignLib files _) = @@ -277,6 +283,18 @@ completeTypeSCC (CyclicSCC modTypeDefs) = do mapM_ (uncurry completeType) modTypeDefs +-- |Check that the specified module name is valid, reporting and error if not. +validateModuleName :: String -> OptPos -> Ident -> Compiler () +validateModuleName what pos name = + unless (validModuleName name) + $ errmsg pos $ "invalid character in " ++ what ++ " name `" ++ name ++ "`" + + +-- |Check that the specified module name is valid, reporting and error if not. +validateModSpec :: OptPos -> ModSpec -> Compiler () +validateModSpec pos = mapM_ (validateModuleName "module" pos) + + -- | Information about a non-constant constructor data CtorInfo = CtorInfo { ctorInfoName :: ProcName, -- ^ this constructor's name diff --git a/test-cases/final-dump/badmodname.exp b/test-cases/final-dump/badmodname.exp new file mode 100644 index 00000000..8d19bf8b --- /dev/null +++ b/test-cases/final-dump/badmodname.exp @@ -0,0 +1,3 @@ +Error detected during preliminary processing of module badmodname +final-dump/badmodname.wybe:6:1: invalid character in module name `a.b` + diff --git a/test-cases/final-dump/badmodname.wybe b/test-cases/final-dump/badmodname.wybe new file mode 100644 index 00000000..2d386906 --- /dev/null +++ b/test-cases/final-dump/badmodname.wybe @@ -0,0 +1,9 @@ +module a { + pub module b { + !print("in a.b") + } +} +module `a.b` { + !print("in `a.b`") +} +pass \ No newline at end of file