mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-18 00:30:43 +00:00
ecs: baseoffset
This commit is contained in:
parent
1f64a623aa
commit
3a77e31e47
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { mergeLocs, Tokenizer, TokenType } from "../tokenizer";
|
import { mergeLocs, Tokenizer, TokenType } from "../tokenizer";
|
||||||
import { SourceLocated } from "../workertypes";
|
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 {
|
export enum ECSTokenType {
|
||||||
Ellipsis = 'ellipsis',
|
Ellipsis = 'ellipsis',
|
||||||
@ -129,14 +129,18 @@ export class ECSCompiler extends Tokenizer {
|
|||||||
if (this.peekToken().str == '[') {
|
if (this.peekToken().str == '[') {
|
||||||
return { dtype: 'ref', query: this.parseQuery() } as RefType;
|
return { dtype: 'ref', query: this.parseQuery() } as RefType;
|
||||||
}
|
}
|
||||||
if (this.peekToken().str == 'array') {
|
if (this.ifToken('array')) {
|
||||||
let index : IntType | undefined = undefined;
|
let index : IntType | undefined = undefined;
|
||||||
this.expectToken('array');
|
|
||||||
if (this.peekToken().type == ECSTokenType.Integer) {
|
if (this.peekToken().type == ECSTokenType.Integer) {
|
||||||
index = this.parseDataType() as IntType;
|
index = this.parseDataType() as IntType;
|
||||||
}
|
}
|
||||||
this.expectToken('of');
|
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();
|
this.internalError(); throw new Error();
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ how to avoid cycle crossing for critical code and data?
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import { data } from "jquery";
|
||||||
import { SourceLocated, SourceLocation } from "../workertypes";
|
import { SourceLocated, SourceLocation } from "../workertypes";
|
||||||
|
|
||||||
export class ECSError extends Error {
|
export class ECSError extends Error {
|
||||||
@ -153,6 +154,7 @@ export interface ArrayType {
|
|||||||
dtype: 'array'
|
dtype: 'array'
|
||||||
elem: DataType
|
elem: DataType
|
||||||
index?: DataType
|
index?: DataType
|
||||||
|
baseoffset?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RefType {
|
export interface RefType {
|
||||||
@ -651,8 +653,18 @@ class ActionEval {
|
|||||||
let bitofs = parseInt(args[1] || '0');
|
let bitofs = parseInt(args[1] || '0');
|
||||||
return this.generateCodeForField(fieldName, bitofs, canwrite);
|
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[]) {
|
__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) {
|
if (this.entities.length == 1) {
|
||||||
return this.dialect.absolute(ident);
|
return this.dialect.absolute(ident);
|
||||||
} else {
|
} else {
|
||||||
@ -727,6 +739,7 @@ class ActionEval {
|
|||||||
// find archetypes
|
// find archetypes
|
||||||
let field = component.fields.find(f => f.name == fieldName);
|
let field = component.fields.find(f => f.name == fieldName);
|
||||||
if (field == null) throw new ECSError(`no field named "${fieldName}" in component`, action);
|
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
|
// see if all entities have the same constant value
|
||||||
// TODO: should be done somewhere else?
|
// TODO: should be done somewhere else?
|
||||||
let constValues = new Set<DataValue>();
|
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);
|
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
|
if (!range) throw new ECSError(`couldn't find field for ${component.name}:${fieldName}, maybe no entities?`); // TODO
|
||||||
// TODO: dialect
|
// TODO: dialect
|
||||||
let ident = this.dialect.fieldsymbol(component, field, bitofs);
|
|
||||||
let eidofs = qr.entities.length && qr.entities[0].id - range.elo; // TODO: negative?
|
let eidofs = qr.entities.length && qr.entities[0].id - range.elo; // TODO: negative?
|
||||||
if (baseLookup) {
|
if (baseLookup) {
|
||||||
return this.dialect.absolute(ident);
|
return this.dialect.absolute(ident);
|
||||||
@ -940,24 +952,27 @@ export class EntityScope implements SourceLocated {
|
|||||||
// is it a bounded array? (TODO)
|
// is it a bounded array? (TODO)
|
||||||
if (f.dtype == 'array' && f.index) {
|
if (f.dtype == 'array' && f.index) {
|
||||||
let datasym = this.dialect.datasymbol(c, f, e.id);
|
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 ptrlosym = this.dialect.fieldsymbol(c, f, 0);
|
||||||
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
|
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
|
||||||
let loofs = segment.allocateBytes(ptrlosym, entcount);
|
let loofs = segment.allocateBytes(ptrlosym, entcount);
|
||||||
let hiofs = segment.allocateBytes(ptrhisym, 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[loofs + e.id - range.elo] = { symbol: datasym, bitofs: 0 };
|
||||||
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
|
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this is a constant
|
// this is a constant
|
||||||
// is it a byte array?
|
// 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);
|
let datasym = this.dialect.datasymbol(c, f, e.id);
|
||||||
segment.allocateInitData(datasym, v);
|
segment.allocateInitData(datasym, v);
|
||||||
let ptrlosym = this.dialect.fieldsymbol(c, f, 0);
|
let ptrlosym = this.dialect.fieldsymbol(c, f, 0);
|
||||||
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
|
let ptrhisym = this.dialect.fieldsymbol(c, f, 8);
|
||||||
let loofs = segment.allocateBytes(ptrlosym, entcount);
|
let loofs = segment.allocateBytes(ptrlosym, entcount);
|
||||||
let hiofs = segment.allocateBytes(ptrhisym, 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[loofs + e.id - range.elo] = { symbol: datasym, bitofs: 0 };
|
||||||
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
|
segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 };
|
||||||
// TODO: } else if (v instanceof Uint16Array) {
|
// TODO: } else if (v instanceof Uint16Array) {
|
||||||
|
@ -160,6 +160,9 @@ export class Tokenizer {
|
|||||||
let tok = this.lasttoken = (this.tokens.shift() || this.eof);
|
let tok = this.lasttoken = (this.tokens.shift() || this.eof);
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
ifToken(match: string): Token | undefined {
|
||||||
|
if (this.peekToken().str == match) return this.consumeToken();
|
||||||
|
}
|
||||||
expectToken(str: string, msg?: string): Token {
|
expectToken(str: string, msg?: string): Token {
|
||||||
let tok = this.consumeToken();
|
let tok = this.consumeToken();
|
||||||
let tokstr = tok.str;
|
let tokstr = tok.str;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user