Skip to content

Commit 473e9c5

Browse files
committed
f-strings: Make optional, defaulting to !CIRCUITPY_MINIMAL_BUILD
This should reclaim *most* code space added to handle f-strings. However, there may be some small code growth as parse_string_literal takes a new parameter (which will always be 0, so hopefully the optimizer eliminates it)
1 parent 32647cd commit 473e9c5

File tree

5 files changed

+48
-1
lines changed

5 files changed

+48
-1
lines changed

py/circuitpy_mpconfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ typedef long mp_off_t;
187187
#if !defined(MICROPY_CPYTHON_COMPAT)
188188
#define MICROPY_CPYTHON_COMPAT (CIRCUITPY_FULL_BUILD)
189189
#endif
190+
#if !defined(MICROPY_COMP_FSTRING_LITERAL)
191+
#define MICROPY_COMP_FSTRING_LITERAL (MICROPY_CPYTHON_COMPAT)
192+
#endif
190193
#define MICROPY_MODULE_WEAK_LINKS (CIRCUITPY_FULL_BUILD)
191194
#define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD)
192195
#define MICROPY_PY_BUILTINS_COMPLEX (CIRCUITPY_FULL_BUILD)

py/lexer.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ STATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {
6464
return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
6565
}
6666

67+
#if MICROPY_COMP_FSTRING_LITERAL
6768
STATIC bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) {
6869
return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3 || lex->chr0 == c4;
6970
}
71+
#endif
7072

7173
STATIC bool is_char_following(mp_lexer_t *lex, byte c) {
7274
return lex->chr1 == c;
@@ -111,9 +113,13 @@ STATIC bool is_following_odigit(mp_lexer_t *lex) {
111113

112114
STATIC bool is_string_or_bytes(mp_lexer_t *lex) {
113115
return is_char_or(lex, '\'', '\"')
116+
#if MICROPY_COMP_FSTRING_LITERAL
114117
|| (is_char_or4(lex, 'r', 'u', 'b', 'f') && is_char_following_or(lex, '\'', '\"'))
115118
|| ((is_char_and(lex, 'r', 'f') || is_char_and(lex, 'f', 'r'))
116119
&& is_char_following_following_or(lex, '\'', '\"'))
120+
#else
121+
|| (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
122+
#endif
117123
|| ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))
118124
&& is_char_following_following_or(lex, '\'', '\"'));
119125
}
@@ -127,6 +133,7 @@ STATIC bool is_tail_of_identifier(mp_lexer_t *lex) {
127133
return is_head_of_identifier(lex) || is_digit(lex);
128134
}
129135

136+
#if MICROPY_COMP_FSTRING_LITERAL
130137
STATIC void swap_char_banks(mp_lexer_t *lex) {
131138
if (lex->vstr_postfix_processing) {
132139
lex->chr3 = lex->chr0;
@@ -149,6 +156,7 @@ STATIC void swap_char_banks(mp_lexer_t *lex) {
149156
lex->vstr_postfix_idx = 0;
150157
}
151158
}
159+
#endif
152160

153161
STATIC void next_char(mp_lexer_t *lex) {
154162
if (lex->chr0 == '\n') {
@@ -166,13 +174,16 @@ STATIC void next_char(mp_lexer_t *lex) {
166174
lex->chr0 = lex->chr1;
167175
lex->chr1 = lex->chr2;
168176

177+
#if MICROPY_COMP_FSTRING_LITERAL
169178
if (lex->vstr_postfix_processing) {
170179
if (lex->vstr_postfix_idx == lex->vstr_postfix.len) {
171180
lex->chr2 = '\0';
172181
} else {
173182
lex->chr2 = lex->vstr_postfix.buf[lex->vstr_postfix_idx++];
174183
}
175-
} else {
184+
} else
185+
#endif
186+
{
176187
lex->chr2 = lex->reader.readbyte(lex->reader.data);
177188
}
178189

@@ -190,10 +201,12 @@ STATIC void next_char(mp_lexer_t *lex) {
190201
lex->chr2 = '\n';
191202
}
192203

204+
#if MICROPY_COMP_FSTRING_LITERAL
193205
if (lex->vstr_postfix_processing && lex->chr0 == '\0') {
194206
lex->vstr_postfix_processing = false;
195207
swap_char_banks(lex);
196208
}
209+
#endif
197210
}
198211

199212
STATIC void indent_push(mp_lexer_t *lex, size_t indent) {
@@ -334,15 +347,18 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring)
334347
}
335348

336349
size_t n_closing = 0;
350+
#if MICROPY_COMP_FSTRING_LITERAL
337351
bool in_expression = false;
338352
bool expression_eat = true;
353+
#endif
339354

340355
while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
341356
if (is_char(lex, quote_char)) {
342357
n_closing += 1;
343358
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
344359
} else {
345360
n_closing = 0;
361+
#if MICROPY_COMP_FSTRING_LITERAL
346362
if (is_fstring && is_char(lex, '{')) {
347363
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
348364
in_expression = !in_expression;
@@ -390,6 +406,7 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring)
390406
next_char(lex);
391407
continue;
392408
}
409+
#endif
393410

394411
if (is_char(lex, '\\')) {
395412
next_char(lex);
@@ -525,12 +542,14 @@ STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {
525542
}
526543

527544
void mp_lexer_to_next(mp_lexer_t *lex) {
545+
#if MICROPY_COMP_FSTRING_LITERAL
528546
if (lex->vstr_postfix.len && !lex->vstr_postfix_processing) {
529547
// end format call injection
530548
vstr_add_char(&lex->vstr_postfix, ')');
531549
lex->vstr_postfix_processing = true;
532550
swap_char_banks(lex);
533551
}
552+
#endif
534553

535554
// start new token text
536555
vstr_reset(&lex->vstr);
@@ -583,13 +602,19 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
583602
// MP_TOKEN_END is used to indicate that this is the first string token
584603
lex->tok_kind = MP_TOKEN_END;
585604

605+
#if MICROPY_COMP_FSTRING_LITERAL
586606
bool saw_normal = false, saw_fstring = false;
607+
#endif
587608

588609
// Loop to accumulate string/bytes literals
589610
do {
590611
// parse type codes
591612
bool is_raw = false;
613+
#if MICROPY_COMP_FSTRING_LITERAL
592614
bool is_fstring = false;
615+
#else
616+
const bool is_fstring = false;
617+
#endif
593618
mp_token_kind_t kind = MP_TOKEN_STRING;
594619
int n_char = 0;
595620
if (is_char(lex, 'u')) {
@@ -608,6 +633,7 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
608633
kind = MP_TOKEN_BYTES;
609634
n_char = 2;
610635
}
636+
#if MICROPY_COMP_FSTRING_LITERAL
611637
if (is_char_following(lex, 'f')) {
612638
lex->tok_kind = MP_TOKEN_FSTRING_RAW;
613639
break;
@@ -619,8 +645,10 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
619645
}
620646
n_char = 1;
621647
is_fstring = true;
648+
#endif
622649
}
623650

651+
#if MICROPY_COMP_FSTRING_LITERAL
624652
if (is_fstring) {
625653
saw_fstring = true;
626654
} else {
@@ -631,6 +659,7 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
631659
// Can't concatenate f-string with normal string
632660
break;
633661
}
662+
#endif
634663

635664
// Set or check token kind
636665
if (lex->tok_kind == MP_TOKEN_END) {
@@ -808,7 +837,9 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
808837
lex->num_indent_level = 1;
809838
lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
810839
vstr_init(&lex->vstr, 32);
840+
#if MICROPY_COMP_FSTRING_LITERAL
811841
vstr_init(&lex->vstr_postfix, 0);
842+
#endif
812843

813844
// store sentinel for first indentation level
814845
lex->indent_level[0] = 0;

py/lexer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ typedef enum _mp_token_kind_t {
4444
MP_TOKEN_INVALID,
4545
MP_TOKEN_DEDENT_MISMATCH,
4646
MP_TOKEN_LONELY_STRING_OPEN,
47+
#if MICROPY_COMP_FSTRING_LITERAL
4748
MP_TOKEN_FSTRING_BACKSLASH,
4849
MP_TOKEN_FSTRING_COMMENT,
4950
MP_TOKEN_FSTRING_UNCLOSED,
5051
MP_TOKEN_FSTRING_UNOPENED,
5152
MP_TOKEN_FSTRING_EMPTY_EXP,
5253
MP_TOKEN_FSTRING_RAW,
54+
#endif
5355

5456
MP_TOKEN_NEWLINE,
5557
MP_TOKEN_INDENT,
@@ -156,7 +158,9 @@ typedef struct _mp_lexer_t {
156158
mp_reader_t reader; // stream source
157159

158160
unichar chr0, chr1, chr2; // current cached characters from source
161+
#if MICROPY_COMP_FSTRING_LITERAL
159162
unichar chr3, chr4, chr5; // current cached characters from alt source
163+
#endif
160164

161165
size_t line; // current source line
162166
size_t column; // current source column
@@ -172,9 +176,11 @@ typedef struct _mp_lexer_t {
172176
size_t tok_column; // token source column
173177
mp_token_kind_t tok_kind; // token kind
174178
vstr_t vstr; // token data
179+
#if MICROPY_COMP_FSTRING_LITERAL
175180
vstr_t vstr_postfix; // postfix to apply to string
176181
bool vstr_postfix_processing;
177182
uint16_t vstr_postfix_idx;
183+
#endif
178184
} mp_lexer_t;
179185

180186
mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader);

py/mpconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@
377377
#define MICROPY_COMP_RETURN_IF_EXPR (0)
378378
#endif
379379

380+
// Whether to include parsing of f-string literals
381+
#ifndef MICROPY_COMP_FSTRING_LITERAL
382+
#define MICROPY_COMP_FSTRING_LITERAL (1)
383+
#endif
384+
380385
/*****************************************************************************/
381386
/* Internal debugging stuff */
382387

py/parse.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
11781178
exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
11791179
translate("unindent does not match any outer indentation level"));
11801180
break;
1181+
#if MICROPY_COMP_FSTRING_LITERAL
11811182
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
11821183
case MP_TOKEN_FSTRING_BACKSLASH:
11831184
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
@@ -1213,6 +1214,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
12131214
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
12141215
translate("malformed f-string"));
12151216
break;
1217+
#endif
12161218
#endif
12171219
default:
12181220
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,

0 commit comments

Comments
 (0)