From bb71c4543dd4b0df5f6a1ec4be61d01c0de2e86f Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 13 Aug 2018 15:18:54 -0400 Subject: [PATCH 01/37] add evaluatable instance for await --- src/Data/Syntax/Expression.hs | 6 +++--- test/fixtures/typescript/analysis/await.ts | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/typescript/analysis/await.ts diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 705e684f7..18956302b 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -469,9 +469,9 @@ instance Eq1 Await where liftEq = genericLiftEq instance Ord1 Await where liftCompare = genericLiftCompare instance Show1 Await where liftShowsPrec = genericLiftShowsPrec --- TODO: Implement Eval instance for Await -instance Evaluatable Await - +instance Evaluatable Await where + eval (Await a) = subtermValue a >> subtermRef a + -- Rval <$> (subtermAddress a >>= runReturn) - this doesn't work -- | An object constructor call in Javascript, Java, etc. newtype New a = New { newSubject :: [a] } diff --git a/test/fixtures/typescript/analysis/await.ts b/test/fixtures/typescript/analysis/await.ts new file mode 100644 index 000000000..c7c0102bf --- /dev/null +++ b/test/fixtures/typescript/analysis/await.ts @@ -0,0 +1,5 @@ +async function f2() { + var y = await 20; + return y; +} +f2(); From ee4f78b5865fa171d17d984619a7c2f128da04c8 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 13:38:30 -0400 Subject: [PATCH 02/37] synchronously handle async await --- src/Data/Syntax/Expression.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 18956302b..6a321c719 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -469,9 +469,10 @@ instance Eq1 Await where liftEq = genericLiftEq instance Ord1 Await where liftCompare = genericLiftCompare instance Show1 Await where liftShowsPrec = genericLiftShowsPrec +-- TODO: Improve this to model asynchrony or capture some data suggesting async calls are not a problem. +-- We are currently dealing with an asynchronous construct synchronously. instance Evaluatable Await where - eval (Await a) = subtermValue a >> subtermRef a - -- Rval <$> (subtermAddress a >>= runReturn) - this doesn't work + eval (Await a) = subtermRef a -- | An object constructor call in Javascript, Java, etc. newtype New a = New { newSubject :: [a] } From a2dd8f131cbdbf71b2216b3bca704f8aa086d578 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 14:20:49 -0400 Subject: [PATCH 03/37] evaluate bitwise or --- src/Data/Syntax/Expression.hs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 6a321c719..03d4c2c82 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -4,6 +4,7 @@ module Data.Syntax.Expression where import Data.Abstract.Evaluatable hiding (Member) import Data.Abstract.Number (liftIntegralFrac, liftReal, liftedExponent, liftedFloorDiv) +import Data.Bits import Data.Fixed import Data.JSON.Fields import Diffing.Algorithm hiding (Delete) @@ -325,6 +326,10 @@ instance Eq1 BOr where liftEq = genericLiftEq instance Ord1 BOr where liftCompare = genericLiftCompare instance Show1 BOr where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BOr where + eval (BOr a b) = do + a' <- subtermValue a + b' <- subtermValue b + liftBitwise2 (.|.) a' b' >>= rvalBox data BAnd a = BAnd { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) @@ -470,7 +475,7 @@ instance Ord1 Await where liftCompare = genericLiftCompare instance Show1 Await where liftShowsPrec = genericLiftShowsPrec -- TODO: Improve this to model asynchrony or capture some data suggesting async calls are not a problem. --- We are currently dealing with an asynchronous construct synchronously. +-- We are currently dealing with an asynchronous construct synchronously. instance Evaluatable Await where eval (Await a) = subtermRef a From 5a40151393082407794fdc1f0b77f81a7a8c193b Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 14:24:22 -0400 Subject: [PATCH 04/37] evaluate bitwise and --- src/Data/Syntax/Expression.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 03d4c2c82..a461fe1e3 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -338,6 +338,11 @@ instance Eq1 BAnd where liftEq = genericLiftEq instance Ord1 BAnd where liftCompare = genericLiftCompare instance Show1 BAnd where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BAnd where + eval (BAnd a b) = do + a' <- subtermValue a + b' <- subtermValue b + liftBitwise2 (.&.) a' b' >>= rvalBox + data BXOr a = BXOr { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) From 9380f0484d5545d52a77d5c710de0a98cf847631 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 15:58:06 -0400 Subject: [PATCH 05/37] xor --- src/Data/Syntax/Expression.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index a461fe1e3..f451b87c0 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -341,7 +341,7 @@ instance Evaluatable BAnd where eval (BAnd a b) = do a' <- subtermValue a b' <- subtermValue b - liftBitwise2 (.&.) a' b' >>= rvalBox + liftBitwise2 (.&.) a' b' >>= rvalBox data BXOr a = BXOr { left :: a, right :: a } @@ -351,6 +351,10 @@ instance Eq1 BXOr where liftEq = genericLiftEq instance Ord1 BXOr where liftCompare = genericLiftCompare instance Show1 BXOr where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BXOr where + eval (BXOr a b) = do + a' <- subtermValue a + b' <- subtermValue b + liftBitwise2 xor a' b' >>= rvalBox data LShift a = LShift { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) From c8c38a976a3854660ca3f3f19c25711fae8664af Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 17:08:37 -0400 Subject: [PATCH 06/37] LShift --- src/Data/Syntax/Expression.hs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index f451b87c0..96294bee1 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -363,6 +363,13 @@ instance Eq1 LShift where liftEq = genericLiftEq instance Ord1 LShift where liftCompare = genericLiftCompare instance Show1 LShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable LShift where + eval (LShift a b) = do + a' <- subtermValue a + trace "hello" + b' <- subtermValue b + liftBitwise2 shiftL' a' b' >>= rvalBox + where + shiftL' a b = shiftL a (fromIntegral (toInteger b)) data RShift a = RShift { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) @@ -370,7 +377,7 @@ data RShift a = RShift { left :: a, right :: a } instance Eq1 RShift where liftEq = genericLiftEq instance Ord1 RShift where liftCompare = genericLiftCompare instance Show1 RShift where liftShowsPrec = genericLiftShowsPrec -instance Evaluatable RShift where +instance Evaluatable RShift data UnsignedRShift a = UnsignedRShift { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) @@ -387,7 +394,7 @@ instance Eq1 Complement where liftEq = genericLiftEq instance Ord1 Complement where liftCompare = genericLiftCompare instance Show1 Complement where liftShowsPrec = genericLiftShowsPrec -instance Evaluatable Complement where +instance Evaluatable Complement -- | Member Access (e.g. a.b) data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name } From 0d6b5ea0f1794486421fb6e94751d2b4300f8061 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 20:15:43 -0400 Subject: [PATCH 07/37] shift right --- src/Data/Syntax/Expression.hs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 96294bee1..0bb80a304 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -365,7 +365,6 @@ instance Show1 LShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable LShift where eval (LShift a b) = do a' <- subtermValue a - trace "hello" b' <- subtermValue b liftBitwise2 shiftL' a' b' >>= rvalBox where @@ -377,7 +376,13 @@ data RShift a = RShift { left :: a, right :: a } instance Eq1 RShift where liftEq = genericLiftEq instance Ord1 RShift where liftCompare = genericLiftCompare instance Show1 RShift where liftShowsPrec = genericLiftShowsPrec -instance Evaluatable RShift +instance Evaluatable RShift where + eval (RShift a b) = do + a' <- subtermValue a + b' <- subtermValue b + liftBitwise2 shiftR' a' b' >>= rvalBox + where + shiftR' a b = shiftR a (fromIntegral (toInteger b)) data UnsignedRShift a = UnsignedRShift { left :: a, right :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) From 79ede5aaf49b15e96444935b569d820717ec5300 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 14 Aug 2018 20:39:19 -0400 Subject: [PATCH 08/37] this is wrong, but I'm trying to add an evaluatable instance for complement --- src/Data/Syntax/Expression.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 0bb80a304..4f178e98d 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -399,7 +399,11 @@ instance Eq1 Complement where liftEq = genericLiftEq instance Ord1 Complement where liftCompare = genericLiftCompare instance Show1 Complement where liftShowsPrec = genericLiftShowsPrec -instance Evaluatable Complement +instance Evaluatable Complement where + eval (Complement a) = do + a' <- subtermValue a + liftBitwise complement a' >>= rvalBox + -- TODO: fix this; it's currently incrementing instead of producing complement -- | Member Access (e.g. a.b) data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name } From d6ccb3651503fafacc755523b037b7b373a69149 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 15 Aug 2018 11:24:49 -0400 Subject: [PATCH 09/37] lol just kidding complement is fine --- src/Data/Syntax/Expression.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 4f178e98d..4c7052484 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -403,7 +403,7 @@ instance Evaluatable Complement where eval (Complement a) = do a' <- subtermValue a liftBitwise complement a' >>= rvalBox - -- TODO: fix this; it's currently incrementing instead of producing complement + -- TODO: Differentiate between signed and unsigned -- | Member Access (e.g. a.b) data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name } From d932f069de04e61d0356c0dec1c502f77ed91cee Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 15 Aug 2018 13:57:49 -0400 Subject: [PATCH 10/37] evaluate unsignedRShift --- src/Control/Abstract/Value.hs | 2 ++ src/Data/Abstract/Value/Type.hs | 2 ++ src/Data/Syntax/Expression.hs | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/src/Control/Abstract/Value.hs b/src/Control/Abstract/Value.hs index fe20c2cc8..1c7ddf4ce 100644 --- a/src/Control/Abstract/Value.hs +++ b/src/Control/Abstract/Value.hs @@ -121,6 +121,8 @@ class AbstractIntro value => AbstractValue address value effects where liftBitwise2 :: (forall a . (Integral a, Bits a) => a -> a -> a) -> (value -> value -> Evaluator address value effects value) + unsignedRShift :: value -> value -> Evaluator address value effects value + -- | Construct an N-ary tuple of multiple (possibly-disjoint) values tuple :: [address] -> Evaluator address value effects value diff --git a/src/Data/Abstract/Value/Type.hs b/src/Data/Abstract/Value/Type.hs index 7224088ed..8e3bf968c 100644 --- a/src/Data/Abstract/Value/Type.hs +++ b/src/Data/Abstract/Value/Type.hs @@ -325,6 +325,8 @@ instance ( Member (Allocator address Type) effects liftBitwise _ = unify Int liftBitwise2 _ t1 t2 = unify Int t1 >>= flip unify t2 + unsignedRShift t1 t2 = unify Int t2 *> unify Int t1 + liftComparison (Concrete _) left right = case (left, right) of (Float, Int) -> pure Bool (Int, Float) -> pure Bool diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 4c7052484..618909c4a 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -11,6 +11,7 @@ import Diffing.Algorithm hiding (Delete) import Prologue hiding (index, Member, This, null) import Prelude hiding (null) import Proto3.Suite.Class +import Data.Word -- | Typical prefix function application, like `f(x)` in many languages, or `f x` in Haskell. data Call a = Call { callContext :: ![a], callFunction :: !a, callParams :: ![a], callBlock :: !a } @@ -391,6 +392,10 @@ instance Eq1 UnsignedRShift where liftEq = genericLiftEq instance Ord1 UnsignedRShift where liftCompare = genericLiftCompare instance Show1 UnsignedRShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable UnsignedRShift where + eval (UnsignedRShift a b) = do + a' <- subtermValue a + b' <- subtermValue b + unsignedRShift a' b' >>= rvalBox newtype Complement a = Complement { value :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) From a73916ecaa4e6921856298c54c65bb7572d8b776 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 15 Aug 2018 15:40:25 -0400 Subject: [PATCH 11/37] add instances for unsignedRShift for abstract, type-checking and concrete semantics --- src/Data/Abstract/Value/Abstract.hs | 2 ++ src/Data/Abstract/Value/Concrete.hs | 12 ++++++++++++ src/Data/Syntax/Expression.hs | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Data/Abstract/Value/Abstract.hs b/src/Data/Abstract/Value/Abstract.hs index 3c854cf4a..1575f6968 100644 --- a/src/Data/Abstract/Value/Abstract.hs +++ b/src/Data/Abstract/Value/Abstract.hs @@ -81,6 +81,8 @@ instance ( Member (Allocator address Abstract) effects liftBitwise _ _ = pure Abstract liftBitwise2 _ _ _ = pure Abstract + unsignedRShift _ _ = pure Abstract + liftComparison _ _ _ = pure Abstract loop f = f empty diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index 58e487f10..c52690f4d 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -16,11 +16,13 @@ import Data.Abstract.Environment (Environment, Bindings, EvalContext(..)) import qualified Data.Abstract.Environment as Env import Data.Abstract.Name import qualified Data.Abstract.Number as Number +import Data.Bits import Data.Coerce import Data.List (genericIndex, genericLength) import Data.Scientific (Scientific) import Data.Scientific.Exts import qualified Data.Set as Set +import Data.Word import Prologue data Value address body @@ -261,6 +263,16 @@ instance ( Coercible body (Eff effects) | otherwise = throwValueError (Bitwise2Error left right) where pair = (left, right) + unsignedRShift left right + | (Integer (Number.Integer i), Integer (Number.Integer j)) <- pair = + if i >= 0 then pure . integer $ ourShift (fromIntegral i) (fromIntegral j) + else throwValueError (Bitwise2Error left right) + | otherwise = throwValueError (Bitwise2Error left right) + where + pair = (left, right) + ourShift :: Word64 -> Int -> Integer + ourShift a b = toInteger (shiftR a b) + loop x = catchLoopControl (fix x) (\ control -> case control of Break value -> deref value -- FIXME: Figure out how to deal with this. Ruby treats this as the result of the current block iteration, while PHP specifies a breakout level and TypeScript appears to take a label. diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 618909c4a..15c5dfab1 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -396,6 +396,7 @@ instance Evaluatable UnsignedRShift where a' <- subtermValue a b' <- subtermValue b unsignedRShift a' b' >>= rvalBox + -- This isn't working for JavaScript newtype Complement a = Complement { value :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) @@ -408,7 +409,6 @@ instance Evaluatable Complement where eval (Complement a) = do a' <- subtermValue a liftBitwise complement a' >>= rvalBox - -- TODO: Differentiate between signed and unsigned -- | Member Access (e.g. a.b) data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name } From dd6141908c43c2e399c73a19ec686eac25b1823a Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 15 Aug 2018 16:52:34 -0400 Subject: [PATCH 12/37] add super --- src/Data/Syntax/Expression.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 15c5dfab1..c58a0ec8c 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -537,7 +537,8 @@ data Super a = Super instance Eq1 Super where liftEq = genericLiftEq instance Ord1 Super where liftCompare = genericLiftCompare instance Show1 Super where liftShowsPrec = genericLiftShowsPrec -instance Evaluatable Super +instance Evaluatable Super where + eval Super = Rval <$> (maybeM (box unit) =<< self) data This a = This deriving (Diffable, Eq, Foldable, Functor, Generic1, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1, Hashable1, Named1, Message1) From 84f4ed4cfe70b8facf3818ccf1867628a7453d53 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 13:08:29 -0400 Subject: [PATCH 13/37] get rid of unnecessary import --- src/Data/Syntax/Expression.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index c58a0ec8c..d84572ff0 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -11,7 +11,6 @@ import Diffing.Algorithm hiding (Delete) import Prologue hiding (index, Member, This, null) import Prelude hiding (null) import Proto3.Suite.Class -import Data.Word -- | Typical prefix function application, like `f(x)` in many languages, or `f x` in Haskell. data Call a = Call { callContext :: ![a], callFunction :: !a, callParams :: ![a], callBlock :: !a } From 18694f8143ba8e69ce4ce80aadcdf593a86f306a Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 13:22:48 -0400 Subject: [PATCH 14/37] add test for bitwise OR --- test/fixtures/typescript/analysis/bor.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/fixtures/typescript/analysis/bor.ts diff --git a/test/fixtures/typescript/analysis/bor.ts b/test/fixtures/typescript/analysis/bor.ts new file mode 100644 index 000000000..e1c9efd6e --- /dev/null +++ b/test/fixtures/typescript/analysis/bor.ts @@ -0,0 +1 @@ +1 | 2; From c76948c76ad02bf65b06a9d14cafd9df722a2c15 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 13:23:53 -0400 Subject: [PATCH 15/37] add test for bitwise and --- test/fixtures/typescript/analysis/band.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/fixtures/typescript/analysis/band.ts diff --git a/test/fixtures/typescript/analysis/band.ts b/test/fixtures/typescript/analysis/band.ts new file mode 100644 index 000000000..53908aadc --- /dev/null +++ b/test/fixtures/typescript/analysis/band.ts @@ -0,0 +1 @@ +1 & 2; From a5c7010f8554836eed940cac674e5b7e87352053 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 13:24:40 -0400 Subject: [PATCH 16/37] add test file for bxor --- test/Analysis/TypeScript/Spec.hs | 6 ++++++ test/fixtures/typescript/analysis/bxor.ts | 1 + 2 files changed, 7 insertions(+) create mode 100644 test/fixtures/typescript/analysis/bxor.ts diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index b4f20090c..467947045 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -69,6 +69,12 @@ spec config = parallel $ do Env.names env `shouldBe` [ "x" ] other -> expectationFailure (show other) + it "evaluates await statements" $ do + (_, (heap, res)) <- evaluate ["await.ts"] + case ModuleTable.lookup "await.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 20.0)] + other -> expectationFailure (show other) + where fixtures = "test/fixtures/typescript/analysis/" evaluate = evalTypeScriptProject . map (fixtures <>) diff --git a/test/fixtures/typescript/analysis/bxor.ts b/test/fixtures/typescript/analysis/bxor.ts new file mode 100644 index 000000000..10a02890b --- /dev/null +++ b/test/fixtures/typescript/analysis/bxor.ts @@ -0,0 +1 @@ +1 ^ 2; From 5891fe85106c90e7188377c9ba9f4c91265362bf Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 13:26:34 -0400 Subject: [PATCH 17/37] add tests for lshift, rshift, unsignedRshift --- test/fixtures/typescript/analysis/lshift.ts | 1 + test/fixtures/typescript/analysis/rshift.ts | 1 + test/fixtures/typescript/analysis/unsignedrshift.ts | 1 + 3 files changed, 3 insertions(+) create mode 100644 test/fixtures/typescript/analysis/lshift.ts create mode 100644 test/fixtures/typescript/analysis/rshift.ts create mode 100644 test/fixtures/typescript/analysis/unsignedrshift.ts diff --git a/test/fixtures/typescript/analysis/lshift.ts b/test/fixtures/typescript/analysis/lshift.ts new file mode 100644 index 000000000..c95bf5341 --- /dev/null +++ b/test/fixtures/typescript/analysis/lshift.ts @@ -0,0 +1 @@ +1 << 2; diff --git a/test/fixtures/typescript/analysis/rshift.ts b/test/fixtures/typescript/analysis/rshift.ts new file mode 100644 index 000000000..0eae5322b --- /dev/null +++ b/test/fixtures/typescript/analysis/rshift.ts @@ -0,0 +1 @@ +1 >> 2; diff --git a/test/fixtures/typescript/analysis/unsignedrshift.ts b/test/fixtures/typescript/analysis/unsignedrshift.ts new file mode 100644 index 000000000..a85780469 --- /dev/null +++ b/test/fixtures/typescript/analysis/unsignedrshift.ts @@ -0,0 +1 @@ +1 >>> 2; From 6526071cd2b6de1591448715eef052d4a89f6ea6 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 14:14:11 -0400 Subject: [PATCH 18/37] WIP test for bitwise OR --- test/Analysis/TypeScript/Spec.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 467947045..f96966060 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -68,12 +68,12 @@ spec config = parallel $ do (derefQName heap ("x" :| []) env) `shouldBe` Nothing Env.names env `shouldBe` [ "x" ] other -> expectationFailure (show other) - - it "evaluates await statements" $ do - (_, (heap, res)) <- evaluate ["await.ts"] - case ModuleTable.lookup "await.ts" <$> res of - Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 20.0)] - other -> expectationFailure (show other) + -- + -- it "evaluates BOr statements" $ do + -- (_, (heap, res)) <- evaluate ["bor.ts"] + -- case ModuleTable.lookup "bor.ts" <$> res of + -- Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 3.0)] + -- other -> expectationFailure (show other) where fixtures = "test/fixtures/typescript/analysis/" From 51e19ee24267b3015b7a99146186d0d777f228c6 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Fri, 17 Aug 2018 23:47:14 -0400 Subject: [PATCH 19/37] add test for BOr statements --- test/Analysis/TypeScript/Spec.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index f96966060..6cc8138c8 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -68,12 +68,12 @@ spec config = parallel $ do (derefQName heap ("x" :| []) env) `shouldBe` Nothing Env.names env `shouldBe` [ "x" ] other -> expectationFailure (show other) - -- - -- it "evaluates BOr statements" $ do - -- (_, (heap, res)) <- evaluate ["bor.ts"] - -- case ModuleTable.lookup "bor.ts" <$> res of - -- Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 3.0)] - -- other -> expectationFailure (show other) + + it "evaluates BOr statements" $ do + (_, (heap, res)) <- evaluate ["bor.ts"] + case ModuleTable.lookup "bor.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 3)] + other -> expectationFailure (show other) where fixtures = "test/fixtures/typescript/analysis/" From 6b99b321ce2b859b26eeafb7e4084d563ebd553a Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 11:10:56 -0400 Subject: [PATCH 20/37] use Data.Scientific to convert digit --- src/Data/Abstract/Value/Concrete.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index ae6fbc2d1..6f11698a1 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -19,7 +19,7 @@ import qualified Data.Abstract.Number as Number import Data.Bits import Data.Coerce import Data.List (genericIndex, genericLength) -import Data.Scientific (Scientific) +import Data.Scientific (Scientific, coefficient) import Data.Scientific.Exts import qualified Data.Set as Set import Data.Word @@ -158,6 +158,7 @@ instance ( Coercible body (Eff effects) , Member (Resumable (BaseError (ValueError address body))) effects , Member (Resumable (BaseError (AddressError address (Value address body)))) effects , Member (State (Heap address (Value address body))) effects + , Member Trace effects , Ord address , Show address ) @@ -272,6 +273,7 @@ instance ( Coercible body (Eff effects) liftBitwise2 operator left right | (Integer (Number.Integer i), Integer (Number.Integer j)) <- pair = pure . integer $ operator i j + | (Float (Number.Decimal i), Float (Number.Decimal j)) <- pair = pure . integer $ operator (coefficient (normalize i)) (coefficient (normalize j)) | otherwise = throwValueError (Bitwise2Error left right) where pair = (left, right) From a3bec5b910c668e61e3150df9172cc34ff13ed19 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 16:47:59 -0400 Subject: [PATCH 21/37] add tests for bor, band, bxor --- test/Analysis/TypeScript/Spec.hs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 6cc8138c8..702b55ee4 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -72,9 +72,22 @@ spec config = parallel $ do it "evaluates BOr statements" $ do (_, (heap, res)) <- evaluate ["bor.ts"] case ModuleTable.lookup "bor.ts" <$> res of - Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 3)] + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)] other -> expectationFailure (show other) + it "evaluates BAnd statements" $ do + (_, (heap, res)) <- evaluate ["band.ts"] + case ModuleTable.lookup "band.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)] + other -> expectationFailure (show other) + + it "evaluates BXOr statements" $ do + (_, (heap, res)) <- evaluate ["bxor.ts"] + case ModuleTable.lookup "bxor.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)] + other -> expectationFailure (show other) + + where fixtures = "test/fixtures/typescript/analysis/" evaluate = evalTypeScriptProject . map (fixtures <>) From 8cf838217c3a33c3232a72b367bc595874ee1b33 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 16:56:37 -0400 Subject: [PATCH 22/37] test for lshift --- test/Analysis/TypeScript/Spec.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 702b55ee4..83fa972ed 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -87,6 +87,12 @@ spec config = parallel $ do Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)] other -> expectationFailure (show other) + it "evaluates LShift statements" $ do + (_, (heap, res)) <- evaluate ["lshift.ts"] + case ModuleTable.lookup "lshift.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)] + other -> expectationFailure (show other) + where fixtures = "test/fixtures/typescript/analysis/" From 167e9e393470918e4ae80d22133dfed5bd80a689 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 16:57:35 -0400 Subject: [PATCH 23/37] test for rshift --- test/Analysis/TypeScript/Spec.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 83fa972ed..95ee23c78 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -87,9 +87,9 @@ spec config = parallel $ do Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)] other -> expectationFailure (show other) - it "evaluates LShift statements" $ do - (_, (heap, res)) <- evaluate ["lshift.ts"] - case ModuleTable.lookup "lshift.ts" <$> res of + it "evaluates RShift statements" $ do + (_, (heap, res)) <- evaluate ["rshift.ts"] + case ModuleTable.lookup "rshift.ts" <$> res of Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)] other -> expectationFailure (show other) From c6b31ab8865b1816b82bc8b5145820985a402e9b Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 17:01:13 -0400 Subject: [PATCH 24/37] fix rshift and lshift tests --- test/Analysis/TypeScript/Spec.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 95ee23c78..00e51a396 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -87,10 +87,16 @@ spec config = parallel $ do Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)] other -> expectationFailure (show other) + it "evaluates LShift statements" $ do + (_, (heap, res)) <- evaluate ["Lshift.ts"] + case ModuleTable.lookup "rshift.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)] + other -> expectationFailure (show other) + it "evaluates RShift statements" $ do (_, (heap, res)) <- evaluate ["rshift.ts"] case ModuleTable.lookup "rshift.ts" <$> res of - Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)] + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)] other -> expectationFailure (show other) From da79989904ca8d340de6244e9ce0d360b3fc1387 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 17:42:58 -0400 Subject: [PATCH 25/37] add test for await --- test/Analysis/TypeScript/Spec.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 00e51a396..21596f9a2 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -69,6 +69,14 @@ spec config = parallel $ do Env.names env `shouldBe` [ "x" ] other -> expectationFailure (show other) + it "evaluates await" $ do + (_, (heap, res)) <- evaluate ["await.ts"] + case ModuleTable.lookup "await.ts" <$> res of + Right (Just (Module _ (env, addr) :| [])) -> do + Env.names env `shouldBe` [ "f2" ] + (derefQName heap ("y" :| []) env) `shouldBe` Nothing + other -> expectationFailure (show other) + it "evaluates BOr statements" $ do (_, (heap, res)) <- evaluate ["bor.ts"] case ModuleTable.lookup "bor.ts" <$> res of From bf0d2c04184038c73bda9533898c2895c96e84fc Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Mon, 20 Aug 2018 18:57:28 -0400 Subject: [PATCH 26/37] adjust liftBitwise to include float --- src/Data/Abstract/Value/Concrete.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index 6f11698a1..845d61bd2 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -269,6 +269,7 @@ instance ( Coercible body (Eff effects) liftBitwise operator target | Integer (Number.Integer i) <- target = pure . integer $ operator i + | Float (Number.Decimal i) <- target = pure . integer $ operator (coefficient i) | otherwise = throwValueError (BitwiseError target) liftBitwise2 operator left right From a4ce904e5d35c3a0132b69cc864327799648b2b5 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 21 Aug 2018 16:12:05 -0400 Subject: [PATCH 27/37] add normalize function --- src/Data/Abstract/Value/Concrete.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index 845d61bd2..7159ee64d 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -269,7 +269,7 @@ instance ( Coercible body (Eff effects) liftBitwise operator target | Integer (Number.Integer i) <- target = pure . integer $ operator i - | Float (Number.Decimal i) <- target = pure . integer $ operator (coefficient i) + | Float (Number.Decimal i) <- target = pure . integer $ operator (coefficient (normalize i)) | otherwise = throwValueError (BitwiseError target) liftBitwise2 operator left right From 09f735b2b7177f0dbfb001db9f8b0f1ab6960fac Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 21 Aug 2018 17:47:45 -0400 Subject: [PATCH 28/37] add typescript assignment for complement operator --- src/Language/TypeScript/Assignment.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Language/TypeScript/Assignment.hs b/src/Language/TypeScript/Assignment.hs index 699830e96..2b40e195b 100644 --- a/src/Language/TypeScript/Assignment.hs +++ b/src/Language/TypeScript/Assignment.hs @@ -295,7 +295,8 @@ awaitExpression = makeTerm <$> symbol Grammar.AwaitExpression <*> children (Expr unaryExpression :: Assignment Term unaryExpression = symbol Grammar.UnaryExpression >>= \ loc -> - makeTerm loc . Expression.Not <$> children ((symbol AnonTilde <|> symbol AnonBang) *> term expression) + makeTerm loc . Expression.Not <$> children (symbol AnonBang *> term expression) + <|> makeTerm loc . Expression.Complement <$> children (symbol AnonTilde *> term expression) <|> makeTerm loc . Expression.Negate <$> children ((symbol AnonMinus <|> symbol AnonPlus) *> term expression) <|> makeTerm loc . Expression.Typeof <$> children (symbol AnonTypeof *> term expression) <|> makeTerm loc . Expression.Void <$> children (symbol AnonVoid *> term expression) From 7b4f0f2605044f5cdeed76b82ddd349ce27ab770 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 21 Aug 2018 17:48:18 -0400 Subject: [PATCH 29/37] handle floats in unsignedRShift function --- src/Data/Abstract/Value/Concrete.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index 7159ee64d..1a373ba20 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -282,6 +282,9 @@ instance ( Coercible body (Eff effects) | (Integer (Number.Integer i), Integer (Number.Integer j)) <- pair = if i >= 0 then pure . integer $ ourShift (fromIntegral i) (fromIntegral j) else throwValueError (Bitwise2Error left right) + | (Float (Number.Decimal i), Float (Number.Decimal j)) <- pair = + if i >= 0 then pure . integer $ ourShift (fromInteger (coefficient (normalize i))) (fromInteger (coefficient (normalize j))) + else throwValueError (Bitwise2Error left right) | otherwise = throwValueError (Bitwise2Error left right) where pair = (left, right) From 9d676c5ba1559d9f6e9c7c6a27050b22674fa01e Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Tue, 21 Aug 2018 18:33:16 -0400 Subject: [PATCH 30/37] make these tests passsssgit diffgit diff --- test/Analysis/TypeScript/Spec.hs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/Analysis/TypeScript/Spec.hs b/test/Analysis/TypeScript/Spec.hs index 21596f9a2..6ebd635ff 100644 --- a/test/Analysis/TypeScript/Spec.hs +++ b/test/Analysis/TypeScript/Spec.hs @@ -96,8 +96,8 @@ spec config = parallel $ do other -> expectationFailure (show other) it "evaluates LShift statements" $ do - (_, (heap, res)) <- evaluate ["Lshift.ts"] - case ModuleTable.lookup "rshift.ts" <$> res of + (_, (heap, res)) <- evaluate ["lshift.ts"] + case ModuleTable.lookup "lshift.ts" <$> res of Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)] other -> expectationFailure (show other) @@ -107,6 +107,12 @@ spec config = parallel $ do Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)] other -> expectationFailure (show other) + it "evaluates Complement statements" $ do + (_, (heap, res)) <- evaluate ["complement.ts"] + case ModuleTable.lookup "complement.ts" <$> res of + Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer (-2))] + other -> expectationFailure (show other) + where fixtures = "test/fixtures/typescript/analysis/" From 86f21c7e21c440c80bcb946b46fb3b1a4d30c529 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 22 Aug 2018 15:48:30 -0400 Subject: [PATCH 31/37] add castToInteger --- src/Control/Abstract/Value.hs | 4 ++++ src/Data/Abstract/Value/Abstract.hs | 2 ++ src/Data/Abstract/Value/Concrete.hs | 9 +++------ src/Data/Abstract/Value/Type.hs | 2 ++ src/Data/Syntax/Expression.hs | 26 +++++++++++++------------- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Control/Abstract/Value.hs b/src/Control/Abstract/Value.hs index 90528dea1..45cfc7fd3 100644 --- a/src/Control/Abstract/Value.hs +++ b/src/Control/Abstract/Value.hs @@ -97,6 +97,10 @@ class Show value => AbstractIntro value where -- -- This allows us to abstract the choice of whether to evaluate under binders for different value types. class AbstractIntro value => AbstractValue address value effects where + -- | Cast numbers to integers + castToInteger :: value -> Evaluator address value effects value + + -- | Lift a unary operator over a 'Num' to a function on 'value's. liftNumeric :: (forall a . Num a => a -> a) -> (value -> Evaluator address value effects value) diff --git a/src/Data/Abstract/Value/Abstract.hs b/src/Data/Abstract/Value/Abstract.hs index d7314fc2a..d30645019 100644 --- a/src/Data/Abstract/Value/Abstract.hs +++ b/src/Data/Abstract/Value/Abstract.hs @@ -95,3 +95,5 @@ instance ( Member (Allocator address) effects liftComparison _ _ _ = pure Abstract loop f = f empty + + castToInteger _ = pure Abstract diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index 1a373ba20..e8a99773e 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -19,7 +19,7 @@ import qualified Data.Abstract.Number as Number import Data.Bits import Data.Coerce import Data.List (genericIndex, genericLength) -import Data.Scientific (Scientific, coefficient) +import Data.Scientific (Scientific, coefficient, normalize) import Data.Scientific.Exts import qualified Data.Set as Set import Data.Word @@ -269,12 +269,10 @@ instance ( Coercible body (Eff effects) liftBitwise operator target | Integer (Number.Integer i) <- target = pure . integer $ operator i - | Float (Number.Decimal i) <- target = pure . integer $ operator (coefficient (normalize i)) | otherwise = throwValueError (BitwiseError target) liftBitwise2 operator left right | (Integer (Number.Integer i), Integer (Number.Integer j)) <- pair = pure . integer $ operator i j - | (Float (Number.Decimal i), Float (Number.Decimal j)) <- pair = pure . integer $ operator (coefficient (normalize i)) (coefficient (normalize j)) | otherwise = throwValueError (Bitwise2Error left right) where pair = (left, right) @@ -282,9 +280,6 @@ instance ( Coercible body (Eff effects) | (Integer (Number.Integer i), Integer (Number.Integer j)) <- pair = if i >= 0 then pure . integer $ ourShift (fromIntegral i) (fromIntegral j) else throwValueError (Bitwise2Error left right) - | (Float (Number.Decimal i), Float (Number.Decimal j)) <- pair = - if i >= 0 then pure . integer $ ourShift (fromInteger (coefficient (normalize i))) (fromInteger (coefficient (normalize j))) - else throwValueError (Bitwise2Error left right) | otherwise = throwValueError (Bitwise2Error left right) where pair = (left, right) @@ -296,6 +291,8 @@ instance ( Coercible body (Eff effects) -- FIXME: Figure out how to deal with this. Ruby treats this as the result of the current block iteration, while PHP specifies a breakout level and TypeScript appears to take a label. Continue _ -> loop x) + castToInteger (Integer (Number.Integer i)) = pure (Integer (Number.Integer i)) + castToInteger (Float (Number.Decimal i)) = pure (Integer (Number.Integer (coefficient (normalize i)))) -- | The type of exceptions that can be thrown when constructing values in 'Value'’s 'MonadValue' instance. data ValueError address body resume where diff --git a/src/Data/Abstract/Value/Type.hs b/src/Data/Abstract/Value/Type.hs index 9078e2719..c6f35c8cf 100644 --- a/src/Data/Abstract/Value/Type.hs +++ b/src/Data/Abstract/Value/Type.hs @@ -343,3 +343,5 @@ instance ( Member (Allocator address) effects _ -> unify left right $> Bool loop f = f empty + + castToInteger t = unify t (Int :+ Float :+ Rational) $> Int diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index d84572ff0..b96c3cbc9 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -327,8 +327,8 @@ instance Ord1 BOr where liftCompare = genericLiftCompare instance Show1 BOr where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BOr where eval (BOr a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger liftBitwise2 (.|.) a' b' >>= rvalBox data BAnd a = BAnd { left :: a, right :: a } @@ -339,8 +339,8 @@ instance Ord1 BAnd where liftCompare = genericLiftCompare instance Show1 BAnd where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BAnd where eval (BAnd a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger liftBitwise2 (.&.) a' b' >>= rvalBox @@ -352,8 +352,8 @@ instance Ord1 BXOr where liftCompare = genericLiftCompare instance Show1 BXOr where liftShowsPrec = genericLiftShowsPrec instance Evaluatable BXOr where eval (BXOr a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger liftBitwise2 xor a' b' >>= rvalBox data LShift a = LShift { left :: a, right :: a } @@ -364,8 +364,8 @@ instance Ord1 LShift where liftCompare = genericLiftCompare instance Show1 LShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable LShift where eval (LShift a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger liftBitwise2 shiftL' a' b' >>= rvalBox where shiftL' a b = shiftL a (fromIntegral (toInteger b)) @@ -378,8 +378,8 @@ instance Ord1 RShift where liftCompare = genericLiftCompare instance Show1 RShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable RShift where eval (RShift a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger liftBitwise2 shiftR' a' b' >>= rvalBox where shiftR' a b = shiftR a (fromIntegral (toInteger b)) @@ -392,8 +392,8 @@ instance Ord1 UnsignedRShift where liftCompare = genericLiftCompare instance Show1 UnsignedRShift where liftShowsPrec = genericLiftShowsPrec instance Evaluatable UnsignedRShift where eval (UnsignedRShift a b) = do - a' <- subtermValue a - b' <- subtermValue b + a' <- subtermValue a >>= castToInteger + b' <- subtermValue b >>= castToInteger unsignedRShift a' b' >>= rvalBox -- This isn't working for JavaScript @@ -406,7 +406,7 @@ instance Show1 Complement where liftShowsPrec = genericLiftShowsPrec instance Evaluatable Complement where eval (Complement a) = do - a' <- subtermValue a + a' <- subtermValue a >>= castToInteger liftBitwise complement a' >>= rvalBox -- | Member Access (e.g. a.b) From 77f7273b7549530113a962c60a0fb79d99f19093 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 22 Aug 2018 15:54:40 -0400 Subject: [PATCH 32/37] add error handling for castToInteger --- src/Data/Abstract/Value/Concrete.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Abstract/Value/Concrete.hs b/src/Data/Abstract/Value/Concrete.hs index e8a99773e..401bdd0c2 100644 --- a/src/Data/Abstract/Value/Concrete.hs +++ b/src/Data/Abstract/Value/Concrete.hs @@ -293,6 +293,7 @@ instance ( Coercible body (Eff effects) castToInteger (Integer (Number.Integer i)) = pure (Integer (Number.Integer i)) castToInteger (Float (Number.Decimal i)) = pure (Integer (Number.Integer (coefficient (normalize i)))) + castToInteger i = throwValueError (NumericError i) -- | The type of exceptions that can be thrown when constructing values in 'Value'’s 'MonadValue' instance. data ValueError address body resume where From 534bf2b728d126cf4a56556c03447b7c87e55f15 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Wed, 22 Aug 2018 17:22:47 -0400 Subject: [PATCH 33/37] fake evaluating cast expressions --- src/Data/Syntax/Expression.hs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index b96c3cbc9..2b7e1ef7f 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -273,7 +273,6 @@ instance Eq1 Delete where liftEq = genericLiftEq instance Ord1 Delete where liftCompare = genericLiftCompare instance Show1 Delete where liftShowsPrec = genericLiftShowsPrec --- TODO: Implement Eval instance for Delete instance Evaluatable Delete where eval (Delete a) = do valueRef <- subtermRef a @@ -289,7 +288,6 @@ instance Eq1 SequenceExpression where liftEq = genericLiftEq instance Ord1 SequenceExpression where liftCompare = genericLiftCompare instance Show1 SequenceExpression where liftShowsPrec = genericLiftShowsPrec --- TODO: Implement Eval instance for SequenceExpression instance Evaluatable SequenceExpression where eval (SequenceExpression a b) = subtermValue a >> subtermRef b @@ -302,7 +300,6 @@ instance Eq1 Void where liftEq = genericLiftEq instance Ord1 Void where liftCompare = genericLiftCompare instance Show1 Void where liftShowsPrec = genericLiftShowsPrec --- TODO: Implement Eval instance for Void instance Evaluatable Void where eval (Void a) = subtermValue a >> rvalBox null @@ -527,8 +524,9 @@ instance Eq1 Cast where liftEq = genericLiftEq instance Ord1 Cast where liftCompare = genericLiftCompare instance Show1 Cast where liftShowsPrec = genericLiftShowsPrec --- TODO: Implement Eval instance for Cast -instance Evaluatable Cast +-- TODO: This isn't actually casting anything; we need to be able to extract a type from a subterm and implement a subtyping relation. +instance Evaluatable Cast where + eval (Cast value type') = subtermRef value data Super a = Super deriving (Diffable, Eq, Foldable, Functor, Generic1, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1, Hashable1) From 6cf92bb760f931273837240a6abfce0cc121959f Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Thu, 23 Aug 2018 10:38:53 -0400 Subject: [PATCH 34/37] remove eval instances for cast because of ci fail --- src/Data/Syntax/Expression.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 2b7e1ef7f..3d74ef988 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -524,9 +524,7 @@ instance Eq1 Cast where liftEq = genericLiftEq instance Ord1 Cast where liftCompare = genericLiftCompare instance Show1 Cast where liftShowsPrec = genericLiftShowsPrec --- TODO: This isn't actually casting anything; we need to be able to extract a type from a subterm and implement a subtyping relation. -instance Evaluatable Cast where - eval (Cast value type') = subtermRef value +instance Evaluatable Cast data Super a = Super deriving (Diffable, Eq, Foldable, Functor, Generic1, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1, Hashable1) From 4be365ddcb54ab43209b53f40cae5441f9b09c18 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Thu, 23 Aug 2018 11:25:20 -0400 Subject: [PATCH 35/37] add test --- test/fixtures/typescript/analysis/complement.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/fixtures/typescript/analysis/complement.ts diff --git a/test/fixtures/typescript/analysis/complement.ts b/test/fixtures/typescript/analysis/complement.ts new file mode 100644 index 000000000..f6c761f5d --- /dev/null +++ b/test/fixtures/typescript/analysis/complement.ts @@ -0,0 +1 @@ +~1; From 8e17c2df87d83d0676257b50f35b710697ce1439 Mon Sep 17 00:00:00 2001 From: Ayman Nadeem Date: Thu, 23 Aug 2018 12:09:51 -0400 Subject: [PATCH 36/37] remove fake news comment about unsignedRshift --- src/Data/Syntax/Expression.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Data/Syntax/Expression.hs b/src/Data/Syntax/Expression.hs index 3d74ef988..2722986c1 100644 --- a/src/Data/Syntax/Expression.hs +++ b/src/Data/Syntax/Expression.hs @@ -392,7 +392,6 @@ instance Evaluatable UnsignedRShift where a' <- subtermValue a >>= castToInteger b' <- subtermValue b >>= castToInteger unsignedRShift a' b' >>= rvalBox - -- This isn't working for JavaScript newtype Complement a = Complement { value :: a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1) From 99a19e6e1746af60f8136d64158804c8b07ba575 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 23 Aug 2018 13:37:56 -0400 Subject: [PATCH 37/37] Bump effects for more accurate error context. This brings in https://github.com/joshvera/effects/pull/65, avoiding a bug where local changes would be applied outside the local scope. --- vendor/effects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/effects b/vendor/effects index b78e9c6e7..8ded4a641 160000 --- a/vendor/effects +++ b/vendor/effects @@ -1 +1 @@ -Subproject commit b78e9c6e77c89ab9c338aae9cf2e24d0e5f3abfc +Subproject commit 8ded4a64133ce77ddd2fc734f455753e62af0ad3