068 関連。
Language Report 4.4.3.1 にある例 a ## b : xs = exp のうち、 コンパイルできなければいけないケースで失敗:
$ ./tcheck testcases/t4.4.3.1a.hs # 1. test-compile source file: testcases/t4.4.3.1a.hs dst dir: /t4.4.3.1a doCompile ... done. implicitPrelude ... done. doCompile ... bunnyc.exe: qname not found: ## CallStack (from HasCallStack): error, called at src\RenUtil.hs:126:26 in main:RenUtil
なお、t4.3.3.1b.hs はコンパイルエラーにならなければいけない。
069 の対処でこちらも Ok になるかと期待したがだめだった。
最初、## の qname がみつからないというので resolveFixity でひっかかっていたのを、 仮対処的に回避してみた(see 071) が、こんどは、(:) の名前解決で引っかかっているよう。
$ ./tcheck testcases/t4.4.3.1a.hs # 1. test-compile source file: testcases/t4.4.3.1a.hs dst dir: /t4.4.3.1a doCompile ... done. implicitPrelude ... done. doCompile ... bunnyc: findCMs failed: "Main.:" CallStack (from HasCallStack): error, called at src/Rename.hs:506:28 in main:Rename
なお、t4.4.3.1a2.hs では OK。
t4.4.3.1a2.hs では OK なので、それとの違いに着目したい。
renDecl に以下のように trace を仕込んで様子をみる:
renDecl (A.ValDecl expr rhs) = do enterNewLevel trace ("renDecl: expr = " ++ show expr) $ return () expr' <- removeInfix expr trace ("renDecl: expr' = " ++ show expr') $ return () (n, pats) <- renFExp expr' rexp <- renRhs rhs exitLevel return [(n, Nothing, [(pats, rexp)])]
まずは、大丈夫なほう t4.3.3.1.a2 での:
renDecl: expr = InfixExp (VarExp (Name {origName = "a", namePos = (1,1), isConName = False})) (Name {origName = "##", namePos = (1,3), isConName = False}) (ParExp (InfixExp (VarExp (Name {origName = "b", namePos = (1,7), isConName = False})) (Name {origName = ":", namePos = (1,9), isConName = True}) (VarExp (Name {origName = "xs", namePos = (1,11), isConName = False})))) renDecl: expr' = FunAppExp (FunAppExp (VarExp (Name {origName = "##", namePos = (1,3), isConName = False})) (VarExp (Name {origName = "a", namePos = (1,1), isConName = False}))) (FunAppExp (FunAppExp (VarExp (Name {origName = ":", namePos = (1,9), isConName = True})) (VarExp (Name {origName = "b", namePos = (1,7), isConName = False}))) (VarExp (Name {origName = "xs", namePos = (1,11), isConName = False})))
次に、だめな t4.3.3.1.a.hs での:
renDecl: expr = InfixExp (InfixExp (VarExp (Name {origName = "a", namePos = (2,1), isConName = False})) (Name {origName = "##", namePos = (2,3), isConName = False}) (VarExp (Name {origName = "b", namePos = (2,6), isConName = False}))) (Name {origName = ":", namePos = (2,8), isConName = True}) (VarExp (Name {origName = "xs", namePos = (2,10), isConName = False})) renDecl: expr' = FunAppExp (FunAppExp (VarExp (Name {origName = "##", namePos = (2,3), isConName = False})) (VarExp (Name {origName = "a", namePos = (2,1), isConName = False}))) (FunAppExp (FunAppExp (VarExp (Name {origName = ":", namePos = (2,8), isConName = True})) (VarExp (Name {origName = "b", namePos = (2,6), isConName = False}))) (VarExp (Name {origName = "xs", namePos = (2,10), isConName = False})))
こちらは、bunnyc: findCMs failed: "Main.:" となってエラーする。
うえの2つを見比べると、expr' は同じだ。(期待通り)
ってことは、expr' の形がおかしいのではなく、この時点で ":" の qname として、 "Main.:" を誤って登録してしまっている、ということになりそう。
被疑個所はわかった。scanDecl で、fixity Resolution まえに extrName が あやまって ":" を抽出、それを renameVar しているので、そこで ":" -> "Main.:" とあやまって登録されてしまっている。
scandecl (A.VDecl d@(A.ValDecl e _)) = do _ <- renameVar (extrName e) return ([d], [], [])
extrName は InfixExp から名前を抽出しないことにし、renameVar もそれに対応する… とかで対処もできそうだが、そもそも、1 パス目に rename しようとするのが間違いという 感もあって、むずかしい。extrName は他の場所でも使っているので、 影響範囲の見極めも必要。
scanDecl の中を2パスにした:
scanDecls :: [A.Decl] -> RN ([A.ValueDecl], [A.ClassDecl], [A.InstDecl]) scanDecls ds = do r <- mapM scandecl ds let (dss, cdss, idss) = unzip3 r ds = concat dss cds = concat cdss ids = concat idss ds' <- mapM scanValueDecl2 ds cds' <- mapM scanClassDecl2 cds ids' <- mapM scanInstDecl2 ids return (ds', cds', ids')
scandecl では、まだ infix 宣言が出そろっていない可能性があるため、 ValueDecl から正確に左辺の関数名を抽出できない (a ## b : xs のうち、どちらを定義したいのかは、fixity resolution を正しく行わないとわからない)。
なので、scandecl で renameVar していたのはやめ、あとで scanValueDecl2 内で fixity resolution, および、infix 式の除去をしたうえで、 名前の登録を実施した。
class decls, inst decls についても同様に対処。
sample191.hs は、期待通りエラーはするが、エラーの仕方はいまいちな気はする。
が、本件はクローズ。