mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-15 07:51:32 +00:00
Make type checking builtins also accept just a type argument
This commit is contained in:
152
src/builtins.ts
152
src/builtins.ts
@ -105,118 +105,46 @@ export function compileCall(
|
||||
|
||||
// types
|
||||
|
||||
case "isInteger": {
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
reportNode.range, prototype.internalName
|
||||
); // recoverable
|
||||
}
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
let type = compiler.currentType;
|
||||
case "isInteger": { // isInteger<T!>() / isInteger<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (!type) return module.createUnreachable();
|
||||
return type.is(TypeFlags.INTEGER) && !type.is(TypeFlags.REFERENCE)
|
||||
? module.createI32(1)
|
||||
: module.createI32(0);
|
||||
}
|
||||
case "isFloat": {
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
reportNode.range, prototype.internalName
|
||||
); // recoverable
|
||||
}
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
let type = compiler.currentType;
|
||||
case "isFloat": { // isFloat<T!>() / isFloat<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (!type) return module.createUnreachable();
|
||||
return type.is(TypeFlags.FLOAT)
|
||||
? module.createI32(1)
|
||||
: module.createI32(0);
|
||||
}
|
||||
case "isReference": {
|
||||
case "isReference": { // isReference<T!>() / isReference<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
reportNode.range, prototype.internalName
|
||||
); // recoverable
|
||||
}
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
let type = compiler.currentType;
|
||||
if (!type) return module.createUnreachable();
|
||||
compiler.currentType = Type.bool;
|
||||
return type.is(TypeFlags.REFERENCE)
|
||||
? module.createI32(1)
|
||||
: module.createI32(0);
|
||||
}
|
||||
case "isString": {
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
reportNode.range, prototype.internalName
|
||||
); // recoverable
|
||||
}
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
let type = compiler.currentType;
|
||||
case "isString": { // isString<T!>() / isString<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (!type) return module.createUnreachable();
|
||||
let classType = type.classReference;
|
||||
if (classType) {
|
||||
let stringInstance = compiler.program.stringInstance;
|
||||
if (!stringInstance) return module.createUnreachable();
|
||||
if (classType.isAssignableTo(stringInstance)) {
|
||||
return module.createI32(1);
|
||||
}
|
||||
if (stringInstance && classType.isAssignableTo(stringInstance)) return module.createI32(1);
|
||||
}
|
||||
return module.createI32(0);
|
||||
}
|
||||
case "isArray": {
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_generic,
|
||||
reportNode.range, prototype.internalName
|
||||
); // recoverable
|
||||
}
|
||||
if (operands.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
let type = compiler.currentType;
|
||||
case "isArray": { // isArray<T!>() / isArray<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (!type) return module.createUnreachable();
|
||||
let classType = type.classReference;
|
||||
return classType != null && classType.prototype.fnIndexedGet != null
|
||||
? module.createI32(1)
|
||||
@ -2546,6 +2474,54 @@ export function compileCall(
|
||||
return module.createUnreachable();
|
||||
}
|
||||
|
||||
function evaluateConstantType(
|
||||
compiler: Compiler,
|
||||
typeArguments: Type[] | null,
|
||||
operands: Expression[],
|
||||
reportNode: Node
|
||||
): Type | null {
|
||||
if (operands.length == 0) { // requires type argument
|
||||
if (!typeArguments || typeArguments.length != 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
return typeArguments[0];
|
||||
}
|
||||
if (operands.length == 1) { // optional type argument
|
||||
if (typeArguments) {
|
||||
if (typeArguments.length == 1) {
|
||||
compiler.compileExpression(operands[0], typeArguments[0], ConversionKind.IMPLICIT, false);
|
||||
} else {
|
||||
if (typeArguments.length) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||
reportNode.range, "1", typeArguments.length.toString(10)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
}
|
||||
} else {
|
||||
compiler.compileExpressionRetainType(operands[0], Type.i32, false);
|
||||
}
|
||||
return compiler.currentType;
|
||||
}
|
||||
if (typeArguments && typeArguments.length > 1) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||
reportNode.range, "1", typeArguments.length.toString(10)
|
||||
);
|
||||
}
|
||||
compiler.error(
|
||||
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||
reportNode.range, "1", operands.length.toString(10)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32 {
|
||||
var expr: ExpressionRef;
|
||||
var value: i32;
|
||||
|
Reference in New Issue
Block a user