Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retain print separators during transpile #373

Merged
merged 3 commits into from
Mar 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/files/BrsFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2149,7 +2149,7 @@ describe('BrsFile', () => {
returnValue = 12 'comment
return returnValue 'comment
end function 'comment
print "a" ; "b" ; 3 'comment
print "a"; "b"; 3 'comment
a(1, 2, 3) 'comment
person.functionCall(1, 2, 3) 'comment
if true then 'comment
Expand Down
19 changes: 11 additions & 8 deletions src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,19 +578,22 @@ export class PrintStatement extends Statement {
' '
];
for (let i = 0; i < this.expressions.length; i++) {
let expression: any = this.expressions[i];
if (expression.transpile) {
//separate print statements with a semi-colon
if (i > 0) {
result.push(' ; ');
}
result.push(...(expression as ExpressionStatement).transpile(state));
const expressionOrSeparator: any = this.expressions[i];
if (expressionOrSeparator.transpile) {
result.push(...(expressionOrSeparator as ExpressionStatement).transpile(state));
} else {
//skip these because I think they are bogus items only added for use in the runtime
result.push(
state.tokenToSourceNode(expressionOrSeparator)
);
}
//if there's an expression after us, add a space
if ((this.expressions[i + 1] as any)?.transpile) {
result.push(' ');
}
}
return result;
}

walk(visitor: WalkVisitor, options: WalkOptions) {
if (options.walkMode & InternalWalkMode.walkExpressions) {
for (let i = 0; i < this.expressions.length; i++) {
Expand Down
105 changes: 104 additions & 1 deletion src/parser/tests/statement/PrintStatement.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { expect } from 'chai';

import { Parser } from '../../Parser';
import { TokenKind } from '../../../lexer';
import { EOF, token } from '../Parser.spec';
import { Range } from 'vscode-languageserver';
import { Program } from '../../../Program';
import { standardizePath as s } from '../../../util';
import { getTestTranspile } from '../../../testHelpers.spec';

const rootDir = s`${process.cwd()}/.tmp/rootDir`;

describe('parser print statements', () => {

let program: Program;
const testTranspile = getTestTranspile(() => [program, rootDir]);

beforeEach(() => {
program = new Program({
rootDir: rootDir
});
});

it('parses singular print statements', () => {
let { statements, diagnostics } = Parser.parse([
token(TokenKind.Print),
Expand Down Expand Up @@ -90,4 +104,93 @@ describe('parser print statements', () => {
expect(statements).to.be.lengthOf(1);
expect(statements[0].range).to.deep.include(Range.create(0, 0, 0, 11));
});

describe('transpile', () => {
it('retains comma separators', () => {
testTranspile(`
a$ = "string"
print a$, a$, a$
`);
});

it('retains semicolon separators', () => {
testTranspile(`
a$ = "string"
print a$; a$; a$
`);
});

it('supports no space between function calls', () => {
testTranspile(`
function getText()
return "text"
end function
print getText() getText() getText()
`);
});

it('supports print in loop', () => {
testTranspile(`
paramArr = ["This", "is", true, "and", "this", "is", 1]
print "This is one line of stuff:";
for each item in paramArr
print item; " ";
end for
print ""
`, `
paramArr = [
"This",
"is",
true,
"and",
"this",
"is",
1
]
print "This is one line of stuff:";
for each item in paramArr
print item; " ";
end for
print ""
`);
});

it('handles roku documentation examples', () => {
testTranspile(`
x=5:print 25; " is equal to"; x^2
a$="string":print a$;a$,a$;" ";a$
print "zone 1","zone 2","zone 3","zone 4"
print "print statement #1 ":print "print statement #2"
print "this is a five " 5 "!!"
print {}
print {a:1}
print []
print [5]
print tab(5)"tabbed 5";tab(25)"tabbed 25"
print tab(40) pos(0) 'prints 40 at position 40
print "these" tab(pos(0)+5)"words" tab(pos(0)+5)"are":print tab(pos(0)+5)"evenly" tab(pos(0)+5)"spaced"
`, `
x = 5
print 25; " is equal to"; x ^ 2
a$ = "string"
print a$; a$, a$; " "; a$
print "zone 1", "zone 2", "zone 3", "zone 4"
print "print statement #1 "
print "print statement #2"
print "this is a five " 5 "!!"
print {}
print {
a: 1
}
print []
print [
5
]
print tab(5) "tabbed 5"; tab(25) "tabbed 25"
print tab(40) pos(0) 'prints 40 at position 40
print "these" tab(pos(0) + 5) "words" tab(pos(0) + 5) "are"
print tab(pos(0) + 5) "evenly" tab(pos(0) + 5) "spaced"
`);
});
});
});