Skip to content

Commit f2e267d

Browse files
committed
py/compile: Implement PEP 526, syntax for variable annotations.
This addition to the grammar was introduced in Python 3.6. It allows annotating the type of a varilable, like: x: int = 123 s: str The implementation in this commit is quite simple and just ignores the annotation (the int and str bits above). The reason to implement this is to allow Python 3.6+ code that uses this feature to compile under MicroPython without change, and for users to use type checkers. In the future viper could use this syntax as a way to give types to variables, which is currently done in a bit of an ad-hoc way, eg x = int(123). And this syntax could potentially be used in the inline assembler to define labels in an way that's easier to read.
1 parent 131b0de commit f2e267d

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

py/compile.c

+24-7
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,8 @@ STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
19811981
#endif
19821982

19831983
STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1984-
if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
1984+
mp_parse_node_t pn_rhs = pns->nodes[1];
1985+
if (MP_PARSE_NODE_IS_NULL(pn_rhs)) {
19851986
if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
19861987
// for REPL, evaluate then print the expression
19871988
compile_load_id(comp, MP_QSTR___repl_print__);
@@ -1999,10 +2000,26 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
19992000
EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
20002001
}
20012002
}
2002-
} else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2003-
mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
2003+
} else if (MP_PARSE_NODE_IS_STRUCT(pn_rhs)) {
2004+
mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn_rhs;
20042005
int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
2005-
if (kind == PN_expr_stmt_augassign) {
2006+
if (kind == PN_annassign) {
2007+
// the annotation is in pns1->nodes[0] and is ignored
2008+
if (MP_PARSE_NODE_IS_NULL(pns1->nodes[1])) {
2009+
// an annotation of the form "x: y"
2010+
// inside a function this declares "x" as a local
2011+
if (comp->scope_cur->kind == SCOPE_FUNCTION) {
2012+
if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
2013+
qstr lhs = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2014+
scope_find_or_add_id(comp->scope_cur, lhs, ID_INFO_KIND_LOCAL);
2015+
}
2016+
}
2017+
} else {
2018+
// an assigned annotation of the form "x: y = z"
2019+
pn_rhs = pns1->nodes[1];
2020+
goto plain_assign;
2021+
}
2022+
} else if (kind == PN_expr_stmt_augassign) {
20062023
c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
20072024
compile_node(comp, pns1->nodes[1]); // rhs
20082025
assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
@@ -2027,10 +2044,10 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
20272044
} else {
20282045
plain_assign:
20292046
#if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
2030-
if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
2047+
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_rhs, PN_testlist_star_expr)
20312048
&& MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) {
20322049
mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t *)pns->nodes[0];
2033-
pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
2050+
pns1 = (mp_parse_node_struct_t *)pn_rhs;
20342051
uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0);
20352052
// Can only optimise a tuple-to-tuple assignment when all of the following hold:
20362053
// - equal number of items in LHS and RHS tuples
@@ -2070,7 +2087,7 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
20702087
}
20712088
#endif
20722089

2073-
compile_node(comp, pns->nodes[1]); // rhs
2090+
compile_node(comp, pn_rhs); // rhs
20742091
c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
20752092
}
20762093
} else {

py/grammar.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,22 @@ DEF_RULE_NC(simple_stmt, and_ident(2), rule(simple_stmt_2), tok(NEWLINE))
9898
DEF_RULE(simple_stmt_2, c(generic_all_nodes), list_with_end, rule(small_stmt), tok(DEL_SEMICOLON))
9999

100100
// small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt
101-
// expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*)
101+
// expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*)
102102
// testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
103+
// annassign: ':' test ['=' (yield_expr|testlist_star_expr)]
103104
// augassign: '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='
104-
// # For normal assignments, additional restrictions enforced by the interpreter
105+
// # For normal and annotated assignments, additional restrictions enforced by the interpreter
105106

106107
DEF_RULE_NC(small_stmt, or(8), rule(del_stmt), rule(pass_stmt), rule(flow_stmt), rule(import_stmt), rule(global_stmt), rule(nonlocal_stmt), rule(assert_stmt), rule(expr_stmt))
107108
DEF_RULE(expr_stmt, c(expr_stmt), and(2), rule(testlist_star_expr), opt_rule(expr_stmt_2))
108-
DEF_RULE_NC(expr_stmt_2, or(2), rule(expr_stmt_augassign), rule(expr_stmt_assign_list))
109+
DEF_RULE_NC(expr_stmt_2, or(3), rule(annassign), rule(expr_stmt_augassign), rule(expr_stmt_assign_list))
109110
DEF_RULE_NC(expr_stmt_augassign, and_ident(2), rule(augassign), rule(expr_stmt_6))
110111
DEF_RULE_NC(expr_stmt_assign_list, one_or_more, rule(expr_stmt_assign))
111112
DEF_RULE_NC(expr_stmt_assign, and_ident(2), tok(DEL_EQUAL), rule(expr_stmt_6))
112113
DEF_RULE_NC(expr_stmt_6, or(2), rule(yield_expr), rule(testlist_star_expr))
113114
DEF_RULE(testlist_star_expr, c(generic_tuple), list_with_end, rule(testlist_star_expr_2), tok(DEL_COMMA))
114115
DEF_RULE_NC(testlist_star_expr_2, or(2), rule(star_expr), rule(test))
116+
DEF_RULE_NC(annassign, and(3), tok(DEL_COLON), rule(test), opt_rule(expr_stmt_assign))
115117
DEF_RULE_NC(augassign, or(13), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(DEL_STAR_EQUAL), tok(DEL_AT_EQUAL), tok(DEL_SLASH_EQUAL), tok(DEL_PERCENT_EQUAL), tok(DEL_AMPERSAND_EQUAL), tok(DEL_PIPE_EQUAL), tok(DEL_CARET_EQUAL), tok(DEL_DBL_LESS_EQUAL), tok(DEL_DBL_MORE_EQUAL), tok(DEL_DBL_STAR_EQUAL), tok(DEL_DBL_SLASH_EQUAL))
116118

117119
// del_stmt: 'del' exprlist

0 commit comments

Comments
 (0)