Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
andrey-zherikov committed Dec 16, 2024
1 parent b808760 commit e47b8ac
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 67 deletions.
4 changes: 2 additions & 2 deletions source/argparse/api/argument.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
9 changes: 6 additions & 3 deletions source/argparse/internal/argumentuda.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
15 changes: 8 additions & 7 deletions source/argparse/internal/argumentudahelpers.d
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand All @@ -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;
Expand All @@ -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)))
Expand All @@ -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);

Expand Down
5 changes: 4 additions & 1 deletion source/argparse/internal/command.d
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down
2 changes: 1 addition & 1 deletion source/argparse/internal/errorhelpers.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion source/argparse/internal/parsefunc.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
84 changes: 32 additions & 52 deletions source/argparse/internal/valueparser.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}));
}
Expand Down Expand Up @@ -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; }));
Expand All @@ -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)
{
Expand Down Expand Up @@ -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);
}
}
Expand Down

0 comments on commit e47b8ac

Please sign in to comment.