mimo-lang 1.1.0 → 1.1.1
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 +59 -6
- package/bun.lockb +0 -0
- package/compiler/lexer/tokenizer.js +11 -0
- package/compiler/parser/parseStatement.js +0 -1
- package/compiler/parser/parser.js +29 -0
- package/compiler/parser/statement/function.js +2 -2
- package/converter/js/convert.js +3 -3
- package/index.js +48 -9
- package/package.json +5 -3
- package/vite.config.js +17 -0
- package/i.js +0 -30
- package/test.js +0 -1
- package/webpack.config.js +0 -9
package/README.md
CHANGED
|
@@ -1,15 +1,68 @@
|
|
|
1
1
|
# mimo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/bethropolis/mimo/releases/)
|
|
4
|
+
[](#license)
|
|
5
|
+
[](https://github.com/bethropolis/mimo/actions/workflows/deploy.yml)
|
|
6
|
+
|
|
7
|
+
a simple programming language written in js.
|
|
8
|
+
|
|
9
|
+
## Instalation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
# install globally
|
|
13
|
+
npm install -g mimo-lang
|
|
14
|
+
|
|
15
|
+
# install project scope
|
|
16
|
+
npm install mimo-lang
|
|
4
17
|
|
|
5
|
-
```bash
|
|
6
|
-
bun install
|
|
7
18
|
```
|
|
8
19
|
|
|
9
|
-
|
|
20
|
+
### Global cli commands
|
|
21
|
+
|
|
22
|
+
the folowing are available commands and flags for the cli tool.
|
|
10
23
|
|
|
11
24
|
```bash
|
|
12
|
-
|
|
25
|
+
$ mimo [FILENAME] [-o|--output] [-t|--time] [-h|--help] [-q|--quiet] [-d|--debug] [-v|--version]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
example `mimo exampleFile.mimo`
|
|
29
|
+
|
|
30
|
+
### Library usage
|
|
31
|
+
|
|
32
|
+
example:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import Mimo from "../index.js";
|
|
36
|
+
|
|
37
|
+
let mimo = new Mimo();
|
|
38
|
+
|
|
39
|
+
let code = /* your code here*/
|
|
40
|
+
|
|
41
|
+
mimo.run(code);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Language syntax:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
function add(a,b)
|
|
48
|
+
return + a b
|
|
49
|
+
endfunction
|
|
50
|
+
|
|
51
|
+
set x 5
|
|
52
|
+
set y 2
|
|
53
|
+
|
|
54
|
+
call add(x,y) -> result
|
|
55
|
+
show result
|
|
13
56
|
```
|
|
14
57
|
|
|
15
|
-
|
|
58
|
+
more example id the [test directory]('./test/mimo/')
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## About
|
|
62
|
+
this is just a simple language i created to learn more about how programing languages work.
|
|
63
|
+
contributions are welcome.
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
Released under [MIT](./LICENSE)
|
|
67
|
+
|
|
68
|
+
happy coding 💜
|
package/bun.lockb
CHANGED
|
Binary file
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { processToken, processStringToken, processOperatorToken, isOperator } from './processToken.js';
|
|
2
2
|
import { PUNCTUATION } from './tokenTypes.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} Token
|
|
6
|
+
* @property {string} type - The type of the token (e.g., 'number', 'identifier', 'operator', etc.).
|
|
7
|
+
* @property {string} value - The value of the token (e.g., '42', 'x', '+', etc.).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate tokens from the given input.
|
|
12
|
+
* @param {string} input - The input to be tokenized.
|
|
13
|
+
* @returns {Token[]} An array of tokens.
|
|
14
|
+
*/
|
|
4
15
|
function generateTokens(input) {
|
|
5
16
|
const tokens = [];
|
|
6
17
|
let currentToken = "";
|
|
@@ -10,7 +10,6 @@ import { showStatement } from "./statement/show.js";
|
|
|
10
10
|
export const parseStatement = (tokens, index) => {
|
|
11
11
|
let statement = { type: "statement" };
|
|
12
12
|
|
|
13
|
-
// console.log("parsing..", tokens[index].type, tokens[index].value);
|
|
14
13
|
if (tokens[index].value === "set") {
|
|
15
14
|
({ statement, index } = setStatement(tokens, index));
|
|
16
15
|
} else if (tokens[index].value === "if") {
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
import { parseStatement } from "./parseStatement.js";
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../lexer/tokenizer.js').Token} Token
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} Node
|
|
10
|
+
* @property {string} type - The type of the node (e.g., 'binary', 'assignment', 'literal', etc.).
|
|
11
|
+
* optionals
|
|
12
|
+
* @property {string} [operator] - The operator (e.g., '+', '-', '*', '/', etc.).
|
|
13
|
+
* @property {Node} [left] - The left node.
|
|
14
|
+
* @property {Node} [right] - The right node.
|
|
15
|
+
* @property {Node} [condition] - The expression node.
|
|
16
|
+
* @property {Node} [consequent] - The consequent node.
|
|
17
|
+
* @property {Node} [expression] - The expression node.
|
|
18
|
+
* @property {Node} [alternate] - The alternate node.
|
|
19
|
+
* @property {string} [target] - The target of the assignment.
|
|
20
|
+
* @property {number} [value] - The value to be assigned.
|
|
21
|
+
* @property {string} [name] - The name of functions and variables.
|
|
22
|
+
* @property {string[]} [params] - The parameters of a function.
|
|
23
|
+
* @property {Node[]} [body] - The body of a block statement.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parse the list of tokens into an abstract syntax tree (AST).
|
|
28
|
+
* @param {Token[]} tokens - The list of tokens to be parsed.
|
|
29
|
+
* @returns {Node[]} An array of AST nodes.
|
|
30
|
+
*/
|
|
31
|
+
|
|
3
32
|
export function parseTokens(tokens) {
|
|
4
33
|
let index = 0;
|
|
5
34
|
|
|
@@ -7,7 +7,7 @@ export const functionStatement = (tokens, index) => {
|
|
|
7
7
|
statement.name = tokens[index++]?.value;
|
|
8
8
|
index++; // Skip 'function' and function name
|
|
9
9
|
statement.params = [];
|
|
10
|
-
while (tokens[index]?.value !== ")") {
|
|
10
|
+
while (tokens[index] && tokens[index]?.value !== ")") {
|
|
11
11
|
statement.params.push(tokens[index]?.value);
|
|
12
12
|
index++; // Skip parameter
|
|
13
13
|
if (tokens[index]?.value === ",") {
|
|
@@ -21,7 +21,7 @@ export const functionStatement = (tokens, index) => {
|
|
|
21
21
|
body.push(result.statement);
|
|
22
22
|
index = result.index; // Update the index
|
|
23
23
|
}
|
|
24
|
-
if (tokens[index].value === "endfunction") {
|
|
24
|
+
if (tokens[index] && tokens[index].value === "endfunction") {
|
|
25
25
|
index++;
|
|
26
26
|
}
|
|
27
27
|
statement.body = body;
|
package/converter/js/convert.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import pkg from
|
|
1
|
+
import pkg from "js-beautify";
|
|
2
2
|
const { js_beautify } = pkg;
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
let declaredVariables = new Set();
|
|
6
5
|
|
|
7
6
|
export function generateCodeFromAst(node) {
|
|
@@ -31,12 +30,13 @@ export function generateCodeFromAst(node) {
|
|
|
31
30
|
case "list":
|
|
32
31
|
return generateList(node);
|
|
33
32
|
default:
|
|
34
|
-
console.
|
|
33
|
+
console.error(`Unknown node type: ${node.type} during conversion.`);
|
|
35
34
|
throw new Error(`Unknown node type: ${node.type}`);
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
export function generateCodeJsFromAstArray(ast) {
|
|
39
|
+
declaredVariables = new Set();
|
|
40
40
|
const generatedCode = ast.map(generateCodeFromAst).join("\n");
|
|
41
41
|
return js_beautify(generatedCode);
|
|
42
42
|
}
|
package/index.js
CHANGED
|
@@ -3,39 +3,78 @@ import { parseTokens } from "./compiler/parser/parser.js";
|
|
|
3
3
|
import { interpret } from "./compiler/execute/interpreter.js";
|
|
4
4
|
import { generateCodeJsFromAstArray } from "./converter/js/convert.js";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import('./compiler/lexer/tokenizer.js').Token} Token
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {import('./compiler/parser/parser.js').Node} Node
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The main class for the Mimo language.
|
|
19
|
+
*/
|
|
7
20
|
export default class Mimo {
|
|
8
21
|
constructor() {
|
|
9
22
|
// Initialize the environment for variables
|
|
10
23
|
this.env = {};
|
|
11
24
|
}
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Tokenize the given code into a list of tokens.
|
|
28
|
+
* @param {string} code - The code to be tokenized.
|
|
29
|
+
* @returns {Promise<Token[]>} A promise that resolves to an array of tokens.
|
|
30
|
+
*/
|
|
14
31
|
async tokenize(code) {
|
|
15
32
|
return generateTokens(code);
|
|
16
33
|
}
|
|
17
34
|
|
|
18
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Parse the list of tokens into an abstract syntax tree (AST).
|
|
37
|
+
* @param {Token[]} tokens - The list of tokens to be parsed.
|
|
38
|
+
* @returns {Promise<Node[]>} A promise that resolves to an array of AST nodes.
|
|
39
|
+
*/
|
|
19
40
|
async parse(tokens) {
|
|
20
41
|
return parseTokens(tokens);
|
|
21
42
|
}
|
|
22
43
|
|
|
23
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Interpret the AST and execute the code.
|
|
46
|
+
* @param {Node[]} program - The AST to be interpreted.
|
|
47
|
+
* @returns {Promise<Object>} A promise that resolves to the result of interpreting the AST.
|
|
48
|
+
*/
|
|
24
49
|
async interpret(program) {
|
|
25
50
|
return interpret(program, this.env);
|
|
26
51
|
}
|
|
27
52
|
|
|
28
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Run the given code by tokenizing, parsing, and interpreting it.
|
|
55
|
+
* @param {string} code - The code to be run.
|
|
56
|
+
* @returns {Promise<{program: Node[], env: Object}>} A promise that resolves to an object containing the AST and the environment.
|
|
57
|
+
*/
|
|
29
58
|
async run(code) {
|
|
30
59
|
const tokens = await this.tokenize(code);
|
|
31
|
-
const program = await this.parse(tokens);
|
|
60
|
+
const program = await this.parse(tokens, this.env);
|
|
32
61
|
const env = await this.interpret(program);
|
|
33
62
|
return { program, env };
|
|
34
63
|
}
|
|
35
64
|
|
|
36
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Clear the environment for variables.
|
|
67
|
+
*/
|
|
68
|
+
clearEnv() {
|
|
69
|
+
this.env = {};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Convert the AST to JavaScript code.
|
|
74
|
+
* @param {Node[]} ast - The AST to be converted.
|
|
75
|
+
* @returns {string} The generated JavaScript code.
|
|
76
|
+
*/
|
|
37
77
|
toJS(ast) {
|
|
38
78
|
return generateCodeJsFromAstArray(ast);
|
|
39
79
|
}
|
|
40
|
-
}
|
|
41
|
-
|
|
80
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mimo-lang",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A programming language made in javascript mostly for learning purposes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"programing language"
|
|
@@ -16,13 +16,15 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"mimo": "bun cli.js",
|
|
18
18
|
"dev": "bun index.js",
|
|
19
|
-
"test": "node test/index.js"
|
|
19
|
+
"test": "node test/index.js",
|
|
20
|
+
"build": "vite build"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/bun": "latest"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"js-beautify": "^1.15.1"
|
|
26
|
+
"js-beautify": "^1.15.1",
|
|
27
|
+
"vite": "^5.2.10"
|
|
26
28
|
},
|
|
27
29
|
"repository": {
|
|
28
30
|
"type": "git",
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// vite.config.js
|
|
2
|
+
import { defineConfig } from 'vite'
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
rollupOptions: {
|
|
7
|
+
input: {
|
|
8
|
+
main: './index.js' // Specify the entry point as index.js
|
|
9
|
+
},
|
|
10
|
+
output: {
|
|
11
|
+
manualChunks: false,
|
|
12
|
+
inlineDynamicImports: true,
|
|
13
|
+
entryFileNames: 'assets/[name].js' // Specify the output file name and directory
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
})
|
package/i.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
function addJsExtensionToImports(filePath) {
|
|
5
|
-
const code = fs.readFileSync(filePath, 'utf8');
|
|
6
|
-
const newCode = code.replace(/from\s+(['"])(.*?)(?<!\.js)\1/g, 'from $1$2.js$1');
|
|
7
|
-
|
|
8
|
-
if (code !== newCode) {
|
|
9
|
-
fs.writeFileSync(filePath, newCode, 'utf8');
|
|
10
|
-
console.log(`Updated imports in ${filePath}`);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function traverseDirectory(dirPath) {
|
|
15
|
-
const files = fs.readdirSync(dirPath);
|
|
16
|
-
|
|
17
|
-
for (const file of files) {
|
|
18
|
-
const filePath = path.join(dirPath, file);
|
|
19
|
-
const stats = fs.statSync(filePath);
|
|
20
|
-
|
|
21
|
-
if (stats.isDirectory()) {
|
|
22
|
-
traverseDirectory(filePath);
|
|
23
|
-
} else if (path.extname(filePath) === '.js') {
|
|
24
|
-
addJsExtensionToImports(filePath);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const rootDir = './'; // replace with your directory path
|
|
30
|
-
traverseDirectory(rootDir);
|
package/test.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log(a)
|
package/webpack.config.js
DELETED