packages feed

quickjs-hs-0.1: src/Quickjs/Types.hsc

{-# LANGUAGE QuasiQuotes, TemplateHaskell, OverloadedStrings, MultiParamTypeClasses, FlexibleInstances, GeneralizedNewtypeDeriving #-}

module Quickjs.Types where

import qualified Data.Map                  as Map
import           Data.Bits                 (Bits)
import           Foreign.C.Types
import           Foreign.Ptr               (plusPtr)
import           Foreign.Storable          (Storable(..))
import qualified Language.Haskell.TH       as TH
import           Language.C.Inline
import           Language.C.Inline.Context
import qualified Language.C.Types          as C

#include "quickjs.h"

data JSValue = JSValue
  { u :: {-# UNPACK #-} !CDouble
  , tag :: {-# UNPACK #-} !CLong
  } deriving (Show, Eq)

instance Storable JSValue where
  sizeOf _ = #{size JSValue}
  alignment _ = #{alignment JSValue}
  peek ptr = do
    u <- peek (#{ptr JSValue, u} ptr)
    tag <- peek (#{ptr JSValue, tag} ptr)
    Prelude.pure (JSValue u tag)
  poke ptr (JSValue u tag) = do
    poke (#{ptr JSValue, u} ptr) u
    poke (#{ptr JSValue, tag} ptr) tag

type JSValueConst = JSValue

newtype JSRuntime = JSRuntime { _unusedRuntime :: CUChar }

newtype JSContext = JSContext { _unusedContext :: CUChar }


type JSBool = CInt

type JSAtom = CUInt


data JSPropertyEnum = JSPropertyEnum
  { is_enumerable :: {-# UNPACK #-} !JSBool
  , atom :: {-# UNPACK #-} !JSAtom
  } deriving (Show, Eq)

instance Storable JSPropertyEnum where
  sizeOf _ = #{size JSPropertyEnum}
  alignment _ = #{alignment JSPropertyEnum}
  peek ptr = do
    is_enumerable <- peek (#{ptr JSPropertyEnum, is_enumerable} ptr)
    atom <- peek (#{ptr JSPropertyEnum, atom} ptr)
    Prelude.pure (JSPropertyEnum is_enumerable atom)
  poke ptr (JSPropertyEnum is_enumerable atom) = do
    poke (#{ptr JSPropertyEnum, is_enumerable} ptr) is_enumerable
    poke (#{ptr JSPropertyEnum, atom} ptr) atom



data JSRefCountHeader = JSRefCountHeader
  { ref_count :: {-# UNPACK #-} !CInt
  } deriving (Show, Eq)

instance Storable JSRefCountHeader where
  sizeOf _ = #{size JSRefCountHeader}
  alignment _ = #{alignment JSRefCountHeader}
  peek ptr = do
    ref_count <- peek (#{ptr JSRefCountHeader, ref_count} ptr)
    Prelude.pure (JSRefCountHeader ref_count)
  poke ptr (JSRefCountHeader ref_count) = do
    poke (#{ptr JSRefCountHeader, ref_count} ptr) ref_count



class ToCType ty cty where
  toCType :: ty -> cty


class FromCType ty cty where
  fromCType :: cty -> Maybe ty


data JSTagEnum = JSTagFirst
               | JSTagBigDecimal
               | JSTagBigInt
               | JSTagBigFloat
               | JSTagSymbol
               | JSTagString
               | JSTagModule
               | JSTagFunctionBytecode
               | JSTagObject
               | JSTagInt
               | JSTagBool
               | JSTagNull
               | JSTagUndefined
               | JSTagUninitialized
               | JSTagCatchOffset
               | JSTagException
               | JSTagFloat64
  deriving (Show, Eq)
  
instance Num a => ToCType JSTagEnum a where
  toCType JSTagFirst            = #{const JS_TAG_FIRST}
  toCType JSTagBigDecimal       = #{const JS_TAG_BIG_DECIMAL}
  toCType JSTagBigInt           = #{const JS_TAG_BIG_INT}
  toCType JSTagBigFloat         = #{const JS_TAG_BIG_FLOAT}
  toCType JSTagSymbol           = #{const JS_TAG_SYMBOL}
  toCType JSTagString           = #{const JS_TAG_STRING}
  toCType JSTagModule           = #{const JS_TAG_MODULE}
  toCType JSTagFunctionBytecode = #{const JS_TAG_FUNCTION_BYTECODE}
  toCType JSTagObject           = #{const JS_TAG_OBJECT}
  toCType JSTagInt              = #{const JS_TAG_INT}
  toCType JSTagBool             = #{const JS_TAG_BOOL}
  toCType JSTagNull             = #{const JS_TAG_NULL}
  toCType JSTagUndefined        = #{const JS_TAG_UNDEFINED}
  toCType JSTagUninitialized    = #{const JS_TAG_UNINITIALIZED}
  toCType JSTagCatchOffset      = #{const JS_TAG_CATCH_OFFSET}
  toCType JSTagException        = #{const JS_TAG_EXCEPTION}
  toCType JSTagFloat64          = #{const JS_TAG_FLOAT64}


instance (Eq a, Num a) => FromCType JSTagEnum a where
  fromCType (#{const JS_TAG_BIG_DECIMAL}) = Just JSTagBigDecimal
  fromCType (#{const JS_TAG_BIG_INT}) = Just JSTagBigInt
  fromCType (#{const JS_TAG_BIG_FLOAT}) = Just JSTagBigFloat
  fromCType (#{const JS_TAG_SYMBOL}) = Just JSTagSymbol
  fromCType (#{const JS_TAG_STRING}) = Just JSTagString
  fromCType (#{const JS_TAG_MODULE}) = Just JSTagModule
  fromCType (#{const JS_TAG_FUNCTION_BYTECODE}) = Just JSTagFunctionBytecode
  fromCType (#{const JS_TAG_OBJECT}) = Just JSTagObject
  fromCType (#{const JS_TAG_INT}) = Just JSTagInt
  fromCType (#{const JS_TAG_BOOL}) = Just JSTagBool
  fromCType (#{const JS_TAG_NULL}) = Just JSTagNull
  fromCType (#{const JS_TAG_UNDEFINED}) = Just JSTagUndefined
  fromCType (#{const JS_TAG_UNINITIALIZED}) = Just JSTagUninitialized
  fromCType (#{const JS_TAG_CATCH_OFFSET}) = Just JSTagCatchOffset
  fromCType (#{const JS_TAG_EXCEPTION}) = Just JSTagException 
  fromCType (#{const JS_TAG_FLOAT64}) = Just JSTagFloat64
  fromCType _ = Nothing

data JSTypeEnum = JSTypeFromTag JSTagEnum
                | JSIsNumber
                | JSIsArray
                | JSIsDate
                | JSIsError
  deriving Show

data JSEvalType = Global | Module

  
instance Num a => ToCType JSEvalType a where
  toCType Global = #{const JS_EVAL_TYPE_GLOBAL}
  toCType Module = #{const JS_EVAL_TYPE_MODULE}


newtype JSGPNMask = JSGPNMask { unJSGPNMask :: CInt }
  deriving (Eq, Bits)

#{enum JSGPNMask, JSGPNMask
, jsGPNStringMask  = JS_GPN_STRING_MASK
, jsGPNSymbolMask  = JS_GPN_SYMBOL_MASK
, jsGPNPrivateMask = JS_GPN_PRIVATE_MASK
, jsGPNEnumOnly    = JS_GPN_ENUM_ONLY
, jsGPNSetEnum     = JS_GPN_SET_ENUM
}


quickjsCtx :: Context
quickjsCtx = baseCtx <> fptrCtx <> ctx
  where
    ctx = mempty
      { ctxTypesTable = quickjsTypesTable
      }

quickjsTypesTable :: Map.Map C.TypeSpecifier TH.TypeQ
quickjsTypesTable = Map.fromList
  [ 
    (C.TypeName "JSValue", [t| JSValue |])
  , (C.TypeName "JSValueConst", [t| JSValueConst |])
  , (C.TypeName "JSRuntime", [t| JSRuntime |])
  , (C.TypeName "JSContext", [t| JSContext |])
  , (C.TypeName "JSBool", [t| JSBool |])
  , (C.TypeName "JSAtom", [t| JSAtom |])
  , (C.TypeName "JSPropertyEnum", [t| JSPropertyEnum |])
  ]