mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
232 lines
9.1 KiB
TypeScript
232 lines
9.1 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');
|
|
});
|
|
});
|