egglog/ast/
remove_globals.rs1use crate::*;
9use crate::{core::ResolvedCall, typechecking::FuncType};
10use egglog_ast::generic_ast::{GenericAction, GenericExpr, GenericFact, GenericRule};
11
12struct GlobalRemover<'a> {
13 fresh: &'a mut SymbolGen,
14}
15
16pub(crate) fn remove_globals(
46 prog: Vec<ResolvedNCommand>,
47 fresh: &mut SymbolGen,
48) -> Vec<ResolvedNCommand> {
49 let mut remover = GlobalRemover { fresh };
50 prog.into_iter()
51 .flat_map(|cmd| remover.remove_globals_cmd(cmd))
52 .collect()
53}
54
55fn resolved_var_to_call(var: &ResolvedVar) -> ResolvedCall {
56 assert!(
57 var.is_global_ref,
58 "resolved_var_to_call called on non-global var"
59 );
60 ResolvedCall::Func(FuncType {
61 name: var.name.clone(),
62 subtype: FunctionSubtype::Custom,
63 input: vec![],
64 output: var.sort.clone(),
65 })
66}
67
68fn replace_global_vars(expr: ResolvedExpr) -> ResolvedExpr {
73 match expr.get_global_var() {
74 Some(resolved_var) => {
75 GenericExpr::Call(expr.span(), resolved_var_to_call(&resolved_var), vec![])
76 }
77 None => expr,
78 }
79}
80
81pub(crate) fn remove_globals_expr(expr: ResolvedExpr) -> ResolvedExpr {
82 expr.visit_exprs(&mut replace_global_vars)
83}
84
85fn remove_globals_action(action: ResolvedAction) -> ResolvedAction {
86 action.visit_exprs(&mut replace_global_vars)
87}
88
89impl GlobalRemover<'_> {
90 fn remove_globals_cmd(&mut self, cmd: ResolvedNCommand) -> Vec<ResolvedNCommand> {
91 match cmd {
92 GenericNCommand::CoreAction(action) => match action {
93 GenericAction::Let(span, name, expr) => {
94 let ty = expr.output_type();
95
96 let resolved_call = ResolvedCall::Func(FuncType {
97 name: name.name.clone(),
98 subtype: FunctionSubtype::Custom,
99 input: vec![],
100 output: ty.clone(),
101 });
102 let func_decl = ResolvedFunctionDecl {
103 name: name.name,
104 subtype: FunctionSubtype::Custom,
105 schema: Schema {
106 input: vec![],
107 output: ty.name().to_owned(),
108 },
109 resolved_schema: resolved_call.clone(),
110 merge: None,
111 cost: None,
112 unextractable: true,
113 internal_hidden: false,
114 internal_let: true,
115 span: span.clone(),
116 term_constructor: None,
117 };
118 vec![
119 GenericNCommand::Function(func_decl),
120 GenericNCommand::CoreAction(GenericAction::Set(
121 span,
122 resolved_call,
123 vec![],
124 remove_globals_expr(expr),
125 )),
126 ]
127 }
128 _ => vec![GenericNCommand::CoreAction(remove_globals_action(action))],
129 },
130 GenericNCommand::NormRule { rule } => {
131 let mut globals = HashMap::default();
134 rule.head.clone().visit_exprs(&mut |expr| {
135 if let Some(resolved_var) = expr.get_global_var() {
136 let new_name = self.fresh.fresh(&resolved_var.name);
137 globals.insert(
138 resolved_var.clone(),
139 GenericExpr::Var(
140 expr.span(),
141 ResolvedVar {
142 name: new_name,
143 sort: resolved_var.sort.clone(),
144 is_global_ref: false,
145 },
146 ),
147 );
148 }
149 expr
150 });
151 let new_facts: Vec<ResolvedFact> = globals
152 .iter()
153 .map(|(old, new)| {
154 GenericFact::Eq(
155 new.span(),
156 GenericExpr::Call(new.span(), resolved_var_to_call(old), vec![]),
157 new.clone(),
158 )
159 })
160 .collect();
161
162 let new_rule = GenericRule {
163 span: rule.span,
164 body: rule
166 .body
167 .iter()
168 .map(|fact| fact.clone().visit_exprs(&mut replace_global_vars))
169 .chain(new_facts)
170 .collect(),
171 head: rule.head.clone().visit_exprs(&mut |expr| {
173 if let Some(resolved_var) = expr.get_global_var() {
174 globals.get(&resolved_var).unwrap().clone()
175 } else {
176 expr
177 }
178 }),
179 name: rule.name.clone(),
180 ruleset: rule.ruleset.clone(),
181 eval_mode: rule.eval_mode,
182 no_decomp: rule.no_decomp,
183 include_subsumed: rule.include_subsumed,
184 };
185 vec![GenericNCommand::NormRule { rule: new_rule }]
186 }
187 GenericNCommand::Fail(span, cmd) => {
189 let mut removed = self.remove_globals_cmd(*cmd);
190 let last = removed.pop().unwrap();
191 let boxed_last = Box::new(last);
192 let new_command = GenericNCommand::Fail(span, boxed_last);
193 removed.push(new_command);
194 removed
195 }
196 _ => vec![cmd.visit_exprs(&mut replace_global_vars)],
197 }
198 }
199}