mimo-lang 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/README.md +15 -0
- package/bun.lockb +0 -0
- package/cli.js +44 -0
- package/compiler/execute/interpreter.js +68 -0
- package/compiler/execute/interpreters/binary.js +12 -0
- package/compiler/execute/interpreters/call.js +10 -0
- package/compiler/execute/interpreters/if.js +10 -0
- package/compiler/execute/interpreters/try-catch.js +9 -0
- package/compiler/execute/interpreters/while.js +8 -0
- package/compiler/execute/utils/createfunction.js +11 -0
- package/compiler/execute/utils/evaluate.js +20 -0
- package/compiler/execute/utils/operate.js +23 -0
- package/compiler/lexer/processToken.js +40 -0
- package/compiler/lexer/tokenTypes.js +4 -0
- package/compiler/lexer/tokenizer.js +63 -0
- package/compiler/parser/expression/comparison.js +18 -0
- package/compiler/parser/expression/identifier.js +29 -0
- package/compiler/parser/expression/number.js +10 -0
- package/compiler/parser/expression/operator.js +21 -0
- package/compiler/parser/expression/punctuation.js +31 -0
- package/compiler/parser/expression/string.js +6 -0
- package/compiler/parser/parseExpression.js +27 -0
- package/compiler/parser/parseStatement.js +36 -0
- package/compiler/parser/parser.js +16 -0
- package/compiler/parser/statement/call.js +26 -0
- package/compiler/parser/statement/function.js +29 -0
- package/compiler/parser/statement/if.js +34 -0
- package/compiler/parser/statement/return.js +10 -0
- package/compiler/parser/statement/set.js +11 -0
- package/compiler/parser/statement/show.js +10 -0
- package/compiler/parser/statement/try-catch.js +25 -0
- package/compiler/parser/statement/while.js +22 -0
- package/converter/go/convert.js +100 -0
- package/converter/js/convert.js +106 -0
- package/index.js +48 -0
- package/jsconfig.json +27 -0
- package/package.json +33 -0
- package/test.js +1 -0
package/README.md
ADDED
package/bun.lockb
ADDED
|
Binary file
|
package/cli.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import Mimo from "./index.js";
|
|
5
|
+
import { version } from "./package.json";
|
|
6
|
+
|
|
7
|
+
// Check if the user asked for the version
|
|
8
|
+
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
9
|
+
console.log(version);
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Check if a filename was provided
|
|
14
|
+
if (process.argv.length < 3) {
|
|
15
|
+
console.error("Error: No file name provided.");
|
|
16
|
+
console.log("Usage: mimo [FILENAME]");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const filename = process.argv[2];
|
|
21
|
+
|
|
22
|
+
// Check if the file exists
|
|
23
|
+
if (!fs.existsSync(filename)) {
|
|
24
|
+
console.error(`Error: File '${filename}' does not exist.`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Read the file
|
|
29
|
+
let code;
|
|
30
|
+
try {
|
|
31
|
+
code = fs.readFileSync(filename, "utf-8");
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error(`Error reading file '${filename}':`, err.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Run the code
|
|
38
|
+
const mimo = new Mimo();
|
|
39
|
+
try {
|
|
40
|
+
mimo.run(code);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error("Error running code:", err.message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
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";
|
|
8
|
+
|
|
9
|
+
export async function interpretStatement(statement, env) {
|
|
10
|
+
if (Array.isArray(statement)) {
|
|
11
|
+
for (let i = 0; i < statement.length; i++) {
|
|
12
|
+
if (await interpretStatement(statement[i], env)) return true;
|
|
13
|
+
}
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (typeof statement === "object") {
|
|
18
|
+
if (statement.type === "try-catch") {
|
|
19
|
+
await interpretTryCatch(statement, env);
|
|
20
|
+
} else {
|
|
21
|
+
await interpretObjectStatement(statement, env);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function interpretObjectStatement(statement, env) {
|
|
27
|
+
switch (statement.type) {
|
|
28
|
+
case "assignment":
|
|
29
|
+
env[statement.target] = evaluate(statement.value, env);
|
|
30
|
+
break;
|
|
31
|
+
case "binary":
|
|
32
|
+
await interpretBinary(statement, env);
|
|
33
|
+
break;
|
|
34
|
+
case "if":
|
|
35
|
+
await interpretIf(statement, env);
|
|
36
|
+
break;
|
|
37
|
+
case "while":
|
|
38
|
+
await interpretWhile(statement, env);
|
|
39
|
+
break;
|
|
40
|
+
case "function":
|
|
41
|
+
env[statement.name] = createFunction(
|
|
42
|
+
statement.params,
|
|
43
|
+
statement.body,
|
|
44
|
+
env
|
|
45
|
+
);
|
|
46
|
+
break;
|
|
47
|
+
case "return":
|
|
48
|
+
env["return"] = evaluate(statement.expression, env);
|
|
49
|
+
return true;
|
|
50
|
+
case "call":
|
|
51
|
+
await interpretCall(statement, env);
|
|
52
|
+
break;
|
|
53
|
+
case "print":
|
|
54
|
+
console.log(evaluate(statement.value, env));
|
|
55
|
+
break;
|
|
56
|
+
default:
|
|
57
|
+
console.log("Unknown statement type", statement.type);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function interpret(program, env = {}) {
|
|
63
|
+
let index = 0;
|
|
64
|
+
while (index < program.length) {
|
|
65
|
+
if (await interpretStatement(program[index++], env)) break;
|
|
66
|
+
}
|
|
67
|
+
return env;
|
|
68
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { evaluate } from "../utils/evaluate";
|
|
2
|
+
|
|
3
|
+
export async function interpretBinary(statement, env) {
|
|
4
|
+
if (env[statement.target] === undefined) {
|
|
5
|
+
env[statement.target] = null;
|
|
6
|
+
}
|
|
7
|
+
env[statement.target] = await operate(
|
|
8
|
+
statement.operator,
|
|
9
|
+
await evaluate(statement.left, env),
|
|
10
|
+
await evaluate(statement.right, env)
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { evaluate } from "../utils/evaluate";
|
|
2
|
+
|
|
3
|
+
export async function interpretCall(statement, env) {
|
|
4
|
+
const func = env[statement.name];
|
|
5
|
+
if (typeof func !== "function") {
|
|
6
|
+
throw new Error(`${statement.name} is not a function`);
|
|
7
|
+
}
|
|
8
|
+
const args = statement.args.map((arg) => evaluate(arg, env));
|
|
9
|
+
env[statement.target] = await func(...args);
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { interpretStatement } from "../interpreter";
|
|
2
|
+
import { evaluate } from "../utils/evaluate";
|
|
3
|
+
|
|
4
|
+
export async function interpretIf(statement, env) {
|
|
5
|
+
if (evaluate(statement.condition, env)) {
|
|
6
|
+
if (await interpretStatement(statement.consequent, env)) return true;
|
|
7
|
+
} else if (statement.alternate) {
|
|
8
|
+
if (await interpretStatement(statement.alternate, env)) return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { interpretStatement } from "../interpreter";
|
|
2
|
+
import { evaluate } from "../utils/evaluate";
|
|
3
|
+
|
|
4
|
+
export async function interpretWhile(statement, env) {
|
|
5
|
+
while (evaluate(statement.condition, env)) {
|
|
6
|
+
if (await interpretStatement(statement.body, env)) return true;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { interpret } from "../interpreter";
|
|
2
|
+
|
|
3
|
+
export function createFunction(params, body, env) {
|
|
4
|
+
return async function (...args) {
|
|
5
|
+
const newEnv = { ...env };
|
|
6
|
+
params.forEach((param, index) => {
|
|
7
|
+
newEnv[param] = args[index] ?? undefined;
|
|
8
|
+
});
|
|
9
|
+
return (await interpret(body, newEnv))["return"];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { operate } from "./operate";
|
|
2
|
+
|
|
3
|
+
export const evaluate = (expression, env) =>
|
|
4
|
+
expression.type === "literal"
|
|
5
|
+
? expression.value
|
|
6
|
+
: expression.type === "variable"
|
|
7
|
+
? env.hasOwnProperty(expression.name)
|
|
8
|
+
? env[expression.name]
|
|
9
|
+
: null
|
|
10
|
+
: expression.type === "list"
|
|
11
|
+
? expression.elements.map((element) => evaluate(element, env))
|
|
12
|
+
: expression.type === "indexAccess"
|
|
13
|
+
? env[expression.name][evaluate(expression.index, env)]
|
|
14
|
+
: expression.type === "binary"
|
|
15
|
+
? operate(
|
|
16
|
+
expression.operator,
|
|
17
|
+
evaluate(expression.left, env),
|
|
18
|
+
evaluate(expression.right, env)
|
|
19
|
+
)
|
|
20
|
+
: null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const operations = new Map([
|
|
2
|
+
["+", (left, right) => left + right],
|
|
3
|
+
["-", (left, right) => left - right],
|
|
4
|
+
["*", (left, right) => left * right],
|
|
5
|
+
["/", (left, right) => left / right],
|
|
6
|
+
["%", (left, right) => left % right],
|
|
7
|
+
["**", (left, right) => left ** right],
|
|
8
|
+
[">", (left, right) => left > right],
|
|
9
|
+
["<", (left, right) => left < right],
|
|
10
|
+
[">=", (left, right) => left >= right],
|
|
11
|
+
["<=", (left, right) => left <= right],
|
|
12
|
+
["==", (left, right) => left == right],
|
|
13
|
+
["!=", (left, right) => left != right],
|
|
14
|
+
["!", (left) => !left],
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
export const operate = (operator, left, right) => {
|
|
18
|
+
const operation = operations.get(operator);
|
|
19
|
+
if (!operation) {
|
|
20
|
+
throw new Error(`Invalid operator: ${operator}`);
|
|
21
|
+
}
|
|
22
|
+
return operation(left, right);
|
|
23
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// processToken.js
|
|
2
|
+
|
|
3
|
+
import { OPERATORS } from "./tokenTypes";
|
|
4
|
+
|
|
5
|
+
export const isOperator = (char) => OPERATORS.includes(char);
|
|
6
|
+
|
|
7
|
+
export const processToken = (currentToken, currentType, tokens) => {
|
|
8
|
+
if (currentToken) {
|
|
9
|
+
tokens.push({ type: currentType, value: currentToken });
|
|
10
|
+
return { currentToken: "", currentType: null };
|
|
11
|
+
}
|
|
12
|
+
return { currentToken, currentType };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const processStringToken = (inString, currentToken, tokens) => {
|
|
16
|
+
inString = !inString;
|
|
17
|
+
if (!inString) {
|
|
18
|
+
tokens.push({ type: "string", value: currentToken });
|
|
19
|
+
currentToken = "";
|
|
20
|
+
}
|
|
21
|
+
return { inString, currentToken };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const processOperatorToken = (char, index, input, currentType, currentToken, tokens) => {
|
|
25
|
+
if (currentToken) {
|
|
26
|
+
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
currentType = "operator";
|
|
31
|
+
currentToken += char;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if (index < input.length - 1 && isOperator(input[index + 1])) {
|
|
35
|
+
currentToken += input[index + 1];
|
|
36
|
+
index++; // Skip the next operator character
|
|
37
|
+
}
|
|
38
|
+
tokens.push({ type: currentType, value: currentToken });
|
|
39
|
+
return { currentToken: "", currentType: null, i:index };
|
|
40
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { processToken, processStringToken, processOperatorToken, isOperator } from './processToken.js';
|
|
2
|
+
import { PUNCTUATION } from './tokenTypes.js';
|
|
3
|
+
|
|
4
|
+
function generateTokens(input) {
|
|
5
|
+
const tokens = [];
|
|
6
|
+
let currentToken = "";
|
|
7
|
+
let currentType = null;
|
|
8
|
+
let inComment = false;
|
|
9
|
+
let inString = false;
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < input.length; i++) {
|
|
12
|
+
const char = input[i];
|
|
13
|
+
|
|
14
|
+
if (inComment) {
|
|
15
|
+
if (char === "\n") {
|
|
16
|
+
inComment = false;
|
|
17
|
+
}
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (char === "/" && input[i + 1] === "/") {
|
|
22
|
+
inComment = true;
|
|
23
|
+
i++; // Skip the second '/'
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (char === '"') {
|
|
28
|
+
({ inString, currentToken } = processStringToken(inString, currentToken, tokens));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (inString) {
|
|
33
|
+
currentToken += char;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (/\s/.test(char)) {
|
|
38
|
+
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isOperator(char)) {
|
|
43
|
+
({ currentToken, currentType, i } = processOperatorToken(char, i, input, currentType, currentToken, tokens));
|
|
44
|
+
}else if (PUNCTUATION.includes(char)) {
|
|
45
|
+
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
46
|
+
tokens.push({ type: "punctuation", value: char });
|
|
47
|
+
} else {
|
|
48
|
+
currentToken += char;
|
|
49
|
+
if (!currentType) {
|
|
50
|
+
currentType = /[a-zA-Z]/.test(char)
|
|
51
|
+
? "identifier"
|
|
52
|
+
: /[0-9]/.test(char)
|
|
53
|
+
? "number"
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
60
|
+
return tokens;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { generateTokens };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export function comparisonExpression(tokens, index) {
|
|
4
|
+
const operator = tokens[index++].value;
|
|
5
|
+
let left = parseExpression(tokens, index);
|
|
6
|
+
index = left.index; // Update the index
|
|
7
|
+
let right = parseExpression(tokens, index);
|
|
8
|
+
index = right.index; // Update the index
|
|
9
|
+
return {
|
|
10
|
+
expression: {
|
|
11
|
+
type: "comparison",
|
|
12
|
+
operator,
|
|
13
|
+
left: left.expression,
|
|
14
|
+
right: right.expression,
|
|
15
|
+
},
|
|
16
|
+
index,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export function identifierExpression(tokens, index) {
|
|
4
|
+
if (
|
|
5
|
+
tokens[index + 1]?.value === "[" &&
|
|
6
|
+
tokens[index + 3]?.value === "]"
|
|
7
|
+
) {
|
|
8
|
+
const name = tokens[index].value;
|
|
9
|
+
index += 2; // Skip identifier and '['
|
|
10
|
+
const indexExpression = parseExpression(tokens, index);
|
|
11
|
+
index = indexExpression.index; // Update the index
|
|
12
|
+
if (tokens[index]?.value === "]") {
|
|
13
|
+
index++; // Skip ']'
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
expression: {
|
|
17
|
+
type: "indexAccess",
|
|
18
|
+
name,
|
|
19
|
+
index: indexExpression.expression,
|
|
20
|
+
},
|
|
21
|
+
index,
|
|
22
|
+
};
|
|
23
|
+
} else {
|
|
24
|
+
return {
|
|
25
|
+
expression: { type: "variable", name: tokens[index++].value },
|
|
26
|
+
index,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export function operatorExpression(tokens, index) {
|
|
4
|
+
let operator = tokens[index++].value;
|
|
5
|
+
let left = parseExpression(tokens, index);
|
|
6
|
+
index = left.index; // Update the index
|
|
7
|
+
if (tokens[index]?.type === "operator") {
|
|
8
|
+
operator += tokens[index++].value; // Handle two-character operators like '=='
|
|
9
|
+
}
|
|
10
|
+
let right = parseExpression(tokens, index);
|
|
11
|
+
index = right.index; // Update the index
|
|
12
|
+
return {
|
|
13
|
+
expression: {
|
|
14
|
+
type: "binary",
|
|
15
|
+
operator,
|
|
16
|
+
left: left.expression,
|
|
17
|
+
right: right.expression,
|
|
18
|
+
},
|
|
19
|
+
index,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export function punctuationExpression(tokens, index) {
|
|
4
|
+
if (tokens[index].value === "[") {
|
|
5
|
+
index++; // Skip '['
|
|
6
|
+
const elements = [];
|
|
7
|
+
while (
|
|
8
|
+
tokens[index]?.type !== "punctuation" &&
|
|
9
|
+
tokens[index]?.value !== "]"
|
|
10
|
+
) {
|
|
11
|
+
let result = parseExpression(tokens, index);
|
|
12
|
+
elements.push(result.expression);
|
|
13
|
+
index = result.index; // Update the index
|
|
14
|
+
if (
|
|
15
|
+
tokens[index]?.type === "punctuation" &&
|
|
16
|
+
tokens[index]?.value === ","
|
|
17
|
+
) {
|
|
18
|
+
index++; // Skip ',' between elements
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (tokens[index]?.value === "]") {
|
|
22
|
+
index++; // Skip ']'
|
|
23
|
+
}
|
|
24
|
+
return { expression: { type: "list", elements }, index };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
expression: { type: "punctuation", value: tokens[index++].value },
|
|
29
|
+
index,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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";
|
|
7
|
+
|
|
8
|
+
export const parseExpression = (tokens, index) => {
|
|
9
|
+
// console.log("expression..", tokens[index].type, tokens[index].value);
|
|
10
|
+
|
|
11
|
+
switch (tokens[index].type) {
|
|
12
|
+
case "number":
|
|
13
|
+
return numberExpression(tokens, index);
|
|
14
|
+
case "string":
|
|
15
|
+
return stringExpression(tokens, index);
|
|
16
|
+
case "identifier":
|
|
17
|
+
return identifierExpression(tokens, index);
|
|
18
|
+
case "operator":
|
|
19
|
+
return operatorExpression(tokens, index);
|
|
20
|
+
case "punctuation":
|
|
21
|
+
return punctuationExpression(tokens, index);
|
|
22
|
+
default:
|
|
23
|
+
if (["<", ">", ">=", "<=", "==", "!="].includes(tokens[index].value)) {
|
|
24
|
+
return comparisonExpression(tokens, index);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { parseExpression } from "./parseExpression";
|
|
2
|
+
import { ifStatement } from "./statement/if";
|
|
3
|
+
import { setStatement } from "./statement/set";
|
|
4
|
+
import { tryCatchStatement } from "./statement/try-catch";
|
|
5
|
+
import { whileStatement } from "./statement/while";
|
|
6
|
+
import { functionStatement } from "./statement/function";
|
|
7
|
+
import { callStatement } from "./statement/call";
|
|
8
|
+
import { returnStatement } from "./statement/return";
|
|
9
|
+
import { showStatement } from "./statement/show";
|
|
10
|
+
|
|
11
|
+
export const parseStatement = (tokens, index) => {
|
|
12
|
+
let statement = { type: "statement" };
|
|
13
|
+
|
|
14
|
+
// console.log("parsing..", tokens[index].type, tokens[index].value);
|
|
15
|
+
if (tokens[index].value === "set") {
|
|
16
|
+
({ statement, index } = setStatement(tokens, index));
|
|
17
|
+
} else if (tokens[index].value === "if") {
|
|
18
|
+
({ statement, index } = ifStatement(tokens, index));
|
|
19
|
+
} else if (tokens[index].value === "while") {
|
|
20
|
+
({ statement, index } = whileStatement(tokens, index));
|
|
21
|
+
} else if (tokens[index].value === "try") {
|
|
22
|
+
({ statement, index } = tryCatchStatement(tokens, index));
|
|
23
|
+
} else if (tokens[index].value === "function") {
|
|
24
|
+
({ statement, index } = functionStatement(tokens, index));
|
|
25
|
+
} else if (tokens[index].value === "call") {
|
|
26
|
+
({ statement, index } = callStatement(tokens, index));
|
|
27
|
+
} else if (tokens[index].value === "return") {
|
|
28
|
+
({ statement, index } = returnStatement(tokens, index));
|
|
29
|
+
} else if (tokens[index].value === "show") {
|
|
30
|
+
({ statement, index } = showStatement(tokens, index));
|
|
31
|
+
} else {
|
|
32
|
+
index++;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { statement, index };
|
|
36
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseStatement } from "./parseStatement";
|
|
2
|
+
|
|
3
|
+
export function parseTokens(tokens) {
|
|
4
|
+
let index = 0;
|
|
5
|
+
|
|
6
|
+
const program = [];
|
|
7
|
+
while (index < tokens.length) {
|
|
8
|
+
let statement;
|
|
9
|
+
let result = parseStatement(tokens, index);
|
|
10
|
+
statement = result.statement;
|
|
11
|
+
index = result.index; // Update the index
|
|
12
|
+
program.push(statement);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return program;
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export const callStatement = (tokens, index) => {
|
|
4
|
+
let statement = { type: "call" };
|
|
5
|
+
statement.name = tokens[index + 1]?.value;
|
|
6
|
+
index += 2; // Skip 'call' and function name
|
|
7
|
+
statement.args = [];
|
|
8
|
+
statement.target = null;
|
|
9
|
+
if (tokens[index].value === "(") {
|
|
10
|
+
index++; // Skip '('
|
|
11
|
+
while (tokens[index].value !== ")") {
|
|
12
|
+
if (tokens[index].value !== ",") {
|
|
13
|
+
let result = parseExpression(tokens, index);
|
|
14
|
+
statement.args.push(result.expression);
|
|
15
|
+
index = result.index; // Update the index
|
|
16
|
+
} else {
|
|
17
|
+
index++; // Skip ','
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
index++; // Skip ')'
|
|
21
|
+
}
|
|
22
|
+
if ((tokens[index++].value = "->")) {
|
|
23
|
+
statement.target = tokens[index++].value;
|
|
24
|
+
}
|
|
25
|
+
return { statement, index };
|
|
26
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseStatement } from "../parseStatement";
|
|
2
|
+
|
|
3
|
+
// #file:statement/function.js
|
|
4
|
+
export const functionStatement = (tokens, index) => {
|
|
5
|
+
index++; // Skip 'function'
|
|
6
|
+
let statement = { type: "function" };
|
|
7
|
+
statement.name = tokens[index++]?.value;
|
|
8
|
+
index++; // Skip 'function' and function name
|
|
9
|
+
statement.params = [];
|
|
10
|
+
while (tokens[index]?.value !== ")") {
|
|
11
|
+
statement.params.push(tokens[index]?.value);
|
|
12
|
+
index++; // Skip parameter
|
|
13
|
+
if (tokens[index]?.value === ",") {
|
|
14
|
+
index++; // Skip ','
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
index++; // Skip ')'
|
|
18
|
+
const body = [];
|
|
19
|
+
while (tokens[index] && tokens[index].value !== "endfunction") {
|
|
20
|
+
let result = parseStatement(tokens, index);
|
|
21
|
+
body.push(result.statement);
|
|
22
|
+
index = result.index; // Update the index
|
|
23
|
+
}
|
|
24
|
+
if (tokens[index].value === "endfunction") {
|
|
25
|
+
index++;
|
|
26
|
+
}
|
|
27
|
+
statement.body = body;
|
|
28
|
+
return { statement, index };
|
|
29
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
import { parseStatement } from "../parseStatement";
|
|
3
|
+
|
|
4
|
+
export function ifStatement(tokens, index) {
|
|
5
|
+
let statement = { type: "if" };
|
|
6
|
+
index++;
|
|
7
|
+
let result = parseExpression(tokens, index);
|
|
8
|
+
statement.condition = result.expression;
|
|
9
|
+
index = result.index; // Update the index
|
|
10
|
+
statement.consequent = [];
|
|
11
|
+
|
|
12
|
+
while (
|
|
13
|
+
tokens[index] &&
|
|
14
|
+
tokens[index].value !== "endif" &&
|
|
15
|
+
tokens[index].value !== "else"
|
|
16
|
+
) {
|
|
17
|
+
let result = parseStatement(tokens, index);
|
|
18
|
+
statement.consequent.push(result.statement);
|
|
19
|
+
index = result.index; // Update the index
|
|
20
|
+
}
|
|
21
|
+
if (tokens[index].value === "else") {
|
|
22
|
+
index++;
|
|
23
|
+
statement.alternate = [];
|
|
24
|
+
while (tokens[index] && tokens[index].value !== "endif") {
|
|
25
|
+
let result = parseStatement(tokens, index);
|
|
26
|
+
statement.alternate.push(result.statement);
|
|
27
|
+
index = result.index; // Update the index
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (tokens[index].value === "endif") {
|
|
31
|
+
index++;
|
|
32
|
+
}
|
|
33
|
+
return { statement, index };
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
// #file:statement/return.js
|
|
4
|
+
export const returnStatement = (tokens, index) => {
|
|
5
|
+
let statement = { type: "return" };
|
|
6
|
+
let result = parseExpression(tokens, index + 1);
|
|
7
|
+
statement.expression = result.expression;
|
|
8
|
+
index = result.index; // Update the index
|
|
9
|
+
return { statement, index };
|
|
10
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export function setStatement(tokens, index) {
|
|
4
|
+
let statement = { type: "assignment" };
|
|
5
|
+
index++;
|
|
6
|
+
statement.target = tokens[index++].value;
|
|
7
|
+
let result = parseExpression(tokens, index);
|
|
8
|
+
statement.value = result.expression;
|
|
9
|
+
index = result.index; // Update the index
|
|
10
|
+
return { statement, index };
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
|
|
3
|
+
export const showStatement = (tokens, index) => {
|
|
4
|
+
let statement = { type: "print" };
|
|
5
|
+
index++; // Skip 'show'
|
|
6
|
+
let result = parseExpression(tokens, index);
|
|
7
|
+
statement.value = result.expression;
|
|
8
|
+
index = result.index; // Update the index
|
|
9
|
+
return { statement, index };
|
|
10
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { parseStatement } from "../parseStatement";
|
|
2
|
+
|
|
3
|
+
export const tryCatchStatement = (tokens, index) => {
|
|
4
|
+
let statement = { type: "try-catch" };
|
|
5
|
+
statement.tryBlock = [];
|
|
6
|
+
index++;
|
|
7
|
+
while (tokens[index] && tokens[index].value !== "catch") {
|
|
8
|
+
let result = parseStatement(tokens, index);
|
|
9
|
+
statement.tryBlock.push(result.statement);
|
|
10
|
+
index = result.index; // Update the index
|
|
11
|
+
}
|
|
12
|
+
if (tokens[index].value === "catch") {
|
|
13
|
+
index++;
|
|
14
|
+
statement.catchBlock = [];
|
|
15
|
+
while (tokens[index] && tokens[index].value !== "endtry") {
|
|
16
|
+
let result = parseStatement(tokens, index);
|
|
17
|
+
statement.catchBlock.push(result.statement);
|
|
18
|
+
index = result.index; // Update the index
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (tokens[index].value === "endtry") {
|
|
22
|
+
index++;
|
|
23
|
+
}
|
|
24
|
+
return { statement, index };
|
|
25
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { parseExpression } from "../parseExpression";
|
|
2
|
+
import { parseStatement } from "../parseStatement";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const whileStatement = (tokens, index) => {
|
|
6
|
+
index++; // Skip 'while'
|
|
7
|
+
let statement = { type: "while" };
|
|
8
|
+
let result = parseExpression(tokens, index);
|
|
9
|
+
statement.condition = result.expression;
|
|
10
|
+
index = result.index; // Update the index
|
|
11
|
+
const body = [];
|
|
12
|
+
while (tokens[index] && tokens[index].value !== "endwhile") {
|
|
13
|
+
let result = parseStatement(tokens, index);
|
|
14
|
+
body.push(result.statement);
|
|
15
|
+
index = result.index; // Update the index
|
|
16
|
+
}
|
|
17
|
+
if (tokens[index].value === "endwhile") {
|
|
18
|
+
index++;
|
|
19
|
+
}
|
|
20
|
+
statement.body = body;
|
|
21
|
+
return { statement, index };
|
|
22
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
let declaredVariables = new Set();
|
|
2
|
+
|
|
3
|
+
function generateGoCodeFromAst(node) {
|
|
4
|
+
switch (node.type) {
|
|
5
|
+
case "function":
|
|
6
|
+
return generateFunction(node);
|
|
7
|
+
case "assignment":
|
|
8
|
+
return generateAssignment(node);
|
|
9
|
+
case "while":
|
|
10
|
+
return generateWhile(node);
|
|
11
|
+
case "if":
|
|
12
|
+
return generateIf(node);
|
|
13
|
+
case "return":
|
|
14
|
+
return generateReturn(node);
|
|
15
|
+
case "call":
|
|
16
|
+
return generateCall(node);
|
|
17
|
+
case "print":
|
|
18
|
+
return generatePrint(node);
|
|
19
|
+
case "literal":
|
|
20
|
+
return node.value;
|
|
21
|
+
case "variable":
|
|
22
|
+
return node.name;
|
|
23
|
+
case "binary":
|
|
24
|
+
return generateBinary(node);
|
|
25
|
+
default:
|
|
26
|
+
throw new Error(`Unknown node type: ${node.type}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function generateGoCodeFromAstArray(ast) {
|
|
31
|
+
declaredVariables = new Set();
|
|
32
|
+
const generatedCode = ast.map(generateGoCodeFromAst).join("\n\n");
|
|
33
|
+
return formatGoCode(`
|
|
34
|
+
package main
|
|
35
|
+
|
|
36
|
+
import "fmt"
|
|
37
|
+
|
|
38
|
+
${generatedCode}
|
|
39
|
+
`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function generateFunction(node) {
|
|
43
|
+
const params = node.params.join(", ");
|
|
44
|
+
const body = node.body.map(generateGoCodeFromAst).join("\n");
|
|
45
|
+
return `func ${node.name}(${params}) int {\n${body}\n}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function generateAssignment(node) {
|
|
49
|
+
let prefix = "";
|
|
50
|
+
if (!declaredVariables.has(node.target)) {
|
|
51
|
+
prefix = "var ";
|
|
52
|
+
declaredVariables.add(node.target);
|
|
53
|
+
}
|
|
54
|
+
return `${prefix}${node.target} := ${generateGoCodeFromAst(node.value)}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function generateWhile(node) {
|
|
58
|
+
const condition = generateGoCodeFromAst(node.condition);
|
|
59
|
+
const body = node.body.map(generateGoCodeFromAst).join("\n");
|
|
60
|
+
return `for ${condition} {\n${body}\n}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function generateIf(node) {
|
|
64
|
+
const condition = generateGoCodeFromAst(node.condition);
|
|
65
|
+
const consequent = node.consequent.map(generateGoCodeFromAst).join("\n");
|
|
66
|
+
return `if ${condition} {\n${consequent}\n}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function generateReturn(node) {
|
|
70
|
+
return `return ${generateGoCodeFromAst(node.expression)}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function generateCall(node) {
|
|
74
|
+
const args = node.args.map(generateGoCodeFromAst).join(", ");
|
|
75
|
+
let callCode = `${node.name}(${args})`;
|
|
76
|
+
if (node.target) {
|
|
77
|
+
let prefix = "";
|
|
78
|
+
if (!declaredVariables.has(node.target)) {
|
|
79
|
+
prefix = "var ";
|
|
80
|
+
declaredVariables.add(node.target);
|
|
81
|
+
}
|
|
82
|
+
callCode = `${prefix}${node.target} := ${callCode}`;
|
|
83
|
+
}
|
|
84
|
+
return callCode;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
function generatePrint(node) {
|
|
89
|
+
return `fmt.Println(${generateGoCodeFromAst(node.value)})`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function generateBinary(node) {
|
|
93
|
+
const left = generateGoCodeFromAst(node.left);
|
|
94
|
+
const right = generateGoCodeFromAst(node.right);
|
|
95
|
+
return `${left} ${node.operator} ${right}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function formatGoCode(code) {
|
|
99
|
+
return code;
|
|
100
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import esformatter from 'esformatter';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let declaredVariables = new Set();
|
|
5
|
+
|
|
6
|
+
export function generateCodeFromAst(node) {
|
|
7
|
+
switch (node.type) {
|
|
8
|
+
case "function":
|
|
9
|
+
return generateFunction(node);
|
|
10
|
+
case "assignment":
|
|
11
|
+
return generateAssignment(node);
|
|
12
|
+
case "while":
|
|
13
|
+
return generateWhile(node);
|
|
14
|
+
case "if":
|
|
15
|
+
return generateIf(node);
|
|
16
|
+
case "return":
|
|
17
|
+
return generateReturn(node);
|
|
18
|
+
case "call":
|
|
19
|
+
return generateCall(node);
|
|
20
|
+
case "print":
|
|
21
|
+
return generatePrint(node);
|
|
22
|
+
case "literal":
|
|
23
|
+
return node.value;
|
|
24
|
+
case "variable":
|
|
25
|
+
return node.name;
|
|
26
|
+
case "binary":
|
|
27
|
+
return generateBinary(node);
|
|
28
|
+
case "indexAccess":
|
|
29
|
+
return generateIndexAccess(node);
|
|
30
|
+
case "list":
|
|
31
|
+
return generateList(node);
|
|
32
|
+
default:
|
|
33
|
+
console.log(node);
|
|
34
|
+
throw new Error(`Unknown node type: ${node.type}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function generateCodeJsFromAstArray(ast) {
|
|
39
|
+
const generatedCode = ast.map(generateCodeFromAst).join("\n");
|
|
40
|
+
return esformatter.format(generatedCode);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function generateFunction(node) {
|
|
44
|
+
const params = node.params.join(", ");
|
|
45
|
+
const body = node.body.map(generateCodeFromAst).join("\n");
|
|
46
|
+
return `function ${node.name}(${params}) {\n${body}\n}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function generateAssignment(node) {
|
|
50
|
+
let prefix = "";
|
|
51
|
+
if (!declaredVariables.has(node.target)) {
|
|
52
|
+
prefix = "let ";
|
|
53
|
+
declaredVariables.add(node.target);
|
|
54
|
+
}
|
|
55
|
+
return `${prefix}${node.target} = ${generateCodeFromAst(node.value)};`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function generateWhile(node) {
|
|
59
|
+
const condition = generateCodeFromAst(node.condition);
|
|
60
|
+
const body = node.body.map(generateCodeFromAst).join("\n");
|
|
61
|
+
return `while (${condition}) {\n${body}\n}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function generateIf(node) {
|
|
65
|
+
const condition = generateCodeFromAst(node.condition);
|
|
66
|
+
const consequent = node.consequent.map(generateCodeFromAst).join("\n");
|
|
67
|
+
return `if (${condition}) {\n${consequent}\n}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function generateReturn(node) {
|
|
71
|
+
return `return ${generateCodeFromAst(node.expression)};`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function generateCall(node) {
|
|
75
|
+
const args = node.args.map(generateCodeFromAst).join(", ");
|
|
76
|
+
let callCode = `${node.name}(${args})`;
|
|
77
|
+
if (node.target) {
|
|
78
|
+
let prefix = "";
|
|
79
|
+
if (!declaredVariables.has(node.target)) {
|
|
80
|
+
prefix = "let ";
|
|
81
|
+
declaredVariables.add(node.target);
|
|
82
|
+
}
|
|
83
|
+
callCode = `${prefix}${node.target} = ${callCode};`;
|
|
84
|
+
}
|
|
85
|
+
return callCode;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function generatePrint(node) {
|
|
89
|
+
return `console.log(${generateCodeFromAst(node.value)});`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function generateBinary(node) {
|
|
93
|
+
const left = generateCodeFromAst(node.left);
|
|
94
|
+
const right = generateCodeFromAst(node.right);
|
|
95
|
+
return `${left} ${node.operator} ${right}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function generateIndexAccess(node) {
|
|
99
|
+
const index = generateCodeFromAst(node.index);
|
|
100
|
+
return `${node.name}[${index}]`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function generateList(node) {
|
|
104
|
+
const elements = node.elements.map(generateCodeFromAst).join(", ");
|
|
105
|
+
return `[${elements}]`;
|
|
106
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { generateTokens } from "./compiler/lexer/tokenizer";
|
|
2
|
+
import { parseTokens } from "./compiler/parser/parser";
|
|
3
|
+
import { interpret } from "./compiler/execute/interpreter";
|
|
4
|
+
import { generateGoCodeFromAstArray } from "./converter/go/convert";
|
|
5
|
+
import { generateCodeJsFromAstArray } from "./converter/js/convert";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
|
|
8
|
+
// The main class for the Mimo language
|
|
9
|
+
export default class Mimo {
|
|
10
|
+
constructor() {
|
|
11
|
+
// Initialize the environment for variables
|
|
12
|
+
this.env = {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Tokenize the given code into a list of tokens
|
|
16
|
+
async tokenize(code) {
|
|
17
|
+
return generateTokens(code);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Parse the list of tokens into an abstract syntax tree (AST)
|
|
21
|
+
async parse(tokens) {
|
|
22
|
+
return parseTokens(tokens);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Interpret the AST and execute the code
|
|
26
|
+
async interpret(program) {
|
|
27
|
+
return interpret(program, this.env);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Run the given code by tokenizing, parsing, and interpreting it
|
|
31
|
+
async run(code) {
|
|
32
|
+
const tokens = await this.tokenize(code);
|
|
33
|
+
const program = await this.parse(tokens);
|
|
34
|
+
return await this.interpret(program);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Convert the AST to JavaScript code
|
|
38
|
+
toJS(ast) {
|
|
39
|
+
return generateCodeJsFromAstArray(ast);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Convert the AST to Go code
|
|
43
|
+
toGO(ast) {
|
|
44
|
+
return generateGoCodeFromAstArray(ast);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
package/jsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
|
|
22
|
+
// Some stricter flags (disabled by default)
|
|
23
|
+
"noUnusedLocals": false,
|
|
24
|
+
"noUnusedParameters": false,
|
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mimo-lang",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A programming language made in javascript mostly for learning purposes.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"programing language"
|
|
7
|
+
],
|
|
8
|
+
"author": "bethropolis",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"main": "index.js",
|
|
11
|
+
"module": "index.js",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"bin": {
|
|
14
|
+
"mimo": "./cli.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"dev": "bun index.js"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/bun": "latest"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"esformatter": "^0.11.3"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/bethropolis/mimo.git"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://bethropolis.github.io/mimo",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/bethropolis/mimo/issues"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log(a)
|