module HJScript.Lang
(
preinc, postinc, predec, postdec,
(.+.), (.-.), (.*.), (./.), (.&&.), (.||.), (.==.), (.!=.),
(.>.), (.<.) , (.>=.), (.<=.) , (.=.), (.+=.), (?), (<|>),
this, callMethod, callVoidMethod, callProc,
function, procedure, functionDecl, procedureDecl,
for, forIn, forInVar, while, doWhile, doIf, doElse, doIfElse, doIfNoElse, noElse,
var, varWith, inVar, new, delete, ( # ), ( #. ),
rec, first, second, x, y,
( #! ) , jnull, jShow, castObject, hasFeature,
break, continue, true ,ifOp, false, int, float, bool, string,
HJScript, IsHJScript(..),
outputBlock, outputStmt,
evaluateHJScript, evalHJScript,
module Language.HJavaScript.Syntax
) where
import Language.HJavaScript.Syntax
import HJScript.Monad
import Prelude hiding (break)
infixr 2 .||.
infixr 3 .&&.
infix 4 .=. , .==. , .!=., .>., .<. , .<=. , .>=. , ? ,
`doIfNoElse` , `doIfElse`
infixl 6 .+. , .-.
infixl 7 .*., ./.
infixl 8 # , #! , #. , <|>
type HJSJBinOperator t r = Exp t -> Exp t -> Exp r
preinc :: Num t => Var t -> HJScript ()
preinc = outputStmt . ExpStmt . JIncrement Pre
postinc :: Num t => Var t -> HJScript ()
postinc = outputStmt . ExpStmt . JIncrement Pst
predec :: Num t => Var t -> HJScript ()
predec = outputStmt . ExpStmt . JDecrement Pre
postdec :: Num t => Var t -> HJScript ()
postdec = outputStmt . ExpStmt . JDecrement Pst
binOp :: BinOp t r -> HJSJBinOperator t r
binOp op e1 e2 = JBinOp (toExp e1) op (toExp e2)
(.+.) :: PlusOpType a => HJSJBinOperator a a
(.+.) = binOp Plus
(.-.) :: Num a => HJSJBinOperator a a
(.-.) = binOp Minus
(.*.) :: Num a => HJSJBinOperator a a
(.*.) = binOp Times
(./.) :: Num a => HJSJBinOperator a a
(./.) = binOp Div
(.&&.) :: HJSJBinOperator Bool Bool
(.&&.) = binOp And
(.||.) :: HJSJBinOperator Bool Bool
(.||.) = binOp Or
(.==.) :: HJSJBinOperator a Bool
(.==.) = binOp Equals
(.!=.) :: HJSJBinOperator a Bool
(.!=.) = binOp NotEquals
(.>.) :: Num a => HJSJBinOperator a Bool
(.>.) = binOp GThan
(.<.) :: Num a => HJSJBinOperator a Bool
(.<.) = binOp LThan
(.>=.) :: Num a => HJSJBinOperator a Bool
(.>=.) = binOp GEThan
(.<=.) :: Num a => HJSJBinOperator a Bool
(.<=.) = binOp LEThan
(.=.) :: Var t -> Exp t -> HJScript ()
v .=. e = outputStmt . ExpStmt $ JAssign v e
(.+=.) :: Num t => Var t -> Exp t -> HJScript ()
v .+=. e = outputStmt . ExpStmt $ JAssignWith v PlusAssign e
for :: JInt -> JInt -> (JInt -> HJScript t) -> HJScript ()
for from to script = do
name <- newVarName
(_,body) <- hjsInside $ script (val $ JVar name)
outputStmt $ For (pre name) (cond name) (inc name) body
where
inc name = JIncrement Pst (JVar name) :: JInt
pre name = VarDeclAssign name from
cond name = (val $ JVar name) .<=. to
forIn :: (IsDeref d) => d -> (JString -> HJScript ()) -> HJScript ()
forIn obj script =
do v <- var
(_, body) <- hjsInside $ script (val v)
outputStmt $ ForIn v obj body
forInVar :: (IsDeref d) => d -> (Var a -> HJScript ()) -> HJScript ()
forInVar obj script =
do v <- var
(_, body) <- hjsInside $ script (obj # propertyVar (val v))
outputStmt $ ForIn v obj body
while :: JBool -> HJScript t -> HJScript ()
while cond script = do
(_,body) <- hjsInside script
outputStmt $ While cond body
doWhile :: HJScript t -> JBool -> HJScript ()
doWhile = flip while
doIf :: JBool -> HJScript t -> HJScript (Elses ()) -> HJScript ()
doIf cond script els = do
(_,body) <- hjsInside script
els' <- els
outputStmt $ If cond body els'
doElse :: HJScript () -> HJScript (Elses ())
doElse script = do
(_,body) <- hjsInside script
return $ Else body
doIfElse :: JBool -> (HJScript t1, HJScript t2) -> HJScript ()
doIfElse cond (hj1,hj2) = do
(_,body1) <- hjsInside hj1
(_,body2) <- hjsInside hj2
outputStmt $ If cond body1 (Else body2)
(?) :: JBool -> (HJScript t1, HJScript t2) -> HJScript ()
(?) = doIfElse
(<|>) :: a -> a -> (a,a)
(<|>) = (,)
doIfNoElse :: Exp Bool -> HJScript () -> HJScript ()
doIfNoElse cond script = doIf cond script noElse
noElse :: HJScript (Elses ())
noElse = return NoElse
function :: (FormalParams a t, VarsToExps a e) =>
(e -> HJScript (Exp r)) -> HJScript (Exp (t -> r))
function fun = do
n <- newVarNum
let args = mkFParams (\_ -> ()) n
let script = fun $ v2e args
(ret, body) <- hjsInside script
let body' = addReturn ret body
return $ JFunction Nothing args body'
procedure :: (FormalParams a t, VarsToExps a e) =>
(e -> HJScript ()) -> HJScript (Exp (t -> ()))
procedure fun = do
n <- newVarNum
let args = mkFParams (\_ -> ()) n
body <- return . snd =<< (hjsInside $ fun $ v2e args)
return $ JFunction Nothing args body
functionDecl :: (FormalParams a t, VarsToExps a e) =>
String -> (e -> HJScript (Exp r)) -> HJScript ()
functionDecl name fun = do
n <- newVarNum
let args = mkFParams (\_ -> ()) n
let script = fun $ v2e args
(ret,body) <- hjsInside script
let body' = addReturn ret body
outputStmt $ ExpStmt $ JFunction (Just name) args body'
procedureDecl :: (FormalParams a t, VarsToExps a e) =>
String -> (e -> HJScript ()) -> HJScript ()
procedureDecl name fun = do
n <- newVarNum
let args = mkFParams (\_ -> ()) n
let script = fun $ v2e args
(_, body) <- hjsInside script
outputStmt $ ExpStmt $ JFunction (Just name) args body
addReturn :: Exp t -> Block () -> Block t
addReturn e block = Sequence block (Return e)
evaluateHJScript :: HJScript (Exp t) -> Block t
evaluateHJScript m =
let (v,b) = evalHJScript m
in addReturn v b
callMethod :: (IsDeref d, Args e t1) => String -> e -> d -> Exp t2
callMethod = methodCall
callVoidMethod :: (Args e t1, IsDeref a) => String -> e -> a -> HJScript ()
callVoidMethod fun args = outputStmt . ExpStmt . callMethod fun args
var :: HJScript (Var t)
var = do
name <- newVarName
outputStmt $ VarDecl name
return $ JVar name
varWith :: Exp t -> HJScript (Var t)
varWith e = do
name <- newVarName
outputStmt $ VarDeclAssign name e
return $ JVar name
inVar :: Exp t -> HJScript (Exp t)
inVar = fmap val . varWith
this :: IsClass c => Exp c
this = JThis
callProc :: (Args e t) => Exp (t -> t1) -> e -> HJScript ()
callProc e = outputStmt . ExpStmt . (JCall e)
new :: (HasConstructor o e t, Args e t) => o -> e -> HJScript (Exp o)
new o = fmap val . varWith . JNew o
delete :: Var a -> Exp Bool
delete = JDelete
( # ) :: a -> (a -> b) -> b
a # f = f a
( #. ) :: (a -> b) -> (b -> c) -> (a -> c)
( #. ) = flip (.)
rec :: Exp a -> Exp b -> Exp (Rec a b)
rec = JRec
first, x :: Exp (Rec a b) -> Exp a
first = JFst
x = first
second, y :: Exp (Rec a b) -> Exp b
second = JSnd
y = second
( #! ) :: JArray t -> JInt -> Var t
( #! ) = JArrayIndex
jnull :: IsNullable t => Exp t
jnull = JNull
jShow :: JShow t => Exp t -> JString
jShow = JShow
castObject :: (IsClass c1, IsClass c2) => JObject c1 -> JObject c2
castObject = JCastObject
hasFeature :: (IsFeature f , IsClass c) => JObject c -> f -> JBool
hasFeature = JIsImpl
ifOp :: JBool -> Exp t -> Exp t -> Exp t
ifOp = JIfOp
break :: HJScript ()
break = outputStmt Break
continue :: HJScript ()
continue = outputStmt Continue
true :: JBool
true = JBool True
false :: JBool
false = JBool False
int :: Int -> JInt
int = JInt
float :: Float -> JFloat
float = JFloat
bool :: Bool -> JBool
bool = JBool
string :: String -> JString
string = JString