From e47b8acc2eb04650e52dff0e26d6bb04065c36ba Mon Sep 17 00:00:00 2001 From: Andrey Zherikov Date: Mon, 16 Dec 2024 12:04:44 -0500 Subject: [PATCH] Refactor --- source/argparse/api/argument.d | 4 +- source/argparse/internal/argumentuda.d | 9 +- source/argparse/internal/argumentudahelpers.d | 15 ++-- source/argparse/internal/command.d | 5 +- source/argparse/internal/errorhelpers.d | 2 +- source/argparse/internal/parsefunc.d | 2 +- source/argparse/internal/valueparser.d | 84 +++++++------------ 7 files changed, 54 insertions(+), 67 deletions(-) diff --git a/source/argparse/api/argument.d b/source/argparse/api/argument.d index b004e61..e6507b8 100644 --- a/source/argparse/api/argument.d +++ b/source/argparse/api/argument.d @@ -340,11 +340,11 @@ unittest private struct CounterParsingFunction { - static Result parseParameter(T)(T* receiver, RawParam param) + static Result parseParameter(T)(ref T receiver, RawParam param) { assert(param.value.length == 0); - ++(*receiver); + ++receiver; return Result.Success; } diff --git a/source/argparse/internal/argumentuda.d b/source/argparse/internal/argumentuda.d index c2caad8..2b370a4 100644 --- a/source/argparse/internal/argumentuda.d +++ b/source/argparse/internal/argumentuda.d @@ -20,6 +20,7 @@ package(argparse) struct ArgumentUDA(ValueParser) package Result parse(COMMAND_STACK, RECEIVER)(const COMMAND_STACK cmdStack, ref RECEIVER receiver, RawParam param) { + static assert(!is(RECEIVER == T*, T)); try { auto res = info.checkValuesCount(param); @@ -51,11 +52,13 @@ package(argparse) struct ArgumentUDA(ValueParser) return createArgumentUDA(newInfo, newValueParser); } - auto addDefaultsForType(T)() + auto addReceiverTypeDefaults(T)() { - static if(is(typeof(valueParser.addTypeDefaults!T))) + static assert(!is(T == P*, P)); + + static if(__traits(hasMember, valueParser, "typeDefaults")) { - auto newValueParser = valueParser.addTypeDefaults!T; + auto newValueParser = valueParser.addDefaults(valueParser.typeDefaults!T); return createArgumentUDA(info, newValueParser); } diff --git a/source/argparse/internal/argumentudahelpers.d b/source/argparse/internal/argumentudahelpers.d index 90e0286..f416992 100644 --- a/source/argparse/internal/argumentudahelpers.d +++ b/source/argparse/internal/argumentudahelpers.d @@ -32,7 +32,7 @@ private template defaultValuesCount(T) enum min = 1; enum max = size_t.max; } - else static if(is(T == function)) + else static if(is(T == function) || is(T == delegate)) { // ... function() static if(__traits(compiles, T())) @@ -47,7 +47,7 @@ private template defaultValuesCount(T) enum max = 1; } // ... function(string[] value) - else static if(__traits(compiles, T([string.init]))) + else static if(__traits(compiles, T(string[].init))) { enum min = 1; enum max = size_t.max; @@ -71,7 +71,11 @@ package auto getMemberArgumentUDA(TYPE, string symbol)(const Config config) import std.meta: AliasSeq, Filter; alias member = __traits(getMember, TYPE, symbol); - alias MemberType = typeof(member); + + static if(is(typeof(member) == function) || is(typeof(member) == delegate)) + alias MemberType = typeof(&__traits(getMember, TYPE.init, symbol)); + else + alias MemberType = typeof(member); alias udas = Filter!(isArgumentUDA, __traits(getAttributes, member)); static if(__traits(compiles, __traits(getAttributes, MemberType))) @@ -92,10 +96,7 @@ package auto getMemberArgumentUDA(TYPE, string symbol)(const Config config) else enum initUDA = memberUDA; - static if(is(MemberType == function) || is(MemberType == delegate)) - auto result = initUDA.addDefaultsForType!(typeof(&__traits(getMember, TYPE.init, symbol))); - else - auto result = initUDA.addDefaultsForType!MemberType; + auto result = initUDA.addReceiverTypeDefaults!MemberType; result.info = result.info.finalize!MemberType(config, symbol); diff --git a/source/argparse/internal/command.d b/source/argparse/internal/command.d index 6700689..72dffb5 100644 --- a/source/argparse/internal/command.d +++ b/source/argparse/internal/command.d @@ -50,7 +50,10 @@ private Result ArgumentParsingFunction(alias uda, RECEIVER)(const Command[] cmdS else auto target = null; - return uda.parse(cmdStack, target, param); + static if(is(typeof(target) == typeof(null)) || is(typeof(target) == function) || is(typeof(target) == delegate)) + return uda.parse(cmdStack, target, param); + else + return uda.parse(cmdStack, *target, param); } private alias getArgumentParsingFunction1(alias uda) = diff --git a/source/argparse/internal/errorhelpers.d b/source/argparse/internal/errorhelpers.d index 4dd926d..ea4ebda 100644 --- a/source/argparse/internal/errorhelpers.d +++ b/source/argparse/internal/errorhelpers.d @@ -13,7 +13,7 @@ package Result processingError(T)(Param!T param, string prefix = "Can't process auto a = appender!string(prefix); - static if(is(typeof(param.value))) + static if(__traits(hasMember, param, "value")) { a ~= " '"; a ~= param.config.styling.positionalArgumentValue(param.value.to!string); diff --git a/source/argparse/internal/parsefunc.d b/source/argparse/internal/parsefunc.d index 406cfc2..b9c271b 100644 --- a/source/argparse/internal/parsefunc.d +++ b/source/argparse/internal/parsefunc.d @@ -169,7 +169,7 @@ unittest // has to do this way otherwise DMD compiler chokes - linker reports unresolved symbol for lambda: // Error: undefined reference to `pure nothrow @nogc @safe immutable(char)[][] argparse.internal.parsefunc.__lambda12(immutable(char)[][])` -// referenced from `pure nothrow @nogc @safe argparse.internal.valueparser.ValueParser!(immutable(char)[][], void delegate()).ValueParser argparse.internal.valueparser.ValueParser!(void, void).ValueParser.addTypeDefaults!(void delegate()).addTypeDefaults()` +// referenced from `pure nothrow @nogc @safe argparse.internal.valueparser.ValueParser!(immutable(char)[][], void delegate()).ValueParser argparse.internal.valueparser.ValueParser!(void, void).ValueParser.addReceiverTypeDefaults!(void delegate()).addReceiverTypeDefaults()` private enum PassThroughImpl(TYPE) = ParseFunc!TYPE ((TYPE value) { diff --git a/source/argparse/internal/valueparser.d b/source/argparse/internal/valueparser.d index 3893084..4e5b882 100644 --- a/source/argparse/internal/valueparser.d +++ b/source/argparse/internal/valueparser.d @@ -135,56 +135,37 @@ package(argparse) struct ValueParser(PARSE_TYPE, RECEIVER_TYPE) return res; } - auto addTypeDefaults(TYPE)() - { - static if(!is(typeof(TypedValueParser!TYPE) == void)) - return addDefaults(TypedValueParser!TYPE); - else - return this; - } - - // Procedure to process (parse) the values to an argument of type RECEIVER - // - if there is a value(s): - // - pre validate raw strings - // - parse raw strings - // - validate parsed values - // - action with values - // - if there is no value: - // - action if no value - // Requirement: rawValues.length must be correct - Result parseParameter(RECEIVER)(ref RECEIVER receiver, RawParam param) - { - static assert(!is(PARSE_TYPE == void) && !is(RECEIVER_TYPE == void)); - return addTypeDefaults!RECEIVER.addDefaults.parseImpl(receiver, param); - } + enum typeDefaults(TYPE) = TypedValueParser!TYPE; static if(!is(PARSE_TYPE == void) && !is(RECEIVER_TYPE == void)) { - auto addDefaults() + static auto defaults() { - if(!preProcess) - preProcess = (ref _) {}; - if(!preValidate) - preValidate = (string[] _) => true; - if(!validate) - validate = (PARSE_TYPE _) => true; - static if(__traits(compiles, { RECEIVER_TYPE receiver; receiver = PARSE_TYPE.init; })) - { - if (!action) - action = (ref RECEIVER_TYPE receiver, Param!PARSE_TYPE param) { receiver = param.value; }; - } - if(!noValueAction) - noValueAction = (ref RECEIVER_TYPE _, param) => processingError(param); + ValueParser!(PARSE_TYPE, RECEIVER_TYPE) res; - return this; - } + res.preProcess = (ref _) {}; + res.preValidate = (string[] _) => true; + res.validate = (PARSE_TYPE _) => true; + static if(is(RECEIVER_TYPE == PARSE_TYPE)) + res.action = (ref RECEIVER_TYPE receiver, Param!PARSE_TYPE param) { receiver = param.value; }; - Result parseImpl(RECEIVER_TYPE* receiver, ref RawParam rawParam) const - { - return parseImpl(*receiver, rawParam); + if(!res.noValueAction) + res.noValueAction = (ref RECEIVER_TYPE _, param) => processingError(param); + + return res; } - Result parseImpl(ref RECEIVER_TYPE receiver, ref RawParam rawParam) const + + // Procedure to process (parse) the values to an argument of type RECEIVER + // - if there is a value(s): + // - pre validate raw strings + // - parse raw strings + // - validate parsed values + // - action with values + // - if there is no value: + // - action if no value + // Requirement: rawValues.length must be correct + Result parseParameter(ref RECEIVER_TYPE receiver, RawParam rawParam) const { assert(preProcess); assert(preValidate); @@ -243,18 +224,18 @@ if(!is(T == void)) static if(is(T == enum)) { - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changePreValidation(ValidationFunc!(string[])((RawParam _) => ValueInList(getEnumValues!T)(_))) .changeParse(ParseFunc!T((string _) => getEnumValue!T(_))); } else static if(isSomeString!T || isNumeric!T) { - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changeParse(Convert!T); } else static if(isBoolean!T) { - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changePreProcess((ref RawParam param) { import std.algorithm.iteration: map; @@ -279,10 +260,9 @@ if(!is(T == void)) } else static if(isSomeChar!T) { - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changeParse(ParseFunc!T((string value) { - import std.conv: to; return value.length > 0 ? value[0].to!T : T.init; })); } @@ -316,14 +296,14 @@ if(!is(T == void)) else enum action = Assign!T; - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changeParse(parseValue!T) .changeAction(action) .changeNoValueAction(NoValueActionFunc!T((ref T receiver) => Result.Success)); } else static if(!isArray!(ForeachType!TElement) || isSomeString!(ForeachType!TElement)) // 2D array { - enum TypedValueParser = ValueParser!(TElement, T).init + enum TypedValueParser = ValueParser!(TElement, T).defaults .changeParse(parseValue!TElement) .changeAction(Extend!T) .changeNoValueAction(NoValueActionFunc!T((ref T receiver) { receiver ~= TElement.init; })); @@ -334,7 +314,7 @@ if(!is(T == void)) else static if(isAssociativeArray!T) { import std.string : indexOf; - enum TypedValueParser = ValueParser!(string[], T).init + enum TypedValueParser = ValueParser!(string[], T).defaults .changeParse(PassThrough) .changeAction(ActionFunc!(T,string[])((ref T receiver, RawParam param) { @@ -365,14 +345,14 @@ if(!is(T == void)) } else static if(is(T == function) || is(T == delegate) || is(typeof(*T) == function) || is(typeof(*T) == delegate)) { - enum TypedValueParser = ValueParser!(string[], T).init + enum TypedValueParser = ValueParser!(string[], T).defaults .changeParse(PassThrough) .changeAction(CallFunction!T) .changeNoValueAction(CallFunctionNoParam!T); } else { - enum TypedValueParser = ValueParser!(T, T).init + enum TypedValueParser = ValueParser!(T, T).defaults .changeAction(Assign!T); } }