Changelog for husk-scheme-3.7
A major change for this release is the introduction of Scheme libraries using R7RS library syntax. For an example of how to use libraries, see
examples/hello-library/hello.scm in the husk source tree. Note that since R7RS is not currently implemented by husk, the library system only has the built-in import
(r5rs base) to allow you to import the standard husk R5RS environment. Also, please keep in mind this is still a beta feature that is not yet implemented by the compiler.
This release also contains many improvements to the Haskell API:
r5rsEnvto the Core module to expose the full environment, including functions loaded from the Scheme standard library.
getDataFileFullPathto the Core module to allow third party code to reference Scheme files such as
stdlib.scmthat are installed alongside husk.
NumArgsto optionally require an explicit number of arguments. This helps when writing variable-length functions where specifying a single number of arguments may be misleading.
- Added a new module
Language.Scheme.Utilto contain general purpose utility functions.
- Updated the parser to accept floating point numbers that contain only a fractional component, such as
- Enhanced numerical comparison operators (
>=) to be able to accept an unlimited number of arguments, per R5RS.
Added support for R<sup>7</sup>RS bytevectors.
Improved support for using husk as an extension language by adding Haskell function
evalLisp'. This function evaluates a lisp data structure and returns the
LispError result directly:
evalLisp' :: Env -> LispVal -> IO (ThrowsError LispVal)
This makes it much easier to retrieve results when using husk as an extension language:
result <- evalLisp' env $ List [Atom "/", Number 1, Number 0] case result of Left err -> putStrLn $ "Error: " ++ (show err) Right val -> putStrLn $ show val
Finally, fixed a bug where setting a variable to refer back to itself would result in an infinite loop. For example, the last line of the following code would cause
huski to hang:
(define a '()) (define b a) (define a b)
This release adds support for nested quasi-quotation forms, which now respect depth level. This was done by replacing the quasi-quotation special form with a macro based on the one from chibi scheme. A nice side-benefit is that by removing the special forms, quasi-quotation now works in the compiler.
Also added support for SRFI 2,
and-let*. From the SRFI document:
Like an ordinary AND, an AND-LET* special form evaluates its arguments - expressions - one after another in order, until the first one that yields #f. Unlike AND, however, a non-#f result of one expression can be bound to a fresh variable and used in the subsequent expressions. AND-LET* is a cross-breed between LET* and AND.
And added support for environment specifiers, including the following functions:
(load filename environment-specifier)
(eval expression environment-specifier)
This release also includes the following bug fixes:
- Fixed a bug where nested explicit renaming macros may not always expand properly.
- Unfortunately, the storage model changes introduced in 3.6 cause problems with hash table literals defined using the
#hash()syntax. For now, hash table literals have been removed to prevent further problems. This feature may be added back in the future.
- Fixed the code for
require-extensionto allow passing multiple SRFI numbers in the same call. For example:
(require-extension (srfi 1 2)).
- Improved compiler support by diverting renamed variables back into the enclosing environment. Such variables would previously throw a runtime error when accessed by the compiled program.
- Improved compiler support by loading macros defined using
define-syntaxso they are available at runtime.
Added support for GHC 7.6.
Enhanced the variable storage model to correctly store references to objects. For example, consider the following:
(define x (list 'a 'b 'c)) (define y x) (set-cdr! x 4)
After executing this code, previous versions of husk assigned
(a b c) to
y. With this release, husk now evaluates
y to the expected value of
(a . 4).
The more general problem is that certain data types denote a memory location which may be modified by mutator functions such as
set-cdr!. This is discussed specifically in section 3.4 <b>Storage Model</b>:
Variables and objects such as pairs, vectors, and strings implicitly denote locations or sequences of locations. A string, for example, denotes as many locations as there are characters in the string. (These locations need not correspond to a full machine word.) A new value may be stored into one of these locations using the string-set! procedure, but the string continues to denote the same locations as before.
Internally husk uses Haskell data types, so the husk model differs slightly from the one in R<sup>5</sup>RS - references are used instead of individual memory locations. This has implications for the
set-cdr! special forms, where circular lists and similar low-level optimizations are not possible as Haskell lists are used instead of raw pointers. However, these issues aside, the enhanced storage model is a big step forward to bringing husk's variable support closer in line to that of other Schemes.
The major change in this release is support for explicit renaming macros. This low-level macro system provides the ability to break macro hygiene, if necessary, and offers a macro system that is similar to
In addition, all of the character functions from R<sup>5</sup>RS have been implemented.
Enhanced the compiler to accept<pre> <code> $ time huski ffi-cputime.scm Seconds of CPU time spent: 2.756171
load-ffias a special form, so a compiled version of a program does not have to wait for a module to be dynamically loaded. Instead, the module is included at compile time. This offers a nice speed improvement:
$ time ./ffi-cputime Seconds of CPU time spent: 2.4001e-2 </code> </pre>
Allow a hash table to be defined directly using
#hash(alist)- for example,
#hash()for an empty table or
#hash((a 1) (b . 2))for a table with two elements. This is not part of R<sup>5</sup>RS but seems less clumsy than the standard way, and a similar language feature is provided by Racket.
Added support for
hash-table-delete!to the compiler.
Fixed a bug where
integer?would always return false for negative rational numbers. For example,
(integer? -2/2)should evaluate to
- Added support for SRFI-1 (List Library), which can be loaded using
(require-extension (srfi 1)). Note that linear update functions (such as
take!, etc) and circular lists are not supported at this time.
- Added a new LispVal type called
Opaquefor Haskell integration, courtesy of Josh Triplett. The Opaque type allows a native Haskell function to package an arbitrary Haskell type for use by other native code called by husk. See
examples/ffi/Opaque.hsfor an example of how to use this feature.
- Enhanced the parser to read numbers in scientific notation such as
denominatorto add support for integers and floating point numbers.
- Fixed a bug in
set-cdr!where an unsimplified list may be output. For example,
(3 . (2 . (1 . ())))instead of
(3 2 1).
applyto receive multiple arguments, as long as the last one is a list.
huskcto print errors to console when a runtime exception occurs, and to not print any results to console unless the user calls an I/O function such as
- Added a special form
expandthat can be used to see the result of a macro expansion, for debugging purposes. For example:
(expand (let ((x 1)) x)).
- Allow a list to be enclosed by matched brackets as well as parentheses. For example:
(+ 1 2 [+ 3 4]).
- Internal change - cleaned up code by using Language pragmas instead of explicitly using extensions in the cabal and make files.
- Modified huski to escape baskslashes in the path to the standard library, to guarantee stdlib is loaded when husk is installed on a Windows machine.
- Removed an unnecessary dependency on
huskito interpret files when run on Windows.
- Prevent divide-by-zero errors when dividing by a single number, or processing a rational number with zero as the denominator.
This release adds full support for GHC 7.2.2 / 7.4.1 as well as a number of small enhancements.
- Fixed the FFI to work in both GHC 7.2.2 and GHC 7.4.1.
- Implemented SRFI 23, which adds error reporting via the
- Added support for
lambda(pair syntax) to the huskc compiler.
- Added the
--dynamicoption to the compiler to use dynamic Haskell libraries.
- Added the
--extraoption to the compiler to allow passing of arbitrary arguments directly to ghc.
- Fixed huski to allow any redefinition of
This is a series of quick bug-fix releases that allows husk to build under GHC 7.4.1.
- Added an experimental compiler, huskc. For more information see Issue #62.
- Streamlined the cabal file so that each source file is only compiled a single time.
- Improved support for comparing instances of functions using
- Reduced variable access time by using a Map to store variables within an environment.
- Various internal changes such as renaming the tests directory and integrating R<sup>5</sup>RS pitfalls with the unit tests.
This release continues the trend of quick point releases for the 3.4.x series. The key change is support for GHC 7.2:
- husk now compiles in GHC 7.2. This ended up being a simple change - I had mis-interpreted the value of a pre-processor directive. Sorry about that!
- Replaced the definition of
letrecwith the macro from R<sup>5</sup>RS.
- Allow a continuation to call into another continuation via call/cc - see R<sup>5</sup>RS pitfall 1.2
letrec-syntaxto prevent conflicts between identifiers of the same name in the outer scope and within the macro body.
- Per R5RS,
(if <test> <consequent>)is supposed to evaluate
<consequent>for any value of
#f. However, husk was only allowing
<test>to pass if it was equal to
#t. This has been fixed.
(append)to accept an arbitrary number of arguments, per R<sup>5</sup>RS.
- Replaced the macro for
casewith the one from R<sup>5</sup>RS.
- Many improvements and bug fixes for let-syntax and letrec-syntax.
- Improved handling of define and set! within a macro definition.
Added experimental support for let-syntax and letrec-syntax.
- Fixed a nasty issue where the macro pattern matching code would not properly reset itself when transcribing a macro containing an ellipsis in the middle of a list. For example:
(a ... b c). This caused the expanded macro to be incomplete and/or malformed.
- Fixed a bug that would cause the evaluator to terminate if define-syntax was called within a nested scope.
This release adds the first hygienic macro support to husk. There are two "sides" to macro hygiene:
- Hygiene: Names that are introduced by the macro do not clash with names in sub-expressions that are passed from user code to it
- Referential transparency: names that the macro references are coming from the lexical context of its definition, rather than the lexical context of its use
Support has been added for both sides, although there are some issues as noted in the Version 3.4.x Milestones. Macro support will continue to improve in future releases.
In addition, this release contains the following bug fixes:
- When searching for a redefinition of a special form, the code now recursively examines parent environments instead of only inspecting the current environment.
(let*)is now defined in terms of the definition from R<sup>5</sup>RS, to fix problems with valid inputs not being matched by
This release includes major improvements to the macro module. In particular:
- husk now supports arbitrary nesting levels of macro 0-or-many matches (IE:
...). Previous versions would not handle macros that had more than 2 nesting levels of 0-or-more matches.
- Macros now correctly handle improper lists. Previous versions of husk did not respect the fact that the trailing item in an improper list may be matched zero or more times. Also, husk macros now properly convert the transformed code into improper or proper lists depending upon the pattern, input, and transform.
- (do) is now defined in terms of the macro from R<sup>5</sup>RS.
- Updated the parser to simplify improper lists; for example the following input:
'(1 2 . (3 . ()))will now be converted to
(1 2 3)
- Corrected the order of arguments to (fold). For example, the expression (fold (lambda (x y) x) 8 (list 1 2 3)) should yield 3, however in previous releases husk would incorrectly yield 8 because of the order of arguments.
- Added a conditional compilation check to allow husk to build on GHC 6 and GHC 7.
- Significant improvements to the parser, including proper handling of whitespace and comments. This represents a critical upgrade from the previous releases.
- Added support for nested block comments using
|#, per the R<sup>7</sup>RS draft.
- Fixed issues with lexical scope, where proper scope was not observed for special forms, including: if, cond, set!, begin, define, lambda, set-car!, set-cdr!, string-set!, vector-set!, and hash-table-set! - For example:
(let ((if +)) (if 1 2 3)) was 2 instead of 6. Now it eval's to 6
orare now defined using the corresponding macros from R<sup>5</sup>RS, to give them the expected semantics.
- Added a
- Internal change - relocated primitive functions to a new Language.Scheme.Primitives module.
- Marked macro support as non-hygienic since hygiene is not fully supported at present.
- Added a foreign function interface (FFI) to allow husk to call directly into Haskell code.
- Simplified the core evaluator by moving several functions out of eval. Practically, this means that the following functions are now first-class objects: apply, call-with-current-continuation, call-with-values, eval, and load. They can be called directly, assigned to variables, etc just like any other first-class value.
- (call-with-values) now accepts multiple return values from the producer function.
- If (values) is called with multiple arguments and is not part of an enclosing (call-with-values), the first value is returned to the interpreter instead of generating an error.
- Added additional error handling for set! - and related functions - when these functions are called with the wrong number or type of arguments.
- Added limited support for (dynamic-wind).
- The parser now recognizes rational number components of a complex number. For example: 1/2+3/4i
- Automatically load the scheme standard library when running .scm files.
- Suppress excess output when running a program by piping it to /dev/null.
- Added missing I/O functions, including display, input-port?, output-port?, newline, write-char, read-char, peek-char, current-input-port, current-output-port, call-with-input-file, and call-with-output-port.
- Added eval.
- Added a limited version of (call-with-values) that currently only accepts one argument.
- Added vector support to macros.
- Added an example program to demonstrate file I/O: examples/simple-file-io.scm.
- Moved all Haskell code from the 'Scheme' namespace to the 'Language/Scheme' namespace.
- Fixed cases where backquoting of a vector would crash the interpreter.
- Prevent interpreter from crashing when calling (load) if the file does not exist.
- Improved support of different numeric types across the numerical functions.
- Added support for binary numbers to (number->string)
- Implemented (alist->hash-table)
- Full implementation of continuations via call/cc. This involved passing a new continuation type through all versions of the eval function.
- Fixed a bug where a macro pattern would be incorrectly matched even though a literal identifier in the pattern was not present in the input.
- Added over 100 new Scheme test cases from the R5RS language specification.
- Added set-cdr!
- Changed the banner text on startup to match the new husk logo.
- Added limited support for continuations, by adding the call/cc keyword and first-class continuations. This is still a work in progress, and only a subset of continuations are supported - continuations can only be used as escape procedures from a function (along the lines of a 'return' call).
- Fixed an ugly bug where the underlying functions used to mutate variabiables in (define), (set!), etc implemented dynamic scoping instead of the lexical (static) scoping required by R5RS. This reference implementation written by Kyle Miller was used as a starting point.
- Many improvements to quasi-quotation, including support for unquote splicing (,@).
- Initial release