Compare commits
4 Commits
0.12.0
...
ecf1115742
Author | SHA1 | Date | |
---|---|---|---|
ecf1115742 | |||
33c2119708 | |||
3b833ca75b | |||
203bc1898d |
@ -10,7 +10,7 @@ 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
|
- Immutable 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)`
|
||||||
@ -45,7 +45,7 @@ tricu > 12
|
|||||||
|
|
||||||
[Releases are available for Linux.](https://git.eversole.co/James/tricu/releases)
|
[Releases are available for Linux.](https://git.eversole.co/James/tricu/releases)
|
||||||
|
|
||||||
Or you can easily build and/or run this project using [Nix](https://nixos.org/download/).
|
Or you can easily build and run this project using [Nix](https://nixos.org/download/).
|
||||||
|
|
||||||
- Quick Start (REPL):
|
- Quick Start (REPL):
|
||||||
- `nix run git+https://git.eversole.co/James/tricu`
|
- `nix run git+https://git.eversole.co/James/tricu`
|
||||||
|
32
src/Eval.hs
32
src/Eval.hs
@ -10,26 +10,26 @@ import qualified Data.Set as Set
|
|||||||
|
|
||||||
evalSingle :: Env -> TricuAST -> Env
|
evalSingle :: Env -> TricuAST -> Env
|
||||||
evalSingle env term
|
evalSingle env term
|
||||||
| SDef name [] body <- term =
|
| SDef name [] body <- term
|
||||||
if
|
= case Map.lookup name env of
|
||||||
| Map.member name env ->
|
Just existingValue
|
||||||
errorWithoutStackTrace $
|
| existingValue == evalAST env body -> env
|
||||||
"Error: Identifier '" ++ name ++ "' is already defined."
|
| otherwise -> errorWithoutStackTrace $
|
||||||
| otherwise ->
|
"Unable to rebind immutable identifier: " ++ name
|
||||||
let res = evalAST env body
|
Nothing ->
|
||||||
in Map.insert "!result" res (Map.insert name res env)
|
let res = evalAST env body
|
||||||
| SApp func arg <- term =
|
in Map.insert "!result" res (Map.insert name res env)
|
||||||
let res = apply (evalAST env func) (evalAST env arg)
|
| SApp func arg <- term
|
||||||
|
= let res = apply (evalAST env func) (evalAST env arg)
|
||||||
in Map.insert "!result" res env
|
in Map.insert "!result" res env
|
||||||
| SVar name <- term =
|
| SVar name <- term
|
||||||
case Map.lookup name env of
|
= case Map.lookup name env of
|
||||||
Just v ->
|
Just v -> Map.insert "!result" v env
|
||||||
Map.insert "!result" v env
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
errorWithoutStackTrace $ "Variable `" ++ name ++ "` not defined\n\
|
errorWithoutStackTrace $ "Variable `" ++ name ++ "` not defined\n\
|
||||||
\This error should never occur here. Please report this as an issue."
|
\This error should never occur here. Please report this as an issue."
|
||||||
| otherwise =
|
| otherwise
|
||||||
Map.insert "!result" (evalAST env term) env
|
= Map.insert "!result" (evalAST env term) env
|
||||||
|
|
||||||
evalTricu :: Env -> [TricuAST] -> Env
|
evalTricu :: Env -> [TricuAST] -> Env
|
||||||
evalTricu env x = go env (reorderDefs env x)
|
evalTricu env x = go env (reorderDefs env x)
|
||||||
|
@ -59,9 +59,8 @@ main = do
|
|||||||
case args of
|
case args of
|
||||||
Repl -> do
|
Repl -> do
|
||||||
putStrLn "Welcome to the tricu REPL"
|
putStrLn "Welcome to the tricu REPL"
|
||||||
putStrLn "You can exit with `CTRL+D` or the `:_exit` command.`"
|
putStrLn "You can exit with `CTRL+D` or the `!exit` command.`"
|
||||||
library <- liftIO $ evaluateFile "./lib/base.tri"
|
repl Map.empty
|
||||||
repl $ Map.delete "!result" library
|
|
||||||
Evaluate { file = filePaths, form = form } -> do
|
Evaluate { file = filePaths, form = form } -> do
|
||||||
result <- case filePaths of
|
result <- case filePaths of
|
||||||
[] -> do
|
[] -> do
|
||||||
@ -77,8 +76,7 @@ main = do
|
|||||||
value <- case filePaths of
|
value <- case filePaths of
|
||||||
[] -> getContents
|
[] -> getContents
|
||||||
(filePath:_) -> readFile filePath
|
(filePath:_) -> readFile filePath
|
||||||
library <- liftIO $ evaluateFile "./lib/base.tri"
|
putStrLn $ decodeResult $ result $ evalTricu Map.empty $ parseTricu value
|
||||||
putStrLn $ decodeResult $ result $ evalTricu library $ parseTricu value
|
|
||||||
|
|
||||||
runTricu :: String -> T
|
runTricu :: String -> T
|
||||||
runTricu input =
|
runTricu input =
|
||||||
|
47
src/REPL.hs
47
src/REPL.hs
@ -8,6 +8,7 @@ import Research
|
|||||||
|
|
||||||
import Control.Exception (SomeException, catch)
|
import Control.Exception (SomeException, catch)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
import Control.Monad.Catch (handle, MonadCatch)
|
||||||
import Data.Char (isSpace)
|
import Data.Char (isSpace)
|
||||||
import Data.List (dropWhile, dropWhileEnd, intercalate)
|
import Data.List (dropWhile, dropWhileEnd, intercalate)
|
||||||
import System.Console.Haskeline
|
import System.Console.Haskeline
|
||||||
@ -15,33 +16,37 @@ import System.Console.Haskeline
|
|||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
repl :: Env -> IO ()
|
repl :: Env -> IO ()
|
||||||
repl env = runInputT defaultSettings (loop env)
|
repl env = runInputT defaultSettings (withInterrupt (loop env))
|
||||||
where
|
where
|
||||||
loop :: Env -> InputT IO ()
|
loop :: Env -> InputT IO ()
|
||||||
loop env = do
|
loop env = handle (interruptHandler env) $ do
|
||||||
minput <- getInputLine "tricu < "
|
minput <- getInputLine "tricu < "
|
||||||
if
|
case minput of
|
||||||
| Nothing <- minput -> outputStrLn "Exiting tricu"
|
Nothing -> outputStrLn "Exiting tricu"
|
||||||
| Just s <- minput, strip s == "!exit" -> outputStrLn "Exiting tricu"
|
Just s
|
||||||
| Just s <- minput, strip s == "" -> do
|
| strip s == "!exit" -> outputStrLn "Exiting tricu"
|
||||||
outputStrLn ""
|
| strip s == "" -> loop env
|
||||||
loop env
|
| strip s == "!import" -> do
|
||||||
| Just s <- minput, strip s == "!import" -> do
|
path <- getInputLine "File path to load < "
|
||||||
path <- getInputLine "File path to load < "
|
case path of
|
||||||
if
|
Nothing -> do
|
||||||
| Nothing <- path -> do
|
outputStrLn "No input received; stopping import."
|
||||||
outputStrLn "No input received; stopping import."
|
loop env
|
||||||
loop env
|
Just p -> do
|
||||||
| Just p <- path -> do
|
loadedEnv <- liftIO $ evaluateFileWithContext env
|
||||||
loadedEnv <- liftIO $ evaluateFileWithContext env (strip p) `catch` \e -> errorHandler env e
|
(strip p) `catch` \e -> errorHandler env e
|
||||||
loop $ Map.delete "!result" (Map.union loadedEnv env)
|
loop $ Map.delete "!result" (Map.union loadedEnv env)
|
||||||
| Just s <- minput -> do
|
| take 2 s == "--" -> loop env
|
||||||
if
|
| otherwise -> do
|
||||||
| take 2 s == "--" -> loop env
|
|
||||||
| otherwise -> do
|
|
||||||
newEnv <- liftIO $ processInput env s `catch` errorHandler env
|
newEnv <- liftIO $ processInput env s `catch` errorHandler env
|
||||||
loop newEnv
|
loop newEnv
|
||||||
|
|
||||||
|
interruptHandler :: Env -> Interrupt -> InputT IO ()
|
||||||
|
interruptHandler env _ = do
|
||||||
|
outputStrLn "Interrupted with CTRL+C\n\
|
||||||
|
\You can use the !exit command or CTRL+D to exit"
|
||||||
|
loop env
|
||||||
|
|
||||||
processInput :: Env -> String -> IO Env
|
processInput :: Env -> String -> IO Env
|
||||||
processInput env input = do
|
processInput env input = do
|
||||||
let asts = parseTricu input
|
let asts = parseTricu input
|
||||||
|
@ -26,6 +26,7 @@ executable tricu
|
|||||||
base >=4.7
|
base >=4.7
|
||||||
, cmdargs
|
, cmdargs
|
||||||
, containers
|
, containers
|
||||||
|
, exceptions
|
||||||
, haskeline
|
, haskeline
|
||||||
, megaparsec
|
, megaparsec
|
||||||
, mtl
|
, mtl
|
||||||
@ -52,6 +53,7 @@ test-suite tricu-tests
|
|||||||
base
|
base
|
||||||
, cmdargs
|
, cmdargs
|
||||||
, containers
|
, containers
|
||||||
|
, exceptions
|
||||||
, haskeline
|
, haskeline
|
||||||
, megaparsec
|
, megaparsec
|
||||||
, mtl
|
, mtl
|
||||||
|
Reference in New Issue
Block a user