ecs: added label sources

This commit is contained in:
Steven Hugg 2022-02-27 10:58:47 -06:00
parent 6f3affaaef
commit c73263d944
3 changed files with 25 additions and 9 deletions

View File

@ -92,9 +92,11 @@ export class ECSCompiler extends Tokenizer {
}
annotate<T extends SourceLocated>(fn: () => T) {
let tok = this.peekToken();
let start = this.peekToken();
let obj = fn();
if (obj) (obj as SourceLocated).$loc = tok.$loc;
let end = this.lasttoken;
let $loc = end ? mergeLocs(start.$loc, end.$loc) : start.$loc;
if (obj) (obj as SourceLocated).$loc = $loc;
return obj;
}
@ -349,7 +351,7 @@ export class ECSCompiler extends Tokenizer {
tempbytes = this.parseIntegerConstant();
}
let system: System = { name, tempbytes, actions: [] };
let expr = this.parseBlockStatement();
let expr = this.annotate(() => this.parseBlockStatement());
let action: Action = { expr, event: name };
system.actions.push(action);
return system;
@ -363,7 +365,7 @@ export class ECSCompiler extends Tokenizer {
let critical = undefined;
if (this.ifToken('critical')) critical = true;
if (this.ifToken('fit')) fitbytes = this.parseIntegerConstant();
let expr = this.parseBlockStatement();
let expr = this.annotate(() => this.parseBlockStatement());
//query, join, select, direction,
let action : Action = { expr, event, fitbytes, critical };
return action as Action;
@ -770,6 +772,7 @@ export class ECSCompiler extends Tokenizer {
parseExprList(): Expr[] {
return this.parseList(this.parseExpr, ',');
}
// TODO: annotate with location
parseBlockStatement(): Statement {
let valtype : IntType = { dtype:'int', lo:0, hi: 0 } // TODO?
if (this.peekToken().type == ECSTokenType.CodeFragment) {
@ -778,7 +781,7 @@ export class ECSCompiler extends Tokenizer {
if (this.ifToken('begin')) {
let stmts = [];
while (this.peekToken().str != 'end') {
stmts.push(this.parseBlockStatement());
stmts.push(this.annotate(() => this.parseBlockStatement()));
}
this.expectToken('end');
return { valtype, stmts };
@ -812,7 +815,7 @@ export class ECSCompiler extends Tokenizer {
let direction = undefined;
if (modifiers['asc']) direction = 'asc';
else if (modifiers['desc']) direction = 'desc';
let body = this.parseBlockStatement();
let body = this.annotate(() => this.parseBlockStatement());
return { select, query, join, direction, stmts: [body], loop: select == 'foreach' } as QueryExpr;
}
}

View File

@ -3,8 +3,10 @@ import { Token } from "../tokenizer";
import { SourceLocated, SourceLocation } from "../workertypes";
import { Bin, Packer } from "./binpack";
export class ECSError extends Error {
export class ECSError extends Error implements SourceLocated {
$loc: SourceLocation;
$sources: SourceLocated[] = [];
constructor(msg: string, obj?: SourceLocation | SourceLocated) {
super(msg);
Object.setPrototypeOf(this, ECSError.prototype);
@ -834,7 +836,12 @@ class ActionEval {
__emit(args: string[]) {
let event = args[0];
let eventargs = args.slice(1);
return this.scope.generateCodeForEvent(event, eventargs);
try {
return this.scope.generateCodeForEvent(event, eventargs);
} catch (e) {
if (e.$sources) e.$sources.push(this.action);
throw e;
}
}
__local(args: string[]) {
let tempinc = parseInt(args[0]);
@ -1053,6 +1060,7 @@ class ActionEval {
case 'once':
// TODO: how is this different from begin/end?
//state.xreg = state.yreg = null;
//state.working = new EntitySet(scope, undefined, [], []);
break;
case 'foreach':
case 'unroll':
@ -1077,7 +1085,7 @@ class ActionEval {
if (select == 'if') {
qr.entities = []; // "if" failed
} else {
throw new ECSError(`no entities in statement`, action);
throw new ECSError(`no entities match query`, qexpr);
}
} else {
// TODO: must be a better way...

View File

@ -27,6 +27,11 @@ export function assembleECS(step: BuildStep): BuildStepResult {
} catch (e) {
if (e instanceof ECSError) {
compiler.addError(e.message, e.$loc);
for (let obj of e.$sources) {
let name = (obj as any).event;
if (name == 'start') break;
compiler.addError(`... ${name}`, obj.$loc); // TODO?
}
return { errors: compiler.errors };
} else if (e instanceof CompileError) {
return { errors: compiler.errors };