GitXplorerGitXplorer
h

slox

public
12 stars
1 forks
1 issues

Commits

List of commits on branch master.
Unverified
f5c3bb7e95e177d456231b71729f5b894e986006

Reorganize Scanner

hhashemi committed 7 years ago
Unverified
6a6d27d5438075641fdd0082046144e007196228

Minor access control change

hhashemi committed 7 years ago
Unverified
489d60a5d655edd70409ec155ce16921407d6555

Apply Environment refactoring to assign

hhashemi committed 7 years ago
Unverified
33b0c0ebfbaeb41e89c584fecd915633ce53fab8

Simplify & decouple Environment from interpreter

hhashemi committed 7 years ago
Unverified
2e4e15831b98d7fd975a1c957506717fc1d5a534

Minor reorganization of Parser

hhashemi committed 7 years ago
Unverified
132b24894a8408dcfb51bd561246d00d225b9b65

Update SPM package to latest format

hhashemi committed 7 years ago

README

The README file for this repository.

slox

This is an interpreter of the Lox Language written in Swift.

This project follows Bob Nystrom's excellent book, Crafting Interpreters which takes you through the process of writing an interpreter for a language called Lox.

In the book, the lox is implemented as an tree-walking interpreter in Java then as a bytecode compiler and VM in C. This project ports the Java version to Swift.

This project is now complete 🎉.

Related Projects

  • bslox is my Swift port of the bytecode/VM, C version.

  • CompilerKit is a Swift collection data structures and algorithms that can be used in constructing a compiler.

Tests

The test suite is from the reference Java implementation. To run the tests:

$ swift build
$ ./test_swift.py chap13_inheritance

Almost all tests pass. The only two exceptions are class and method equality.

Goals & Design

The main goal is to write a Lox interpreter in Swift while demonstrating Swift's strengths. The project takes advantage of Swift's enums and extensions to implementer the interpreter in a type-safe, clear and concise way.

Enums for type safety. The reference Java implementation stores and exchanges all Lox data as Java Object types. This neccessates runtime type checks and coerced type casting. In this Swift implementation, enums are used instead to create a restricted and explicit set of possible Lox data types with the actual data attached as associated values to the enum cases in the correct Swift types. There's no type casting and the Any type (Swift's equivalent to Object) is not used in this project.

Enums make the visitor pattern redundant. As Bob Nystrom says in the book:

The Visitor pattern is really about approximating the functional style within an OOP language.

Fortunately, it's totally unnecessary in Swift! As a multi-paradigm programming laugnage, Swift has support for both the OOP and functional-styles of programming. Instead of using objects, the Swift version uses enum cases with associated values to represent the different kinds of expressions that get parsed. Different operations you need to perform on the expressions can then be written as simple recursive functions with a switch statement over the differet kinds of expressions.

This is an important improvement since the visitor pattern adds so much cruft and boilerplate code to the Java version that one of the first things you have to do is write a little code generator utility to produce the supporting Java code.

Extensions for better code organization. Swift's extensions allow you to add to an existing data type outside of its inital declaration. For example, the abstract syntax tree printer is written as a function in a source file separate from the expression data type, Expr. However, it is added to the Expr data type as a simple computed property that returns a string and can be accessed like this:

expression.ast

Without extensions, you would need to make an ast function that takes the expression as an argument. Since the function is now in the global namespace, it would be a bad idea to just call it ast. This is what the Java implementation looks like:

new AstPrinter().print(expression)

Alternatives

License

MIT