Make unary + call __pos__

Fixes #1109.

__pos__ doesn't work on strings, lists, or tuples, so I've removed some tests that required (= (+ "a") "a") etc.
This commit is contained in:
Kodi Arfer 2016-09-20 13:05:52 -07:00
parent b94211251c
commit a60b749d3e
4 changed files with 33 additions and 13 deletions

View File

@ -1910,7 +1910,6 @@ class HyASTCompiler(object):
col_offset=child.start_column) col_offset=child.start_column)
return ret return ret
@builds("+")
@builds("*") @builds("*")
@builds("/") @builds("/")
@builds("//") @builds("//")
@ -1918,8 +1917,7 @@ class HyASTCompiler(object):
if len(expression) > 2: if len(expression) > 2:
return self.compile_maths_expression(expression) return self.compile_maths_expression(expression)
else: else:
id_op = {"+": HyInteger(0), "*": HyInteger(1), "/": HyInteger(1), id_op = {"*": HyInteger(1), "/": HyInteger(1), "//": HyInteger(1)}
"//": HyInteger(1)}
op = expression.pop(0) op = expression.pop(0)
arg = expression.pop(0) if expression else id_op[op] arg = expression.pop(0) if expression else id_op[op]
@ -1930,20 +1928,34 @@ class HyASTCompiler(object):
]).replace(expression) ]).replace(expression)
return self.compile_maths_expression(expr) return self.compile_maths_expression(expr)
@builds("-") def compile_maths_expression_additive(self, expression):
@checkargs(min=1)
def compile_maths_expression_sub(self, expression):
if len(expression) > 2: if len(expression) > 2:
return self.compile_maths_expression(expression) return self.compile_maths_expression(expression)
else: else:
arg = expression[1] op = {"+": ast.UAdd, "-": ast.USub}[expression.pop(0)]()
arg = expression.pop(0)
ret = self.compile(arg) ret = self.compile(arg)
ret += ast.UnaryOp(op=ast.USub(), ret += ast.UnaryOp(op=op,
operand=ret.force_expr, operand=ret.force_expr,
lineno=arg.start_line, lineno=arg.start_line,
col_offset=arg.start_column) col_offset=arg.start_column)
return ret return ret
@builds("+")
def compile_maths_expression_add(self, expression):
if len(expression) == 1:
# Nullary +
return ast.Num(n=long_type(0),
lineno=expression.start_line,
col_offset=expression.start_column)
else:
return self.compile_maths_expression_additive(expression)
@builds("-")
@checkargs(min=1)
def compile_maths_expression_sub(self, expression):
return self.compile_maths_expression_additive(expression)
@builds("+=") @builds("+=")
@builds("/=") @builds("/=")
@builds("//=") @builds("//=")

View File

@ -30,7 +30,7 @@
(if (zero? count) (if (zero? count)
(raise (TypeError "Need at least 1 argument to add/concatenate")) (raise (TypeError "Need at least 1 argument to add/concatenate"))
(if (= count 1) (if (= count 1)
(get args 0) (operator.pos (get args 0))
(reduce operator.add args))))) (reduce operator.add args)))))

View File

@ -28,6 +28,18 @@
(assert (= 0 (+))))) (assert (= 0 (+)))))
(defn test-add-unary []
"NATIVE: test that unary + calls __pos__"
(defclass X [object]
[__pos__ (fn [self] "called __pos__")])
(assert (= (+ (X)) "called __pos__"))
; Make sure the shadowed version works, too.
(setv f +)
(assert (= (f (X)) "called __pos__")))
(setv test_div (fn [] (setv test_div (fn []
"NATIVE: Test division" "NATIVE: Test division"
(assert (= 25 (/ 100 2 2))) (assert (= 25 (/ 100 2 2)))

View File

@ -8,13 +8,9 @@
(assert (= (x 1 2 3 4) 10)) (assert (= (x 1 2 3 4) 10))
(assert (= (x 1 2 3 4 5) 15)) (assert (= (x 1 2 3 4 5) 15))
; with strings ; with strings
(assert (= (x "a")
"a"))
(assert (= (x "a" "b" "c") (assert (= (x "a" "b" "c")
"abc")) "abc"))
; with lists ; with lists
(assert (= (x ["a"])
["a"]))
(assert (= (x ["a"] ["b"] ["c"]) (assert (= (x ["a"] ["b"] ["c"])
["a" "b" "c"])))) ["a" "b" "c"]))))