janofidel 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eyuel Getachew(EyuReaper)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+
2
+ ---
3
+ # ጃኖ ፊደል (Jano Fidel) ![ጃኖ ፊደል (Jano Fidel)](assets/favicon.ico)
4
+
5
+
6
+ **A Native Amharic Programming Language built on Node.js.**
7
+
8
+ ጃኖ ፊደል (Jano Fidel) is a high-level programming language that allows developers to write full-scale applications using the Ethiopic (Ge'ez) script. It transpiles directly to JavaScript, giving you the power of the Node.js ecosystem with a completely native writing experience.
9
+
10
+ ## ✨ ዋና ዋና ባህሪያት (Features)
11
+
12
+ * **Native Keywords**: Use `ይሁን` (let), `ተግባር` (function), and `ከሆነ` (if) instead of English equivalents.
13
+ * **Ethiopic Numerals**: Full support for Ge'ez numbers (፩, ፪, ፲፪...) with a built-in conversion engine.
14
+ * **Amharic Built-ins**: Native aliases for common objects like `ሒሳብ` (Math), `ቀን` (Date), and `ያትም` (console.log).
15
+ * **Asynchronous Support**: Full `ጊዜጠባቂ` (async) and `ጠብቅ` (await) support for modern development.
16
+ * **CLI Tool**: Run your code globally with the `jano` command.
17
+
18
+ ---
19
+ ![ጃኖ ፊደል (Jano Fidel)](assets/logo.png)
20
+ ## 🚀 አጀማመር (Quick Start)
21
+
22
+ ### 1. Installation
23
+
24
+ Clone the repository and link it to your global path:
25
+
26
+ ```bash
27
+ cd JanoFidel
28
+ npm install
29
+ sudo npm link
30
+
31
+ ```
32
+
33
+ ### 2. Writing your first Jano file (`ሰላምታ.jf`)
34
+
35
+ ```javascript
36
+ ተግባር ሰላምታ_ስጥ(ስም) {
37
+ መልስ "ሰላም " + ስም + " እንኳን ወደ ጃኖ ፊደል መጣህ!"፤
38
+ }
39
+
40
+ ያትም(ሰላምታ_ስጥ("ዮናስ"))፤
41
+
42
+ // Math with Ge'ez numbers
43
+ ይሁን ውጤት = ፲፪ + ፰፤
44
+ ያትም("፲፪ + ፰ = " + ውጤት)፤
45
+
46
+ ```
47
+
48
+ ### 3. Running the code
49
+
50
+ ```bash
51
+ jano ሰላምታ.jf
52
+
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 📚 የቋንቋው መዝገበ-ቃላት (Dictionary Mapping)
58
+
59
+ | Jano (ጃኖ) | JavaScript Equivalent |
60
+ | --- | --- |
61
+ | `ይሁን` | `let` / `var` |
62
+ | `ቋሚ` | `const` |
63
+ | `ተግባር` | `function` |
64
+ | `መደብ` | `class` |
65
+ | `ከሆነ` | `if` |
66
+ | `ካልሆነ` | `else` |
67
+ | `መልስ` | `return` |
68
+ | `ያትም` | `console.log` |
69
+ | `።` | `.` (Dot operator) |
70
+
71
+ ---
72
+
73
+ ## 🛠️ የቴክኒክ መዋቅር (Architecture)
74
+
75
+ 1. **Lexer**: Scans `.jf` files for Ethiopic characters and tokens.
76
+ 2. **Number Engine**: Converts additive Ethiopic numerals () into Arabic numerals for JavaScript.
77
+ 3. **Prelude**: A standard library injected at runtime to provide prototype aliases (e.g., adding `.ርዝመት` to Arrays).
78
+ 4. **Transpiler**: Maps the tokens to valid JavaScript and executes via the Node.js VM.
79
+
80
+ ---
81
+
82
+ ## 🤝 ማበረታቻ (Contributing)
83
+
84
+ We welcome contributions! If you want to add more keywords to the `dictionary.js` or expand the `prelude.js` standard library, feel free to open a Pull Request.
85
+
86
+ ---
87
+
88
+ ## 📄 ፈቃድ (License)
89
+
90
+ This project is licensed under the **MIT License**.
91
+
92
+ ---
93
+
package/bin/jano.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ const { processFile } = require('../src/engine'); // Assuming processFile handles reading + prelude
3
+ const { runCode } = require('../src/runner');
4
+ const path = require('path');
5
+
6
+ // Branding
7
+ const RED_BG = '\x1b[41m';
8
+ const WHITE_TEXT = '\x1b[37m';
9
+ const BOLD = '\x1b[1m';
10
+ const RESET = '\x1b[0m';
11
+
12
+ const logo = `${RED_BG}${WHITE_TEXT}${BOLD} ጃ ${RESET} ${RED_BG}${WHITE_TEXT}${BOLD} ፊ ${RESET} ${BOLD}ጃኖ ፊደል (Jano Fidel)${RESET}\n`;
13
+
14
+ const fileArg = process.argv[2];
15
+
16
+ // 1. Show Help/Logo if no file provided
17
+ if (!fileArg) {
18
+ console.log(logo);
19
+ console.log("አጠቃቀም: jano <ፋይል_ስም.jf>");
20
+ process.exit(1);
21
+ }
22
+
23
+ // 2. Resolve paths
24
+ const filePath = path.resolve(process.cwd(), fileArg);
25
+
26
+ if (!filePath.endsWith('.jf')) {
27
+ console.error("ስህተት: ፋይሉ በ '.jf' ማለቅ አለበት።");
28
+ process.exit(1);
29
+ }
30
+
31
+ // 3. The Execution Flow
32
+ try {
33
+ // Note: Use your existing processFile which reads the code and adds the prelude
34
+ const jsCode = processFile(filePath);
35
+
36
+ // This calls your professional runner with the styled boxes
37
+ runCode(jsCode, filePath);
38
+
39
+ } catch (err) {
40
+ // This catches high-level file reading errors
41
+ console.error(`\n[የጃኖ ስህተት]: ${err.message}`);
42
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "janofidel",
3
+ "version": "1.0.0",
4
+ "description": "Amharic Programming Language (Jano Fidel)",
5
+ "main": "src/engine.js",
6
+ "bin": {
7
+ "jano": "bin/jano.js"
8
+ },
9
+ "type": "commonjs",
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "engines": {
14
+ "node": ">=16.0.0"
15
+ },
16
+ "scripts": {
17
+ "test": "mocha test/**/*.test.js"
18
+ },
19
+ "keywords": [
20
+ "amharic",
21
+ "ethiopia",
22
+ "ጃኖ",
23
+ "ፊደል",
24
+ "jano",
25
+ "fidel",
26
+ "language",
27
+ "compiler"
28
+ ],
29
+ "author": "EyuReaper",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/EyuReaper/JanoFidel.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/EyuReaper/JanoFidel/issues"
37
+ },
38
+ "homepage": "https://github.com/EyuReaper/JanoFidel#readme",
39
+ "devDependencies": {
40
+ "mocha": "^11.7.5"
41
+ },
42
+ "files": [
43
+ "bin/",
44
+ "src/",
45
+ "README.md",
46
+ "LICENSE.txt"
47
+ ]
48
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * ጃኖ ፊደል (Jano Fidel) - Official Dictionary
3
+ * Mapping Amharic keywords to JavaScript equivalents.
4
+ * Optimized for DX (Developer Experience) and logical flow.
5
+ */
6
+
7
+ const JANO_KEYWORDS = {
8
+ // --- Variables & Constants ---
9
+ 'ተለዋጭ': 'var', // Added: Traditional variable declaration
10
+ 'ይሁን': 'let', // Block-scoped variable
11
+ 'ቋሚ': 'const', // Constant
12
+ 'ይህ': 'this', // Current context reference
13
+
14
+ // --- Functions & Classes ---
15
+ 'ተግባር': 'function',
16
+ 'ግንባታ': 'constructor',
17
+ 'መልስ': 'return',
18
+ 'ተቀባይ' : 'resolve',
19
+ "መደብ": "class",
20
+ 'አዲስ': 'new',
21
+ 'ያራዝማል': 'extends', // Updated: Logical for inheritance
22
+ 'የበላይ': 'super', // Updated: Logical for "the one above"
23
+ 'አስገኝ': 'yield', // Updated: Better DX for generators
24
+ 'ቃልኪዳን': 'Promise',
25
+ 'ቃልኪዳን': 'Promise',
26
+ "ክፍል": "module", // Module
27
+ "ጠይቅ": "require", // Require
28
+ // --- Logic & Flow Control ---
29
+ 'ከሆነ': 'if',
30
+ 'ካልሆነ': 'else',
31
+ 'ምረጥ': 'switch',
32
+ 'ሁኔታ': 'case',
33
+ 'መደበኛ': 'default',
34
+ 'ውጣ': 'break',
35
+ 'ቀጥል': 'continue',
36
+
37
+ // --- Loops & Iteration ---
38
+ 'ለእያንዳንዱ': 'for',
39
+ 'እስከ': 'while',
40
+ 'ውስጥ': 'in',
41
+ "የ": "of",
42
+
43
+ // --- Booleans & Types ---
44
+ 'እውነት': 'true',
45
+ 'ሀሰት': 'false',
46
+ 'ባዶ': 'null',
47
+ 'አይነት': 'typeof',
48
+ 'ምሳሌ': 'instanceof',
49
+
50
+ // --- Exception Handling ---
51
+ 'ሞክር': 'try',
52
+ 'ያዝ': 'catch',
53
+ 'በመጨረሻ': 'finally',
54
+
55
+ // --- Modules & Access Control (Strict/Future Use) ---
56
+ 'የጋራ': 'public', // Updated: Intuitive for shared access
57
+ 'የግል': 'private', // Hidden/Encapsulated
58
+ 'የተጠበቀ': 'protected',
59
+ 'ላክ': 'export',
60
+ 'ውጤት': 'exports',
61
+ 'አምጣ': 'import',
62
+ 'ጠብቅ': 'await',
63
+ 'መገናኛ': 'interface',
64
+ 'ጥቅል': 'package',
65
+ 'የማይንቀሳቀስ': 'static',
66
+ 'ተከተል': 'enum',
67
+
68
+ // --- Punctuation & Operators ---
69
+ '።': '.', // Updated: Now used as the Dot Operator
70
+ '፤': ';', // Statement terminator
71
+ '፡': ':', // Colon
72
+ '፦': ':', // Preface colon
73
+ '፣': ',', // Comma
74
+
75
+ // --- Math / ሒሳብ ---
76
+ 'ሒሳብ': 'Math',
77
+ 'ጣራ': 'ceil',
78
+ 'ወለል': 'floor',
79
+ 'ዘፈቀደ': 'random',
80
+ 'ፍጹም': 'abs',
81
+ 'ኃይል': 'pow',
82
+ 'ሥር': 'sqrt',
83
+
84
+ // --- Numbers ---
85
+ '፟': '0', '፩': '1', '፪': '2', '፫': '3', '፬': '4', '፭': '5',
86
+ '፮': '6', '፯': '7', '፰': '8', '፱': '9', '፲': '10', '፳': '20',
87
+ '፴': '30', '፵': '40', '፶': '50', '፷': '60', '፸': '70', '፹': '80', '፺': '90',
88
+ '፻': '100', '፼': '10000',
89
+ // --- Built-in Utilities ---
90
+ 'ያትም': 'console.log',
91
+ 'ማንቂያ': 'alert',
92
+ 'ጊዜጠባቂ': 'async'
93
+ };
94
+
95
+ module.exports = JANO_KEYWORDS;
package/src/engine.js ADDED
@@ -0,0 +1,75 @@
1
+ const JANO_KEYWORDS = require('./dictionary');
2
+ const { JANO_PRELUDE } = require('./prelude');
3
+ const fs = require('fs');
4
+
5
+ /**
6
+ * ጃኖ ፊደል (Jano Fidel) Transpiler Engine
7
+ */
8
+ function transpile(inputCode) {
9
+ // This regex identifies words, strings, and Ethiopic symbols
10
+ const regex = /("[^"]*"|'[^']*'|`[^`]*`|\/\/[^\n]*|[።፤፡፦፣]|[ሀ-፟፩-፿]+|[a-zA-Z0-9_]+|[^\s])/g;
11
+
12
+ return inputCode.replace(regex, (token) => {
13
+ if (token.startsWith('"') || token.startsWith("'") || token.startsWith("//")) {
14
+ return token;
15
+ }
16
+
17
+ // Check if the token is an Ethiopic Number (e.g., ፲፪)
18
+ if (/^[፩-፿]+$/.test(token)) {
19
+ return convertEthiopicToArabic(token);
20
+ }
21
+
22
+ return JANO_KEYWORDS[token] || token;
23
+ });
24
+ }
25
+
26
+ // Simple helper to turn Ethiopic numerals into JavaScript numbers
27
+ function convertEthiopicToArabic(eth) {
28
+ const valueMap = {
29
+ '፩':1, '፪':2, '፫':3, '፬':4, '፭':5, '፮':6, '፯':7, '፰':8, '፱':9,
30
+ '፲':10, '፳':20, '፴':30, '፵':40, '፶':50, '፷':60, '፸':70, '፹':80, '፺':90,
31
+ '፟':0 // Zero, or acts as a separator
32
+ };
33
+ const multiplierMap = {
34
+ '፻': 100,
35
+ '፼': 10000
36
+ };
37
+
38
+ let total = 0;
39
+ let currentBlockValue = 0; // Stores the value of the current digit/tens before a multiplier
40
+
41
+ for (let i = 0; i < eth.length; i++) {
42
+ const char = eth[i];
43
+
44
+ if (multiplierMap[char]) {
45
+ // If it's a multiplier (፻ or ፼)
46
+ if (currentBlockValue === 0 && char === '፻') { // Handle cases like just '፻' meaning 100
47
+ currentBlockValue = 1;
48
+ } else if (currentBlockValue === 0 && char === '፼') { // Handle cases like just '፼' meaning 10000
49
+ currentBlockValue = 1;
50
+ }
51
+
52
+ total += currentBlockValue * multiplierMap[char];
53
+ currentBlockValue = 0; // Reset for the next block of numbers
54
+ } else if (valueMap[char] !== undefined) {
55
+ // If it's a digit or ten
56
+ currentBlockValue += valueMap[char];
57
+ } else {
58
+ // Unknown character or invalid numeral sequence
59
+ // For robustness, returning NaN or throwing an error is better
60
+ return NaN;
61
+ }
62
+ }
63
+ // Add any remaining units/tens that weren't followed by a multiplier
64
+ total += currentBlockValue;
65
+ return total.toString();
66
+ }
67
+ function processFile(filePath) {
68
+ const content = fs.readFileSync(filePath, 'utf8');
69
+ const transpiled = transpile(content);
70
+ // Combine the prelude (built-ins) with the user's code
71
+ return `(function(){\n${JANO_PRELUDE}\n${transpiled}\n})();`;}
72
+
73
+
74
+
75
+ module.exports = { transpile, processFile, JANO_PRELUDE, convertEthiopicToArabic };
package/src/hook.js ADDED
@@ -0,0 +1,17 @@
1
+ const fs = require('fs');
2
+ const { transpile, JANO_PRELUDE } = require('./engine');
3
+
4
+ // WARNING: require.extensions is a deprecated API.
5
+ // This usage is temporary and needs to be replaced with a more robust module
6
+ // loading strategy (e.g., Node.js Loader Hooks for ESM or pre-transpilation)
7
+ // in future versions to ensure long-term compatibility and stability with Node.js.
8
+ // Tell Node.js to handle .jf files
9
+ require.extensions['.jf'] = function (module, filename) {
10
+ const content = fs.readFileSync(filename, 'utf8');
11
+ const transpiled = transpile(content);
12
+
13
+ // Inject prelude so the required file also has access to 'ያትም' etc.
14
+ const finalCode = `${JANO_PRELUDE}\n${transpiled}`;
15
+
16
+ module._compile(finalCode, filename);
17
+ };
package/src/prelude.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * ጃኖ ፊደል (Jano Fidel) - Prelude (Standard Library)
3
+ */
4
+
5
+ // 1. Node.js safe aliases (only things that exist in Node)
6
+ const ሒሳብ = Math;
7
+ const ጃነማ = JSON;
8
+ const ቀን = Date;
9
+ const ቃልኪዳን = Promise;
10
+ const ያትም = console.log;
11
+
12
+ // 2. Export the template for the transpiler
13
+ // We put 'ማንቂያ' inside the string so it doesn't crash the Node.js process
14
+ const JANO_PRELUDE = `
15
+ const ሒሳብ = Math;
16
+ const ጃነማ = JSON;
17
+ const ቀን = Date;
18
+ const ቃልኪዳን = Promise;
19
+ const ያትም = console.log;
20
+ const ማንቂያ = (typeof alert !== 'undefined') ? alert : console.log;
21
+
22
+ // Global function aliases
23
+ const ቆይ = setTimeout;
24
+
25
+ // Safety Check for Prototypes
26
+ if (!Array.prototype.hasOwnProperty('ርዝመት')) {
27
+ Object.defineProperty(Array.prototype, 'ርዝመት', {
28
+ get: function() { return this.length; },
29
+ configurable: true
30
+ });
31
+ }
32
+
33
+ if (!String.prototype.hasOwnProperty('ርዝመት')) {
34
+ Object.defineProperty(String.prototype, 'ርዝመት', {
35
+ get: function() { return this.length; },
36
+ configurable: true
37
+ });
38
+ }
39
+
40
+ if (!Date.prototype.ወደ_ጽሑፍ) {
41
+ Date.prototype.ወደ_ጽሑፍ = Date.prototype.toDateString;
42
+ }
43
+ `;
44
+
45
+ module.exports = { JANO_PRELUDE };
package/src/runner.js ADDED
@@ -0,0 +1,81 @@
1
+ const { spawn } = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const hookPath = require.resolve('./hook');
5
+
6
+ // --- 1. Helpers (Top of the file) ---
7
+
8
+ const style = {
9
+ red: (t) => `\x1b[31m${t}\x1b[0m`,
10
+ yellow: (t) => `\x1b[33m${t}\x1b[0m`,
11
+ bold: (t) => `\x1b[1m${t}\x1b[0m`,
12
+ reset: '\x1b[0m'
13
+ };
14
+
15
+ function getExitSummary(code) {
16
+ if (code === 1) return "ያልተጠበቀ ስህተት አጋጥሟል (Uncaught Error)";
17
+ if (code === 130) return "ተጠቃሚው ፕሮግራሙን አቋርጦታል (User Interrupted)";
18
+ return `ፕሮግራሙ በስህተት ተዘግቷል (Exit Code: ${code})`;
19
+ }
20
+
21
+ function remapStack(data, tempFilePath, originalFileName) {
22
+ const output = data.toString();
23
+ const escapedPath = tempFilePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
24
+ const regex = new RegExp(escapedPath, 'g');
25
+ return output.replace(regex, originalFileName);
26
+ }
27
+
28
+ // --- 2. Main Execution Function ---
29
+
30
+ function runCode(jsCode, originalFilePath) {
31
+ const fileName = path.basename(originalFilePath);
32
+ const dirName = path.dirname(path.resolve(originalFilePath));
33
+ const tempFile = path.join(dirName, `.${path.basename(originalFilePath, '.jf')}.tmp.js`);
34
+
35
+ try {
36
+ fs.writeFileSync(tempFile, jsCode, 'utf8');
37
+
38
+ // Preload the hook to handle imports
39
+ const hookPath = require.resolve('./hook');
40
+ const child = spawn('node', ['-r', hookPath, tempFile], {
41
+ stdio: ['inherit', 'inherit', 'pipe'],
42
+ cwd: process.cwd()
43
+ });
44
+
45
+ child.stderr.on('data', (data) => {
46
+ const remappedError = remapStack(data, tempFile, fileName);
47
+ process.stderr.write(remappedError);
48
+ });
49
+
50
+ // --- THE BOX UI LOGIC HERE ---
51
+ child.on('close', (code) => {
52
+ if (fs.existsSync(tempFile)) {
53
+ try { fs.unlinkSync(tempFile); } catch(e) {}
54
+ }
55
+
56
+ if (code !== 0 && code !== null) {
57
+ const summary = getExitSummary(code);
58
+ const border = style.red("┃");
59
+
60
+ console.error(`\n` + style.red("┏" + "━".repeat(60) + "┓"));
61
+ console.error(`${border} ${style.bold(style.red("⚠️ የጃኖ ማጠቃለያ (Jano Summary)"))}`.padEnd(74) + border);
62
+ console.error(style.red("┣" + "━".repeat(60) + "┫"));
63
+ console.error(`${border} ${style.bold("ሁኔታ፦")} ${summary}`.padEnd(68) + border);
64
+ console.error(`${border} ${style.bold("ፋይል፦")} ${fileName}`.padEnd(68) + border);
65
+ console.error(`${border}${' '.repeat(60)}${border}`);
66
+ console.error(`${border} 🔍 ${style.bold("ፍንጭ፦")} የመስመር ቁጥሩን በ ${style.bold(fileName)} ውስጥ ይዩ።`.padEnd(72) + border);
67
+ console.error(style.red("┗" + "━".repeat(60) + "┛") + `\n`);
68
+ }
69
+ });
70
+
71
+ process.on('SIGINT', () => {
72
+ if (fs.existsSync(tempFile)) fs.unlinkSync(tempFile);
73
+ process.exit();
74
+ });
75
+
76
+ } catch (err) {
77
+ console.error(`\n[የፋይል ስህተት]: ጊዜያዊ ፋይል መፍጠር አልተቻለም፦ ${err.message}`);
78
+ }
79
+ }
80
+
81
+ module.exports = { runCode };