88
99--}
1010
11-
11+ {-# LANGUAGE FlexibleInstances #-}
12+ {-# LANGUAGE TypeSynonymInstances #-}
1213{-# LANGUAGE OverloadedStrings #-}
1314{-# LANGUAGE DeriveGeneric #-}
1415{-# LANGUAGE LambdaCase #-}
1516module Stack2JS where
1617-- import qualified IR2JS
1718
1819import IR (SerializationUnit (.. ), HFN (.. )
19- , ppId , ppFunCall , ppArgs , Fields (.. ), Ident
20+ , ppFunCall , ppArgs , Fields (.. ), Ident
2021 , serializeFunDef
2122 , serializeAtoms )
2223import qualified Data.ByteString.Lazy.Char8 as BL
@@ -115,6 +116,35 @@ initState = TheState { freshCounter = 0
115116
116117a $$+ b = a $$ (nest 2 b)
117118
119+
120+
121+ class Identifier a where
122+ ppId :: a -> PP. Doc
123+
124+
125+ instance Identifier VarName where
126+ ppId = IR. ppVarName
127+
128+ -- instance Identifier IR.VarAccess where
129+ -- ppId = IR.ppVarAccess
130+
131+ instance Identifier HFN where
132+ ppId (HFN n) = text n
133+
134+ instance Identifier Basics. LibName where
135+ ppId (Basics. LibName s) = text s
136+
137+ instance Identifier Basics. AtomName where
138+ ppId = text
139+
140+ instance Identifier RawVar where
141+ ppId (RawVar x) = text x
142+
143+ instance Identifier Raw. Assignable where
144+ ppId (Raw. AssignableRaw x) = ppId x
145+ ppId (Raw. AssignableLVal x) = ppId x
146+ ppId (Raw. Env ) = text " $env"
147+
118148-- | Translation monad collecting the generated JS parts when passing through the 'StackProgram' tree.
119149class ToJS a where
120150 toJS :: a -> W PP. Doc
@@ -165,7 +195,16 @@ instance ToJS StackUnit where
165195 toJS (AtomStackUnit ca) = toJS ca
166196 toJS (ProgramStackUnit p) = error " not implemented"
167197
198+ instance ToJS IR. VarAccess where
199+ toJS (IR. VarLocal vn) = return $ IR. ppVarName vn
200+ toJS (IR. VarEnv vn) = return $ text " $env." PP. <> (IR. ppVarName vn)
201+ toJS (IR. VarFunSelfRef ) = do
202+ HFN (fname) <- gets stHFN
203+ return $ text fname
204+
168205
206+ -- instance (Identifier a) => ToJS a where
207+ -- toJS x = return $ ppId x
169208
170209ppNamespaceName = text " Top" -- should be generating a new namespace per received blob
171210
@@ -356,18 +395,28 @@ ir2js (StoreStack x i) = return $
356395ir2js (MkFunClosures envBindings funBindings) = do
357396 -- Create new environment
358397 env <- freshEnvVar
398+ dd_env_ids <- ppEnvIds env envBindings
359399 let ppEnv = vcat [ semi $ hsep [ ppLet env
360400 , text " new rt.Env()" ]
361- , ppEnvIds env envBindings ]
401+ , dd_env_ids ]
362402 let ppFF = map (\ (v, f) -> jsClosure v env f) funBindings
363403 return $ vcat (ppEnv : ppFF)
364404
365- where ppEnvIds env ls =
366- vcat (
367- (map (\ (a,b) -> semi $ (ppId env) PP. <> text " ." PP. <> (ppId a) <+> text " =" <+> ppId b ) ls)
368- ++
369- [ppId env PP. <> text " .__dataLevel = " <+> jsFunCall (text $ binOpToJS Basics. LatticeJoin ) (map (\ (_, b) -> ppId b <> text " .dataLevel" ) ls ) ]
370- )
405+ where ppEnvIds :: VarName -> [(VarName , IR. VarAccess )] -> W PP. Doc
406+ ppEnvIds env ls = do
407+ let penv = ppId env
408+ d1 <- mapM (\ (a,b) -> do
409+ d_b <- toJS b
410+ return $ semi $ penv PP. <> text " ." PP. <> (ppId a) <+> text " =" <+> d_b
411+ )
412+ ls
413+ d3 <- mapM (\ (_, b) -> do
414+ d_b <- toJS b
415+ return $ d_b <> text " .dataLevel" ) ls
416+ let d2 = penv PP. <> text " .__dataLevel = "
417+ <+> jsFunCall (text $ binOpToJS Basics. LatticeJoin ) d3
418+
419+ return $ vcat ( d1 ++ [d2])
371420 hsepc ls = semi $ PP. hsep (PP. punctuate (text " ," ) ls)
372421
373422
@@ -480,8 +529,9 @@ tr2js (Error va pos) = return $
480529tr2js (TailCall va1 ) = return $
481530 " return" <+> ppId va1
482531
483- tr2js (LibExport va) = return $
484- jsFunCall (text " return" ) [ppId va]
532+ tr2js (LibExport va) = do
533+ d <- toJS va
534+ return $ jsFunCall (text " return" ) [d]
485535
486536
487537monStateToJs c =
@@ -507,52 +557,72 @@ ppSparseSlot = do
507557-----------------------------------------------------------
508558
509559
510- ppField :: IR. Identifier a => (String , a ) -> PP. Doc
511- ppField (f, v) = PP. brackets $ PP. quotes (text f) <> text " ," <> ppId v
560+ fieldToJS :: ToJS a => (String , a ) -> W PP. Doc
561+ fieldToJS (f, v) = do
562+ d <- toJS v
563+ return $ PP. brackets $ PP. quotes (text f) <> text " ," <> d
512564
513- ppFields :: IR. Identifier a => [(String , a )] -> [PP. Doc ]
514- ppFields fs = PP. punctuate (text " ," ) (map ppField fs)
565+ fieldsToJS :: ToJS a => [(String , a )] -> W [PP. Doc ]
566+ fieldsToJS fs = do
567+ dd <- mapM fieldToJS fs
568+ return $ PP. punctuate (text " ," ) dd
515569
516570instance ToJS RawExpr where
517- toJS = \ case
518- ProjectState c -> return $ monStateToJs c
519- e@ (ProjectLVal _ _) -> return $ ppRawExpr e
520- Bin binop va1 va2 -> return $
521- let text' = (text . binOpToJS) binop in
522- if isInfixBinop binop
523- then hsep [ ppId va1, text', ppId va2 ]
524- else jsFunCall text' [ppId va1, ppId va2]
525- Un op v -> return $ text (unaryOpToJS op) <> PP. parens (ppId v)
526- Tuple vars -> return $
527- text " rt.mkTuple" <> PP. parens (PP. brackets $ PP. hsep $ PP. punctuate (text " ," ) (map ppId vars))
528- Record fields -> return $
529- PP. parens $ text " rt.mkRecord" <> PP. parens (PP. brackets $ PP. hsep $ ppFields fields)
530- WithRecord r fields -> return $
531- text " rt.withRecord" <> PP. parens (
532- PP. hsep [ppId r, text " ," , PP. brackets $ PP. hsep $ ppFields fields ])
533- ProjField x f -> return $
534- text " rt.getField" <> PP. parens (ppId x <> text " ," <> PP. quotes (text f ) )
535- ProjIdx x idx -> return $
536- text " rt.raw_indexTuple" <> PP. parens (ppId x <> text " ," <> text (show idx) )
537- List vars -> return $
538- PP. parens $ text " rt.mkList" <> PP. parens (PP. brackets $ PP. hsep $ PP. punctuate (text " ," ) (map ppId vars))
539- ListCons v1 v2 -> return $
540- text " rt.cons" <> PP. parens (ppId v1 <> text " ," <> ppId v2)
541- Const C. LUnit -> return $ text " rt.__unitbase"
542- Const (C. LLabel s) -> return $
543- text " rt.mkV1Label" <> (PP. parens . PP. doubleQuotes) (text s)
544- Const lit -> do
545- case lit of
546- C. LAtom atom -> tell ([] , [atom], [] )
547- _ -> return ()
548- return $ ppLit lit
549- Lib lib'@ (Basics. LibName libname) varname -> do
550- tell ([LibAccess lib' varname], [] , [] )
551- return $
552- text " rt.loadLib" <> PP. parens ((PP. quotes. text) libname <> text " , " <> (PP. quotes. text) varname <> text " , this" )
553- ConstructLVal r1 r2 r3 -> return $
554- ppFunCall (text " rt.constructLVal" ) (map ppId [r1,r2,r3])
555- Base b -> return $ text " rt." <+> text b -- Note: The "$$authorityarg" case is handled in IR2Raw
571+ toJS x = do
572+ HFN (fname) <- gets stHFN
573+ let ppFunSelfRef = text " $env." PP. <> ppId fname
574+ let ppVarName IR. VarFunSelfRef = ppFunSelfRef
575+ ppVarName x = IR. ppVarAccess x
576+
577+ case x of
578+ ProjectState c -> return $ monStateToJs c
579+ ProjectLVal IR. VarFunSelfRef lf -> return (
580+ case lf of
581+ Raw. FieldValue -> ppFunSelfRef PP. <>
582+ text " ." PP. <> PP. text (show Raw. FieldValue )
583+ Raw. FieldValLev -> monStateToJs MonPC
584+ Raw. FieldTypLev -> monStateToJs MonPC )
585+ e@ (ProjectLVal _ _) -> return $ ppRawExpr e
586+ Bin binop va1 va2 -> return $
587+ let text' = (text . binOpToJS) binop in
588+ if isInfixBinop binop
589+ then hsep [ ppId va1, text', ppId va2 ]
590+ else jsFunCall text' [ppId va1, ppId va2]
591+ Un op v -> return $ text (unaryOpToJS op) <> PP. parens (ppId v)
592+ Tuple vars -> return $
593+ text " rt.mkTuple" <> PP. parens (PP. brackets $ PP. hsep $ PP. punctuate (text " ," ) (map ppVarName vars))
594+ Record fields -> do
595+ jsFields <- fieldsToJS fields
596+ return $
597+ PP. parens $ text " rt.mkRecord" <> PP. parens (PP. brackets $ PP. hsep $ jsFields )
598+ WithRecord r fields -> do
599+ jsFields <- fieldsToJS fields
600+ return $
601+ text " rt.withRecord" <> PP. parens (
602+ PP. hsep [ppId r, text " ," , PP. brackets $ PP. hsep $ jsFields ])
603+ ProjField x f -> return $
604+ text " rt.getField" <> PP. parens (ppId x <> text " ," <> PP. quotes (text f ) )
605+ ProjIdx x idx -> return $
606+ text " rt.raw_indexTuple" <> PP. parens (ppId x <> text " ," <> text (show idx) )
607+ List vars -> return $
608+ PP. parens $ text " rt.mkList" <> PP. parens (PP. brackets $ PP. hsep $ PP. punctuate (text " ," ) (map ppVarName vars))
609+ ListCons v1 v2 -> return $
610+ text " rt.cons" <> PP. parens (ppVarName v1 <> text " ," <> ppId v2)
611+ Const C. LUnit -> return $ text " rt.__unitbase"
612+ Const (C. LLabel s) -> return $
613+ text " rt.mkV1Label" <> (PP. parens . PP. doubleQuotes) (text s)
614+ Const lit -> do
615+ case lit of
616+ C. LAtom atom -> tell ([] , [atom], [] )
617+ _ -> return ()
618+ return $ ppLit lit
619+ Lib lib'@ (Basics. LibName libname) varname -> do
620+ tell ([LibAccess lib' varname], [] , [] )
621+ return $
622+ text " rt.loadLib" <> PP. parens ((PP. quotes. text) libname <> text " , " <> (PP. quotes. text) varname <> text " , this" )
623+ ConstructLVal r1 r2 r3 -> return $
624+ ppFunCall (text " rt.constructLVal" ) (map ppId [r1,r2,r3])
625+ Base b -> return $ text " rt." <+> text b -- Note: The "$$authorityarg" case is handled in IR2Raw
556626
557627
558628
0 commit comments