nlfiedler / bakeneko Goto Github PK
View Code? Open in Web Editor NEWScheme R7RS interpreter in Go
License: BSD 3-Clause "New" or "Revised" License
Scheme R7RS interpreter in Go
License: BSD 3-Clause "New" or "Revised" License
See section 4.2 of R7RS for a complete list of the standard derived expressions expected in Scheme. This includes, but is not limited to, cond, case, and, or, when, unless, let and friends, begin, do, delay, force, etc.
A means of reading the contents of a Scheme program from a file into the current file, in place, as if wrapped in a (begin). The -ci variant inserts a #!fold-case directive.
Some procedures may take an arbitrary number of arguments (e.g. (list)). This should be done in the closure.Bind() function. If the closure.parameters field is an improper list (i.e. the last parameter label is preceded by a space-delimited period (.)) then after assigning the values to the preceding labels, the rest of the values are stored in a list and assigned to the last label.
Prior to having the line number information compiled into the byte code object, the compilation was quite fast. After gathering and storing the line number data, the compilation time increased by 33%. Would be ideal to gather some profiling stats and see if there's room for improvement. However, the -test.cpuprofile flag does not seem to work properly in Mac OS X 10.9, so may need to try a Linux VM.
When reading Scheme code, symbols with the same name should be interned to be the same Scheme object, rather than two separate instances that are equal.
Supposedly this expression yields itself:
(let ((let '(let ((let
,let))
,let)))
'(let ((let `,let))
,let))
Should write a test to try it out.
See section 4.2.1 for a description of the case syntactic keyword.
The bytevector.go file is little more than a placeholder at this point. For R7RS need to implement the various byte vector methods described in section 6.9 of R7RS.
Need this for proper support of ports, especially for use with (current-input-port) and friends.
Read about floating point math [1] and ensure none of those mistakes are made in the "Float" code in the atom.go source file.
[1] http://www.codeproject.com/Articles/29637/Five-Tips-for-Floating-Point-Programming
Eventually will need a means of invoking Go functions from within the Scheme language. Not sure how feasible this is since the Go linker eliminates any unused functions in the final executable. Nonetheless, should look into it.
See http://matt.might.net/articles/cesk-machines/ for a good discussion on these keywords, in the context of a Lisp-like interpreter.
The builtin procedures atom, car, cdr, eq, and label are still missing from bakeneko.
Compared to gocheck, the github.com/bmizerany/assert package is feeble and poorly documented. Its use should be replaced with equivalent gocheck calls and subsequently removed as a dependency.
Scheme R7RS specifies a means for defining objects that have defined fields, predicates, accessors, and optional modifiers.
Find and convert the r7rs-test.scm from chibi-scheme into a test suite in bakeneko.
See section 4.3 of R7RS for a specification on hygienic macros. The Lispy.py code seems to support macros, so adding this feature to that milestone, but also needed for R7RS.
When an error occurs during lexing, parsing, or interpretation of a Scheme program, there is no location information provided (i.e. line and column). Really need that.
See http://labix.org/gocheck for more on gocheck, which adds a bunch of convenience types and functions for unit testing. Looks very useful.
Scheme R7RS specifies what a REPL for Scheme should do.
There are numerous SRFI implementations available and they would make bakeneko richer and more useful. Most of the code is licensed under an open source license and is basically just Scheme, so should work out of the box.
Invoking (scheme-report-environment 5) would simply return an environment in which the standard R5RS bindings are set up.
Scheme defines predicates for determining the type of a Scheme object, which includes: boolean? bytevector? char? eof-object? null? number? pair? port? procedure? string? symbol? vector?
The unit tests are pretty good but really need to evaluate them more carefully with a code coverage tool, such as gocov.
See vector.go and section 6.8 of R7RS for a description of the procedures needed for supporting vectors.
Scheme R7RS specifies support for defining and using libraries written in Scheme.
For testing the results of evaluation, can assign "stdout" in the global environment to a bytes.Buffer then read the contents of that to see what the s-expr yielded.
See chibi-scheme: all of the tests are written in Scheme using a basic test framework which is itself written in Scheme. Hard for bootstrapping, but once the interpreter is sufficiently complete, this would be the ideal way to express the tests. The source code editor can properly match parentheses and syntax colorize the code, which is much better than editing the test code inside a quoted string.
This is a design issue with the Scheme interpreter, in that it is using Go's interface{} meta type everywhere. Really need to create a basic "anything" type that supports a small number of common operations for Scheme objects. Make Atom implement this new type. Then seek out all the occurrences of interface{} and determine if they would be better represented as Any.
The pair_test.go file does some basic testing of Pair.Append() but does not currently test chaining the calls to Append(). The parser code does this already, but still a good idea to explicitly test the API.
See section 6.13 of R7RS for the set of procedures expected to be provided for performing input and output operations.
In order to assess the level of achievement in reaching the Lispy.py milestone, the Lispy.py test suite should be converted into a series of unit tests (presumably written in Go). This should provide a great deal of focus in achieving said milestone.
Provide the call-with-current-continuation procedure, usually aliased to call/cc. This is specified in section 6.10 of R7RS, and a simple implementation can be found in lispy.py. This procedure is useful for implementing other interesting control structures (e.g. exceptions) and hence is highly regarded.
Based on Ewen's analysis of various Go iterator patterns, using an interface with an interator struct implementation is much slower than an iterator struct implementation without the corresponding iterator interface. That is, just remove PairIterator the interface and promote pairIterator the struct to "PairIterator".
See section 4.2.1 of R7RS where => is used to evaluate an expression.
Along with call/cc, the dynamic-wind procedure and support for before/after thunks are a very useful feature for implementing interesting control structures in Scheme. See section 6.10 of R7RS for details.
The interpreter theoretically supports tail call optimization as described in section 3.5 of R7RS, but it remains unproven and untested.
Presently the lex() function is very optimistic, in that it only returns a channel of tokens. If an error is encountered (e.g. the text is not UTF-8 compliant), it can only return nil and no other indication of an error. Should have it return both the channel and an 'error'.
For objects that are frequently created, used briefly, and thrown away, should utilize a mechanism for recycling these objects. Go 1.3 may introduce a type called sync.Pool which provides a convenient means of recycling objects. See [1] for a description.
See [1] for the complete list. Some of these are actually syntactic keywords, many of which bakeneko already implements, while others are library procedures. These establish a good starting point for a basic LISP interpreter.
Seem to have forgotten to add the BSD license file at the root of the source tree. The standard license text will suffice.
See core/numbers.go for the set of predicates and procedures existing so far, and compare with what is specified in section 6.2 of R7RS.
See section 4.1 of R7RS for the set of primitive expressions that all Scheme R7RS compliant interpreters must support. This includes variable references, literal expressions (e.g. quote, '), procedure calls, procedure definitions (e.g. lambda), conditionals (if), assignments (set), and inclusion (include).
All of the really cool Scheme interpreters compile the Scheme code to some form of bytecode to improve performance. Some even compile to native code, though that may be a bit far given my resources.
This needs testing.
In the Scheme interpreter, need to replace the use of hash tables with something more appropriate to Scheme (i.e. space efficient for small numbers of properties), such as a left-leaning red-black tree. That's just one idea, there are many more in Steve Yegge's essay "The Universal Design Pattern" [1], such as linked lists that morph into hash tables when a threshold is crossed.
Additionally, this [2] came up on HackerNews recently.
[1] http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html
[2] http://www.soi.city.ac.uk/~ross/papers/FingerTree.pdf
Not convinced that the VM will correctly return from a lambda called within a lambda. Add a test to vm_test.go that invokes a lambda from within another one.
Because hash tables are obvious and programming without them is painful. See the specification and complete implementation at [1]. Chibi-Scheme also has an R7RS compliant version as well.
For sake of time, should save compiled byte code and reload rather than compiling the same source repeatedly.
See section 4.2.8 of R7RS for a description of quasi-quotation. Add support for applying quasi-quotation to vectors via the `#() syntax.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.