ghc-9.6.0.20230111: The GHC API
Copyright(c) The University of Glasgow 2001
LicenseBSD-style (see the file LICENSE)
MaintainerJeffrey Young <jeffrey.young@iohk.io> Luite Stegeman <luite.stegeman@iohk.io> Sylvain Henry <sylvain.henry@iohk.io> Josh Meredith <josh.meredith@iohk.io>
Stabilityexperimental
Safe HaskellSafe-Inferred
LanguageHaskell2010

GHC.JS.Make

Description

  • Domain and Purpose

    GHC.JS.Make defines helper functions to ease the creation of JavaScript ASTs as defined in Syntax. Its purpose is twofold: make the EDSL more ergonomic to program in, and make errors in the EDSL look obvious because the EDSL is untyped. It is primarily concerned with injecting terms into the domain of the EDSL to construct JS programs in Haskell.

  • Strategy

    The strategy for this module comes straight from gentzen; where we have two types of helper functions. Functions which inject terms into the EDSL, and combinator functions which operate on terms in the EDSL to construct new terms in the EDSL. Crucially, missing from this module are corresponding elimination or destructing functions which would project information from the EDSL back to Haskell. See UnitUtils and CoreUtils for such functions.

    • Introduction functions

      We define various primitive helpers which introduce terms in the EDSL, for example jVar, jLam, and var and jString. Notice that the type of each of these functions have the domain isSat a => a -> ...; indicating that they each take something that can be injected into the EDSL domain, and the range JExpr or JStat; indicating the corresponding value in the EDSL domain. Similarly this module exports two typeclasses ToExpr and ToSat, ToExpr injects values as a JS expression into the EDSL. ToSat ensures that terms introduced into the EDSL carry identifier information so terms in the EDSL must have meaning.

    • Combinator functions

      The rest of the module defines combinators which create terms in the EDSL from terms in the EDSL. Notable examples are |= and ||=, |= is sugar for AssignStat, it is a binding form that declares foo = bar assuming foo has been already declared. ||= is more sugar on top of |=, it is also a binding form that declares the LHS of |= before calling |= to bind a value, bar, to a variable foo. Other common examples are the if_ and math_ helpers such as math_cos.

  • Consumers

    The entire JS backend consumes this module, e.g., the modules in GHC.StgToJS.*.

  • Notation

    In this module we use ==> in docstrings to show the translation from the JS EDSL domain to JS code. For example, foo ||= bar ==> var foo; foo = bar; should be read as foo ||= bar is in the EDSL domain and results in the JS code var foo; foo = bar; when compiled.

Synopsis

Injection Type classes

The ToJExpr class handles injection of of things into the EDSL as a JS expression

class ToJExpr a where Source #

Things that can be marshalled into javascript values. Instantiate for any necessary data structures.

Minimal complete definition

toJExpr

Methods

toJExpr :: a -> JExpr Source #

toJExprFromList :: [a] -> JExpr Source #

Instances

Instances details
ToJExpr FastString Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr Ident Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr JExpr Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr JVal Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr Special Source # 
Instance details

Defined in GHC.StgToJS.Regs

ToJExpr StgReg Source # 
Instance details

Defined in GHC.StgToJS.Regs

ToJExpr StgRet Source # 
Instance details

Defined in GHC.StgToJS.Regs

ToJExpr CIStatic Source #

static refs: array = references, null = nothing to report note: only works after all top-level objects have been created

Instance details

Defined in GHC.StgToJS.Types

ToJExpr ClosureType Source # 
Instance details

Defined in GHC.StgToJS.Types

ToJExpr StaticLit Source # 
Instance details

Defined in GHC.StgToJS.Types

ToJExpr VarType Source # 
Instance details

Defined in GHC.StgToJS.Types

ToJExpr Integer Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr () Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: () -> JExpr Source #

toJExprFromList :: [()] -> JExpr Source #

ToJExpr Bool Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr Char Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr Double Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr Int Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr a => ToJExpr [a] Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: [a] -> JExpr Source #

toJExprFromList :: [[a]] -> JExpr Source #

ToJExpr a => ToJExpr (Map String a) Source # 
Instance details

Defined in GHC.JS.Make

ToJExpr a => ToJExpr (UniqMap FastString a) Source # 
Instance details

Defined in GHC.JS.Make

(ToJExpr a, ToJExpr b) => ToJExpr (a, b) Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: (a, b) -> JExpr Source #

toJExprFromList :: [(a, b)] -> JExpr Source #

(ToJExpr a, ToJExpr b, ToJExpr c) => ToJExpr (a, b, c) Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: (a, b, c) -> JExpr Source #

toJExprFromList :: [(a, b, c)] -> JExpr Source #

(ToJExpr a, ToJExpr b, ToJExpr c, ToJExpr d) => ToJExpr (a, b, c, d) Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: (a, b, c, d) -> JExpr Source #

toJExprFromList :: [(a, b, c, d)] -> JExpr Source #

(ToJExpr a, ToJExpr b, ToJExpr c, ToJExpr d, ToJExpr e) => ToJExpr (a, b, c, d, e) Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: (a, b, c, d, e) -> JExpr Source #

toJExprFromList :: [(a, b, c, d, e)] -> JExpr Source #

(ToJExpr a, ToJExpr b, ToJExpr c, ToJExpr d, ToJExpr e, ToJExpr f) => ToJExpr (a, b, c, d, e, f) Source # 
Instance details

Defined in GHC.JS.Make

Methods

toJExpr :: (a, b, c, d, e, f) -> JExpr Source #

toJExprFromList :: [(a, b, c, d, e, f)] -> JExpr Source #

class ToStat a where Source #

The ToStat class handles injection of of things into the EDSL as a JS statement. This ends up being polymorphic sugar for JS blocks, see helper function expr2stat. Instantiate for any necessary data structures.

Methods

toStat :: a -> JStat Source #

Instances

Instances details
ToStat JExpr Source # 
Instance details

Defined in GHC.JS.Make

Methods

toStat :: JExpr -> JStat Source #

ToStat JStat Source # 
Instance details

Defined in GHC.JS.Make

Methods

toStat :: JStat -> JStat Source #

ToStat [JExpr] Source # 
Instance details

Defined in GHC.JS.Make

Methods

toStat :: [JExpr] -> JStat Source #

ToStat [JStat] Source # 
Instance details

Defined in GHC.JS.Make

Methods

toStat :: [JStat] -> JStat Source #

Introduction functions

var :: FastString -> JExpr Source #

construct a JS variable reference

jString :: FastString -> JExpr Source #

Convert a ShortText to a Javascript String

jLam :: ToSat a => a -> JExpr Source #

Create a new anonymous function. The result is a JExpr expression. Usage:

jLam $ \x -> jVar x + one_
jLam $ \f -> (jLam $ \x -> (f `app` (x `app` x))) `app` (jLam $ \x -> (f `app` (x `app` x)))

jVar :: ToSat a => a -> JStat Source #

Introduce a new variable into scope for the duration of the enclosed expression. The result is a block statement. Usage:

jVar $ x y -> mconcat [jVar x ||= one_, jVar y ||= two_, jVar x + jVar y]

jFor :: (ToJExpr a, ToStat b) => JStat -> a -> JStat -> b -> JStat Source #

Create a for statement

jForIn :: ToSat a => JExpr -> (JExpr -> a) -> JStat Source #

Create a 'for in' statement. Usage:

jForIn {expression} $ x -> {block involving x}

jForEachIn :: ToSat a => JExpr -> (JExpr -> a) -> JStat Source #

As with "jForIn" but creating a "for each in" statement.

jTryCatchFinally :: ToSat a => JStat -> a -> JStat -> JStat Source #

As with "jForIn" but creating a "for each in" statement.

Combinators

Combinators operate on terms in the JS EDSL domain to create new terms in the EDSL domain.

(||=) :: Ident -> JExpr -> JStat infixl 2 Source #

Declare a variable and then Assign the variable to an expression

foo |= expr ==> var foo; foo = expr;

(|=) :: JExpr -> JExpr -> JStat infixl 2 Source #

Assign a variable to an expression

foo |= expr ==> var foo = expr;

(.==.) :: JExpr -> JExpr -> JExpr infixl 6 Source #

JS infix Equality operators

(.===.) :: JExpr -> JExpr -> JExpr infixl 6 Source #

JS infix Equality operators

(.!=.) :: JExpr -> JExpr -> JExpr infixl 6 Source #

JS infix Equality operators

(.!==.) :: JExpr -> JExpr -> JExpr infixl 6 Source #

JS infix Equality operators

(.!) :: JExpr -> JExpr -> JExpr infixl 8 Source #

return the expression at idx of obj

obj .! idx ==> obj[idx]

(.>.) :: JExpr -> JExpr -> JExpr infixl 7 Source #

JS infix Ord operators

(.>=.) :: JExpr -> JExpr -> JExpr infixl 7 Source #

JS infix Ord operators

(.<.) :: JExpr -> JExpr -> JExpr infixl 7 Source #

JS infix Ord operators

(.<=.) :: JExpr -> JExpr -> JExpr infixl 7 Source #

JS infix Ord operators

(.<<.) :: JExpr -> JExpr -> JExpr infixl 9 Source #

JS infix bit shift operators

(.>>.) :: JExpr -> JExpr -> JExpr infixl 9 Source #

JS infix bit shift operators

(.>>>.) :: JExpr -> JExpr -> JExpr infixl 9 Source #

JS infix bit shift operators

(.|.) :: JExpr -> JExpr -> JExpr Source #

JS infix bit operators

(.||.) :: JExpr -> JExpr -> JExpr infixl 8 Source #

JS infix bit operators

(.&&.) :: JExpr -> JExpr -> JExpr infixl 8 Source #

JS infix bit operators

if_ :: JExpr -> JExpr -> JExpr -> JExpr Source #

JS if-expression

if_ e1 e2 e3 ==> e1 ? e2 : e3

if10 :: JExpr -> JExpr Source #

if-expression that returns 1 if condition = true, 0 otherwise

if10 e ==> e ? 1 : 0

if01 :: JExpr -> JExpr Source #

if-expression that returns 0 if condition = true, 1 otherwise

if01 e ==> e ? 0 : 1

ifS :: JExpr -> JStat -> JStat -> JStat Source #

If-expression which returns statements, see related ifBlockS

if e s1 s2 ==> if(e) { s1 } else { s2 }

ifBlockS :: JExpr -> [JStat] -> [JStat] -> JStat Source #

If-expression which returns blocks

ifBlockS e s1 s2 ==> if(e) { s1 } else { s2 }

jwhenS :: JExpr -> JStat -> JStat Source #

A when-statement as syntactic sugar via ifS

jwhenS cond block ==> if(cond) { block } else {  }

app :: FastString -> [JExpr] -> JExpr Source #

an expression application, see related appS

app f xs ==> f(xs)

appS :: FastString -> [JExpr] -> JStat Source #

A statement application, see the expression form app

loop :: JExpr -> (JExpr -> JExpr) -> (JExpr -> JStat) -> JStat Source #

"for" loop with increment at end of body

loopBlockS :: JExpr -> (JExpr -> JExpr) -> (JExpr -> [JStat]) -> JStat Source #

"for" loop with increment at end of body

preIncrS :: JExpr -> JStat Source #

Prefix-increment a JExpr

postIncrS :: JExpr -> JStat Source #

Postfix-increment a JExpr

preDecrS :: JExpr -> JStat Source #

Prefix-decrement a JExpr

postDecrS :: JExpr -> JStat Source #

Postfix-decrement a JExpr

off8 :: JExpr -> JExpr -> JExpr Source #

Byte indexing of o with a 8-bit offset

off16 :: JExpr -> JExpr -> JExpr Source #

Byte indexing of o with a 16-bit offset

off32 :: JExpr -> JExpr -> JExpr Source #

Byte indexing of o with a 32-bit offset

off64 :: JExpr -> JExpr -> JExpr Source #

Byte indexing of o with a 64-bit offset

mask8 :: JExpr -> JExpr Source #

a bit mask to retrieve the lower 8-bits

mask16 :: JExpr -> JExpr Source #

a bit mask to retrieve the lower 16-bits

signExtend8 :: JExpr -> JExpr Source #

Sign-extend/narrow a 8-bit value

signExtend16 :: JExpr -> JExpr Source #

Sign-extend/narrow a 16-bit value

typeof :: JExpr -> JExpr Source #

Given a JExpr, return the its type.

nullStat :: JStat Source #

The empty JS statement

(.^) :: JExpr -> FastString -> JExpr infixl 8 Source #

Select a property prop, from and object obj

obj .^ prop ==> obj.prop

trace :: ToJExpr a => a -> JStat Source #

Hash combinators

jhEmpty :: Map k JExpr Source #

The empty JS HashMap

jhSingle :: (Ord k, ToJExpr a) => k -> a -> Map k JExpr Source #

A singleton JS HashMap

jhAdd :: (Ord k, ToJExpr a) => k -> a -> Map k JExpr -> Map k JExpr Source #

insert a key-value pair into a JS HashMap

jhFromList :: [(FastString, JExpr)] -> JVal Source #

Construct a JS HashMap from a list of key-value pairs

Literals

Literals in the JS EDSL are constants in the Haskell domain. These are useful helper values and never change

null_ :: JExpr Source #

The JS literal null

undefined_ :: JExpr Source #

The JS literal undefined

false_ :: JExpr Source #

The JS literal false

true_ :: JExpr Source #

The JS literal true

zero_ :: JExpr Source #

The JS literal 0

one_ :: JExpr Source #

The JS literal 1

two_ :: JExpr Source #

The JS literal 2

three_ :: JExpr Source #

The JS literal 3

Math functions

Math functions in the EDSL are literals, with the exception of math_ which is the sole math introduction function.

Statement helpers

decl :: Ident -> JStat Source #

construct a js declaration with the given identifier

Miscellaneous

Everything else,

Orphan instances