1pub use open_vaf;
10use open_vaf::ast::{UnaryOperator, VariableType};
11use open_vaf::cfg::{BasicBlockId, Terminator};
12use open_vaf::hir::{Block, DisciplineAccess};
13use open_vaf::ir::mir::RealExpression;
14use open_vaf::ir::*;
15use open_vaf::mir::ExpressionId;
16use open_vaf::mir::*;
17use open_vaf::ControlFlowGraph;
18use open_vaf::StringLiteral;
19use proc_macro2::{Ident, Literal, Span, TokenStream, TokenTree};
20use quote::*;
21
22pub struct RealNumberInterpolator(pub f64);
23impl ToTokens for RealNumberInterpolator {
24 fn to_tokens(&self, tokens: &mut TokenStream) {
25 match self.0 {
26 val if val.is_finite() => tokens.append(Literal::f64_suffixed(val)),
27 val if val == f64::INFINITY => quote!(f64::INFINITY).to_tokens(tokens),
28 val if val == f64::NEG_INFINITY => quote!(f64::NEG_INFINITY).to_tokens(tokens),
29 val if val.is_nan() => quote!(f64::NAN).to_tokens(tokens),
30 val => unreachable!(
31 "f64 can only be NAN, INFINITY, NEG_INFINITY or a finite number! {} didnt match any of these",
32 val
33 ),
34 }
35 }
36}
37
38pub struct ParameterTypeInterpolator<'lt>(pub &'lt ParameterType);
39impl<'lt> ToTokens for ParameterTypeInterpolator<'lt> {
40 fn to_tokens(&self, tokens: &mut TokenStream) {
41 match self.0 {
42 ParameterType::String { .. } => quote!(&str).to_tokens(tokens),
43 ParameterType::Real { .. } => quote!(f64).to_tokens(tokens),
44 ParameterType::Integer { .. } => quote!(i64).to_tokens(tokens),
45 }
46 }
47}
48
49pub struct CfgInterpolator<'lt, EI> {
50 pub mir: &'lt Mir,
51 pub cfg: &'lt ControlFlowGraph,
52 pub start: BasicBlockId,
53 pub end: Option<BasicBlockId>,
54 pub external_interpolator: &'lt EI,
55}
56impl<'lt, EI: TargetSpecificInterpolator> ToTokens for CfgInterpolator<'lt, EI> {
57 fn to_tokens(&self, tokens: &mut TokenStream) {
58 let mut current = self.start;
59 loop {
60 match self.end {
61 Some(end) if end == current => break,
62 _ => BasicBlockInterpolator {
63 mir: self.mir,
64 external_interpolator: self.external_interpolator,
65 block: current,
66 cfg: self.cfg,
67 }
68 .to_tokens(tokens),
69 }
70 match self.cfg.blocks[current].terminator {
71 Terminator::Goto(next) => current = next,
72 Terminator::End => break,
73 Terminator::Split {
74 condition,
75 true_block,
76 false_block,
77 merge,
78 } => {
79 let condition = IntegerExpressionInterpolator {
80 mir: self.mir,
81 expression: condition,
82 external_interpolator: self.external_interpolator,
83 };
84
85 if merge == current {
86 let mut body = TokenStream::new();
88 CfgInterpolator {
89 mir: self.mir,
90 start: true_block,
91 end: Some(merge),
92 cfg: self.cfg,
93 external_interpolator: self.external_interpolator,
94 }
95 .to_tokens(&mut body);
96
97 quote!(
98 while (#condition) != 0 {
99 #body
100 }
101 )
102 .to_tokens(tokens);
103
104 current = false_block;
105 } else if merge == true_block {
106 let mut body = TokenStream::new();
108 CfgInterpolator {
109 mir: self.mir,
110 start: false_block,
111 end: Some(merge),
112 cfg: self.cfg,
113 external_interpolator: self.external_interpolator,
114 }
115 .to_tokens(&mut body);
116
117 quote!(
119 if (#condition) == 0 {
120 #body
121 }
122 )
123 .to_tokens(tokens);
124
125 current = merge;
126 } else if merge == false_block {
127 let mut body = TokenStream::new();
129 CfgInterpolator {
130 mir: self.mir,
131 start: true_block,
132 end: Some(merge),
133 cfg: self.cfg,
134 external_interpolator: self.external_interpolator,
135 }
136 .to_tokens(&mut body);
137
138 quote!(
139 if (#condition) != 0 {
140 #body
141 }
142 )
143 .to_tokens(tokens);
144
145 current = merge;
146 } else {
147 let mut if_block = TokenStream::new();
149 let mut else_block = TokenStream::new();
150
151 CfgInterpolator {
152 mir: self.mir,
153 start: true_block,
154 end: Some(merge),
155 cfg: self.cfg,
156 external_interpolator: self.external_interpolator,
157 }
158 .to_tokens(&mut if_block);
159
160 CfgInterpolator {
161 mir: self.mir,
162 start: false_block,
163 end: Some(merge),
164 cfg: self.cfg,
165 external_interpolator: self.external_interpolator,
166 }
167 .to_tokens(&mut else_block);
168
169 quote!(
170 if (#condition) != 0 {
171 #if_block
172 } else {
173 #else_block
174 }
175 )
176 .to_tokens(tokens);
177 current = merge;
178 }
179 }
180 }
181 }
182 }
183}
184
185pub struct BasicBlockInterpolator<'lt, EI> {
186 pub mir: &'lt Mir,
187 pub cfg: &'lt ControlFlowGraph,
188 pub block: BasicBlockId,
189 pub external_interpolator: &'lt EI,
190}
191
192impl<'lt, EI: TargetSpecificInterpolator> ToTokens for BasicBlockInterpolator<'lt, EI> {
193 fn to_tokens(&self, tokens: &mut TokenStream) {
194 for stmt in self.cfg.blocks[self.block].statements.iter().copied() {
195 match self.mir[stmt] {
196 Statement::Assignment(_, variable, value) => {
197 let name = gen_variable_ident(variable);
198 match value {
199 ExpressionId::Real(value) => {
200 let value = RealExpressionInterpolator {
201 expression: value,
202 mir: self.mir,
203 external_interpolator: self.external_interpolator,
204 };
205 (quote! {#name = #value;}).to_tokens(tokens);
206 }
207
208 ExpressionId::Integer(value) => {
209 let value = IntegerExpressionInterpolator {
210 expression: value,
211 mir: self.mir,
212 external_interpolator: self.external_interpolator,
213 };
214 (quote! {#name = #value;}).to_tokens(tokens);
215 }
216 ExpressionId::String(_) => todo!("string expressions"),
217 }
218 }
219
220 Statement::Contribute(attr, access, branch, val) => self
221 .external_interpolator
222 .contribute_to_tokens(self.mir, tokens, attr, access, branch, val),
223 }
224 }
225 }
226}
227
228pub trait TargetSpecificInterpolator: Sized {
229 #[allow(unused_variables)]
230 fn temperature_to_tokens(&self, mir: &Mir, tokens: &mut TokenStream) {
231 tokens.append(Ident::new("temperature", Span::call_site()))
233 }
234
235 #[allow(unused_variables)]
236 fn vt_to_tokens(
237 &self,
238 mir: &Mir,
239 tokens: &mut TokenStream,
240 arg: Option<RealExpressionInterpolator<'_, Self>>,
241 ) {
242 if let Some(arg) = arg {
244 quote!(1.3806488e-23 * #arg / 1.602176565e-19).to_tokens(tokens)
245 } else {
246 quote!(1.3806488e-23 * temperature / 1.602176565e-19).to_tokens(tokens)
247 }
248 }
249
250 fn simparam_to_tokens(
251 &self,
252 mir: &Mir,
253 tokens: &mut TokenStream,
254 name: StringExpressionId,
255 default: Option<RealExpressionInterpolator<'_, Self>>,
256 );
257
258 fn simparam_str_to_tokens(&self, mir: &Mir, tokens: &mut TokenStream, name: StringExpressionId);
259
260 fn param_given_to_tokens(&self, mir: &Mir, tokens: &mut TokenStream, param: ParameterId);
261
262 fn port_connected_to_tokens(&self, mir: &Mir, tokens: &mut TokenStream, port: PortId);
263
264 #[allow(unused_variables)]
265 fn limexp_to_tokens(
266 &self,
267 mir: &Mir,
268 tokens: &mut TokenStream,
269 arg: RealExpressionInterpolator<'_, Self>,
270 ) {
271 quote!(#arg.exp()).to_tokens(tokens)
273 }
274 fn noise_to_tokens(
275 &self,
276 mir: &Mir,
277 tokens: &mut TokenStream,
278 noise_source: NoiseSource<RealExpressionId, ()>,
279 source: Option<StringLiteral>,
280 );
281
282 fn contribute_to_tokens(
283 &self,
284 mir: &Mir,
285 tokens: &mut TokenStream,
286 attr: Attributes,
287 access: DisciplineAccess,
288 branch: BranchId,
289 val: RealExpressionId,
290 );
291}
292
293pub struct RealBuiltInFunctionCallInterpolator1p<'lt, EI> {
294 pub mir: &'lt Mir,
295 pub call: BuiltInFunctionCall1p,
296 pub arg: RealExpressionId,
297 pub external_interpolator: &'lt EI,
298}
299
300impl<'lt, EI: TargetSpecificInterpolator> ToTokens
301 for RealBuiltInFunctionCallInterpolator1p<'lt, EI>
302{
303 fn to_tokens(&self, tokens: &mut TokenStream) {
304 let arg = RealExpressionInterpolator {
305 mir: self.mir,
306 external_interpolator: self.external_interpolator,
307 expression: self.arg,
308 };
309 match self.call {
310 BuiltInFunctionCall1p::Sqrt => {
311 quote!(#arg.sqrt()).to_tokens(tokens);
312 }
313 BuiltInFunctionCall1p::Exp(false) => {
314 quote!(#arg.exp()).to_tokens(tokens);
315 }
316 BuiltInFunctionCall1p::Exp(true) => {
317 self.external_interpolator
318 .limexp_to_tokens(self.mir, tokens, arg);
319 }
320 BuiltInFunctionCall1p::Ln => {
321 quote!(#arg.ln()).to_tokens(tokens);
322 }
323 BuiltInFunctionCall1p::Log => {
324 quote!(#arg.log10()).to_tokens(tokens);
325 }
326 BuiltInFunctionCall1p::Abs => {
327 quote!(#arg.abs()).to_tokens(tokens);
328 }
329 BuiltInFunctionCall1p::Floor => {
330 quote!(#arg.floor()).to_tokens(tokens);
331 }
332 BuiltInFunctionCall1p::Ceil => {
333 quote!(#arg.ceil()).to_tokens(tokens);
334 }
335 BuiltInFunctionCall1p::Sin => {
336 quote!(#arg.sin()).to_tokens(tokens);
337 }
338 BuiltInFunctionCall1p::Cos => {
339 quote!(#arg.cos()).to_tokens(tokens);
340 }
341 BuiltInFunctionCall1p::Tan => {
342 quote!(#arg.tan()).to_tokens(tokens);
343 }
344 BuiltInFunctionCall1p::ArcSin => {
345 quote!(#arg.asin()).to_tokens(tokens);
346 }
347 BuiltInFunctionCall1p::ArcCos => {
348 quote!(#arg.acos()).to_tokens(tokens);
349 }
350 BuiltInFunctionCall1p::ArcTan => {
351 quote!(#arg.atan()).to_tokens(tokens);
352 }
353 BuiltInFunctionCall1p::SinH => {
354 quote!(#arg.sinh()).to_tokens(tokens);
355 }
356 BuiltInFunctionCall1p::CosH => {
357 quote!(#arg.cosh()).to_tokens(tokens);
358 }
359 BuiltInFunctionCall1p::TanH => {
360 quote!(#arg.tanh()).to_tokens(tokens);
361 }
362 BuiltInFunctionCall1p::ArcSinH => {
363 quote!(#arg.asinh()).to_tokens(tokens);
364 }
365 BuiltInFunctionCall1p::ArcCosH => {
366 quote!(#arg.acosh()).to_tokens(tokens);
367 }
368 BuiltInFunctionCall1p::ArcTanH => {
369 quote!(#arg.atanh()).to_tokens(tokens);
370 }
371 }
372 }
373}
374
375pub struct RealBuiltInFunctionCallInterpolator2p<'lt, EI: TargetSpecificInterpolator> {
376 pub mir: &'lt Mir,
377 pub call: BuiltInFunctionCall2p,
378 pub arg1: RealExpressionId,
379 pub arg2: RealExpressionId,
380 pub external_interpolator: &'lt EI,
381}
382impl<'lt, EI: TargetSpecificInterpolator> ToTokens
383 for RealBuiltInFunctionCallInterpolator2p<'lt, EI>
384{
385 fn to_tokens(&self, tokens: &mut TokenStream) {
386 let arg1 = RealExpressionInterpolator {
387 mir: self.mir,
388 expression: self.arg1,
389 external_interpolator: self.external_interpolator,
390 };
391 let arg2 = RealExpressionInterpolator {
392 mir: self.mir,
393 expression: self.arg2,
394 external_interpolator: self.external_interpolator,
395 };
396 arg1.to_tokens(tokens);
397
398 match self.call {
399 BuiltInFunctionCall2p::Pow => {
400 quote! (.powf).to_tokens(tokens);
401 }
402 BuiltInFunctionCall2p::Hypot => {
403 quote! (.hypot).to_tokens(tokens);
404 }
405 BuiltInFunctionCall2p::Min => {
406 quote! (.min).to_tokens(tokens);
407 }
408 BuiltInFunctionCall2p::Max => {
409 quote! (.max).to_tokens(tokens);
410 }
411 BuiltInFunctionCall2p::ArcTan2 => {
412 quote! (.antan2).to_tokens(tokens);
413 }
414 }
415 quote!((#arg2)).to_tokens(tokens);
416 }
417}
418
419pub trait StatementInterpolatorFactory<'lt, 'out> {
420 type Interpolator: ToTokens;
421 fn new(&'lt self, stmt: StatementId, block: &'out mut Block) -> Self::Interpolator;
422}
423
424#[derive(Clone)]
425pub struct IntegerExpressionInterpolator<'lt, EI> {
426 pub mir: &'lt Mir,
427 pub expression: IntegerExpressionId,
428 pub external_interpolator: &'lt EI,
429}
430impl<'lt, EI: TargetSpecificInterpolator> ToTokens for IntegerExpressionInterpolator<'lt, EI> {
431 fn to_tokens(&self, tokens: &mut TokenStream) {
432 match self.mir[self.expression].contents {
433 IntegerExpression::Condition(condition, _, if_val, _, else_val) => {
434 let condition = IntegerExpressionInterpolator {
435 expression: condition,
436 ..*self
437 };
438 let if_val = IntegerExpressionInterpolator {
439 expression: if_val,
440 ..*self
441 };
442 let else_val = IntegerExpressionInterpolator {
443 expression: else_val,
444 ..*self
445 };
446 (quote! {
447 if #condition != 0 {
448 #if_val
449 } else {
450 #else_val
451 }
452 })
453 .to_tokens(tokens)
454 }
455
456 IntegerExpression::Literal(val) => tokens.append(Literal::i64_suffixed(val)),
457
458 IntegerExpression::VariableReference(var_id) => {
459 tokens.append(gen_variable_ident(var_id))
460 }
461
462 IntegerExpression::ParameterReference(par_id) => {
463 tokens.append(gen_parameter_ident(par_id))
464 }
465
466 IntegerExpression::NetReference(_) | IntegerExpression::PortReference(_) => {
467 unimplemented!("Digital Nets")
468 }
469
470 IntegerExpression::FunctionCall(_, _) => unimplemented!("FunctionCalls"),
471
472 IntegerExpression::BinaryOperator(lhs, op, rhs) => {
473 let lhs = IntegerExpressionInterpolator {
474 expression: lhs,
475 ..*self
476 };
477 let rhs = IntegerExpressionInterpolator {
478 expression: rhs,
479 ..*self
480 };
481 match op.contents {
482 IntegerBinaryOperator::Sum => quote! {(#lhs + #rhs)}.to_tokens(tokens),
483 IntegerBinaryOperator::Subtract => quote! {(#lhs - #rhs)}.to_tokens(tokens),
484 IntegerBinaryOperator::Multiply => quote! {(#lhs*#rhs)}.to_tokens(tokens),
485 IntegerBinaryOperator::Divide => quote! {(#lhs/#rhs)}.to_tokens(tokens),
486 IntegerBinaryOperator::Exponent => {
487 (quote! {if #rhs >= 0 {#lhs.pow(#rhs)} else {0}}).to_tokens(tokens)
488 }
489 IntegerBinaryOperator::Modulus => quote! {(#lhs % #rhs)}.to_tokens(tokens),
490 IntegerBinaryOperator::ShiftLeft => quote! {(#lhs << #rhs)}.to_tokens(tokens),
491 IntegerBinaryOperator::ShiftRight => quote! {(#lhs >> #rhs)}.to_tokens(tokens),
492 IntegerBinaryOperator::LogicOr => {
493 (quote! {(((#lhs != 0) || (#rhs != 0)) as i64)}).to_tokens(tokens)
494 }
495 IntegerBinaryOperator::LogicAnd => {
496 (quote! {(((#lhs != 0) && (#rhs != 0)) as i64)}).to_tokens(tokens)
497 }
498 IntegerBinaryOperator::Xor => quote! {(#lhs ^ #rhs)}.to_tokens(tokens),
499 IntegerBinaryOperator::NXor => quote! {!(#lhs ^ #rhs)}.to_tokens(tokens),
500 IntegerBinaryOperator::And => quote! {(#lhs & #rhs)}.to_tokens(tokens),
501 IntegerBinaryOperator::Or => quote! {(#lhs | #rhs)}.to_tokens(tokens),
502 }
503 }
504
505 IntegerExpression::RealComparison(lhs, op, rhs) => {
506 let lhs = RealExpressionInterpolator {
507 expression: lhs,
508 mir: self.mir,
509 external_interpolator: self.external_interpolator,
510 };
511 let rhs = RealExpressionInterpolator {
512 expression: rhs,
513 mir: self.mir,
514 external_interpolator: self.external_interpolator,
515 };
516 match op.contents {
517 ComparisonOperator::LessThen => {
518 (quote! {((#lhs < #rhs) as i64)}).to_tokens(tokens)
519 }
520 ComparisonOperator::LessEqual => {
521 (quote! {((#lhs <= #rhs) as i64)}).to_tokens(tokens)
522 }
523 ComparisonOperator::GreaterThen => {
524 (quote! {((#lhs > #rhs) as i64)}).to_tokens(tokens)
525 }
526 ComparisonOperator::GreaterEqual => {
527 (quote! {((#lhs >= #rhs ) as i64)}).to_tokens(tokens)
528 }
529 ComparisonOperator::LogicEqual => {
530 (quote! {((#lhs.approx_eq(#rhs, F64Margin::default())) as i64)})
531 .to_tokens(tokens)
532 }
533 ComparisonOperator::LogicalNotEqual => {
534 (quote! {((#lhs.approx_ne(#rhs, F64Margin::default())) as i64)})
535 .to_tokens(tokens)
536 }
537 }
538 }
539
540 IntegerExpression::IntegerComparison(lhs, op, rhs) => {
541 let lhs = IntegerExpressionInterpolator {
542 expression: lhs,
543 ..*self
544 };
545 let rhs = IntegerExpressionInterpolator {
546 expression: rhs,
547 ..*self
548 };
549 match op.contents {
550 ComparisonOperator::LessThen => {
551 (quote! {((#lhs < #rhs) as i64)}).to_tokens(tokens)
552 }
553 ComparisonOperator::LessEqual => {
554 (quote! {((#lhs <= #rhs) as i64)}).to_tokens(tokens)
555 }
556 ComparisonOperator::GreaterThen => {
557 (quote! {((#lhs > #rhs) as i64)}).to_tokens(tokens)
558 }
559 ComparisonOperator::GreaterEqual => {
560 (quote! {((#lhs >= #rhs ) as i64)}).to_tokens(tokens)
561 }
562 ComparisonOperator::LogicEqual => {
563 (quote! {((#lhs == #rhs) as i64)}).to_tokens(tokens)
564 }
565 ComparisonOperator::LogicalNotEqual => {
566 (quote! {((#lhs != #rhs) as i64)}).to_tokens(tokens)
567 }
568 }
569 }
570
571 IntegerExpression::UnaryOperator(op, expr) => {
572 let expr = IntegerExpressionInterpolator {
573 expression: expr,
574 ..*self
575 };
576 match op.contents {
577 UnaryOperator::LogicNegate | UnaryOperator::BitNegate =>
578 {
580 (quote! {(!#expr)}).to_tokens(tokens)
581 }
582 UnaryOperator::ArithmeticNegate => quote! {(-#expr)}.to_tokens(tokens),
583 UnaryOperator::ExplicitPositive => expr.to_tokens(tokens),
584 }
585 }
586
587 IntegerExpression::Abs(arg) => {
588 let arg = IntegerExpressionInterpolator {
589 expression: arg,
590 ..*self
591 };
592 (quote! {
593 #arg.abs()
594 })
595 .to_tokens(tokens);
596 }
597
598 IntegerExpression::Min(arg1, arg2) => {
599 let arg1 = IntegerExpressionInterpolator {
600 expression: arg1,
601 ..*self
602 };
603 let arg2 = IntegerExpressionInterpolator {
604 expression: arg2,
605 ..*self
606 };
607 (quote! {
608 #arg1.min(#arg2)
609 })
610 .to_tokens(tokens);
611 }
612
613 IntegerExpression::Max(arg1, arg2) => {
614 let arg1 = IntegerExpressionInterpolator {
615 expression: arg1,
616 ..*self
617 };
618 let arg2 = IntegerExpressionInterpolator {
619 expression: arg2,
620 ..*self
621 };
622 (quote! {
623 #arg1.max(#arg2)
624 })
625 .to_tokens(tokens);
626 }
627
628 IntegerExpression::RealCast(expression) => {
629 let expression = RealExpressionInterpolator {
630 expression,
631 mir: self.mir,
632 external_interpolator: self.external_interpolator,
633 };
634 (quote! {
635 (#expression.round() as i64)
636 })
637 .to_tokens(tokens);
638 }
639
640 IntegerExpression::StringEq(lhs, rhs) => {
641 let lhs = StringExpressionInterpolator {
642 mir: self.mir,
643 expression: lhs,
644 external_interpolator: self.external_interpolator,
645 };
646 let rhs = StringExpressionInterpolator {
647 mir: self.mir,
648 expression: rhs,
649 external_interpolator: self.external_interpolator,
650 };
651 quote!((#lhs == #rhs) as i64).to_tokens(tokens)
652 }
653
654 IntegerExpression::StringNEq(lhs, rhs) => {
655 let lhs = StringExpressionInterpolator {
656 mir: self.mir,
657 expression: lhs,
658 external_interpolator: self.external_interpolator,
659 };
660 let rhs = StringExpressionInterpolator {
661 mir: self.mir,
662 expression: rhs,
663 external_interpolator: self.external_interpolator,
664 };
665 quote!((#lhs != #rhs) as i64).to_tokens(tokens)
666 }
667 IntegerExpression::ParamGiven(param) => self
668 .external_interpolator
669 .param_given_to_tokens(self.mir, tokens, param),
670 IntegerExpression::PortConnected(port) => self
671 .external_interpolator
672 .port_connected_to_tokens(self.mir, tokens, port),
673 }
674 }
675}
676
677#[derive(Clone)]
678pub struct StringExpressionInterpolator<'lt, EI> {
679 pub mir: &'lt Mir,
680 pub expression: StringExpressionId,
681 pub external_interpolator: &'lt EI,
682}
683impl<'lt, EI: TargetSpecificInterpolator> ToTokens for StringExpressionInterpolator<'lt, EI> {
684 fn to_tokens(&self, tokens: &mut TokenStream) {
685 match self.mir[self.expression].contents {
686 StringExpression::SimParam(name) => self
687 .external_interpolator
688 .simparam_str_to_tokens(self.mir, tokens, name),
689 StringExpression::Condition(cond, _, true_val, _, false_val) => {
690 let cond = IntegerExpressionInterpolator {
691 mir: self.mir,
692 expression: cond,
693 external_interpolator: self.external_interpolator,
694 };
695
696 let true_val = StringExpressionInterpolator {
697 mir: self.mir,
698 expression: true_val,
699 external_interpolator: self.external_interpolator,
700 };
701
702 let false_val = StringExpressionInterpolator {
703 mir: self.mir,
704 expression: false_val,
705 external_interpolator: self.external_interpolator,
706 };
707
708 (quote! {
709 if #cond != 0 {
710 #true_val
711 }else{
712 #false_val
713 }
714 })
715 .to_tokens(tokens)
716 }
717 StringExpression::Literal(val) => tokens.append(Literal::string(&val.as_str())),
718 StringExpression::VariableReference(var) => tokens.append(gen_variable_ident(var)),
719 StringExpression::ParameterReference(param) => {
720 tokens.append(gen_parameter_ident(param))
721 }
722 }
723 }
724}
725
726#[derive(Clone)]
727pub struct RealExpressionInterpolator<'lt, EI> {
728 pub mir: &'lt Mir,
729 pub expression: RealExpressionId,
730 pub external_interpolator: &'lt EI,
731}
732impl<'lt, EI: TargetSpecificInterpolator> ToTokens for RealExpressionInterpolator<'lt, EI> {
733 fn to_tokens(&self, tokens: &mut TokenStream) {
734 match self.mir[self.expression].contents {
735 RealExpression::Temperature => self
736 .external_interpolator
737 .temperature_to_tokens(self.mir, tokens),
738 RealExpression::Vt(arg) => self.external_interpolator.vt_to_tokens(
739 self.mir,
740 tokens,
741 arg.map(|arg| RealExpressionInterpolator {
742 mir: self.mir,
743 expression: arg,
744 external_interpolator: self.external_interpolator,
745 }),
746 ),
747 RealExpression::SimParam(name, default) => {
748 self.external_interpolator.simparam_to_tokens(
749 self.mir,
750 tokens,
751 name,
752 default.map(|default| RealExpressionInterpolator {
753 mir: self.mir,
754 expression: default,
755 external_interpolator: self.external_interpolator,
756 }),
757 )
758 }
759 RealExpression::Condition(condition, _, if_val, _, else_val) => {
760 let condition = IntegerExpressionInterpolator {
761 mir: self.mir,
762 external_interpolator: self.external_interpolator,
763 expression: condition,
764 };
765 let if_val = RealExpressionInterpolator {
766 expression: if_val,
767 ..*self
768 };
769 let else_val = RealExpressionInterpolator {
770 expression: else_val,
771 ..*self
772 };
773 (quote! {
774 if #condition != 0 {
775 #if_val
776 }else {
777 #else_val
778 }
779 })
780 .to_tokens(tokens)
781 }
782
783 RealExpression::Literal(val) => RealNumberInterpolator(val).to_tokens(tokens),
784
785 RealExpression::BranchAccess(discipline_access, branch_access, order) => {
786 tokens.append(gen_branch_access(discipline_access, branch_access, order))
787 }
788
789 RealExpression::VariableReference(var_id) => tokens.append(gen_variable_ident(var_id)),
790
791 RealExpression::BuiltInFunctionCall2p(call, arg1, arg2) => {
792 let call = RealBuiltInFunctionCallInterpolator2p {
793 mir: self.mir,
794 call,
795 arg1,
796 arg2,
797 external_interpolator: self.external_interpolator,
798 };
799 (quote! {(#call)}).to_tokens(tokens)
800 }
801 RealExpression::BuiltInFunctionCall1p(call, arg) => {
802 let call = RealBuiltInFunctionCallInterpolator1p {
803 mir: self.mir,
804 external_interpolator: self.external_interpolator,
805 call,
806 arg,
807 };
808 (quote! {(#call)}).to_tokens(tokens)
809 }
810
811 RealExpression::ParameterReference(par_id) => {
812 tokens.append(gen_parameter_ident(par_id))
813 }
814
815 RealExpression::BinaryOperator(lhs, op, rhs) => {
816 let lhs = RealExpressionInterpolator {
817 expression: lhs,
818 ..*self
819 };
820 let rhs = RealExpressionInterpolator {
821 expression: rhs,
822 ..*self
823 };
824 match op.contents {
825 RealBinaryOperator::Sum => quote! {(#lhs + #rhs)}.to_tokens(tokens),
826 RealBinaryOperator::Subtract => quote! {(#lhs - #rhs)}.to_tokens(tokens),
827 RealBinaryOperator::Multiply => quote! {(#lhs*#rhs)}.to_tokens(tokens),
828 RealBinaryOperator::Divide => quote! {(#lhs/#rhs)}.to_tokens(tokens),
829 RealBinaryOperator::Exponent => quote! {(#lhs.powf(#rhs))}.to_tokens(tokens),
830 RealBinaryOperator::Modulus => quote! {(#lhs % #rhs)}.to_tokens(tokens),
831 }
832 }
833
834 RealExpression::Negate(_, expression) => {
835 let expr = RealExpressionInterpolator {
836 expression,
837 ..*self
838 };
839 quote!((-#expr)).to_tokens(tokens)
840 }
841
842 RealExpression::IntegerConversion(expression) => {
843 let expression = IntegerExpressionInterpolator {
844 expression,
845 mir: self.mir,
846 external_interpolator: self.external_interpolator,
847 };
848 (quote! {
849 (#expression as f64)
850 })
851 .to_tokens(tokens);
852 }
853 RealExpression::Noise(source, name) => self
854 .external_interpolator
855 .noise_to_tokens(self.mir, tokens, source, name),
856 }
857 }
858}
859
860pub fn gen_branch_access(
861 discipline_access: DisciplineAccess,
862 branch_access: BranchId,
863 order: u8,
864) -> Ident {
865 Ident::new(
866 format!("branch_{:?}_{}_{}", discipline_access, branch_access, order).as_str(),
867 proc_macro2::Span::call_site(),
868 )
869}
870
871pub fn gen_parameter_ident(parameter: ParameterId) -> Ident {
872 Ident::new(
873 format!("parameter_{}", parameter).as_str(),
874 proc_macro2::Span::call_site(),
875 )
876}
877
878pub fn gen_variable_ident(id: VariableId) -> Ident {
879 Ident::new(
880 format!("variable_{}", id).as_str(),
881 proc_macro2::Span::call_site(),
882 )
883}
884
885pub fn gen_port_ident(port: PortId) -> Ident {
886 Ident::new(
887 format!("port_{}", port).as_str(),
888 proc_macro2::Span::call_site(),
889 )
890}
891
892pub fn generate_variable_type(variable_type: VariableType) -> TokenTree {
893 match variable_type {
894 VariableType::INTEGER => {
895 TokenTree::Ident(Ident::new("i32", proc_macro2::Span::call_site()))
896 }
897 VariableType::REAL => TokenTree::Ident(Ident::new("f64", proc_macro2::Span::call_site())),
898 }
899}
900
901pub fn gen_net_ident(net: NetId) -> Ident {
902 Ident::new(
903 format!("net_{}", net).as_str(),
904 proc_macro2::Span::call_site(),
905 )
906}