-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v1.1.0 :: Add modules and GitHub Actions. Rework examples and README.
- Loading branch information
Showing
10 changed files
with
236 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
name: Haskell CI | ||
|
||
on: | ||
push: | ||
branches: [ "master" ] | ||
pull_request: | ||
branches: [ "master" ] | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: windows-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: haskell-actions/setup@v2 | ||
with: | ||
ghc-version: '9.6.6' | ||
cabal-version: '3.12' | ||
|
||
- name: Cache | ||
uses: actions/cache@v3 | ||
env: | ||
cache-name: cache-cabal | ||
with: | ||
path: ~/.cabal | ||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }} | ||
restore-keys: | | ||
${{ runner.os }}-build-${{ env.cache-name }}- | ||
${{ runner.os }}-build- | ||
${{ runner.os }}- | ||
- name: Install dependencies | ||
run: | | ||
cabal update | ||
cabal build --only-dependencies | ||
- name: Build | ||
run: cabal build | ||
- name: Install | ||
run: cabal install --installdir . | ||
- uses: actions/upload-artifact@v4 | ||
with: | ||
name: lapse-windows | ||
path: | | ||
lapse.exe | ||
build-linux: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: haskell-actions/setup@v2 | ||
with: | ||
ghc-version: '9.6.6' | ||
cabal-version: '3.12' | ||
|
||
- name: Cache | ||
uses: actions/cache@v3 | ||
env: | ||
cache-name: cache-cabal | ||
with: | ||
path: ~/.cabal | ||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }} | ||
restore-keys: | | ||
${{ runner.os }}-build-${{ env.cache-name }}- | ||
${{ runner.os }}-build- | ||
${{ runner.os }}- | ||
- name: Install dependencies | ||
run: | | ||
cabal update | ||
cabal build --only-dependencies | ||
- name: Build | ||
run: cabal build --enable-executable-static | ||
- name: Install | ||
run: cabal install --installdir . --enable-executable-static | ||
- uses: actions/upload-artifact@v4 | ||
with: | ||
name: lapse-linux | ||
path: | | ||
lapse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,13 @@ | ||
# lapse-hs (WIP) | ||
This will be a Lapse (my LISP dialect) interpreter in future. | ||
This is Lapse (my Lisp dialect) interpreter in future. | ||
|
||
Just an example: | ||
```lapse | ||
(set message "Running an example\n...") | ||
(print message) | ||
(print "Enter your name:") | ||
(set name (getline)) | ||
(let ((message (concat "Hello, " name "!"))) (print message)) | ||
(set result (let ((a 1) (b 2) (c 3)) | ||
'(a b c ,a ,b ,c (+ a b c) ,(+ a b c)) | ||
)) | ||
(print result) | ||
(defmacro if (c then else) (cond ((eval c) then) (1 else))) | ||
(if (> 1 2) (print "1 > 2") | ||
(print "1 <= 2")) | ||
(if (< 1 2) (print "1 < 2") | ||
(print "1 >= 2")) | ||
(defn fac (x) (if (< x 1) 1 (* x (fac (- x 1))))) | ||
(print (fac 6)) | ||
``` | ||
Examples: [here](https://github.com/ProggerX/lapse-hs/blob/master/example/example.lp) | ||
|
||
## How to use this/try this | ||
- Go to [this page](https://github.com/ProggerX/lapse-hs/actions) | ||
- Click on latest successful action run (or run from specific tag) | ||
- Find an "Artifacts" section and download version for your OS. (If you can't see download button, log in to your github account) | ||
- Unzip this artifact and you will get an executable of Lapse interpreter | ||
- To run some code, write this code in ".lp" file (in fact, extension does not matter) and run `<path-to-lapse-interpreter> <path-to-file>` command in command line | ||
- (You can find example files [here](https://github.com/ProggerX/lapse-hs/blob/master/example/example.lp)) | ||
- Also, Lapse provides a clean REPL by `<path-to-lapse-interpreter>` command |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,23 @@ | ||
(import "std" "io") | ||
|
||
(set message "Running an example\n...") | ||
(print message) | ||
(print "Enter your name:") | ||
|
||
(write "Enter your name: ") | ||
(flush) | ||
(set name (getline)) | ||
(let ((message (concat "Hello, " name "!"))) (print message)) | ||
(set result (let ((a 1) (b 2) (c 3)) | ||
'(a b c ,a ,b ,c (+ a b c) ,(+ a b c)) | ||
)) | ||
(print result) | ||
|
||
(defmacro if (c then else) (cond ((eval c) then) (1 else))) | ||
(if (> 1 2) (print "1 > 2") | ||
(print "1 <= 2")) | ||
(if (< 1 2) (print "1 < 2") | ||
(print "1 >= 2")) | ||
|
||
(defn fac (x) (if (< x 1) 1 (* x (fac (- x 1))))) | ||
(print (fac 6)) | ||
(set fact6 (show (fac 6))) | ||
(print (concat "Factorial of 6: " fact6)) | ||
|
||
(import "fibonacci.lp") | ||
(set fib8 (show (fib 8))) | ||
(print (concat "8-th Fibonacci number: " fib8)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
(import "std") | ||
|
||
(defmacro if (c then else) (cond ((eval c) then) (1 else))) | ||
(defn fib (a) | ||
(if (< a 2) | ||
a | ||
(+ (fib (- a 1)) (fib (- a 2))) | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
(import "std" "io") | ||
|
||
(defn repl () | ||
(eval | ||
(write "(repl@lapse)>> ") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
module Lapse.Modules where | ||
|
||
import Control.Exception (SomeException (..), catch) | ||
import Control.Monad.IO.Class (liftIO) | ||
import Control.Monad.State (evalStateT, runStateT) | ||
import Data.Map.Strict (Map, empty, fromList, (!?)) | ||
import Lapse.Eval (eval) | ||
import Lapse.Lambda (define, defmacro, lambda, macro) | ||
import Lapse.Operators | ||
import Lapse.Parser (parse) | ||
import Lapse.Scopes (addScope, addScopes) | ||
import Lapse.Types (Func, LapseM, Scope, Scopes, Value (..)) | ||
import System.IO ( | ||
IOMode (ReadMode), | ||
hClose, | ||
openFile, | ||
readFile', | ||
) | ||
|
||
std :: (Monad m) => Scope m | ||
std = | ||
fromList | ||
[ ("+", Function ladd) | ||
, ("*", Function lmul) | ||
, ("/", Function ldiv) | ||
, ("-", Function lsub) | ||
, ("<", Function llss) | ||
, (">", Function lgrt) | ||
, ("==", Function leql) | ||
, ("^", Function lpow) | ||
, ("sqrt", Function lsqr) | ||
, ("let", Macros llet) | ||
, ("set", Macros lset) | ||
, ("cond", Macros cond) | ||
, ("map", Function lmap) | ||
, ("double", Function ldouble) | ||
, ("list", Function llist) | ||
, ("gensym", Function gensym) | ||
, ("eval", Function leval) | ||
, ("nil", Nil) | ||
, ("raw", Macros lraw) | ||
, ("fst", Function lfst) | ||
, ("snd", Function lsnd) | ||
, ("fact", Function lfac) | ||
, ("concat", Function lcon) | ||
, ("show", Function lshow) | ||
, ("lambda", Macros lambda) | ||
, ("defn", Macros define) | ||
, ("macro", Macros macro) | ||
, ("defmacro", Macros defmacro) | ||
, ("read", Function lread) | ||
] | ||
|
||
io :: Scope IO | ||
io = | ||
fromList | ||
[ ("print", Function lprint) | ||
, ("write", Function lwrite) | ||
, ("getline", Function lgetl) | ||
, ("flush", Function lflush) | ||
] | ||
|
||
builtins :: Map String (Scope IO) | ||
builtins = | ||
fromList | ||
[ ("std", std) | ||
, ("io", io) | ||
] | ||
|
||
fileExists :: FilePath -> IO Bool | ||
fileExists path = | ||
do | ||
handle <- openFile path ReadMode | ||
hClose handle | ||
return True | ||
`catch` (\(SomeException _) -> return False) | ||
|
||
getScopesIO' :: LapseM IO a -> IO (Scopes IO) | ||
getScopesIO' = (snd <$>) . (`evalStateT` 0) . (`runStateT` initIOState) | ||
|
||
getScopesIO :: String -> IO (Scopes IO) | ||
getScopesIO = getScopesIO' . mapM eval . parse | ||
|
||
limport :: Func IO | ||
limport (Pair (String s) Nil) = case builtins !? s of | ||
Just x -> addScope x >> pure Nil | ||
Nothing -> do | ||
exists <- liftIO $ fileExists s | ||
if exists | ||
then do | ||
fileText <- liftIO $ readFile' s | ||
scopes <- liftIO $ getScopesIO fileText | ||
addScopes scopes | ||
pure Nil | ||
else error $ "Can't find module: " ++ s | ||
limport (Pair (String s) a) = limport (Pair (String s) Nil) >> limport a | ||
limport _ = error "import argument must be string" | ||
|
||
prelude :: Scope IO | ||
prelude = | ||
fromList | ||
[("import", Macros limport)] | ||
|
||
initState :: (Monad m) => Scopes m | ||
initState = [empty, std] | ||
|
||
initIOState :: Scopes IO | ||
initIOState = [empty, prelude] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters