ecs: baseoffset

This commit is contained in:
Steven Hugg 2022-02-04 19:48:08 -06:00
parent 1f64a623aa
commit 3a77e31e47
3 changed files with 30 additions and 8 deletions

View File

@ -1,7 +1,7 @@
import { mergeLocs, Tokenizer, TokenType } from "../tokenizer";
import { SourceLocated } from "../workertypes";
import { Action, ArrayType, ComponentType, DataField, DataType, DataValue, 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, SourceFileExport, System } from "./ecs";
export enum ECSTokenType {
Ellipsis = 'ellipsis',
@ -129,14 +129,18 @@ export class ECSCompiler extends Tokenizer {
if (this.peekToken().str == '[') {
return { dtype: 'ref', query: this.parseQuery() } as RefType;
}
if (this.peekToken().str == 'array') {
if (this.ifToken('array')) {
let index : IntType | undefined = undefined;
this.expectToken('array');
if (this.peekToken().type == ECSTokenType.Integer) {
index = this.parseDataType() as IntType;
}
this.expectToken('of');
return { dtype: 'array', index, elem: this.parseDataType() } as ArrayType;
let elem = this.parseDataType();
let baseoffset;
if (this.ifToken('baseoffset')) {
baseoffset = this.expectInteger();
}
return { dtype: 'array', index, elem, baseoffset } as ArrayType;
}
this.internalError(); throw new Error();
}

View File

@ -58,6 +58,7 @@ how to avoid cycle crossing for critical code and data?
*/
import { data } from "jquery";
import { SourceLocated, SourceLocation } from "../workertypes";
export class ECSError extends Error {
@ -153,6 +154,7 @@ export interface ArrayType {
dtype: 'array'
elem: DataType
index?: DataType
baseoffset?: number
}
export interface RefType {
@ -651,8 +653,18 @@ class ActionEval {
let bitofs = parseInt(args[1] || '0');
return this.generateCodeForField(fieldName, bitofs, canwrite);
}
__base(args: string[]) {
// TODO: refactor into generateCode..
let fieldName = args[0];
let bitofs = parseInt(args[1] || '0');
let component = this.em.singleComponentWithFieldName(this.qr.atypes, fieldName, this.action);
let field = component.fields.find(f => f.name == fieldName);
if (field == null) throw new ECSError(`no field named "${fieldName}" in component`, this.action);
return this.dialect.fieldsymbol(component, field, bitofs);
}
__index(args: string[]) {
let ident = args[0]; // TODO?
// TODO: check select type and if we actually have an index...
let ident = args[0];
if (this.entities.length == 1) {
return this.dialect.absolute(ident);
} else {
@ -727,6 +739,7 @@ class ActionEval {
// find archetypes
let field = component.fields.find(f => f.name == fieldName);
if (field == null) throw new ECSError(`no field named "${fieldName}" in component`, action);
let ident = this.dialect.fieldsymbol(component, field, bitofs);
// see if all entities have the same constant value
// TODO: should be done somewhere else?
let constValues = new Set<DataValue>();
@ -753,7 +766,6 @@ class ActionEval {
let range = this.scope.bss.getFieldRange(component, fieldName) || this.scope.rodata.getFieldRange(component, fieldName);
if (!range) throw new ECSError(`couldn't find field for ${component.name}:${fieldName}, maybe no entities?`); // TODO
// TODO: dialect
let ident = this.dialect.fieldsymbol(component, field, bitofs);
let eidofs = qr.entities.length && qr.entities[0].id - range.elo; // TODO: negative?
if (baseLookup) {
return this.dialect.absolute(ident);
@ -940,24 +952,27 @@ export class EntityScope implements SourceLocated {
// is it a bounded array? (TODO)
if (f.dtype == 'array' && f.index) {
let datasym = this.dialect.datasymbol(c, f, e.id);
let offset = this.bss.allocateBytes(datasym, getFieldLength(f.index));
let databytes = getFieldLength(f.index);
let offset = this.bss.allocateBytes(datasym, databytes);
let ptrlosym = this.dialect.fieldsymbol(c, f, 0);
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
let loofs = segment.allocateBytes(ptrlosym, entcount);
let hiofs = segment.allocateBytes(ptrhisym, entcount);
if (f.baseoffset) datasym = `(${datasym}+${f.baseoffset})`;
segment.initdata[loofs + e.id - range.elo] = { symbol: datasym, bitofs: 0 };
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
}
} else {
// this is a constant
// is it a byte array?
if (v instanceof Uint8Array) {
if (v instanceof Uint8Array && f.dtype == 'array') {
let datasym = this.dialect.datasymbol(c, f, e.id);
segment.allocateInitData(datasym, v);
let ptrlosym = this.dialect.fieldsymbol(c, f, 0);
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
let loofs = segment.allocateBytes(ptrlosym, entcount);
let hiofs = segment.allocateBytes(ptrhisym, entcount);
if (f.baseoffset) datasym = `(${datasym}+${f.baseoffset})`;
segment.initdata[loofs + e.id - range.elo] = { symbol: datasym, bitofs: 0 };
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
// TODO: } else if (v instanceof Uint16Array) {

View File

@ -160,6 +160,9 @@ export class Tokenizer {
let tok = this.lasttoken = (this.tokens.shift() || this.eof);
return tok;
}
ifToken(match: string): Token | undefined {
if (this.peekToken().str == match) return this.consumeToken();
}
expectToken(str: string, msg?: string): Token {
let tok = this.consumeToken();
let tokstr = tok.str;