Skip to content

Commit

Permalink
Use operator module to define binary operators on Python objects
Browse files Browse the repository at this point in the history
This simplifies things considerably, as we don't need to worry about
checking for NotImplemented, using the reflected versions of each
method, or handling errors.
  • Loading branch information
d-torrance committed Jan 9, 2025
1 parent 17909bd commit 1c99b60
Showing 1 changed file with 32 additions and 38 deletions.
70 changes: 32 additions & 38 deletions M2/Macaulay2/packages/Python.m2
Original file line number Diff line number Diff line change
Expand Up @@ -272,33 +272,39 @@ PythonObject == PythonObject := (x, y) ->
PythonObject == Thing := (x, y) -> x == toPython y
Thing == PythonObject := (x, y) -> toPython x == y

isimplemented = x -> value x@@"__class__"@@"__name__" != "NotImplementedType"
getattr = method()
getattr(PythonObject, String) := pythonObjectGetAttrString
PythonObject @@ Thing := (x, y) -> getattr(x, toString y)

hasattr = method()
hasattr(PythonObject, String) := pythonObjectHasAttrString

setattr = method()
setattr(PythonObject, String, Thing) := (x, y, e) ->
pythonObjectSetAttrString(x, y, toPython e)
PythonObject @@ Thing = (x, y, e) -> setattr(x, toString y, e)

-- binary operators
operator = import "operator"
scan({
(symbol +, "add"),
(symbol -, "sub"),
(symbol *, "mul"),
(symbol @, "matmul"),
(symbol /, "truediv"),
(symbol //, "floordiv"),
(symbol %, "mod"),
(symbol ^, "pow"),
(symbol <<, "lshift"),
(symbol >>, "rshift"),
(symbol &, "and"),
(symbol |, "or"),
(symbol ^^, "xor"),
(symbol and, "and"),
(symbol or, "or"),
(symbol xor, "xor")},
(op, name) -> (
m := "__" | name | "__";
rm := "__r" | name | "__";
f := (x, y) -> (
local r;
if hasattr(x, m) and isimplemented(r = x@@m y) then r else
if hasattr(y, rm) and isimplemented(r = y@@rm x) then r else
error("no method for ", format toString op));
installMethod(op, PythonObject, PythonObject, f);
(symbol +, operator@@"add"),
(symbol -, operator@@"sub"),
(symbol *, operator@@"mul"),
(symbol @, operator@@"matmul"),
(symbol /, operator@@"truediv"),
(symbol //, operator@@"floordiv"),
(symbol %, operator@@"mod"),
(symbol ^, operator@@"pow"),
(symbol <<, operator@@"lshift"),
(symbol >>, operator@@"rshift"),
(symbol &, operator@@"and_"),
(symbol |, operator@@"or_"),
(symbol ^^, operator@@"xor"),
(symbol and, operator@@"and_"),
(symbol or, operator@@"or_"),
(symbol xor, operator@@"xor")},
(op, f) -> (
installMethod(op, PythonObject, PythonObject, toFunction f);
installMethod(op, PythonObject, Thing, (x, y) -> f(x, toPython y));
installMethod(op, Thing, PythonObject, (x, y) -> f(toPython x, y))
)
Expand Down Expand Up @@ -348,18 +354,6 @@ setitem(PythonObject, Thing, Thing) := (x, i, e) -> (
null)
PythonObject_Thing = setitem

getattr = method()
getattr(PythonObject, String) := pythonObjectGetAttrString
PythonObject @@ Thing := (x, y) -> getattr(x, toString y)

hasattr = method()
hasattr(PythonObject, String) := pythonObjectHasAttrString

setattr = method()
setattr(PythonObject, String, Thing) := (x, y, e) ->
pythonObjectSetAttrString(x, y, toPython e)
PythonObject @@ Thing = (x, y, e) -> setattr(x, toString y, e)

isMember(Thing, PythonObject) := (x, y) -> false
isMember(PythonObject, PythonObject) := (x, y) -> value y@@"__contains__" x

Expand Down

0 comments on commit 1c99b60

Please sign in to comment.