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`
|
||||
- Assignments: `x = t t`
|
||||
- Immutabile definitions
|
||||
- Lambda abstraction syntax: `id = (\a : a)`
|
||||
- List, Number, and String literals: `[(2) ("Hello")]`
|
||||
- Function application: `not (not false)`
|
||||
- Higher order/first-class functions: `map (\a : lconcat a "!") [("Hello")]`
|
||||
- Intensionality blurs the distinction between functions and data (see REPL examples)
|
||||
- Immutability
|
||||
- Simple module system for code organization
|
||||
|
||||
## REPL examples
|
||||
|
||||
|
@ -76,12 +76,16 @@ parseProgramM = do
|
||||
skipMany topLevelNewline
|
||||
moduleNode <- optional parseModuleM
|
||||
skipMany topLevelNewline
|
||||
importNodes <- many parseImportM
|
||||
importNodes <- many (do
|
||||
node <- parseImportM
|
||||
skipMany topLevelNewline
|
||||
return node)
|
||||
skipMany topLevelNewline
|
||||
exprs <- sepEndBy parseOneExpression (some topLevelNewline)
|
||||
skipMany topLevelNewline
|
||||
return (maybe [] (: []) moduleNode ++ importNodes ++ exprs)
|
||||
|
||||
|
||||
parseModuleM :: ParserM TricuAST
|
||||
parseModuleM = do
|
||||
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.Monad.IO.Class (liftIO)
|
||||
import Data.List (isInfixOf)
|
||||
import Test.Tasty
|
||||
import Test.Tasty.HUnit
|
||||
import Test.Tasty.QuickCheck
|
||||
@ -31,6 +32,7 @@ tests = testGroup "Tricu Tests"
|
||||
, lambdas
|
||||
, baseLibrary
|
||||
, fileEval
|
||||
, modules
|
||||
, demos
|
||||
]
|
||||
|
||||
@ -498,6 +500,42 @@ fileEval = testGroup "File evaluation tests"
|
||||
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 = testGroup "Test provided demo functionality"
|
||||
[ 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