Commit fd8cc825 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Misc things to get chaos.py working

reduce(), some float precision issues, string interpolation improvements
parent 3263a159
...@@ -1424,14 +1424,16 @@ public: ...@@ -1424,14 +1424,16 @@ public:
// Ugly, but for now special-case the set of type-pairs that we know will always work // Ugly, but for now special-case the set of type-pairs that we know will always work
if (exp_type == BinOp if (exp_type == BinOp
&& ((cls == int_cls && rhs_cls == int_cls) || (cls == float_cls && rhs_cls == float_cls) && ((cls == int_cls && rhs_cls == int_cls) || (cls == float_cls && rhs_cls == float_cls)
|| (cls == list_cls && rhs_cls == int_cls))) { || (cls == list_cls && rhs_cls == int_cls) || (cls == str_cls))) {
const std::string& left_side_name = getOpName(op_type); const std::string& left_side_name = getOpName(op_type);
ConcreteCompilerVariable* called_constant = tryCallattrConstant( ConcreteCompilerVariable* called_constant = tryCallattrConstant(
emitter, info, var, &left_side_name, true, ArgPassSpec(1, 0, 0, 0), { converted_rhs }, NULL, false); emitter, info, var, &left_side_name, true, ArgPassSpec(1, 0, 0, 0), { converted_rhs }, NULL, false);
if (called_constant) if (called_constant) {
converted_rhs->decvref(emitter);
return called_constant; return called_constant;
}
} }
} }
...@@ -1588,7 +1590,7 @@ public: ...@@ -1588,7 +1590,7 @@ public:
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs, CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override { AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN); ConcreteCompilerVariable* converted = var->makeConverted(emitter, STR);
CompilerVariable* rtn = converted->binexp(emitter, info, rhs, op_type, exp_type); CompilerVariable* rtn = converted->binexp(emitter, info, rhs, op_type, exp_type);
converted->decvref(emitter); converted->decvref(emitter);
return rtn; return rtn;
......
...@@ -378,6 +378,25 @@ Box* map2(Box* f, Box* container) { ...@@ -378,6 +378,25 @@ Box* map2(Box* f, Box* container) {
return rtn; return rtn;
} }
Box* reduce(Box* f, Box* container, Box* initial) {
Box* current = initial;
for (Box* e : container->pyElements()) {
assert(e);
if (current == NULL) {
current = e;
} else {
current = runtimeCall(f, ArgPassSpec(2), current, e, NULL, NULL, NULL);
}
}
if (current == NULL) {
raiseExcHelper(TypeError, "reduce() of empty sequence with no initial value");
}
return current;
}
Box* filter2(Box* f, Box* container) { Box* filter2(Box* f, Box* container) {
// If the filter-function argument is None, filter() works by only returning // If the filter-function argument is None, filter() works by only returning
// the elements that are truthy. This is equivalent to using the bool() constructor. // the elements that are truthy. This is equivalent to using the bool() constructor.
...@@ -720,6 +739,8 @@ void setupBuiltins() { ...@@ -720,6 +739,8 @@ void setupBuiltins() {
builtins_module->giveAttr("execfile", new BoxedFunction(boxRTFunction((void*)execfile, UNKNOWN, 1))); builtins_module->giveAttr("execfile", new BoxedFunction(boxRTFunction((void*)execfile, UNKNOWN, 1)));
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2))); builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2)));
builtins_module->giveAttr("reduce",
new BoxedFunction(boxRTFunction((void*)reduce, UNKNOWN, 3, 1, false, false), { NULL }));
builtins_module->giveAttr("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2))); builtins_module->giveAttr("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2))); builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
builtins_module->giveAttr("dir", new BoxedFunction(boxRTFunction((void*)dir, LIST, 1, 1, false, false), { NULL })); builtins_module->giveAttr("dir", new BoxedFunction(boxRTFunction((void*)dir, LIST, 1, 1, false, false), { NULL }));
......
...@@ -654,12 +654,20 @@ extern "C" int PyNumber_Check(PyObject*) { ...@@ -654,12 +654,20 @@ extern "C" int PyNumber_Check(PyObject*) {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" PyObject* PyNumber_Add(PyObject*, PyObject*) { extern "C" PyObject* PyNumber_Add(PyObject* lhs, PyObject* rhs) {
Py_FatalError("unimplemented"); try {
return binop(lhs, rhs, AST_TYPE::Add);
} catch (Box* b) {
Py_FatalError("unimplemented");
}
} }
extern "C" PyObject* PyNumber_Subtract(PyObject*, PyObject*) { extern "C" PyObject* PyNumber_Subtract(PyObject* lhs, PyObject* rhs) {
Py_FatalError("unimplemented"); try {
return binop(lhs, rhs, AST_TYPE::Sub);
} catch (Box* b) {
Py_FatalError("unimplemented");
}
} }
extern "C" PyObject* PyNumber_Multiply(PyObject* lhs, PyObject* rhs) { extern "C" PyObject* PyNumber_Multiply(PyObject* lhs, PyObject* rhs) {
......
...@@ -154,7 +154,7 @@ extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) { ...@@ -154,7 +154,7 @@ extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) {
if (rhs->n == 0) { if (rhs->n == 0) {
raiseDivZeroExc(); raiseDivZeroExc();
} }
return boxComplex(lhs->real / (float)rhs->n, lhs->imag / (float)rhs->n); return boxComplex(lhs->real / (double)rhs->n, lhs->imag / (double)rhs->n);
} }
extern "C" Box* complexDiv(BoxedComplex* lhs, Box* rhs) { extern "C" Box* complexDiv(BoxedComplex* lhs, Box* rhs) {
......
...@@ -331,7 +331,7 @@ extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) { ...@@ -331,7 +331,7 @@ extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) {
if (rhs->n == 0) { if (rhs->n == 0) {
raiseExcHelper(ZeroDivisionError, "division by zero"); raiseExcHelper(ZeroDivisionError, "division by zero");
} }
return boxFloat(lhs->n / (float)rhs->n); return boxFloat(lhs->n / (double)rhs->n);
} }
extern "C" Box* intTruedivFloat(BoxedInt* lhs, BoxedFloat* rhs) { extern "C" Box* intTruedivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
...@@ -731,7 +731,7 @@ void setupInt() { ...@@ -731,7 +731,7 @@ void setupInt() {
_addFuncIntFloatUnknown("__sub__", (void*)intSubInt, (void*)intSubFloat, (void*)intSub); _addFuncIntFloatUnknown("__sub__", (void*)intSubInt, (void*)intSubFloat, (void*)intSub);
_addFuncIntFloatUnknown("__div__", (void*)intDivInt, (void*)intDivFloat, (void*)intDiv); _addFuncIntFloatUnknown("__div__", (void*)intDivInt, (void*)intDivFloat, (void*)intDiv);
_addFuncIntFloatUnknown("__floordiv__", (void*)intFloordivInt, (void*)intFloordivFloat, (void*)intFloordiv); _addFuncIntFloatUnknown("__floordiv__", (void*)intFloordivInt, (void*)intFloordivFloat, (void*)intFloordiv);
_addFuncIntFloatUnknown("__truediv__", (void*)intTruedivInt, (void*)intDivFloat, (void*)intTruediv); _addFuncIntFloatUnknown("__truediv__", (void*)intTruedivInt, (void*)intTruedivFloat, (void*)intTruediv);
_addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul); _addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul);
_addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod); _addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod);
_addFuncIntFloatUnknown("__pow__", (void*)intPowInt, (void*)intPowFloat, (void*)intPow); _addFuncIntFloatUnknown("__pow__", (void*)intPowInt, (void*)intPowFloat, (void*)intPow);
......
...@@ -147,7 +147,26 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) { ...@@ -147,7 +147,26 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
BoxedString* s = str(val_to_use); BoxedString* s = str(val_to_use);
os << s->s; os << s->s;
break; break;
} else if (c == 'd') { } else if (c == 'c') {
if (!val_to_use) {
RELEASE_ASSERT(elt_num < num_elts, "insufficient number of arguments for format string");
val_to_use = (*elts)[elt_num];
elt_num++;
}
RELEASE_ASSERT(val_to_use->cls == int_cls, "unsupported");
RELEASE_ASSERT(nspace == 0, "unsupported");
RELEASE_ASSERT(ndot == 0, "unsupported");
RELEASE_ASSERT(nzero == 0, "unsupported");
int64_t n = static_cast<BoxedInt*>(val_to_use)->n;
if (n < 0)
raiseExcHelper(OverflowError, "unsigned byte integer is less than minimum");
if (n >= 256)
raiseExcHelper(OverflowError, "unsigned byte integer is greater than maximum");
os << (char)n;
break;
} else if (c == 'd' || c == 'i') {
if (!val_to_use) { if (!val_to_use) {
RELEASE_ASSERT(elt_num < num_elts, "insufficient number of arguments for format string"); RELEASE_ASSERT(elt_num < num_elts, "insufficient number of arguments for format string");
val_to_use = (*elts)[elt_num]; val_to_use = (*elts)[elt_num];
......
import operator
print reduce(operator.add, range(50))
print reduce(operator.add, range(40), 0)
print reduce(operator.add, "hello world")
print reduce(operator.add, "", 0)
def f(a, b):
print "f", a, b
return b
print reduce(f, "abc", 0)
print reduce(f, "abc")
try:
print reduce(f, [])
except TypeError, e:
print e
# expected: fail
# - can't pass exceptions through C API yet
# (TODO fold this into reduce.py once it works)
import operator
try:
print reduce(operator.add, "hello world", 0)
except TypeError, e:
print e
...@@ -8,3 +8,17 @@ print "%(a(b))s" % {'a(b)': 1} ...@@ -8,3 +8,17 @@ print "%(a(b))s" % {'a(b)': 1}
# I'm not sure if this is a feature or a bug, but both CPython and PyPy will accept it: # I'm not sure if this is a feature or a bug, but both CPython and PyPy will accept it:
print "%s %(a)s" % {'a': 1} print "%s %(a)s" % {'a': 1}
print "%c" % ord('A')
print repr("%c" % 255)
print repr("%c" % 0)
try:
print repr("%c" % -1)
except OverflowError, e:
print e
try:
print repr("%c" % 256)
except OverflowError, e:
print e
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