From d27fbe96a6e514db29ee803a48b10febb607fe97 Mon Sep 17 00:00:00 2001 From: Gavin Morris Date: Sun, 16 Jun 2024 18:38:02 -0400 Subject: [PATCH 1/9] feat: initial PadLeft func impl --- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index e169e6d..56b55a9 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -679,6 +679,59 @@ public static string ExecEnd(string src) } } +public sealed partial class TextPadLeftFunc: RexlOper +{ + public static readonly TextPadLeftFunc Instance = new TextPadLeftFunc(); + + private TextPadLeftFunc() + : base(isFunc: true, new DName("PadLeft"), BindUtil.TextNs, 1, 2) + { + } + + protected override ArgTraits GetArgTraitsCore(int carg) + { + Validation.BugCheckParam(SupportsArity(carg), nameof(carg)); + var maskAll = BitSet.GetMask(carg); + var maskOpt = maskAll.ClearBit(0); + return ArgTraitsLifting.Create(this, carg, maskLiftSeq: maskAll, maskLiftTen: maskAll); + } + + + + protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) + { + Validation.AssertValue(reducer); + Validation.Assert(IsValidCall(call)); + + var args = call.Args; + if (args[0].TryGetString(out var str)) + return BndIntNode.CreateI8(Util.Size(str)); + + return call; + } + + protected override bool CertifyCore(BndCallNode call, ref bool full) + { + if (call.Type != DType.Text) + return false; + var args = call.Args; + if (args[0].Type != DType.I8Req) + return false; + if (args[1].Type != DType.Text) + return false; + return true; + } + + public static string Exec(string src, int padding_len, char padding_char = ' ') + { + if (string.IsNullOrEmpty(src)) + return src; + if (padding_len == 0) + return src; + return src.PadLeft(padding_len, padding_char); + } +} + public sealed partial class TextReplaceFunc : RexlOper { public static readonly TextReplaceFunc Instance = new TextReplaceFunc(); From 7212e8f19cbf30a96c606347ff33af71436bf229 Mon Sep 17 00:00:00 2001 From: Gavin Date: Tue, 18 Jun 2024 19:26:25 -0400 Subject: [PATCH 2/9] adding some decs, removing unneeded functions --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 2 + src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 38 ++++++------------- src/Core/Rexl.Bind/Strings/RexlStrings.cs | 2 + src/Core/Rexl.Bind/Strings/RexlStrings.tt | 3 ++ 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index ef089a2..d3b6621 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,6 +378,8 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); + AddOne(TextPadLeftFunc.Instance, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPadLeft_Source))); + AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), A.Create(S.TextReplace_Remove, S.AboutTextReplace_Remove), diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index 56b55a9..987011a 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -679,56 +679,40 @@ public static string ExecEnd(string src) } } -public sealed partial class TextPadLeftFunc: RexlOper +public sealed partial class TextPadLeftFunc: TextFuncOne { public static readonly TextPadLeftFunc Instance = new TextPadLeftFunc(); private TextPadLeftFunc() - : base(isFunc: true, new DName("PadLeft"), BindUtil.TextNs, 1, 2) + : base(new DName("PadLeft"), BindUtil.TextNs, 1, 2) { } protected override ArgTraits GetArgTraitsCore(int carg) { - Validation.BugCheckParam(SupportsArity(carg), nameof(carg)); - var maskAll = BitSet.GetMask(carg); - var maskOpt = maskAll.ClearBit(0); - return ArgTraitsLifting.Create(this, carg, maskLiftSeq: maskAll, maskLiftTen: maskAll); - } - - - - protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) - { - Validation.AssertValue(reducer); - Validation.Assert(IsValidCall(call)); - - var args = call.Args; - if (args[0].TryGetString(out var str)) - return BndIntNode.CreateI8(Util.Size(str)); - - return call; + Validation.Assert(SupportsArity(carg)); + return ArgTraitsSimple.Create(this, eager: true, carg); } protected override bool CertifyCore(BndCallNode call, ref bool full) { if (call.Type != DType.Text) return false; - var args = call.Args; - if (args[0].Type != DType.I8Req) - return false; - if (args[1].Type != DType.Text) - return false; + // var args = call.Args; + // if (args[0].Type != DType.I8Req) + // return false; + // if (args[1].Type != DType.Text) + // return false; return true; } - public static string Exec(string src, int padding_len, char padding_char = ' ') + public static string Exec(string src, int padding_len) { if (string.IsNullOrEmpty(src)) return src; if (padding_len == 0) return src; - return src.PadLeft(padding_len, padding_char); + return src.PadLeft(padding_len); } } diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index bf86c7b..21a76d6 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -348,6 +348,8 @@ static partial class RexlStrings public static readonly StringId AboutEndsWith = new(nameof(AboutEndsWith), "Tests whether the end of the source text matches the lookup text."); + public static readonly StringId AboutPadLeft = new(nameof(AboutPadLeft), "Returns a new string with the provided number of spaces/specified characters added to the left."); + public static readonly StringId AboutPadLeft_Source = new(nameof(AboutPadLeft), "The text to convert to lowercase."); public static readonly StringId AboutStrLen = new(nameof(AboutStrLen), "Returns the number of characters in the text value."); public static readonly StringId AboutStrLen_Source = new(nameof(AboutStrLen_Source), "The text in which to count the characters."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index 84c5af0..eac956b 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -336,6 +336,9 @@ AboutLower_Source = "The text to convert to lowercase." AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." +AboutPadLeft = "Adds characters to the left of a string." +AboutPadLeft_Source = "The text to add padding to." + AboutStartsWith = "Tests whether the beginning of the source text matches the lookup text." AboutStartsWith_Source = "The text to look in." AboutStartsWith_LookUp = "The text to look for." From 9e6f68525af5ab1f6c4c6e52ebec059f54697783 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Thu, 20 Jun 2024 17:32:06 -0400 Subject: [PATCH 3/9] adding generators --- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 76 ++++++++++--------- .../Rexl.Code/Operations/BuiltinGenerators.cs | 1 + src/Core/Rexl.Code/Operations/Funcs/Text.cs | 23 ++++++ 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index 987011a..7bb67d7 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -679,43 +679,6 @@ public static string ExecEnd(string src) } } -public sealed partial class TextPadLeftFunc: TextFuncOne -{ - public static readonly TextPadLeftFunc Instance = new TextPadLeftFunc(); - - private TextPadLeftFunc() - : base(new DName("PadLeft"), BindUtil.TextNs, 1, 2) - { - } - - protected override ArgTraits GetArgTraitsCore(int carg) - { - Validation.Assert(SupportsArity(carg)); - return ArgTraitsSimple.Create(this, eager: true, carg); - } - - protected override bool CertifyCore(BndCallNode call, ref bool full) - { - if (call.Type != DType.Text) - return false; - // var args = call.Args; - // if (args[0].Type != DType.I8Req) - // return false; - // if (args[1].Type != DType.Text) - // return false; - return true; - } - - public static string Exec(string src, int padding_len) - { - if (string.IsNullOrEmpty(src)) - return src; - if (padding_len == 0) - return src; - return src.PadLeft(padding_len); - } -} - public sealed partial class TextReplaceFunc : RexlOper { public static readonly TextReplaceFunc Instance = new TextReplaceFunc(); @@ -795,3 +758,42 @@ public static string Exec(string src, string remove, string insert) return src.Replace(remove, insert); } } + +public sealed partial class TextPadLeftFunc: RexlOper +{ + public static readonly TextPadLeftFunc Instance = new TextPadLeftFunc(); + + private TextPadLeftFunc() + : base(isFunc: true, new DName("PadLeft"), BindUtil.TextNs, 1, 2) + { + } + + public Func Map { get; } + + protected override ArgTraits GetArgTraitsCore(int carg) + { + Validation.Assert(SupportsArity(carg)); + return ArgTraitsSimple.Create(this, eager: true, carg); + } + + protected override bool CertifyCore(BndCallNode call, ref bool full) + { + if (call.Type != DType.Text) + return false; + // var args = call.Args; + // if (args[0].Type != DType.I8Req) + // return false; + // if (args[1].Type != DType.Text) + // return false; + return true; + } + + public static string Exec(string src, int padding_len) + { + if (string.IsNullOrEmpty(src)) + return src; + if (padding_len == 0) + return src; + return src.PadLeft(padding_len); + } +} diff --git a/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs b/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs index 8f3b13e..bbd7ee5 100644 --- a/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs +++ b/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs @@ -59,6 +59,7 @@ private BuiltinGenerators() Add(TextPartGen.Instance); Add(TextTrimGen.Instance); Add(TextReplaceGen.Instance); + Add(TextPadLeftGen.Instance); Add(typeof(SumFunc), SumBaseGen.Instance); Add(typeof(MeanFunc), SumBaseGen.Instance); diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index 7cd8827..ec01c6d 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -293,3 +293,26 @@ protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out Metho return true; } } + +public sealed class TextPadLeftGen : GetMethGen +{ + public static readonly TextPadLeftGen Instance = new TextPadLeftGen(); + + //private readonly MethodInfo _meth; + + private TextPadLeftGen() + { + //_meth = new Func(TextPadLeftFunc.Exec).Method; + } + + + protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) + { + Validation.AssertValue(codeGen); + Validation.Assert(IsValidCall(call, true)); + + var fn = GetOper(call); + meth = fn.Map.Method; + return true; + } +} From 5e09f083327e3feb9c58367d327648911be79cb9 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Wed, 26 Jun 2024 17:22:25 -0400 Subject: [PATCH 4/9] single arg version of padleft padright implemented with simple tests --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 3 +- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 56 +++++++++++++------ src/Core/Rexl.Bind/Strings/RexlStrings.cs | 6 +- src/Core/Rexl.Bind/Strings/RexlStrings.tt | 3 +- .../Rexl.Code/Operations/BuiltinGenerators.cs | 2 +- src/Core/Rexl.Code/Operations/Funcs/Text.cs | 15 ++--- .../Scripts/Binder/Functions/String.txt | 16 ++++++ .../Scripts/CodeGen/Functions/String.txt | 11 ++++ 8 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index d3b6621..a452b90 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,7 +378,8 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); - AddOne(TextPadLeftFunc.Instance, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPadLeft_Source))); + AddOne(TextPadFunc.Left, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source))); + AddOne(TextPadFunc.Right, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source))); AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index 7bb67d7..03d0af3 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -759,41 +759,65 @@ public static string Exec(string src, string remove, string insert) } } -public sealed partial class TextPadLeftFunc: RexlOper +public sealed partial class TextPadFunc : RexlOper { - public static readonly TextPadLeftFunc Instance = new TextPadLeftFunc(); + public static readonly TextPadFunc Left = new TextPadFunc(isLeft: true); + public static readonly TextPadFunc Right = new TextPadFunc(isLeft: false); - private TextPadLeftFunc() - : base(isFunc: true, new DName("PadLeft"), BindUtil.TextNs, 1, 2) + public readonly bool IsLeft; + + private TextPadFunc(bool isLeft) + : base(isFunc: true, new DName(isLeft ? "PadLeft" : "PadRight"), BindUtil.TextNs, 2, 2) { + IsLeft = isLeft; } - public Func Map { get; } - protected override ArgTraits GetArgTraitsCore(int carg) { Validation.Assert(SupportsArity(carg)); - return ArgTraitsSimple.Create(this, eager: true, carg); + var maskAll = BitSet.GetMask(carg); + var maskOpt = maskAll.ClearBit(0); + return ArgTraitsLifting.Create(this, carg, maskLiftSeq: maskAll, maskLiftTen: maskAll, maskLiftOpt: maskOpt); + } + + protected override (DType, Immutable.Array) SpecializeTypesCore(InvocationInfo info) + { + Validation.AssertValue(info); + Validation.Assert(SupportsArity(info.Arity)); + Validation.Assert(info.Arity == 2); + + return (DType.Text, Immutable.Array.Create(DType.Text, DType.I8Req)); } protected override bool CertifyCore(BndCallNode call, ref bool full) { if (call.Type != DType.Text) return false; - // var args = call.Args; - // if (args[0].Type != DType.I8Req) - // return false; - // if (args[1].Type != DType.Text) - // return false; + var args = call.Args; + if (args[0].Type != DType.Text) + return false; + if (args[1].Type != DType.I8Req) + return false; return true; } - public static string Exec(string src, int padding_len) + public static string ExecLeft(string src, long padTo) { - if (string.IsNullOrEmpty(src)) + if (padTo <= 0) return src; - if (padding_len == 0) + int count = (int)Math.Min(padTo, int.MaxValue); + if (string.IsNullOrEmpty(src)) + return new string(' ', count); + return src.PadLeft(count); + } + + public static string ExecRight(string src, long padTo) + { + if (padTo <= 0) return src; - return src.PadLeft(padding_len); + int count = (int)Math.Min(padTo, int.MaxValue); + if (string.IsNullOrEmpty(src)) + return new string(' ', count); + return src.PadRight(count); } } diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index 21a76d6..2ca7cda 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -342,14 +342,16 @@ static partial class RexlStrings public static readonly StringId AboutUpper = new(nameof(AboutUpper), "Converts text to uppercase."); public static readonly StringId AboutUpper_Source = new(nameof(AboutUpper_Source), "The text to convert to uppercase."); + public static readonly StringId AboutPadLeft = new(nameof(AboutPadLeft), "Adds characters to the left of a string."); + public static readonly StringId AboutPadRight = new(nameof(AboutPadRight), "Adds characters to the right of a string."); + public static readonly StringId AboutPad_Source = new(nameof(AboutPad_Source), "The text to add padding to."); + public static readonly StringId AboutStartsWith = new(nameof(AboutStartsWith), "Tests whether the beginning of the source text matches the lookup text."); public static readonly StringId AboutStartsWith_Source = new(nameof(AboutStartsWith_Source), "The text to look in."); public static readonly StringId AboutStartsWith_LookUp = new(nameof(AboutStartsWith_LookUp), "The text to look for."); public static readonly StringId AboutEndsWith = new(nameof(AboutEndsWith), "Tests whether the end of the source text matches the lookup text."); - public static readonly StringId AboutPadLeft = new(nameof(AboutPadLeft), "Returns a new string with the provided number of spaces/specified characters added to the left."); - public static readonly StringId AboutPadLeft_Source = new(nameof(AboutPadLeft), "The text to convert to lowercase."); public static readonly StringId AboutStrLen = new(nameof(AboutStrLen), "Returns the number of characters in the text value."); public static readonly StringId AboutStrLen_Source = new(nameof(AboutStrLen_Source), "The text in which to count the characters."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index eac956b..7a34145 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -337,7 +337,8 @@ AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." AboutPadLeft = "Adds characters to the left of a string." -AboutPadLeft_Source = "The text to add padding to." +AboutPadRight = "Adds characters to the right of a string." +AboutPad_Source = "The text to add padding to." AboutStartsWith = "Tests whether the beginning of the source text matches the lookup text." AboutStartsWith_Source = "The text to look in." diff --git a/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs b/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs index bbd7ee5..e3658f8 100644 --- a/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs +++ b/src/Core/Rexl.Code/Operations/BuiltinGenerators.cs @@ -59,7 +59,7 @@ private BuiltinGenerators() Add(TextPartGen.Instance); Add(TextTrimGen.Instance); Add(TextReplaceGen.Instance); - Add(TextPadLeftGen.Instance); + Add(TextPadGen.Instance); Add(typeof(SumFunc), SumBaseGen.Instance); Add(typeof(MeanFunc), SumBaseGen.Instance); diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index ec01c6d..65118cc 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -294,25 +294,26 @@ protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out Metho } } -public sealed class TextPadLeftGen : GetMethGen +public sealed class TextPadGen : GetMethGen { - public static readonly TextPadLeftGen Instance = new TextPadLeftGen(); + public static readonly TextPadGen Instance = new TextPadGen(); - //private readonly MethodInfo _meth; + private readonly MethodInfo _methLeft; + private readonly MethodInfo _methRight; - private TextPadLeftGen() + private TextPadGen() { - //_meth = new Func(TextPadLeftFunc.Exec).Method; + _methLeft = new Func(TextPadFunc.ExecLeft).Method; + _methRight = new Func(TextPadFunc.ExecRight).Method; } - protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) { Validation.AssertValue(codeGen); Validation.Assert(IsValidCall(call, true)); var fn = GetOper(call); - meth = fn.Map.Method; + meth = fn.IsLeft ? _methLeft : _methRight; return true; } } diff --git a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt index 6e89e64..9b38337 100644 --- a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt +++ b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt @@ -238,6 +238,14 @@ Text.Replace("ABC", "X", s) Text.Replace("ABC", "B", "X") Text.Replace("ABACDAE", "A", "!!") +Text.PadLeft(null, 0) +Text.PadLeft("hello", -1) +Text.PadLeft("hello", 10) + +Text.PadRight(null, 0) +Text.PadRight("hello", -1) +Text.PadRight(" hello", 10) + // Lifting. :: {g:g*, o:o*, s:s*, b:b*, qb:b?*, d:d*, n:n*, qn:n?*, r8:r8*, qr8:r8?*, r4:r4*, qr4:r4?*, i:i*, qi:i?*, i8:i8*, qi8:i8?*, i4:i4*, qi4:i4?*, i2:i2*, qi2:i2?*, i1:i1*, qi1:i1?*, u8:u8*, qu8:u8?*, u4:u4*, qu4:u4?*, u2:u2*, qu2:u2?*, u1:u1*, qu1:u1?*} @@ -360,3 +368,11 @@ Text.Replace("ABC", s, s) Text.Replace(s, s, s) Text.Replace(s, "", s) + +Text.PadLeft(null, 0) +Text.PadLeft("hello", -1) +Text.PadLeft("hello", 10) + +Text.PadRight(null, 0) +Text.PadRight("hello", -1) +Text.PadRight(" hello", 10) diff --git a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt index 3705ef1..d89e5b4 100644 --- a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt +++ b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt @@ -71,3 +71,14 @@ Text.TrimEnd(Wrap(Null(""))) | With(_, {S: it, L: Text.Len(it)}) Text.Replace(N, "A", "B") Text.Replace("A", N, "B") Text.Replace("ABC", Wrap("B"), N) + +Text.PadLeft(null, 0) +Text.PadLeft("hello", -1) +Text.PadLeft("hello", 10) +Text.PadLeft(Wrap("hello"), 10) + +Text.PadRight(null, 0) +Text.PadRight("hello", -1) +Text.PadRight(" hello", 5) +Text.PadRight(Wrap(" hello"), 10) + From 8a5d7d9062d34fc6105163ee18fb632c45c943f1 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Tue, 9 Jul 2024 13:35:15 -0400 Subject: [PATCH 5/9] addressing comments --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 4 +-- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 29 +++++++++++-------- src/Core/Rexl.Bind/Strings/RexlStrings.cs | 1 + src/Core/Rexl.Bind/Strings/RexlStrings.tt | 5 ++-- src/Core/Rexl.Code/Operations/Funcs/Text.cs | 4 +-- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index a452b90..3b93788 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,8 +378,8 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); - AddOne(TextPadFunc.Left, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source))); - AddOne(TextPadFunc.Right, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source))); + AddOne(TextPadFunc.Left, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.Right, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index 03d0af3..9607f33 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -759,17 +759,22 @@ public static string Exec(string src, string remove, string insert) } } +/// +/// Functions to add padding to either end of a string. +/// The left version (PadLeft) will add spaces to the left of the given string. +/// The right version (PadRight) will add spaces to the right of the given string. +/// public sealed partial class TextPadFunc : RexlOper { - public static readonly TextPadFunc Left = new TextPadFunc(isLeft: true); - public static readonly TextPadFunc Right = new TextPadFunc(isLeft: false); + public static readonly TextPadFunc Start = new TextPadFunc(atStart: true); + public static readonly TextPadFunc End = new TextPadFunc(atStart: false); - public readonly bool IsLeft; + public readonly bool AtStart; - private TextPadFunc(bool isLeft) - : base(isFunc: true, new DName(isLeft ? "PadLeft" : "PadRight"), BindUtil.TextNs, 2, 2) + private TextPadFunc(bool atStart) + : base(isFunc: true, new DName(atStart ? "PadStart" : "PadEnd"), BindUtil.TextNs, 2, 2) { - IsLeft = isLeft; + AtStart = atStart; } protected override ArgTraits GetArgTraitsCore(int carg) @@ -801,21 +806,21 @@ protected override bool CertifyCore(BndCallNode call, ref bool full) return true; } - public static string ExecLeft(string src, long padTo) + public static string ExecStart(string src, long len) { - if (padTo <= 0) + if (len <= 0) return src; - int count = (int)Math.Min(padTo, int.MaxValue); + int count = (int)Math.Min(len, int.MaxValue); if (string.IsNullOrEmpty(src)) return new string(' ', count); return src.PadLeft(count); } - public static string ExecRight(string src, long padTo) + public static string ExecEnd(string src, long len) { - if (padTo <= 0) + if (len <= 0) return src; - int count = (int)Math.Min(padTo, int.MaxValue); + int count = (int)Math.Min(len, int.MaxValue); if (string.IsNullOrEmpty(src)) return new string(' ', count); return src.PadRight(count); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index 2ca7cda..147bc68 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -345,6 +345,7 @@ static partial class RexlStrings public static readonly StringId AboutPadLeft = new(nameof(AboutPadLeft), "Adds characters to the left of a string."); public static readonly StringId AboutPadRight = new(nameof(AboutPadRight), "Adds characters to the right of a string."); public static readonly StringId AboutPad_Source = new(nameof(AboutPad_Source), "The text to add padding to."); + public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The number of spaces to add to the string."); public static readonly StringId AboutStartsWith = new(nameof(AboutStartsWith), "Tests whether the beginning of the source text matches the lookup text."); public static readonly StringId AboutStartsWith_Source = new(nameof(AboutStartsWith_Source), "The text to look in."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index 7a34145..21aea17 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -336,9 +336,10 @@ AboutLower_Source = "The text to convert to lowercase." AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." -AboutPadLeft = "Adds characters to the left of a string." -AboutPadRight = "Adds characters to the right of a string." +AboutPadLeft = "Adds the specified number of spaces to the left of a string." +AboutPadRight = "Adds the specified number of spaces to the right of a string." AboutPad_Source = "The text to add padding to." +AboutPad_Len = "The number of spaces to add to the string." AboutStartsWith = "Tests whether the beginning of the source text matches the lookup text." AboutStartsWith_Source = "The text to look in." diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index 65118cc..9781061 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -303,8 +303,8 @@ public sealed class TextPadGen : GetMethGen private TextPadGen() { - _methLeft = new Func(TextPadFunc.ExecLeft).Method; - _methRight = new Func(TextPadFunc.ExecRight).Method; + _methLeft = new Func(TextPadFunc.ExecStart).Method; + _methRight = new Func(TextPadFunc.ExecEnd).Method; } protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) From 94496598ea1bde73dec000833ef3b1c9b0faefa6 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Tue, 9 Jul 2024 13:37:10 -0400 Subject: [PATCH 6/9] addressing comments --- src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs | 4 ++-- src/Core/Rexl.Code/Operations/Funcs/Text.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index 3b93788..729913b 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,8 +378,8 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); - AddOne(TextPadFunc.Left, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); - AddOne(TextPadFunc.Right, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.Start, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.End, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index 9781061..2194bd1 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -298,13 +298,13 @@ public sealed class TextPadGen : GetMethGen { public static readonly TextPadGen Instance = new TextPadGen(); - private readonly MethodInfo _methLeft; - private readonly MethodInfo _methRight; + private readonly MethodInfo _methStart; + private readonly MethodInfo _methEnd; private TextPadGen() { - _methLeft = new Func(TextPadFunc.ExecStart).Method; - _methRight = new Func(TextPadFunc.ExecEnd).Method; + _methStart = new Func(TextPadFunc.ExecStart).Method; + _methEnd = new Func(TextPadFunc.ExecEnd).Method; } protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) @@ -313,7 +313,7 @@ protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out Metho Validation.Assert(IsValidCall(call, true)); var fn = GetOper(call); - meth = fn.IsLeft ? _methLeft : _methRight; + meth = fn.AtStart ? _methStart : _methEnd; return true; } } From 202a82d150b7593855d2cd3a159a8bb7b1e93faa Mon Sep 17 00:00:00 2001 From: gavin morris Date: Tue, 9 Jul 2024 16:33:02 -0400 Subject: [PATCH 7/9] addressing comments --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 5 +- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 64 +++++++++++++++++-- src/Core/Rexl.Bind/Strings/RexlStrings.cs | 7 +- src/Core/Rexl.Bind/Strings/RexlStrings.tt | 5 +- src/Core/Rexl.Code/Operations/Funcs/Text.cs | 10 +-- .../Scripts/Binder/Functions/String.txt | 46 +++++++++---- .../Scripts/CodeGen/Functions/String.txt | 20 +++--- 7 files changed, 119 insertions(+), 38 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index 729913b..fcd97cc 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,8 +378,9 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); - AddOne(TextPadFunc.Start, new Sig(S.AboutPadLeft, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); - AddOne(TextPadFunc.End, new Sig(S.AboutPadRight, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.PadCenter, new Sig(S.AboutPadCenter, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.PadStart, new Sig(S.AboutPadStart, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.PadEnd, new Sig(S.AboutPadEnd, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index 9607f33..c48e1d3 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -766,15 +766,41 @@ public static string Exec(string src, string remove, string insert) /// public sealed partial class TextPadFunc : RexlOper { - public static readonly TextPadFunc Start = new TextPadFunc(atStart: true); - public static readonly TextPadFunc End = new TextPadFunc(atStart: false); + public enum PadKind : byte + { + // Trim both leading and trailing whitespace. + Center, + // Trim only leading whitespace. + Start, + // Trim only trailing whitespace. + End + } + + public static readonly TextPadFunc PadCenter = new TextPadFunc(PadKind.Center, "PadCenter"); + public static readonly TextPadFunc PadStart = new TextPadFunc(PadKind.Start, "PadStart"); + public static readonly TextPadFunc PadEnd = new TextPadFunc(PadKind.End, "PadEnd"); + + public PadKind Kind { get; } - public readonly bool AtStart; + public Func Map { get; } - private TextPadFunc(bool atStart) - : base(isFunc: true, new DName(atStart ? "PadStart" : "PadEnd"), BindUtil.TextNs, 2, 2) + private TextPadFunc(PadKind kind, string name) + : base(isFunc: true, new DName(name), BindUtil.TextNs, 2, 2) { - AtStart = atStart; + switch(kind) { + case PadKind.Start: + Map = ExecStart; + break; + case PadKind.End: + Map = ExecEnd; + break; + case PadKind.Center: + default: + Map = ExecCenter; + break; + } + + Kind = kind; } protected override ArgTraits GetArgTraitsCore(int carg) @@ -806,6 +832,32 @@ protected override bool CertifyCore(BndCallNode call, ref bool full) return true; } + protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) + { + Validation.AssertValue(reducer); + Validation.Assert(IsValidCall(call)); + + var srcArg = call.Args[0]; + var lenArg = call.Args[1]; + if (srcArg.TryGetString(out var str) && lenArg.TryGetI8(out var len )) + { + if (string.IsNullOrEmpty(str) || len == 0) + return srcArg; + return BndStrNode.Create(Map(str, len)); + } + + return call; + } + + public static string ExecCenter(string src, long len) { + if (len <= 0) + return src; + int count = (int)Math.Min(len, int.MaxValue); + if (string.IsNullOrEmpty(src)) + return new string(' ', count); + return src.PadLeft(count).PadLeft(count); + } + public static string ExecStart(string src, long len) { if (len <= 0) diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index 147bc68..decfc83 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -3,6 +3,8 @@ // WARNING: This .cs file is generated from the corresponding .tt file. DO NOT edit this .cs directly. +using System; + namespace Microsoft.Rexl; static partial class RexlStrings @@ -342,8 +344,9 @@ static partial class RexlStrings public static readonly StringId AboutUpper = new(nameof(AboutUpper), "Converts text to uppercase."); public static readonly StringId AboutUpper_Source = new(nameof(AboutUpper_Source), "The text to convert to uppercase."); - public static readonly StringId AboutPadLeft = new(nameof(AboutPadLeft), "Adds characters to the left of a string."); - public static readonly StringId AboutPadRight = new(nameof(AboutPadRight), "Adds characters to the right of a string."); + public static readonly StringId AboutPadCenter = new(nameof(AboutPadCenter), "Adds the specified number of spaces to both ends of a string."); + public static readonly StringId AboutPadStart = new(nameof(AboutPadStart), "Adds the specified number of spaces to the start of a string."); + public static readonly StringId AboutPadEnd = new(nameof(AboutPadEnd), "Adds the specified number of spaces to the end of a string."); public static readonly StringId AboutPad_Source = new(nameof(AboutPad_Source), "The text to add padding to."); public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The number of spaces to add to the string."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index 21aea17..1d2457c 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -336,8 +336,9 @@ AboutLower_Source = "The text to convert to lowercase." AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." -AboutPadLeft = "Adds the specified number of spaces to the left of a string." -AboutPadRight = "Adds the specified number of spaces to the right of a string." +AboutPadCenter = "Adds the specified number of spaces to both ends of the string." +AboutPadStart = "Adds the specified number of spaces to the start of a string." +AboutPadEnd = "Adds the specified number of spaces to the end of a string." AboutPad_Source = "The text to add padding to." AboutPad_Len = "The number of spaces to add to the string." diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index 2194bd1..3905dd3 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -298,13 +298,13 @@ public sealed class TextPadGen : GetMethGen { public static readonly TextPadGen Instance = new TextPadGen(); - private readonly MethodInfo _methStart; - private readonly MethodInfo _methEnd; + // private readonly MethodInfo _methStart; + // private readonly MethodInfo _methEnd; private TextPadGen() { - _methStart = new Func(TextPadFunc.ExecStart).Method; - _methEnd = new Func(TextPadFunc.ExecEnd).Method; + // _methStart = new Func(TextPadFunc.ExecStart).Method; + // _methEnd = new Func(TextPadFunc.ExecEnd).Method; } protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) @@ -313,7 +313,7 @@ protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out Metho Validation.Assert(IsValidCall(call, true)); var fn = GetOper(call); - meth = fn.AtStart ? _methStart : _methEnd; + meth = fn.Map.Method; return true; } } diff --git a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt index 9b38337..b6a8153 100644 --- a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt +++ b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt @@ -238,13 +238,29 @@ Text.Replace("ABC", "X", s) Text.Replace("ABC", "B", "X") Text.Replace("ABACDAE", "A", "!!") -Text.PadLeft(null, 0) -Text.PadLeft("hello", -1) -Text.PadLeft("hello", 10) - -Text.PadRight(null, 0) -Text.PadRight("hello", -1) -Text.PadRight(" hello", 10) +Text.PadStart(null, 0) +Text.PadStart("hello", -1) +Text.PadStart("hello", 10) +Text.PadStart(s, s) +Text.PadStart(s, u2) +Text.PadStart(s, qi8) +Text.PadStart(s, qu2) + +Text.PadEnd(null, 0) +Text.PadEnd("hello", -1) +Text.PadEnd("hello", 10) +Text.PadEnd(s, s) +Text.PadEnd(s, u2) +Text.PadEnd(s, qi8) +Text.PadEnd(s, qu2) + +Text.PadCenter(null, 0) +Text.PadCenter("hello", -1) +Text.PadCenter("hello", 10) +Text.PadCenter(s, s) +Text.PadCenter(s, u2) +Text.PadCenter(s, qi8) +Text.PadCenter(s, qu2) // Lifting. :: {g:g*, o:o*, s:s*, b:b*, qb:b?*, d:d*, n:n*, qn:n?*, r8:r8*, qr8:r8?*, r4:r4*, qr4:r4?*, i:i*, qi:i?*, i8:i8*, qi8:i8?*, i4:i4*, qi4:i4?*, i2:i2*, qi2:i2?*, i1:i1*, qi1:i1?*, u8:u8*, qu8:u8?*, u4:u4*, qu4:u4?*, u2:u2*, qu2:u2?*, u1:u1*, qu1:u1?*} @@ -369,10 +385,14 @@ Text.Replace(s, s, s) Text.Replace(s, "", s) -Text.PadLeft(null, 0) -Text.PadLeft("hello", -1) -Text.PadLeft("hello", 10) +Text.PadStart(null, 0) +Text.PadStart("hello", -1) +Text.PadStart("hello", 10) + +Text.PadEnd(null, 0) +Text.PadEnd("hello", -1) +Text.PadEnd("hello", 10) -Text.PadRight(null, 0) -Text.PadRight("hello", -1) -Text.PadRight(" hello", 10) +Text.PadCenter(null, 0) +Text.PadCenter("hello", -1) +Text.PadCenter("hello", 10) diff --git a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt index d89e5b4..5fe9cfd 100644 --- a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt +++ b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt @@ -72,13 +72,17 @@ Text.Replace(N, "A", "B") Text.Replace("A", N, "B") Text.Replace("ABC", Wrap("B"), N) -Text.PadLeft(null, 0) -Text.PadLeft("hello", -1) -Text.PadLeft("hello", 10) -Text.PadLeft(Wrap("hello"), 10) +Text.PadStart(null, 0) +Text.PadStart("hello", -1) +Text.PadStart("hello", 10) +Text.PadStart(Wrap("hello"), 10) -Text.PadRight(null, 0) -Text.PadRight("hello", -1) -Text.PadRight(" hello", 5) -Text.PadRight(Wrap(" hello"), 10) +Text.PadEnd(null, 0) +Text.PadEnd("hello", -1) +Text.PadEnd("hello", 10) +Text.PadEnd(Wrap("hello"), 10) +Text.PadCenter(null, 0) +Text.PadCenter("hello", -1) +Text.PadCenter("hello", 10) +Text.PadCenter(Wrap("hello"), 10) From f806902cf5cdd3ccd69a9a2343e9881cdfc1bc80 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Wed, 24 Jul 2024 16:14:47 -0400 Subject: [PATCH 8/9] addressing comments, adding tests --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 6 +-- src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 41 +++++++++++++------ src/Core/Rexl.Bind/Strings/RexlStrings.cs | 11 +++-- src/Core/Rexl.Bind/Strings/RexlStrings.tt | 9 ++-- src/Core/Rexl.Code/Operations/Funcs/Text.cs | 5 --- .../Scripts/Binder/Functions/String.txt | 21 ++++++++++ 6 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index fcd97cc..cb7099c 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -378,9 +378,9 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimStart, new Sig(S.AboutTrimStart, A.Create(S.ArgSource, S.AboutTrimStart_Source))); AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); - AddOne(TextPadFunc.PadCenter, new Sig(S.AboutPadCenter, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); - AddOne(TextPadFunc.PadStart, new Sig(S.AboutPadStart, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); - AddOne(TextPadFunc.PadEnd, new Sig(S.AboutPadEnd, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgSource, S.AboutPad_Len))); + AddOne(TextPadFunc.PadCenter, new Sig(S.AboutPadCenter, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); + AddOne(TextPadFunc.PadStart, new Sig(S.AboutPadStart, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); + AddOne(TextPadFunc.PadEnd, new Sig(S.AboutPadEnd, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); AddOne(TextReplaceFunc.Instance, new Sig(S.AboutTextReplace, A.Create(S.ArgSource, S.AboutTextReplace_Source), diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index c48e1d3..a9d2dae 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -761,18 +761,19 @@ public static string Exec(string src, string remove, string insert) /// /// Functions to add padding to either end of a string. -/// The left version (PadLeft) will add spaces to the left of the given string. -/// The right version (PadRight) will add spaces to the right of the given string. +/// The center version (PadCenter) will add spaces to both ends of the given string. +/// The left version (PadStart) will add spaces to the left of the given string. +/// The right version (PadEnd) will add spaces to the right of the given string. /// public sealed partial class TextPadFunc : RexlOper { public enum PadKind : byte { - // Trim both leading and trailing whitespace. + // Center justification, pad both ends of the string Center, - // Trim only leading whitespace. + // Pad the start of the string. Start, - // Trim only trailing whitespace. + // Pad the end of the string. End } @@ -787,7 +788,8 @@ public enum PadKind : byte private TextPadFunc(PadKind kind, string name) : base(isFunc: true, new DName(name), BindUtil.TextNs, 2, 2) { - switch(kind) { + switch (kind) + { case PadKind.Start: Map = ExecStart; break; @@ -839,23 +841,38 @@ protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) var srcArg = call.Args[0]; var lenArg = call.Args[1]; - if (srcArg.TryGetString(out var str) && lenArg.TryGetI8(out var len )) + if (lenArg.TryGetI8(out var len)) { - if (string.IsNullOrEmpty(str) || len == 0) + if (len <= 0) return srcArg; - return BndStrNode.Create(Map(str, len)); + if (srcArg.TryGetString(out var str)) + { + if (Util.Size(str) >= len) + return srcArg; + return BndStrNode.Create(Map(str, len)); + } } return call; } - public static string ExecCenter(string src, long len) { - if (len <= 0) + public static string ExecCenter(string src, long len) + { + if (len <= 0 || len < src.Length) return src; int count = (int)Math.Min(len, int.MaxValue); if (string.IsNullOrEmpty(src)) return new string(' ', count); - return src.PadLeft(count).PadLeft(count); + return string.Create(count, src, (dst, src) => + { + int spaces = (count - src.Length) / 2; + for (int i = 0; i < count; i++) + { + if (i < spaces || i > src.Length + spaces - 1) + dst[i] = ' '; + else dst[i] = src[i - spaces]; + } + }); } public static string ExecStart(string src, long len) diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index decfc83..726ee40 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -3,8 +3,6 @@ // WARNING: This .cs file is generated from the corresponding .tt file. DO NOT edit this .cs directly. -using System; - namespace Microsoft.Rexl; static partial class RexlStrings @@ -31,6 +29,7 @@ static partial class RexlStrings public static readonly StringId ArgX = new(nameof(ArgX), "x"); public static readonly StringId ArgY = new(nameof(ArgY), "y"); public static readonly StringId ArgAngle = new(nameof(ArgAngle), "angle"); + public static readonly StringId ArgLength = new(nameof(ArgLength), "length"); public static readonly StringId AboutArgSeqSource = new(nameof(AboutArgSeqSource), "The source sequence."); public static readonly StringId AboutArgPredicate = new(nameof(AboutArgPredicate), "The condition with which to test an item."); @@ -344,11 +343,11 @@ static partial class RexlStrings public static readonly StringId AboutUpper = new(nameof(AboutUpper), "Converts text to uppercase."); public static readonly StringId AboutUpper_Source = new(nameof(AboutUpper_Source), "The text to convert to uppercase."); - public static readonly StringId AboutPadCenter = new(nameof(AboutPadCenter), "Adds the specified number of spaces to both ends of a string."); - public static readonly StringId AboutPadStart = new(nameof(AboutPadStart), "Adds the specified number of spaces to the start of a string."); - public static readonly StringId AboutPadEnd = new(nameof(AboutPadEnd), "Adds the specified number of spaces to the end of a string."); + public static readonly StringId AboutPadCenter = new(nameof(AboutPadCenter), "Adds spaces to both ends of the given string so the result is at least the given length."); + public static readonly StringId AboutPadStart = new(nameof(AboutPadStart), "Adds spaces to the start of the given string so the result is at least the given length."); + public static readonly StringId AboutPadEnd = new(nameof(AboutPadEnd), "Adds spaces to the end of the given string so the result is at least the given length."); public static readonly StringId AboutPad_Source = new(nameof(AboutPad_Source), "The text to add padding to."); - public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The number of spaces to add to the string."); + public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The minimum length of the string after adding the padding."); public static readonly StringId AboutStartsWith = new(nameof(AboutStartsWith), "Tests whether the beginning of the source text matches the lookup text."); public static readonly StringId AboutStartsWith_Source = new(nameof(AboutStartsWith_Source), "The text to look in."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index 1d2457c..3d53fe1 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -23,6 +23,7 @@ ArgValue = "value" ArgX = "x" ArgY = "y" ArgAngle = "angle" +ArgLength = "length" AboutArgSeqSource = "The source sequence." AboutArgPredicate = "The condition with which to test an item." @@ -336,11 +337,11 @@ AboutLower_Source = "The text to convert to lowercase." AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." -AboutPadCenter = "Adds the specified number of spaces to both ends of the string." -AboutPadStart = "Adds the specified number of spaces to the start of a string." -AboutPadEnd = "Adds the specified number of spaces to the end of a string." +AboutPadCenter = "Adds spaces to both ends of the given string so the result is at least the given length." +AboutPadStart = "Adds spaces to the start of the given string so the result is at least the given length." +AboutPadEnd = "Adds spaces to the end of the given string so the result is at least the given length." AboutPad_Source = "The text to add padding to." -AboutPad_Len = "The number of spaces to add to the string." +AboutPad_Len = "The minimum length of the string after adding the padding." AboutStartsWith = "Tests whether the beginning of the source text matches the lookup text." AboutStartsWith_Source = "The text to look in." diff --git a/src/Core/Rexl.Code/Operations/Funcs/Text.cs b/src/Core/Rexl.Code/Operations/Funcs/Text.cs index 3905dd3..514050b 100644 --- a/src/Core/Rexl.Code/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Code/Operations/Funcs/Text.cs @@ -298,13 +298,8 @@ public sealed class TextPadGen : GetMethGen { public static readonly TextPadGen Instance = new TextPadGen(); - // private readonly MethodInfo _methStart; - // private readonly MethodInfo _methEnd; - private TextPadGen() { - // _methStart = new Func(TextPadFunc.ExecStart).Method; - // _methEnd = new Func(TextPadFunc.ExecEnd).Method; } protected override bool TryGetMeth(ICodeGen codeGen, BndCallNode call, out MethodInfo meth) diff --git a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt index b6a8153..a8484d4 100644 --- a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt +++ b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt @@ -388,11 +388,32 @@ Text.Replace(s, "", s) Text.PadStart(null, 0) Text.PadStart("hello", -1) Text.PadStart("hello", 10) +Text.PadStart(s, s) +Text.PadStart(s, u1) +Text.PadStart(s, u2) +Text.PadStart(s, u4) +Text.PadStart(s, u8) +Text.PadStart(s, qi8) +Text.PadStart(s, qu2) Text.PadEnd(null, 0) Text.PadEnd("hello", -1) Text.PadEnd("hello", 10) +Text.PadEnd(s, s) +Text.PadEnd(s, u1) +Text.PadEnd(s, u2) +Text.PadEnd(s, u4) +Text.PadEnd(s, u8) +Text.PadEnd(s, qi8) +Text.PadEnd(s, qu2) Text.PadCenter(null, 0) Text.PadCenter("hello", -1) Text.PadCenter("hello", 10) +Text.PadCenter(s, s) +Text.PadCenter(s, u1) +Text.PadCenter(s, u2) +Text.PadCenter(s, u4) +Text.PadCenter(s, u8) +Text.PadCenter(s, qi8) +Text.PadCenter(s, qu2) From 7855fc146ae32aefab56de113bcdc898f1484396 Mon Sep 17 00:00:00 2001 From: gavin morris Date: Sun, 1 Sep 2024 10:28:09 -0400 Subject: [PATCH 9/9] updating tests and function optimizations --- .../Rexl.Bind/Operations/BuiltinFunctions.cs | 1 + src/Core/Rexl.Bind/Operations/Funcs/Text.cs | 29 +++++------ src/Core/Rexl.Bind/Strings/RexlStrings.cs | 8 +-- src/Core/Rexl.Bind/Strings/RexlStrings.tt | 8 +-- .../Scripts/Binder/Functions/String.txt | 50 +++++++++++++++---- .../Scripts/CodeGen/Functions/String.txt | 20 ++++---- 6 files changed, 74 insertions(+), 42 deletions(-) diff --git a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs index cb7099c..2fdd4d2 100644 --- a/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs +++ b/src/Core/Rexl.Bind/Operations/BuiltinFunctions.cs @@ -379,6 +379,7 @@ private BuiltinFunctions() AddOne(TextTrimFunc.TrimEnd, new Sig(S.AboutTrimEnd, A.Create(S.ArgSource, S.AboutTrimEnd_Source))); AddOne(TextPadFunc.PadCenter, new Sig(S.AboutPadCenter, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); + AddOne(TextPadFunc.PadCenter, "PadCenter"); AddOne(TextPadFunc.PadStart, new Sig(S.AboutPadStart, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); AddOne(TextPadFunc.PadEnd, new Sig(S.AboutPadEnd, A.Create(S.ArgSource, S.AboutPad_Source), A.Create(S.ArgLength, S.AboutPad_Len))); diff --git a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs index a9d2dae..52e5fd2 100644 --- a/src/Core/Rexl.Bind/Operations/Funcs/Text.cs +++ b/src/Core/Rexl.Bind/Operations/Funcs/Text.cs @@ -762,8 +762,8 @@ public static string Exec(string src, string remove, string insert) /// /// Functions to add padding to either end of a string. /// The center version (PadCenter) will add spaces to both ends of the given string. -/// The left version (PadStart) will add spaces to the left of the given string. -/// The right version (PadEnd) will add spaces to the right of the given string. +/// The start version (PadStart) will add spaces to the start of the given string. +/// The end version (PadEnd) will add spaces to the end of the given string. /// public sealed partial class TextPadFunc : RexlOper { @@ -777,7 +777,7 @@ public enum PadKind : byte End } - public static readonly TextPadFunc PadCenter = new TextPadFunc(PadKind.Center, "PadCenter"); + public static readonly TextPadFunc PadCenter = new TextPadFunc(PadKind.Center, "Pad"); public static readonly TextPadFunc PadStart = new TextPadFunc(PadKind.Start, "PadStart"); public static readonly TextPadFunc PadEnd = new TextPadFunc(PadKind.End, "PadEnd"); @@ -796,8 +796,8 @@ private TextPadFunc(PadKind kind, string name) case PadKind.End: Map = ExecEnd; break; - case PadKind.Center: default: + Validation.Assert(kind == PadKind.Center); Map = ExecCenter; break; } @@ -839,10 +839,10 @@ protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) Validation.AssertValue(reducer); Validation.Assert(IsValidCall(call)); - var srcArg = call.Args[0]; var lenArg = call.Args[1]; if (lenArg.TryGetI8(out var len)) { + var srcArg = call.Args[0]; if (len <= 0) return srcArg; if (srcArg.TryGetString(out var str)) @@ -858,20 +858,21 @@ protected override BoundNode ReduceCore(IReducer reducer, BndCallNode call) public static string ExecCenter(string src, long len) { - if (len <= 0 || len < src.Length) + if (len <= 0) return src; int count = (int)Math.Min(len, int.MaxValue); if (string.IsNullOrEmpty(src)) return new string(' ', count); - return string.Create(count, src, (dst, src) => + if (count <= src.Length) + return src; + return string.Create(count, src.AsMemory(), static (dst, mem) => { - int spaces = (count - src.Length) / 2; - for (int i = 0; i < count; i++) - { - if (i < spaces || i > src.Length + spaces - 1) - dst[i] = ' '; - else dst[i] = src[i - spaces]; - } + int spaces = (dst.Length - mem.Length) / 2; + + if (spaces > 0) + dst.Slice(0, spaces).Fill(' '); + mem.Span.CopyTo(dst.Slice(spaces, mem.Length)); + dst.Slice(spaces + mem.Length).Fill(' '); }); } diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.cs b/src/Core/Rexl.Bind/Strings/RexlStrings.cs index 726ee40..299536a 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.cs +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.cs @@ -343,11 +343,11 @@ static partial class RexlStrings public static readonly StringId AboutUpper = new(nameof(AboutUpper), "Converts text to uppercase."); public static readonly StringId AboutUpper_Source = new(nameof(AboutUpper_Source), "The text to convert to uppercase."); - public static readonly StringId AboutPadCenter = new(nameof(AboutPadCenter), "Adds spaces to both ends of the given string so the result is at least the given length."); - public static readonly StringId AboutPadStart = new(nameof(AboutPadStart), "Adds spaces to the start of the given string so the result is at least the given length."); - public static readonly StringId AboutPadEnd = new(nameof(AboutPadEnd), "Adds spaces to the end of the given string so the result is at least the given length."); + public static readonly StringId AboutPadCenter = new(nameof(AboutPadCenter), "Adds spaces to both ends of the given text so the result is of the given length."); + public static readonly StringId AboutPadStart = new(nameof(AboutPadStart), "Adds spaces to the start of the given text so the result is of the given length."); + public static readonly StringId AboutPadEnd = new(nameof(AboutPadEnd), "Adds spaces to the end of the given text so the result is of the given length."); public static readonly StringId AboutPad_Source = new(nameof(AboutPad_Source), "The text to add padding to."); - public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The minimum length of the string after adding the padding."); + public static readonly StringId AboutPad_Len = new(nameof(AboutPad_Len), "The minimum length of the text after padding."); public static readonly StringId AboutStartsWith = new(nameof(AboutStartsWith), "Tests whether the beginning of the source text matches the lookup text."); public static readonly StringId AboutStartsWith_Source = new(nameof(AboutStartsWith_Source), "The text to look in."); diff --git a/src/Core/Rexl.Bind/Strings/RexlStrings.tt b/src/Core/Rexl.Bind/Strings/RexlStrings.tt index 3d53fe1..488b9da 100644 --- a/src/Core/Rexl.Bind/Strings/RexlStrings.tt +++ b/src/Core/Rexl.Bind/Strings/RexlStrings.tt @@ -337,11 +337,11 @@ AboutLower_Source = "The text to convert to lowercase." AboutUpper = "Converts text to uppercase." AboutUpper_Source = "The text to convert to uppercase." -AboutPadCenter = "Adds spaces to both ends of the given string so the result is at least the given length." -AboutPadStart = "Adds spaces to the start of the given string so the result is at least the given length." -AboutPadEnd = "Adds spaces to the end of the given string so the result is at least the given length." +AboutPadCenter = "Adds spaces to both ends of the given text so the result is of the given length." +AboutPadStart = "Adds spaces to the start of the given text so the result is of the given length." +AboutPadEnd = "Adds spaces to the end of the given text so the result is of the given length." AboutPad_Source = "The text to add padding to." -AboutPad_Len = "The minimum length of the string after adding the padding." +AboutPad_Len = "The minimum length of the text after padding." AboutStartsWith = "Tests whether the beginning of the source text matches the lookup text." AboutStartsWith_Source = "The text to look in." diff --git a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt index a8484d4..8b69a23 100644 --- a/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt +++ b/src/Test/Rexl.Bind.Test/Scripts/Binder/Functions/String.txt @@ -238,29 +238,42 @@ Text.Replace("ABC", "X", s) Text.Replace("ABC", "B", "X") Text.Replace("ABACDAE", "A", "!!") +Text.PadStart(s, i8) Text.PadStart(null, 0) Text.PadStart("hello", -1) +Text.PadStart(s, -1) Text.PadStart("hello", 10) +Text.PadStart(s, 10) Text.PadStart(s, s) Text.PadStart(s, u2) Text.PadStart(s, qi8) Text.PadStart(s, qu2) +Text.PadStart(i8, i8) +Text.PadEnd(s, i8) Text.PadEnd(null, 0) Text.PadEnd("hello", -1) +Text.PadEnd(s, -1) Text.PadEnd("hello", 10) +Text.PadEnd(s, 10) Text.PadEnd(s, s) Text.PadEnd(s, u2) Text.PadEnd(s, qi8) Text.PadEnd(s, qu2) - -Text.PadCenter(null, 0) -Text.PadCenter("hello", -1) -Text.PadCenter("hello", 10) -Text.PadCenter(s, s) -Text.PadCenter(s, u2) -Text.PadCenter(s, qi8) -Text.PadCenter(s, qu2) +Text.PadEnd(i8, i8) + +Tex.Pad(s, i8) +Text.PadCenter(s, i8) +Text.Pad(null, 15) +Text.Pad("hello", -1) +Text.Pad(s, -1) +Text.Pad("hello", 10) +Text.Pad(s, 10) +Text.Pad(s, s) +Text.Pad(s, u2) +Text.Pad(s, qi8) +Text.Pad(s, qu2) +Text.Pad(i8, i8) // Lifting. :: {g:g*, o:o*, s:s*, b:b*, qb:b?*, d:d*, n:n*, qn:n?*, r8:r8*, qr8:r8?*, r4:r4*, qr4:r4?*, i:i*, qi:i?*, i8:i8*, qi8:i8?*, i4:i4*, qi4:i4?*, i2:i2*, qi2:i2?*, i1:i1*, qi1:i1?*, u8:u8*, qu8:u8?*, u4:u4*, qu4:u4?*, u2:u2*, qu2:u2?*, u1:u1*, qu1:u1?*} @@ -385,9 +398,15 @@ Text.Replace(s, s, s) Text.Replace(s, "", s) +Text.PadStart(s, i8) Text.PadStart(null, 0) Text.PadStart("hello", -1) +Text.PadStart("hello", [3, 4, 1]) +Text.PadStart(s, [3, 4, 1]) +Text.PadStart(s, -1) Text.PadStart("hello", 10) +Text.PadStart(["hello", "howdy", null], 10) +Text.PadStart(s, 10) Text.PadStart(s, s) Text.PadStart(s, u1) Text.PadStart(s, u2) @@ -396,9 +415,13 @@ Text.PadStart(s, u8) Text.PadStart(s, qi8) Text.PadStart(s, qu2) +Text.PadEnd(s, i8) Text.PadEnd(null, 0) -Text.PadEnd("hello", -1) -Text.PadEnd("hello", 10) +Text.PadEnd(s, -1) +Text.PadEnd(s, [3, 4, 1]) +Text.PadEnd("hello", [3, 4, 9]) +Text.PadEnd(["hello", "howdy", null], 10) +Text.PadEnd(s, 10) Text.PadEnd(s, s) Text.PadEnd(s, u1) Text.PadEnd(s, u2) @@ -407,9 +430,14 @@ Text.PadEnd(s, u8) Text.PadEnd(s, qi8) Text.PadEnd(s, qu2) +Text.PadCenter(s, i8) Text.PadCenter(null, 0) Text.PadCenter("hello", -1) -Text.PadCenter("hello", 10) +Text.PadCenter("hello", [3, 4, 9]) +Text.PadCenter(s, -1) +Text.PadCenter(s, [3, 4, 1]) +Text.PadCenter(["hello", "howdy", null], 10) +Text.PadCenter(s, 10) Text.PadCenter(s, s) Text.PadCenter(s, u1) Text.PadCenter(s, u2) diff --git a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt index 5fe9cfd..d12f089 100644 --- a/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt +++ b/src/Test/Rexl.Code.Test/Scripts/CodeGen/Functions/String.txt @@ -1,6 +1,6 @@ ::: {g:g, o:o, s:s, b:b, qb:b?, d:d, qd:d?, n:n, qn:n?, r8:r8, qr8:r8?, r4:r4, qr4:r4?, i:i, qi:i?, i8:i8, qi8:i8?, i4:i4, qi4:i4?, i2:i2, qi2:i2?, i1:i1, qi1:i1?, u8:u8, qu8:u8?, u4:u4, qu4:u4?, u2:u2, qu2:u2?, u1:u1, qu1:u1?} -``` N := First([null, "hello"]); +``` N := Null("hello"); Text.Part(Wrap(""), 0) Text.Part(Wrap(""), 1) @@ -72,17 +72,19 @@ Text.Replace(N, "A", "B") Text.Replace("A", N, "B") Text.Replace("ABC", Wrap("B"), N) -Text.PadStart(null, 0) -Text.PadStart("hello", -1) -Text.PadStart("hello", 10) -Text.PadStart(Wrap("hello"), 10) +Text.PadStart(N, 0) +Text.PadStart(N, Wrap(10)) +Text.PadStart("hello", Wrap(-1)) +Text.PadStart("hello", Wrap(10)) -Text.PadEnd(null, 0) +Text.PadEnd(N, 0) +Text.PadEnd(N, Wrap(10)) Text.PadEnd("hello", -1) Text.PadEnd("hello", 10) Text.PadEnd(Wrap("hello"), 10) -Text.PadCenter(null, 0) +Text.Pad(N, 0) +Text.Pad(N, Wrap(10)) Text.PadCenter("hello", -1) -Text.PadCenter("hello", 10) -Text.PadCenter(Wrap("hello"), 10) +Text.Pad("hello", 10) +Text.Pad(Wrap("hello"), 10)