UNPKG

castelog

Version:

Programación JavaScript en castellano.

830 lines (802 loc) 41.6 kB
class Castelog_compiler { static get HOOK_ID() { return { "Sentencia": "/\n '######~{ Hooks del Parser de Castelog: SENTENCIA }~######'", "Generativa": "/\n '######~{ Hooks del Parser de Castelog: GENERATIVA }~######'", "Prepéndice": "/\n '######~{ Hooks del Parser de Castelog: PREPÉNDICE }~######'", "Apéndice": "/\n '######~{ Hooks del Parser de Castelog: APÉNDICE }~######'" }; } static getCaloxParser() { return require(__dirname + "/castelog-xtensions.js"); } static getDefaultCastelogParserSourceCode() { return require("fs").readFileSync(__dirname + "/castelog.pegjs").toString(); } static getDefaultParserExtensionsDirectory() { const fs = require("fs"); const path = require("path"); const basePath = path.resolve(process.cwd()); let pivotPath = basePath; let previousPath = undefined; while(pivotPath !== previousPath) { const caloModulesDirectory = fs.readdirSync(pivotPath).filter(f => f === "calo_modules"); if(caloModulesDirectory.length) { const caloModulesPath = path.resolve(pivotPath, "calo_modules"); const caloModulesList = fs.readdirSync(caloModulesPath); return caloModulesPath; } previousPath = pivotPath; pivotPath = path.dirname(pivotPath); } throw new Error("Required directory 'calo_modules' to exist in any subpath of «" + basePath + "» in order to «Castelog_compiler.getDefaultParserExtensionsDirectory»") } static get parser() { return require(__dirname + "/castelog.js"); } static normalize_file_1(file_dirty, file_dir, file_dir_2 = process.cwd()) { const path = require("path"); return file_dirty.startsWith("./") ? path.resolve(file_dir, file_dirty.substr(2)) : file_dirty.startsWith("@/") ? path.resolve(file_dir_2, file_dirty.substr(2)) : file_dirty; } static dirname(file) { return require("path").dirname(file); } static custom_require(file, dirname, dirprocess) { return `function(id) { return ((typeof(require) === 'function') ? require : (...args) => { return Castelog.metodos.un_modulo_importado(id, ${JSON.stringify(dirname)}, ${JSON.stringify(dirprocess)}); })(id); }`; } static get custom_module() { return `{ exports:undefined }`; } static getIndexesOf(str, searchKeyword) { let startingIndices = []; let indexOccurence = str.indexOf(searchKeyword, 0); while (indexOccurence >= 0) { startingIndices.push(indexOccurence); indexOccurence = str.indexOf(searchKeyword, indexOccurence + 1); } return startingIndices; } static wrapUmdModuleFunction(mod, file) { const dirname = this.dirname(file); const dirprocess = process.cwd(); const sane_dirname = JSON.stringify(dirname); const sane_dirprocess = JSON.stringify(dirprocess); return `\n// [castelog:modulo] [origen:] ${file}\n(function(factory_original, filename, metadata) { try { const require_ = (typeof require === "function") ? require : ${this.custom_require(file, dirname, dirprocess)}; const module_ = (typeof module !== "undefined") ? module : ${this.custom_module}; const __filename_ = filename; const fileparts = filename.split("/"); fileparts.pop(); const __dirname_ = fileparts.join("/"); const factory = (require_, module_, ...others) => { const output1 = factory_original(require_, module_, ...others); const output2 = module_.exports; const output = (typeof(output1) !== "undefined") ? output1 : output2; const name = module_.__castelog_module_name__ ? module_.__castelog_module_name__ : filename; return { output, name }; }; const { output, name } = factory(require_, module_, __dirname_, __filename_); const envs = []; if(typeof window !== "undefined") { window[name] = output; envs.push("window[" + JSON.stringify(name) + "]"); } if(typeof global !== "undefined") { global[name] = output; envs.push("global[" + JSON.stringify(name) + "]"); } if((typeof(Castelog) !== "undefined") && (typeof(Castelog.metodos) !== "undefined") && (typeof(Castelog.metodos.un_modulo_exportado) === "function")) { Castelog.metodos.un_modulo_exportado(name, output, factory, ${sane_dirname}, ${sane_dirprocess} ); envs.push("Castelog.modulos[" + JSON.stringify(name) + "].value"); } // console.log("Exportado módulo calo " + JSON.stringify(name) + " en:\\n - " + envs.join("\\n - ")); } catch(error) { console.error("Error en la exportación del módulo ${file}:", error); throw error; } })(${mod});`; } static compileCode(code, customOption = {}) { return this.parser.parse(code, { customOption: { ...customOption, } }); } static compileFile(fileParameter, customOption, console_log = console.log) { let last_file = undefined; const fs = require("fs"); const path = require("path"); const file = path.resolve(fileParameter); const jsFile = file.replace(/\.(calo)$/gi, ".js"); if (!fs.existsSync(file)) { throw new Error("[CASTELOG] File not found: " + file); } else if (!fs.lstatSync(file).isFile()) { throw new Error("[CASTELOG] Path must point to a file: " + file); } last_file = file; const clgCode = fs.readFileSync(file).toString(); let jsCode = undefined; try { jsCode = this.compileCode(clgCode, { ...customOption, }); } catch (error) { console_log("Error al compilar fichero Castelog a JavaScript: " + file, error); error.castelog_api_last_file = last_file; throw error; } try { fs.writeFileSync(jsFile, jsCode, "utf8"); } catch (error) { console_log("Error al volcar fichero JavaScript a Castelog: " + file, error); error.castelog_api_last_file = last_file; throw error; } return jsCode; } static compileFiles(files, customOption, console_log = console.log) { let last_file = undefined; try { const starting_moment = new Date(); const resultado_final = {} const fs = require("fs"); const path = require("path"); let compiled_files = {}; let configurations = { isHtml5: false }; const token_compilable = "\n// [castelog:compilables] "; const token_empaquetable = "\n// [castelog:empaquetables] "; const token_html5izable = "\n// [castelog:html5izable] ACTIVADO con:"; console_log(`[Paso 1.1] Compilando ${files.length} fichero${(files.length > 1) ? "s" : ""} principal${(files.length > 1) ? "s" : ""} de Castelog a JavaScript. ${JSON.stringify(files, null, 2)}`) let first_file = undefined; let first_file_original = undefined; for (let index = 0; index < files.length; index++) { const file = files[index]; let js_code = ""; try { last_file = file; console.log("[Paso 1.1." + (index+1) + "] Compilando fichero principal: " + file); js_code = this.compileFile(file, { __filename: file, is_runnable: index === 0, ...customOption }); compiled_files[file] = js_code; if (index === 0) { first_file = { file, js_code }; first_file_original = { file, js_code }; } } catch (error) { console_log("Error compilando fichero (principal) Castelog a JavaScript: " + file); error.castelog_api_last_file = last_file; throw error; } try { fs.writeFileSync(file.replace(/\.(calo)$/gi, "") + ".js", js_code); } catch (error) { console_log("Error volcando fichero (principal) JavaScript (de Castelog): " + file); error.castelog_api_last_file = last_file; throw error; } } last_file = first_file.file; const compilable_files = (() => { try { const compilableMatches = this.getIndexesOf(first_file.js_code, token_compilable).map(ind => { try { const substr_1 = first_file.js_code.substr(ind + token_compilable.length); const next_line_pos_1_ = substr_1.indexOf("\n"); const next_line_pos_1 = (next_line_pos_1_ === -1) ? first_file.js_code.length : next_line_pos_1_; const compilable_item = JSON.parse(substr_1.substr(0, next_line_pos_1).trim()); return compilable_item; } catch (error) { throw error; } }); return compilableMatches; } catch(error) { console.log("Error obteniendo detalles de ficheros secundarios:", error); throw error; } })(); const file_dir = path.dirname(first_file.file); if (compilable_files.length) { const compilable_files_2 = compilable_files.map(f => this.normalize_file_1(f, file_dir, process.cwd())); console_log(`[Paso 1.2] Compilando ${compilable_files.length} fichero${(compilable_files.length > 1) ? "s" : ""} asociado${(compilable_files.length > 1) ? "s" : ""} de Castelog a JavaScript. ${JSON.stringify(compilable_files_2, null, 2)}`) for (let index = 0; index < compilable_files_2.length; index++) { const file_dirty = compilable_files_2[index]; const file = file_dirty; last_file = file; let js_code = ""; try { console.log("[Paso 1.2." + (index+1) + "] Compilando fichero secundario " + file) js_code = this.compileFile(file, { __filename: file, is_runnable: index === 0, ...customOption }); compiled_files[file] = js_code; } catch (error) { console_log("Error compilando fichero (asociado) Castelog a JavaScript: " + file); error.castelog_api_last_file = last_file; throw error; } let js_file = file.replace(/\.(calo)$/gi, "") + ".js"; try { fs.writeFileSync(js_file, js_code, "utf8"); } catch (error) { console_log("Error volcando fichero (asociado) JavaScript (de Castelog): " + js_file); error.castelog_api_last_file = last_file; throw error; } } Object.assign(resultado_final, { compiled_files }); } else { console_log("No se encontraron compilables asociados."); } console_log(`[Paso 1.2] ¡Compilación de ficheros Castelog a JavaScript exitoso!`) //const child_process = require("child_process"); const salida = path.resolve(customOption.empaquetar || path.dirname(first_file.file)); const calofiles = compilable_files.map(file => path.resolve(file)); try { fs.mkdirSync(salida); } catch (error) { // @noop. } let main_contents = ""; try { const empaquetableMatches = this.getIndexesOf(first_file.js_code, token_empaquetable).map(ind => { const substr_1 = first_file.js_code.substr(ind + token_empaquetable.length); const next_line_pos_1_ = substr_1.indexOf("\n"); const next_line_pos_1 = (next_line_pos_1_ === -1) ? substr_1.length : next_line_pos_1_; const empaquetable_item = this.normalize_file_1(JSON.parse(substr_1.substr(0, next_line_pos_1).trim()), file_dir, process.cwd()); return empaquetable_item; }); if (empaquetableMatches.length) { console_log(`[Paso 2.1] Empaquetando ${empaquetableMatches.length} ficheros JavaScript en 1. ${JSON.stringify(empaquetableMatches, null, 2)}`); Object.assign(resultado_final, { packed_files: empaquetableMatches }); const output_dir = salida; const main_file = path.resolve(salida, "main.js"); const main_dir = file_dir; const process_dir = process.cwd(); main_contents = empaquetableMatches.map(file => { last_file = file; const js_code = fs.readFileSync(file).toString(); return this.wrapUmdModuleFunction(`function(require, module, __filename, __dirname) { try { ${js_code} } catch(error) { console.error('Hubo errores al cargar el fichero ' + ${JSON.stringify(file)} + ':', error); throw error; } }, ${JSON.stringify(file)}`, file); }).join("\n\n"); main_contents += "\n" + this.wrapUmdModuleFunction(`function(require, module, __filename, __dirname) { try { ${first_file_original.js_code} } catch(error) { console.error('Hubo errores al cargar el fichero ' + ${JSON.stringify(first_file_original.file)} + ':', error); throw error; } }, ${JSON.stringify(first_file_original.file)}`, first_file_original.file, { output_dir, main_file, main_dir, process_dir, }); console_log("Empaquetación en: " + main_file); fs.writeFileSync(main_file, main_contents, "utf8"); console_log("[Paso 2.2] ¡Empaquetación en 1 JavaScript exitosa! Ver: " + main_file); } else { console_log("[Paso 2.1] No se encontraron empaquetables asociados."); main_contents = first_file.js_code; } } catch (error) { console_log("Hubo errores en el proceso de empaquetación de Castelog a 1 fichero JavaScript:", error); throw error; } try { last_file = first_file.file; const html5izableMatches = this.getIndexesOf(first_file.js_code, token_html5izable).map(ind => { const substr_1 = first_file.js_code.substr(ind + token_html5izable.length); const next_line_pos_1_ = substr_1.indexOf("\n"); const next_line_pos_1 = (next_line_pos_1_ === -1) ? substr_1.length : next_line_pos_1_; const app_metadata_json = substr_1.substr(0, next_line_pos_1).trim(); const html5izable_item = JSON.parse(app_metadata_json); return html5izable_item; }); if (html5izableMatches.length) { console_log("[Paso 3.1] Compilando aplicación HTML5..."); const app = html5izableMatches[0]; const { nombre, version, autor, prefijo = false, sufijo = false } = app; const { head, body } = app.contenido; const html5file = path.resolve(salida, `${prefijo ? (prefijo + ".") : ""}${nombre}.${version}${sufijo ? ("." + sufijo) : ""}.html`); Object.assign(resultado_final, { html5_app: { app, file: html5file } }); const html5contents = `<!DOCTYPE html><html>${head}${ body.trim() .replace(/\<[\t\r\n ]*\/[\t\r\n ]*body[\t\r\n ]*\>[\t\r\n ]*$/g, "") }<script>${ main_contents .replace(/\<script/g, "&gt;script") .replace(/\<\/script/g, "&gt;/script") }</script></body></html>`; fs.writeFileSync(html5file, html5contents, "utf8"); console_log("[Paso 3.2] ¡Compilación en HTML5 exitosa! Ver: " + html5file); } else { console_log("[Paso 3.1] No se encontró app HTML5 asociada."); } } catch (error) { console_log("Hubo errores en el proceso de compilación a app HTML5:", error); error.castelog_api_last_file = last_file; throw error; } console.log("La compilación tomó " + (((new Date()) - starting_moment) / 1000) + " segundos.") return {}; } catch (error) { console_log("Error compilando ficheros Castelog a JavaScript:", error); error.castelog_api_last_file = last_file; throw error; } } static executeCalox(args) { let command = ""; let indexArgs = -1; IteraComando: for(let index = 0; index < args._.length; index++) { indexArgs = index + 2; const arg = args._[index]; if(arg === "instalar") { if(args._[index+1] === "sintaxis") { command = "instalar sintaxis"; break IteraComando; } } else if (arg === "desinstalar") { if (args._[index + 1] === "sintaxis") { command = "desinstalar sintaxis"; break IteraComando; } } else if (arg === "listar") { if (args._[index + 1] === "sintaxis") { command = "listar sintaxis"; break IteraComando; } } else if (arg === "iniciar") { if (args._[index + 1] === "proyecto") { command = "iniciar proyecto"; break IteraComando; } } else if (arg === "compilar") { command = "compilar"; break IteraComando; } } const positionals = args._.slice(indexArgs); if(command === "instalar sintaxis") { return this.installSyntax(args, positionals); } else if (command === "desinstalar sintaxis") { return this.uninstallSyntax(args, positionals); } else if (command === "listar sintaxis") { return this.listSyntax(args, positionals); } else if (command === "iniciar proyecto") { return this.initiateProject(args, positionals); } else if (command === "compilar") { return this.compileLanguage(args, positionals); } else { return this.help_for_calox_cli(); } } static installSyntax(args, positionals) { try { const fs = require("fs"); const path = require("path"); console.log("[CALOX] Instalando sintaxis..."); console.log(positionals); if(positionals.length === 0) { throw new Error("Required argument «positionals» to have 1 or more items in order to «Castelog_compiler.installSyntax»"); } const [ directorioSintaxis ] = positionals; const directorioDeOrigen = path.resolve(directorioSintaxis); const directorioDeModulos = this.getDefaultParserExtensionsDirectory(); const directorioDeDestino = path.join(directorioDeModulos, path.basename(directorioDeOrigen)); try { fs.mkdirSync(directorioDeDestino); } catch(error) { } console.log("[CALOX] Comprobando formato de extensión de Castelog contra directorio de origen:"); console.log("[CALOX] " + directorioDeOrigen); const rutaDeSintaxis = path.join(directorioDeOrigen, "sintaxis.calox"); if (!fs.lstatSync(rutaDeSintaxis).isFile() ) { throw new Error("Required file «" + rutaDeSintaxis + "» to exist in order to «Castelog_compiler.installSyntax»") } const contenidoDeSintaxis = fs.readFileSync(rutaDeSintaxis).toString(); const caloxParser = this.getCaloxParser(); try { caloxParser.parse(contenidoDeSintaxis); } catch(error) { console.log("[CALOX] Hubo errores al interpretar el código fuente de la nueva sintaxis en: " + rutaDeSintaxis); console.log(error); throw error; } console.log("[CALOX] Instalando sintaxis en carpeta:"); console.log("[CALOX] " + directorioDeDestino); const syntaxFiles = fs.readdirSync(directorioDeOrigen); for(let index = 0; index < syntaxFiles.length; index++) { const syntaxFile = syntaxFiles[index]; const ficheroOrigen = path.join(directorioDeOrigen, syntaxFile); const ficheroDestino = path.join(directorioDeDestino, syntaxFile); const errores = this.copyAllFileContents([{ src: ficheroOrigen, dst: ficheroDestino }]); if(errores.length) { throw new Error("[CALOX] Hubo errores copiando fichero «" + ficheroOrigen + "» a «" + ficheroDestino + "»"); } } console.log("[CALOX] Sintaxis instalada exitosamente."); } catch(error) { console.log("[CALOX] Hubo errores al instalar sintaxis:"); console.log(error); throw error; } } static uninstallSyntax(args, positionals) { try { const fs = require("fs"); const path = require("path"); console.log("[CALOX] Desinstalando sintaxis..."); if (positionals.length === 0) { throw new Error("Required argument «positionals» to have 1 or more items in order to «Castelog_compiler.installSyntax»"); } const [nombreDeSintaxis] = positionals; console.log("[CALOX] Desinstalando sintaxis: " + nombreDeSintaxis); const directorioDeModulos = this.getDefaultParserExtensionsDirectory(); const directorioDeDestino = path.join(directorioDeModulos, nombreDeSintaxis); if (!fs.lstatSync(directorioDeDestino).isDirectory()) { console.log("[CALOX] La sintaxis a desinstalar no fue encontrada."); return false; } fs.rmdirSync(directorioDeDestino, { recursive: true }); // @TODO... console.log("[CALOX] Sintaxis desinstalada exitosamente."); } catch(error) { console.log("[CALOX] Hubo errores al desinstalar sintaxis:"); console.log(error); throw error; } } static listSyntax(args, positionals) { try { const fs = require("fs"); const path = require("path"); console.log("[CALOX] Sintaxis instaladas:"); const directorioDeModulos = this.getDefaultParserExtensionsDirectory(); const directorioDeProyecto = path.dirname(directorioDeModulos); const sintaxisInstaladas = fs.readdirSync(directorioDeModulos).filter(f => f !== ".source"); for(let index = 0; index < sintaxisInstaladas.length; index++) { const sintaxisInstalada = sintaxisInstaladas[index]; console.log("[CALOX] · " + sintaxisInstalada); } } catch(error) { console.log("[CALOX] Hubo errores al listar sintaxis:"); console.log(error); throw error; } } static compileLanguage(args, positionals) { let ultimo_fichero = undefined; try { const fs = require("fs"); const path = require("path"); const pegjs = require("pegjs"); // 1. Conseguir el parser de calox: const directorioDeModulos = this.getDefaultParserExtensionsDirectory(); const directorioDeSource = path.join(directorioDeModulos, ".source"); const directorioDeProyecto = path.dirname(directorioDeModulos); const caloxParser = this.getCaloxParser(); console.log("[CALOX] Compilando lenguaje..."); // 2. Conseguir las gramáticas: const ficherosDeModulos = fs.readdirSync(directorioDeModulos); let gramaticas = []; IterandoModulos: for(let index = 0; index < ficherosDeModulos.length; index++) { const fichero = ficherosDeModulos[index]; if(fichero === ".source") continue IterandoModulos; ultimo_fichero = fichero; const contenido = fs.readFileSync(path.resolve(directorioDeModulos, fichero, "sintaxis.calox")).toString(); const grupoDeGramaticas = caloxParser.parse(contenido); gramaticas = gramaticas.concat(grupoDeGramaticas.map(g => { g.original_source = fichero; return g; })); } // 3. Conseguir el nuevo parser de calo: const castelogSource = this.getDefaultCastelogParserSourceCode(); let extendedSource = castelogSource; const mountToken = (hook_id, tab = 2) => { return `\n${" ".repeat(tab)}// @~{ Hooks del Parser de Castelog: ${hook_id} }~@`; }; for(let index = 0; index < gramaticas.length; index++) { const gramatica = gramaticas[index]; const { hook_id, syntax_name, syntax_content, syntax_prescript } = gramatica; console.log(gramatica); const hook_id_uppercase = hook_id.toUpperCase(); const hook_token = mountToken(hook_id_uppercase); let wasReplaced = false; if (hook_id_uppercase === "GENERATIVA PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "GENERATIVA") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "SENTENCIA PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "SENTENCIA") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "APÉNDICE PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "APÉNDICE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "PREPÉNDICE PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "PREPÉNDICE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "APÉNDICE NEGABLE PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "APÉNDICE NEGABLE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "COMENTARIO") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "COMENTARIO PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "SENTENCIA COMPLETA") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else if (hook_id_uppercase === "SENTENCIA COMPLETA PREFERENTE") { extendedSource = extendedSource.replace(hook_token, () => { wasReplaced = true; return "\n / " + syntax_name + hook_token; }); } else { throw new Error("Required parameter «tipo» or «hook_id» to be a valid string on syntax «" + syntax_name + "» in order to «Castelog_compiler.compileLanguage»") } if(!wasReplaced) { throw new Error("Required parameter «tipo» or «hook_id» to appear on parser source code on syntax «" + syntax_name + "» in order to «Castelog_compiler.compileLanguage»"); } if(syntax_content) { const tokenDeSintaxis = `\n// @~{ Hooks del Parser de Castelog: CONTENIDOS DE SINTAXIS }~@`; extendedSource = extendedSource.replace(tokenDeSintaxis, syntax_content + tokenDeSintaxis); } if(syntax_prescript) { const tokenDePrescript = `\n // @~{ Hooks del Parser de Castelog: CONTENIDOS DE PRESCRIPT }~@`; extendedSource = extendedSource.replace(tokenDePrescript, syntax_prescript + tokenDePrescript); } } let parser_source = undefined; try { parser_source = pegjs.generate(extendedSource, Object.assign({}, { format: "umd", exportVar: "Castelog_parser", output: "source", })); } catch (error) { console.log("Error compilando parser con PEGjs: "); console.log(error); throw error; } // 4. Persistir cambios const ficheroCastelogExtendidoPegjs = path.join(directorioDeSource, "castelog.extendido.pegjs"); fs.writeFileSync(ficheroCastelogExtendidoPegjs, extendedSource, "utf8"); const ficheroCastelogExtendidoJs = path.join(directorioDeSource, "castelog.js"); fs.writeFileSync(ficheroCastelogExtendidoJs, parser_source, "utf8"); // 5. OK. console.log(`[CALOX] Castelog fue compilado exitosamente con ${gramaticas.length} gramáticas.`); console.log(`[CALOX] Puedes ejecutar la nueva instancia de Castelog en:`); console.log(`[CALOX] ${path.resolve(directorioDeProyecto, "calo")}`); } catch (error) { console.log("[CALOX] Hubo errores al compilar sintaxis con fichero: " + ultimo_fichero); console.log(error); throw error; } } static copyAllFileContents(files) { const fs = require("fs"); const path = require("path"); const errors = []; for(let index = 0; index < files.length; index++) { const file = files[index]; const { src, dst } = file; const srcSolved = path.resolve(src); const dstSolved = path.resolve(dst); try { const srcContents = fs.readFileSync(srcSolved).toString(); fs.writeFileSync(dstSolved, srcContents, "utf8"); } catch(error) { errors.push(error); } console.log("[CALOX] Copiado fichero «" + path.basename(srcSolved) + "» a «" + path.basename(dstSolved) + "»") } return errors; } static initiateProject(args, positionals) { try { console.log("[CALOX] Iniciar proyecto..."); const fs = require("fs"); const path = require("path"); const currentDirectory = __dirname; console.log(args, positionals); if(positionals.length === 0) { throw new Error("Required positional argument «positionals» to be an array of 1 item in order to «Castelog_compiler.initiateProject»") } const [ directorio ] = positionals; const directorioAbsoluto = path.resolve(directorio); console.log("[CALOX] Iniciando proyecto en:"); console.log("[CALOX] " + directorioAbsoluto); try {fs.mkdirSync(directorioAbsoluto);} catch(error) {} if(!fs.lstatSync(directorioAbsoluto).isDirectory()) { throw new Error("Required to create directory «./» in project in order to «Castelog_compiler.initiateProject»"); } const directorioModulos = path.resolve(directorio, "calo_modules"); try {fs.mkdirSync(directorioModulos);} catch(error) {} if(!fs.lstatSync(directorioModulos).isDirectory()) { throw new Error("Required to create directory «./calo_modules» in project root in order to «Castelog_compiler.initiateProject»"); } const directorioSource = path.resolve(directorio, "calo_modules/.source"); try { fs.mkdirSync(directorioSource); } catch (error) { } if (!fs.lstatSync(directorioSource).isDirectory()) { throw new Error("Required to create directory «./calo_modules/.source» in project root in order to «Castelog_compiler.initiateProject»"); } console.log("[CALOX] Creada carpeta «calo_modules» para proyecto."); const errores = this.copyAllFileContents([{ src: path.resolve(currentDirectory, "castelog.bin.js"), dst: path.resolve(directorioSource, "castelog.bin.js") }, { src: path.resolve(currentDirectory, "castelog.api.js"), dst: path.resolve(directorioSource, "castelog.api.js") }, { src: path.resolve(currentDirectory, "castelog.pegjs"), dst: path.resolve(directorioSource, "castelog.pegjs") }, { src: path.resolve(currentDirectory, "castelog.js"), dst: path.resolve(directorioSource, "castelog.js") }, { src: path.resolve(currentDirectory, "castelog-xtensions.js"), dst: path.resolve(directorioSource, "castelog-xtensions.js") }, { src: path.resolve(currentDirectory, "castelog-xtensions.bin.js"), dst: path.resolve(directorioSource, "castelog-xtensions.bin.js") }, { src: path.resolve(currentDirectory, "castelog-xtensions.pegjs"), dst: path.resolve(directorioSource, "castelog-xtensions.pegjs") }]); if(errores.length) { console.log(errores); throw new Error("[CALOX] Hubo errores copiando ficheros y el proceso se interrumpirá aquí"); } console.log("[CALOX] Creados ficheros de Castelog-Xtensions en la carpeta «calo_modules» del proyecto."); try { fs.unlinkSync(path.resolve(directorioAbsoluto, "calo")); } catch (error) { } try { fs.unlinkSync(path.resolve(directorioAbsoluto, "calox")); } catch (error) { } fs.symlinkSync( path.resolve(directorioSource, "castelog.bin.js"), path.resolve(directorioAbsoluto, "calo"), ); fs.symlinkSync( path.resolve(directorioSource, "castelog-xtensions.bin.js"), path.resolve(directorioAbsoluto, "calox"), ); const caloxJsonPath = path.resolve(directorioAbsoluto, "calox.json"); const DEFAULT_CALOX_JSON_CONTENTS = { proyecto: path.basename(directorioAbsoluto), autor: "allnulled", version: "1.0.0", gramaticas: [], detalles: { ultima_compilacion: null } }; try { fs.readFileSync(caloxJsonPath, "utf8"); } catch(error) { fs.writeFileSync(caloxJsonPath, JSON.stringify(DEFAULT_CALOX_JSON_CONTENTS)); fs.readFileSync(caloxJsonPath, "utf8"); } require("child_process").execSync("npm init -y", { cwd: directorioAbsoluto }); console.log("[CALOX] Iniciado como proyecto npm."); console.log("[CALOX] Disponibles los ejecutable en:"); console.log("[CALOX] ./calo"); console.log("[CALOX] ./calox"); console.log("[CALOX] Directorio raíz:"); console.log("[CALOX] " + directorioAbsoluto); console.log("[CALOX] Proyecto iniciado exitosamente."); } catch (error) { console.log("[CALOX] Hubo errores al iniciar proyecto:"); console.log(error); throw error; } } static getPackageVersion() { try { return require(__dirname + "/../package.json").version; } catch (error) { try { return require(__dirname + "/../../package.json").version; } catch (error) { try { return require(__dirname + "/package.json").version; } catch (error) { return "unknown"; } } } } static help_for_calox_cli() { const packageVersion = this.getPackageVersion(); console.log(" Bienvenido a la ayuda de Castelog-Xtensions v0.0.1"); console.log(" Versión de proyecto: " + packageVersion + ""); console.log(" Uso desde línea de comandos:"); console.log(" [ Iniciar proyecto: ]"); console.log(" ~$ calox iniciar proyecto ."); console.log(" [ Listar sintaxis: ]"); console.log(" ~$ calox listar sintaxis"); console.log(" [ Instalar sintaxis: ]"); console.log(" ~$ calox instalar sintaxis './sintaxis-x.calox'"); console.log(" [ Desinstalar sintaxis: ]"); console.log(" ~$ calox desinstalar sintaxis 'Sintaxis-x'"); console.log(" [ Compilar binarios: ]"); console.log(" ~$ calox compilar"); return; } static help_for_cli() { const packageVersion = this.getPackageVersion(); console.log(" Bienvenido a la ayuda de Castelog v0.0.1"); console.log(" Versión de proyecto: " + packageVersion + ""); console.log(" Uso desde línea de comandos:"); console.log(" ~$ calo 1.calo 2.calo 3.calo { opciones }"); console.log(" Opciones:"); console.log(" [ Opción: ] --ejecutar | -e"); console.log(" [ Ejemplo: ] calo 1.calo 2.calo --ejecutar"); console.log(" [ Descripción: ] Correría 1.calo tras la compilación."); return; } } Castelog_compiler.default = Castelog_compiler; module.exports = Castelog_compiler;