Refactor resolve infrastructure to its own file

This has become a little clumsy over time. Doesn't hurt to have it in its own place to get a grasp of it more easily.
This commit is contained in:
dcodeIO 2018-07-13 00:22:22 +02:00
parent 585d246165
commit cd14b296ce
6 changed files with 1314 additions and 1064 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2794,7 +2794,7 @@ export function compileAllocate(
return module.createUnreachable();
}
var allocateInstance = (<FunctionPrototype>allocatePrototype).resolve(); // reports
var allocateInstance = compiler.resolver.resolveFunction(<FunctionPrototype>allocatePrototype, null);
if (!(allocateInstance && compiler.compileFunction(allocateInstance))) return module.createUnreachable();
compiler.currentType = classInstance.type;
@ -2825,7 +2825,7 @@ export function compileAbort(
var abortPrototype = program.elementsLookup.get(abortInternalName); // might be intended
if (!abortPrototype || abortPrototype.kind != ElementKind.FUNCTION_PROTOTYPE) return module.createUnreachable();
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
var abortInstance = compiler.resolver.resolveFunction(<FunctionPrototype>abortPrototype, null);
if (!(abortInstance && compiler.compileFunction(abortInstance))) return module.createUnreachable();
var messageArg = message != null

View File

@ -73,6 +73,10 @@ import {
DecoratorFlags
} from "./program";
import {
Resolver
} from "./resolver";
import {
Token,
operatorTokenToString
@ -250,6 +254,8 @@ export class Compiler extends DiagnosticEmitter {
/** Program reference. */
program: Program;
/** Resolver reference. */
resolver: Resolver;
/** Provided options. */
options: Options;
/** Module instance being compiled. */
@ -288,6 +294,7 @@ export class Compiler extends DiagnosticEmitter {
constructor(program: Program, options: Options | null = null) {
super(program.diagnostics);
this.program = program;
this.resolver = program.resolver;
if (!options) options = new Options();
this.options = options;
this.memoryOffset = i64_new(
@ -430,7 +437,7 @@ export class Compiler extends DiagnosticEmitter {
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
!(<ClassDeclaration>statement).isGeneric
) {
this.compileClassDeclaration(<ClassDeclaration>statement, []);
this.compileClassDeclaration(<ClassDeclaration>statement, [], null);
}
break;
}
@ -514,7 +521,7 @@ export class Compiler extends DiagnosticEmitter {
// resolve now if annotated
if (declaration.type) {
let resolvedType = this.program.resolveType(declaration.type); // reports
let resolvedType = this.resolver.resolveType(declaration.type); // reports
if (!resolvedType) return false;
if (resolvedType == Type.void) {
this.error(
@ -827,7 +834,8 @@ export class Compiler extends DiagnosticEmitter {
outerScope: Flow | null,
reportNode: Node
): Function | null {
var instance = prototype.resolveUsingTypeArguments( // reports
var instance = this.resolver.resolveFunctionInclTypeArguments(
prototype,
typeArguments,
contextualTypeArguments,
reportNode
@ -1203,8 +1211,7 @@ export class Compiler extends DiagnosticEmitter {
compileClassDeclaration(
declaration: ClassDeclaration,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null = null,
alternativeReportNode: Node | null = null
contextualTypeArguments: Map<string,Type> | null = null
): void {
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
@ -1212,7 +1219,7 @@ export class Compiler extends DiagnosticEmitter {
<ClassPrototype>element,
typeArguments,
contextualTypeArguments,
alternativeReportNode
declaration
);
}
@ -1222,10 +1229,11 @@ export class Compiler extends DiagnosticEmitter {
contextualTypeArguments: Map<string,Type> | null = null,
alternativeReportNode: Node | null = null
): void {
var instance = prototype.resolveUsingTypeArguments( // reports
var instance = this.resolver.resolveClassInclTypeArguments(
prototype,
typeArguments,
contextualTypeArguments,
alternativeReportNode
alternativeReportNode || prototype.declaration
);
if (!instance) return;
this.compileClass(instance);
@ -2002,13 +2010,14 @@ export class Compiler extends DiagnosticEmitter {
// other variables become locals
var initializers = new Array<ExpressionRef>();
var flow = this.currentFunction.flow;
var resolver = this.resolver;
for (let i = 0; i < numDeclarations; ++i) {
let declaration = declarations[i];
let name = declaration.name.text;
let type: Type | null = null;
let initExpr: ExpressionRef = 0;
if (declaration.type) {
type = program.resolveType( // reports
type = resolver.resolveType( // reports
declaration.type,
flow.contextualTypeArguments
);
@ -2609,7 +2618,7 @@ export class Compiler extends DiagnosticEmitter {
}
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): ExpressionRef {
var toType = this.program.resolveType( // reports
var toType = this.resolver.resolveType( // reports
expression.toType,
this.currentFunction.flow.contextualTypeArguments
);
@ -3585,7 +3594,7 @@ export class Compiler extends DiagnosticEmitter {
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32PowInstance = instance = (<FunctionPrototype>prototype).resolve();
this.f32PowInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
// Math.pow otherwise (result is f64)
@ -3627,7 +3636,7 @@ export class Compiler extends DiagnosticEmitter {
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64PowInstance = instance = (<FunctionPrototype>prototype).resolve();
this.f64PowInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
}
if (!(instance && this.compileFunction(instance))) {
@ -3877,7 +3886,7 @@ export class Compiler extends DiagnosticEmitter {
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32ModInstance = instance = (<FunctionPrototype>prototype).resolve();
this.f32ModInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
if (!(instance && this.compileFunction(instance))) {
expr = module.createUnreachable();
@ -3908,7 +3917,7 @@ export class Compiler extends DiagnosticEmitter {
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64ModInstance = instance = (<FunctionPrototype>prototype).resolve();
this.f64ModInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
if (!(instance && this.compileFunction(instance))) {
expr = module.createUnreachable();
@ -4577,8 +4586,9 @@ export class Compiler extends DiagnosticEmitter {
compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
var program = this.program;
var resolver = program.resolver;
var currentFunction = this.currentFunction;
var target = program.resolveExpression(expression, currentFunction); // reports
var target = resolver.resolveExpression(expression, currentFunction); // reports
if (!target) return this.module.createUnreachable();
// to compile just the value, we need to know the target's type
@ -4597,9 +4607,9 @@ export class Compiler extends DiagnosticEmitter {
break;
}
case ElementKind.PROPERTY: {
let prototype = (<Property>target).setterPrototype;
if (prototype) {
let instance = prototype.resolve(); // reports
let setterPrototype = (<Property>target).setterPrototype;
if (setterPrototype) {
let instance = this.resolver.resolveFunction(setterPrototype, null);
if (!instance) return this.module.createUnreachable();
assert(instance.signature.parameterTypes.length == 1); // parser must guarantee this
targetType = instance.signature.parameterTypes[0];
@ -4612,7 +4622,7 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable();
}
case ElementKind.CLASS: {
if (program.resolvedElementExpression) { // indexed access
if (resolver.resolvedElementExpression) { // indexed access
let isUnchecked = currentFunction.flow.is(FlowFlags.UNCHECKED_CONTEXT);
let indexedSet = (<Class>target).lookupOverload(OperatorKind.INDEXED_SET, isUnchecked);
if (!indexedSet) {
@ -4661,7 +4671,7 @@ export class Compiler extends DiagnosticEmitter {
tee: bool = false
): ExpressionRef {
var module = this.module;
var target = this.program.resolveExpression(expression, this.currentFunction); // reports
var target = this.resolver.resolveExpression(expression, this.currentFunction); // reports
if (!target) return module.createUnreachable();
switch (target.kind) {
@ -4725,7 +4735,7 @@ export class Compiler extends DiagnosticEmitter {
);
return module.createUnreachable();
}
let thisExpression = assert(this.program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,
@ -4771,13 +4781,13 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.PROPERTY: {
let setterPrototype = (<Property>target).setterPrototype;
if (setterPrototype) {
let setterInstance = setterPrototype.resolve(); // reports
let setterInstance = this.resolver.resolveFunction(setterPrototype, null);
if (!setterInstance) return module.createUnreachable();
// call just the setter if the return value isn't of interest
if (!tee) {
if (setterInstance.is(CommonFlags.INSTANCE)) {
let thisExpression = assert(this.program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,
@ -4792,12 +4802,12 @@ export class Compiler extends DiagnosticEmitter {
// otherwise call the setter first, then the getter
let getterPrototype = (<Property>target).getterPrototype;
assert(getterPrototype != null); // must have one if there is a setter
let getterInstance = (<FunctionPrototype>getterPrototype).resolve(); // reports
let getterInstance = this.resolver.resolveFunction(<FunctionPrototype>getterPrototype, null);
if (!getterInstance) return module.createUnreachable();
let returnType = getterInstance.signature.returnType;
let nativeReturnType = returnType.toNativeType();
if (setterInstance.is(CommonFlags.INSTANCE)) {
let thisExpression = assert(this.program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,
@ -4830,7 +4840,7 @@ export class Compiler extends DiagnosticEmitter {
return module.createUnreachable();
}
case ElementKind.CLASS: {
let elementExpression = this.program.resolvedElementExpression;
let elementExpression = this.resolver.resolvedElementExpression;
if (elementExpression) {
let isUnchecked = this.currentFunction.flow.is(FlowFlags.UNCHECKED_CONTEXT);
let indexedGet = (<Class>target).lookupOverload(OperatorKind.INDEXED_GET, isUnchecked);
@ -4851,7 +4861,7 @@ export class Compiler extends DiagnosticEmitter {
return module.createUnreachable();
}
let targetType = (<Class>target).type;
let thisExpression = assert(this.program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,
@ -4901,7 +4911,7 @@ export class Compiler extends DiagnosticEmitter {
compileCallExpression(expression: CallExpression, contextualType: Type): ExpressionRef {
var module = this.module;
var currentFunction = this.currentFunction;
var target = this.program.resolveExpression(expression.expression, currentFunction); // reports
var target = this.resolver.resolveExpression(expression.expression, currentFunction); // reports
if (!target) return module.createUnreachable();
var signature: Signature | null;
@ -4929,7 +4939,8 @@ export class Compiler extends DiagnosticEmitter {
);
return module.createUnreachable();
}
instance = prototype.resolveUsingTypeArguments( // reports
instance = this.resolver.resolveFunctionInclTypeArguments(
prototype,
typeArguments,
this.currentFunction.flow.contextualTypeArguments,
expression
@ -4984,10 +4995,9 @@ export class Compiler extends DiagnosticEmitter {
}
inferredTypes.set(name, inferredType);
} else {
let concreteType = this.program.resolveType(
let concreteType = this.resolver.resolveType(
parameterTypes[i].type,
this.currentFunction.flow.contextualTypeArguments,
true
this.currentFunction.flow.contextualTypeArguments
);
if (!concreteType) return module.createUnreachable();
argumentExprs[i] = this.compileExpression(
@ -5003,7 +5013,8 @@ export class Compiler extends DiagnosticEmitter {
let inferredType = assert(inferredTypes.get(typeParameters[i].name.text)); // TODO
resolvedTypeArguments[i] = inferredType;
}
instance = prototype.resolve(
instance = this.resolver.resolveFunction(
prototype,
resolvedTypeArguments,
this.currentFunction.flow.contextualTypeArguments
);
@ -5015,7 +5026,8 @@ export class Compiler extends DiagnosticEmitter {
// otherwise resolve the non-generic call as usual
} else {
instance = prototype.resolve(
instance = this.resolver.resolveFunction(
prototype,
null,
this.currentFunction.flow.contextualTypeArguments
);
@ -5026,7 +5038,7 @@ export class Compiler extends DiagnosticEmitter {
let thisExpr: ExpressionRef = 0;
if (instance.is(CommonFlags.INSTANCE)) {
thisExpr = this.compileExpressionRetainType(
assert(this.program.resolvedThisExpression),
assert(this.resolver.resolvedThisExpression),
this.options.usizeType,
WrapMode.NONE
);
@ -5069,7 +5081,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.FIELD: {
let type = (<Field>target).type;
if (signature = type.signatureReference) {
let thisExpression = assert(this.program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,
@ -5125,13 +5137,31 @@ export class Compiler extends DiagnosticEmitter {
expression: CallExpression,
contextualType: Type
): ExpressionRef {
var expr = compileBuiltinCall( // reports
var typeArguments: Type[] | null = null;
// builtins handle omitted type arguments on their own. if present, however, resolve them here
// and pass them to the builtin, even if it's still up to the builtin how to handle them.
var typeArgumentNodes = expression.typeArguments;
if (expression.typeArguments) {
if (!prototype.is(CommonFlags.GENERIC)) {
this.error(
DiagnosticCode.Type_0_is_not_generic,
expression.range, prototype.internalName
);
}
typeArguments = this.resolver.resolveTypeArguments(
assert(prototype.declaration.typeParameters),
typeArgumentNodes,
this.currentFunction.flow.contextualTypeArguments,
expression
);
}
// now compile the builtin, which usually returns a block of code that replaces the call.
var expr = compileBuiltinCall(
this,
prototype,
prototype.resolveBuiltinTypeArguments(
expression.typeArguments,
this.currentFunction.flow.contextualTypeArguments
),
typeArguments,
expression.arguments,
contextualType,
expression
@ -5733,7 +5763,7 @@ export class Compiler extends DiagnosticEmitter {
}
compileElementAccessExpression(expression: ElementAccessExpression, contextualType: Type): ExpressionRef {
var target = this.program.resolveElementAccess(expression, this.currentFunction); // reports
var target = this.resolver.resolveElementAccess(expression, this.currentFunction); // reports
if (!target) return this.module.createUnreachable();
switch (target.kind) {
case ElementKind.CLASS: {
@ -5895,7 +5925,7 @@ export class Compiler extends DiagnosticEmitter {
}
// otherwise resolve
var target = this.program.resolveIdentifier( // reports
var target = this.resolver.resolveIdentifier( // reports
expression,
this.currentEnum || currentFunction
);
@ -5940,7 +5970,8 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createGetGlobal((<EnumValue>target).internalName, NativeType.I32);
}
case ElementKind.FUNCTION_PROTOTYPE: {
let instance = (<FunctionPrototype>target).resolve(
let instance = this.resolver.resolveFunction(
<FunctionPrototype>target,
null,
currentFunction.flow.contextualTypeArguments
);
@ -5967,7 +5998,7 @@ export class Compiler extends DiagnosticEmitter {
// possible in AS anyway.
var expr = this.compileExpressionRetainType(expression.expression, this.options.usizeType, WrapMode.NONE);
var type = this.currentType;
var isType = this.program.resolveType(expression.isType);
var isType = this.resolver.resolveType(expression.isType);
this.currentType = Type.bool;
if (!isType) return module.createUnreachable();
return type.is(TypeFlags.NULLABLE) && !isType.is(TypeFlags.NULLABLE)
@ -6161,7 +6192,7 @@ export class Compiler extends DiagnosticEmitter {
// obtain the array type
var arrayPrototype = assert(this.program.arrayPrototype);
if (!arrayPrototype || arrayPrototype.kind != ElementKind.CLASS_PROTOTYPE) return module.createUnreachable();
var arrayInstance = (<ClassPrototype>arrayPrototype).resolve([ elementType ]);
var arrayInstance = this.resolver.resolveClass(<ClassPrototype>arrayPrototype, [ elementType ]);
if (!arrayInstance) return module.createUnreachable();
var arrayType = arrayInstance.type;
@ -6367,7 +6398,7 @@ export class Compiler extends DiagnosticEmitter {
var currentFunction = this.currentFunction;
// obtain the class being instantiated
var target = this.program.resolveExpression( // reports
var target = this.resolver.resolveExpression( // reports
expression.expression,
currentFunction
);
@ -6388,12 +6419,14 @@ export class Compiler extends DiagnosticEmitter {
(classReference = contextualType.classReference) !== null &&
classReference.is(CommonFlags.GENERIC)
) {
classInstance = classPrototype.resolve(
classInstance = this.resolver.resolveClass(
classPrototype,
classReference.typeArguments,
currentFunction.flow.contextualTypeArguments
);
} else {
classInstance = classPrototype.resolveUsingTypeArguments( // reports
classInstance = this.resolver.resolveClassInclTypeArguments(
classPrototype,
typeArguments,
currentFunction.flow.contextualTypeArguments,
expression
@ -6448,10 +6481,9 @@ export class Compiler extends DiagnosticEmitter {
contextualType: Type,
retainConstantType: bool
): ExpressionRef {
var program = this.program;
var module = this.module;
var target = program.resolvePropertyAccess(propertyAccess, this.currentFunction); // reports
var target = this.resolver.resolvePropertyAccess(propertyAccess, this.currentFunction); // reports
if (!target) return module.createUnreachable();
switch (target.kind) {
@ -6480,7 +6512,7 @@ export class Compiler extends DiagnosticEmitter {
return module.createGetGlobal((<EnumValue>target).internalName, NativeType.I32);
}
case ElementKind.FIELD: { // instance field
let thisExpression = assert(program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
assert((<Field>target).memoryOffset >= 0);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
@ -6499,7 +6531,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.PROPERTY: { // instance property (here: getter)
let prototype = (<Property>target).getterPrototype;
if (prototype) {
let instance = prototype.resolve(null); // reports
let instance = this.resolver.resolveFunction(prototype, null);
if (!instance) return module.createUnreachable();
let signature = instance.signature;
if (!this.checkCallSignature( // reports
@ -6514,7 +6546,7 @@ export class Compiler extends DiagnosticEmitter {
if (instance.is(CommonFlags.INSTANCE)) {
let parent = assert(instance.parent);
assert(parent.kind == ElementKind.CLASS);
let thisExpression = assert(program.resolvedThisExpression);
let thisExpression = assert(this.resolver.resolvedThisExpression);
let thisExpr = this.compileExpressionRetainType(
thisExpression,
this.options.usizeType,

File diff suppressed because it is too large Load Diff

1168
src/resolver.ts Normal file

File diff suppressed because it is too large Load Diff