content: {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE MultiParamTypeClasses  #-}
  
  module Language.Wasm.Core (
    toCore,
    Func(..),
    Decl(..),
    Module(..),
    Import(..),
    Export(..),
  
    -- reexport common elements
    Syn.Name(..),
    Syn.Expr(..),
    Syn.Type(..),
    Syn.Value(..),
    {-Syn.Param(..),-}
    Syn.UnOp(..),
    Syn.BinOp(..),
    Syn.RelOp(..),
    Syn.ConvertOp(..)
  ) where
  
  import qualified Language.Wasm.Syntax as Syn
  
  data Decl
    = ModDecl Module
    | ExprDecl Syn.Expr
    deriving (Eq, Show)
  
  data Module = Module
    { _funcs   :: [Func]
    , _imports :: [Import]
    , _exports :: [Export]
    } deriving (Eq, Show)
  
  data Func = Func
    { _fname  :: Maybe Syn.Name
    , _params :: Int
    , _fbody  :: [Syn.Expr]
    } deriving (Eq, Show)
  
  data Import
    = Import Syn.Name Syn.Name
    deriving (Eq, Show)
  
  data Export
    = Export Syn.Name Syn.Name
    deriving (Eq, Show)
  
  -------------------------------------------------------------------------------
  -- Conversion
  -------------------------------------------------------------------------------
  
  toCoreFunc :: Syn.Func -> Func
  toCoreFunc (Syn.Func ftype params _) = Func ftype (length params) body
    where
      body = [f | Syn.Body f <- params]
      result = head [f | Syn.Result f <- params]
  toCoreFunc _ = error "not impelemented"
  
  toCoreExport :: Syn.Func -> Export
  toCoreExport (Syn.Export fname val) = Export (undefined fname) (undefined fname)
  toCoreExport _ = error "not impelemented"
  
  toCoreImport :: Syn.Func -> Import
  toCoreImport _ = undefined
  
  toCoreMod :: Syn.Module -> Module
  toCoreMod (Syn.Module defs) = Module
    { _funcs   = [toCoreFunc f | f@Syn.Func {} <- defs]
    , _imports = [toCoreImport f | f@Syn.Import {} <- defs]
    , _exports = [toCoreExport f | f@Syn.Export {} <- defs]
    }
  
  toCoreDecl :: Syn.Decl -> Decl
  toCoreDecl (Syn.ModDecl mod)  = ModDecl (toCoreMod mod)
  toCoreDecl (Syn.ExprDecl exp) = ExprDecl exp
  
  toCore = toCoreDecl
  
  {-toCore :: [Syn.Decl] -> [Decl]-}
  {-toCore = fmap toCoreDecl-}
  