refactor: remove half baked context typing

This commit is contained in:
cha0s 2019-09-08 01:15:17 -05:00
parent f07ba70dd5
commit a062a3fe51
5 changed files with 21 additions and 262 deletions

View File

@ -1,6 +1,5 @@
import {TickingPromise} from '@avocado/core';
import {register as registerType} from './types/registry';
import {Traversal} from '../item/traversal';
export class Globals {
@ -59,85 +58,3 @@ export class Globals {
}
}
// Globals.
registerType('globals', {
label: 'Globals',
children: {
log: {
type: {
key: 'function',
args: [
{
type: 'any',
label: 'Thing to log',
},
],
return: {
type: 'void',
},
},
label: 'Log to console',
},
randomNumber: {
type: {
key: 'function',
args: [
{
type: {
key: 'number',
},
label: 'Minimum value',
advanced: true,
},
{
type: 'number',
label: 'Maximum value',
},
{
type: 'boolean',
label: 'Convert to an integer?',
default: true,
},
],
return: {
type: 'number',
},
},
label: 'Random number',
},
test: {
type: {
key: 'function',
args: [
{
type: 'number',
label: 'Milliseconds to wait',
},
],
return: {
type: {
key: 'entity',
traits: ['mobile'],
},
},
},
label: 'Entityyyyy',
},
waitMs: {
type: {
key: 'function',
args: [
{
type: 'number',
label: 'Milliseconds to wait',
},
],
return: {
type: 'void',
},
},
label: 'Wait for a specified time',
},
},
});

View File

@ -5,7 +5,6 @@ import {Rectangle, Vector} from '@avocado/math';
import {Globals} from './globals';
import {TraversalCompiler} from './traversal-compiler';
import {TypeMap} from './types';
const compiled = new Map();
const debug = D('@avocado:behavior:context');
@ -38,9 +37,26 @@ class Context extends Map {
super.clear();
}
renderStepsUntilNow(steps, step) {
static renderSteps(steps) {
return steps.reduce((rendered, step) => {
switch (step.type) {
case 'key':
if (rendered) {
rendered += '.';
}
rendered += step.key;
break;
case 'invoke':
rendered += `(${step.args.length > 0 ? '...' : ''})`;
break;
}
return rendered;
}, '');
}
static renderStepsUntilNow(steps, step) {
const stepsUntilNow = steps.slice(0, steps.indexOf(step));
return TypeMap.renderSteps(stepsUntilNow);
return this.renderSteps(stepsUntilNow);
}
takeStep(value, fn) {
@ -81,7 +97,7 @@ class Context extends Map {
traverseOneStep(steps, previousNode, node, step) {
if ('undefined' === typeof node) {
const rendered = this.renderStepsUntilNow(steps, step);
const rendered = this.constructor.renderStepsUntilNow(steps, step);
debug(`"${rendered}" is traversed through but undefined`);
return;
}
@ -125,7 +141,7 @@ class Context extends Map {
case 'key':
return node[step.key] = value.get(this);
case 'invoke':
const rendered = this.renderStepsUntilNow(steps, step);
const rendered = this.constructor.renderStepsUntilNow(steps, step);
debug(`invalid assignment to function "${rendered}"`);
return;
}

View File

@ -1,143 +0,0 @@
import {get, register} from './registry';
export class TypeMap {
static normalizeSpec(type) {
if ('string' === typeof type) {
type = {key: type};
}
return {...get(type.key), type};
}
static renderSteps(steps) {
return steps.reduce((rendered, step) => {
switch (step.type) {
case 'key':
if (rendered) {
rendered += '.';
}
rendered += step.key;
break;
case 'invoke':
rendered += `(${step.args.length > 0 ? '...' : ''})`;
break;
}
return rendered;
}, '');
}
constructor(types) {
this.types = types;
}
get(matchType, options = {}) {
options = {
doIncludeAdvanced: false,
onlyWritable: false,
...options
};
const result = {};
const typeMap = {};
for (const key in this.types) {
const spec = TypeMap.normalizeSpec(this.types[key])
this.pushSpec(typeMap, options, spec, key, []);
}
for (const type in typeMap) {
const spec = TypeMap.normalizeSpec(type);
const doesMatch = (
'any' === matchType
|| type === matchType
|| spec.matcher(matchType)
);
if (doesMatch) {
result[type] = typeMap[type];
}
}
return result;
}
pushSpec(typeMap, options, spec, key, steps) {
steps = [...steps, {type: 'key', key}];
this.pushTypeSteps(typeMap, options, spec, steps);
if (spec.children) {
this.pushSpecChildren(typeMap, options, spec.children, steps, spec);
}
spec.extraSteps(spec).forEach(({spec, steps: extraSteps}) => {
extraSteps = [...steps, ...extraSteps];
this.pushTypeSteps(typeMap, options, spec, extraSteps);
if (spec.children) {
this.pushSpecChildren(typeMap, options, spec.children, extraSteps, spec);
}
});
}
pushSpecChildren(typeMap, options, children, steps, spec) {
children = 'function' === typeof children ? children(spec) : children;
for (const childKey in children) {
const child = children[childKey];
const spec = TypeMap.normalizeSpec(child.type);
const compoundChild = {...spec, ...child};
if (compoundChild.advanced && !options.doIncludeAdvanced) {
continue;
}
this.pushSpec(typeMap, options, compoundChild, childKey, steps);
}
}
pushTypeSteps(typeMap, options, spec, steps) {
const {isWritable} = spec;
if (options.onlyWritable && !isWritable) {
return;
}
const {type: {key}} = spec;
typeMap[key] = typeMap[key] || [];
typeMap[key].push(steps);
}
}
// Defaults...
register('boolean', {
label: 'A boolean value, either true or false',
});
register('function', {
label: 'A function',
children: {
name: {
advanced: true,
type: 'string',
label: 'Function name',
},
},
valueMap: {
invoke: (value, step) => {
return value(...step.args);
},
},
extraSteps: (spec) => {
const returnSpec = TypeMap.normalizeSpec(spec.type.return.type);
return [{
spec: {
...returnSpec,
...spec.type.return,
type: returnSpec.type,
},
steps: [{
type: 'invoke',
args: spec.type.args,
}],
}];
}
});
register('number', {
label: 'A numeric value',
});
register('object', {
label: 'An object',
});
register('string', {
label: 'A string of text',
});
register('void', {
label: 'An undefined or unspecified value',
});

View File

@ -1,26 +0,0 @@
const _types = new Map();
export function get(type) {
return _types.get(type);
}
export function register(type, info) {
info = {
advanced: false,
children: [],
extraSteps: (spec) => {
return [];
},
isWritable: false,
matcher: (matchType) => {
return false;
},
type,
...info,
};
info.valueMap = {
identity: (value, step) => { return value },
...info.valueMap,
}
_types.set(type, info);
}

View File

@ -1,9 +1,4 @@
export {createContext} from './context';
export {TypeMap} from './context/types';
export {
get as getType,
register as registerType
} from './context/types/registry';
export {
fromJSON as behaviorItemFromJSON,
register as registerBehaviorItem