cajyu 0.0.0-stage → 1.0.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 +165 -2
- package/bin/cajyu.js +157 -0
- package/examples/classe.cjy +16 -0
- package/examples/fatorial.cjy +13 -0
- package/examples/servidor-post.cjy +18 -0
- package/package.json +15 -4
- package/src/compiler.js +149 -0
package/README.md
CHANGED
|
@@ -1,3 +1,166 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Cajyu
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A clean, practical programming language that transpiles to JavaScript.**
|
|
4
|
+
|
|
5
|
+
Cajyu gives you a simpler, more expressive syntax while staying fully compatible with the JavaScript ecosystem.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/cajyu)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](package.json)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Clean syntax for variables, functions, classes, loops and conditionals
|
|
16
|
+
- Transpiles to modern JavaScript
|
|
17
|
+
- Real HTTP server with POST handlers, sleep/wake
|
|
18
|
+
- Official libraries: `serial`, `fs`, `math`, `http`, `websocket`
|
|
19
|
+
- Optional runtime typing
|
|
20
|
+
- Async with `sync fn` and `wait`
|
|
21
|
+
- One-liners and stacking
|
|
22
|
+
- CLI with flags and multiple commands
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# After publishing
|
|
30
|
+
npm install -g cajyu
|
|
31
|
+
|
|
32
|
+
# Or from source
|
|
33
|
+
node bin/cajyu.js --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cajyu init
|
|
38
|
+
cajyu inst serial
|
|
39
|
+
cajyu inst http
|
|
40
|
+
cajyu run examples/fatorial.cjy
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## CLI
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
cajyu [flags]
|
|
49
|
+
cajyu <command> [options]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
|------------------|--------------------------------------|
|
|
54
|
+
| `init` | Create a new project |
|
|
55
|
+
| `inst <lib>` | Install a library from CajyuLibs |
|
|
56
|
+
| `run <file.cjy>` | Compile and run a file |
|
|
57
|
+
| `list` | List installed libraries |
|
|
58
|
+
| `update` | Update libraries (planned) |
|
|
59
|
+
|
|
60
|
+
| Flag | Description |
|
|
61
|
+
|------------------|----------------------|
|
|
62
|
+
| `-h, --help` | Show help |
|
|
63
|
+
| `-v, --version` | Show version |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Syntax
|
|
68
|
+
|
|
69
|
+
### Variables
|
|
70
|
+
```cajyu
|
|
71
|
+
var name = "Cajyu"
|
|
72
|
+
var age:Number = 17
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Functions
|
|
76
|
+
```cajyu
|
|
77
|
+
fn add a, b {
|
|
78
|
+
return a + b
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Control flow & loops
|
|
83
|
+
```cajyu
|
|
84
|
+
if x > 10 {
|
|
85
|
+
print("big")
|
|
86
|
+
} elif x > 5 {
|
|
87
|
+
print("medium")
|
|
88
|
+
} else {
|
|
89
|
+
print("small")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for i in range(10) {
|
|
93
|
+
print(i)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Classes
|
|
98
|
+
```cajyu
|
|
99
|
+
class Person {
|
|
100
|
+
Main name, age {
|
|
101
|
+
Self.name = name
|
|
102
|
+
Self.age = age
|
|
103
|
+
}
|
|
104
|
+
greet {
|
|
105
|
+
return "Hello, " + Self.name
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### HTTP
|
|
111
|
+
```cajyu
|
|
112
|
+
import Server from CajyuLibs.http
|
|
113
|
+
|
|
114
|
+
var server = new Server(3000)
|
|
115
|
+
|
|
116
|
+
server.post(fn b {
|
|
117
|
+
if !b.a and !b.b {
|
|
118
|
+
return { code: 400 }
|
|
119
|
+
}
|
|
120
|
+
return { code: 200, result: b.a + b.b }
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### WebSocket
|
|
125
|
+
```cajyu
|
|
126
|
+
import WS from CajyuLibs.websocket
|
|
127
|
+
|
|
128
|
+
var wss = new WS.Server(8080)
|
|
129
|
+
wss.on("connection", fn client {
|
|
130
|
+
print("client connected")
|
|
131
|
+
})
|
|
132
|
+
wss.on("message", fn msg, client {
|
|
133
|
+
wss.broadcast(msg)
|
|
134
|
+
})
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Libraries
|
|
140
|
+
|
|
141
|
+
Official libraries: https://github.com/abs-js/CajyuLibs
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
cajyu inst serial
|
|
145
|
+
cajyu inst fs
|
|
146
|
+
cajyu inst math
|
|
147
|
+
cajyu inst http
|
|
148
|
+
cajyu inst websocket
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Contributing
|
|
154
|
+
|
|
155
|
+
Pull requests are welcome. Priority areas:
|
|
156
|
+
|
|
157
|
+
- A proper parser (current one is regex-based)
|
|
158
|
+
- More language features
|
|
159
|
+
- Additional libraries
|
|
160
|
+
- Better error messages
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|
package/bin/cajyu.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { compileAndRun } from '../src/compiler.js';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const CAJYULIBS_REPO = 'https://github.com/abs-js/CajyuLibs.git';
|
|
12
|
+
const VERSION = '1.1.0';
|
|
13
|
+
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const command = args[0];
|
|
16
|
+
const flags = args.filter(a => a.startsWith('-'));
|
|
17
|
+
|
|
18
|
+
function hasFlag(...names) {
|
|
19
|
+
return names.some(n => flags.includes(n) || flags.includes(`-${n}`) || flags.includes(`--${n}`));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function main() {
|
|
23
|
+
if (hasFlag('v', 'version', '--version')) {
|
|
24
|
+
console.log(`Cajyu ${VERSION}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (hasFlag('h', 'help', '--help') || !command) {
|
|
29
|
+
showHelp();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (command === 'init') {
|
|
34
|
+
initProject();
|
|
35
|
+
} else if (command === 'inst' || command === 'install') {
|
|
36
|
+
const libName = args[1];
|
|
37
|
+
if (!libName || libName.startsWith('-')) {
|
|
38
|
+
console.error('Usage: cajyu inst <library>');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
await installLib(libName);
|
|
42
|
+
} else if (command === 'run') {
|
|
43
|
+
const file = args.find(a => a.endsWith('.cjy') || (a !== 'run' && !a.startsWith('-')));
|
|
44
|
+
if (!file) {
|
|
45
|
+
console.error('Usage: cajyu run <file.cjy>');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
await compileAndRun(file);
|
|
49
|
+
} else if (command === 'list') {
|
|
50
|
+
listInstalled();
|
|
51
|
+
} else if (command === 'update') {
|
|
52
|
+
console.log('Updating is not yet implemented. Re-run `cajyu inst <lib>` after deleting the folder.');
|
|
53
|
+
} else {
|
|
54
|
+
console.error(`Unknown command: ${command}`);
|
|
55
|
+
showHelp();
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function showHelp() {
|
|
61
|
+
console.log(`
|
|
62
|
+
Cajyu ${VERSION} — a custom programming language that transpiles to JavaScript
|
|
63
|
+
|
|
64
|
+
Usage:
|
|
65
|
+
cajyu [flags]
|
|
66
|
+
cajyu <command> [options]
|
|
67
|
+
|
|
68
|
+
Commands:
|
|
69
|
+
init Create a new Cajyu project
|
|
70
|
+
inst <lib> Install a library from CajyuLibs
|
|
71
|
+
run <file.cjy> Compile and execute a Cajyu file
|
|
72
|
+
list List installed libraries
|
|
73
|
+
update Update installed libraries (coming soon)
|
|
74
|
+
|
|
75
|
+
Flags:
|
|
76
|
+
-h, --help Show this help
|
|
77
|
+
-v, --version Show version
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
cajyu init
|
|
81
|
+
cajyu inst http
|
|
82
|
+
cajyu inst websocket
|
|
83
|
+
cajyu run examples/fatorial.cjy
|
|
84
|
+
cajyu list
|
|
85
|
+
`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function initProject() {
|
|
89
|
+
const pkg = {
|
|
90
|
+
name: "cajyu-project",
|
|
91
|
+
version: "1.0.0",
|
|
92
|
+
description: "Cajyu project",
|
|
93
|
+
main: "index.cjy",
|
|
94
|
+
type: "module"
|
|
95
|
+
};
|
|
96
|
+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
|
|
97
|
+
if (!fs.existsSync('CajyuLibs')) fs.mkdirSync('CajyuLibs');
|
|
98
|
+
console.log('Cajyu project initialized.');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function installLib(libName) {
|
|
102
|
+
console.log(`Installing "${libName}" from CajyuLibs...`);
|
|
103
|
+
|
|
104
|
+
const targetDir = path.join(process.cwd(), 'CajyuLibs', libName);
|
|
105
|
+
if (fs.existsSync(targetDir)) {
|
|
106
|
+
console.log(`Library "${libName}" already installed.`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const tmpDir = path.join('/tmp', `cajyulibs-${Date.now()}`);
|
|
111
|
+
try {
|
|
112
|
+
console.log('Cloning CajyuLibs repository...');
|
|
113
|
+
execSync(`git clone --depth 1 ${CAJYULIBS_REPO} ${tmpDir}`, { stdio: 'inherit' });
|
|
114
|
+
|
|
115
|
+
const sourceLib = path.join(tmpDir, libName);
|
|
116
|
+
if (!fs.existsSync(sourceLib)) {
|
|
117
|
+
console.error(`Library "${libName}" not found in CajyuLibs.`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fs.mkdirSync(path.dirname(targetDir), { recursive: true });
|
|
122
|
+
fs.cpSync(sourceLib, targetDir, { recursive: true });
|
|
123
|
+
|
|
124
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
125
|
+
if (fs.existsSync(pkgPath)) {
|
|
126
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
127
|
+
if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
|
|
128
|
+
console.log('Installing library dependencies...');
|
|
129
|
+
execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(`✓ Library "${libName}" installed to CajyuLibs/${libName}/`);
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('Failed to install library:', err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
} finally {
|
|
138
|
+
try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch {}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function listInstalled() {
|
|
143
|
+
const libsDir = path.join(process.cwd(), 'CajyuLibs');
|
|
144
|
+
if (!fs.existsSync(libsDir)) {
|
|
145
|
+
console.log('No libraries installed yet.');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const libs = fs.readdirSync(libsDir).filter(d => fs.statSync(path.join(libsDir, d)).isDirectory());
|
|
149
|
+
if (libs.length === 0) {
|
|
150
|
+
console.log('No libraries installed.');
|
|
151
|
+
} else {
|
|
152
|
+
console.log('Installed libraries:');
|
|
153
|
+
libs.forEach(l => console.log(` - ${l}`));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import print from CajyuLibs.serial
|
|
2
|
+
|
|
3
|
+
class Pessoa {
|
|
4
|
+
Main nome, idade {
|
|
5
|
+
Self.nome = nome
|
|
6
|
+
Self.idade = idade
|
|
7
|
+
}
|
|
8
|
+
// private nome
|
|
9
|
+
// private idade
|
|
10
|
+
apresentar {
|
|
11
|
+
return "Oi, eu sou " + Self.nome + " e tenho " + Self.idade + " anos"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
var p = new Pessoa("Ana", 17)
|
|
16
|
+
print(p.apresentar())
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Server from CajyuLibs.http
|
|
2
|
+
import print from CajyuLibs.serial
|
|
3
|
+
|
|
4
|
+
var server = new Server(3000)
|
|
5
|
+
print("Servidor Cajyu pronto na porta 3000")
|
|
6
|
+
|
|
7
|
+
server.post(fn b {
|
|
8
|
+
if !b.a and !b.b {
|
|
9
|
+
return { code: 400 }
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
code: 200,
|
|
13
|
+
result: b.a + b.b
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
print("POST / com JSON {a, b} para somar")
|
|
18
|
+
print("server.sleep() e server.wake() disponíveis")
|
package/package.json
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cajyu",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.01",
|
|
4
|
+
"description": "Cajyu programming language - a custom language that compiles to JavaScript",
|
|
5
|
+
"main": "src/compiler.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cajyu": "./bin/cajyu.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/cajyu.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["cajyu", "compiler", "language", "javascript"],
|
|
13
|
+
"author": "Cajyu Team",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"dependencies": {},
|
|
16
|
+
"type": "module"
|
|
17
|
+
}
|
package/src/compiler.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
|
|
5
|
+
export async function compileAndRun(filePath) {
|
|
6
|
+
if (!fs.existsSync(filePath)) {
|
|
7
|
+
console.error(`Arquivo não encontrado: ${filePath}`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const source = fs.readFileSync(filePath, 'utf-8');
|
|
11
|
+
const jsCode = transpile(source, path.dirname(filePath));
|
|
12
|
+
const tempFile = path.join('/tmp', `cajyu_${Date.now()}.mjs`);
|
|
13
|
+
fs.writeFileSync(tempFile, jsCode);
|
|
14
|
+
try {
|
|
15
|
+
await import(pathToFileURL(tempFile).href);
|
|
16
|
+
console.log('--- Execução Cajyu ---');
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.error('Erro na execução:', err.message);
|
|
19
|
+
console.error(err.stack);
|
|
20
|
+
} finally {
|
|
21
|
+
try { fs.unlinkSync(tempFile); } catch {}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function transpile(source, baseDir) {
|
|
26
|
+
const lines = source.split('\n');
|
|
27
|
+
const imports = [];
|
|
28
|
+
const codeLines = [];
|
|
29
|
+
for (const line of lines) {
|
|
30
|
+
const m = line.match(/^\s*import\s+(\*|\w+)\s+from\s+['"]?([^\s'"]+)['"]?\s*;?\s*$/);
|
|
31
|
+
if (m) imports.push({ what: m[1], from: m[2] });
|
|
32
|
+
else codeLines.push(line);
|
|
33
|
+
}
|
|
34
|
+
let code = codeLines.join('\n');
|
|
35
|
+
|
|
36
|
+
let importCode = '';
|
|
37
|
+
for (const imp of imports) {
|
|
38
|
+
const libPath = resolveLib(imp.from, baseDir);
|
|
39
|
+
if (libPath && fs.existsSync(libPath)) {
|
|
40
|
+
const url = pathToFileURL(libPath).href;
|
|
41
|
+
if (imp.what === '*') {
|
|
42
|
+
importCode += `const _lib = await import('${url}'); Object.assign(globalThis, _lib.CayjuLib || _lib);\n`;
|
|
43
|
+
} else {
|
|
44
|
+
importCode += `const { CayjuLib: _lib${imp.what} } = await import('${url}'); const ${imp.what} = _lib${imp.what}.${imp.what} || _lib${imp.what};\n`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
code = preprocessKeywords(code);
|
|
50
|
+
code = transpileFunctions(code);
|
|
51
|
+
code = transpileAnonymousFunctions(code);
|
|
52
|
+
code = transpileControlFlow(code);
|
|
53
|
+
code = transpileOneLiners(code);
|
|
54
|
+
|
|
55
|
+
const builtins = `
|
|
56
|
+
function _range(a, b, c) {
|
|
57
|
+
const r = [];
|
|
58
|
+
if (b == null) for (let i = 1; i <= a; i++) r.push(i);
|
|
59
|
+
else if (c == null) for (let i = a; i <= b; i++) r.push(i);
|
|
60
|
+
else for (let i = a; i <= b; i += c) r.push(i);
|
|
61
|
+
return r;
|
|
62
|
+
}
|
|
63
|
+
function _typeCheck(val, type) {
|
|
64
|
+
if (!type) return val;
|
|
65
|
+
const t = String(type).toLowerCase();
|
|
66
|
+
if (t === 'string' && typeof val !== 'string') throw new Error('esperado String');
|
|
67
|
+
if ((t === 'number' || t === 'int' || t === 'float') && typeof val !== 'number') throw new Error('esperado Number');
|
|
68
|
+
if (t === 'boolean' && typeof val !== 'boolean') throw new Error('esperado Boolean');
|
|
69
|
+
if (t === 'array' && !Array.isArray(val)) throw new Error('esperado Array');
|
|
70
|
+
return val;
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const final = `
|
|
75
|
+
${importCode}
|
|
76
|
+
${builtins}
|
|
77
|
+
(async () => {
|
|
78
|
+
${code}
|
|
79
|
+
})().catch(console.error);
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
fs.writeFileSync('/tmp/cajyu_debug.mjs', final);
|
|
83
|
+
return final;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resolveLib(from, baseDir) {
|
|
87
|
+
if (from.startsWith('CajyuLibs')) {
|
|
88
|
+
const name = from.split('.')[1] || 'serial';
|
|
89
|
+
const cands = [
|
|
90
|
+
path.resolve(baseDir, 'CajyuLibs', name, 'main.js'),
|
|
91
|
+
path.resolve(baseDir, '..', 'CajyuLibs', name, 'main.js'),
|
|
92
|
+
path.resolve(process.cwd(), 'CajyuLibs', name, 'main.js'),
|
|
93
|
+
];
|
|
94
|
+
return cands.find(p => fs.existsSync(p));
|
|
95
|
+
}
|
|
96
|
+
return path.resolve(baseDir, from);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function cleanParams(s) {
|
|
100
|
+
return (s || '').trim().split(',').map(p => p.trim().split(':')[0].trim()).filter(Boolean).join(', ');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function preprocessKeywords(code) {
|
|
104
|
+
return code
|
|
105
|
+
.replace(/\band\b/g, '&&')
|
|
106
|
+
.replace(/\bor\b/g, '||')
|
|
107
|
+
.replace(/\bnot\b/g, '!')
|
|
108
|
+
.replace(/sync\s+fn\s+(\w+)/g, 'async function $1')
|
|
109
|
+
.replace(/\bwait\s+/g, 'await ')
|
|
110
|
+
.replace(/\belif\b/g, 'else if')
|
|
111
|
+
.replace(/\bSelf\./g, 'this.')
|
|
112
|
+
.replace(/\brange\(/g, '_range(')
|
|
113
|
+
.replace(/\/\/\s*private\s+(\w+)/g, '/* private $1 */')
|
|
114
|
+
.replace(/var\s+(\w+):(\w+)\s*=\s*(.+)/g, 'let $1 = _typeCheck($3, "$2")')
|
|
115
|
+
.replace(/var\s+(\w+)\s*=/g, 'let $1 =');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function transpileFunctions(code) {
|
|
119
|
+
return code
|
|
120
|
+
.replace(/^fn\s+(\w+)\s+([^{]*)\{/gm, (_, n, p) => `function ${n}(${cleanParams(p)}) {`)
|
|
121
|
+
.replace(/^fn\s+(\w+)\s*\{/gm, 'function $1() {')
|
|
122
|
+
.replace(/Main\s+([^{]*)\{/g, (_, p) => `constructor(${cleanParams(p)}) {`)
|
|
123
|
+
.replace(/^\s*(\w+)\s*\{/gm, (m, name) => {
|
|
124
|
+
const keywords = ['if','else','while','for','return','class','fn','function','constructor'];
|
|
125
|
+
if (keywords.includes(name)) return m;
|
|
126
|
+
return ` ${name}() {`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function transpileAnonymousFunctions(code) {
|
|
131
|
+
return code.replace(/(?<!^|\n)fn\s+([^{]*)\{/g, (_, params) => {
|
|
132
|
+
const p = cleanParams(params);
|
|
133
|
+
return `function(${p}) {`;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function transpileControlFlow(code) {
|
|
138
|
+
return code
|
|
139
|
+
.replace(/if\s+([^{]+?)\s*\{/g, 'if ($1) {')
|
|
140
|
+
.replace(/else\s+if\s+([^{]+?)\s*\{/g, 'else if ($1) {')
|
|
141
|
+
.replace(/while\s+([^{]+?)\s*\{/g, 'while ($1) {')
|
|
142
|
+
.replace(/for\s+(\w+)\s+in\s+([^ {\n]+)(\s*\{)/g, 'for (let $1 of $2) $3');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function transpileOneLiners(code) {
|
|
146
|
+
return code
|
|
147
|
+
.replace(/return\s+(\{[^}]*\}|.+?)\s+if\s+([^;]+);/g, 'if ($2) return $1;')
|
|
148
|
+
.replace(/if\s+([^:{;\n]+)\s+return\s+([^;\n{]+)/g, 'if ($1) return $2;');
|
|
149
|
+
}
|