1use crate::*;
2
3
4#[derive(Clone, Debug)]
5pub enum Expr
6{
7 Literal(diagn::Span, Value),
8 Variable(diagn::Span, String),
9 StructInit {
10 span: diagn::Span,
11 members_init: Vec<ExprStructMemberInit>,
12 },
13 NestingLevel {
14 span: diagn::Span,
15 nesting_level: usize,
16 },
17 MemberAccess {
18 span: diagn::Span,
19 lhs: Box<Expr>,
20 member_name: String,
21 },
22 UnaryOp(diagn::Span, diagn::Span, UnaryOp, Box<Expr>),
23 BinaryOp(diagn::Span, diagn::Span, BinaryOp, Box<Expr>, Box<Expr>),
24 TernaryOp(diagn::Span, Box<Expr>, Box<Expr>, Box<Expr>),
25 Slice(diagn::Span, diagn::Span, Box<Expr>, Box<Expr>, Box<Expr>),
26 SliceShort(diagn::Span, diagn::Span, Box<Expr>, Box<Expr>),
27 Block(diagn::Span, Vec<Expr>),
28 Call(diagn::Span, Box<Expr>, Vec<Expr>),
29 Asm(diagn::Span, asm::AstTopLevel),
30}
31
32
33#[derive(Clone, Debug)]
34pub struct ExprStructMemberInit
35{
36 pub span: diagn::Span,
37 pub name: String,
38 pub value: Expr,
39}
40
41
42#[derive(Clone, Debug)]
43pub enum Value
44{
45 Unknown(ValueMetadata),
46 FailedConstraint(ValueMetadata, diagn::Message),
47 Void(ValueMetadata),
48 Integer(ValueMetadata, util::BigInt),
49 String(ValueMetadata, ValueString),
50 Bool(ValueMetadata, bool),
51 Struct(ValueMetadata, ValueStruct),
52 ExprBuiltInFunction(ValueMetadata, String),
53 AsmBuiltInFunction(ValueMetadata, String),
54 Function(ValueMetadata, util::ItemRef<asm::Function>),
55 Bankdef(ValueMetadata, util::ItemRef<asm::Bankdef>),
56}
57
58
59#[derive(Clone, Debug)]
60pub struct ValueMetadata
61{
62 pub symbol_ref: Option<util::ItemRef<asm::Symbol>>,
63 pub bank_ref: Option<util::ItemRef<asm::Bankdef>>,
64}
65
66
67#[derive(Clone, Debug, PartialEq)]
68pub struct ValueString
69{
70 pub utf8_contents: String,
71 pub encoding: String,
72}
73
74
75#[derive(Clone, Debug, PartialEq)]
76pub struct ValueStruct
77{
78 pub members: Vec<ValueStructMember>,
79}
80
81
82#[derive(Clone, Debug, PartialEq)]
83pub struct ValueStructMember
84{
85 pub name: String,
86 pub value: Value,
87}
88
89
90#[derive(Copy, Clone, Debug, Eq, PartialEq)]
91pub enum UnaryOp
92{
93 Neg,
94 Not
95}
96
97
98#[derive(Copy, Clone, Debug, Eq, PartialEq)]
99pub enum BinaryOp
100{
101 Assign,
102
103 Add, Sub, Mul, Div, Mod,
104 Shl, Shr,
105 And, Or, Xor,
106
107 Eq, Ne,
108 Lt, Le,
109 Gt, Ge,
110
111 LazyAnd, LazyOr,
112
113 Concat
114}
115
116
117impl Expr
118{
119 pub fn new_dummy() -> Expr
120 {
121 Expr::Literal(diagn::Span::new_dummy(), Value::make_bool(false))
122 }
123
124
125 pub fn span(&self) -> diagn::Span
126 {
127 match self
128 {
129 &Expr::Literal (span, ..) => span,
130 &Expr::Variable (span, ..) => span,
131 &Expr::StructInit { span, .. } => span,
132 &Expr::NestingLevel { span, .. } => span,
133 &Expr::MemberAccess { span, .. } => span,
134 &Expr::UnaryOp (span, ..) => span,
135 &Expr::BinaryOp (span, ..) => span,
136 &Expr::TernaryOp (span, ..) => span,
137 &Expr::Slice (span, ..) => span,
138 &Expr::SliceShort (span, ..) => span,
139 &Expr::Block (span, ..) => span,
140 &Expr::Call (span, ..) => span,
141 &Expr::Asm (span, ..) => span,
142 }
143 }
144}
145
146
147impl Value
148{
149 pub fn type_name(&self) -> &str
150 {
151 match self
152 {
153 Value::Unknown(..) => "unknown",
154 Value::FailedConstraint(..) => "failed constraint",
155 Value::Void(..) => "void",
156 Value::Integer(..) => "integer",
157 Value::String(..) => "string",
158 Value::Bool(..) => "bool",
159 Value::Struct(..) => "struct",
160 Value::ExprBuiltInFunction(..) => "built-in function",
161 Value::AsmBuiltInFunction(..) => "built-in function",
162 Value::Function(..) => "function",
163 Value::Bankdef(..) => "bankdef",
164 }
165 }
166
167
168 pub fn is_unknown(&self) -> bool
169 {
170 match self
171 {
172 Value::Unknown(_) => true,
173 _ => false,
174 }
175 }
176
177
178 pub fn should_propagate(&self) -> bool
179 {
180 match self
181 {
182 Value::Unknown(_) => true,
183 Value::FailedConstraint(_, _) => true,
184 _ => false,
185 }
186 }
187
188
189 pub fn make_literal(&self) -> Expr
190 {
191 Expr::Literal(diagn::Span::new_dummy(), self.clone())
192 }
193
194
195 pub fn make_unknown() -> Value
196 {
197 Value::Unknown(Value::make_metadata())
198 }
199
200
201 pub fn make_void() -> Value
202 {
203 Value::Void(Value::make_metadata())
204 }
205
206
207 pub fn make_integer<T: Into<util::BigInt>>(value: T) -> Value
208 {
209 Value::Integer(
210 Value::make_metadata(),
211 value.into())
212 }
213
214
215 pub fn make_maybe_integer<T: Into<util::BigInt>>(maybe_value: Option<T>) -> Value
216 {
217 if let Some(value) = maybe_value
218 {
219 Value::Integer(
220 Value::make_metadata(),
221 value.into())
222 }
223 else
224 {
225 Value::make_void()
226 }
227 }
228
229
230 pub fn make_bool(value: bool) -> Value
231 {
232 Value::Bool(
233 Value::make_metadata(),
234 value)
235 }
236
237
238 pub fn make_string<T: Into<String>, S: Into<String>>(value: T, encoding: S) -> Value
239 {
240 Value::String(
241 Value::make_metadata(),
242 ValueString {
243 utf8_contents: value.into(),
244 encoding: encoding.into(),
245 })
246 }
247
248
249 pub fn make_struct(value: ValueStruct) -> Value
250 {
251 Value::Struct(
252 Value::make_metadata(),
253 value)
254 }
255
256
257 pub fn make_bankdef(value: util::ItemRef<asm::Bankdef>) -> Value
258 {
259 Value::Bankdef(
260 Value::make_metadata(),
261 value)
262 }
263
264
265 pub fn make_metadata() -> ValueMetadata
266 {
267 ValueMetadata {
268 symbol_ref: None,
269 bank_ref: None,
270 }
271 }
272
273
274 pub fn with_symbol_ref(mut self, symbol_ref: util::ItemRef<asm::Symbol>) -> Value
275 {
276 self.get_mut_metadata().symbol_ref = Some(symbol_ref);
277 self
278 }
279
280
281 pub fn with_bank_ref(mut self, bank_ref: util::ItemRef<asm::Bankdef>) -> Value
282 {
283 self.get_mut_metadata().bank_ref = Some(bank_ref);
284 self
285 }
286
287
288 pub fn get_metadata(&self) -> &ValueMetadata
289 {
290 match self
291 {
292 Value::Unknown(meta, ..) => meta,
293 Value::FailedConstraint(meta, ..) => meta,
294 Value::Void(meta, ..) => meta,
295 Value::Integer(meta, ..) => meta,
296 Value::String(meta, ..) => meta,
297 Value::Bool(meta, ..) => meta,
298 Value::Struct(meta, ..) => meta,
299 Value::ExprBuiltInFunction(meta, ..) => meta,
300 Value::AsmBuiltInFunction(meta, ..) => meta,
301 Value::Function(meta, ..) => meta,
302 Value::Bankdef(meta, ..) => meta,
303 }
304 }
305
306
307 pub fn get_mut_metadata(&mut self) -> &mut ValueMetadata
308 {
309 match self
310 {
311 Value::Unknown(meta, ..) => meta,
312 Value::FailedConstraint(meta, ..) => meta,
313 Value::Void(meta, ..) => meta,
314 Value::Integer(meta, ..) => meta,
315 Value::String(meta, ..) => meta,
316 Value::Bool(meta, ..) => meta,
317 Value::Struct(meta, ..) => meta,
318 Value::ExprBuiltInFunction(meta, ..) => meta,
319 Value::AsmBuiltInFunction(meta, ..) => meta,
320 Value::Function(meta, ..) => meta,
321 Value::Bankdef(meta, ..) => meta,
322 }
323 }
324
325
326 pub fn get_bigint(&self) -> Option<util::BigInt>
327 {
328 match &self
329 {
330 &Value::Integer(_, bigint) => Some(bigint.clone()),
331 &Value::String(_, s) => Some(s.to_bigint()),
332 _ => None,
333 }
334 }
335
336
337 pub fn coallesce_to_integer<'a>(
338 &'a self)
339 -> std::borrow::Cow<'a, expr::Value>
340 {
341 match self
342 {
343 Value::String(_, s) =>
344 std::borrow::Cow::Owned(
345 expr::Value::make_integer(s.to_bigint())),
346
347 _ => std::borrow::Cow::Borrowed(self),
348 }
349 }
350
351
352 pub fn unwrap_bigint(
353 &self)
354 -> &util::BigInt
355 {
356 match &self
357 {
358 Value::Integer(_, bigint) => bigint,
359 _ => panic!(),
360 }
361 }
362
363
364 pub fn expect_bigint(
365 &self,
366 report: &mut diagn::Report,
367 span: diagn::Span)
368 -> Result<&util::BigInt, ()>
369 {
370 match &self
371 {
372 Value::Integer(_, bigint) => Ok(bigint),
373
374 Value::Unknown(_) =>
375 {
376 report.error_span(
377 "value is unknown",
378 span);
379
380 Err(())
381 }
382
383 _ =>
384 {
385 report.error_span(
386 format!(
387 "expected integer, got {}",
388 self.type_name()),
389 span);
390
391 Err(())
392 }
393 }
394 }
395
396
397 pub fn expect_bigint_mut(
398 &mut self,
399 report: &mut diagn::Report,
400 span: diagn::Span)
401 -> Result<&mut util::BigInt, ()>
402 {
403 match self
404 {
405 Value::Integer(_, bigint) => Ok(bigint),
406
407 Value::Unknown(_) =>
408 {
409 report.error_span(
410 "value is unknown",
411 span);
412
413 Err(())
414 }
415
416 _ =>
417 {
418 report.error_span(
419 format!(
420 "expected integer, got {}",
421 self.type_name()),
422 span);
423
424 Err(())
425 }
426 }
427 }
428
429
430 pub fn expect_sized_bigint(
431 &self,
432 report: &mut diagn::Report,
433 span: diagn::Span)
434 -> Result<&util::BigInt, ()>
435 {
436 let bigint = self.expect_bigint(report, span)?;
437
438 match bigint.size
439 {
440 Some(_) => Ok(&bigint),
441
442 None =>
443 {
444 report.error_span(
445 format!(
446 "expected integer with definite size, got {}",
447 self.type_name()),
448 span);
449
450 Err(())
451 }
452 }
453 }
454
455
456 pub fn expect_sized_integerlike(
457 &self,
458 report: &mut diagn::Report,
459 span: diagn::Span)
460 -> Result<(util::BigInt, usize), ()>
461 {
462 if let Some(bigint) = self.coallesce_to_integer().get_bigint()
463 {
464 if let Some(size) = bigint.size
465 {
466 return Ok((bigint, size));
467 }
468
469 report.error_span(
470 "value has no definite size",
471 span);
472
473 return Err(());
474 }
475
476 report.error_span(
477 format!(
478 "expected integer-like value with definite size, got {}",
479 self.type_name()),
480 span);
481
482 Err(())
483 }
484
485
486 pub fn expect_error_or_bigint(
487 self,
488 report: &mut diagn::Report,
489 span: diagn::Span)
490 -> Result<expr::Value, ()>
491 {
492 let coallesced = self.coallesce_to_integer();
493
494 match coallesced.as_ref()
495 {
496 expr::Value::Unknown(_) |
497 expr::Value::FailedConstraint(_, _) =>
498 Ok(coallesced.into_owned()),
499
500 expr::Value::Integer(_, _) =>
501 Ok(coallesced.into_owned()),
502
503 _ =>
504 {
505 report.error_span(
506 format!(
507 "expected integer, got {}",
508 coallesced.type_name()),
509 span);
510
511 Err(())
512 }
513 }
514 }
515
516
517 pub fn expect_error_or_sized_bigint(
518 self,
519 report: &mut diagn::Report,
520 span: diagn::Span)
521 -> Result<expr::Value, ()>
522 {
523 let coallesced = self.coallesce_to_integer();
524
525 match coallesced.as_ref()
526 {
527 expr::Value::Unknown(_) |
528 expr::Value::FailedConstraint(_, _) =>
529 Ok(coallesced.into_owned()),
530
531 expr::Value::Integer(_, bigint)
532 if bigint.size.is_some() =>
533 Ok(expr::Value::make_integer(bigint.to_owned())),
534
535 _ =>
536 {
537 report.error_span(
538 format!(
539 "expected integer with definite size, got {}",
540 coallesced.type_name()),
541 span);
542
543 Err(())
544 }
545 }
546 }
547
548
549 pub fn expect_error_or_bool(
550 self,
551 report: &mut diagn::Report,
552 span: diagn::Span)
553 -> Result<expr::Value, ()>
554 {
555 let coallesced = self.coallesce_to_integer();
556
557 match coallesced.as_ref()
558 {
559 expr::Value::Unknown(_) |
560 expr::Value::FailedConstraint(_, _) =>
561 Ok(coallesced.into_owned()),
562
563 expr::Value::Bool(_, _) =>
564 Ok(coallesced.into_owned()),
565
566 _ =>
567 {
568 report.error_span(
569 format!(
570 "expected boolean, got {}",
571 coallesced.type_name()),
572 span);
573
574 Err(())
575 }
576 }
577 }
578
579
580 pub fn as_usize(&self) -> Option<usize>
581 {
582 match &self
583 {
584 Value::Integer(_, bigint) =>
585 bigint.maybe_into::<usize>(),
586
587 _ => None,
588 }
589 }
590
591
592 pub fn expect_usize(
593 &self,
594 report: &mut diagn::Report,
595 span: diagn::Span)
596 -> Result<usize, ()>
597 {
598 match &self
599 {
600 Value::Integer(_, bigint) =>
601 bigint.checked_into::<usize>(
602 report,
603 span),
604
605 Value::Unknown(_) =>
606 {
607 report.error_span(
608 "value is unknown",
609 span);
610
611 Err(())
612 }
613
614 _ =>
615 {
616 report.error_span(
617 format!(
618 "expected non-negative integer, got {}",
619 self.type_name()),
620 span);
621
622 Err(())
623 }
624 }
625 }
626
627
628 pub fn expect_error_or_usize(
629 self,
630 report: &mut diagn::Report,
631 span: diagn::Span)
632 -> Result<expr::Value, ()>
633 {
634 match &self
635 {
636 expr::Value::Unknown(_) |
637 expr::Value::FailedConstraint(_, _) =>
638 Ok(self.clone()),
639
640 expr::Value::Integer(_, bigint) =>
641 {
642 bigint.checked_into::<usize>(
643 report,
644 span)?;
645
646 Ok(self.clone())
647 }
648
649 _ =>
650 {
651 report.error_span(
652 format!(
653 "expected non-negative integer, got {}",
654 self.type_name()),
655 span);
656
657 Err(())
658 }
659 }
660 }
661
662
663 pub fn expect_nonzero_usize(
664 &self,
665 report: &mut diagn::Report,
666 span: diagn::Span)
667 -> Result<usize, ()>
668 {
669 match &self
670 {
671 Value::Integer(_, bigint) =>
672 {
673 bigint.checked_into_nonzero_usize(
674 report,
675 span)
676 }
677
678 Value::Unknown(_) =>
679 {
680 report.error_span(
681 "value is unknown",
682 span);
683
684 Err(())
685 }
686
687 _ =>
688 {
689 report.error_span(
690 format!(
691 "expected positive integer, got {}",
692 self.type_name()),
693 span);
694
695 Err(())
696 }
697 }
698 }
699
700
701 pub fn expect_bool(
702 &self,
703 report: &mut diagn::Report,
704 span: diagn::Span)
705 -> Result<bool, ()>
706 {
707 match &self
708 {
709 expr::Value::Bool(_, value) => Ok(*value),
710
711 _ =>
712 {
713 report.error_span(
714 format!(
715 "expected boolean, got {}",
716 self.type_name()),
717 span);
718
719 Err(())
720 }
721 }
722 }
723
724
725 pub fn expect_string(
726 &self,
727 report: &mut diagn::Report,
728 span: diagn::Span)
729 -> Result<&ValueString, ()>
730 {
731 match &self
732 {
733 expr::Value::String(_, value) => Ok(value),
734
735 _ =>
736 {
737 report.error_span(
738 format!(
739 "expected string, got {}",
740 self.type_name()),
741 span);
742
743 Err(())
744 }
745 }
746 }
747}
748
749
750impl std::cmp::PartialEq for Value
751{
752 fn eq(&self, other: &Value) -> bool
753 {
754 match self
756 {
757 Value::Unknown(_) => match other
758 {
759 Value::Unknown(_) => true,
760 _ => false,
761 }
762
763 Value::FailedConstraint(_, _) => match other
764 {
765 Value::FailedConstraint(_, _) => true,
766 _ => false,
767 }
768
769 Value::Void(_) => match other
770 {
771 Value::Void(_) => true,
772 _ => false,
773 }
774
775 Value::Integer(_, a) => match other
776 {
777 Value::Integer(_, b) => a == b,
778 _ => false,
779 }
780
781 Value::Bool(_, a) => match other
782 {
783 Value::Bool(_, b) => a == b,
784 _ => false,
785 }
786
787 Value::String(_, a) => match other
788 {
789 Value::String(_, b) => a == b,
790 _ => false,
791 }
792
793 Value::Struct(_, a) => match other
794 {
795 Value::Struct(_, b) => a == b,
796 _ => false,
797 }
798
799 Value::ExprBuiltInFunction(_, a) => match other
800 {
801 Value::ExprBuiltInFunction(_, b) => a == b,
802 _ => false,
803 }
804
805 Value::AsmBuiltInFunction(_, a) => match other
806 {
807 Value::AsmBuiltInFunction(_, b) => a == b,
808 _ => false,
809 }
810
811 Value::Function(_, a) => match other
812 {
813 Value::Function(_, b) => a == b,
814 _ => false,
815 }
816
817 Value::Bankdef(_, a) => match other
818 {
819 Value::Bankdef(_, b) => a == b,
820 _ => false,
821 }
822 }
823 }
824}
825
826
827impl ValueString
828{
829 pub fn to_bigint(&self) -> util::BigInt
830 {
831 match &*self.encoding
832 {
833 "utf8" => util::BigInt::from_bytes_be(&self.utf8_contents.as_bytes()),
834 "utf16be" =>
835 {
836 let units = self.utf8_contents.encode_utf16();
837 let mut bytes = Vec::new();
838 for unit in units
839 {
840 bytes.push(((unit >> 8) & 0xff) as u8);
841 bytes.push(((unit >> 0) & 0xff) as u8);
842 }
843
844 util::BigInt::from_bytes_be(&bytes[..])
845 }
846 "utf16le" =>
847 {
848 let units = self.utf8_contents.encode_utf16();
849 let mut bytes = Vec::new();
850 for unit in units
851 {
852 bytes.push(((unit >> 0) & 0xff) as u8);
853 bytes.push(((unit >> 8) & 0xff) as u8);
854 }
855
856 util::BigInt::from_bytes_be(&bytes[..])
857 }
858 "utf32be" =>
859 {
860 let units = self.utf8_contents.chars();
861 let mut bytes = Vec::new();
862 for unit in units
863 {
864 bytes.push(((unit as u32 >> 24) & 0xff) as u8);
865 bytes.push(((unit as u32 >> 16) & 0xff) as u8);
866 bytes.push(((unit as u32 >> 8) & 0xff) as u8);
867 bytes.push(((unit as u32 >> 0) & 0xff) as u8);
868 }
869
870 util::BigInt::from_bytes_be(&bytes[..])
871 }
872 "utf32le" =>
873 {
874 let units = self.utf8_contents.chars();
875 let mut bytes = Vec::new();
876 for unit in units
877 {
878 bytes.push(((unit as u32 >> 0) & 0xff) as u8);
879 bytes.push(((unit as u32 >> 8) & 0xff) as u8);
880 bytes.push(((unit as u32 >> 16) & 0xff) as u8);
881 bytes.push(((unit as u32 >> 24) & 0xff) as u8);
882 }
883
884 util::BigInt::from_bytes_be(&bytes[..])
885 }
886 "ascii" =>
887 {
888 let units = self.utf8_contents.chars();
889 let bytes = units.map(|c|
890 {
891 if c as u32 >= 0x100
892 {
893 0x00
894 }
895 else
896 {
897 c as u8
898 }
899 });
900
901 util::BigInt::from_bytes_be(&bytes.collect::<Vec<_>>()[..])
902 }
903 _ => panic!("invalid string encoding"),
904 }
905 }
906}