示例#1
0
文件: Expr.cs 项目: taiab/nledger
        protected override Value RealCalc(Scope scope)
        {
            if (Op != null)
            {
                ExprOp locus = null;
                try
                {
                    return(Op.Calc(scope, locus));
                }
                catch
                {
                    if (locus != null)
                    {
                        string currentContext = ErrorContext.Current.GetContext();

                        ErrorContext.Current.AddErrorContext("While evaluating value expression:");
                        ErrorContext.Current.AddErrorContext(ErrorContext.OpContext(Op, locus));

                        if (Logger.Current.ShowInfo())
                        {
                            ErrorContext.Current.AddErrorContext("The value expression tree was:");
                            ErrorContext.Current.AddErrorContext(Op.Dump());
                        }

                        if (!String.IsNullOrEmpty(currentContext))
                        {
                            ErrorContext.Current.AddErrorContext(currentContext);
                        }
                    }
                    throw;
                }
            }
            return(new Value());
        }
示例#2
0
文件: Expr.cs 项目: taiab/nledger
 public override string ContextToStr()
 {
     return(Op != null?ErrorContext.OpContext(Op) : "<empty expression>");
 }
示例#3
0
        /// <summary>
        /// Ported from value_t expr_t::op_t::calc
        /// </summary>
        public Value Calc(Scope scope, ExprOp locus = null, int depth = 0)
        {
            try
            {
                Value result = Value.Empty;

                Logger.Current.Debug("expr.calc", () => String.Format("{0}{1} => ...", new String('.', depth), ErrorContext.OpContext(this)));

                switch (Kind)
                {
                case OpKindEnum.VALUE:
                    result = AsValue;
                    break;

                case OpKindEnum.O_DEFINE:
                    result = Value.Empty;
                    break;

                case OpKindEnum.IDENT:
                    ExprOp definition = LookupIdent(this, scope);
                    if (definition != null)
                    {
                        // Evaluating an identifier is the same as calling its definition
                        // directly
                        result = definition.Calc(scope, locus, depth + 1);
                        CheckTypeContext(scope, result);
                    }
                    break;

                case OpKindEnum.FUNCTION:
                    // Evaluating a FUNCTION is the same as calling it directly; this
                    // happens when certain functions-that-look-like-variables (such as
                    // "amount") are resolved.
                    CallScope callArgs = new CallScope(scope, locus, depth + 1);
                    result = AsFunction(callArgs);
                    CheckTypeContext(scope, result);
                    break;

                case OpKindEnum.SCOPE:
                    // assert(! is_scope_unset()); - does not make sense here
                    if (IsScopeUnset)
                    {
                        SymbolScope subscope = new SymbolScope(scope);
                        result = Left.Calc(subscope, locus, depth + 1);
                    }
                    else
                    {
                        BindScope boundScope = new BindScope(scope, AsScope);
                        result = Left.Calc(boundScope, locus, depth + 1);
                    }
                    break;

                case OpKindEnum.O_LOOKUP:
                    ContextScope contextScope = new ContextScope(scope, ValueTypeEnum.Scope);
                    bool         scopeError   = true;
                    Value        obj          = Left.Calc(contextScope, locus, depth + 1);
                    if (obj != null)
                    {
                        if (obj.Type == ValueTypeEnum.Scope && obj.AsScope != null)
                        {
                            BindScope boundScope = new BindScope(scope, obj.AsScope);
                            result     = Right.Calc(boundScope, locus, depth + 1);
                            scopeError = false;
                        }
                    }
                    if (scopeError)
                    {
                        throw new CalcError(CalcError.ErrorMessageLeftOperandDoesNotEvaluateToObject);
                    }
                    break;

                case OpKindEnum.O_CALL:
                    result = CalcCall(scope, locus, depth);
                    CheckTypeContext(scope, result);
                    break;

                case OpKindEnum.O_LAMBDA:
                    result = Value.Get(this);
                    break;

                case OpKindEnum.O_MATCH:
                    result = Value.Get(Right.Calc(scope, locus, depth + 1).AsMask.Match(Left.Calc(scope, locus, depth + 1).ToString()));
                    break;

                case OpKindEnum.O_EQ:
                    result = Value.Get(Left.Calc(scope, locus, depth + 1).IsEqualTo(Right.Calc(scope, locus, depth + 1)));
                    break;

                case OpKindEnum.O_LT:
                    result = Value.Get(Left.Calc(scope, locus, depth + 1).IsLessThan(Right.Calc(scope, locus, depth + 1)));
                    break;

                case OpKindEnum.O_LTE:
                    result = Value.Get(!Left.Calc(scope, locus, depth + 1).IsGreaterThan(Right.Calc(scope, locus, depth + 1)));
                    break;

                case OpKindEnum.O_GT:
                    result = Value.Get(Left.Calc(scope, locus, depth + 1).IsGreaterThan(Right.Calc(scope, locus, depth + 1)));
                    break;

                case OpKindEnum.O_GTE:
                    result = Value.Get(!Left.Calc(scope, locus, depth + 1).IsLessThan(Right.Calc(scope, locus, depth + 1)));
                    break;

                case OpKindEnum.O_ADD:
                    result = Left.Calc(scope, locus, depth + 1) + Right.Calc(scope, locus, depth + 1);
                    break;

                case OpKindEnum.O_SUB:
                    result = Left.Calc(scope, locus, depth + 1) - Right.Calc(scope, locus, depth + 1);
                    break;

                case OpKindEnum.O_MUL:
                    result = Left.Calc(scope, locus, depth + 1) * Right.Calc(scope, locus, depth + 1);
                    break;

                case OpKindEnum.O_DIV:
                    result = Left.Calc(scope, locus, depth + 1) / Right.Calc(scope, locus, depth + 1);
                    break;

                case OpKindEnum.O_NEG:
                    result = Left.Calc(scope, locus, depth + 1).Negated();
                    break;

                case OpKindEnum.O_NOT:
                    result = Value.Get(!Left.Calc(scope, locus, depth + 1).Bool);
                    break;

                case OpKindEnum.O_AND:
                    if (Left.Calc(scope, locus, depth + 1).Bool)
                    {
                        result = Right.Calc(scope, locus, depth + 1);
                    }
                    else
                    {
                        result = Value.Get(false);
                    }
                    break;

                case OpKindEnum.O_OR:
                    Value temp_O_OR = Left.Calc(scope, locus, depth + 1);
                    if (temp_O_OR.Bool)
                    {
                        result = temp_O_OR;
                    }
                    else
                    {
                        result = Right.Calc(scope, locus, depth + 1);
                    }
                    break;

                case OpKindEnum.O_QUERY:
                    if (Right == null || Right.Kind != OpKindEnum.O_COLON)
                    {
                        throw new InvalidOperationException("O_QUERY");
                    }

                    Value temp = Left.Calc(scope, locus, depth + 1);
                    if (temp.Bool)
                    {
                        result = Right.Left.Calc(scope, locus, depth + 1);
                    }
                    else
                    {
                        result = Right.Right.Calc(scope, locus, depth + 1);
                    }
                    break;

                case OpKindEnum.O_COLON:
                    throw new InvalidOperationException("We should never calculate an O_COLON operator");

                case OpKindEnum.O_CONS:
                    result = CalcCons(scope, locus, depth);
                    break;

                case OpKindEnum.O_SEQ:
                    result = CalcSeq(scope, locus, depth);
                    break;

                default:
                    throw new CalcError(String.Format(CalcError.ErrorMessageUnexpectedExprNode, this));
                }

                Logger.Current.Debug("expr.calc", () => String.Format("{0}{1} => {2}", new String('.', depth), ErrorContext.OpContext(this), result.Dump(true)));

                return(result);
            }
            catch
            {
                if (locus == null)
                {
                    locus = this;
                }
                throw;
            }
        }