Adds basic tests for modules
Basic tests for modules. Fixes for parsing multiple import statements.
This commit is contained in:
parent
ae971ec968
commit
f97bd84050
@ -10,12 +10,13 @@ tricu is the word for "tree" in Lojban: `(x1) is a tree of species/cultivar (x2)
|
|||||||
|
|
||||||
- Tree Calculus operator: `t`
|
- Tree Calculus operator: `t`
|
||||||
- Assignments: `x = t t`
|
- Assignments: `x = t t`
|
||||||
|
- Immutabile definitions
|
||||||
- Lambda abstraction syntax: `id = (\a : a)`
|
- Lambda abstraction syntax: `id = (\a : a)`
|
||||||
- List, Number, and String literals: `[(2) ("Hello")]`
|
- List, Number, and String literals: `[(2) ("Hello")]`
|
||||||
- Function application: `not (not false)`
|
- Function application: `not (not false)`
|
||||||
- Higher order/first-class functions: `map (\a : lconcat a "!") [("Hello")]`
|
- Higher order/first-class functions: `map (\a : lconcat a "!") [("Hello")]`
|
||||||
- Intensionality blurs the distinction between functions and data (see REPL examples)
|
- Intensionality blurs the distinction between functions and data (see REPL examples)
|
||||||
- Immutability
|
- Simple module system for code organization
|
||||||
|
|
||||||
## REPL examples
|
## REPL examples
|
||||||
|
|
||||||
|
@ -76,12 +76,16 @@ parseProgramM = do
|
|||||||
skipMany topLevelNewline
|
skipMany topLevelNewline
|
||||||
moduleNode <- optional parseModuleM
|
moduleNode <- optional parseModuleM
|
||||||
skipMany topLevelNewline
|
skipMany topLevelNewline
|
||||||
importNodes <- many parseImportM
|
importNodes <- many (do
|
||||||
|
node <- parseImportM
|
||||||
|
skipMany topLevelNewline
|
||||||
|
return node)
|
||||||
skipMany topLevelNewline
|
skipMany topLevelNewline
|
||||||
exprs <- sepEndBy parseOneExpression (some topLevelNewline)
|
exprs <- sepEndBy parseOneExpression (some topLevelNewline)
|
||||||
skipMany topLevelNewline
|
skipMany topLevelNewline
|
||||||
return (maybe [] (: []) moduleNode ++ importNodes ++ exprs)
|
return (maybe [] (: []) moduleNode ++ importNodes ++ exprs)
|
||||||
|
|
||||||
|
|
||||||
parseModuleM :: ParserM TricuAST
|
parseModuleM :: ParserM TricuAST
|
||||||
parseModuleM = do
|
parseModuleM = do
|
||||||
LModule moduleName <- satisfyM isModule
|
LModule moduleName <- satisfyM isModule
|
||||||
|
38
test/Spec.hs
38
test/Spec.hs
@ -9,6 +9,7 @@ import Research
|
|||||||
|
|
||||||
import Control.Exception (evaluate, try, SomeException)
|
import Control.Exception (evaluate, try, SomeException)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
import Data.List (isInfixOf)
|
||||||
import Test.Tasty
|
import Test.Tasty
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
import Test.Tasty.QuickCheck
|
import Test.Tasty.QuickCheck
|
||||||
@ -31,6 +32,7 @@ tests = testGroup "Tricu Tests"
|
|||||||
, lambdas
|
, lambdas
|
||||||
, baseLibrary
|
, baseLibrary
|
||||||
, fileEval
|
, fileEval
|
||||||
|
, modules
|
||||||
, demos
|
, demos
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -498,6 +500,42 @@ fileEval = testGroup "File evaluation tests"
|
|||||||
decodeResult (result res) @?= "\"String test!\""
|
decodeResult (result res) @?= "\"String test!\""
|
||||||
]
|
]
|
||||||
|
|
||||||
|
modules :: TestTree
|
||||||
|
modules = testGroup "Test modules"
|
||||||
|
[ testCase "Detect cyclic dependencies" $ do
|
||||||
|
result <- try (liftIO $ evaluateFileResult "./test/cycle-1.tri") :: IO (Either SomeException T)
|
||||||
|
case result of
|
||||||
|
Left e -> do
|
||||||
|
let errorMsg = show e
|
||||||
|
if "Encountered cyclic import" `isInfixOf` errorMsg
|
||||||
|
then return ()
|
||||||
|
else assertFailure $ "Unexpected error: " ++ errorMsg
|
||||||
|
Right _ -> assertFailure "Expected cyclic dependencies"
|
||||||
|
, testCase "Module imports and namespacing" $ do
|
||||||
|
res <- liftIO $ evaluateFileResult "./test/namespace-A.tri"
|
||||||
|
res @?= Leaf
|
||||||
|
, testCase "Multiple imports" $ do
|
||||||
|
res <- liftIO $ evaluateFileResult "./test/vars-A.tri"
|
||||||
|
res @?= Leaf
|
||||||
|
, testCase "Error on unresolved variable" $ do
|
||||||
|
result <- try (liftIO $ evaluateFileResult "./test/unresolved-A.tri") :: IO (Either SomeException T)
|
||||||
|
case result of
|
||||||
|
Left e -> do
|
||||||
|
let errorMsg = show e
|
||||||
|
if "undefinedVar" `isInfixOf` errorMsg
|
||||||
|
then return ()
|
||||||
|
else assertFailure $ "Unexpected error: " ++ errorMsg
|
||||||
|
Right _ -> assertFailure "Expected unresolved variable error"
|
||||||
|
, testCase "Multi-level imports" $ do
|
||||||
|
res <- liftIO $ evaluateFileResult "./test/multi-level-A.tri"
|
||||||
|
res @?= Leaf
|
||||||
|
, testCase "Lambda expression namespaces" $ do
|
||||||
|
res <- liftIO $ evaluateFileResult "./test/lambda-A.tri"
|
||||||
|
res @?= Leaf
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
-- All of our demo tests are also module tests
|
||||||
demos :: TestTree
|
demos :: TestTree
|
||||||
demos = testGroup "Test provided demo functionality"
|
demos = testGroup "Test provided demo functionality"
|
||||||
[ testCase "Structural equality demo" $ do
|
[ testCase "Structural equality demo" $ do
|
||||||
|
2
test/lambda-A.tri
Normal file
2
test/lambda-A.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module A
|
||||||
|
main = (\x : x) t
|
3
test/multi-level-A.tri
Normal file
3
test/multi-level-A.tri
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
!module A
|
||||||
|
!import "./test/multi-level-B.tri" B
|
||||||
|
main = B.main
|
3
test/multi-level-B.tri
Normal file
3
test/multi-level-B.tri
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
!module B
|
||||||
|
!import "./test/multi-level-C.tri" C
|
||||||
|
main = C.val
|
2
test/multi-level-C.tri
Normal file
2
test/multi-level-C.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module C
|
||||||
|
val = t
|
3
test/namespace-A.tri
Normal file
3
test/namespace-A.tri
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
!module A
|
||||||
|
!import "./test/namespace-B.tri" B
|
||||||
|
main = B.x
|
2
test/namespace-B.tri
Normal file
2
test/namespace-B.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module B
|
||||||
|
x = t
|
2
test/unresolved-A.tri
Normal file
2
test/unresolved-A.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module A
|
||||||
|
main = undefinedVar
|
7
test/vars-A.tri
Normal file
7
test/vars-A.tri
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
!module A
|
||||||
|
|
||||||
|
!import "./test/vars-B.tri" B
|
||||||
|
|
||||||
|
!import "./test/vars-C.tri" C
|
||||||
|
|
||||||
|
main = B.y (C.z)
|
2
test/vars-B.tri
Normal file
2
test/vars-B.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module B
|
||||||
|
y = \x : x
|
2
test/vars-C.tri
Normal file
2
test/vars-C.tri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!module C
|
||||||
|
z = t
|
Loading…
x
Reference in New Issue
Block a user