diff --git a/.changeset/array-scope-fix.md b/.changeset/array-scope-fix.md deleted file mode 100644 index a10f8cd..0000000 --- a/.changeset/array-scope-fix.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'pascal-js-compiler': patch ---- - -Fix silent codegen corruption when two arrays in different scopes share a name. Array -low-bounds were tracked in a single flat map keyed only by name, so a local `array[1..n]` -inside a subprogram overwrote the low-bound of a same-named outer array, making the outer -array's 1-based index offset wrong (writes/reads landed outside the allocated array). Array -scope is now snapshotted and restored around each subprogram body, so a homonym array in one -scope no longer changes the meaning of the same identifier in a sibling or outer scope. diff --git a/.changeset/ast-driven-formatter.md b/.changeset/ast-driven-formatter.md deleted file mode 100644 index 4fc2ce0..0000000 --- a/.changeset/ast-driven-formatter.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'pascal-code-formatter': minor ---- - -Add `formatPascalSource(code, options?)`: an AST-driven formatter that parses the -source and pretty-prints the parser's AST into clean, consistently indented Pascal -text (a string). Because structure comes from the AST rather than string-matching the -token stream, classification is exact and parentheses are precedence-aware (`a + b * c`, -not `(a + (b * c))`). Verified to round-trip (output re-parses), be idempotent, and -preserve semantics (the formatted source compiles to identical JS) across the golden -fixtures. Also exports `AstFormatter` and the `AstFormatOptions` type. - -The existing token-stream `formatPascalCode` is unchanged. This adds a dependency on -`pascal-parser`. diff --git a/.changeset/builtin-position-check.md b/.changeset/builtin-position-check.md deleted file mode 100644 index 3de8846..0000000 --- a/.changeset/builtin-position-check.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'pascal-js-compiler': patch ---- - -Reject builtins used in the wrong position with a `CompileError` instead of emitting a -call to a nonexistent JS function. A value-returning builtin used as a statement -(`abs(x);`) and a statement-only builtin used in an expression (`x := writeln(1)`) used to -compile to `abs(x);` / `writeln(1)`, which throw `ReferenceError` at runtime. They now fail -at compile time, consistent with how the compiler already rejects `var` parameters and -wrong arity. A user subprogram sharing a builtin's name still shadows it in either position. diff --git a/.changeset/compile-error-type.md b/.changeset/compile-error-type.md deleted file mode 100644 index c4fde07..0000000 --- a/.changeset/compile-error-type.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'pascal-js-compiler': minor ---- - -Export a typed `CompileError`. Unsupported-Pascal errors — `var` (by-reference) -parameters, bitwise `and`/`or`/`not` over integers, and wrong-arity builtin calls — -now throw `CompileError` instead of a bare `Error`, so a consumer can `catch` and tell -"this program uses an unsupported feature" apart from an internal compiler bug (which -stays a plain `Error`). Mirrors `ParseError` in `pascal-parser`. diff --git a/.changeset/declaration-discriminated-union.md b/.changeset/declaration-discriminated-union.md deleted file mode 100644 index 75f7533..0000000 --- a/.changeset/declaration-discriminated-union.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'pascal-parser': minor ---- - -`Declaration` is now a discriminated union (`VariableDeclaration | FunctionDeclaration -| ProcedureDeclaration | ConstantDeclaration`) instead of one wide interface where every -field was optional. Each variant is exported and carries exactly the fields it has, so a -`switch (decl.type)` narrows to the concrete node with no cast — matching how `Statement` -and `Expression` already work. Consumers that switch on `decl.type` gain precise field -types; code that read fields like `decl.parameters` off a bare `Declaration` without -narrowing must now narrow first. diff --git a/.changeset/drop-deep-compare-dep.md b/.changeset/drop-deep-compare-dep.md deleted file mode 100644 index 1cfdb84..0000000 --- a/.changeset/drop-deep-compare-dep.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'pascal-code-formatter': patch ---- - -Drop the `objects-deep-compare` dependency and simplify the indentation tracker. The -begin/end/var nesting is now an explicit local marker stack instead of a general-purpose -counterweight structure plus per-token deep-equality — clearer, testable without an -external dependency, and one fewer package to install. Output is unchanged. diff --git a/.changeset/explicit-commonjs-type.md b/.changeset/explicit-commonjs-type.md deleted file mode 100644 index 01e6745..0000000 --- a/.changeset/explicit-commonjs-type.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'pascal-tokenizer': patch -'pascal-parser': patch -'pascal-js-compiler': patch ---- - -Declare `"type": "commonjs"` explicitly in package.json. The packages already ship -CommonJS; stating it removes Node's module-type detection step for consumers (as flagged -by publint) and brings these three in line with `pascal-code-formatter`. diff --git a/.changeset/formatter-spacing-fix.md b/.changeset/formatter-spacing-fix.md deleted file mode 100644 index 4494176..0000000 --- a/.changeset/formatter-spacing-fix.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'pascal-code-formatter': patch ---- - -Fix `formatPascalCode` producing output that its own parser would reject. `needWhiteSpace` -had an ad-hoc allow-list with no rule to separate two adjacent word tokens, so control -keywords glued to their neighbours (`for`+`i`, `to`+`5`, `do`+`writeln`, `then`+the body). -Spacing is now driven by a general rule — a space between any two word-like tokens -(keyword/identifier/number/boolean/string, which also covers the `div`/`mod`/`and`/`or`/`not` -word operators) plus a leading space before control keywords after `)`/`]`. Trailing -whitespace is no longer emitted on a token that ends its line. Added a round-trip test -harness that renders the formatted lines and re-parses them, covering for/while/if-then/case -bodies on the same line as their header. diff --git a/.changeset/parser-statement-locations.md b/.changeset/parser-statement-locations.md deleted file mode 100644 index f33fecb..0000000 --- a/.changeset/parser-statement-locations.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'pascal-parser': minor ---- - -Statement AST nodes now carry their real source location (`location.start` = the -line/column/offset of their first token), stamped in `parseStatement`. Previously -every node location was zeroed. This enables consumers to map a statement back to -its source line — the playground step-debugger being the first such consumer. -Expression and declaration nodes remain zeroed until they too have a position -consumer. diff --git a/.changeset/token-source-positions.md b/.changeset/token-source-positions.md deleted file mode 100644 index e9ae68c..0000000 --- a/.changeset/token-source-positions.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'pascal-tokenizer': minor -'pascal-parser': minor -'pascal-code-formatter': patch ---- - -Track source positions through the toolchain. - -- **pascal-tokenizer**: every emitted token now carries `line` (1-based), `column` - (1-based) and `offset` (0-based) marking where it starts in the source. Positions - are computed with a forward-only cursor, so tokenizing stays O(n). -- **pascal-parser**: `ParseError` now reports where the input went wrong — its - message is suffixed with `at line L, column C` and its `location` points at the - offending token, instead of a bare, position-less message. -- **pascal-code-formatter**: tolerates the new token fields (indentation matching now - compares tokens by structural identity, not deep object equality). diff --git a/packages/code-formatter/CHANGELOG.md b/packages/code-formatter/CHANGELOG.md new file mode 100644 index 0000000..fa1a77e --- /dev/null +++ b/packages/code-formatter/CHANGELOG.md @@ -0,0 +1,49 @@ +# pascal-code-formatter + +## 0.1.0 + +### Minor Changes + +- 00944ab: Add `formatPascalSource(code, options?)`: an AST-driven formatter that parses the + source and pretty-prints the parser's AST into clean, consistently indented Pascal + text (a string). Because structure comes from the AST rather than string-matching the + token stream, classification is exact and parentheses are precedence-aware (`a + b * c`, + not `(a + (b * c))`). Verified to round-trip (output re-parses), be idempotent, and + preserve semantics (the formatted source compiles to identical JS) across the golden + fixtures. Also exports `AstFormatter` and the `AstFormatOptions` type. + + The existing token-stream `formatPascalCode` is unchanged. This adds a dependency on + `pascal-parser`. + +### Patch Changes + +- 3035567: Drop the `objects-deep-compare` dependency and simplify the indentation tracker. The + begin/end/var nesting is now an explicit local marker stack instead of a general-purpose + counterweight structure plus per-token deep-equality — clearer, testable without an + external dependency, and one fewer package to install. Output is unchanged. +- f5e4ec8: Fix `formatPascalCode` producing output that its own parser would reject. `needWhiteSpace` + had an ad-hoc allow-list with no rule to separate two adjacent word tokens, so control + keywords glued to their neighbours (`for`+`i`, `to`+`5`, `do`+`writeln`, `then`+the body). + Spacing is now driven by a general rule — a space between any two word-like tokens + (keyword/identifier/number/boolean/string, which also covers the `div`/`mod`/`and`/`or`/`not` + word operators) plus a leading space before control keywords after `)`/`]`. Trailing + whitespace is no longer emitted on a token that ends its line. Added a round-trip test + harness that renders the formatted lines and re-parses them, covering for/while/if-then/case + bodies on the same line as their header. +- 1965329: Track source positions through the toolchain. + + - **pascal-tokenizer**: every emitted token now carries `line` (1-based), `column` + (1-based) and `offset` (0-based) marking where it starts in the source. Positions + are computed with a forward-only cursor, so tokenizing stays O(n). + - **pascal-parser**: `ParseError` now reports where the input went wrong — its + message is suffixed with `at line L, column C` and its `location` points at the + offending token, instead of a bare, position-less message. + - **pascal-code-formatter**: tolerates the new token fields (indentation matching now + compares tokens by structural identity, not deep object equality). + +- Updated dependencies [14fe8d3] +- Updated dependencies [a3f86d6] +- Updated dependencies [d8861ac] +- Updated dependencies [1965329] + - pascal-parser@0.3.0 + - pascal-tokenizer@0.1.0 diff --git a/packages/code-formatter/package.json b/packages/code-formatter/package.json index 953dbb0..c9ef039 100644 --- a/packages/code-formatter/package.json +++ b/packages/code-formatter/package.json @@ -1,6 +1,6 @@ { "name": "pascal-code-formatter", - "version": "0.0.4", + "version": "0.1.0", "description": "A Pascal code formatter written in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -46,8 +46,8 @@ }, "dependencies": { "counterweight-stack": "0.0.1", - "pascal-parser": "^0.2.1", - "pascal-tokenizer": "^0.0.3" + "pascal-parser": "^0.3.0", + "pascal-tokenizer": "^0.1.0" }, "directories": { "doc": "docs", diff --git a/packages/compiler/CHANGELOG.md b/packages/compiler/CHANGELOG.md index 3bc799d..32ecf38 100644 --- a/packages/compiler/CHANGELOG.md +++ b/packages/compiler/CHANGELOG.md @@ -1,5 +1,38 @@ # pascal-js-compiler +## 0.4.0 + +### Minor Changes + +- c043a37: Export a typed `CompileError`. Unsupported-Pascal errors — `var` (by-reference) + parameters, bitwise `and`/`or`/`not` over integers, and wrong-arity builtin calls — + now throw `CompileError` instead of a bare `Error`, so a consumer can `catch` and tell + "this program uses an unsupported feature" apart from an internal compiler bug (which + stays a plain `Error`). Mirrors `ParseError` in `pascal-parser`. + +### Patch Changes + +- 9020b19: Fix silent codegen corruption when two arrays in different scopes share a name. Array + low-bounds were tracked in a single flat map keyed only by name, so a local `array[1..n]` + inside a subprogram overwrote the low-bound of a same-named outer array, making the outer + array's 1-based index offset wrong (writes/reads landed outside the allocated array). Array + scope is now snapshotted and restored around each subprogram body, so a homonym array in one + scope no longer changes the meaning of the same identifier in a sibling or outer scope. +- 7855f89: Reject builtins used in the wrong position with a `CompileError` instead of emitting a + call to a nonexistent JS function. A value-returning builtin used as a statement + (`abs(x);`) and a statement-only builtin used in an expression (`x := writeln(1)`) used to + compile to `abs(x);` / `writeln(1)`, which throw `ReferenceError` at runtime. They now fail + at compile time, consistent with how the compiler already rejects `var` parameters and + wrong arity. A user subprogram sharing a builtin's name still shadows it in either position. +- a3f86d6: Declare `"type": "commonjs"` explicitly in package.json. The packages already ship + CommonJS; stating it removes Node's module-type detection step for consumers (as flagged + by publint) and brings these three in line with `pascal-code-formatter`. +- Updated dependencies [14fe8d3] +- Updated dependencies [a3f86d6] +- Updated dependencies [d8861ac] +- Updated dependencies [1965329] + - pascal-parser@0.3.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/compiler/package.json b/packages/compiler/package.json index c196e33..f043352 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,6 +1,6 @@ { "name": "pascal-js-compiler", - "version": "0.3.0", + "version": "0.4.0", "description": "Compiles Pascal source code to JavaScript from the pascal-toolchain parser AST.", "type": "commonjs", "main": "dist/index.js", @@ -42,7 +42,7 @@ "author": "Damian Sire", "license": "MIT", "dependencies": { - "pascal-parser": "^0.2.0" + "pascal-parser": "^0.3.0" }, "devDependencies": { "typescript": "^5.6.3" diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index 4d8ac77..b7dab76 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/CHANGELOG.md @@ -1,5 +1,42 @@ # pascal-parser +## 0.3.0 + +### Minor Changes + +- 14fe8d3: `Declaration` is now a discriminated union (`VariableDeclaration | FunctionDeclaration +| ProcedureDeclaration | ConstantDeclaration`) instead of one wide interface where every + field was optional. Each variant is exported and carries exactly the fields it has, so a + `switch (decl.type)` narrows to the concrete node with no cast — matching how `Statement` + and `Expression` already work. Consumers that switch on `decl.type` gain precise field + types; code that read fields like `decl.parameters` off a bare `Declaration` without + narrowing must now narrow first. +- d8861ac: Statement AST nodes now carry their real source location (`location.start` = the + line/column/offset of their first token), stamped in `parseStatement`. Previously + every node location was zeroed. This enables consumers to map a statement back to + its source line — the playground step-debugger being the first such consumer. + Expression and declaration nodes remain zeroed until they too have a position + consumer. +- 1965329: Track source positions through the toolchain. + + - **pascal-tokenizer**: every emitted token now carries `line` (1-based), `column` + (1-based) and `offset` (0-based) marking where it starts in the source. Positions + are computed with a forward-only cursor, so tokenizing stays O(n). + - **pascal-parser**: `ParseError` now reports where the input went wrong — its + message is suffixed with `at line L, column C` and its `location` points at the + offending token, instead of a bare, position-less message. + - **pascal-code-formatter**: tolerates the new token fields (indentation matching now + compares tokens by structural identity, not deep object equality). + +### Patch Changes + +- a3f86d6: Declare `"type": "commonjs"` explicitly in package.json. The packages already ship + CommonJS; stating it removes Node's module-type detection step for consumers (as flagged + by publint) and brings these three in line with `pascal-code-formatter`. +- Updated dependencies [a3f86d6] +- Updated dependencies [1965329] + - pascal-tokenizer@0.1.0 + ## 0.2.1 ### Patch Changes diff --git a/packages/parser/package.json b/packages/parser/package.json index a54924f..23b3fa7 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "pascal-parser", - "version": "0.2.1", + "version": "0.3.0", "description": "A Pascal language parser library", "type": "commonjs", "main": "dist/index.js", @@ -58,6 +58,6 @@ "typescript": "^5.3.3" }, "dependencies": { - "pascal-tokenizer": "^0.0.3" + "pascal-tokenizer": "^0.1.0" } } diff --git a/packages/tokenizer/CHANGELOG.md b/packages/tokenizer/CHANGELOG.md new file mode 100644 index 0000000..b1bb632 --- /dev/null +++ b/packages/tokenizer/CHANGELOG.md @@ -0,0 +1,22 @@ +# pascal-tokenizer + +## 0.1.0 + +### Minor Changes + +- 1965329: Track source positions through the toolchain. + + - **pascal-tokenizer**: every emitted token now carries `line` (1-based), `column` + (1-based) and `offset` (0-based) marking where it starts in the source. Positions + are computed with a forward-only cursor, so tokenizing stays O(n). + - **pascal-parser**: `ParseError` now reports where the input went wrong — its + message is suffixed with `at line L, column C` and its `location` points at the + offending token, instead of a bare, position-less message. + - **pascal-code-formatter**: tolerates the new token fields (indentation matching now + compares tokens by structural identity, not deep object equality). + +### Patch Changes + +- a3f86d6: Declare `"type": "commonjs"` explicitly in package.json. The packages already ship + CommonJS; stating it removes Node's module-type detection step for consumers (as flagged + by publint) and brings these three in line with `pascal-code-formatter`. diff --git a/packages/tokenizer/package.json b/packages/tokenizer/package.json index da996e4..2bef4aa 100644 --- a/packages/tokenizer/package.json +++ b/packages/tokenizer/package.json @@ -1,6 +1,6 @@ { "name": "pascal-tokenizer", - "version": "0.0.3", + "version": "0.1.0", "description": "A tokenizer for Pascal programming language", "type": "commonjs", "main": "dist/index.js",