From dda51c34677796f50895a159758188284002c558 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Tue, 8 Feb 2022 06:18:28 -0600 Subject: [PATCH] ecs: asc desc --- src/common/ecs/compiler.ts | 21 ++++++++++++--------- src/common/ecs/ecs.ts | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/common/ecs/compiler.ts b/src/common/ecs/compiler.ts index 3e452930..30b95465 100644 --- a/src/common/ecs/compiler.ts +++ b/src/common/ecs/compiler.ts @@ -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, SELECT_TYPE, SourceFileExport, System } from "./ecs"; +import { Action, ActionWithJoin, 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', @@ -224,13 +224,16 @@ export class ECSCompiler extends Tokenizer { parseAction(): Action { // TODO: unused events? - let event = this.expectIdent().str; + const event = this.expectIdent().str; this.expectToken('do'); - let select = this.expectTokens(SELECT_TYPE).str as SelectType; // TODO: type check? + const all_modifiers = ['cyclecritical','asc','desc']; // TODO + const modifiers = this.parseModifiers(all_modifiers); + // TODO: include modifiers in error msg + const select = this.expectTokens(SELECT_TYPE).str as SelectType; // TODO: type check? let query = undefined; let join = undefined; if (select == 'once') { - if (this.peekToken().str == '[') this.compileError(`A "${select}" query can't include a query.`) + if (this.peekToken().str == '[') this.compileError(`A "${select}" action can't include a query.`) } else { query = this.parseQuery(); } @@ -242,12 +245,12 @@ export class ECSCompiler extends Tokenizer { if (!query) { this.compileError(`A "${select}" query can't include a limit.`); } else query.limit = this.expectInteger(); } - if (this.ifToken('cyclecritical')) { - // TODO - } let text = this.parseCode(); - let action = { text, event, query, join, select }; - return action as Action; + let direction = undefined; + if (modifiers['asc']) direction = 'asc'; + else if (modifiers['desc']) direction = 'desc'; + let action = { text, event, query, join, select, direction }; + return action as ActionWithJoin; } parseQuery() { diff --git a/src/common/ecs/ecs.ts b/src/common/ecs/ecs.ts index d7604f48..40e1a31f 100644 --- a/src/common/ecs/ecs.ts +++ b/src/common/ecs/ecs.ts @@ -59,8 +59,6 @@ how to avoid cycle crossing for critical code and data? */ - -import { data } from "jquery"; import { SourceLocated, SourceLocation } from "../workertypes"; export class ECSError extends Error { @@ -132,6 +130,7 @@ export interface ActionOnce extends ActionBase { export interface ActionWithQuery extends ActionBase { select: 'foreach' | 'join' | 'with' | 'if' | 'select' query: Query + direction?: 'asc' | 'desc' } export interface ActionWithJoin extends ActionWithQuery { @@ -191,7 +190,7 @@ interface ComponentFieldPair { export class Dialect_CA65 { - ASM_ITERATE_EACH = ` + ASM_ITERATE_EACH_ASC = ` ldx #0 @__each: {{%code}} @@ -201,7 +200,16 @@ export class Dialect_CA65 { @__exit: `; - ASM_ITERATE_JOIN = ` + ASM_ITERATE_EACH_DESC = ` + ldx #{{%ecount}}-1 +@__each: + {{%code}} + dex + bpl @__each +@__exit: +`; + + ASM_ITERATE_JOIN_ASC = ` ldy #0 @__each: ldx {{%joinfield}},y @@ -210,6 +218,16 @@ export class Dialect_CA65 { cpy #{{%ecount}} bne @__each @__exit: +`; + + ASM_ITERATE_JOIN_DESC = ` + ldy #{{%ecount}}-1 +@__each: + ldx {{%joinfield}},y + {{%code}} + dey + bpl @__each +@__exit: `; ASM_FILTER_RANGE_LO_X = ` @@ -490,8 +508,8 @@ class ActionCPUState { } class ActionEval { - em; - dialect; + em : EntityManager; + dialect : Dialect_CA65; qr: EntitySet; jr: EntitySet | undefined; oldState : ActionCPUState; @@ -675,12 +693,14 @@ class ActionEval { __bss_init(args: string[]) { return this.scope.allocateInitData(this.scope.bss); } - wrapCodeInLoop(code: string, action: Action, ents: Entity[], joinfield?: ComponentFieldPair): string { + wrapCodeInLoop(code: string, action: ActionWithQuery, ents: Entity[], joinfield?: ComponentFieldPair): string { // TODO: check ents // TODO: check segment bounds // TODO: what if 0 or 1 entitites? - let s = this.dialect.ASM_ITERATE_EACH; - if (joinfield) s = this.dialect.ASM_ITERATE_JOIN; + // TODO: check > 127 or > 255 + let dir = action.direction; + let s = dir == 'desc' ? this.dialect.ASM_ITERATE_EACH_DESC : this.dialect.ASM_ITERATE_EACH_ASC; + if (joinfield) s = dir == 'desc' ? this.dialect.ASM_ITERATE_JOIN_DESC : this.dialect.ASM_ITERATE_JOIN_ASC; s = s.replace('{{%code}}', code); return s; }