Skip to content

Commit 3b811aa

Browse files
committed
Add required properties and refinement types to traits
1 parent 52c8520 commit 3b811aa

File tree

12 files changed

+478
-45
lines changed

12 files changed

+478
-45
lines changed

app/Main.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import AST qualified
77
import BytecodeCompiler (CompilerError (..), compileFail, renderCompilerErrors)
88
import BytecodeCompiler qualified
99
import Control.Exception
10-
import Control.Monad (filterM)
10+
import Control.Monad (filterM, when)
1111
import Control.Monad.IO.Class (MonadIO, liftIO)
1212
import Control.Monad.Identity (Identity (..))
1313
import Control.Monad.State (StateT (runStateT), evalStateT)

lib/AST.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ data Expr
5757
| Cast {castExpr :: Expr, castType :: Expr, castPos :: Position}
5858
| TypeLit {typeLitType :: Type, typeLitPos :: Position}
5959
| Flexible {flexibleExpr :: Expr, flexiblePos :: Position}
60-
| Trait {name :: String, methods :: [Expr], generics :: [GenericExpr], traitPos :: Position}
60+
| Trait {name :: String, methods :: [Expr], generics :: [GenericExpr], requiredProperties :: [(String, Type)], refinement :: Maybe Expr, refinementSrc :: String, traitPos :: Position}
6161
| Impl {trait :: String, traitTypeArgs :: [Type], for :: Type, methods :: [Expr], implPos :: Position}
6262
| StrictEval {strictEvalExpr :: Expr, strictEvalPos :: Position}
6363
| External {externalName :: String, externalArgs :: [Expr], externalPos :: Position}
@@ -119,7 +119,7 @@ children (Lambda _ a _) = [a]
119119
children (Cast a b _) = [a, b]
120120
children (TypeLit _ _) = []
121121
children (Flexible a _) = [a]
122-
children (Trait _ a _ _) = a
122+
children (Trait _ a _ _ r _ _) = a ++ maybeToList r
123123
children (Impl _ _ _ a _) = a
124124
children (FuncDec{}) = []
125125
children (StrictEval a _) = [a]

lib/BytecodeCompiler.hs

Lines changed: 63 additions & 26 deletions
Large diffs are not rendered by default.

lib/Parser.hs

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ parseFreeUnsafe t = case parseProgram t initCompilerFlags{needsMain = False} of
770770
replacePositionWithAnyPosition (Cast a b _) = Cast (replacePositionWithAnyPosition a) (replacePositionWithAnyPosition b) anyPosition
771771
replacePositionWithAnyPosition (TypeLit type' _) = TypeLit type' anyPosition
772772
replacePositionWithAnyPosition (Flexible a _) = Flexible (replacePositionWithAnyPosition a) anyPosition
773-
replacePositionWithAnyPosition (Trait name methods g _) = Trait name (map replacePositionWithAnyPosition methods) g anyPosition
773+
replacePositionWithAnyPosition (Trait name methods g reqProps ref refSrc _) = Trait name (map replacePositionWithAnyPosition methods) g reqProps (fmap replacePositionWithAnyPosition ref) refSrc anyPosition
774774
replacePositionWithAnyPosition (Impl traitName traitTypeArgs f m _) = Impl traitName traitTypeArgs f (map replacePositionWithAnyPosition m) anyPosition
775775
replacePositionWithAnyPosition (StrictEval a _) = StrictEval (replacePositionWithAnyPosition a) anyPosition
776776
replacePositionWithAnyPosition (External n a _) = External n (map replacePositionWithAnyPosition a) anyPosition
@@ -867,18 +867,57 @@ trait = do
867867
keyword "trait"
868868
name <- identifier <?> "trait name"
869869
generics <- fromMaybe [] <$> optional generic <?> "trait generics"
870-
methods <-
871-
( do
870+
hasEquals <- lookAhead (optional (try (symbol "=")))
871+
(requiredProperties, refinementSrc, refinement, methods) <- case hasEquals of
872+
Just _ -> do
872873
symbol "="
873-
keyword "do"
874-
newline'
875-
fds <- funcDec `sepEndBy` newline' <?> "trait methods"
876-
keyword "end"
877-
return fds
878-
)
879-
<|> return []
874+
reqProps <- optional (try (parens (traitField `sepBy` symbol ",")) <?> "required properties")
875+
refSrc <- lookAhead $ optional $ do
876+
keyword "satisfies"
877+
parens (many (noneOf [')'])) <?> "refinement source"
878+
ref <- optional $ do
879+
keyword "satisfies"
880+
parens expr <?> "refinement"
881+
methods' <-
882+
( do
883+
keyword "do"
884+
newline'
885+
fds <- funcDec `sepEndBy` newline' <?> "trait methods"
886+
keyword "end"
887+
return fds
888+
)
889+
<|> return []
890+
return (reqProps, refSrc, ref, methods')
891+
Nothing -> do
892+
reqProps <- optional (try (parens (traitField `sepBy` symbol ",")) <?> "required properties")
893+
refSrc <- lookAhead $ optional $ do
894+
keyword "satisfies"
895+
parens (many (noneOf [')'])) <?> "refinement source"
896+
ref <- optional $ do
897+
keyword "satisfies"
898+
parens expr <?> "refinement"
899+
hasEqualsAfter <- lookAhead (optional (try (symbol "=")))
900+
methods' <- case hasEqualsAfter of
901+
Just _ -> do
902+
symbol "="
903+
( do
904+
keyword "do"
905+
newline'
906+
fds <- funcDec `sepEndBy` newline' <?> "trait methods"
907+
keyword "end"
908+
return fds
909+
)
910+
<|> return []
911+
Nothing -> return []
912+
return (reqProps, refSrc, ref, methods')
880913
end <- getOffset
881-
return $ Trait name methods generics (Position (start, end))
914+
return $ Trait name methods generics (fromMaybe [] requiredProperties) refinement (fromMaybe "" refinementSrc) (Position (start, end))
915+
where
916+
traitField = do
917+
fieldName <- identifier <?> "field name"
918+
symbol ":"
919+
fieldType <- validType <?> "field type"
920+
return (fieldName, fieldType)
882921

883922
impl :: Parser Expr
884923
impl = do
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
import qualified Module2
22

33
let x = Module2.
4+
5+
6+
7+
8+
9+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
import Module2
22

33
let x =
4+
5+
6+
7+
8+
9+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
import NonExistentModule
22

33
let x = 42
4+
5+
6+
7+
8+
9+

lsp/tests/data/hover_qualified.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
import qualified Module2
22

33
let x = Module2.add
4+
5+
6+
7+
8+
9+

lsp/tests/data/module2.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ let add (a: Int b: Int) : Int = a + b
55
let multiply (a: Int b: Int) : Int = a * b
66

77
let greet (name: String) : String = "Hello, " ++ name ++ "!"
8+
9+
10+
11+
12+
13+

0 commit comments

Comments
 (0)