1use crate::conv::Context;
2use crate::conv::checker::clock_domain::check_clock_domain;
3use crate::ir::assign_table::{AssignContext, AssignTable};
4use crate::ir::utils::convert_cast;
5use crate::ir::{
6 Comptime, ExpressionContext, FfTable, FunctionCall, Op, Signature, SystemFunctionCall,
7 SystemFunctionKind, Type, TypeKind, ValueVariant, VarId, VarIndex, VarSelect,
8};
9use crate::symbol::{ClockDomain, Symbol, SymbolKind};
10use crate::value::{Value, ValueBigUint};
11use std::fmt;
12use veryl_parser::resource_table::StrId;
13use veryl_parser::token_range::TokenRange;
14
15#[derive(Clone, Debug)]
16pub enum Expression {
17 Term(Box<Factor>),
18 Unary(Op, Box<Expression>, Box<Comptime>),
19 Binary(Box<Expression>, Op, Box<Expression>, Box<Comptime>),
20 Ternary(
21 Box<Expression>,
22 Box<Expression>,
23 Box<Expression>,
24 Box<Comptime>,
25 ),
26 Concatenation(Vec<(Expression, Option<Expression>)>, Box<Comptime>),
27 ArrayLiteral(Vec<ArrayLiteralItem>, Box<Comptime>),
28 StructConstructor(Type, Vec<(StrId, Expression)>, Box<Comptime>),
29}
30
31impl Expression {
32 pub fn create_value(value: Value, token: TokenRange) -> Self {
33 Self::Term(Box::new(Factor::create_value(value, token)))
34 }
35}
36
37impl fmt::Display for Expression {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 let ret = match self {
40 Expression::Term(x) => x.to_string(),
41 Expression::Unary(x, y, _) => {
42 format!("({x} {y})")
43 }
44 Expression::Binary(x, y, z, _) => {
45 format!("({x} {y} {z})")
46 }
47 Expression::Ternary(x, y, z, _) => {
48 format!("({x} ? {y} : {z})")
49 }
50 Expression::Concatenation(x, _) => {
51 let mut ret = String::new();
52 for (x, y) in x {
53 if let Some(y) = y {
54 ret = format!("{ret}, {x} repeat {y}")
55 } else {
56 ret = format!("{ret}, {x}")
57 }
58 }
59 format!("{{{}}}", &ret[2..])
60 }
61 Expression::ArrayLiteral(x, _) => {
62 let mut ret = String::new();
63 for x in x {
64 ret = format!("{ret}, {x}")
65 }
66 format!("'{{{}}}", &ret[2..])
67 }
68 Expression::StructConstructor(_, x, _) => {
69 let mut ret = String::new();
70 for x in x {
71 ret = format!("{ret}, {}: {}", x.0, x.1)
72 }
73 format!("'{{{}}}", &ret[2..])
74 }
75 };
76
77 ret.fmt(f)
78 }
79}
80
81impl Expression {
82 pub fn is_assignable(&self) -> bool {
83 match self {
84 Expression::Term(x) => x.is_assignable(),
85 Expression::Concatenation(x, _) => {
86 x.iter().all(|x| x.0.is_assignable() && x.1.is_none())
87 }
88 _ => false,
89 }
90 }
91
92 pub fn gather_context(&mut self, context: &mut Context) -> ExpressionContext {
93 match self {
94 Expression::Term(x) => x.gather_context(context),
95 Expression::Unary(op, x, comptime) => {
96 let x = x.gather_context(context);
97
98 comptime.is_const = x.is_const;
99 comptime.is_global = x.is_global;
100
101 op.eval_context_unary(x)
102 }
103 Expression::Binary(x, op, y, comptime) => {
104 let (x, y) = if op.binary_op_self_determined() {
105 let expr_context = x.gather_context(context).merge(y.gather_context(context));
106 x.apply_context(context, expr_context);
107 y.apply_context(context, expr_context);
108 (expr_context, expr_context)
109 } else {
110 let x = if op.binary_x_self_determined() {
111 let expr_context = x.gather_context(context);
112 x.apply_context(context, expr_context);
113 x.comptime().expr_context
114 } else {
115 x.gather_context(context)
116 };
117
118 let y = if op.binary_y_self_determined() {
119 let expr_context = y.gather_context(context);
120 y.apply_context(context, expr_context);
121 y.comptime().expr_context
122 } else {
123 y.gather_context(context)
124 };
125
126 (x, y)
127 };
128
129 comptime.is_const = x.is_const & y.is_const;
130 comptime.is_global = x.is_global & y.is_global;
131
132 op.eval_context_binary(x, y)
133 }
134 Expression::Ternary(x, y, z, comptime) => {
135 let expr_context = x.gather_context(context);
137 x.apply_context(context, expr_context);
138 let x = x.comptime();
139
140 let y = y.gather_context(context);
141 let z = z.gather_context(context);
142
143 let is_const = x.is_const & y.is_const & z.is_const;
144 let is_global = x.is_global & y.is_global & z.is_global;
145
146 comptime.is_const = is_const;
147 comptime.is_global = is_global;
148
149 ExpressionContext {
150 width: y.width.max(z.width),
151 signed: y.signed & z.signed,
152 is_const,
153 is_global,
154 }
155 }
156 Expression::Concatenation(x, comptime) => {
157 let op = Op::Concatenation;
158 op.eval_type_concatenation(context, x, comptime);
159 comptime.evaluated = true;
160
161 ExpressionContext {
162 width: comptime.r#type.total_width().unwrap_or(0),
163 signed: comptime.r#type.signed,
164 is_const: comptime.is_const,
165 is_global: comptime.is_global,
166 }
167 }
168 Expression::StructConstructor(r#type, exprs, comptime) => {
169 let mut is_const = true;
170 let mut is_global = true;
171 for (_, expr) in exprs {
172 let expr_context = expr.gather_context(context);
173 is_const &= expr_context.is_const;
174 is_global &= expr_context.is_global;
175
176 let expr = expr.comptime();
177 check_clock_domain(context, comptime, expr, &comptime.token.beg);
178 comptime.clock_domain = expr.clock_domain;
179 }
180
181 comptime.r#type = r#type.clone();
182 comptime.is_const = is_const;
183 comptime.is_global = is_global;
184 comptime.evaluated = true;
185
186 ExpressionContext {
187 width: r#type.total_width().unwrap_or(0),
188 signed: false,
189 is_const,
190 is_global,
191 }
192 }
193 Expression::ArrayLiteral(items, comptime) => {
194 let mut is_const = true;
195 let mut is_global = true;
196 for item in items {
197 match item {
198 ArrayLiteralItem::Value(x, y) => {
199 let x_context = x.gather_context(context);
200 is_const &= x_context.is_const;
201 is_global &= x_context.is_global;
202 if let Some(y) = y {
203 let y_context = y.gather_context(context);
204 is_const &= y_context.is_const;
205 is_global &= y_context.is_global;
206 }
207 }
208 ArrayLiteralItem::Defaul(x) => {
209 let x_context = x.gather_context(context);
210 is_const &= x_context.is_const;
211 is_global &= x_context.is_global;
212 }
213 }
214 }
215
216 comptime.is_const = is_const;
217 comptime.is_global = is_global;
218 comptime.evaluated = true;
219
220 ExpressionContext {
222 width: 0,
223 signed: false,
224 is_const,
225 is_global,
226 }
227 }
228 }
229 }
230
231 pub fn apply_context(&mut self, context: &mut Context, expr_context: ExpressionContext) {
232 match self {
233 Expression::Term(x) => x.apply_context(expr_context),
234 Expression::Unary(op, x, comptime) => {
235 x.apply_context(context, expr_context);
236 comptime.expr_context = expr_context;
237 op.eval_type_unary(context, x.comptime(), comptime);
238 comptime.evaluated = true;
239 }
240 Expression::Binary(x, op, y, comptime) => {
241 if !op.binary_op_self_determined() {
242 if !op.binary_x_self_determined() {
243 x.apply_context(context, expr_context);
244 }
245 if !op.binary_y_self_determined() {
246 y.apply_context(context, expr_context);
247 }
248 }
249
250 comptime.expr_context = expr_context;
251 op.eval_type_binary(context, x.comptime(), y.comptime(), comptime);
252 comptime.evaluated = true;
253 }
254 Expression::Ternary(x, y, z, comptime) => {
255 y.apply_context(context, expr_context);
256 z.apply_context(context, expr_context);
257
258 comptime.expr_context = expr_context;
259 let op = Op::Ternary;
260 op.eval_type_ternary(context, x.comptime(), y.comptime(), z.comptime(), comptime);
261 comptime.evaluated = true;
262 }
263 Expression::Concatenation(_, _) => (),
264 Expression::StructConstructor(_, _, _) => (),
265 Expression::ArrayLiteral(_, _) => (),
266 }
267 }
268
269 pub fn eval_value(&self, context: &mut Context) -> Option<Value> {
270 let context_width = self.comptime().expr_context.width;
271 let signed = self.comptime().expr_context.signed;
272
273 match self {
274 Expression::Term(x) => x.eval_value(context),
275 Expression::Unary(op, x, _) => {
276 let ret = x.eval_value(context)?;
277 let x_kind = &x.comptime().r#type.kind;
278 if x_kind.is_float() {
279 op.eval_float_unary(&ret, x_kind)
280 } else {
281 let ret =
282 op.eval_value_unary(&ret, context_width, signed, &mut context.mask_cache);
283 Some(ret)
284 }
285 }
286 Expression::Binary(x, op, y, comptime) => {
287 if op == &Op::As {
288 let src_kind = &x.comptime().r#type.kind;
289 let dst_kind = &comptime.r#type.kind;
290
291 let val = x.eval_value(context)?;
292 if src_kind.is_float() || dst_kind.is_float() {
293 return Some(convert_cast(val, src_kind, dst_kind, context_width));
294 }
295
296 let cast_width = comptime.r#type.total_width()?;
297 let val_width = val.width();
298 if val_width > cast_width {
299 let mut val = val.clone();
300 val.trunc(cast_width);
301 return Some(convert_cast(val, src_kind, dst_kind, context_width));
302 } else if val_width < cast_width {
303 let val = val.expand(cast_width, false).into_owned();
304 return Some(convert_cast(val, src_kind, dst_kind, context_width));
305 } else {
306 return Some(convert_cast(val, src_kind, dst_kind, context_width));
307 }
308 }
309
310 let signed = if matches!(op, Op::Div | Op::Rem) {
314 x.comptime().expr_context.signed & y.comptime().expr_context.signed
315 } else {
316 signed
317 };
318
319 let x_kind = x.comptime().r#type.kind.clone();
320 let y_kind = y.comptime().r#type.kind.clone();
321 let x = x.eval_value(context)?;
322 let y = y.eval_value(context)?;
323 if x_kind.is_float() || y_kind.is_float() {
324 let float_kind = if x_kind.is_float() { &x_kind } else { &y_kind };
325 let float_width = if matches!(float_kind, TypeKind::F32) {
326 32
327 } else {
328 64
329 };
330 let x = if !x_kind.is_float() {
331 convert_cast(x, &x_kind, float_kind, float_width)
332 } else {
333 x
334 };
335 let y = if !y_kind.is_float() {
336 convert_cast(y, &y_kind, float_kind, float_width)
337 } else {
338 y
339 };
340 op.eval_float_binary(&x, &y, float_kind)
341 } else {
342 let ret = op.eval_value_binary(
343 &x,
344 &y,
345 context_width,
346 signed,
347 &mut context.mask_cache,
348 );
349 Some(ret)
350 }
351 }
352 Expression::Ternary(x, y, z, _) => {
353 let x = x.eval_value(context)?;
354 let y = y.eval_value(context)?;
355 let z = z.eval_value(context)?;
356
357 let width = y.width().max(z.width());
358
359 let ret = if x.to_usize().unwrap_or(0) == 0 { z } else { y };
360 let ret = ret.expand(width, false).into_owned();
361 Some(ret)
362 }
363 Expression::Concatenation(x, _) => {
364 let mut ret = Value::new(0, 0, false);
365 for (exp, rep) in x.iter() {
366 let exp = exp.eval_value(context)?;
367
368 let rep = if let Some(rep) = rep {
369 let token = rep.token_range();
370 let rep = rep.eval_value(context)?;
371 let rep = rep.to_usize()?;
372 context.check_size(rep, token)?
373 } else {
374 1
375 };
376
377 for _ in 0..rep {
378 ret = ret.concat(&exp);
379 }
380 }
381 Some(ret)
382 }
383 Expression::StructConstructor(r#type, exprs, _) => {
384 let mut ret = Value::new(0u32.into(), 0, false);
385 for (name, expr) in exprs {
386 let sub_type = r#type.get_member_type(*name)?;
387 let width = sub_type.total_width()?;
388 let mut value = expr.eval_value(context)?;
389 value.trunc(width);
390 ret = ret.concat(&value);
391 }
392 Some(ret)
393 }
394 Expression::ArrayLiteral(_, _) => None,
396 }
397 }
398
399 pub fn eval_comptime(
400 &mut self,
401 context: &mut Context,
402 context_width: Option<usize>,
403 ) -> &Comptime {
404 if !self.comptime().evaluated {
405 let mut expr_context = self.gather_context(context);
406 expr_context.width = expr_context.width.max(context_width.unwrap_or(0));
407 self.apply_context(context, expr_context);
408
409 let value = self.eval_value(context);
410 let comptime = self.comptime_mut();
411 if comptime.value.is_unknown()
412 && let Some(x) = &value
413 {
414 comptime.value = ValueVariant::Numeric(x.clone());
415 }
416
417 if !context.disalbe_const_opt
419 && comptime.is_const
420 && let Some(value) = value
421 && !value.is_xz()
422 {
423 let is_global = comptime.is_global;
424 let r#type = comptime.r#type.clone();
425 let mut expr = Expression::create_value(value.clone(), self.token_range());
426
427 let expr_comptime = expr.comptime_mut();
428 expr_comptime.is_global = is_global;
429 expr_comptime.r#type = r#type;
430 expr_comptime.evaluated = true;
431
432 *self = expr;
433 }
434 }
435
436 self.comptime()
437 }
438
439 pub fn eval_assign(
440 &self,
441 context: &mut Context,
442 assign_table: &mut AssignTable,
443 assign_context: AssignContext,
444 ) {
445 match self {
446 Expression::Term(x) => x.eval_assign(context, assign_table, assign_context),
447 Expression::Unary(_, x, _) => x.eval_assign(context, assign_table, assign_context),
448 Expression::Binary(x, _, y, _) => {
449 x.eval_assign(context, assign_table, assign_context);
450 y.eval_assign(context, assign_table, assign_context);
451 }
452 Expression::Ternary(x, y, z, _) => {
453 x.eval_assign(context, assign_table, assign_context);
454 y.eval_assign(context, assign_table, assign_context);
455 z.eval_assign(context, assign_table, assign_context);
456 }
457 Expression::Concatenation(x, _) => {
458 for (x, y) in x {
459 x.eval_assign(context, assign_table, assign_context);
460 if let Some(y) = y {
461 y.eval_assign(context, assign_table, assign_context);
462 }
463 }
464 }
465 Expression::StructConstructor(_, exprs, _) => {
466 for (_, expr) in exprs {
467 expr.eval_assign(context, assign_table, assign_context);
468 }
469 }
470 Expression::ArrayLiteral(_, _) => (),
472 }
473 }
474
475 pub fn gather_ff(
476 &self,
477 context: &mut Context,
478 table: &mut FfTable,
479 decl: usize,
480 assign_target: Option<(VarId, Option<usize>)>,
481 from_ff: bool,
482 ) {
483 match self {
484 Expression::Term(x) => x.gather_ff(context, table, decl, assign_target, from_ff),
485 Expression::Unary(_, x, _) => x.gather_ff(context, table, decl, assign_target, from_ff),
486 Expression::Binary(x, _, y, _) => {
487 x.gather_ff(context, table, decl, assign_target, from_ff);
488 y.gather_ff(context, table, decl, assign_target, from_ff);
489 }
490 Expression::Ternary(x, y, z, _) => {
491 x.gather_ff(context, table, decl, assign_target, from_ff);
492 y.gather_ff(context, table, decl, assign_target, from_ff);
493 z.gather_ff(context, table, decl, assign_target, from_ff);
494 }
495 Expression::Concatenation(x, _) => {
496 for (x, y) in x {
497 x.gather_ff(context, table, decl, assign_target, from_ff);
498 if let Some(y) = y {
499 y.gather_ff(context, table, decl, assign_target, from_ff);
500 }
501 }
502 }
503 Expression::StructConstructor(_, exprs, _) => {
504 for (_, expr) in exprs {
505 expr.gather_ff(context, table, decl, assign_target, from_ff);
506 }
507 }
508 Expression::ArrayLiteral(_, _) => (),
510 }
511 }
512
513 pub fn set_index(&mut self, index: &VarIndex) {
514 match self {
515 Expression::Term(x) => x.set_index(index),
516 Expression::Unary(_, x, _) => x.set_index(index),
517 Expression::Binary(x, _, y, _) => {
518 x.set_index(index);
519 y.set_index(index);
520 }
521 Expression::Ternary(x, y, z, _) => {
522 x.set_index(index);
523 y.set_index(index);
524 z.set_index(index);
525 }
526 Expression::Concatenation(x, _) => {
527 for (x, y) in x {
528 x.set_index(index);
529 if let Some(y) = y {
530 y.set_index(index);
531 }
532 }
533 }
534 Expression::StructConstructor(_, exprs, _) => {
535 for (_, expr) in exprs {
536 expr.set_index(index);
537 }
538 }
539 Expression::ArrayLiteral(_, _) => (),
541 }
542 }
543
544 pub fn comptime(&self) -> &Comptime {
545 match self {
546 Expression::Term(x) => x.comptime(),
547 Expression::Unary(_, _, x) => x,
548 Expression::Binary(_, _, _, x) => x,
549 Expression::Ternary(_, _, _, x) => x,
550 Expression::Concatenation(_, x) => x,
551 Expression::ArrayLiteral(_, x) => x,
552 Expression::StructConstructor(_, _, x) => x,
553 }
554 }
555
556 pub fn comptime_mut(&mut self) -> &mut Comptime {
557 match self {
558 Expression::Term(x) => x.comptime_mut(),
559 Expression::Unary(_, _, x) => x,
560 Expression::Binary(_, _, _, x) => x,
561 Expression::Ternary(_, _, _, x) => x,
562 Expression::Concatenation(_, x) => x,
563 Expression::ArrayLiteral(_, x) => x,
564 Expression::StructConstructor(_, _, x) => x,
565 }
566 }
567
568 pub fn token_range(&self) -> TokenRange {
569 match self {
570 Expression::Term(x) => x.token_range(),
571 Expression::Unary(_, _, x) => x.token,
572 Expression::Binary(_, _, _, x) => x.token,
573 Expression::Ternary(_, _, _, x) => x.token,
574 Expression::Concatenation(_, x) => x.token,
575 Expression::ArrayLiteral(_, x) => x.token,
576 Expression::StructConstructor(_, _, x) => x.token,
577 }
578 }
579}
580
581#[derive(Clone, Debug)]
582pub enum Factor {
583 Variable(VarId, VarIndex, VarSelect, Comptime),
584 Value(Comptime),
585 SystemFunctionCall(SystemFunctionCall),
586 FunctionCall(FunctionCall),
587 Anonymous(Comptime),
588 Unknown(Comptime),
589}
590
591impl Factor {
592 pub fn create_value(value: Value, token: TokenRange) -> Self {
593 let comptime = Comptime::create_value(value, token);
594 Factor::Value(comptime)
595 }
596
597 pub fn from_component_symbol(symbol: &Symbol, token: TokenRange) -> Self {
598 let sig = Signature::new(symbol.id);
599 let kind = match &symbol.kind {
600 SymbolKind::Module(_)
601 | SymbolKind::ProtoModule(_)
602 | SymbolKind::AliasModule(_)
603 | SymbolKind::ProtoAliasModule(_) => TypeKind::Module(sig),
604 SymbolKind::Interface(_)
605 | SymbolKind::ProtoInterface(_)
606 | SymbolKind::AliasInterface(_)
607 | SymbolKind::ProtoAliasInterface(_) => TypeKind::Interface(sig),
608 SymbolKind::Package(_)
609 | SymbolKind::ProtoPackage(_)
610 | SymbolKind::AliasPackage(_)
611 | SymbolKind::ProtoAliasPackage(_) => TypeKind::Package(sig),
612 _ => unreachable!(),
613 };
614 let r#type = Type::new(kind);
615
616 let mut comptime = Comptime::from_type(r#type, ClockDomain::None, token);
617 comptime.is_const = true;
618 comptime.is_global = true;
619
620 Factor::Value(comptime)
621 }
622
623 pub fn is_assignable(&self) -> bool {
624 match self {
625 Factor::Value(x) => x.r#type.is_systemverilog(),
627 Factor::FunctionCall(_) | Factor::SystemFunctionCall(_) => false,
628 _ => true,
629 }
630 }
631
632 pub fn gather_context(&mut self, context: &mut Context) -> ExpressionContext {
633 match self {
634 Factor::Variable(_, _index, select, comptime) => {
635 if !comptime.evaluated {
639 if !select.is_empty() {
641 comptime.r#type.flatten_struct_union_enum();
642 }
643
644 if !select.is_empty()
646 && let Some(width) = select.eval_comptime(context, &comptime.r#type, false)
647 {
648 comptime.r#type.set_concrete_width(width);
649 }
650 }
651
652 ExpressionContext {
653 width: comptime.r#type.total_width().unwrap_or(0),
654 signed: comptime.r#type.signed,
655 is_const: comptime.is_const,
656 is_global: comptime.is_global,
657 }
658 }
659 Factor::Value(x) => ExpressionContext {
660 width: x.r#type.total_width().unwrap_or(0),
661 signed: x.r#type.signed,
662 is_const: x.is_const,
663 is_global: x.is_global,
664 },
665 Factor::FunctionCall(x) => {
666 x.eval_type(context);
667 ExpressionContext {
668 width: x.comptime.r#type.total_width().unwrap_or(0),
669 signed: x.comptime.r#type.signed,
670 is_const: x.comptime.is_const,
671 is_global: x.comptime.is_global,
672 }
673 }
674 Factor::SystemFunctionCall(x) => ExpressionContext {
675 width: x.comptime.r#type.total_width().unwrap_or(0),
676 signed: x.comptime.expr_context.signed,
677 is_const: x.comptime.is_const,
678 is_global: x.comptime.is_global,
679 },
680 Factor::Anonymous(_) | Factor::Unknown(_) => ExpressionContext::default(),
681 }
682 }
683
684 pub fn apply_context(&mut self, expr_context: ExpressionContext) {
685 match self {
686 Factor::Variable(_, _, _, x) => {
687 x.expr_context = expr_context;
688 x.evaluated = true;
689 }
690 Factor::Value(x) => {
691 x.expr_context = expr_context;
692 x.evaluated = true;
693 }
694 Factor::SystemFunctionCall(x) => {
695 let preserve_signed = matches!(
699 x.kind,
700 SystemFunctionKind::Signed(_) | SystemFunctionKind::Unsigned(_)
701 );
702 let kept = x.comptime.expr_context.signed;
703 x.comptime.expr_context = expr_context;
704 if preserve_signed {
705 x.comptime.expr_context.signed = kept;
706 }
707 x.comptime.evaluated = true;
708 }
709 Factor::FunctionCall(x) => {
710 x.comptime.expr_context = expr_context;
711 x.comptime.evaluated = true;
712 }
713 Factor::Anonymous(x) => {
714 x.expr_context = expr_context;
715 x.evaluated = true
716 }
717 Factor::Unknown(x) => {
718 x.expr_context = expr_context;
719 x.evaluated = true;
720 }
721 }
722 }
723
724 pub fn eval_value(&self, context: &mut Context) -> Option<Value> {
725 match self {
726 Factor::Variable(id, index, select, comptime) => {
727 let index = index.eval_value(context)?;
728 let value = context.variables.get(id)?.get_value(&index)?.clone();
729
730 if !select.is_empty() {
731 let (beg, end) = select.eval_value(context, &comptime.r#type, false)?;
732 Some(value.select(beg, end))
733 } else {
734 Some(value)
735 }
736 }
737 Factor::Value(x) => x.get_value().ok().cloned(),
738 Factor::SystemFunctionCall(x) => x.eval_value(context),
739 Factor::FunctionCall(x) => x.eval_value(context),
740 Factor::Anonymous(_) => None,
741 Factor::Unknown(_) => None,
742 }
743 }
744
745 pub fn eval_assign(
746 &self,
747 context: &mut Context,
748 assign_table: &mut AssignTable,
749 assign_context: AssignContext,
750 ) {
751 match self {
752 Factor::Variable(id, index, select, _) => {
753 let total_array = context
757 .variables
758 .get(id)
759 .map(|v| v.r#type.total_array().unwrap_or(0))
760 .unwrap_or(0);
761 if total_array > assign_table.array_limit {
762 return;
763 }
764 if let Some(index) = index.eval_value(context)
765 && let Some(variable) = context.variables.get(id).cloned()
766 && let Some((beg, end)) = select.eval_value(context, &variable.r#type, false)
767 {
768 let mask = ValueBigUint::gen_mask_range(beg, end);
769 assign_table.insert_reference(&variable, index, mask);
770 }
771 }
772 Factor::FunctionCall(x) => {
773 x.eval_assign(context, assign_table, assign_context);
774 }
775 Factor::SystemFunctionCall(x) => {
776 x.eval_assign(context, assign_table, assign_context);
777 }
778 _ => (),
779 }
780 }
781
782 pub fn gather_ff(
783 &self,
784 context: &mut Context,
785 table: &mut FfTable,
786 decl: usize,
787 assign_target: Option<(VarId, Option<usize>)>,
788 from_ff: bool,
789 ) {
790 match self {
791 Factor::Variable(id, index, _, _) => {
792 if let Some(variable) = context.get_variable_info(*id) {
793 if let Some(index) = index.eval_value(context) {
794 if let Some(index) = variable.r#type.array.calc_index(&index) {
795 table.insert_refered(*id, index, decl, assign_target, from_ff);
796 }
797 } else if let Some(total_array) = variable.r#type.total_array() {
798 for i in 0..total_array {
799 table.insert_refered(*id, i, decl, assign_target, from_ff);
800 }
801 }
802 }
803 }
804 Factor::FunctionCall(x) => {
805 x.gather_ff(context, table, decl, assign_target, from_ff);
806 }
807 _ => (),
808 }
809 }
810
811 pub fn set_index(&mut self, index: &VarIndex) {
812 match self {
813 Factor::Variable(_, i, _, _) => {
814 *i = index.clone();
815 }
816 Factor::FunctionCall(x) => {
817 x.set_index(index);
818 }
819 _ => (),
820 }
821 }
822
823 pub fn comptime(&self) -> &Comptime {
824 match self {
825 Factor::Variable(_, _, _, x) => x,
826 Factor::Value(x) => x,
827 Factor::SystemFunctionCall(x) => &x.comptime,
828 Factor::FunctionCall(x) => &x.comptime,
829 Factor::Anonymous(x) => x,
830 Factor::Unknown(x) => x,
831 }
832 }
833
834 pub fn comptime_mut(&mut self) -> &mut Comptime {
835 match self {
836 Factor::Variable(_, _, _, x) => x,
837 Factor::Value(x) => x,
838 Factor::SystemFunctionCall(x) => &mut x.comptime,
839 Factor::FunctionCall(x) => &mut x.comptime,
840 Factor::Anonymous(x) => x,
841 Factor::Unknown(x) => x,
842 }
843 }
844
845 pub fn token_range(&self) -> TokenRange {
846 match self {
847 Factor::Variable(_, _, _, x) => x.token,
848 Factor::Value(x) => x.token,
849 Factor::SystemFunctionCall(x) => x.comptime.token,
850 Factor::FunctionCall(x) => x.comptime.token,
851 Factor::Anonymous(x) => x.token,
852 Factor::Unknown(x) => x.token,
853 }
854 }
855}
856
857impl fmt::Display for Factor {
858 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
859 let ret = match self {
860 Factor::Variable(id, index, select, _) => {
861 format!("{id}{index}{select}")
862 }
863 Factor::Value(x) => {
864 if let Ok(x) = x.get_value() {
865 format!("{:x}", x)
866 } else {
867 String::from("unknown")
868 }
869 }
870 Factor::SystemFunctionCall(x) => x.to_string(),
871 Factor::FunctionCall(x) => x.to_string(),
872 Factor::Anonymous(_) => String::from("_"),
873 Factor::Unknown(_) => String::from("unknown"),
874 };
875
876 ret.fmt(f)
877 }
878}
879
880#[derive(Clone, Debug)]
881pub enum ArrayLiteralItem {
882 Value(Box<Expression>, Option<Box<Expression>>),
883 Defaul(Box<Expression>),
884}
885
886impl ArrayLiteralItem {
887 pub fn token_range(&self) -> TokenRange {
888 match self {
889 ArrayLiteralItem::Value(x, y) => {
890 let beg = x.token_range();
891 let mut end = if let Some(y) = y {
892 y.token_range()
893 } else {
894 beg
895 };
896 end.set_beg(beg);
897 end
898 }
899 ArrayLiteralItem::Defaul(x) => x.token_range(),
900 }
901 }
902
903 pub fn is_const(&self) -> bool {
904 match self {
905 ArrayLiteralItem::Value(x, y) => {
906 let mut ret = x.comptime().is_const;
907 if let Some(y) = y {
908 ret &= y.comptime().is_const;
909 }
910 ret
911 }
912 ArrayLiteralItem::Defaul(x) => x.comptime().is_const,
913 }
914 }
915
916 pub fn is_global(&self) -> bool {
917 match self {
918 ArrayLiteralItem::Value(x, y) => {
919 let mut ret = x.comptime().is_global;
920 if let Some(y) = y {
921 ret &= y.comptime().is_global;
922 }
923 ret
924 }
925 ArrayLiteralItem::Defaul(x) => x.comptime().is_global,
926 }
927 }
928}
929
930impl fmt::Display for ArrayLiteralItem {
931 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932 let ret = match self {
933 ArrayLiteralItem::Value(x, y) => {
934 if let Some(y) = y {
935 format!("{} repeat {}", x, y)
936 } else {
937 format!("{}", x)
938 }
939 }
940 ArrayLiteralItem::Defaul(x) => {
941 format!("default: {}", x)
942 }
943 };
944
945 ret.fmt(f)
946 }
947}
948
949#[cfg(test)]
950mod tests {
951 use super::*;
952 use crate::conv::utils::parse_expression;
953 use crate::conv::{Context, Conv};
954 use crate::ir::{Shape, TypeKind};
955
956 fn calc_expression(s: &str, context_width: Option<usize>) -> Value {
957 let mut context = Context::default();
958 let x = parse_expression(s);
959 let mut x: Expression = Conv::conv(&mut context, &x).unwrap();
960 x.eval_comptime(&mut context, context_width)
961 .get_value()
962 .unwrap()
963 .clone()
964 }
965
966 #[test]
967 fn arithmetic() {
968 let x00 = calc_expression("1 + 2", None);
969 let x01 = calc_expression("5 - 1", None);
970 let x02 = calc_expression("2 * 7", None);
971 let x03 = calc_expression("8 / 3", None);
972 let x04 = calc_expression("9 % 4", None);
973 let x05 = calc_expression("2 ** 3", None);
974 let x06 = calc_expression("+5", None);
975 let x07 = calc_expression("-1", None);
976 let x08 = calc_expression("1 << 2", None);
977 let x09 = calc_expression("1 <<< 2", None);
978 let x10 = calc_expression("-8 >> 2", None);
979 let x11 = calc_expression("-8 >>> 2", None);
980
981 assert_eq!(format!("{:x}", x00), "32'sh00000003");
982 assert_eq!(format!("{:x}", x01), "32'sh00000004");
983 assert_eq!(format!("{:x}", x02), "32'sh0000000e");
984 assert_eq!(format!("{:x}", x03), "32'sh00000002");
985 assert_eq!(format!("{:x}", x04), "32'sh00000001");
986 assert_eq!(format!("{:x}", x05), "32'sh00000008");
987 assert_eq!(format!("{:x}", x06), "32'sh00000005");
988 assert_eq!(format!("{:x}", x07), "32'shffffffff");
989 assert_eq!(format!("{:x}", x08), "32'h00000004");
990 assert_eq!(format!("{:x}", x09), "32'sh00000004");
991 assert_eq!(format!("{:x}", x10), "32'h3ffffffe");
992 assert_eq!(format!("{:x}", x11), "32'shfffffffe");
993 }
994
995 #[test]
996 fn relational() {
997 let x0 = calc_expression("1 <: 2", None);
998 let x1 = calc_expression("1 >: 2", None);
999 let x2 = calc_expression("1 <= 2", None);
1000 let x3 = calc_expression("1 >= 2", None);
1001 let x4 = calc_expression("2 <: 2", None);
1002 let x5 = calc_expression("2 >: 2", None);
1003 let x6 = calc_expression("2 <= 2", None);
1004 let x7 = calc_expression("2 >= 2", None);
1005
1006 assert_eq!(format!("{:x}", x0), "1'h1");
1007 assert_eq!(format!("{:x}", x1), "1'h0");
1008 assert_eq!(format!("{:x}", x2), "1'h1");
1009 assert_eq!(format!("{:x}", x3), "1'h0");
1010 assert_eq!(format!("{:x}", x4), "1'h0");
1011 assert_eq!(format!("{:x}", x5), "1'h0");
1012 assert_eq!(format!("{:x}", x6), "1'h1");
1013 assert_eq!(format!("{:x}", x7), "1'h1");
1014 }
1015
1016 #[test]
1017 fn equality() {
1018 let x0 = calc_expression("1 == 2", None);
1019 let x1 = calc_expression("1 != 2", None);
1020 let x2 = calc_expression("2 == 2", None);
1021 let x3 = calc_expression("2 != 2", None);
1022
1023 assert_eq!(format!("{:x}", x0), "1'h0");
1024 assert_eq!(format!("{:x}", x1), "1'h1");
1025 assert_eq!(format!("{:x}", x2), "1'h1");
1026 assert_eq!(format!("{:x}", x3), "1'h0");
1027 }
1028
1029 #[test]
1030 fn wildcard_equality() {
1031 let x0 = calc_expression("4'b0000 ==? 4'b00xx", None);
1032 let x1 = calc_expression("4'b0011 ==? 4'b00xx", None);
1033 let x2 = calc_expression("4'b0100 ==? 4'b00xx", None);
1034 let x3 = calc_expression("4'b0111 ==? 4'b00xx", None);
1035 let x4 = calc_expression("4'b0000 !=? 4'b00xx", None);
1036 let x5 = calc_expression("4'b0011 !=? 4'b00xx", None);
1037 let x6 = calc_expression("4'b0100 !=? 4'b00xx", None);
1038 let x7 = calc_expression("4'b0111 !=? 4'b00xx", None);
1039
1040 assert_eq!(format!("{:x}", x0), "1'h1");
1041 assert_eq!(format!("{:x}", x1), "1'h1");
1042 assert_eq!(format!("{:x}", x2), "1'h0");
1043 assert_eq!(format!("{:x}", x3), "1'h0");
1044 assert_eq!(format!("{:x}", x4), "1'h0");
1045 assert_eq!(format!("{:x}", x5), "1'h0");
1046 assert_eq!(format!("{:x}", x6), "1'h1");
1047 assert_eq!(format!("{:x}", x7), "1'h1");
1048 }
1049
1050 #[test]
1051 fn logical() {
1052 let x0 = calc_expression("10 && 0", None);
1053 let x1 = calc_expression("10 || 0", None);
1054 let x2 = calc_expression("!0", None);
1055 let x3 = calc_expression("!10", None);
1056
1057 assert_eq!(format!("{:x}", x0), "1'h0");
1058 assert_eq!(format!("{:x}", x1), "1'h1");
1059 assert_eq!(format!("{:x}", x2), "1'h1");
1060 assert_eq!(format!("{:x}", x3), "1'h0");
1061 }
1062
1063 #[test]
1064 fn bitwise() {
1065 let x0 = calc_expression("4'b0001 & 4'b0101", None);
1066 let x1 = calc_expression("4'b0001 | 4'b0101", None);
1067 let x2 = calc_expression("4'b0001 ^ 4'b0101", None);
1068 let x3 = calc_expression("4'b0001 ~^ 4'b0101", None);
1069 let x4 = calc_expression("~4'b0101", None);
1070
1071 assert_eq!(format!("{:x}", x0), "4'h1");
1072 assert_eq!(format!("{:x}", x1), "4'h5");
1073 assert_eq!(format!("{:x}", x2), "4'h4");
1074 assert_eq!(format!("{:x}", x3), "4'hb");
1075 assert_eq!(format!("{:x}", x4), "4'ha");
1076 }
1077
1078 #[test]
1079 fn reduction() {
1080 let x00 = calc_expression(" &4'b0000", None);
1081 let x01 = calc_expression(" |4'b0000", None);
1082 let x02 = calc_expression(" ^4'b0000", None);
1083 let x03 = calc_expression("~&4'b0000", None);
1084 let x04 = calc_expression("~|4'b0000", None);
1085 let x05 = calc_expression("~^4'b0000", None);
1086
1087 let x06 = calc_expression(" &4'b1111", None);
1088 let x07 = calc_expression(" |4'b1111", None);
1089 let x08 = calc_expression(" ^4'b1111", None);
1090 let x09 = calc_expression("~&4'b1111", None);
1091 let x10 = calc_expression("~|4'b1111", None);
1092 let x11 = calc_expression("~^4'b1111", None);
1093
1094 let x12 = calc_expression(" &4'b0110", None);
1095 let x13 = calc_expression(" |4'b0110", None);
1096 let x14 = calc_expression(" ^4'b0110", None);
1097 let x15 = calc_expression("~&4'b0110", None);
1098 let x16 = calc_expression("~|4'b0110", None);
1099 let x17 = calc_expression("~^4'b0110", None);
1100
1101 let x18 = calc_expression(" &4'b1000", None);
1102 let x19 = calc_expression(" |4'b1000", None);
1103 let x20 = calc_expression(" ^4'b1000", None);
1104 let x21 = calc_expression("~&4'b1000", None);
1105 let x22 = calc_expression("~|4'b1000", None);
1106 let x23 = calc_expression("~^4'b1000", None);
1107
1108 assert_eq!(format!("{:x}", x00), "1'h0");
1109 assert_eq!(format!("{:x}", x01), "1'h0");
1110 assert_eq!(format!("{:x}", x02), "1'h0");
1111 assert_eq!(format!("{:x}", x03), "1'h1");
1112 assert_eq!(format!("{:x}", x04), "1'h1");
1113 assert_eq!(format!("{:x}", x05), "1'h1");
1114
1115 assert_eq!(format!("{:x}", x06), "1'h1");
1116 assert_eq!(format!("{:x}", x07), "1'h1");
1117 assert_eq!(format!("{:x}", x08), "1'h0");
1118 assert_eq!(format!("{:x}", x09), "1'h0");
1119 assert_eq!(format!("{:x}", x10), "1'h0");
1120 assert_eq!(format!("{:x}", x11), "1'h1");
1121
1122 assert_eq!(format!("{:x}", x12), "1'h0");
1123 assert_eq!(format!("{:x}", x13), "1'h1");
1124 assert_eq!(format!("{:x}", x14), "1'h0");
1125 assert_eq!(format!("{:x}", x15), "1'h1");
1126 assert_eq!(format!("{:x}", x16), "1'h0");
1127 assert_eq!(format!("{:x}", x17), "1'h1");
1128
1129 assert_eq!(format!("{:x}", x18), "1'h0");
1130 assert_eq!(format!("{:x}", x19), "1'h1");
1131 assert_eq!(format!("{:x}", x20), "1'h1");
1132 assert_eq!(format!("{:x}", x21), "1'h1");
1133 assert_eq!(format!("{:x}", x22), "1'h0");
1134 assert_eq!(format!("{:x}", x23), "1'h0");
1135 }
1136
1137 #[test]
1138 fn conditional() {
1139 let x0 = calc_expression("if 0 ? 1 : 2", None);
1140 let x1 = calc_expression("if 1 ? 1 : 2", None);
1141
1142 assert_eq!(format!("{:x}", x0), "32'sh00000002");
1143 assert_eq!(format!("{:x}", x1), "32'sh00000001");
1144 }
1145
1146 #[test]
1147 fn concatenation() {
1148 let x0 = calc_expression("{4'h1, 4'h3}", None);
1149 let x1 = calc_expression("{4'h1 repeat 3, 4'h3}", None);
1150
1151 assert_eq!(format!("{:x}", x0), "8'h13");
1152 assert_eq!(format!("{:x}", x1), "16'h1113");
1153 }
1154
1155 #[test]
1156 fn inside_outside() {
1157 let x0 = calc_expression("inside 1 {1, 2}", None);
1158 let x1 = calc_expression("inside 0 {1, 2}", None);
1159 let x2 = calc_expression("inside 5 {3, 2..=10}", None);
1160 let x3 = calc_expression("inside 1 {3, 2..=10}", None);
1161 let x4 = calc_expression("outside 1 {1, 2}", None);
1162 let x5 = calc_expression("outside 0 {1, 2}", None);
1163 let x6 = calc_expression("outside 5 {3, 2..=10}", None);
1164 let x7 = calc_expression("outside 1 {3, 2..=10}", None);
1165
1166 assert_eq!(format!("{:x}", x0), "1'h1");
1167 assert_eq!(format!("{:x}", x1), "1'h0");
1168 assert_eq!(format!("{:x}", x2), "1'h1");
1169 assert_eq!(format!("{:x}", x3), "1'h0");
1170 assert_eq!(format!("{:x}", x4), "1'h0");
1171 assert_eq!(format!("{:x}", x5), "1'h1");
1172 assert_eq!(format!("{:x}", x6), "1'h0");
1173 assert_eq!(format!("{:x}", x7), "1'h1");
1174 }
1175
1176 #[test]
1177 fn mixed_int_float_pow() {
1178 let x0 = calc_expression("2 ** (41 as f64)", None);
1179 let x1 = calc_expression("2 ** ((48 - 7) as f64)", None);
1180
1181 let expected = 2.0_f64.powf(41.0).to_bits();
1182 assert_eq!(x0.to_u64(), Some(expected), "2 ** (41 as f64)");
1183 assert_eq!(x1.to_u64(), Some(expected), "2 ** ((48-7) as f64)");
1184 }
1185
1186 #[test]
1187 fn context_width() {
1188 let x0 = calc_expression("(2'd0 - 2'd1) == 3'd7", None);
1189
1190 assert_eq!(format!("{:x}", x0), "1'h1");
1191 }
1192
1193 fn bit(width: usize) -> Box<Expression> {
1194 let mut t = Type::new(TypeKind::Bit);
1195 t.set_concrete_width(Shape::new(vec![Some(width)]));
1196 let ret = Comptime {
1197 value: ValueVariant::Unknown,
1198 r#type: t,
1199 ..Default::default()
1200 };
1201 Box::new(Expression::Term(Box::new(Factor::Value(ret))))
1202 }
1203
1204 fn logic(width: usize) -> Box<Expression> {
1205 let mut t = Type::new(TypeKind::Logic);
1206 t.set_concrete_width(Shape::new(vec![Some(width)]));
1207 let ret = Comptime {
1208 value: ValueVariant::Unknown,
1209 r#type: t,
1210 ..Default::default()
1211 };
1212 Box::new(Expression::Term(Box::new(Factor::Value(ret))))
1213 }
1214
1215 fn signed_bit(width: usize) -> Box<Expression> {
1216 let mut t = Type::new(TypeKind::Bit);
1217 t.set_concrete_width(Shape::new(vec![Some(width)]));
1218 t.signed = true;
1219 let ret = Comptime {
1220 value: ValueVariant::Unknown,
1221 r#type: t,
1222 ..Default::default()
1223 };
1224 Box::new(Expression::Term(Box::new(Factor::Value(ret))))
1225 }
1226
1227 fn signed_logic(width: usize) -> Box<Expression> {
1228 let mut t = Type::new(TypeKind::Logic);
1229 t.set_concrete_width(Shape::new(vec![Some(width)]));
1230 t.signed = true;
1231 let ret = Comptime {
1232 value: ValueVariant::Unknown,
1233 r#type: t,
1234 ..Default::default()
1235 };
1236 Box::new(Expression::Term(Box::new(Factor::Value(ret))))
1237 }
1238
1239 fn value(value: usize) -> Box<Expression> {
1240 let mut t = Type::new(TypeKind::Logic);
1241 t.set_concrete_width(Shape::new(vec![Some(32)]));
1242 let ret = Comptime {
1243 value: ValueVariant::Numeric(Value::new(value as u64, 32, false)),
1244 r#type: t,
1245 is_const: true,
1246 is_global: true,
1247 ..Default::default()
1248 };
1249 Box::new(Expression::Term(Box::new(Factor::Value(ret))))
1250 }
1251
1252 fn eval_comptime_unary(context: &mut Context, op: Op, x: Box<Expression>) -> Comptime {
1253 let comptime = Box::new(Comptime::create_unknown(TokenRange::default()));
1254 let mut ret = Expression::Unary(op, x, comptime);
1255 ret.eval_comptime(context, None).clone()
1256 }
1257
1258 fn eval_comptime_binary(
1259 context: &mut Context,
1260 x: Box<Expression>,
1261 op: Op,
1262 y: Box<Expression>,
1263 ) -> Comptime {
1264 let comptime = Box::new(Comptime::create_unknown(TokenRange::default()));
1265 let mut ret = Expression::Binary(x, op, y, comptime);
1266 ret.eval_comptime(context, None).clone()
1267 }
1268
1269 fn eval_comptime_ternary(
1270 context: &mut Context,
1271 x: Box<Expression>,
1272 y: Box<Expression>,
1273 z: Box<Expression>,
1274 ) -> Comptime {
1275 let comptime = Box::new(Comptime::create_unknown(TokenRange::default()));
1276 let mut ret = Expression::Ternary(x, y, z, comptime);
1277 ret.eval_comptime(context, None).clone()
1278 }
1279
1280 fn eval_comptime_concat(
1281 context: &mut Context,
1282 x: Vec<(Expression, Option<Expression>)>,
1283 ) -> Comptime {
1284 let comptime = Box::new(Comptime::create_unknown(TokenRange::default()));
1285 let mut ret = Expression::Concatenation(x, comptime);
1286 ret.eval_comptime(context, None).clone()
1287 }
1288
1289 #[test]
1290 fn unary_type() {
1291 let mut context = Context::default();
1292
1293 let x0 = eval_comptime_unary(&mut context, Op::BitAnd, bit(3));
1294 let x1 = eval_comptime_unary(&mut context, Op::BitAnd, logic(4));
1295 let x2 = eval_comptime_unary(&mut context, Op::BitNot, bit(3));
1296 let x3 = eval_comptime_unary(&mut context, Op::BitNot, logic(4));
1297 let x4 = eval_comptime_unary(&mut context, Op::LogicNot, bit(1));
1298 let x5 = eval_comptime_unary(&mut context, Op::LogicNot, logic(1));
1299 let x6 = eval_comptime_unary(&mut context, Op::Add, bit(3));
1300 let x7 = eval_comptime_unary(&mut context, Op::Add, logic(4));
1301
1302 let errors = context.drain_errors();
1303 assert!(errors.is_empty());
1304
1305 assert_eq!(format!("{}", x0.r#type), "bit<1>");
1306 assert_eq!(format!("{}", x1.r#type), "logic<1>");
1307 assert_eq!(format!("{}", x2.r#type), "bit<3>");
1308 assert_eq!(format!("{}", x3.r#type), "logic<4>");
1309 assert_eq!(format!("{}", x4.r#type), "bit<1>");
1310 assert_eq!(format!("{}", x5.r#type), "logic<1>");
1311 assert_eq!(format!("{}", x6.r#type), "bit<3>");
1312 assert_eq!(format!("{}", x7.r#type), "logic<4>");
1313 }
1314
1315 #[test]
1316 fn binary_type() {
1317 let mut context = Context::default();
1318
1319 let x00 = eval_comptime_binary(&mut context, bit(4), Op::Add, bit(3));
1320 let x01 = eval_comptime_binary(&mut context, bit(4), Op::Add, logic(3));
1321 let x02 = eval_comptime_binary(&mut context, logic(4), Op::Add, logic(3));
1322 let x03 = eval_comptime_binary(&mut context, bit(4), Op::Eq, bit(3));
1323 let x04 = eval_comptime_binary(&mut context, bit(4), Op::Eq, logic(3));
1324 let x05 = eval_comptime_binary(&mut context, logic(4), Op::Eq, logic(3));
1325 let x06 = eval_comptime_binary(&mut context, bit(1), Op::LogicAnd, bit(1));
1326 let x07 = eval_comptime_binary(&mut context, bit(1), Op::LogicAnd, logic(1));
1327 let x08 = eval_comptime_binary(&mut context, logic(1), Op::LogicAnd, logic(1));
1328 let x09 = eval_comptime_binary(&mut context, signed_bit(4), Op::ArithShiftL, bit(3));
1329 let x10 = eval_comptime_binary(&mut context, signed_bit(4), Op::ArithShiftL, logic(3));
1330 let x11 = eval_comptime_binary(&mut context, signed_logic(4), Op::ArithShiftL, logic(3));
1331
1332 let errors = context.drain_errors();
1333 assert!(errors.is_empty());
1334
1335 assert_eq!(format!("{}", x00.r#type), "bit<4>");
1336 assert_eq!(format!("{}", x01.r#type), "logic<4>");
1337 assert_eq!(format!("{}", x02.r#type), "logic<4>");
1338 assert_eq!(format!("{}", x03.r#type), "bit<1>");
1339 assert_eq!(format!("{}", x04.r#type), "logic<1>");
1340 assert_eq!(format!("{}", x05.r#type), "logic<1>");
1341 assert_eq!(format!("{}", x06.r#type), "bit<1>");
1342 assert_eq!(format!("{}", x07.r#type), "logic<1>");
1343 assert_eq!(format!("{}", x08.r#type), "logic<1>");
1344 assert_eq!(format!("{}", x09.r#type), "signed bit<4>");
1345 assert_eq!(format!("{}", x10.r#type), "signed bit<4>");
1346 assert_eq!(format!("{}", x11.r#type), "signed logic<4>");
1347 }
1348
1349 #[test]
1350 fn ternary_type() {
1351 let mut context = Context::default();
1352
1353 let x0 = eval_comptime_ternary(&mut context, bit(1), bit(4), bit(3));
1354 let x1 = eval_comptime_ternary(&mut context, bit(1), bit(4), logic(3));
1355 let x2 = eval_comptime_ternary(&mut context, bit(1), logic(4), bit(3));
1356 let x3 = eval_comptime_ternary(&mut context, bit(1), logic(4), logic(3));
1357 let x4 = eval_comptime_ternary(&mut context, logic(1), bit(4), bit(3));
1358 let x5 = eval_comptime_ternary(&mut context, logic(1), bit(4), logic(3));
1359 let x6 = eval_comptime_ternary(&mut context, logic(1), logic(4), bit(3));
1360 let x7 = eval_comptime_ternary(&mut context, logic(1), logic(4), logic(3));
1361
1362 let errors = context.drain_errors();
1363 assert!(errors.is_empty());
1364
1365 assert_eq!(format!("{}", x0.r#type), "bit<4>");
1366 assert_eq!(format!("{}", x1.r#type), "logic<4>");
1367 assert_eq!(format!("{}", x2.r#type), "logic<4>");
1368 assert_eq!(format!("{}", x3.r#type), "logic<4>");
1369 assert_eq!(format!("{}", x4.r#type), "bit<4>");
1370 assert_eq!(format!("{}", x5.r#type), "logic<4>");
1371 assert_eq!(format!("{}", x6.r#type), "logic<4>");
1372 assert_eq!(format!("{}", x7.r#type), "logic<4>");
1373 }
1374
1375 #[test]
1376 fn concat_type() {
1377 let mut context = Context::default();
1378
1379 let x0 = eval_comptime_concat(
1380 &mut context,
1381 vec![(*bit(1), None), (*bit(4), None), (*bit(3), None)],
1382 );
1383 let x1 = eval_comptime_concat(
1384 &mut context,
1385 vec![(*bit(1), None), (*logic(4), None), (*bit(3), None)],
1386 );
1387 let x2 = eval_comptime_concat(
1388 &mut context,
1389 vec![(*logic(1), None), (*logic(4), None), (*logic(3), None)],
1390 );
1391 let x3 = eval_comptime_concat(
1392 &mut context,
1393 vec![(*bit(1), Some(*value(2))), (*bit(4), None), (*bit(3), None)],
1394 );
1395 let x4 = eval_comptime_concat(
1396 &mut context,
1397 vec![
1398 (*bit(1), None),
1399 (*logic(4), Some(*value(2))),
1400 (*bit(3), None),
1401 ],
1402 );
1403 let x5 = eval_comptime_concat(
1404 &mut context,
1405 vec![
1406 (*logic(1), None),
1407 (*logic(4), None),
1408 (*logic(3), Some(*value(3))),
1409 ],
1410 );
1411
1412 let errors = context.drain_errors();
1413 assert!(errors.is_empty());
1414
1415 assert_eq!(format!("{}", x0.r#type), "bit<8>");
1416 assert_eq!(format!("{}", x1.r#type), "logic<8>");
1417 assert_eq!(format!("{}", x2.r#type), "logic<8>");
1418 assert_eq!(format!("{}", x3.r#type), "bit<9>");
1419 assert_eq!(format!("{}", x4.r#type), "logic<12>");
1420 assert_eq!(format!("{}", x5.r#type), "logic<14>");
1421 }
1422}