# 070: t4.4.3.1a.hs で qname not found: ## [↑up](bunny_notes) - issued: 2020-05-09 - 分類: A サンプルコードが fail - status: Closed (2020-05-11) ## 概要 [068](bissue068) 関連。 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

[069](bissue069) の対処でこちらも Ok になるかと期待したがだめだった。

最初、## の qname がみつからないというので resolveFixity でひっかかっていたのを、
仮対処的に回避してみた(see [071](bissue071)) が、こんどは、(:) の名前解決で引っかかっているよう。

$$
{
$ ./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

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 についても同様に対処。

- t4.4.3.1a.hs -> sample189.hs
- t4.4.3.1a2.hs -> sample190.hs
- t4.4.3.1b.hs -> sample191.hs

sample191.hs は、期待通りエラーはするが、エラーの仕方はいまいちな気はする。

が、本件はクローズ。