from datetime import datetime
from textwrap import indent, dedent
from ast import *
from util import *
@linewise
def exhaustiveness_check(se, target):
yield 'match %s {' % target
for v, path in variants_paths(se):
yield ' &%s => {},' % struct_pattern(v, path)
yield '}'
@linewise
def comparison(se, method, target1, target2):
yield 'match (%s, %s) {' % (target1, target2)
for v, path in variants_paths(se):
yield ' (&%s,' % struct_pattern(v, path, '1')
yield ' &%s) => {' % struct_pattern(v, path, '2')
for f in v.fields:
yield ' AstEquiv::%s(%s1, %s2) &&' % \
(method, f.name, f.name)
yield ' true'
yield ' }'
yield ' (_, _) => false,'
yield '}'
@linewise
def compare_impl(se):
yield '#[allow(unused, non_shorthand_field_patterns)]'
yield 'impl AstEquiv for %s {' % se.name
yield ' fn ast_equiv(&self, other: &Self) -> bool {'
yield ' // Exhaustiveness check'
yield indent(exhaustiveness_check(se, 'self'), ' ')
yield ''
yield ' // Comparison'
yield indent(comparison(se, 'ast_equiv', 'self', 'other'), ' ')
yield ' }'
yield ' fn unnamed_equiv(&self, other: &Self) -> bool {'
yield indent(comparison(se, 'unnamed_equiv', 'self', 'other'), ' ')
yield ' }'
yield '}'
@linewise
def eq_impl(d):
yield '#[allow(unused)]'
yield 'impl AstEquiv for %s {' % d.name
yield ' fn ast_equiv(&self, other: &Self) -> bool {'
yield ' self == other'
yield ' }'
yield ' fn unnamed_equiv(&self, other: &Self) -> bool {'
yield ' self == other'
yield ' }'
yield '}'
@linewise
def ignore_impl(d):
yield '#[allow(unused)]'
yield 'impl AstEquiv for %s {' % d.name
yield ' fn ast_equiv(&self, other: &Self) -> bool {'
yield ' true'
yield ' }'
yield ' fn unnamed_equiv(&self, other: &Self) -> bool {'
yield ' true'
yield ' }'
yield '}'
@linewise
def generate(decls):
yield '// AUTOMATICALLY GENERATED - DO NOT EDIT'
yield '// Produced %s by process_ast.py' % (datetime.now(),)
yield ''
for d in decls:
mode = d.attrs.get('equiv_mode')
if mode is None:
if isinstance(d, (Struct, Enum)):
mode = 'compare'
else:
mode = 'eq'
if mode == 'compare':
yield compare_impl(d)
elif mode == 'eq':
yield eq_impl(d)
elif mode == 'ignore':
yield ignore_impl(d)
elif mode == 'custom':
pass