git.delta.rocks / jrsonnet / refs/heads / master

difftreelog

source

crates/jrsonnet-ir/src/visit.rs6.4 KiBsourcehistory
1use jrsonnet_interner::IStr;23#[cfg(feature = "exp-object-iteration")]4use crate::ForObjSpecData;5use crate::{6	ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, Expr, ExprParam,7	ExprParams, FieldMember, FieldName, ForSpecData, IfElse, IfSpecData, ImportKind, IndexPart,8	ObjBody, ObjComp, ObjMembers, Slice, SliceDesc, TrivialVal,9};1011pub trait Visitor: Sized {12	fn visit_expr(&mut self, e: &Expr) {13		visit_expr(self, e)14	}15	fn visit_import(&mut self, _as_expression: bool, _value: IStr) {}16}1718#[cfg(feature = "exp-destruct")]19pub fn visit_destruct_rest<V: Visitor>(_v: &mut V, destruct: &crate::DestructRest) {20	match destruct {21		crate::DestructRest::Keep(_name) => {}22		crate::DestructRest::Drop => {}23	}24}2526#[allow(unused_variables, reason = "used with exp-destruct")]27pub fn visit_destruct<V: Visitor>(v: &mut V, destruct: &Destruct) {28	match destruct {29		Destruct::Full(_istr) => {}30		#[cfg(feature = "exp-destruct")]31		Destruct::Skip => {}32		#[cfg(feature = "exp-destruct")]33		Destruct::Array { start, rest, end } => {34			for s in start {35				visit_destruct(v, s);36			}37			if let Some(rest) = rest {38				visit_destruct_rest(v, rest);39			}40			for s in end {41				visit_destruct(v, s);42			}43		}44		#[cfg(feature = "exp-destruct")]45		Destruct::Object { fields, rest } => {46			for (_name, into, default) in fields {47				if let Some(into) = into {48					visit_destruct(v, into);49				}50				if let Some(default) = default {51					v.visit_expr(default);52				}53				if let Some(rest) = rest {54					visit_destruct_rest(v, rest);55				}56			}57		}58	}59}6061pub fn visit_if_spec<V: Visitor>(v: &mut V, cond: &IfSpecData) {62	let IfSpecData { span: _, cond } = cond;63	v.visit_expr(cond);64}6566pub fn visit_comp_spec<V: Visitor>(v: &mut V, c: &CompSpec) {67	match c {68		CompSpec::IfSpec(cond) => visit_if_spec(v, cond),69		CompSpec::ForSpec(for_spec_data) => {70			let ForSpecData { destruct, over } = for_spec_data;71			visit_destruct(v, destruct);72			v.visit_expr(over);73		}74		#[cfg(feature = "exp-object-iteration")]75		CompSpec::ForObjSpec(for_obj_spec_data) => {76			let ForObjSpecData {77				key: _,78				visibility: _,79				value,80				over,81			} = for_obj_spec_data;82			visit_destruct(v, value);83			v.visit_expr(over);84		}85	}86}87pub fn visit_params<V: Visitor>(v: &mut V, par: &ExprParams) {88	let ExprParams {89		exprs,90		signature: _,91		binds_len: _,92	} = par;93	for par in &**exprs {94		let ExprParam { destruct, default } = &par;95		visit_destruct(v, destruct);96		if let Some(default) = default {97			v.visit_expr(default);98		}99	}100}101102pub fn visit_bind_spec<V: Visitor>(v: &mut V, bind: &BindSpec) {103	match bind {104		BindSpec::Field { into, value } => {105			visit_destruct(v, into);106			v.visit_expr(value);107		}108		BindSpec::Function {109			name: _,110			params,111			value,112		} => {113			visit_params(v, params);114			v.visit_expr(value);115		}116	}117}118119pub fn visit_field_member<V: Visitor>(v: &mut V, mem: &FieldMember) {120	let FieldMember {121		name,122		plus: _,123		params,124		visibility: _,125		value,126	} = mem;127	match &**name {128		FieldName::Fixed(_istr) => {}129		FieldName::Dyn(expr) => v.visit_expr(expr),130	}131	if let Some(params) = params {132		visit_params(v, params);133	}134	v.visit_expr(value);135}136137pub fn visit_obj_body<V: Visitor>(v: &mut V, obj_body: &ObjBody) {138	match obj_body {139		ObjBody::MemberList(obj_members) => {140			let ObjMembers {141				locals,142				asserts,143				fields,144			} = obj_members;145			for local in &**locals {146				visit_bind_spec(v, local);147			}148			for assert in &**asserts {149				visit_assert_stmt(v, assert);150			}151			for field in fields {152				visit_field_member(v, field);153			}154		}155		ObjBody::ObjComp(obj_comp) => {156			let ObjComp {157				locals,158				field,159				compspecs,160			} = obj_comp;161			for local in &**locals {162				visit_bind_spec(v, local);163			}164			visit_field_member(v, field);165			for compspec in compspecs {166				visit_comp_spec(v, compspec);167			}168		}169	}170}171172pub fn visit_assert_stmt<V: Visitor>(v: &mut V, ass: &AssertStmt) {173	let AssertStmt { assertion, message } = ass;174	v.visit_expr(assertion);175	if let Some(message) = message {176		v.visit_expr(message);177	}178}179pub fn visit_expr<V: Visitor>(v: &mut V, e: &Expr) {180	match e {181		Expr::Identity(_span, _identity_kind) => {}182		Expr::Trivial(_) => {}183		Expr::Var(_spanned) => {}184		Expr::Arr(exprs) => {185			for e in &**exprs {186				v.visit_expr(e);187			}188		}189		Expr::ArrComp(expr, comp_specs) => {190			v.visit_expr(expr);191			for ele in comp_specs {192				visit_comp_spec(v, ele);193			}194		}195		Expr::Obj(obj_body) => visit_obj_body(v, obj_body),196		Expr::ObjExtend(expr, obj_body) => {197			v.visit_expr(expr);198			visit_obj_body(v, obj_body);199		}200		Expr::UnaryOp(_unary_op_type, expr) => {201			v.visit_expr(expr);202		}203		Expr::BinaryOp(binary_op) => {204			let BinaryOp { lhs, op: _, rhs } = &**binary_op;205			v.visit_expr(lhs);206			v.visit_expr(rhs);207		}208		Expr::AssertExpr(assert_expr) => {209			let AssertExpr { assert, rest } = &**assert_expr;210			visit_assert_stmt(v, assert);211			v.visit_expr(rest);212		}213		Expr::LocalExpr(bind_specs, expr) => {214			for local in bind_specs {215				visit_bind_spec(v, local);216			}217			v.visit_expr(expr);218		}219		Expr::Import(kind, expr) => {220			v.visit_expr(expr);221222			if let Expr::Trivial(TrivialVal::Str(expr)) = &**expr {223				v.visit_import(matches!(**kind, ImportKind::Normal), expr.clone());224			}225		}226		Expr::ErrorStmt(_span, expr) => {227			v.visit_expr(expr);228		}229		Expr::Apply(expr, spanned, _) => {230			v.visit_expr(expr);231			let ArgsDesc {232				unnamed,233				names: _,234				values,235			} = &**spanned;236			for unnamed in unnamed {237				v.visit_expr(unnamed);238			}239			for named in values {240				v.visit_expr(named);241			}242		}243		Expr::Index { indexable, parts } => {244			v.visit_expr(indexable);245246			for part in parts {247				let IndexPart {248					span: _,249					value,250					#[cfg(feature = "exp-null-coaelse")]251						null_coaelse: _,252				} = part;253				v.visit_expr(value);254			}255		}256		Expr::Function(_span, expr_params, expr) => {257			visit_params(v, expr_params);258			v.visit_expr(expr);259		}260		Expr::IfElse(if_else) => {261			let IfElse {262				cond,263				cond_then,264				cond_else,265			} = &**if_else;266			visit_if_spec(v, cond);267			v.visit_expr(cond_then);268			if let Some(cond_else) = cond_else {269				v.visit_expr(cond_else);270			}271		}272		Expr::Slice(slice) => {273			let Slice { value, slice } = &**slice;274			v.visit_expr(value);275			let SliceDesc { start, end, step } = slice;276277			if let Some(start) = start {278				v.visit_expr(start);279			}280			if let Some(end) = end {281				v.visit_expr(end);282			}283			if let Some(step) = step {284				v.visit_expr(step);285			}286		}287	}288}