Debugger step-into, uninitialized-value errors, and misc fixes - #27
Merged
Conversation
Emitters now generate ← instead of ASCII <- for Praxis and CSP, matching the languages' authoritative pseudocode notation (specs already documented this but emitted <-). Parsers still accept <- and ⟵ as input variants; CSP additionally now accepts ⟵, mirroring what Praxis already allowed. Updated demo programs, sample catalog entries, and the CSP CodeMirror grammar (regenerated) to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The CSP grammar (highlighting) and spec already documented != as an accepted ASCII alternate for ≠, but the actual lexer/parser never implemented it — ! wasn't even in the lexer's recognized character set, so it threw "Unexpected character". Wires it up to match the existing docs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Loads examples/demo.* for the currently selected source language via Vite ?raw imports, reusing the same files the round-trip/examples/blocks test suites already read, so the content isn't duplicated anywhere. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Java no longer accepts bare top-level statements as an implicit main(). The
parser now requires public class Main { public static void main(String[] args)
{ ... } }, matching real javac, so code written in Praxly compiles as-is if
copied into another Java toolchain. Also adds real `import` statement parsing
(consumed and discarded), since the emitter already emits imports that the
parser previously only tolerated via silent error recovery.
The CSP emitter gained the same "unwrap Java's Main class" logic the JS/
Python/Praxis emitters already had, since Java source can no longer produce
flat top-level statements for it to iterate directly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…as errors, not defaults A declared-but-unassigned variable or field (Java int x;, Python bare x: int, JS let x;, Praxis bare int x) previously evaluated to a type-appropriate default (0/false/null) instead of erroring, so reading it silently proceeded. It's now a distinct "uninitialized" sentinel: reading, incrementing, or compound-assigning it before a real assignment throws a runtime error, mirroring Java's compile-time definite-assignment check (enforced dynamically here since Praxly has no static analysis pass). Praxis's `/* ... */` placeholder gets the same treatment for consistency: assigning one to a variable leaves it uninitialized (error on later read), and using one directly (e.g. `if (/* cond */)`) is an immediate error, instead of silently defaulting to 0 and letting `if (0)` run without complaint. Translation/emission is unaffected — emitters still lower a placeholder or a bare declaration's synthesized default to the same output text as before; only interpretation of that AST changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Praxis previously accepted `if`/`while`/`do-while`/`repeat-until`/`for` headers without parentheses even though the spec always shows them, silently parsing malformed input like `for i <- 0; i < 5; i <- i + 1`. Missing header parens now throw a PraxisSyntaxError that bypasses the parser's live-typing error recovery, surfacing as a real syntax error on Run — the same way Python's UnsupportedFeatureError and Java's JavaEntryPointError already do. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the existing language-switch confirm dialog so a full editor isn't silently overwritten when loading a demo or example program. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…first statement Program no longer special-cases the file-top comment block; it now travels as the leading statement's leadingComments like any other comment run, so emitters no longer need a separate emitProgram entry point. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rations ClassDeclaration/FunctionDeclaration were already in comments.ts's ATTACHABLE set, but two things silently dropped their comments: parsers never gave these nodes a `loc`, so attachComments had nothing to match them against, and each emitter's visitProgram called visitClassDeclaration/visitFunctionDeclaration directly instead of through visitStatement, which is what actually emits leadingComments/ trailingComment. Fixed both: every parser's top-level dispatch now tags class/function declarations with a loc (Python's nested block-level function declarations too), and every emitter routes top-level classes/ functions through visitStatement. Giving ClassDeclaration/FunctionDeclaration a loc also unlocked a latent bug in insertBlankLines, which had never previously touched top-level blank lines between classes since they lacked loc: the Java emitter counted those newly-inserted BlankLine nodes as "real" main-body content and wrapped an empty synthetic `public class Main` around them. Fixed by ignoring BlankLine nodes in that check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
useCodeDebugger,debugger.ts,VariableFrames)/* ... */placeholders now error on read instead of silently defaulting to0/false/null— a placeholder standing alone as a statement (e.g. a missing loop-body line) is still a no-opMainclass with amainmethod, like standard Java; add main-class unwrappingif/while/forheaders; canonicalize assignment arrow output to←!=as a not-equal operator variantheaderComments, attach file-top comments to the first statement insteadnpm audit fix(adds achromedriver/adm-zipoverride), updated demo programs, docs, and specs to matchTest plan
npx tsc --noEmit— cleannpm run test:run— 552 passed, 4 skippednpm run test-browser(Seleniumcsv/praxly.test.csvregression suite) — 90 passed, 0 failed🤖 Generated with Claude Code