Skip to content

Commit

Permalink
Support #if not
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce committed May 10, 2024
1 parent cc6f762 commit 900277e
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/astUtils/visitors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1257,5 +1257,34 @@ describe('astUtils visitors', () => {
// did walk false block
expect(foundMainFunc).to.be.true;
});

it('will correct walk `not condition` cc blocks', () => {
const { ast } = program.setFile<BrsFile>('source/main.brs', `
#const DEBUG = false
#if not DEBUG
sub notDebug()
end sub
#end if
#if not false
sub notFalse()
end sub
#end if
`);
const bsConsts = new Map<string, boolean>();
let functionsFound = new Set<string>();
const visitor = createVisitor({
FunctionStatement: (func) => {
functionsFound.add(func.getName(ParseMode.BrighterScript));
}
});
ast.walk(visitor, {
walkMode: WalkMode.visitStatements,
bsConsts: bsConsts
});
// did walk 'not' block
expect(functionsFound.has('notDebug')).to.be.true;
expect(functionsFound.has('notFalse')).to.be.true;
});
});
});
31 changes: 31 additions & 0 deletions src/files/BrsFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,23 @@ describe('BrsFile', () => {
`);
});


it('transpiles conditional compilation directives with not', async () => {
await testTranspile(`
sub main()
#const thing = true
#if not thing
print "if"
#elseif not false
print "elseif"
#else
#error crash
print "else"
#endif
end sub
`);
});

it('supports whitespace-separated directives', async () => {
const file = program.setFile<BrsFile>('source/main.bs', `
sub main()
Expand Down Expand Up @@ -721,6 +738,20 @@ describe('BrsFile', () => {
]);
});

it('detects syntax error in #if not', () => {
program.setFile('source/main.brs', `
sub main()
#if not true1
print "true"
#end if
end sub
`);
program.validate();
expectDiagnostics(program, [
DiagnosticMessages.referencedConstDoesNotExist()
]);
});

it('detects syntax error in #const', () => {
program.setFile('source/main.brs', `
sub main()
Expand Down
24 changes: 24 additions & 0 deletions src/parser/Parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,30 @@ describe('parser', () => {
expectZeroDiagnostics(diagnostics);
});

it('allows #if not bs_const', () => {
let { diagnostics } = parse(`
sub foo()
#if not DEBUG
print "not debug"
#end if
end sub
`, ParseMode.BrighterScript, { debug: false });
expectZeroDiagnostics(diagnostics);
});

it('allows #elseif not bs_const', () => {
let { diagnostics } = parse(`
sub foo()
#if DEBUG
print "debug"
#else if not STAGING
print "not debug and not staging"
#end if
end sub
`, ParseMode.BrighterScript, { debug: false, staging: false });
expectZeroDiagnostics(diagnostics);
});

describe('#const', () => {
it('parses #const', () => {
let { diagnostics, ast } = parse(`
Expand Down
7 changes: 7 additions & 0 deletions src/parser/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ export class Parser {
private conditionalCompileStatement(): ConditionalCompileStatement {
const hashIfToken = this.advance();
const startingRange = hashIfToken.range;
let notToken: Token | undefined;

if (this.check(TokenKind.Not)) {
notToken = this.advance();
}

if (!this.checkAny(TokenKind.True, TokenKind.False, TokenKind.Identifier)) {
this.diagnostics.push({
Expand All @@ -1997,6 +2002,7 @@ export class Parser {
});
}


const condition = this.advance();

let thenBranch: Block;
Expand Down Expand Up @@ -2056,6 +2062,7 @@ export class Parser {
hashIf: hashIfToken,
hashElse: hashElseToken,
hashEndIf: hashEndIfToken,
not: notToken,
condition: condition,
thenBranch: thenBranch,
elseBranch: elseBranch
Expand Down
13 changes: 12 additions & 1 deletion src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3581,6 +3581,7 @@ export class AliasStatement extends Statement {
export class ConditionalCompileStatement extends Statement {
constructor(options: {
hashIf?: Token;
not?: Token;
condition: Token;
hashElse?: Token;
hashEndIf?: Token;
Expand All @@ -3593,6 +3594,7 @@ export class ConditionalCompileStatement extends Statement {

this.tokens = {
hashIf: options.hashIf,
not: options.not,
condition: options.condition,
hashElse: options.hashElse,
hashEndIf: options.hashEndIf
Expand All @@ -3607,6 +3609,7 @@ export class ConditionalCompileStatement extends Statement {

readonly tokens: {
readonly hashIf?: Token;
readonly not?: Token;
readonly condition: Token;
readonly hashElse?: Token;
readonly hashEndIf?: Token;
Expand All @@ -3628,6 +3631,10 @@ export class ConditionalCompileStatement extends Statement {

results.push(' ');
//conditions
if (this.tokens.not) {
results.push('not');
results.push(' ');
}
results.push(state.transpileToken(this.tokens.condition));
state.lineage.unshift(this);

Expand Down Expand Up @@ -3687,7 +3694,11 @@ export class ConditionalCompileStatement extends Statement {

walk(visitor: WalkVisitor, options: WalkOptions) {
if (options.walkMode & InternalWalkMode.walkStatements) {
const conditionTrue = options.bsConsts?.get(this.tokens.condition.text.toLowerCase());
let conditionTrue = options.bsConsts?.get(this.tokens.condition.text.toLowerCase());
if (this.tokens.not) {
// flips the boolean value
conditionTrue = !conditionTrue;
}
const walkFalseBlocks = options.walkMode & InternalWalkMode.visitFalseConditionalCompilationBlocks;
if (conditionTrue || walkFalseBlocks) {
walk(this, 'thenBranch', visitor, options);
Expand Down

0 comments on commit 900277e

Please sign in to comment.