vba-runner 0.1.1-alpha.2 → 0.1.1-alpha.4
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/bin/vba-analyzer.cjs +32 -4
- package/dist/bin/vba-formatter.cjs +12 -1
- package/dist/bin/vba-parse-check.cjs +34 -4
- package/dist/bin/vba-run.cjs +114 -11
- package/dist/bin/vba-runner.cjs +120 -13
- package/dist/lib.cjs +103 -11
- package/package.json +1 -1
|
@@ -2521,7 +2521,7 @@ var Parser = class _Parser {
|
|
|
2521
2521
|
parseEventDeclaration(scope) {
|
|
2522
2522
|
this.advance();
|
|
2523
2523
|
const idToken = this.advance();
|
|
2524
|
-
if (!this.isIdentifier(idToken)
|
|
2524
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'Event' at line ${idToken.line}`);
|
|
2525
2525
|
const name = { type: "Identifier", name: idToken.value };
|
|
2526
2526
|
const parameters = [];
|
|
2527
2527
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2539,7 +2539,7 @@ var Parser = class _Parser {
|
|
|
2539
2539
|
parseRaiseEventStatement() {
|
|
2540
2540
|
this.advance();
|
|
2541
2541
|
const idToken = this.advance();
|
|
2542
|
-
if (!this.isIdentifier(idToken)
|
|
2542
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'RaiseEvent' at line ${idToken.line}`);
|
|
2543
2543
|
const eventName = { type: "Identifier", name: idToken.value };
|
|
2544
2544
|
const args = [];
|
|
2545
2545
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2864,13 +2864,39 @@ function evaluateCCExpr(expr, resolve) {
|
|
|
2864
2864
|
}
|
|
2865
2865
|
return parseOr();
|
|
2866
2866
|
}
|
|
2867
|
+
function stripVBAFileHeader(source) {
|
|
2868
|
+
const lines = source.split("\n");
|
|
2869
|
+
if (!lines[0]?.trimEnd().toUpperCase().startsWith("VERSION")) return source;
|
|
2870
|
+
const result = [...lines];
|
|
2871
|
+
let i = 0;
|
|
2872
|
+
result[i] = "";
|
|
2873
|
+
i++;
|
|
2874
|
+
while (i < result.length) {
|
|
2875
|
+
const trimmed = result[i].trimEnd().toUpperCase();
|
|
2876
|
+
result[i] = "";
|
|
2877
|
+
i++;
|
|
2878
|
+
if (trimmed === "END") break;
|
|
2879
|
+
}
|
|
2880
|
+
return result.join("\n");
|
|
2881
|
+
}
|
|
2867
2882
|
|
|
2868
2883
|
// ../../test-libs/vba-analyzer.ts
|
|
2869
2884
|
var fs = __toESM(require("fs"), 1);
|
|
2870
2885
|
var path = __toESM(require("path"), 1);
|
|
2871
2886
|
|
|
2872
2887
|
// ../../test-libs/version.ts
|
|
2873
|
-
var
|
|
2888
|
+
var import_fs = require("fs");
|
|
2889
|
+
var import_path = require("path");
|
|
2890
|
+
function readVersion() {
|
|
2891
|
+
for (const rel of ["../build/runner/package.json", "../../package.json"]) {
|
|
2892
|
+
try {
|
|
2893
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(__dirname, rel), "utf8")).version;
|
|
2894
|
+
} catch {
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
return "unknown";
|
|
2898
|
+
}
|
|
2899
|
+
var VERSION = readVersion();
|
|
2874
2900
|
|
|
2875
2901
|
// ../../test-libs/vba-analyzer.ts
|
|
2876
2902
|
function isStatementArray(v) {
|
|
@@ -4379,7 +4405,9 @@ function analyzeGotoInProc(proc) {
|
|
|
4379
4405
|
};
|
|
4380
4406
|
}
|
|
4381
4407
|
function analyzeFile(filePath) {
|
|
4382
|
-
const
|
|
4408
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
4409
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
4410
|
+
const src = stripVBAFileHeader(raw);
|
|
4383
4411
|
const lines = src.split("\n");
|
|
4384
4412
|
const warnings = [];
|
|
4385
4413
|
let ast;
|
|
@@ -943,7 +943,18 @@ function applyEdits(source, edits) {
|
|
|
943
943
|
}
|
|
944
944
|
|
|
945
945
|
// ../../test-libs/version.ts
|
|
946
|
-
var
|
|
946
|
+
var import_fs = require("fs");
|
|
947
|
+
var import_path = require("path");
|
|
948
|
+
function readVersion() {
|
|
949
|
+
for (const rel of ["../build/runner/package.json", "../../package.json"]) {
|
|
950
|
+
try {
|
|
951
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(__dirname, rel), "utf8")).version;
|
|
952
|
+
} catch {
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return "unknown";
|
|
956
|
+
}
|
|
957
|
+
var VERSION = readVersion();
|
|
947
958
|
|
|
948
959
|
// ../../test-libs/vba-formatter.ts
|
|
949
960
|
var VBA_EXTENSIONS = /\.(bas|cls|frm)$/i;
|
|
@@ -2508,7 +2508,7 @@ var Parser = class _Parser {
|
|
|
2508
2508
|
parseEventDeclaration(scope) {
|
|
2509
2509
|
this.advance();
|
|
2510
2510
|
const idToken = this.advance();
|
|
2511
|
-
if (!this.isIdentifier(idToken)
|
|
2511
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'Event' at line ${idToken.line}`);
|
|
2512
2512
|
const name = { type: "Identifier", name: idToken.value };
|
|
2513
2513
|
const parameters = [];
|
|
2514
2514
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2526,7 +2526,7 @@ var Parser = class _Parser {
|
|
|
2526
2526
|
parseRaiseEventStatement() {
|
|
2527
2527
|
this.advance();
|
|
2528
2528
|
const idToken = this.advance();
|
|
2529
|
-
if (!this.isIdentifier(idToken)
|
|
2529
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'RaiseEvent' at line ${idToken.line}`);
|
|
2530
2530
|
const eventName = { type: "Identifier", name: idToken.value };
|
|
2531
2531
|
const args = [];
|
|
2532
2532
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2604,16 +2604,46 @@ var Parser = class _Parser {
|
|
|
2604
2604
|
}
|
|
2605
2605
|
};
|
|
2606
2606
|
|
|
2607
|
+
// ../../src/engine/preprocessor.ts
|
|
2608
|
+
function stripVBAFileHeader(source) {
|
|
2609
|
+
const lines = source.split("\n");
|
|
2610
|
+
if (!lines[0]?.trimEnd().toUpperCase().startsWith("VERSION")) return source;
|
|
2611
|
+
const result = [...lines];
|
|
2612
|
+
let i = 0;
|
|
2613
|
+
result[i] = "";
|
|
2614
|
+
i++;
|
|
2615
|
+
while (i < result.length) {
|
|
2616
|
+
const trimmed = result[i].trimEnd().toUpperCase();
|
|
2617
|
+
result[i] = "";
|
|
2618
|
+
i++;
|
|
2619
|
+
if (trimmed === "END") break;
|
|
2620
|
+
}
|
|
2621
|
+
return result.join("\n");
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2607
2624
|
// ../../test-libs/vba-parse-check.ts
|
|
2608
2625
|
var fs = __toESM(require("fs"), 1);
|
|
2609
2626
|
var path = __toESM(require("path"), 1);
|
|
2610
2627
|
|
|
2611
2628
|
// ../../test-libs/version.ts
|
|
2612
|
-
var
|
|
2629
|
+
var import_fs = require("fs");
|
|
2630
|
+
var import_path = require("path");
|
|
2631
|
+
function readVersion() {
|
|
2632
|
+
for (const rel of ["../build/runner/package.json", "../../package.json"]) {
|
|
2633
|
+
try {
|
|
2634
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(__dirname, rel), "utf8")).version;
|
|
2635
|
+
} catch {
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
return "unknown";
|
|
2639
|
+
}
|
|
2640
|
+
var VERSION = readVersion();
|
|
2613
2641
|
|
|
2614
2642
|
// ../../test-libs/vba-parse-check.ts
|
|
2615
2643
|
function checkFile(filePath) {
|
|
2616
|
-
const
|
|
2644
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
2645
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
2646
|
+
const src = stripVBAFileHeader(raw);
|
|
2617
2647
|
const diags = [];
|
|
2618
2648
|
const lexer = new Lexer(src);
|
|
2619
2649
|
let tokens;
|
package/dist/bin/vba-run.cjs
CHANGED
|
@@ -2510,7 +2510,7 @@ var Parser = class _Parser {
|
|
|
2510
2510
|
parseEventDeclaration(scope) {
|
|
2511
2511
|
this.advance();
|
|
2512
2512
|
const idToken = this.advance();
|
|
2513
|
-
if (!this.isIdentifier(idToken)
|
|
2513
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'Event' at line ${idToken.line}`);
|
|
2514
2514
|
const name = { type: "Identifier", name: idToken.value };
|
|
2515
2515
|
const parameters = [];
|
|
2516
2516
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2528,7 +2528,7 @@ var Parser = class _Parser {
|
|
|
2528
2528
|
parseRaiseEventStatement() {
|
|
2529
2529
|
this.advance();
|
|
2530
2530
|
const idToken = this.advance();
|
|
2531
|
-
if (!this.isIdentifier(idToken)
|
|
2531
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'RaiseEvent' at line ${idToken.line}`);
|
|
2532
2532
|
const eventName = { type: "Identifier", name: idToken.value };
|
|
2533
2533
|
const args = [];
|
|
2534
2534
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -4294,6 +4294,16 @@ var Evaluator = class _Evaluator {
|
|
|
4294
4294
|
inConstEval = false;
|
|
4295
4295
|
vbaCallStack = [];
|
|
4296
4296
|
debugHook = null;
|
|
4297
|
+
/**
|
|
4298
|
+
* resolveIdentifiers 完了後に true になる。
|
|
4299
|
+
* evaluateModule はこのフラグを見て、バッチロード中(false)はモジュールレベル
|
|
4300
|
+
* 実行文を pendingTopLevel に退避し、インタラクティブ呼び出し(true)では即時実行する。
|
|
4301
|
+
*/
|
|
4302
|
+
resolveIdentifiersDone = false;
|
|
4303
|
+
/** Pass 1 で配列境界を評価できなかった VariableDeclaration。Pass 2 で再評価。 */
|
|
4304
|
+
pendingArrayDecls = [];
|
|
4305
|
+
/** Pass 1 でシンボルテーブルに退避したモジュールレベル実行文。Pass 2 後に実行。 */
|
|
4306
|
+
pendingTopLevel = [];
|
|
4297
4307
|
constructor(onPrint, config = {}) {
|
|
4298
4308
|
this.builtinEnv = new Environment();
|
|
4299
4309
|
this.env = this.builtinEnv;
|
|
@@ -5715,22 +5725,70 @@ var Evaluator = class _Evaluator {
|
|
|
5715
5725
|
}
|
|
5716
5726
|
}
|
|
5717
5727
|
/**
|
|
5718
|
-
*
|
|
5719
|
-
*
|
|
5720
|
-
|
|
5728
|
+
* モジュールレベルでシンボルテーブルに登録すべき宣言文かどうかを返す。
|
|
5729
|
+
* false の場合はモジュールレベル実行文として pendingTopLevel に退避する。
|
|
5730
|
+
*/
|
|
5731
|
+
isModuleLevelDeclaration(stmt) {
|
|
5732
|
+
switch (stmt.type) {
|
|
5733
|
+
case "ProcedureDeclaration":
|
|
5734
|
+
case "VariableDeclaration":
|
|
5735
|
+
case "ConstDeclaration":
|
|
5736
|
+
case "TypeDeclaration":
|
|
5737
|
+
case "ClassDeclaration":
|
|
5738
|
+
case "EnumDeclaration":
|
|
5739
|
+
case "OptionExplicitStatement":
|
|
5740
|
+
case "OptionBaseStatement":
|
|
5741
|
+
case "OptionCompareStatement":
|
|
5742
|
+
case "OptionPrivateModuleStatement":
|
|
5743
|
+
case "DefDirective":
|
|
5744
|
+
case "AttributeStatement":
|
|
5745
|
+
case "DeclareStatement":
|
|
5746
|
+
case "EventDeclaration":
|
|
5747
|
+
case "ImplementsDirective":
|
|
5748
|
+
case "LabelStatement":
|
|
5749
|
+
return true;
|
|
5750
|
+
default:
|
|
5751
|
+
return false;
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
/**
|
|
5755
|
+
* Pass 1: 1モジュール分の AST を登録する(シンボルテーブル構築)。
|
|
5721
5756
|
*
|
|
5722
|
-
*
|
|
5723
|
-
*
|
|
5724
|
-
*
|
|
5757
|
+
* - ConstDeclaration → スキップ。Pass 2(resolveIdentifiers)で依存順に評価。
|
|
5758
|
+
* - VariableDeclaration → 配列境界なしは即時登録。配列境界ありは pendingArrayDecls
|
|
5759
|
+
* に退避し Pass 2 で Const 解決後に評価。
|
|
5760
|
+
* - モジュールレベル実行文 → resolveIdentifiers 完了前(バッチロード中)は
|
|
5761
|
+
* pendingTopLevel に退避。Pass 2 後に実行。
|
|
5762
|
+
* resolveIdentifiers 完了後(インタラクティブ呼び出し)は
|
|
5763
|
+
* 即時実行(evalExpression や追加モジュールロード等)。
|
|
5725
5764
|
*/
|
|
5726
5765
|
evaluateModule(program) {
|
|
5727
5766
|
if (this.currentSourceModule && !this.env.hasVariable(this.currentSourceModule.toLowerCase())) {
|
|
5728
5767
|
this.env.set(this.currentSourceModule.toLowerCase(), new VbaNamespaceRef(this.currentSourceModule, "module"));
|
|
5729
5768
|
}
|
|
5769
|
+
const batchMode = !this.resolveIdentifiersDone;
|
|
5770
|
+
const topLevelStmts = [];
|
|
5730
5771
|
for (const stmt of program.body) {
|
|
5731
|
-
if (stmt.type === "ConstDeclaration")
|
|
5772
|
+
if (stmt.type === "ConstDeclaration") {
|
|
5773
|
+
if (!batchMode) this.evaluateConstDeclaration(stmt);
|
|
5774
|
+
continue;
|
|
5775
|
+
}
|
|
5776
|
+
if (batchMode && stmt.type === "VariableDeclaration") {
|
|
5777
|
+
const varDecl = stmt;
|
|
5778
|
+
if (varDecl.declarations.some((d) => d.isArray && d.arrayBounds && d.arrayBounds.length > 0)) {
|
|
5779
|
+
this.pendingArrayDecls.push({ stmt: varDecl, moduleName: this.currentSourceModule || "" });
|
|
5780
|
+
continue;
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
if (batchMode && !this.isModuleLevelDeclaration(stmt)) {
|
|
5784
|
+
topLevelStmts.push(stmt);
|
|
5785
|
+
continue;
|
|
5786
|
+
}
|
|
5732
5787
|
this.evaluateStatement(stmt);
|
|
5733
5788
|
}
|
|
5789
|
+
if (batchMode && topLevelStmts.length > 0) {
|
|
5790
|
+
this.pendingTopLevel.push({ moduleName: this.currentSourceModule || "", stmts: topLevelStmts });
|
|
5791
|
+
}
|
|
5734
5792
|
}
|
|
5735
5793
|
/** @deprecated Use {@link evaluateModule} instead. */
|
|
5736
5794
|
evaluate(program) {
|
|
@@ -7001,6 +7059,13 @@ var Evaluator = class _Evaluator {
|
|
|
7001
7059
|
this.evaluateConstDeclaration(stmt);
|
|
7002
7060
|
this.currentSourceModule = prev;
|
|
7003
7061
|
}
|
|
7062
|
+
for (const { stmt, moduleName } of this.pendingArrayDecls) {
|
|
7063
|
+
const prev = this.currentSourceModule;
|
|
7064
|
+
this.currentSourceModule = moduleName;
|
|
7065
|
+
this.evaluateVariableDeclaration(stmt);
|
|
7066
|
+
this.currentSourceModule = prev;
|
|
7067
|
+
}
|
|
7068
|
+
this.pendingArrayDecls = [];
|
|
7004
7069
|
for (const { ast, moduleName } of modules) {
|
|
7005
7070
|
const seen = /* @__PURE__ */ new Set();
|
|
7006
7071
|
for (const stmt of ast.body) {
|
|
@@ -7026,6 +7091,16 @@ var Evaluator = class _Evaluator {
|
|
|
7026
7091
|
}
|
|
7027
7092
|
}
|
|
7028
7093
|
}
|
|
7094
|
+
this.resolveIdentifiersDone = true;
|
|
7095
|
+
for (const { moduleName, stmts } of this.pendingTopLevel) {
|
|
7096
|
+
const prev = this.currentSourceModule;
|
|
7097
|
+
this.currentSourceModule = moduleName;
|
|
7098
|
+
for (const stmt of stmts) {
|
|
7099
|
+
this.evaluateStatement(stmt);
|
|
7100
|
+
}
|
|
7101
|
+
this.currentSourceModule = prev;
|
|
7102
|
+
}
|
|
7103
|
+
this.pendingTopLevel = [];
|
|
7029
7104
|
}
|
|
7030
7105
|
/** @deprecated Use {@link resolveIdentifiers} instead. */
|
|
7031
7106
|
reEvaluateModuleConstsAll(modules) {
|
|
@@ -9707,9 +9782,35 @@ function evaluateCCExpr(expr, resolve2) {
|
|
|
9707
9782
|
}
|
|
9708
9783
|
return parseOr();
|
|
9709
9784
|
}
|
|
9785
|
+
function stripVBAFileHeader(source) {
|
|
9786
|
+
const lines = source.split("\n");
|
|
9787
|
+
if (!lines[0]?.trimEnd().toUpperCase().startsWith("VERSION")) return source;
|
|
9788
|
+
const result = [...lines];
|
|
9789
|
+
let i = 0;
|
|
9790
|
+
result[i] = "";
|
|
9791
|
+
i++;
|
|
9792
|
+
while (i < result.length) {
|
|
9793
|
+
const trimmed = result[i].trimEnd().toUpperCase();
|
|
9794
|
+
result[i] = "";
|
|
9795
|
+
i++;
|
|
9796
|
+
if (trimmed === "END") break;
|
|
9797
|
+
}
|
|
9798
|
+
return result.join("\n");
|
|
9799
|
+
}
|
|
9710
9800
|
|
|
9711
9801
|
// ../../test-libs/version.ts
|
|
9712
|
-
var
|
|
9802
|
+
var import_fs = require("fs");
|
|
9803
|
+
var import_path2 = require("path");
|
|
9804
|
+
function readVersion() {
|
|
9805
|
+
for (const rel of ["../build/runner/package.json", "../../package.json"]) {
|
|
9806
|
+
try {
|
|
9807
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path2.join)(__dirname, rel), "utf8")).version;
|
|
9808
|
+
} catch {
|
|
9809
|
+
}
|
|
9810
|
+
}
|
|
9811
|
+
return "unknown";
|
|
9812
|
+
}
|
|
9813
|
+
var VERSION = readVersion();
|
|
9713
9814
|
|
|
9714
9815
|
// ../../test-libs/vba-run.ts
|
|
9715
9816
|
var VBA_EXTENSIONS = /* @__PURE__ */ new Set([".bas", ".cls", ".frm"]);
|
|
@@ -9754,8 +9855,10 @@ function main(args) {
|
|
|
9754
9855
|
for (const file of files) {
|
|
9755
9856
|
const moduleName = path4.basename(file, path4.extname(file));
|
|
9756
9857
|
ev.setSourceModule(moduleName);
|
|
9757
|
-
const src = preprocess(fs2.readFileSync(file, "utf-8"));
|
|
9758
9858
|
const ext = path4.extname(file).toLowerCase();
|
|
9859
|
+
let src = fs2.readFileSync(file, "utf-8");
|
|
9860
|
+
src = stripVBAFileHeader(src);
|
|
9861
|
+
src = preprocess(src);
|
|
9759
9862
|
const isRawCls = ext === ".cls" && !src.trim().toLowerCase().startsWith("class ") && !src.toLowerCase().includes("end class");
|
|
9760
9863
|
const ast = new Parser(new Lexer(src).tokenize(), isRawCls ? { parseAsClass: moduleName } : {}).parse();
|
|
9761
9864
|
ev.evaluateModule(ast);
|
package/dist/bin/vba-runner.cjs
CHANGED
|
@@ -2500,7 +2500,7 @@ var Parser = class _Parser {
|
|
|
2500
2500
|
parseEventDeclaration(scope) {
|
|
2501
2501
|
this.advance();
|
|
2502
2502
|
const idToken = this.advance();
|
|
2503
|
-
if (!this.isIdentifier(idToken)
|
|
2503
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'Event' at line ${idToken.line}`);
|
|
2504
2504
|
const name = { type: "Identifier", name: idToken.value };
|
|
2505
2505
|
const parameters = [];
|
|
2506
2506
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2518,7 +2518,7 @@ var Parser = class _Parser {
|
|
|
2518
2518
|
parseRaiseEventStatement() {
|
|
2519
2519
|
this.advance();
|
|
2520
2520
|
const idToken = this.advance();
|
|
2521
|
-
if (!this.isIdentifier(idToken)
|
|
2521
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'RaiseEvent' at line ${idToken.line}`);
|
|
2522
2522
|
const eventName = { type: "Identifier", name: idToken.value };
|
|
2523
2523
|
const args = [];
|
|
2524
2524
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -4284,6 +4284,16 @@ var Evaluator = class _Evaluator {
|
|
|
4284
4284
|
inConstEval = false;
|
|
4285
4285
|
vbaCallStack = [];
|
|
4286
4286
|
debugHook = null;
|
|
4287
|
+
/**
|
|
4288
|
+
* resolveIdentifiers 完了後に true になる。
|
|
4289
|
+
* evaluateModule はこのフラグを見て、バッチロード中(false)はモジュールレベル
|
|
4290
|
+
* 実行文を pendingTopLevel に退避し、インタラクティブ呼び出し(true)では即時実行する。
|
|
4291
|
+
*/
|
|
4292
|
+
resolveIdentifiersDone = false;
|
|
4293
|
+
/** Pass 1 で配列境界を評価できなかった VariableDeclaration。Pass 2 で再評価。 */
|
|
4294
|
+
pendingArrayDecls = [];
|
|
4295
|
+
/** Pass 1 でシンボルテーブルに退避したモジュールレベル実行文。Pass 2 後に実行。 */
|
|
4296
|
+
pendingTopLevel = [];
|
|
4287
4297
|
constructor(onPrint, config = {}) {
|
|
4288
4298
|
this.builtinEnv = new Environment();
|
|
4289
4299
|
this.env = this.builtinEnv;
|
|
@@ -5705,22 +5715,70 @@ var Evaluator = class _Evaluator {
|
|
|
5705
5715
|
}
|
|
5706
5716
|
}
|
|
5707
5717
|
/**
|
|
5708
|
-
*
|
|
5709
|
-
*
|
|
5710
|
-
|
|
5718
|
+
* モジュールレベルでシンボルテーブルに登録すべき宣言文かどうかを返す。
|
|
5719
|
+
* false の場合はモジュールレベル実行文として pendingTopLevel に退避する。
|
|
5720
|
+
*/
|
|
5721
|
+
isModuleLevelDeclaration(stmt) {
|
|
5722
|
+
switch (stmt.type) {
|
|
5723
|
+
case "ProcedureDeclaration":
|
|
5724
|
+
case "VariableDeclaration":
|
|
5725
|
+
case "ConstDeclaration":
|
|
5726
|
+
case "TypeDeclaration":
|
|
5727
|
+
case "ClassDeclaration":
|
|
5728
|
+
case "EnumDeclaration":
|
|
5729
|
+
case "OptionExplicitStatement":
|
|
5730
|
+
case "OptionBaseStatement":
|
|
5731
|
+
case "OptionCompareStatement":
|
|
5732
|
+
case "OptionPrivateModuleStatement":
|
|
5733
|
+
case "DefDirective":
|
|
5734
|
+
case "AttributeStatement":
|
|
5735
|
+
case "DeclareStatement":
|
|
5736
|
+
case "EventDeclaration":
|
|
5737
|
+
case "ImplementsDirective":
|
|
5738
|
+
case "LabelStatement":
|
|
5739
|
+
return true;
|
|
5740
|
+
default:
|
|
5741
|
+
return false;
|
|
5742
|
+
}
|
|
5743
|
+
}
|
|
5744
|
+
/**
|
|
5745
|
+
* Pass 1: 1モジュール分の AST を登録する(シンボルテーブル構築)。
|
|
5711
5746
|
*
|
|
5712
|
-
*
|
|
5713
|
-
*
|
|
5714
|
-
*
|
|
5747
|
+
* - ConstDeclaration → スキップ。Pass 2(resolveIdentifiers)で依存順に評価。
|
|
5748
|
+
* - VariableDeclaration → 配列境界なしは即時登録。配列境界ありは pendingArrayDecls
|
|
5749
|
+
* に退避し Pass 2 で Const 解決後に評価。
|
|
5750
|
+
* - モジュールレベル実行文 → resolveIdentifiers 完了前(バッチロード中)は
|
|
5751
|
+
* pendingTopLevel に退避。Pass 2 後に実行。
|
|
5752
|
+
* resolveIdentifiers 完了後(インタラクティブ呼び出し)は
|
|
5753
|
+
* 即時実行(evalExpression や追加モジュールロード等)。
|
|
5715
5754
|
*/
|
|
5716
5755
|
evaluateModule(program) {
|
|
5717
5756
|
if (this.currentSourceModule && !this.env.hasVariable(this.currentSourceModule.toLowerCase())) {
|
|
5718
5757
|
this.env.set(this.currentSourceModule.toLowerCase(), new VbaNamespaceRef(this.currentSourceModule, "module"));
|
|
5719
5758
|
}
|
|
5759
|
+
const batchMode = !this.resolveIdentifiersDone;
|
|
5760
|
+
const topLevelStmts = [];
|
|
5720
5761
|
for (const stmt of program.body) {
|
|
5721
|
-
if (stmt.type === "ConstDeclaration")
|
|
5762
|
+
if (stmt.type === "ConstDeclaration") {
|
|
5763
|
+
if (!batchMode) this.evaluateConstDeclaration(stmt);
|
|
5764
|
+
continue;
|
|
5765
|
+
}
|
|
5766
|
+
if (batchMode && stmt.type === "VariableDeclaration") {
|
|
5767
|
+
const varDecl = stmt;
|
|
5768
|
+
if (varDecl.declarations.some((d) => d.isArray && d.arrayBounds && d.arrayBounds.length > 0)) {
|
|
5769
|
+
this.pendingArrayDecls.push({ stmt: varDecl, moduleName: this.currentSourceModule || "" });
|
|
5770
|
+
continue;
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
if (batchMode && !this.isModuleLevelDeclaration(stmt)) {
|
|
5774
|
+
topLevelStmts.push(stmt);
|
|
5775
|
+
continue;
|
|
5776
|
+
}
|
|
5722
5777
|
this.evaluateStatement(stmt);
|
|
5723
5778
|
}
|
|
5779
|
+
if (batchMode && topLevelStmts.length > 0) {
|
|
5780
|
+
this.pendingTopLevel.push({ moduleName: this.currentSourceModule || "", stmts: topLevelStmts });
|
|
5781
|
+
}
|
|
5724
5782
|
}
|
|
5725
5783
|
/** @deprecated Use {@link evaluateModule} instead. */
|
|
5726
5784
|
evaluate(program) {
|
|
@@ -6991,6 +7049,13 @@ var Evaluator = class _Evaluator {
|
|
|
6991
7049
|
this.evaluateConstDeclaration(stmt);
|
|
6992
7050
|
this.currentSourceModule = prev;
|
|
6993
7051
|
}
|
|
7052
|
+
for (const { stmt, moduleName } of this.pendingArrayDecls) {
|
|
7053
|
+
const prev = this.currentSourceModule;
|
|
7054
|
+
this.currentSourceModule = moduleName;
|
|
7055
|
+
this.evaluateVariableDeclaration(stmt);
|
|
7056
|
+
this.currentSourceModule = prev;
|
|
7057
|
+
}
|
|
7058
|
+
this.pendingArrayDecls = [];
|
|
6994
7059
|
for (const { ast, moduleName } of modules) {
|
|
6995
7060
|
const seen = /* @__PURE__ */ new Set();
|
|
6996
7061
|
for (const stmt of ast.body) {
|
|
@@ -7016,6 +7081,16 @@ var Evaluator = class _Evaluator {
|
|
|
7016
7081
|
}
|
|
7017
7082
|
}
|
|
7018
7083
|
}
|
|
7084
|
+
this.resolveIdentifiersDone = true;
|
|
7085
|
+
for (const { moduleName, stmts } of this.pendingTopLevel) {
|
|
7086
|
+
const prev = this.currentSourceModule;
|
|
7087
|
+
this.currentSourceModule = moduleName;
|
|
7088
|
+
for (const stmt of stmts) {
|
|
7089
|
+
this.evaluateStatement(stmt);
|
|
7090
|
+
}
|
|
7091
|
+
this.currentSourceModule = prev;
|
|
7092
|
+
}
|
|
7093
|
+
this.pendingTopLevel = [];
|
|
7019
7094
|
}
|
|
7020
7095
|
/** @deprecated Use {@link resolveIdentifiers} instead. */
|
|
7021
7096
|
reEvaluateModuleConstsAll(modules) {
|
|
@@ -9697,9 +9772,35 @@ function evaluateCCExpr(expr, resolve2) {
|
|
|
9697
9772
|
}
|
|
9698
9773
|
return parseOr();
|
|
9699
9774
|
}
|
|
9775
|
+
function stripVBAFileHeader(source) {
|
|
9776
|
+
const lines = source.split("\n");
|
|
9777
|
+
if (!lines[0]?.trimEnd().toUpperCase().startsWith("VERSION")) return source;
|
|
9778
|
+
const result = [...lines];
|
|
9779
|
+
let i = 0;
|
|
9780
|
+
result[i] = "";
|
|
9781
|
+
i++;
|
|
9782
|
+
while (i < result.length) {
|
|
9783
|
+
const trimmed = result[i].trimEnd().toUpperCase();
|
|
9784
|
+
result[i] = "";
|
|
9785
|
+
i++;
|
|
9786
|
+
if (trimmed === "END") break;
|
|
9787
|
+
}
|
|
9788
|
+
return result.join("\n");
|
|
9789
|
+
}
|
|
9700
9790
|
|
|
9701
9791
|
// ../../test-libs/version.ts
|
|
9702
|
-
var
|
|
9792
|
+
var import_fs = require("fs");
|
|
9793
|
+
var import_path2 = require("path");
|
|
9794
|
+
function readVersion() {
|
|
9795
|
+
for (const rel of ["../build/runner/package.json", "../../package.json"]) {
|
|
9796
|
+
try {
|
|
9797
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path2.join)(__dirname, rel), "utf8")).version;
|
|
9798
|
+
} catch {
|
|
9799
|
+
}
|
|
9800
|
+
}
|
|
9801
|
+
return "unknown";
|
|
9802
|
+
}
|
|
9803
|
+
var VERSION = readVersion();
|
|
9703
9804
|
|
|
9704
9805
|
// ../../test-libs/vba-run.ts
|
|
9705
9806
|
var VBA_EXTENSIONS = /* @__PURE__ */ new Set([".bas", ".cls", ".frm"]);
|
|
@@ -9744,8 +9845,10 @@ function main(args) {
|
|
|
9744
9845
|
for (const file of files) {
|
|
9745
9846
|
const moduleName = path4.basename(file, path4.extname(file));
|
|
9746
9847
|
ev.setSourceModule(moduleName);
|
|
9747
|
-
const src = preprocess(fs2.readFileSync(file, "utf-8"));
|
|
9748
9848
|
const ext = path4.extname(file).toLowerCase();
|
|
9849
|
+
let src = fs2.readFileSync(file, "utf-8");
|
|
9850
|
+
src = stripVBAFileHeader(src);
|
|
9851
|
+
src = preprocess(src);
|
|
9749
9852
|
const isRawCls = ext === ".cls" && !src.trim().toLowerCase().startsWith("class ") && !src.toLowerCase().includes("end class");
|
|
9750
9853
|
const ast = new Parser(new Lexer(src).tokenize(), isRawCls ? { parseAsClass: moduleName } : {}).parse();
|
|
9751
9854
|
ev.evaluateModule(ast);
|
|
@@ -11271,7 +11374,9 @@ function analyzeGotoInProc(proc) {
|
|
|
11271
11374
|
};
|
|
11272
11375
|
}
|
|
11273
11376
|
function analyzeFile(filePath) {
|
|
11274
|
-
const
|
|
11377
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
11378
|
+
const raw = fs3.readFileSync(filePath, "utf-8");
|
|
11379
|
+
const src = stripVBAFileHeader(raw);
|
|
11275
11380
|
const lines = src.split("\n");
|
|
11276
11381
|
const warnings = [];
|
|
11277
11382
|
let ast;
|
|
@@ -12730,7 +12835,9 @@ if (process.argv[1]?.includes("vba-formatter")) main3(process.argv.slice(2));
|
|
|
12730
12835
|
var fs5 = __toESM(require("fs"), 1);
|
|
12731
12836
|
var path7 = __toESM(require("path"), 1);
|
|
12732
12837
|
function checkFile(filePath) {
|
|
12733
|
-
const
|
|
12838
|
+
const ext = path7.extname(filePath).toLowerCase();
|
|
12839
|
+
const raw = fs5.readFileSync(filePath, "utf8");
|
|
12840
|
+
const src = stripVBAFileHeader(raw);
|
|
12734
12841
|
const diags = [];
|
|
12735
12842
|
const lexer = new Lexer(src);
|
|
12736
12843
|
let tokens;
|
package/dist/lib.cjs
CHANGED
|
@@ -2522,7 +2522,7 @@ var Parser = class _Parser {
|
|
|
2522
2522
|
parseEventDeclaration(scope) {
|
|
2523
2523
|
this.advance();
|
|
2524
2524
|
const idToken = this.advance();
|
|
2525
|
-
if (!this.isIdentifier(idToken)
|
|
2525
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'Event' at line ${idToken.line}`);
|
|
2526
2526
|
const name = { type: "Identifier", name: idToken.value };
|
|
2527
2527
|
const parameters = [];
|
|
2528
2528
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -2540,7 +2540,7 @@ var Parser = class _Parser {
|
|
|
2540
2540
|
parseRaiseEventStatement() {
|
|
2541
2541
|
this.advance();
|
|
2542
2542
|
const idToken = this.advance();
|
|
2543
|
-
if (!this.isIdentifier(idToken)
|
|
2543
|
+
if (!this.isIdentifier(idToken)) this.throwError(`Expected identifier after 'RaiseEvent' at line ${idToken.line}`);
|
|
2544
2544
|
const eventName = { type: "Identifier", name: idToken.value };
|
|
2545
2545
|
const args = [];
|
|
2546
2546
|
if (this.match(128 /* OperatorLParen */)) {
|
|
@@ -4306,6 +4306,16 @@ var Evaluator = class _Evaluator {
|
|
|
4306
4306
|
inConstEval = false;
|
|
4307
4307
|
vbaCallStack = [];
|
|
4308
4308
|
debugHook = null;
|
|
4309
|
+
/**
|
|
4310
|
+
* resolveIdentifiers 完了後に true になる。
|
|
4311
|
+
* evaluateModule はこのフラグを見て、バッチロード中(false)はモジュールレベル
|
|
4312
|
+
* 実行文を pendingTopLevel に退避し、インタラクティブ呼び出し(true)では即時実行する。
|
|
4313
|
+
*/
|
|
4314
|
+
resolveIdentifiersDone = false;
|
|
4315
|
+
/** Pass 1 で配列境界を評価できなかった VariableDeclaration。Pass 2 で再評価。 */
|
|
4316
|
+
pendingArrayDecls = [];
|
|
4317
|
+
/** Pass 1 でシンボルテーブルに退避したモジュールレベル実行文。Pass 2 後に実行。 */
|
|
4318
|
+
pendingTopLevel = [];
|
|
4309
4319
|
constructor(onPrint, config = {}) {
|
|
4310
4320
|
this.builtinEnv = new Environment();
|
|
4311
4321
|
this.env = this.builtinEnv;
|
|
@@ -5727,22 +5737,70 @@ var Evaluator = class _Evaluator {
|
|
|
5727
5737
|
}
|
|
5728
5738
|
}
|
|
5729
5739
|
/**
|
|
5730
|
-
*
|
|
5731
|
-
*
|
|
5732
|
-
|
|
5740
|
+
* モジュールレベルでシンボルテーブルに登録すべき宣言文かどうかを返す。
|
|
5741
|
+
* false の場合はモジュールレベル実行文として pendingTopLevel に退避する。
|
|
5742
|
+
*/
|
|
5743
|
+
isModuleLevelDeclaration(stmt) {
|
|
5744
|
+
switch (stmt.type) {
|
|
5745
|
+
case "ProcedureDeclaration":
|
|
5746
|
+
case "VariableDeclaration":
|
|
5747
|
+
case "ConstDeclaration":
|
|
5748
|
+
case "TypeDeclaration":
|
|
5749
|
+
case "ClassDeclaration":
|
|
5750
|
+
case "EnumDeclaration":
|
|
5751
|
+
case "OptionExplicitStatement":
|
|
5752
|
+
case "OptionBaseStatement":
|
|
5753
|
+
case "OptionCompareStatement":
|
|
5754
|
+
case "OptionPrivateModuleStatement":
|
|
5755
|
+
case "DefDirective":
|
|
5756
|
+
case "AttributeStatement":
|
|
5757
|
+
case "DeclareStatement":
|
|
5758
|
+
case "EventDeclaration":
|
|
5759
|
+
case "ImplementsDirective":
|
|
5760
|
+
case "LabelStatement":
|
|
5761
|
+
return true;
|
|
5762
|
+
default:
|
|
5763
|
+
return false;
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
/**
|
|
5767
|
+
* Pass 1: 1モジュール分の AST を登録する(シンボルテーブル構築)。
|
|
5733
5768
|
*
|
|
5734
|
-
*
|
|
5735
|
-
*
|
|
5736
|
-
*
|
|
5769
|
+
* - ConstDeclaration → スキップ。Pass 2(resolveIdentifiers)で依存順に評価。
|
|
5770
|
+
* - VariableDeclaration → 配列境界なしは即時登録。配列境界ありは pendingArrayDecls
|
|
5771
|
+
* に退避し Pass 2 で Const 解決後に評価。
|
|
5772
|
+
* - モジュールレベル実行文 → resolveIdentifiers 完了前(バッチロード中)は
|
|
5773
|
+
* pendingTopLevel に退避。Pass 2 後に実行。
|
|
5774
|
+
* resolveIdentifiers 完了後(インタラクティブ呼び出し)は
|
|
5775
|
+
* 即時実行(evalExpression や追加モジュールロード等)。
|
|
5737
5776
|
*/
|
|
5738
5777
|
evaluateModule(program) {
|
|
5739
5778
|
if (this.currentSourceModule && !this.env.hasVariable(this.currentSourceModule.toLowerCase())) {
|
|
5740
5779
|
this.env.set(this.currentSourceModule.toLowerCase(), new VbaNamespaceRef(this.currentSourceModule, "module"));
|
|
5741
5780
|
}
|
|
5781
|
+
const batchMode = !this.resolveIdentifiersDone;
|
|
5782
|
+
const topLevelStmts = [];
|
|
5742
5783
|
for (const stmt of program.body) {
|
|
5743
|
-
if (stmt.type === "ConstDeclaration")
|
|
5784
|
+
if (stmt.type === "ConstDeclaration") {
|
|
5785
|
+
if (!batchMode) this.evaluateConstDeclaration(stmt);
|
|
5786
|
+
continue;
|
|
5787
|
+
}
|
|
5788
|
+
if (batchMode && stmt.type === "VariableDeclaration") {
|
|
5789
|
+
const varDecl = stmt;
|
|
5790
|
+
if (varDecl.declarations.some((d) => d.isArray && d.arrayBounds && d.arrayBounds.length > 0)) {
|
|
5791
|
+
this.pendingArrayDecls.push({ stmt: varDecl, moduleName: this.currentSourceModule || "" });
|
|
5792
|
+
continue;
|
|
5793
|
+
}
|
|
5794
|
+
}
|
|
5795
|
+
if (batchMode && !this.isModuleLevelDeclaration(stmt)) {
|
|
5796
|
+
topLevelStmts.push(stmt);
|
|
5797
|
+
continue;
|
|
5798
|
+
}
|
|
5744
5799
|
this.evaluateStatement(stmt);
|
|
5745
5800
|
}
|
|
5801
|
+
if (batchMode && topLevelStmts.length > 0) {
|
|
5802
|
+
this.pendingTopLevel.push({ moduleName: this.currentSourceModule || "", stmts: topLevelStmts });
|
|
5803
|
+
}
|
|
5746
5804
|
}
|
|
5747
5805
|
/** @deprecated Use {@link evaluateModule} instead. */
|
|
5748
5806
|
evaluate(program) {
|
|
@@ -7013,6 +7071,13 @@ var Evaluator = class _Evaluator {
|
|
|
7013
7071
|
this.evaluateConstDeclaration(stmt);
|
|
7014
7072
|
this.currentSourceModule = prev;
|
|
7015
7073
|
}
|
|
7074
|
+
for (const { stmt, moduleName } of this.pendingArrayDecls) {
|
|
7075
|
+
const prev = this.currentSourceModule;
|
|
7076
|
+
this.currentSourceModule = moduleName;
|
|
7077
|
+
this.evaluateVariableDeclaration(stmt);
|
|
7078
|
+
this.currentSourceModule = prev;
|
|
7079
|
+
}
|
|
7080
|
+
this.pendingArrayDecls = [];
|
|
7016
7081
|
for (const { ast, moduleName } of modules) {
|
|
7017
7082
|
const seen = /* @__PURE__ */ new Set();
|
|
7018
7083
|
for (const stmt of ast.body) {
|
|
@@ -7038,6 +7103,16 @@ var Evaluator = class _Evaluator {
|
|
|
7038
7103
|
}
|
|
7039
7104
|
}
|
|
7040
7105
|
}
|
|
7106
|
+
this.resolveIdentifiersDone = true;
|
|
7107
|
+
for (const { moduleName, stmts } of this.pendingTopLevel) {
|
|
7108
|
+
const prev = this.currentSourceModule;
|
|
7109
|
+
this.currentSourceModule = moduleName;
|
|
7110
|
+
for (const stmt of stmts) {
|
|
7111
|
+
this.evaluateStatement(stmt);
|
|
7112
|
+
}
|
|
7113
|
+
this.currentSourceModule = prev;
|
|
7114
|
+
}
|
|
7115
|
+
this.pendingTopLevel = [];
|
|
7041
7116
|
}
|
|
7042
7117
|
/** @deprecated Use {@link resolveIdentifiers} instead. */
|
|
7043
7118
|
reEvaluateModuleConstsAll(modules) {
|
|
@@ -9666,6 +9741,21 @@ function evaluateCCExpr(expr, resolve2) {
|
|
|
9666
9741
|
}
|
|
9667
9742
|
return parseOr();
|
|
9668
9743
|
}
|
|
9744
|
+
function stripVBAFileHeader(source) {
|
|
9745
|
+
const lines = source.split("\n");
|
|
9746
|
+
if (!lines[0]?.trimEnd().toUpperCase().startsWith("VERSION")) return source;
|
|
9747
|
+
const result = [...lines];
|
|
9748
|
+
let i = 0;
|
|
9749
|
+
result[i] = "";
|
|
9750
|
+
i++;
|
|
9751
|
+
while (i < result.length) {
|
|
9752
|
+
const trimmed = result[i].trimEnd().toUpperCase();
|
|
9753
|
+
result[i] = "";
|
|
9754
|
+
i++;
|
|
9755
|
+
if (trimmed === "END") break;
|
|
9756
|
+
}
|
|
9757
|
+
return result.join("\n");
|
|
9758
|
+
}
|
|
9669
9759
|
|
|
9670
9760
|
// ../../test-libs/mock-loader.ts
|
|
9671
9761
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -9720,7 +9810,8 @@ function loadVbaMock(file, evaluator) {
|
|
|
9720
9810
|
const source = fs.readFileSync(file, "utf-8");
|
|
9721
9811
|
const ext = path4.extname(file).toLowerCase();
|
|
9722
9812
|
const moduleName = path4.basename(file, ext);
|
|
9723
|
-
const
|
|
9813
|
+
const stripped = stripVBAFileHeader(source);
|
|
9814
|
+
const processed = preprocess(stripped);
|
|
9724
9815
|
const isRawCls = ext === ".cls" && !processed.trim().toLowerCase().startsWith("class ") && !processed.toLowerCase().includes("end class");
|
|
9725
9816
|
const parseOpts = isRawCls ? { parseAsClass: moduleName } : {};
|
|
9726
9817
|
const classesBefore = evaluator.getRegisteredClassNames();
|
|
@@ -10577,8 +10668,9 @@ var VBARunner = class {
|
|
|
10577
10668
|
try {
|
|
10578
10669
|
const moduleName = path5.basename(file, path5.extname(file));
|
|
10579
10670
|
this.evaluator.setSourceModule(moduleName);
|
|
10580
|
-
source = preprocess(source, config.compilerConstants);
|
|
10581
10671
|
const ext = path5.extname(file).toLowerCase();
|
|
10672
|
+
source = stripVBAFileHeader(source);
|
|
10673
|
+
source = preprocess(source, config.compilerConstants);
|
|
10582
10674
|
const isRawCls = ext === ".cls" && !source.trim().toLowerCase().startsWith("class ") && !source.toLowerCase().includes("end class");
|
|
10583
10675
|
const parseOpts = isRawCls ? { parseAsClass: moduleName } : {};
|
|
10584
10676
|
const ast = new Parser(new Lexer(source).tokenize(), parseOpts).parse();
|