Introduce "special" query kind

master
Paul Loyd 2017-11-28 20:21:50 +03:00
parent c843463c0e
commit 9941cbf380
4 changed files with 41 additions and 17 deletions

View File

@ -86,8 +86,10 @@ export default class Collector {
// TODO: warning.
invariant(result.kind !== 'unknown');
// Resulting scope is always the best choice for waiting.
scope = result.scope;
if (result.kind !== 'special') {
// Resulting scope is always the best choice for waiting.
scope = result.scope;
}
// It's only valid the sequence: E*[CT]?F,
// where E - external, C - declaration, T - template, F - definition.
@ -141,6 +143,13 @@ export default class Collector {
// Fallthrough.
case 'definition':
return result.type;
case 'special':
const type = result.call(params);
invariant(type);
return type;
}
invariant(false);

View File

@ -1,7 +1,8 @@
export default [
{
id: ['Buffer'],
kind: 'record',
fields: [],
export default {
Buffer() {
return {
kind: 'reference',
to: ["Buffer"],
};
},
];
}

View File

@ -8,7 +8,8 @@ export type Query =
| Declaration
| Template
| Definition
| External;
| External
| Special;
export type Unknown = {
kind: 'unknown',
@ -42,6 +43,13 @@ export type External = {
scope: Scope,
};
export type Special = {
kind: 'special',
call: SpecialFn,
};
export type SpecialFn = (?Type)[] => ?Type;
export type TemplateParam = {
name: string,
value: ?Type,

View File

@ -4,7 +4,7 @@ import type {Node} from '@babel/types';
import {invariant, last} from './utils';
import type Module from './module';
import type {Type, TypeId} from './types';
import type {Query, Template, TemplateParam, ExternalInfo} from './query';
import type {Query, Template, TemplateParam, ExternalInfo, SpecialFn} from './query';
export default class Scope {
+id: TypeId;
@ -12,16 +12,13 @@ export default class Scope {
+module: ?Module;
_entries: Map<string, Query>;
static global(types: Type[]) {
static global(specials: {[string]: SpecialFn}) {
const global = new Scope(null, null);
for (const type of types) {
invariant(type.id);
for (const name in specials) {
const fn = specials[name];
const name = last(type.id);
invariant(name != null);
global.addDefinition(name, type, false);
global.addSpecial(name, fn);
}
return global;
@ -38,6 +35,15 @@ export default class Scope {
return new Scope(this, module || this.module);
}
addSpecial(name: string, fn: SpecialFn) {
invariant(!this._entries.has(name));
this._entries.set(name, {
kind: 'special',
call: fn,
});
}
addDeclaration(name: string, node: Node, params: TemplateParam[]) {
invariant(!this._entries.has(name));