mimo-lang 1.1.0 → 2.0.6
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/.gitattributes +24 -0
- package/LICENSE +21 -0
- package/README.md +91 -6
- package/adapters/browserAdapter.js +86 -0
- package/adapters/nodeAdapter.js +101 -0
- package/bin/cli.js +80 -0
- package/bin/commands/convert.js +27 -0
- package/bin/commands/doctor.js +139 -0
- package/bin/commands/eval.js +39 -0
- package/bin/commands/fmt.js +109 -0
- package/bin/commands/help.js +72 -0
- package/bin/commands/lint.js +117 -0
- package/bin/commands/repl.js +24 -0
- package/bin/commands/run.js +64 -0
- package/bin/commands/test.js +126 -0
- package/bin/utils/colors.js +38 -0
- package/bin/utils/formatError.js +47 -0
- package/bin/utils/fs.js +57 -0
- package/bin/utils/version.js +8 -0
- package/build.js +18 -0
- package/bun.lock +74 -0
- package/index.js +49 -39
- package/index.web.js +364 -0
- package/interpreter/BuiltinFunction.js +32 -0
- package/interpreter/ErrorHandler.js +120 -0
- package/interpreter/ExpressionEvaluator.js +106 -0
- package/interpreter/Interpreter.js +172 -0
- package/interpreter/MimoError.js +112 -0
- package/interpreter/ModuleLoader.js +236 -0
- package/interpreter/StatementExecutor.js +107 -0
- package/interpreter/Utils.js +82 -0
- package/interpreter/Values.js +87 -0
- package/interpreter/coreBuiltins.js +490 -0
- package/interpreter/environment.js +99 -0
- package/interpreter/evaluators/binaryExpressionEvaluator.js +111 -0
- package/interpreter/evaluators/collectionEvaluator.js +151 -0
- package/interpreter/evaluators/functionCallEvaluator.js +76 -0
- package/interpreter/evaluators/literalEvaluator.js +27 -0
- package/interpreter/evaluators/moduleAccessEvaluator.js +25 -0
- package/interpreter/evaluators/templateLiteralEvaluator.js +20 -0
- package/interpreter/executors/BaseExecutor.js +37 -0
- package/interpreter/executors/ControlFlowExecutor.js +206 -0
- package/interpreter/executors/FunctionExecutor.js +126 -0
- package/interpreter/executors/PatternMatchExecutor.js +93 -0
- package/interpreter/executors/VariableExecutor.js +144 -0
- package/interpreter/index.js +8 -0
- package/interpreter/stdlib/array/accessFunctions.js +61 -0
- package/interpreter/stdlib/array/arrayUtils.js +36 -0
- package/interpreter/stdlib/array/higherOrderFunctions.js +285 -0
- package/interpreter/stdlib/array/searchFunctions.js +77 -0
- package/interpreter/stdlib/array/setFunctions.js +49 -0
- package/interpreter/stdlib/array/transformationFunctions.js +68 -0
- package/interpreter/stdlib/array.js +85 -0
- package/interpreter/stdlib/assert.js +143 -0
- package/interpreter/stdlib/datetime.js +170 -0
- package/interpreter/stdlib/env.js +54 -0
- package/interpreter/stdlib/fs.js +161 -0
- package/interpreter/stdlib/http.js +92 -0
- package/interpreter/stdlib/json.js +70 -0
- package/interpreter/stdlib/math.js +309 -0
- package/interpreter/stdlib/object.js +142 -0
- package/interpreter/stdlib/path.js +69 -0
- package/interpreter/stdlib/regex.js +134 -0
- package/interpreter/stdlib/string.js +260 -0
- package/interpreter/suggestions.js +46 -0
- package/lexer/Lexer.js +245 -0
- package/lexer/TokenTypes.js +131 -0
- package/lexer/createToken.js +11 -0
- package/lexer/tokenizers/commentTokenizer.js +45 -0
- package/lexer/tokenizers/literalTokenizer.js +163 -0
- package/lexer/tokenizers/symbolTokenizer.js +69 -0
- package/lexer/tokenizers/whitespaceTokenizer.js +36 -0
- package/package.json +29 -11
- package/parser/ASTNodes.js +448 -0
- package/parser/Parser.js +188 -0
- package/parser/expressions/atomicExpressions.js +165 -0
- package/parser/expressions/conditionalExpressions.js +0 -0
- package/parser/expressions/operatorExpressions.js +79 -0
- package/parser/expressions/primaryExpressions.js +77 -0
- package/parser/parseStatement.js +184 -0
- package/parser/parserExpressions.js +115 -0
- package/parser/parserUtils.js +19 -0
- package/parser/statements/controlFlowParsers.js +106 -0
- package/parser/statements/functionParsers.js +314 -0
- package/parser/statements/moduleParsers.js +57 -0
- package/parser/statements/patternMatchParsers.js +124 -0
- package/parser/statements/variableParsers.js +155 -0
- package/repl.js +325 -0
- package/test.js +47 -1
- package/tools/PrettyPrinter.js +3 -0
- package/tools/convert/Args.js +46 -0
- package/tools/convert/Registry.js +91 -0
- package/tools/convert/Transpiler.js +78 -0
- package/tools/convert/plugins/README.md +66 -0
- package/tools/convert/plugins/alya/index.js +10 -0
- package/tools/convert/plugins/alya/to_alya.js +289 -0
- package/tools/convert/plugins/alya/visitors/expressions.js +257 -0
- package/tools/convert/plugins/alya/visitors/statements.js +403 -0
- package/tools/convert/plugins/base_converter.js +228 -0
- package/tools/convert/plugins/javascript/index.js +10 -0
- package/tools/convert/plugins/javascript/mimo_runtime.js +265 -0
- package/tools/convert/plugins/javascript/to_js.js +155 -0
- package/tools/convert/plugins/javascript/visitors/expressions.js +197 -0
- package/tools/convert/plugins/javascript/visitors/patterns.js +102 -0
- package/tools/convert/plugins/javascript/visitors/statements.js +236 -0
- package/tools/convert/plugins/python/index.js +10 -0
- package/tools/convert/plugins/python/mimo_runtime.py +811 -0
- package/tools/convert/plugins/python/to_py.js +329 -0
- package/tools/convert/plugins/python/visitors/expressions.js +272 -0
- package/tools/convert/plugins/python/visitors/patterns.js +100 -0
- package/tools/convert/plugins/python/visitors/statements.js +257 -0
- package/tools/convert.js +102 -0
- package/tools/format/CommentAttacher.js +190 -0
- package/tools/format/CommentLexer.js +152 -0
- package/tools/format/Printer.js +849 -0
- package/tools/format/config.js +107 -0
- package/tools/formatter.js +169 -0
- package/tools/lint/Linter.js +391 -0
- package/tools/lint/config.js +114 -0
- package/tools/lint/rules/consistent-return.js +62 -0
- package/tools/lint/rules/max-depth.js +56 -0
- package/tools/lint/rules/no-empty-function.js +45 -0
- package/tools/lint/rules/no-magic-numbers.js +46 -0
- package/tools/lint/rules/no-shadow.js +113 -0
- package/tools/lint/rules/no-unused-vars.js +26 -0
- package/tools/lint/rules/prefer-const.js +19 -0
- package/tools/linter.js +261 -0
- package/tools/replFormatter.js +93 -0
- package/tools/stamp-version.js +32 -0
- package/web/index.js +9 -0
- package/bun.lockb +0 -0
- package/cli.js +0 -84
- package/compiler/execute/interpreter.js +0 -68
- package/compiler/execute/interpreters/binary.js +0 -12
- package/compiler/execute/interpreters/call.js +0 -10
- package/compiler/execute/interpreters/if.js +0 -10
- package/compiler/execute/interpreters/try-catch.js +0 -10
- package/compiler/execute/interpreters/while.js +0 -8
- package/compiler/execute/utils/createfunction.js +0 -11
- package/compiler/execute/utils/evaluate.js +0 -20
- package/compiler/execute/utils/operate.js +0 -23
- package/compiler/lexer/processToken.js +0 -40
- package/compiler/lexer/tokenTypes.js +0 -4
- package/compiler/lexer/tokenizer.js +0 -63
- package/compiler/parser/expression/comparison.js +0 -18
- package/compiler/parser/expression/identifier.js +0 -29
- package/compiler/parser/expression/number.js +0 -10
- package/compiler/parser/expression/operator.js +0 -21
- package/compiler/parser/expression/punctuation.js +0 -31
- package/compiler/parser/expression/string.js +0 -6
- package/compiler/parser/parseExpression.js +0 -27
- package/compiler/parser/parseStatement.js +0 -35
- package/compiler/parser/parser.js +0 -16
- package/compiler/parser/statement/call.js +0 -26
- package/compiler/parser/statement/function.js +0 -29
- package/compiler/parser/statement/if.js +0 -34
- package/compiler/parser/statement/return.js +0 -10
- package/compiler/parser/statement/set.js +0 -11
- package/compiler/parser/statement/show.js +0 -10
- package/compiler/parser/statement/try-catch.js +0 -25
- package/compiler/parser/statement/while.js +0 -22
- package/converter/go/convert.js +0 -110
- package/converter/js/convert.js +0 -107
- package/i.js +0 -30
- package/jsconfig.json +0 -27
- package/webpack.config.js +0 -9
package/bun.lock
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 0,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "mimo-next",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"@types/bun": "latest",
|
|
9
|
+
"esbuild": "^0.25.5",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
"packages": {
|
|
14
|
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="],
|
|
15
|
+
|
|
16
|
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="],
|
|
17
|
+
|
|
18
|
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.5", "", { "os": "android", "cpu": "arm64" }, "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg=="],
|
|
19
|
+
|
|
20
|
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.5", "", { "os": "android", "cpu": "x64" }, "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw=="],
|
|
21
|
+
|
|
22
|
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ=="],
|
|
23
|
+
|
|
24
|
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ=="],
|
|
25
|
+
|
|
26
|
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw=="],
|
|
27
|
+
|
|
28
|
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw=="],
|
|
29
|
+
|
|
30
|
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.5", "", { "os": "linux", "cpu": "arm" }, "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw=="],
|
|
31
|
+
|
|
32
|
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg=="],
|
|
33
|
+
|
|
34
|
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA=="],
|
|
35
|
+
|
|
36
|
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg=="],
|
|
37
|
+
|
|
38
|
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg=="],
|
|
39
|
+
|
|
40
|
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ=="],
|
|
41
|
+
|
|
42
|
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA=="],
|
|
43
|
+
|
|
44
|
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="],
|
|
45
|
+
|
|
46
|
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, ""],
|
|
47
|
+
|
|
48
|
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="],
|
|
49
|
+
|
|
50
|
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.5", "", { "os": "none", "cpu": "x64" }, "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ=="],
|
|
51
|
+
|
|
52
|
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw=="],
|
|
53
|
+
|
|
54
|
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg=="],
|
|
55
|
+
|
|
56
|
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA=="],
|
|
57
|
+
|
|
58
|
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw=="],
|
|
59
|
+
|
|
60
|
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ=="],
|
|
61
|
+
|
|
62
|
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g=="],
|
|
63
|
+
|
|
64
|
+
"@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
|
|
65
|
+
|
|
66
|
+
"@types/node": ["@types/node@25.3.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A=="],
|
|
67
|
+
|
|
68
|
+
"bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
|
|
69
|
+
|
|
70
|
+
"esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": "bin/esbuild" }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="],
|
|
71
|
+
|
|
72
|
+
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
|
73
|
+
}
|
|
74
|
+
}
|
package/index.js
CHANGED
|
@@ -1,41 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @file The Mimo library entry point for NODE.JS environments.
|
|
3
|
+
* Exports the Mimo class and Node.js-specific helpers.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Interpreter } from './interpreter/index.js';
|
|
7
|
+
import { Lexer } from './lexer/Lexer.js';
|
|
8
|
+
import { Parser } from './parser/Parser.js';
|
|
9
|
+
import { MimoError } from './interpreter/MimoError.js';
|
|
10
|
+
import { nodeAdapter } from './adapters/nodeAdapter.js';
|
|
11
|
+
|
|
12
|
+
export class Mimo {
|
|
13
|
+
constructor(adapter = nodeAdapter) {
|
|
14
|
+
this.interpreter = new Interpreter(adapter);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
run(source, filePath) {
|
|
18
|
+
if (!filePath) {
|
|
19
|
+
throw new Error("Mimo.run() requires a filePath argument in a Node.js environment for module resolution.");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const lexer = new Lexer(source, filePath);
|
|
24
|
+
const tokens = [];
|
|
25
|
+
let token;
|
|
26
|
+
while ((token = lexer.nextToken()) !== null) {
|
|
27
|
+
tokens.push(token);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const parser = new Parser(tokens, filePath);
|
|
31
|
+
this.interpreter.errorHandler.addSourceFile(filePath, source);
|
|
32
|
+
parser.setErrorHandler(this.interpreter.errorHandler);
|
|
33
|
+
const ast = parser.parse();
|
|
34
|
+
|
|
35
|
+
const result = this.interpreter.interpret(ast, filePath);
|
|
36
|
+
|
|
37
|
+
return result;
|
|
38
|
+
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (error instanceof MimoError) {
|
|
41
|
+
throw error.format(this.interpreter.errorHandler.getLine(error.location.file, error.location.line));
|
|
42
|
+
} else {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
|
|
50
|
+
// Export Node.js specific helpers and other components
|
|
51
|
+
export { Interpreter, Lexer, Parser, MimoError, nodeAdapter };
|
package/index.web.js
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Mimo library entry point for BROWSER environments.
|
|
3
|
+
* It exports the Mimo class but avoids importing any Node.js-specific modules.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Interpreter } from './interpreter/index.js';
|
|
7
|
+
import { Lexer } from './lexer/Lexer.js';
|
|
8
|
+
import { Parser } from './parser/Parser.js';
|
|
9
|
+
import { MimoError } from './interpreter/MimoError.js';
|
|
10
|
+
import { Linter } from './tools/lint/Linter.js';
|
|
11
|
+
import { PrettyPrinter } from './tools/PrettyPrinter.js';
|
|
12
|
+
import { extractComments } from './tools/format/CommentLexer.js';
|
|
13
|
+
import { attachComments } from './tools/format/CommentAttacher.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Tokenizer module - handles lexical analysis
|
|
17
|
+
*/
|
|
18
|
+
export class MimoTokenizer {
|
|
19
|
+
constructor(source, filePath = '/playground.mimo') {
|
|
20
|
+
this.source = source;
|
|
21
|
+
this.filePath = filePath;
|
|
22
|
+
this.lexer = new Lexer(source, filePath);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
tokenize() {
|
|
26
|
+
const tokens = [];
|
|
27
|
+
let token;
|
|
28
|
+
while ((token = this.lexer.nextToken()) !== null) {
|
|
29
|
+
tokens.push(token);
|
|
30
|
+
}
|
|
31
|
+
return tokens;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parser module - handles syntax analysis
|
|
37
|
+
*/
|
|
38
|
+
export class MimoParser {
|
|
39
|
+
constructor(tokens, filePath = '/playground.mimo', errorHandler = null) {
|
|
40
|
+
this.tokens = tokens;
|
|
41
|
+
this.filePath = filePath;
|
|
42
|
+
this.parser = new Parser(tokens, filePath);
|
|
43
|
+
if (errorHandler) {
|
|
44
|
+
this.parser.setErrorHandler(errorHandler);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
parse() {
|
|
49
|
+
return this.parser.parse();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* AST Hook Manager - manages AST interception callbacks
|
|
55
|
+
*/
|
|
56
|
+
export class ASTHookManager {
|
|
57
|
+
constructor() {
|
|
58
|
+
this.hooks = [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Register a callback to receive the AST
|
|
63
|
+
* @param {Function} callback - Function that receives (ast, filePath) as parameters
|
|
64
|
+
* @param {string} [name] - Optional name for the hook
|
|
65
|
+
*/
|
|
66
|
+
registerHook(callback, name = null) {
|
|
67
|
+
if (typeof callback !== 'function') {
|
|
68
|
+
throw new Error('AST hook must be a function');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const hook = {
|
|
72
|
+
callback,
|
|
73
|
+
name: name || `hook_${this.hooks.length}`,
|
|
74
|
+
id: Date.now() + Math.random()
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
this.hooks.push(hook);
|
|
78
|
+
return hook.id;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Unregister a hook by ID
|
|
83
|
+
* @param {string|number} hookId - The ID returned by registerHook
|
|
84
|
+
*/
|
|
85
|
+
unregisterHook(hookId) {
|
|
86
|
+
this.hooks = this.hooks.filter(hook => hook.id !== hookId);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Unregister all hooks with a specific name
|
|
91
|
+
* @param {string} name - The name of hooks to remove
|
|
92
|
+
*/
|
|
93
|
+
unregisterHooksByName(name) {
|
|
94
|
+
this.hooks = this.hooks.filter(hook => hook.name !== name);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Clear all registered hooks
|
|
99
|
+
*/
|
|
100
|
+
clearHooks() {
|
|
101
|
+
this.hooks = [];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Execute all registered hooks with the AST
|
|
106
|
+
* @param {Object} ast - The parsed AST
|
|
107
|
+
* @param {string} filePath - The file path
|
|
108
|
+
*/
|
|
109
|
+
executeHooks(ast, filePath) {
|
|
110
|
+
for (const hook of this.hooks) {
|
|
111
|
+
try {
|
|
112
|
+
hook.callback(ast, filePath);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(`Error in AST hook '${hook.name}':`, error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get list of registered hooks
|
|
121
|
+
*/
|
|
122
|
+
getHooks() {
|
|
123
|
+
return this.hooks.map(hook => ({
|
|
124
|
+
id: hook.id,
|
|
125
|
+
name: hook.name
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Main Mimo class with modular design and AST interception
|
|
132
|
+
*/
|
|
133
|
+
export class Mimo {
|
|
134
|
+
constructor(adapter, options = {}) {
|
|
135
|
+
if (!adapter) {
|
|
136
|
+
throw new Error("Mimo constructor requires an adapter object.");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.interpreter = new Interpreter(adapter);
|
|
140
|
+
this.astHookManager = new ASTHookManager();
|
|
141
|
+
|
|
142
|
+
// Configuration options
|
|
143
|
+
this.options = {
|
|
144
|
+
enableASTHooks: options.enableASTHooks !== false,
|
|
145
|
+
throwOnHookError: options.throwOnHookError || false,
|
|
146
|
+
...options
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Register an AST hook
|
|
152
|
+
* @param {Function} callback - Function that receives (ast, filePath)
|
|
153
|
+
* @param {string} [name] - Optional name for the hook
|
|
154
|
+
* @returns {string|number} Hook ID for later removal
|
|
155
|
+
*/
|
|
156
|
+
onAST(callback, name) {
|
|
157
|
+
return this.astHookManager.registerHook(callback, name);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Remove an AST hook by ID
|
|
162
|
+
* @param {string|number} hookId - The hook ID
|
|
163
|
+
*/
|
|
164
|
+
offAST(hookId) {
|
|
165
|
+
this.astHookManager.unregisterHook(hookId);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get the AST hook manager for advanced hook management
|
|
170
|
+
*/
|
|
171
|
+
getASTHookManager() {
|
|
172
|
+
return this.astHookManager;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Tokenize source code
|
|
177
|
+
* @param {string} source - The source code
|
|
178
|
+
* @param {string} [filePath] - Optional file path
|
|
179
|
+
* @returns {Array} Array of tokens
|
|
180
|
+
*/
|
|
181
|
+
tokenize(source, filePath = '/playground.mimo') {
|
|
182
|
+
const tokenizer = new MimoTokenizer(source, filePath);
|
|
183
|
+
return tokenizer.tokenize();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Parse tokens into an AST
|
|
188
|
+
* @param {Array} tokens - Array of tokens
|
|
189
|
+
* @param {string} [filePath] - Optional file path
|
|
190
|
+
* @returns {Object} The parsed AST
|
|
191
|
+
*/
|
|
192
|
+
parse(tokens, filePath = '/playground.mimo') {
|
|
193
|
+
const parser = new MimoParser(tokens, filePath, this.interpreter.errorHandler);
|
|
194
|
+
this.interpreter.errorHandler.addSourceFile(filePath, ''); // Add empty source for now
|
|
195
|
+
return parser.parse();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Parse source code directly into an AST
|
|
200
|
+
* @param {string} source - The source code
|
|
201
|
+
* @param {string} [filePath] - Optional file path
|
|
202
|
+
* @returns {Object} The parsed AST
|
|
203
|
+
*/
|
|
204
|
+
parseSource(source, filePath = '/playground.mimo') {
|
|
205
|
+
const tokens = this.tokenize(source, filePath);
|
|
206
|
+
this.interpreter.errorHandler.addSourceFile(filePath, source);
|
|
207
|
+
const parser = new MimoParser(tokens, filePath, this.interpreter.errorHandler);
|
|
208
|
+
const ast = parser.parse();
|
|
209
|
+
|
|
210
|
+
// Execute AST hooks if enabled
|
|
211
|
+
if (this.options.enableASTHooks) {
|
|
212
|
+
this.astHookManager.executeHooks(ast, filePath);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return ast;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Run source code with full pipeline
|
|
220
|
+
* @param {string} source - The source code
|
|
221
|
+
* @param {string} [filePath] - Optional file path
|
|
222
|
+
* @returns {*} The execution result
|
|
223
|
+
*/
|
|
224
|
+
run(source, filePath = '/playground.mimo') {
|
|
225
|
+
const effectivePath = filePath;
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
// Tokenize
|
|
229
|
+
const tokens = this.tokenize(source, effectivePath);
|
|
230
|
+
|
|
231
|
+
// Parse and get AST
|
|
232
|
+
const ast = this.parseSource(source, effectivePath);
|
|
233
|
+
|
|
234
|
+
// Interpret
|
|
235
|
+
const result = this.interpreter.interpret(ast, effectivePath);
|
|
236
|
+
|
|
237
|
+
return result;
|
|
238
|
+
|
|
239
|
+
} catch (error) {
|
|
240
|
+
if (error instanceof MimoError) {
|
|
241
|
+
throw error.format(this.interpreter.errorHandler.getLine(error.location.file, error.location.line));
|
|
242
|
+
} else {
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Run pre-parsed AST
|
|
250
|
+
* @param {Object} ast - The parsed AST
|
|
251
|
+
* @param {string} [filePath] - Optional file path
|
|
252
|
+
* @returns {*} The execution result
|
|
253
|
+
*/
|
|
254
|
+
runAST(ast, filePath = '/playground.mimo') {
|
|
255
|
+
try {
|
|
256
|
+
return this.interpreter.interpret(ast, filePath);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
if (error instanceof MimoError) {
|
|
259
|
+
throw error.format(this.interpreter.errorHandler.getLine(error.location.file, error.location.line));
|
|
260
|
+
} else {
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Export all classes and modules
|
|
268
|
+
export { Interpreter } from './interpreter/index.js';
|
|
269
|
+
export { Lexer } from './lexer/Lexer.js';
|
|
270
|
+
export { Parser } from './parser/Parser.js';
|
|
271
|
+
export { MimoError } from './interpreter/MimoError.js';
|
|
272
|
+
export { Linter } from './tools/lint/Linter.js';
|
|
273
|
+
export { PrettyPrinter } from './tools/PrettyPrinter.js';
|
|
274
|
+
|
|
275
|
+
const DEFAULT_LINT_RULES = {
|
|
276
|
+
'no-unused-vars': true,
|
|
277
|
+
'prefer-const': true,
|
|
278
|
+
'no-magic-numbers': false
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export function lintSource(source, filePath = '/playground.mimo', rules = {}) {
|
|
282
|
+
const enabledRules = { ...DEFAULT_LINT_RULES, ...rules };
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const lexer = new Lexer(source, filePath);
|
|
286
|
+
const tokens = [];
|
|
287
|
+
let token;
|
|
288
|
+
while ((token = lexer.nextToken()) !== null) {
|
|
289
|
+
tokens.push(token);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const parser = new Parser(tokens, filePath);
|
|
293
|
+
const ast = parser.parse();
|
|
294
|
+
|
|
295
|
+
const linter = new Linter({ rules: enabledRules });
|
|
296
|
+
const messages = linter.verify(ast, source, filePath);
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
ok: true,
|
|
300
|
+
file: filePath,
|
|
301
|
+
messages: messages.map(msg => ({
|
|
302
|
+
line: msg.line,
|
|
303
|
+
column: msg.column,
|
|
304
|
+
endColumn: msg.endColumn,
|
|
305
|
+
message: msg.message,
|
|
306
|
+
ruleId: msg.ruleId,
|
|
307
|
+
severity: 'warning'
|
|
308
|
+
}))
|
|
309
|
+
};
|
|
310
|
+
} catch (err) {
|
|
311
|
+
// Convert syntax/parse errors into lint diagnostics
|
|
312
|
+
return {
|
|
313
|
+
ok: false,
|
|
314
|
+
file: filePath,
|
|
315
|
+
error: {
|
|
316
|
+
message: err.message,
|
|
317
|
+
line: err.location?.line || 1,
|
|
318
|
+
column: err.location?.column || 1
|
|
319
|
+
},
|
|
320
|
+
messages: [{
|
|
321
|
+
line: err.location?.line || 1,
|
|
322
|
+
column: err.location?.column || 1,
|
|
323
|
+
endColumn: (err.location?.column || 1) + 1,
|
|
324
|
+
message: err.message,
|
|
325
|
+
ruleId: 'syntax-error',
|
|
326
|
+
severity: 'error'
|
|
327
|
+
}]
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function formatSource(source) {
|
|
333
|
+
try {
|
|
334
|
+
// Extract comments from raw source (formatter-only path)
|
|
335
|
+
const { comments } = extractComments(source);
|
|
336
|
+
|
|
337
|
+
const lexer = new Lexer(source, '/format.mimo');
|
|
338
|
+
const tokens = [];
|
|
339
|
+
let token;
|
|
340
|
+
while ((token = lexer.nextToken()) !== null) {
|
|
341
|
+
tokens.push(token);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const parser = new Parser(tokens, '/format.mimo');
|
|
345
|
+
const ast = parser.parse();
|
|
346
|
+
|
|
347
|
+
// Attach extracted comments to AST nodes
|
|
348
|
+
attachComments(ast, comments);
|
|
349
|
+
|
|
350
|
+
const printer = new PrettyPrinter();
|
|
351
|
+
// A8: format() already normalises the trailing newline
|
|
352
|
+
const formatted = printer.format(ast);
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
ok: true,
|
|
356
|
+
formatted,
|
|
357
|
+
};
|
|
358
|
+
} catch (err) {
|
|
359
|
+
return {
|
|
360
|
+
ok: false,
|
|
361
|
+
error: err.message,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export class BuiltinFunction {
|
|
2
|
+
constructor(name, implementation, arity) {
|
|
3
|
+
this.name = name;
|
|
4
|
+
this.implementation = implementation;
|
|
5
|
+
this.arity = arity;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
call(interpreter, args, callNode) { // Add callNode parameter
|
|
9
|
+
// Handle variable arity functions (arity can be an array [min, max])
|
|
10
|
+
if (Array.isArray(this.arity)) {
|
|
11
|
+
const [min, max] = this.arity;
|
|
12
|
+
if (args.length < min || args.length > max) {
|
|
13
|
+
throw interpreter.errorHandler.createRuntimeError(
|
|
14
|
+
`Built-in function '${this.name}' expects ${min}-${max} arguments but received ${args.length}.`,
|
|
15
|
+
callNode,
|
|
16
|
+
'BUILTIN001',
|
|
17
|
+
`Check the arguments provided to built-in function '${this.name}'.`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
if (args.length !== this.arity) {
|
|
22
|
+
throw interpreter.errorHandler.createRuntimeError(
|
|
23
|
+
`Built-in function '${this.name}' expects ${this.arity} arguments but received ${args.length}.`,
|
|
24
|
+
callNode,
|
|
25
|
+
'BUILTIN001',
|
|
26
|
+
`Check the arguments provided to built-in function '${this.name}'.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return this.implementation(args, interpreter, callNode); // Pass callNode to implementation
|
|
31
|
+
}
|
|
32
|
+
}
|