public override int Compile(FunctionContext context) { context.Line(FileName, Line); var stack = 0; TokenType assignOperation; var hasAssignOperation = _assignMap.TryGetValue(Operation, out assignOperation); var isAssign = Operation == TokenType.Assign || hasAssignOperation; if (isAssign) { var storable = Left as IStorableExpression; if (storable == null) { throw new MondCompilerException(FileName, Line, CompilerError.LeftSideMustBeStorable); } var needResult = !(Parent is IBlockExpression); stack += Right.Compile(context); if (hasAssignOperation) { stack += Left.Compile(context); stack += context.BinaryOperation(assignOperation); } if (needResult) { stack += context.Dup(); } stack += storable.CompileStore(context); CheckStack(stack, needResult ? 1 : 0); return(stack); } if (Operation == TokenType.ConditionalOr) { var endOr = context.MakeLabel("endOr"); stack += Left.Compile(context); stack += context.JumpTruePeek(endOr); stack += context.Drop(); stack += Right.Compile(context); stack += context.Bind(endOr); CheckStack(stack, 1); return(stack); } if (Operation == TokenType.ConditionalAnd) { var endAnd = context.MakeLabel("endAnd"); stack += Left.Compile(context); stack += context.JumpFalsePeek(endAnd); stack += context.Drop(); stack += Right.Compile(context); stack += context.Bind(endAnd); CheckStack(stack, 1); return(stack); } stack += Right.Compile(context); stack += Left.Compile(context); stack += context.BinaryOperation(Operation); CheckStack(stack, 1); return(stack); }
public override int Compile(FunctionContext context) { context.Line(FileName, Line); TokenType assignOperation; var hasAssignOperation = _assignMap.TryGetValue(Operation, out assignOperation); var isAssign = Operation == TokenType.Assign || hasAssignOperation; if (isAssign) { var storable = Left as IStorableExpression; if (storable == null) throw new MondCompilerException(FileName, Line, "The left-hand side of an assignment must be storable"); var needResult = !(Parent is BlockExpression); var stack = 0; CompileCheck(context, Right, 1); if (hasAssignOperation) { CompileCheck(context, Left, 1); context.BinaryOperation(assignOperation); } if (needResult) { context.Dup(); stack++; } storable.CompileStore(context); return stack; } if (Operation == TokenType.LogicalOr) { var endOr = context.MakeLabel("endOr"); CompileCheck(context, Left, 1); context.JumpTruePeek(endOr); CompileCheck(context, Right, 1); context.Bind(endOr); return 1; } if (Operation == TokenType.LogicalAnd) { var endAnd = context.MakeLabel("endAnd"); CompileCheck(context, Left, 1); context.JumpFalsePeek(endAnd); CompileCheck(context, Right, 1); context.Bind(endAnd); return 1; } CompileCheck(context, Right, 1); CompileCheck(context, Left, 1); context.BinaryOperation(Operation); return 1; }
public override int Compile(FunctionContext context) { var stack = 0; var isAssignOperation = _assignMap.TryGetValue(Operation, out var assignOperation); if (IsAssign) { var storable = Left as IStorableExpression; if (storable == null) { throw new MondCompilerException(this, CompilerError.LeftSideMustBeStorable); } var needResult = !(Parent is IBlockExpression); if (isAssignOperation) { int preTotal; var preTimes = needResult ? 3 : 2; stack += preTotal = storable.CompilePreLoadStore(context, preTimes); stack += storable.CompileLoad(context); stack += Right.Compile(context); stack += context.BinaryOperation(assignOperation); switch (preTotal / preTimes) { case 0: break; case 1: stack += context.Swap(); break; case 2: stack += context.Swap1For2(); break; default: throw new NotSupportedException(); } stack += storable.CompileStore(context); if (needResult) { stack += storable.CompileLoad(context); } } else { stack += Right.Compile(context); if (needResult) { stack += context.Dup(); } stack += storable.CompilePreLoadStore(context, 1); stack += storable.CompileStore(context); } CheckStack(stack, needResult ? 1 : 0); return(stack); } if (Operation == TokenType.ConditionalOr) { var endOr = context.MakeLabel("endOr"); stack += Left.Compile(context); stack += context.JumpTruePeek(endOr); stack += context.Drop(); stack += Right.Compile(context); stack += context.Bind(endOr); CheckStack(stack, 1); return(stack); } if (Operation == TokenType.ConditionalAnd) { var endAnd = context.MakeLabel("endAnd"); stack += Left.Compile(context); stack += context.JumpFalsePeek(endAnd); stack += context.Drop(); stack += Right.Compile(context); stack += context.Bind(endAnd); CheckStack(stack, 1); return(stack); } stack += Left.Compile(context); stack += Right.Compile(context); context.Position(Token); // debug info stack += context.BinaryOperation(Operation); CheckStack(stack, 1); return(stack); }