Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #186

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading