Skip to main content

veryl_analyzer/conv/
expression.rs

1use crate::analyzer_error::AnalyzerError;
2use crate::conv::utils::{
3    TypePosition, case_condition, eval_expr, eval_factor_path, eval_function_call, eval_size,
4    eval_struct_constructor, eval_type, range_list, switch_condition,
5};
6use crate::conv::{Context, Conv};
7use crate::ir::{
8    self, Comptime, IrResult, Op, Shape, Type, TypeKind, ValueVariant, VarPath, VarPathSelect,
9};
10use crate::symbol::SymbolKind;
11use crate::symbol_path::GenericSymbolPath;
12use crate::symbol_table;
13use crate::value::{Value, string_to_byte_value};
14use crate::{ir_error, msb_table};
15use veryl_parser::token_range::TokenRange;
16use veryl_parser::veryl_grammar_trait::*;
17
18impl Conv<&Expression> for ir::Expression {
19    fn conv(context: &mut Context, value: &Expression) -> IrResult<Self> {
20        Conv::conv(context, value.if_expression.as_ref())
21    }
22}
23
24fn is_if_expression(value: &Expression) -> bool {
25    !value.if_expression.if_expression_list.is_empty()
26}
27
28impl Conv<&IfExpression> for ir::Expression {
29    fn conv(context: &mut Context, value: &IfExpression) -> IrResult<Self> {
30        let mut ret: ir::Expression = Conv::conv(context, value.expression01.as_ref())?;
31        for x in value.if_expression_list.iter().rev() {
32            let y: ir::Expression = Conv::conv(context, x.expression.as_ref())?;
33            let z: ir::Expression = Conv::conv(context, x.expression0.as_ref())?;
34
35            if is_if_expression(&x.expression) {
36                let token: TokenRange = x.expression.as_ref().into();
37                context.insert_error(AnalyzerError::unenclosed_inner_if_expression(&token));
38            }
39            if is_if_expression(&x.expression0) {
40                let token: TokenRange = x.expression0.as_ref().into();
41                context.insert_error(AnalyzerError::unenclosed_inner_if_expression(&token));
42            }
43
44            let token = TokenRange::from_range(&y.token_range(), &ret.token_range());
45            let comptime = Box::new(Comptime::create_unknown(token));
46
47            ret = ir::Expression::Ternary(Box::new(y), Box::new(z), Box::new(ret), comptime);
48        }
49        Ok(ret)
50    }
51}
52
53fn resolve_op(op: &Expression01Op) -> (Op, u32) {
54    match op {
55        Expression01Op::Operator01(x) => {
56            let tok = x.operator01.operator01_token.to_string();
57            match tok.as_str() {
58                "||" => (Op::LogicOr, 1),
59                "&&" => (Op::LogicAnd, 2),
60                _ => unreachable!(),
61            }
62        }
63        Expression01Op::Operator03(_) => (Op::BitOr, 3),
64        Expression01Op::Operator04(x) => {
65            let tok = x.operator04.operator04_token.to_string();
66            match tok.as_str() {
67                "^" => (Op::BitXor, 4),
68                "~^" => (Op::BitXnor, 4),
69                _ => unreachable!(),
70            }
71        }
72        Expression01Op::Operator05(_) => (Op::BitAnd, 5),
73        Expression01Op::Operator02(x) => {
74            let tok = x.operator02.operator02_token.to_string();
75            match tok.as_str() {
76                "==" => (Op::Eq, 6),
77                "!=" => (Op::Ne, 6),
78                "==?" => (Op::EqWildcard, 6),
79                "!=?" => (Op::NeWildcard, 6),
80                "<=" => (Op::LessEq, 7),
81                ">=" => (Op::GreaterEq, 7),
82                "<:" => (Op::Less, 7),
83                ">:" => (Op::Greater, 7),
84                "<<<" => (Op::ArithShiftL, 8),
85                ">>>" => (Op::ArithShiftR, 8),
86                "<<" => (Op::LogicShiftL, 8),
87                ">>" => (Op::LogicShiftR, 8),
88                _ => unreachable!(),
89            }
90        }
91        Expression01Op::Operator06(x) => {
92            let tok = x.operator06.operator06_token.to_string();
93            match tok.as_str() {
94                "+" => (Op::Add, 9),
95                "-" => (Op::Sub, 9),
96                _ => unreachable!(),
97            }
98        }
99        Expression01Op::Operator07(x) => {
100            let tok = x.operator07.operator07_token.to_string();
101            match tok.as_str() {
102                "/" => (Op::Div, 10),
103                "%" => (Op::Rem, 10),
104                _ => unreachable!(),
105            }
106        }
107        Expression01Op::Star(_) => (Op::Mul, 10),
108        Expression01Op::Operator08(_) => (Op::Pow, 11),
109    }
110}
111
112fn prec_climb(
113    context: &mut Context,
114    exprs: &[&Expression02],
115    ops: &[(Op, u32)],
116    lo: usize,
117    hi: usize,
118) -> IrResult<ir::Expression> {
119    if lo == hi {
120        return Conv::conv(context, exprs[lo]);
121    }
122    // find the lowest-precedence (leftmost if tied) operator in [lo..hi)
123    let mut min_idx = lo;
124    let mut min_prec = ops[lo].1;
125    for (i, op) in ops.iter().enumerate().take(hi).skip(lo + 1) {
126        if op.1 <= min_prec {
127            min_idx = i;
128            min_prec = op.1;
129        }
130    }
131    let left = prec_climb(context, exprs, ops, lo, min_idx)?;
132    let right = prec_climb(context, exprs, ops, min_idx + 1, hi)?;
133    let token = TokenRange::from_range(&left.token_range(), &right.token_range());
134    let comptime = Box::new(Comptime::create_unknown(token));
135    Ok(ir::Expression::Binary(
136        Box::new(left),
137        ops[min_idx].0,
138        Box::new(right),
139        comptime,
140    ))
141}
142
143impl Conv<&Expression01> for ir::Expression {
144    fn conv(context: &mut Context, value: &Expression01) -> IrResult<Self> {
145        if value.expression01_list.is_empty() {
146            return Conv::conv(context, value.expression02.as_ref());
147        }
148
149        let mut exprs: Vec<&Expression02> = vec![value.expression02.as_ref()];
150        let mut ops: Vec<(Op, u32)> = Vec::new();
151
152        for x in &value.expression01_list {
153            let (op, prec) = resolve_op(x.expression01_op.as_ref());
154            ops.push((op, prec));
155            exprs.push(x.expression02.as_ref());
156        }
157
158        prec_climb(context, &exprs, &ops, 0, exprs.len() - 1)
159    }
160}
161
162impl Conv<&Expression02> for ir::Expression {
163    fn conv(context: &mut Context, value: &Expression02) -> IrResult<Self> {
164        let mut ret: ir::Expression = Conv::conv(context, value.factor.as_ref())?;
165
166        // optional `as` cast
167        if let Some(x) = &value.expression02_opt {
168            let right: ir::Factor = Conv::conv(context, x.casting_type.as_ref())?;
169
170            let token = TokenRange::from_range(&ret.token_range(), &right.token_range());
171            let comptime = Box::new(Comptime::create_unknown(token));
172
173            ret = ir::Expression::Binary(
174                Box::new(ret),
175                Op::As,
176                Box::new(ir::Expression::Term(Box::new(right))),
177                comptime,
178            );
179        }
180
181        // unary prefix operators (reverse iteration for right-associativity)
182        for x in value.expression02_list.iter().rev() {
183            let op = match x.expression02_op.as_ref() {
184                Expression02Op::UnaryOperator(x) => {
185                    let token = x.unary_operator.unary_operator_token.to_string();
186                    match token.as_str() {
187                        "~&" => Op::BitNand,
188                        "~|" => Op::BitNor,
189                        "~" => Op::BitNot,
190                        "!" => Op::LogicNot,
191                        _ => unreachable!(),
192                    }
193                }
194                Expression02Op::Operator03(_) => Op::BitOr,
195                Expression02Op::Operator04(x) => {
196                    let token = x.operator04.operator04_token.to_string();
197                    match token.as_str() {
198                        "^" => Op::BitXor,
199                        "~^" => Op::BitXnor,
200                        _ => unreachable!(),
201                    }
202                }
203                Expression02Op::Operator05(_) => Op::BitAnd,
204                Expression02Op::Operator06(x) => {
205                    let token = x.operator06.operator06_token.to_string();
206                    match token.as_str() {
207                        "+" => Op::Add,
208                        "-" => Op::Sub,
209                        _ => unreachable!(),
210                    }
211                }
212            };
213
214            let token: TokenRange = value.into();
215            let comptime = Box::new(Comptime::create_unknown(token));
216            ret = ir::Expression::Unary(op, Box::new(ret), comptime);
217        }
218
219        Ok(ret)
220    }
221}
222
223impl Conv<&FactorType> for ir::Factor {
224    fn conv(context: &mut Context, value: &FactorType) -> IrResult<Self> {
225        let token = value.into();
226        let mut is_global = true;
227        let value = match value.factor_type_group.as_ref() {
228            FactorTypeGroup::VariableTypeFactorTypeOpt(x) => {
229                let width = if let Some(x) = &x.factor_type_opt {
230                    let exprs: Vec<_> = x.width.as_ref().into();
231                    let mut ret = Shape::default();
232                    for expr in exprs {
233                        let (comptime, value) = eval_size(context, expr, false)?;
234
235                        is_global &= comptime.is_global;
236
237                        ret.push(value);
238                    }
239                    ret
240                } else {
241                    Shape::new(vec![Some(1)])
242                };
243                let kind = match x.variable_type.as_ref() {
244                    VariableType::Clock(_) => TypeKind::Clock,
245                    VariableType::ClockPosedge(_) => TypeKind::ClockPosedge,
246                    VariableType::ClockNegedge(_) => TypeKind::ClockNegedge,
247                    VariableType::Reset(_) => TypeKind::Reset,
248                    VariableType::ResetAsyncHigh(_) => TypeKind::ResetAsyncHigh,
249                    VariableType::ResetAsyncLow(_) => TypeKind::ResetAsyncLow,
250                    VariableType::ResetSyncHigh(_) => TypeKind::ResetSyncHigh,
251                    VariableType::ResetSyncLow(_) => TypeKind::ResetSyncLow,
252                    VariableType::Logic(_) => TypeKind::Logic,
253                    VariableType::Bit(_) => TypeKind::Bit,
254                };
255                {
256                    let mut t = Type::new(kind);
257                    t.set_concrete_width(width);
258                    t
259                }
260            }
261            FactorTypeGroup::FixedType(x) => {
262                let (kind, width, signed, is_positive) = match x.fixed_type.as_ref() {
263                    FixedType::P8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), false, true),
264                    FixedType::P16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), false, true),
265                    FixedType::P32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), false, true),
266                    FixedType::P64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), false, true),
267                    FixedType::U8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), false, false),
268                    FixedType::U16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), false, false),
269                    FixedType::U32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), false, false),
270                    FixedType::U64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), false, false),
271                    FixedType::I8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), true, false),
272                    FixedType::I16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), true, false),
273                    FixedType::I32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), true, false),
274                    FixedType::I64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), true, false),
275                    FixedType::F32(_) => (TypeKind::F32, Shape::new(vec![Some(32)]), false, false),
276                    FixedType::F64(_) => (TypeKind::F64, Shape::new(vec![Some(64)]), false, false),
277                    FixedType::BBool(_) => (TypeKind::Bit, Shape::new(vec![Some(1)]), false, false),
278                    FixedType::LBool(_) => (TypeKind::Bit, Shape::new(vec![Some(1)]), false, false),
279                    FixedType::Strin(_) => {
280                        (TypeKind::Unknown, Shape::new(vec![Some(1)]), false, false)
281                    }
282                };
283                {
284                    let mut t = Type::new(kind);
285                    t.set_concrete_width(width);
286                    t.signed = signed;
287                    t.is_positive = is_positive;
288                    t
289                }
290            }
291        };
292        let r#type = Type::new(TypeKind::Type);
293        let ret = Comptime {
294            value: ValueVariant::Type(value),
295            r#type,
296            is_const: true,
297            is_global,
298            token,
299            ..Default::default()
300        };
301        Ok(ir::Factor::Value(ret))
302    }
303}
304
305impl Conv<&CastingType> for ir::Factor {
306    fn conv(context: &mut Context, value: &CastingType) -> IrResult<Self> {
307        let token = value.into();
308        let value = if let CastingType::UserDefinedType(x) = value {
309            let identifier = x.user_defined_type.scoped_identifier.as_ref();
310            let symbol_path: GenericSymbolPath = identifier.into();
311
312            let r#type = eval_type(context, &symbol_path, TypePosition::Cast);
313            if r#type.is_ok() {
314                r#type?
315            } else {
316                let var_path: VarPathSelect = Conv::conv(context, identifier)?;
317                return eval_factor_path(context, symbol_path, var_path, false, token);
318            }
319        } else {
320            let (kind, width, signed, is_positive) = match value {
321                CastingType::P8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), false, true),
322                CastingType::P16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), false, true),
323                CastingType::P32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), false, true),
324                CastingType::P64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), false, true),
325                CastingType::U8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), false, false),
326                CastingType::U16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), false, false),
327                CastingType::U32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), false, false),
328                CastingType::U64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), false, false),
329                CastingType::I8(_) => (TypeKind::Bit, Shape::new(vec![Some(8)]), true, false),
330                CastingType::I16(_) => (TypeKind::Bit, Shape::new(vec![Some(16)]), true, false),
331                CastingType::I32(_) => (TypeKind::Bit, Shape::new(vec![Some(32)]), true, false),
332                CastingType::I64(_) => (TypeKind::Bit, Shape::new(vec![Some(64)]), true, false),
333                CastingType::F32(_) => (TypeKind::F32, Shape::new(vec![Some(32)]), false, false),
334                CastingType::F64(_) => (TypeKind::F64, Shape::new(vec![Some(64)]), false, false),
335                CastingType::BBool(_) => (TypeKind::Bit, Shape::new(vec![Some(1)]), false, false),
336                CastingType::LBool(_) => (TypeKind::Bit, Shape::new(vec![Some(1)]), false, false),
337                CastingType::Clock(_) => (TypeKind::Clock, Shape::new(vec![Some(1)]), false, false),
338                CastingType::ClockPosedge(_) => (
339                    TypeKind::ClockPosedge,
340                    Shape::new(vec![Some(1)]),
341                    false,
342                    false,
343                ),
344                CastingType::ClockNegedge(_) => (
345                    TypeKind::ClockNegedge,
346                    Shape::new(vec![Some(1)]),
347                    false,
348                    false,
349                ),
350                CastingType::Reset(_) => (TypeKind::Reset, Shape::new(vec![Some(1)]), false, false),
351                CastingType::ResetAsyncHigh(_) => (
352                    TypeKind::ResetAsyncHigh,
353                    Shape::new(vec![Some(1)]),
354                    false,
355                    false,
356                ),
357                CastingType::ResetAsyncLow(_) => (
358                    TypeKind::ResetAsyncLow,
359                    Shape::new(vec![Some(1)]),
360                    false,
361                    false,
362                ),
363                CastingType::ResetSyncHigh(_) => (
364                    TypeKind::ResetSyncHigh,
365                    Shape::new(vec![Some(1)]),
366                    false,
367                    false,
368                ),
369                CastingType::ResetSyncLow(_) => (
370                    TypeKind::ResetSyncLow,
371                    Shape::new(vec![Some(1)]),
372                    false,
373                    false,
374                ),
375                CastingType::Based(x) => {
376                    let token: TokenRange = x.based.based_token.token.into();
377                    let comptime: Comptime = Conv::conv(context, x.based.as_ref())?;
378
379                    if let Ok(value) = comptime.get_value()
380                        && let Some(value) = value.to_usize()
381                    {
382                        let _ = context.check_size(value, token);
383                    }
384
385                    return Ok(ir::Factor::Value(comptime));
386                }
387                CastingType::BaseLess(x) => {
388                    let token: TokenRange = x.base_less.base_less_token.token.into();
389                    let comptime: Comptime = Conv::conv(context, x.base_less.as_ref())?;
390
391                    if let Ok(value) = comptime.get_value()
392                        && let Some(value) = value.to_usize()
393                    {
394                        let _ = context.check_size(value, token);
395                    }
396
397                    return Ok(ir::Factor::Value(comptime));
398                }
399                CastingType::UserDefinedType(_) => unreachable!(),
400            };
401            {
402                let mut t = Type::new(kind);
403                t.set_concrete_width(width);
404                t.signed = signed;
405                t.is_positive = is_positive;
406                t
407            }
408        };
409
410        let r#type = Type::new(TypeKind::Type);
411        let ret = Comptime {
412            value: ValueVariant::Type(value),
413            r#type,
414            is_const: true,
415            is_global: true,
416            token,
417            ..Default::default()
418        };
419        Ok(ir::Factor::Value(ret))
420    }
421}
422
423impl Conv<&Factor> for ir::Expression {
424    fn conv(context: &mut Context, value: &Factor) -> IrResult<Self> {
425        let token = value.into();
426        match value {
427            Factor::Number(x) => {
428                let x: Comptime = Conv::conv(context, x.number.as_ref())?;
429                Ok(ir::Expression::Term(Box::new(ir::Factor::Value(x))))
430            }
431            Factor::BooleanLiteral(x) => {
432                let x = match x.boolean_literal.as_ref() {
433                    BooleanLiteral::True(_) => 1,
434                    BooleanLiteral::False(_) => 0,
435                };
436                let value = Value::new(x, 1, false);
437                let r#type = {
438                    let mut t = Type::new(TypeKind::Bit);
439                    t.set_concrete_width(Shape::new(vec![Some(1)]));
440                    t
441                };
442                let ret = Comptime {
443                    value: ValueVariant::Numeric(value),
444                    r#type,
445                    is_const: true,
446                    is_global: true,
447                    token,
448                    ..Default::default()
449                };
450                Ok(ir::Expression::Term(Box::new(ir::Factor::Value(ret))))
451            }
452            Factor::IdentifierFactor(x) => Conv::conv(context, x.identifier_factor.as_ref()),
453            Factor::LParenExpressionRParen(x) => Conv::conv(context, x.expression.as_ref()),
454            Factor::LBraceConcatenationListRBrace(x) => {
455                let x = x.concatenation_list.as_ref();
456                let exp: ir::Expression =
457                    Conv::conv(context, x.concatenation_item.expression.as_ref())?;
458                let rep: Option<ir::Expression> =
459                    if let Some(x) = x.concatenation_item.concatenation_item_opt.as_ref() {
460                        Some(Conv::conv(context, x.expression.as_ref())?)
461                    } else {
462                        None
463                    };
464                let mut ret = vec![(exp, rep)];
465
466                for x in &x.concatenation_list_list {
467                    let exp: ir::Expression =
468                        Conv::conv(context, x.concatenation_item.expression.as_ref())?;
469                    let rep: Option<ir::Expression> =
470                        if let Some(x) = x.concatenation_item.concatenation_item_opt.as_ref() {
471                            Some(Conv::conv(context, x.expression.as_ref())?)
472                        } else {
473                            None
474                        };
475                    ret.push((exp, rep));
476                }
477
478                let comptime = Box::new(Comptime::create_unknown(token));
479
480                Ok(ir::Expression::Concatenation(ret, comptime))
481            }
482            Factor::QuoteLBraceArrayLiteralListRBrace(x) => {
483                let items: Vec<_> = x.array_literal_list.as_ref().into();
484                let mut ret = vec![];
485
486                for item in items {
487                    let item = match item.array_literal_item_group.as_ref() {
488                        ArrayLiteralItemGroup::ExpressionArrayLiteralItemOpt(x) => {
489                            let rep: Option<ir::Expression> =
490                                if let Some(x) = x.array_literal_item_opt.as_ref() {
491                                    Some(Conv::conv(context, x.expression.as_ref())?)
492                                } else {
493                                    None
494                                };
495                            let rep = rep.map(Box::new);
496                            let exp: ir::Expression = Conv::conv(context, x.expression.as_ref())?;
497                            let exp = Box::new(exp);
498                            ir::ArrayLiteralItem::Value(exp, rep)
499                        }
500                        ArrayLiteralItemGroup::DefaulColonExpression(x) => {
501                            let exp: ir::Expression = Conv::conv(context, x.expression.as_ref())?;
502                            ir::ArrayLiteralItem::Defaul(Box::new(exp))
503                        }
504                    };
505                    ret.push(item);
506                }
507
508                let comptime = Box::new(Comptime::create_unknown(token));
509
510                Ok(ir::Expression::ArrayLiteral(ret, comptime))
511            }
512            Factor::CaseExpression(x) => {
513                let mut tgt: ir::Expression =
514                    Conv::conv(context, x.case_expression.expression.as_ref())?;
515                tgt.eval_comptime(context, None);
516                let exp: ir::Expression =
517                    Conv::conv(context, x.case_expression.expression0.as_ref())?;
518                let defaul: ir::Expression =
519                    Conv::conv(context, x.case_expression.expression1.as_ref())?;
520                let cond =
521                    case_condition(context, &tgt, x.case_expression.case_condition.as_ref())?;
522
523                let comptime = Box::new(Comptime::create_unknown(token));
524
525                let mut ret = ir::Expression::Ternary(
526                    Box::new(cond),
527                    Box::new(exp),
528                    Box::new(defaul),
529                    comptime,
530                );
531
532                for x in &x.case_expression.case_expression_list {
533                    let cond = case_condition(context, &tgt, x.case_condition.as_ref())?;
534                    let exp: ir::Expression = Conv::conv(context, x.expression.as_ref())?;
535
536                    if let ir::Expression::Ternary(x, y, z, comptime) = ret {
537                        let arm = ir::Expression::Ternary(
538                            Box::new(cond),
539                            Box::new(exp),
540                            z,
541                            comptime.clone(),
542                        );
543                        ret = ir::Expression::Ternary(x, y, Box::new(arm), comptime);
544                    } else {
545                        unreachable!()
546                    }
547                }
548                Ok(ret)
549            }
550            Factor::SwitchExpression(x) => {
551                let exp: ir::Expression =
552                    Conv::conv(context, x.switch_expression.expression.as_ref())?;
553                let defaul: ir::Expression =
554                    Conv::conv(context, x.switch_expression.expression0.as_ref())?;
555                let cond =
556                    switch_condition(context, x.switch_expression.switch_condition.as_ref())?;
557
558                let comptime = Box::new(Comptime::create_unknown(token));
559
560                let mut ret = ir::Expression::Ternary(
561                    Box::new(cond),
562                    Box::new(exp),
563                    Box::new(defaul),
564                    comptime,
565                );
566
567                for x in &x.switch_expression.switch_expression_list {
568                    let cond = switch_condition(context, x.switch_condition.as_ref())?;
569                    let exp: ir::Expression = Conv::conv(context, x.expression.as_ref())?;
570
571                    if let ir::Expression::Ternary(x, y, z, comptime) = ret {
572                        let arm = ir::Expression::Ternary(
573                            Box::new(cond),
574                            Box::new(exp),
575                            z,
576                            comptime.clone(),
577                        );
578                        ret = ir::Expression::Ternary(x, y, Box::new(arm), comptime);
579                    } else {
580                        unreachable!()
581                    }
582                }
583                Ok(ret)
584            }
585            Factor::StringLiteral(x) => {
586                let text = x.string_literal.string_literal_token.token.text;
587                let text_str =
588                    veryl_parser::resource_table::get_str_value(text).unwrap_or_default();
589                let value = string_to_byte_value(&text_str);
590                let width = value.width() as usize;
591                let r#type = {
592                    let mut t = Type::new(TypeKind::String);
593                    t.set_concrete_width(Shape::new(vec![Some(width)]));
594                    t
595                };
596                let ret = Comptime {
597                    value: ValueVariant::Numeric(value),
598                    r#type,
599                    is_const: true,
600                    is_global: true,
601                    token,
602                    ..Default::default()
603                };
604                Ok(ir::Expression::Term(Box::new(ir::Factor::Value(ret))))
605            }
606            Factor::FactorGroup(x) => {
607                let Some((path, generic_path)) = context.select_paths.last().cloned() else {
608                    return Err(ir_error!(token));
609                };
610
611                match x.factor_group.as_ref() {
612                    FactorGroup::Msb(msb) => {
613                        if let Some((_, comptime)) = context.find_path(&path) {
614                            // msb through interface is forbidden
615                            // https://github.com/veryl-lang/veryl/pull/1154
616                            if let Some((_, comptime)) =
617                                context.find_path(&VarPath::new(path.first()))
618                                && comptime.r#type.is_interface()
619                            {
620                                return Err(ir_error!(token));
621                            }
622
623                            if comptime.r#type.is_systemverilog() {
624                                return Err(ir_error!(token));
625                            }
626
627                            let dim = context.get_select_dim().unwrap();
628
629                            let width =
630                                if comptime.r#type.is_struct() || comptime.r#type.is_unknown() {
631                                    comptime.r#type.total_width()
632                                } else {
633                                    comptime.r#type.width()[dim]
634                                };
635                            let comptime = if let Some(width) = width {
636                                let msb = width.saturating_sub(1);
637                                Comptime::create_value(Value::new(msb as u64, 32, false), token)
638                            } else {
639                                let mut ret =
640                                    Comptime::create_value(Value::new(0, 32, false), token);
641                                ret.value = ValueVariant::Unknown;
642                                ret
643                            };
644                            Ok(ir::Expression::Term(Box::new(ir::Factor::Value(comptime))))
645                        } else if let Ok(symbol) = symbol_table::resolve(&generic_path)
646                            && let SymbolKind::Parameter(x) = &symbol.found.kind
647                        {
648                            let r#type = x.r#type.to_ir_type(context, TypePosition::Variable)?;
649                            let dim = context.get_select_dim().unwrap();
650
651                            msb_table::insert(msb.msb.msb_token.token.id, dim + 1);
652
653                            let width = if r#type.is_struct() {
654                                r#type.total_width()
655                            } else {
656                                r#type.width()[dim]
657                            };
658                            let msb = if let Some(width) = width {
659                                width - 1
660                            } else {
661                                0
662                            };
663                            Ok(ir::Expression::create_value(
664                                Value::new(msb as u64, 32, false),
665                                token,
666                            ))
667                        } else {
668                            context.insert_error(AnalyzerError::unknown_msb(&token));
669                            Err(ir_error!(token))
670                        }
671                    }
672                    FactorGroup::Lsb(_) => Ok(ir::Expression::create_value(
673                        Value::new(0, 32, false),
674                        token,
675                    )),
676                }
677            }
678            Factor::InsideExpression(x) => {
679                let mut exp: ir::Expression =
680                    Conv::conv(context, x.inside_expression.expression.as_ref())?;
681                exp.eval_comptime(context, None);
682                let ret = range_list(context, &exp, x.inside_expression.range_list.as_ref())?;
683                Ok(ret)
684            }
685            Factor::OutsideExpression(x) => {
686                let mut exp: ir::Expression =
687                    Conv::conv(context, x.outside_expression.expression.as_ref())?;
688                exp.eval_comptime(context, None);
689                let ret = range_list(context, &exp, x.outside_expression.range_list.as_ref())?;
690                let comptime = Box::new(Comptime::create_unknown(token));
691                Ok(ir::Expression::Unary(Op::LogicNot, Box::new(ret), comptime))
692            }
693            Factor::TypeExpression(x) => {
694                let (comptime, _) = eval_expr(context, None, &x.type_expression.expression, false)?;
695                let r#type = Type::new(TypeKind::Type);
696                let ret = Comptime {
697                    value: ValueVariant::Type(comptime.r#type),
698                    r#type,
699                    is_const: true,
700                    is_global: comptime.is_global,
701                    token,
702                    ..Default::default()
703                };
704                Ok(ir::Expression::Term(Box::new(ir::Factor::Value(ret))))
705            }
706            Factor::FactorTypeFactor(x) => {
707                let ret = Conv::conv(context, x.factor_type_factor.factor_type.as_ref())?;
708                Ok(ir::Expression::Term(Box::new(ret)))
709            }
710        }
711    }
712}
713
714impl Conv<&IdentifierFactor> for ir::Expression {
715    fn conv(context: &mut Context, value: &IdentifierFactor) -> IrResult<Self> {
716        let token: TokenRange = value.into();
717        if let Some(x) = &value.identifier_factor_opt {
718            let x = x.identifier_factor_opt_group.as_ref();
719            match x {
720                IdentifierFactorOptGroup::FunctionCall(_) => {
721                    eval_function_call(context, value, token)
722                }
723                IdentifierFactorOptGroup::StructConstructor(_) => {
724                    eval_struct_constructor(context, value, token)
725                }
726            }
727        } else {
728            let var_path: VarPathSelect =
729                Conv::conv(context, value.expression_identifier.as_ref())?;
730            let symbol_path: GenericSymbolPath = value.expression_identifier.as_ref().into();
731
732            let factor = eval_factor_path(context, symbol_path, var_path, true, token)?;
733            Ok(ir::Expression::Term(Box::new(factor)))
734        }
735    }
736}
737
738impl Conv<&Number> for Comptime {
739    fn conv(context: &mut Context, value: &Number) -> IrResult<Self> {
740        match value {
741            Number::IntegralNumber(x) => match x.integral_number.as_ref() {
742                IntegralNumber::Based(x) => Conv::conv(context, x.based.as_ref()),
743                IntegralNumber::BaseLess(x) => Conv::conv(context, x.base_less.as_ref()),
744                IntegralNumber::AllBit(x) => Conv::conv(context, x.all_bit.as_ref()),
745            },
746            Number::RealNumber(x) => Conv::conv(context, x.real_number.as_ref()),
747        }
748    }
749}
750
751impl Conv<&Based> for Comptime {
752    fn conv(context: &mut Context, value: &Based) -> IrResult<Self> {
753        let token: TokenRange = value.into();
754        let value: Value = value.into();
755
756        let kind = if value.is_xz() {
757            TypeKind::Logic
758        } else {
759            TypeKind::Bit
760        };
761
762        let width = context.check_size(value.width(), token);
763
764        let mut r#type = Type::new(kind);
765        r#type.signed = value.signed();
766        r#type.set_concrete_width(Shape::new(vec![width]));
767
768        Ok(Comptime {
769            value: ValueVariant::Numeric(value),
770            r#type,
771            is_const: true,
772            is_global: true,
773            token,
774            ..Default::default()
775        })
776    }
777}
778
779impl Conv<&BaseLess> for Comptime {
780    fn conv(_context: &mut Context, value: &BaseLess) -> IrResult<Self> {
781        let token: TokenRange = value.into();
782        let value: Value = value.into();
783        let mut r#type = Type::new(TypeKind::Bit);
784        r#type.signed = true;
785        r#type.set_concrete_width(Shape::new(vec![Some(32)]));
786
787        Ok(Comptime {
788            value: ValueVariant::Numeric(value),
789            r#type,
790            is_const: true,
791            is_global: true,
792            token,
793            ..Default::default()
794        })
795    }
796}
797
798impl Conv<&AllBit> for Comptime {
799    fn conv(_context: &mut Context, value: &AllBit) -> IrResult<Self> {
800        let token: TokenRange = value.into();
801        let value: Value = value.into();
802
803        let kind = if value.is_xz() {
804            TypeKind::Logic
805        } else {
806            TypeKind::Bit
807        };
808
809        let mut r#type = Type::new(kind);
810        r#type.signed = true;
811        r#type.set_concrete_width(Shape::new(vec![Some(0)]));
812
813        Ok(Comptime {
814            value: ValueVariant::Numeric(value),
815            r#type,
816            is_const: true,
817            is_global: true,
818            token,
819            ..Default::default()
820        })
821    }
822}
823
824impl Conv<&RealNumber> for Comptime {
825    fn conv(_context: &mut Context, value: &RealNumber) -> IrResult<Self> {
826        let token: TokenRange = value.into();
827        let ret = match value {
828            RealNumber::FixedPoint(x) => {
829                let value: Value = x.fixed_point.as_ref().into();
830                let mut r#type = Type::new(TypeKind::F64);
831                r#type.set_concrete_width(Shape::new(vec![Some(64)]));
832
833                Comptime {
834                    value: ValueVariant::Numeric(value),
835                    r#type,
836                    is_const: true,
837                    is_global: true,
838                    token,
839                    ..Default::default()
840                }
841            }
842            RealNumber::Exponent(x) => {
843                let value: Value = x.exponent.as_ref().into();
844                let mut r#type = Type::new(TypeKind::F64);
845                r#type.set_concrete_width(Shape::new(vec![Some(64)]));
846
847                Comptime {
848                    value: ValueVariant::Numeric(value),
849                    r#type,
850                    is_const: true,
851                    is_global: true,
852                    token,
853                    ..Default::default()
854                }
855            }
856        };
857        Ok(ret)
858    }
859}
860
861impl Conv<&AssignmentOperator> for Op {
862    fn conv(_context: &mut Context, value: &AssignmentOperator) -> IrResult<Self> {
863        let text = value.assignment_operator_token.token.text.to_string();
864        let ret = match text.as_str() {
865            "+=" => Op::Add,
866            "-=" => Op::Sub,
867            "*=" => Op::Mul,
868            "/=" => Op::Div,
869            "%=" => Op::Rem,
870            "&=" => Op::BitAnd,
871            "|=" => Op::BitOr,
872            "^=" => Op::BitXor,
873            "<<=" => Op::LogicShiftL,
874            ">>=" => Op::LogicShiftR,
875            "<<<=" => Op::ArithShiftL,
876            ">>>=" => Op::ArithShiftR,
877            _ => unreachable!(),
878        };
879        Ok(ret)
880    }
881}
882
883#[cfg(test)]
884mod tests {
885    use super::*;
886    use crate::conv::utils::{parse_expression, parse_number};
887
888    #[test]
889    fn baseless() {
890        let mut context = Context::default();
891
892        let x0 = parse_number("0");
893        let x1 = parse_number("1");
894        let x2 = parse_number("1_00");
895        let x3 = parse_number("10_000");
896
897        let x0: Comptime = Conv::conv(&mut context, &x0).unwrap();
898        let x1: Comptime = Conv::conv(&mut context, &x1).unwrap();
899        let x2: Comptime = Conv::conv(&mut context, &x2).unwrap();
900        let x3: Comptime = Conv::conv(&mut context, &x3).unwrap();
901
902        let x0 = x0.get_value().unwrap();
903        let x1 = x1.get_value().unwrap();
904        let x2 = x2.get_value().unwrap();
905        let x3 = x3.get_value().unwrap();
906
907        assert_eq!(format!("{x0:x}"), "32'sh00000000");
908        assert_eq!(format!("{x1:x}"), "32'sh00000001");
909        assert_eq!(format!("{x2:x}"), "32'sh00000064");
910        assert_eq!(format!("{x3:x}"), "32'sh00002710");
911    }
912
913    #[test]
914    fn based() {
915        let mut context = Context::default();
916
917        let x0 = parse_number("16'b000011110101");
918        let x1 = parse_number("16'b0x0X11z10Z01");
919        let x2 = parse_number("24'o20701231");
920        let x3 = parse_number("24'o11z173x1");
921        let x4 = parse_number("32'd123456789");
922        let x5 = parse_number("32'd987654321");
923        let x6 = parse_number("32'h12a45f78");
924        let x7 = parse_number("32'hfx7Z5X32");
925
926        let x0: Comptime = Conv::conv(&mut context, &x0).unwrap();
927        let x1: Comptime = Conv::conv(&mut context, &x1).unwrap();
928        let x2: Comptime = Conv::conv(&mut context, &x2).unwrap();
929        let x3: Comptime = Conv::conv(&mut context, &x3).unwrap();
930        let x4: Comptime = Conv::conv(&mut context, &x4).unwrap();
931        let x5: Comptime = Conv::conv(&mut context, &x5).unwrap();
932        let x6: Comptime = Conv::conv(&mut context, &x6).unwrap();
933        let x7: Comptime = Conv::conv(&mut context, &x7).unwrap();
934
935        let x0 = x0.get_value().unwrap();
936        let x1 = x1.get_value().unwrap();
937        let x2 = x2.get_value().unwrap();
938        let x3 = x3.get_value().unwrap();
939        let x4 = x4.get_value().unwrap();
940        let x5 = x5.get_value().unwrap();
941        let x6 = x6.get_value().unwrap();
942        let x7 = x7.get_value().unwrap();
943
944        assert_eq!(format!("{x0:x}"), "16'h00f5");
945        assert_eq!(format!("{x1:x}"), "16'h0XZZ");
946        assert_eq!(format!("{x2:x}"), "24'h438299");
947        assert_eq!(format!("{x3:x}"), "24'h2ZZeXX");
948        assert_eq!(format!("{x4:x}"), "32'h075bcd15");
949        assert_eq!(format!("{x5:x}"), "32'h3ade68b1");
950        assert_eq!(format!("{x6:x}"), "32'h12a45f78");
951        assert_eq!(format!("{x7:x}"), "32'hfx7z5x32");
952    }
953
954    #[test]
955    fn widthless_based() {
956        let mut context = Context::default();
957
958        let x0 = parse_number("'b000011110101");
959        let x1 = parse_number("'b0x0X11z10Z01");
960        let x2 = parse_number("'o20701231");
961        let x3 = parse_number("'o11z173x1");
962        let x4 = parse_number("'d123456789");
963        let x5 = parse_number("'d987654321");
964        let x6 = parse_number("'h12a45f78");
965        let x7 = parse_number("'hfx7Z5X32");
966
967        let x0: Comptime = Conv::conv(&mut context, &x0).unwrap();
968        let x1: Comptime = Conv::conv(&mut context, &x1).unwrap();
969        let x2: Comptime = Conv::conv(&mut context, &x2).unwrap();
970        let x3: Comptime = Conv::conv(&mut context, &x3).unwrap();
971        let x4: Comptime = Conv::conv(&mut context, &x4).unwrap();
972        let x5: Comptime = Conv::conv(&mut context, &x5).unwrap();
973        let x6: Comptime = Conv::conv(&mut context, &x6).unwrap();
974        let x7: Comptime = Conv::conv(&mut context, &x7).unwrap();
975
976        let x0 = x0.get_value().unwrap();
977        let x1 = x1.get_value().unwrap();
978        let x2 = x2.get_value().unwrap();
979        let x3 = x3.get_value().unwrap();
980        let x4 = x4.get_value().unwrap();
981        let x5 = x5.get_value().unwrap();
982        let x6 = x6.get_value().unwrap();
983        let x7 = x7.get_value().unwrap();
984
985        assert_eq!(format!("{x0:x}"), "8'hf5");
986        assert_eq!(format!("{x1:x}"), "11'hXZZ");
987        assert_eq!(format!("{x2:x}"), "23'h438299");
988        assert_eq!(format!("{x3:x}"), "22'h2ZZeXX");
989        assert_eq!(format!("{x4:x}"), "27'h75bcd15");
990        assert_eq!(format!("{x5:x}"), "30'h3ade68b1");
991        assert_eq!(format!("{x6:x}"), "29'h12a45f78");
992        assert_eq!(format!("{x7:x}"), "32'hfx7z5x32");
993    }
994
995    #[test]
996    fn all_bit() {
997        let mut context = Context::default();
998
999        let x0 = parse_number("'0");
1000        let x1 = parse_number("'1");
1001        let x2 = parse_number("'x");
1002        let x3 = parse_number("'X");
1003        let x4 = parse_number("'z");
1004        let x5 = parse_number("'Z");
1005
1006        let x0: Comptime = Conv::conv(&mut context, &x0).unwrap();
1007        let x1: Comptime = Conv::conv(&mut context, &x1).unwrap();
1008        let x2: Comptime = Conv::conv(&mut context, &x2).unwrap();
1009        let x3: Comptime = Conv::conv(&mut context, &x3).unwrap();
1010        let x4: Comptime = Conv::conv(&mut context, &x4).unwrap();
1011        let x5: Comptime = Conv::conv(&mut context, &x5).unwrap();
1012
1013        let x0 = x0.get_value().unwrap();
1014        let x1 = x1.get_value().unwrap();
1015        let x2 = x2.get_value().unwrap();
1016        let x3 = x3.get_value().unwrap();
1017        let x4 = x4.get_value().unwrap();
1018        let x5 = x5.get_value().unwrap();
1019
1020        assert_eq!(format!("{x0:x}"), "'0");
1021        assert_eq!(format!("{x1:x}"), "'1");
1022        assert_eq!(format!("{x2:x}"), "'x");
1023        assert_eq!(format!("{x3:x}"), "'x");
1024        assert_eq!(format!("{x4:x}"), "'z");
1025        assert_eq!(format!("{x5:x}"), "'z");
1026    }
1027
1028    #[test]
1029    fn float() {
1030        let mut context = Context::default();
1031
1032        let x0 = parse_number("0123456789.0123456789");
1033        let x1 = parse_number("0123456789.0123456789e+012");
1034        let x2 = parse_number("0123456789.0123456789e-012");
1035        let x3 = parse_number("0123456789.0123456789E+012");
1036        let x4 = parse_number("0123456789.0123456789E-012");
1037
1038        let x0: Comptime = Conv::conv(&mut context, &x0).unwrap();
1039        let x1: Comptime = Conv::conv(&mut context, &x1).unwrap();
1040        let x2: Comptime = Conv::conv(&mut context, &x2).unwrap();
1041        let x3: Comptime = Conv::conv(&mut context, &x3).unwrap();
1042        let x4: Comptime = Conv::conv(&mut context, &x4).unwrap();
1043
1044        let x0 = x0.get_value().unwrap();
1045        let x1 = x1.get_value().unwrap();
1046        let x2 = x2.get_value().unwrap();
1047        let x3 = x3.get_value().unwrap();
1048        let x4 = x4.get_value().unwrap();
1049
1050        assert_eq!(format!("{x0:x}"), "64'h419d6f34540ca458");
1051        assert_eq!(format!("{x1:x}"), "64'h441ac53a7e04bcda");
1052        assert_eq!(format!("{x2:x}"), "64'h3f202e85be180b74");
1053        assert_eq!(format!("{x3:x}"), "64'h441ac53a7e04bcda");
1054        assert_eq!(format!("{x4:x}"), "64'h3f202e85be180b74");
1055    }
1056
1057    #[test]
1058    fn unary() {
1059        let mut context = Context::default();
1060
1061        let x0 = parse_expression("+1");
1062        let x1 = parse_expression("-1");
1063        let x2 = parse_expression("!1");
1064        let x3 = parse_expression("~1");
1065        let x4 = parse_expression("&1");
1066        let x5 = parse_expression("|1");
1067        let x6 = parse_expression("^1");
1068        let x7 = parse_expression("~&1");
1069        let x8 = parse_expression("~|1");
1070        let x9 = parse_expression("~^1");
1071
1072        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1073        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1074        let x2: ir::Expression = Conv::conv(&mut context, &x2).unwrap();
1075        let x3: ir::Expression = Conv::conv(&mut context, &x3).unwrap();
1076        let x4: ir::Expression = Conv::conv(&mut context, &x4).unwrap();
1077        let x5: ir::Expression = Conv::conv(&mut context, &x5).unwrap();
1078        let x6: ir::Expression = Conv::conv(&mut context, &x6).unwrap();
1079        let x7: ir::Expression = Conv::conv(&mut context, &x7).unwrap();
1080        let x8: ir::Expression = Conv::conv(&mut context, &x8).unwrap();
1081        let x9: ir::Expression = Conv::conv(&mut context, &x9).unwrap();
1082
1083        assert_eq!(format!("{x0}"), "(+ 32'sh00000001)");
1084        assert_eq!(format!("{x1}"), "(- 32'sh00000001)");
1085        assert_eq!(format!("{x2}"), "(! 32'sh00000001)");
1086        assert_eq!(format!("{x3}"), "(~ 32'sh00000001)");
1087        assert_eq!(format!("{x4}"), "(& 32'sh00000001)");
1088        assert_eq!(format!("{x5}"), "(| 32'sh00000001)");
1089        assert_eq!(format!("{x6}"), "(^ 32'sh00000001)");
1090        assert_eq!(format!("{x7}"), "(~& 32'sh00000001)");
1091        assert_eq!(format!("{x8}"), "(~| 32'sh00000001)");
1092        assert_eq!(format!("{x9}"), "(~^ 32'sh00000001)");
1093    }
1094
1095    #[test]
1096    fn binary() {
1097        let mut context = Context::default();
1098
1099        let x00 = parse_expression("1 ** 1");
1100        let x01 = parse_expression("1 * 1");
1101        let x02 = parse_expression("1 / 1");
1102        let x03 = parse_expression("1 % 1");
1103        let x04 = parse_expression("1 + 1");
1104        let x05 = parse_expression("1 - 1");
1105        let x06 = parse_expression("1 << 1");
1106        let x07 = parse_expression("1 >> 1");
1107        let x08 = parse_expression("1 <<< 1");
1108        let x09 = parse_expression("1 >>> 1");
1109        let x10 = parse_expression("1 <: 1");
1110        let x11 = parse_expression("1 <= 1");
1111        let x12 = parse_expression("1 >: 1");
1112        let x13 = parse_expression("1 >= 1");
1113        let x14 = parse_expression("1 == 1");
1114        let x15 = parse_expression("1 != 1");
1115        let x16 = parse_expression("1 ==? 1");
1116        let x17 = parse_expression("1 !=? 1");
1117        let x18 = parse_expression("1 & 1");
1118        let x19 = parse_expression("1 ^ 1");
1119        let x20 = parse_expression("1 ~^ 1");
1120        let x21 = parse_expression("1 | 1");
1121        let x22 = parse_expression("1 && 1");
1122        let x23 = parse_expression("1 || 1");
1123        let x24 = parse_expression("1 ** 1 + 1 - 1 / 1 % 1");
1124
1125        let x00: ir::Expression = Conv::conv(&mut context, &x00).unwrap();
1126        let x01: ir::Expression = Conv::conv(&mut context, &x01).unwrap();
1127        let x02: ir::Expression = Conv::conv(&mut context, &x02).unwrap();
1128        let x03: ir::Expression = Conv::conv(&mut context, &x03).unwrap();
1129        let x04: ir::Expression = Conv::conv(&mut context, &x04).unwrap();
1130        let x05: ir::Expression = Conv::conv(&mut context, &x05).unwrap();
1131        let x06: ir::Expression = Conv::conv(&mut context, &x06).unwrap();
1132        let x07: ir::Expression = Conv::conv(&mut context, &x07).unwrap();
1133        let x08: ir::Expression = Conv::conv(&mut context, &x08).unwrap();
1134        let x09: ir::Expression = Conv::conv(&mut context, &x09).unwrap();
1135        let x10: ir::Expression = Conv::conv(&mut context, &x10).unwrap();
1136        let x11: ir::Expression = Conv::conv(&mut context, &x11).unwrap();
1137        let x12: ir::Expression = Conv::conv(&mut context, &x12).unwrap();
1138        let x13: ir::Expression = Conv::conv(&mut context, &x13).unwrap();
1139        let x14: ir::Expression = Conv::conv(&mut context, &x14).unwrap();
1140        let x15: ir::Expression = Conv::conv(&mut context, &x15).unwrap();
1141        let x16: ir::Expression = Conv::conv(&mut context, &x16).unwrap();
1142        let x17: ir::Expression = Conv::conv(&mut context, &x17).unwrap();
1143        let x18: ir::Expression = Conv::conv(&mut context, &x18).unwrap();
1144        let x19: ir::Expression = Conv::conv(&mut context, &x19).unwrap();
1145        let x20: ir::Expression = Conv::conv(&mut context, &x20).unwrap();
1146        let x21: ir::Expression = Conv::conv(&mut context, &x21).unwrap();
1147        let x22: ir::Expression = Conv::conv(&mut context, &x22).unwrap();
1148        let x23: ir::Expression = Conv::conv(&mut context, &x23).unwrap();
1149        let x24: ir::Expression = Conv::conv(&mut context, &x24).unwrap();
1150
1151        assert_eq!(format!("{x00}"), "(32'sh00000001 ** 32'sh00000001)");
1152        assert_eq!(format!("{x01}"), "(32'sh00000001 * 32'sh00000001)");
1153        assert_eq!(format!("{x02}"), "(32'sh00000001 / 32'sh00000001)");
1154        assert_eq!(format!("{x03}"), "(32'sh00000001 % 32'sh00000001)");
1155        assert_eq!(format!("{x04}"), "(32'sh00000001 + 32'sh00000001)");
1156        assert_eq!(format!("{x05}"), "(32'sh00000001 - 32'sh00000001)");
1157        assert_eq!(format!("{x06}"), "(32'sh00000001 << 32'sh00000001)");
1158        assert_eq!(format!("{x07}"), "(32'sh00000001 >> 32'sh00000001)");
1159        assert_eq!(format!("{x08}"), "(32'sh00000001 <<< 32'sh00000001)");
1160        assert_eq!(format!("{x09}"), "(32'sh00000001 >>> 32'sh00000001)");
1161        assert_eq!(format!("{x10}"), "(32'sh00000001 <: 32'sh00000001)");
1162        assert_eq!(format!("{x11}"), "(32'sh00000001 <= 32'sh00000001)");
1163        assert_eq!(format!("{x12}"), "(32'sh00000001 >: 32'sh00000001)");
1164        assert_eq!(format!("{x13}"), "(32'sh00000001 >= 32'sh00000001)");
1165        assert_eq!(format!("{x14}"), "(32'sh00000001 == 32'sh00000001)");
1166        assert_eq!(format!("{x15}"), "(32'sh00000001 != 32'sh00000001)");
1167        assert_eq!(format!("{x16}"), "(32'sh00000001 ==? 32'sh00000001)");
1168        assert_eq!(format!("{x17}"), "(32'sh00000001 !=? 32'sh00000001)");
1169        assert_eq!(format!("{x18}"), "(32'sh00000001 & 32'sh00000001)");
1170        assert_eq!(format!("{x19}"), "(32'sh00000001 ^ 32'sh00000001)");
1171        assert_eq!(format!("{x20}"), "(32'sh00000001 ~^ 32'sh00000001)");
1172        assert_eq!(format!("{x21}"), "(32'sh00000001 | 32'sh00000001)");
1173        assert_eq!(format!("{x22}"), "(32'sh00000001 && 32'sh00000001)");
1174        assert_eq!(format!("{x23}"), "(32'sh00000001 || 32'sh00000001)");
1175        assert_eq!(
1176            format!("{x24}"),
1177            "(((32'sh00000001 ** 32'sh00000001) + 32'sh00000001) - ((32'sh00000001 / 32'sh00000001) % 32'sh00000001))"
1178        );
1179    }
1180
1181    #[test]
1182    fn ternary() {
1183        let mut context = Context::default();
1184
1185        let x0 = parse_expression("if 1 ? 2 : 3");
1186        let x1 = parse_expression("if 1 ? 2 : if 3 ? 4 : 5");
1187
1188        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1189        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1190
1191        assert_eq!(
1192            format!("{x0}"),
1193            "(32'sh00000001 ? 32'sh00000002 : 32'sh00000003)"
1194        );
1195        assert_eq!(
1196            format!("{x1}"),
1197            "(32'sh00000001 ? 32'sh00000002 : (32'sh00000003 ? 32'sh00000004 : 32'sh00000005))"
1198        );
1199    }
1200
1201    #[test]
1202    fn boolean() {
1203        let mut context = Context::default();
1204
1205        let x0 = parse_expression("true");
1206        let x1 = parse_expression("false");
1207
1208        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1209        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1210
1211        assert_eq!(format!("{x0}"), "1'h1");
1212        assert_eq!(format!("{x1}"), "1'h0");
1213    }
1214
1215    #[test]
1216    fn paren() {
1217        let mut context = Context::default();
1218
1219        let x0 = parse_expression("(1 + 2) * 3");
1220        let x1 = parse_expression("1 + (2 * 3)");
1221
1222        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1223        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1224
1225        assert_eq!(
1226            format!("{x0}"),
1227            "((32'sh00000001 + 32'sh00000002) * 32'sh00000003)"
1228        );
1229        assert_eq!(
1230            format!("{x1}"),
1231            "(32'sh00000001 + (32'sh00000002 * 32'sh00000003))"
1232        );
1233    }
1234
1235    #[test]
1236    fn concatenation() {
1237        let mut context = Context::default();
1238
1239        let x0 = parse_expression("{1, 2, 3}");
1240        let x1 = parse_expression("{1 repeat 2, 2, 3 repeat 4}");
1241
1242        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1243        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1244
1245        assert_eq!(
1246            format!("{x0}"),
1247            "{32'sh00000001, 32'sh00000002, 32'sh00000003}"
1248        );
1249        assert_eq!(
1250            format!("{x1}"),
1251            "{32'sh00000001 repeat 32'sh00000002, 32'sh00000002, 32'sh00000003 repeat 32'sh00000004}"
1252        );
1253    }
1254
1255    #[test]
1256    fn case_expression() {
1257        let mut context = Context::default();
1258
1259        let x0 = parse_expression("case 10 {0: 1, 1: 2, default: 3}");
1260        let x1 = parse_expression("case 10 {0..=2: 1, 4..5: 2, default: 3}");
1261
1262        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1263        let x1: ir::Expression = Conv::conv(&mut context, &x1).unwrap();
1264
1265        assert_eq!(
1266            format!("{x0}"),
1267            "((32'sh0000000a ==? 32'sh00000000) ? 32'sh00000001 : ((32'sh0000000a ==? 32'sh00000001) ? 32'sh00000002 : 32'sh00000003))"
1268        );
1269        assert_eq!(
1270            format!("{x1}"),
1271            "(((32'sh00000000 <= 32'sh0000000a) && (32'sh0000000a <= 32'sh00000002)) ? 32'sh00000001 : (((32'sh00000004 <= 32'sh0000000a) && (32'sh0000000a <: 32'sh00000005)) ? 32'sh00000002 : 32'sh00000003))"
1272        );
1273    }
1274
1275    #[test]
1276    fn switch_expression() {
1277        let mut context = Context::default();
1278
1279        let x0 = parse_expression("switch {0 == 1: 2, 1 <: 2: 2, default: 3}");
1280
1281        let x0: ir::Expression = Conv::conv(&mut context, &x0).unwrap();
1282
1283        assert_eq!(
1284            format!("{x0}"),
1285            "((32'sh00000000 == 32'sh00000001) ? 32'sh00000002 : ((32'sh00000001 <: 32'sh00000002) ? 32'sh00000002 : 32'sh00000003))"
1286        );
1287    }
1288}