Writing a simple Core evaluator, having trouble with name lookups

Christopher Done chrisdone at gmail.com
Fri Nov 30 11:23:45 UTC 2018


Hi Csaba,

Thanks for your answer. I think I'm doing something very similar to
you. I'm converting the GHC AST to my own AST with this code:

https://gist.github.com/chrisdone/96e228f12bdbc3c43d06718467e69029#file-main-hs-L815--L915

I have an Id type that's similar to yours,

    data Id = Id
      { idStableName :: {-# UNPACK #-}!ByteString
      , idUnique :: {-# UNPACK #-}!Unique
      , idCategory :: !Cat
      } deriving (Generic, Data, Typeable, Eq, Show, Ord)

And (I think) I've solved my first question by adding that category
field, which can be one of:

    data Cat
      = ValCat
      | DataCat
      | ClassCat
      deriving (Generic, Data, Typeable, Eq, Show, Ord)

When an expression like this comes along:

    AppE
      (AppE
         (VarE
            (Id
               { idStableName = "main:Main.C:Wiggle"
               , idUnique = Unique 8214565720323785205
               , idCategory = ClassCat
               }))
         (TypE (Typ "Int")))
      (VarE
         (Id
            { idStableName = "main:Main.$cfoo"
            , idUnique = Unique 6989586621679010971
            , idCategory = ValCat
            }))
      VarE
      (Id
         { idStableName = "main:Main.$cbar"
         , idUnique = Unique 6989586621679010975
         , idCategory = ValCat
         })

It constructs a class dictionary for the class "Wiggle", with the
methods "foo" and "bar", and the interpreter treats Wiggle as a regular
data constructor. Meanwhile, when an nth class method (like
"main:Main.$cfoo") is resolved, it produces a Method, and when applying
a method to a data constructor Wiggle, the interpreter access the nth
slot.

That works out. An example is here:

https://gist.github.com/chrisdone/771292425a9f1bb428ef4eda3779dc40

See how the "main:Main.$fWiggleInt" is resolved to the above dictionary.

As for the second question, and your answer, I am a bit puzzled, maybe
you can clarify?

> Regarding the names you can use qualified (module + occ) names for
> exported ids. (see: Var.isExportedId).
>
> For non exported Id's you can rely on unique values.

You say that for exported names I can rely soley on the stable name
(package+module+ident), and for internal IDs I can use the Unique?

I believe that's what I'm reproducing, here. The following name isn't
resolved:

    Id
      { idStableName = "base:GHC.Base.$fApplicativeIO"
      , idUnique = Unique 8214565720323784738
      , idCategory = ValCat
      }

If I list all bindings available, I find this name, which has a
different Unique:

    Id
      { idStableName = "base:GHC.Base.$fApplicativeIO"
      , idUnique = Unique 8214565720323793553 <--- differing
      , idCategory = ValCat
      }

So if I were to apply your approach and do exported lookups by
idStableName, and local-module lookups (beta substitution) by Unique, it
should work out.

The question is whether "base:GHC.Base.$fApplicativeIO" is actually
exported -- I presume all instance dictionaries are exported.

I will give it a try and report back to you!

Cheers!


More information about the ghc-devs mailing list