Skip to content

Commit

Permalink
Add Evaluator of BrainFuck and WhiteSpace
Browse files Browse the repository at this point in the history
Add WrapperIO, FilterIf0, MockIO and tests for WrapperIf0
  • Loading branch information
kamil-adam committed Jun 15, 2020
1 parent 4a51848 commit 27ce749
Show file tree
Hide file tree
Showing 40 changed files with 1,511 additions and 402 deletions.
4 changes: 4 additions & 0 deletions alias.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
#!/bin/bash
alias etlas='../etlas'

etlas clean && etlas build && etlas test

git check-whitespace
5 changes: 5 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Revision history for HelCam

## 0.4.0.0 -- 2020-06-15

* Add Evaluator of BrainFuck and WhiteSpace
* Add WrapperIO, FilterIf0, MockIO and tests for FilterIf0

## 0.3.0.0 -- 2020-05-30

* Add WhiteSpace Parser
Expand Down
6 changes: 6 additions & 0 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ git clone https://github.com/helvm/helcam.git
cd helcam
```

## HLint

```bash
curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s .
```

## Cabal

Compile and run with `cabal`:
Expand Down
4 changes: 2 additions & 2 deletions docs/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**New features.**

* Add Parser for WhiteSpace
* Add Lexer for BrainFuck
* Add Lexer and Evaluator for BrainFuck
* Add Parser and Evaluator for WhiteSpace

For more see [CHANGELOG](CHANGELOG.md).
4 changes: 2 additions & 2 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
For short version see [TODO](TODO.md).

* [BrainFuck](https://esolangs.org/wiki/Brainfuck)
* [SubLeq](http://mazonka.com/subleq/)
* [ETA](http://www.miketaylor.org.uk/tech/eta/doc/manual.html)
* [Piet](https://www.dangermouse.net/esoteric/piet.html)
* [Funge](https://web.archive.org/web/20010417044912/http://cantor.res.cmu.edu/bozeman/befunge/beffaq.html)
* [Piet](https://www.dangermouse.net/esoteric/piet.html)
* [SubLeq](http://mazonka.com/subleq/)
* [WhiteSpace](http://web.archive.org/web/20150623025348/http://compsoc.dur.ac.uk/whitespace/)
7 changes: 4 additions & 3 deletions docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

Features to do:
* [x] BrainFuck Lexer
* [ ] BrainFuck Evaluator
* [X] BrainFuck Evaluator
* [ ] BrainFuck Interpreter
* [x] WhiteSpace Parser
* [ ] WhiteSpace Evaluator
* [x] WhiteSpace Lexer
* [x] WhiteSpace Parser
* [x] WhiteSpace Evaluator
* [ ] WhiteSpace Interpreter

You can propose feature by [GitHub](https://github.com/helvm/helcam/issues).
Expand Down
69 changes: 56 additions & 13 deletions helcam.cabal
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
-- Initial helcam.cabal generated by etlas init. For further
-- Initial helcam.cabal generated by etlas init. For further
-- documentation, see http://eta-lang.org/docs/

name: helcam
version: 0.3.0.0
version: 0.5.0.0

synopsis: Heavenly Esoteric Little Concrete Absolute Machine
description: Please see the README on GitHub at <https://github.com/helvm/helcam#readme>
Expand All @@ -26,15 +26,29 @@ source-repository head

library
other-modules:
HelVM.HelCam.Common.Util
HelVM.HelCam.BrainFuck.Token
HelVM.HelCam.BrainFuck.Token
HelVM.HelCam.BrainFuck.Symbol
HelVM.HelCam.BrainFuck.TableOfInstructions
HelVM.HelCam.WhiteSpace.EvaluatorUtil
HelVM.HelCam.WhiteSpace.Lexer
exposed-modules:
HelVM.HelCam.BrainFuck.Tokens
HelVM.HelCam.WhiteSpace.Token
HelVM.HelCam.WhiteSpace.Instruction
HelVM.HelCam.WhiteSpace.Parser
HelVM.HelCam.Common.Util
HelVM.HelCam.Common.WrapperIO
HelVM.HelCam.Common.FilterIf0
HelVM.HelCam.BrainFuck.Evaluator.InteractEvaluator
HelVM.HelCam.BrainFuck.Evaluator.MonadicEvaluator
HelVM.HelCam.BrainFuck.Lexer
HelVM.HelCam.BrainFuck.TapeOfSymbols
HelVM.HelCam.WhiteSpace.Evaluator.InteractEvaluator
HelVM.HelCam.WhiteSpace.Evaluator.MonadicEvaluator
HelVM.HelCam.WhiteSpace.Instruction
HelVM.HelCam.WhiteSpace.OperandParsers
HelVM.HelCam.WhiteSpace.Parser
HelVM.HelCam.WhiteSpace.Token
other-extensions:
build-depends: base >=4.8
build-depends:
base >=4.8
, mtl == 2.2.2
hs-source-dirs: src/main/eta
default-language: Haskell2010
ghc-options: -Wall
Expand All @@ -43,11 +57,21 @@ test-suite helcam-test
type: exitcode-stdio-1.0
main-is: Test.hs
other-modules:
HelVM.HelCam.BrainFuck.TokensTest
HelVM.HelCam.WhiteSpace.ParserTest
HelVM.HelCam.Common.MockIO
HelVM.HelCam.Common.FilterIf0Test
HelVM.HelCam.BrainFuck.TokensTest
HelVM.HelCam.BrainFuck.Evaluator.InteractEvaluatorTest
HelVM.HelCam.BrainFuck.Evaluator.MonadicEvaluatorTest
HelVM.HelCam.BrainFuck.EvaluatorTestData
HelVM.HelCam.WhiteSpace.ParserTest
HelVM.HelCam.WhiteSpace.Evaluator.InteractEvaluatorTest
HelVM.HelCam.WhiteSpace.Evaluator.MonadicEvaluatorTest
HelVM.HelCam.WhiteSpace.EvaluatorTestData
HelVM.HelCam.WhiteSpace.OperandParsersTest
other-extensions:
build-depends:
base >=4.8
, mtl == 2.2.2
, helcam
, HUnit
hs-source-dirs: src/test/eta
Expand All @@ -57,9 +81,28 @@ test-suite helcam-test
executable helcam
main-is: Main.hs
other-modules:
HelVM.HelCam.Common.Util
HelVM.HelCam.Common.FilterIf0
HelVM.HelCam.Common.WrapperIO
HelVM.HelCam.BrainFuck.Evaluator.InteractEvaluator
HelVM.HelCam.BrainFuck.Evaluator.MonadicEvaluator
HelVM.HelCam.BrainFuck.Lexer
HelVM.HelCam.BrainFuck.Symbol
HelVM.HelCam.BrainFuck.TableOfInstructions
HelVM.HelCam.BrainFuck.TapeOfSymbols
HelVM.HelCam.BrainFuck.Token
HelVM.HelCam.WhiteSpace.Evaluator.InteractEvaluator
HelVM.HelCam.WhiteSpace.Evaluator.MonadicEvaluator
HelVM.HelCam.WhiteSpace.EvaluatorUtil
HelVM.HelCam.WhiteSpace.Instruction
HelVM.HelCam.WhiteSpace.Lexer
HelVM.HelCam.WhiteSpace.OperandParsers
HelVM.HelCam.WhiteSpace.Parser
HelVM.HelCam.WhiteSpace.Token
other-extensions:
build-depends: base >=4.8
build-depends:
base >=4.8
, mtl == 2.2.2
hs-source-dirs: src/main/eta
default-language: Haskell2010
ghc-options: -threaded -rtsopts -with-rtsopts=-N

57 changes: 57 additions & 0 deletions src/main/eta/HelVM/HelCam/BrainFuck/Evaluator/InteractEvaluator.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module HelVM.HelCam.BrainFuck.Evaluator.InteractEvaluator (batchEvalBFInt8, batchEvalBFWord8) where

import HelVM.HelCam.BrainFuck.Symbol
import HelVM.HelCam.BrainFuck.TableOfInstructions
import HelVM.HelCam.BrainFuck.TapeOfSymbols
import HelVM.HelCam.BrainFuck.Token
import HelVM.HelCam.BrainFuck.Lexer

import HelVM.HelCam.Common.Util

import Data.Int
import Data.Word

batchEvalBFInt8 :: Source -> Output
batchEvalBFInt8 = flip evalBFInt8 ([]::String)

batchEvalBFWord8 :: Source -> Output
batchEvalBFWord8 = flip evalBFWord8 ([]::String)

evalBFInt8 :: Source -> Interact
evalBFInt8 = flip evalBF (newTape :: Tape Int8)

evalBFWord8 :: Source -> Interact
evalBFWord8 = flip evalBF (newTape :: Tape Word8)

evalBF :: Symbol s => Source -> Tape s -> Interact
evalBF source = doInstruction ([], tokenizeBF source)

doInstruction :: Symbol s => Table -> Tape s -> Interact
doInstruction table@(_, MoveR :_) tape = doInstruction (nextInst table) (moveHeadRight tape)
doInstruction table@(_, MoveL :_) tape = doInstruction (nextInst table) (moveHeadLeft tape)
doInstruction table@(_, Inc :_) tape = doInstruction (nextInst table) (wSuccSymbol tape)
doInstruction table@(_, Dec :_) tape = doInstruction (nextInst table) (wPredSymbol tape)
doInstruction table@(_, JmpPast :_) tape = doJmpPast table tape
doInstruction table@(_, JmpBack :_) tape = doJmpBack table tape
doInstruction table@(_, Output :_) tape = doOutput table tape
doInstruction table@(_, Input :_) tape = doInput table tape
doInstruction (_, [] ) _ = doEnd

doJmpPast :: Symbol s => Table -> Tape s -> Interact
doJmpPast table tape@(_, 0:_) = doInstruction (jumpPast table) tape
doJmpPast table tape = doInstruction (nextInst table) tape

doJmpBack :: Symbol s => Table -> Tape s -> Interact
doJmpBack table tape@(_, 0:_) = doInstruction (nextInst table) tape
doJmpBack table tape = doInstruction (jumpBack table) tape

doInput :: Symbol s => Table -> Tape s -> Interact
doInput _ _ [] = error "Empty input"
doInput table tape (char:input) = doInstruction (nextInst table) (writeSymbol char tape) input

doOutput :: Symbol s => Table -> Tape s -> Interact
doOutput _ (_, []) _ = error "Illegal State"
doOutput table tape@(_, symbol:_) input = toChar symbol : doInstruction (nextInst table) tape input

doEnd :: Interact
doEnd _ = []
57 changes: 57 additions & 0 deletions src/main/eta/HelVM/HelCam/BrainFuck/Evaluator/MonadicEvaluator.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module HelVM.HelCam.BrainFuck.Evaluator.MonadicEvaluator (evalBFInt8, evalBFWord8, evalBF) where

import HelVM.HelCam.BrainFuck.Symbol
import HelVM.HelCam.BrainFuck.TableOfInstructions
import HelVM.HelCam.BrainFuck.TapeOfSymbols
import HelVM.HelCam.BrainFuck.Token
import HelVM.HelCam.BrainFuck.Lexer

import HelVM.HelCam.Common.WrapperIO
import HelVM.HelCam.Common.Util

import Data.Int
import Data.Word

evalBFInt8 :: WrapperIO m => Source -> m ()
evalBFInt8 = flip evalBF (newTape :: Tape Int8)

evalBFWord8 :: WrapperIO m => Source -> m ()
evalBFWord8 = flip evalBF (newTape :: Tape Word8)

evalBF :: (Symbol s, WrapperIO m) => Source -> Tape s -> m ()
evalBF source = doInstruction ([], tokenizeBF source)

--

doInstruction :: (Symbol s, WrapperIO m) => Table -> Tape s -> m()
doInstruction table@(_, MoveR :_) tape = doInstruction (nextInst table) (moveHeadRight tape)
doInstruction table@(_, MoveL :_) tape = doInstruction (nextInst table) (moveHeadLeft tape)
doInstruction table@(_, Inc :_) tape = doInstruction (nextInst table) (wSuccSymbol tape)
doInstruction table@(_, Dec :_) tape = doInstruction (nextInst table) (wPredSymbol tape)
doInstruction table@(_, JmpPast :_) tape = doJmpPast table tape
doInstruction table@(_, JmpBack :_) tape = doJmpBack table tape
doInstruction table@(_, Output :_) tape = doOutput table tape
doInstruction table@(_, Input :_) tape = doInput table tape
doInstruction (_, [] ) _ = doEnd

doJmpPast :: (Symbol s, WrapperIO m) => Table -> Tape s -> m()
doJmpPast table tape@(_, 0:_) = doInstruction (jumpPast table) tape
doJmpPast table tape = doInstruction (nextInst table) tape

doJmpBack :: (Symbol s, WrapperIO m) => Table -> Tape s -> m()
doJmpBack table tape@(_, 0:_) = doInstruction (nextInst table) tape
doJmpBack table tape = doInstruction (jumpBack table) tape

doInput :: (Symbol s, WrapperIO m) => Table -> Tape s -> m()
doInput table tape = do
char <- wGetChar
doInstruction (nextInst table) (writeSymbol char tape)

doOutput :: (Symbol s, WrapperIO m) => Table -> Tape s -> m()
doOutput _ (_, []) = error "Illegal State"
doOutput table tape@(_, symbol:_) = do
wPutChar $ toChar symbol
doInstruction (nextInst table) tape

doEnd :: WrapperIO m => m()
doEnd = return ()
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
module HelVM.HelCam.BrainFuck.Tokens where
module HelVM.HelCam.BrainFuck.Lexer where

import HelVM.HelCam.BrainFuck.Token
import HelVM.HelCam.Common.Util

import Data.Maybe
import Text.Read

newtype Tokens = Tokens TokenList
-- Lexer
tokenizeBF :: String -> TokenList
tokenizeBF = tokenList . readTokens

readTokens :: String -> Tokens
readTokens source = read source :: Tokens

--
tokenList :: Tokens -> TokenList
tokenList (Tokens tokens) = tokens

----

newtype Tokens = Tokens TokenList

instance Show Tokens where
show (Tokens tokens) = tokens >>= show

instance Read Tokens where
readsPrec _ source = [( Tokens $ source >>= maybeToList . readMaybe . charToString, "")]

--

tokenList :: Tokens -> TokenList
tokenList (Tokens tokens) = tokens

readTokens :: String -> Tokens
readTokens source = read source :: Tokens

-- Lexer
tokenize :: String -> TokenList
tokenize = tokenList . readTokens
62 changes: 62 additions & 0 deletions src/main/eta/HelVM/HelCam/BrainFuck/Symbol.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module HelVM.HelCam.BrainFuck.Symbol where

import Data.Char
import Data.Int
import Data.Word

class (Num a, Eq a) => Symbol a where
blank :: a
fromChar :: Char -> a
toChar :: a -> Char
succSymbol :: a -> a
predSymbol :: a -> a

--

instance Symbol Int where
blank = 0
fromChar = fromIntegral . ord
toChar = chr . fromIntegral
succSymbol = succMod
predSymbol = predMod

instance Symbol Word where
blank = 0
fromChar = fromIntegral . ord
toChar = chr . fromIntegral
succSymbol = succMod
predSymbol = predMod

instance Symbol Int8 where
blank = 0
fromChar = fromIntegral . ord
toChar = chr . normalizeMod . fromIntegral
succSymbol = (+1)
predSymbol = subtract 1

instance Symbol Word8 where
blank = 0
fromChar = fromIntegral . ord
toChar = chr . fromIntegral
succSymbol = (+1)
predSymbol = subtract 1

--

countSymbols :: (Integral a) => a
countSymbols = 256

modifyMod :: (Integral a) => (a -> a) -> a -> a
modifyMod f i = f (i + countSymbols) `mod` countSymbols

normalizeMod :: (Integral a) => a -> a
normalizeMod = modifyMod id

succMod :: (Integral a) => a -> a
succMod = modifyMod succ

predMod :: (Integral a) => a -> a
predMod = modifyMod pred

modifyChar :: (Int -> Int) -> Char -> Char
modifyChar modify = chr . modify . ord
Loading

0 comments on commit 27ce749

Please sign in to comment.