braintsck
Version:
Brainfuck to JavaScript compiler in TypeScript
147 lines (135 loc) • 4.88 kB
JavaScript
;
// -- START HEADER --
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
// Copyright (c) benja2998. You may redistribute under the terms of the GPL-3.0-or-later.
// brainTSck is a Brainfuck to JavaScript compiler written in TypeScript.
// -- END HEADER --
// -- START IMPORTS --
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
// -- END IMPORTS --
// Check if the provided file exists
// If it does, return the contents of the file
// If it doesn't, exit with an error
if (process.argv[2] == undefined) {
console.log("Usage: braintsck <file>");
process.exit(1);
}
const file = process.argv[2];
if (!fs.existsSync(file)) {
console.log(`File ${file} does not exist`);
process.exit(1);
}
const contents = fs.readFileSync(file, 'utf8');
let compiledContents = "";
compiledContents = `#!/usr/bin/env node
// DO NOT MODIFY.
// This is an automatically generated file by brainTSck.
// If you want to modify it, modify ${file} and recompile by running: braintsck ${file}
const TAPE_SIZE = 30000;
const tape = new Uint8Array(TAPE_SIZE);
let pointer = 0;
`;
// Display a banner
console.log(`
_ _ _____ ___ _
| |__ _ _ __ _(_)_ |_ _/ __| __| |__
| '_ \\ '_/ _\` | | ' \\| | \\__ \\/ _| / /
|_.__/\\_| \\__,_|_|_||_|_| |___/\\__|_\\_\\
`);
console.log(`Compiling ${file}...`);
console.time("Compilation time");
// In a loop, store each character of <contents> in a variable
for (let i = 0; i < contents.length; i++) {
const char = contents.charAt(i);
switch (char) {
case '+':
console.log("Compiling '+'");
compiledContents += `tape[pointer]++;
`;
break;
case '-':
console.log("Compiling '-'");
compiledContents += `tape[pointer]--;
`;
break;
case '>':
console.log("Compiling '>'");
compiledContents += `pointer = (pointer + 1) % TAPE_SIZE;
`;
break;
case '<':
console.log("Compiling '<'");
compiledContents += `pointer = (pointer - 1 + TAPE_SIZE) % TAPE_SIZE;
`;
break;
case '.':
console.log("Compiling '.'");
compiledContents += `process.stdout.write(String.fromCharCode(tape[pointer]));
`;
break;
case ',':
console.log("Compiling ','");
compiledContents += `{
const buffer = Buffer.alloc(1);
require('fs').readSync(0, buffer, 0, 1, null);
tape[pointer] = buffer[0];
}
`;
break;
case '[':
console.log("Compiling '['");
compiledContents += `while (tape[pointer] != 0) {
`;
break;
case ']':
console.log("Compiling ']'");
compiledContents += `}
`;
break;
default:
console.log(`Skipping ${char}`);
break;
}
}
console.timeEnd("Compilation time");
// Get the file name without the extension
const fileName = path.parse(file).name;
// Write the compiled contents to a file named <fileName>.js
fs.writeFileSync(`${fileName}.js`, compiledContents);
console.log(`Compiled ${file} to ${fileName}.js`);
console.log(`Run it by running: node ${fileName}.js`);