1use std::collections::HashSet;
171
172use chandeliers_err::{self as err, EAccum, Transparent};
173use chandeliers_san::ast as tgt;
174use chandeliers_san::sp::{Sp, Span, WithSpan};
175
176use crate::ast as src;
177
178mod options;
179
180type This = tgt::options::usage::Parsing;
182
183pub trait Translate {
185 type Output;
187 type Ctx<'i>;
189 fn translate(
200 self,
201 eaccum: &mut EAccum,
202 run_uid: Transparent<usize>,
203 span: Span,
204 ctx: Self::Ctx<'_>,
205 ) -> Option<Self::Output>;
206}
207
208#[expect(
211 clippy::module_name_repetitions,
212 reason = "False positive: we want the name to match the `Translate` trait."
213)]
214pub trait SpanTranslate {
215 type Output;
217 type Ctx<'i>;
219 fn translate(
230 self,
231 eaccum: &mut EAccum,
232 run_uid: Transparent<usize>,
233 ctx: Self::Ctx<'_>,
234 ) -> Option<Sp<Self::Output>>;
235 fn flat_translate(
241 self,
242 eaccum: &mut EAccum,
243 run_uid: Transparent<usize>,
244 ctx: Self::Ctx<'_>,
245 ) -> Option<Self::Output>;
246}
247
248impl<T> SpanTranslate for Sp<T>
251where
252 T: Translate,
253{
254 type Ctx<'i> = T::Ctx<'i>;
255 type Output = T::Output;
256
257 fn translate(
258 self,
259 eaccum: &mut EAccum,
260 run_uid: Transparent<usize>,
261 ctx: Self::Ctx<'_>,
262 ) -> Option<Sp<Self::Output>> {
263 let res = self.t.translate(eaccum, run_uid, self.span, ctx)?;
264 Some(Sp {
265 t: res,
266 span: self.span,
267 })
268 }
269
270 fn flat_translate(
271 self,
272 eaccum: &mut EAccum,
273 run_uid: Transparent<usize>,
274 ctx: Self::Ctx<'_>,
275 ) -> Option<Self::Output> {
276 self.t.translate(eaccum, run_uid, self.span, ctx)
277 }
278}
279
280type DepTyAccum<'i> = &'i mut Vec<Sp<tgt::var::Local>>;
285
286impl<T> Translate for Box<T>
291where
292 T: Translate,
293{
294 type Ctx<'i> = T::Ctx<'i>;
295 type Output = T::Output;
296 fn translate(
297 self,
298 eaccum: &mut EAccum,
299 run_uid: Transparent<usize>,
300 span: Span,
301 ctx: Self::Ctx<'_>,
302 ) -> Option<Self::Output> {
303 (*self).translate(eaccum, run_uid, span, ctx)
304 }
305}
306
307impl Translate for src::Prog {
308 type Ctx<'i> = ();
309 type Output = tgt::decl::Prog;
310 fn translate(
311 self,
312 eaccum: &mut EAccum,
313 run_uid: Transparent<usize>,
314 _span: Span,
315 (): (),
316 ) -> Option<tgt::decl::Prog> {
317 let mut decls = Vec::new();
318 for decl in self.decls {
319 decls.push(decl.translate(eaccum, run_uid, options::Decl::default())?);
320 }
321 Some(tgt::decl::Prog { decls })
322 }
323}
324
325impl Translate for src::AttrDecl {
326 type Ctx<'i> = options::Decl;
327 type Output = tgt::decl::Decl;
328 fn translate(
329 self,
330 eaccum: &mut EAccum,
331 run_uid: Transparent<usize>,
332 _span: Span,
333 options: options::Decl,
334 ) -> Option<tgt::decl::Decl> {
335 match self {
336 Self::Tagged(attr, n) => {
337 let options = options.with(eaccum, attr.map(|_, x| *x))?;
338 n.flat_translate(eaccum, run_uid, options)
339 }
340 Self::Node(n) => n.flat_translate(eaccum, run_uid, options),
341 }
342 }
343}
344
345impl Translate for src::Decl {
346 type Ctx<'i> = options::Decl;
347 type Output = tgt::decl::Decl;
348 fn translate(
349 self,
350 eaccum: &mut EAccum,
351 run_uid: Transparent<usize>,
352 _span: Span,
353 options: options::Decl,
354 ) -> Option<tgt::decl::Decl> {
355 Some(match self {
356 Self::Const(c) => {
357 let options = options.for_const(eaccum)?;
358 tgt::decl::Decl::Const(c.translate(eaccum, run_uid, options)?)
359 }
360 Self::Node(n) => {
361 let options = options.for_node(eaccum)?;
362 tgt::decl::Decl::Node(n.translate(eaccum, run_uid, options)?)
363 }
364 Self::Extern(e) => e.flat_translate(eaccum, run_uid, options)?,
365 })
366 }
367}
368
369impl Translate for src::Extern {
370 type Ctx<'i> = options::Decl;
371 type Output = tgt::decl::Decl;
372 fn translate(
373 self,
374 eaccum: &mut EAccum,
375 run_uid: Transparent<usize>,
376 _span: Span,
377 options: options::Decl,
378 ) -> Option<tgt::decl::Decl> {
379 Some(match self {
380 Self::Const(c) => {
381 let options = options.for_ext_const(eaccum)?;
382 tgt::decl::Decl::ExtConst(c.translate(eaccum, run_uid, options)?)
383 }
384 Self::Node(n) => {
385 let options = options.for_ext_node(eaccum)?;
386 tgt::decl::Decl::ExtNode(n.translate(eaccum, run_uid, options)?)
387 }
388 })
389 }
390}
391
392impl Translate for src::ExtConst {
393 type Ctx<'i> = tgt::options::ExtConst;
394 type Output = tgt::decl::ExtConst;
395 fn translate(
396 self,
397 eaccum: &mut EAccum,
398 run_uid: Transparent<usize>,
399 _span: Span,
400 options: tgt::options::ExtConst,
401 ) -> Option<Self::Output> {
402 let name = self.name.map(|span, name| tgt::var::Global {
403 repr: name.to_string().with_span(span),
404 run_uid,
405 });
406 let ty = self.ty.translate(eaccum, run_uid, &mut Vec::new())?;
407 Some(tgt::decl::ExtConst {
408 name,
409 ty: ty.t.inner,
410 options,
411 })
412 }
413}
414
415impl Translate for src::ExtNode {
416 type Ctx<'i> = tgt::options::ExtNode;
417 type Output = tgt::decl::ExtNode;
418 fn translate(
419 self,
420 eaccum: &mut EAccum,
421 run_uid: Transparent<usize>,
422 _span: Span,
423 options: tgt::options::ExtNode,
424 ) -> Option<tgt::decl::ExtNode> {
425 let name = self.name.map(|span, name| tgt::decl::NodeName {
426 repr: name.to_string().with_span(span),
427 run_uid,
428 });
429 let inputs = self.inputs.translate(eaccum, run_uid, &mut Vec::new())?;
430 let outputs = self.outputs.translate(eaccum, run_uid, &mut Vec::new())?;
431 Some(tgt::decl::ExtNode {
432 name,
433 inputs,
434 outputs,
435 options,
436 })
437 }
438}
439
440#[derive(Default)]
445struct ExprCtx {
446 blocks: Vec<tgt::decl::NodeInstance>,
448 stmts: Vec<Sp<tgt::stmt::Statement>>,
450 shadow_glob: HashSet<String>,
452 use_registers: bool,
454 registers: Vec<tgt::decl::RegisterInstance>,
457 flips: Vec<tgt::decl::FlipInstance>,
460}
461
462pub struct ExprCtxView<'i> {
466 blocks: &'i mut Vec<tgt::decl::NodeInstance>,
468 stmts: &'i mut Vec<Sp<tgt::stmt::Statement>>,
470 shadow_glob: &'i HashSet<String>,
472 depth: usize,
475 use_registers: bool,
477 registers: &'i mut Vec<tgt::decl::RegisterInstance>,
479 flips: &'i mut Vec<tgt::decl::FlipInstance>,
481}
482
483impl ExprCtx {
484 fn view(&mut self) -> ExprCtxView<'_> {
486 ExprCtxView {
487 blocks: &mut self.blocks,
488 stmts: &mut self.stmts,
489 shadow_glob: &self.shadow_glob,
490 depth: 0,
491 use_registers: self.use_registers,
492 registers: &mut self.registers,
493 flips: &mut self.flips,
494 }
495 }
496}
497
498impl ExprCtxView<'_> {
499 fn bump(self, n: usize) -> Self {
502 Self {
503 depth: self.depth + n,
504 ..self
505 }
506 }
507
508 fn incr(self) -> Self {
510 self.bump(1)
511 }
512}
513
514macro_rules! fork {
516 ($this:expr) => {
517 crate::translate::ExprCtxView {
518 blocks: &mut *$this.blocks,
519 stmts: &mut *$this.stmts,
520 shadow_glob: &*$this.shadow_glob,
521 registers: &mut *$this.registers,
522 flips: &mut *$this.flips,
523 depth: $this.depth,
524 use_registers: $this.use_registers,
525 }
526 };
527}
528
529impl Translate for src::Node {
530 type Ctx<'i> = tgt::options::Node;
531 type Output = tgt::decl::Node;
532 fn translate(
533 self,
534 eaccum: &mut EAccum,
535 run_uid: Transparent<usize>,
536 _span: Span,
537 options: tgt::options::Node,
538 ) -> Option<Self::Output> {
539 let name = self.name.map(|span, name| tgt::decl::NodeName {
540 repr: name.to_string().with_span(span),
541 run_uid,
542 });
543 let mut deptys = Vec::default();
544 let inputs = self.inputs.translate(eaccum, run_uid, &mut deptys)?;
545 let outputs = self.outputs.translate(eaccum, run_uid, &mut deptys)?;
546 let locals = self.locals.translate(eaccum, run_uid, &mut deptys)?;
547 let mut ectx = ExprCtx {
548 use_registers: *options.universal_pre.fetch::<This>(),
549 ..Default::default()
550 };
551 for shadows in &[&inputs, &outputs, &locals] {
552 for s in shadows.t.iter() {
553 ectx.shadow_glob.insert(s.t.name.t.repr.t.clone());
554 }
555 }
556
557 for def in self.defs {
558 def.translate(eaccum, run_uid, ectx.view())?;
559 }
560 let ExprCtx {
561 blocks,
562 stmts,
563 registers,
564 flips,
565 ..
566 } = ectx;
567 Some(tgt::decl::Node {
568 name,
569 options,
570 inputs,
571 outputs,
572 locals,
573 blocks,
574 deptys,
575 stmts,
576 registers,
577 flips,
578 })
579 }
580}
581
582impl Translate for src::Const {
583 type Ctx<'i> = tgt::options::Const;
584 type Output = tgt::decl::Const;
585 fn translate(
586 self,
587 eaccum: &mut EAccum,
588 run_uid: Transparent<usize>,
589 span: Span,
590 options: tgt::options::Const,
591 ) -> Option<tgt::decl::Const> {
592 let name = self.name.map(|span, name| tgt::var::Global {
593 repr: name.to_string().with_span(span),
594 run_uid,
595 });
596 let ty = self.ty.translate(eaccum, run_uid, ())?;
597 let mut ectx = ExprCtx::default();
598 let value = self.value.translate(eaccum, run_uid, ectx.view())?;
599 if !ectx.stmts.is_empty() || !ectx.blocks.is_empty() {
600 eaccum.error(err::NotConst {
601 site: span,
602 what: "Function calls are",
603 })?;
604 }
605 Some(tgt::decl::Const {
606 name,
607 options,
608 ty,
609 value,
610 })
611 }
612}
613
614impl Translate for src::ArgsTys {
615 type Ctx<'i> = DepTyAccum<'i>;
616 type Output = tgt::Tuple<Sp<tgt::decl::TyVar>>;
617 fn translate(
618 self,
619 eaccum: &mut EAccum,
620 run_uid: Transparent<usize>,
621 _span: Span,
622 ctx: Self::Ctx<'_>,
623 ) -> Option<tgt::Tuple<Sp<tgt::decl::TyVar>>> {
624 let mut vs = tgt::Tuple::default();
625 for item in self.items {
626 item.translate(eaccum, run_uid, (&mut vs, ctx))?;
627 }
628 Some(vs)
629 }
630}
631
632impl Translate for src::ArgsTy {
633 type Ctx<'i> = (&'i mut tgt::Tuple<Sp<tgt::decl::TyVar>>, DepTyAccum<'i>);
634 type Output = ();
635 fn translate(
636 self,
637 eaccum: &mut EAccum,
638 run_uid: Transparent<usize>,
639 _span: Span,
640 ctx: Self::Ctx<'_>,
641 ) -> Option<()> {
642 let ty = self.ty.translate(eaccum, run_uid, ctx.1)?;
643 self.args.translate(eaccum, run_uid, (ctx.0, ty))?;
644 Some(())
645 }
646}
647
648impl Translate for src::Decls {
649 type Ctx<'i> = (
650 &'i mut tgt::Tuple<Sp<tgt::decl::TyVar>>,
651 Sp<tgt::ty::Clocked<tgt::ty::Base>>,
652 );
653 type Output = ();
654 fn translate(
655 self,
656 _eaccum: &mut EAccum,
657 _run_uid: Transparent<usize>,
658 _span: Span,
659 (vars, ty): Self::Ctx<'_>,
660 ) -> Option<()> {
661 for id in self.ids {
662 vars.push(id.map(|span, id| {
663 tgt::decl::TyVar {
664 name: tgt::var::Local {
665 repr: id.to_string().with_span(span),
666 }
667 .with_span(span),
668 ty: ty.clone().map(|span, ty| {
669 tgt::ty::Stream {
670 ty: ty.with_span(span),
671 depth: tgt::past::Depth {
672 dt: 0,
675 }
676 .with_span(span),
677 }
678 }),
679 }
680 }));
681 }
682 Some(())
683 }
684}
685
686impl Translate for src::ty::Type {
687 type Ctx<'i> = DepTyAccum<'i>;
688 type Output = tgt::ty::Clocked<tgt::ty::Base>;
689 fn translate(
690 self,
691 eaccum: &mut EAccum,
692 run_uid: Transparent<usize>,
693 _span: Span,
694 ctx: Self::Ctx<'_>,
695 ) -> Option<Self::Output> {
696 let inner = self.base.translate(eaccum, run_uid, ())?;
697 let clk = self.clock.translate(eaccum, run_uid, ctx)?;
698 Some(tgt::ty::Clocked { inner, clk })
699 }
700}
701
702impl Translate for src::ty::Base {
703 type Ctx<'i> = ();
704 type Output = tgt::ty::Base;
705 fn translate(
706 self,
707 _eaccum: &mut EAccum,
708 _run_uid: Transparent<usize>,
709 _span: Span,
710 (): (),
711 ) -> Option<Self::Output> {
712 Some(match self {
713 Self::Int(_) => tgt::ty::Base::Int,
714 Self::Float(_) => tgt::ty::Base::Float,
715 Self::Bool(_) => tgt::ty::Base::Bool,
716 Self::Other(t) => tgt::ty::Base::Other(t.as_ref().map(|_, c| format!("{c}"))),
717 })
718 }
719}
720
721impl Translate for src::ty::Clock {
722 type Ctx<'i> = DepTyAccum<'i>;
723 type Output = tgt::ty::Clock;
724 fn translate(
725 self,
726 eaccum: &mut EAccum,
727 run_uid: Transparent<usize>,
728 _span: Span,
729 ctx: Self::Ctx<'_>,
730 ) -> Option<Self::Output> {
731 match self {
732 Self::When(w) => w.flat_translate(eaccum, run_uid, ctx),
733 Self::Whenot(w) => w.flat_translate(eaccum, run_uid, ctx),
734 Self::None => Some(tgt::ty::Clock::Implicit),
735 }
736 }
737}
738
739impl Translate for src::ty::When {
740 type Ctx<'i> = DepTyAccum<'i>;
741 type Output = tgt::ty::Clock;
742 fn translate(
743 self,
744 _eaccum: &mut EAccum,
745 _run_uid: Transparent<usize>,
746 _span: Span,
747 ctx: Self::Ctx<'_>,
748 ) -> Option<Self::Output> {
749 ctx.push(
750 tgt::var::Local {
751 repr: self.clock.as_ref().map(|_, c| format!("{c}")),
752 }
753 .with_span(self.clock.span),
754 );
755 Some(tgt::ty::Clock::Explicit {
756 activation: true,
757 id: self.clock.map(|_, c| format!("{c}")),
758 })
759 }
760}
761
762impl Translate for src::ty::Whenot {
763 type Ctx<'i> = DepTyAccum<'i>;
764 type Output = tgt::ty::Clock;
765 fn translate(
766 self,
767 _eaccum: &mut EAccum,
768 _run_uid: Transparent<usize>,
769 _span: Span,
770 ctx: Self::Ctx<'_>,
771 ) -> Option<Self::Output> {
772 ctx.push(
773 tgt::var::Local {
774 repr: self.clock.as_ref().map(|_, c| format!("{c}")),
775 }
776 .with_span(self.clock.span),
777 );
778 Some(tgt::ty::Clock::Explicit {
779 activation: false,
780 id: self.clock.map(|_, c| format!("{c}")),
781 })
782 }
783}
784
785impl Translate for src::OptionalVarsDecl {
786 type Ctx<'i> = DepTyAccum<'i>;
787 type Output = tgt::Tuple<Sp<tgt::decl::TyVar>>;
788 fn translate(
789 self,
790 eaccum: &mut EAccum,
791 run_uid: Transparent<usize>,
792 _span: Span,
793 ctx: Self::Ctx<'_>,
794 ) -> Option<Self::Output> {
795 match self {
796 Self::Decls(d) => d.flat_translate(eaccum, run_uid, ctx),
797 Self::None => Some(tgt::Tuple::default()),
798 }
799 }
800}
801
802impl Translate for src::VarsDecl {
803 type Ctx<'i> = DepTyAccum<'i>;
804 type Output = tgt::Tuple<Sp<tgt::decl::TyVar>>;
805 fn translate(
806 self,
807 eaccum: &mut EAccum,
808 run_uid: Transparent<usize>,
809 _span: Span,
810 ctx: Self::Ctx<'_>,
811 ) -> Option<Self::Output> {
812 self.decls.flat_translate(eaccum, run_uid, ctx)
813 }
814}
815
816impl Translate for src::Statement {
817 type Ctx<'i> = ExprCtxView<'i>;
818 type Output = ();
819 fn translate(
820 self,
821 eaccum: &mut EAccum,
822 run_uid: Transparent<usize>,
823 _span: Span,
824 ctx: Self::Ctx<'_>,
825 ) -> Option<()> {
826 match self {
827 Self::Assert(ass) => ass.flat_translate(eaccum, run_uid, ctx),
828 Self::Def(def) => def.flat_translate(eaccum, run_uid, ctx),
829 }
830 }
831}
832
833impl Translate for src::Assertion {
834 type Ctx<'i> = ExprCtxView<'i>;
835 type Output = ();
836 fn translate(
837 self,
838 eaccum: &mut EAccum,
839 run_uid: Transparent<usize>,
840 span: Span,
841 ctx: Self::Ctx<'_>,
842 ) -> Option<()> {
843 let e = self.expr.translate(eaccum, run_uid, fork!(ctx))?;
844 ctx.stmts
845 .push(tgt::stmt::Statement::Assert(e).with_span(span));
846 Some(())
847 }
848}
849
850impl Translate for src::Def {
851 type Ctx<'i> = ExprCtxView<'i>;
852 type Output = ();
853 fn translate(
854 self,
855 eaccum: &mut EAccum,
856 run_uid: Transparent<usize>,
857 span: Span,
858 ctx: Self::Ctx<'_>,
859 ) -> Option<()> {
860 let target = self.target.translate(eaccum, run_uid, ())?;
861 let source = self.source.translate(eaccum, run_uid, fork!(ctx))?;
862 ctx.stmts
863 .push(tgt::stmt::Statement::Let { target, source }.with_span(span));
864 Some(())
865 }
866}
867
868impl Translate for src::TargetExpr {
869 type Ctx<'i> = ();
870 type Output = tgt::stmt::VarTuple;
871 fn translate(
872 self,
873 eaccum: &mut EAccum,
874 run_uid: Transparent<usize>,
875 span: Span,
876 (): (),
877 ) -> Option<Self::Output> {
878 match self {
879 Self::Var(i) => Some(tgt::stmt::VarTuple::Single(
880 tgt::var::Local {
881 repr: i.map(|_, t| t.to_string()),
882 }
883 .with_span(span),
884 )),
885 Self::Tuple(ts) => ts.flat_translate(eaccum, run_uid, ()),
886 }
887 }
888}
889
890impl Translate for src::TargetExprTuple {
891 type Ctx<'i> = ();
892 type Output = tgt::stmt::VarTuple;
893 fn translate(
894 self,
895 eaccum: &mut EAccum,
896 run_uid: Transparent<usize>,
897 span: Span,
898 (): (),
899 ) -> Option<Self::Output> {
900 let mut vs = tgt::Tuple::default();
901 let trail = self.fields.trailing_punct();
902 for t in self.fields {
903 vs.push(t.translate(eaccum, run_uid, ())?);
904 }
905 if vs.len() == 1 && !trail {
906 Some(
907 vs.into_iter()
908 .next()
909 .unwrap_or_else(|| chandeliers_err::malformed!())
910 .t,
911 )
912 } else {
913 Some(tgt::stmt::VarTuple::Multiple(vs.with_span(span)))
914 }
915 }
916}
917
918impl Translate for src::Expr {
919 type Ctx<'i> = ExprCtxView<'i>;
920 type Output = tgt::expr::Expr;
921 fn translate(
922 self,
923 eaccum: &mut EAccum,
924 run_uid: Transparent<usize>,
925 _span: Span,
926 ctx: Self::Ctx<'_>,
927 ) -> Option<tgt::expr::Expr> {
928 self.inner.flat_translate(eaccum, run_uid, ctx)
929 }
930}
931
932impl Translate for src::expr::If {
933 type Ctx<'i> = ExprCtxView<'i>;
934 type Output = tgt::expr::Expr;
935 fn translate(
936 self,
937 eaccum: &mut EAccum,
938 run_uid: Transparent<usize>,
939 _span: Span,
940 ctx: Self::Ctx<'_>,
941 ) -> Option<tgt::expr::Expr> {
942 let cond = self.cond.translate(eaccum, run_uid, fork!(ctx))?.boxed();
943 let yes = self.yes.translate(eaccum, run_uid, fork!(ctx))?.boxed();
944 let no = self.no.translate(eaccum, run_uid, ctx)?.boxed();
945 Some(tgt::expr::Expr::Ifx { cond, yes, no })
946 }
947}
948
949mod assoc {
967 use super::{Sp, WithSpan};
968 use chandeliers_err as err;
969 use std::fmt::Display;
970 use syn::punctuated::{Pair, Punctuated};
971
972 pub struct Descr<'i, Label, Convert, Compose> {
974 pub ctx: super::ExprCtxView<'i>,
976 pub label: Label,
979 pub convert: Convert,
981 pub compose: Compose,
983 }
984
985 impl<'i, Label, Convert, Compose> Descr<'i, Label, Convert, Compose>
986 where
987 Label: Display,
988 {
989 pub fn left_associative<Elem, Punct, Accum, Item>(
993 &mut self,
994 elems: Punctuated<Sp<Elem>, Punct>,
995 ) -> Option<Accum>
996 where
997 Convert: FnMut(Sp<Elem>, usize, super::ExprCtxView<'_>) -> Option<Sp<Item>>,
998 Compose: FnMut(Sp<Accum>, Punct, usize, Sp<Item>, super::ExprCtxView<'_>) -> Accum,
999 Accum: WithSpan<Output = Sp<Accum>>,
1000 Item: Into<Accum>,
1001 {
1002 chandeliers_err::consistency!(
1004 !elems.trailing_punct(),
1005 "Bug in the parser: {} should not accept trailing punctuation",
1006 self.label
1007 );
1008 let mut pairs = elems.into_pairs().enumerate();
1009 let mut oper: Punct;
1010 let mut accum: Sp<Accum>;
1011 let Some((depth, fst)) = pairs.next() else {
1015 chandeliers_err::abort!("Should not be able to get an empty `Pairs` from a `Punctuated::parse_nonempty`");
1016 };
1017 match fst {
1018 Pair::Punctuated(elem, punct) => {
1019 accum = (self.convert)(elem, depth, fork!(self.ctx))?.map(|_, i| i.into());
1020 oper = punct;
1021 }
1022 Pair::End(elem) => {
1023 return Some((self.convert)(elem, depth, fork!(self.ctx))?.t.into());
1024 }
1025 }
1026 for (depth, pair) in pairs {
1028 match pair {
1029 Pair::Punctuated(elem, punct) => {
1032 let expr = (self.convert)(elem, depth, fork!(self.ctx))?;
1033 let Some(span) = expr.span.join(accum.span) else {
1034 chandeliers_err::abort!(
1035 "Malformed span between {:?} and {:?}",
1036 expr.span,
1037 accum.span
1038 );
1039 };
1040 accum = (self.compose)(accum, oper, depth, expr, fork!(self.ctx))
1041 .with_span(span);
1042 oper = punct;
1043 }
1044 Pair::End(elem) => {
1046 let expr = (self.convert)(elem, depth, fork!(self.ctx))?;
1047 return Some((self.compose)(accum, oper, depth, expr, fork!(self.ctx)));
1048 }
1049 }
1050 }
1051 err::malformed!()
1052 }
1053
1054 pub fn right_associative<Elem, Punct, Accum, Item>(
1058 &mut self,
1059 elems: Punctuated<Sp<Elem>, Punct>,
1060 ) -> Option<Accum>
1061 where
1062 Accum: WithSpan<Output = Sp<Accum>>,
1063 Convert: FnMut(Sp<Elem>, usize, super::ExprCtxView<'_>) -> Option<Sp<Item>>,
1064 Compose: FnMut(Sp<Item>, Punct, usize, Sp<Accum>, super::ExprCtxView<'_>) -> Accum,
1065 Item: Into<Accum>,
1066 {
1067 chandeliers_err::consistency!(
1069 !elems.trailing_punct(),
1070 "Bug in the parser: {} should not accept trailing punctuation",
1071 self.label
1072 );
1073
1074 let mut pairs = elems.into_pairs().enumerate().rev();
1075 let mut accum: Sp<Accum>;
1076 let Some((depth, last)) = pairs.next() else {
1079 chandeliers_err::abort!("Should not be able to get an empty `Pairs` from a `Punctuated::parse_nonempty`");
1080 };
1081
1082 let Pair::End(elem) = last else {
1083 err::malformed!()
1084 };
1085 accum = (self.convert)(elem, depth, fork!(self.ctx))?.map(|_, i| i.into());
1086 for (depth, pair) in pairs {
1091 let Pair::Punctuated(elem, punct) = pair else {
1092 err::malformed!()
1093 };
1094 let expr = (self.convert)(elem, depth, fork!(self.ctx))?;
1095 let Some(span) = expr.span.join(accum.span) else {
1096 chandeliers_err::abort!(
1097 "Malformed span between {:?} and {:?}",
1098 expr.span,
1099 accum.span
1100 );
1101 };
1102 accum = (self.compose)(expr, punct, depth, accum, fork!(self.ctx)).with_span(span);
1103 }
1104 Some(accum.t)
1105 }
1106 }
1107}
1108
1109impl Translate for src::expr::Or {
1110 type Ctx<'i> = ExprCtxView<'i>;
1111 type Output = tgt::expr::Expr;
1112 fn translate(
1113 self,
1114 eaccum: &mut EAccum,
1115 run_uid: Transparent<usize>,
1116 _span: Span,
1117 ctx: Self::Ctx<'_>,
1118 ) -> Option<tgt::expr::Expr> {
1119 assoc::Descr {
1120 ctx,
1121 label: "OrExpr",
1122 convert: |elem: Sp<src::expr::And>, _depth, ctx: ExprCtxView| {
1123 elem.translate(eaccum, run_uid, fork!(ctx))
1124 },
1125 compose: |lhs: Sp<tgt::expr::Expr>,
1126 _op,
1127 _depth,
1128 rhs: Sp<tgt::expr::Expr>,
1129 _ctx: ExprCtxView| {
1130 tgt::expr::Expr::Bin {
1131 op: tgt::op::Bin::BitOr,
1132 lhs: lhs.boxed(),
1133 rhs: rhs.boxed(),
1134 }
1135 },
1136 }
1137 .left_associative(self.items)
1138 }
1139}
1140
1141impl Translate for src::expr::And {
1142 type Ctx<'i> = ExprCtxView<'i>;
1143 type Output = tgt::expr::Expr;
1144 fn translate(
1145 self,
1146 eaccum: &mut EAccum,
1147 run_uid: Transparent<usize>,
1148 _span: Span,
1149 ctx: Self::Ctx<'_>,
1150 ) -> Option<tgt::expr::Expr> {
1151 assoc::Descr {
1152 ctx,
1153 label: "AndExpr",
1154 convert: |elem: Sp<src::expr::Cmp>, _depth, ctx: ExprCtxView| {
1155 elem.translate(eaccum, run_uid, fork!(ctx))
1156 },
1157 compose: |lhs: Sp<tgt::expr::Expr>,
1158 _op,
1159 _depth,
1160 rhs: Sp<tgt::expr::Expr>,
1161 _ctx: ExprCtxView| {
1162 tgt::expr::Expr::Bin {
1163 op: tgt::op::Bin::BitAnd,
1164 lhs: lhs.boxed(),
1165 rhs: rhs.boxed(),
1166 }
1167 },
1168 }
1169 .left_associative(self.items)
1170 }
1171}
1172
1173impl Translate for src::expr::Not {
1174 type Ctx<'i> = ExprCtxView<'i>;
1175 type Output = tgt::expr::Expr;
1176 fn translate(
1177 self,
1178 eaccum: &mut EAccum,
1179 run_uid: Transparent<usize>,
1180 _span: Span,
1181 ctx: Self::Ctx<'_>,
1182 ) -> Option<tgt::expr::Expr> {
1183 let inner = self.inner.translate(eaccum, run_uid, ctx)?.boxed();
1184 Some(tgt::expr::Expr::Un {
1185 op: tgt::op::Un::Not,
1186 inner,
1187 })
1188 }
1189}
1190
1191impl Translate for src::expr::Cmp {
1192 type Ctx<'i> = ExprCtxView<'i>;
1193 type Output = tgt::expr::Expr;
1194 fn translate(
1195 self,
1196 eaccum: &mut EAccum,
1197 run_uid: Transparent<usize>,
1198 span: Span,
1199 ctx: Self::Ctx<'_>,
1200 ) -> Option<tgt::expr::Expr> {
1201 use syn::punctuated::Pair;
1202 chandeliers_err::consistency!(
1203 !self.items.trailing_punct(),
1204 "Bug in the parser: Comparisons should not accept trailing punctuation",
1205 );
1206 let mut it = self.items.into_pairs();
1207 let Some(first) = it.next() else {
1209 err::abort!("Bug in the parser: comparison should have at least one member")
1210 };
1211 let Some(second) = it.next() else {
1212 let Pair::End(first) = first else {
1216 err::malformed!()
1217 };
1218 return first.flat_translate(eaccum, run_uid, ctx);
1219 };
1220 let Pair::Punctuated(lhs, op) = first else {
1221 err::malformed!()
1222 };
1223 let lhs = lhs.translate(eaccum, run_uid, fork!(ctx))?.boxed();
1224 let op = op.translate(eaccum, run_uid, span, ())?;
1225 if let Some(third) = it.next() {
1227 let Pair::Punctuated(second, oper2) = second else {
1230 err::malformed!()
1231 };
1232 let second = second.translate(eaccum, run_uid, fork!(ctx))?;
1233 let oper2 = oper2.translate(eaccum, run_uid, span, ())?;
1234 let third = match third {
1235 Pair::Punctuated(third, _) | Pair::End(third) => third,
1236 };
1237 let third = third.translate(eaccum, run_uid, fork!(ctx))?;
1238 return eaccum.error(err::CmpNotAssociative {
1239 site: span,
1240 first: lhs,
1241 oper1: op,
1242 oper2,
1243 second,
1244 third,
1245 });
1246 }
1247 let Pair::End(rhs) = second else {
1248 err::malformed!()
1249 };
1250 let rhs = rhs.translate(eaccum, run_uid, ctx)?.boxed();
1251 Some(tgt::expr::Expr::Cmp { op, lhs, rhs })
1252 }
1253}
1254
1255impl Translate for src::op::Cmp {
1256 type Ctx<'i> = ();
1257 type Output = tgt::op::Cmp;
1258 fn translate(
1259 self,
1260 _eaccum: &mut EAccum,
1261 _run_uid: Transparent<usize>,
1262 _span: Span,
1263 (): (),
1264 ) -> Option<Self::Output> {
1265 Some(match self {
1266 Self::Le(_) => tgt::op::Cmp::Le,
1267 Self::Lt(_) => tgt::op::Cmp::Lt,
1268 Self::Ge(_) => tgt::op::Cmp::Ge,
1269 Self::Gt(_) => tgt::op::Cmp::Gt,
1270 Self::Eq(_) => tgt::op::Cmp::Eq,
1271 Self::Ne(_) => tgt::op::Cmp::Ne,
1272 })
1273 }
1274}
1275
1276impl Translate for src::expr::Fby {
1277 type Ctx<'i> = ExprCtxView<'i>;
1278 type Output = tgt::expr::Expr;
1279 fn translate(
1280 self,
1281 eaccum: &mut EAccum,
1282 run_uid: Transparent<usize>,
1283 span: Span,
1284 ctx: Self::Ctx<'_>,
1285 ) -> Option<tgt::expr::Expr> {
1286 if ctx.use_registers {
1287 assoc::Descr {
1288 ctx,
1289 label: "FbyExpr",
1290 convert: |elem: Sp<src::expr::Then>, _depth, ctx: ExprCtxView| {
1291 elem.translate(eaccum, run_uid, fork!(ctx) )
1292 },
1293 compose: |before: Sp<tgt::expr::Expr>,
1294 _op,
1295 _depth,
1296 after: Sp<tgt::expr::Expr>,
1297 ctx: ExprCtxView| {
1298 let id: Sp<tgt::var::Register> = tgt::var::Register {
1299 id: ctx.registers.len().with_span(span),
1300 }
1301 .with_span(span);
1302 ctx.registers
1303 .push(tgt::decl::RegisterInstance { id, typ: None });
1304 ctx.stmts.push(
1305 tgt::stmt::Statement::UpdateRegister {
1306 id,
1307 val: after.clone(),
1308 }
1309 .with_span(span),
1310 );
1311 ctx.stmts.push(
1312 tgt::stmt::Statement::InitRegister {
1313 id,
1314 val: Some(before.clone()),
1315 clk: None,
1316 }
1317 .with_span(span),
1318 );
1319
1320 tgt::expr::Expr::FetchRegister {
1321 id,
1322 dummy_init: Some(before.boxed()),
1323 dummy_followed_by: after.boxed(),
1324 }
1325 },
1326 }
1327 .right_associative(self.items)
1328 } else {
1329 assoc::Descr {
1330 ctx,
1331 label: "FbyExpr",
1332 convert: |elem: Sp<src::expr::Then>, depth, ctx: ExprCtxView| {
1333 elem.translate(eaccum, run_uid, fork!(ctx).bump(depth) )
1334 },
1335 compose: |before: Sp<tgt::expr::Expr>,
1336 _op,
1337 depth,
1338 after: Sp<tgt::expr::Expr>,
1339 ctx: ExprCtxView<'_>| {
1340 tgt::expr::Expr::Later {
1341 delay: tgt::past::Depth {
1342 dt: ctx.depth + depth, }
1344 .with_span(
1345 before.span.join(after.span).unwrap_or_else(|| {
1346 err::abort!("Malformed span between {before:?} and {after:?}")
1347 }),
1348 ),
1349 before: before.boxed(),
1350 after: after.boxed(),
1351 }
1352 },
1353 }
1354 .right_associative(self.items)
1355 }
1356 }
1357}
1358
1359impl Translate for src::expr::Pre {
1360 type Ctx<'i> = ExprCtxView<'i>;
1361 type Output = tgt::expr::Expr;
1362 fn translate(
1363 self,
1364 eaccum: &mut EAccum,
1365 run_uid: Transparent<usize>,
1366 span: Span,
1367 ctx: Self::Ctx<'_>,
1368 ) -> Option<tgt::expr::Expr> {
1369 if ctx.use_registers {
1370 let id = tgt::var::Register {
1371 id: ctx.registers.len().with_span(span),
1372 }
1373 .with_span(span);
1374 ctx.registers
1375 .push(tgt::decl::RegisterInstance { id, typ: None });
1376 let inner = self.inner.translate(eaccum, run_uid, fork!(ctx))?;
1379 ctx.stmts.push(
1380 tgt::stmt::Statement::UpdateRegister {
1381 id,
1382 val: inner.clone(),
1383 }
1384 .with_span(span),
1385 );
1386 ctx.stmts.push(
1387 tgt::stmt::Statement::InitRegister {
1388 id,
1389 val: None,
1390 clk: None,
1391 }
1392 .with_span(span),
1393 );
1394 Some(tgt::expr::Expr::FetchRegister {
1395 id,
1396 dummy_init: None,
1397 dummy_followed_by: inner.boxed(),
1398 })
1399 } else {
1400 Some(tgt::expr::Expr::DummyPre(
1401 self.inner.translate(eaccum, run_uid, ctx.incr())?.boxed(),
1402 ))
1403 }
1404 }
1405}
1406
1407impl Translate for src::expr::Then {
1408 type Ctx<'i> = ExprCtxView<'i>;
1409 type Output = tgt::expr::Expr;
1410 fn translate(
1411 self,
1412 eaccum: &mut EAccum,
1413 run_uid: Transparent<usize>,
1414 span: Span,
1415 ctx: Self::Ctx<'_>,
1416 ) -> Option<tgt::expr::Expr> {
1417 if ctx.use_registers {
1418 assoc::Descr {
1419 ctx,
1420 label: "ThenExpr",
1421 convert: |elem: Sp<src::expr::Add>, _depth, ctx: ExprCtxView| {
1422 elem.translate(eaccum, run_uid, fork!(ctx) )
1423 },
1424 compose: |before: Sp<tgt::expr::Expr>,
1425 _op,
1426 _depth,
1427 after: Sp<tgt::expr::Expr>,
1428 ctx: ExprCtxView| {
1429 let id: Sp<tgt::var::Flip> = tgt::var::Flip {
1430 id: ctx.flips.len().with_span(span),
1431 }
1432 .with_span(span);
1433 ctx.flips.push(tgt::decl::FlipInstance { id });
1434 tgt::expr::Expr::Flip {
1435 id,
1436 initial: before.boxed(),
1437 continued: after.boxed(),
1438 }
1439 },
1440 }
1441 .right_associative(self.items)
1442 } else {
1443 assoc::Descr {
1446 ctx,
1447 label: "ThenExpr",
1448 convert: |elem: Sp<src::expr::Add>, _depth, ctx: ExprCtxView| {
1449 elem.translate(eaccum, run_uid, fork!(ctx) )
1450 },
1451 compose: |before: Sp<tgt::expr::Expr>,
1452 _op,
1453 depth,
1454 after: Sp<tgt::expr::Expr>,
1455 ctx: ExprCtxView<'_>| {
1456 tgt::expr::Expr::Later {
1457 delay: tgt::past::Depth {
1458 dt: ctx.depth + depth,
1459 }
1460 .with_span(
1461 before.span.join(after.span).unwrap_or_else(|| {
1462 chandeliers_err::abort!(
1463 "Malformed span between {before:?} and {after:?}"
1464 )
1465 }),
1466 ),
1467 before: before.boxed(),
1468 after: after.boxed(),
1469 }
1470 },
1471 }
1472 .right_associative(self.items)
1473 }
1474 }
1475}
1476
1477impl Translate for src::expr::Add {
1478 type Ctx<'i> = ExprCtxView<'i>;
1479 type Output = tgt::expr::Expr;
1480 fn translate(
1481 self,
1482 eaccum: &mut EAccum,
1483 run_uid: Transparent<usize>,
1484 _span: Span,
1485 ctx: Self::Ctx<'_>,
1486 ) -> Option<tgt::expr::Expr> {
1487 assoc::Descr {
1490 ctx,
1491 label: "AddExpr",
1492 convert: |elem: Sp<src::expr::Mul>, _depth, ctx: ExprCtxView| {
1493 elem.translate(eaccum, run_uid, fork!(ctx))
1494 },
1495 compose: |lhs: Sp<tgt::expr::Expr>,
1496 op: src::op::Add,
1497 _depth,
1498 rhs: Sp<tgt::expr::Expr>,
1499 _ctx: ExprCtxView| {
1500 tgt::expr::Expr::Bin {
1501 op: op.translate(),
1502 lhs: lhs.boxed(),
1503 rhs: rhs.boxed(),
1504 }
1505 },
1506 }
1507 .left_associative(self.items)
1508 }
1509}
1510
1511impl src::op::Add {
1512 fn translate(self) -> tgt::op::Bin {
1514 match self {
1515 Self::Add(_) => tgt::op::Bin::Add,
1516 Self::Sub(_) => tgt::op::Bin::Sub,
1517 }
1518 }
1519}
1520
1521impl src::op::Mul {
1522 fn translate(self) -> tgt::op::Bin {
1524 match self {
1525 Self::Mul(_) => tgt::op::Bin::Mul,
1526 Self::Div(_) => tgt::op::Bin::Div,
1527 Self::Rem(_) => tgt::op::Bin::Rem,
1528 }
1529 }
1530}
1531
1532impl Translate for src::expr::Mul {
1533 type Ctx<'i> = ExprCtxView<'i>;
1534 type Output = tgt::expr::Expr;
1535 fn translate(
1536 self,
1537 eaccum: &mut EAccum,
1538 run_uid: Transparent<usize>,
1539 _span: Span,
1540 ctx: Self::Ctx<'_>,
1541 ) -> Option<tgt::expr::Expr> {
1542 assoc::Descr {
1543 ctx,
1544 label: "MulExpr",
1545 convert: |elem: Sp<src::expr::Clock>, _depth, ctx: ExprCtxView| {
1546 elem.translate(eaccum, run_uid, fork!(ctx))
1547 },
1548 compose: |lhs: Sp<tgt::expr::Expr>,
1549 op: src::op::Mul,
1550 _depth,
1551 rhs: Sp<tgt::expr::Expr>,
1552 _ctx: ExprCtxView| {
1553 tgt::expr::Expr::Bin {
1554 op: op.translate(),
1555 lhs: lhs.boxed(),
1556 rhs: rhs.boxed(),
1557 }
1558 },
1559 }
1560 .left_associative(self.items)
1561 }
1562}
1563
1564impl src::op::Clock {
1565 fn translate(self) -> tgt::op::Clock {
1567 match self {
1568 Self::When(_) => tgt::op::Clock::When,
1569 Self::Whenot(_) => tgt::op::Clock::Whenot,
1570 }
1571 }
1572}
1573
1574impl Translate for src::expr::Clock {
1575 type Ctx<'i> = ExprCtxView<'i>;
1576 type Output = tgt::expr::Expr;
1577 fn translate(
1578 self,
1579 eaccum: &mut EAccum,
1580 run_uid: Transparent<usize>,
1581 _span: Span,
1582 ctx: Self::Ctx<'_>,
1583 ) -> Option<tgt::expr::Expr> {
1584 assoc::Descr {
1585 ctx,
1586 label: "ClockExpr",
1587 convert: |elem: Sp<src::expr::Positive>, _depth, ctx: ExprCtxView| {
1588 elem.translate(eaccum, run_uid, fork!(ctx))
1589 },
1590 compose: |lhs: Sp<tgt::expr::Expr>,
1591 op: src::op::Clock,
1592 _depth,
1593 rhs: Sp<tgt::expr::Expr>,
1594 _ctx: ExprCtxView| {
1595 tgt::expr::Expr::Clock {
1596 op: op.translate(),
1597 inner: lhs.boxed(),
1598 activate: rhs.boxed(),
1599 }
1600 },
1601 }
1602 .left_associative(self.items)
1603 }
1604}
1605
1606impl Translate for src::expr::Neg {
1607 type Ctx<'i> = ExprCtxView<'i>;
1608 type Output = tgt::expr::Expr;
1609 fn translate(
1610 self,
1611 eaccum: &mut EAccum,
1612 run_uid: Transparent<usize>,
1613 _span: Span,
1614 ctx: Self::Ctx<'_>,
1615 ) -> Option<tgt::expr::Expr> {
1616 let inner = self.inner.translate(eaccum, run_uid, ctx)?.boxed();
1617 Some(tgt::expr::Expr::Un {
1618 op: tgt::op::Un::Neg,
1619 inner,
1620 })
1621 }
1622}
1623
1624impl Translate for src::expr::Paren {
1625 type Ctx<'i> = ExprCtxView<'i>;
1626 type Output = tgt::expr::Expr;
1627 fn translate(
1628 self,
1629 eaccum: &mut EAccum,
1630 run_uid: Transparent<usize>,
1631 span: Span,
1632 ctx: Self::Ctx<'_>,
1633 ) -> Option<tgt::expr::Expr> {
1634 let mut es = tgt::Tuple::default();
1635 let trail = self.inner.trailing_punct();
1636 for e in self.inner {
1637 es.push(e.translate(eaccum, run_uid, fork!(ctx))?);
1638 }
1639 if es.len() == 1 && !trail {
1640 Some(tgt::expr::Expr::DummyParen(
1641 es.into_iter()
1642 .next()
1643 .unwrap_or_else(|| err::malformed!())
1644 .boxed(),
1645 ))
1646 } else {
1647 Some(tgt::expr::Expr::Tuple(es.with_span(span)))
1648 }
1649 }
1650}
1651
1652impl Translate for src::expr::Call {
1653 type Ctx<'i> = ExprCtxView<'i>;
1654 type Output = tgt::expr::Expr;
1655 fn translate(
1656 self,
1657 eaccum: &mut EAccum,
1658 run_uid: Transparent<usize>,
1659 span: Span,
1660 ctx: Self::Ctx<'_>,
1661 ) -> Option<tgt::expr::Expr> {
1662 let args = self.args.translate(eaccum, run_uid, fork!(ctx))?;
1663 let repr = self.fun.map(|_, t| t.to_string());
1664 let id = tgt::var::Node {
1665 id: ctx.blocks.len().with_span(span),
1666 repr: repr.clone(),
1667 }
1668 .with_span(span);
1669 ctx.blocks.push(tgt::decl::NodeInstance {
1670 name: tgt::decl::NodeName { repr, run_uid }.with_span(span),
1671 generics: None,
1672 });
1673 Some(tgt::expr::Expr::Substep {
1674 delay: ctx.depth,
1675 id: id.clone(),
1676 args: args.boxed(),
1677 })
1678 }
1679}
1680
1681impl Translate for src::expr::Atomic {
1682 type Ctx<'i> = ExprCtxView<'i>;
1683 type Output = tgt::expr::Expr;
1684 fn translate(
1685 self,
1686 eaccum: &mut EAccum,
1687 run_uid: Transparent<usize>,
1688 _span: Span,
1689 ctx: Self::Ctx<'_>,
1690 ) -> Option<tgt::expr::Expr> {
1691 match self {
1692 Self::Lit(l) => l.flat_translate(eaccum, run_uid, ctx),
1693 Self::Var(v) => v.flat_translate(eaccum, run_uid, ctx),
1694 Self::Paren(p) => p.flat_translate(eaccum, run_uid, ctx),
1695 }
1696 }
1697}
1698
1699impl Translate for src::expr::Positive {
1700 type Ctx<'i> = ExprCtxView<'i>;
1701 type Output = tgt::expr::Expr;
1702 fn translate(
1703 self,
1704 eaccum: &mut EAccum,
1705 run_uid: Transparent<usize>,
1706 _span: Span,
1707 ctx: Self::Ctx<'_>,
1708 ) -> Option<tgt::expr::Expr> {
1709 match self {
1710 Self::If(i) => i.flat_translate(eaccum, run_uid, ctx),
1711 Self::Merge(m) => m.flat_translate(eaccum, run_uid, ctx),
1712 Self::Call(c) => c.flat_translate(eaccum, run_uid, ctx),
1713 Self::Pre(p) => p.flat_translate(eaccum, run_uid, ctx),
1714 Self::Neg(n) => n.flat_translate(eaccum, run_uid, ctx),
1715 Self::Not(n) => n.flat_translate(eaccum, run_uid, ctx),
1716 Self::Atomic(a) => a.flat_translate(eaccum, run_uid, ctx),
1717 }
1718 }
1719}
1720
1721impl Translate for src::expr::Merge {
1722 type Ctx<'i> = ExprCtxView<'i>;
1723 type Output = tgt::expr::Expr;
1724 fn translate(
1725 self,
1726 eaccum: &mut EAccum,
1727 run_uid: Transparent<usize>,
1728 _span: Span,
1729 ctx: Self::Ctx<'_>,
1730 ) -> Option<tgt::expr::Expr> {
1731 let switch = self.clk.translate(eaccum, run_uid, fork!(ctx))?.boxed();
1732 let on = self.on.translate(eaccum, run_uid, fork!(ctx))?.boxed();
1733 let off = self.off.translate(eaccum, run_uid, fork!(ctx))?.boxed();
1734 Some(tgt::expr::Expr::Merge { switch, on, off })
1735 }
1736}
1737
1738impl Translate for src::expr::Var {
1739 type Ctx<'i> = ExprCtxView<'i>;
1740 type Output = tgt::expr::Expr;
1741 fn translate(
1742 self,
1743 _eaccum: &mut EAccum,
1744 run_uid: Transparent<usize>,
1745 span: Span,
1746 ctx: Self::Ctx<'_>,
1747 ) -> Option<tgt::expr::Expr> {
1748 let repr = self.name.map(|_, t| t.to_string());
1749 if ctx.shadow_glob.contains(&repr.t) {
1750 Some(tgt::expr::Expr::Reference(
1751 tgt::var::Reference::Var(
1752 tgt::var::Past {
1753 var: tgt::var::Local { repr }.with_span(span),
1754 depth: tgt::past::Depth { dt: ctx.depth }.with_span(span),
1755 }
1756 .with_span(span),
1757 )
1758 .with_span(span),
1759 ))
1760 } else {
1761 Some(tgt::expr::Expr::Reference(
1762 tgt::var::Reference::Global(tgt::var::Global { repr, run_uid }.with_span(span))
1763 .with_span(span),
1764 ))
1765 }
1766 }
1767}
1768
1769impl Translate for src::expr::Lit {
1770 type Ctx<'i> = ExprCtxView<'i>;
1771 type Output = tgt::expr::Expr;
1772 fn translate(
1773 self,
1774 eaccum: &mut EAccum,
1775 _run_uid: Transparent<usize>,
1776 span: Span,
1777 _ctx: Self::Ctx<'_>,
1778 ) -> Option<tgt::expr::Expr> {
1779 use syn::Lit;
1780 let lit = match self.lit.t {
1781 Lit::Bool(b) => tgt::expr::Lit::Bool(b.value()),
1782 Lit::Int(i) => tgt::expr::Lit::Int(
1783 i.base10_parse()
1784 .unwrap_or_else(|e| err::abort!("Unable to parse {i} as an int: {e}")),
1785 ),
1786 Lit::Float(f) => tgt::expr::Lit::Float(
1787 f.base10_parse()
1788 .unwrap_or_else(|e| err::abort!("Unable to parse {f} as a float: {e}")),
1789 ),
1790 _ => eaccum.error(err::UnhandledLitType { site: span })?,
1791 };
1792 Some(tgt::expr::Expr::Lit(lit.with_span(span)))
1793 }
1794}