static int compiler_nameop(struct compiler *, location, identifier, expr_context_ty);
static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
-static int compiler_visit_stmt(struct compiler *, stmt_ty);
-static int compiler_visit_keyword(struct compiler *, keyword_ty);
-static int compiler_visit_expr(struct compiler *, expr_ty);
+static int codegen_visit_stmt(struct compiler *, stmt_ty);
+static int codegen_visit_keyword(struct compiler *, keyword_ty);
+static int codegen_visit_expr(struct compiler *, expr_ty);
static int codegen_augassign(struct compiler *, stmt_ty);
static int codegen_annassign(struct compiler *, stmt_ty);
static int codegen_subscript(struct compiler *, expr_ty);
*/
#define VISIT(C, TYPE, V) \
- RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V)));
+ RETURN_IF_ERROR(codegen_visit_ ## TYPE((C), (V)));
#define VISIT_IN_SCOPE(C, TYPE, V) \
- RETURN_IF_ERROR_IN_SCOPE((C), compiler_visit_ ## TYPE((C), (V)))
+ RETURN_IF_ERROR_IN_SCOPE((C), codegen_visit_ ## TYPE((C), (V)))
#define VISIT_SEQ(C, TYPE, SEQ) { \
int _i; \
asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \
for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
- RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), elt)); \
+ RETURN_IF_ERROR(codegen_visit_ ## TYPE((C), elt)); \
} \
}
asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \
for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
- if (compiler_visit_ ## TYPE((C), elt) < 0) { \
+ if (codegen_visit_ ## TYPE((C), elt) < 0) { \
compiler_exit_scope(C); \
return ERROR; \
} \
Return -1 on error, 0 if no dict pushed, 1 if a dict is pushed.
*/
- int i;
- PyObject *keys = NULL;
int default_count = 0;
- for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
+ for (int i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
arg_ty arg = asdl_seq_GET(kwonlyargs, i);
expr_ty default_ = asdl_seq_GET(kw_defaults, i);
if (default_) {
default_count++;
PyObject *mangled = compiler_maybe_mangle(c, arg->arg);
if (!mangled) {
- goto error;
+ return ERROR;
}
ADDOP_LOAD_CONST_NEW(c, loc, mangled);
- if (compiler_visit_expr(c, default_) < 0) {
- goto error;
- }
+ VISIT(c, expr, default_);
}
}
if (default_count) {
else {
return 0;
}
-
-error:
- Py_XDECREF(keys);
- return ERROR;
}
static int
-compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
+codegen_visit_annexpr(struct compiler *c, expr_ty annotation)
{
location loc = LOC(annotation);
ADDOP_LOAD_CONST_NEW(c, loc, _PyAST_ExprAsUnicode(annotation));
}
static int
-compiler_visit_stmt(struct compiler *c, stmt_ty s)
+codegen_visit_stmt(struct compiler *c, stmt_ty s)
{
switch (s->kind) {
static int
-compiler_visit_keyword(struct compiler *c, keyword_ty k)
+codegen_visit_keyword(struct compiler *c, keyword_ty k)
{
VISIT(c, expr, k->value);
return SUCCESS;
}
static int
-compiler_visit_expr(struct compiler *c, expr_ty e)
+codegen_visit_expr(struct compiler *c, expr_ty e)
{
location loc = LOC(e);
switch (e->kind) {
return SUCCESS;
}
-/* Raises a SyntaxError and returns 0.
+/* Raises a SyntaxError and returns ERROR.
If something goes wrong, a different exception may be raised.
*/
return SUCCESS;
}
+static int
+codegen_pattern_mapping_key(struct compiler *c, PyObject *seen, pattern_ty p, Py_ssize_t i)
+{
+ asdl_expr_seq *keys = p->v.MatchMapping.keys;
+ asdl_pattern_seq *patterns = p->v.MatchMapping.patterns;
+ expr_ty key = asdl_seq_GET(keys, i);
+ if (key == NULL) {
+ const char *e = "can't use NULL keys in MatchMapping "
+ "(set 'rest' parameter instead)";
+ location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));
+ return compiler_error(c, loc, e);
+ }
+
+ if (key->kind == Constant_kind) {
+ int in_seen = PySet_Contains(seen, key->v.Constant.value);
+ RETURN_IF_ERROR(in_seen);
+ if (in_seen) {
+ const char *e = "mapping pattern checks duplicate key (%R)";
+ return compiler_error(c, LOC(p), e, key->v.Constant.value);
+ }
+ RETURN_IF_ERROR(PySet_Add(seen, key->v.Constant.value));
+ }
+ else if (key->kind != Attribute_kind) {
+ const char *e = "mapping pattern keys may only match literals and attribute lookups";
+ return compiler_error(c, LOC(p), e);
+ }
+ VISIT(c, expr, key);
+ return SUCCESS;
+}
+
static int
codegen_pattern_mapping(struct compiler *c, pattern_ty p,
pattern_context *pc)
if (seen == NULL) {
return ERROR;
}
-
- // NOTE: goto error on failure in the loop below to avoid leaking `seen`
for (Py_ssize_t i = 0; i < size; i++) {
- expr_ty key = asdl_seq_GET(keys, i);
- if (key == NULL) {
- const char *e = "can't use NULL keys in MatchMapping "
- "(set 'rest' parameter instead)";
- location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));
- compiler_error(c, loc, e);
- goto error;
- }
-
- if (key->kind == Constant_kind) {
- int in_seen = PySet_Contains(seen, key->v.Constant.value);
- if (in_seen < 0) {
- goto error;
- }
- if (in_seen) {
- const char *e = "mapping pattern checks duplicate key (%R)";
- compiler_error(c, LOC(p), e, key->v.Constant.value);
- goto error;
- }
- if (PySet_Add(seen, key->v.Constant.value)) {
- goto error;
- }
- }
-
- else if (key->kind != Attribute_kind) {
- const char *e = "mapping pattern keys may only match literals and attribute lookups";
- compiler_error(c, LOC(p), e);
- goto error;
- }
- if (compiler_visit_expr(c, key) < 0) {
- goto error;
+ if (codegen_pattern_mapping_key(c, seen, p, i) < 0) {
+ Py_DECREF(seen);
+ return ERROR;
}
}
+ Py_DECREF(seen);
// all keys have been checked; there are no duplicates
- Py_DECREF(seen);
ADDOP_I(c, LOC(p), BUILD_TUPLE, size);
ADDOP(c, LOC(p), MATCH_KEYS);
ADDOP(c, LOC(p), POP_TOP); // Subject.
}
return SUCCESS;
-
-error:
- Py_DECREF(seen);
- return ERROR;
}
static int