{-#LANGUAGE ScopedTypeVariables #-}moduleText.HPaco.Writers.Run(run,RunState(..),RunOptions(..),defaultOptions,runAST,runStatement,runExpression)whereimportPreludehiding(toInteger)importData.VariantimportqualifiedData.VariantasVimportData.MaybeimportData.MonoidimportqualifiedData.ListasListimportqualifiedData.List.SplitasSplitimportControl.Monad.StateimportSafeimportText.HPaco.Writers.Run.EncodeimportText.HPaco.Writers.Run.LibraryimportText.HPaco.ASTimportText.HPaco.AST.ASTimportText.HPaco.AST.StatementimportText.HPaco.AST.ExpressiondataRunOptions=RunOptions{roTemplateName::String}defaultOptions=RunOptions{roTemplateName="unnamed"}dataRunState=RunState{rsScope::Variant,rsOptions::RunOptions,rsAST::AST}typeRuna=StateTRunStateIOarun::RunOptions->AST->IO()runoptsast=doletst=RunState{rsScope=AList[],rsOptions=opts,rsAST=ast}execStateT(runASTast)streturn()getVar::String->RunVariantgetVar"."=getsrsScopegetVarkey=liftM(V.lookup$Stringkey)(getsrsScope)runAST::AST->Run()runASTast=dorunStatement.astRootStatement$ast-- StatementsrunStatement::Statement->Run()runStatement(PrintStatemente)=dod<-runExpressioneliftIO.putStr.flatten$drunStatement(StatementSequencess)=mapM_runStatementssrunStatement(IfStatementcondtruefalse)=dob<-liftMtoBool$runExpressioncondrunStatement$ifbthentrueelsefalserunStatement(LetStatementidentexprstmt)=runExpressionexpr>>=\e->withIdentifiedScopeidente(runStatementstmt)runStatement(ForStatementNothingidentexprstmt)=does<-runExpressionexprsequence_$vmap(\e->withIdentifiedScopeidente(runStatementstmt))esrunStatement(ForStatement(Justiter)identexprstmt)=does<-runExpressionexprsequence_$vamap(\(k,v)->withIdentifiedScopeiterk$withIdentifiedScopeidentv(runStatementstmt))esrunStatement(SwitchStatementexprbranches)=doev<-runExpressionexprtests<-mapMrunExpression$mapfstbranchesletfteststmt=ifev~==testthenJuststmtelseNothingbranch=headMay$catMaybes$zipWithftests(mapsndbranches)maybe(return())runStatementbranchrunStatementNullStatement=return()runStatement(CallStatementidentifier)=doast<-getsrsASTletbody=fromMaybeNullStatement$List.lookupidentifier$astDefsastrunStatementbodyrunStatementSourcePositionStatement{}=return()-- Scope helpers-- Run with a completely independent scope; do not inherit parent scopewithScope::Variant->Runa->RunawithScopescopeinner=dooldScope<-getsrsScopemodify(\s->s{rsScope=scope})a<-innermodify(\s->s{rsScope=oldScope})returna-- Run with a merged scope, based on local scope and parent scope. The local-- scope has precedence over the inherited one.withInheritingScope::Variant->Runa->RunawithInheritingScopescopeinner=dooldScope<-getsrsScopeletnewScope=V.scopeMergescopeoldScopewithScopenewScopeinnerwithLocalVar::Variant->Variant->Runa->RunawithLocalVarkeyvalinner=withInheritingScope(AList[(key,val)])innerwithIdentifiedScope::String->Variant->Runa->RunawithIdentifiedScopekeyvalinner=ifkey=="."thenwithInheritingScopevalinnerelsewithLocalVar(Stringkey)valinner-- ExpressionsrunExpression::Expression->RunVariantrunExpression(StringLiteralstr)=return$StringstrrunExpression(BooleanLiteralstr)=return$BoolstrrunExpression(IntLiteralstr)=return$IntegerstrrunExpression(FloatLiteralstr)=return$DoublestrrunExpression(ListExpressionitems)=List`liftM`mapMrunExpressionitemsrunExpression(AListExpressionitems)=dolet(keys,values)=unzipitemskeys'<-mapMrunExpressionkeysvalues'<-mapMrunExpressionvaluesreturn.AList$zipkeys'values'runExpression(EscapeExpressionEscapeHTMLe)=(String.htmlEncode.flatten)`liftM`runExpressionerunExpression(EscapeExpressionEscapeURLe)=(String.urlEncode.flatten)`liftM`runExpressionerunExpression(BinaryExpressionopleftright)=dolhs<-runExpressionleftrhs<-runExpressionrightreturn$applyBinaryOperationoplhsrhsrunExpression(UnaryExpressionoparg)=doapplyUnaryOperationop`liftM`runExpressionargrunExpression(VariableReferencevarname)=getVarvarnamerunExpression(FunctionCallExpression(VariableReference"library")(libnameExpr:_))=dolibname<-runExpressionlibnameExprreturn$loadLibrary$V.flattenlibnamerunExpression(FunctionCallExpressionfnargExprs)=dofunc<-runExpressionfnargs<-mapMrunExpressionargExprsreturn$V.callfuncargsapplyBinaryOperation::BinaryOperator->Variant->Variant->VariantapplyBinaryOperationOpPlus=(+)applyBinaryOperationOpMinus=(-)applyBinaryOperationOpMul=(*)applyBinaryOperationOpDiv=\l->\r->iftoDoubler==0.0thenNullelseDouble$toDoublel/toDoublerapplyBinaryOperationOpMod=\l->\r->iftoIntegerr==0thenNullelseInteger$toIntegerl`mod`toIntegerrapplyBinaryOperationOpEquals=\l->\r->Bool$l==rapplyBinaryOperationOpNotEquals=\l->\r->Bool$l/=rapplyBinaryOperationOpLooseEquals=\l->\r->Bool$l~==rapplyBinaryOperationOpLooseNotEquals=\l->\r->Bool$l~/=rapplyBinaryOperationOpLess=\l->\r->Bool$toDoublel<toDoublerapplyBinaryOperationOpNotLess=\l->\r->Bool$toDoublel>=toDoublerapplyBinaryOperationOpGreater=\l->\r->Bool$toDoublel>toDoublerapplyBinaryOperationOpNotGreater=\l->\r->Bool$toDoublel<=toDoublerapplyBinaryOperation(Flippedop)=\l->\r->applyBinaryOperationoprlapplyBinaryOperationOpMember=flipV.lookupapplyBinaryOperationOpInList=V.elemapplyBinaryOperationOpConcat=mappendapplyBinaryOperationOpBooleanAnd=\l->\r->Bool$toBooll&&toBoolrapplyBinaryOperationOpBooleanOr=\l->\r->Bool$toBooll||toBoolrapplyBinaryOperationOpBooleanXor=\l->\r->letlb=toBoollrb=toBoolrinBool$(lb||rb)&&not(lb&&rb)applyUnaryOperationOpNotarg=Bool.not.V.toBool$arg