mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-16 00:11:28 +00:00
Implement ternary using if, see AssemblyScript/assemblyscript#123
This commit is contained in:
12
src/ast.ts
12
src/ast.ts
@ -19,7 +19,7 @@
|
||||
│ ├ ParenthesizedExpression
|
||||
│ ├ NewExpression
|
||||
│ ├ PropertyAccessExpression
|
||||
│ ├ SelectExpression
|
||||
│ ├ TernaryExpression
|
||||
│ └ UnaryExpression
|
||||
│ ├ UnaryPostfixExpression
|
||||
│ └ UnaryPrefixExpression
|
||||
@ -101,7 +101,7 @@ export enum NodeKind {
|
||||
NULL,
|
||||
PARENTHESIZED,
|
||||
PROPERTYACCESS,
|
||||
SELECT,
|
||||
TERNARY,
|
||||
SUPER,
|
||||
THIS,
|
||||
TRUE,
|
||||
@ -302,8 +302,8 @@ export abstract class Expression extends Node {
|
||||
return expr;
|
||||
}
|
||||
|
||||
static createSelect(condition: Expression, ifThen: Expression, ifElse: Expression, range: Range): SelectExpression {
|
||||
const expr: SelectExpression = new SelectExpression();
|
||||
static createTernary(condition: Expression, ifThen: Expression, ifElse: Expression, range: Range): TernaryExpression {
|
||||
const expr: TernaryExpression = new TernaryExpression();
|
||||
expr.range = range;
|
||||
(expr.condition = condition).parent = expr;
|
||||
(expr.ifThen = ifThen).parent = expr;
|
||||
@ -549,9 +549,9 @@ export class RegexpLiteralExpression extends LiteralExpression {
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectExpression extends Expression {
|
||||
export class TernaryExpression extends Expression {
|
||||
|
||||
kind = NodeKind.SELECT;
|
||||
kind = NodeKind.TERNARY;
|
||||
condition: Expression;
|
||||
ifThen: Expression;
|
||||
ifElse: Expression;
|
||||
|
@ -59,7 +59,7 @@ import {
|
||||
NewExpression,
|
||||
ParenthesizedExpression,
|
||||
PropertyAccessExpression,
|
||||
SelectExpression,
|
||||
TernaryExpression,
|
||||
StringLiteralExpression,
|
||||
UnaryPostfixExpression,
|
||||
UnaryPrefixExpression,
|
||||
@ -927,8 +927,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
expr = this.compilePropertyAccessExpression(<PropertyAccessExpression>expression, contextualType);
|
||||
break;
|
||||
|
||||
case NodeKind.SELECT:
|
||||
expr = this.compileSelectExpression(<SelectExpression>expression, contextualType);
|
||||
case NodeKind.TERNARY:
|
||||
expr = this.compileTernaryExpression(<TernaryExpression>expression, contextualType);
|
||||
break;
|
||||
|
||||
case NodeKind.UNARYPOSTFIX:
|
||||
@ -1482,6 +1482,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
/** Compiles a call to a function. If an instance method, `this` is the first element in `argumentExpressions`. */
|
||||
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): ExpressionRef {
|
||||
const previousType: Type = this.currentType;
|
||||
|
||||
// validate and compile arguments
|
||||
const parameters: Parameter[] = functionInstance.parameters;
|
||||
@ -1627,6 +1628,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createHost(HostOp.GrowMemory, null, operands);
|
||||
|
||||
case "unreachable":
|
||||
this.currentType = previousType;
|
||||
return this.module.createUnreachable();
|
||||
|
||||
case "isNaN": // value != value
|
||||
@ -1645,35 +1647,35 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
break;
|
||||
|
||||
case "isFinite": // value != value ? false : abs(value) != Infinity
|
||||
case "isFinite": // v=[abs(value) != Infinity, false]; return value == value ? v[0] : v[1]
|
||||
if (functionInstance.typeArguments[0] == Type.f64) {
|
||||
tempLocal = this.currentFunction.addLocal(Type.f64);
|
||||
return this.module.createSelect(
|
||||
this.module.createBinary(BinaryOp.NeF64,
|
||||
this.module.createTeeLocal(tempLocal.index, operands[0]),
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F64)
|
||||
),
|
||||
this.module.createI32(0),
|
||||
this.module.createBinary(BinaryOp.NeF64,
|
||||
this.module.createUnary(UnaryOp.AbsF64,
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F64)
|
||||
this.module.createTeeLocal(tempLocal.index, operands[0])
|
||||
),
|
||||
this.module.createF64(Infinity)
|
||||
),
|
||||
this.module.createI32(0),
|
||||
this.module.createBinary(BinaryOp.EqF64,
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F64),
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F64)
|
||||
)
|
||||
);
|
||||
} else if (functionInstance.typeArguments[0] == Type.f32) {
|
||||
tempLocal = this.currentFunction.addLocal(Type.f32);
|
||||
return this.module.createSelect(
|
||||
this.module.createBinary(BinaryOp.NeF32,
|
||||
this.module.createTeeLocal(tempLocal.index, operands[0]),
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F32)
|
||||
),
|
||||
this.module.createI32(0),
|
||||
this.module.createBinary(BinaryOp.NeF32,
|
||||
this.module.createUnary(UnaryOp.AbsF32,
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F32)
|
||||
this.module.createTeeLocal(tempLocal.index, operands[0])
|
||||
),
|
||||
this.module.createF32(Infinity)
|
||||
),
|
||||
this.module.createI32(0),
|
||||
this.module.createBinary(BinaryOp.EqF32,
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F32),
|
||||
this.module.createGetLocal(tempLocal.index, NativeType.F32)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1845,11 +1847,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileSelectExpression(expression: SelectExpression, contextualType: Type): ExpressionRef {
|
||||
compileTernaryExpression(expression: TernaryExpression, contextualType: Type): ExpressionRef {
|
||||
const condition: ExpressionRef = this.compileExpression(expression.condition, Type.i32);
|
||||
const ifThen: ExpressionRef = this.compileExpression(expression.ifThen, contextualType);
|
||||
const ifElse: ExpressionRef = this.compileExpression(expression.ifElse, contextualType);
|
||||
return this.module.createSelect(condition, ifThen, ifElse);
|
||||
return this.module.createIf(condition, ifThen, ifElse);
|
||||
}
|
||||
|
||||
compileUnaryPostfixExpression(expression: UnaryPostfixExpression, contextualType: Type): ExpressionRef {
|
||||
|
@ -448,7 +448,7 @@ export class Module {
|
||||
return _BinaryenReturn(this.ref, expression);
|
||||
}
|
||||
|
||||
createSelect(condition: ExpressionRef, ifTrue: ExpressionRef, ifFalse: ExpressionRef): ExpressionRef {
|
||||
createSelect(ifTrue: ExpressionRef, ifFalse: ExpressionRef, condition: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenSelect(this.ref, condition, ifTrue, ifFalse);
|
||||
}
|
||||
|
@ -1456,7 +1456,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, expr.range);
|
||||
expr = Expression.createUnaryPostfix(token, expr, tn.range(startPos, tn.pos));
|
||||
|
||||
// SelectExpression
|
||||
// TernaryExpression
|
||||
} else if (token == Token.QUESTION) {
|
||||
const ifThen: Expression | null = this.parseExpression(tn);
|
||||
if (!ifThen)
|
||||
@ -1465,7 +1465,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
const ifElse: Expression | null = this.parseExpression(tn);
|
||||
if (!ifElse)
|
||||
return null;
|
||||
expr = Expression.createSelect(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos));
|
||||
expr = Expression.createTernary(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos));
|
||||
} else {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), ":");
|
||||
return null;
|
||||
|
Reference in New Issue
Block a user