add ~ operator

This commit is contained in:
BLUELOVETH 2023-07-07 18:43:50 +08:00
parent 4cb6241598
commit d5fc2c8686
13 changed files with 45 additions and 3 deletions

View File

@ -96,6 +96,8 @@ class mat3x3:
def transpose(self) -> mat3x3: ... def transpose(self) -> mat3x3: ...
def inverse(self) -> mat3x3: ... def inverse(self) -> mat3x3: ...
def __invert__(self) -> mat3x3: ...
@staticmethod @staticmethod
def zeros() -> mat3x3: ... def zeros() -> mat3x3: ...
@staticmethod @staticmethod

View File

@ -78,6 +78,13 @@ struct NameExpr: Expr{
bool emit_store(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override;
}; };
struct InvertExpr: Expr{
Expr_ child;
InvertExpr(Expr_&& child): child(std::move(child)) {}
std::string str() const override { return "Invert()"; }
void emit(CodeEmitContext* ctx) override;
};
struct StarredExpr: Expr{ struct StarredExpr: Expr{
int level; int level;
Expr_ child; Expr_ child;

View File

@ -21,7 +21,7 @@ constexpr const char* kTokens[] = {
/*****************************************/ /*****************************************/
".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}",
"**", "=", ">", "<", "...", "->", "?", "@", "==", "!=", ">=", "<=", "**", "=", ">", "<", "...", "->", "?", "@", "==", "!=", ">=", "<=",
"++", "--", "++", "--", "~",
/** SPEC_BEGIN **/ /** SPEC_BEGIN **/
"$goto", "$label", "$goto", "$label",
/** KW_BEGIN **/ /** KW_BEGIN **/
@ -92,7 +92,7 @@ enum Precedence {
PREC_BITWISE_SHIFT, // << >> PREC_BITWISE_SHIFT, // << >>
PREC_TERM, // + - PREC_TERM, // + -
PREC_FACTOR, // * / % // @ PREC_FACTOR, // * / % // @
PREC_UNARY, // - not PREC_UNARY, // - not ~
PREC_EXPONENT, // ** PREC_EXPONENT, // **
PREC_CALL, // () PREC_CALL, // ()
PREC_SUBSCRIPT, // [] PREC_SUBSCRIPT, // []

View File

@ -99,6 +99,7 @@ OPCODE(SET_ADD)
OPCODE(UNARY_NEGATIVE) OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT) OPCODE(UNARY_NOT)
OPCODE(UNARY_STAR) OPCODE(UNARY_STAR)
OPCODE(UNARY_INVERT)
/**************************/ /**************************/
OPCODE(GET_ITER) OPCODE(GET_ITER)
OPCODE(FOR_ITER) OPCODE(FOR_ITER)

View File

@ -281,6 +281,7 @@ const StrName __rshift__ = StrName::get("__rshift__");
const StrName __and__ = StrName::get("__and__"); const StrName __and__ = StrName::get("__and__");
const StrName __or__ = StrName::get("__or__"); const StrName __or__ = StrName::get("__or__");
const StrName __xor__ = StrName::get("__xor__"); const StrName __xor__ = StrName::get("__xor__");
const StrName __invert__ = StrName::get("__invert__");
// indexer // indexer
const StrName __getitem__ = StrName::get("__getitem__"); const StrName __getitem__ = StrName::get("__getitem__");
const StrName __setitem__ = StrName::get("__setitem__"); const StrName __setitem__ = StrName::get("__setitem__");

View File

@ -65,6 +65,7 @@ struct PyTypeInfo{
PyObject* (*m__json__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__json__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__bool__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__bool__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__invert__)(VM* vm, PyObject*) = nullptr;
BinaryFuncC m__eq__ = nullptr; BinaryFuncC m__eq__ = nullptr;
BinaryFuncC m__lt__ = nullptr; BinaryFuncC m__lt__ = nullptr;
@ -221,6 +222,7 @@ public:
BIND_UNARY_SPECIAL(__json__) BIND_UNARY_SPECIAL(__json__)
BIND_UNARY_SPECIAL(__neg__) BIND_UNARY_SPECIAL(__neg__)
BIND_UNARY_SPECIAL(__bool__) BIND_UNARY_SPECIAL(__bool__)
BIND_UNARY_SPECIAL(__invert__)
void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*)); void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*));
void bind__len__(Type type, i64 (*f)(VM* vm, PyObject*)); void bind__len__(Type type, i64 (*f)(VM* vm, PyObject*));

View File

@ -566,6 +566,12 @@ __NEXT_STEP:;
TARGET(UNARY_STAR) TARGET(UNARY_STAR)
TOP() = VAR(StarWrapper(byte.arg, TOP())); TOP() = VAR(StarWrapper(byte.arg, TOP()));
DISPATCH(); DISPATCH();
TARGET(UNARY_INVERT)
_ti = _inst_type_info(TOP());
if(_ti->m__invert__) _0 = _ti->m__invert__(this, TOP());
else _0 = call_method(TOP(), __invert__);
TOP() = _0;
DISPATCH();
/*****************************************/ /*****************************************/
TARGET(GET_ITER) TARGET(GET_ITER)
TOP() = py_iter(TOP()); TOP() = py_iter(TOP());

View File

@ -52,6 +52,7 @@ namespace pkpy{
rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM }; rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM };
rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM }; rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM };
rules[TK("*")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_FACTOR }; rules[TK("*")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("~")] = { METHOD(exprUnaryOp), nullptr, PREC_UNARY };
rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("**")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_EXPONENT }; rules[TK("**")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_EXPONENT };
@ -241,6 +242,9 @@ namespace pkpy{
case TK("-"): case TK("-"):
ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx())); ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx()));
break; break;
case TK("~"):
ctx()->s_expr.push(make_expr<InvertExpr>(ctx()->s_expr.popx()));
break;
case TK("*"): case TK("*"):
ctx()->s_expr.push(make_expr<StarredExpr>(1, ctx()->s_expr.popx())); ctx()->s_expr.push(make_expr<StarredExpr>(1, ctx()->s_expr.popx()));
break; break;

View File

@ -139,6 +139,10 @@ namespace pkpy{
return true; return true;
} }
void InvertExpr::emit(CodeEmitContext* ctx) {
child->emit(ctx);
ctx->emit(OP_UNARY_INVERT, BC_NOARG, line);
}
void StarredExpr::emit(CodeEmitContext* ctx) { void StarredExpr::emit(CodeEmitContext* ctx) {
child->emit(ctx); child->emit(ctx);

View File

@ -286,6 +286,7 @@ namespace pkpy{
switch (c) { switch (c) {
case '\'': case '"': eat_string(c, NORMAL_STRING); return true; case '\'': case '"': eat_string(c, NORMAL_STRING); return true;
case '#': skip_line_comment(); break; case '#': skip_line_comment(); break;
case '~': add_token(TK("~")); return true;
case '{': add_token(TK("{")); return true; case '{': add_token(TK("{")); return true;
case '}': add_token(TK("}")); return true; case '}': add_token(TK("}")); return true;
case ',': add_token(TK(",")); return true; case ',': add_token(TK(",")); return true;

View File

@ -375,6 +375,14 @@ namespace pkpy{
return VAR_T(PyMat3x3, ret); return VAR_T(PyMat3x3, ret);
}); });
vm->bind__invert__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyMat3x3& self = _CAST(PyMat3x3&, obj);
Mat3x3 ret;
bool ok = self.inverse(ret);
if(!ok) vm->ValueError("matrix is not invertible");
return VAR_T(PyMat3x3, ret);
});
vm->bind_func<0>(type, "zeros", [](VM* vm, ArgsView args){ vm->bind_func<0>(type, "zeros", [](VM* vm, ArgsView args){
PK_UNUSED(args); PK_UNUSED(args);
return VAR_T(PyMat3x3, Mat3x3::zeros()); return VAR_T(PyMat3x3, Mat3x3::zeros());

View File

@ -343,6 +343,8 @@ void init_builtins(VM* _vm) {
_vm->bind__hash__(_vm->tp_int, [](VM* vm, PyObject* obj) { return _CAST(i64, obj); }); _vm->bind__hash__(_vm->tp_int, [](VM* vm, PyObject* obj) { return _CAST(i64, obj); });
_vm->bind__invert__(_vm->tp_int, [](VM* vm, PyObject* obj) { return VAR(~_CAST(i64, obj)); });
#define INT_BITWISE_OP(name, op) \ #define INT_BITWISE_OP(name, op) \
_vm->bind##name(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \ _vm->bind##name(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
return VAR(_CAST(i64, lhs) op CAST(i64, rhs)); \ return VAR(_CAST(i64, lhs) op CAST(i64, rhs)); \

View File

@ -59,3 +59,7 @@ assert 2**60 == 1152921504606846976
assert -2**60 == -1152921504606846976 assert -2**60 == -1152921504606846976
assert 4**13 == 67108864 assert 4**13 == 67108864
assert (-4)**13 == -67108864 assert (-4)**13 == -67108864
assert ~3 == -4
assert ~-3 == 2
assert ~0 == -1