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 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
- import { version } from "./package.json";
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
- mimo.run(code);
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.message);
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,4 +1,4 @@
1
- import { evaluate } from "../utils/evaluate";
1
+ import { evaluate } from "../utils/evaluate.js";
2
2
 
3
3
  export async function interpretBinary(statement, env) {
4
4
  if (env[statement.target] === undefined) {
@@ -1,4 +1,4 @@
1
- import { evaluate } from "../utils/evaluate";
1
+ import { evaluate } from "../utils/evaluate.js";
2
2
 
3
3
  export async function interpretCall(statement, env) {
4
4
  const func = env[statement.name];
@@ -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,3 +1,4 @@
1
+ import { interpretStatement } from "../interpreter.js";
1
2
 
2
3
  export async function interpretTryCatch(statement, env) {
3
4
  try {
@@ -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,4 +1,4 @@
1
- import { interpret } from "../interpreter";
1
+ import { interpret } from "../interpreter.js";
2
2
 
3
3
  export function createFunction(params, body, env) {
4
4
  return async function (...args) {
@@ -1,4 +1,4 @@
1
- import { operate } from "./operate";
1
+ import { operate } from "./operate.js";
2
2
 
3
3
  export const evaluate = (expression, env) =>
4
4
  expression.type === "literal"
@@ -1,6 +1,6 @@
1
1
  // processToken.js
2
2
 
3
- import { OPERATORS } from "./tokenTypes";
3
+ import { OPERATORS } from "./tokenTypes.js";
4
4
 
5
5
  export const isOperator = (char) => OPERATORS.includes(char);
6
6
 
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export function comparisonExpression(tokens, index) {
4
4
  const operator = tokens[index++].value;
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export function identifierExpression(tokens, index) {
4
4
  if (
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export function operatorExpression(tokens, index) {
4
4
  let operator = tokens[index++].value;
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export function punctuationExpression(tokens, index) {
4
4
  if (tokens[index].value === "[") {
@@ -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 { 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";
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,4 +1,4 @@
1
- import { parseStatement } from "./parseStatement";
1
+ import { parseStatement } from "./parseStatement.js";
2
2
 
3
3
  export function parseTokens(tokens) {
4
4
  let index = 0;
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export const callStatement = (tokens, index) => {
4
4
  let statement = { type: "call" };
@@ -1,4 +1,4 @@
1
- import { parseStatement } from "../parseStatement";
1
+ import { parseStatement } from "../parseStatement.js";
2
2
 
3
3
  // #file:statement/function.js
4
4
  export const functionStatement = (tokens, index) => {
@@ -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,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  // #file:statement/return.js
4
4
  export const returnStatement = (tokens, index) => {
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export function setStatement(tokens, index) {
4
4
  let statement = { type: "assignment" };
@@ -1,4 +1,4 @@
1
- import { parseExpression } from "../parseExpression";
1
+ import { parseExpression } from "../parseExpression.js";
2
2
 
3
3
  export const showStatement = (tokens, index) => {
4
4
  let statement = { type: "print" };
@@ -1,4 +1,4 @@
1
- import { parseStatement } from "../parseStatement";
1
+ import { parseStatement } from "../parseStatement.js";
2
2
 
3
3
  export const tryCatchStatement = (tokens, index) => {
4
4
  let statement = { type: "try-catch" };
@@ -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) => {
@@ -29,20 +29,31 @@ function generateGoCodeFromAst(node) {
29
29
 
30
30
  export function generateGoCodeFromAstArray(ast) {
31
31
  declaredVariables = new Set();
32
- const generatedCode = ast.map(generateGoCodeFromAst).join("\n\n");
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
- ${generatedCode}
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}) int {\n${body}\n}`;
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} := ${generateGoCodeFromAst(node.value)}`;
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} := ${callCode}`;
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 { generateGoCodeFromAstArray } from "./converter/go/convert";
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
- return await this.interpret(program);
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.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
- "dev": "bun index.js"
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"
@@ -0,0 +1,9 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ entry: './index.js', // Entry point of your application
5
+ output: {
6
+ filename: 'bundle.js', // Name of the bundled output file
7
+ path: path.resolve(__dirname, 'dist'), // Output directory
8
+ },
9
+ };