Skip to content

Commit 3845eae

Browse files
committed
Automatically generate Lua getters for all fields inside AST nodes
1 parent 7abdb80 commit 3845eae

File tree

10 files changed

+504
-377
lines changed

10 files changed

+504
-377
lines changed

Diff for: c2rust-refactor/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ fn main() {
3232
process_ast("mac_table", &out_dir.join("mac_table_gen.inc.rs"));
3333
process_ast("nt_match", &out_dir.join("nt_match_gen.inc.rs"));
3434
process_ast("ast_names", &out_dir.join("ast_names_gen.inc.rs"));
35+
process_ast("lua_ast_node", &out_dir.join("lua_ast_node_gen.inc.rs"));
3536

3637
process_ast(
3738
"rewrite_rewrite",

Diff for: c2rust-refactor/gen/ast.txt

+50-23
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct Mod { inner, #[mac_table_seq] items, #[rewrite_ignore] inline }
3131

3232

3333
#[rewrite_print_recover] #[rewrite_seq_item] #[rewrite_extra_strategies=item_header]
34-
#[nonterminal] #[extend_span]
34+
#[nonterminal] #[extend_span] #[fold_kind=ItemKind] #[boxed]
3535
struct Item { ident, #[match=ignore] attrs, id, kind, vis, span,
3636
#[match=ignore] #[rewrite_ignore] tokens }
3737
enum ItemKind {
@@ -61,9 +61,10 @@ enum UseTreeKind {
6161
Nested(nested),
6262
}
6363

64+
#[fold_kind=UseTreeKind] #[boxed=both]
6465
struct UseTree { kind, prefix, span }
6566

66-
#[nonterminal] #[extend_span]
67+
#[nonterminal] #[extend_span] #[fold_kind=TraitItemKind]
6768
struct TraitItem { id, ident, #[match=ignore] attrs, generics, kind, span,
6869
#[match=ignore] #[rewrite_ignore] tokens }
6970
enum TraitItemKind {
@@ -73,7 +74,7 @@ enum TraitItemKind {
7374
Macro(mac),
7475
}
7576

76-
#[nonterminal] #[extend_span]
77+
#[nonterminal] #[extend_span] #[fold_item=ImplItemKind]
7778
struct ImplItem { id, ident, vis, defaultness, #[match=ignore] attrs, generics, kind, span,
7879
#[match=ignore] #[rewrite_ignore] tokens }
7980
enum ImplItemKind {
@@ -102,6 +103,7 @@ struct MethodSig { header, decl }
102103

103104
struct ForeignMod { abi, #[mac_table_seq] items }
104105
#[rewrite_print_recover] #[rewrite_seq_item] #[nonterminal] #[extend_span]
106+
#[fold_kind=ForeignItemKind]
105107
struct ForeignItem { ident, #[match=ignore] attrs, kind, id, span, vis }
106108
enum ForeignItemKind {
107109
Fn(decl, generics),
@@ -112,7 +114,7 @@ enum ForeignItemKind {
112114

113115

114116
struct Generics { params, where_clause, span }
115-
#[extend_span]
117+
#[extend_span] #[fold_kind=GenericParamKind]
116118
struct GenericParam { id, ident, attrs, bounds, kind, is_placeholder }
117119
enum GenericParamKind {
118120
Lifetime,
@@ -145,6 +147,7 @@ enum CrateSugar {
145147
}
146148

147149
#[match=custom] #[rewrite_print_recover] #[mac_table_record] #[nonterminal]
150+
#[fold_kind=TyKind] #[boxed]
148151
struct Ty { id, kind, span }
149152
struct MutTy {ty, mutbl}
150153
enum TyKind {
@@ -167,12 +170,15 @@ enum TyKind {
167170
CVarArgs,
168171
}
169172

170-
flag TraitObjectSyntax;
171-
173+
enum TraitObjectSyntax {
174+
Dyn,
175+
None,
176+
}
172177

173178
flag LitIntType;
174179
flag FloatTy;
175180

181+
#[boxed]
176182
struct BareFnTy { unsafety, abi, decl, generic_params }
177183
struct Lifetime { id, ident }
178184
enum GenericBound {
@@ -182,6 +188,7 @@ enum GenericBound {
182188

183189
struct PolyTraitRef { trait_ref, span, bound_generic_params }
184190

191+
#[boxed]
185192
struct FnDecl { inputs, output }
186193
struct FnHeader { unsafety, asyncness, constness, abi }
187194
#[rewrite_print]
@@ -193,6 +200,7 @@ enum FunctionRetTy {
193200

194201

195202
#[match=custom] #[rewrite_print_recover] #[rewrite_seq_item] #[nonterminal]
203+
#[fold_kind=StmtKind]
196204
struct Stmt { id, kind, span }
197205
#[no_debug]
198206
enum StmtKind {
@@ -203,11 +211,12 @@ enum StmtKind {
203211
Mac(mac),
204212
}
205213

206-
#[extend_span]
214+
#[extend_span] #[boxed]
207215
struct Local { pat, ty, init, id, span, #[match=ignore] attrs }
208216

209217

210218
#[match=custom] #[rewrite_print_recover] #[extend_span] #[mac_table_record] #[nonterminal]
219+
#[fold_kind=ExprKind] #[boxed]
211220
struct Expr { id, kind, span, #[match=ignore] attrs }
212221
#[prec_contains_expr]
213222
enum ExprKind {
@@ -295,11 +304,12 @@ enum BinOpKind {
295304
struct Field { id, ident, expr, span, is_shorthand, attrs, is_placeholder }
296305
#[extend_span]
297306
struct Arm { id, attrs, pat, guard, body, span, is_placeholder }
298-
#[match=custom] #[rewrite_print_recover] #[nonterminal]
307+
#[match=custom] #[rewrite_print_recover] #[nonterminal] #[boxed]
299308
struct Block { #[mac_table_seq] stmts, id, rules, span }
300309

301310

302311
#[match=custom] #[mac_table_record] #[nonterminal]
312+
#[fold_kind=PatKind] #[boxed]
303313
struct Pat { id, kind, span }
304314
enum PatKind {
305315
Wild,
@@ -337,18 +347,28 @@ enum LitKind {
337347
Err(sym),
338348
}
339349

340-
#[no_kind]
350+
#[fold_kind=TokenLitKind]
341351
struct TokenLit { kind, symbol, suffix }
342352

343-
flag TokenLitKind;
344-
353+
enum TokenLitKind {
354+
Bool,
355+
Byte,
356+
Char,
357+
Integer,
358+
Float,
359+
Str,
360+
StrRaw(n),
361+
ByteStr,
362+
ByteStrRaw(n),
363+
Err,
364+
}
345365

346366
flag Defaultness;
347367
flag Constness;
348368
flag ImplPolarity;
349369
flag IsAuto;
350370
flag Unsafety;
351-
flag Abi;
371+
#[to_lua_custom] flag Abi;
352372
#[match=eq] flag Mutability;
353373
enum RangeEnd {
354374
Included(syntax),
@@ -379,9 +399,11 @@ struct AttrItem { path, tokens }
379399
flag AttrStyle;
380400

381401

382-
#[match=custom] #[nonterminal]
402+
#[match=custom] #[nonterminal] #[boxed=both]
383403
struct Path { span, segments }
384404
struct PathSegment { ident, id, args }
405+
406+
#[boxed]
385407
enum GenericArgs {
386408
AngleBracketed(abpd),
387409
Parenthesized(ppd),
@@ -408,11 +430,13 @@ flag MacStmtStyle;
408430
flag TokenStream;
409431
struct MacroDef { tokens, legacy }
410432

411-
433+
#[boxed]
412434
struct InlineAsm {
413435
asm, asm_str_style, outputs, inputs, clobbers,
414436
volatile, alignstack, dialect
415437
}
438+
439+
#[boxed]
416440
struct GlobalAsm { asm }
417441
struct InlineAsmOutput { constraint, expr, is_rw, is_indirect }
418442

@@ -429,22 +453,24 @@ struct AnonConst {
429453
value,
430454
}
431455

432-
#[match=custom] #[equiv_mode=custom] struct Ident { name, span }
433-
#[match=eq] flag Name;
456+
#[match=custom] #[equiv_mode=custom] #[to_lua_custom] struct Ident { name, span }
457+
#[match=eq] #[to_lua_custom] flag Name;
434458
#[equiv_mode=ignore] #[match=eq] flag SyntaxContext;
435459

436-
#[equiv_mode=ignore] #[rewrite_ignore]
460+
#[equiv_mode=ignore] #[rewrite_ignore] #[to_lua_custom]
437461
flag Span;
438462
#[equiv_mode=ignore] #[rewrite_ignore] #[list_node_ids=custom] #[mac_table_custom]
463+
#[to_lua_custom]
439464
flag NodeId;
440-
#[equiv_mode=ignore] #[rewrite_ignore]
465+
#[equiv_mode=ignore] #[rewrite_ignore] #[to_lua_custom]
441466
flag AttrId;
442467

443-
flag usize;
444-
#[match=eq] flag bool;
445-
#[match=eq] flag u128;
446-
#[match=eq] flag u8;
447-
#[match=eq] flag char;
468+
#[to_lua_custom] flag usize;
469+
#[match=eq] #[to_lua_custom] flag bool;
470+
#[match=eq] #[to_lua_custom] flag u128;
471+
#[match=eq] #[to_lua_custom] flag u16;
472+
#[match=eq] #[to_lua_custom] flag u8;
473+
#[match=eq] #[to_lua_custom] flag char;
448474

449475

450476
enum Nonterminal {
@@ -476,6 +502,7 @@ struct DelimSpan { open, close }
476502
flag DelimToken;
477503
flag Token;
478504

505+
#[fold_kind=MetaItemKind]
479506
struct MetaItem { path, kind, span }
480507
enum MetaItemKind {
481508
Word,

Diff for: c2rust-refactor/gen/ast_names.py

-20
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,6 @@ def do_ast_names_impl(d):
2424
yield ' }'
2525
yield '}'
2626

27-
def find_kind_field(s):
28-
if 'no_kind' in s.attrs:
29-
return None
30-
31-
marked_fields = []
32-
for f in s.fields:
33-
if 'kind' in f.attrs:
34-
marked_fields.append(f.name)
35-
if len(marked_fields) == 1:
36-
return marked_fields[0]
37-
elif len(marked_fields) > 1:
38-
raise ValueError('struct %s has %d fields marked #[kind] (expected 0 or 1)' %
39-
(s.name, len(marked_fields)))
40-
41-
for f in s.fields:
42-
if f.name == 'kind':
43-
return f.name
44-
45-
return None
46-
4727
@linewise
4828
def generate(decls):
4929
yield '// AUTOMATICALLY GENERATED - DO NOT EDIT'

Diff for: c2rust-refactor/gen/lua_ast_node.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
'''This module generates `LuaAstNode` impls for each AST node.
2+
3+
Attributes:
4+
5+
- `#[fold_kind=FooKind]`: Folds the kind enum with the given name
6+
into the current structure.
7+
8+
- `#[to_lua_custom]`: implements `ToLuaExt` and `UserData` separately.
9+
'''
10+
11+
from datetime import datetime
12+
from textwrap import indent, dedent
13+
14+
from ast import *
15+
from util import *
16+
17+
@linewise
18+
def do_enum_variants(s, match_pat):
19+
# Emit `children`
20+
yield ' methods.add_method("children", |_lua_ctx, this, ()| {'
21+
yield ' match %s {' % match_pat
22+
for v in s.variants:
23+
fpat = struct_pattern(v, '%s::%s' % (s.name, v.name))
24+
yield ' %s => Ok([' % fpat
25+
for f in v.fields:
26+
yield ' %s.clone().to_lua_ext(_lua_ctx)?,' % f.name
27+
yield ' ].iter().cloned().collect::<Vec<Value>>()),'
28+
yield ' }'
29+
yield ' });'
30+
31+
# Emit `nth_child`
32+
yield ' methods.add_method("nth_child", |_lua_ctx, this, idx: usize| {'
33+
yield ' match (%s, idx) {' % match_pat
34+
for v in s.variants:
35+
for idx, f in enumerate(v.fields):
36+
fpat = struct_pattern(v, '%s::%s' % (s.name, v.name))
37+
yield ' (%s, %d) => %s.clone().to_lua_ext(_lua_ctx),' % (fpat, idx, f.name)
38+
yield ' _ => Ok(Value::Nil)' # FIXME
39+
yield ' }'
40+
yield ' });'
41+
42+
@linewise
43+
def do_one_impl(s, kind_map, boxed):
44+
# This object is NOT thread-safe. Do not use an object of this class from a
45+
# thread that did not acquire it.
46+
type_name = 'P<%s>' % s.name if boxed else s.name
47+
yield 'unsafe impl Send for LuaAstNode<%s> {}' % type_name
48+
yield 'impl LuaAstNodeSafe for LuaAstNode<%s> {}' % type_name
49+
yield 'impl UserData for LuaAstNode<%s> {' % type_name
50+
yield ' #[allow(unused, non_shorthand_field_patterns)]'
51+
yield ' fn add_methods<\'lua, M: UserDataMethods<\'lua, Self>>(methods: &mut M) {'
52+
if isinstance(s, Struct):
53+
# FIXME: handle tuple struct
54+
kind_field = find_kind_field(s)
55+
for f in s.fields:
56+
yield ' methods.add_method("get_%s", |_lua_ctx, this, ()| {' % f.name
57+
if f.name == kind_field:
58+
yield ' Ok(this.borrow().%s.ast_name())' % f.name
59+
else:
60+
yield ' this.borrow().%s.clone().to_lua_ext(_lua_ctx)' % f.name
61+
yield ' });'
62+
63+
if 'fold_kind' in s.attrs:
64+
kind_name = s.attrs['fold_kind']
65+
kind_decl = kind_map[kind_name]
66+
yield do_enum_variants(kind_decl, '&this.borrow().%s' % kind_field)
67+
68+
elif isinstance(s, Enum):
69+
yield ' methods.add_method("get_kind", |_lua_ctx, this, ()| {'
70+
yield ' Ok(this.borrow().ast_name())'
71+
yield ' });'
72+
box_prefix = '&**' if boxed else '&*'
73+
yield do_enum_variants(s, box_prefix + 'this.borrow()')
74+
75+
yield ' <Self as AddMoreMethods>::add_more_methods(methods);'
76+
yield ' }'
77+
yield '}'
78+
79+
@linewise
80+
def do_impl(s, kind_map):
81+
if 'boxed' in s.attrs:
82+
yield do_one_impl(s, kind_map, True)
83+
if 'boxed' not in s.attrs or s.attrs['boxed'] == 'both':
84+
yield do_one_impl(s, kind_map, False)
85+
86+
@linewise
87+
def generate(decls):
88+
yield '// AUTOMATICALLY GENERATED - DO NOT EDIT'
89+
yield '// Produced %s by process_ast.py' % (datetime.now(),)
90+
yield ''
91+
92+
kind_map = {}
93+
for d in decls:
94+
if 'fold_kind' in d.attrs:
95+
kind_name = d.attrs['fold_kind']
96+
kind_map[kind_name] = None
97+
98+
for d in decls:
99+
if d.name in kind_map:
100+
kind_map[d.name] = d
101+
102+
for d in decls:
103+
if 'to_lua_custom' in d.attrs:
104+
continue
105+
106+
yield do_impl(d, kind_map)
107+

Diff for: c2rust-refactor/gen/process_ast.py

+3
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ def parse(s):
252252
elif mode == 'ast_names':
253253
import ast_names
254254
text = ast_names.generate(decls)
255+
elif mode == 'lua_ast_node':
256+
import lua_ast_node
257+
text = lua_ast_node.generate(decls)
255258
else:
256259
raise ValueError('unknown mode: %r' % mode)
257260

Diff for: c2rust-refactor/gen/util.py

+19
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,22 @@ def snake(s):
4949
s = s[1:]
5050
return s
5151

52+
def find_kind_field(s):
53+
if 'no_kind' in s.attrs:
54+
return None
55+
56+
marked_fields = []
57+
for f in s.fields:
58+
if 'kind' in f.attrs:
59+
marked_fields.append(f.name)
60+
if len(marked_fields) == 1:
61+
return marked_fields[0]
62+
elif len(marked_fields) > 1:
63+
raise ValueError('struct %s has %d fields marked #[kind] (expected 0 or 1)' %
64+
(s.name, len(marked_fields)))
65+
66+
for f in s.fields:
67+
if f.name == 'kind':
68+
return f.name
69+
70+
return None

0 commit comments

Comments
 (0)