Skip to content

Commit 6d628ce

Browse files
authored
Support resolving all kinds of expressions (AssemblyScript#726)
1 parent 19d06a3 commit 6d628ce

24 files changed

+13468
-600
lines changed

src/ast.ts

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ export abstract class Node {
246246
stmt.range = range;
247247
stmt.name = name;
248248
stmt.arguments = args;
249-
stmt.decoratorKind = decoratorNameToKind(name);
249+
stmt.decoratorKind = DecoratorKind.fromNode(name);
250250
return stmt;
251251
}
252252

@@ -1187,73 +1187,76 @@ export enum DecoratorKind {
11871187
UNSAFE
11881188
}
11891189

1190-
/** Returns the kind of the specified decorator. Defaults to {@link DecoratorKind.CUSTOM}. */
1191-
export function decoratorNameToKind(name: Expression): DecoratorKind {
1192-
// @global, @inline, @operator, @sealed, @unmanaged
1193-
if (name.kind == NodeKind.IDENTIFIER) {
1194-
let nameStr = (<IdentifierExpression>name).text;
1195-
assert(nameStr.length);
1196-
switch (nameStr.charCodeAt(0)) {
1197-
case CharCode.b: {
1198-
if (nameStr == "builtin") return DecoratorKind.BUILTIN;
1199-
break;
1200-
}
1201-
case CharCode.e: {
1202-
if (nameStr == "external") return DecoratorKind.EXTERNAL;
1203-
break;
1204-
}
1205-
case CharCode.g: {
1206-
if (nameStr == "global") return DecoratorKind.GLOBAL;
1207-
break;
1208-
}
1209-
case CharCode.i: {
1210-
if (nameStr == "inline") return DecoratorKind.INLINE;
1211-
break;
1212-
}
1213-
case CharCode.l: {
1214-
if (nameStr == "lazy") return DecoratorKind.LAZY;
1215-
break;
1216-
}
1217-
case CharCode.o: {
1218-
if (nameStr == "operator") return DecoratorKind.OPERATOR;
1219-
break;
1220-
}
1221-
case CharCode.s: {
1222-
if (nameStr == "sealed") return DecoratorKind.SEALED;
1223-
break;
1224-
}
1225-
case CharCode.u: {
1226-
if (nameStr == "unmanaged") return DecoratorKind.UNMANAGED;
1227-
if (nameStr == "unsafe") return DecoratorKind.UNSAFE;
1228-
break;
1229-
}
1230-
}
1231-
} else if (
1232-
name.kind == NodeKind.PROPERTYACCESS &&
1233-
(<PropertyAccessExpression>name).expression.kind == NodeKind.IDENTIFIER
1234-
) {
1235-
let nameStr = (<IdentifierExpression>(<PropertyAccessExpression>name).expression).text;
1236-
assert(nameStr.length);
1237-
let propStr = (<PropertyAccessExpression>name).property.text;
1238-
assert(propStr.length);
1239-
// @operator.binary, @operator.prefix, @operator.postfix
1240-
if (nameStr == "operator") {
1241-
switch (propStr.charCodeAt(0)) {
1190+
export namespace DecoratorKind {
1191+
1192+
/** Returns the kind of the specified decorator name node. Defaults to {@link DecoratorKind.CUSTOM}. */
1193+
export function fromNode(nameNode: Expression): DecoratorKind {
1194+
// @global, @inline, @operator, @sealed, @unmanaged
1195+
if (nameNode.kind == NodeKind.IDENTIFIER) {
1196+
let nameStr = (<IdentifierExpression>nameNode).text;
1197+
assert(nameStr.length);
1198+
switch (nameStr.charCodeAt(0)) {
12421199
case CharCode.b: {
1243-
if (propStr == "binary") return DecoratorKind.OPERATOR_BINARY;
1200+
if (nameStr == "builtin") return DecoratorKind.BUILTIN;
12441201
break;
12451202
}
1246-
case CharCode.p: {
1247-
switch (propStr) {
1248-
case "prefix": return DecoratorKind.OPERATOR_PREFIX;
1249-
case "postfix": return DecoratorKind.OPERATOR_POSTFIX;
1250-
}
1203+
case CharCode.e: {
1204+
if (nameStr == "external") return DecoratorKind.EXTERNAL;
12511205
break;
12521206
}
1207+
case CharCode.g: {
1208+
if (nameStr == "global") return DecoratorKind.GLOBAL;
1209+
break;
1210+
}
1211+
case CharCode.i: {
1212+
if (nameStr == "inline") return DecoratorKind.INLINE;
1213+
break;
1214+
}
1215+
case CharCode.l: {
1216+
if (nameStr == "lazy") return DecoratorKind.LAZY;
1217+
break;
1218+
}
1219+
case CharCode.o: {
1220+
if (nameStr == "operator") return DecoratorKind.OPERATOR;
1221+
break;
1222+
}
1223+
case CharCode.s: {
1224+
if (nameStr == "sealed") return DecoratorKind.SEALED;
1225+
break;
1226+
}
1227+
case CharCode.u: {
1228+
if (nameStr == "unmanaged") return DecoratorKind.UNMANAGED;
1229+
if (nameStr == "unsafe") return DecoratorKind.UNSAFE;
1230+
break;
1231+
}
1232+
}
1233+
} else if (
1234+
nameNode.kind == NodeKind.PROPERTYACCESS &&
1235+
(<PropertyAccessExpression>nameNode).expression.kind == NodeKind.IDENTIFIER
1236+
) {
1237+
let nameStr = (<IdentifierExpression>(<PropertyAccessExpression>nameNode).expression).text;
1238+
assert(nameStr.length);
1239+
let propStr = (<PropertyAccessExpression>nameNode).property.text;
1240+
assert(propStr.length);
1241+
// @operator.binary, @operator.prefix, @operator.postfix
1242+
if (nameStr == "operator") {
1243+
switch (propStr.charCodeAt(0)) {
1244+
case CharCode.b: {
1245+
if (propStr == "binary") return DecoratorKind.OPERATOR_BINARY;
1246+
break;
1247+
}
1248+
case CharCode.p: {
1249+
switch (propStr) {
1250+
case "prefix": return DecoratorKind.OPERATOR_PREFIX;
1251+
case "postfix": return DecoratorKind.OPERATOR_POSTFIX;
1252+
}
1253+
break;
1254+
}
1255+
}
12531256
}
12541257
}
1258+
return DecoratorKind.CUSTOM;
12551259
}
1256-
return DecoratorKind.CUSTOM;
12571260
}
12581261

12591262
/** Represents a decorator. */

src/builtins.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -595,29 +595,38 @@ export function compileCall(
595595
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
596596
compiler.currentType = Type.bool;
597597
if (!type) return module.unreachable();
598-
let classType = type.classReference;
599-
if (classType) {
600-
let stringInstance = compiler.program.stringInstance;
601-
if (stringInstance && classType.isAssignableTo(stringInstance)) return module.i32(1);
598+
if (type.is(TypeFlags.REFERENCE)) {
599+
let classReference = type.classReference;
600+
if (classReference) {
601+
let stringInstance = compiler.program.stringInstance;
602+
if (stringInstance && classReference.isAssignableTo(stringInstance)) return module.i32(1);
603+
}
602604
}
603605
return module.i32(0);
604606
}
605607
case BuiltinSymbols.isArray: { // isArray<T!>() / isArray<T?>(value: T) -> bool
606608
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
607609
compiler.currentType = Type.bool;
608610
if (!type) return module.unreachable();
609-
let classReference = type.classReference;
610-
if (!classReference) return module.i32(0);
611-
let classPrototype = classReference.prototype;
612-
return module.i32(classPrototype.extends(compiler.program.arrayPrototype) ? 1 : 0);
611+
if (type.is(TypeFlags.REFERENCE)) {
612+
let classReference = type.classReference;
613+
if (classReference) {
614+
return module.i32(classReference.prototype.extends(compiler.program.arrayPrototype) ? 1 : 0);
615+
}
616+
}
617+
return module.i32(0);
613618
}
614619
case BuiltinSymbols.isArrayLike: { // isArrayLike<T!>() / isArrayLike<T?>(value: T) -> bool
615620
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
616621
compiler.currentType = Type.bool;
617622
if (!type) return module.unreachable();
618-
let classReference = type.classReference;
619-
if (!classReference) return module.i32(0);
620-
return module.i32(classReference.isArrayLike ? 1 : 0);
623+
if (type.is(TypeFlags.REFERENCE)) {
624+
let classReference = type.classReference;
625+
if (classReference) {
626+
return module.i32(classReference.isArrayLike ? 1 : 0);
627+
}
628+
}
629+
return module.i32(0);
621630
}
622631
case BuiltinSymbols.isFunction: { // isFunction<T!> / isFunction<T?>(value: T) -> bool
623632
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
@@ -637,7 +646,7 @@ export function compileCall(
637646
checkTypeAbsent(typeArguments, reportNode, prototype) |
638647
checkArgsRequired(operands, 1, reportNode, compiler)
639648
) return module.unreachable();
640-
let element = compiler.resolver.resolveExpression(
649+
let element = compiler.resolver.lookupExpression(
641650
operands[0],
642651
compiler.currentFlow,
643652
Type.auto,
@@ -747,8 +756,9 @@ export function compileCall(
747756
checkTypeRequired(typeArguments, reportNode, compiler) |
748757
checkArgsOptional(operands, 0, 1, reportNode, compiler)
749758
) return module.unreachable();
750-
let classType = typeArguments![0].classReference;
751-
if (!classType) {
759+
let typeArgument = typeArguments![0];
760+
let classType = typeArgument.classReference;
761+
if (!(typeArgument.is(TypeFlags.REFERENCE) && classType !== null)) {
752762
compiler.error(
753763
DiagnosticCode.Operation_not_supported,
754764
reportNode.typeArgumentsRange
@@ -2436,8 +2446,9 @@ export function compileCall(
24362446
if (
24372447
checkTypeRequired(typeArguments, reportNode, compiler, true)
24382448
) return module.unreachable();
2439-
let classInstance = typeArguments![0].classReference;
2440-
if (!classInstance) {
2449+
let typeArgument = typeArguments![0];
2450+
let classInstance = typeArgument.classReference;
2451+
if (!(typeArgument.is(TypeFlags.REFERENCE) && classInstance !== null)) {
24412452
compiler.error(
24422453
DiagnosticCode.Operation_not_supported,
24432454
reportNode.typeArgumentsRange
@@ -3665,7 +3676,7 @@ export function compileCall(
36653676
}
36663677

36673678
let classReference = type.classReference;
3668-
if (!classReference || classReference.hasDecorator(DecoratorFlags.UNMANAGED)) {
3679+
if (!type.is(TypeFlags.REFERENCE) || !classReference || classReference.hasDecorator(DecoratorFlags.UNMANAGED)) {
36693680
compiler.error(
36703681
DiagnosticCode.Operation_not_supported,
36713682
reportNode.range
@@ -4102,11 +4113,13 @@ export function compileVisitGlobals(compiler: Compiler): void {
41024113
for (let element of compiler.program.elementsByName.values()) {
41034114
if (element.kind != ElementKind.GLOBAL) continue;
41044115
let global = <Global>element;
4105-
let classReference = global.type.classReference;
4116+
let globalType = global.type;
4117+
let classType = globalType.classReference;
41064118
if (
4107-
global.is(CommonFlags.COMPILED) &&
4108-
classReference !== null &&
4109-
!classReference.hasDecorator(DecoratorFlags.UNMANAGED)
4119+
globalType.is(TypeFlags.REFERENCE) &&
4120+
classType !== null &&
4121+
!classType.hasDecorator(DecoratorFlags.UNMANAGED) &&
4122+
global.is(CommonFlags.COMPILED)
41104123
) {
41114124
if (global.is(CommonFlags.INLINED)) {
41124125
let value = global.constantIntegerValue;

0 commit comments

Comments
 (0)