private Metadata(IEnumerable <NE> exprsHdr, IEnumerable <NE> exprsRow, IEnumerable <NE> exprsRes, Generator.Ctx parentCtx) { var sb = new StringBuilder(); FixSheetExpr = Expr.RecursiveModifier(FixSheetImpl); FixRowExpr = Expr.RecursiveModifier(FixRowImpl); #region generate header code ctxHdr = new Generator.Ctx(parentCtx); ctxHdr.CreateValue(HdrCellsRef.name, Generator.LazyDummy); ctxHdr.CreateValue(PrevValsRef.name, Generator.LazyDummy); foreach (var p in exprsHdr) { FCurrName = p.name; var expr = FixSheetExpr(p.expr); var val = Generator.Generate(expr, ctxHdr); ctxHdr.CreateValue(p.name, val); if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } sb.AppendLine($"{p.name} = {expr}"); } sb.AppendLine(); RequiredInHdr(sSourceKey); RequiredInHdr(sSourceName); RequiredInHdr(sCondition); RequiredInHdr(sFirstDataRowNum); { if (ctxHdr.name2ndx.TryGetValue(sFileContentKind, out int i)) { FileContentKind = Convert.ToString(ctxHdr.GetConstant(sFileContentKind)); } else { FileContentKind = "XLSX"; } } { if (ctxHdr.name2ndx.TryGetValue(sFileNameExtension, out int i)) { var val = ctxHdr.GetConstant(sFileNameExtension); FileNameExtension = Utils.AsIList(val).Cast <object>().Select(Convert.ToString).ToArray(); } else { FileNameExtension = new string[] { "xls", "xlsx", "xlsm" } }; } #endregion #region generate row code ctxRow = new Generator.Ctx(ctxHdr); ctxRow.CreateValue(sDataKey, Generator.LazyDummy); // [0] - iKey ctxRow.CreateValue(sDataSubkey, Generator.LazyDummy); // [1] - iSubkey ctxRow.CreateValue(CellValsRef.name, Generator.LazyDummy); // [2] - iRowVals foreach (var p in exprsRow) { string name; if (p.name.StartsWith("~")) { // calculated name name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name; } else { name = p.name; } FCurrName = name; int i = ctxRow.GetOrCreateIndexOf(name); var expr = FixRowExpr(p.expr); var val = Generator.Generate(expr, ctxRow); ctxRow.values[i] = val; if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } sb.AppendLine($"{name} = {expr}"); } RequiredInRow(sDataKey); RequiredInRow(sDataSubkey); ctxRow.values[iRowVals] = null; ctxRow.CheckUndefinedValues(); #endregion #region generate res code if (exprsRes != null) { // copy all code from row to res ctxRes = new Generator.Ctx(ctxHdr); foreach (var p in ctxRow.name2ndx.OrderBy(p => p.Value)) { ctxRes.values[ctxRes.CreateValue(p.Key)] = ctxRow.values[p.Value]; } foreach (var p in exprsRes) { string name; if (p.name.StartsWith("~")) { // calculated name name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name; } else { name = p.name; } FCurrName = name; int i = ctxRes.GetOrCreateIndexOf(name); var expr = FixRowExpr(p.expr); var val = Generator.Generate(expr, ctxRes); ctxRes.values[i] = val; if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } } ctxRes.values[iRowVals] = null; ctxRes.CheckUndefinedValues(); } #endregion ctxHdr[HdrCellsRef.name] = null; ctxHdr[PrevValsRef.name] = null; ctxHdr.CheckUndefinedValues(); FCodeText = sb.ToString(); if (iHdrMinUsedRow > iHdrMaxUsedRow) { iHdrMinUsedRow = iHdrMaxUsedRow; } }
Expr SpecFuncs(CallExpr ce) { Expr src, ndx; bool forPrev = false, forCell = false; int nMinArgs = 1; switch (ce.funcName) { case "PREVCELL": forCell = true; forPrev = true; break; case "PREV": nMinArgs = 0; forPrev = true; break; case "INDIRECT": forCell = true; break; case nameof(FuncDefs_Xlsx.COLUMN): // avoid COLUMN(args) fixing return(new CallExpr(nameof(FuncDefs_Xlsx.COLUMN), ce.args)); default: return(ce); } if (ce.args.Count < nMinArgs) { return(ce); } Expr arg; string name; if (ce.args.Count == 0) { arg = null; name = FCurrName; } else { arg = ce.args[0]; if (arg.nodeType == ExprType.Reference) { name = ((ReferenceExpr)arg).name; if (IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name))) { forCell = true; } else { name = OPs.TryAsString(arg, ctxRow) ?? name; } } else { arg = FixRowExpr(arg); name = OPs.TryAsName(arg, ctxRow); } } if (name == null) { var undefs = string.Join(", ", ctxHdr.NamesOfUndefinedValues().Concat(ctxRow.NamesOfUndefinedValues())); throw new Source.Exception($"Constant expected as value of {ce.args[0]}={arg} // ??? {undefs}"); } if (forCell || IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name))) { if (forPrev) { src = new IndexExpr(PrevValsRef, new ConstExpr(ctxRow.IndexOf(CellValsRef.name))); } else { var re1 = new ReferenceExpr(name); var re2 = FixHdrCellRef(re1); if (re2 != re1) { // ref to header cell return(re2); } else { // ref to row cell src = CellValsRef; } } ndx = new ConstExpr(name); } else { int i = ctxRow.IndexOf(name); if (i < 0 || Generator.Ctx.ctxDepthStep <= i) { throw new Source.Exception($"Value named '{name}' not found in row context"); } src = PrevValsRef; ndx = new ConstExpr(i); } return(new IndexExpr(src, ndx)); }