Socket
Socket
Sign inDemoInstall

gravlax

Package Overview
Dependencies
1
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    gravlax

A Lox interpreter with tasty TypeScript seasoning


Version published
Weekly downloads
4
decreased by-92%
Maintainers
1
Install size
315 kB
Created
Weekly downloads
 

Changelog

Source

0.13.1 (2024-04-18)

Bug Fixes

  • Fix build (#181) (9245a4e)

Features

  • implement chapters 14-25 🇦🇺 🦘 (#168) (7a8d0b9)

Readme

Source

Gravlax

A Lox interpreter with tasty TypeScript seasoning

👪 All Contributors: 2 🤝 Code of Conduct: Kept 🧪 Coverage 📝 License: MIT 📦 npm version 💪 TypeScript: Strict

This is my implementation of an interpreter for the Lox language from Robert Nystrom's Crafting Interpreters. I'm building this as part of my Winter 2024 batch at the Recurse Center.

Usage

npx gravlax [file.lox]

Departures from the book

Features not in the book

There's one notable feature I added beyond what's in the text of Crafting Interpreters: support for commas as numeric separators and currencies as first-class values.

You can write 1,234 + 2,456 and gravlax will happily print out 3690. Note that this has the… interesting side effect of making the grammar whitespace-sensitive: f(1,2) and f(1, 2) parse differently (the former is a one-argument call).

You can also write out currency values like $123 or €456 and do math on them. The operations you'd expect to work will work: adding or subtracting values from the same currency is OK, multiply a currency by a scalar is OK, etc:

> ($1,234 + $2,345) / 10
$357.9
> $12 + €23
MixedCurrencyError: Operands must be the same currency.

Two other niceties:

  1. Support for expressions in the REPL (Chapter 8 Challenge 1). If you run npx gravlax and then 1+2, it will print 3. No need to write a print statement. This makes it possible to use gravlax as a calculator.

  2. The REPL uses readline so you can hit up arrow to get the previous expression and edit it.

Implementation details

Rather than representing AST nodes as classes, I used TypeScript interfaces and a discriminated union for Expr and Stmt. This means that we don't need a codegen step. It also means that we don't need the visitor pattern: pattern-matching with switch/case is more idiomatic and less code.

While I used a class for the Scanner (same as the book), I used a closure for the parser. Mostly this just means less writing this dot whatever.

Performance

On my machine, gravlax runs the Fibonacci code from Chapter 14 in ~3 minutes (174 seconds). Compare this with 27s for jlox. So we're ~6x slower than Java.

In jlox and gravlax, returning from a function is implemented by throwing an exception. It's critical that this class not derive from Error, so that it doesn't carry along stack traces:

- class ReturnCall extends Error {
+ class ReturnCall {

The latter winds up being ~10x faster than the former. This is the JS equivalent of the weird super(null, null, false, false) call in jlox. See #37.

Development

pnpm install
pnpm test
pnpm repl

Contributors

Dan Vanderkam
Dan Vanderkam

💻 🖋 📖 🤔 🚇 🚧 📆 🔧
Josh Goldberg ✨
Josh Goldberg ✨

🔧

💙 This package was templated with create-typescript-app.

FAQs

Last updated on 18 Apr 2024

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc