mimo-lang 1.0.0 → 1.0.8
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/cli.js +46 -6
- package/compiler/execute/interpreter.js +7 -7
- package/compiler/execute/interpreters/binary.js +1 -1
- package/compiler/execute/interpreters/call.js +1 -1
- package/compiler/execute/interpreters/if.js +2 -2
- package/compiler/execute/interpreters/try-catch.js +1 -0
- package/compiler/execute/interpreters/while.js +2 -2
- package/compiler/execute/utils/createfunction.js +1 -1
- package/compiler/execute/utils/evaluate.js +1 -1
- package/compiler/lexer/processToken.js +1 -1
- package/compiler/parser/expression/comparison.js +1 -1
- package/compiler/parser/expression/identifier.js +1 -1
- package/compiler/parser/expression/operator.js +1 -1
- package/compiler/parser/expression/punctuation.js +1 -1
- package/compiler/parser/parseExpression.js +6 -6
- package/compiler/parser/parseStatement.js +8 -9
- package/compiler/parser/parser.js +1 -1
- package/compiler/parser/statement/call.js +1 -1
- package/compiler/parser/statement/function.js +1 -1
- package/compiler/parser/statement/if.js +2 -2
- package/compiler/parser/statement/return.js +1 -1
- package/compiler/parser/statement/set.js +1 -1
- package/compiler/parser/statement/show.js +1 -1
- package/compiler/parser/statement/try-catch.js +1 -1
- package/compiler/parser/statement/while.js +2 -2
- package/converter/go/convert.js +17 -7
- package/index.js +6 -13
- package/package.json +4 -2
- package/webpack.config.js +9 -0
package/cli.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
4
5
|
import Mimo from "./index.js";
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
// Get the directory of the current script
|
|
8
|
+
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
9
|
+
|
|
10
|
+
// Read the package.json file
|
|
11
|
+
const packageJson = JSON.parse(
|
|
12
|
+
fs.readFileSync(path.join(__dirname, "package.json"), "utf-8")
|
|
13
|
+
);
|
|
14
|
+
const { version } = packageJson;
|
|
6
15
|
|
|
7
16
|
// Check if the user asked for the version
|
|
8
17
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
@@ -10,14 +19,32 @@ if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
|
10
19
|
process.exit(0);
|
|
11
20
|
}
|
|
12
21
|
|
|
22
|
+
// Check if the user asked for help
|
|
23
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
24
|
+
console.log("Usage: mimo [FILENAME] [-o|--output] [-t|--time] [-h|--help] [-q|--quiet] [-d|--debug] [-v|--version]");
|
|
25
|
+
console.log("FILENAME: The file to process.");
|
|
26
|
+
console.log("-o, --output: Generate output file.");
|
|
27
|
+
console.log("-t, --time: Measure execution time.");
|
|
28
|
+
console.log("-h, --help: Show this help message.");
|
|
29
|
+
console.log("-q, --quiet: Suppress all non-essential output.");
|
|
30
|
+
console.log("-d, --debug: Display additional debug information.");
|
|
31
|
+
console.log("-v, --version: Display the version number.");
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
13
35
|
// Check if a filename was provided
|
|
14
36
|
if (process.argv.length < 3) {
|
|
15
|
-
console.error("Error: No file name provided
|
|
16
|
-
console.log("Usage: mimo [FILENAME]");
|
|
37
|
+
console.error("Error: No file name provided.\n");
|
|
38
|
+
console.log("Usage: mimo [FILENAME] [-o|--output] [-t|--time] [-h|--help] [-q|--quiet] [-d|--debug] [-v|--version]");
|
|
39
|
+
console.log("Use the --help flag for more information.\n\n");
|
|
17
40
|
process.exit(1);
|
|
18
41
|
}
|
|
19
42
|
|
|
20
43
|
const filename = process.argv[2];
|
|
44
|
+
const shouldGenerateOutput = process.argv.includes("-o") || process.argv.includes("--output");
|
|
45
|
+
const shouldMeasureTime = process.argv.includes("-t") || process.argv.includes("--time");
|
|
46
|
+
const shouldSuppressOutput = process.argv.includes("-q") || process.argv.includes("--quiet");
|
|
47
|
+
const shouldDisplayDebugInfo = process.argv.includes("-d") || process.argv.includes("--debug");
|
|
21
48
|
|
|
22
49
|
// Check if the file exists
|
|
23
50
|
if (!fs.existsSync(filename)) {
|
|
@@ -37,8 +64,21 @@ try {
|
|
|
37
64
|
// Run the code
|
|
38
65
|
const mimo = new Mimo();
|
|
39
66
|
try {
|
|
40
|
-
|
|
67
|
+
if (shouldMeasureTime) console.time("Execution time");
|
|
68
|
+
|
|
69
|
+
let { program } = await mimo.run(code);
|
|
70
|
+
|
|
71
|
+
if (shouldMeasureTime) console.timeEnd("Execution time");
|
|
72
|
+
|
|
73
|
+
if (shouldGenerateOutput) {
|
|
74
|
+
const outputFilename = path.join(
|
|
75
|
+
path.dirname(filename),
|
|
76
|
+
path.basename(filename, path.extname(filename)) + ".js"
|
|
77
|
+
);
|
|
78
|
+
fs.writeFileSync(outputFilename, mimo.toJS(program), "utf-8");
|
|
79
|
+
if (!shouldSuppressOutput) console.log(`Output written to: ${outputFilename}`);
|
|
80
|
+
}
|
|
41
81
|
} catch (err) {
|
|
42
|
-
console.error("Error running code:", err
|
|
82
|
+
if (shouldDisplayDebugInfo) console.error("Error running code:", err);
|
|
43
83
|
process.exit(1);
|
|
44
|
-
}
|
|
84
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { interpretBinary } from "./interpreters/binary";
|
|
2
|
-
import { interpretCall } from "./interpreters/call";
|
|
3
|
-
import { interpretIf } from "./interpreters/if";
|
|
4
|
-
import { interpretTryCatch } from "./interpreters/try-catch";
|
|
5
|
-
import { interpretWhile } from "./interpreters/while";
|
|
6
|
-
import { createFunction } from "./utils/createfunction";
|
|
7
|
-
import { evaluate } from "./utils/evaluate";
|
|
1
|
+
import { interpretBinary } from "./interpreters/binary.js";
|
|
2
|
+
import { interpretCall } from "./interpreters/call.js";
|
|
3
|
+
import { interpretIf } from "./interpreters/if.js";
|
|
4
|
+
import { interpretTryCatch } from "./interpreters/try-catch.js";
|
|
5
|
+
import { interpretWhile } from "./interpreters/while.js";
|
|
6
|
+
import { createFunction } from "./utils/createfunction.js";
|
|
7
|
+
import { evaluate } from "./utils/evaluate.js";
|
|
8
8
|
|
|
9
9
|
export async function interpretStatement(statement, env) {
|
|
10
10
|
if (Array.isArray(statement)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { interpretStatement } from "../interpreter";
|
|
2
|
-
import { evaluate } from "../utils/evaluate";
|
|
1
|
+
import { interpretStatement } from "../interpreter.js";
|
|
2
|
+
import { evaluate } from "../utils/evaluate.js";
|
|
3
3
|
|
|
4
4
|
export async function interpretIf(statement, env) {
|
|
5
5
|
if (evaluate(statement.condition, env)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { interpretStatement } from "../interpreter";
|
|
2
|
-
import { evaluate } from "../utils/evaluate";
|
|
1
|
+
import { interpretStatement } from "../interpreter.js";
|
|
2
|
+
import { evaluate } from "../utils/evaluate.js";
|
|
3
3
|
|
|
4
4
|
export async function interpretWhile(statement, env) {
|
|
5
5
|
while (evaluate(statement.condition, env)) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { comparisonExpression } from "./expression/comparison";
|
|
2
|
-
import { identifierExpression } from "./expression/identifier";
|
|
3
|
-
import { numberExpression } from "./expression/number";
|
|
4
|
-
import { operatorExpression } from "./expression/operator";
|
|
5
|
-
import { punctuationExpression } from "./expression/punctuation";
|
|
6
|
-
import { stringExpression } from "./expression/string";
|
|
1
|
+
import { comparisonExpression } from "./expression/comparison.js";
|
|
2
|
+
import { identifierExpression } from "./expression/identifier.js";
|
|
3
|
+
import { numberExpression } from "./expression/number.js";
|
|
4
|
+
import { operatorExpression } from "./expression/operator.js";
|
|
5
|
+
import { punctuationExpression } from "./expression/punctuation.js";
|
|
6
|
+
import { stringExpression } from "./expression/string.js";
|
|
7
7
|
|
|
8
8
|
export const parseExpression = (tokens, index) => {
|
|
9
9
|
// console.log("expression..", tokens[index].type, tokens[index].value);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { showStatement } from "./statement/show";
|
|
1
|
+
import { ifStatement } from "./statement/if.js";
|
|
2
|
+
import { setStatement } from "./statement/set.js";
|
|
3
|
+
import { tryCatchStatement } from "./statement/try-catch.js";
|
|
4
|
+
import { whileStatement } from "./statement/while.js";
|
|
5
|
+
import { functionStatement } from "./statement/function.js";
|
|
6
|
+
import { callStatement } from "./statement/call.js";
|
|
7
|
+
import { returnStatement } from "./statement/return.js";
|
|
8
|
+
import { showStatement } from "./statement/show.js";
|
|
10
9
|
|
|
11
10
|
export const parseStatement = (tokens, index) => {
|
|
12
11
|
let statement = { type: "statement" };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression";
|
|
2
|
-
import { parseStatement } from "../parseStatement";
|
|
1
|
+
import { parseExpression } from "../parseExpression.js";
|
|
2
|
+
import { parseStatement } from "../parseStatement.js";
|
|
3
3
|
|
|
4
4
|
export function ifStatement(tokens, index) {
|
|
5
5
|
let statement = { type: "if" };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression";
|
|
2
|
-
import { parseStatement } from "../parseStatement";
|
|
1
|
+
import { parseExpression } from "../parseExpression.js";
|
|
2
|
+
import { parseStatement } from "../parseStatement.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export const whileStatement = (tokens, index) => {
|
package/converter/go/convert.js
CHANGED
|
@@ -29,20 +29,31 @@ function generateGoCodeFromAst(node) {
|
|
|
29
29
|
|
|
30
30
|
export function generateGoCodeFromAstArray(ast) {
|
|
31
31
|
declaredVariables = new Set();
|
|
32
|
-
const
|
|
32
|
+
const functionCode = ast
|
|
33
|
+
.filter((node) => node.type === "function")
|
|
34
|
+
.map(generateGoCodeFromAst)
|
|
35
|
+
.join("\n\n");
|
|
36
|
+
const otherCode = ast
|
|
37
|
+
.filter((node) => node.type !== "function")
|
|
38
|
+
.map(generateGoCodeFromAst)
|
|
39
|
+
.join("\n");
|
|
33
40
|
return formatGoCode(`
|
|
34
41
|
package main
|
|
35
42
|
|
|
36
43
|
import "fmt"
|
|
37
44
|
|
|
38
|
-
${
|
|
45
|
+
${functionCode}
|
|
46
|
+
|
|
47
|
+
func main() {
|
|
48
|
+
${otherCode}
|
|
49
|
+
}
|
|
39
50
|
`);
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
function generateFunction(node) {
|
|
43
|
-
const params = node.params.join(", ");
|
|
54
|
+
const params = node.params.map((p) => `${p} any`).join(", ");
|
|
44
55
|
const body = node.body.map(generateGoCodeFromAst).join("\n");
|
|
45
|
-
return `func ${node.name}(${params})
|
|
56
|
+
return `func ${node.name}(${params}) any {\n${body}\n}`;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
function generateAssignment(node) {
|
|
@@ -51,7 +62,7 @@ function generateAssignment(node) {
|
|
|
51
62
|
prefix = "var ";
|
|
52
63
|
declaredVariables.add(node.target);
|
|
53
64
|
}
|
|
54
|
-
return `${prefix}${node.target}
|
|
65
|
+
return `${prefix}${node.target} = ${generateGoCodeFromAst(node.value)}`;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
function generateWhile(node) {
|
|
@@ -79,12 +90,11 @@ function generateCall(node) {
|
|
|
79
90
|
prefix = "var ";
|
|
80
91
|
declaredVariables.add(node.target);
|
|
81
92
|
}
|
|
82
|
-
callCode = `${prefix}${node.target}
|
|
93
|
+
callCode = `${prefix}${node.target} = ${callCode}`;
|
|
83
94
|
}
|
|
84
95
|
return callCode;
|
|
85
96
|
}
|
|
86
97
|
|
|
87
|
-
|
|
88
98
|
function generatePrint(node) {
|
|
89
99
|
return `fmt.Println(${generateGoCodeFromAst(node.value)})`;
|
|
90
100
|
}
|
package/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { generateTokens } from "./compiler/lexer/tokenizer";
|
|
2
|
-
import { parseTokens } from "./compiler/parser/parser";
|
|
3
|
-
import { interpret } from "./compiler/execute/interpreter";
|
|
4
|
-
import {
|
|
5
|
-
import { generateCodeJsFromAstArray } from "./converter/js/convert";
|
|
6
|
-
import fs from "fs";
|
|
1
|
+
import { generateTokens } from "./compiler/lexer/tokenizer.js";
|
|
2
|
+
import { parseTokens } from "./compiler/parser/parser.js";
|
|
3
|
+
import { interpret } from "./compiler/execute/interpreter.js";
|
|
4
|
+
import { generateCodeJsFromAstArray } from "./converter/js/convert.js";
|
|
7
5
|
|
|
8
6
|
// The main class for the Mimo language
|
|
9
7
|
export default class Mimo {
|
|
@@ -31,18 +29,13 @@ export default class Mimo {
|
|
|
31
29
|
async run(code) {
|
|
32
30
|
const tokens = await this.tokenize(code);
|
|
33
31
|
const program = await this.parse(tokens);
|
|
34
|
-
|
|
32
|
+
const env = await this.interpret(program);
|
|
33
|
+
return { program, env };
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
// Convert the AST to JavaScript code
|
|
38
37
|
toJS(ast) {
|
|
39
38
|
return generateCodeJsFromAstArray(ast);
|
|
40
39
|
}
|
|
41
|
-
|
|
42
|
-
// Convert the AST to Go code
|
|
43
|
-
toGO(ast) {
|
|
44
|
-
return generateGoCodeFromAstArray(ast);
|
|
45
|
-
}
|
|
46
40
|
}
|
|
47
41
|
|
|
48
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mimo-lang",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "A programming language made in javascript mostly for learning purposes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"programing language"
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"mimo": "./cli.js"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"
|
|
17
|
+
"mimo": "bun cli.js",
|
|
18
|
+
"dev": "bun index.js",
|
|
19
|
+
"test": "bun test/index.js"
|
|
18
20
|
},
|
|
19
21
|
"devDependencies": {
|
|
20
22
|
"@types/bun": "latest"
|