Skip to content

Commit 11dfb5d

Browse files
committed
[JS] Implements file primitives in JS
1 parent d032a13 commit 11dfb5d

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

rosetta-test-js/interpreter-tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ for (const entry of testTable) {
8383
evalResult = error;
8484
}
8585

86-
if (matches(evalResult, entry.expected)) {
86+
if (!entry.hasOwnProperty("expected") || matches(evalResult, entry.expected)) {
8787
console.log(`✅: ${input}`);
8888
} else {
8989
if (expected_failures.includes(input)) {

rosetta-test-js/scheme.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { parseWithoutExpand } from './parser.js';
22

3-
import { readFile, readFileSync } from 'fs';
3+
import { readFileSync, openSync, closeSync, writeSync } from 'fs';
44
import URL from 'url';
55

66
// Use JavaScript native Symbol instead of custom implementation
@@ -241,6 +241,8 @@ macro_table.set(_let, letMacro);
241241
// Global environment setup
242242
export const globalEnv = new Env();
243243

244+
const EOF_OBJECT = Symbol.for('#<eof-object>');
245+
244246
function addGlobals(env) {
245247
// Add basic operations
246248
env.set(Sym('+'), (a, b) => a + b);
@@ -273,6 +275,30 @@ function addGlobals(env) {
273275
env.set(Sym('hash-table-delete!'), (table, key) => { table.delete(key); });
274276
env.set(Sym('hash-table-keys'), table => Array.from(table.keys()));
275277
env.set(Sym('hash-table-values'), table => Array.from(table.values()));
278+
279+
// File operations
280+
function isIteratorLike(obj) {
281+
// Copied from https://github.com/ayonli/check-iterable/
282+
return typeof obj === "object"
283+
&& obj !== null
284+
&& typeof obj.next === "function";
285+
}
286+
env.set(Sym('open-output-file'), filename => openSync(filename, 'w'));
287+
env.set(Sym('open-input-file'), filename => readFileSync(filename, "utf-8")[Symbol.iterator]());
288+
env.set(Sym('close-port'), (port) => {
289+
if (typeof port === "number") {
290+
closeSync(port);
291+
}
292+
});
293+
env.set(Sym('read-char'), (port) => {
294+
const value = port.next();
295+
return value.done ? EOF_OBJECT : value.value;
296+
});
297+
env.set(Sym('write-char'), (char, fd) => { writeSync(fd, char); });
298+
env.set(Sym('eof-object?'), object => object === EOF_OBJECT);
299+
env.set(Sym('port?'), port => isIteratorLike(port) || typeof port === "number");
300+
env.set(Sym('input-port?'), port => isIteratorLike(port));
301+
env.set(Sym('output-port?'), port => typeof port === "number");
276302

277303
// Error handling
278304
env.set(Sym('error'), msg => { throw new Error(msg); });

0 commit comments

Comments
 (0)