From bc3b2cd81d5237fb0628bf5ecce1ef7ac4f8b4ec Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Thu, 3 Feb 2022 09:24:00 -0600 Subject: [PATCH] ecs: with/if --- src/codemirror/ecs.js | 4 ++-- src/common/ecs/compiler.ts | 2 +- src/common/ecs/ecs.ts | 27 +++++++++++++++++++-------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/codemirror/ecs.js b/src/codemirror/ecs.js index 10b835a2..869f9eab 100644 --- a/src/codemirror/ecs.js +++ b/src/codemirror/ecs.js @@ -20,14 +20,14 @@ 'end', 'component', 'system', 'entity', 'scope', 'using', 'demo', 'const', 'init', 'locals', 'on', 'do', 'emit', 'limit', - 'once', 'foreach', 'with', 'join' + 'once', 'foreach', 'with', 'join', 'if', ]; var keywords_list = [ 'processor', 'byte', 'word', 'long', 'include', 'seg', 'dc', 'ds', 'dv', 'hex', 'err', 'org', 'rorg', 'echo', 'rend', 'align', 'subroutine', 'equ', 'eqm', 'set', 'mac', 'endm', 'mexit', 'ifconst', - 'ifnconst', 'if', 'else', 'endif', 'eif', 'repeat', 'repend' + 'ifnconst', 'else', 'endif', 'eif', 'repeat', 'repend' ]; var directives = new Map(); diff --git a/src/common/ecs/compiler.ts b/src/common/ecs/compiler.ts index f187d428..79823b65 100644 --- a/src/common/ecs/compiler.ts +++ b/src/common/ecs/compiler.ts @@ -212,7 +212,7 @@ export class ECSCompiler extends Tokenizer { let event = this.expectIdent().str; this.expectToken('do'); let select = this.expectTokens( - ['once', 'foreach', 'join', 'with', 'select']).str as SelectType; // TODO: type check? + ['once', 'foreach', 'join', 'with', 'if', 'select']).str as SelectType; // TODO: type check? let query = undefined; let join = undefined; if (select != 'once') { diff --git a/src/common/ecs/ecs.ts b/src/common/ecs/ecs.ts index 38f6f466..18147ecb 100644 --- a/src/common/ecs/ecs.ts +++ b/src/common/ecs/ecs.ts @@ -111,7 +111,7 @@ export interface System extends SourceLocated { tempbytes?: number; } -export type SelectType = 'once' | 'foreach' | 'join' | 'with' | 'select'; +export type SelectType = 'once' | 'foreach' | 'join' | 'with' | 'if' | 'select'; export interface ActionBase extends SourceLocated { select: SelectType; @@ -125,7 +125,7 @@ export interface ActionOnce extends ActionBase { } export interface ActionWithQuery extends ActionBase { - select: 'foreach' | 'join' | 'with' | 'select' + select: 'foreach' | 'join' | 'with' | 'if' | 'select' query: Query limit?: number } @@ -529,14 +529,20 @@ class ActionEval { this.jr = new QueryResult(this.scope, (this.action as ActionWithJoin).join); state.x = this.jr; break; + case 'if': case 'with': if (state.x) { let int = state.x.intersection(this.qr); - // TODO: what if we filter 0 entities? - if (int.entities.length == 0) throw new ECSError('queries do not intersect', this.action); - let indofs = int.entities[0].id - state.x.entities[0].id; - state.xofs += indofs; // TODO: should merge with filter - state.x = int; + if (int.entities.length == 0) { + if (this.action.select == 'with') + throw new ECSError('queries do not intersect', this.action); + else + break; + } else { + let indofs = int.entities[0].id - state.x.entities[0].id; + state.xofs += indofs; // TODO: should merge with filter + state.x = int; + } } else { if (this.qr.entities.length != 1) throw new ECSError(`query outside of loop must match exactly one entity`, this.action); @@ -566,7 +572,7 @@ class ActionEval { if (action.select == 'join' && this.jr) { let jentities = this.jr.entities; if (jentities.length == 0) - throw new ECSError(`join query doesn't match any entities`, action); // TODO + throw new ECSError(`join query doesn't match any entities`, (action as ActionWithJoin).join); // TODO let joinfield = this.getJoinField(action, this.qr.atypes, this.jr.atypes); // TODO: what if only 1 item? // TODO: should be able to access fields via Y reg @@ -580,6 +586,8 @@ class ActionEval { if (action.limit) { entities = entities.slice(0, action.limit); } + if (entities.length == 0 && action.select == 'if') + return ''; if (entities.length == 0) throw new ECSError(`query doesn't match any entities`, action.query); // TODO this.qr.entities = entities; @@ -587,6 +595,9 @@ class ActionEval { if (action.select == 'with' && entities.length > 1) { code = this.wrapCodeInFilter(code); } + if (action.select == 'if' && entities.length > 1) { + code = this.wrapCodeInFilter(code); + } // define properties props['%elo'] = entities[0].id.toString(); props['%ehi'] = entities[entities.length - 1].id.toString();