purus 0.1.0 → 0.2.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/bin/purus.js +50 -1
- package/lib/build-wrapper.js +142 -0
- package/lib/config.js +67 -0
- package/lib/create.js +195 -0
- package/lib/purus-compiler.js +14 -69
- package/lib/run-wrapper.js +111 -0
- package/package.json +1 -1
package/bin/purus.js
CHANGED
|
@@ -1,3 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
const VERSION = require("../package.json").version;
|
|
5
|
+
const cmd = process.argv[2];
|
|
6
|
+
|
|
7
|
+
function printHelp() {
|
|
8
|
+
console.log(`purus v${VERSION} - A language that compiles to JavaScript`);
|
|
9
|
+
console.log("");
|
|
10
|
+
console.log("Usage:");
|
|
11
|
+
console.log(" purus build [file] Compile to JavaScript");
|
|
12
|
+
console.log(" purus build --directory <dir> Compile all files in directory");
|
|
13
|
+
console.log(" purus build --output <dir> Specify output directory");
|
|
14
|
+
console.log(" purus build Compile using config.purus");
|
|
15
|
+
console.log(" .purus -> .js");
|
|
16
|
+
console.log(" .cpurus -> .cjs (CommonJS)");
|
|
17
|
+
console.log(" .mpurus -> .mjs (ES Module)");
|
|
18
|
+
console.log(" purus build --no-header [file] Compile without header comment");
|
|
19
|
+
console.log(" purus run [file] Run without generating files");
|
|
20
|
+
console.log(" purus run --directory <dir> Run all files in directory");
|
|
21
|
+
console.log(" purus run Run using config.purus");
|
|
22
|
+
console.log(" purus check <file> Syntax check only");
|
|
23
|
+
console.log(" purus new [name] [-y] Create a new project");
|
|
24
|
+
console.log(" purus init Initialize project in current directory");
|
|
25
|
+
console.log(" purus version Show version");
|
|
26
|
+
console.log(" purus help Show this help");
|
|
27
|
+
console.log("");
|
|
28
|
+
console.log("Aliases: compile = build, create = new");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (cmd) {
|
|
32
|
+
case "new":
|
|
33
|
+
case "create":
|
|
34
|
+
require("../lib/create.js");
|
|
35
|
+
break;
|
|
36
|
+
case "build":
|
|
37
|
+
case "compile":
|
|
38
|
+
require("../lib/build-wrapper.js");
|
|
39
|
+
break;
|
|
40
|
+
case "run":
|
|
41
|
+
require("../lib/run-wrapper.js");
|
|
42
|
+
break;
|
|
43
|
+
case "help":
|
|
44
|
+
case "--help":
|
|
45
|
+
case "-h":
|
|
46
|
+
case undefined:
|
|
47
|
+
printHelp();
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
require("../lib/purus-compiler.js");
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { loadConfig } = require("./config.js");
|
|
6
|
+
const { compile } = require("./purus-core.js");
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(3);
|
|
9
|
+
|
|
10
|
+
let file = null;
|
|
11
|
+
let directory = null;
|
|
12
|
+
let output = null;
|
|
13
|
+
let noHeader = false;
|
|
14
|
+
let toStdout = false;
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < args.length; i++) {
|
|
17
|
+
if (args[i] === "--no-header") {
|
|
18
|
+
noHeader = true;
|
|
19
|
+
} else if (args[i] === "--stdout") {
|
|
20
|
+
toStdout = true;
|
|
21
|
+
} else if (args[i] === "--directory" || args[i] === "-d") {
|
|
22
|
+
directory = args[++i];
|
|
23
|
+
} else if (args[i] === "--output" || args[i] === "-o") {
|
|
24
|
+
output = args[++i];
|
|
25
|
+
} else if (!args[i].startsWith("-")) {
|
|
26
|
+
file = args[i];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (file) {
|
|
31
|
+
// Single file - delegate to MoonBit compiler
|
|
32
|
+
require("./purus-compiler.js");
|
|
33
|
+
} else {
|
|
34
|
+
let entryDir;
|
|
35
|
+
let outputDir;
|
|
36
|
+
let useHeader;
|
|
37
|
+
|
|
38
|
+
if (directory) {
|
|
39
|
+
entryDir = path.resolve(directory);
|
|
40
|
+
outputDir = output ? path.resolve(output) : path.resolve("dist");
|
|
41
|
+
useHeader = !noHeader;
|
|
42
|
+
|
|
43
|
+
const result = loadConfig();
|
|
44
|
+
if (result) {
|
|
45
|
+
if (!output) {
|
|
46
|
+
outputDir = path.resolve(
|
|
47
|
+
result.configDir,
|
|
48
|
+
result.config.output || "dist"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
useHeader = result.config.header !== false && !noHeader;
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
const result = loadConfig();
|
|
55
|
+
if (!result) {
|
|
56
|
+
console.log("Error: no input file specified and no config.purus found");
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log("Usage:");
|
|
59
|
+
console.log(" purus build <file> Compile a single file");
|
|
60
|
+
console.log(
|
|
61
|
+
" purus build --directory <dir> Compile all files in directory"
|
|
62
|
+
);
|
|
63
|
+
console.log(
|
|
64
|
+
" purus build Compile using config.purus"
|
|
65
|
+
);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { config, configDir } = result;
|
|
70
|
+
entryDir = path.resolve(configDir, config.entry || "src");
|
|
71
|
+
outputDir = output
|
|
72
|
+
? path.resolve(output)
|
|
73
|
+
: path.resolve(configDir, config.output || "dist");
|
|
74
|
+
useHeader = config.header !== false && !noHeader;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!fs.existsSync(entryDir)) {
|
|
78
|
+
console.log(`Error: entry directory '${entryDir}' not found`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const stat = fs.statSync(entryDir);
|
|
83
|
+
let files;
|
|
84
|
+
|
|
85
|
+
if (stat.isFile()) {
|
|
86
|
+
files = [entryDir];
|
|
87
|
+
// For single file entry, output is a file too
|
|
88
|
+
if (!fs.existsSync(path.dirname(outputDir))) {
|
|
89
|
+
fs.mkdirSync(path.dirname(outputDir), { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
files = findPurusFiles(entryDir);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (files.length === 0) {
|
|
96
|
+
console.log(`No .purus files found in ${entryDir}`);
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let count = 0;
|
|
101
|
+
for (const f of files) {
|
|
102
|
+
const source = fs.readFileSync(f, "utf8");
|
|
103
|
+
const js = compile(source, { header: useHeader });
|
|
104
|
+
let outputPath;
|
|
105
|
+
|
|
106
|
+
if (stat.isFile()) {
|
|
107
|
+
outputPath = outputDir;
|
|
108
|
+
} else {
|
|
109
|
+
outputPath = getOutputPath(f, entryDir, outputDir);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
113
|
+
fs.writeFileSync(outputPath, js);
|
|
114
|
+
console.log(
|
|
115
|
+
`Compiled ${path.relative(process.cwd(), f)} -> ${path.relative(process.cwd(), outputPath)}`
|
|
116
|
+
);
|
|
117
|
+
count++;
|
|
118
|
+
}
|
|
119
|
+
console.log(`\n${count} file${count === 1 ? "" : "s"} compiled.`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function findPurusFiles(dir) {
|
|
123
|
+
const results = [];
|
|
124
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
125
|
+
const fullPath = path.join(dir, entry.name);
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
results.push(...findPurusFiles(fullPath));
|
|
128
|
+
} else if (/\.(c|m)?purus$/.test(entry.name)) {
|
|
129
|
+
results.push(fullPath);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return results;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getOutputPath(inputFile, inputBase, outputBase) {
|
|
136
|
+
const relative = path.relative(inputBase, inputFile);
|
|
137
|
+
let ext = ".js";
|
|
138
|
+
if (inputFile.endsWith(".cpurus")) ext = ".cjs";
|
|
139
|
+
else if (inputFile.endsWith(".mpurus")) ext = ".mjs";
|
|
140
|
+
const base = relative.replace(/\.(c|m)?purus$/, "");
|
|
141
|
+
return path.join(outputBase, base + ext);
|
|
142
|
+
}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
function parseConfig(configPath) {
|
|
7
|
+
const content = fs.readFileSync(configPath, "utf8");
|
|
8
|
+
const config = {};
|
|
9
|
+
|
|
10
|
+
for (const line of content.split("\n")) {
|
|
11
|
+
const trimmed = line.trim();
|
|
12
|
+
if (trimmed === "" || trimmed.startsWith("--")) continue;
|
|
13
|
+
|
|
14
|
+
const match = trimmed.match(/^const\s+([\w.-]+)\s+be\s+(.+)$/);
|
|
15
|
+
if (!match) continue;
|
|
16
|
+
|
|
17
|
+
const key = match[1];
|
|
18
|
+
let value = match[2].trim();
|
|
19
|
+
|
|
20
|
+
if (value.startsWith("///") && value.endsWith("///")) {
|
|
21
|
+
value = value.slice(3, -3);
|
|
22
|
+
} else if (value === "true") {
|
|
23
|
+
value = true;
|
|
24
|
+
} else if (value === "false") {
|
|
25
|
+
value = false;
|
|
26
|
+
} else if (/^\d+$/.test(value)) {
|
|
27
|
+
value = parseInt(value, 10);
|
|
28
|
+
} else if (/^\d+\.\d+$/.test(value)) {
|
|
29
|
+
value = parseFloat(value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const keys = key.split(".");
|
|
33
|
+
let target = config;
|
|
34
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
35
|
+
if (!target[keys[i]] || typeof target[keys[i]] !== "object") {
|
|
36
|
+
target[keys[i]] = {};
|
|
37
|
+
}
|
|
38
|
+
target = target[keys[i]];
|
|
39
|
+
}
|
|
40
|
+
target[keys[keys.length - 1]] = value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return config;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findConfig(startDir) {
|
|
47
|
+
let dir = startDir || process.cwd();
|
|
48
|
+
while (true) {
|
|
49
|
+
const configPath = path.join(dir, "config.purus");
|
|
50
|
+
if (fs.existsSync(configPath)) return configPath;
|
|
51
|
+
const parent = path.dirname(dir);
|
|
52
|
+
if (parent === dir) return null;
|
|
53
|
+
dir = parent;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadConfig(startDir) {
|
|
58
|
+
const configPath = findConfig(startDir);
|
|
59
|
+
if (!configPath) return null;
|
|
60
|
+
return {
|
|
61
|
+
config: parseConfig(configPath),
|
|
62
|
+
configPath,
|
|
63
|
+
configDir: path.dirname(configPath),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { parseConfig, findConfig, loadConfig };
|
package/lib/create.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const readline = require("readline");
|
|
6
|
+
const { spawnSync } = require("child_process");
|
|
7
|
+
|
|
8
|
+
function question(rl, text) {
|
|
9
|
+
return new Promise((resolve) => rl.question(text, (a) => resolve(a.trim())));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function isDirEmpty(dir) {
|
|
13
|
+
return fs.readdirSync(dir).length === 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function run() {
|
|
17
|
+
const args = process.argv.slice(3);
|
|
18
|
+
const yesFlag = args.includes("-y") || args.includes("--yes");
|
|
19
|
+
const positionalArgs = args.filter((a) => !a.startsWith("-"));
|
|
20
|
+
|
|
21
|
+
let projectName = positionalArgs[0] || "";
|
|
22
|
+
|
|
23
|
+
const rl = readline.createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
if (!projectName) {
|
|
30
|
+
projectName = await question(rl, "Project name: ");
|
|
31
|
+
if (!projectName) {
|
|
32
|
+
console.log("Error: project name required");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const projectDir = path.resolve(projectName);
|
|
38
|
+
|
|
39
|
+
if (fs.existsSync(projectDir) && !isDirEmpty(projectDir)) {
|
|
40
|
+
console.log(`Error: directory '${projectName}' already exists and is not empty`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`\nCreating project in ./${projectName}...`);
|
|
45
|
+
fs.mkdirSync(path.join(projectDir, "src"), { recursive: true });
|
|
46
|
+
|
|
47
|
+
// config.purus
|
|
48
|
+
const configPurus = `-- Purus Configuration
|
|
49
|
+
|
|
50
|
+
const entry be ///src///
|
|
51
|
+
const output be ///dist///
|
|
52
|
+
const header be true
|
|
53
|
+
|
|
54
|
+
-- Linter settings
|
|
55
|
+
const lint.no-var be ///warn///
|
|
56
|
+
const lint.indent-size be 2
|
|
57
|
+
const lint.max-line-length be ///off///
|
|
58
|
+
`;
|
|
59
|
+
fs.writeFileSync(path.join(projectDir, "config.purus"), configPurus);
|
|
60
|
+
|
|
61
|
+
// .prettierrc
|
|
62
|
+
const prettierrc =
|
|
63
|
+
JSON.stringify(
|
|
64
|
+
{
|
|
65
|
+
tabWidth: 2,
|
|
66
|
+
semi: false,
|
|
67
|
+
plugins: ["@puruslang/prettier-plugin-purus"],
|
|
68
|
+
},
|
|
69
|
+
null,
|
|
70
|
+
2
|
|
71
|
+
) + "\n";
|
|
72
|
+
fs.writeFileSync(path.join(projectDir, ".prettierrc"), prettierrc);
|
|
73
|
+
|
|
74
|
+
// src/main.purus
|
|
75
|
+
const mainPurus = `-- main.purus
|
|
76
|
+
|
|
77
|
+
const message be ///Hello, World///
|
|
78
|
+
console.log[message]
|
|
79
|
+
`;
|
|
80
|
+
fs.writeFileSync(path.join(projectDir, "src/main.purus"), mainPurus);
|
|
81
|
+
|
|
82
|
+
// README.md
|
|
83
|
+
const readme = `# ${projectName}
|
|
84
|
+
|
|
85
|
+
A [Purus](https://purus.work) project.
|
|
86
|
+
|
|
87
|
+
## Getting Started
|
|
88
|
+
|
|
89
|
+
\`\`\`sh
|
|
90
|
+
npm install
|
|
91
|
+
purus build
|
|
92
|
+
\`\`\`
|
|
93
|
+
|
|
94
|
+
## Scripts
|
|
95
|
+
|
|
96
|
+
| Script | Description |
|
|
97
|
+
|---|---|
|
|
98
|
+
| \`npm run build\` | Compile Purus to JavaScript |
|
|
99
|
+
| \`npm run exec\` | Run without compiling to files |
|
|
100
|
+
| \`npm run format\` | Format with Prettier |
|
|
101
|
+
| \`npm run lint\` | Lint with purus-lint |
|
|
102
|
+
`;
|
|
103
|
+
fs.writeFileSync(path.join(projectDir, "README.md"), readme);
|
|
104
|
+
|
|
105
|
+
// .gitignore
|
|
106
|
+
const gitignore = `dist/
|
|
107
|
+
node_modules/
|
|
108
|
+
`;
|
|
109
|
+
fs.writeFileSync(path.join(projectDir, ".gitignore"), gitignore);
|
|
110
|
+
|
|
111
|
+
console.log(" config.purus");
|
|
112
|
+
console.log(" .prettierrc");
|
|
113
|
+
console.log(" .gitignore");
|
|
114
|
+
console.log(" README.md");
|
|
115
|
+
console.log(" src/main.purus");
|
|
116
|
+
|
|
117
|
+
// npm init
|
|
118
|
+
console.log("");
|
|
119
|
+
if (yesFlag) {
|
|
120
|
+
console.log("Running npm init -y...");
|
|
121
|
+
spawnSync("npm", ["init", "-y"], {
|
|
122
|
+
cwd: projectDir,
|
|
123
|
+
stdio: "inherit",
|
|
124
|
+
shell: true,
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
console.log("Running npm init...");
|
|
128
|
+
spawnSync("npm", ["init"], {
|
|
129
|
+
cwd: projectDir,
|
|
130
|
+
stdio: "inherit",
|
|
131
|
+
shell: true,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Add scripts to package.json
|
|
136
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
137
|
+
if (fs.existsSync(pkgPath)) {
|
|
138
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
139
|
+
pkg.scripts = {
|
|
140
|
+
...(pkg.scripts || {}),
|
|
141
|
+
purus: "purus",
|
|
142
|
+
build: "purus build",
|
|
143
|
+
compile: "purus compile",
|
|
144
|
+
exec: "purus run",
|
|
145
|
+
format: "prettier --write ./src",
|
|
146
|
+
lint: "purus-lint",
|
|
147
|
+
};
|
|
148
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
149
|
+
console.log("\nAdded scripts to package.json");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Ask about dependencies
|
|
153
|
+
let installDeps;
|
|
154
|
+
if (yesFlag) {
|
|
155
|
+
installDeps = true;
|
|
156
|
+
} else {
|
|
157
|
+
const answer = await question(rl, "\nInstall dependencies? (y/N) ");
|
|
158
|
+
installDeps =
|
|
159
|
+
answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (installDeps) {
|
|
163
|
+
const devDeps = [
|
|
164
|
+
"@puruslang/linter",
|
|
165
|
+
"@puruslang/prettier-plugin-purus",
|
|
166
|
+
"prettier",
|
|
167
|
+
"purus",
|
|
168
|
+
];
|
|
169
|
+
console.log("\nInstalling devDependencies...");
|
|
170
|
+
for (const dep of devDeps) {
|
|
171
|
+
console.log(` ${dep}`);
|
|
172
|
+
}
|
|
173
|
+
console.log("");
|
|
174
|
+
spawnSync("npm", ["install", "--save-dev", ...devDeps], {
|
|
175
|
+
cwd: projectDir,
|
|
176
|
+
stdio: "inherit",
|
|
177
|
+
shell: true,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.log("\nDone! To get started:");
|
|
182
|
+
console.log(` cd ${projectName}`);
|
|
183
|
+
if (!installDeps) {
|
|
184
|
+
console.log(" npm install");
|
|
185
|
+
}
|
|
186
|
+
console.log(" purus build");
|
|
187
|
+
} finally {
|
|
188
|
+
rl.close();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
run().catch((err) => {
|
|
193
|
+
console.error(err.message);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
});
|
package/lib/purus-compiler.js
CHANGED
|
@@ -616,7 +616,7 @@ function $64$username$47$core$46$MatchBody$BlockBody(param0) {
|
|
|
616
616
|
$64$username$47$core$46$MatchBody$BlockBody.prototype.$tag = 1;
|
|
617
617
|
$64$username$47$core$46$MatchBody$BlockBody.prototype.$name = "BlockBody";
|
|
618
618
|
const _M0FP095_40moonbitlang_2fcore_2fbuiltin_2eStringBuilder_24as_24_40moonbitlang_2fcore_2fbuiltin_2eLogger = { method_0: _M0IP311moonbitlang4core7builtin13StringBuilderP311moonbitlang4core7builtin6Logger13write__string, method_1: _M0IP016_24default__implP311moonbitlang4core7builtin6Logger16write__substringGRP311moonbitlang4core7builtin13StringBuilderE, method_2: _M0IP311moonbitlang4core7builtin13StringBuilderP311moonbitlang4core7builtin6Logger11write__view, method_3: _M0IP311moonbitlang4core7builtin13StringBuilderP311moonbitlang4core7builtin6Logger11write__char };
|
|
619
|
-
const _M0FP48username4core3cmd4main7version = "0.
|
|
619
|
+
const _M0FP48username4core3cmd4main7version = "0.2.0";
|
|
620
620
|
const _M0FP311moonbitlang4core7builtin33brute__force__find_2econstr_2f209 = 0;
|
|
621
621
|
const _M0FP311moonbitlang4core7builtin43boyer__moore__horspool__find_2econstr_2f195 = 0;
|
|
622
622
|
function _M0FP311moonbitlang4core5abort5abortGRP311moonbitlang4core7builtin9ArrayViewGsEE(msg) {
|
|
@@ -7867,11 +7867,11 @@ function _M0FP48username4core3cmd4main8cmd__new(name) {
|
|
|
7867
7867
|
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: cannot create src directory: ${msg}`);
|
|
7868
7868
|
return undefined;
|
|
7869
7869
|
}
|
|
7870
|
-
const
|
|
7870
|
+
const main_purus = "-- main.purus\n\nconst message be ///Hello, World///\nconsole.log[message]\n";
|
|
7871
7871
|
let _try_err$3;
|
|
7872
7872
|
_L$3: {
|
|
7873
7873
|
_L$4: {
|
|
7874
|
-
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner(`${name}/purus
|
|
7874
|
+
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner(`${name}/src/main.purus`, main_purus, "utf8");
|
|
7875
7875
|
if (_bind.$tag === 1) {
|
|
7876
7876
|
const _ok = _bind;
|
|
7877
7877
|
_ok._0;
|
|
@@ -7892,11 +7892,11 @@ function _M0FP48username4core3cmd4main8cmd__new(name) {
|
|
|
7892
7892
|
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: ${msg}`);
|
|
7893
7893
|
return undefined;
|
|
7894
7894
|
}
|
|
7895
|
-
const
|
|
7895
|
+
const gitignore = "*.js\nnode_modules/\n";
|
|
7896
7896
|
let _try_err$4;
|
|
7897
7897
|
_L$4: {
|
|
7898
7898
|
_L$5: {
|
|
7899
|
-
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner(`${name}
|
|
7899
|
+
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner(`${name}/.gitignore`, gitignore, "utf8");
|
|
7900
7900
|
if (_bind.$tag === 1) {
|
|
7901
7901
|
const _ok = _bind;
|
|
7902
7902
|
_ok._0;
|
|
@@ -7917,41 +7917,11 @@ function _M0FP48username4core3cmd4main8cmd__new(name) {
|
|
|
7917
7917
|
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: ${msg}`);
|
|
7918
7918
|
return undefined;
|
|
7919
7919
|
}
|
|
7920
|
-
const gitignore = "*.js\nnode_modules/\n";
|
|
7921
|
-
let _try_err$5;
|
|
7922
|
-
_L$5: {
|
|
7923
|
-
_L$6: {
|
|
7924
|
-
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner(`${name}/.gitignore`, gitignore, "utf8");
|
|
7925
|
-
if (_bind.$tag === 1) {
|
|
7926
|
-
const _ok = _bind;
|
|
7927
|
-
_ok._0;
|
|
7928
|
-
} else {
|
|
7929
|
-
const _err = _bind;
|
|
7930
|
-
_try_err$5 = _err._0;
|
|
7931
|
-
break _L$6;
|
|
7932
|
-
}
|
|
7933
|
-
break _L$5;
|
|
7934
|
-
}
|
|
7935
|
-
let msg;
|
|
7936
|
-
_L$7: {
|
|
7937
|
-
const _IOError = _try_err$5;
|
|
7938
|
-
const _msg = _IOError._0;
|
|
7939
|
-
msg = _msg;
|
|
7940
|
-
break _L$7;
|
|
7941
|
-
}
|
|
7942
|
-
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: ${msg}`);
|
|
7943
|
-
return undefined;
|
|
7944
|
-
}
|
|
7945
7920
|
_M0FP311moonbitlang4core7builtin7printlnGsE(`Created project '${name}'`);
|
|
7946
|
-
_M0FP311moonbitlang4core7builtin7printlnGsE(` ${name}/purus.json`);
|
|
7947
7921
|
_M0FP311moonbitlang4core7builtin7printlnGsE(` ${name}/src/main.purus`);
|
|
7948
7922
|
_M0FP311moonbitlang4core7builtin7printlnGsE(` ${name}/.gitignore`);
|
|
7949
7923
|
}
|
|
7950
7924
|
function _M0FP48username4core3cmd4main9cmd__init() {
|
|
7951
|
-
if (_M0FP311moonbitlang1x2fs12path__exists("purus.json")) {
|
|
7952
|
-
_M0FP311moonbitlang4core7builtin7printlnGsE("Error: purus.json already exists in current directory");
|
|
7953
|
-
return undefined;
|
|
7954
|
-
}
|
|
7955
7925
|
if (!_M0FP311moonbitlang1x2fs12path__exists("src")) {
|
|
7956
7926
|
let _try_err;
|
|
7957
7927
|
_L: {
|
|
@@ -7978,53 +7948,28 @@ function _M0FP48username4core3cmd4main9cmd__init() {
|
|
|
7978
7948
|
return undefined;
|
|
7979
7949
|
}
|
|
7980
7950
|
}
|
|
7981
|
-
const purus_json = "{\n \"name\": \"my-project\",\n \"version\": \"0.1.0\",\n \"main\": \"src/main.purus\"\n}\n";
|
|
7982
|
-
let _try_err;
|
|
7983
|
-
_L: {
|
|
7984
|
-
_L$2: {
|
|
7985
|
-
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner("purus.json", purus_json, "utf8");
|
|
7986
|
-
if (_bind.$tag === 1) {
|
|
7987
|
-
const _ok = _bind;
|
|
7988
|
-
_ok._0;
|
|
7989
|
-
} else {
|
|
7990
|
-
const _err = _bind;
|
|
7991
|
-
_try_err = _err._0;
|
|
7992
|
-
break _L$2;
|
|
7993
|
-
}
|
|
7994
|
-
break _L;
|
|
7995
|
-
}
|
|
7996
|
-
let msg;
|
|
7997
|
-
_L$3: {
|
|
7998
|
-
const _IOError = _try_err;
|
|
7999
|
-
const _msg = _IOError._0;
|
|
8000
|
-
msg = _msg;
|
|
8001
|
-
break _L$3;
|
|
8002
|
-
}
|
|
8003
|
-
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: ${msg}`);
|
|
8004
|
-
return undefined;
|
|
8005
|
-
}
|
|
8006
7951
|
if (!_M0FP311moonbitlang1x2fs12path__exists("src/main.purus")) {
|
|
8007
7952
|
const main_purus = "-- main.purus\n\nconst message be ///Hello, World///\nconsole.log[message]\n";
|
|
8008
|
-
let _try_err
|
|
8009
|
-
_L
|
|
8010
|
-
_L$
|
|
7953
|
+
let _try_err;
|
|
7954
|
+
_L: {
|
|
7955
|
+
_L$2: {
|
|
8011
7956
|
const _bind = _M0FP311moonbitlang1x2fs31write__string__to__file_2einner("src/main.purus", main_purus, "utf8");
|
|
8012
7957
|
if (_bind.$tag === 1) {
|
|
8013
7958
|
const _ok = _bind;
|
|
8014
7959
|
_ok._0;
|
|
8015
7960
|
} else {
|
|
8016
7961
|
const _err = _bind;
|
|
8017
|
-
_try_err
|
|
8018
|
-
break _L$
|
|
7962
|
+
_try_err = _err._0;
|
|
7963
|
+
break _L$2;
|
|
8019
7964
|
}
|
|
8020
|
-
break _L
|
|
7965
|
+
break _L;
|
|
8021
7966
|
}
|
|
8022
7967
|
let msg;
|
|
8023
|
-
_L$
|
|
8024
|
-
const _IOError = _try_err
|
|
7968
|
+
_L$3: {
|
|
7969
|
+
const _IOError = _try_err;
|
|
8025
7970
|
const _msg = _IOError._0;
|
|
8026
7971
|
msg = _msg;
|
|
8027
|
-
break _L$
|
|
7972
|
+
break _L$3;
|
|
8028
7973
|
}
|
|
8029
7974
|
_M0FP311moonbitlang4core7builtin7printlnGsE(`Error: ${msg}`);
|
|
8030
7975
|
return undefined;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { execFileSync } = require("child_process");
|
|
6
|
+
const { loadConfig } = require("./config.js");
|
|
7
|
+
const { compile } = require("./purus-core.js");
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(3);
|
|
10
|
+
|
|
11
|
+
let file = null;
|
|
12
|
+
let directory = null;
|
|
13
|
+
let noHeader = false;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
if (args[i] === "--no-header") {
|
|
17
|
+
noHeader = true;
|
|
18
|
+
} else if (args[i] === "--directory" || args[i] === "-d") {
|
|
19
|
+
directory = args[++i];
|
|
20
|
+
} else if (!args[i].startsWith("-")) {
|
|
21
|
+
file = args[i];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (file) {
|
|
26
|
+
// Single file - compile and run
|
|
27
|
+
const source = fs.readFileSync(file, "utf8");
|
|
28
|
+
const js = compile(source, { header: false });
|
|
29
|
+
const m = new (require("module"))();
|
|
30
|
+
m._compile(js, file);
|
|
31
|
+
} else {
|
|
32
|
+
let entryDir;
|
|
33
|
+
let useHeader;
|
|
34
|
+
|
|
35
|
+
if (directory) {
|
|
36
|
+
entryDir = path.resolve(directory);
|
|
37
|
+
useHeader = false;
|
|
38
|
+
} else {
|
|
39
|
+
const result = loadConfig();
|
|
40
|
+
if (!result) {
|
|
41
|
+
console.log("Error: no input file specified and no config.purus found");
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log("Usage:");
|
|
44
|
+
console.log(" purus run <file> Run a single file");
|
|
45
|
+
console.log(
|
|
46
|
+
" purus run --directory <dir> Run all files in directory"
|
|
47
|
+
);
|
|
48
|
+
console.log(" purus run Run using config.purus");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { config, configDir } = result;
|
|
53
|
+
entryDir = path.resolve(configDir, config.entry || "src");
|
|
54
|
+
useHeader = false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!fs.existsSync(entryDir)) {
|
|
58
|
+
console.log(`Error: entry directory '${entryDir}' not found`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stat = fs.statSync(entryDir);
|
|
63
|
+
let files;
|
|
64
|
+
|
|
65
|
+
if (stat.isFile()) {
|
|
66
|
+
files = [entryDir];
|
|
67
|
+
} else {
|
|
68
|
+
files = findPurusFiles(entryDir);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (files.length === 0) {
|
|
72
|
+
console.log(`No .purus files found in ${entryDir}`);
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for (const f of files) {
|
|
77
|
+
const source = fs.readFileSync(f, "utf8");
|
|
78
|
+
const js = compile(source, { header: false });
|
|
79
|
+
|
|
80
|
+
const tmpFile = path.join(
|
|
81
|
+
require("os").tmpdir(),
|
|
82
|
+
`purus_run_${Date.now()}_${Math.random().toString(36).slice(2)}.js`
|
|
83
|
+
);
|
|
84
|
+
try {
|
|
85
|
+
fs.writeFileSync(tmpFile, js, "utf8");
|
|
86
|
+
execFileSync(process.execPath, [tmpFile], {
|
|
87
|
+
stdio: "inherit",
|
|
88
|
+
cwd: path.dirname(f),
|
|
89
|
+
});
|
|
90
|
+
} finally {
|
|
91
|
+
try {
|
|
92
|
+
fs.unlinkSync(tmpFile);
|
|
93
|
+
} catch {
|
|
94
|
+
// ignore cleanup errors
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function findPurusFiles(dir) {
|
|
101
|
+
const results = [];
|
|
102
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
103
|
+
const fullPath = path.join(dir, entry.name);
|
|
104
|
+
if (entry.isDirectory()) {
|
|
105
|
+
results.push(...findPurusFiles(fullPath));
|
|
106
|
+
} else if (/\.(c|m)?purus$/.test(entry.name)) {
|
|
107
|
+
results.push(fullPath);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return results;
|
|
111
|
+
}
|