Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More โ†’
Socket
Sign inDemoInstall
Socket

gravlax

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gravlax - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

lib/environment.js

31

lib/ast-printer.js

@@ -1,16 +0,33 @@

import { visitExpr } from "./ast.js";
import {
visitExpr,
visitStmt
} from "./ast.js";
const astPrinter = {
assign: (stmt) => parenthesize("assign", stmt.name.lexeme, stmt.value),
binary: (expr) => parenthesize(expr.operator.lexeme, expr.left, expr.right),
block: (block) => parenthesizeText(
"block",
...block.statements.map((stmt) => visitStmt(stmt, astPrinter))
),
expr: (stmt) => visitExpr(stmt.expression, astPrinter),
grouping: (expr) => parenthesize("group", expr.expr),
literal: (expr) => expr.value === null ? "nil" : String(expr.value),
unary: (expr) => parenthesize(expr.operator.lexeme, expr.right)
print: (stmt) => parenthesize("print", stmt.expression),
unary: (expr) => parenthesize(expr.operator.lexeme, expr.right),
"var-expr": (expr) => String(expr.name.literal),
"var-stmt": (stmt) => parenthesizeText(
"var",
String(stmt.name.literal),
...stmt.initializer ? [visitExpr(stmt.initializer, astPrinter)] : []
)
};
function parenthesizeText(...parts) {
return "(" + parts.join(" ") + ")";
}
function parenthesize(name, ...exprs) {
const parts = ["(", name];
const parts = [name];
for (const expr of exprs) {
parts.push(" ");
parts.push(visitExpr(expr, astPrinter));
parts.push(typeof expr == "string" ? expr : visitExpr(expr, astPrinter));
}
parts.push(")");
return parts.join("");
return parenthesizeText(...parts);
}

@@ -17,0 +34,0 @@ export {

function visitExpr(expr, visitor) {
return visitor[expr.kind](expr);
}
function visitStmt(stmt, visitor) {
return visitor[stmt.kind](stmt);
}
export {
visitExpr
visitExpr,
visitStmt
};
//# sourceMappingURL=ast.js.map
import {
visitExpr
visitExpr,
visitStmt
} from "./ast.js";
import { Environment } from "./environment.js";
import { runtimeError } from "./main.js";
class Interpreter {
#environment = new Environment();
"var-expr"(expr) {
return this.#environment.get(expr.name);
}
"var-stmt"(stmt) {
let value = null;
if (stmt.initializer) {
value = this.evaluate(stmt.initializer);
}
this.#environment.define(stmt.name.lexeme, value);
return null;
}
assign(expr) {
const value = this.evaluate(expr.value);
this.#environment.assign(expr.name, value);
return value;
}
binary(expr) {

@@ -56,12 +75,33 @@ const left = this.evaluate(expr.left);

}
block(block) {
this.executeBlock(block.statements, new Environment(this.#environment));
}
evaluate(expr) {
return visitExpr(expr, this);
}
execute(stmt) {
visitStmt(stmt, this);
}
executeBlock(stmts, environment) {
const prev = this.#environment;
try {
this.#environment = environment;
for (const stmt of stmts) {
this.execute(stmt);
}
} finally {
this.#environment = prev;
}
}
expr(stmt) {
this.evaluate(stmt.expression);
}
grouping(expr) {
return this.evaluate(expr.expr);
}
interpret(expr) {
interpret(statements) {
try {
const value = this.evaluate(expr);
console.log(stringify(value));
for (const statement of statements) {
this.execute(statement);
}
} catch (e) {

@@ -76,2 +116,6 @@ if (e instanceof RuntimeError) {

}
print(stmt) {
const value = this.evaluate(stmt.expression);
console.log(stringify(value));
}
unary(expr) {

@@ -78,0 +122,0 @@ const right = this.evaluate(expr.right);

@@ -6,5 +6,2 @@ import * as fs from "node:fs/promises";

import { Scanner } from "./scanner.js";
function add(a, b) {
return a + b;
}
async function runFile(interpreter, path) {

@@ -20,2 +17,6 @@ const contents = await fs.readFile(path, "utf-8");

}
function resetErrors() {
hadError = false;
hadRuntimeError = false;
}
async function runPrompt(interpreter) {

@@ -25,3 +26,3 @@ process.stdout.write("> ");

run(interpreter, line);
hadError = false;
resetErrors();
process.stdout.write("> ");

@@ -49,2 +50,3 @@ }

console.error(`[line ${line}] Error${where}: ${message}`);
hadError = true;
}

@@ -54,7 +56,7 @@ function run(interpreter, contents) {

const tokens = scanner.scanTokens();
const expr = parse(tokens);
if (hadError || !expr) {
const statements = parse(tokens);
if (hadError || !statements) {
return;
}
interpreter.interpret(expr);
interpreter.interpret(statements);
}

@@ -64,3 +66,3 @@ async function main() {

if (args.length > 1) {
console.error("Usage:", args[1], "[script]");
console.error("Usage:", process.argv[1], "[script]");
process.exit(64);

@@ -76,6 +78,6 @@ }

export {
add,
error,
errorOnToken,
main,
resetErrors,
runFile,

@@ -82,0 +84,0 @@ runPrompt,

@@ -57,3 +57,68 @@ import { errorOnToken } from "./main.js";

};
const expression = () => equality();
const declaration = () => {
try {
if (match("var")) {
return varDeclaration();
}
return statement();
} catch (e) {
if (e instanceof ParseError) {
synchronize();
} else {
throw e;
}
}
};
const varDeclaration = () => {
const name = consume("identifier", "Expect variable name.");
let initializer = null;
if (match("=")) {
initializer = expression();
}
consume(";", "Expect ';' after variable declaration.");
return { initializer, kind: "var-stmt", name };
};
const statement = () => {
if (match("print")) {
return printStatement();
} else if (match("{")) {
return { kind: "block", statements: block() };
}
return expressionStatement();
};
const expressionStatement = () => {
const expr = expression();
consume(";", "Expect ';' after expression.");
return { expression: expr, kind: "expr" };
};
const printStatement = () => {
const expr = expression();
consume(";", "Expect ';' after expression.");
return { expression: expr, kind: "print" };
};
const block = () => {
const statements = [];
while (!check("}") && !isAtEnd()) {
const d = declaration();
if (d) {
statements.push(d);
}
}
consume("}", "Expect '}' after block.");
return statements;
};
const expression = () => assignment();
const assignment = () => {
const expr = equality();
if (match("=")) {
const equals = previous();
const value = assignment();
if (expr.kind == "var-expr") {
const name = expr.name;
return { kind: "assign", name, value };
}
error(equals, "Invalid assignment target.");
}
return expr;
};
const unary = () => {

@@ -80,2 +145,4 @@ if (match("!", "-")) {

return { expr, kind: "grouping" };
} else if (match("identifier")) {
return { kind: "var-expr", name: previous() };
}

@@ -100,3 +167,10 @@ throw error(peek(), "Expect expression.");

try {
return expression();
const statements = [];
while (!isAtEnd()) {
const decl = declaration();
if (decl) {
statements.push(decl);
}
}
return statements;
} catch (e) {

@@ -103,0 +177,0 @@ if (e instanceof ParseError) {

{
"name": "gravlax",
"version": "0.4.0",
"version": "0.5.0",
"description": "A Lox interpreter with tasty TypeScript seasoning",

@@ -31,2 +31,3 @@ "repository": {

"lint:spelling": "cspell \"**\" \".github/**/*\"",
"pre-push": "pnpm run '/^lint(?!:packages).*$/'",
"prepare": "husky install",

@@ -33,0 +34,0 @@ "repl": "pnpm run:ts src/index.ts",

@@ -18,12 +18,17 @@ <h1 align="center">Gravlax</h1>

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
```shell
npm i gravlax
npx gravlax [file.lox]
```
```ts
import { greet } from "gravlax";
## Development
greet("Hello, world! ๐Ÿ’–");
```shell
pnpm install
pnpm test
pnpm repl
```

@@ -55,1 +60,4 @@

> ๐Ÿ’™ This package was templated with [`create-typescript-app`](https://github.com/JoshuaKGoldberg/create-typescript-app).
[Crafting Interpreters]: https://craftinginterpreters.com/contents.html
[Recurse Center]: https://www.recurse.com/

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc