From a444de693b13674e6e8f312e6b1d7e1cf4d0bcc9 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 20 Feb 2022 07:37:51 -0600 Subject: [PATCH] ecs: field, ref type checking, start cmd --- .gitignore | 14 ++-- src/common/ecs/README.md | 8 ++ src/common/ecs/compiler.ts | 150 ++++++++++++++++++++----------------- src/common/ecs/ecs.ts | 53 ++++++++++--- test/ecs/superman.ecs | 3 +- test/ecs/superman.txt | 6 +- 6 files changed, 143 insertions(+), 91 deletions(-) diff --git a/.gitignore b/.gitignore index 0998cb12..3be955f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,13 @@ *~ node_modules -./local/ -./tests_output/ -./test/output/ +/local/ +/tests_output/ +/test/output/ .DS_Store -./tmp/ -./web/ -./release/ -./gen/ +/tmp/ +/web/ +/release/ +/gen/ config.js chromedriver.log nightwatch.conf.js diff --git a/src/common/ecs/README.md b/src/common/ecs/README.md index 907da05a..73db0182 100644 --- a/src/common/ecs/README.md +++ b/src/common/ecs/README.md @@ -143,3 +143,11 @@ banks need to duplicate code and/or rodata - don't split critical code across banks need bank trampoline macro nested scopes for game modes? (title / demo / play) + +critical data fields +if accessed in critical section, make critical +ignore arrays that aren't referenced + +use DASM for multipass? + +default values for component fields diff --git a/src/common/ecs/compiler.ts b/src/common/ecs/compiler.ts index db2274ac..8ca73c01 100644 --- a/src/common/ecs/compiler.ts +++ b/src/common/ecs/compiler.ts @@ -25,8 +25,7 @@ export class ECSCompiler extends Tokenizer { debuginfo = false; constructor( - public readonly em: EntityManager) - { + public readonly em: EntityManager) { super(); //this.includeEOL = true; this.setTokenRules([ @@ -52,7 +51,7 @@ export class ECSCompiler extends Tokenizer { if (obj) (obj as SourceLocated).$loc = tok.$loc; return obj; } - + parseFile(text: string, path: string) { this.tokenizeFile(text, path); while (!this.isEOF()) { @@ -78,6 +77,7 @@ export class ECSCompiler extends Tokenizer { comp.parseFile(text, path); } catch (e) { for (var err of comp.errors) this.errors.push(err); + throw e; } } } @@ -99,12 +99,14 @@ export class ECSCompiler extends Tokenizer { } if (tok.str == 'import') { let tok = this.expectTokenTypes([ECSTokenType.QuotedString]); - let path = tok.str.substring(1, tok.str.length-1); + let path = tok.str.substring(1, tok.str.length - 1); return this.importFile(path); } if (tok.str == 'demo') { let scope = this.parseScope(); scope.isDemo = true; + // TODO: make required + if (this.peekToken().str == 'demo') this.expectToken('demo'); return scope; } if (tok.str == 'comment') { @@ -143,7 +145,7 @@ export class ECSCompiler extends Tokenizer { return { dtype: 'ref', query: this.parseQuery() } as RefType; } if (this.ifToken('array')) { - let index : IntType | undefined = undefined; + let index: IntType | undefined = undefined; if (this.peekToken().type == ECSTokenType.Integer) { index = this.parseDataType() as IntType; } @@ -158,7 +160,7 @@ export class ECSCompiler extends Tokenizer { this.compileError(`I expected a data type here.`); throw new Error(); } - parseDataValue(field: DataField) : DataValue | ForwardRef { + parseDataValue(field: DataField): DataValue | ForwardRef { let tok = this.peekToken(); if (tok.type == 'integer') { return this.expectInteger(); @@ -175,7 +177,7 @@ export class ECSCompiler extends Tokenizer { this.compileError(`I expected a ${field.dtype} here.`); throw new Error(); } - parseEntityForwardRef(reftype?: RefType) : ForwardRef { + parseEntityForwardRef(reftype?: RefType): ForwardRef { let token = this.expectIdent(); return { reftype, token }; } @@ -189,7 +191,7 @@ export class ECSCompiler extends Tokenizer { expectInteger(): number { let s = this.consumeToken().str; - let i : number; + let i: number; if (s.startsWith('$')) i = parseInt(s.substring(1), 16); // hex $... else if (s.startsWith('%')) @@ -205,7 +207,7 @@ export class ECSCompiler extends Tokenizer { let actions: Action[] = []; let system: System = { name, actions }; let cmd; - while ((cmd = this.expectTokens(['on','locals','end']).str) != 'end') { + while ((cmd = this.expectTokens(['on', 'locals', 'end']).str) != 'end') { if (cmd == 'on') { let action = this.annotate(() => this.parseAction(system)); actions.push(action); @@ -225,11 +227,11 @@ export class ECSCompiler extends Tokenizer { this.consumeToken(); tempbytes = this.expectInteger(); } - let system : System = { name, tempbytes, actions: [] }; - let context : ActionContext = { scope: null, system }; + let system: System = { name, tempbytes, actions: [] }; + let context: ActionContext = { scope: null, system }; let text = this.parseCode(context); - let select : SelectType = 'once'; - let action : Action = { text, event: name, select }; + let select: SelectType = 'once'; + let action: Action = { text, event: name, select }; system.actions.push(action); return system; } @@ -240,7 +242,7 @@ export class ECSCompiler extends Tokenizer { this.expectToken('do'); // TODO: include modifiers in error msg const select = this.expectTokens(SELECT_TYPE).str as SelectType; // TODO: type check? - const all_modifiers = ['critical','asc','desc']; // TODO + const all_modifiers = ['critical', 'asc', 'desc']; // TODO let query = undefined; let join = undefined; if (select == 'once') { @@ -261,7 +263,7 @@ export class ECSCompiler extends Tokenizer { if (this.ifToken('fit')) { fitbytes = this.expectInteger(); } - let context : ActionContext = { scope: null, system }; + let context: ActionContext = { scope: null, system }; // parse --- code --- let text = this.parseCode(context); let direction = undefined; @@ -271,7 +273,7 @@ export class ECSCompiler extends Tokenizer { if (modifiers['critical']) (action as ActionWithJoin).critical = true; return action as ActionWithJoin; } - + parseQuery() { let q: Query = { include: [] }; let start = this.expectToken('['); @@ -319,12 +321,12 @@ export class ECSCompiler extends Tokenizer { parseCode(context: ActionContext): string { // TODOActionNode[] { // TODO: add $loc let tok = this.expectTokenTypes([ECSTokenType.CodeFragment]); - let code = tok.str.substring(3, tok.str.length-3); + let code = tok.str.substring(3, tok.str.length - 3); // TODO: add after parsing maybe? let lines = code.split('\n'); if (this.debuginfo) this.addDebugInfo(lines, tok.$loc.line); code = lines.join('\n'); - + let acomp = new ECSActionCompiler(context); let nodes = acomp.parseFile(code, this.path); // TODO: return nodes @@ -333,13 +335,13 @@ export class ECSCompiler extends Tokenizer { addDebugInfo(lines: string[], startline: number) { const re = /^\s*(;|\/\/|$)/; // ignore comments and blank lines - for (let i=0; i field.hi) + throw new ECSError(`This "${field.name}" value is out of range, should be between ${field.lo} and ${field.hi}.`); + } else if (field.dtype == 'ref') { + // TODO: allow override if number + let eset = new EntitySet(this, field.query); + if (value < 0 || value >= eset.entities.length) + throw new ECSError(`This "${field.name}" value is out of range for this ref type.`); + } + } + } generateCodeForEvent(event: string, args?: string[], codelabel?: string): string { // find systems that respond to event // and have entities in this scope diff --git a/test/ecs/superman.ecs b/test/ecs/superman.ecs index 137bc1ba..db50c3c7 100644 --- a/test/ecs/superman.ecs +++ b/test/ecs/superman.ecs @@ -159,6 +159,7 @@ end entity NullShape [Bitmap,Colormap] decode vcs_sprite --- +........ 00 --- end @@ -504,7 +505,7 @@ x.x.x.x.x.x.x.x.x.x. .. 06 .. var sprite = #Superdude end entity Slot1 [SpriteSlot] - var sprite = $ff + var sprite = 0 // $ff end using VersatilePlayfield with #Superdude.room diff --git a/test/ecs/superman.txt b/test/ecs/superman.txt index e798d8af..e26502e7 100644 --- a/test/ecs/superman.txt +++ b/test/ecs/superman.txt @@ -60,8 +60,9 @@ Bitmap_bitmapdata_b8: .byte >(Bitmap_bitmapdata_e2_b0+31) .byte >(Bitmap_bitmapdata_e3_b0+31) Bitmap_bitmapdata_e1_b0: +.byte 0 Bitmap_height_b0: -.byte 255 +.byte 0 .byte 17 .byte 27 Colormap_colormapdata_b0: @@ -73,6 +74,7 @@ Colormap_colormapdata_b8: .byte >(Colormap_colormapdata_e2_b0+31) .byte >(Colormap_colormapdata_e3_b0+31) Colormap_colormapdata_e1_b0: +.byte 0 Bitmap_bitmapdata_e2_b0: .byte 128 .byte 192 @@ -622,7 +624,7 @@ Main__INITDATA: .byte 60 .byte 90 .byte 0 -.byte 255 +.byte 0 .byte 0 .byte 0 .byte 0