Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit 3dea3d7

Browse files
authored
Merge branch 'master' into add-php
2 parents 3daee38 + e0ff53e commit 3dea3d7

23 files changed

+336
-99
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ script:
3737
- cabal new-build
3838
- cabal new-run semantic:test
3939
- cabal new-run semantic-core:spec
40+
- cabal new-run semantic-core:doctest
4041
# parse-examples is disabled because it slaughters our CI
4142
# - cabal new-run semantic:parse-examples
4243

cabal.project

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
packages: . semantic-core
1+
packages: . semantic-core semantic-python
22

33
jobs: $ncpus
44

semantic-core/semantic-core.cabal

+20-9
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ cabal-version: 2.4
33
name: semantic-core
44
version: 0.0.0.0
55
synopsis: Semantic core intermediate language
6-
-- description:
7-
homepage: https://github.com/github/semantic-core
8-
-- bug-reports:
6+
description: Core intermediate language for program analysis using abstract definitional interpretation.
7+
homepage: https://github.com/github/semantic/tree/master/semantic-core#readme
8+
bug-reports: https://github.com/github/semantic/issues
99
license: MIT
1010
license-file: LICENSE
11-
author: Rob Rix
12-
maintainer: robrix@github.com
13-
-- copyright:
11+
author: The Semantic authors
12+
maintainer: opensource+semantic@github.com
13+
copyright: (c) 2019 GitHub, Inc.
1414
category: Language
1515
build-type: Simple
16+
stability: alpha
1617
extra-source-files: README.md
1718

1819
tested-with: GHC == 8.6.4
@@ -46,14 +47,24 @@ library
4647
, prettyprinter-ansi-terminal ^>= 1.1.1
4748
, recursion-schemes ^>= 5.1
4849
, semigroupoids ^>= 5.3
50+
, text ^>= 1.2.3.1
4951
, transformers ^>= 0.5.6
5052
, trifecta ^>= 2
5153
, unordered-containers ^>= 0.2.10
5254
hs-source-dirs: src
5355
default-language: Haskell2010
54-
ghc-options: -Weverything -Wno-missing-local-signatures -Wno-missing-import-lists -Wno-implicit-prelude -Wno-safe -Wno-unsafe -Wno-name-shadowing -Wno-monomorphism-restriction -Wno-missed-specialisations -Wno-all-missed-specialisations
55-
if (impl(ghc >= 8.6))
56-
ghc-options: -Wno-star-is-type
56+
ghc-options:
57+
-Weverything
58+
-Wno-missing-local-signatures
59+
-Wno-missing-import-lists
60+
-Wno-implicit-prelude
61+
-Wno-safe
62+
-Wno-unsafe
63+
-Wno-name-shadowing
64+
-Wno-monomorphism-restriction
65+
-Wno-missed-specialisations
66+
-Wno-all-missed-specialisations
67+
-Wno-star-is-type
5768

5869
test-suite doctest
5970
type: exitcode-stdio-1.0

semantic-core/src/Analysis/Concrete.hs

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, RecordWildCards, TypeOperators, UndecidableInstances #-}
1+
{-# LANGUAGE FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, RecordWildCards, TypeOperators, UndecidableInstances #-}
22
module Analysis.Concrete
33
( Concrete(..)
44
, concrete
@@ -29,6 +29,7 @@ import Data.Loc
2929
import qualified Data.Map as Map
3030
import Data.Monoid (Alt(..))
3131
import Data.Name
32+
import Data.Text (Text, pack)
3233
import Prelude hiding (fail)
3334

3435
type Precise = Int
@@ -41,7 +42,7 @@ data Concrete
4142
= Closure Loc Name Core.Core Precise
4243
| Unit
4344
| Bool Bool
44-
| String String
45+
| String Text
4546
| Obj Frame
4647
deriving (Eq, Ord, Show)
4748

@@ -60,7 +61,7 @@ type Heap = IntMap.IntMap Concrete
6061

6162
-- | Concrete evaluation of a term to a value.
6263
--
63-
-- >>> snd (concrete [File (Loc "bool" emptySpan) (Core.Bool True)])
64+
-- >>> map fileBody (snd (concrete [File (Loc "bool" emptySpan) (Core.Bool True)]))
6465
-- [Right (Bool True)]
6566
concrete :: [File Core.Core] -> (Heap, [File (Either (Loc, String) Concrete)])
6667
concrete
@@ -184,28 +185,32 @@ heapValueGraph h = heapGraph (const id) (const fromAddr) h
184185
heapAddressGraph :: Heap -> G.Graph (EdgeType, Precise)
185186
heapAddressGraph = heapGraph (\ addr v -> (Value v, addr)) (fmap G.vertex . (,) . either Edge Slot)
186187

187-
addressStyle :: Heap -> G.Style (EdgeType, Precise) String
188+
addressStyle :: Heap -> G.Style (EdgeType, Precise) Text
188189
addressStyle heap = (G.defaultStyle vertex) { G.edgeAttributes }
189-
where vertex (_, addr) = maybe (show addr <> " = ?") (((show addr <> " = ") <>) . fromConcrete) (IntMap.lookup addr heap)
190+
where vertex (_, addr) = pack (show addr) <> " = " <> maybe "?" fromConcrete (IntMap.lookup addr heap)
190191
edgeAttributes _ (Slot name, _) = ["label" G.:= fromName name]
191192
edgeAttributes _ (Edge Core.Import, _) = ["color" G.:= "blue"]
192193
edgeAttributes _ (Edge Core.Lexical, _) = ["color" G.:= "green"]
193194
edgeAttributes _ _ = []
194195
fromConcrete = \case
195196
Unit -> "()"
196-
Bool b -> show b
197-
String s -> show s
197+
Bool b -> pack $ show b
198+
String s -> pack $ show s
198199
Closure (Loc p (Span s e)) n _ _ -> "\\\\ " <> fromName n <> " [" <> p <> ":" <> showPos s <> "-" <> showPos e <> "]"
199200
Obj _ -> "{}"
200-
showPos (Pos l c) = show l <> ":" <> show c
201+
showPos (Pos l c) = pack (show l) <> ":" <> pack (show c)
201202
fromName (User s) = s
202203
fromName (Gen sym) = fromGensym sym
203-
fromName (Path p) = show p
204+
fromName (Path p) = pack $ show p
204205
fromGensym (Root s) = s
205-
fromGensym (ss :/ (s, i)) = fromGensym ss <> "." <> s <> show i
206+
fromGensym (ss :/ (s, i)) = fromGensym ss <> "." <> s <> pack (show i)
206207

207208
data EdgeType
208209
= Edge Core.Edge
209210
| Slot Name
210211
| Value Concrete
211212
deriving (Eq, Ord, Show)
213+
214+
215+
-- $setup
216+
-- >>> :seti -XOverloadedStrings

semantic-core/src/Analysis/Eval.hs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE FlexibleContexts, LambdaCase, RankNTypes, RecordWildCards #-}
1+
{-# LANGUAGE FlexibleContexts, LambdaCase, OverloadedStrings, RankNTypes, RecordWildCards #-}
22
module Analysis.Eval
33
( eval
44
, prog1
@@ -21,6 +21,7 @@ import Data.Functor
2121
import Data.Loc
2222
import Data.Maybe (fromJust)
2323
import Data.Name
24+
import Data.Text (Text)
2425
import GHC.Stack
2526
import Prelude hiding (fail)
2627

@@ -207,8 +208,8 @@ data Analysis address value m = Analysis
207208
, unit :: m value
208209
, bool :: Bool -> m value
209210
, asBool :: value -> m Bool
210-
, string :: String -> m value -- FIXME: Text
211-
, asString :: value -> m String
211+
, string :: Text -> m value
212+
, asString :: value -> m Text
212213
, frame :: m value
213214
, edge :: Edge -> address -> m ()
214215
, (...) :: forall a . address -> m a -> m a

semantic-core/src/Analysis/FlowInsensitive.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
1+
{-# LANGUAGE FlexibleContexts, OverloadedStrings, ScopedTypeVariables #-}
22
module Analysis.FlowInsensitive
33
( Heap
44
, FrameId(..)

semantic-core/src/Analysis/ImportGraph.hs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE FlexibleContexts, RecordWildCards #-}
1+
{-# LANGUAGE FlexibleContexts, OverloadedStrings, RecordWildCards #-}
22
module Analysis.ImportGraph
33
( ImportGraph
44
, importGraph
@@ -22,9 +22,10 @@ import Data.Loc
2222
import qualified Data.Map as Map
2323
import Data.Name
2424
import qualified Data.Set as Set
25+
import Data.Text (Text)
2526
import Prelude hiding (fail)
2627

27-
type ImportGraph = Map.Map FilePath (Set.Set FilePath)
28+
type ImportGraph = Map.Map Text (Set.Set Text)
2829

2930
data Value = Value
3031
{ valueSemi :: Semi
@@ -41,7 +42,7 @@ instance Monoid Value where
4142
data Semi
4243
= Closure Loc Name Core.Core Name
4344
-- FIXME: Bound String values.
44-
| String String
45+
| String Text
4546
| Abstract
4647
deriving (Eq, Ord, Show)
4748

@@ -98,7 +99,7 @@ importGraphAnalysis = Analysis{..}
9899
asBool _ = pure True <|> pure False
99100
string s = pure (Value (String s) mempty)
100101
asString (Value (String s) _) = pure s
101-
asString _ = pure ""
102+
asString _ = pure mempty
102103
frame = pure mempty
103104
edge Core.Import (Path to) = do
104105
Loc{locPath=from} <- ask

semantic-core/src/Analysis/Typecheck.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, LambdaCase, RecordWildCards, ScopedTypeVariables, TypeApplications #-}
1+
{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, LambdaCase, OverloadedStrings, RecordWildCards, ScopedTypeVariables, TypeApplications #-}
22
module Analysis.Typecheck
33
( Monotype (..)
44
, Meta
@@ -160,7 +160,7 @@ typecheckingAnalysis = Analysis{..}
160160
bool _ = pure MBool
161161
asBool b = unify MBool b >> pure True <|> pure False
162162
string _ = pure MString
163-
asString s = unify MString s $> ""
163+
asString s = unify MString s $> mempty
164164
frame = fail "unimplemented"
165165
edge _ _ = pure ()
166166
_ ... m = m

semantic-core/src/Data/Core.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Data.Foldable (foldl')
2020
import Data.Loc
2121
import Data.Name
2222
import Data.Stack
23+
import Data.Text (Text)
2324
import GHC.Stack
2425

2526
data Edge = Lexical | Import
@@ -36,7 +37,7 @@ data Core
3637
| Unit
3738
| Bool Bool
3839
| If Core Core Core
39-
| String String -- FIXME: Text
40+
| String Text
4041
-- | Load the specified file (by path).
4142
| Load Core
4243
| Edge Edge Core

semantic-core/src/Data/Core/Parser.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Data.Core
1414
import Data.Name
1515
import Data.Semigroup
1616
import Data.String
17+
import Data.Text (pack)
1718
import qualified Text.Parser.Token as Token
1819
import qualified Text.Parser.Token.Highlight as Highlight
1920
import Text.Trifecta hiding (ident)
@@ -94,7 +95,7 @@ lvalue = choice
9495
name :: (TokenParsing m, Monad m) => m Name
9596
name = choice [regular, strpath] <?> "name" where
9697
regular = User <$> identifier
97-
strpath = Path <$> between (symbolic '"') (symbolic '"') (some $ noneOf "\"")
98+
strpath = Path . pack <$> between (symbolic '"') (symbolic '"') (some $ noneOf "\"")
9899

99100
lit :: (TokenParsing m, Monad m) => m Core
100101
lit = let x `given` n = x <$ reserved n in choice
@@ -112,4 +113,3 @@ lambda = Lam <$ lambduh <*> name <* arrow <*> core <?> "lambda" where
112113

113114
ident :: (Monad m, TokenParsing m) => m Core
114115
ident = Var <$> name <?> "identifier"
115-

semantic-core/src/Data/Loc.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ import Control.Effect.Error
1616
import Control.Effect.Fail
1717
import Control.Effect.Reader
1818
import Control.Effect.Sum
19+
import Data.Text (Text, pack)
1920
import Data.Text.Prettyprint.Doc (Pretty (..))
2021
import GHC.Stack
2122
import Prelude hiding (fail)
2223

2324
data Loc = Loc
24-
{ locPath :: !FilePath
25+
{ locPath :: !Text
2526
, locSpan :: {-# UNPACK #-} !Span
2627
}
2728
deriving (Eq, Ord, Show)
@@ -58,7 +59,7 @@ stackLoc cs = case getCallStack cs of
5859
_ -> Nothing
5960

6061
fromGHCSrcLoc :: SrcLoc -> Loc
61-
fromGHCSrcLoc SrcLoc{..} = Loc srcLocFile (Span (Pos srcLocStartLine srcLocStartCol) (Pos srcLocEndLine srcLocEndCol))
62+
fromGHCSrcLoc SrcLoc{..} = Loc (pack srcLocFile) (Span (Pos srcLocStartLine srcLocStartCol) (Pos srcLocEndLine srcLocEndCol))
6263

6364

6465
runFailWithLoc :: FailWithLocC m a -> m (Either (Loc, String) a)

semantic-core/src/Data/Name.hs

+12-11
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ import Control.Monad.IO.Class
2626
import qualified Data.Char as Char
2727
import Data.HashSet (HashSet)
2828
import qualified Data.HashSet as HashSet
29+
import Data.Text as Text (Text, any, unpack)
2930
import Data.Text.Prettyprint.Doc (Pretty (..))
3031
import qualified Data.Text.Prettyprint.Doc as Pretty
3132

3233
-- | User-specified and -relevant names.
33-
type User = String
34+
type User = Text
3435

3536
-- | The type of namespaced actions, i.e. actions occurring within some outer name.
3637
--
@@ -47,7 +48,7 @@ data Name
4748
-- This should be used for names which the user provided and which other code (other functions, other modules, other packages) could call, e.g. declaration names.
4849
| User User
4950
-- | A variable name represented as the path to a source file. Used for loading modules at a specific name.
50-
| Path FilePath
51+
| Path Text
5152
deriving (Eq, Ord, Show)
5253

5354
instance Pretty Name where
@@ -56,14 +57,14 @@ instance Pretty Name where
5657
User n -> pretty n
5758
Path p -> pretty (show p)
5859

59-
reservedNames :: HashSet User
60+
reservedNames :: HashSet String
6061
reservedNames = [ "#true", "#false", "let", "#frame", "if", "then", "else"
6162
, "lexical", "import", "#unit", "load"]
6263

6364
-- | Returns true if any character would require quotation or if the
6465
-- name conflicts with a Core primitive.
6566
needsQuotation :: User -> Bool
66-
needsQuotation u = HashSet.member u reservedNames || any (not . isSimpleCharacter) u
67+
needsQuotation u = HashSet.member (unpack u) reservedNames || Text.any (not . isSimpleCharacter) u
6768

6869
-- | A ‘simple’ character is, loosely defined, a character that is compatible
6970
-- with identifiers in most ASCII-oriented programming languages. This is defined
@@ -76,30 +77,30 @@ isSimpleCharacter = \case
7677
c -> Char.isAlphaNum c
7778

7879
data Gensym
79-
= Root String
80-
| Gensym :/ (String, Int)
80+
= Root Text
81+
| Gensym :/ (Text, Int)
8182
deriving (Eq, Ord, Show)
8283

8384
instance Pretty Gensym where
8485
pretty = \case
8586
Root s -> pretty s
8687
p :/ (n, x) -> Pretty.hcat [pretty p, "/", pretty n, "^", pretty x]
8788

88-
(//) :: Gensym -> String -> Gensym
89+
(//) :: Gensym -> Text -> Gensym
8990
root // s = root :/ (s, 0)
9091

9192
infixl 6 //
9293

93-
gensym :: (Carrier sig m, Member Naming sig) => String -> m Gensym
94+
gensym :: (Carrier sig m, Member Naming sig) => Text -> m Gensym
9495
gensym s = send (Gensym s pure)
9596

96-
namespace :: (Carrier sig m, Member Naming sig) => String -> m a -> m a
97+
namespace :: (Carrier sig m, Member Naming sig) => Text -> m a -> m a
9798
namespace s m = send (Namespace s m pure)
9899

99100

100101
data Naming m k
101-
= Gensym String (Gensym -> k)
102-
| forall a . Namespace String (m a) (a -> k)
102+
= Gensym Text (Gensym -> k)
103+
| forall a . Namespace Text (m a) (a -> k)
103104

104105
deriving instance Functor (Naming m)
105106

semantic-core/test/Doctest.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ main :: IO ()
99
main = do
1010
args <- getArgs
1111
autogen <- fmap (<> "/build/doctest/autogen") <$> lookupEnv "HASKELL_DIST_DIR"
12-
doctest (maybe id ((:) . ("-i" <>)) autogen ("-isrc" : "--fast" : if null args then ["src"] else args))
12+
doctest (maybe id ((:) . ("-i" <>)) autogen ("-isemantic-code/src" : "--fast" : if null args then ["semantic-core/src"] else args))

semantic-core/test/Generators.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Data.Name
2424
-- interesting property as they parse regardless.
2525
name :: MonadGen m => m Name
2626
name = Gen.prune (User <$> names) where
27-
names = Gen.string (Range.linear 1 10) Gen.lower
27+
names = Gen.text (Range.linear 1 10) Gen.lower
2828

2929
boolean :: MonadGen m => m Core
3030
boolean = Bool <$> Gen.bool

semantic-core/test/Spec.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ true, false :: Core
2525
true = Bool True
2626
false = Bool False
2727

28-
instance IsString Name where fromString = User
28+
instance IsString Name where fromString = User . fromString
2929

3030
parseEither :: Trifecta.Parser a -> String -> Either String a
3131
parseEither p = Trifecta.foldResult (Left . show . Trifecta._errDoc) Right . Trifecta.parseString (p <* Trifecta.eof) mempty

0 commit comments

Comments
 (0)