/**
* This file describes the interface between compilation time
* and runtime.
*
* # Locators
*
* Compile time and runtime must share the same Locator. A Locator is an
* object that describes the location of a template, and is roughly a
* module name. The compiler and runtime may use the Locator to locally
* resolve names relative to the template the name was found in, but must
* share resolution rules between compilation time and runtime.
*
* For example, given this template with Locator
* `{ module: 'components/Articles/Container' }:
*
* ```
*
* ```
*
* The compiler may resolve `` to `components/Articles/TabBar`. The
* important thing is that the compiler and runtime share resolution rules.
*
* # CompileTimeLookup
*
* When compiling an application, the `CompileTimeLookup` is responsible
* for resolving helpers, modifiers, components, and partials into "handles"
* (numbers) that can be embedded into the program and used at runtime.
*
* # RuntimeResolver
*
* The `RuntimeResolver` has two responsibilities.
*
* 1. To turn handles created by the `CompileTimeLookup` into live helpers,
* modifiers, components, and partials.
* 2. To resolve dynamic components and partials at runtime that come from
* calls to `{{component dynamic}}` or `{{partial dynamic}}`.
*
* The `CompileTimeLookup` and `RuntimeResolver` must maintain symmetry
* between:
*
* * `resolver.resolve(lookup.lookupComponentDefinition(name, referrer))`; and
* * `resolver.lookupComponentDefinition(name, referrer))`
*
* And between:
*
* * `resolver.resolve(lookup.lookupPartial(name, referrer))`; and
* * `resolver.lookupPartial(name, referrer))`
*
* # Coupling
*
* In practice, the `CompileTimeLookup` and `RuntimeResolver` are two parts
* of one system. The goal of this system is to allow the `CompileTimeLookup`
* to do as much resolution as possible ahead of time, while still allowing
* the `RuntimeResolver` to do dynamic resolution when necessary.
*/
import { Option } from './core';
import { ProgramSymbolTable } from './tier1/symbol-table';
import { ComponentDefinitionState, ComponentInstanceState } from './components';
import { CompilableProgram, Template, HandleResult } from './template';
import { CompileTimeCompilationContext } from './program';
import { Owner, ModifierDefinitionState, HelperDefinitionState } from './runtime';
import { InternalComponentCapability, InternalComponentManager } from './managers';
export interface CompileTimeComponent {
handle: number;
capabilities: InternalComponentCapability;
compilable: Option;
}
export interface ResolvedComponentDefinition<
D = ComponentDefinitionState,
I = ComponentInstanceState,
M extends InternalComponentManager = InternalComponentManager
> {
state: D;
manager: M;
template: Template | null;
}
export const enum ResolverContext {
Component,
Modifier,
Helper,
HelperOrComponent,
}
export interface CompileTimeResolver {
lookupHelper(name: string, owner: O): Option;
lookupModifier(name: string, owner: O): Option;
lookupComponent(name: string, owner: O): Option;
lookupPartial(name: string, owner: O): Option;
// TODO: These are used to lookup keywords that are implemented as helpers/modifiers.
// We should try to figure out a cleaner way to do this.
lookupBuiltInHelper(name: string): Option;
lookupBuiltInModifier(name: string): Option;
}
export interface PartialDefinition {
name: string; // for debugging
getPartial(
context: CompileTimeCompilationContext
): { symbolTable: ProgramSymbolTable; handle: HandleResult };
}
export interface RuntimeResolver {
lookupComponent(name: string, owner: O): Option;
lookupPartial(name: string, owner: O): Option;
}