Skip to content

Commit 7322bfc

Browse files
authored
chore: refactor builtin type resolving to builtins.ts (#2951)
1 parent ade022e commit 7322bfc

File tree

2 files changed

+167
-142
lines changed

2 files changed

+167
-142
lines changed

src/builtins.ts

Lines changed: 158 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ import {
4343
NodeKind,
4444
LiteralExpression,
4545
ArrayLiteralExpression,
46-
IdentifierExpression
46+
IdentifierExpression,
47+
NamedTypeNode
4748
} from "./ast";
4849

4950
import {
@@ -85,7 +86,9 @@ import {
8586
DecoratorFlags,
8687
Class,
8788
PropertyPrototype,
88-
VariableLikeElement
89+
VariableLikeElement,
90+
Element,
91+
OperatorKind
8992
} from "./program";
9093

9194
import {
@@ -94,11 +97,13 @@ import {
9497
} from "./flow";
9598

9699
import {
97-
ReportMode
100+
ReportMode,
101+
Resolver
98102
} from "./resolver";
99103

100104
import {
101105
CommonFlags,
106+
CommonNames,
102107
Feature,
103108
featureToString,
104109
TypeinfoFlags
@@ -768,6 +773,17 @@ export namespace BuiltinNames {
768773
export const Object = "~lib/object/Object";
769774
}
770775

776+
/** Builtin types context. */
777+
export class BuiltinTypesContext {
778+
constructor(
779+
public resolver: Resolver,
780+
public node: NamedTypeNode,
781+
public ctxElement: Element,
782+
public ctxTypes: Map<string, Type> | null,
783+
public reportMode: ReportMode
784+
) {}
785+
}
786+
771787
/** Builtin variable compilation context. */
772788
export class BuiltinVariableContext {
773789
constructor(
@@ -804,13 +820,152 @@ export class BuiltinFunctionContext {
804820
) {}
805821
}
806822

823+
/** Builtin types map. */
824+
export const builtinTypes = new Map<string, (ctx: BuiltinTypesContext) => Type | null>();
825+
807826
/** Builtin functions map. */
808827
export const builtinFunctions = new Map<string, (ctx: BuiltinFunctionContext) => ExpressionRef>();
809828

810829
/** Builtin variables map. */
811830
export const builtinVariables_onCompile = new Map<string, (ctx: BuiltinVariableContext) => void>();
812831
export const builtinVariables_onAccess = new Map<string, (ctx: BuiltinVariableContext) => ExpressionRef>();
813832

833+
// === Builtin Types ==========================================================================
834+
function builtin_resolveNativeType(ctx: BuiltinTypesContext): Type | null {
835+
let resolver = ctx.resolver;
836+
let node = ctx.node;
837+
let ctxElement = ctx.ctxElement;
838+
let ctxTypes = ctx.ctxTypes;
839+
let reportMode = ctx.reportMode;
840+
const typeArgumentNode = resolver.ensureOneTypeArgument(node, reportMode);
841+
if (!typeArgumentNode) return null;
842+
let typeArgument = resolver.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
843+
if (!typeArgument) return null;
844+
switch (typeArgument.kind) {
845+
case TypeKind.I8:
846+
case TypeKind.I16:
847+
case TypeKind.I32: return Type.i32;
848+
case TypeKind.Isize: if (!resolver.program.options.isWasm64) return Type.i32;
849+
case TypeKind.I64: return Type.i64;
850+
case TypeKind.U8:
851+
case TypeKind.U16:
852+
case TypeKind.U32:
853+
case TypeKind.Bool: return Type.u32;
854+
case TypeKind.Usize: if (!resolver.program.options.isWasm64) return Type.u32;
855+
case TypeKind.U64: return Type.u64;
856+
case TypeKind.F32: return Type.f32;
857+
case TypeKind.F64: return Type.f64;
858+
case TypeKind.V128: return Type.v128;
859+
case TypeKind.Void: return Type.void;
860+
default: assert(false);
861+
}
862+
return null;
863+
}
864+
builtinTypes.set(CommonNames.native, builtin_resolveNativeType);
865+
866+
function builtin_resolveIndexOfType(ctx: BuiltinTypesContext): Type | null {
867+
let resolver = ctx.resolver;
868+
let node = ctx.node;
869+
let ctxElement = ctx.ctxElement;
870+
let ctxTypes = ctx.ctxTypes;
871+
let reportMode = ctx.reportMode;
872+
const typeArgumentNode = resolver.ensureOneTypeArgument(node, reportMode);
873+
if (!typeArgumentNode) return null;
874+
let typeArgument = resolver.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
875+
if (!typeArgument) return null;
876+
let classReference = typeArgument.classReference;
877+
if (!classReference) {
878+
if (reportMode == ReportMode.Report) {
879+
resolver.error(
880+
DiagnosticCode.Index_signature_is_missing_in_type_0,
881+
typeArgumentNode.range, typeArgument.toString()
882+
);
883+
}
884+
return null;
885+
}
886+
let overload = classReference.lookupOverload(OperatorKind.IndexedGet);
887+
if (overload) {
888+
let parameterTypes = overload.signature.parameterTypes;
889+
if (overload.is(CommonFlags.Static)) {
890+
assert(parameterTypes.length == 2);
891+
return parameterTypes[1];
892+
} else {
893+
assert(parameterTypes.length == 1);
894+
return parameterTypes[0];
895+
}
896+
}
897+
if (reportMode == ReportMode.Report) {
898+
resolver.error(
899+
DiagnosticCode.Index_signature_is_missing_in_type_0,
900+
typeArgumentNode.range, typeArgument.toString()
901+
);
902+
}
903+
return null;
904+
}
905+
builtinTypes.set(CommonNames.indexof, builtin_resolveIndexOfType);
906+
907+
function builtin_resolveValueOfType(ctx: BuiltinTypesContext): Type | null {
908+
let resolver = ctx.resolver;
909+
let node = ctx.node;
910+
let ctxElement = ctx.ctxElement;
911+
let ctxTypes = ctx.ctxTypes;
912+
let reportMode = ctx.reportMode;
913+
const typeArgumentNode = resolver.ensureOneTypeArgument(node, reportMode);
914+
if (!typeArgumentNode) return null;
915+
let typeArgument = resolver.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
916+
if (!typeArgument) return null;
917+
let classReference = typeArgument.getClassOrWrapper(resolver.program);
918+
if (classReference) {
919+
let overload = classReference.lookupOverload(OperatorKind.IndexedGet);
920+
if (overload) return overload.signature.returnType;
921+
}
922+
if (reportMode == ReportMode.Report) {
923+
resolver.error(
924+
DiagnosticCode.Index_signature_is_missing_in_type_0,
925+
typeArgumentNode.range, typeArgument.toString()
926+
);
927+
}
928+
return null;
929+
}
930+
builtinTypes.set(CommonNames.valueof, builtin_resolveValueOfType);
931+
932+
function builtin_resolveReturnOfType(ctx: BuiltinTypesContext): Type | null {
933+
let resolver = ctx.resolver;
934+
let node = ctx.node;
935+
let ctxElement = ctx.ctxElement;
936+
let ctxTypes = ctx.ctxTypes;
937+
let reportMode = ctx.reportMode;
938+
const typeArgumentNode = resolver.ensureOneTypeArgument(node, reportMode);
939+
if (!typeArgumentNode) return null;
940+
let typeArgument = resolver.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
941+
if (!typeArgument) return null;
942+
let signatureReference = typeArgument.getSignature();
943+
if (signatureReference) return signatureReference.returnType;
944+
if (reportMode == ReportMode.Report) {
945+
resolver.error(
946+
DiagnosticCode.Type_0_has_no_call_signatures,
947+
typeArgumentNode.range, typeArgument.toString()
948+
);
949+
}
950+
return null;
951+
}
952+
builtinTypes.set(CommonNames.returnof, builtin_resolveReturnOfType);
953+
954+
function builtin_resolveNonnullableType(ctx: BuiltinTypesContext): Type | null {
955+
let resolver = ctx.resolver;
956+
let node = ctx.node;
957+
let ctxElement = ctx.ctxElement;
958+
let ctxTypes = ctx.ctxTypes;
959+
let reportMode = ctx.reportMode;
960+
const typeArgumentNode = resolver.ensureOneTypeArgument(node, reportMode);
961+
if (!typeArgumentNode) return null;
962+
let typeArgument = resolver.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
963+
if (!typeArgument) return null;
964+
if (!typeArgument.isNullableReference) return typeArgument;
965+
return typeArgument.nonNullableType;
966+
}
967+
builtinTypes.set(CommonNames.nonnull, builtin_resolveNonnullableType);
968+
814969
// === Static type evaluation =================================================================
815970

816971
// helper global used by checkConstantType

src/resolver.ts

Lines changed: 9 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ import {
103103
} from "./tokenizer";
104104

105105
import {
106-
BuiltinNames
106+
BuiltinNames,
107+
builtinTypes,
108+
BuiltinTypesContext
107109
} from "./builtins";
108110

109111
/** Indicates whether errors are reported or not. */
@@ -299,11 +301,11 @@ export class Resolver extends DiagnosticEmitter {
299301
// Handle special built-in types
300302
if (isSimpleType) {
301303
let text = nameNode.identifier.text;
302-
if (text == CommonNames.native) return this.resolveBuiltinNativeType(node, ctxElement, ctxTypes, reportMode);
303-
if (text == CommonNames.indexof) return this.resolveBuiltinIndexofType(node, ctxElement, ctxTypes, reportMode);
304-
if (text == CommonNames.valueof) return this.resolveBuiltinValueofType(node, ctxElement, ctxTypes, reportMode);
305-
if (text == CommonNames.returnof) return this.resolveBuiltinReturnTypeType(node, ctxElement, ctxTypes, reportMode);
306-
if (text == CommonNames.nonnull) return this.resolveBuiltinNotNullableType(node, ctxElement, ctxTypes, reportMode);
304+
if (builtinTypes.has(text)) {
305+
let fn = assert(builtinTypes.get(text));
306+
let ctx = new BuiltinTypesContext(this, node, ctxElement, ctxTypes, reportMode);
307+
return fn(ctx);
308+
}
307309
}
308310

309311
// Resolve normally
@@ -441,138 +443,6 @@ export class Resolver extends DiagnosticEmitter {
441443
return node.isNullable ? signature.type.asNullable() : signature.type;
442444
}
443445

444-
private resolveBuiltinNativeType(
445-
/** The type to resolve. */
446-
node: NamedTypeNode,
447-
/** Contextual element. */
448-
ctxElement: Element,
449-
/** Contextual types, i.e. `T`. */
450-
ctxTypes: Map<string,Type> | null = null,
451-
/** How to proceed with eventual diagnostics. */
452-
reportMode: ReportMode = ReportMode.Report
453-
): Type | null {
454-
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
455-
if (!typeArgumentNode) return null;
456-
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
457-
if (!typeArgument) return null;
458-
switch (typeArgument.kind) {
459-
case TypeKind.I8:
460-
case TypeKind.I16:
461-
case TypeKind.I32: return Type.i32;
462-
case TypeKind.Isize: if (!this.program.options.isWasm64) return Type.i32;
463-
case TypeKind.I64: return Type.i64;
464-
case TypeKind.U8:
465-
case TypeKind.U16:
466-
case TypeKind.U32:
467-
case TypeKind.Bool: return Type.u32;
468-
case TypeKind.Usize: if (!this.program.options.isWasm64) return Type.u32;
469-
case TypeKind.U64: return Type.u64;
470-
case TypeKind.F32: return Type.f32;
471-
case TypeKind.F64: return Type.f64;
472-
case TypeKind.V128: return Type.v128;
473-
case TypeKind.Void: return Type.void;
474-
default: assert(false);
475-
}
476-
return null;
477-
}
478-
479-
private resolveBuiltinIndexofType(
480-
/** The type to resolve. */
481-
node: NamedTypeNode,
482-
/** Contextual element. */
483-
ctxElement: Element,
484-
/** Contextual types, i.e. `T`. */
485-
ctxTypes: Map<string,Type> | null = null,
486-
/** How to proceed with eventual diagnostics. */
487-
reportMode: ReportMode = ReportMode.Report
488-
): Type | null {
489-
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
490-
if (!typeArgumentNode) return null;
491-
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
492-
if (!typeArgument) return null;
493-
let classReference = typeArgument.classReference;
494-
if (!classReference) {
495-
if (reportMode == ReportMode.Report) {
496-
this.error(
497-
DiagnosticCode.Index_signature_is_missing_in_type_0,
498-
typeArgumentNode.range, typeArgument.toString()
499-
);
500-
}
501-
return null;
502-
}
503-
let overload = classReference.lookupOverload(OperatorKind.IndexedGet);
504-
if (overload) {
505-
let parameterTypes = overload.signature.parameterTypes;
506-
if (overload.is(CommonFlags.Static)) {
507-
assert(parameterTypes.length == 2);
508-
return parameterTypes[1];
509-
} else {
510-
assert(parameterTypes.length == 1);
511-
return parameterTypes[0];
512-
}
513-
}
514-
if (reportMode == ReportMode.Report) {
515-
this.error(
516-
DiagnosticCode.Index_signature_is_missing_in_type_0,
517-
typeArgumentNode.range, typeArgument.toString()
518-
);
519-
}
520-
return null;
521-
}
522-
523-
private resolveBuiltinValueofType(
524-
/** The type to resolve. */
525-
node: NamedTypeNode,
526-
/** Contextual element. */
527-
ctxElement: Element,
528-
/** Contextual types, i.e. `T`. */
529-
ctxTypes: Map<string,Type> | null = null,
530-
/** How to proceed with eventual diagnostics. */
531-
reportMode: ReportMode = ReportMode.Report
532-
): Type | null {
533-
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
534-
if (!typeArgumentNode) return null;
535-
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
536-
if (!typeArgument) return null;
537-
let classReference = typeArgument.getClassOrWrapper(this.program);
538-
if (classReference) {
539-
let overload = classReference.lookupOverload(OperatorKind.IndexedGet);
540-
if (overload) return overload.signature.returnType;
541-
}
542-
if (reportMode == ReportMode.Report) {
543-
this.error(
544-
DiagnosticCode.Index_signature_is_missing_in_type_0,
545-
typeArgumentNode.range, typeArgument.toString()
546-
);
547-
}
548-
return null;
549-
}
550-
551-
private resolveBuiltinReturnTypeType(
552-
/** The type to resolve. */
553-
node: NamedTypeNode,
554-
/** Contextual element. */
555-
ctxElement: Element,
556-
/** Contextual types, i.e. `T`. */
557-
ctxTypes: Map<string,Type> | null = null,
558-
/** How to proceed with eventualy diagnostics. */
559-
reportMode: ReportMode = ReportMode.Report
560-
): Type | null {
561-
const typeArgumentNode = this.ensureOneTypeArgument(node, reportMode);
562-
if (!typeArgumentNode) return null;
563-
let typeArgument = this.resolveType(typeArgumentNode, null, ctxElement, ctxTypes, reportMode);
564-
if (!typeArgument) return null;
565-
let signatureReference = typeArgument.getSignature();
566-
if (signatureReference) return signatureReference.returnType;
567-
if (reportMode == ReportMode.Report) {
568-
this.error(
569-
DiagnosticCode.Type_0_has_no_call_signatures,
570-
typeArgumentNode.range, typeArgument.toString()
571-
);
572-
}
573-
return null;
574-
}
575-
576446
private resolveBuiltinNotNullableType(
577447
/** The type to resolve. */
578448
node: NamedTypeNode,
@@ -3814,7 +3684,7 @@ export class Resolver extends DiagnosticEmitter {
38143684
return instance;
38153685
}
38163686

3817-
private ensureOneTypeArgument(
3687+
ensureOneTypeArgument(
38183688
/** The type to resolve. */
38193689
node: NamedTypeNode,
38203690
/** How to proceed with eventual diagnostics. */

0 commit comments

Comments
 (0)