Example #1
0
        private Value CallLambda(ExprOp func, Scope scope, CallScope callArgs, ExprOp locus, int depth)
        {
            int  argsIndex = 0;
            long argsCount = callArgs.Size;

            SymbolScope argsScope = new SymbolScope(Scope.EmptyScope);

            for (ExprOp sym = func.Left; sym != null; sym = sym.HasRight ? sym.Right : null)
            {
                ExprOp varName = sym.Kind == OpKindEnum.O_CONS ? sym.Left : sym;

                if (!varName.IsIdent)
                {
                    throw new CalcError(CalcError.ErrorMessageInvalidFunctionDefinition);
                }

                if (argsIndex == argsCount)
                {
                    Logger.Current.Debug("expr.calc", () => String.Format("Defining function argument as null: {0}", varName.AsIdent));
                    argsScope.Define(SymbolKindEnum.FUNCTION, varName.AsIdent, WrapValue(Value.Empty));
                }
                else
                {
                    Logger.Current.Debug("expr.calc", () => String.Format("Defining function argument from call_args: {0}", varName.AsIdent));
                    argsScope.Define(SymbolKindEnum.FUNCTION, varName.AsIdent, WrapValue(callArgs[argsIndex++]));
                }
            }

            if (argsIndex < argsCount)
            {
                throw new CalcError(String.Format(CalcError.ErrorMessageTooFewArgumentsInFunctionCall, argsCount, argsIndex));
            }

            if (func.Right.IsScope)
            {
                BindScope outerScope = new BindScope(scope, func.Right.AsScope);
                BindScope boundScope = new BindScope(outerScope, argsScope);
                return(func.Right.Left.Calc(boundScope, locus, depth + 1));
            }
            else
            {
                return(func.Right.Calc(argsScope, locus, depth + 1));
            }
        }
Example #2
0
        public void SymbolScope_Define_AddsSymbolToSymbols()
        {
            MockScope   mockScope   = new MockScope();
            SymbolScope symbolScope = new SymbolScope(mockScope);

            SymbolKindEnum kind   = SymbolKindEnum.FUNCTION;
            string         name   = "the-name";
            ExprOp         exprOp = new ExprOp(OpKindEnum.CONSTANTS);

            symbolScope.Define(kind, name, exprOp);

            Assert.Equal(1, symbolScope.Symbols.Count);
            Assert.Equal(kind, symbolScope.Symbols.First().Key.Kind);
            Assert.Equal(name, symbolScope.Symbols.First().Key.Name);
            Assert.Equal(exprOp, symbolScope.Symbols.First().Key.Definition);
            Assert.Equal(exprOp, symbolScope.Symbols[symbolScope.Symbols.First().Key]);
        }
Example #3
0
        public void SymbolScope_Lookup_TriesGetAValueFromSymbols()
        {
            MockScope   mockScope   = new MockScope();
            SymbolScope symbolScope = new SymbolScope(mockScope);

            SymbolKindEnum kind   = SymbolKindEnum.FUNCTION;
            string         name   = "the-name";
            ExprOp         exprOp = new ExprOp(OpKindEnum.CONSTANTS);

            symbolScope.Define(kind, name, exprOp);

            ExprOp result = symbolScope.Lookup(kind, name);

            Assert.Equal(exprOp, result);

            ExprOp result2 = symbolScope.Lookup(SymbolKindEnum.OPTION, "dummy");

            Assert.Equal(mockScope.LookupResult, result2);
        }
Example #4
0
        /// <summary>
        /// Ported from expr_t::ptr_op_t expr_t::op_t::compile
        /// </summary>
        public ExprOp Compile(Scope scope, int depth = 0, Scope paramScope = null)
        {
            ExprOp result = null;
            Scope  boundScope;

            Logger.Current.Debug("expr.compile", () => new String('.', depth));

            if (Kind >= OpKindEnum.LAST)
            {
                throw new InvalidOperationException();
            }

            if (IsIdent)
            {
                Logger.Current.Debug("expr.compile", () => String.Format("Lookup: {0} in {1}", AsIdent, scope));
                ExprOp def = null;
                if (paramScope != null)
                {
                    def = paramScope.Lookup(SymbolKindEnum.FUNCTION, AsIdent);
                }

                if (def == null)
                {
                    def = scope.Lookup(SymbolKindEnum.FUNCTION, AsIdent);
                }

                if (def != null)
                {
                    // Identifier references are first looked up at the point of
                    // definition, and then at the point of every use if they could
                    // not be found there.
                    Logger.Current.Debug("expr.compile", () => String.Format("Found definition:{0}", def.Dump()));
                    result = Copy(def);
                }
                else if (Left != null)
                {
                    result = Copy();
                }
                else
                {
                    result = this;
                }
            }
            else if (IsScope)
            {
                Scope subScope = new SymbolScope(Scope.EmptyScope);
                AsScope    = subScope;
                boundScope = new BindScope(scope, subScope);
                scope      = boundScope;
            }
            else if (Kind < OpKindEnum.TERMINALS)
            {
                result = this;
            }
            else if (Kind == OpKindEnum.O_DEFINE)
            {
                switch (Left.Kind)
                {
                case OpKindEnum.IDENT:
                {
                    ExprOp node = Right.Compile(scope, depth + 1, paramScope);
                    Logger.Current.Debug("expr.compile", () => String.Format("Defining {0} in {1}", Left.AsIdent, scope));
                    scope.Define(SymbolKindEnum.FUNCTION, Left.AsIdent, node);
                }
                break;

                case OpKindEnum.O_CALL:
                    if (Left.Left.IsIdent)
                    {
                        ExprOp node = new ExprOp(OpKindEnum.O_LAMBDA);
                        node.Left  = Left.Right;
                        node.Right = Right;

                        node.Compile(scope, depth + 1, paramScope);
                        Logger.Current.Debug("expr.compile", () => String.Format("Defining {0} in {1}", Left.Left.AsIdent, scope));
                        scope.Define(SymbolKindEnum.FUNCTION, Left.Left.AsIdent, node);
                        break;
                    }
                    throw new CompileError(CompileError.ErrorMessageInvalidFunctionDefinition);

                default:
                    throw new CompileError(CompileError.ErrorMessageInvalidFunctionDefinition);
                }
                result = WrapValue(Value.Empty);
            }
            else if (Kind == OpKindEnum.O_LAMBDA)
            {
                SymbolScope parms = new SymbolScope(paramScope ?? Scope.EmptyScope);

                for (ExprOp sym = Left; sym != null; sym = sym.HasRight ? sym.Right : null)
                {
                    ExprOp varName = sym.Kind == OpKindEnum.O_CONS ? sym.Left : sym;
                    if (!varName.IsIdent)
                    {
                        string buf = varName.Dump();
                        throw new CalcError(String.Format(CalcError.ErrorMessageInvalidFunctionOrLambdaParameter, buf));
                    }
                    else
                    {
                        Logger.Current.Debug("expr.compile", () => String.Format("Defining function parameter {0}", varName.AsIdent));
                        parms.Define(SymbolKindEnum.FUNCTION, varName.AsIdent, new ExprOp(OpKindEnum.PLUG));
                    }
                }

                ExprOp rhs = Right.Compile(scope, depth + 1, parms);
                if (rhs == Right)
                {
                    result = this;
                }
                else
                {
                    result = Copy(Left, rhs);
                }
            }

            if (result == null)
            {
                if (Left == null)
                {
                    throw new CalcError(CalcError.ErrorMessageSyntaxError);
                }

                ExprOp lhs = Left.Compile(scope, depth + 1, paramScope);
                ExprOp rhs = Kind > OpKindEnum.UNARY_OPERATORS && HasRight
                    ? (Kind == OpKindEnum.O_LOOKUP ? Right : Right.Compile(scope, depth + 1, paramScope))
                    : null;

                if (lhs == Left && (rhs == null || rhs == Right))
                {
                    result = this;
                }
                else
                {
                    ExprOp intermediate = Copy(lhs, rhs);

                    // Reduce constants immediately if possible
                    if ((lhs == null || lhs.IsValue) && (rhs == null || rhs.IsValue))
                    {
                        result = WrapValue(intermediate.Calc(scope, null, depth + 1));
                    }
                    else
                    {
                        result = intermediate;
                    }
                }
            }

            Logger.Current.Debug("expr.compile", () => new String('.', depth));

            return(result);
        }
Example #5
0
        /// <summary>
        /// Ported from void posts_to_org_table::operator()(post_t& post)
        /// </summary>
        public override void Handle(Post post)
        {
            if (!post.HasXData || !post.XData.Displayed)
            {
                StringBuilder sb = new StringBuilder();

                BindScope boundScope = new BindScope(Report, post);

                if (!HeaderPrinted)
                {
                    sb.AppendLine("|Date|Code|Payee|X|Account|Amount|Total|Note|");
                    sb.AppendLine("|-|");
                    sb.AppendLine("|||<20>|||<r>|<r>|<20>|");
                    HeaderPrinted = true;
                }

                if (!String.IsNullOrEmpty(ReportTitle))
                {
                    if (FirstReportTitle)
                    {
                        FirstReportTitle = false;
                    }
                    else
                    {
                        sb.AppendLine();
                    }

                    ValueScope valScope         = new ValueScope(boundScope, Value.StringValue(ReportTitle));
                    Format     groupTitleFormat = new Format(Report.GroupTitleFormatHandler.Str());

                    sb.AppendLine("|-|");
                    sb.Append("|" + groupTitleFormat.Calc(valScope));
                    sb.AppendLine("|-|");

                    ReportTitle = String.Empty;
                }

                if (PrependFormat != null)
                {
                    sb.Append("|" + PrependFormat.Calc(boundScope));
                }

                if (LastXact != post.Xact)
                {
                    sb.Append(FirstLineFormat.Calc(boundScope));
                    LastXact = post.Xact;
                }
                else if (LastPost != null && LastPost.GetDate() != post.GetDate())
                {
                    sb.Append(FirstLineFormat.Calc(boundScope));
                }
                else
                {
                    sb.Append(NextLineFormat.Calc(boundScope));
                }

                Value amt = new Expr("display_amount").Calc(boundScope).Simplified();
                Value tot = new Expr("display_total").Calc(boundScope).Simplified();

                if (amt.Type == ValueTypeEnum.Balance || tot.Type == ValueTypeEnum.Balance)
                {
                    Balance amtBal = amt.AsBalance;
                    Balance totBal = tot.AsBalance;

                    var  i     = amtBal.Amounts.GetIterator();
                    var  j     = totBal.Amounts.GetIterator();
                    bool first = true;

                    while (!i.IsEnd || !j.IsEnd)
                    {
                        if (first)
                        {
                            first = false;
                            if (!i.IsEnd)
                            {
                                i.MoveNext();
                            }
                            if (!j.IsEnd)
                            {
                                j.MoveNext();
                            }
                        }
                        else
                        {
                            SymbolScope callScope = new SymbolScope(boundScope);
                            bool        assigned  = false;

                            if (!i.IsEnd)
                            {
                                if (i.Current.Value != null)
                                {
                                    Logger.Current.Debug(DebugOrgNextAmount, () => String.Format("next_amount = {0}", i.Current.Value));
                                    callScope.Define(SymbolKindEnum.FUNCTION, "next_amount", ExprOp.WrapValue(Value.Get(i.Current.Value)));
                                    i.MoveNext();
                                    assigned = true;
                                }
                                else
                                {
                                    callScope.Define(SymbolKindEnum.FUNCTION, "next_amount", ExprOp.WrapValue(Value.StringValue(String.Empty)));
                                    i.MoveNext();
                                }
                            }
                            else
                            {
                                callScope.Define(SymbolKindEnum.FUNCTION, "next_amount", ExprOp.WrapValue(Value.StringValue(String.Empty)));
                            }

                            if (!j.IsEnd)
                            {
                                if (j.Current.Value != null)
                                {
                                    Logger.Current.Debug(DebugOrgNextTotal, () => String.Format("next_total = {0}", j.Current.Value));
                                    callScope.Define(SymbolKindEnum.FUNCTION, "next_total", ExprOp.WrapValue(Value.Get(j.Current.Value)));
                                    j.MoveNext();
                                    Logger.Current.Debug(DebugOrgNextTotal, () => String.Format("2.next_total = {0}", callScope.Lookup(SymbolKindEnum.FUNCTION, "next_total").AsValue));
                                    assigned = true;
                                }
                                else
                                {
                                    callScope.Define(SymbolKindEnum.FUNCTION, "next_total", ExprOp.WrapValue(Value.StringValue(String.Empty)));
                                    j.MoveNext();
                                }
                            }
                            else
                            {
                                callScope.Define(SymbolKindEnum.FUNCTION, "next_total", ExprOp.WrapValue(Value.StringValue(String.Empty)));
                            }

                            if (assigned)
                            {
                                AmountLinesFormat.MarkUncomplited();
                                sb.Append(AmountLinesFormat.Calc(callScope));
                            }
                        }
                    }
                }

                post.XData.Displayed = true;
                LastPost             = post;

                Report.OutputStream.Write(sb.ToString());
            }
        }