diff --git a/src/builtins.ts b/src/builtins.ts index d163e1b8..efc8345c 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -5,7 +5,7 @@ import { Compiler, - ContextualFlags, + Constraints, RuntimeFeatures, flatten } from "./compiler"; @@ -782,8 +782,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -873,8 +873,8 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -883,7 +883,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); let expr: ExpressionRef; switch (type.kind) { case TypeKind.I8: @@ -934,8 +934,8 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.i32, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -944,7 +944,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); let expr: ExpressionRef; switch (type.kind) { case TypeKind.I8: @@ -995,8 +995,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1120,8 +1120,8 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1130,7 +1130,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT | ContextualFlags.WRAP); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); let op: BinaryOp; switch (type.kind) { case TypeKind.I8: @@ -1190,8 +1190,8 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1200,7 +1200,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT | ContextualFlags.WRAP); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); let op: BinaryOp; switch (type.kind) { case TypeKind.I8: @@ -1261,8 +1261,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1312,8 +1312,8 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1322,7 +1322,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); let op: BinaryOp; switch (type.kind) { // TODO: does an integer version make sense? @@ -1344,8 +1344,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1407,13 +1407,13 @@ export function compileCall( switch (type.kind) { case TypeKind.I32: case TypeKind.U32: { - let arg0 = compiler.compileExpression(operands[0], Type.f32, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_IMPLICIT); expr = module.unary(UnaryOp.ReinterpretF32, arg0); break; } case TypeKind.I64: case TypeKind.U64: { - let arg0 = compiler.compileExpression(operands[0], Type.f64, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_IMPLICIT); expr = module.unary(UnaryOp.ReinterpretF64, arg0); break; } @@ -1423,7 +1423,7 @@ export function compileCall( compiler.options.isWasm64 ? Type.f64 : Type.f32, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); expr = module.unary( compiler.options.isWasm64 @@ -1434,12 +1434,12 @@ export function compileCall( break; } case TypeKind.F32: { - let arg0 = compiler.compileExpression(operands[0], Type.i32, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT); expr = module.unary(UnaryOp.ReinterpretI32, arg0); break; } case TypeKind.F64: { - let arg0 = compiler.compileExpression(operands[0], Type.i64, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_IMPLICIT); expr = module.unary(UnaryOp.ReinterpretI64, arg0); break; } @@ -1461,8 +1461,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.currentType = type; @@ -1499,8 +1499,8 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, ContextualFlags.NONE); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; if (type.is(TypeFlags.REFERENCE)) { compiler.error( @@ -1562,7 +1562,7 @@ export function compileCall( ) ? contextualType : type; let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let numOperands = operands.length; let immOffset = numOperands >= 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports @@ -1616,19 +1616,19 @@ export function compileCall( let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = isAsm ? compiler.compileExpression(operands[1], contextualType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) : compiler.compileExpression( operands[1], type, type.is(TypeFlags.INTEGER) - ? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) - : ContextualFlags.IMPLICIT + ? Constraints.NONE // no need to convert to small int (but now might result in a float) + : Constraints.CONV_IMPLICIT ); let inType = compiler.currentType; if ( @@ -1705,7 +1705,7 @@ export function compileCall( } let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let immOffset = operands.length == 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports if (immOffset < 0) { @@ -1737,20 +1737,20 @@ export function compileCall( } let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = isAsm ? compiler.compileExpression( operands[1], contextualType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) : compiler.compileExpression( operands[1], type, type.is(TypeFlags.INTEGER) - ? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) - : ContextualFlags.IMPLICIT + ? Constraints.NONE // no need to convert to small int (but now might result in a float) + : Constraints.CONV_IMPLICIT ); let inType = compiler.currentType; if ( @@ -1796,19 +1796,19 @@ export function compileCall( } let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = isAsm ? compiler.compileExpression(operands[1], contextualType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) : compiler.compileExpression( operands[1], type, type.is(TypeFlags.INTEGER) - ? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) - : ContextualFlags.IMPLICIT + ? Constraints.NONE // no need to convert to small int (but now might result in a float) + : Constraints.CONV_IMPLICIT ); let inType = compiler.currentType; if ( @@ -1861,24 +1861,24 @@ export function compileCall( } let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = isAsm ? compiler.compileExpression(operands[1], contextualType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) : compiler.compileExpression( operands[1], type, type.is(TypeFlags.INTEGER) - ? ContextualFlags.NONE // no need to convert to small int (but now might result in a float) - : ContextualFlags.IMPLICIT + ? Constraints.NONE // no need to convert to small int (but now might result in a float) + : Constraints.CONV_IMPLICIT ); let inType = compiler.currentType; let arg2 = compiler.compileExpression(operands[2], inType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); if ( type.is(TypeFlags.INTEGER) && @@ -1926,14 +1926,14 @@ export function compileCall( } let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = compiler.compileExpression(operands[1], type, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg2 = compiler.compileExpression(operands[2], Type.i64, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); compiler.currentType = Type.i32; return module.atomic_wait(arg0, arg1, arg2, type.toNativeType()); @@ -1947,11 +1947,11 @@ export function compileCall( ) return module.unreachable(); let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let arg1 = compiler.compileExpression(operands[1], Type.i32, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); compiler.currentType = Type.i32; return module.atomic_notify(arg0, arg1); @@ -1965,7 +1965,7 @@ export function compileCall( checkArgsRequired(operands, 3, reportNode, compiler) ) return module.unreachable(); let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT) + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.auto); let type = compiler.currentType; if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) { @@ -1975,7 +1975,7 @@ export function compileCall( ); return module.unreachable(); } - let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); let arg2 = compiler.makeIsTrueish( compiler.compileExpression(operands[2], Type.bool), compiler.currentType // ^ @@ -2011,7 +2011,7 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); return module.host(HostOp.MemoryGrow, null, [ - compiler.compileExpression(operands[0], Type.i32, ContextualFlags.IMPLICIT) + compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT) ]); } case BuiltinSymbols.memory_copy: { // memory.copy(dest: usize, src: usize: n: usize) -> void @@ -2027,9 +2027,9 @@ export function compileCall( return compiler.compileCallDirect(instance, operands, reportNode); } let usizeType = compiler.options.usizeType; - let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], usizeType, ContextualFlags.IMPLICIT); - let arg2 = compiler.compileExpression(operands[2], usizeType, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], usizeType, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], usizeType, Constraints.CONV_IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], usizeType, Constraints.CONV_IMPLICIT); compiler.currentType = Type.void; return module.memory_copy(arg0, arg1, arg2); } @@ -2046,9 +2046,9 @@ export function compileCall( return compiler.compileCallDirect(instance, operands, reportNode); } let usizeType = compiler.options.usizeType; - let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); - let arg2 = compiler.compileExpression(operands[2], usizeType, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], usizeType, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], usizeType, Constraints.CONV_IMPLICIT); compiler.currentType = Type.void; return module.memory_fill(arg0, arg1, arg2); } @@ -2085,8 +2085,8 @@ export function compileCall( return module.unreachable(); } let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP) - : compiler.compileExpression(operands[0], Type.bool, ContextualFlags.WRAP); + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.bool, Constraints.MUST_WRAP); let type = compiler.currentType; compiler.currentType = type.nonNullableType; @@ -2333,7 +2333,7 @@ export function compileCall( return module.unreachable(); } compiler.currentType = classInstance.type; - return compiler.compileInstantiate(classInstance, operands, ContextualFlags.NONE, reportNode); + return compiler.compileInstantiate(classInstance, operands, Constraints.NONE, reportNode); } // === User-defined diagnostics =============================================================== @@ -2373,7 +2373,7 @@ export function compileCall( compiler.currentType = Type.i8; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.i8, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.i8, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.i16: { if ( @@ -2383,7 +2383,7 @@ export function compileCall( compiler.currentType = Type.i16; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.i16, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.i16, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.i32: { if ( @@ -2393,7 +2393,7 @@ export function compileCall( compiler.currentType = Type.i32; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.i32, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.i64: { if ( @@ -2403,7 +2403,7 @@ export function compileCall( compiler.currentType = Type.i64; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.i64, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.isize: { let isizeType = compiler.options.isizeType; @@ -2414,7 +2414,7 @@ export function compileCall( compiler.currentType = isizeType; return module.unreachable(); } - return compiler.compileExpression(operands[0], isizeType, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], isizeType, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.u8: { if ( @@ -2424,7 +2424,7 @@ export function compileCall( compiler.currentType = Type.u8; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.u8, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.u8, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.u16: { if ( @@ -2434,7 +2434,7 @@ export function compileCall( compiler.currentType = Type.u16; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.u16, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.u16, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.u32: { if ( @@ -2444,7 +2444,7 @@ export function compileCall( compiler.currentType = Type.u32; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.u32, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.u64: { if ( @@ -2454,7 +2454,7 @@ export function compileCall( compiler.currentType = Type.u64; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.u64, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.u64, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.usize: { let usizeType = compiler.options.usizeType; @@ -2465,7 +2465,7 @@ export function compileCall( compiler.currentType = usizeType; return module.unreachable(); } - return compiler.compileExpression(operands[0], usizeType, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], usizeType, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.bool: { if ( @@ -2475,7 +2475,7 @@ export function compileCall( compiler.currentType = Type.bool; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.bool, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.bool, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.f32: { if ( @@ -2485,7 +2485,7 @@ export function compileCall( compiler.currentType = Type.f32; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.f32, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_EXPLICIT); } case BuiltinSymbols.f64: { if ( @@ -2495,7 +2495,7 @@ export function compileCall( compiler.currentType = Type.f64; return module.unreachable(); } - return compiler.compileExpression(operands[0], Type.f64, ContextualFlags.EXPLICIT); + return compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_EXPLICIT); } // === SIMD =================================================================================== @@ -2514,7 +2514,7 @@ export function compileCall( for (let i = 0; i < 16; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.i8, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.i8, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2543,7 +2543,7 @@ export function compileCall( for (let i = 0; i < 8; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.i16, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.i16, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2572,7 +2572,7 @@ export function compileCall( for (let i = 0; i < 4; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.i32, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.i32, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2601,7 +2601,7 @@ export function compileCall( for (let i = 0; i < 2; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.i64, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.i64, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2632,7 +2632,7 @@ export function compileCall( for (let i = 0; i < 4; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.f32, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.f32, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2661,7 +2661,7 @@ export function compileCall( for (let i = 0; i < 2; ++i) { let value = operands[i]; if (value) { - let expr = compiler.precomputeExpression(value, Type.f64, ContextualFlags.IMPLICIT); + let expr = compiler.precomputeExpression(value, Type.f64, Constraints.CONV_IMPLICIT); if (getExpressionId(expr) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2723,7 +2723,7 @@ export function compileCall( return module.unreachable(); } } - let arg0 = compiler.compileExpression(operands[0], type, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], type, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; return module.unary(op, arg0); } @@ -2770,8 +2770,8 @@ export function compileCall( return module.unreachable(); } } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.precomputeExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT); compiler.currentType = type; if (getExpressionId(arg1) != ExpressionId.Const) { compiler.error( @@ -2838,8 +2838,8 @@ export function compileCall( return module.unreachable(); } } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.precomputeExpression(operands[1], Type.u8, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT); if (getExpressionId(arg1) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -2858,7 +2858,7 @@ export function compileCall( ); return module.unreachable(); } - let arg2 = compiler.compileExpression(operands[2], type, ContextualFlags.IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], type, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; return module.simd_replace(op, arg0, idx, arg2); } @@ -2910,13 +2910,13 @@ export function compileCall( return module.unreachable(); } } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); let mask = new Uint8Array(16); let maxIdx = (laneCount << 1) - 1; for (let i = 0; i < laneCount; ++i) { let operand = operands[2 + i]; - let argN = compiler.precomputeExpression(operand, Type.u8, ContextualFlags.IMPLICIT); + let argN = compiler.precomputeExpression(operand, Type.u8, Constraints.CONV_IMPLICIT); if (getExpressionId(argN) != ExpressionId.Const) { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, @@ -3242,8 +3242,8 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; return module.binary(op, arg0, arg1); } @@ -3334,7 +3334,7 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; return module.unary(op, arg0); } @@ -3413,8 +3413,8 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.i32, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; return module.simd_shift(op, arg0, arg1); } @@ -3436,8 +3436,8 @@ export function compileCall( case BuiltinSymbols.v128_or: { op = BinaryOp.OrVec128; break; } case BuiltinSymbols.v128_xor: { op = BinaryOp.XorVec128; break; } } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); return module.binary(op, arg0, arg1); } case BuiltinSymbols.v128_not: { // any_bitwise_unary(a: v128) -> v128 @@ -3449,7 +3449,7 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); return module.unary(UnaryOp.NotVec128, arg0); } case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128 @@ -3461,9 +3461,9 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.v128, ContextualFlags.IMPLICIT); - let arg2 = compiler.compileExpression(operands[2], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT); return module.simd_bitselect(arg0, arg1, arg2); } case BuiltinSymbols.v128_any_true: // any_test(a: v128) -> bool @@ -3536,7 +3536,7 @@ export function compileCall( compiler.currentType = Type.bool; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.v128, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); compiler.currentType = Type.bool; return module.unary(op, arg0); } @@ -3565,7 +3565,7 @@ export function compileCall( compiler.currentType = Type.void; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], Type.u32, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_IMPLICIT); compiler.runtimeFeatures |= RuntimeFeatures.visitGlobals; compiler.currentType = Type.void; return module.call(BuiltinSymbols.visit_globals, [ arg0 ], NativeType.None); @@ -3578,8 +3578,8 @@ export function compileCall( compiler.currentType = Type.void; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.u32, ContextualFlags.IMPLICIT); + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.u32, Constraints.CONV_IMPLICIT); compiler.runtimeFeatures |= RuntimeFeatures.visitMembers; compiler.currentType = Type.void; return module.call(BuiltinSymbols.visit_members, [ arg0, arg1 ], NativeType.None); @@ -3950,7 +3950,7 @@ export function compileAbort( // assertion succeeds respectively is only being computed if the program actually crashes. // Hence, let's make it so that the autorelease is skipped at the end of the current block, // essentially ignoring the message GC-wise. Doesn't matter anyway on a crash. - messageArg = compiler.compileExpression(message, stringInstance.type, ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE); + messageArg = compiler.compileExpression(message, stringInstance.type, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN); } else { messageArg = stringInstance.type.toNativeZero(module); } @@ -4241,7 +4241,7 @@ function evaluateConstantType( ); return null; } - compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT); + compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT); } else { compiler.compileExpression(operands[0], Type.auto); } @@ -4265,7 +4265,7 @@ function evaluateImmediateOffset(expression: Expression, compiler: Compiler): i3 var expr: ExpressionRef; var value: i32; if (compiler.options.isWasm64) { - expr = compiler.precomputeExpression(expression, Type.usize64, ContextualFlags.IMPLICIT); + expr = compiler.precomputeExpression(expression, Type.usize64, Constraints.CONV_IMPLICIT); if ( getExpressionId(expr) != ExpressionId.Const || getExpressionType(expr) != NativeType.I64 || @@ -4279,7 +4279,7 @@ function evaluateImmediateOffset(expression: Expression, compiler: Compiler): i3 value = -1; } } else { - expr = compiler.precomputeExpression(expression, Type.usize32, ContextualFlags.IMPLICIT); + expr = compiler.precomputeExpression(expression, Type.usize32, Constraints.CONV_IMPLICIT); if ( getExpressionId(expr) != ExpressionId.Const || getExpressionType(expr) != NativeType.I32 || diff --git a/src/compiler.ts b/src/compiler.ts index a4352acb..d9261a5e 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -233,23 +233,23 @@ export class Options { } } -/** Requests or indicates compilation conditions of statements and expressions. */ -export const enum ContextualFlags { +/** Various constraints in expression compilation. */ +export const enum Constraints { NONE = 0, - /** Implicit conversion required. */ - IMPLICIT = 1 << 0, - /** Explicit conversion required. */ - EXPLICIT = 1 << 1, - /** Small integer wrap required. */ - WRAP = 1 << 2, + /** Must implicitly convert to the target type. */ + CONV_IMPLICIT = 1 << 0, + /** Must explicitly convert to the target type. */ + CONV_EXPLICIT = 1 << 1, + /** Must wrap small integer values to match the target type. */ + MUST_WRAP = 1 << 2, - /** Value is known to be immediately dropped. */ + /** Indicates that the value will be dropped immediately. */ WILL_DROP = 1 << 3, - /** Value is known to be immediately assigned to a retaining target. */ - SKIP_AUTORELEASE = 1 << 4, - /** Data can be compiled statically. */ - STATIC_CAPABLE = 1 << 5 + /** Indicates that the value will be retained immediately. */ + WILL_RETAIN = 1 << 4, + /** Indicates that static data is preferred. */ + PREFER_STATIC = 1 << 5 } /** Runtime features to be activated by the compiler. */ @@ -813,7 +813,7 @@ export class Compiler extends DiagnosticEmitter { this.currentFlow = global.file.startFunction.flow; } initExpr = this.compileExpression(initializerNode, Type.auto, // reports - ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE + Constraints.MUST_WRAP | Constraints.WILL_RETAIN ); if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true; this.currentFlow = previousFlow; @@ -886,7 +886,7 @@ export class Compiler extends DiagnosticEmitter { this.currentFlow = global.file.startFunction.flow; } initExpr = this.compileExpression(initializerNode, type, - ContextualFlags.IMPLICIT | ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.STATIC_CAPABLE + Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP | Constraints.WILL_RETAIN | Constraints.PREFER_STATIC ); if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true; this.currentFlow = previousFlow; @@ -995,7 +995,7 @@ export class Compiler extends DiagnosticEmitter { let initExpr: ExpressionRef; if (valueNode) { initExpr = this.compileExpression(valueNode, Type.i32, - ContextualFlags.IMPLICIT // autorelease is not applicable in i32 context + Constraints.CONV_IMPLICIT // autorelease is not applicable in i32 context ); if (getExpressionId(initExpr) != ExpressionId.Const) { initExpr = module.precomputeExpression(initExpr); @@ -1138,7 +1138,7 @@ export class Compiler extends DiagnosticEmitter { assert(!instance.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.GET | CommonFlags.SET | CommonFlags.MAIN)); let expr = this.compileExpression((bodyNode).expression, returnType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); if (!stmts) stmts = [ expr ]; else stmts.push(expr); @@ -1965,7 +1965,7 @@ export class Compiler extends DiagnosticEmitter { compileExpressionStatement( statement: ExpressionStatement ): ExpressionRef { - return this.compileExpression(statement.expression, Type.void, ContextualFlags.IMPLICIT); + return this.compileExpression(statement.expression, Type.void, Constraints.CONV_IMPLICIT); } compileForStatement( @@ -2017,7 +2017,7 @@ export class Compiler extends DiagnosticEmitter { // Compile incrementor var incrementor = statement.incrementor; var incrExpr: ExpressionRef = 0; - if (incrementor) incrExpr = this.compileExpression(incrementor, Type.void, ContextualFlags.IMPLICIT | ContextualFlags.WILL_DROP); + if (incrementor) incrExpr = this.compileExpression(incrementor, Type.void, Constraints.CONV_IMPLICIT | Constraints.WILL_DROP); // Compile body (break: drop out, continue: fall through to incrementor, + loop) var breakLabel = innerFlow.breakLabel = "break|" + label; innerFlow.breakLabel = breakLabel; @@ -2193,9 +2193,9 @@ export class Compiler extends DiagnosticEmitter { this.currentType = Type.void; return module.unreachable(); } - let contextualFlags = ContextualFlags.IMPLICIT; - if (flow.actualFunction.is(CommonFlags.MODULE_EXPORT)) contextualFlags |= ContextualFlags.WRAP; - expr = this.compileExpression(valueExpression, returnType, contextualFlags | ContextualFlags.SKIP_AUTORELEASE); + let constraints = Constraints.CONV_IMPLICIT; + if (flow.actualFunction.is(CommonFlags.MODULE_EXPORT)) constraints |= Constraints.MUST_WRAP; + expr = this.compileExpression(valueExpression, returnType, constraints | Constraints.WILL_RETAIN); // when returning a local, and it is already retained, skip the final set // of retaining it as the return value and releasing it as a variable @@ -2269,7 +2269,7 @@ export class Compiler extends DiagnosticEmitter { var numCases = cases.length; if (!numCases) { return this.compileExpression(statement.condition, Type.void, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); } @@ -2286,7 +2286,7 @@ export class Compiler extends DiagnosticEmitter { breaks[0] = module.local_set( // initializer tempLocalIndex, this.compileExpression(statement.condition, Type.u32, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) ); @@ -2301,7 +2301,7 @@ export class Compiler extends DiagnosticEmitter { module.binary(BinaryOp.EqI32, module.local_get(tempLocalIndex, NativeType.I32), this.compileExpression(label, Type.u32, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) ) ); @@ -2437,7 +2437,7 @@ export class Compiler extends DiagnosticEmitter { if (!type) continue; if (declaration.initializer) { initExpr = this.compileExpression(declaration.initializer, type, // reports - ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE + Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN ); initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr); } @@ -2445,7 +2445,7 @@ export class Compiler extends DiagnosticEmitter { // Otherwise infer type from initializer } else if (declaration.initializer) { initExpr = this.compileExpression(declaration.initializer, Type.auto, - ContextualFlags.SKIP_AUTORELEASE + Constraints.WILL_RETAIN ); // reports initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr); if (this.currentType == Type.void) { @@ -2607,7 +2607,7 @@ export class Compiler extends DiagnosticEmitter { statement: VoidStatement ): ExpressionRef { return this.compileExpression(statement.expression, Type.void, - ContextualFlags.EXPLICIT | ContextualFlags.WILL_DROP + Constraints.CONV_EXPLICIT | Constraints.WILL_DROP ); } @@ -2695,12 +2695,12 @@ export class Compiler extends DiagnosticEmitter { compileInlineConstant( element: VariableLikeElement, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { assert(element.is(CommonFlags.INLINED)); var type = element.type; switch ( - !(contextualFlags & (ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT)) && + !(constraints & (Constraints.CONV_IMPLICIT | Constraints.CONV_EXPLICIT)) && type.is(TypeFlags.INTEGER) && contextualType.is(TypeFlags.INTEGER) && type.size < contextualType.size @@ -2775,34 +2775,34 @@ export class Compiler extends DiagnosticEmitter { compileExpression( expression: Expression, contextualType: Type, - contextualFlags: ContextualFlags = ContextualFlags.NONE + constraints: Constraints = Constraints.NONE ): ExpressionRef { this.currentType = contextualType; var expr: ExpressionRef; - if (contextualType == Type.void) contextualFlags |= ContextualFlags.WILL_DROP; + if (contextualType == Type.void) constraints |= Constraints.WILL_DROP; switch (expression.kind) { case NodeKind.ASSERTION: { - expr = this.compileAssertionExpression(expression, contextualType, contextualFlags); + expr = this.compileAssertionExpression(expression, contextualType, constraints); break; } case NodeKind.BINARY: { - expr = this.compileBinaryExpression(expression, contextualType, contextualFlags); + expr = this.compileBinaryExpression(expression, contextualType, constraints); break; } case NodeKind.CALL: { - expr = this.compileCallExpression(expression, contextualType, contextualFlags); + expr = this.compileCallExpression(expression, contextualType, constraints); break; } case NodeKind.COMMA: { - expr = this.compileCommaExpression(expression, contextualType, contextualFlags); + expr = this.compileCommaExpression(expression, contextualType, constraints); break; } case NodeKind.ELEMENTACCESS: { - expr = this.compileElementAccessExpression(expression, contextualType, contextualFlags); + expr = this.compileElementAccessExpression(expression, contextualType, constraints); break; } case NodeKind.FUNCTION: { - expr = this.compileFunctionExpression(expression, contextualType.signatureReference, contextualFlags); + expr = this.compileFunctionExpression(expression, contextualType.signatureReference, constraints); break; } case NodeKind.IDENTIFIER: @@ -2811,39 +2811,39 @@ export class Compiler extends DiagnosticEmitter { case NodeKind.THIS: case NodeKind.SUPER: case NodeKind.TRUE: { - expr = this.compileIdentifierExpression(expression, contextualType, contextualFlags); + expr = this.compileIdentifierExpression(expression, contextualType, constraints); break; } case NodeKind.INSTANCEOF: { - expr = this.compileInstanceOfExpression(expression, contextualType, contextualFlags); + expr = this.compileInstanceOfExpression(expression, contextualType, constraints); break; } case NodeKind.LITERAL: { - expr = this.compileLiteralExpression(expression, contextualType, contextualFlags); + expr = this.compileLiteralExpression(expression, contextualType, constraints); break; } case NodeKind.NEW: { - expr = this.compileNewExpression(expression, contextualType, contextualFlags); + expr = this.compileNewExpression(expression, contextualType, constraints); break; } case NodeKind.PARENTHESIZED: { - expr = this.compileExpression((expression).expression, contextualType, contextualFlags); + expr = this.compileExpression((expression).expression, contextualType, constraints); break; } case NodeKind.PROPERTYACCESS: { - expr = this.compilePropertyAccessExpression(expression, contextualType, contextualFlags); + expr = this.compilePropertyAccessExpression(expression, contextualType, constraints); break; } case NodeKind.TERNARY: { - expr = this.compileTernaryExpression(expression, contextualType, contextualFlags); + expr = this.compileTernaryExpression(expression, contextualType, constraints); break; } case NodeKind.UNARYPOSTFIX: { - expr = this.compileUnaryPostfixExpression(expression, contextualType, contextualFlags); + expr = this.compileUnaryPostfixExpression(expression, contextualType, constraints); break; } case NodeKind.UNARYPREFIX: { - expr = this.compileUnaryPrefixExpression(expression, contextualType, contextualFlags); + expr = this.compileUnaryPrefixExpression(expression, contextualType, constraints); break; } default: { @@ -2856,13 +2856,13 @@ export class Compiler extends DiagnosticEmitter { } // ensure conversion and wrapping in case the respective function doesn't on its own var currentType = this.currentType; - var wrap = (contextualFlags & ContextualFlags.WRAP) != 0; + var wrap = (constraints & Constraints.MUST_WRAP) != 0; if (currentType != contextualType) { - if (contextualFlags & ContextualFlags.EXPLICIT) { + if (constraints & Constraints.CONV_EXPLICIT) { expr = this.convertExpression(expr, currentType, contextualType, true, wrap, expression); wrap = false; this.currentType = contextualType; - } else if (contextualFlags & ContextualFlags.IMPLICIT) { + } else if (constraints & Constraints.CONV_IMPLICIT) { expr = this.convertExpression(expr, currentType, contextualType, false, wrap, expression); wrap = false; this.currentType = contextualType; @@ -2879,10 +2879,10 @@ export class Compiler extends DiagnosticEmitter { precomputeExpression( expression: Expression, contextualType: Type, - contextualFlags: ContextualFlags = ContextualFlags.NONE + constraints: Constraints = Constraints.NONE ): ExpressionRef { return this.module.precomputeExpression( - this.compileExpression(expression, contextualType, contextualFlags) + this.compileExpression(expression, contextualType, constraints) ); } @@ -3082,9 +3082,9 @@ export class Compiler extends DiagnosticEmitter { compileAssertionExpression( expression: AssertionExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { - var inheritedFlags = contextualFlags & ~(ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT); + var inheritedConstraints = constraints & ~(Constraints.CONV_IMPLICIT | Constraints.CONV_EXPLICIT); switch (expression.assertionKind) { case AssertionKind.PREFIX: case AssertionKind.AS: { @@ -3095,11 +3095,11 @@ export class Compiler extends DiagnosticEmitter { flow.contextualTypeArguments ); if (!toType) return this.module.unreachable(); - return this.compileExpression(expression.expression, toType, inheritedFlags | ContextualFlags.EXPLICIT); + return this.compileExpression(expression.expression, toType, inheritedConstraints | Constraints.CONV_EXPLICIT); } case AssertionKind.NONNULL: { assert(!expression.toType); - let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedFlags); + let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedConstraints); let type = this.currentType; if (this.currentFlow.isNonnull(expr, type)) { this.info( @@ -3134,7 +3134,7 @@ export class Compiler extends DiagnosticEmitter { compileBinaryExpression( expression: BinaryExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var left = expression.left; @@ -3759,7 +3759,7 @@ export class Compiler extends DiagnosticEmitter { } if (compound) { - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); } else { rightExpr = this.compileExpression(right, leftType); rightType = this.currentType; @@ -3848,7 +3848,7 @@ export class Compiler extends DiagnosticEmitter { } if (compound) { - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -3939,7 +3939,7 @@ export class Compiler extends DiagnosticEmitter { if (compound) { leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); } else { rightExpr = this.compileExpression(right, leftType); rightType = this.currentType; @@ -4031,7 +4031,7 @@ export class Compiler extends DiagnosticEmitter { // Mathf.pow if lhs is f32 (result is f32) if (this.currentType.kind == TypeKind.F32) { - rightExpr = this.compileExpression(right, Type.f32, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, Type.f32, Constraints.CONV_IMPLICIT); rightType = this.currentType; if (!(instance = this.f32PowInstance)) { let namespace = this.program.lookupGlobal(CommonSymbols.Mathf); @@ -4065,7 +4065,7 @@ export class Compiler extends DiagnosticEmitter { left ); leftType = this.currentType; - rightExpr = this.compileExpression(right, Type.f64, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, Type.f64, Constraints.CONV_IMPLICIT); rightType = this.currentType; if (!(instance = this.f64PowInstance)) { let namespace = this.program.lookupGlobal(CommonSymbols.Math); @@ -4121,7 +4121,7 @@ export class Compiler extends DiagnosticEmitter { if (compound) { leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -4230,7 +4230,7 @@ export class Compiler extends DiagnosticEmitter { if (compound) { leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -4394,7 +4394,7 @@ export class Compiler extends DiagnosticEmitter { return this.module.unreachable(); } - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; switch (this.currentType.kind) { case TypeKind.I8: @@ -4461,7 +4461,7 @@ export class Compiler extends DiagnosticEmitter { } leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; switch (this.currentType.kind) { case TypeKind.I8: @@ -4549,7 +4549,7 @@ export class Compiler extends DiagnosticEmitter { } leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType); // must clear garbage bits - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; switch (this.currentType.kind) { case TypeKind.U8: @@ -4618,7 +4618,7 @@ export class Compiler extends DiagnosticEmitter { } if (compound) { - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -4708,7 +4708,7 @@ export class Compiler extends DiagnosticEmitter { } if (compound) { - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -4801,7 +4801,7 @@ export class Compiler extends DiagnosticEmitter { } if (compound) { - rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, Constraints.CONV_IMPLICIT); rightType = this.currentType; } else { rightExpr = this.compileExpression(right, leftType); @@ -4876,14 +4876,14 @@ export class Compiler extends DiagnosticEmitter { case Token.AMPERSAND_AMPERSAND: { // left && right -> (t = left) ? right : t let flow = this.currentFlow; - let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP); - leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags); + let inheritedConstraints = constraints & (Constraints.WILL_RETAIN | Constraints.MUST_WRAP); + leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedConstraints); leftType = this.currentType; let rightFlow = flow.fork(); this.currentFlow = rightFlow; rightFlow.inheritNonnullIfTrue(leftExpr); - rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, inheritedConstraints | Constraints.CONV_IMPLICIT); rightType = leftType; // simplify if only interested in true or false @@ -4915,7 +4915,7 @@ export class Compiler extends DiagnosticEmitter { rightExpr = this.makeRetain(rightExpr); rightAutoreleaseSkipped = true; } - } else if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { // otherwise keep right alive a little longer + } else if (!(constraints & Constraints.WILL_RETAIN)) { // otherwise keep right alive a little longer rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow); } @@ -4974,14 +4974,14 @@ export class Compiler extends DiagnosticEmitter { } case Token.BAR_BAR: { // left || right -> ((t = left) ? t : right) let flow = this.currentFlow; - let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP); - leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags); + let inheritedConstraints = constraints & (Constraints.WILL_RETAIN | Constraints.MUST_WRAP); + leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedConstraints); leftType = this.currentType; let rightFlow = flow.fork(); this.currentFlow = rightFlow; rightFlow.inheritNonnullIfFalse(leftExpr); - rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT); + rightExpr = this.compileExpression(right, leftType, inheritedConstraints | Constraints.CONV_IMPLICIT); rightType = leftType; // simplify if only interested in true or false @@ -5013,7 +5013,7 @@ export class Compiler extends DiagnosticEmitter { rightExpr = this.makeRetain(rightExpr); rightAutoreleaseSkipped = true; } - } else if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { // otherwise keep right alive a little longer + } else if (!(constraints & Constraints.WILL_RETAIN)) { // otherwise keep right alive a little longer rightExpr = this.moveAutorelease(rightExpr, rightFlow, flow); } @@ -5124,7 +5124,7 @@ export class Compiler extends DiagnosticEmitter { // it can actually resolve every kind of expression without ever having to recompile. rightType = operatorInstance.signature.parameterTypes[1]; } - var rightExpr = this.compileExpression(right, rightType, ContextualFlags.IMPLICIT); + var rightExpr = this.compileExpression(right, rightType, Constraints.CONV_IMPLICIT); return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode); } @@ -5232,7 +5232,7 @@ export class Compiler extends DiagnosticEmitter { assert(targetType != Type.void); return this.makeAssignment( target, - this.compileExpression(valueExpression, targetType, ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE), + this.compileExpression(valueExpression, targetType, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN), expression, thisExpression, elementExpression, @@ -5388,7 +5388,7 @@ export class Compiler extends DiagnosticEmitter { } let targetType = (target).type; let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType); - let elementExpr = this.compileExpression(indexExpression, Type.i32, ContextualFlags.IMPLICIT); + let elementExpr = this.compileExpression(indexExpression, Type.i32, Constraints.CONV_IMPLICIT); if (tee) { let tempLocalTarget = flow.getTempLocal(targetType); let tempLocalElement = flow.getAndFreeTempLocal(this.currentType); @@ -5700,8 +5700,8 @@ export class Compiler extends DiagnosticEmitter { expression: CallExpression, /** Contextual type indicating the return type the caller expects, if any. */ contextualType: Type, - /** Contextual flags indicating contextual conditions. */ - contextualFlags: ContextualFlags + /** Constraints indicating contextual conditions. */ + constraints: Constraints ): ExpressionRef { var module = this.module; @@ -5740,7 +5740,7 @@ export class Compiler extends DiagnosticEmitter { this.makeAllocation(classInstance) ) ), - ContextualFlags.SKIP_AUTORELEASE + Constraints.WILL_RETAIN ); assert(this.skippedAutoreleases.has(theCall)); // guaranteed let stmts: ExpressionRef[] = [ @@ -5858,7 +5858,7 @@ export class Compiler extends DiagnosticEmitter { flow.contextualTypeArguments ); if (!concreteType) return module.unreachable(); - argumentExprs[i] = this.compileExpression(argumentExpression, concreteType, ContextualFlags.IMPLICIT); + argumentExprs[i] = this.compileExpression(argumentExpression, concreteType, Constraints.CONV_IMPLICIT); } } let resolvedTypeArguments = new Array(numTypeParameters); @@ -5894,7 +5894,7 @@ export class Compiler extends DiagnosticEmitter { expression.arguments, expression, thisExpr, - contextualFlags + constraints ); } @@ -5950,7 +5950,7 @@ export class Compiler extends DiagnosticEmitter { } case ElementKind.FUNCTION_TARGET: { signature = (target).signature; - indexArg = this.compileExpression(expression.expression, (target).type, ContextualFlags.IMPLICIT); + indexArg = this.compileExpression(expression.expression, (target).type, Constraints.CONV_IMPLICIT); break; } @@ -6113,7 +6113,7 @@ export class Compiler extends DiagnosticEmitter { argumentExpressions: Expression[], reportNode: Node, thisArg: ExpressionRef = 0, - contextualFlags: ContextualFlags = ContextualFlags.NONE + constraints: Constraints = Constraints.NONE ): ExpressionRef { var numArguments = argumentExpressions.length; var signature = instance.signature; @@ -6143,13 +6143,13 @@ export class Compiler extends DiagnosticEmitter { let args = new Array(numArguments); for (let i = 0; i < numArguments; ++i) { args[i] = this.compileExpression(argumentExpressions[i], parameterTypes[i], - ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE + Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN ); } // make the inlined call (is aware of autoreleases) - let expr = this.makeCallInline(instance, args, thisArg, (contextualFlags & ContextualFlags.WILL_DROP) != 0); + let expr = this.makeCallInline(instance, args, thisArg, (constraints & Constraints.WILL_DROP) != 0); if (this.currentType.isManaged) { - if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { + if (!(constraints & Constraints.WILL_RETAIN)) { expr = this.makeAutorelease(expr, this.currentFlow); } else { this.skippedAutoreleases.add(expr); @@ -6171,15 +6171,15 @@ export class Compiler extends DiagnosticEmitter { var parameterTypes = signature.parameterTypes; for (let i = 0; i < numArguments; ++i, ++index) { operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i], - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); } assert(index == numArgumentsInclThis); if (signature.returnType.isManaged) { - if (contextualFlags & ContextualFlags.WILL_DROP) { + if (constraints & Constraints.WILL_DROP) { // Skip autorelease and simply release return this.makeCallDirect(instance, operands, reportNode, true); - } else if (contextualFlags & ContextualFlags.SKIP_AUTORELEASE) { + } else if (constraints & Constraints.WILL_RETAIN) { // Skip autorelease and remember let expr = this.makeCallDirect(instance, operands, reportNode, false, true); this.skippedAutoreleases.add(expr); @@ -6189,7 +6189,7 @@ export class Compiler extends DiagnosticEmitter { } } return this.makeCallDirect(instance, operands, reportNode, - (contextualFlags & ContextualFlags.WILL_DROP) != 0 + (constraints & Constraints.WILL_DROP) != 0 ); } @@ -6256,7 +6256,7 @@ export class Compiler extends DiagnosticEmitter { let initExpr = this.compileExpression( assert(instance.prototype.signatureNode.parameters[i].initializer), initType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); let argumentLocal = flow.addScopedLocal(signature.getParameterName(i), initType); if (!flow.canOverflow(initExpr, initType)) flow.setLocalFlag(argumentLocal.index, LocalFlags.WRAPPED); @@ -6398,7 +6398,7 @@ export class Compiler extends DiagnosticEmitter { this.compileExpression( initializer, type, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) ); } else { @@ -6715,7 +6715,7 @@ export class Compiler extends DiagnosticEmitter { operands.push(this.compileExpression( parameterNodes[i].initializer, parameterTypes[i], - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT )); continue; } @@ -6726,7 +6726,7 @@ export class Compiler extends DiagnosticEmitter { if (this.compileGlobal(global)) { if (global.is(CommonFlags.INLINED)) { operands.push( - this.compileInlineConstant(global, parameterTypes[i], ContextualFlags.IMPLICIT) + this.compileInlineConstant(global, parameterTypes[i], Constraints.CONV_IMPLICIT) ); } else { operands.push( @@ -6817,7 +6817,7 @@ export class Compiler extends DiagnosticEmitter { var parameterTypes = signature.parameterTypes; for (let i = 0; i < numArguments; ++i, ++index) { operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i], - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); } assert(index == numArgumentsInclThis); @@ -6881,24 +6881,24 @@ export class Compiler extends DiagnosticEmitter { compileCommaExpression( expression: CommaExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var expressions = expression.expressions; var numExpressions = expressions.length; var exprs = new Array(numExpressions--); for (let i = 0; i < numExpressions; ++i) { exprs[i] = this.compileExpression(expressions[i], Type.void, // drop all except last - ContextualFlags.IMPLICIT | ContextualFlags.WILL_DROP + Constraints.CONV_IMPLICIT | Constraints.WILL_DROP ); } - exprs[numExpressions] = this.compileExpression(expressions[numExpressions], contextualType, contextualFlags); + exprs[numExpressions] = this.compileExpression(expressions[numExpressions], contextualType, constraints); return this.module.block(null, exprs, this.currentType.toNativeType()); } compileElementAccessExpression( expression: ElementAccessExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var target = this.resolver.resolveElementAccessExpression( expression, @@ -6917,11 +6917,11 @@ export class Compiler extends DiagnosticEmitter { return this.module.unreachable(); } let thisArg = this.compileExpression(expression.expression, (target).type, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ); return this.compileCallDirect(indexedGet, [ expression.elementExpression - ], expression, thisArg, contextualFlags & (ContextualFlags.WILL_DROP | ContextualFlags.SKIP_AUTORELEASE)); + ], expression, thisArg, constraints); } } this.error( @@ -6934,7 +6934,7 @@ export class Compiler extends DiagnosticEmitter { compileFunctionExpression( expression: FunctionExpression, contextualSignature: Signature | null, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var declaration = expression.declaration.clone(); // generic contexts can have multiple assert(!declaration.typeParameters); // function expression cannot be generic @@ -7088,7 +7088,7 @@ export class Compiler extends DiagnosticEmitter { compileIdentifierExpression( expression: IdentifierExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var flow = this.currentFlow; @@ -7215,7 +7215,7 @@ export class Compiler extends DiagnosticEmitter { let type = (target).type; assert(type != Type.void); if ((target).is(CommonFlags.INLINED)) { - return this.compileInlineConstant(target, contextualType, contextualFlags); + return this.compileInlineConstant(target, contextualType, constraints); } let localIndex = (target).index; assert(localIndex >= 0); @@ -7232,7 +7232,7 @@ export class Compiler extends DiagnosticEmitter { let type = (target).type; assert(type != Type.void); if ((target).is(CommonFlags.INLINED)) { - return this.compileInlineConstant(target, contextualType, contextualFlags); + return this.compileInlineConstant(target, contextualType, constraints); } this.currentType = type; return this.module.global_get((target).internalName, type.toNativeType()); @@ -7275,7 +7275,7 @@ export class Compiler extends DiagnosticEmitter { compileInstanceOfExpression( expression: InstanceOfExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; // NOTE that this differs from TypeScript in that the rhs is a type, not an expression. at the @@ -7291,7 +7291,7 @@ export class Compiler extends DiagnosticEmitter { // instanceof - must be exact if (!expectedType.is(TypeFlags.REFERENCE)) { return module.block(null, [ - this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), + module.drop(expr), module.i32(actualType == expectedType ? 1 : 0) ], NativeType.I32); } @@ -7299,7 +7299,7 @@ export class Compiler extends DiagnosticEmitter { // instanceof - always false if (!actualType.is(TypeFlags.REFERENCE)) { return module.block(null, [ - this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0,false, expression.expression), + module.drop(expr), module.i32(0) ], NativeType.I32); } @@ -7356,7 +7356,7 @@ export class Compiler extends DiagnosticEmitter { // downcast - check statically if (actualType.isAssignableTo(expectedType)) { return module.block(null, [ - this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), + this.convertExpression(expr, actualType, Type.void, false, false, expression.expression), module.i32(1) ], NativeType.I32); @@ -7395,7 +7395,7 @@ export class Compiler extends DiagnosticEmitter { // false return module.block(null, [ - this.convertExpression(expr, actualType, Type.void, (contextualFlags & ContextualFlags.EXPLICIT) != 0, false, expression.expression), + module.drop(expr), module.i32(0) ], NativeType.I32); } @@ -7403,7 +7403,7 @@ export class Compiler extends DiagnosticEmitter { compileLiteralExpression( expression: LiteralExpression, contextualType: Type, - contextualFlags: ContextualFlags, + constraints: Constraints, implicitlyNegate: bool = false ): ExpressionRef { var module = this.module; @@ -7416,8 +7416,7 @@ export class Compiler extends DiagnosticEmitter { return this.compileArrayLiteral( assert(classType.typeArguments)[0], (expression).elementExpressions, - false, // TODO: isConst? - contextualFlags, + constraints, expression ); } @@ -7484,8 +7483,7 @@ export class Compiler extends DiagnosticEmitter { compileArrayLiteral( elementType: Type, expressions: (Expression | null)[], - isConst: bool, - contextualFlags: ContextualFlags, + constraints: Constraints, reportNode: Node ): ExpressionRef { var module = this.module; @@ -7510,7 +7508,7 @@ export class Compiler extends DiagnosticEmitter { let expr = expression ? module.precomputeExpression( this.compileExpression(expression, elementType, - ContextualFlags.IMPLICIT + Constraints.CONV_IMPLICIT ) ) : elementType.toNativeZero(module); @@ -7533,7 +7531,7 @@ export class Compiler extends DiagnosticEmitter { // make both the buffer and array header static if assigned to a global. this can't be done // if inside of a function because each invocation must create a new array reference then. - if (contextualFlags & ContextualFlags.STATIC_CAPABLE) { + if (constraints & Constraints.PREFER_STATIC) { let arraySegment = this.ensureStaticArrayHeader(elementType, bufferSegment); let arrayAddress = i64_add(arraySegment.offset, i64_new(runtimeHeaderSize)); this.currentType = arrayType; @@ -7693,7 +7691,7 @@ export class Compiler extends DiagnosticEmitter { exprs[i + 1] = this.module.store( // TODO: handle setters as well type.byteSize, this.module.local_get(tempLocal.index, this.options.nativeSizeType), - this.compileExpression(values[i], (member).type, ContextualFlags.IMPLICIT), + this.compileExpression(values[i], (member).type, Constraints.CONV_IMPLICIT), type.toNativeType(), (member).memoryOffset ); @@ -7719,7 +7717,7 @@ export class Compiler extends DiagnosticEmitter { compileNewExpression( expression: NewExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var flow = this.currentFlow; @@ -7761,8 +7759,8 @@ export class Compiler extends DiagnosticEmitter { ); } if (!classInstance) return module.unreachable(); - if (contextualType == Type.void) contextualFlags |= ContextualFlags.WILL_DROP; - return this.compileInstantiate(classInstance, expression.arguments, contextualFlags, expression); + if (contextualType == Type.void) constraints |= Constraints.WILL_DROP; + return this.compileInstantiate(classInstance, expression.arguments, constraints, expression); } /** Gets the compiled constructor of the specified class or generates one if none is present. */ @@ -7879,7 +7877,7 @@ export class Compiler extends DiagnosticEmitter { /** Constructor arguments. */ argumentExpressions: Expression[], /** Contextual flags. */ - contextualFlags: ContextualFlags, + constraints: Constraints, /** Node to report on. */ reportNode: Node ): ExpressionRef { @@ -7889,7 +7887,7 @@ export class Compiler extends DiagnosticEmitter { argumentExpressions, reportNode, this.options.usizeType.toNativeZero(this.module), - contextualFlags + constraints ); if (getExpressionType(expr) != NativeType.None) { // possibly IMM_DROPPED this.currentType = classInstance.type; // important because a super ctor could be called @@ -7905,7 +7903,7 @@ export class Compiler extends DiagnosticEmitter { compilePropertyAccessExpression( propertyAccess: PropertyAccessExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var flow = this.currentFlow; @@ -7923,7 +7921,7 @@ export class Compiler extends DiagnosticEmitter { let globalType = (target).type; assert(globalType != Type.void); if ((target).is(CommonFlags.INLINED)) { - return this.compileInlineConstant(target, contextualType, contextualFlags); + return this.compileInlineConstant(target, contextualType, constraints); } this.currentType = globalType; return module.global_get((target).internalName, globalType.toNativeType()); @@ -7985,7 +7983,7 @@ export class Compiler extends DiagnosticEmitter { compileTernaryExpression( expression: TernaryExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var ifThen = expression.ifThen; var ifElse = expression.ifElse; @@ -8008,15 +8006,17 @@ export class Compiler extends DiagnosticEmitter { : this.compileExpression(ifElse, contextualType); } + var inheritedConstraints = constraints & Constraints.WILL_RETAIN; + var ifThenFlow = outerFlow.fork(); this.currentFlow = ifThenFlow; - var ifThenExpr = this.compileExpression(ifThen, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE); + var ifThenExpr = this.compileExpression(ifThen, contextualType, inheritedConstraints); var ifThenType = this.currentType; var IfThenAutoreleaseSkipped = this.skippedAutoreleases.has(ifThenExpr); var ifElseFlow = outerFlow.fork(); this.currentFlow = ifElseFlow; - var ifElseExpr = this.compileExpression(ifElse, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE); + var ifElseExpr = this.compileExpression(ifElse, contextualType, inheritedConstraints); var ifElseType = this.currentType; var ifElseAutoreleaseSkipped = this.skippedAutoreleases.has(ifElseExpr); @@ -8052,7 +8052,7 @@ export class Compiler extends DiagnosticEmitter { ifElseAutoreleaseSkipped = true; } } else if (!IfThenAutoreleaseSkipped && commonType.isManaged) { // keep alive a little longer - // if (!(contextualFlags & ContextualFlags.SKIP_AUTORELEASE)) { + // if (!(constraints & Constraints.WILL_RETAIN)) { ifThenExpr = this.moveAutorelease(ifThenExpr, ifThenFlow, outerFlow); ifElseExpr = this.moveAutorelease(ifElseExpr, ifElseFlow, outerFlow); // } @@ -8076,7 +8076,7 @@ export class Compiler extends DiagnosticEmitter { compileUnaryPostfixExpression( expression: UnaryPostfixExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var flow = this.currentFlow; @@ -8085,7 +8085,7 @@ export class Compiler extends DiagnosticEmitter { var getValue = this.compileExpression( // reports expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // shortcut if compiling the getter already failed @@ -8306,7 +8306,7 @@ export class Compiler extends DiagnosticEmitter { compileUnaryPrefixExpression( expression: UnaryPrefixExpression, contextualType: Type, - contextualFlags: ContextualFlags + constraints: Constraints ): ExpressionRef { var module = this.module; var compound = false; @@ -8317,7 +8317,7 @@ export class Compiler extends DiagnosticEmitter { expr = this.compileExpression( expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8346,7 +8346,7 @@ export class Compiler extends DiagnosticEmitter { (expression.operand).literalKind == LiteralKind.FLOAT )) { // implicitly negate integer and float literals. also enables proper checking of literal ranges. - expr = this.compileLiteralExpression(expression.operand, contextualType, ContextualFlags.NONE, true); + expr = this.compileLiteralExpression(expression.operand, contextualType, Constraints.NONE, true); // compileExpression normally does this: if (this.options.sourceMap) this.addDebugLocation(expr, expression.range); break; @@ -8355,7 +8355,7 @@ export class Compiler extends DiagnosticEmitter { expr = this.compileExpression( expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8422,7 +8422,7 @@ export class Compiler extends DiagnosticEmitter { expr = this.compileExpression( expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8489,7 +8489,7 @@ export class Compiler extends DiagnosticEmitter { expr = this.compileExpression( expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8555,7 +8555,7 @@ export class Compiler extends DiagnosticEmitter { expr = this.compileExpression( expression.operand, contextualType.exceptVoid, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8583,7 +8583,7 @@ export class Compiler extends DiagnosticEmitter { : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, - ContextualFlags.NONE + Constraints.NONE ); // check operator overload @@ -8873,7 +8873,7 @@ export class Compiler extends DiagnosticEmitter { let initializerNode = field.prototype.initializerNode; if (initializerNode) { // use initializer let initExpr = this.compileExpression(initializerNode, fieldType, // reports - ContextualFlags.IMPLICIT | ContextualFlags.SKIP_AUTORELEASE + Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN ); if (fieldType.isManaged && !this.skippedAutoreleases.has(initExpr)) { initExpr = this.makeRetain(initExpr);