mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 03:34:05 +00:00
ecs: test files
This commit is contained in:
parent
109e60ae10
commit
2dfe65932b
@ -2,7 +2,7 @@
|
||||
import { mergeLocs, Tokenizer, TokenType } from "../tokenizer";
|
||||
import { SourceLocated } from "../workertypes";
|
||||
import { newDecoder } from "./decoder";
|
||||
import { Action, ArrayType, ComponentType, DataField, DataType, DataValue, ECSError, Entity, EntityArchetype, EntityManager, EntityScope, IntType, Query, RefType, SelectType, SourceFileExport, System } from "./ecs";
|
||||
import { Action, ArrayType, ComponentType, DataField, DataType, DataValue, ECSError, Entity, EntityArchetype, EntityManager, EntityScope, IntType, Query, RefType, SelectType, SELECT_TYPE, SourceFileExport, System } from "./ecs";
|
||||
|
||||
export enum ECSTokenType {
|
||||
Ellipsis = 'ellipsis',
|
||||
@ -15,6 +15,7 @@ export enum ECSTokenType {
|
||||
export class ECSCompiler extends Tokenizer {
|
||||
|
||||
currentScope: EntityScope | null = null;
|
||||
debuginfo = false;
|
||||
|
||||
constructor(
|
||||
public readonly em: EntityManager)
|
||||
@ -63,6 +64,7 @@ export class ECSCompiler extends Tokenizer {
|
||||
if (!text) this.compileError(`I can't find the import file "${path}".`);
|
||||
this.em.imported[path] = true;
|
||||
let comp = new ECSCompiler(this.em);
|
||||
comp.debuginfo = this.debuginfo; // TODO: clone compiler
|
||||
try {
|
||||
comp.parseFile(text, path);
|
||||
} catch (e) {
|
||||
@ -224,11 +226,12 @@ export class ECSCompiler extends Tokenizer {
|
||||
// TODO: unused events?
|
||||
let event = this.expectIdent().str;
|
||||
this.expectToken('do');
|
||||
let select = this.expectTokens(
|
||||
['once', 'foreach', 'join', 'with', 'if', 'select']).str as SelectType; // TODO: type check?
|
||||
let select = this.expectTokens(SELECT_TYPE).str as SelectType; // TODO: type check?
|
||||
let query = undefined;
|
||||
let join = undefined;
|
||||
if (select != 'once') {
|
||||
if (select == 'once') {
|
||||
if (this.peekToken().str == '[') this.compileError(`A "${select}" query can't include a query.`)
|
||||
} else {
|
||||
query = this.parseQuery();
|
||||
}
|
||||
if (select == 'join') {
|
||||
@ -273,12 +276,12 @@ export class ECSCompiler extends Tokenizer {
|
||||
}
|
||||
}
|
||||
|
||||
parseEvent() {
|
||||
parseEventName() {
|
||||
return this.expectIdent().str;
|
||||
}
|
||||
|
||||
parseEventList() {
|
||||
return this.parseList(this.parseEvent, ",");
|
||||
return this.parseList(this.parseEventName, ",");
|
||||
}
|
||||
|
||||
parseCode(): string {
|
||||
@ -286,12 +289,16 @@ export class ECSCompiler extends Tokenizer {
|
||||
let tok = this.expectTokenTypes([ECSTokenType.CodeFragment]);
|
||||
let code = tok.str.substring(3, tok.str.length-3);
|
||||
let lines = code.split('\n');
|
||||
let re = /^\s*(;|\/\/|$)/; // ignore comments and blank lines
|
||||
if (this.debuginfo) this.addDebugInfo(lines, tok.$loc.line);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
addDebugInfo(lines: string[], startline: number) {
|
||||
const re = /^\s*(;|\/\/|$)/; // ignore comments and blank lines
|
||||
for (let i=0; i<lines.length; i++) {
|
||||
if (!lines[i].match(re))
|
||||
lines[i] = this.em.dialect.debug_line(this.path, tok.$loc.line+i) + '\n' + lines[i];
|
||||
lines[i] = this.em.dialect.debug_line(this.path, startline+i) + '\n' + lines[i];
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
parseScope() : EntityScope {
|
||||
|
@ -115,7 +115,9 @@ export interface System extends SourceLocated {
|
||||
tempbytes?: number;
|
||||
}
|
||||
|
||||
export type SelectType = 'once' | 'foreach' | 'join' | 'with' | 'if' | 'select';
|
||||
export const SELECT_TYPE = ['once', 'foreach', 'join', 'with', 'if', 'select'] as const;
|
||||
|
||||
export type SelectType = typeof SELECT_TYPE[number];
|
||||
|
||||
export interface ActionBase extends SourceLocated {
|
||||
select: SelectType;
|
||||
@ -1062,9 +1064,9 @@ export class EntityScope implements SourceLocated {
|
||||
let codeeval = new ActionEval(this, sys, action);
|
||||
codeeval.tmplabel = tmplabel;
|
||||
codeeval.begin();
|
||||
s += this.dialect.comment(`<action ${sys.name}:${event}>`); // TODO
|
||||
s += this.dialect.comment(`start action ${sys.name} ${event}`); // TODO
|
||||
s += codeeval.codeToString();
|
||||
s += this.dialect.comment(`</action ${sys.name}:${event}>`);
|
||||
s += this.dialect.comment(`end action ${sys.name} ${event}`);
|
||||
// TODO: check that this happens once?
|
||||
codeeval.end();
|
||||
numActions++;
|
||||
|
@ -171,7 +171,7 @@ export class Tokenizer {
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
expectTokens(strlist: string[], msg?: string): Token {
|
||||
expectTokens(strlist: readonly string[], msg?: string): Token {
|
||||
let tok = this.consumeToken();
|
||||
let tokstr = tok.str;
|
||||
if (!strlist.includes(tokstr)) {
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { readdirSync, readFileSync } from "fs";
|
||||
import assert from "assert";
|
||||
import { execFileSync } from "child_process";
|
||||
import { readdirSync, readFileSync, writeFileSync } from "fs";
|
||||
import { describe } from "mocha";
|
||||
import { ECSCompiler } from "../common/ecs/compiler";
|
||||
import { Dialect_CA65, EntityManager, SourceFileExport } from "../common/ecs/ecs";
|
||||
@ -338,7 +340,7 @@ scope Root
|
||||
end
|
||||
|
||||
`, 'foo.txt');
|
||||
console.log('json', c.em.toJSON());
|
||||
//console.log('json', c.em.toJSON());
|
||||
let src = new SourceFileExport();
|
||||
c.exportToFile(src);
|
||||
// TODO: test?
|
||||
@ -368,14 +370,27 @@ describe('Tokenizer', function() {
|
||||
describe('Compiler', function() {
|
||||
let testdir = './test/ecs/';
|
||||
let files = readdirSync(testdir).filter(f => f.endsWith('.ecs'));
|
||||
files.forEach((ecspath) => {
|
||||
files.forEach((ecsfn) => {
|
||||
let goodfn = ecsfn.replace('.ecs','.txt')
|
||||
let srcpath = testdir + ecsfn;
|
||||
let destpath = testdir + goodfn;
|
||||
let dialect = new Dialect_CA65();
|
||||
let em = new EntityManager(dialect);
|
||||
em.mainPath = srcpath;
|
||||
let compiler = new ECSCompiler(em);
|
||||
let code = readFileSync(testdir + ecspath, 'utf-8');
|
||||
compiler.parseFile(code, ecspath);
|
||||
compiler.getImportFile = (path: string) => {
|
||||
return readFileSync(testdir + path, 'utf-8');
|
||||
}
|
||||
let code = readFileSync(srcpath, 'utf-8');
|
||||
compiler.parseFile(code, srcpath);
|
||||
let out = new SourceFileExport();
|
||||
em.exportToFile(out);
|
||||
console.log(out.toString());
|
||||
let outtxt = out.toString();
|
||||
let goodtxt = readFileSync(destpath, 'utf-8');
|
||||
if (outtxt.trim() != goodtxt.trim()) {
|
||||
writeFileSync('/tmp/' + goodfn, outtxt, 'utf-8');
|
||||
execFileSync('/usr/bin/diff', [srcpath, destpath]);
|
||||
throw new Error(ecsfn + ' did not match test file');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ export function assembleECS(step: BuildStep): BuildStepResult {
|
||||
if (staleFiles(step, [destpath])) {
|
||||
let code = getWorkFileAsString(step.path);
|
||||
try {
|
||||
compiler.debuginfo = true;
|
||||
compiler.parseFile(code, step.path);
|
||||
let outtext = compiler.export().toString();
|
||||
putWorkFile(destpath, outtext);
|
||||
|
0
test/ecs/basic1.txt
Normal file
0
test/ecs/basic1.txt
Normal file
235
test/ecs/vcs1.ecs
Normal file
235
test/ecs/vcs1.ecs
Normal file
@ -0,0 +1,235 @@
|
||||
|
||||
//#resource "vcs-ca65.h"
|
||||
|
||||
system Init
|
||||
on main_init do once
|
||||
---
|
||||
.include "vcs-ca65.h"
|
||||
.define PAL 0
|
||||
__NMI:
|
||||
__Reset:
|
||||
__BRK:
|
||||
CLEAN_START
|
||||
{{bss_init}} ; initialize data segment
|
||||
{{!start}} ; start main routine
|
||||
.segment "VECTORS"
|
||||
Return: .word $6060
|
||||
VecNMI:
|
||||
VecReset: .word Main::__Reset
|
||||
VecBRK: .word Main::__BRK
|
||||
---
|
||||
end
|
||||
|
||||
component Player
|
||||
end
|
||||
|
||||
component KernelSection
|
||||
lines: 1..255
|
||||
end
|
||||
|
||||
component BGColor
|
||||
bgcolor: 0..255
|
||||
end
|
||||
|
||||
component PFColor
|
||||
pfcolor: 0..255
|
||||
end
|
||||
|
||||
component Playfield
|
||||
pf: 0..0xffffff
|
||||
end
|
||||
|
||||
component AsymPlayfield
|
||||
pfleft: 0..0xffffff
|
||||
pfright: 0..0xffffff
|
||||
end
|
||||
|
||||
component VersatilePlayfield
|
||||
data: array of 0..255 baseoffset -1
|
||||
end
|
||||
|
||||
system FrameLoop
|
||||
on start do once
|
||||
---
|
||||
@NextFrame:
|
||||
FRAME_START
|
||||
{{emit preframe}}
|
||||
KERNEL_START
|
||||
{{emit kernel}}
|
||||
KERNEL_END
|
||||
{{emit postframe}}
|
||||
FRAME_END
|
||||
{{emit nextframe}}
|
||||
jmp @NextFrame ; loop to next frame
|
||||
---
|
||||
end
|
||||
|
||||
system ResetSwitch
|
||||
on nextframe do once
|
||||
---
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcs @NoStart
|
||||
{{!resetswitch}}
|
||||
@NoStart:
|
||||
---
|
||||
end
|
||||
|
||||
system ResetConsole
|
||||
on resetswitch do once
|
||||
---
|
||||
jmp Main::__Reset ; jump to Reset handler
|
||||
---
|
||||
end
|
||||
|
||||
system JoyButton
|
||||
on postframe do foreach [Player]
|
||||
---
|
||||
lda {{index INPT4}} ;read button input
|
||||
bmi @NotPressed
|
||||
{{emit joybutton}}
|
||||
@NotPressed:
|
||||
---
|
||||
end
|
||||
|
||||
system Joystick
|
||||
locals 1
|
||||
on postframe do once
|
||||
---
|
||||
; 2 control inputs share a single byte, 4 bits each
|
||||
lda SWCHA
|
||||
sta {{$0}}
|
||||
---
|
||||
on postframe do foreach [Player]
|
||||
---
|
||||
asl {{$0}}
|
||||
bcs @SkipMoveRight
|
||||
{{!joyright}}
|
||||
@SkipMoveRight:
|
||||
asl {{$0}}
|
||||
bcs @SkipMoveLeft
|
||||
{{!joyleft}}
|
||||
@SkipMoveLeft:
|
||||
asl {{$0}}
|
||||
bcs @SkipMoveDown
|
||||
{{!joydown}}
|
||||
@SkipMoveDown:
|
||||
asl {{$0}}
|
||||
bcs @SkipMoveUp
|
||||
{{!joyup}}
|
||||
@SkipMoveUp:
|
||||
---
|
||||
end
|
||||
|
||||
system SetHorizPos
|
||||
on SetHorizPos do once
|
||||
---
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; Y = player number (0 or 1)
|
||||
sta WSYNC ; start a new line
|
||||
sec ; set carry flag
|
||||
nop
|
||||
@DivideLoop:
|
||||
sbc #15 ; subtract 15
|
||||
bcs @DivideLoop ; branch until negative
|
||||
eor #7 ; calculate fine offset
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta RESP0,y ; fix coarse position
|
||||
sta HMP0,y ; set fine offset
|
||||
---
|
||||
end
|
||||
|
||||
|
||||
system StaticKernel
|
||||
on preframe do foreach [KernelSection] limit 1
|
||||
---
|
||||
{{!kernelsetup}}
|
||||
---
|
||||
on kernel do foreach [KernelSection]
|
||||
---
|
||||
sta WSYNC
|
||||
{{!kernelsetup}}
|
||||
ldy {{<lines}}
|
||||
@loop:
|
||||
sta WSYNC
|
||||
{{!scanline}}
|
||||
dey
|
||||
bne @loop
|
||||
{{!kerneldone}}
|
||||
---
|
||||
on kernelsetup do if [BGColor]
|
||||
---
|
||||
lda {{<bgcolor}}
|
||||
sta COLUBK
|
||||
---
|
||||
on kernelsetup do if [PFColor]
|
||||
---
|
||||
lda {{get pfcolor}}
|
||||
sta COLUPF
|
||||
---
|
||||
on kernelsetup do if [Playfield]
|
||||
---
|
||||
lda {{get pf 0}}
|
||||
sta PF0
|
||||
lda {{get pf 8}}
|
||||
sta PF1
|
||||
lda {{get pf 16}}
|
||||
sta PF2
|
||||
---
|
||||
end
|
||||
|
||||
///
|
||||
|
||||
demo Main
|
||||
using FrameLoop, ResetSwitch, ResetConsole
|
||||
using StaticKernel, JoyButton
|
||||
entity [Player]
|
||||
end
|
||||
entity [KernelSection,BGColor]
|
||||
const lines = 2
|
||||
const bgcolor = $18
|
||||
end
|
||||
entity [KernelSection,BGColor]
|
||||
const lines = 2
|
||||
const bgcolor = $16
|
||||
end
|
||||
entity [KernelSection,BGColor]
|
||||
const lines = 2
|
||||
const bgcolor = $14
|
||||
end
|
||||
entity [KernelSection,BGColor]
|
||||
const lines = 2
|
||||
const bgcolor = $12
|
||||
end
|
||||
entity [KernelSection,BGColor,Playfield]
|
||||
const lines = 10
|
||||
const bgcolor = $14
|
||||
const pf = 0x125244
|
||||
end
|
||||
entity Trees [KernelSection,BGColor,PFColor,Playfield]
|
||||
const lines = 50
|
||||
const bgcolor = $14
|
||||
const pf = 0x112244
|
||||
end
|
||||
entity [KernelSection,BGColor,PFColor,Playfield]
|
||||
const lines = 50
|
||||
const bgcolor = $16
|
||||
const pf = 0x124
|
||||
end
|
||||
entity [KernelSection,BGColor,Playfield]
|
||||
const lines = 10
|
||||
const bgcolor = $18
|
||||
const pf = 0
|
||||
end
|
||||
|
||||
system Local
|
||||
locals 1
|
||||
on joybutton do foreach [PFColor] limit 1 ---
|
||||
inc {{$0}}
|
||||
inc {{set Trees.pfcolor}}
|
||||
---
|
||||
end
|
||||
end
|
241
test/ecs/vcs1.txt
Normal file
241
test/ecs/vcs1.txt
Normal file
@ -0,0 +1,241 @@
|
||||
.scope Main
|
||||
.zeropage
|
||||
PFColor_pfcolor_b0:
|
||||
.res 1
|
||||
.res 1
|
||||
Local_tmp:
|
||||
.res 1
|
||||
.code
|
||||
KernelSection_lines_b0:
|
||||
.byte 2
|
||||
.byte 2
|
||||
.byte 2
|
||||
.byte 2
|
||||
.byte 10
|
||||
.byte 50
|
||||
.byte 50
|
||||
.byte 10
|
||||
BGColor_bgcolor_b0:
|
||||
.byte 24
|
||||
.byte 22
|
||||
.byte 20
|
||||
.byte 18
|
||||
.byte 20
|
||||
.byte 20
|
||||
.byte 22
|
||||
.byte 24
|
||||
Playfield_pf_b0:
|
||||
.byte 68
|
||||
.byte 68
|
||||
.byte 36
|
||||
.byte 0
|
||||
Playfield_pf_b8:
|
||||
.byte 82
|
||||
.byte 34
|
||||
.byte 1
|
||||
.byte 0
|
||||
Playfield_pf_b16:
|
||||
.byte 18
|
||||
.byte 17
|
||||
.byte 0
|
||||
.byte 0
|
||||
Main__INITDATA:
|
||||
.byte 0
|
||||
.byte 0
|
||||
__Start:
|
||||
.code
|
||||
|
||||
;;; start action Init main_init
|
||||
|
||||
.include "vcs-ca65.h"
|
||||
.define PAL 0
|
||||
__NMI:
|
||||
__Reset:
|
||||
__BRK:
|
||||
CLEAN_START
|
||||
|
||||
ldy #2
|
||||
: lda Main__INITDATA-1,y
|
||||
sta PFColor_pfcolor_b0-1,y
|
||||
dey
|
||||
bne :-
|
||||
; initialize data segment
|
||||
.code
|
||||
|
||||
;;; start action FrameLoop start
|
||||
|
||||
FrameLoop__start__2__NextFrame:
|
||||
FRAME_START
|
||||
.code
|
||||
|
||||
;;; start action StaticKernel preframe
|
||||
|
||||
.code
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
lda #24
|
||||
sta COLUBK
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
cpx #0+2
|
||||
bcs StaticKernel__kernelsetup__5____skipxhi
|
||||
|
||||
cpx #0
|
||||
bcc StaticKernel__kernelsetup__5____skipxlo
|
||||
|
||||
lda PFColor_pfcolor_b0,x
|
||||
sta COLUPF
|
||||
|
||||
StaticKernel__kernelsetup__5____skipxlo:
|
||||
|
||||
StaticKernel__kernelsetup__5____skipxhi:
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
cpx #0+4
|
||||
bcs StaticKernel__kernelsetup__6____skipxhi
|
||||
|
||||
cpx #0
|
||||
bcc StaticKernel__kernelsetup__6____skipxlo
|
||||
|
||||
lda Playfield_pf_b0,x
|
||||
sta PF0
|
||||
lda Playfield_pf_b8,x
|
||||
sta PF1
|
||||
lda Playfield_pf_b16,x
|
||||
sta PF2
|
||||
|
||||
StaticKernel__kernelsetup__6____skipxlo:
|
||||
|
||||
StaticKernel__kernelsetup__6____skipxhi:
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
|
||||
;;; end action StaticKernel preframe
|
||||
|
||||
KERNEL_START
|
||||
.code
|
||||
|
||||
;;; start action StaticKernel kernel
|
||||
|
||||
ldx #0
|
||||
StaticKernel__kernel__7____each:
|
||||
|
||||
sta WSYNC
|
||||
.code
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
lda BGColor_bgcolor_b0,x
|
||||
sta COLUBK
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
cpx #5+2
|
||||
bcs StaticKernel__kernelsetup__9____skipxhi
|
||||
|
||||
cpx #5
|
||||
bcc StaticKernel__kernelsetup__9____skipxlo
|
||||
|
||||
lda PFColor_pfcolor_b0-5,x
|
||||
sta COLUPF
|
||||
|
||||
StaticKernel__kernelsetup__9____skipxlo:
|
||||
|
||||
StaticKernel__kernelsetup__9____skipxhi:
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
;;; start action StaticKernel kernelsetup
|
||||
|
||||
cpx #4
|
||||
bcc StaticKernel__kernelsetup__10____skipxlo
|
||||
|
||||
lda Playfield_pf_b0-4,x
|
||||
sta PF0
|
||||
lda Playfield_pf_b8-4,x
|
||||
sta PF1
|
||||
lda Playfield_pf_b16-4,x
|
||||
sta PF2
|
||||
|
||||
StaticKernel__kernelsetup__10____skipxlo:
|
||||
|
||||
;;; end action StaticKernel kernelsetup
|
||||
|
||||
ldy KernelSection_lines_b0,x
|
||||
StaticKernel__kernel__7__loop:
|
||||
sta WSYNC
|
||||
|
||||
dey
|
||||
bne StaticKernel__kernel__7__loop
|
||||
|
||||
|
||||
inx
|
||||
cpx #8
|
||||
bne StaticKernel__kernel__7____each
|
||||
StaticKernel__kernel__7____exit:
|
||||
|
||||
;;; end action StaticKernel kernel
|
||||
|
||||
KERNEL_END
|
||||
.code
|
||||
|
||||
;;; start action JoyButton postframe
|
||||
|
||||
lda INPT4 ;read button input
|
||||
bmi JoyButton__postframe__11__NotPressed
|
||||
.code
|
||||
|
||||
;;; start action Local joybutton
|
||||
|
||||
inc Local_tmp+0
|
||||
inc PFColor_pfcolor_b0
|
||||
|
||||
;;; end action Local joybutton
|
||||
|
||||
JoyButton__postframe__11__NotPressed:
|
||||
|
||||
;;; end action JoyButton postframe
|
||||
|
||||
FRAME_END
|
||||
.code
|
||||
|
||||
;;; start action ResetSwitch nextframe
|
||||
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcs ResetSwitch__nextframe__13__NoStart
|
||||
.code
|
||||
|
||||
;;; start action ResetConsole resetswitch
|
||||
|
||||
jmp Main::__Reset ; jump to Reset handler
|
||||
|
||||
;;; end action ResetConsole resetswitch
|
||||
|
||||
ResetSwitch__nextframe__13__NoStart:
|
||||
|
||||
;;; end action ResetSwitch nextframe
|
||||
|
||||
jmp FrameLoop__start__2__NextFrame ; loop to next frame
|
||||
|
||||
;;; end action FrameLoop start
|
||||
; start main routine
|
||||
.segment "VECTORS"
|
||||
Return: .word $6060
|
||||
VecNMI:
|
||||
VecReset: .word Main::__Reset
|
||||
VecBRK: .word Main::__BRK
|
||||
|
||||
;;; end action Init main_init
|
||||
|
||||
.endscope
|
||||
Main__Start = Main::__Start
|
Loading…
Reference in New Issue
Block a user