Commit c4260dbc authored by Boxiang Sun's avatar Boxiang Sun

add keyword parameter to min and max, extract common part to min_max

parent bef560b0
...@@ -145,30 +145,77 @@ extern "C" Box* any(Box* container) { ...@@ -145,30 +145,77 @@ extern "C" Box* any(Box* container) {
return boxBool(false); return boxBool(false);
} }
extern "C" Box* min(Box* arg0, BoxedTuple* args) { Box* min_max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs, int opid) {
assert(args->cls == tuple_cls); assert(args->cls == tuple_cls);
if (kwargs)
assert(kwargs->cls == dict_cls);
Box* minElement; Box* key_func = nullptr;
Box* extremElement;
Box* container; Box* container;
Box* extremVal;
if (kwargs && kwargs->d.size()) {
static BoxedString* key_str = static_cast<BoxedString*>(PyString_InternFromString("key"));
auto it = kwargs->d.find(key_str);
if (it != kwargs->d.end() && kwargs->d.size() == 1) {
key_func = it->second;
} else {
if (opid == Py_LT)
raiseExcHelper(TypeError, "min() got an unexpected keyword argument");
else
raiseExcHelper(TypeError, "max() got an unexpected keyword argument");
}
}
if (args->size() == 0) { if (args->size() == 0) {
minElement = nullptr; extremElement = nullptr;
extremVal = nullptr;
container = arg0; container = arg0;
} else { } else {
minElement = arg0; extremElement = arg0;
if (key_func != NULL) {
extremVal = runtimeCall(key_func, ArgPassSpec(1), extremElement, NULL, NULL, NULL, NULL);
} else {
extremVal = extremElement;
}
container = args; container = args;
} }
Box* curVal = nullptr;
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
if (!minElement) { if (key_func != NULL) {
minElement = e; if (!extremElement) {
extremVal = runtimeCall(key_func, ArgPassSpec(1), e, NULL, NULL, NULL, NULL);
extremElement = e;
continue;
}
curVal = runtimeCall(key_func, ArgPassSpec(1), e, NULL, NULL, NULL, NULL);
} else { } else {
int r = PyObject_RichCompareBool(minElement, e, Py_GT); if (!extremElement) {
if (r == -1) extremVal = e;
throwCAPIException(); extremElement = e;
if (r) continue;
minElement = e; }
curVal = e;
}
int r = PyObject_RichCompareBool(curVal, extremVal, opid);
if (r == -1)
throwCAPIException();
if (r) {
extremElement = e;
extremVal = curVal;
} }
} }
return extremElement;
}
extern "C" Box* min(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
if (arg0 == None && args->size() == 0) {
raiseExcHelper(TypeError, "min expected 1 arguments, got 0");
}
Box* minElement = min_max(arg0, args, kwargs, Py_LT);
if (!minElement) { if (!minElement) {
raiseExcHelper(ValueError, "min() arg is an empty sequence"); raiseExcHelper(ValueError, "min() arg is an empty sequence");
...@@ -176,30 +223,12 @@ extern "C" Box* min(Box* arg0, BoxedTuple* args) { ...@@ -176,30 +223,12 @@ extern "C" Box* min(Box* arg0, BoxedTuple* args) {
return minElement; return minElement;
} }
extern "C" Box* max(Box* arg0, BoxedTuple* args) { extern "C" Box* max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
assert(args->cls == tuple_cls); if (arg0 == None && args->size() == 0) {
raiseExcHelper(TypeError, "max expected 1 arguments, got 0");
Box* maxElement;
Box* container;
if (args->size() == 0) {
maxElement = nullptr;
container = arg0;
} else {
maxElement = arg0;
container = args;
} }
for (Box* e : container->pyElements()) { Box* maxElement = min_max(arg0, args, kwargs, Py_GT);
if (!maxElement) {
maxElement = e;
} else {
int r = PyObject_RichCompareBool(maxElement, e, Py_LT);
if (r == -1)
throwCAPIException();
if (r)
maxElement = e;
}
}
if (!maxElement) { if (!maxElement) {
raiseExcHelper(ValueError, "max() arg is an empty sequence"); raiseExcHelper(ValueError, "max() arg is an empty sequence");
...@@ -1170,10 +1199,10 @@ void setupBuiltins() { ...@@ -1170,10 +1199,10 @@ void setupBuiltins() {
builtins_module->giveAttr("oct", builtins_module->giveAttr("oct",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)octFunc, UNKNOWN, 1), "oct")); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)octFunc, UNKNOWN, 1), "oct"));
min_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)min, UNKNOWN, 1, 0, true, false), "min"); min_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)min, UNKNOWN, 1, 1, true, true), "min", { None });
builtins_module->giveAttr("min", min_obj); builtins_module->giveAttr("min", min_obj);
max_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)max, UNKNOWN, 1, 0, true, false), "max"); max_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)max, UNKNOWN, 1, 1, true, true), "max", { None });
builtins_module->giveAttr("max", max_obj); builtins_module->giveAttr("max", max_obj);
builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod( builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment