UNPKG

ekushscript

Version:

EkushScript is a Bengali Romanized programming language designed to be simple, fun, and expressive — written in TypeScript.

1,562 lines (1,560 loc) 71.2 kB
#!/usr/bin/env node var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; // libs/core/dist/index.js import { stdin as input, stdout as output } from "node:process"; import * as readline from "node:readline/promises"; function parseEkushInput(raw) { const val = raw.trim(); if (val === "thik") return true; if (val === "bhul") return false; if (val === "faka") return null; if (!isNaN(Number(val))) return Number(val); return val; } function throwTypeError(msg, line) { throw new EkushRuntimeError(`Ektu bhabo! ${msg}`, line); } function throwUndefinedError(name, line) { throw new EkushRuntimeError(`Khuje dekho! '${name}' variable pawa jayni.`, line); } async function runEkushScript(code, isRepl = false) { const lexer = new Lexer(code); const parser = new Parser(lexer); const ast = parser.parseProgram(); if (isRepl) { if (!replInterpreter) { replInterpreter = new Interpreter(); } await replInterpreter.evaluate(ast); } else { const interpreter = new Interpreter(); await interpreter.evaluate(ast); } } var builtins, EkushRuntimeError, Interpreter, TokenType, keywords, booleanLiterals, nullLiteral, operatorKeywords, symbols, punctuation, Lexer, Parser, replInterpreter, Compiler; var init_dist = __esm({ "libs/core/dist/index.js"() { "use strict"; builtins = { /** * bolo(): Prints output to the console * Example: bolo("Hello") */ bolo: (...args2) => { let env2 = {}; if (args2.length && typeof args2[args2.length - 1] === "object" && !Array.isArray(args2[args2.length - 1])) { env2 = args2.pop(); } const formatValue = (arg) => { if (typeof arg === "boolean") { return arg ? "thik" : "bhul"; } if (arg === null) { return "faka"; } if (typeof arg === "number" && !Number.isInteger(arg)) { return arg.toFixed(2); } if (arg instanceof String || typeof arg === "string") { return arg.replace(/\$\{([^}]+)\}/g, (_, expr) => { try { const fn = new Function(...Object.keys(env2), `return ${expr}`); return fn(...Object.values(env2)); } catch { return "${" + expr + "}"; } }); } if (Array.isArray(arg)) { return arg.map((item) => formatValue(item)); } return arg; }; for (let i = 0; i < args2.length; i++) { if (typeof args2[i] === "string" || args2[i] instanceof String) { for (let j = 0; j < args2.length; j++) { if (i !== j && typeof args2[j] !== "string" && typeof args2[j] !== "number" && !(args2[j] instanceof String)) { throw new Error("bolo(): String concatenation only allowed with other strings or numbers."); } } } } const formattedArgs = args2.map((arg) => formatValue(arg)); console.log(...formattedArgs); }, /** * shuno(): Gets input from the user * Example: rakho nam = shuno("Tomar nam ki?") */ shuno: async (text) => { const rl2 = readline.createInterface({ input, output }); const raw = await rl2.question(text ?? "Input: "); rl2.close(); return parseEkushInput(raw); }, /** * lottery(min, max): Returns a random integer between min and max * Example: rakho num = lottery(1, 100) */ lottery: (min, max) => { if (typeof min !== "number" || typeof max !== "number") { throw new Error("lottery(): min and max must be numbers"); } return Math.floor(Math.random() * (max - min + 1)) + min; }, /** * ghumao(ms): Waits asynchronously for the given milliseconds * Example: ghumao(1000) // waits 1 second */ ghumao: async (ms) => { if (typeof ms !== "number") { throw new Error("ghumao(): ms must be a number"); } return new Promise((resolve2) => setTimeout(resolve2, ms)); }, /** * kat(start, length): Returns a substring from string * Example: "Bangladesh".kat(1, 3) → "ang" */ kat: function(start, length) { if (typeof this !== "string") { throw new Error("kat(): should be called on a string"); } return this.substring(start, start + length); }, /** * jog_koro(value): Appends a value to the array * Example: list.jog_koro(5) */ arrayMethods: { jog_koro: function(...items) { if (!Array.isArray(this)) { throw new Error("jog_koro(): array er jonno"); } this.push(...items); return this; }, ber_koro: function() { if (!Array.isArray(this)) { throw new Error("ber_koro(): array er jonno"); } return this.pop(); }, lomba: function() { if (this instanceof String || typeof this === "string") { return this.length; } if (Array.isArray(this)) { return this.length; } throw new Error("lomba: string ba array er jonno"); } } }; EkushRuntimeError = class extends Error { constructor(message, line) { super(`\u{1F6A8} EkushScript Error${line ? ` [Line ${line}]` : ""}: ${message}`); this.line = line; this.name = "EkushRuntimeError"; } }; Interpreter = class { env = {}; constructor() { this.env = { ...builtins }; } async evaluate(node) { let returnValue; switch (node.type) { case "Program": return await this.evaluateProgram(node); case "VariableDeclaration": return await this.evaluateVariableDeclaration(node); case "FunctionDeclaration": return await this.evaluateFunctionDeclaration(node); case "ExpressionStatement": return await this.evaluate(node.expression); case "BlockStatement": return await this.evaluateBlockStatement(node); case "IfStatement": return await this.evaluateIfStatement(node); case "WhileStatement": return await this.evaluateWhileStatement(node); case "ForStatement": return await this.evaluateForStatement(node); case "BreakStatement": throw "break"; case "ContinueStatement": throw "continue"; case "ReturnStatement": returnValue = node.argument ? await this.evaluate(node.argument) : void 0; throw { type: "return", value: returnValue }; case "Literal": return node.value; case "Identifier": return this.evaluateIdentifier(node); case "BinaryExpression": return await this.evaluateBinaryExpression(node); case "CallExpression": return await this.evaluateCallExpression(node); case "MethodCallExpression": return await this.evaluateMethodCallExpression(node); case "ArrayLiteral": return await this.evaluateArrayLiteral(node); case "UnaryExpression": return await this.evaluateUnaryExpression(node); case "AssignmentExpression": return await this.evaluateAssignmentExpression(node); case "Comment": return void 0; case "StringLiteral": return await this.evaluateStringLiteral(node); case "MemberExpression": return await this.evaluateMemberExpression(node); default: throw new Error(`Unknown node type: ${node.type}`); } } async evaluateProgram(program) { let result; for (const stmt of program.body) { result = await this.evaluate(stmt); } return result; } async evaluateBlockStatement(block) { let result; for (const stmt of block.body) { try { result = await this.evaluate(stmt); } catch (error) { if (error === "break" || error === "continue") { throw error; } if (this.isReturnSignal(error)) { throw error; } throw error; } } return result; } isReturnSignal(error) { return error && typeof error === "object" && error.type === "return"; } async evaluateVariableDeclaration(node) { const value = await this.evaluate(node.value); this.env[node.identifier] = value; return value; } evaluateIdentifier(node) { const val = this.env[node.name]; if (val === void 0) { throwUndefinedError(node.name, node.line); } return val; } async evaluateBinaryExpression(node) { const left = await this.evaluate(node.left); const right = await this.evaluate(node.right); switch (node.operator) { case "+": case "jog": if (typeof left === "number" && typeof right === "number") return left + right; if ((typeof left === "string" || left instanceof String) && (typeof right === "string" || right instanceof String)) return String(left) + String(right); if ((typeof left === "string" || left instanceof String) && (typeof right === "number" || right instanceof Number)) { return String(left) + String(right); } if ((typeof left === "number" || left instanceof Number) && (typeof right === "string" || right instanceof String)) { return String(left) + String(right); } throwTypeError("Jog ba concatenation shudhu string er shathe string, ba number kora jabe.", node.line); break; case "-": case "biyog": return left - right; case "*": case "gun": return left * right; case "/": case "vag": return left / right; case "%": case "vag_shesh": return left % right; case "==": return left === right; case "!=": return left !== right; case "<": return left < right; case "<=": return left <= right; case ">": return left > right; case ">=": return left >= right; default: throw new Error(`Unknown operator: ${node.operator}`); } } async evaluateUnaryExpression(node) { const value = await this.evaluate(node.argument); switch (node.operator) { case "-": return -value; case "!": return !value; default: throw new Error(`Unknown unary operator: ${node.operator}`); } } async evaluateCallExpression(node) { const callee = await this.evaluate(node.callee); const args2 = await Promise.all(node.arguments.map((arg) => this.evaluate(arg))); if (typeof callee !== "function") { const name = node.callee.name; throwTypeError(`'${name}' ke call kora jabena`); } if (node.callee.type === "Identifier" && node.callee.name === "bolo") { return await callee(...args2, this.env); } return await callee(...args2); } async evaluateMethodCallExpression(node) { const object = await this.evaluate(node.object); const method = object[node.method]; if (typeof method !== "function") { throwTypeError(`'${node.method}' method ta exist korena`); } const args2 = await Promise.all(node.arguments.map((arg) => this.evaluate(arg))); return await method.apply(object, args2); } async evaluateArrayLiteral(node) { const elements = await Promise.all(node.elements.map((element) => this.evaluate(element))); Object.defineProperties(elements, { jog_koro: { value: builtins.arrayMethods.jog_koro, enumerable: false, configurable: true, writable: true }, ber_koro: { value: builtins.arrayMethods.ber_koro, enumerable: false, configurable: true, writable: true }, lomba: { value: builtins.arrayMethods.lomba, enumerable: false, configurable: true, writable: true } }); return elements; } async evaluateStringLiteral(node) { const str = node.value; const strObj = new String(str); Object.defineProperties(strObj, { lomba: { value: builtins.arrayMethods.lomba, enumerable: false, configurable: true, writable: true } }); return strObj; } async evaluateIfStatement(node) { const test = await this.evaluate(node.test); if (test) return await this.evaluate(node.consequent); if (node.alternate) return await this.evaluate(node.alternate); return void 0; } async evaluateWhileStatement(node) { let result; while (await this.evaluate(node.test)) { try { result = await this.evaluate(node.body); } catch (error) { if (error === "break") { break; } else if (error === "continue") { continue; } throw error; } } return result; } async evaluateForStatement(node) { let result; await this.evaluate(node.init); while (await this.evaluate(node.test)) { try { result = await this.evaluate(node.body); await this.evaluate(node.update); } catch (error) { if (error === "break") { break; } else if (error === "continue") { await this.evaluate(node.update); continue; } throw error; } } return result; } async evaluateAssignmentExpression(node) { let target; let value; if (node.left.type === "Identifier") { target = node.left.name; if (!(target in this.env)) { throwUndefinedError(target, node.left.line); } value = this.env[target]; } else { const object = await this.evaluate(node.left.object); const property = await this.evaluate(node.left.property); target = [object, property]; value = object[property]; } const right = await this.evaluate(node.right); switch (node.operator) { case "=": if (Array.isArray(target)) { target[0][target[1]] = right; } else { this.env[target] = right; } break; case "+=": case "jog=": if (Array.isArray(target)) { target[0][target[1]] = value + right; } else { this.env[target] = value + right; } break; case "-=": case "biyog=": if (Array.isArray(target)) { target[0][target[1]] = value - right; } else { this.env[target] = value - right; } break; case "*=": case "gun=": if (Array.isArray(target)) { target[0][target[1]] = value * right; } else { this.env[target] = value * right; } break; case "/=": case "vag=": if (Array.isArray(target)) { target[0][target[1]] = value / right; } else { this.env[target] = value / right; } break; case "%=": case "vag_shesh=": if (Array.isArray(target)) { target[0][target[1]] = value % right; } else { this.env[target] = value % right; } break; default: throw new Error(`Unsupported assignment operator: ${node.operator}`); } return Array.isArray(target) ? target[0][target[1]] : this.env[target]; } async evaluateFunctionDeclaration(node) { const func = async (...args2) => { const localEnv = { ...this.env }; node.params.forEach((param, index) => { const value = args2[index] !== void 0 ? args2[index] : this.evaluate(param.default); localEnv[param.name] = value; }); const prevEnv = this.env; this.env = localEnv; let result; try { result = await this.evaluate(node.body); } catch (error) { if (this.isReturnSignal(error)) { result = error.value; } else { throw error; } } finally { this.env = prevEnv; } return result; }; if (node.name) { this.env[node.name] = func; } return func; } async evaluateMemberExpression(node) { const object = await this.evaluate(node.object); const property = await this.evaluate(node.property); if (Array.isArray(object)) { if (typeof property !== "number") { throwTypeError("Array index must be a number", node.line); } return object[property]; } if (node.computed) { return object[property]; } else { return object[property]; } } }; TokenType = /* @__PURE__ */ ((TokenType2) => { TokenType2[TokenType2["Keyword"] = 0] = "Keyword"; TokenType2[TokenType2["Identifier"] = 1] = "Identifier"; TokenType2[TokenType2["Number"] = 2] = "Number"; TokenType2[TokenType2["String"] = 3] = "String"; TokenType2[TokenType2["Boolean"] = 4] = "Boolean"; TokenType2[TokenType2["Null"] = 5] = "Null"; TokenType2[TokenType2["Operator"] = 6] = "Operator"; TokenType2[TokenType2["Punctuation"] = 7] = "Punctuation"; TokenType2[TokenType2["Comment"] = 8] = "Comment"; TokenType2[TokenType2["EOF"] = 9] = "EOF"; return TokenType2; })(TokenType || {}); keywords = /* @__PURE__ */ new Set([ "rakho", "jodi", "nahoi", "kaj", "ferot", "cheshta", "koro", "dhoro", "ghuro", "jotokkhon", "thamo", "cholo" ]); booleanLiterals = /* @__PURE__ */ new Set(["thik", "bhul"]); nullLiteral = "faka"; operatorKeywords = /* @__PURE__ */ new Set([ "jog", "biyog", "gun", "vag", "vag_shesh", "jog=", "biyog=", "gun=", "vag=", "vag_shesh=" ]); symbols = /* @__PURE__ */ new Set([ "+", "-", "*", "/", "%", "+=", "-=", "*=", "/=", "%=", "=", "==", "!=", "<", ">", "<=", ">=", "(", ")", "{", "}", "[", "]", ";", ",", ".", "++", "--" ]); punctuation = /* @__PURE__ */ new Set([ "(", ")", "{", "}", "[", "]", ";", ",", "." ]); Lexer = class { code; pos = 0; line = 1; col = 1; currentChar; constructor(code) { this.code = code; this.currentChar = this.code[this.pos] || null; } advance() { if (this.currentChar === "\n") { this.line++; this.col = 1; } else { this.col++; } this.pos++; this.currentChar = this.code[this.pos] || null; } peek() { return this.code[this.pos + 1] || null; } skipWhitespace() { while (this.currentChar && /\s/.test(this.currentChar)) { this.advance(); } } skipComment() { if (this.currentChar === "/" && this.peek() === "/") { while (this.currentChar !== null && this.currentChar !== "\n") { this.advance(); } } if (this.currentChar === "/" && this.peek() === "*") { this.advance(); this.advance(); while (this.currentChar !== null && !(this.currentChar === "*" && this.peek() === "/")) { this.advance(); } if (this.currentChar) this.advance(); if (this.currentChar) this.advance(); } } isIdentifierStart(char) { return /[a-zA-Z_]/.test(char); } isIdentifierPart(char) { return /[a-zA-Z0-9_]/.test(char); } getOperator() { let op = this.currentChar || ""; this.advance(); if (this.currentChar === "=") { op += this.currentChar; this.advance(); } return { type: 6, value: op, line: this.line, col: this.col - op.length }; } getNumber() { let num = ""; const startCol = this.col; while (this.currentChar && /[0-9.]/.test(this.currentChar)) { num += this.currentChar; this.advance(); } return { type: 2, value: num, line: this.line, col: startCol }; } getString() { const quoteType = this.currentChar; let str = ""; const startCol = this.col; const startLine = this.line; this.advance(); while (this.currentChar && this.currentChar !== quoteType) { if (this.currentChar === "\\") { this.advance(); if (typeof this.currentChar === "string") { const ch = this.currentChar; if (ch === "n") str += "\n"; else if (ch === "t") str += " "; else if (ch === "\\") str += "\\"; else if (ch === '"') str += '"'; else if (ch === "'") str += "'"; else if (ch === "r") str += "\r"; else if (ch === "b") str += "\b"; else if (ch === "v") str += "\v"; else str += ch; } this.advance(); } else { str += this.currentChar; this.advance(); } } if (this.currentChar !== quoteType) { throw new Error(`String not closed properly. Line ${startLine}`); } this.advance(); return { type: 3, value: str, line: startLine, col: startCol }; } getIdentifier() { let id = ""; const startCol = this.col; while (this.currentChar && this.isIdentifierPart(this.currentChar)) { id += this.currentChar; this.advance(); } if (this.currentChar === "=" && operatorKeywords.has(id)) { id += this.currentChar; this.advance(); return { type: 6, value: id, line: this.line, col: startCol }; } if (keywords.has(id)) { return { type: 0, value: id, line: this.line, col: startCol }; } if (operatorKeywords.has(id)) { return { type: 6, value: id, line: this.line, col: startCol }; } if (booleanLiterals.has(id)) { return { type: 4, value: id, line: this.line, col: startCol }; } if (id === nullLiteral) { return { type: 5, value: id, line: this.line, col: startCol }; } return { type: 1, value: id, line: this.line, col: startCol }; } getNextToken() { while (this.currentChar !== null) { if (/\s/.test(this.currentChar)) { this.skipWhitespace(); continue; } if (this.currentChar === "/" && (this.peek() === "/" || this.peek() === "*")) { this.skipComment(); continue; } if (/[0-9]/.test(this.currentChar)) return this.getNumber(); if (this.currentChar === `"`) return this.getString(); if (this.isIdentifierStart(this.currentChar)) return this.getIdentifier(); const char = this.currentChar; const next = this.peek(); const twoChar = char + next; if (symbols.has(twoChar)) { this.advance(); this.advance(); return { type: 6, value: twoChar, line: this.line, col: this.col - 2 }; } if (operatorKeywords.has(char)) { return this.getOperator(); } if (punctuation.has(char)) { this.advance(); return { type: 7, value: char, line: this.line, col: this.col - 1 }; } if (symbols.has(char)) { this.advance(); return { type: 6, value: char, line: this.line, col: this.col - 1 }; } throw new Error( `Unknown character '${char}' at line ${this.line}, column ${this.col}` ); } return { type: 9, value: "EOF", line: this.line, col: this.col }; } }; Parser = class { lexer; current; constructor(lexer) { this.lexer = lexer; this.current = this.lexer.getNextToken(); } eat(type, value) { if (this.current.type === type && (!value || this.current.value === value)) { const prev = this.current; this.current = this.lexer.getNextToken(); return prev; } throw new Error(`Expected ${TokenType[type]} but got ${this.current.value}`); } parseProgram() { const body = []; while (this.current.type !== 9) { const stmt = this.parseStatement(); if (stmt) body.push(stmt); } return { type: "Program", body }; } parseStatement() { if (this.current.type === 8) { const comment = this.current.value; const multiline = comment.startsWith("/*"); this.eat( 8 /* Comment */ ); return { type: "Comment", value: comment, multiline }; } if (this.current.type === 0) { switch (this.current.value) { case "rakho": return this.parseVariableDeclaration(); case "kaj": return this.parseFunctionDeclaration(); case "jodi": return this.parseIfStatement(); case "jotokkhon": return this.parseWhileStatement(); case "ghuro": return this.parseForStatement(); case "thamo": return this.parseBreakStatement(); case "cholo": return this.parseContinueStatement(); case "ferot": return this.parseReturnStatement(); case "cheshta": return this.parseTryCatchStatement(); } } return this.parseExpressionStatement(); } parseVariableDeclaration() { this.eat(0, "rakho"); const identifier = this.eat( 1 /* Identifier */ ).value; this.eat(6, "="); const value = this.parseExpression(); this.optionalSemicolon(); return { type: "VariableDeclaration", identifier, value }; } parseFunctionDeclaration() { this.eat(0, "kaj"); let name = null; if (this.current.type === 1) { name = this.eat( 1 /* Identifier */ ).value; } this.eat(7, "("); const params = []; while (this.current.type !== 7 || this.current.value !== ")") { const paramName = this.eat( 1 /* Identifier */ ).value; let defaultValue = void 0; if (this.current.value === "=") { this.eat(6, "="); defaultValue = this.parseExpression(); } params.push({ name: paramName, default: defaultValue }); if (this.current.value === ",") this.eat(7, ","); } this.eat(7, ")"); const body = this.parseBlockStatement(); return { type: "FunctionDeclaration", name, params, body }; } parseIfStatement() { this.eat(0, "jodi"); this.eat(7, "("); const test = this.parseExpression(); this.eat(7, ")"); const consequent = this.parseBlockStatement(); let alternate = void 0; if (this.current.type === 0 && this.current.value === "nahoi") { this.eat(0, "nahoi"); if (this.current.type === 0 && this.current.value === "jodi") { alternate = this.parseIfStatement(); } else { alternate = this.parseBlockStatement(); } } return { type: "IfStatement", test, consequent, alternate }; } parseWhileStatement() { this.eat(0, "jotokkhon"); this.eat(7, "("); const test = this.parseExpression(); this.eat(7, ")"); const body = this.parseBlockStatement(); return { type: "WhileStatement", test, body }; } parseForStatement() { this.eat(0, "ghuro"); this.eat(7, "("); const init = this.parseVariableDeclaration(); const test = this.parseExpression(); this.eat(7, ";"); const update = this.parseExpression(); this.eat(7, ")"); const body = this.parseBlockStatement(); return { type: "ForStatement", init, test, update, body }; } parseBreakStatement() { this.eat(0, "thamo"); this.optionalSemicolon(); return { type: "BreakStatement" }; } parseContinueStatement() { this.eat(0, "cholo"); this.optionalSemicolon(); return { type: "ContinueStatement" }; } parseReturnStatement() { this.eat(0, "ferot"); let argument = void 0; if (this.current.value !== ";" && this.current.type !== 9) { argument = this.parseExpression(); } this.optionalSemicolon(); return { type: "ReturnStatement", argument }; } parseTryCatchStatement() { this.eat(0, "cheshta"); this.eat(0, "koro"); const tryBlock = this.parseBlockStatement(); this.eat(0, "dhoro"); this.eat(7, "("); const catchParam = this.eat( 1 /* Identifier */ ).value; this.eat(7, ")"); const catchBlock = this.parseBlockStatement(); return { type: "TryCatchStatement", tryBlock, catchParam, catchBlock }; } parseBlockStatement() { this.eat(7, "{"); const body = []; while (this.current.value !== "}" && this.current.type !== 9) { const stmt = this.parseStatement(); if (stmt) body.push(stmt); } this.eat(7, "}"); return { type: "BlockStatement", body }; } parseExpressionStatement() { const expr = this.parseExpression(); this.optionalSemicolon(); return { type: "ExpressionStatement", expression: expr }; } parseExpression() { const left = this.parseAssignmentExpression(); return this.parseMemberExpression(left); } parseAssignmentExpression() { let left = this.parseBinaryExpression(); left = this.parseMemberExpression(left); const compoundOperators = /* @__PURE__ */ new Set([ "=", "+=", "-=", "*=", "/=", "%=", "jog=", "biyog=", "gun=", "vag=", "vag_shesh=" ]); if (this.current.type === 6 && compoundOperators.has(this.current.value)) { if (left.type !== "Identifier" && left.type !== "MemberExpression") { throw new Error("Assignment target must be a variable name or member expression."); } const operatorToken = this.eat( 6 /* Operator */ ); const operator = operatorToken.value; const right = this.parseAssignmentExpression(); return { type: "AssignmentExpression", // eslint-disable-next-line @typescript-eslint/no-explicit-any operator, left, right, line: operatorToken.line }; } return left; } parseBinaryExpression() { let left = this.parsePrimaryExpression(); const binaryOperators = /* @__PURE__ */ new Set([ "+", "-", "*", "/", "%", "==", "!=", "<", ">", "<=", ">=", "jog", "biyog", "gun", "vag", "vag_shesh" ]); while (this.current.type === 6 && binaryOperators.has(this.current.value)) { const operatorToken = this.eat( 6 /* Operator */ ); const operator = operatorToken.value; const right = this.parsePrimaryExpression(); left = { type: "BinaryExpression", operator, left, right, line: operatorToken.line }; } return left; } parsePrimaryExpression() { if (this.current.type === 2) { const token = this.eat( 2 /* Number */ ); const value = Number(token.value); return { type: "Literal", value, line: token.line }; } if (this.current.type === 3) { const token = this.eat( 3 /* String */ ); return { type: "StringLiteral", value: token.value, line: token.line }; } if (this.current.type === 4) { const token = this.eat( 4 /* Boolean */ ); return { type: "Literal", value: token.value === "thik", line: token.line }; } if (this.current.type === 5) { const token = this.eat( 5 /* Null */ ); return { type: "Literal", value: null, line: token.line }; } if (this.current.type === 1) { const token = this.eat( 1 /* Identifier */ ); const name = token.value; if (this.current.value === "(") { this.eat(7, "("); const args2 = []; while (this.current.type !== 7 || this.current.value !== ")") { if (this.current.type === 9) { throw new Error("Expected ')' but reached end of file."); } args2.push(this.parseExpression()); if (this.current.type === 7 && this.current.value === ",") { this.eat(7, ","); } else if (this.current.type === 7 && this.current.value !== ")") { throw new Error(`Unexpected token in arguments: ${this.current.value}`); } } this.eat(7, ")"); return { type: "CallExpression", callee: { type: "Identifier", name, line: token.line }, arguments: args2, line: token.line }; } if (this.current.value === ".") { this.eat(7, "."); const property = this.eat( 1 /* Identifier */ ).value; if (this.current.value === "(") { this.eat(7, "("); const args2 = []; while (this.current.type !== 7 || this.current.value !== ")") { if (this.current.type === 9) { throw new Error("Expected ')' but reached end of file."); } args2.push(this.parseExpression()); if (this.current.type === 7 && this.current.value === ",") { this.eat(7, ","); } else if (this.current.type === 7 && this.current.value !== ")") { throw new Error(`Unexpected token in arguments: ${this.current.value}`); } } this.eat(7, ")"); return { type: "MethodCallExpression", object: { type: "Identifier", name, line: token.line }, method: property, arguments: args2, line: token.line }; } } return { type: "Identifier", name, line: token.line }; } if (this.current.type === 7 && this.current.value === "[") { return this.parseArrayLiteral(); } if (this.current.type === 7 && this.current.value === "(") { this.eat(7, "("); const expr = this.parseExpression(); this.eat(7, ")"); return expr; } throw new Error(`Unexpected token: ${this.current.value}`); } parseArrayLiteral() { this.eat(7, "["); const elements = []; while (this.current.type !== 7 || this.current.value !== "]") { elements.push(this.parseExpression()); if (this.current.value === ",") { this.eat(7, ","); } } this.eat(7, "]"); return { type: "ArrayLiteral", elements }; } parseMemberExpression(object) { if (this.current.type === 7 && this.current.value === "[") { this.eat(7, "["); const property = this.parseExpression(); this.eat(7, "]"); return { type: "MemberExpression", object, property, computed: true }; } return object; } optionalSemicolon() { if (this.current.value === ";") { this.eat(7, ";"); } } }; replInterpreter = null; Compiler = class { indentLevel = 0; INDENT = " "; // 2 spaces compile(ast) { return this.compileNode(ast); } indent() { return this.INDENT.repeat(this.indentLevel); } compileNode(node) { switch (node.type) { case "Program": return this.compileProgram(node); case "VariableDeclaration": return this.compileVariableDeclaration(node); case "FunctionDeclaration": return this.compileFunctionDeclaration(node); case "BlockStatement": return this.compileBlockStatement(node); case "ExpressionStatement": return this.compileExpressionStatement(node); case "CallExpression": return this.compileCallExpression(node); case "MethodCallExpression": return this.compileMethodCallExpression(node); case "BinaryExpression": return this.compileBinaryExpression(node); case "UnaryExpression": return this.compileUnaryExpression(node); case "Identifier": return this.compileIdentifier(node); case "Literal": return this.compileLiteral(node); case "StringLiteral": return this.compileStringLiteral(node); case "ArrayLiteral": return this.compileArrayLiteral(node); case "IfStatement": return this.compileIfStatement(node); case "WhileStatement": return this.compileWhileStatement(node); case "ForStatement": return this.compileForStatement(node); case "ReturnStatement": return this.compileReturnStatement(node); case "BreakStatement": return this.compileBreakStatement(node); case "ContinueStatement": return this.compileContinueStatement(node); case "AssignmentExpression": return this.compileAssignmentExpression(node); case "MemberExpression": return this.compileMemberExpression(node); case "TryCatchStatement": return this.compileTryCatchStatement(node); case "Comment": return this.compileComment(node); default: throw new Error(`Unknown node type: ${node.type}`); } } compileProgram(node) { return node.body.map((stmt) => this.compileNode(stmt)).join("\n"); } compileVariableDeclaration(node) { const isReassigned = this.isVariableReassigned(node.identifier); const declarationType = isReassigned ? "let" : "const"; return `${this.indent()}${declarationType} ${node.identifier} = ${this.compileNode(node.value)};`; } isVariableReassigned(identifier) { return false; } compileFunctionDeclaration(node) { const name = node.name || ""; const params = node.params.map((param) => { if (param.default) { return `${param.name} = ${this.compileNode(param.default)}`; } return param.name; }).join(", "); return `${this.indent()}function ${name}(${params}) ${this.compileNode(node.body)}`; } compileBlockStatement(node) { this.indentLevel++; const body = node.body.map((stmt) => this.compileNode(stmt)).join("\n"); this.indentLevel--; return `{ ${body} ${this.indent()}}`; } compileExpressionStatement(node) { return `${this.indent()}${this.compileNode(node.expression)};`; } compileCallExpression(node) { const args2 = node.arguments.map((arg) => this.compileNode(arg)).join(", "); return `${this.compileNode(node.callee)}(${args2})`; } compileMethodCallExpression(node) { const args2 = node.arguments.map((arg) => this.compileNode(arg)).join(", "); const methodTranslations = { "lomba": "length", "jog_koro": "push", "ber_koro": "pop", "suru_koro": "unshift", "suru_ber_koro": "shift", "khojo": "indexOf", "ache": "includes" }; const translatedMethod = methodTranslations[node.method] || node.method; if (translatedMethod === "length") { return `${this.compileNode(node.object)}.${translatedMethod}`; } return `${this.compileNode(node.object)}.${translatedMethod}(${args2})`; } compileBinaryExpression(node) { const operator = this.translateOperator(node.operator); return `${this.compileNode(node.left)} ${operator} ${this.compileNode(node.right)}`; } compileUnaryExpression(node) { return `${node.operator}${this.compileNode(node.argument)}`; } compileIdentifier(node) { const translations = { "bolo": "console.log", "shuno": "prompt", "thik": "true", "bhul": "false", "faka": "null" }; return translations[node.name] || node.name; } compileLiteral(node) { if (node.value === null) return "null"; if (typeof node.value === "boolean") { return node.value ? "true" : "false"; } return String(node.value); } compileStringLiteral(node) { return `"${node.value}"`; } compileArrayLiteral(node) { const elements = node.elements.map((elem) => this.compileNode(elem)).join(", "); return `[${elements}]`; } compileIfStatement(node) { let result = `${this.indent()}if (${this.compileNode(node.test)}) ${this.compileNode(node.consequent)}`; if (node.alternate) { if (node.alternate.type === "IfStatement") { result += ` else ${this.compileIfStatement(node.alternate)}`; } else { result += ` else ${this.compileNode(node.alternate)}`; } } return result; } compileWhileStatement(node) { return `${this.indent()}while (${this.compileNode(node.test)}) ${this.compileNode(node.body)}`; } compileForStatement(node) { const init = this.compileNode(node.init).replace("const", "let"); return `${this.indent()}for (${init} ${this.compileNode(node.test)}; ${this.compileNode(node.update)}) ${this.compileNode(node.body)}`; } compileReturnStatement(node) { return `${this.indent()}return${node.argument ? " " + this.compileNode(node.argument) : ""};`; } compileBreakStatement(_node) { return `${this.indent()}break;`; } compileContinueStatement(_node) { return `${this.indent()}continue;`; } compileAssignmentExpression(node) { const operator = this.translateOperator(node.operator); return `${this.compileNode(node.left)} ${operator} ${this.compileNode(node.right)}`; } compileMemberExpression(node) { if (node.computed) { return `${this.compileNode(node.object)}[${this.compileNode(node.property)}]`; } return `${this.compileNode(node.object)}.${this.compileNode(node.property)}`; } compileTryCatchStatement(node) { return `${this.indent()}try ${this.compileNode(node.tryBlock)} ${this.indent()}catch(${node.catchParam}) ${this.compileNode(node.catchBlock)}`; } compileComment(node) { return node.multiline ? `${this.indent()}/*${node.value}*/` : `${this.indent()}//${node.value}`; } translateOperator(operator) { const operatorMap = { "jog": "+", "biyog": "-", "gun": "*", "vag": "/", "vag_shesh": "%", "jog=": "+=", "biyog=": "-=", "gun=": "*=", "vag=": "/=", "vag_shesh=": "%=" }; return operatorMap[operator] || operator; } }; } }); // node_modules/.pnpm/chalk@5.4.1/node_modules/chalk/source/vendor/ansi-styles/index.js function assembleStyles() { const codes = /* @__PURE__ */ new Map(); for (const [groupName, group] of Object.entries(styles)) { for (const [styleName, style] of Object.entries(group)) { styles[styleName] = { open: `\x1B[${style[0]}m`, close: `\x1B[${style[1]}m` }; group[styleName] = styles[styleName]; codes.set(style[0], style[1]); } Object.defineProperty(styles, groupName, { value: group, enumerable: false }); } Object.defineProperty(styles, "codes", { value: codes, enumerable: false }); styles.color.close = "\x1B[39m"; styles.bgColor.close = "\x1B[49m"; styles.color.ansi = wrapAnsi16(); styles.color.ansi256 = wrapAnsi256(); styles.color.ansi16m = wrapAnsi16m(); styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET); styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET); styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET); Object.defineProperties(styles, { rgbToAnsi256: { value(red, green, blue) { if (red === green && green === blue) { if (red < 8) { return 16; } if (red > 248) { return 231; } return Math.round((red - 8) / 247 * 24) + 232; } return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5); }, enumerable: false }, hexToRgb: { value(hex) { const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16)); if (!matches) { return [0, 0, 0]; } let [colorString] = matches; if (colorString.length === 3) { colorString = [...colorString].map((character) => character + character).join(""); } const integer = Number.parseInt(colorString, 16); return [ /* eslint-disable no-bitwise */ integer >> 16 & 255, integer >> 8 & 255, integer & 255 /* eslint-enable no-bitwise */ ]; }, enumerable: false }, hexToAnsi256: { value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)), enumerable: false }, ansi256ToAnsi: { value(code) { if (code < 8) { return 30 + code; } if (code < 16) { re