darijacode 0.2.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 ADDED
@@ -0,0 +1,130 @@
1
+ # DarijaCode Community License (DCL) v1.0
2
+
3
+ Copyright (c) 2025–present, krnl0xsns1nk and DarijaCode contributors.
4
+
5
+ This is a custom license. It is not a standard OSI-approved license β€” read
6
+ it, don't assume it matches something you've seen before.
7
+
8
+ ---
9
+
10
+ ## Plain-language summary (not a substitute for the terms below)
11
+
12
+ - Install it, run it, change it, learn from it, do basically whatever you want with it.
13
+ - Build extra tools around it β€” an IDE, docs, an editor, error tooling, new language features β€” as your own separate project.
14
+ - Fork it, fix it, ship your own build.
15
+
16
+ - Don't take this project and present it as something you created. Keep the credit where it belongs.
17
+ - Don't publish a fork and call it "DarijaCode" as if it's the original, official project.
18
+
19
+ - πŸ•ŠοΈ If the maintainer goes quiet for a long stretch, the community is free to keep this project alive β€” fixes, releases, all of it β€” until the maintainer returns, if ever.
20
+
21
+ If anything below conflicts with this summary, the terms below control.
22
+
23
+ ---
24
+
25
+ ## 1. Definitions
26
+
27
+ - **"The Project"** means the DarijaCode source code, documentation, and
28
+ associated files in this repository.
29
+ - **"You"** means anyone using, copying, modifying, or distributing the
30
+ Project under this license.
31
+ - **"Derivative Tool"** means a separate piece of software that works with
32
+ or alongside the Project β€” an editor, IDE plugin, documentation site,
33
+ linter, error formatter, package manager frontend, new-feature add-on,
34
+ and so on β€” but is not itself a redistribution of the Project as a
35
+ whole.
36
+ - **"The Maintainer"** means krnl0xsns1nk, the original author of the
37
+ Project, or anyone the Maintainer formally designates in writing.
38
+
39
+ ## 2. What you're permitted to do
40
+
41
+ You are granted a free, worldwide, royalty-free license to:
42
+
43
+ 1. **Use** the Project for any purpose, personal or commercial.
44
+ 2. **Study and learn from** the source code.
45
+ 3. **Modify** the source code, for your own use or to contribute back.
46
+ 4. **Copy and redistribute** the Project, or your modified version of it,
47
+ subject to Section 3 (Attribution) and Section 4 (No Misrepresentation)
48
+ below.
49
+ 5. **Build and distribute Derivative Tools** β€” an IDE, a docs site, a code
50
+ editor, error-handling libraries, new language features, package
51
+ registries, and so on β€” under any license you choose, including
52
+ proprietary or commercial ones, as long as the Derivative Tool does not
53
+ itself claim to *be* DarijaCode (see Section 4).
54
+
55
+ ## 3. Attribution
56
+
57
+ Any copy or substantial redistribution of the Project, modified or not,
58
+ must:
59
+
60
+ 1. Keep this license file intact.
61
+ 2. Retain a visible credit to the original author and a link to the
62
+ original repository, in the copy's README or an equally prominent
63
+ location.
64
+ 3. Clearly state, if modified, that changes were made.
65
+
66
+ ## 4. No misrepresentation of authorship or origin
67
+
68
+ This is the core restriction of this license, and the main reason it
69
+ isn't a plain MIT/ISC license:
70
+
71
+ 1. You may **not** present the Project, or a fork of it, as your own
72
+ original creation.
73
+ 2. You may **not** publish a fork, rebrand, or redistribution in a way
74
+ that implies it is the official or original DarijaCode project, unless
75
+ you are the Maintainer or have been designated as a steward under
76
+ Section 5.
77
+ 3. Forks are welcome and encouraged, but must be clearly labeled as a
78
+ fork or derivative (e.g. "MyLang, a DarijaCode fork") β€” not presented
79
+ as if it were the primary project or as if you created it from
80
+ scratch.
81
+ 4. Derivative Tools (Section 2.5) are exempt from labeling themselves as
82
+ a "fork," since they are separate works β€” but they may not claim to
83
+ have authored the DarijaCode language or compiler itself.
84
+
85
+ ## 5. Maintainer inactivity and community stewardship
86
+
87
+ This project is maintained by one person, for fun, with no promises about
88
+ how long that continues. So:
89
+
90
+ 1. **Active** means the Maintainer has made at least one commit to the
91
+ main repository within the preceding **6 months**.
92
+ 2. If the Project becomes **inactive** by that definition, the community
93
+ is explicitly permitted, without needing to ask, to:
94
+ - Fork the repository and continue development, bug fixes, and
95
+ releases under this same license.
96
+ - Coordinate a community-maintained fork as the de facto continuation
97
+ of the project, clearly labeled as community-maintained (per
98
+ Section 4.3) for as long as the Maintainer remains inactive.
99
+ 3. If the Maintainer resumes committing to the original repository, the
100
+ original repository remains the canonical project, and community
101
+ forks are expected to acknowledge this and may merge their work back
102
+ if the Maintainer is willing.
103
+ 4. This clause does not transfer copyright or ownership β€” it is a
104
+ standing permission to fork, maintain, and release, granted in
105
+ advance, so the community never has to wait for a response that may
106
+ never come.
107
+
108
+ ## 6. No warranty
109
+
110
+ The Project is provided "as is," without warranty of any kind, express or
111
+ implied, including but not limited to warranties of merchantability,
112
+ fitness for a particular purpose, and non-infringement. In no event shall
113
+ the Maintainer or contributors be liable for any claim, damages, or other
114
+ liability arising from the Project or its use.
115
+
116
+ ## 7. Termination
117
+
118
+ Your rights under this license terminate automatically if you violate
119
+ Section 4 (No Misrepresentation) and do not correct the violation within
120
+ 30 days of being notified. All other rights survive termination for
121
+ copies already lawfully distributed.
122
+
123
+ ---
124
+
125
+ *This license was written in plain terms to match how the Maintainer
126
+ actually wants this project used. If you need a legally binding
127
+ interpretation for a specific situation (e.g. enterprise use, a
128
+ large-scale fork, a dispute), consult a lawyer β€” this document has not
129
+ been reviewed by one.*
130
+
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ <div align="center">
2
+
3
+ # πŸ•ŠοΈ DarijaCode
4
+
5
+ A programming language and compiler written for fun, using Moroccan Darija.
6
+
7
+ [![Status](https://img.shields.io/badge/status-experimental-orange)](https://github.com/krnl0xsns1nk/DarijaCode)
8
+ [![Language](https://img.shields.io/badge/language-TypeScript-3178c6)](https://www.typescriptlang.org/)
9
+ [![License](https://img.shields.io/badge/license-DCL-blue)](LICENSE)
10
+ [![GitHub stars](https://img.shields.io/github/stars/krnl0xsns1nk/DarijaCode?style=social)](https://github.com/krnl0xsns1nk/DarijaCode)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ### Quick install
19
+
20
+ Linux / Termux:
21
+
22
+ ```bash
23
+ curl -fsSL https://raw.githubusercontent.com/krnl0xsns1nk/DarijaCode/main/scripts/install.sh | sh
24
+ ```
25
+
26
+ ---
27
+
28
+
29
+ > **DarijaCode is a hobby project built for learning compiler development and experimenting with a programming language based on Moroccan Darija.**
30
+ >
31
+ > It is **not** trying to replace JavaScript, Python, C, or any existing language.
32
+
33
+ ---
34
+
35
+ ## Why?
36
+
37
+ The goal isn't simply replacing English keywords.
38
+
39
+ The goal is building a complete programming ecosystem where everything speaks Darija:
40
+
41
+ - lexer
42
+ - parser
43
+ - semantic checker
44
+ - native compiler
45
+ - CLI
46
+ - runtime
47
+ - package manager *(planned)*
48
+ - standard library *(planned)*
49
+ - compiler errors written in Darija
50
+
51
+ For example:
52
+
53
+ ```drj
54
+ kteb("Salam");
55
+ ```
56
+ and when something goes wrong, the compiler also responds in Darija:
57
+ - take a real example of mine :
58
+
59
+ <pre style="background:#0d1117; color:#c9d1d9; padding:16px; border-radius:8px; font-family:monospace; overflow-x:auto">
60
+ <span style="color:#7ee787">user@localhost</span> <span style="color:#a5d6ff">~/projects/DarijaCode</span> <span style="color:#ffa657">(master●)</span>
61
+ <span style="color:#7ee787">$</span> <span style="color:#ffa657">bat ex.drj</span>
62
+
63
+ <span style="color:#8b949e">β”‚</span> <span style="color:#8b949e">File: ex.drj</span>
64
+ <span style="color:#8b949e">──┼────────────────────────────────────────</span>
65
+ <span style="color:#8b949e">1</span> <span style="color:#8b949e">β”‚</span> <span style="color:#d2a8ff">dir</span> <span style="color:#79c0ff">name</span> <span style="color:#c9d1d9">:</span> <span style="color:#79c0ff">ra9m</span> <span style="color:#c9d1d9">=</span> <span style="color:#a5d6ff">"krnl0xsns"</span><span style="color:#c9d1d9">;</span>
66
+ <span style="color:#8b949e">2</span> <span style="color:#8b949e">β”‚</span> <span style="color:#d2a8ff">kteb</span><span style="color:#c9d1d9">(</span><span style="color:#79c0ff">name</span><span style="color:#c9d1d9">);</span>
67
+ <span style="color:#8b949e">──┴────────────────────────────────────────</span>
68
+
69
+ <span style="color:#7ee787">user@localhost</span> <span style="color:#a5d6ff">~/projects/DarijaCode</span> <span style="color:#ffa657">(master●)</span>
70
+ <span style="color:#7ee787">$</span> <span style="color:#ffa657">drj run ex.drj</span>
71
+ <span style="color:#f85149; font-weight:bold">DarijaCode error[checker:DCE15]</span> <span style="color:#ffa657">twa93na ra9m, wlkin l9ina nass</span>
72
+ <span style="color:#58a6ff">--> /data/data/com.termux/files/home/projects/DarijaCode/ex.drj:1:1</span>
73
+ <span style="color:#8b949e">1</span> <span style="color:#8b949e">β”‚</span> <span style="color:#d2a8ff">dir</span> <span style="color:#79c0ff">name</span> <span style="color:#c9d1d9">:</span> <span style="color:#79c0ff">ra9m</span> <span style="color:#c9d1d9">=</span> <span style="color:#a5d6ff">"krnl0xsns"</span><span style="color:#c9d1d9">;</span>
74
+ <span style="color:#8b949e">β”‚</span> <span style="color:#f85149">^</span>
75
+ <span style="color:#a371f7">jrb/chof:</span> <span style="color:#ffa657">ach ban link tstkhdm ra9m fbalst nass</span>
76
+ </pre>
77
+
78
+ - see docs/error_codes.md for more info about these codes.
package/dist/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const index_1 = __importDefault(require("./compiler/index"));
10
+ const VERSION = "0.2.0";
11
+ function error(message) {
12
+ console.error(`βœ— ${message}`);
13
+ process.exit(1);
14
+ }
15
+ function success(message) {
16
+ console.log(`βœ“ ${message}`);
17
+ }
18
+ function validateFile(file) {
19
+ const path = (0, path_1.resolve)(file);
20
+ if (!(0, fs_1.existsSync)(path)) {
21
+ error(`milaf mkaynch: ${path}`);
22
+ }
23
+ if ((0, path_1.extname)(path) !== ".drj") {
24
+ error(`twa93t milf b .drj`);
25
+ }
26
+ return path;
27
+ }
28
+ function help() {
29
+ console.log(`
30
+ DarijaCode ${VERSION}
31
+
32
+ listikhdam:
33
+ drj run <file>
34
+ drj build <file>
35
+ drj check <file>
36
+
37
+ lawamir:
38
+ run Compile and execute
39
+ build Compile to binary
40
+ check Check syntax and types
41
+ `);
42
+ }
43
+ async function main() {
44
+ const args = process.argv.slice(2);
45
+ if (args.length === 0) {
46
+ help();
47
+ return;
48
+ }
49
+ const command = args[0];
50
+ const v = ["--verion", "version", "-v", "--v", "-version", "lisdar", "--isdar"];
51
+ if (v.includes(command)) {
52
+ console.log(VERSION);
53
+ return;
54
+ }
55
+ const file = args[1];
56
+ if (!file) {
57
+ error("khask milf dyal .drj");
58
+ }
59
+ const filePath = validateFile(file);
60
+ switch (command) {
61
+ case "check": {
62
+ (0, index_1.default)("check", filePath);
63
+ break;
64
+ }
65
+ case "run": {
66
+ (0, index_1.default)("run", filePath);
67
+ break;
68
+ }
69
+ case "build": {
70
+ (0, index_1.default)("build", filePath);
71
+ break;
72
+ }
73
+ default:
74
+ help();
75
+ }
76
+ }
77
+ main();
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExpressionChecker = void 0;
4
+ const errors_1 = require("../errors");
5
+ const showType_1 = require("../../utils/showType");
6
+ const types_1 = require("./types");
7
+ /**
8
+ * ExpressionChecker handles type inference for all expression types.
9
+ * Validates expressions and returns their inferred types.
10
+ */
11
+ class ExpressionChecker {
12
+ functions;
13
+ typeChecker;
14
+ constructor(functions) {
15
+ this.functions = functions;
16
+ this.typeChecker = new types_1.TypeChecker();
17
+ }
18
+ /**
19
+ * Infer the type of an expression.
20
+ * Performs semantic validation and returns the resulting type.
21
+ */
22
+ inferType(expr, scope) {
23
+ switch (expr.type) {
24
+ case "NumericLiteral":
25
+ return { base: "ra9m", d: 0 };
26
+ case "StringLiteral":
27
+ return { base: "nass", d: 0 };
28
+ case "BooleanLiteral":
29
+ return { base: "tona2i", d: 0 };
30
+ case "NullLiteral":
31
+ return { base: "khawi", d: 0 };
32
+ case "ArrayExpression":
33
+ return this.checkArrayExpression(expr, scope);
34
+ case "Identifier":
35
+ return this.checkIdentifier(expr, scope);
36
+ case "AssignmentExpression":
37
+ return this.checkAssignmentExpression(expr, scope);
38
+ case "BinaryExpression":
39
+ return this.checkBinaryExpression(expr, scope);
40
+ case "LogicalExpression":
41
+ return this.checkLogicalExpression(expr, scope);
42
+ case "UnaryExpression":
43
+ return this.checkUnaryExpression(expr, scope);
44
+ case "UpdateExpression":
45
+ return this.checkUpdateExpression(expr, scope);
46
+ case "ConditionalExpression":
47
+ return this.checkConditionalExpression(expr, scope);
48
+ case "CallExpression":
49
+ return this.checkCallExpression(expr, scope);
50
+ case "MemberExpression":
51
+ return this.checkMemberExpression(expr, scope);
52
+ default:
53
+ throw new errors_1.DarijaError({
54
+ code: "DCE-2",
55
+ stage: "checker",
56
+ message: `'${expr.type}' ba9i mmd3omach`,
57
+ location: {
58
+ line: expr.pos.line,
59
+ column: expr.pos.column,
60
+ },
61
+ });
62
+ }
63
+ }
64
+ checkArrayExpression(expr, scope) {
65
+ if (expr.elements.length === 0) {
66
+ return { base: "unknown", d: 1 };
67
+ }
68
+ const elementType = this.inferType(expr.elements[0], scope);
69
+ for (const element of expr.elements) {
70
+ this.inferType(element, scope);
71
+ }
72
+ return {
73
+ base: elementType.base,
74
+ d: (elementType.d ?? 0) + 1,
75
+ };
76
+ }
77
+ checkIdentifier(expr, scope) {
78
+ const info = scope.resolve(expr.name);
79
+ if (!info) {
80
+ throw new errors_1.DarijaError({
81
+ code: "DCE1",
82
+ stage: "checker",
83
+ message: `'${expr.name}' mm3rofach`,
84
+ location: {
85
+ line: expr.pos.line,
86
+ column: expr.pos.column,
87
+ },
88
+ });
89
+ }
90
+ return info.type;
91
+ }
92
+ checkAssignmentExpression(expr, scope) {
93
+ const valueType = this.inferType(expr.value, scope);
94
+ if (expr.target.type === "Identifier") {
95
+ const info = scope.resolve(expr.target.name);
96
+ if (!info) {
97
+ throw new errors_1.DarijaError({
98
+ code: "DCE1",
99
+ stage: "checker",
100
+ message: `'${expr.target.name}' mm3rofch`,
101
+ location: {
102
+ line: expr.pos.line,
103
+ column: expr.pos.column,
104
+ },
105
+ });
106
+ }
107
+ if (info.kind === "khli") {
108
+ throw new errors_1.DarijaError({
109
+ code: "DCE16",
110
+ stage: "checker",
111
+ message: `mat9drh t3ti 9ima l '${expr.target.name}', la79ach how tabit (m3rf b 'khli')`,
112
+ location: {
113
+ line: expr.pos.line,
114
+ column: expr.pos.column,
115
+ },
116
+ });
117
+ }
118
+ if (info.type.base !== types_1.UNKNOWN &&
119
+ !this.typeChecker.compatible(info.type, valueType)) {
120
+ throw new errors_1.DarijaError({
121
+ code: "DCE15",
122
+ stage: "checker",
123
+ message: `twa93na ${(0, showType_1.showType)(info.type)}, wlkin l9ina ${(0, showType_1.showType)(valueType)}`,
124
+ location: {
125
+ line: expr.pos.line,
126
+ column: expr.pos.column,
127
+ },
128
+ });
129
+ }
130
+ }
131
+ else {
132
+ this.inferType(expr.target, scope);
133
+ }
134
+ return valueType;
135
+ }
136
+ checkBinaryExpression(expr, scope) {
137
+ const leftType = this.inferType(expr.left, scope);
138
+ const rightType = this.inferType(expr.right, scope);
139
+ if (["==", "!=", "<", "<=", ">", ">="].includes(expr.operator)) {
140
+ return { base: "tona2i", d: 0 };
141
+ }
142
+ if (expr.operator === "+") {
143
+ if (this.typeChecker.isType(leftType, "nass") || this.typeChecker.isType(rightType, "nass")) {
144
+ return { base: "nass", d: 0 };
145
+ }
146
+ this.typeChecker.expectType(leftType, "ra9m", expr.pos);
147
+ this.typeChecker.expectType(rightType, "ra9m", expr.pos);
148
+ return { base: "ra9m", d: 0 };
149
+ }
150
+ // Other arithmetic operators require numbers
151
+ this.typeChecker.expectType(leftType, "ra9m", expr.pos);
152
+ this.typeChecker.expectType(rightType, "ra9m", expr.pos);
153
+ return { base: "ra9m", d: 0 };
154
+ }
155
+ checkLogicalExpression(expr, scope) {
156
+ this.inferType(expr.left, scope);
157
+ this.inferType(expr.right, scope);
158
+ return { base: "tona2i", d: 0 };
159
+ }
160
+ checkUnaryExpression(expr, scope) {
161
+ const argType = this.inferType(expr.argument, scope);
162
+ if (expr.operator === "!") {
163
+ return { base: "tona2i", d: 0 };
164
+ }
165
+ this.typeChecker.expectType(argType, "ra9m", expr.pos);
166
+ return { base: "ra9m", d: 0 };
167
+ }
168
+ checkUpdateExpression(expr, scope) {
169
+ const argType = this.inferType(expr.argument, scope);
170
+ this.typeChecker.expectType(argType, "ra9m", expr.pos);
171
+ return { base: "ra9m", d: 0 };
172
+ }
173
+ checkConditionalExpression(expr, scope) {
174
+ this.inferType(expr.condition, scope);
175
+ const consequentType = this.inferType(expr.consequent, scope);
176
+ const alternateType = this.inferType(expr.alternate, scope);
177
+ return consequentType === alternateType
178
+ ? consequentType
179
+ : { base: types_1.UNKNOWN, d: 0 };
180
+ }
181
+ checkCallExpression(expr, scope) {
182
+ if (expr.callee.type !== "Identifier") {
183
+ throw new errors_1.DarijaError({
184
+ code: "DCE-2",
185
+ stage: "checker",
186
+ message: "ghir dawal direct lli md3omim",
187
+ location: {
188
+ line: expr.pos.line,
189
+ column: expr.pos.column,
190
+ },
191
+ });
192
+ }
193
+ const fn = this.functions.get(expr.callee.name);
194
+ if (!fn) {
195
+ throw new errors_1.DarijaError({
196
+ code: "DCE1",
197
+ stage: "checker",
198
+ message: `dala '${expr.callee.name}' mm3rofach`,
199
+ location: {
200
+ line: expr.pos.line,
201
+ column: expr.pos.column,
202
+ },
203
+ hint: `dir ta3rif l dala ${expr.callee.name} bhal haka : dalla ${expr.callee.name}(){ chi logic }}`,
204
+ });
205
+ }
206
+ const required = fn.params.filter((p) => !p.defaultValue).length;
207
+ if (expr.args.length < required ||
208
+ expr.args.length > fn.params.length) {
209
+ throw new errors_1.DarijaError({
210
+ code: "DCE17",
211
+ stage: "checker",
212
+ message: `'${expr.callee.name}' twa93 ${required === fn.params.length
213
+ ? required
214
+ : `${required}-${fn.params.length}`} dyal lhojaj, wlkin l9a ${expr.args.length}`,
215
+ location: {
216
+ line: expr.pos.line,
217
+ column: expr.pos.column,
218
+ },
219
+ });
220
+ }
221
+ expr.args.forEach((arg, i) => {
222
+ const argType = this.inferType(arg, scope);
223
+ const param = fn.params[i];
224
+ if (param.typeAnnotation &&
225
+ !this.typeChecker.compatible(param.typeAnnotation, argType)) {
226
+ throw new errors_1.DarijaError({
227
+ code: "DCE15",
228
+ stage: "checker",
229
+ message: `twa93na ${(0, showType_1.showType)(param.typeAnnotation)}, wlkin l9ina ${(0, showType_1.showType)(argType)}`,
230
+ location: {
231
+ line: expr.pos.line,
232
+ column: expr.pos.column,
233
+ },
234
+ });
235
+ }
236
+ });
237
+ return fn.returnType ?? { base: types_1.UNKNOWN, d: 0 };
238
+ }
239
+ checkMemberExpression(expr, scope) {
240
+ const objectType = this.inferType(expr.object, scope);
241
+ if (expr.computed)
242
+ this.inferType(expr.property, scope);
243
+ return objectType.d
244
+ ? { base: objectType.base, d: objectType.d - 1 }
245
+ : { base: types_1.UNKNOWN, d: 0 };
246
+ }
247
+ }
248
+ exports.ExpressionChecker = ExpressionChecker;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Checker = void 0;
4
+ const errors_1 = require("../errors");
5
+ const scope_1 = require("./scope");
6
+ const statements_1 = require("./statements");
7
+ class Checker {
8
+ globalScope = new scope_1.Scope();
9
+ functions = new scope_1.FunctionRegistry();
10
+ statementChecker;
11
+ constructor() {
12
+ this.statementChecker = new statements_1.StatementChecker(this.functions, this.globalScope);
13
+ }
14
+ check(program) {
15
+ // Pass 1: Hoist function signatures
16
+ for (const stmt of program.body) {
17
+ if (stmt.type === "FunctionDeclaration") {
18
+ this.registerFunctionSignature(stmt);
19
+ }
20
+ }
21
+ // Pass 2: Validate all statements
22
+ for (const stmt of program.body) {
23
+ this.statementChecker.checkStatement(stmt, this.globalScope);
24
+ }
25
+ }
26
+ registerFunctionSignature(fn) {
27
+ if (this.functions.has(fn.name)) {
28
+ throw new errors_1.DarijaError({
29
+ code: "DCE13",
30
+ stage: "checker",
31
+ message: `dala '${fn.name}' dija m3rfa`,
32
+ location: {
33
+ line: fn.pos.line,
34
+ column: fn.pos.column,
35
+ },
36
+ hint: `stkhdm dalla dyal ${fn.name}() awla dir dalla jdida`,
37
+ });
38
+ }
39
+ this.functions.register(fn.name, {
40
+ params: fn.params,
41
+ returnType: fn.returnType ?? { base: "walo", d: 0 },
42
+ }, fn.pos.line, fn.pos.column);
43
+ }
44
+ }
45
+ exports.Checker = Checker;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FunctionRegistry = exports.Scope = void 0;
4
+ const errors_1 = require("../errors");
5
+ //welcome to the scope
6
+ class Scope {
7
+ parent;
8
+ vars = new Map();
9
+ constructor(parent = null) {
10
+ this.parent = parent;
11
+ }
12
+ declare(name, info, line, column) {
13
+ if (this.vars.has(name)) {
14
+ throw new errors_1.DarijaError({
15
+ code: "DCE13",
16
+ stage: "checker",
17
+ message: `'${name}' dija m3rfa`,
18
+ location: { line, column },
19
+ hint: `${name} = 9ima fblast (dir/khli ${name} = 9ima)`,
20
+ });
21
+ }
22
+ this.vars.set(name, info);
23
+ }
24
+ resolve(name) {
25
+ return this.vars.get(name) ?? this.parent?.resolve(name);
26
+ }
27
+ child() {
28
+ return new Scope(this);
29
+ }
30
+ }
31
+ exports.Scope = Scope;
32
+ /**
33
+ * Global function registry.
34
+ * Tracks all function signatures for validation during calls and recursion.
35
+ */
36
+ class FunctionRegistry {
37
+ functions = new Map();
38
+ register(name, info, line, column) {
39
+ if (this.functions.has(name)) {
40
+ throw new errors_1.DarijaError({
41
+ code: "DCE13",
42
+ stage: "checker",
43
+ message: `dala '${name}' dija m3rfa`,
44
+ location: { line, column },
45
+ hint: `stkhdm dalla dyal ${name}() awla dir dalla jdida`,
46
+ });
47
+ }
48
+ this.functions.set(name, info);
49
+ }
50
+ get(name) {
51
+ return this.functions.get(name);
52
+ }
53
+ has(name) {
54
+ return this.functions.has(name);
55
+ }
56
+ }
57
+ exports.FunctionRegistry = FunctionRegistry;