minangscript
Version:
Modern programming language with Minangkabau philosophy. Features native arrays (kumpulan), objects (benda), web development support, and comprehensive algorithm examples. Ready for web applications, data structures, and algorithmic programming.
663 lines (553 loc) ⢠21.3 kB
JavaScript
const { MinangCompiler } = require('./src/compiler/MinangCompiler');
const { MinangRuntime } = require('./src/runtime/MinangRuntime');
const { MinangLexer } = require('./src/lexer/MinangLexer');
const { MinangUtils } = require('./src/utils/MinangUtils');
const { MinangI18n } = require('./src/utils/i18n');
const { MinangConfig } = require('./src/utils/config');
const { MinangTestFramework } = require('./src/testing/MinangTestFramework');
const { MinangPaket } = require('./src/package-manager/MinangPaket');
const { EnhancedMinangPaketCLI } = require('./src/package-manager/EnhancedMinangPaketCLI');
const fs = require('fs');
const path = require('path');
class MinangScript {
constructor() {
this.compiler = new MinangCompiler();
this.runtime = new MinangRuntime();
this.lexer = new MinangLexer();
this.i18n = new MinangI18n();
}
// Main entry point for MinangScript CLI
run(filePath) {
try {
console.log(this.i18n.t('welcome'));
if (!fs.existsSync(filePath)) {
console.error(this.i18n.t('fileNotFound', filePath));
process.exit(1);
}
const sourceCode = fs.readFileSync(filePath, 'utf8');
const compiled = this.compiler.compile(sourceCode);
this.runtime.execute(compiled);
} catch (error) {
console.error(this.i18n.t('error', error.message));
process.exit(1);
}
}
// Build MinangScript to JavaScript
build(inputPath, outputPath) {
try {
console.log(this.i18n.t('building'));
const sourceCode = fs.readFileSync(inputPath, 'utf8');
const jsCode = this.compiler.transpile(sourceCode);
fs.writeFileSync(outputPath, jsCode);
console.log(this.i18n.t('buildSuccess', outputPath));
} catch (error) {
console.error(this.i18n.t('buildFailed', error.message));
process.exit(1);
}
}
// Create new MinangScript project
createProject(projectName) {
const projectDir = path.join(process.cwd(), projectName);
if (!fs.existsSync(projectDir)) {
fs.mkdirSync(projectDir, { recursive: true });
}
// Create sample MinangScript file with updated keywords
const sampleCode = `// Selamat datang di MinangScript!
// File ini menggunakan filosofi Minangkabau
cetak "Salamat datang ka " + "${projectName}"
// Contoh variabel
buek namo = "MinangScript"
ambiak versi = "1.0.1"
tagak filosofi = "Gotong Royong"
// Contoh fungsi dengan nilai gotong royong
karojo sambutan(nama) {
jadi "Salamat datang, " + nama + "! Mari bergotong royong."
}
cetak sambutan(namo)
`;
fs.writeFileSync(path.join(projectDir, 'main.minang'), sampleCode);
console.log(this.i18n.t('projectCreated', projectName));
console.log(this.i18n.t('enterDirectory', projectName));
console.log(this.i18n.t('runProject'));
}
// Interactive REPL
repl() {
console.log(this.i18n.t('replWelcome'));
console.log(this.i18n.t('replInstructions'));
console.log(this.i18n.t('replHelp'));
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'minang> '
});
rl.prompt();
rl.on('line', (input) => {
const trimmed = input.trim();
if (trimmed === '.exit') {
console.log(this.i18n.t('goodbye'));
rl.close();
return;
}
if (trimmed === '.help') {
this.showReplHelp();
rl.prompt();
return;
}
if (trimmed === '.examples') {
this.showExamples();
rl.prompt();
return;
}
if (trimmed.startsWith('.analyze ')) {
const code = trimmed.substring(9);
this.analyzeCode(code);
rl.prompt();
return;
}
if (trimmed === '') {
rl.prompt();
return;
}
try {
const compiled = this.compiler.compile(trimmed);
this.runtime.execute(compiled);
} catch (error) {
console.error('Error:', error.message);
}
rl.prompt();
});
rl.on('close', () => {
console.log('\n' + this.i18n.t('goodbye'));
process.exit(0);
});
}
showReplHelp() {
const lang = this.i18n.getCurrentLanguage();
console.log(`
${this.i18n.t('replHelpTitle')}
${this.i18n.t('replCommands')}
.help - ${this.i18n.t('helpCommand')}
.exit - ${this.i18n.t('exitCommand')}
.examples - ${this.i18n.t('examplesCommand')}
.analyze <code> - ${this.i18n.t('analyzeCommand')}
${this.i18n.t('replExamples')}
buek nama = "Minang"
cetak "Hello " + nama
karojo tambah(a, b) {
jadi a + b
}
kalau 5 > 3 {
cetak "${lang === 'id' ? 'Lima lebih besar' : 'Five is greater'}"
}
${this.i18n.t('replCulturalFunctions')}
cetak "Salamat datang ka MinangScript!"
cetak "Program sederhana untuk demonstrasi"
buek nama = "Dunia"
cetak "Hello " + nama
`);
}
showExamples() {
const lang = this.i18n.getCurrentLanguage();
console.log(`
š MinangScript Examples:
${lang === 'id' ? 'Deklarasi Variabel:' : 'Variable Declaration:'}
buek nama = "Siti" // var
ambiak umur = 25 // let
tagak PI = 3.14 // const
${lang === 'id' ? 'Fungsi:' : 'Functions:'}
karojo salam(nama) {
jadi "Salamat datang " + nama
}
${lang === 'id' ? 'Kondisi:' : 'Conditionals:'}
kalau umur >= 18 {
cetak "${lang === 'id' ? 'Dewasa' : 'Adult'}"
} lain {
cetak "${lang === 'id' ? 'Muda' : 'Young'}"
}
Loop:
selamo i < 5 {
cetak "Iterasi ke-" + i
i = i + 1
}
Console Methods:
cetak "Output normal"
cetak.pesan "Info message"
cetak.peringatan "Warning"
cetak.rusak "Error message"
Cultural Programming:
cetak "Program MinangScript sederhana"
buek hasil = 10 + 20
cetak "Hasil perhitungan: " + hasil
`);
}
// Analyze code structure
analyzeCode(code) {
try {
console.log('\nš Analisis Kode:');
// Tokenize
const tokens = this.lexer.tokenize(code);
console.log(`š Tokens: ${tokens.length - 1} (excluding EOF)`);
// Parse
const ast = this.compiler.compile(code);
console.log(`š³ AST Nodes: ${this.countASTNodes(ast)}`);
// Cultural analysis
const cultural = MinangUtils.validateCulturalPrinciples(ast);
if (cultural.length > 0) {
console.log('šļø Saran Budaya:');
cultural.forEach(suggestion => {
console.log(` ⢠${suggestion}`);
});
} else {
console.log('ā
Prinsip budaya terintegrasi dengan baik');
}
} catch (error) {
console.error('ā Analisis gagal:', error.message);
}
}
countASTNodes(node) {
if (!node || typeof node !== 'object') return 0;
let count = 1;
for (const key in node) {
const value = node[key];
if (Array.isArray(value)) {
count += value.reduce((sum, item) => sum + this.countASTNodes(item), 0);
} else if (typeof value === 'object') {
count += this.countASTNodes(value);
}
}
return count;
}
// Validate MinangScript file
validate(filePath) {
if (!fs.existsSync(filePath)) {
console.error(this.i18n.t('fileNotFound', filePath));
process.exit(1);
}
console.log(`š ${this.i18n.getCurrentLanguage() === 'id' ? 'Memvalidasi' : 'Validating'}: ${filePath}`);
try {
const code = fs.readFileSync(filePath, 'utf8');
// Check syntax
this.compiler.compile(code);
console.log(this.i18n.getCurrentLanguage() === 'id' ? 'ā
Sintaks valid' : 'ā
Syntax valid');
// Cultural validation
const cultural = MinangUtils.validateCulturalPrinciples(code);
if (cultural.length > 0) {
console.log(this.i18n.getCurrentLanguage() === 'id' ? 'šļø Saran budaya:' : 'šļø Cultural suggestions:');
cultural.forEach(suggestion => {
console.log(` ⢠${suggestion}`);
});
} else {
console.log(this.i18n.getCurrentLanguage() === 'id' ?
'ā
Prinsip budaya terintegrasi dengan baik' :
'ā
Cultural principles well integrated');
}
// Test transpilation
this.compiler.transpile(code);
console.log(this.i18n.getCurrentLanguage() === 'id' ?
'ā
Transpilasi berhasil' :
'ā
Transpilation successful');
console.log(this.i18n.getCurrentLanguage() === 'id' ?
'š Validasi file selesai' :
'š File validation complete');
} catch (error) {
console.error(this.i18n.t('validationFailed', error.message));
process.exit(1);
}
}
// Format MinangScript code
format(filePath) {
if (!fs.existsSync(filePath)) {
console.error(this.i18n.t('fileNotFound', filePath));
process.exit(1);
}
const code = fs.readFileSync(filePath, 'utf8');
const formatted = MinangUtils.formatCode(code);
console.log(this.i18n.getCurrentLanguage() === 'id' ?
'š Kode yang diformat:' :
'š Formatted code:');
console.log(formatted);
// Option to save formatted code
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Simpan kode yang diformat? (y/N): ', (answer) => {
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
fs.writeFileSync(filePath, formatted);
console.log('ā
File diformat dan disimpan');
}
rl.close();
});
}
// Generate template code
template(type, outputPath) {
const templates = {
'basic': MinangUtils.generateTemplate('basic'),
'simple': MinangUtils.generateTemplate('basic'),
'function': MinangUtils.generateTemplate('basic'),
'web-app': MinangUtils.generateTemplate('web-app'),
'api-client': MinangUtils.generateTemplate('api-client'),
'interactive': MinangUtils.generateTemplate('interactive'),
'form-handler': MinangUtils.generateTemplate('form-handler')
};
if (!templates[type]) {
console.error(`Template type not recognized: ${type}`);
console.log('Template yang tersedia:', Object.keys(templates).join(', '));
process.exit(1);
}
const code = templates[type];
if (outputPath) {
fs.writeFileSync(outputPath, code);
console.log(`ā
Template dibuat: ${outputPath}`);
} else {
console.log(code);
}
}
// Show version information
version() {
const packageJson = require('./package.json');
console.log(`
šļø MinangScript v${packageJson.version}
${packageJson.description}
Pengarang: ${packageJson.author}
Lisensi: ${packageJson.license}
Prinsip Budaya Minangkabau:
š¤ Gotong Royong - Kerja sama dan tolong-menolong
š£ļø Musyawarah Mufakat - Pengambilan keputusan bersama
šæ Alam Takambang Jadi Guru - Alam sebagai guru
āļø Adat Basandi Syarak - Adat berdasarkan syariat
Runtime: Node.js ${process.version}
Platform: ${process.platform} ${process.arch}
GitHub: https://github.com/DityaPerdana/minangScript
NPM: https://www.npmjs.com/package/minangscript
`);
}
}
// Export for use as a module
module.exports = { MinangScript };
// CLI usage when run directly
if (require.main === module) {
const args = process.argv.slice(2);
const minang = new MinangScript();
if (args.length === 0) {
console.log(`
šļø MinangScript v1.0.1
Bahasa pemrograman dengan filosofi Minangkabau
Penggunaan:
minang run <file.minang> - Jalankan file MinangScript
minang build <input> <output> - Bangun ke JavaScript
minang new <project> - Buat proyek baru
minang repl - Mode interaktif REPL
minang validate <file.minang> - Validasi file MinangScript
minang format <file.minang> - Format kode MinangScript
minang template <type> [file] - Generate template kode
minang version - Informasi versi
minang help - Tampilkan bantuan
Template yang tersedia:
basic, simple, function, web-app, api-client, interactive, form-handler
Contoh:
minang new myproject
minang install minang-ui
minang run main.minang
minang repl
minang template basic hello.minang
š¦ NPM: npm install -g minangscript
šļø "Alam Takambang Jadi Guru" - Belajar dari alam
`);
process.exit(0);
}
const command = args[0];
switch (command) {
case 'run':
if (args[1]) {
minang.run(args[1]);
} else {
console.error('ā Harap berikan nama file untuk dijalankan');
console.log('Contoh: minang run main.minang');
process.exit(1);
}
break;
case 'build':
if (args[1] && args[2]) {
minang.build(args[1], args[2]);
} else {
console.error(minang.i18n.t('provideFile'));
console.log(minang.i18n.t('example', 'minang build app.minang app.js'));
process.exit(1);
}
break;
case 'new':
if (args[1]) {
minang.createProject(args[1]);
} else {
console.error(minang.i18n.t('provideFile'));
console.log(minang.i18n.t('example', 'minang new myproject'));
process.exit(1);
}
break;
// Package Manager Commands
case 'install':
if (args[1]) {
const installCLI = new EnhancedMinangPaketCLI();
installCLI.handleInstall([args[1]]);
} else {
console.error('Please specify a package name');
console.log('Example: minang install minang-ui');
process.exit(1);
}
break;
case 'uninstall':
case 'remove':
if (args[1]) {
const uninstallCLI = new EnhancedMinangPaketCLI();
uninstallCLI.handleUninstall([args[1]]);
} else {
console.error('Please specify a package name');
console.log('Example: minang uninstall minang-ui');
process.exit(1);
}
break;
case 'list':
const listCLI = new EnhancedMinangPaketCLI();
listCLI.handleList([]);
break;
case 'search':
if (args[1]) {
const searchCLI = new EnhancedMinangPaketCLI();
searchCLI.handleSearch([args[1]]);
} else {
console.error('ā Please specify a search query');
console.log('Example: minang search ui');
process.exit(1);
}
break;
case 'update':
const updateCLI = new EnhancedMinangPaketCLI();
if (args[1]) {
updateCLI.handleUpdate([args[1]]);
} else {
updateCLI.handleUpdate([]);
}
break;
case 'publish':
const publishCLI = new EnhancedMinangPaketCLI();
publishCLI.handlePublish([]);
break;
case 'init':
const initCLI = new EnhancedMinangPaketCLI();
if (args[1]) {
initCLI.handleInit([args[1]]);
} else {
initCLI.handleInit([]);
}
break;
case 'repl':
minang.repl();
break;
case 'validate':
if (args[1]) {
minang.validate(args[1]);
} else {
console.error(minang.i18n.t('provideFile'));
console.log(minang.i18n.t('example', 'minang validate main.minang'));
process.exit(1);
}
break;
case 'format':
if (args[1]) {
minang.format(args[1]);
} else {
console.error(minang.i18n.t('provideFile'));
console.log(minang.i18n.t('example', 'minang format main.minang'));
process.exit(1);
}
break;
case 'template':
if (args[1]) {
minang.template(args[1], args[2]);
} else {
console.error(minang.i18n.t('provideFile'));
console.log(minang.i18n.t('example', 'minang template basic hello.minang'));
console.log('Template: basic, simple, function, web-app, api-client, interactive, form-handler');
process.exit(1);
}
break;
case 'version':
minang.version();
break;
case 'lang':
case 'language':
if (args[1]) {
if (minang.i18n.setLanguage(args[1])) {
console.log(minang.i18n.t('languageChanged'));
if (args[1] === 'en') {
console.log(minang.i18n.t('switchToIndonesian'));
} else if (args[1] === 'id') {
console.log(minang.i18n.t('switchToEnglish'));
} else if (args[1] === 'auto') {
console.log('š Auto-detection enabled. Language will be detected automatically.');
}
} else {
console.error('ā Language not supported. Available: en, id, auto');
}
} else {
minang.i18n.showLanguageHelp();
}
break;
case 'help':
console.log(`
${minang.i18n.t('helpTitle')}
${minang.i18n.t('helpAvailable')}
${minang.i18n.t('projectManagement')}
new <project> - ${minang.i18n.t('newProject')}
init <n> - Initialize new package / Inisialisasi paket baru
template <type> - ${minang.i18n.t('template')}
${minang.i18n.t('execution')}
run <file> - ${minang.i18n.t('runFile')}
build <in> <out> - ${minang.i18n.t('buildFile')}
repl - ${minang.i18n.t('repl')}
š¦ Package Management:
install <pkg> - Install package / Pasang paket
uninstall <pkg> - Remove package / Hapus paket
list - List installed packages / Daftar paket terpasang
search <query> - Search packages / Cari paket
update [pkg] - Update packages / Perbarui paket
publish - Publish package / Terbitkan paket
${minang.i18n.t('devTools')}
validate <file> - ${minang.i18n.t('validate')}
format <file> - ${minang.i18n.t('format')}
version - ${minang.i18n.t('version')}
lang <en|id> - Change language / Ganti bahasa
${minang.i18n.t('templates')}
basic - ${minang.i18n.t('templateBasic')}
basic - ${minang.i18n.t('templateBasic')}
simple - Simple MinangScript program
function - Function-based program template
web-app - Web application with DOM manipulation
api-client - REST API client application
interactive - Interactive web components
form-handler - Form handling and validation
${minang.i18n.t('examples')}
minang new nagari-digital
minang install minang-ui
minang template web-app my-app.minang
minang run team.minang
minang repl
minang lang en
${minang.i18n.t('philosophy')}
${minang.i18n.t('philosophyQuote')}
${minang.i18n.t('philosophyDesc')}
š¦ Installation: npm install -g minangscript
šļø Repository: https://github.com/DityaPerdana/minangScript
`);
break;
default:
console.error(minang.i18n.t('unknownCommand', command));
console.log(minang.i18n.t('useHelp'));
console.log(minang.i18n.t('useHelpShort'));
process.exit(1);
}
}