public override void Accept(BinaryExpression pattern) { IodineLabel shortCircuitTrueLabel = methodBuilder.CreateLabel(); IodineLabel shortCircuitFalseLabel = methodBuilder.CreateLabel(); IodineLabel endLabel = methodBuilder.CreateLabel(); pattern.Left.Visit(this); /* * Short circuit evaluation */ switch (pattern.Operation) { case BinaryOperation.And: methodBuilder.EmitInstruction(pattern.Location, Opcode.Dup); methodBuilder.EmitInstruction(pattern.Location, Opcode.JumpIfFalse, shortCircuitFalseLabel); break; case BinaryOperation.Or: methodBuilder.EmitInstruction(pattern.Location, Opcode.Dup); methodBuilder.EmitInstruction(pattern.Location, Opcode.JumpIfTrue, shortCircuitTrueLabel); break; } pattern.Right.Visit(this); methodBuilder.EmitInstruction(pattern.Location, Opcode.BinOp, (int)pattern.Operation); methodBuilder.EmitInstruction(pattern.Location, Opcode.Jump, endLabel); methodBuilder.MarkLabelPosition(shortCircuitTrueLabel); methodBuilder.EmitInstruction(pattern.Location, Opcode.Pop); methodBuilder.EmitInstruction(pattern.Location, Opcode.LoadTrue); methodBuilder.EmitInstruction(pattern.Location, Opcode.Jump, endLabel); methodBuilder.MarkLabelPosition(shortCircuitFalseLabel); methodBuilder.EmitInstruction(pattern.Location, Opcode.Pop); methodBuilder.EmitInstruction(pattern.Location, Opcode.LoadFalse); methodBuilder.MarkLabelPosition(endLabel); }
public override void Accept(BinaryExpression binop) { if (binop.Operation == BinaryOperation.Assign) { binop.Right.Visit(this); if (binop.Left is NameExpression) { NameExpression ident = (NameExpression)binop.Left; Symbol sym = symbolTable.GetSymbol(ident.Value); if (sym.Type == SymbolType.Local) { methodBuilder.EmitInstruction(ident.Location, Opcode.StoreLocal, sym.Index); methodBuilder.EmitInstruction(ident.Location, Opcode.LoadLocal, sym.Index); } else { int globalIndex = methodBuilder.Module.DefineConstant(new IodineName(ident.Value)); methodBuilder.EmitInstruction(ident.Location, Opcode.StoreGlobal, globalIndex); methodBuilder.EmitInstruction(ident.Location, Opcode.LoadGlobal, globalIndex); } } else if (binop.Left is GetExpression) { GetExpression getattr = binop.Left as GetExpression; getattr.Target.Visit(this); int attrIndex = methodBuilder.Module.DefineConstant(new IodineName(getattr.Field)); methodBuilder.EmitInstruction(getattr.Location, Opcode.StoreAttribute, attrIndex); getattr.Target.Visit(this); methodBuilder.EmitInstruction(getattr.Location, Opcode.LoadAttribute, attrIndex); } else if (binop.Left is IndexerExpression) { IndexerExpression indexer = binop.Left as IndexerExpression; indexer.Target.Visit(this); indexer.Index.Visit(this); methodBuilder.EmitInstruction(indexer.Location, Opcode.StoreIndex); binop.Left.Visit(this); } } else if (binop.Operation == BinaryOperation.InstanceOf) { binop.Right.Visit(this); binop.Left.Visit(this); methodBuilder.EmitInstruction(binop.Location, Opcode.InstanceOf); } else if (binop.Operation == BinaryOperation.NotInstanceOf) { binop.Right.Visit(this); binop.Left.Visit(this); methodBuilder.EmitInstruction(binop.Location, Opcode.InstanceOf); methodBuilder.EmitInstruction(binop.Location, Opcode.UnaryOp, (int)UnaryOperation.BoolNot); } else if (binop.Operation == BinaryOperation.DynamicCast) { binop.Right.Visit(this); binop.Left.Visit(this); methodBuilder.EmitInstruction(binop.Location, Opcode.DynamicCast); } else if (binop.Operation == BinaryOperation.NullCoalescing) { binop.Right.Visit(this); binop.Left.Visit(this); methodBuilder.EmitInstruction(binop.Location, Opcode.NullCoalesce); } else { IodineLabel shortCircuitTrueLabel = methodBuilder.CreateLabel(); IodineLabel shortCircuitFalseLabel = methodBuilder.CreateLabel(); IodineLabel endLabel = methodBuilder.CreateLabel(); binop.Left.Visit(this); /* * Short circuit evaluation */ switch (binop.Operation) { case BinaryOperation.BoolAnd: methodBuilder.EmitInstruction(binop.Location, Opcode.Dup); methodBuilder.EmitInstruction(binop.Location, Opcode.JumpIfFalse, shortCircuitFalseLabel); break; case BinaryOperation.BoolOr: methodBuilder.EmitInstruction(binop.Location, Opcode.Dup); methodBuilder.EmitInstruction(binop.Location, Opcode.JumpIfTrue, shortCircuitTrueLabel); break; } binop.Right.Visit(this); methodBuilder.EmitInstruction(binop.Location, Opcode.BinOp, (int)binop.Operation); methodBuilder.EmitInstruction(binop.Location, Opcode.Jump, endLabel); methodBuilder.MarkLabelPosition(shortCircuitTrueLabel); methodBuilder.EmitInstruction(binop.Location, Opcode.Pop); methodBuilder.EmitInstruction(binop.Location, Opcode.LoadTrue); methodBuilder.EmitInstruction(binop.Location, Opcode.Jump, endLabel); methodBuilder.MarkLabelPosition(shortCircuitFalseLabel); methodBuilder.EmitInstruction(binop.Location, Opcode.Pop); methodBuilder.EmitInstruction(binop.Location, Opcode.LoadFalse); methodBuilder.MarkLabelPosition(endLabel); } }