Support conditional compilation (#if) inside class bodies#1744
Draft
chrisdp wants to merge 1 commit into
Draft
Conversation
In v0, conditional compilation was handled by a preprocessor that ran
before parsing, so #if blocks worked anywhere - including class bodies.
In v1, #if became a first-class AST statement handled by the parser at
block and file-root level, but class bodies were never taught about it,
producing a cascade of parse errors ("expected-end-keyword", "Unexpected
token '#end if'", etc.) for previously-valid code.
Changes:
- Parser: class bodies now accept #if blocks. Branches are parsed in a
class-member context (methods, fields, annotations, nested #if) and
follow the same token-position contract as regular conditional compile
blocks.
- ClassStatement: methods/fields/memberMap now register members found
inside conditional compile branches, so the type system and tooling
can see them.
- Transpile: methods and builder assignments are emitted wrapped in the
equivalent #if/#else if/#else/#end if directives. Field initializers
injected into the constructor are wrapped in an equivalent conditional
compile statement. Field-only branches don't emit empty directives in
the methods/builder sections.
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.
Problem
In v0, conditional compilation was handled by a preprocessor that ran before parsing, so
#ifblocks worked anywhere — including class bodies. In v1,#ifbecame a first-class AST statement (ConditionalCompileStatement) handled by the parser at block and file-root level, butclassDeclaration()was never taught about it. Code like this (valid in v0, common in test suites and debug tooling) produces a cascade of parse errors in v1 (expected-end-keyword,Unexpected token '#end if',unexpected-statement, etc.):Changes
#ifblocks. The class-member parsing was extracted intoclassMemberDeclaration()and reused by a newclassBodyConditionalCompileBlock(), which parses branch contents in a class-member context (methods, fields, annotations, nested#if). It plugs into the existingconditionalCompileStatement()machinery via an injected branch parser, so#else ifchains,notconditions, false-branch diagnostic suppression, and the token-position contract all behave exactly like function-body#if.methods/fields/memberMapnow register members found inside conditional compile branches, so the type system and tooling can see them (e.g. calling a conditional method viam.from another method validates cleanly).#if/#else if/#else/#end ifdirectives (resolved by the Roku compiler from manifestbs_const, same as function-body#if)ConditionalCompileStatement#if/#end ifshells in the methods/builder sectionsExample transpile output:
Known limitations
sub new()) inside#ifblocks are not supported — builder/class-function generation assumes a single known constructor signature (unchanged from current behavior).getTypedef()does not yet emit conditional members into.d.bstypedefs.Testing
#else ifchains, nesting, empty blocks, annotations on conditional members, class-type membership, unterminated-block diagnostics