Skip to content
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"ts-node/register"
],
"fullTrace": true,
"timeout": 987654321,
"timeout": 2000,
"watchExtensions": [
"ts"
]
Expand Down
27 changes: 27 additions & 0 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,33 @@ describe('Program', () => {
]);
});

it('supports using vars defined in nested if statements', () => {
//call a function that doesn't exist
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
sub Main()
if true
name = "bob"
end if
print name
end sub
`);

program.validate();
expectZeroDiagnostics(program);
});

it('supports using `m` vars in parameter default values', () => {
//call a function that doesn't exist
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
sub findNode(nodeId as string, parentNode = m.top as object)
return parentNode.findNode(nodeId)
end sub
`);

program.validate();
expectZeroDiagnostics(program);
});

it('detects methods from another file in a subdirectory', () => {
program.setFile('source/main.brs', `
sub Main()
Expand Down
5 changes: 5 additions & 0 deletions src/bscPlugin/validation/BrsFileValidator.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { interpolatedRange } from '../../astUtils/creators';
import { isBody, isClassStatement, isCommentStatement, isConstStatement, isDottedGetExpression, isEnumStatement, isForEachStatement, isForStatement, isFunctionStatement, isImportStatement, isInterfaceStatement, isLibraryStatement, isLiteralExpression, isNamespacedVariableNameExpression, isNamespaceStatement, isUnaryExpression, isWhileStatement } from '../../astUtils/reflection';
import { createVisitor, WalkMode } from '../../astUtils/visitors';
import { DiagnosticMessages } from '../../DiagnosticMessages';
Expand All @@ -8,6 +9,7 @@ import type { AstNode, Expression } from '../../parser/AstNode';
import type { LiteralExpression } from '../../parser/Expression';
import { ParseMode } from '../../parser/Parser';
import type { ContinueStatement, EnumMemberStatement, EnumStatement, ForEachStatement, ForStatement, ImportStatement, LibraryStatement, NamespaceStatement, WhileStatement } from '../../parser/Statement';
import { SymbolTable } from '../../SymbolTable';
import { DynamicType } from '../../types/DynamicType';
import util from '../../util';

Expand Down Expand Up @@ -95,6 +97,9 @@ export class BrsFileValidator {
},
FunctionParameterExpression: (node) => {
node.getSymbolTable()?.addSymbol(node.name.text, node.name.range, node.type);
//define a symbolTable for each FunctionParameterExpression that contains `m`. TODO, add previous parameter names to this list
node.symbolTable = new SymbolTable(node.getSymbolTable());
node.symbolTable.addSymbol('m', interpolatedRange, DynamicType.instance);
},
ForEachStatement: (node) => {
//register the for loop variable
Expand Down
6 changes: 6 additions & 0 deletions src/parser/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { DynamicType } from '../types/DynamicType';
import type { BscType } from '../types/BscType';
import { FunctionType } from '../types/FunctionType';
import { Expression } from './AstNode';
import { SymbolTable } from '../SymbolTable';

export type ExpressionVisitor = (expression: Expression, parent: Expression) => void;

Expand Down Expand Up @@ -127,6 +128,11 @@ export class FunctionExpression extends Expression implements TypedefProvider {
} else {
this.returnType = DynamicType.instance;
}

//if there's a body, and it doesn't have a SymbolTable, assign one
if (this.body && !this.body.symbolTable) {
this.body.symbolTable = new SymbolTable();
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/parser/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import { createVisitor, WalkMode } from '../astUtils/visitors';
import { createStringLiteral, createToken } from '../astUtils/creators';
import { Cache } from '../Cache';
import type { Expression, Statement } from './AstNode';
import { SymbolTable } from '../SymbolTable';

export class Parser {
/**
Expand Down Expand Up @@ -903,6 +904,8 @@ export class Parser {
try {
//support ending the function with `end sub` OR `end function`
func.body = this.block();
//attach a new SymbolTable for this function body
func.body.symbolTable = new SymbolTable();
} finally {
this.currentFunctionExpression = previousFunctionExpression;
}
Expand Down
2 changes: 0 additions & 2 deletions src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ export class Block extends Statement {

public readonly range: Range;

public symbolTable = new SymbolTable();

transpile(state: BrsTranspileState) {
state.blockDepth++;
let results = [] as TranspileResult;
Expand Down