mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-27 07:52:14 +00:00
Use a special 'auto' type in type inference
This commit is contained in:
parent
40dac8269d
commit
acda2d05c8
@ -648,7 +648,7 @@ export function compileCall(
|
|||||||
checkTypeAbsent(typeArguments, reportNode, prototype) |
|
checkTypeAbsent(typeArguments, reportNode, prototype) |
|
||||||
checkArgsRequired(operands, 1, reportNode, compiler)
|
checkArgsRequired(operands, 1, reportNode, compiler)
|
||||||
) return module.unreachable();
|
) return module.unreachable();
|
||||||
let expr = compiler.compileExpressionRetainType(operands[0], Type.i32);
|
let expr = compiler.compileExpression(operands[0], Type.auto);
|
||||||
compiler.currentType = Type.bool;
|
compiler.currentType = Type.bool;
|
||||||
return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0);
|
return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0);
|
||||||
}
|
}
|
||||||
@ -1555,6 +1555,7 @@ export function compileCall(
|
|||||||
) return module.unreachable();
|
) return module.unreachable();
|
||||||
let type = typeArguments![0];
|
let type = typeArguments![0];
|
||||||
let outType = (
|
let outType = (
|
||||||
|
contextualType != Type.auto &&
|
||||||
type.is(TypeFlags.INTEGER) &&
|
type.is(TypeFlags.INTEGER) &&
|
||||||
contextualType.is(TypeFlags.INTEGER) &&
|
contextualType.is(TypeFlags.INTEGER) &&
|
||||||
contextualType.size > type.size
|
contextualType.size > type.size
|
||||||
@ -1965,7 +1966,7 @@ export function compileCall(
|
|||||||
) return module.unreachable();
|
) return module.unreachable();
|
||||||
let arg0 = typeArguments
|
let arg0 = typeArguments
|
||||||
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT)
|
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT)
|
||||||
: compiler.compileExpressionRetainType(operands[0], Type.i32);
|
: compiler.compileExpression(operands[0], Type.auto);
|
||||||
let type = compiler.currentType;
|
let type = compiler.currentType;
|
||||||
if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) {
|
if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) {
|
||||||
compiler.error(
|
compiler.error(
|
||||||
@ -1976,7 +1977,7 @@ export function compileCall(
|
|||||||
}
|
}
|
||||||
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT);
|
let arg1 = compiler.compileExpression(operands[1], type, ContextualFlags.IMPLICIT);
|
||||||
let arg2 = compiler.makeIsTrueish(
|
let arg2 = compiler.makeIsTrueish(
|
||||||
compiler.compileExpressionRetainType(operands[2], Type.bool),
|
compiler.compileExpression(operands[2], Type.bool),
|
||||||
compiler.currentType // ^
|
compiler.currentType // ^
|
||||||
);
|
);
|
||||||
compiler.currentType = type;
|
compiler.currentType = type;
|
||||||
@ -2060,7 +2061,7 @@ export function compileCall(
|
|||||||
checkArgsRequired(operands, 1, reportNode, compiler)
|
checkArgsRequired(operands, 1, reportNode, compiler)
|
||||||
) return module.unreachable();
|
) return module.unreachable();
|
||||||
let toType = typeArguments![0];
|
let toType = typeArguments![0];
|
||||||
let arg0 = compiler.compileExpressionRetainType(operands[0], toType);
|
let arg0 = compiler.compileExpression(operands[0], toType);
|
||||||
let fromType = compiler.currentType;
|
let fromType = compiler.currentType;
|
||||||
compiler.currentType = toType;
|
compiler.currentType = toType;
|
||||||
if (fromType.size != toType.size) {
|
if (fromType.size != toType.size) {
|
||||||
@ -2085,7 +2086,7 @@ export function compileCall(
|
|||||||
}
|
}
|
||||||
let arg0 = typeArguments
|
let arg0 = typeArguments
|
||||||
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP)
|
? compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT | ContextualFlags.WRAP)
|
||||||
: compiler.compileExpressionRetainType(operands[0], Type.bool, ContextualFlags.WRAP);
|
: compiler.compileExpression(operands[0], Type.bool, ContextualFlags.WRAP);
|
||||||
let type = compiler.currentType;
|
let type = compiler.currentType;
|
||||||
compiler.currentType = type.nonNullableType;
|
compiler.currentType = type.nonNullableType;
|
||||||
|
|
||||||
@ -2272,7 +2273,7 @@ export function compileCall(
|
|||||||
checkArgsOptional(operands, 1, i32.MAX_VALUE, reportNode, compiler)
|
checkArgsOptional(operands, 1, i32.MAX_VALUE, reportNode, compiler)
|
||||||
) return module.unreachable();
|
) return module.unreachable();
|
||||||
let returnType = typeArguments ? typeArguments[0] : contextualType;
|
let returnType = typeArguments ? typeArguments[0] : contextualType;
|
||||||
let arg0 = compiler.compileExpressionRetainType(operands[0], Type.u32);
|
let arg0 = compiler.compileExpression(operands[0], Type.u32);
|
||||||
let arg0Type = compiler.currentType;
|
let arg0Type = compiler.currentType;
|
||||||
if (!(
|
if (!(
|
||||||
arg0Type == Type.u32 || // either plain index
|
arg0Type == Type.u32 || // either plain index
|
||||||
@ -2290,7 +2291,7 @@ export function compileCall(
|
|||||||
let parameterTypes = new Array<Type>(numOperands);
|
let parameterTypes = new Array<Type>(numOperands);
|
||||||
let nativeParamTypes = new Array<NativeType>(numOperands);
|
let nativeParamTypes = new Array<NativeType>(numOperands);
|
||||||
for (let i = 0; i < numOperands; ++i) {
|
for (let i = 0; i < numOperands; ++i) {
|
||||||
operandExprs[i] = compiler.compileExpressionRetainType(operands[1 + i], Type.i32);
|
operandExprs[i] = compiler.compileExpression(operands[1 + i], Type.i32);
|
||||||
let operandType = compiler.currentType;
|
let operandType = compiler.currentType;
|
||||||
parameterTypes[i] = operandType;
|
parameterTypes[i] = operandType;
|
||||||
nativeParamTypes[i] = operandType.toNativeType();
|
nativeParamTypes[i] = operandType.toNativeType();
|
||||||
@ -4232,21 +4233,17 @@ function evaluateConstantType(
|
|||||||
return typeArguments[0];
|
return typeArguments[0];
|
||||||
}
|
}
|
||||||
if (operands.length == 1) { // optional type argument
|
if (operands.length == 1) { // optional type argument
|
||||||
if (typeArguments) {
|
if (typeArguments !== null && typeArguments.length) {
|
||||||
if (typeArguments.length == 1) {
|
if (typeArguments.length > 1) {
|
||||||
compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT);
|
|
||||||
} else {
|
|
||||||
if (typeArguments.length) {
|
|
||||||
compiler.error(
|
compiler.error(
|
||||||
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||||
reportNode.typeArgumentsRange, "1", typeArguments.length.toString(10)
|
reportNode.typeArgumentsRange, "1", typeArguments.length.toString(10)
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
compiler.compileExpressionRetainType(operands[0], Type.i32);
|
compiler.compileExpression(operands[0], typeArguments[0], ContextualFlags.IMPLICIT);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
compiler.compileExpressionRetainType(operands[0], Type.i32);
|
compiler.compileExpression(operands[0], Type.auto);
|
||||||
}
|
}
|
||||||
return compiler.currentType;
|
return compiler.currentType;
|
||||||
}
|
}
|
||||||
|
287
src/compiler.ts
287
src/compiler.ts
@ -248,10 +248,8 @@ export const enum ContextualFlags {
|
|||||||
WILL_DROP = 1 << 3,
|
WILL_DROP = 1 << 3,
|
||||||
/** Value is known to be immediately assigned to a retaining target. */
|
/** Value is known to be immediately assigned to a retaining target. */
|
||||||
SKIP_AUTORELEASE = 1 << 4,
|
SKIP_AUTORELEASE = 1 << 4,
|
||||||
/** Is the last statement in a function body. */
|
|
||||||
LAST_IN_BODY = 1 << 5,
|
|
||||||
/** Data can be compiled statically. */
|
/** Data can be compiled statically. */
|
||||||
STATIC_CAPABLE = 1 << 6
|
STATIC_CAPABLE = 1 << 5
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runtime features to be activated by the compiler. */
|
/** Runtime features to be activated by the compiler. */
|
||||||
@ -814,7 +812,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (global.hasDecorator(DecoratorFlags.LAZY)) {
|
if (global.hasDecorator(DecoratorFlags.LAZY)) {
|
||||||
this.currentFlow = global.file.startFunction.flow;
|
this.currentFlow = global.file.startFunction.flow;
|
||||||
}
|
}
|
||||||
initExpr = this.compileExpression(initializerNode, Type.i32, // reports
|
initExpr = this.compileExpression(initializerNode, Type.auto, // reports
|
||||||
ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE
|
ContextualFlags.WRAP | ContextualFlags.SKIP_AUTORELEASE
|
||||||
);
|
);
|
||||||
if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
|
if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
|
||||||
@ -1686,70 +1684,70 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
compileStatement(
|
compileStatement(
|
||||||
statement: Statement,
|
statement: Statement,
|
||||||
contextualFlags: ContextualFlags = ContextualFlags.NONE
|
isLastInBody: bool = false
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var stmt: ExpressionRef;
|
var stmt: ExpressionRef;
|
||||||
switch (statement.kind) {
|
switch (statement.kind) {
|
||||||
case NodeKind.BLOCK: {
|
case NodeKind.BLOCK: {
|
||||||
stmt = this.compileBlockStatement(<BlockStatement>statement, contextualFlags);
|
stmt = this.compileBlockStatement(<BlockStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.BREAK: {
|
case NodeKind.BREAK: {
|
||||||
stmt = this.compileBreakStatement(<BreakStatement>statement, contextualFlags);
|
stmt = this.compileBreakStatement(<BreakStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.CONTINUE: {
|
case NodeKind.CONTINUE: {
|
||||||
stmt = this.compileContinueStatement(<ContinueStatement>statement, contextualFlags);
|
stmt = this.compileContinueStatement(<ContinueStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.DO: {
|
case NodeKind.DO: {
|
||||||
stmt = this.compileDoStatement(<DoStatement>statement, contextualFlags);
|
stmt = this.compileDoStatement(<DoStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.EMPTY: {
|
case NodeKind.EMPTY: {
|
||||||
stmt = this.compileEmptyStatement(<EmptyStatement>statement, contextualFlags);
|
stmt = this.compileEmptyStatement(<EmptyStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.EXPRESSION: {
|
case NodeKind.EXPRESSION: {
|
||||||
stmt = this.compileExpressionStatement(<ExpressionStatement>statement, contextualFlags);
|
stmt = this.compileExpressionStatement(<ExpressionStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.FOR: {
|
case NodeKind.FOR: {
|
||||||
stmt = this.compileForStatement(<ForStatement>statement, contextualFlags);
|
stmt = this.compileForStatement(<ForStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.IF: {
|
case NodeKind.IF: {
|
||||||
stmt = this.compileIfStatement(<IfStatement>statement, contextualFlags);
|
stmt = this.compileIfStatement(<IfStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.RETURN: {
|
case NodeKind.RETURN: {
|
||||||
stmt = this.compileReturnStatement(<ReturnStatement>statement, contextualFlags);
|
stmt = this.compileReturnStatement(<ReturnStatement>statement, isLastInBody);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.SWITCH: {
|
case NodeKind.SWITCH: {
|
||||||
stmt = this.compileSwitchStatement(<SwitchStatement>statement, contextualFlags);
|
stmt = this.compileSwitchStatement(<SwitchStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.THROW: {
|
case NodeKind.THROW: {
|
||||||
stmt = this.compileThrowStatement(<ThrowStatement>statement, contextualFlags);
|
stmt = this.compileThrowStatement(<ThrowStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.TRY: {
|
case NodeKind.TRY: {
|
||||||
stmt = this.compileTryStatement(<TryStatement>statement, contextualFlags);
|
stmt = this.compileTryStatement(<TryStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.VARIABLE: {
|
case NodeKind.VARIABLE: {
|
||||||
stmt = this.compileVariableStatement(<VariableStatement>statement, contextualFlags);
|
stmt = this.compileVariableStatement(<VariableStatement>statement);
|
||||||
if (!stmt) stmt = module.nop();
|
if (!stmt) stmt = module.nop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.VOID: {
|
case NodeKind.VOID: {
|
||||||
stmt = this.compileVoidStatement(<VoidStatement>statement, contextualFlags);
|
stmt = this.compileVoidStatement(<VoidStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.WHILE: {
|
case NodeKind.WHILE: {
|
||||||
stmt = this.compileWhileStatement(<WhileStatement>statement, contextualFlags);
|
stmt = this.compileWhileStatement(<WhileStatement>statement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.TYPEDECLARATION: {
|
case NodeKind.TYPEDECLARATION: {
|
||||||
@ -1783,11 +1781,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var module = this.module;
|
var module = this.module;
|
||||||
var flow = this.currentFlow;
|
var flow = this.currentFlow;
|
||||||
for (let i = 0; i < numStatements; ++i) {
|
for (let i = 0; i < numStatements; ++i) {
|
||||||
let stmt = this.compileStatement(statements[i],
|
let stmt = this.compileStatement(statements[i], isBody && i == numStatements - 1);
|
||||||
isBody && i == numStatements - 1
|
|
||||||
? ContextualFlags.LAST_IN_BODY
|
|
||||||
: ContextualFlags.NONE
|
|
||||||
);
|
|
||||||
switch (getExpressionId(stmt)) {
|
switch (getExpressionId(stmt)) {
|
||||||
case ExpressionId.Block: {
|
case ExpressionId.Block: {
|
||||||
if (!getBlockName(stmt)) {
|
if (!getBlockName(stmt)) {
|
||||||
@ -1808,8 +1802,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileBlockStatement(
|
compileBlockStatement(
|
||||||
statement: BlockStatement,
|
statement: BlockStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var statements = statement.statements;
|
var statements = statement.statements;
|
||||||
var outerFlow = this.currentFlow;
|
var outerFlow = this.currentFlow;
|
||||||
@ -1825,8 +1818,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileBreakStatement(
|
compileBreakStatement(
|
||||||
statement: BreakStatement,
|
statement: BreakStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
if (statement.label) {
|
if (statement.label) {
|
||||||
@ -1859,8 +1851,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileContinueStatement(
|
compileContinueStatement(
|
||||||
statement: ContinueStatement,
|
statement: ContinueStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var label = statement.label;
|
var label = statement.label;
|
||||||
@ -1895,8 +1886,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileDoStatement(
|
compileDoStatement(
|
||||||
statement: DoStatement,
|
statement: DoStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
|
|
||||||
@ -1967,24 +1957,19 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileEmptyStatement(
|
compileEmptyStatement(
|
||||||
statement: EmptyStatement,
|
statement: EmptyStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
return this.module.nop();
|
return this.module.nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileExpressionStatement(
|
compileExpressionStatement(
|
||||||
statement: ExpressionStatement,
|
statement: ExpressionStatement
|
||||||
contextualFlags: ContextualFlags,
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
return this.compileExpression(statement.expression, Type.void,
|
return this.compileExpression(statement.expression, Type.void, ContextualFlags.IMPLICIT);
|
||||||
contextualFlags | ContextualFlags.EXPLICIT | ContextualFlags.WILL_DROP
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileForStatement(
|
compileForStatement(
|
||||||
statement: ForStatement,
|
statement: ForStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
|
|
||||||
@ -2005,7 +1990,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (statement.condition) {
|
if (statement.condition) {
|
||||||
condExpr = module.precomputeExpression(
|
condExpr = module.precomputeExpression(
|
||||||
this.makeIsTrueish(
|
this.makeIsTrueish(
|
||||||
this.compileExpressionRetainType(<Expression>statement.condition, Type.bool),
|
this.compileExpression(<Expression>statement.condition, Type.bool),
|
||||||
this.currentType
|
this.currentType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -2113,8 +2098,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileIfStatement(
|
compileIfStatement(
|
||||||
statement: IfStatement,
|
statement: IfStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var ifTrue = statement.ifTrue;
|
var ifTrue = statement.ifTrue;
|
||||||
@ -2124,7 +2108,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// The condition doesn't initiate a branch yet
|
// The condition doesn't initiate a branch yet
|
||||||
var condExpr = module.precomputeExpression(
|
var condExpr = module.precomputeExpression(
|
||||||
this.makeIsTrueish(
|
this.makeIsTrueish(
|
||||||
this.compileExpressionRetainType(statement.condition, Type.bool),
|
this.compileExpression(statement.condition, Type.bool),
|
||||||
this.currentType
|
this.currentType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -2189,7 +2173,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
compileReturnStatement(
|
compileReturnStatement(
|
||||||
statement: ReturnStatement,
|
statement: ReturnStatement,
|
||||||
contextualFlags: ContextualFlags
|
isLastInBody: bool
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var expr: ExpressionRef = 0;
|
var expr: ExpressionRef = 0;
|
||||||
@ -2256,7 +2240,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
flow.freeScopedLocals();
|
flow.freeScopedLocals();
|
||||||
|
|
||||||
// If the last statement anyway, make it the block's return value
|
// If the last statement anyway, make it the block's return value
|
||||||
if ((contextualFlags & ContextualFlags.LAST_IN_BODY) != 0 && expr && returnType != Type.void) {
|
if (isLastInBody && expr && returnType != Type.void) {
|
||||||
if (!stmts.length) return expr;
|
if (!stmts.length) return expr;
|
||||||
stmts.push(expr);
|
stmts.push(expr);
|
||||||
return module.block(null, stmts, returnType.toNativeType());
|
return module.block(null, stmts, returnType.toNativeType());
|
||||||
@ -2276,7 +2260,9 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return module.block(null, stmts);
|
return module.block(null, stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSwitchStatement(statement: SwitchStatement, contextualFlags: ContextualFlags): ExpressionRef {
|
compileSwitchStatement(
|
||||||
|
statement: SwitchStatement
|
||||||
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
|
|
||||||
var cases = statement.cases;
|
var cases = statement.cases;
|
||||||
@ -2389,8 +2375,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileThrowStatement(
|
compileThrowStatement(
|
||||||
statement: ThrowStatement,
|
statement: ThrowStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
var flow = this.currentFlow;
|
var flow = this.currentFlow;
|
||||||
|
|
||||||
@ -2413,8 +2398,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileTryStatement(
|
compileTryStatement(
|
||||||
statement: TryStatement,
|
statement: TryStatement
|
||||||
contextualFlags: ContextualFlags
|
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
// TODO: can't yet support something like: try { return ... } finally { ... }
|
// TODO: can't yet support something like: try { return ... } finally { ... }
|
||||||
// worthwhile to investigate lowering returns to block results (here)?
|
// worthwhile to investigate lowering returns to block results (here)?
|
||||||
@ -2426,7 +2410,9 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compiles a variable statement. Returns `0` if an initializer is not necessary. */
|
/** Compiles a variable statement. Returns `0` if an initializer is not necessary. */
|
||||||
compileVariableStatement(statement: VariableStatement, contextualFlags: ContextualFlags): ExpressionRef {
|
compileVariableStatement(
|
||||||
|
statement: VariableStatement
|
||||||
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var declarations = statement.declarations;
|
var declarations = statement.declarations;
|
||||||
var numDeclarations = declarations.length;
|
var numDeclarations = declarations.length;
|
||||||
@ -2458,7 +2444,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// Otherwise infer type from initializer
|
// Otherwise infer type from initializer
|
||||||
} else if (declaration.initializer) {
|
} else if (declaration.initializer) {
|
||||||
initExpr = this.compileExpressionRetainType(declaration.initializer, Type.void,
|
initExpr = this.compileExpression(declaration.initializer, Type.auto,
|
||||||
ContextualFlags.SKIP_AUTORELEASE
|
ContextualFlags.SKIP_AUTORELEASE
|
||||||
); // reports
|
); // reports
|
||||||
initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr);
|
initAutoreleaseSkipped = this.skippedAutoreleases.has(initExpr);
|
||||||
@ -2617,20 +2603,24 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
: flatten(module, initializers, NativeType.None);
|
: flatten(module, initializers, NativeType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileVoidStatement(statement: VoidStatement, contextualFlags: ContextualFlags): ExpressionRef {
|
compileVoidStatement(
|
||||||
|
statement: VoidStatement
|
||||||
|
): ExpressionRef {
|
||||||
return this.compileExpression(statement.expression, Type.void,
|
return this.compileExpression(statement.expression, Type.void,
|
||||||
ContextualFlags.EXPLICIT | ContextualFlags.WILL_DROP
|
ContextualFlags.EXPLICIT | ContextualFlags.WILL_DROP
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileWhileStatement(statement: WhileStatement, contextualFlags: ContextualFlags): ExpressionRef {
|
compileWhileStatement(
|
||||||
|
statement: WhileStatement
|
||||||
|
): ExpressionRef {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var outerFlow = this.currentFlow;
|
var outerFlow = this.currentFlow;
|
||||||
|
|
||||||
// Compile condition
|
// Compile condition
|
||||||
var condExpr = module.precomputeExpression(
|
var condExpr = module.precomputeExpression(
|
||||||
this.makeIsTrueish(
|
this.makeIsTrueish(
|
||||||
this.compileExpressionRetainType(statement.condition, Type.bool),
|
this.compileExpression(statement.condition, Type.bool),
|
||||||
this.currentType
|
this.currentType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -2885,20 +2875,6 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compiles an expression while retaining the type, that is not void, it ultimately compiles to. */
|
|
||||||
compileExpressionRetainType(
|
|
||||||
expression: Expression,
|
|
||||||
contextualType: Type,
|
|
||||||
contextualFlags: ContextualFlags = ContextualFlags.NONE
|
|
||||||
): ExpressionRef {
|
|
||||||
return this.compileExpression(expression,
|
|
||||||
contextualType == Type.void
|
|
||||||
? Type.i32 // default to i32
|
|
||||||
: contextualType,
|
|
||||||
(contextualFlags & ~(ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compiles and precomputes an expression, possibly yielding a costant value. */
|
/** Compiles and precomputes an expression, possibly yielding a costant value. */
|
||||||
precomputeExpression(
|
precomputeExpression(
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
@ -3108,6 +3084,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
contextualType: Type,
|
contextualType: Type,
|
||||||
contextualFlags: ContextualFlags
|
contextualFlags: ContextualFlags
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
|
var inheritedFlags = contextualFlags & ~(ContextualFlags.IMPLICIT | ContextualFlags.EXPLICIT);
|
||||||
switch (expression.assertionKind) {
|
switch (expression.assertionKind) {
|
||||||
case AssertionKind.PREFIX:
|
case AssertionKind.PREFIX:
|
||||||
case AssertionKind.AS: {
|
case AssertionKind.AS: {
|
||||||
@ -3118,13 +3095,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
flow.contextualTypeArguments
|
flow.contextualTypeArguments
|
||||||
);
|
);
|
||||||
if (!toType) return this.module.unreachable();
|
if (!toType) return this.module.unreachable();
|
||||||
return this.compileExpression(expression.expression, toType,
|
return this.compileExpression(expression.expression, toType, inheritedFlags | ContextualFlags.EXPLICIT);
|
||||||
contextualFlags | ContextualFlags.EXPLICIT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
case AssertionKind.NONNULL: {
|
case AssertionKind.NONNULL: {
|
||||||
assert(!expression.toType);
|
assert(!expression.toType);
|
||||||
let expr = this.compileExpressionRetainType(expression.expression, contextualType);
|
let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedFlags);
|
||||||
let type = this.currentType;
|
let type = this.currentType;
|
||||||
if (this.currentFlow.isNonnull(expr, type)) {
|
if (this.currentFlow.isNonnull(expr, type)) {
|
||||||
this.info(
|
this.info(
|
||||||
@ -3177,7 +3152,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var operator = expression.operator;
|
var operator = expression.operator;
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case Token.LESSTHAN: {
|
case Token.LESSTHAN: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3197,7 +3172,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.unreachable();
|
return this.module.unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3277,7 +3252,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.GREATERTHAN: {
|
case Token.GREATERTHAN: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3297,7 +3272,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.unreachable();
|
return this.module.unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3377,7 +3352,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.LESSTHAN_EQUALS: {
|
case Token.LESSTHAN_EQUALS: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3397,7 +3372,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.unreachable();
|
return this.module.unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3477,7 +3452,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.GREATERTHAN_EQUALS: {
|
case Token.GREATERTHAN_EQUALS: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3497,7 +3472,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.unreachable();
|
return this.module.unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3584,7 +3559,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// checking for a possible use of unary EQZ. while the most classic of all optimizations,
|
// checking for a possible use of unary EQZ. while the most classic of all optimizations,
|
||||||
// that's not what the source told us to do. for reference, `!left` emits unary EQZ.
|
// that's not what the source told us to do. for reference, `!left` emits unary EQZ.
|
||||||
|
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3600,7 +3575,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// still allow '==' with references
|
// still allow '==' with references
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3672,7 +3647,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.EXCLAMATION_EQUALS_EQUALS:
|
case Token.EXCLAMATION_EQUALS_EQUALS:
|
||||||
case Token.EXCLAMATION_EQUALS: {
|
case Token.EXCLAMATION_EQUALS: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3688,7 +3663,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// still allow '!=' with references
|
// still allow '!=' with references
|
||||||
}
|
}
|
||||||
|
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3763,7 +3738,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.PLUS_EQUALS: compound = true;
|
case Token.PLUS_EQUALS: compound = true;
|
||||||
case Token.PLUS: {
|
case Token.PLUS: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3786,7 +3761,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (compound) {
|
if (compound) {
|
||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3852,7 +3827,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.MINUS_EQUALS: compound = true;
|
case Token.MINUS_EQUALS: compound = true;
|
||||||
case Token.MINUS: {
|
case Token.MINUS: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3876,7 +3851,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -3942,7 +3917,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.ASTERISK_EQUALS: compound = true;
|
case Token.ASTERISK_EQUALS: compound = true;
|
||||||
case Token.ASTERISK: {
|
case Token.ASTERISK: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -3966,7 +3941,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType);
|
leftExpr = this.ensureSmallIntegerWrap(leftExpr, leftType);
|
||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4032,7 +4007,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.ASTERISK_ASTERISK_EQUALS: compound = true;
|
case Token.ASTERISK_ASTERISK_EQUALS: compound = true;
|
||||||
case Token.ASTERISK_ASTERISK: {
|
case Token.ASTERISK_ASTERISK: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4124,7 +4099,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.SLASH_EQUALS: compound = true;
|
case Token.SLASH_EQUALS: compound = true;
|
||||||
case Token.SLASH: {
|
case Token.SLASH: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4149,7 +4124,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4233,7 +4208,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.PERCENT_EQUALS: compound = true;
|
case Token.PERCENT_EQUALS: compound = true;
|
||||||
case Token.PERCENT: {
|
case Token.PERCENT: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType);
|
leftExpr = this.compileExpression(left, contextualType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4258,7 +4233,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4399,7 +4374,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.LESSTHAN_LESSTHAN_EQUALS: compound = true;
|
case Token.LESSTHAN_LESSTHAN_EQUALS: compound = true;
|
||||||
case Token.LESSTHAN_LESSTHAN: {
|
case Token.LESSTHAN_LESSTHAN: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4465,7 +4440,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.GREATERTHAN_GREATERTHAN_EQUALS: compound = true;
|
case Token.GREATERTHAN_GREATERTHAN_EQUALS: compound = true;
|
||||||
case Token.GREATERTHAN_GREATERTHAN: {
|
case Token.GREATERTHAN_GREATERTHAN: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4553,7 +4528,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: compound = true;
|
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: compound = true;
|
||||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: {
|
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4622,7 +4597,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.AMPERSAND_EQUALS: compound = true;
|
case Token.AMPERSAND_EQUALS: compound = true;
|
||||||
case Token.AMPERSAND: {
|
case Token.AMPERSAND: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overloadd
|
// check operator overloadd
|
||||||
@ -4646,7 +4621,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4712,7 +4687,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.BAR_EQUALS: compound = true;
|
case Token.BAR_EQUALS: compound = true;
|
||||||
case Token.BAR: {
|
case Token.BAR: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4736,7 +4711,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4805,7 +4780,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.CARET_EQUALS: compound = true;
|
case Token.CARET_EQUALS: compound = true;
|
||||||
case Token.CARET: {
|
case Token.CARET: {
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType.intType);
|
leftExpr = this.compileExpression(left, contextualType.intType);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
// check operator overload
|
// check operator overload
|
||||||
@ -4829,7 +4804,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
} else {
|
} else {
|
||||||
rightExpr = this.compileExpressionRetainType(right, leftType);
|
rightExpr = this.compileExpression(right, leftType);
|
||||||
rightType = this.currentType;
|
rightType = this.currentType;
|
||||||
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
if (commonType = Type.commonDenominator(leftType, rightType, false)) {
|
||||||
leftExpr = this.convertExpression(leftExpr,
|
leftExpr = this.convertExpression(leftExpr,
|
||||||
@ -4901,13 +4876,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
case Token.AMPERSAND_AMPERSAND: { // left && right -> (t = left) ? right : t
|
case Token.AMPERSAND_AMPERSAND: { // left && right -> (t = left) ? right : t
|
||||||
let flow = this.currentFlow;
|
let flow = this.currentFlow;
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType, contextualFlags);
|
let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP);
|
||||||
|
leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
let rightFlow = flow.fork();
|
let rightFlow = flow.fork();
|
||||||
this.currentFlow = rightFlow;
|
this.currentFlow = rightFlow;
|
||||||
rightFlow.inheritNonnullIfTrue(leftExpr);
|
rightFlow.inheritNonnullIfTrue(leftExpr);
|
||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT | (contextualFlags & ~ContextualFlags.WILL_DROP));
|
rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT);
|
||||||
rightType = leftType;
|
rightType = leftType;
|
||||||
|
|
||||||
// simplify if only interested in true or false
|
// simplify if only interested in true or false
|
||||||
@ -4998,13 +4974,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case Token.BAR_BAR: { // left || right -> ((t = left) ? t : right)
|
case Token.BAR_BAR: { // left || right -> ((t = left) ? t : right)
|
||||||
let flow = this.currentFlow;
|
let flow = this.currentFlow;
|
||||||
leftExpr = this.compileExpressionRetainType(left, contextualType, contextualFlags);
|
let inheritedFlags = contextualFlags & (ContextualFlags.SKIP_AUTORELEASE | ContextualFlags.WRAP);
|
||||||
|
leftExpr = this.compileExpression(left, contextualType.exceptVoid, inheritedFlags);
|
||||||
leftType = this.currentType;
|
leftType = this.currentType;
|
||||||
|
|
||||||
let rightFlow = flow.fork();
|
let rightFlow = flow.fork();
|
||||||
this.currentFlow = rightFlow;
|
this.currentFlow = rightFlow;
|
||||||
rightFlow.inheritNonnullIfFalse(leftExpr);
|
rightFlow.inheritNonnullIfFalse(leftExpr);
|
||||||
rightExpr = this.compileExpression(right, leftType, ContextualFlags.IMPLICIT | contextualFlags);
|
rightExpr = this.compileExpression(right, leftType, inheritedFlags | ContextualFlags.IMPLICIT);
|
||||||
rightType = leftType;
|
rightType = leftType;
|
||||||
|
|
||||||
// simplify if only interested in true or false
|
// simplify if only interested in true or false
|
||||||
@ -5326,11 +5303,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
return this.makeFieldAssignment(<Field>target,
|
return this.makeFieldAssignment(<Field>target,
|
||||||
valueExpr,
|
valueExpr,
|
||||||
this.compileExpressionRetainType(
|
|
||||||
assert(thisExpression),
|
|
||||||
// FIXME: explicit type (currently fails due to missing null checking)
|
// FIXME: explicit type (currently fails due to missing null checking)
|
||||||
this.options.usizeType
|
this.compileExpression(assert(thisExpression), this.options.usizeType),
|
||||||
),
|
|
||||||
tee
|
tee
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -5371,20 +5345,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
// call just the setter if the return value isn't of interest
|
// call just the setter if the return value isn't of interest
|
||||||
if (!tee) {
|
if (!tee) {
|
||||||
let thisExpr = this.compileExpressionRetainType(
|
let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType);
|
||||||
assert(thisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
return this.makeCallDirect(setterInstance, [ thisExpr, valueExpr ], valueExpression);
|
return this.makeCallDirect(setterInstance, [ thisExpr, valueExpr ], valueExpression);
|
||||||
}
|
}
|
||||||
// otherwise call the setter first, then the getter
|
// otherwise call the setter first, then the getter
|
||||||
let getterInstance = assert((<Property>target).getterInstance); // must be present
|
let getterInstance = assert((<Property>target).getterInstance); // must be present
|
||||||
let returnType = getterInstance.signature.returnType;
|
let returnType = getterInstance.signature.returnType;
|
||||||
let nativeReturnType = returnType.toNativeType();
|
let nativeReturnType = returnType.toNativeType();
|
||||||
let thisExpr = this.compileExpressionRetainType(
|
let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType);
|
||||||
assert(thisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
let tempLocal = flow.getAndFreeTempLocal(returnType);
|
let tempLocal = flow.getAndFreeTempLocal(returnType);
|
||||||
let tempLocalIndex = tempLocal.index;
|
let tempLocalIndex = tempLocal.index;
|
||||||
return module.block(null, [
|
return module.block(null, [
|
||||||
@ -5419,10 +5387,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return module.unreachable();
|
return module.unreachable();
|
||||||
}
|
}
|
||||||
let targetType = (<Class>target).type;
|
let targetType = (<Class>target).type;
|
||||||
let thisExpr = this.compileExpressionRetainType(
|
let thisExpr = this.compileExpression(assert(thisExpression), this.options.usizeType);
|
||||||
assert(thisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
let elementExpr = this.compileExpression(indexExpression, Type.i32, ContextualFlags.IMPLICIT);
|
let elementExpr = this.compileExpression(indexExpression, Type.i32, ContextualFlags.IMPLICIT);
|
||||||
if (tee) {
|
if (tee) {
|
||||||
let tempLocalTarget = flow.getTempLocal(targetType);
|
let tempLocalTarget = flow.getTempLocal(targetType);
|
||||||
@ -5868,7 +5833,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (templateName !== null && inferredTypes.has(templateName)) {
|
if (templateName !== null && inferredTypes.has(templateName)) {
|
||||||
let inferredType = inferredTypes.get(templateName);
|
let inferredType = inferredTypes.get(templateName);
|
||||||
if (inferredType) {
|
if (inferredType) {
|
||||||
argumentExprs[i] = this.compileExpressionRetainType(argumentExpression, inferredType);
|
argumentExprs[i] = this.compileExpression(argumentExpression, inferredType);
|
||||||
let commonType: Type | null;
|
let commonType: Type | null;
|
||||||
if (!(commonType = Type.commonDenominator(inferredType, this.currentType, true))) {
|
if (!(commonType = Type.commonDenominator(inferredType, this.currentType, true))) {
|
||||||
if (!(commonType = Type.commonDenominator(inferredType, this.currentType, false))) {
|
if (!(commonType = Type.commonDenominator(inferredType, this.currentType, false))) {
|
||||||
@ -5881,7 +5846,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
inferredType = commonType;
|
inferredType = commonType;
|
||||||
} else {
|
} else {
|
||||||
argumentExprs[i] = this.compileExpressionRetainType(argumentExpression, Type.i32);
|
argumentExprs[i] = this.compileExpression(argumentExpression, Type.auto);
|
||||||
inferredType = this.currentType;
|
inferredType = this.currentType;
|
||||||
// ++numInferred;
|
// ++numInferred;
|
||||||
}
|
}
|
||||||
@ -5921,10 +5886,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// compile 'this' expression if an instance method
|
// compile 'this' expression if an instance method
|
||||||
let thisExpr: ExpressionRef = 0;
|
let thisExpr: ExpressionRef = 0;
|
||||||
if (instance.is(CommonFlags.INSTANCE)) {
|
if (instance.is(CommonFlags.INSTANCE)) {
|
||||||
thisExpr = this.compileExpressionRetainType(
|
thisExpr = this.compileExpression(assert(this.resolver.currentThisExpression), this.options.usizeType);
|
||||||
assert(this.resolver.currentThisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.compileCallDirect(
|
return this.compileCallDirect(
|
||||||
@ -5969,10 +5931,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let type = (<Field>target).type;
|
let type = (<Field>target).type;
|
||||||
if (signature = type.signatureReference) {
|
if (signature = type.signatureReference) {
|
||||||
let thisExpression = assert(this.resolver.currentThisExpression);
|
let thisExpression = assert(this.resolver.currentThisExpression);
|
||||||
let thisExpr = this.compileExpressionRetainType(
|
let thisExpr = this.compileExpression(thisExpression, this.options.usizeType);
|
||||||
thisExpression,
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
indexArg = module.load(
|
indexArg = module.load(
|
||||||
4,
|
4,
|
||||||
false,
|
false,
|
||||||
@ -6013,10 +5972,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case ElementKind.PROPERTY: { // instance property
|
case ElementKind.PROPERTY: { // instance property
|
||||||
let getterInstance = assert((<Property>target).getterInstance);
|
let getterInstance = assert((<Property>target).getterInstance);
|
||||||
indexArg = this.compileCallDirect(getterInstance, [], expression.expression,
|
indexArg = this.compileCallDirect(getterInstance, [], expression.expression,
|
||||||
this.compileExpressionRetainType(
|
this.compileExpression(assert(this.resolver.currentThisExpression), this.options.usizeType)
|
||||||
assert(this.resolver.currentThisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
signature = this.currentType.signatureReference;
|
signature = this.currentType.signatureReference;
|
||||||
if (!signature) {
|
if (!signature) {
|
||||||
@ -6579,6 +6535,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
/** Makes an automatic release call at the end of the current flow. */
|
/** Makes an automatic release call at the end of the current flow. */
|
||||||
makeAutorelease(expr: ExpressionRef, flow: Flow = this.currentFlow): ExpressionRef {
|
makeAutorelease(expr: ExpressionRef, flow: Flow = this.currentFlow): ExpressionRef {
|
||||||
|
// FIXME: loses track of nonNull state?
|
||||||
return this.module.local_tee(flow.getAutoreleaseLocal(this.options.usizeType).index, expr);
|
return this.module.local_tee(flow.getAutoreleaseLocal(this.options.usizeType).index, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7325,7 +7282,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// time of implementation, this seemed more useful because dynamic rhs expressions are not
|
// time of implementation, this seemed more useful because dynamic rhs expressions are not
|
||||||
// possible in AS anyway. also note that the code generated below must preserve side-effects of
|
// possible in AS anyway. also note that the code generated below must preserve side-effects of
|
||||||
// the LHS expression even when the result is a constant, i.e. return a block dropping `expr`.
|
// the LHS expression even when the result is a constant, i.e. return a block dropping `expr`.
|
||||||
var expr = this.compileExpressionRetainType(expression.expression, this.options.usizeType);
|
var expr = this.compileExpression(expression.expression, this.options.usizeType);
|
||||||
var actualType = this.currentType;
|
var actualType = this.currentType;
|
||||||
var expectedType = this.resolver.resolveType(expression.isType, this.currentFlow.actualFunction);
|
var expectedType = this.resolver.resolveType(expression.isType, this.currentFlow.actualFunction);
|
||||||
this.currentType = Type.bool;
|
this.currentType = Type.bool;
|
||||||
@ -7986,10 +7943,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case ElementKind.FIELD: { // instance field
|
case ElementKind.FIELD: { // instance field
|
||||||
assert((<Field>target).memoryOffset >= 0);
|
assert((<Field>target).memoryOffset >= 0);
|
||||||
let thisExpr = this.compileExpressionRetainType(
|
let thisExpr = this.compileExpression(assert(this.resolver.currentThisExpression), this.options.usizeType);
|
||||||
assert(this.resolver.currentThisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
);
|
|
||||||
this.currentType = (<Field>target).type;
|
this.currentType = (<Field>target).type;
|
||||||
return module.load(
|
return module.load(
|
||||||
(<Field>target).type.byteSize,
|
(<Field>target).type.byteSize,
|
||||||
@ -8010,10 +7964,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case ElementKind.PROPERTY: { // instance property
|
case ElementKind.PROPERTY: { // instance property
|
||||||
let getterInstance = assert((<Property>target).getterInstance);
|
let getterInstance = assert((<Property>target).getterInstance);
|
||||||
return this.compileCallDirect(getterInstance, [], propertyAccess,
|
return this.compileCallDirect(getterInstance, [], propertyAccess,
|
||||||
this.compileExpressionRetainType(
|
this.compileExpression(assert(this.resolver.currentThisExpression), this.options.usizeType)
|
||||||
assert(this.resolver.currentThisExpression),
|
|
||||||
this.options.usizeType
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||||
@ -8042,7 +7993,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
var condExpr = this.module.precomputeExpression(
|
var condExpr = this.module.precomputeExpression(
|
||||||
this.makeIsTrueish(
|
this.makeIsTrueish(
|
||||||
this.compileExpressionRetainType(expression.condition, Type.bool),
|
this.compileExpression(expression.condition, Type.bool),
|
||||||
this.currentType
|
this.currentType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -8053,19 +8004,19 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
getExpressionType(condExpr) == NativeType.I32
|
getExpressionType(condExpr) == NativeType.I32
|
||||||
) {
|
) {
|
||||||
return getConstValueI32(condExpr)
|
return getConstValueI32(condExpr)
|
||||||
? this.compileExpressionRetainType(ifThen, contextualType)
|
? this.compileExpression(ifThen, contextualType)
|
||||||
: this.compileExpressionRetainType(ifElse, contextualType);
|
: this.compileExpression(ifElse, contextualType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ifThenFlow = outerFlow.fork();
|
var ifThenFlow = outerFlow.fork();
|
||||||
this.currentFlow = ifThenFlow;
|
this.currentFlow = ifThenFlow;
|
||||||
var ifThenExpr = this.compileExpressionRetainType(ifThen, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE);
|
var ifThenExpr = this.compileExpression(ifThen, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE);
|
||||||
var ifThenType = this.currentType;
|
var ifThenType = this.currentType;
|
||||||
var IfThenAutoreleaseSkipped = this.skippedAutoreleases.has(ifThenExpr);
|
var IfThenAutoreleaseSkipped = this.skippedAutoreleases.has(ifThenExpr);
|
||||||
|
|
||||||
var ifElseFlow = outerFlow.fork();
|
var ifElseFlow = outerFlow.fork();
|
||||||
this.currentFlow = ifElseFlow;
|
this.currentFlow = ifElseFlow;
|
||||||
var ifElseExpr = this.compileExpressionRetainType(ifElse, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE);
|
var ifElseExpr = this.compileExpression(ifElse, contextualType, contextualFlags & ContextualFlags.SKIP_AUTORELEASE);
|
||||||
var ifElseType = this.currentType;
|
var ifElseType = this.currentType;
|
||||||
var ifElseAutoreleaseSkipped = this.skippedAutoreleases.has(ifElseExpr);
|
var ifElseAutoreleaseSkipped = this.skippedAutoreleases.has(ifElseExpr);
|
||||||
|
|
||||||
@ -8133,9 +8084,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// make a getter for the expression (also obtains the type)
|
// make a getter for the expression (also obtains the type)
|
||||||
var getValue = this.compileExpression( // reports
|
var getValue = this.compileExpression( // reports
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8367,9 +8316,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case Token.PLUS: {
|
case Token.PLUS: {
|
||||||
expr = this.compileExpression(
|
expr = this.compileExpression(
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8407,9 +8354,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
expr = this.compileExpression(
|
expr = this.compileExpression(
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8476,9 +8421,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
compound = true;
|
compound = true;
|
||||||
expr = this.compileExpression(
|
expr = this.compileExpression(
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8545,9 +8488,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
compound = true;
|
compound = true;
|
||||||
expr = this.compileExpression(
|
expr = this.compileExpression(
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8613,9 +8554,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case Token.EXCLAMATION: {
|
case Token.EXCLAMATION: {
|
||||||
expr = this.compileExpression(
|
expr = this.compileExpression(
|
||||||
expression.operand,
|
expression.operand,
|
||||||
contextualType == Type.void
|
contextualType.exceptVoid,
|
||||||
? Type.i32
|
|
||||||
: contextualType,
|
|
||||||
ContextualFlags.NONE
|
ContextualFlags.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -280,8 +280,8 @@ export abstract class DiagnosticEmitter {
|
|||||||
var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2).withRange(range);
|
var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2).withRange(range);
|
||||||
if (relatedRange) message.relatedRange = relatedRange;
|
if (relatedRange) message.relatedRange = relatedRange;
|
||||||
this.diagnostics.push(message);
|
this.diagnostics.push(message);
|
||||||
// console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
|
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
|
||||||
// console.log(<string>new Error("stack").stack);
|
console.log(<string>new Error("stack").stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Emits an informatory diagnostic message. */
|
/** Emits an informatory diagnostic message. */
|
||||||
|
@ -145,6 +145,12 @@ export class Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Substitutes this type with the auto type if this type is void. */
|
||||||
|
get exceptVoid(): Type {
|
||||||
|
if (this.kind == TypeKind.VOID) return Type.auto;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets this type's logarithmic alignment in memory. */
|
/** Gets this type's logarithmic alignment in memory. */
|
||||||
get alignLog2(): i32 {
|
get alignLog2(): i32 {
|
||||||
return 31 - clz<i32>(this.byteSize);
|
return 31 - clz<i32>(this.byteSize);
|
||||||
@ -526,6 +532,9 @@ export class Type {
|
|||||||
|
|
||||||
/** No return type. */
|
/** No return type. */
|
||||||
static readonly void: Type = new Type(TypeKind.VOID, TypeFlags.NONE, 0);
|
static readonly void: Type = new Type(TypeKind.VOID, TypeFlags.NONE, 0);
|
||||||
|
|
||||||
|
/** Alias of i32 indicating type inference of locals and globals with just an initializer. */
|
||||||
|
static readonly auto: Type = new Type(Type.i32.kind, Type.i32.flags, Type.i32.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts an array of types to an array of native types. */
|
/** Converts an array of types to an array of native types. */
|
||||||
|
@ -116,6 +116,12 @@
|
|||||||
(func $assert-nonnull/testElem (; 8 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
(func $assert-nonnull/testElem (; 8 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
||||||
local.get $0
|
local.get $0
|
||||||
call $~lib/array/Array<assert-nonnull/Foo | null>#__get
|
call $~lib/array/Array<assert-nonnull/Foo | null>#__get
|
||||||
|
local.tee $0
|
||||||
|
i32.eqz
|
||||||
|
if
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
local.get $0
|
||||||
)
|
)
|
||||||
(func $assert-nonnull/testAll (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
(func $assert-nonnull/testAll (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
||||||
local.get $0
|
local.get $0
|
||||||
|
@ -179,7 +179,6 @@
|
|||||||
)
|
)
|
||||||
(func $assert-nonnull/testElem (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
(func $assert-nonnull/testElem (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
||||||
(local $1 i32)
|
(local $1 i32)
|
||||||
(local $2 i32)
|
|
||||||
local.get $0
|
local.get $0
|
||||||
call $~lib/rt/stub/__retain
|
call $~lib/rt/stub/__retain
|
||||||
drop
|
drop
|
||||||
@ -187,13 +186,16 @@
|
|||||||
i32.const 0
|
i32.const 0
|
||||||
call $~lib/array/Array<assert-nonnull/Foo | null>#__get
|
call $~lib/array/Array<assert-nonnull/Foo | null>#__get
|
||||||
local.tee $1
|
local.tee $1
|
||||||
call $~lib/rt/stub/__retain
|
if (result i32)
|
||||||
local.set $2
|
|
||||||
local.get $1
|
local.get $1
|
||||||
call $~lib/rt/stub/__release
|
else
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call $~lib/rt/stub/__retain
|
||||||
|
local.set $1
|
||||||
local.get $0
|
local.get $0
|
||||||
call $~lib/rt/stub/__release
|
call $~lib/rt/stub/__release
|
||||||
local.get $2
|
local.get $1
|
||||||
)
|
)
|
||||||
(func $assert-nonnull/testAll (; 12 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
(func $assert-nonnull/testAll (; 12 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
|
||||||
(local $1 i32)
|
(local $1 i32)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
(data (i32.const 8) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00r\00e\00t\00a\00i\00n\00-\00i\003\002\00.\00t\00s")
|
(data (i32.const 8) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00r\00e\00t\00a\00i\00n\00-\00i\003\002\00.\00t\00s")
|
||||||
(global $retain-i32/si (mut i32) (i32.const 0))
|
(global $retain-i32/si (mut i32) (i32.const 0))
|
||||||
(global $retain-i32/ui (mut i32) (i32.const 0))
|
(global $retain-i32/ui (mut i32) (i32.const 0))
|
||||||
|
(global $retain-i32/ri (mut i32) (i32.const 0))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $start:retain-i32 (; 1 ;) (type $FUNCSIG$v)
|
(func $start:retain-i32 (; 1 ;) (type $FUNCSIG$v)
|
||||||
@ -254,6 +255,12 @@
|
|||||||
call $~lib/builtins/abort
|
call $~lib/builtins/abort
|
||||||
unreachable
|
unreachable
|
||||||
end
|
end
|
||||||
|
i32.const 0
|
||||||
|
i32.load8_s
|
||||||
|
global.set $retain-i32/ri
|
||||||
|
i32.const 0
|
||||||
|
i32.load8_s
|
||||||
|
drop
|
||||||
)
|
)
|
||||||
(func $start (; 2 ;) (type $FUNCSIG$v)
|
(func $start (; 2 ;) (type $FUNCSIG$v)
|
||||||
call $start:retain-i32
|
call $start:retain-i32
|
||||||
|
@ -129,3 +129,14 @@ assert(ui == 1);
|
|||||||
|
|
||||||
ui = 255 % 255;
|
ui = 255 % 255;
|
||||||
assert(ui == 0);
|
assert(ui == 0);
|
||||||
|
|
||||||
|
// inferring global type from load should still retain T
|
||||||
|
var ri = load<i8>(0);
|
||||||
|
assert(ri instanceof i8);
|
||||||
|
|
||||||
|
// inferring local type from load should still retain T
|
||||||
|
function testLocalRetain(): void {
|
||||||
|
var ri = load<i8>(0);
|
||||||
|
assert(ri instanceof i8);
|
||||||
|
}
|
||||||
|
testLocalRetain();
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
(global $~lib/builtins/u32.MAX_VALUE i32 (i32.const -1))
|
(global $~lib/builtins/u32.MAX_VALUE i32 (i32.const -1))
|
||||||
(global $retain-i32/si (mut i32) (i32.const 0))
|
(global $retain-i32/si (mut i32) (i32.const 0))
|
||||||
(global $retain-i32/ui (mut i32) (i32.const 0))
|
(global $retain-i32/ui (mut i32) (i32.const 0))
|
||||||
|
(global $retain-i32/ri (mut i32) (i32.const 0))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $retain-i32/test (; 1 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
|
(func $retain-i32/test (; 1 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
|
||||||
@ -330,7 +331,25 @@
|
|||||||
unreachable
|
unreachable
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
(func $start:retain-i32 (; 2 ;) (type $FUNCSIG$v)
|
(func $retain-i32/testLocalRetain (; 2 ;) (type $FUNCSIG$v)
|
||||||
|
(local $0 i32)
|
||||||
|
i32.const 0
|
||||||
|
i32.load8_s
|
||||||
|
local.set $0
|
||||||
|
local.get $0
|
||||||
|
drop
|
||||||
|
i32.const 1
|
||||||
|
i32.eqz
|
||||||
|
if
|
||||||
|
i32.const 0
|
||||||
|
i32.const 24
|
||||||
|
i32.const 140
|
||||||
|
i32.const 2
|
||||||
|
call $~lib/builtins/abort
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
)
|
||||||
|
(func $start:retain-i32 (; 3 ;) (type $FUNCSIG$v)
|
||||||
(local $0 i32)
|
(local $0 i32)
|
||||||
i32.const 0
|
i32.const 0
|
||||||
global.get $~lib/builtins/i8.MAX_VALUE
|
global.get $~lib/builtins/i8.MAX_VALUE
|
||||||
@ -786,10 +805,26 @@
|
|||||||
call $~lib/builtins/abort
|
call $~lib/builtins/abort
|
||||||
unreachable
|
unreachable
|
||||||
end
|
end
|
||||||
|
i32.const 0
|
||||||
|
i32.load8_s
|
||||||
|
global.set $retain-i32/ri
|
||||||
|
global.get $retain-i32/ri
|
||||||
|
drop
|
||||||
|
i32.const 1
|
||||||
|
i32.eqz
|
||||||
|
if
|
||||||
|
i32.const 0
|
||||||
|
i32.const 24
|
||||||
|
i32.const 135
|
||||||
|
i32.const 0
|
||||||
|
call $~lib/builtins/abort
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call $retain-i32/testLocalRetain
|
||||||
)
|
)
|
||||||
(func $start (; 3 ;) (type $FUNCSIG$v)
|
(func $start (; 4 ;) (type $FUNCSIG$v)
|
||||||
call $start:retain-i32
|
call $start:retain-i32
|
||||||
)
|
)
|
||||||
(func $null (; 4 ;) (type $FUNCSIG$v)
|
(func $null (; 5 ;) (type $FUNCSIG$v)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1475,6 +1475,7 @@
|
|||||||
call $~lib/string/String.__concat
|
call $~lib/string/String.__concat
|
||||||
)
|
)
|
||||||
(func $start:std/symbol (; 27 ;) (type $FUNCSIG$v)
|
(func $start:std/symbol (; 27 ;) (type $FUNCSIG$v)
|
||||||
|
(local $0 i32)
|
||||||
i32.const 24
|
i32.const 24
|
||||||
call $~lib/symbol/Symbol
|
call $~lib/symbol/Symbol
|
||||||
global.set $std/symbol/sym1
|
global.set $std/symbol/sym1
|
||||||
@ -1537,9 +1538,21 @@
|
|||||||
end
|
end
|
||||||
global.get $std/symbol/sym3
|
global.get $std/symbol/sym3
|
||||||
call $~lib/symbol/_Symbol.keyFor
|
call $~lib/symbol/_Symbol.keyFor
|
||||||
|
local.tee $0
|
||||||
|
i32.eqz
|
||||||
|
if
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
local.get $0
|
||||||
global.set $std/symbol/key3
|
global.set $std/symbol/key3
|
||||||
global.get $std/symbol/sym4
|
global.get $std/symbol/sym4
|
||||||
call $~lib/symbol/_Symbol.keyFor
|
call $~lib/symbol/_Symbol.keyFor
|
||||||
|
local.tee $0
|
||||||
|
i32.eqz
|
||||||
|
if
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
local.get $0
|
||||||
global.set $std/symbol/key4
|
global.set $std/symbol/key4
|
||||||
global.get $std/symbol/key3
|
global.get $std/symbol/key3
|
||||||
i32.const 24
|
i32.const 24
|
||||||
|
@ -3342,8 +3342,6 @@
|
|||||||
(local $1 i32)
|
(local $1 i32)
|
||||||
(local $2 i32)
|
(local $2 i32)
|
||||||
(local $3 i32)
|
(local $3 i32)
|
||||||
(local $4 i32)
|
|
||||||
(local $5 i32)
|
|
||||||
i32.const 24
|
i32.const 24
|
||||||
call $~lib/symbol/Symbol
|
call $~lib/symbol/Symbol
|
||||||
global.set $std/symbol/sym1
|
global.set $std/symbol/sym1
|
||||||
@ -3423,11 +3421,21 @@
|
|||||||
global.get $std/symbol/sym3
|
global.get $std/symbol/sym3
|
||||||
call $~lib/symbol/_Symbol.keyFor
|
call $~lib/symbol/_Symbol.keyFor
|
||||||
local.tee $0
|
local.tee $0
|
||||||
|
if (result i32)
|
||||||
|
local.get $0
|
||||||
|
else
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
call $~lib/rt/stub/__retain
|
call $~lib/rt/stub/__retain
|
||||||
global.set $std/symbol/key3
|
global.set $std/symbol/key3
|
||||||
global.get $std/symbol/sym4
|
global.get $std/symbol/sym4
|
||||||
call $~lib/symbol/_Symbol.keyFor
|
call $~lib/symbol/_Symbol.keyFor
|
||||||
local.tee $1
|
local.tee $0
|
||||||
|
if (result i32)
|
||||||
|
local.get $0
|
||||||
|
else
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
call $~lib/rt/stub/__retain
|
call $~lib/rt/stub/__retain
|
||||||
global.set $std/symbol/key4
|
global.set $std/symbol/key4
|
||||||
global.get $std/symbol/key3
|
global.get $std/symbol/key3
|
||||||
@ -3457,7 +3465,7 @@
|
|||||||
i32.const 0
|
i32.const 0
|
||||||
call $~lib/symbol/Symbol
|
call $~lib/symbol/Symbol
|
||||||
call $~lib/symbol/_Symbol#toString
|
call $~lib/symbol/_Symbol#toString
|
||||||
local.tee $2
|
local.tee $0
|
||||||
i32.const 704
|
i32.const 704
|
||||||
call $~lib/string/String.__eq
|
call $~lib/string/String.__eq
|
||||||
i32.eqz
|
i32.eqz
|
||||||
@ -3471,7 +3479,7 @@
|
|||||||
end
|
end
|
||||||
global.get $std/symbol/sym3
|
global.get $std/symbol/sym3
|
||||||
call $~lib/symbol/_Symbol#toString
|
call $~lib/symbol/_Symbol#toString
|
||||||
local.tee $3
|
local.tee $1
|
||||||
i32.const 736
|
i32.const 736
|
||||||
call $~lib/string/String.__eq
|
call $~lib/string/String.__eq
|
||||||
i32.eqz
|
i32.eqz
|
||||||
@ -3489,7 +3497,7 @@
|
|||||||
global.set $std/symbol/isConcatSpreadable
|
global.set $std/symbol/isConcatSpreadable
|
||||||
global.get $std/symbol/hasInstance
|
global.get $std/symbol/hasInstance
|
||||||
call $~lib/symbol/_Symbol#toString
|
call $~lib/symbol/_Symbol#toString
|
||||||
local.tee $4
|
local.tee $2
|
||||||
i32.const 776
|
i32.const 776
|
||||||
call $~lib/string/String.__eq
|
call $~lib/string/String.__eq
|
||||||
i32.eqz
|
i32.eqz
|
||||||
@ -3503,7 +3511,7 @@
|
|||||||
end
|
end
|
||||||
global.get $std/symbol/isConcatSpreadable
|
global.get $std/symbol/isConcatSpreadable
|
||||||
call $~lib/symbol/_Symbol#toString
|
call $~lib/symbol/_Symbol#toString
|
||||||
local.tee $5
|
local.tee $3
|
||||||
i32.const 832
|
i32.const 832
|
||||||
call $~lib/string/String.__eq
|
call $~lib/string/String.__eq
|
||||||
i32.eqz
|
i32.eqz
|
||||||
@ -3527,10 +3535,6 @@
|
|||||||
call $~lib/rt/stub/__release
|
call $~lib/rt/stub/__release
|
||||||
local.get $3
|
local.get $3
|
||||||
call $~lib/rt/stub/__release
|
call $~lib/rt/stub/__release
|
||||||
local.get $4
|
|
||||||
call $~lib/rt/stub/__release
|
|
||||||
local.get $5
|
|
||||||
call $~lib/rt/stub/__release
|
|
||||||
)
|
)
|
||||||
(func $start (; 34 ;) (type $FUNCSIG$v)
|
(func $start (; 34 ;) (type $FUNCSIG$v)
|
||||||
call $start:std/symbol
|
call $start:std/symbol
|
||||||
|
Loading…
x
Reference in New Issue
Block a user