commit 2783fd27400c3b85bf4e83e3584a87f0863e2cd9 Author: Tsuki Date: Mon Dec 18 18:29:13 2023 +0800 I'm OK diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c368d45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.stack-work/ +*~ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..85e7e7d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "cSpell.words": [ + "elems", + "foldr" + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0c21b96 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog for `meo` + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to the +[Haskell Package Versioning Policy](https://pvp.haskell.org/). + +## Unreleased + +## 0.1.0.0 - YYYY-MM-DD diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c5b6c16 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +Copyright Author name here (c) 2023 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Author name here nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..891fe0b --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# meo diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/app/Main.hs b/app/Main.hs new file mode 100644 index 0000000..e3715a4 --- /dev/null +++ b/app/Main.hs @@ -0,0 +1,7 @@ +module Main (main) where + +import Lib (mainIO) +import Premitive (ttest) + +main :: IO () +main = mainIO diff --git a/meo.cabal b/meo.cabal new file mode 100644 index 0000000..45a65a8 --- /dev/null +++ b/meo.cabal @@ -0,0 +1,91 @@ +cabal-version: 2.2 + +-- This file has been generated from package.yaml by hpack version 0.35.2. +-- +-- see: https://github.com/sol/hpack + +name: meo +version: 0.1.0.0 +description: Please see the README on GitHub at +homepage: https://github.com/githubuser/meo#readme +bug-reports: https://github.com/githubuser/meo/issues +author: Author name here +maintainer: example@example.com +copyright: 2023 Author name here +license: BSD-3-Clause +license-file: LICENSE +build-type: Simple +extra-source-files: + README.md + CHANGELOG.md + +source-repository head + type: git + location: https://github.com/githubuser/meo + +library + exposed-modules: + Ast + Lib + Premitive + Type + other-modules: + Paths_meo + autogen-modules: + Paths_meo + hs-source-dirs: + src + ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints + build-depends: + base >=4.7 && <5 + , cmdargs + , containers + , exceptions + , monad-logger + , mtl + , parsec + , text + default-language: Haskell2010 + +executable meo-exe + main-is: Main.hs + other-modules: + Paths_meo + autogen-modules: + Paths_meo + hs-source-dirs: + app + ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N + build-depends: + base >=4.7 && <5 + , cmdargs + , containers + , exceptions + , meo + , monad-logger + , mtl + , parsec + , text + default-language: Haskell2010 + +test-suite meo-test + type: exitcode-stdio-1.0 + main-is: Spec.hs + other-modules: + Paths_meo + autogen-modules: + Paths_meo + hs-source-dirs: + test + ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N + build-depends: + base >=4.7 && <5 + , cmdargs + , containers + , exceptions + , meo + , monad-logger + , mtl + , parsec + , text + default-language: Haskell2010 diff --git a/package.yaml b/package.yaml new file mode 100644 index 0000000..0055725 --- /dev/null +++ b/package.yaml @@ -0,0 +1,66 @@ +name: meo +version: 0.1.0.0 +github: "githubuser/meo" +license: BSD-3-Clause +author: "Author name here" +maintainer: "example@example.com" +copyright: "2023 Author name here" + +extra-source-files: +- README.md +- CHANGELOG.md + +# Metadata used when publishing your package +# synopsis: Short description of your package +# category: Web + +# To avoid duplicated efforts in documentation and dealing with the +# complications of embedding Haddock markup inside cabal files, it is +# common to point users to the README.md file. +description: Please see the README on GitHub at + +dependencies: +- base >= 4.7 && < 5 +- parsec +- mtl +- containers +- text +- cmdargs +- exceptions +- monad-logger + +ghc-options: +- -Wall +- -Wcompat +- -Widentities +- -Wincomplete-record-updates +- -Wincomplete-uni-patterns +- -Wmissing-export-lists +- -Wmissing-home-modules +- -Wpartial-fields +- -Wredundant-constraints + +library: + source-dirs: src + +executables: + meo-exe: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - meo + +tests: + meo-test: + main: Spec.hs + source-dirs: test + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - meo diff --git a/src/Ast.hs b/src/Ast.hs new file mode 100644 index 0000000..bb06410 --- /dev/null +++ b/src/Ast.hs @@ -0,0 +1,73 @@ +{-# LANGUAGE TupleSections #-} +module Ast where +import Foreign (Storable) +import Premitive (Expr,Stmt) + + +type Location = Int +type Index = [String] +type Stack = [Int] + + +position :: String -> Index -> Location +position name index = let pos n (nm:nms) = + if name == nm + then n + else pos (n+1) nms + pos _ [] = -1 + in pos 1 index + +fetch :: Location -> Stack -> Int +fetch n (v:vs) = if n == 1 + then v + else fetch (n-1) vs +fetch _ [] = -1 + +put :: Location -> Int -> Stack -> Stack +put n x (v:vs) = if n == 1 + then x:vs + else v:put (n-1) x vs + +put _ _ [] = [] + + +newtype M a = StOut (Stack -> (a, Stack, String)) + +unStOut :: M a -> Stack -> (a, Stack, String) +unStOut (StOut o) = o + +instance Functor M where + fmap f e = StOut (\n -> let (a,n1,s1) = unStOut e n in + (f a, n1, s1) + ) + +instance Applicative M where + pure x = StOut (x,,"") + ef <*> e = StOut (\n -> let (f,n1,s1) = unStOut ef n + (a,n2,s2) = unStOut e n1 in + (f a, n2, s1++s2) + ) + +instance Monad M where + return = pure + e >>= f = StOut (\n -> let (a,n1,s1) = unStOut e n + (b,n2,s2) = unStOut (f a) n1 in + (b, n2, s1++s2) + ) + + +getFrom :: Location -> M Int +getFrom i = StOut (\ns -> (fetch i ns, ns, "")) + + +write :: Location -> Int -> M () +write i v = StOut (\ns -> (() , put i v ns, "")) + +push :: Int -> M () +push x = StOut (\ns -> ((), x:ns, "")) + +pop :: M () +pop = StOut (\(_:ns) -> ((), ns,"")) + +output :: Show a => a -> M () +output v = StOut ((), , show v) diff --git a/src/Lib.hs b/src/Lib.hs new file mode 100644 index 0000000..02df258 --- /dev/null +++ b/src/Lib.hs @@ -0,0 +1,30 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Lib (mainIO) where + +import Control.Exception (SomeException) +import Control.Monad.IO.Class (liftIO) +import Control.Monad.Logger +import Control.Monad.Reader +import qualified Data.Text.IO as TIO +import System.IO.Error (isDoesNotExistError) + +data Config = Config + { -- | Path to the log file + configLogLevel :: LogLevel -- 日志级别 + } + +type App = ReaderT Config (LoggingT IO) + +-- 日志记录和读取配置的函数 +appFunction :: App () +appFunction = do + Config logLevel <- ask + lift $ filterLogger (\_ level -> level >= logLevel) $ do + logInfoN "This is an informational message." + logDebugN "This is a debug message." + +mainIO :: IO () +mainIO = do + let config = Config LevelInfo + runStdoutLoggingT $ runReaderT appFunction config \ No newline at end of file diff --git a/src/Premitive.hs b/src/Premitive.hs new file mode 100644 index 0000000..030a5b1 --- /dev/null +++ b/src/Premitive.hs @@ -0,0 +1,209 @@ +{-# LANGUAGE PatternSynonyms #-} + +module Premitive (ttest, Stmt, Expr (..)) where + +import Data.Functor.Identity +import Text.Parsec +import qualified Text.Parsec.Expr as E +import Text.Parsec.Language +import Text.Parsec.String +import qualified Text.Parsec.Token as T + +types :: [String] +types = ["number", "bool", "string", "list", "nil", "func"] + +reservedNames :: [String] +reservedNames = ["if", "then", "else", "while", "do", "process", "pipeline", "in", "()", "skip", "declare", "func"] ++ types + +reservedOpNames :: [String] +reservedOpNames = ["+", "-", "*", "/", ":=", "==", "<", ">", "&&", "||", "!", ";", "|", ">>>", "<<<", ">>", "<<"] + +-- 定义语言 +languageDef = + emptyDef + { T.commentStart = "/*", + T.commentEnd = "*/", + T.commentLine = "//", + T.nestedComments = True, + T.identStart = letter :: Parser Char, + T.identLetter = alphaNum :: Parser Char, + T.opStart = oneOf "+-*/", + T.opLetter = oneOf "+-*/", + T.reservedOpNames = reservedOpNames, + T.reservedNames = reservedNames + } + +-- 创建 TokenParser +lexer = T.makeTokenParser languageDef + +data Stmt + = If Expr Stmt Stmt + | While Expr Stmt + | Assign String Expr + | Seq Stmt Stmt + | Skip + deriving (Show) + +data Ks = Ks String Expr deriving (Show) + +ksTerm :: Parser Ks +ksTerm = do + k <- T.identifier lexer <* T.colon lexer + Ks k <$> expr + +data IntOrFloat = IntValue Integer | FloatValue Double deriving (Show) + +-- 定义算术表达式的数据类型 +data Expr + = Num IntOrFloat + | Bool Bool + | Nil + | Str String + | Pipeln String [Expr] + | List [Expr] + | Process String [Ks] + | Block Stmt Expr + | Symbol String + | IfExpr Expr Expr Expr + | Declare [String] [Expr] Expr + | Bin String Expr Expr + | Con Expr Expr + | Func String Expr + deriving (Show) + +data BasicType = NumberType | BoolType | StringType | ListType | NilType | FuncType BasicType BasicType deriving (Show) + +prefix :: String -> (Expr -> Expr) -> E.Operator String () Identity Expr +prefix name fun = E.Prefix (do _ <- T.reservedOp lexer name; return fun) + +binary :: String -> (Expr -> Expr -> Expr) -> E.Operator String () Identity Expr +binary name fun = E.Infix (T.reservedOp lexer name >> return fun) E.AssocLeft + +postfix :: String -> (Expr -> Expr) -> E.Operator String () Identity Expr +postfix name fun = E.Postfix (do T.reservedOp lexer name; return fun) + +pattern Mul :: Expr -> Expr -> Expr +pattern Mul a b = Bin "*" a b + +pattern Div :: Expr -> Expr -> Expr +pattern Div a b = Bin "/" a b + +pattern Add :: Expr -> Expr -> Expr +pattern Add a b = Bin "+" a b + +pattern Sub :: Expr -> Expr -> Expr +pattern Sub a b = Bin "-" a b + +-- 运算符表及其优先级和结合性 +table :: E.OperatorTable String () Identity Expr +table = + [ [binary "*" Mul, binary "/" Div], + [binary "+" Add, binary "-" Sub], + [binary ">>>" Con] + ] + +-- 定义换行分隔的解析器 +lineSepBy :: Parser a -> Parser [a] +lineSepBy element = sepBy element newline + +parserProcess :: Parser Expr +parserProcess = do + T.reserved lexer "process" + name <- T.identifier lexer + T.braces lexer $ do + args <- T.semiSep lexer ksTerm + return $ Process name args + +-- 整数解析器 +numberParser :: Parser Expr +numberParser = + Num <$> do + nf <- T.naturalOrFloat lexer + case nf of + Left i -> return $ IntValue i + Right r -> return $ FloatValue r + +nilParser :: Parser Expr +nilParser = T.brackets lexer (return Nil) + +blockParser :: Parser Expr +blockParser = T.reserved lexer "do" >> T.braces lexer (Block <$> option Skip stmt <*> option Nil expr) + +expr :: ParsecT String () Identity Expr +expr = E.buildExpressionParser table term "expression" + +basicTermParser :: Parser Expr +basicTermParser = try blockParser <|> Str <$> T.stringLiteral lexer <|> numberParser <|> nilParser <|> Symbol <$> T.identifier lexer <|> List <$> T.brackets lexer (T.commaSep lexer basicTermParser) + +term :: Parser Expr +term = T.parens lexer expr <|> basicTermParser <|> parserProcess "simple expression" + +-- 语句解析器 +stmt :: Parser Stmt +stmt = try seqStmt <|> ifStmt <|> whileStmt <|> assignStmt <|> skipStmt "statement" + +basicStmt :: Parser Stmt +basicStmt = ifStmt <|> whileStmt "statement" + +ifExpr :: Parser Expr +ifExpr = do + T.reserved lexer "if" + cond <- expr + T.reserved lexer "then" + expr1 <- expr + T.reserved lexer "else" + IfExpr cond expr1 <$> expr + +ifStmt :: Parser Stmt +ifStmt = do + T.reserved lexer "if" + cond <- expr + T.reserved lexer "then" + stmt1 <- stmt + T.reserved lexer "else" + If cond stmt1 <$> stmt + +whileStmt :: Parser Stmt +whileStmt = do + T.reserved lexer "while" + cond <- expr + T.reserved lexer "do" + While cond <$> stmt + +assignStmt :: Parser Stmt +assignStmt = do + var <- T.identifier lexer + T.reservedOp lexer ":=" + Assign var <$> expr + +declareExpr :: Parser Expr +declareExpr = do + T.reserved lexer "declare" + v <- T.semiSep1 lexer $ do + var <- T.identifier lexer + T.reservedOp lexer ":=" + val <- expr + return (var, val) + T.reservedOp lexer "in" + let (var, val) = unzip v + in Declare var val <$> expr + +skipStmt :: Parser Stmt +skipStmt = T.reserved lexer "skip" >> return Skip + +seqStmt :: Parser Stmt +seqStmt = do + stmt1 <- basicStmt + _ <- T.semi lexer + Seq stmt1 <$> stmt + +parseExpr :: String -> Either ParseError Stmt +parseExpr = parse stmt "" + +ttest :: IO () +ttest = do + putStrLn "Enter a simple arithmetic expression:" + input <- getLine + case parseExpr input of + Left err -> print err + Right x -> print x diff --git a/src/Type.hs b/src/Type.hs new file mode 100644 index 0000000..fa3fd19 --- /dev/null +++ b/src/Type.hs @@ -0,0 +1,149 @@ +{-# LANGUAGE PatternSynonyms #-} + +module Type where + +import Control.Monad.Except +import Control.Monad.RWS as R + ( MonadReader (ask, local), + MonadState (get, put), + MonadWriter (tell), + RWST, + ) +import qualified Data.Map as Map +import qualified Data.Set as Set +import qualified Premitive as P + +type Name = String + +newtype TVar = TV Name deriving (Eq, Show, Ord) + +data Type + = TCon Name [Type] + | TVar TVar + deriving (Show, Eq, Ord) + +pattern TInt = TCon "Int" [] + +pattern TBool = TCon "Bool" [] + +pattern a :-> b = TCon "->" [a, b] + +pattern TNumber = TCon "Number" [] + +pattern TList a = TCon "List" [a] + +pattern TNil = TCon "Nil" [] + +data Scheme = Forall (Set.Set TVar) Type + +data Constraint = Constraint Type Type + +type Context = Map.Map Name Scheme + +type Count = Int + +type Constraints = [Constraint] + +type Infer a = RWST Context Constraints Count (Except String) a + +-- constrain :: Type -> Type -> Infer () +-- constrain t1 t2 = tell [Constraint t1 t2] + +fresh :: Infer Type +fresh = do + count <- get + put (count + 1) + return . TVar . TV $ show count + +type Subst = Map.Map TVar Type + +compose :: Subst -> Subst -> Subst +compose a b = Map.map (apply a) (b `Map.union` a) + +class Substitutable a where + apply :: Subst -> a -> a + tvs :: a -> Set.Set TVar + +instance Substitutable Type where + tvs (TVar tv) = Set.singleton tv + tvs (TCon _ ts) = foldr (Set.union . tvs) Set.empty ts + apply s t@(TVar tv) = Map.findWithDefault t tv s + apply s (TCon c ts) = TCon c $ map (apply s) ts + +instance Substitutable Scheme where + tvs (Forall vs t) = tvs t `Set.difference` vs + apply s (Forall vs t) = Forall vs $ apply (foldr Map.delete s vs) t + +instance Substitutable Constraint where + tvs (Constraint t1 t2) = tvs t1 `Set.union` tvs t2 + apply s (Constraint t1 t2) = Constraint (apply s t1) (apply s t2) + +instance (Substitutable a) => Substitutable [a] where + apply s = map (apply s) + tvs = foldr (Set.union . tvs) Set.empty + +generalize :: Context -> Type -> Scheme +generalize ctx t = Forall (tvs t `Set.difference` tvs (Map.elems ctx)) t + +instantiate :: Scheme -> Infer Type +instantiate (Forall vs t) = do + let vars = Set.toList vs + ftvs <- traverse (const fresh) vars + let subst = Map.fromList (zip vars ftvs) + return $ apply subst t + +constrain :: Type -> Type -> Infer () +constrain a b = tell [Constraint a b] + +infer :: P.Expr -> Infer Type +infer e = case e of + P.Num _ -> return TInt + P.Bool _ -> return TBool -- Boolean literal + P.IfExpr e1 e2 e3 -> do + -- If expression + t1 <- infer e1 + constrain t1 TBool + t2 <- infer e2 + t3 <- infer e3 + constrain t2 t3 + return t2 + P.Bin op e1 e2 -> do + -- Binary operator + t1 <- infer e1 + t2 <- infer e2 + constrain t1 TInt + constrain t2 TInt + case op of + "+" -> return TInt + "-" -> return TInt + "*" -> return TInt + "/" -> return TInt + _ -> throwError $ "unknown operator: " ++ op + P.Con e1 e2 -> do + t1 <- infer e1 + t2 <- infer e2 + constrain t1 t2 + return t2 + P.Nil -> do + return TNil + P.List es -> do + ts <- traverse infer es + return $ TList (head ts) + P.Symbol s -> do + ctx <- ask + case Map.lookup s ctx of + Nothing -> throwError $ "unbound variable: " ++ s + Just s' -> instantiate s' + P.Declare names es e -> do + ts <- traverse infer es + let ctx = Map.fromList $ zip names (map (generalize Map.empty) ts) + local (Map.union ctx) (infer e) + P.Block s e -> do + t2 <- infer e + return t2 + P.Process _ _ -> do + return TNil + P.Pipeln _ _ -> do + return TNil + P.Str _ -> do + return TNil \ No newline at end of file diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..13fd06b --- /dev/null +++ b/stack.yaml @@ -0,0 +1,67 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/yaml_configuration/ + +# Resolver to choose a 'specific' stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# resolver: lts-3.5 +# resolver: nightly-2015-09-21 +# resolver: ghc-7.10.2 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# resolver: ./custom-snapshot.yaml +# resolver: https://example.com/snapshots/2018-01-01.yaml +resolver: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/21.yaml + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the resolver. +# These entries can reference officially published versions as well as +# forks / in-progress versions pinned to a git hash. For example: +# +# extra-deps: +# - acme-missiles-0.3 +# - git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# +# extra-deps: [] + +# Override default flag values for local packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of Stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=2.9" +# +# Override the architecture used by Stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by Stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..fb5c9ae --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,13 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: [] +snapshots: +- completed: + sha256: 7d4b649cf368f9076d8aa049aa44efe58950971d105892734e9957b2a26a2186 + size: 640060 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/21.yaml + original: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/21.yaml diff --git a/test.pll b/test.pll new file mode 100644 index 0000000..ca61c01 --- /dev/null +++ b/test.pll @@ -0,0 +1,45 @@ +[] , 10 ,10.0, "", process, pipeline, true/false + +if then else + +while + +do while + +skip + + +declare a := 2 in do { + print a; + show a; + 3 + 1 +} + +declare a := 2 in if true then ... else ... + +declare a:=2 in do { + if a then .. +} + +declare a:=2; b:=2;c :=2 in do{ + +} + +declare a:=2 in declare b:=2 in declare c:=2 in do { + +} + +a:[] + +(c:(b:(a:[]))) + + +process A { + a :: Number + b :: Number +} + +pipeline { + A >>> B >>> C + A >>> (B ||| C) >>> D +} diff --git a/test/Spec.hs b/test/Spec.hs new file mode 100644 index 0000000..cd4753f --- /dev/null +++ b/test/Spec.hs @@ -0,0 +1,2 @@ +main :: IO () +main = putStrLn "Test suite not yet implemented"