gdritter repos virgil / b64f354
AST, evaluator more-or-less complete; parser and typecheckerare not Getty Ritter 9 years ago
8 changed file(s) with 312 addition(s) and 0 deletion(s). Collapse all Expand all
1 Copyright (c) 2015, Getty Ritter
2
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15
16 * Neither the name of Getty Ritter nor the names of other
17 contributors may be used to endorse or promote products derived
18 from this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 {-# LANGUAGE OverloadedStrings #-}
2
3 module Language.Vergilius.AST where
4
5 import Data.ByteString.Lazy (ByteString)
6 import Data.HashMap.Strict (HashMap, fromList)
7 import Data.Scientific (Scientific)
8 import Data.Text (Text)
9 import Data.Vector (Vector)
10
11 type Ident = ByteString
12
13 data Decl
14 = Fragment ChValue
15 | DFun FunDec
16 | DTyp TypDec
17 deriving (Eq, Show)
18
19 type ChObject = HashMap Text ChValue
20 type ChArray = Vector ChValue
21
22 data ChValue
23 = ChObject ChObject
24 | ChArray ChArray
25 | ChString Text
26 | ChNumber Scientific
27 | ChBool Bool
28 | ChNull
29 | ChQuote Expr
30 deriving (Eq, Show)
31
32 data Typ
33 = TApp Typ Typ
34 | TNamed Ident
35 | TArrow
36 | TUnit
37 | TVar Ident
38 | TFix Ident Typ
39 | TSum [(Ident, Typ)]
40 | TProd [(Ident, Typ)]
41 | TTup [Typ]
42 deriving (Eq, Show)
43
44 data TypDec = TypDec
45 { tdName :: Ident
46 , tdVars :: [Ident]
47 , tdBody :: Typ
48 } deriving (Eq, Show)
49
50 data FunDec = FunDec
51 { fdName :: Ident
52 , fdTyp :: Maybe Typ
53 , fdCases :: [FnCase]
54 } deriving (Eq, Show)
55
56 data FnCase = FnCase
57 { fcPat :: Pattern
58 , fcBody :: Expr
59 } deriving (Eq, Show)
60
61 data Pattern
62 = PConstr Ident Pattern
63 | PVar Ident
64 | PLit Literal
65 | PTup [Pattern]
66 | PUnderscore
67 deriving (Eq, Show)
68
69 type Env = HashMap Ident Value
70
71 data Value
72 = VConstr Ident Value
73 | VRecord [(Ident, Value)]
74 | VTup [Value]
75 | VLam [FnCase] Env
76 | VLit Literal
77 deriving (Eq, Show)
78
79 data Expr
80 = ELit Literal
81 | EConstr Ident
82 | EApp Expr Expr
83 | EVar Ident
84 | ETup [Expr]
85 | EList [Expr]
86 | ERecord [(Ident, Value)]
87 | ELam [FnCase]
88 | ETyped Expr Typ
89 | EAccess Expr Ident
90 deriving (Eq, Show)
91
92 data Literal
93 = LInt Integer
94 | LDouble Double
95 | LString Text
96 | LBool Bool
97 deriving (Eq, Show)
98
99 {-
100 with fact : Int -> Int
101 0 = 1
102 n = n * fact (n - 1)
103 -}
104 fact :: Decl
105 fact = DFun $ FunDec
106 { fdName = "fact"
107 , fdTyp = Just (TApp (TApp TArrow (TNamed "Int"))
108 (TNamed "Int"))
109 , fdCases = [ FnCase { fcPat = PLit (LInt 0)
110 , fcBody = ELit (LInt 1)
111 }
112 , FnCase { fcPat = PVar "n"
113 , fcBody = EApp (EApp (EVar "mul") (EVar "n"))
114 (EApp (EVar "fact")
115 (EApp (EApp
116 (EVar "sub")
117 (EVar "n"))
118 (ELit (LInt 1))))
119 }
120 ]
121 }
122
123 {-
124 foo:
125 bar: '(fact 5)
126 baz: '(fact 10)
127 -}
128 foo :: Decl
129 foo = Fragment $ ChObject $ fromList
130 [ ("foo", ChObject $ fromList
131 [ ("bar", ChQuote (EApp (EVar "fact") (ELit (LInt 5))))
132 , ("baz", ChQuote (EApp (EVar "fact") (ELit (LInt 10))))
133 ]
134 )
135 ]
1 {-# LANGUAGE ParallelListComp #-}
2 {-# LANGUAGE OverloadedStrings #-}
3
4 module Language.Vergilius.Eval where
5
6 import Data.HashMap.Strict (HashMap)
7 import qualified Data.HashMap.Strict as HM
8
9 import Language.Cherenkov.AST
10
11 match :: Pattern -> Value -> Maybe [(Ident, Value)]
12 match (PConstr i p) (VConstr i' v)
13 | i == i' = match p v
14 match (PTup ps) (VTup vs)
15 | length ps == length vs =
16 fmap concat (sequence [ match p v | p <- ps | v <- vs ])
17 match (PVar i) x = return [(i, x)]
18 match (PLit l) (VLit v)
19 | l == v = return []
20 match PUnderscore _ = return []
21 match _ _ = Nothing
22
23 eval :: Env -> Expr -> Either String Value
24 eval _ (ELit l) = return (VLit l)
25 eval _ con@(EConstr _) = do
26 let fnCase = FnCase { fcPat = PVar "x"
27 , fcBody = EApp con (EVar "x")
28 }
29 return (VLam [fnCase] HM.empty)
30 eval env (EApp (EConstr i) e) = do
31 e' <- eval env e
32 return (VConstr i e')
33 eval env (EApp f x) = do
34 VLam cs env' <- eval env f
35 arg <- eval env x
36 app env cs arg
37 eval env (EVar v) = case HM.lookup v env of
38 Just x -> Right x
39 Nothing -> Left ("Unbound variable: " ++ show v)
40 eval env (ETup es) = do
41 vs <- mapM (eval env) es
42 return (VTup vs)
43 eval env (EList es) = do
44 vs <- mapM (eval env) es
45 return (foldr (\ x xs -> VConstr "Cons" (VTup [x, xs]))
46 (VConstr "Nil" (VTup []))
47 vs)
48 eval env (ERecord rs) = do
49 vs <- mapM (eval env . snd) rs
50 return (VRecord [ (i, v) | i <- map fst rs | v <- vs ])
51 eval env (ELam cs) = return (VLam cs env)
52 eval env (ETyped e _) = eval env e
53 eval env (EAccess e i) = do
54 VRecord r <- eval env e
55 case lookup i r of
56 Just v -> return v
57 Nothing -> Left ("Bad lookup: field " ++ show i ++
58 " in " ++ show r)
59
60 extend :: Env -> [(Ident, Value)] -> Env
61 extend = foldr (uncurry HM.insert)
62
63 app :: Env -> [FnCase] -> Value -> Either String Value
64 app _ [] _ = Left "Non-exhaustive cases"
65 app env (c:cs) arg = case match (fcPat c) arg of
66 Just bindings -> eval (extend env bindings) (fcBody c)
67 Nothing -> app env cs arg
1 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2
3 module Language.Vergilius.Parse where
4
5 import Data.Char (isAlpha, isDigit)
6
7 data ParseState = ParseState
8 { indentLevel :: Int
9 } deriving (Eq, Show)
10
11 type Parser a = ParsecT Text ParseState Identity a
12
13 pInt :: Parser Literal
14 pInt = (LInt . read) <$> takeWhile1 digit
15
16 pLiteral :: Parser Expr
17 pLiteral = ELit <$> pInt
18
19 pIChar :: Parser [Char]
20 pIChar = satisfy (getAny (mconcat (map (Any .) tests)))
21 where tests = [ (== '_')
22 , isAlpha
23 , isDigit
24 ]
25
26 pConstr :: Parser Text
27 pConstr = do
28 c <- upper
29 cs <- many pIChar
30 return (T.cons c (T.pack cs))
31
32 pIdent :: Parser Text
33 pIdent = do
34 c <- lower
35 cs <- many pIChar
36 return (T.cons c (T.pack cs))
1 module Language.Vergilius.Types where
2
3 import Language.Cherenkov.AST
4
5 type TEnv = HashMap Ident Typ
6
7 inferType :: TEnv -> Expr -> ()
8 inferType _ (ELit (LInt _)) = TNamed "Int"
9 inferType _ (ELit (LDouble _)) = TNamed "Double"
10 inferType _ (ELit (LString _)) = TNamed "String"
11 inferType _ (ELit (LBool _)) = TNamed "Bool"
12 inferType e (ETup ts) = VTup (map (inferType e ts))
13 inferType e (EList ls) = undefined
14 inferType e (EVar v) = undefined
1 module Language.Cherenkov where
2
3 import Data.Aeson
4 import Data.ByteString.Lazy (ByteString)
5
6 decode :: FromJSON a => ByteString -> Maybe a
7 eitherDecode :: FromJSON a => ByteString -> Either String a
1 import Distribution.Simple
2 main = defaultMain
1 name: vergilius
2 version: 0.1.0.0
3 -- synopsis:
4 -- description:
5 license: BSD3
6 license-file: LICENSE
7 author: Getty Ritter
8 maintainer: gdritter@galois.com
9 -- copyright:
10 category: Language
11 build-type: Simple
12 -- extra-source-files:
13 cabal-version: >=1.10
14
15 library
16 -- exposed-modules:
17 -- other-modules:
18 -- other-extensions:
19 build-depends: base >=4.7 && <4.8
20 -- hs-source-dirs:
21 default-language: Haskell2010