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 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 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 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 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}