internal void CompileEqualityBy(FunctionCompiler compiler, OpCode strictOp, OpCode convOp, bool isLastOperator) { if (!LeftOperand.CanBeObject && !RightOperand.CanBeObject) { LeftOperand.CompileBy(compiler, false); RightOperand.CompileBy(compiler, false); compiler.Emitter.Emit(strictOp); } else { var endLabel = compiler.Emitter.DefineLabel(); var falseLabel = compiler.Emitter.DefineLabel(); LeftOperand.CompileBy(compiler, false); RightOperand.CompileBy(compiler, false); compiler.Emitter.Emit(OpCode.Dup2); compiler.Emitter.Emit(strictOp); compiler.Emitter.Emit(OpCode.GotoIfFalse, falseLabel); compiler.Emitter.Emit(OpCode.Pop2); compiler.Emitter.Emit(OpCode.LdBoolean, true); compiler.Emitter.Emit(OpCode.Goto, endLabel); compiler.Emitter.MarkLabel(falseLabel); // В вершине стека лежит правый операнд if (RightOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } compiler.Emitter.Emit(OpCode.Swap); if (LeftOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } compiler.Emitter.Emit(convOp); compiler.Emitter.MarkLabel(endLabel); } if (isLastOperator) { compiler.Emitter.Emit(OpCode.Pop); } }
internal void CompileBy( FunctionCompiler compiler, OpCode op, bool isLeftAssociative, bool needCastToPrimitive, bool isLastOperator) { if (isLeftAssociative) { LeftOperand.CompileBy(compiler, false); if (needCastToPrimitive && LeftOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } RightOperand.CompileBy(compiler, false); if (needCastToPrimitive && RightOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } } else { RightOperand.CompileBy(compiler, false); if (needCastToPrimitive && RightOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } LeftOperand.CompileBy(compiler, false); if (needCastToPrimitive && LeftOperand.CanBeObject) { compiler.Emitter.Emit(OpCode.CastToPrimitive); } } compiler.Emitter.Emit(op); if (isLastOperator) { compiler.Emitter.Emit(OpCode.Pop); } }