Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generalize parsers signatures to take v type parameter #70

Merged
merged 1 commit into from Jul 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 28 additions & 33 deletions shared/src/Unison/TermParser.hs
Expand Up @@ -9,10 +9,9 @@ import Data.Functor (($>), void)
import Data.List (foldl')
import Data.Set (Set)
import Unison.Parser
import Unison.Symbol (Symbol, Symbol(..))
import Unison.Term (Term, Literal)
import Unison.Type (Type)
import Unison.View (DFO)
import Unison.Var (Var)
import qualified Data.Set as Set
import qualified Data.Text as Text
import qualified Unison.Term as Term
Expand All @@ -29,35 +28,31 @@ operator characters (like empty? or fold-left).
Sections / partial application of infix operators is not implemented.
-}



type V = Symbol DFO

term :: Parser (Term V)
term :: (Var v, Show v) => Parser (Term v)
term = possiblyAnnotated term2

term2 :: Parser (Term V)
term2 :: (Var v, Show v) => Parser (Term v)
term2 = let_ term3 <|> term3

term3 :: Parser (Term V)
term3 ::(Var v, Show v) => Parser (Term v)
term3 = infixApp term4 <|> term4

infixApp :: Parser (Term V) -> Parser (Term V)
infixApp :: Var v => Parser (Term v) -> Parser (Term v)
infixApp p = f <$> arg <*> some ((,) <$> infixVar <*> arg)
where
arg = p
f :: Term V -> [(V, Term V)] -> Term V
f :: Ord v => Term v -> [(v, Term v)] -> Term v
f = foldl' g
g :: Term V -> (V, Term V) -> Term V
g :: Ord v => Term v -> (v, Term v) -> Term v
g lhs (op, rhs) = Term.apps (Term.var op) [lhs,rhs]

term4 :: Parser (Term V)
term4 :: (Var v, Show v) => Parser (Term v)
term4 = prefixApp term5

term5 :: Parser (Term V)
term5 :: (Var v, Show v) => Parser (Term v)
term5 = lam term <|> termLeaf

termLeaf :: Parser (Term V)
termLeaf :: (Var v, Show v) => Parser (Term v)
termLeaf = asum [hashLit, prefixTerm, lit, parenthesized term, blank, vector term]

text' :: Parser Literal
Expand Down Expand Up @@ -96,25 +91,25 @@ lit = Term.lit <$> lit'
blank :: Ord v => Parser (Term v)
blank = token (char '_') $> Term.blank

vector :: Parser (Term V) -> Parser (Term V)
vector :: Ord v => Parser (Term v) -> Parser (Term v)
vector p = Term.vector <$> (lbracket *> elements <* rbracket)
where
lbracket = token (char '[')
elements = sepBy comma p
comma = token (char ',')
rbracket = lineErrorUnless "syntax error" $ token (char ']')

possiblyAnnotated :: Parser (Term V) -> Parser (Term V)
possiblyAnnotated :: Var v => Parser (Term v) -> Parser (Term v)
possiblyAnnotated p = f <$> p <*> optional ann''
where
f t (Just y) = Term.ann t y
f t Nothing = t

ann'' :: Parser (Type V)
ann'' :: Var v => Parser (Type v)
ann'' = token (char ':') *> TypeParser.type_

--let server = _; blah = _ in _
let_ :: Parser (Term V) -> Parser (Term V)
let_ :: (Var v, Show v) => Parser (Term v) -> Parser (Term v)
let_ p = f <$> (let_ *> optional rec_) <*> bindings' <* in_ <*> body
where
let_ = token (string "let")
Expand All @@ -123,40 +118,40 @@ let_ p = f <$> (let_ *> optional rec_) <*> bindings' <* in_ <*> body
in_ = lineErrorUnless "missing 'in' after bindings in let-expression'" $ token (string "in")
body = lineErrorUnless "parse error in body of let-expression" p
-- f = maybe Term.let1'
f :: Maybe () -> [(V, Term V)] -> Term V -> Term V
f :: Ord v => Maybe () -> [(v, Term v)] -> Term v -> Term v
f Nothing bindings body = Term.let1 bindings body
f (Just _) bindings body = Term.letRec bindings body


semicolon :: Parser ()
semicolon = void $ token (char ';')

infixBinding :: Parser (Term V) -> Parser (V, Term V)
infixBinding :: (Var v, Show v) => Parser (Term v) -> Parser (v, Term v)
infixBinding p = ((,,,,) <$> optional (typedecl <* semicolon) <*> prefixVar <*> infixVar <*> prefixVar <*> bindingEqBody p) >>= f
where
f :: (Maybe (V, Type V), V, V, V, Term V) -> Parser (V, Term V)
f :: (Ord v, Show v) => (Maybe (v, Type v), v, v, v, Term v) -> Parser (v, Term v)
f (Just (opName', _), _, opName, _, _) | opName /= opName' =
failWith ("The type signature for ‘" ++ show opName' ++ "’ lacks an accompanying binding")
f (Nothing, arg1, opName, arg2, body) = pure (mkBinding opName [arg1,arg2] body)
f (Just (_, type'), arg1, opName, arg2, body) = pure $ (`Term.ann` type') <$> mkBinding opName [arg1,arg2] body

mkBinding :: V -> [V] -> Term V -> (V, Term V)
mkBinding :: Ord v => v -> [v] -> Term v -> (v, Term v)
mkBinding f [] body = (f, body)
mkBinding f args body = (f, Term.lam'' args body)

typedecl :: Parser (V, Type V)
typedecl :: Var v => Parser (v, Type v)
typedecl = (,) <$> prefixVar <*> ann''

prefixBinding :: Parser (Term V) -> Parser (V, Term V)
prefixBinding :: (Var v, Show v) => Parser (Term v) -> Parser (v, Term v)
prefixBinding p = ((,,,) <$> optional (typedecl <* semicolon) <*> prefixVar <*> many prefixVar <*> bindingEqBody p) >>= f -- todo
where
f :: (Maybe (V, Type V), V, [V], Term V) -> Parser (V, Term V)
f :: (Ord v, Show v) => (Maybe (v, Type v), v, [v], Term v) -> Parser (v, Term v)
f (Just (opName, _), opName', _, _) | opName /= opName' =
failWith ("The type signature for ‘" ++ show opName' ++ "’ lacks an accompanying binding")
f (Nothing, name, args, body) = pure $ mkBinding name args body
f (Just (_, t), name, args, body) = pure $ (`Term.ann` t) <$> mkBinding name args body

bindingEqBody :: Parser (Term V) -> Parser (Term V)
bindingEqBody :: Parser (Term v) -> Parser (Term v)
bindingEqBody p = eq *> body
where
eq = token (char '=')
Expand All @@ -176,37 +171,37 @@ symbolyId = token $ identifier'
[notReservedChar, not . isSpace, \c -> isSymbol c || isPunctuation c]
[(`notElem` keywords)]

infixVar :: Parser V
infixVar :: Var v => Parser v
infixVar = (Var.named . Text.pack) <$> (backticked <|> symbolyId)
where
backticked = char '`' *> wordyId <* token (char '`')


prefixVar :: Parser V
prefixVar :: Var v => Parser v
prefixVar = (Var.named . Text.pack) <$> prefixOp
where
prefixOp :: Parser String
prefixOp = wordyId <|> (char '(' *> symbolyId <* token (char ')')) -- no whitespace w/in parens

prefixTerm :: Parser (Term V)
prefixTerm :: Var v => Parser (Term v)
prefixTerm = Term.var <$> prefixVar

keywords :: Set String
keywords = Set.fromList ["let", "rec", "in", "->", ":", "=", "where"]

lam :: Parser (Term V) -> Parser (Term V)
lam :: Var v => Parser (Term v) -> Parser (Term v)
lam p = Term.lam'' <$> vars <* arrow <*> body
where
vars = some prefixVar
arrow = token (string "->")
body = p

prefixApp :: Parser (Term V) -> Parser (Term V)
prefixApp :: Ord v => Parser (Term v) -> Parser (Term v)
prefixApp p = f <$> some p
where
f (func:args) = Term.apps func args
f [] = error "'some' shouldn't produce an empty list"

bindings :: Parser (Term V) -> Parser [(V, Term V)]
bindings :: (Var v, Show v) => Parser (Term v) -> Parser [(v, Term v)]
bindings p = --many (binding term)
sepBy1 (token (char ';' <|> char '\n')) (prefixBinding p <|> infixBinding p)
21 changes: 10 additions & 11 deletions shared/src/Unison/TypeParser.hs
Expand Up @@ -7,38 +7,37 @@ import Data.Foldable (asum)
import qualified Data.Text as Text

import Unison.Parser
import Unison.Symbol (Symbol)
import Unison.Type (Type)
import Unison.View (DFO)
import Unison.Var (Var)
import qualified Unison.Type as Type

type V = Symbol DFO
-- type V = Symbol DFO

type_ :: Parser (Type V)
type_ :: Var v => Parser (Type v)
type_ = forall type1 <|> type1

typeLeaf :: Parser (Type V)
typeLeaf :: Var v => Parser (Type v)
typeLeaf =
asum [ literal
, parenthesized type_
, fmap (Type.v' . Text.pack) (token varName)
]

type1 :: Parser (Type V)
type1 :: Var v => Parser (Type v)
type1 = arrow type2

type2 :: Parser (Type V)
type2 :: Var v => Parser (Type v)
type2 = app typeLeaf

-- "TypeA TypeB TypeC"
app :: Parser (Type V) -> Parser (Type V)
app :: Ord v => Parser (Type v) -> Parser (Type v)
app rec = fmap (foldl1' Type.app) (some rec)

arrow :: Parser (Type V) -> Parser (Type V)
arrow :: Ord v => Parser (Type v) -> Parser (Type v)
arrow rec = foldr1 Type.arrow <$> sepBy1 (token $ string "->") rec

-- "forall a b . List a -> List b -> Maybe Text"
forall :: Parser (Type V) -> Parser (Type V)
forall :: Var v => Parser (Type v) -> Parser (Type v)
forall rec = do
_ <- token $ string "forall"
vars <- some $ token varName
Expand All @@ -59,7 +58,7 @@ typeName = identifier [isUpper.head]
-- f first more = maybe first (first++) more
-- more = (:) <$> char '.' <*> qualifiedTypeName

literal :: Parser (Type V)
literal :: Var v => Parser (Type v)
literal =
token $ asum [ Type.lit Type.Number <$ string "Number"
, Type.lit Type.Text <$ string "Text"
Expand Down