1use std::cell::RefCell;
2use std::rc::Rc;
5
6use itertools::Itertools;
7
8use crate::ast::{Expr, Literal, RecordField};
9use crate::compiler::EvalStage;
10use crate::interner::{ExprNodeId, Symbol, ToSymbol, TypeNodeId};
11use crate::pattern::{Pattern, TypedPattern};
12use crate::plugin::{MacroFunType, MacroFunction, MacroInfo};
13use crate::types::Type;
14use crate::utils::environment::{Environment, LookupRes};
15
16type ClosureContent<T> = (Environment<(T, EvalStage)>, Vec<Symbol>, ExprNodeId);
17pub trait ValueTrait {
18 fn make_closure(e: ExprNodeId, names: Vec<Symbol>, env: Environment<(Self, EvalStage)>) -> Self
19 where
20 Self: std::marker::Sized;
21 fn get_as_closure(self) -> Option<ClosureContent<Self>>
22 where
23 Self: std::marker::Sized;
24 fn make_fixpoint(name: Symbol, e: ExprNodeId) -> Self;
25 fn get_as_fixpoint(self) -> Option<(Symbol, ExprNodeId)>
26 where
27 Self: std::marker::Sized;
28 fn get_as_external_fn(self) -> Option<Rc<RefCell<dyn Fn(&[(Self, TypeNodeId)]) -> Self>>>
29 where
30 Self: std::marker::Sized;
31}
32pub struct Context<V>
33where
34 V: Clone + ValueTrait + std::fmt::Debug,
35{
36 pub stage: EvalStage,
37 pub env: Environment<(V, EvalStage)>,
38}
39
40pub trait GeneralInterpreter {
42 type Value: Clone + ValueTrait + std::fmt::Debug;
43 fn interpret_expr(&mut self, ctx: &mut Context<Self::Value>, expr: ExprNodeId) -> Self::Value;
44 fn get_empty_val(&self) -> Self::Value;
45
46 fn deref_store(&self, val: &Self::Value) -> Self::Value {
48 val.clone()
49 }
50
51 fn wrap_store(&self, val: Self::Value) -> Self::Value {
53 val
54 }
55 fn eval_in_new_env(
56 &mut self,
57 binds: &[(Symbol, Self::Value)],
58 ctx: &mut Context<Self::Value>,
59 e: ExprNodeId,
60 ) -> Self::Value {
61 ctx.env.extend();
62 let binds = binds
63 .iter()
64 .map(|(name, val)| {
65 let v = val.clone();
66 (*name, (v, ctx.stage))
67 })
68 .collect_vec();
69 ctx.env.add_bind(binds.as_slice());
70 let res = self.eval(ctx, e);
71 ctx.env.to_outer();
72 res
73 }
74 fn eval_with_closure_env(
75 &mut self,
76 binds: &[(Symbol, (Self::Value, TypeNodeId))],
77 mut ctx: Context<Self::Value>,
78 e: ExprNodeId,
79 ) -> Self::Value {
80 let binds = binds
81 .iter()
82 .map(|(name, val)| {
83 let (v, _ty) = val.clone();
84 (*name, (v, ctx.stage))
85 })
86 .collect_vec();
87 ctx.env.extend();
88 ctx.env.add_bind(binds.as_slice());
89 let res = self.eval(&mut ctx, e);
90 ctx.env.to_outer();
91 res
92 }
93 fn eval(&mut self, ctx: &mut Context<Self::Value>, expr: ExprNodeId) -> Self::Value {
94 match expr.to_expr() {
95 Expr::Var(name) => match ctx.env.lookup_cls(&name) {
96 LookupRes::Local((val, bounded_stage)) if ctx.stage == *bounded_stage => {
97 self.deref_store(val)
98 }
99 LookupRes::UpValue(_, (val, bounded_stage)) if ctx.stage == *bounded_stage => {
100 self.deref_store(val)
101 }
102 LookupRes::Global((val, bounded_stage))
103 if ctx.stage == *bounded_stage || *bounded_stage == EvalStage::Persistent =>
104 {
105 self.deref_store(val)
106 }
107 LookupRes::None => panic!("Variable {name} not found"),
108 LookupRes::Local((_, bounded_stage))
109 | LookupRes::UpValue(_, (_, bounded_stage))
110 | LookupRes::Global((_, bounded_stage)) => {
111 panic!(
112 "Variable {name} found, but stage mismatch: expected {:?}, found {:?}",
113 ctx.stage, bounded_stage
114 )
115 }
116 },
117 Expr::Let(
118 TypedPattern {
119 pat: Pattern::Single(name),
120 ..
121 },
122 e,
123 body,
124 ) => {
125 let v = self.eval(ctx, e);
126 log::trace!("letting {} at stage: {}", name, ctx.stage);
127 let empty = self.get_empty_val();
128 let wrapped_v = self.wrap_store(v);
129 body.map_or(empty, |e| {
130 self.eval_in_new_env(&[(name, wrapped_v)], ctx, e)
131 })
132 }
133 Expr::Let(_, _, _) => {
134 panic!("Let with multiple patterns should be destructed before evaluation")
135 }
136 Expr::LetRec(typed_id, e, body) => {
137 let fixpoint = ValueTrait::make_fixpoint(typed_id.id, e);
138 log::trace!(
139 "Creating fixpoint for {}, stage: {}",
140 typed_id.id,
141 ctx.stage
142 );
143 let res = self.eval_in_new_env(&[(typed_id.id, fixpoint)], ctx, e);
144
145 let empty = self.get_empty_val();
146 body.map_or(empty, |e| {
147 self.eval_in_new_env(&[(typed_id.id, res)], ctx, e)
148 })
149 }
150 Expr::Lambda(names, _, body) => {
151 let names = names.iter().map(|name| name.id).collect_vec();
152 ValueTrait::make_closure(body, names, ctx.env.clone())
154 }
155 Expr::Apply(f, a) => {
156 let fv = self.eval(ctx, f);
157 let args = a
158 .clone()
159 .into_iter()
160 .map(|arg| {
161 (
162 self.eval(ctx, arg),
163 Type::Unknown.into_id_with_location(arg.to_location()),
164 )
165 })
166 .collect::<Vec<_>>();
167 if let Some(ext_fn) = fv.clone().get_as_external_fn() {
168 ext_fn.borrow()(args.as_slice())
169 } else if let Some((c_env, names, body)) = fv.clone().get_as_closure() {
170 log::trace!("entering closure app with names: {names:?}");
171 let binds = names.into_iter().zip(args).collect_vec();
172 let new_ctx = Context {
173 env: c_env,
174 stage: ctx.stage,
175 };
176 self.eval_with_closure_env(binds.as_slice(), new_ctx, body)
177 } else if let Some((_, e)) = fv.get_as_fixpoint() {
178 let new_app = Expr::Apply(e, a.clone()).into_id(expr.to_location());
179 self.eval(ctx, new_app)
180 } else {
181 panic!("apply to non-fuctional type")
182 }
183 }
184
185 _ => self.interpret_expr(ctx, expr),
186 }
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub enum ValueToExprError {
192 CodeToExpr,
193 ClosureToExpr,
194 FixpointToExpr,
195 ExternalFnToExpr,
196}
197trait MultiStageInterpreter {
198 type Value: Clone + ValueTrait + std::fmt::Debug + TryInto<ExprNodeId, Error = ValueToExprError>;
199}
200
201#[derive(Clone)]
202pub struct ExtFunction {
203 name: Symbol,
204 f: Rc<RefCell<dyn Fn(&[(Value, TypeNodeId)]) -> Value>>,
205}
206impl ExtFunction {
207 pub fn new(name: Symbol, f: impl Fn(&[(Value, TypeNodeId)]) -> Value + 'static) -> Self {
208 ExtFunction {
209 name,
210 f: Rc::new(RefCell::new(f)),
211 }
212 }
213}
214impl std::fmt::Debug for ExtFunction {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 write!(f, "External function: {}", self.name)
217 }
218}
219#[derive(Clone, Debug)]
221pub enum Value {
222 ErrorV(ExprNodeId),
223 Unit,
224 Number(f64),
225 String(Symbol),
226 Array(Vec<Value>),
227 Record(Vec<(Symbol, Value)>),
228 Tuple(Vec<Value>),
229 Closure(ExprNodeId, Vec<Symbol>, Environment<(Value, EvalStage)>),
230 Fixpoint(Symbol, ExprNodeId),
231 Code(ExprNodeId),
232 ExternalFn(ExtFunction),
233 Store(Rc<RefCell<Value>>),
234}
235impl From<&Box<dyn MacroFunction>> for Value {
236 fn from(macro_fn: &Box<dyn MacroFunction>) -> Self {
237 Value::ExternalFn(ExtFunction {
238 name: macro_fn.get_name(),
239 f: macro_fn.get_fn().clone(),
240 })
241 }
242}
243impl ValueTrait for Value {
244 fn make_closure(
245 e: ExprNodeId,
246 names: Vec<Symbol>,
247 env: Environment<(Self, EvalStage)>,
248 ) -> Self {
249 Value::Closure(e, names, env)
251 }
252
253 fn get_as_closure(self) -> Option<(Environment<(Self, EvalStage)>, Vec<Symbol>, ExprNodeId)> {
254 match self {
255 Value::Closure(e, names, env) => Some((env, names, e)),
256 _ => None,
257 }
258 }
259
260 fn make_fixpoint(name: Symbol, e: ExprNodeId) -> Self {
261 Value::Fixpoint(name, e)
263 }
264
265 fn get_as_fixpoint(self) -> Option<(Symbol, ExprNodeId)>
266 where
267 Self: std::marker::Sized,
268 {
269 match self {
270 Value::Fixpoint(name, e) => Some((name, e)),
271 _ => None,
272 }
273 }
274 fn get_as_external_fn(self) -> Option<Rc<RefCell<dyn Fn(&[(Self, TypeNodeId)]) -> Self>>> {
275 match self {
276 Value::ExternalFn(f) => Some(f.f.clone()),
277 _ => None,
278 }
279 }
280}
281
282impl TryInto<ExprNodeId> for Value {
283 type Error = ValueToExprError;
284
285 fn try_into(self) -> Result<ExprNodeId, Self::Error> {
286 match self {
287 Value::Number(e) => {
288 Ok(Expr::Literal(Literal::Float(e.to_string().to_symbol())).into_id_without_span())
289 }
290 Value::String(s) => Ok(Expr::Literal(Literal::String(s)).into_id_without_span()),
291 Value::Array(elements) => {
292 let elements = elements.into_iter().map(|v| v.try_into()).try_collect()?;
293 Ok(Expr::ArrayLiteral(elements).into_id_without_span())
294 }
295 Value::Record(fields) => {
296 let fields = fields
297 .into_iter()
298 .map(|(name, value)| {
299 value
300 .try_into()
301 .map(|expr: ExprNodeId| RecordField { name, expr })
302 })
303 .try_collect()?;
304 Ok(Expr::RecordLiteral(fields).into_id_without_span())
305 }
306 Value::Tuple(elements) => {
307 let elements = elements.into_iter().map(|e| e.try_into()).try_collect()?;
308 Ok(Expr::Tuple(elements).into_id_without_span())
309 }
310 Value::Closure(_, _, _) => {
311 Err(ValueToExprError::ClosureToExpr)
313 }
314 Value::Fixpoint(_, _) => {
315 Err(ValueToExprError::FixpointToExpr)
317 }
318 Value::Code(e) => Ok(e),
319 Value::ExternalFn(_) => {
320 Err(ValueToExprError::ExternalFnToExpr)
322 }
323 Value::Unit => Ok(Expr::Block(None).into_id_without_span()),
324 Value::ErrorV(e) => Ok(e),
325 Value::Store(store) => {
326 store.borrow().clone().try_into()
328 }
329 }
330 }
331}
332
333#[derive(Default)]
334pub struct StageInterpreter {}
335
336impl MultiStageInterpreter for StageInterpreter {
337 type Value = Value;
338}
339
340impl StageInterpreter {
341 fn eval_address(&mut self, ctx: &mut Context<Value>, expr: ExprNodeId) -> Rc<RefCell<Value>> {
344 match expr.to_expr() {
345 Expr::Var(name) => {
346 match ctx.env.lookup_cls(&name) {
348 LookupRes::Local((Value::Store(store), _))
349 | LookupRes::UpValue(_, (Value::Store(store), _))
350 | LookupRes::Global((Value::Store(store), _)) => store.clone(),
351 _ => panic!("Assignment target must be a Store-bound variable: {name}"),
352 }
353 }
354 Expr::FieldAccess(base, field) => {
355 let base_store = self.eval_address(ctx, base);
356 let base_val = base_store.borrow();
357 match &*base_val {
358 Value::Record(fields) => fields
359 .iter()
360 .filter_map(|(name, v)| match (name, v) {
361 (n, Value::Store(s)) if *n == field => Some(s.clone()),
362 _ => None,
363 })
364 .next()
365 .unwrap_or_else(|| panic!("Field {field} not found in record")),
366 _ => panic!("Field access on non-record type"),
367 }
368 }
369 Expr::ArrayAccess(base, idx) => {
370 let base_store = self.eval_address(ctx, base);
371 let idx_val = self.eval(ctx, idx);
372 let base_val = base_store.borrow();
373 match (&*base_val, idx_val) {
374 (Value::Array(elements), Value::Number(i)) => {
375 if let Some(Value::Store(store)) = elements.get(i as usize) {
376 store.clone()
377 } else {
378 log::error!("Array index {i} out of bounds or non-store was found");
379 Rc::new(RefCell::new(Value::Number(0.0)))
380 }
381 }
382 _ => panic!("Invalid value type detected. Possible bug in type checking."),
383 }
384 }
385 Expr::Proj(base, idx) => {
386 let base_store = self.eval_address(ctx, base);
387 let base_val = base_store.borrow();
388 match &*base_val {
389 Value::Tuple(elements) => {
390 if let Some(Value::Store(store)) = elements.get(idx as usize) {
391 store.clone()
392 } else {
393 panic!("Tuple index {idx} out of bounds or non-store was found");
394 }
395 }
396 _ => panic!("Projection on non-tuple type"),
397 }
398 }
399 _ => panic!("Invalid assignment target expression"),
400 }
401 }
402}
403
404impl GeneralInterpreter for StageInterpreter {
405 type Value = Value;
406
407 fn interpret_expr(&mut self, ctx: &mut Context<Value>, expr: ExprNodeId) -> Self::Value {
408 if ctx.stage != EvalStage::Stage(0) {
410 Value::Code(self.rebuild(ctx, expr))
411 } else {
412 match expr.to_expr() {
413 Expr::ArrayLiteral(ev) => {
414 let elements = ev.into_iter().map(|e| self.eval(ctx, e)).collect();
415 Value::Array(elements)
416 }
417 Expr::RecordLiteral(fields) => {
418 let evaluated_fields = fields
419 .into_iter()
420 .map(|RecordField { name, expr }| (name, self.eval(ctx, expr)))
421 .collect();
422 Value::Record(evaluated_fields)
423 }
424 Expr::Tuple(elements) => {
425 let evaluated_elements =
426 elements.into_iter().map(|e| self.eval(ctx, e)).collect();
427 Value::Tuple(evaluated_elements)
428 }
429 Expr::Proj(e, idx) => {
430 let evaluated_expr = self.eval(ctx, e);
431 match evaluated_expr {
432 Value::Tuple(elements) => {
433 if idx < 0 || idx as usize >= elements.len() {
434 panic!("Index out of bounds for tuple projection");
435 }
436 elements[idx as usize].clone()
437 }
438 _ => panic!("Projection can only be applied to tuples"),
439 }
440 }
441 Expr::ArrayAccess(e, i) => {
442 let evaluated_expr = self.eval(ctx, e);
443 let evaluated_index = self.eval(ctx, i);
444 match evaluated_expr {
445 Value::Array(elements) => {
446 if let Value::Number(idx) = evaluated_index {
447 let idx = idx as usize;
448 if idx < elements.len() {
449 elements[idx].clone()
450 } else {
451 panic!("Index out of bounds for array access");
452 }
453 } else {
454 panic!("Index must be a number for array access");
455 }
456 }
457 _ => panic!("Array access can only be applied to arrays"),
458 }
459 }
460 Expr::FieldAccess(e, name) => {
461 let evaluated_expr = self.eval(ctx, e);
462 match evaluated_expr {
463 Value::Record(fields) => fields
464 .into_iter()
465 .find(|(field_name, _)| field_name == &name)
466 .map_or_else(
467 || panic!("Field {name} not found in record"),
468 |(_, value)| value,
469 ),
470 _ => panic!("Field access can only be applied to records"),
471 }
472 }
473 Expr::Block(e) => e.map_or(Value::Unit, |eid| self.eval_in_new_env(&[], ctx, eid)),
474 Expr::Literal(Literal::Float(f)) => Value::Number(f.to_string().parse().unwrap()),
475 Expr::Literal(Literal::Int(i)) => Value::Number(i as f64),
476 Expr::Literal(Literal::String(s)) => Value::String(s),
477 Expr::Literal(Literal::SelfLit) => {
478 panic!("Self literal cannot be evaluated in macro expansion")
479 }
480 Expr::Literal(Literal::Now) => {
481 panic!("Now literal cannot be evaluated in macro expansion")
482 }
483 Expr::Literal(Literal::SampleRate) => {
484 panic!("Samplerate literal cannot be evaluated in macro expansion")
485 }
486 Expr::Error => Value::ErrorV(expr),
487 Expr::Feed(_, _) => {
488 panic!("Feed expression cannot be evaluated in macro expansion")
489 }
490 Expr::BinOp(_, _, _) => {
491 panic!("BinOp expression should be removed in the previous stage")
492 }
493 Expr::UniOp(_, _) => {
494 panic!("UniOp expression should be removed in the previous stage")
495 }
496 Expr::If(cond, then, else_opt) => {
497 let cond_val = self.eval(ctx, cond);
498 match cond_val {
499 Value::Number(n) if n > 0.0 => self.eval(ctx, then),
500 Value::Number(_) => else_opt.map_or(Value::Unit, |e| self.eval(ctx, e)),
501 _ => panic!("Condition must be a number for if expression"),
502 }
503 }
504 Expr::Then(e1, e2) => {
505 let _v1 = self.eval(ctx, e1);
506 e2.map_or(Value::Unit, |e| self.eval(ctx, e))
507 }
508 Expr::Assign(target, e) => {
509 let new_val = self.eval(ctx, e);
511
512 let store = self.eval_address(ctx, target);
514 *store.borrow_mut() = new_val;
515 Value::Unit
516 }
517 Expr::Escape(_e) => {
518 panic!("escape expression cannot be evaluated in stage 0")
519 }
520 Expr::Bracket(e) => {
521 ctx.stage = EvalStage::Stage(1); log::trace!("Bracketting expression, stage => {:?}", ctx.stage);
523
524 let res = Value::Code(self.rebuild(ctx, e));
525 ctx.stage = EvalStage::Stage(0); res
527 }
528 _ => self.eval(ctx, expr),
530 }
531 }
532 }
533
534 fn get_empty_val(&self) -> Self::Value {
535 Value::Unit
536 }
537
538 fn deref_store(&self, val: &Self::Value) -> Self::Value {
539 match val {
540 Value::Store(store) => store.borrow().clone(),
541 _ => val.clone(),
542 }
543 }
544
545 fn wrap_store(&self, val: Self::Value) -> Self::Value {
546 Value::Store(Rc::new(RefCell::new(val)))
547 }
548}
549
550impl StageInterpreter {
551 fn rebuild(&mut self, ctx: &mut Context<Value>, e: ExprNodeId) -> ExprNodeId {
552 match e.to_expr() {
553 Expr::Bracket(inner) => {
554 ctx.stage = ctx.stage.increment();
555 log::trace!("staging bracket expression, stage => {:?}", ctx.stage);
556 let res = self.rebuild(ctx, inner);
557 ctx.stage = ctx.stage.decrement();
558 res
559 }
560 Expr::Escape(inner) => {
561 ctx.stage = ctx.stage.decrement();
562 log::trace!("Unstaging escape expression, stage => {:?}", ctx.stage);
563
564 let v = self.eval(ctx, inner);
565 ctx.stage = ctx.stage.increment();
566 v.try_into()
567 .expect("Failed to convert escape expression to ExprNodeId")
568 }
569 Expr::Apply(f, a) => {
570 let f_val = self.rebuild(ctx, f);
571 let a_vals = a.into_iter().map(|arg| self.rebuild(ctx, arg)).collect();
572 Expr::Apply(f_val, a_vals).into_id(e.to_location())
573 }
574 Expr::Lambda(params, r_ty, body) => {
575 let body_val = self.rebuild(ctx, body);
576 Expr::Lambda(params, r_ty, body_val).into_id(e.to_location())
577 }
578 Expr::Let(id, value, body) => Expr::Let(
579 id,
580 self.rebuild(ctx, value),
581 body.map(|b| self.rebuild(ctx, b)),
582 )
583 .into_id(e.to_location()),
584 Expr::LetRec(id, value, body) => Expr::LetRec(
585 id,
586 self.rebuild(ctx, value),
587 body.map(|b| self.rebuild(ctx, b)),
588 )
589 .into_id(e.to_location()),
590 Expr::Feed(id, body) => {
591 Expr::Feed(id, self.rebuild(ctx, body)).into_id(e.to_location())
592 }
593 Expr::If(cond, then, else_opt) => Expr::If(
594 self.rebuild(ctx, cond),
595 self.rebuild(ctx, then),
596 else_opt.map(|e| self.rebuild(ctx, e)),
597 )
598 .into_id(e.to_location()),
599 Expr::Then(e1, e2) => {
600 Expr::Then(self.rebuild(ctx, e1), e2.map(|e| self.rebuild(ctx, e)))
601 .into_id(e.to_location())
602 }
603 Expr::Assign(target, value) => {
604 Expr::Assign(self.rebuild(ctx, target), self.rebuild(ctx, value))
605 .into_id(e.to_location())
606 }
607 Expr::ArrayLiteral(elements) => {
608 Expr::ArrayLiteral(elements.into_iter().map(|e| self.rebuild(ctx, e)).collect())
609 .into_id(e.to_location())
610 }
611 Expr::RecordLiteral(fields) => Expr::RecordLiteral(
612 fields
613 .into_iter()
614 .map(|RecordField { name, expr }| RecordField {
615 name,
616 expr: self.rebuild(ctx, expr),
617 })
618 .collect(),
619 )
620 .into_id(e.to_location()),
621 Expr::Tuple(elements) => {
622 Expr::Tuple(elements.into_iter().map(|e| self.rebuild(ctx, e)).collect())
623 .into_id(e.to_location())
624 }
625 Expr::Proj(e, idx) => Expr::Proj(self.rebuild(ctx, e), idx).into_id(e.to_location()),
626 Expr::ArrayAccess(e, i) => {
627 Expr::ArrayAccess(self.rebuild(ctx, e), self.rebuild(ctx, i))
628 .into_id(e.to_location())
629 }
630 Expr::FieldAccess(e, name) => {
631 Expr::FieldAccess(self.rebuild(ctx, e), name).into_id(e.to_location())
632 }
633 Expr::Block(b) => {
634 Expr::Block(b.map(|eid| self.rebuild(ctx, eid))).into_id(e.to_location())
635 }
636 _ => e,
637 }
638 }
639}
640
641pub fn create_default_interpreter(
642 extern_macros: &[Box<dyn MacroFunction>],
643) -> (StageInterpreter, Context<Value>) {
644 let mut env = Environment::new();
645
646 env.extend();
647 env.add_bind(
648 extern_macros
649 .iter()
650 .map(|m| {
651 (m.get_name(), (Value::from(m), EvalStage::Persistent)) })
653 .collect::<Vec<_>>()
654 .as_slice(),
655 );
656 let ctx = Context {
657 stage: EvalStage::Stage(0),
658 env,
659 };
660 (StageInterpreter::default(), ctx)
661}
662
663pub fn expand_macro(
666 expr: ExprNodeId,
667 top_type: TypeNodeId,
668 extern_macros: &[Box<dyn MacroFunction>],
669) -> ExprNodeId {
670 let (mut interpreter, mut ctx) = create_default_interpreter(extern_macros);
671 expand_macro_rec(expr, &mut ctx, &mut interpreter, top_type)
672}
673fn expand_macro_rec(
674 expr: ExprNodeId,
675 ctx: &mut Context<Value>,
676 interpreter: &mut StageInterpreter,
677 ty: TypeNodeId,
678) -> ExprNodeId {
679 if let Type::Code(t) = ty.to_type() {
680 let res = interpreter.eval(ctx, expr);
681 match res {
682 Value::Code(e) => {
683 ctx.stage = EvalStage::Stage(0);
684 expand_macro_rec(e, ctx, interpreter, t)
685 }
686 _ => panic!("macro expansion failed, possible typing error"),
687 }
688 } else {
689 expr
690 }
691}