/* * Copyright © 2011, Petro Protsyk, Denys Vuika * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Scripting.SSharp.Parser.Ast { using Runtime.Operators; using Runtime; using System; /// /// Binary Expression /// internal class ScriptBinExpr : ScriptExpr { protected ScriptExpr left; protected ScriptExpr right; protected string Oper; protected IOperator OperatorFunction; public ScriptExpr Left { get { return left; } } public ScriptExpr Right { get { return right; } } public string Symbol { get { return Oper; } } protected internal override bool IsConst { get { if (Left == null || Right == null) return false; return Left.IsConst && Right.IsConst; } } protected object Value { get; set; } protected Action Evaluation; public ScriptBinExpr(AstNodeArgs args) : base(args) { left = (ScriptExpr)ChildNodes[0]; Oper = ((TokenAst)ChildNodes[1]).Text; right = (ScriptExpr)ChildNodes[2]; Value = RuntimeHost.NullValue; if (IsConst) Evaluation = ConstFirstEvaluate; else Evaluation = CompleteEvaluate; OperatorFunction = RuntimeHost.GetBinaryOperator(Oper); if (OperatorFunction == null) throw new ScriptRuntimeException(string.Format(Strings.MissingOperatorError, Oper)); } public override void Evaluate(IScriptContext context) { Evaluation(context); } private void ConstFirstEvaluate(IScriptContext context) { CompleteEvaluate(context); Value = context.Result; Evaluation = ConstEvaluate; } private void ConstEvaluate(IScriptContext context) { context.Result = Value; } private void CompleteEvaluate(IScriptContext context) { HandleOperatorArgs handling; left.Evaluate(context); var leftVal = context.Result; context.Result = RuntimeHost.NullValue; if ((Oper == "&&" && false.Equals(leftVal)) || (Oper == "||" && true.Equals(leftVal))) { handling = OnHandleOperator(this, context, Oper, leftVal); context.Result = handling.Cancel ? handling.Result : leftVal; return; } right.Evaluate(context); var rightVal = context.Result; handling = OnHandleOperator(this, context, Oper, leftVal, rightVal); context.Result = handling.Cancel ? handling.Result : OperatorFunction.Evaluate(leftVal, rightVal); } } }