070: t4.4.3.1a.hs で qname not found: ##

↑up

概要

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 はコンパイルエラーにならなければいけない。

2020-05-10 (Sun)

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。

2020-05-11 (Mon)

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 は、期待通りエラーはするが、エラーの仕方はいまいちな気はする。

が、本件はクローズ。