arc-lang 0.5.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/dist/index.js ADDED
@@ -0,0 +1,165 @@
1
+ // Arc Language CLI Entry Point
2
+ import { readFileSync, writeFileSync } from "fs";
3
+ import { resolve } from "path";
4
+ import { lex } from "./lexer.js";
5
+ import { parse } from "./parser.js";
6
+ import { interpret } from "./interpreter.js";
7
+ import { createUseHandler } from "./modules.js";
8
+ import { generateIR, printIR } from "./ir.js";
9
+ import { analyze } from "./semantic.js";
10
+ import { optimize } from "./optimizer.js";
11
+ import { generateJS } from "./codegen-js.js";
12
+ import { generateWAT } from "./codegen.js";
13
+ import { format } from "./formatter.js";
14
+ import { lint, formatDiagnostic } from "./linter.js";
15
+ import { printVersion } from "./version.js";
16
+ import { setPrettyErrors } from "./errors.js";
17
+ const args = process.argv.slice(2);
18
+ if (args.includes("--no-pretty-errors"))
19
+ setPrettyErrors(false);
20
+ const command = args[0];
21
+ const file = args[1];
22
+ const target = args.find(a => a.startsWith("--target="))?.split("=")[1] ?? "js";
23
+ if (command === "version" || args.includes("--version") || args.includes("-v")) {
24
+ printVersion();
25
+ process.exit(0);
26
+ }
27
+ else if (command === "bench") {
28
+ const benchArgs = args.slice(1);
29
+ if (benchArgs.includes("--tokens")) {
30
+ // @ts-ignore - benchmarks outside rootDir
31
+ import("../benchmarks/token-efficiency.js");
32
+ }
33
+ else {
34
+ // @ts-ignore - benchmarks outside rootDir
35
+ import("../benchmarks/bench.js");
36
+ }
37
+ }
38
+ else if (command === "repl") {
39
+ import("./repl.js");
40
+ }
41
+ else if (command === "fuzz") {
42
+ const iterArg = args.find(a => a.startsWith("--iterations="));
43
+ const iterations = iterArg ? parseInt(iterArg.split("=")[1]) : 1000;
44
+ // @ts-ignore - tests outside rootDir
45
+ import("../../tests/fuzz/fuzzer.js").then(({ runFuzzer, fuzzReport }) => {
46
+ console.log(`Running fuzzer with ${iterations} iterations...`);
47
+ const result = runFuzzer(iterations);
48
+ fuzzReport(result);
49
+ if (result.crashes.length > 0)
50
+ process.exit(1);
51
+ });
52
+ }
53
+ else if (!command || !file) {
54
+ console.log("Usage:");
55
+ console.log(" npx tsx src/index.ts run <file.arc> - Execute an Arc file");
56
+ console.log(" npx tsx src/index.ts parse <file.arc> - Print the AST");
57
+ console.log(" npx tsx src/index.ts ir <file.arc> - Print the IR");
58
+ console.log(" npx tsx src/index.ts opt <file.arc> - Print optimized IR");
59
+ console.log(" npx tsx src/index.ts compile <file.arc> - Compile to JS (or --target=wat)");
60
+ console.log(" npx tsx src/index.ts check <file.arc> - Run semantic analysis");
61
+ console.log(" npx tsx src/index.ts fmt <file.arc> - Format source code");
62
+ console.log(" npx tsx src/index.ts lint <file.arc> - Lint source code");
63
+ console.log(" npx tsx src/index.ts repl - Start interactive REPL");
64
+ console.log(" npx tsx src/index.ts fuzz [--iterations=N] - Fuzz test the language");
65
+ console.log(" npx tsx src/index.ts bench - Run performance benchmarks");
66
+ console.log(" npx tsx src/index.ts bench --tokens - Run token efficiency comparison");
67
+ process.exit(1);
68
+ }
69
+ else {
70
+ const filePath = resolve(file);
71
+ let source;
72
+ try {
73
+ source = readFileSync(filePath, "utf-8");
74
+ }
75
+ catch {
76
+ console.error(`Error: Cannot read file '${filePath}'`);
77
+ process.exit(1);
78
+ }
79
+ try {
80
+ if (command === "fmt") {
81
+ const formatted = format(source);
82
+ if (args.includes("--write")) {
83
+ writeFileSync(filePath, formatted);
84
+ console.log(`Formatted ${filePath}`);
85
+ }
86
+ else {
87
+ process.stdout.write(formatted);
88
+ }
89
+ }
90
+ else if (command === "lint") {
91
+ const diagnostics = lint(source, { file: filePath });
92
+ if (diagnostics.length === 0) {
93
+ console.log("No lint issues found.");
94
+ }
95
+ else {
96
+ for (const d of diagnostics) {
97
+ console.log(formatDiagnostic(d));
98
+ }
99
+ const warnings = diagnostics.filter(d => d.severity === "warning");
100
+ const errors = diagnostics.filter(d => d.severity === "error");
101
+ console.log(`\n${diagnostics.length} issue(s): ${errors.length} error(s), ${warnings.length} warning(s), ${diagnostics.length - errors.length - warnings.length} info`);
102
+ if (errors.length > 0)
103
+ process.exit(1);
104
+ }
105
+ }
106
+ else {
107
+ const tokens = lex(source);
108
+ const ast = parse(tokens);
109
+ if (command === "parse") {
110
+ console.log(JSON.stringify(ast, null, 2));
111
+ }
112
+ else if (command === "check") {
113
+ const diagnostics = analyze(ast);
114
+ if (diagnostics.length === 0) {
115
+ console.log("No issues found.");
116
+ }
117
+ else {
118
+ for (const d of diagnostics) {
119
+ const prefix = d.level === "error" ? "ERROR" : "WARN";
120
+ console.log(`[${prefix}] Line ${d.loc.line}:${d.loc.col} — ${d.message}`);
121
+ }
122
+ const errors = diagnostics.filter(d => d.level === "error");
123
+ if (errors.length > 0)
124
+ process.exit(1);
125
+ }
126
+ }
127
+ else if (command === "ir") {
128
+ const irModule = generateIR(ast);
129
+ const useOpt = args.includes("--optimize");
130
+ if (useOpt) {
131
+ const optimized = optimize(irModule);
132
+ console.log(printIR(optimized));
133
+ }
134
+ else {
135
+ console.log(printIR(irModule));
136
+ }
137
+ }
138
+ else if (command === "opt") {
139
+ const irModule = generateIR(ast);
140
+ const optimized = optimize(irModule);
141
+ console.log(printIR(optimized));
142
+ }
143
+ else if (command === "compile") {
144
+ const irModule = generateIR(ast);
145
+ if (target === "wat") {
146
+ console.log(generateWAT(irModule));
147
+ }
148
+ else {
149
+ console.log(generateJS(irModule));
150
+ }
151
+ }
152
+ else if (command === "run") {
153
+ interpret(ast, createUseHandler(filePath));
154
+ }
155
+ else {
156
+ console.error(`Unknown command: ${command}`);
157
+ process.exit(1);
158
+ }
159
+ }
160
+ }
161
+ catch (e) {
162
+ console.error(e.message);
163
+ process.exit(1);
164
+ }
165
+ }
@@ -0,0 +1,39 @@
1
+ import * as AST from "./ast.js";
2
+ type Value = number | string | boolean | null | Value[] | MapValue | FnValue | AsyncValue;
3
+ interface AsyncValue {
4
+ __async: true;
5
+ thunk: () => Value;
6
+ }
7
+ interface MapValue {
8
+ __map: true;
9
+ entries: Map<string, Value>;
10
+ }
11
+ interface FnValue {
12
+ __fn: true;
13
+ name: string;
14
+ params: string[];
15
+ body: AST.Expr;
16
+ closure: Env;
17
+ }
18
+ declare class Env {
19
+ parent?: Env | undefined;
20
+ private vars;
21
+ private _depth;
22
+ constructor(parent?: Env | undefined);
23
+ get(name: string): Value;
24
+ getEntry(name: string): {
25
+ value: Value;
26
+ mutable: boolean;
27
+ } | undefined;
28
+ set(name: string, value: Value, mutable?: boolean): void;
29
+ assign(name: string, value: Value): void;
30
+ has(name: string): boolean;
31
+ }
32
+ declare function toStr(v: Value): string;
33
+ export declare function createEnv(): Env;
34
+ export declare function runStmt(stmt: AST.Stmt, env: Env): Value;
35
+ export declare function runExpr(expr: AST.Expr, env: Env): Value;
36
+ export type UseHandler = (stmt: AST.UseStmt, env: Env) => void;
37
+ export declare function interpret(program: AST.Program, onUse?: UseHandler): void;
38
+ export declare function interpretWithEnv(program: AST.Program, env: Env, onUse?: UseHandler): Value;
39
+ export { Env, Value, toStr };