UNPKG

petcarescript

Version:

PetCareScript - A modern, expressive programming language designed for humans with async, HTTP, database, and testing support

479 lines (414 loc) 15.9 kB
/** * PetCareScript Main Entry Point * Main entry point for the language - VERSÃO MELHORADA E CORRIGIDA */ const Tokenizer = require('./lexer/tokenizer'); const Parser = require('./parser/parser'); const Interpreter = require('./interpreter/interpreter'); const CoreLib = require('./stdlib/core'); const MathLib = require('./stdlib/math'); const StringLib = require('./stdlib/string'); const HTTPLib = require('./stdlib/http'); const DatabaseLib = require('./stdlib/database'); const TestingLib = require('./stdlib/testing'); const AsyncLib = require('./stdlib/async'); class PetCareScript { constructor() { this.interpreter = new Interpreter(); this.version = require('../package.json').version; this.setupStandardLibrary(); } setupStandardLibrary() { // A nova abordagem: o interpreter já define todas as funções nativas // Agora vamos apenas adicionar algumas funções específicas que não estão no interpreter this.defineAdditionalFunctions(); } defineAdditionalFunctions() { // Funções específicas que não estão no interpreter this.interpreter.globals.define('version', { arity: () => 0, call: () => this.version }); this.interpreter.globals.define('exit', { arity: () => -1, call: (interpreter, args) => { const code = args[0] || 0; process.exit(code); } }); this.interpreter.globals.define('help', { arity: () => 0, call: () => { console.log(this.getHelpText()); return null; } }); // Adicionar algumas funções do CoreLib que podem ter implementações específicas this.registerSelectiveLibrary(CoreLib, 'Core'); this.registerSelectiveLibrary(MathLib, 'Math'); this.registerSelectiveLibrary(StringLib, 'String'); this.registerSelectiveLibrary(HTTPLib, 'HTTP'); this.registerSelectiveLibrary(TestingLib, 'Testing'); this.registerSelectiveLibrary(AsyncLib, 'Async'); } registerSelectiveLibrary(lib, name) { try { Object.entries(lib).forEach(([key, value]) => { // Só registra se a função não existe ainda no interpreter if (!this.interpreter.globals.has(key)) { if (typeof value === 'function') { // Check if it's a class constructor const isClass = value.prototype && value.prototype.constructor === value; if (isClass) { // For classes, create a wrapper function that uses 'new' const arity = this.getFunctionArity(key, value); this.interpreter.globals.define(key, { arity: () => arity, call: (interpreter, args) => { try { return new value(...args); } catch (error) { throw new Error(`Error in ${name}.${key}: ${error.message}`); } } }); } else { // For regular functions const arity = this.getFunctionArity(key, value); this.interpreter.globals.define(key, { arity: () => arity, call: (interpreter, args) => { try { return value(...args); } catch (error) { throw new Error(`Error in ${name}.${key}: ${error.message}`); } } }); } } else { // For non-function values this.interpreter.globals.define(key, value); } } }); } catch (error) { console.warn(`Warning: Failed to register selective ${name} library: ${error.message}`); } } getHelpText() { return ` PetCareScript v${this.version} - Built-in Functions: TYPE CHECKING: typeOf(value) - Get type of value isNumber(value) - Check if number isString(value) - Check if string isBoolean(value) - Check if boolean isArray(value) - Check if array isObject(value) - Check if object isFunction(value) - Check if function isEmpty(value) - Check if empty TYPE CONVERSION: toString(value) - Convert to string toNumber(value) - Convert to number toBoolean(value) - Convert to boolean toArray(value) - Convert to array ARRAY FUNCTIONS: length(array) - Get length push(array, item) - Add to end pop(array) - Remove from end slice(array, start, end) - Get slice indexOf(array, item) - Find index includes(array, item) - Check if contains join(array, separator) - Join to string map(array, fn) - Transform elements filter(array, fn) - Filter elements reduce(array, fn, init) - Reduce to value sort(array, fn) - Sort array reverse(array) - Reverse array concat(array, ...others) - Concatenate arrays STRING FUNCTIONS: upper(string) - To uppercase lower(string) - To lowercase trim(string) - Remove whitespace split(string, sep) - Split to array replace(string, old, new) - Replace text startsWith(string, prefix) - Check prefix endsWith(string, suffix) - Check suffix charAt(string, index) - Get character at index substring(string, start, end) - Get substring OBJECT FUNCTIONS: Object.keys(obj) - Get object keys Object.values(obj) - Get object values Object.entries(obj) - Get key-value pairs Object.assign(target, ...sources) - Merge objects Object.create(proto) - Create object with prototype Object.freeze(obj) - Freeze object Object.seal(obj) - Seal object Object.preventExtensions(obj) - Prevent extensions Object.isFrozen(obj) - Check if frozen Object.isSealed(obj) - Check if sealed Object.isExtensible(obj) - Check if extensible hasProperty(obj, prop) - Check if has property keys(obj) - Get keys (alias) values(obj) - Get values (alias) entries(obj) - Get entries (alias) MATH FUNCTIONS: abs(number) - Absolute value max(...numbers) - Maximum value min(...numbers) - Minimum value sqrt(number) - Square root pow(base, exp) - Power floor(number) - Round down ceil(number) - Round up round(number) - Round nearest random() - Random 0-1 randomInt(min, max) - Random integer JSON FUNCTIONS: JSON.parse(string) - Parse JSON string JSON.stringify(obj) - Convert to JSON string parseJSON(string) - Parse JSON (alias) stringifyJSON(obj) - Stringify JSON (alias) For more help, visit: https://github.com/estevamsl/petcarescript `; } getFunctionArity(name, func) { // Special cases for functions with variable arguments const variableArityFunctions = { 'format': -1, 'get': -1, 'post': -1, 'put': -1, 'patch': -1, 'delete': -1, 'assign': -1, 'stringifyJSON': -1, 'log': -1, 'error': -1, 'warn': -1, 'info': -1, 'max': -1, 'min': -1, 'sum': -1, 'concat': -1 }; if (variableArityFunctions[name] !== undefined) { return variableArityFunctions[name]; } // Default to function.length return func.length || 0; } run(source) { try { // Add debug logging if environment variable is set const debug = process.env.PCS_DEBUG === 'true'; if (debug) { console.log('🔍 Debug: Starting tokenization...'); } // Tokenization const tokenizer = new Tokenizer(source); const tokens = tokenizer.tokenize(); if (debug) { console.log('🔍 Debug: Tokens generated:', tokens.length); console.log('🔍 Debug: Starting parsing...'); } // Parsing const parser = new Parser(tokens); const ast = parser.parse(); if (debug) { console.log('🔍 Debug: AST generated, statements:', ast.statements.length); console.log('🔍 Debug: Starting interpretation...'); } // Interpretation this.interpreter.interpret(ast.statements); if (debug) { console.log('🔍 Debug: Interpretation completed successfully'); } return { success: true }; } catch (error) { const errorMessage = `${error.message}`; // Don't show full stack trace unless in debug mode if (process.env.PCS_DEBUG === 'true') { console.error(`❌ Runtime Error: ${errorMessage}`); console.error('Stack trace:', error.stack); } else { console.error(`❌ Runtime Error: ${errorMessage}`); } return { success: false, error: errorMessage, stack: error.stack }; } } runFile(filename) { const fs = require('fs'); try { if (!fs.existsSync(filename)) { throw new Error(`File not found: ${filename}`); } const source = fs.readFileSync(filename, 'utf8'); return this.run(source); } catch (error) { const errorMessage = `Error reading file: ${error.message}`; console.error(`❌ File Error: ${errorMessage}`); return { success: false, error: errorMessage }; } } repl() { const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: 'pcs> ' }); console.log(`🐾 PetCareScript v${this.version} REPL`); console.log('Type "exit", "quit", or Ctrl+C to quit.'); console.log('Type "help" for available commands.\n'); rl.prompt(); rl.on('line', (line) => { const input = line.trim(); if (input === 'exit' || input === 'quit') { rl.close(); return; } if (input === 'help') { this.showReplHelp(); rl.prompt(); return; } if (input === 'clear' || input === 'cls') { console.clear(); console.log(`🐾 PetCareScript v${this.version} REPL`); rl.prompt(); return; } if (input === 'version') { console.log(`PetCareScript v${this.version}`); rl.prompt(); return; } if (input === 'debug') { process.env.PCS_DEBUG = process.env.PCS_DEBUG === 'true' ? 'false' : 'true'; console.log(`Debug mode: ${process.env.PCS_DEBUG === 'true' ? 'ON' : 'OFF'}`); rl.prompt(); return; } if (input === '') { rl.prompt(); return; } try { const result = this.run(input); if (!result.success) { console.error(`❌ ${result.error}`); } } catch (error) { console.error(`❌ ${error.message}`); } rl.prompt(); }); rl.on('close', () => { console.log('\n👋 Goodbye!'); process.exit(0); }); rl.on('SIGINT', () => { console.log('\n👋 Goodbye!'); process.exit(0); }); } showReplHelp() { console.log(` REPL COMMANDS: help Show this help clear, cls Clear screen version Show version debug Toggle debug mode exit, quit Exit REPL PETCARESCRIPT SYNTAX: store x = 42; # Define a variable show x; # Print the value build hello() { show "Hello!"; } # Define function hello(); # Call function # Object manipulation store obj = { name: "Test", age: 25 }; store keys = Object.keys(obj); store copy = Object.assign({}, obj); # Blueprints (OOP) blueprint Dog { build init(name) { self.name = name; } build bark() { show self.name + " barks!"; } } store dog = Dog("Rex"); dog.bark(); # HTTP Server store server = createServer(3000); server.get("/", build(req, res) { res.json({message: "Hello!"}); }); server.listen(build() { show "Server started!"; }); # Async/Promises async build fetchData() { store result = await get("https://api.example.com"); give result; } More examples: https://github.com/estevamsl/petcarescript `); } getVersion() { return this.version; } getLanguageInfo() { return { name: 'PetCareScript', version: this.getVersion(), extension: '.pcs', description: 'A modern and expressive programming language with async, HTTP, database, and testing support', features: [ 'Human-readable syntax', 'Object-oriented programming (blueprints)', 'Async/await support', 'Built-in HTTP server', 'Database integration', 'Testing framework', 'Promise support', 'Template strings', 'Array and string utilities', 'Complete Object manipulation support', 'Advanced Math functions', 'String manipulation and validation', 'Type checking and conversion' ] }; } // Method to validate syntax without executing validateSyntax(source) { try { const tokenizer = new Tokenizer(source); const tokens = tokenizer.tokenize(); const parser = new Parser(tokens); parser.parse(); return { valid: true }; } catch (error) { return { valid: false, error: error.message }; } } // Method to get available built-in functions getBuiltinFunctions() { const functions = []; this.interpreter.globals.values.forEach((value, key) => { if (value && typeof value.arity === 'function') { functions.push({ name: key, arity: value.arity() }); } }); return functions.sort((a, b) => a.name.localeCompare(b.name)); } } module.exports = PetCareScript;