starlark/src/syntax/payload_map.rs (259 lines of code) (raw):
/*
* Copyright 2018 The Starlark in Rust Authors.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! Map AST payload.
use gazebo::prelude::*;
use crate::{
codemap::Spanned,
syntax::ast::{
ArgumentP, AssignIdentP, AssignP, AstPayload, ClauseP, ExprP, ForClauseP, LoadP,
ParameterP, StmtP,
},
};
pub(crate) trait AstPayloadFunction<A: AstPayload, B: AstPayload> {
fn map_ident(&mut self, a: A::IdentPayload) -> B::IdentPayload;
fn map_ident_assign(&mut self, a: A::IdentAssignPayload) -> B::IdentAssignPayload;
fn map_def(&mut self, a: A::DefPayload) -> B::DefPayload;
}
impl<A: AstPayload> LoadP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> LoadP<B> {
let LoadP {
module,
args,
visibility,
} = self;
LoadP {
module,
args: args.into_map(|(local, their)| (local.into_map_payload(f), their)),
visibility,
}
}
}
impl<A: AstPayload> StmtP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> StmtP<B> {
match self {
StmtP::Break => StmtP::Break,
StmtP::Continue => StmtP::Continue,
StmtP::Pass => StmtP::Pass,
StmtP::Return(None) => StmtP::Return(None),
StmtP::Return(Some(e)) => StmtP::Return(Some(e.into_map_payload(f))),
StmtP::Expression(e) => StmtP::Expression(e.into_map_payload(f)),
StmtP::Assign(lhs, rhs) => {
StmtP::Assign(lhs.into_map_payload(f), box rhs.into_map_payload(f))
}
StmtP::AssignModify(lhs, op, rhs) => {
StmtP::AssignModify(lhs.into_map_payload(f), op, box rhs.into_map_payload(f))
}
StmtP::Statements(stmts) => {
StmtP::Statements(stmts.into_map(|s| s.into_map_payload(f)))
}
StmtP::If(cond, then_block) => {
StmtP::If(cond.into_map_payload(f), box then_block.into_map_payload(f))
}
StmtP::IfElse(cond, box (then_block, else_block)) => StmtP::IfElse(
cond.into_map_payload(f),
box (
then_block.into_map_payload(f),
else_block.into_map_payload(f),
),
),
StmtP::For(assign, box (coll, body)) => StmtP::For(
assign.into_map_payload(f),
box (coll.into_map_payload(f), body.into_map_payload(f)),
),
StmtP::Def(name, params, ret, body, p) => StmtP::Def(
name.into_map_payload(f),
params.into_map(|p| p.into_map_payload(f)),
ret.map(|ret| box ret.into_map_payload(f)),
box body.into_map_payload(f),
f.map_def(p),
),
StmtP::Load(load) => StmtP::Load(load.into_map_payload(f)),
}
}
}
impl<A: AstPayload> ExprP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> ExprP<B> {
match self {
ExprP::Tuple(exprs) => ExprP::Tuple(exprs.into_map(|e| e.into_map_payload(f))),
ExprP::Dot(object, field) => ExprP::Dot(box object.into_map_payload(f), field),
ExprP::Call(ca, args) => ExprP::Call(
box ca.into_map_payload(f),
args.into_map(|a| a.into_map_payload(f)),
),
ExprP::ArrayIndirection(box (array, index)) => {
ExprP::ArrayIndirection(box (array.into_map_payload(f), index.into_map_payload(f)))
}
ExprP::Slice(x, a, b, c) => ExprP::Slice(
box x.into_map_payload(f),
a.map(|e| box e.into_map_payload(f)),
b.map(|e| box e.into_map_payload(f)),
c.map(|e| box e.into_map_payload(f)),
),
ExprP::Identifier(id, p) => ExprP::Identifier(id, f.map_ident(p)),
ExprP::Lambda(ps, body, p) => ExprP::Lambda(
ps.into_map(|p| p.into_map_payload(f)),
box body.into_map_payload(f),
f.map_def(p),
),
ExprP::Literal(l) => ExprP::Literal(l),
ExprP::Not(e) => ExprP::Not(box e.into_map_payload(f)),
ExprP::Minus(e) => ExprP::Minus(box e.into_map_payload(f)),
ExprP::Plus(e) => ExprP::Plus(box e.into_map_payload(f)),
ExprP::BitNot(e) => ExprP::BitNot(box e.into_map_payload(f)),
ExprP::Op(l, op, r) => {
ExprP::Op(box l.into_map_payload(f), op, box r.into_map_payload(f))
}
ExprP::If(box (a, b, c)) => ExprP::If(box (
a.into_map_payload(f),
b.into_map_payload(f),
c.into_map_payload(f),
)),
ExprP::List(es) => ExprP::List(es.into_map(|e| e.into_map_payload(f))),
ExprP::Dict(kvs) => {
ExprP::Dict(kvs.into_map(|(k, v)| (k.into_map_payload(f), v.into_map_payload(f))))
}
ExprP::ListComprehension(e, c0, cs) => ExprP::ListComprehension(
box e.into_map_payload(f),
box c0.into_map_payload(f),
cs.into_map(|c| c.into_map_payload(f)),
),
ExprP::DictComprehension(box (k, v), c0, cs) => ExprP::DictComprehension(
box (k.into_map_payload(f), v.into_map_payload(f)),
box c0.into_map_payload(f),
cs.into_map(|c| c.into_map_payload(f)),
),
}
}
}
impl<A: AstPayload> AssignP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> AssignP<B> {
match self {
AssignP::Tuple(args) => AssignP::Tuple(args.into_map(|a| a.into_map_payload(f))),
AssignP::ArrayIndirection(box (array, index)) => AssignP::ArrayIndirection(box (
array.into_map_payload(f),
index.into_map_payload(f),
)),
AssignP::Dot(object, field) => AssignP::Dot(box object.into_map_payload(f), field),
AssignP::Identifier(ident) => AssignP::Identifier(ident.into_map_payload(f)),
}
}
}
impl<A: AstPayload> AssignIdentP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> AssignIdentP<B> {
let AssignIdentP(s, p) = self;
AssignIdentP(s, f.map_ident_assign(p))
}
}
impl<A: AstPayload> ParameterP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> ParameterP<B> {
match self {
ParameterP::Normal(name, ty) => ParameterP::Normal(
name.into_map_payload(f),
ty.map(|defa| box defa.into_map_payload(f)),
),
ParameterP::WithDefaultValue(name, ty, defa) => ParameterP::WithDefaultValue(
name.into_map_payload(f),
ty.map(|defa| box defa.into_map_payload(f)),
box defa.into_map_payload(f),
),
ParameterP::NoArgs => ParameterP::NoArgs,
ParameterP::Args(name, ty) => ParameterP::Args(
name.into_map_payload(f),
ty.map(|defa| box defa.into_map_payload(f)),
),
ParameterP::KwArgs(name, ty) => ParameterP::KwArgs(
name.into_map_payload(f),
ty.map(|defa| box defa.into_map_payload(f)),
),
}
}
}
impl<A: AstPayload> ArgumentP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> ArgumentP<B> {
match self {
ArgumentP::Positional(e) => ArgumentP::Positional(e.into_map_payload(f)),
ArgumentP::Named(n, e) => ArgumentP::Named(n, e.into_map_payload(f)),
ArgumentP::Args(e) => ArgumentP::Args(e.into_map_payload(f)),
ArgumentP::KwArgs(e) => ArgumentP::KwArgs(e.into_map_payload(f)),
}
}
}
impl<A: AstPayload> ClauseP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> ClauseP<B> {
match self {
ClauseP::For(c) => ClauseP::For(c.into_map_payload(f)),
ClauseP::If(e) => ClauseP::If(e.into_map_payload(f)),
}
}
}
impl<A: AstPayload> ForClauseP<A> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> ForClauseP<B> {
ForClauseP {
var: self.var.into_map_payload(f),
over: self.over.into_map_payload(f),
}
}
}
macro_rules! ast_payload_map_stub {
($ast_type:ident) => {
impl<A: AstPayload> Spanned<$ast_type<A>> {
pub(crate) fn into_map_payload<B: AstPayload>(
self,
f: &mut impl AstPayloadFunction<A, B>,
) -> Spanned<$ast_type<B>> {
let Spanned { span, node } = self;
Spanned {
span,
node: node.into_map_payload(f),
}
}
}
};
}
ast_payload_map_stub!(ExprP);
ast_payload_map_stub!(AssignP);
ast_payload_map_stub!(AssignIdentP);
ast_payload_map_stub!(ParameterP);
ast_payload_map_stub!(ArgumentP);
ast_payload_map_stub!(LoadP);
ast_payload_map_stub!(StmtP);