From d16dc06380e7b86fdd38eed09616045119df42b4 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 02:21:26 +0100 Subject: [PATCH 01/12] patch (reworked) Render.hs, get less parentheses/brackets fix issue [#3](https://code.google.com/p/lslforge/issues/detail?id=3) - make it work on OSGrid - fix cast of cast blame [pells...@gmail.com](https://code.google.com/u/101374969631348043816/) taken from https://github.com/RayZopf/LSLForge_patched/commit/a037e49476ada47386aba879626d96f3229f1da3 https://github.com/RayZopf/LSLForge_patched/commit/8a3fbc15e233c080763c732d30d5b182ab0e5b6f --- lslforge/haskell/src/Language/Lsl/Render.hs | 206 ++++++++++++++------ 1 file changed, 145 insertions(+), 61 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 09c65a1..2b068a5 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -142,72 +142,77 @@ renderCtxExpr (Ctx _ e) = renderExpression e renderCtxExprs prefix [] = blank renderCtxExprs prefix (e:es) = renderString prefix . renderCtxExpr e . renderCtxExprs "," es -renderExpression (IntLit i) = shows i -renderExpression (FloatLit f) = shows f -renderExpression (StringLit s) = renderString ('"':go s) - where go [] = "\"" - go ('\\':s) = '\\':'\\':go s - go ('\t':s) = '\\':'t':go s - go ('\n':s) = '\\':'n':go s - go ('"':s) = '\\':'"':go s - go (c:s) = c:go s -renderExpression (KeyLit k) = shows k -renderExpression (VecExpr x y z) = - renderChar '<' . renderCtxExpr x . renderChar ',' . - renderCtxExpr y . renderChar ',' . - renderCtxExpr z . renderChar '>' -renderExpression (RotExpr x y z s) = - renderChar '<' . renderCtxExpr x . renderChar ',' . - renderCtxExpr y . renderChar ',' . - renderCtxExpr z . renderChar ',' . - renderCtxExpr s . renderChar '>' -renderExpression (ListExpr l) = - let r prefix [] = blank - r prefix (i:is) = renderString prefix . renderCtxExpr i . r "," is - in renderChar '[' . r "" l . renderChar ']' -renderExpression (Add expr1 expr2) = renderBinExpr "+" expr1 expr2 -renderExpression (Sub expr1 expr2) = renderBinExpr "-" expr1 expr2 -renderExpression (Mul expr1 expr2) = renderBinExpr "*" expr1 expr2 -renderExpression (Div expr1 expr2) = renderBinExpr "/" expr1 expr2 -renderExpression (Mod expr1 expr2) = renderBinExpr "%" expr1 expr2 -renderExpression (BAnd expr1 expr2) = renderBinExpr "&" expr1 expr2 -renderExpression (Xor expr1 expr2) = renderBinExpr "^" expr1 expr2 -renderExpression (BOr expr1 expr2) = renderBinExpr "|" expr1 expr2 -renderExpression (Lt expr1 expr2) = renderBinExpr "<" expr1 expr2 -renderExpression (Gt expr1 expr2) = renderBinExpr ">" expr1 expr2 -renderExpression (Le expr1 expr2) = renderBinExpr "<=" expr1 expr2 -renderExpression (Ge expr1 expr2) = renderBinExpr ">=" expr1 expr2 -renderExpression (And expr1 expr2) = renderBinExpr "&&" expr1 expr2 -renderExpression (Or expr1 expr2) = renderBinExpr "||" expr1 expr2 -renderExpression (ShiftL expr1 expr2) = renderBinExpr "<<" expr1 expr2 -renderExpression (ShiftR expr1 expr2) = renderBinExpr ">>" expr1 expr2 -renderExpression (Inv expr) = renderChar '(' . renderChar '~' . renderCtxExpr expr . renderChar ')' -renderExpression (Not expr) = renderChar '(' . renderChar '!' . renderCtxExpr expr . renderChar ')' -renderExpression (Neg expr) = renderChar '(' . renderChar '-' . renderCtxExpr expr . renderChar ')' -renderExpression (Call name exprs) = renderCtxName name . renderChar '(' . renderCtxExprs "" exprs . renderChar ')' -renderExpression (Cast t expr) = renderString "((" . renderType t . renderChar ')' . renderCtxExpr expr . renderChar ')' -renderExpression (Get var) = renderVarAccess var +renderExpression ex = case ex of + (IntLit i) -> shows i + (FloatLit f) -> shows f + (StringLit s) -> renderString ('"':go s) + where go [] = "\"" + go ('\\':s) = '\\':'\\':go s + go ('\t':s) = '\\':'t':go s + go ('\n':s) = '\\':'n':go s + go ('"':s) = '\\':'"':go s + go (c:s) = c:go s + (KeyLit k) -> shows k + (VecExpr x y z) -> + renderChar '<' . renderCtxExpr x . renderChar ',' . + renderCtxExpr y . renderChar ',' . + renderCtxExpr z . renderChar '>' + (RotExpr x y z s) -> + renderChar '<' . renderCtxExpr x . renderChar ',' . + renderCtxExpr y . renderChar ',' . + renderCtxExpr z . renderChar ',' . + renderCtxExpr s . renderChar '>' + (ListExpr l) -> + let r prefix [] = blank + r prefix (i:is) = renderString prefix . renderCtxExpr i . r "," is + in renderChar '[' . r "" l . renderChar ']' + (Add expr1 expr2) -> renderBinExpr "+" expr1 expr2 lo + (Sub expr1 expr2) -> renderBinExpr "-" expr1 expr2 lo + (Mul expr1 expr2) -> renderBinExpr "*" expr1 expr2 lo + (Div expr1 expr2) -> renderBinExpr "/" expr1 expr2 lo + (Mod expr1 expr2) -> renderBinExpr "%" expr1 expr2 lo + (BAnd expr1 expr2) -> renderBinExpr "&" expr1 expr2 lo + (Xor expr1 expr2) -> renderBinExpr "^" expr1 expr2 lo + (BOr expr1 expr2) -> renderBinExpr "|" expr1 expr2 lo + (Lt expr1 expr2) -> renderBinExpr "<" expr1 expr2 lo + (Gt expr1 expr2) -> renderBinExpr ">" expr1 expr2 lo + (Le expr1 expr2) -> renderBinExpr "<=" expr1 expr2 lo + (Ge expr1 expr2) -> renderBinExpr ">=" expr1 expr2 lo + (And expr1 expr2) -> renderBinExpr "&&" expr1 expr2 lo + (Or expr1 expr2) -> renderBinExpr "||" expr1 expr2 lo + (ShiftL expr1 expr2) -> renderBinExpr "<<" expr1 expr2 lo + (ShiftR expr1 expr2) -> renderBinExpr ">>" expr1 expr2 lo + (Inv expr) -> renderChar '~' . renderInParenIfLower expr lo + (Not expr) -> renderChar '!' . renderInParenIfLower expr lo + (Neg expr) -> renderChar '-' . renderInParenIfLower expr lo + (Call name exprs) -> renderCtxName name . renderChar '(' . renderCtxExprs "" exprs . renderChar ')' + (Cast t expr) -> renderChar '(' . renderType t . renderChar ')' . + renderInParenIfLower expr lo + (Get var) -> renderVarAccess var --renderExpression (Const var) = renderVarAccess var --renderExpression (Set var expr) = renderChar '(' . renderVarAccess var . renderString " = " . renderCtxExpr expr . renderChar ')' -renderExpression (Set va expr) = renderAssignment va "=" expr -renderExpression (IncBy va expr) = renderAssignment va "+=" expr -renderExpression (DecBy va expr) = renderAssignment va "-=" expr -renderExpression (MulBy va expr) = renderAssignment va "*=" expr -renderExpression (DivBy va expr) = renderAssignment va "/=" expr -renderExpression (ModBy va expr) = renderAssignment va "%=" expr -renderExpression (Equal expr1 expr2) = renderBinExpr "==" expr1 expr2 -renderExpression (NotEqual expr1 expr2) = renderBinExpr "!=" expr1 expr2 -renderExpression (PostInc va) = renderInParens (renderVarAccess va . renderString "++") -renderExpression (PostDec va) = renderInParens (renderVarAccess va . renderString "--") -renderExpression (PreInc va) = renderInParens (renderString "++" . renderVarAccess va) -renderExpression (PreDec va) = renderInParens (renderString "--" . renderVarAccess va) + (Set va expr) -> renderAssignment va "=" expr + (IncBy va expr) -> renderAssignment va "+=" expr + (DecBy va expr) -> renderAssignment va "-=" expr + (MulBy va expr) -> renderAssignment va "*=" expr + (DivBy va expr) -> renderAssignment va "/=" expr + (ModBy va expr) -> renderAssignment va "%=" expr + (Equal expr1 expr2) -> renderBinExpr "==" expr1 expr2 lo + (NotEqual expr1 expr2) -> renderBinExpr "!=" expr1 expr2 lo + (PostInc va) -> renderVarAccess va . renderString "++" + (PostDec va) -> renderVarAccess va . renderString "--" + (PreInc va) -> renderString "++" . renderVarAccess va + (PreDec va) -> renderString "--" . renderVarAccess va + where + lo = \ t -> isLower ex t || needsBooleanParens ex t || castCast ex t renderInParens f = renderChar '(' . f . renderChar ')' -renderBinExpr op expr1 expr2 = renderChar '(' . renderCtxExpr expr1 . renderChar ' ' . - renderString op . renderChar ' ' . renderCtxExpr expr2 . renderChar ')' +renderBinExpr op expr1 expr2 f = + renderInParenIfLower expr1 f . renderChar ' ' . renderString op . renderChar ' ' . + renderInParenIfLower expr2 f renderAssignment va op expr = - renderChar '(' . renderVarAccess va . renderChar ' ' . renderString op . renderChar ' ' . renderCtxExpr expr . renderChar ')' + renderVarAccess va . renderChar ' ' . renderString op . renderChar ' ' . renderCtxExpr expr renderComponent All = blank renderComponent X = renderString ".x" renderComponent Y = renderString ".y" @@ -233,4 +238,83 @@ renderPreText :: (Maybe SourceContext) -> String -> String renderPreText = maybe (renderString "\n") (renderString . srcPreText) renderPreText1 :: (String -> String) -> (Maybe SourceContext) -> String -> String -renderPreText1 f = maybe (renderString "\n" . f) (renderString . srcPreText) \ No newline at end of file +renderPreText1 f = maybe (renderString "\n" . f) (renderString . srcPreText) + +-- Wrap with parentheses if lower precedence + +renderInParenIfLower :: (Ctx Expr) -> ((Ctx Expr) -> Bool) -> String -> String +renderInParenIfLower ce f = + if f ce then renderChar '(' . renderCtxExpr ce . renderChar ')' + else renderCtxExpr ce + +needsBooleanParens :: Expr -> Ctx Expr -> Bool +needsBooleanParens ex0 (Ctx _ ex1) = + case ex0 of + (And _ _) -> case ex1 of + (Or _ _) -> True + _ -> False + (Or _ _) -> case ex1 of + (And _ _) -> True + _ -> False + _ -> False + +castCast :: Expr -> Ctx Expr -> Bool +castCast ex0 (Ctx _ ex1) = + case ex0 of + (Cast _ _) -> case ex1 of + (Cast _ _) -> True + _ -> False + _ -> False + +-- Comparing Order of Precedence + +isLower :: Expr -> (Ctx Expr) -> Bool +isLower e0 (Ctx _ e1) = prec e0 < prec e1 + +-- Smaller number is higher precedence + +prec :: Expr -> Int +prec e = + case e of + (IntLit _) -> 0 + (FloatLit _) -> 0 + (StringLit _) -> 0 + (ListExpr _) -> 0 + (VecExpr _ _ _) -> 0 + (RotExpr _ _ _ _) -> 0 + (KeyLit _) -> 0 + (Call _ _) -> 0 + (Cast _ _) -> 1 + (Not _) -> 2 + (Inv _) -> 2 + (Neg _) -> 2 + (PostInc _) -> 2 + (PostDec _) -> 2 + (PreInc _) -> 2 + (PreDec _) -> 2 + (Mul _ _) -> 3 + (Div _ _) -> 3 + (Mod _ _) -> 3 + (Add _ _) -> 4 + (Sub _ _) -> 4 + (ShiftL _ _) -> 5 + (ShiftR _ _) -> 5 + (Lt _ _) -> 6 + (Le _ _) -> 6 + (Gt _ _) -> 6 + (Ge _ _) -> 6 + (Equal _ _) -> 7 + (NotEqual _ _) -> 7 + (BAnd _ _) -> 8 + (Xor _ _) -> 9 + (BOr _ _) -> 10 + (And _ _) -> 11 -- usually And is higher than Or, + (Or _ _) -> 11 -- this seems bug of LSL Compiler. see SVC-779 + (Get _) -> 0 + (Set _ _) -> 12 + (IncBy _ _) -> 12 + (DecBy _ _) -> 12 + (MulBy _ _) -> 12 + (DivBy _ _) -> 12 + (ModBy _ _) -> 12 + _ -> 0 \ No newline at end of file From 067cb56e40bae6282e6b5c7b0a9a981511c701c0 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 02:45:22 +0100 Subject: [PATCH 02/12] get comment/version added to lsl script output modify Render.hs so that version of used LSLForge (executable/preprocessor) is stated in processed lsl script - 'Render.hs' should be removed for release/when in sync - LslForge.hs needs to be kept in sync - should be kept in sync with LSLForge.cabal version number too taken from https://github.com/RayZopf/LSLForge_patched/commit/7053b6578837f9528ec10e4cf41328642753286f --- lslforge/haskell/src/Language/Lsl/Render.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 2b068a5..67889f3 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -10,7 +10,7 @@ tr s x = trace (s ++ show x) x -- and a compiled (i.e. validated, with referenced modules included) LSL script. renderCompiledScript :: String -> CompiledLSLScript -> String renderCompiledScript stamp (CompiledLSLScript comment globals funcs states) = - (renderString "// LSL script generated: " . renderString stamp . renderString "\n" . + (renderString "// LSL script generated - LSLForge Render.hs (0.1.3.2): " . renderString stamp . renderString "\n" . renderString comment . renderGlobals globals . renderFuncs funcs . renderStates states . renderString "\n") "" From eaeacf07ef2f61396ef90ab00cf492a44ff3f461 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 02:47:45 +0100 Subject: [PATCH 03/12] sync version number - LslForge.hs (0.1.3.2) taken from https://github.com/RayZopf/LSLForge_patched/commit/93fadd750c1190b6d9ecc0b6f92b155e8f0e58de --- lslforge/haskell/src/LslForge.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lslforge/haskell/src/LslForge.hs b/lslforge/haskell/src/LslForge.hs index f013fe5..2e224fe 100644 --- a/lslforge/haskell/src/LslForge.hs +++ b/lslforge/haskell/src/LslForge.hs @@ -13,7 +13,7 @@ import IO import System import System.Exit -version="0.1.3" +version="0.1.3.2" usage progName = "Usage: " ++ progName ++ " [Version|MetaData|Compiler|ExpressionHandler|SimMetaData|SystemTester|UnitTester|CompilationServer]" From 9fb49cc42b8fe99592290149fbe4fd92b84967b1 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 03:20:02 +0100 Subject: [PATCH 04/12] apply patch for Syntax.hs addressing issues: - https://code.google.com/p/lslforge/issues/detail?id=9#c1 (Compiler doesn't properly detect using variable out of scope) - https://code.google.com/p/lslforge/issues/detail?id=1 (Redeclaration of built-in functions doesn't show error) - https://code.google.com/p/lslforge/issues/detail?id=10 (Conflict of global/local variables in modules) for patch blame [pells...@gmail.com](https://code.google.com/u/101374969631348043816/) taken from https://github.com/RayZopf/LSLForge_patched/commit/c521e2114568db09ba8ae0bfd79a236518565ac0 https://github.com/RayZopf/LSLForge_patched/commit/c115fcb39ced19c6e27615604ac14e1197d30db1 --- lslforge/haskell/src/Language/Lsl/Syntax.hs | 40 +++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Syntax.hs b/lslforge/haskell/src/Language/Lsl/Syntax.hs index 02ef436..960954b 100644 --- a/lslforge/haskell/src/Language/Lsl/Syntax.hs +++ b/lslforge/haskell/src/Language/Lsl/Syntax.hs @@ -64,6 +64,7 @@ import Data.Generics.Extras.Schemes import Data.Data(Data,Typeable) import Data.List(find,sort,sortBy,nub,foldl',nubBy,deleteFirstsBy) import qualified Data.Map as M +import qualified Data.Set as DS import Data.Maybe(isJust,isNothing) import Language.Lsl.Internal.Util(ctx,findM,lookupM,filtMap,throwStrError) import Control.Monad(when,foldM,MonadPlus(..)) @@ -288,7 +289,7 @@ data ValidationState = ValidationState { vsFuncs :: ![Ctx Func], vsErr :: !CodeErrs, vsWarn :: !CodeErrs, - vsNamesUsed :: [String], + vsNamesUsed :: !(DS.Set String), vsGVs :: ![Var], vsGFs :: ![FuncDec], vsStateNames :: ![String], @@ -298,7 +299,7 @@ data ValidationState = ValidationState { vsImports :: ![(String,[(String,String)],String)], vsContext :: [Maybe SourceContext] } - + emptyValidationState = ValidationState { vsLib = [], vsGlobalRegistry = M.empty, @@ -312,7 +313,7 @@ emptyValidationState = ValidationState { vsFuncs = [], vsErr = CodeErrs [], vsWarn = CodeErrs [], - vsNamesUsed = [], + vsNamesUsed = DS.fromList (map (\ (name, t, ts) -> name) funcSigs), vsGVs = [], vsGFs = [], vsStateNames = [], @@ -395,7 +396,7 @@ vsmAddLocal ctx v@(Var name _) = do vsmAddImport imp = get'vsImports >>= put'vsImports . (imp:) vsmAddToNamesUsed :: String -> VState () -vsmAddToNamesUsed name = get'vsNamesUsed >>= put'vsNamesUsed . (name :) +vsmAddToNamesUsed name = get'vsNamesUsed >>= put'vsNamesUsed . (DS.insert name) vsmWithNewScope :: VState a -> VState a vsmWithNewScope action = do @@ -535,7 +536,7 @@ compileGlob (GV v mexpr) = do when (isConstant $ varName v') (vsmAddErr (srcCtx v, varName v' ++ " is a predefined constant")) namesUsed <- get'vsNamesUsed gvs <- get'vsGVs - when (varName v' `elem` namesUsed) (vsmAddErr (srcCtx v, varName v' ++ " is already defined")) + when (varName v' `DS.member` namesUsed) (vsmAddErr (srcCtx v, varName v' ++ " is already defined")) whenJust mexpr $ \ expr -> do let (_,gvs') = break (\ var -> varName var == varName v') gvs mt <- compileCtxSimple (drop 1 gvs') expr @@ -547,7 +548,7 @@ compileGlob (GF cf@(Ctx ctx f@(Func (FuncDec name t params) statements))) = vsmWithNewScope $ do compileParams params vsmInEntryPoint t False $ do - whenM ((return elem) `ap` (return $ ctxItem name) `ap` get'vsNamesUsed) (vsmAddErr (srcCtx name, ctxItem name ++ " is already defined")) + whenM ((return DS.member) `ap` (return $ ctxItem name) `ap` get'vsNamesUsed) (vsmAddErr (srcCtx name, ctxItem name ++ " is already defined")) returns <- compileStatements statements when (not returns && t /= LLVoid) (vsmAddErr (srcCtx name, ctxItem name ++ ": not all code paths return a value")) vsmRegisterFunc f @@ -576,9 +577,9 @@ rewriteGlob' prefix renames vars (GF (Ctx ctx (Func (FuncDec name t params) stat Nothing -> vsmAddErr (srcCtx name, "can't rename " ++ ctxItem name ++ ": not found") Just name' -> do namesUsed <- get'vsNamesUsed - if name' `elem` namesUsed + if name' `DS.member` namesUsed then vsmAddErr (srcCtx name, name' ++ " imported from module is already defined") - else let rewrittenFunc = (Func (FuncDec (Ctx (srcCtx name) name') t params) $ rewriteStatements 0 renames statements) + else let rewrittenFunc = (Func (FuncDec (Ctx (srcCtx name) name') t params) $ rewriteStatements 0 (removeLocals params renames) statements) in do vsmAddToNamesUsed name' vsmRegisterFunc rewrittenFunc vsmAddFunc (Ctx ctx rewrittenFunc) @@ -587,7 +588,7 @@ rewriteGlob' prefix renames vars (GV (Ctx ctx (Var name t)) mexpr) = Nothing -> vsmAddErr (ctx, "can't rename " ++ name ++ ": not found") Just name' -> do namesUsed <- get'vsNamesUsed - if name' `elem` namesUsed + if name' `DS.member` namesUsed then vsmAddErr (ctx, name' ++ " imported from module is already defined") else let rewrittenGlobVar = GDecl (nullCtx (Var name' t)) (fmap (ctxItem . (rewriteCtxExpr renames)) mexpr) in do vsmAddToNamesUsed name' @@ -613,6 +614,10 @@ rewriteGlob' prefix0 renames vars (GI (Ctx ctx mName) bindings prefix) = Nothing -> vsmAddErr (ctx, rn ++ ": not found") >> return (fv,rn) Just rn' -> return (fv,rn') +removeLocals :: [CtxVar] -> [(String, String)] -> [(String, String)] +removeLocals locals globals = + filter (\ (gName, _) -> (all (\ (Ctx _ (Var localName _)) -> localName /= gName)) locals) globals + compileState :: Ctx State -> VState () compileState state@(Ctx _ (State nm handlers)) = vsmWithinState $ do @@ -693,22 +698,22 @@ compileStatement (Ctx ctx (Decl var@(Var name t) expr)) = do get'vsBranchReturns compileStatement (Ctx ctx (While expr statement)) = do t <- compileCtxExpr expr - vsmInBranch $ compileStatement statement + compileBranchStatement statement get'vsBranchReturns compileStatement (Ctx ctx(DoWhile statement expr)) = do t <- compileCtxExpr expr - vsmInBranch $ compileStatement statement + compileBranchStatement statement get'vsBranchReturns compileStatement (Ctx ctx (For mexpr1 mexpr2 mexpr3 statement)) = do compileExpressions mexpr1 compileExpressions mexpr3 t <- compileMExpression mexpr2 - vsmInBranch $ compileStatement statement + compileBranchStatement statement get'vsBranchReturns compileStatement (Ctx ctx (If expr thenStmt elseStmt)) = do t <- compileCtxExpr expr - ret1 <- vsmInBranch $ compileStatement thenStmt - ret2 <- vsmInBranch $ compileStatement elseStmt + ret1 <- compileBranchStatement thenStmt + ret2 <- compileBranchStatement elseStmt returns <- get'vsBranchReturns put'vsBranchReturns (returns || (ret1 && ret2)) get'vsBranchReturns @@ -744,6 +749,13 @@ compileStatement (Ctx ctx (Jump s)) = do when (s `notElem` concat labels) $ vsmAddErr (ctx, "no such label to jump to: " ++ s) get'vsBranchReturns +compileBranchStatement :: CtxStmt -> VState Bool +compileBranchStatement ctxStmt@(Ctx _ (Decl _ _)) = do + vsmAddErr (srcCtx ctxStmt, "Declaration requires a new scope - - use { and }") + return False +-- get'vsBranchReturns +compileBranchStatement ctxStmt = vsmInBranch $ compileStatement ctxStmt + compileStatements :: [CtxStmt] -> VState Bool compileStatements stmts = do From e015c14390d434946c5e081433c84c30f7e6f818 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 03:21:59 +0100 Subject: [PATCH 05/12] version number, Render.hs/LslForge.hs (0.1.4.0) taken from https://github.com/RayZopf/LSLForge_patched/commit/c115fcb39ced19c6e27615604ac14e1197d30db1 --- lslforge/haskell/src/Language/Lsl/Render.hs | 2 +- lslforge/haskell/src/LslForge.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 67889f3..c764b52 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -10,7 +10,7 @@ tr s x = trace (s ++ show x) x -- and a compiled (i.e. validated, with referenced modules included) LSL script. renderCompiledScript :: String -> CompiledLSLScript -> String renderCompiledScript stamp (CompiledLSLScript comment globals funcs states) = - (renderString "// LSL script generated - LSLForge Render.hs (0.1.3.2): " . renderString stamp . renderString "\n" . + (renderString "// LSL script generated - LSLForge Render.hs (0.1.4.0): " . renderString stamp . renderString "\n" . renderString comment . renderGlobals globals . renderFuncs funcs . renderStates states . renderString "\n") "" diff --git a/lslforge/haskell/src/LslForge.hs b/lslforge/haskell/src/LslForge.hs index 2e224fe..0225724 100644 --- a/lslforge/haskell/src/LslForge.hs +++ b/lslforge/haskell/src/LslForge.hs @@ -13,7 +13,7 @@ import IO import System import System.Exit -version="0.1.3.2" +version="0.1.4.0" usage progName = "Usage: " ++ progName ++ " [Version|MetaData|Compiler|ExpressionHandler|SimMetaData|SystemTester|UnitTester|CompilationServer]" From 7ae61d900fe16b072d261518cefb2948a9c0e112 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 04:26:49 +0100 Subject: [PATCH 06/12] patch files for json support/string conversion adressing issues - https://code.google.com/p/lslforge/issues/detail?id=40 (llJson* Not implemented) - (redone) https://code.google.com/p/lslforge/issues/detail?id=18 (Lslforge corrupts data during optimization) also update LSLForge cabal given patch was not used; - changed version number - added dependency json (== 0.7.*) blame [pells...@gmail.com](https://code.google.com/u/101374969631348043816/) taken from https://github.com/RayZopf/LSLForge_patched/commit/8e8b8b1cad7b5d728b7c8495058c0905d68b5d36 https://github.com/RayZopf/LSLForge_patched/commit/27ea23d17c65a4b8dc90d27235427864f2527f3f https://github.com/RayZopf/LSLForge_patched/commit/af9d403d6256a3cefc0d443911f35bcef02eb4b8 --- lslforge/haskell/LslForge.cabal | 6 +- .../src/Language/Lsl/Internal/Constants.hs | 30 ++- .../Language/Lsl/Internal/InternalLLFuncs.hs | 206 +++++++++++++++++- 3 files changed, 227 insertions(+), 15 deletions(-) diff --git a/lslforge/haskell/LslForge.cabal b/lslforge/haskell/LslForge.cabal index 99d2735..9073ee0 100644 --- a/lslforge/haskell/LslForge.cabal +++ b/lslforge/haskell/LslForge.cabal @@ -1,5 +1,5 @@ Name: LSLForge -version: 0.1.6 +version: 0.1.6.1 Synopsis: An execution and testing framework for the Linden Scripting Language (LSL) Description: Provides a framework for executing Linden Scripting Language scripts offline, @@ -11,7 +11,7 @@ Homepage: http:/lslforge.googlecode.com/ License: BSD3 License-file: LICENSE Category: Language -Copyright: Copyright (c) Robert Greayer 2008-2010, Others 2011-2012 +Copyright: Copyright (c) Robert Greayer 2008-2010, Others 2011-2016 Author: Robert Greayer Maintainer: "Newfie Pendragon" Stability: experimental @@ -27,7 +27,7 @@ Executable LSLForge network >= 2.1 && < 2.3, random >= 1.0, containers >= 0.1 && < 0.3, old-time, utf8-string >= 0.3 && < 0.4, pureMD5 >= 0.2 && < 3, bytestring >= 0.9 && < 0.10, template-haskell >= 2.3.0.0 && < 2.4, - syb >= 0.1.0.0 && < 0.2.0.0, fclabels > 0.4 && < 0.5 + syb >= 0.1.0.0 && < 0.2.0.0, fclabels > 0.4 && < 0.5, json == 0.7.* Main-Is: LslForge.hs Hs-Source-Dirs: src Other-modules: diff --git a/lslforge/haskell/src/Language/Lsl/Internal/Constants.hs b/lslforge/haskell/src/Language/Lsl/Internal/Constants.hs index 48ba886..e0f7a0f 100644 --- a/lslforge/haskell/src/Language/Lsl/Internal/Constants.hs +++ b/lslforge/haskell/src/Language/Lsl/Internal/Constants.hs @@ -154,6 +154,17 @@ validPrimHoleType = flip elem $ map IVal [cPrimHoleDefault,cPrimHoleSquare, llcUrlRequestGranted = SVal "URL_REQUEST_GRANTED" llcUrlRequestDenied = SVal "URL_REQUEST_DENIED" +cJsonAppend = -1;llcJsonAppend :: RealFloat a => LSLValue a; llcJsonAppend = IVal cJsonAppend +cJsonArray = "\xfdd2";llcJsonArray :: RealFloat a => LSLValue a; llcJsonArray = SVal cJsonArray +cJsonDelete = "\xfdd8";llcJsonDelete :: RealFloat a => LSLValue a; llcJsonDelete = SVal cJsonDelete +cJsonFalse = "\xfdd7";llcJsonFalse :: RealFloat a => LSLValue a; llcJsonFalse = SVal cJsonFalse +cJsonInvalid = "\xfdd0";llcJsonInvalid :: RealFloat a => LSLValue a; llcJsonInvalid = SVal cJsonInvalid +cJsonNull = "\xfdd5";llcJsonNull :: RealFloat a => LSLValue a; llcJsonNull = SVal cJsonNull +cJsonNumber = "\xfdd3";llcJsonNumber :: RealFloat a => LSLValue a; llcJsonNumber = SVal cJsonNumber +cJsonObject = "\xfdd1";llcJsonObject :: RealFloat a => LSLValue a; llcJsonObject = SVal cJsonObject +cJsonString = "\xfdd4";llcJsonString :: RealFloat a => LSLValue a; llcJsonString = SVal cJsonString +cJsonTrue = "\xfdd6";llcJsonTrue :: RealFloat a => LSLValue a; llcJsonTrue = SVal cJsonTrue + allConstants :: RealFloat a => [Constant a] allConstants = [ Constant "ACTIVE" llcActive, @@ -347,15 +358,16 @@ allConstants = [ Constant "INVENTORY_SCRIPT" llcInventoryScript, Constant "INVENTORY_SOUND" llcInventorySound, Constant "INVENTORY_TEXTURE" llcInventoryTexture, - Constant "JSON_ARRAY" (SVal "\xfdd2"), - Constant "JSON_DELETE" (SVal "\xfdd8"), - Constant "JSON_FALSE" (SVal "\xfdd7"), - Constant "JSON_INVALID" (SVal "\xfdd0"), - Constant "JSON_NULL" (SVal "\xfdd5"), - Constant "JSON_NUMBER" (SVal "\xfdd3"), - Constant "JSON_OBJECT" (SVal "\xfdd1"), - Constant "JSON_STRING" (SVal "\xfdd4"), - Constant "JSON_TRUE" (SVal "\xfdd6"), + Constant "JSON_APPEND" llcJsonAppend, + Constant "JSON_ARRAY" llcJsonArray, + Constant "JSON_DELETE" llcJsonDelete, + Constant "JSON_FALSE" llcJsonFalse, + Constant "JSON_INVALID" llcJsonInvalid, + Constant "JSON_NULL" llcJsonNull, + Constant "JSON_NUMBER" llcJsonNumber, + Constant "JSON_OBJECT" llcJsonObject, + Constant "JSON_STRING" llcJsonString, + Constant "JSON_TRUE" llcJsonTrue, Constant "KFM_CMD_PAUSE" (IVal 2), Constant "KFM_CMD_PLAY" (IVal 0), Constant "KFM_CMD_STOP" (IVal 1), diff --git a/lslforge/haskell/src/Language/Lsl/Internal/InternalLLFuncs.hs b/lslforge/haskell/src/Language/Lsl/Internal/InternalLLFuncs.hs index 344d198..c406ced 100644 --- a/lslforge/haskell/src/Language/Lsl/Internal/InternalLLFuncs.hs +++ b/lslforge/haskell/src/Language/Lsl/Internal/InternalLLFuncs.hs @@ -53,6 +53,12 @@ module Language.Lsl.Internal.InternalLLFuncs( llXorBase64Strings, llXorBase64StringsCorrect, llSHA1String, + -- JSON functions + llJson2List, + llJsonGetValue, + llJsonSetValue, + llJsonValueType, + llList2Json, -- Math functions llCos, llSin, @@ -114,7 +120,8 @@ import Language.Lsl.Internal.Util(Permutation3(..),axisAngleToRotation,cut,dist3 quaternionToRotations,rotationBetween,rotationsToQuaternion) import Language.Lsl.Internal.Type(LSLType(..),LSLValue(..),lslValString,parseFloat,parseInt,rot2RVal,toSVal,typeOfLSLValue,vVal2Vec) import Language.Lsl.Internal.Evaluation(EvalResult(..)) -import Language.Lsl.Internal.Constants(findConstVal) +--import Language.Lsl.Internal.Constants(findConstVal) +import Language.Lsl.Internal.Constants import Language.Lsl.Internal.Key(LSLKey(..)) import Language.Lsl.Internal.SHA1(hashStoHex) import Data.List(elemIndex,find,foldl',intersperse,isPrefixOf,sort) @@ -125,6 +132,8 @@ import qualified Data.ByteString.Lazy as L import qualified Data.Digest.Pure.MD5 as MD5 import qualified Data.ByteString.UTF8 as UTF8 import Network.URI(escapeURIChar,unEscapeString) +import Codec.Binary.UTF8.String(encodeString,decodeString) +import qualified Text.JSON as J internalLLFuncNames :: [String] internalLLFuncNames = map fst (internalLLFuncs :: (Read a, RealFloat a) => [(String, a -> [LSLValue a] -> Maybe (EvalResult,LSLValue a))]) @@ -155,6 +164,11 @@ internalLLFuncs = [ ("llGetSubString",llGetSubString), ("llInsertString",llInsertString), ("llIntegerToBase64",llIntegerToBase64), + ("llJson2List",llJson2List), + ("llJsonGetValue",llJsonGetValue), + ("llJsonSetValue",llJsonSetValue), + ("llJsonValueType",llJsonValueType), + ("llList2Json",llList2Json), ("llList2CSV",llList2CSV), ("llList2Float",llList2Float), ("llList2Integer",llList2Integer), @@ -264,15 +278,90 @@ escapeURL (c:cs) n = maxResult = 254::Int llEscapeURL _ [SVal string] = - continueWith $ SVal $ escapeURL string maxResult + continueWith $ SVal $ escapeURL (encodeString string) maxResult llUnescapeURL _ [SVal string] = - continueWith $ SVal $ take maxResult $ unEscapeString string + continueWith $ SVal $ decodeString $ take maxResult $ unEscapeString string llMD5String _ [SVal string, IVal nonce] = continueWith $ SVal $ (show . MD5.md5 . L.pack . B.unpack . UTF8.fromString) (string ++ ":" ++ show nonce) llSHA1String _ [SVal string] = continueWith $ SVal (hashStoHex string) + +-- JSON functions + +llJson2List _ [SVal jsonstring] = continueWith $ LVal $ + case J.decode jsonstring of + (J.Ok (J.JSArray a)) -> map js2lsl a + (J.Ok (J.JSObject o)) -> concat $ map (\(k, v) -> [SVal k, js2lsl v]) $ J.fromJSObject o + (J.Ok j) -> [SVal $ J.encode j] + (J.Error _) -> [SVal jsonstring] + +llJsonGetValue _ [SVal jsonstring, LVal sp] = continueWith $ SVal $ + case mapM convSpecifier sp of + (Just sp') -> case J.decodeStrict jsonstring >>= lookupDeep' sp' of + (J.Ok j) -> lslValToString $ js2lsl j + otherwise -> cJsonInvalid + otherwise -> cJsonInvalid + +llJsonSetValue _ [SVal jsonstring, LVal sp, SVal val] = continueWith $ SVal $ + case mapM convSpecifier sp of + (Just sp') -> case J.decodeStrict jsonstring >>= + updateFieldDeep' sp' (decodeFromLsl val) of + (J.Ok js) -> J.encode js + (J.Error _) -> cJsonInvalid + otherwise -> cJsonInvalid + +llJsonValueType _ [SVal jsonstring, LVal sp] = continueWith $ SVal $ + case mapM convSpecifier sp of + (Just sp') -> case J.decodeStrict jsonstring >>= lookupDeep' sp' of + (J.Ok v) -> jsonType v + otherwise -> cJsonInvalid + otherwise -> cJsonInvalid + where + jsonType :: J.JSValue -> String + jsonType J.JSNull = cJsonNull + jsonType (J.JSBool b) = if b then cJsonTrue else cJsonFalse + jsonType (J.JSRational _ _) = cJsonNumber + jsonType (J.JSString _) = cJsonString + jsonType (J.JSArray _) = cJsonArray + jsonType (J.JSObject _) = cJsonObject + +llList2Json _ [SVal typ, LVal list] = continueWith $ SVal $ + if typ == cJsonArray then J.encodeStrict $ J.JSArray $ map lsl2js list + else if typ == cJsonObject then case l2al list of + (Just al) -> J.encode (J.toJSObject al) + _ -> cJsonInvalid + else cJsonInvalid + where + lsl2js :: RealFloat a => LSLValue a -> J.JSValue + lsl2js (IVal i) = J.JSRational False $ toRational i + lsl2js (FVal f) = J.JSRational True $ toRational f + lsl2js s = decodeFromLsl $ lslValToString s + l2al :: RealFloat a => [LSLValue a] -> Maybe [(String, J.JSValue)] + l2al [] = Just [] + l2al ((SVal k):v:xs) = l2al xs >>= \ al -> return $ (k, lsl2js v):al + l2al _ = Nothing + +convSpecifier :: RealFloat a => LSLValue a -> Maybe Specifier +convSpecifier (IVal i) | i == cJsonAppend = Just Append + | otherwise = Just $ Index i +convSpecifier (SVal k) = Just $ Key k +convSpecifier _ = Nothing + +js2lsl :: RealFloat a => J.JSValue -> LSLValue a +js2lsl (J.JSBool b) = if b then llcJsonTrue else llcJsonFalse +js2lsl (J.JSRational True r) = FVal $ fromRational r +js2lsl (J.JSRational False r) = IVal $ floor r +js2lsl jsval = SVal $ J.encode jsval + +decodeFromLsl :: String -> J.JSValue +decodeFromLsl val | val == cJsonTrue = J.JSBool True + | val == cJsonFalse = J.JSBool False + | otherwise = case J.decode val of + (J.Ok js) -> js + _ -> J.JSString $ J.toJSString val + -- Math functions unaryToLL :: (RealFloat a, Monad m) => (a -> a) -> [LSLValue a] -> m (EvalResult,LSLValue a) @@ -661,3 +750,114 @@ encode1 c1 = let b1 = ((fromEnum c1) `shiftR` 2) .&. 63 b2 = ((fromEnum c1) `shiftL` 4) .&. 63 in [base64chars !! b1,base64chars !! b2,'=','='] + +-- +-- TODO: these functions should be in separated module, like Text.JSON.Specifier +-- + +data Specifier = Index Int | Append | Key String + +-- this function shoud be called lookup in separated module +jsonLookup :: Specifier -> J.JSValue -> Maybe J.JSValue +jsonLookup sp json = case lookup' sp json of + (J.Ok j) -> Just j + (J.Error _) -> Nothing + +findWithDefault :: J.JSValue -> Specifier -> J.JSValue -> J.JSValue +findWithDefault d sp json = case lookup' sp json of + (J.Ok j) -> j + (J.Error _) -> d + +lookupDeep :: [Specifier] -> J.JSValue -> Maybe J.JSValue +lookupDeep sp json = case lookupDeep' sp json of + (J.Ok j) -> Just j + (J.Error _) -> Nothing + +findDeepWithDefault :: J.JSValue -> [Specifier] -> J.JSValue -> J.JSValue +findDeepWithDefault d sp json = case lookupDeep' sp json of + (J.Ok j) -> j + (J.Error _) -> d + +updateField :: Specifier -> J.JSValue -> J.JSValue -> Maybe J.JSValue +updateField sp v json = case updateField' sp v json of + (J.Ok j) -> Just j + (J.Error _) -> Nothing + +updateFieldDeep :: [Specifier] -> J.JSValue -> J.JSValue -> Maybe J.JSValue +updateFieldDeep sps v json = case updateFieldDeep' sps v json of + (J.Ok j) -> Just j + (J.Error _) -> Nothing + +delete :: Specifier -> J.JSValue -> Maybe J.JSValue +delete sp json = case delete' sp json of + (J.Ok j) -> Just j + otherwise -> Nothing + +deleteDeep :: [Specifier] -> J.JSValue -> Maybe J.JSValue +deleteDeep sp json = case deleteDeep' sp json of + (J.Ok j) -> Just j + otherwise -> Nothing + +lookup' :: Specifier -> J.JSValue -> J.Result J.JSValue +lookup' (Index i) (J.JSArray list) | i >= 0 && i < length list = return $ list !! i +lookup' (Key k) (J.JSObject obj) = case lookup k $ J.fromJSObject obj of + (Just j) -> return j + otherwise -> J.Error "Invalid specifier" +lookup' _ _ = J.Error "Invalid specifier" + +lookupDeep' :: [Specifier] -> J.JSValue -> J.Result J.JSValue +lookupDeep' [] json = return json +lookupDeep' (sp:sps) json = lookup' sp json >>= lookupDeep' sps + +updateField' :: Specifier -> J.JSValue -> J.JSValue -> J.Result J.JSValue +updateField' sp v js = + case js of + (J.JSArray l) -> case sp of + Append -> return $ J.JSArray $ l ++ [v] + (Index i) -> repl l i v + otherwise -> J.Error "Invalid specifier" + (J.JSObject o) -> case sp of + (Key k) -> return $ J.JSObject $ J.toJSObject $ addToAL (J.fromJSObject o) k v + otherwise -> J.Error "Invalid parameter" + otherwise -> J.Error "Invalid specifier" + +repl :: [J.JSValue] -> Int -> J.JSValue -> J.Result J.JSValue +repl [] _ _ = J.Error "Invalid specifier" +repl _ i _ | i < 0 = J.Error "Invalid specifier" +repl (x:xs) 0 v = return $ J.JSArray (v:xs) +repl (x:xs) n v = repl xs (n - 1) v >>= \(J.JSArray t) -> return $ J.JSArray (x:t) + +updateFieldDeep' :: [Specifier] -> J.JSValue -> J.JSValue -> J.Result J.JSValue +updateFieldDeep' [] v json = return v +updateFieldDeep' (Append:sps) v j@(J.JSArray _) = + updateFieldDeep' sps v (J.JSArray []) >>= \t -> updateField' Append t j +updateFieldDeep' (sp:sps) v json = + updateFieldDeep' sps v (findWithDefault def sp json) >>= \ t -> updateField' sp t json + where def = case sps of + [] -> J.JSNull + Append:_ -> J.JSArray [] + (Index _):_ -> J.JSArray [] + (Key _):_ -> J.JSObject $ J.toJSObject [] + +delete' :: Specifier -> J.JSValue -> J.Result J.JSValue +delete' (Index i) (J.JSArray list) | i >= 0 && i < length list = + return $ J.JSArray $ a ++ b where (a, (_:b)) = splitAt i list +delete' (Key k) (J.JSObject obj) = + return $ J.JSObject $ J.toJSObject $ delFromAL (J.fromJSObject obj) k +delete' _ _ = J.Error "Invalid specifier" + +deleteDeep' :: [Specifier] -> J.JSValue -> J.Result J.JSValue +deleteDeep' [] _ = J.Error "Invalid specifier" +deleteDeep' [sp] json = delete' sp json +deleteDeep' (sp:sps) json = + lookup' sp json >>= deleteDeep' sps >>= \ t -> updateField' sp t json + +addToAL :: Eq k => [(k, v)] -> k -> v -> [(k, v)] +addToAL [] k v = [(k, v)] +addToAL (t@(x, _):xs) k v | x == k = (k, v):xs + | otherwise = t:(addToAL xs k v) + +delFromAL :: Eq k => [(k, v)] -> k -> [(k, v)] +delFromAL [] k = [] +delFromAL (t@(x, _):xs) k | x == k = xs + | otherwise = t:(delFromAL xs k) From 78f1dc93abc51a14632fdae655d9bcebcde37a35 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 04:29:48 +0100 Subject: [PATCH 07/12] version number, Render.hs/LslForge.hs (0.1.5.0) taken from https://github.com/RayZopf/LSLForge_patched/commit/27ea23d17c65a4b8dc90d27235427864f2527f3f --- lslforge/haskell/src/Language/Lsl/Render.hs | 2 +- lslforge/haskell/src/LslForge.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index c764b52..9199be4 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -10,7 +10,7 @@ tr s x = trace (s ++ show x) x -- and a compiled (i.e. validated, with referenced modules included) LSL script. renderCompiledScript :: String -> CompiledLSLScript -> String renderCompiledScript stamp (CompiledLSLScript comment globals funcs states) = - (renderString "// LSL script generated - LSLForge Render.hs (0.1.4.0): " . renderString stamp . renderString "\n" . + (renderString "// LSL script generated - LSLForge Render.hs (0.1.5.0): " . renderString stamp . renderString "\n" . renderString comment . renderGlobals globals . renderFuncs funcs . renderStates states . renderString "\n") "" diff --git a/lslforge/haskell/src/LslForge.hs b/lslforge/haskell/src/LslForge.hs index 0225724..bdbe17d 100644 --- a/lslforge/haskell/src/LslForge.hs +++ b/lslforge/haskell/src/LslForge.hs @@ -13,7 +13,7 @@ import IO import System import System.Exit -version="0.1.4.0" +version="0.1.5.0" usage progName = "Usage: " ++ progName ++ " [Version|MetaData|Compiler|ExpressionHandler|SimMetaData|SystemTester|UnitTester|CompilationServer]" From 4c1a4978171840e5b6a475d4cb49527aaebde532 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 18 Feb 2016 04:38:53 +0100 Subject: [PATCH 08/12] update version number - sync Render.hs, LslForge.hs and LslForge.cabal - (0.1.6.5) taken from https://github.com/RayZopf/LSLForge_patched/commit/5374c00ce02d5db9f39ae17908287b6c88a1100f https://github.com/RayZopf/LSLForge_patched/commit/d0fed91cb2997584b0f495b29082edd18c441957 --- lslforge/haskell/LslForge.cabal | 2 +- lslforge/haskell/src/Language/Lsl/Render.hs | 2 +- lslforge/haskell/src/LslForge.hs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lslforge/haskell/LslForge.cabal b/lslforge/haskell/LslForge.cabal index 9073ee0..9d515a2 100644 --- a/lslforge/haskell/LslForge.cabal +++ b/lslforge/haskell/LslForge.cabal @@ -1,5 +1,5 @@ Name: LSLForge -version: 0.1.6.1 +version: 0.1.6.5 Synopsis: An execution and testing framework for the Linden Scripting Language (LSL) Description: Provides a framework for executing Linden Scripting Language scripts offline, diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 9199be4..a61f1d2 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -10,7 +10,7 @@ tr s x = trace (s ++ show x) x -- and a compiled (i.e. validated, with referenced modules included) LSL script. renderCompiledScript :: String -> CompiledLSLScript -> String renderCompiledScript stamp (CompiledLSLScript comment globals funcs states) = - (renderString "// LSL script generated - LSLForge Render.hs (0.1.5.0): " . renderString stamp . renderString "\n" . + (renderString "// LSL script generated - LSLForge (0.1.6.5): " . renderString stamp . renderString "\n" . renderString comment . renderGlobals globals . renderFuncs funcs . renderStates states . renderString "\n") "" diff --git a/lslforge/haskell/src/LslForge.hs b/lslforge/haskell/src/LslForge.hs index bdbe17d..218d0f4 100644 --- a/lslforge/haskell/src/LslForge.hs +++ b/lslforge/haskell/src/LslForge.hs @@ -13,7 +13,7 @@ import IO import System import System.Exit -version="0.1.5.0" +version="0.1.6.5" usage progName = "Usage: " ++ progName ++ " [Version|MetaData|Compiler|ExpressionHandler|SimMetaData|SystemTester|UnitTester|CompilationServer]" From d5d235eb2e3e62bc12a7a958a9c1a562b0f5a16f Mon Sep 17 00:00:00 2001 From: RayZopf Date: Mon, 22 Feb 2016 16:24:48 +0100 Subject: [PATCH 09/12] hotfix for math bug partly reverted applied patch - ugly - only used on Sub, Div and Mod operations - adding back some unnecessary parenthesis too logic expressions handling (And, Or) seems to be untouched and still correct added comments --- lslforge/haskell/src/Language/Lsl/Render.hs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index a61f1d2..33f9a81 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -167,10 +167,10 @@ renderExpression ex = case ex of r prefix (i:is) = renderString prefix . renderCtxExpr i . r "," is in renderChar '[' . r "" l . renderChar ']' (Add expr1 expr2) -> renderBinExpr "+" expr1 expr2 lo - (Sub expr1 expr2) -> renderBinExpr "-" expr1 expr2 lo + (Sub expr1 expr2) -> renderBinExprMath "-" expr1 expr2 lo (Mul expr1 expr2) -> renderBinExpr "*" expr1 expr2 lo - (Div expr1 expr2) -> renderBinExpr "/" expr1 expr2 lo - (Mod expr1 expr2) -> renderBinExpr "%" expr1 expr2 lo + (Div expr1 expr2) -> renderBinExprMath "/" expr1 expr2 lo + (Mod expr1 expr2) -> renderBinExprMath "%" expr1 expr2 lo (BAnd expr1 expr2) -> renderBinExpr "&" expr1 expr2 lo (Xor expr1 expr2) -> renderBinExpr "^" expr1 expr2 lo (BOr expr1 expr2) -> renderBinExpr "|" expr1 expr2 lo @@ -184,13 +184,16 @@ renderExpression ex = case ex of (ShiftR expr1 expr2) -> renderBinExpr ">>" expr1 expr2 lo (Inv expr) -> renderChar '~' . renderInParenIfLower expr lo (Not expr) -> renderChar '!' . renderInParenIfLower expr lo - (Neg expr) -> renderChar '-' . renderInParenIfLower expr lo +-- similar line for (Neg) was there before patch was applied, but is this really needed - look at renderSimple(Neg expr) above + (Neg expr) -> renderChar '-' . renderInParenIfLower expr lo -- doing almost the same as renderSimple? (Call name exprs) -> renderCtxName name . renderChar '(' . renderCtxExprs "" exprs . renderChar ')' (Cast t expr) -> renderChar '(' . renderType t . renderChar ')' . renderInParenIfLower expr lo (Get var) -> renderVarAccess var --renderExpression (Const var) = renderVarAccess var +-- when and why was (Const var) commented out? --renderExpression (Set var expr) = renderChar '(' . renderVarAccess var . renderString " = " . renderCtxExpr expr . renderChar ')' +-- (Set var expr) with parenthesis adding and renderVarAccess was commented out in pre-patched version too (Set va expr) -> renderAssignment va "=" expr (IncBy va expr) -> renderAssignment va "+=" expr (DecBy va expr) -> renderAssignment va "-=" expr @@ -206,8 +209,14 @@ renderExpression ex = case ex of where lo = \ t -> isLower ex t || needsBooleanParens ex t || castCast ex t -renderInParens f = renderChar '(' . f . renderChar ')' +-- is this renderInParens still used? +-- renderInParens f = renderChar '(' . f . renderChar ')' +-- added back old renderBinExpr handling because of math bug *rendering a = b-(c-d) to a = b-c-d* +-- renamed to renderBinExprMath and only used on Sub, Div, Mod +renderBinExprMath op expr1 expr2 f = renderChar '(' . renderCtxExpr expr1 . renderChar ' ' . + renderString op . renderChar ' ' . renderCtxExpr expr2 . renderChar ')' + renderBinExpr op expr1 expr2 f = renderInParenIfLower expr1 f . renderChar ' ' . renderString op . renderChar ' ' . renderInParenIfLower expr2 f @@ -310,6 +319,8 @@ prec e = (BOr _ _) -> 10 (And _ _) -> 11 -- usually And is higher than Or, (Or _ _) -> 11 -- this seems bug of LSL Compiler. see SVC-779 + -- still LSLForge adds parenthesis around And expression, making it higher + -- maybe done in Syntax.hs (Ctx) (Get _) -> 0 (Set _ _) -> 12 (IncBy _ _) -> 12 From 32e362d02bde659172c22f9abec0c5ac052f0101 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Wed, 24 Feb 2016 03:22:47 +0100 Subject: [PATCH 10/12] hotfix -II- for math bug partly reverted applied patch - ugly - used on ShiftL and ShiftR too - adds back some unnecessary parenthesis too thanks for pointing out @furroy --- lslforge/haskell/src/Language/Lsl/Render.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 33f9a81..6df35a6 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -180,8 +180,8 @@ renderExpression ex = case ex of (Ge expr1 expr2) -> renderBinExpr ">=" expr1 expr2 lo (And expr1 expr2) -> renderBinExpr "&&" expr1 expr2 lo (Or expr1 expr2) -> renderBinExpr "||" expr1 expr2 lo - (ShiftL expr1 expr2) -> renderBinExpr "<<" expr1 expr2 lo - (ShiftR expr1 expr2) -> renderBinExpr ">>" expr1 expr2 lo + (ShiftL expr1 expr2) -> renderBinExprMath "<<" expr1 expr2 lo + (ShiftR expr1 expr2) -> renderBinExprMath ">>" expr1 expr2 lo (Inv expr) -> renderChar '~' . renderInParenIfLower expr lo (Not expr) -> renderChar '!' . renderInParenIfLower expr lo -- similar line for (Neg) was there before patch was applied, but is this really needed - look at renderSimple(Neg expr) above From a903cdf27ce731855345c3d133be0b06e9d3a635 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Thu, 25 Feb 2016 06:38:55 +0100 Subject: [PATCH 11/12] Add Associativity, fix math bug and more Handle associativity similar to precedence - modified/moved Cast of Cast handling - all operators should be covered now - adds too much parenthesis in some cases --- lslforge/haskell/src/Language/Lsl/Render.hs | 62 +++++++++++++-------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index 6df35a6..d6297ee 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -167,10 +167,10 @@ renderExpression ex = case ex of r prefix (i:is) = renderString prefix . renderCtxExpr i . r "," is in renderChar '[' . r "" l . renderChar ']' (Add expr1 expr2) -> renderBinExpr "+" expr1 expr2 lo - (Sub expr1 expr2) -> renderBinExprMath "-" expr1 expr2 lo + (Sub expr1 expr2) -> renderBinExpr "-" expr1 expr2 lo (Mul expr1 expr2) -> renderBinExpr "*" expr1 expr2 lo - (Div expr1 expr2) -> renderBinExprMath "/" expr1 expr2 lo - (Mod expr1 expr2) -> renderBinExprMath "%" expr1 expr2 lo + (Div expr1 expr2) -> renderBinExpr "/" expr1 expr2 lo + (Mod expr1 expr2) -> renderBinExpr "%" expr1 expr2 lo (BAnd expr1 expr2) -> renderBinExpr "&" expr1 expr2 lo (Xor expr1 expr2) -> renderBinExpr "^" expr1 expr2 lo (BOr expr1 expr2) -> renderBinExpr "|" expr1 expr2 lo @@ -180,8 +180,8 @@ renderExpression ex = case ex of (Ge expr1 expr2) -> renderBinExpr ">=" expr1 expr2 lo (And expr1 expr2) -> renderBinExpr "&&" expr1 expr2 lo (Or expr1 expr2) -> renderBinExpr "||" expr1 expr2 lo - (ShiftL expr1 expr2) -> renderBinExprMath "<<" expr1 expr2 lo - (ShiftR expr1 expr2) -> renderBinExprMath ">>" expr1 expr2 lo + (ShiftL expr1 expr2) -> renderBinExpr "<<" expr1 expr2 lo + (ShiftR expr1 expr2) -> renderBinExpr ">>" expr1 expr2 lo (Inv expr) -> renderChar '~' . renderInParenIfLower expr lo (Not expr) -> renderChar '!' . renderInParenIfLower expr lo -- similar line for (Neg) was there before patch was applied, but is this really needed - look at renderSimple(Neg expr) above @@ -207,19 +207,14 @@ renderExpression ex = case ex of (PreInc va) -> renderString "++" . renderVarAccess va (PreDec va) -> renderString "--" . renderVarAccess va where - lo = \ t -> isLower ex t || needsBooleanParens ex t || castCast ex t + lo = \ t -> isLower ex t || needsBooleanParens ex t || explicitAssoc ex t -- is this renderInParens still used? -- renderInParens f = renderChar '(' . f . renderChar ')' --- added back old renderBinExpr handling because of math bug *rendering a = b-(c-d) to a = b-c-d* --- renamed to renderBinExprMath and only used on Sub, Div, Mod -renderBinExprMath op expr1 expr2 f = renderChar '(' . renderCtxExpr expr1 . renderChar ' ' . - renderString op . renderChar ' ' . renderCtxExpr expr2 . renderChar ')' - renderBinExpr op expr1 expr2 f = - renderInParenIfLower expr1 f . renderChar ' ' . renderString op . renderChar ' ' . - renderInParenIfLower expr2 f + renderInParenIfLower expr1 f . renderChar ' ' . renderString op . renderChar ' ' . renderInParenIfLower expr2 f + renderAssignment va op expr = renderVarAccess va . renderChar ' ' . renderString op . renderChar ' ' . renderCtxExpr expr renderComponent All = blank @@ -267,14 +262,6 @@ needsBooleanParens ex0 (Ctx _ ex1) = _ -> False _ -> False -castCast :: Expr -> Ctx Expr -> Bool -castCast ex0 (Ctx _ ex1) = - case ex0 of - (Cast _ _) -> case ex1 of - (Cast _ _) -> True - _ -> False - _ -> False - -- Comparing Order of Precedence isLower :: Expr -> (Ctx Expr) -> Bool @@ -328,4 +315,35 @@ prec e = (MulBy _ _) -> 12 (DivBy _ _) -> 12 (ModBy _ _) -> 12 - _ -> 0 \ No newline at end of file + _ -> 0 + +-- Checking Associativity + +explicitAssoc :: Expr -> Ctx Expr -> Bool +explicitAssoc ex0 (Ctx _ ex1) = + if assoc ex0 && assoc ex1 then True + else False +--may give a few too much parenthesisas, as not comparing e0 and ex1 e.g. (Sub _ _) == (Sub _ _) +--would be no need for parenthesis when e.g (Sub _ _) and (Lt _ _) except for precedence +--but be carefull with Lt, Gt, Le, Ge + +-- Those operators need explicit associative setting + +assoc :: Expr -> Bool +assoc e = + case e of + (Div _ _) -> True + (Mod _ _) -> True + (Sub _ _) -> True + (Lt _ _) -> True + (Gt _ _) -> True + (Le _ _) -> True + (Ge _ _) -> True + (ShiftL _ _) -> True + (ShiftR _ _) -> True + (Cast _ _) -> True + (Equal _ _) -> True + (NotEqual _ _) -> True + _ -> False + +-- http://wiki.secondlife.com/wiki/Category_talk:LSL_Operators \ No newline at end of file From f076b4e62f9d349afdd8534b3890a14658874860 Mon Sep 17 00:00:00 2001 From: RayZopf Date: Tue, 29 Mar 2016 13:53:16 +0200 Subject: [PATCH 12/12] fewer parenthesis on Associativity - also check for precedence there - late commit, change already mentioned in PR --- lslforge/haskell/src/Language/Lsl/Render.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lslforge/haskell/src/Language/Lsl/Render.hs b/lslforge/haskell/src/Language/Lsl/Render.hs index d6297ee..2a782cc 100644 --- a/lslforge/haskell/src/Language/Lsl/Render.hs +++ b/lslforge/haskell/src/Language/Lsl/Render.hs @@ -321,11 +321,8 @@ prec e = explicitAssoc :: Expr -> Ctx Expr -> Bool explicitAssoc ex0 (Ctx _ ex1) = - if assoc ex0 && assoc ex1 then True + if assoc ex0 && assoc ex1 && (prec ex0 == prec ex1) then True else False ---may give a few too much parenthesisas, as not comparing e0 and ex1 e.g. (Sub _ _) == (Sub _ _) ---would be no need for parenthesis when e.g (Sub _ _) and (Lt _ _) except for precedence ---but be carefull with Lt, Gt, Le, Ge -- Those operators need explicit associative setting