husk-scheme 1.0 → 1.1
raw patch · 6 files changed
+46/−54 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.markdown +0/−29
- hs-src/Scheme/Core.hs +34/−22
- hs-src/Scheme/Macro.hs +1/−1
- hs-src/shell.hs +1/−1
- husk-scheme.cabal +1/−1
- stdlib.scm +9/−0
README.markdown view
@@ -22,35 +22,6 @@ - Hash tables, as specified by [SRFI 69](http://srfi.schemers.org/srfi-69/srfi-69.html) - Hygenic Macros: High-level macros via define-syntax - *Note this is still a heavy work in progress* and while it works well enough that many derived forms are implemented in our standard library, you may still run into problems when defining your own macros. -Roadmap----------Features planned for development:--- A scheme "library" that may be used to embed scheme scripting within a Haskell program. This will necessitate extracting the repl code from Core.hs and relocating it to its own file.-- See: http://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html--- Documentation, including a description of Scheme / Haskell, API docs (?), etc-- Release as a cabal package - see: http://www.haskell.org/haskellwiki/How_to_write_a_Haskell_program-- Continuations-- Implementation of approved SRFI's--TODO Items:--- Better error reporting. For example:- * huski crashes when macro transformation not enclosed in ()- * What's up with this error message:- huski> (define vec)- Getting an unbound variable: define-- huski crashes if the first line of a scheme file is blank-- Correct parsing of comments, including allowing them in the middle of a form (eg: (cond))-- Test cases, including those for: backtick, primitives (see spec section 4.1), others-- More example programs, perhaps derive some from SICP and http://www.scheme.dk/planet/-- General refactoring of haskell code including addressing of TODO items, etc...-- Compare our features to R5RS spec: <http://practical-scheme.net/wiliki/schemexref.cgi?R5RS> and <http://en.wikipedia.org/wiki/Scheme_(programming_language)>-- At some point, need to enter bugs for this sort of thing...- husk scheme is available under the [MIT license](http://www.opensource.org/licenses/mit-license.php). Usage
hs-src/Scheme/Core.hs view
@@ -88,27 +88,51 @@ eval env val@(HashTable _) = return val eval env (Atom id) = getVar env id eval env (List [Atom "quote", val]) = return val-eval env (List [Atom "quasiquote", val]) = do- case val of- List [Atom "unquote", val] -> eval env val -- Handle cases like `,(+ 1 2) - List [Atom "unquote-splicing", val] -> eval env val -- TODO: not quite right behavior - List (x : xs) -> mapM (doUnQuote env) (x:xs) >>= return . List -- TODO: understand *why* this works - otherwise -> doUnQuote env val +eval env (List [Atom "quasiquote", val]) = doUnQuote env val where doUnQuote :: Env -> LispVal -> IOThrowsError LispVal doUnQuote env val = do case val of List [Atom "unquote", val] -> eval env val- List [Atom "unquote-splicing", val] -> eval env val -- TODO: not quite right behavior- otherwise -> eval env (List [Atom "quote", val]) -- TODO: could this be simplified?+ List (x : xs) -> unquoteListM env (x:xs) >>= return . List+ DottedList xs x -> do+ rxs <- unquoteListM env xs >>= return + rx <- doUnQuote env x+ case rx of+ List [] -> return $ List rxs+ List rxlst -> return $ List $ rxs ++ rxlst + DottedList rxlst rxlast -> return $ DottedList (rxs ++ rxlst) rxlast+ otherwise -> return $ DottedList rxs rx+ Vector vec -> do+ let len = length (elems vec)+ vList <- unquoteListM env $ elems vec >>= return+ return $ Vector $ listArray (0, len) vList+ otherwise -> eval env (List [Atom "quote", val]) -- Behave like quote if there is nothing to "unquote"... + unquoteListM env lst = foldlM (unquoteListFld env) ([]) lst+ unquoteListFld env (acc) val = do+ case val of+ List [Atom "unquote-splicing", val] -> do+ value <- eval env val+ case value of+ List v -> return $ (acc ++ v)+ -- Question: In which cases should I generate a type error if value is not a list?+ --+ -- csi reports an error for this: `(1 ,@(+ 1 2) 4)+ -- but allows cases such as: `,@2+ -- For now we just throw an error - perhaps more strict than we need to be, but at+ -- least we will not allow anything invalid to be returned.+ --+ -- Old code that we might build on if this changes down the road: otherwise -> return $ (acc ++ [v])+ otherwise -> throwError $ TypeMismatch "proper list" value + otherwise -> do result <- doUnQuote env val+ return $ (acc ++ [result])+ eval env (List [Atom "if", pred, conseq, alt]) = do result <- eval env pred case result of Bool False -> eval env alt otherwise -> eval env conseq- {- ex #1: only allow boolean conditions: otherwise -> throwError $ TypeMismatch "bool" otherwise-} --- TODO: implement this 'if' form, such that it returns nothing if the pred evaluates to false eval env (List [Atom "if", pred, conseq]) = do result <- eval env pred case result of@@ -166,16 +190,6 @@ eval env (List (Atom "lambda" : varargs@(Atom _) : body)) = makeVarargs varargs env [] body -{- TODO: for proper tail calls (above):- -- - consider comments from http://www.sidhe.org/~dan/blog/archives/000211.html- - in particular:- - - how a compiler can deal with tail recursion- - - And if you have a continuation passing style of calling functions, it turns out to be essentially free, which is really cool, though the topic of another WTHI entry- - perhaps: http://www.sidhe.org/~dan/blog/archives/000213.html- - - - -}- eval env (List [Atom "string-fill!", Atom var, character]) = do str <- eval env =<< getVar env var chr <- eval env character@@ -237,8 +251,6 @@ otherwise -> throwError $ TypeMismatch "hash-table" otherwise -- TODO:--- hash-table-update!--- hash-table-update!/default -- hash-table-merge! eval env (List (function : args)) = do
hs-src/Scheme/Macro.hs view
@@ -90,7 +90,7 @@ -- Determine if the next element in a list matches 0-to-n times due to an ellipsis macroElementMatchesMany :: LispVal -> Bool macroElementMatchesMany (List (p:ps)) = do- if length ps > 0+ if not (null ps) then case (head ps) of Atom "..." -> True otherwise -> False
hs-src/shell.hs view
@@ -47,7 +47,7 @@ showBanner = do putStrLn " __ __ __ __ ______ __ __ " putStrLn "/\\ \\_\\ \\ /\\ \\/\\ \\ /\\ ___\\ /\\ \\/ / Scheme Interpreter " - putStrLn "\\ \\ __ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ _\\\"-. Version 1.0"+ putStrLn "\\ \\ __ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ _\\\"-. Version 1.1" putStrLn " \\ \\_\\ \\_\\ \\ \\_____\\ \\/\\_____\\ \\ \\_\\ \\_\\ (c) 2010 Justin Ethier " putStrLn " \\/_/\\/_/ \\/_____/ \\/_____/ \\/_/\\/_/ github.com/justinethier/husk-scheme " putStrLn ""
husk-scheme.cabal view
@@ -1,5 +1,5 @@ Name: husk-scheme-Version: 1.0+Version: 1.1 Synopsis: R5RS Scheme interpreter program and library. Description: Husk is a dialect of Scheme written in Haskell that implements a subset of the R5RS standard. Husk is not intended to be a
stdlib.scm view
@@ -222,11 +222,20 @@ (set! result-ready? #t) result)))))))) ++; Hash table derived forms (define hash-table-walk (lambda (ht proc) (map (lambda (kv) (proc (car kv) (cdr kv))) (hash-table->alist ht)))) ++(define (hash-table-update! hash-table key function)+ (hash-table-set! hash-table key+ (function (hash-table-ref hash-table key thunk))))++;(define (hash-table-update!/default hash-table key function default)+; (hash-table-update! hash-table key function (lambda () default))) ; TODO: hash-table-fold