mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
1e79d9d59d
* Enabled prettier * Update lint, fix issues * Restore some array formatting
259 lines
9.6 KiB
TypeScript
259 lines
9.6 KiB
TypeScript
import ApplesoftDecompiler from 'js/applesoft/decompiler';
|
|
import ApplesoftCompiler from 'js/applesoft/compiler';
|
|
import RAM from 'js/ram';
|
|
import { Memory } from 'js/types';
|
|
|
|
function decompileFromMemory(ram: Memory): string {
|
|
const decompiler = ApplesoftDecompiler.decompilerFromMemory(ram);
|
|
return decompiler.list();
|
|
}
|
|
|
|
describe('ApplesoftDecompiler', () => {
|
|
it('decompiles one-line program from memory', () => {
|
|
const ram = new RAM(0x00, 0xff); // 64K
|
|
ApplesoftCompiler.compileToMemory(ram, '10 PRINT "Hello, World!"');
|
|
|
|
const program = decompileFromMemory(ram);
|
|
expect(program).toEqual(' 10 PRINT "Hello, World!"\n');
|
|
});
|
|
|
|
it('decompiles REM statements correctly', () => {
|
|
const ram = new RAM(0x00, 0xff); // 64K
|
|
ApplesoftCompiler.compileToMemory(
|
|
ram,
|
|
'10 REMNo space before\n20 REM with space'
|
|
);
|
|
|
|
const program = decompileFromMemory(ram);
|
|
expect(program).toEqual(
|
|
' 10 REM No space before\n 20 REM with space\n'
|
|
);
|
|
});
|
|
|
|
it('lists a one-line program', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 PRINT "Hello, World!"');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list();
|
|
expect(program).toEqual(' 10 PRINT "Hello, World!"\n');
|
|
});
|
|
|
|
it('correctly computes the base address when 0 is passed in', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 PRINT "Hello, World!"\n20 GOTO 10');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program(), 0);
|
|
const program = decompiler.list();
|
|
expect(program).toEqual(' 10 PRINT "Hello, World!"\n 20 GOTO 10\n');
|
|
});
|
|
|
|
it('lists a program with a long line', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile(
|
|
'10 PRINT "Hello, World!"\n' +
|
|
'20 PRINT "Hello, again, with a much longer line this time."\n' +
|
|
'30 REM1234567890123456789012345678901234567890'
|
|
);
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list();
|
|
expect(program).toEqual(
|
|
' 10 PRINT "Hello, World!"\n' +
|
|
' 20 PRINT "Hello, again, with a \n' +
|
|
' much longer line this time."\n' +
|
|
' \n' +
|
|
' 30 REM 123456789012345678901234\n' +
|
|
' 5678901234567890\n'
|
|
);
|
|
});
|
|
|
|
it('lists a program with a long line Apple ][+-style', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile(
|
|
'10 PRINT "Hello, World!"\n' +
|
|
'20 PRINT "Hello, again, with a much longer line this time."\n' +
|
|
'30 REM1234567890123456789012345678901234567890'
|
|
);
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list({ apple2: 'plus' });
|
|
expect(program).toEqual(
|
|
'10 PRINT "Hello, World!"\n' +
|
|
'20 PRINT "Hello, again, with a m\n' +
|
|
' uch longer line this time."\n' +
|
|
'30 REM 1234567890123456789012345\n' +
|
|
' 678901234567890\n'
|
|
);
|
|
});
|
|
|
|
it('lists a range of lines', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile(
|
|
'10 PRINT "Hello, World!"\n' +
|
|
'20 PRINT "Hello, again, with a much longer line this time."\n' +
|
|
'30 REM1234567890123456789012345678901234567890'
|
|
);
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list({}, 10, 20);
|
|
expect(program).toEqual(
|
|
' 10 PRINT "Hello, World!"\n' +
|
|
' 20 PRINT "Hello, again, with a \n' +
|
|
' much longer line this time."\n' +
|
|
' \n'
|
|
);
|
|
});
|
|
|
|
it('lists weird code correctly', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 NOT RACE A THEN B');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list();
|
|
expect(program).toEqual(' 10 NOTRACE AT HENB\n');
|
|
});
|
|
|
|
it('lists 10ATOZ correctly', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10ATOZ');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list();
|
|
expect(program).toEqual(' 10 A TO Z\n');
|
|
});
|
|
|
|
it('wraps correctly in 80-column mode', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 ?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.list({ columns: 80 });
|
|
expect(program).toEqual(
|
|
' 10 PRINT : PRINT : PRINT : PRINT : ' +
|
|
'PRINT : PRINT : PRINT : PRINT : PRINT \n' +
|
|
' : PRINT : PRINT : PRINT : PRINT : PRINT : PRINT : ' +
|
|
'PRINT \n'
|
|
);
|
|
});
|
|
|
|
it('decompiles compactly', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 ?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual('10?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?');
|
|
});
|
|
|
|
it('when decompiling compactly, adds a space after the line', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 12345');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual('10 12345');
|
|
});
|
|
|
|
it('when decompiling compactly, adds a space after AT for token', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 AT NEXT');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual('10AT NEXT');
|
|
});
|
|
|
|
it('when decompiling compactly, adds a space after AT for literal', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 AT n');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual('10AT N');
|
|
});
|
|
|
|
it('when decompiling compactly, decompiles 10ATOZ correctly', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10ATOZ');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual('10ATOZ');
|
|
});
|
|
|
|
it('when decompiling compactly, adds a space to disambiguate tokens', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile(
|
|
[
|
|
'10 A THEN B',
|
|
'30 A TO Z',
|
|
'40 AT N',
|
|
'50 A TN',
|
|
'60 N O T R A C E',
|
|
'70 NOT RACE',
|
|
].join('\n')
|
|
);
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'compact' });
|
|
expect(program).toEqual(
|
|
[
|
|
'10ATHENB',
|
|
'30ATOZ',
|
|
'40AT N',
|
|
'50ATN',
|
|
'60NOTRACE',
|
|
'70NOTRACE',
|
|
].join('\n')
|
|
);
|
|
});
|
|
|
|
it('when decompiling prettily, formats reasonably well', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 FORI=1TO10:PRINTI:NEXT');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'pretty' });
|
|
expect(program).toEqual('10 FOR I = 1 TO 10 : PRINT I : NEXT');
|
|
});
|
|
|
|
it('when decompiling prettily, formats relations', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 IFA<BORA>=BORB<=AORB=A THEN');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'pretty' });
|
|
expect(program).toEqual(
|
|
'10 IF A < B OR A >= B OR B <= A OR B = AT HEN'
|
|
);
|
|
});
|
|
|
|
it('when decompiling prettily, decompiles 10ATOZ correctly', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10ATOZ');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'pretty' });
|
|
expect(program).toEqual('10 A TO Z');
|
|
});
|
|
|
|
it('when decompiling prettily, does not insert extra spaces in strings', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10A="::::":B=","');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'pretty' });
|
|
expect(program).toEqual('10 A = "::::" : B = ","');
|
|
});
|
|
|
|
it('when decompiling prettily, inserts space after comma', () => {
|
|
const compiler = new ApplesoftCompiler();
|
|
compiler.compile('10 HPLOTX,Y:GOTO10');
|
|
|
|
const decompiler = new ApplesoftDecompiler(compiler.program());
|
|
const program = decompiler.decompile({ style: 'pretty' });
|
|
expect(program).toEqual('10 HPLOT X, Y : GOTO 10');
|
|
});
|
|
});
|