From 3d05c0ed1ae7786bde75f41eafc4491013ac66f4 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Tue, 22 Feb 2022 10:59:40 -0600 Subject: [PATCH] ecs: use name2cfpairs, fixed identity thing, test errors --- src/common/ecs/ecs.ts | 23 ++++++++++++----------- src/test/testecs.ts | 18 +++++++++++++----- test/ecs/errors1.ecs | 31 +++++++++++++++++++++++++++++++ test/ecs/errors1.txt | 1 + 4 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 test/ecs/errors1.ecs create mode 100644 test/ecs/errors1.txt diff --git a/src/common/ecs/ecs.ts b/src/common/ecs/ecs.ts index 374d11f0..530d04e3 100644 --- a/src/common/ecs/ecs.ts +++ b/src/common/ecs/ecs.ts @@ -1594,19 +1594,20 @@ export class EntityManager { } defineComponent(ctype: ComponentType) { let existing = this.components[ctype.name]; + // we can defer component definitions, just declare a component with 0 fields? if (existing && existing.fields.length > 0) throw new ECSError(`component ${ctype.name} already defined`, existing); + if (existing) { + existing.fields = ctype.fields; + ctype = existing; + } for (let field of ctype.fields) { let list = this.name2cfpairs[field.name]; if (!list) list = this.name2cfpairs[field.name] = []; list.push({ c: ctype, f: field }); } - if (existing) { - existing.fields = ctype.fields; - return existing; - } else { - return this.components[ctype.name] = ctype; - } + this.components[ctype.name] = ctype; + return ctype; } defineSystem(system: System) { let existing = this.systems[system.name]; @@ -1669,15 +1670,15 @@ export class EntityManager { return this.systems[name]; } singleComponentWithFieldName(atypes: EntityArchetype[], fieldName: string, where: SourceLocated) { - let components = this.componentsWithFieldName(atypes, fieldName); - // TODO: use name2cfpairs? - if (components.length == 0) { + let cfpairs = this.name2cfpairs[fieldName]; + let filtered = cfpairs.filter(cf => atypes.find(a => a.components.includes(cf.c))); + if (filtered.length == 0) { throw new ECSError(`cannot find component with field "${fieldName}"`, where); } - if (components.length > 1) { + if (filtered.length > 1) { throw new ECSError(`ambiguous field name "${fieldName}"`, where); } - return components[0]; + return filtered[0].c; } toJSON() { return JSON.stringify({ diff --git a/src/test/testecs.ts b/src/test/testecs.ts index bd93b72d..6936fe0c 100644 --- a/src/test/testecs.ts +++ b/src/test/testecs.ts @@ -98,11 +98,19 @@ describe('Compiler', function() { return readFileSync(testdir + path, 'utf-8'); } let code = readFileSync(ecspath, 'utf-8'); - compiler.parseFile(code, ecspath); - // TODO: errors - let out = new SourceFileExport(); - em.exportToFile(out); - let outtxt = out.toString(); + var outtxt = ''; + try { + compiler.parseFile(code, ecspath); + // TODO: errors + let out = new SourceFileExport(); + em.exportToFile(out); + outtxt = out.toString(); + } catch (e) { + outtxt = e.toString(); + console.log(e); + } + if (compiler.errors.length) + outtxt = compiler.errors.map(e => `${e.line}:${e.msg}`).join('\n'); let goodtxt = existsSync(goodpath) ? readFileSync(goodpath, 'utf-8') : ''; if (outtxt.trim() != goodtxt.trim()) { let asmpath = '/tmp/' + asmfn; diff --git a/test/ecs/errors1.ecs b/test/ecs/errors1.ecs new file mode 100644 index 00000000..b0ad8cb7 --- /dev/null +++ b/test/ecs/errors1.ecs @@ -0,0 +1,31 @@ + +component KernelSection + lines: 1..255 +end + +component BGColor + color: 0..255 +end + +component FGColor + color: 0..255 +end + +demo Main + entity [KernelSection,BGColor] + const lines = 2 + const color = $18 + end + entity [KernelSection,BGColor,FGColor] + const lines = 2 + const color = $16 + end + entity [KernelSection,FGColor] + const lines = 2 + const color = $16 + end + entity [KernelSection,FGColor] + const lines = 2 + const color = $16 + end +end diff --git a/test/ecs/errors1.txt b/test/ecs/errors1.txt new file mode 100644 index 00000000..29b87eac --- /dev/null +++ b/test/ecs/errors1.txt @@ -0,0 +1 @@ +21:I found more than one field named "color" for this entity. \ No newline at end of file