1use super::term::*;
2use crate::filedb::*;
3use alloc::alloc::Layout;
4use core::sync::atomic::AtomicUsize;
5use core::{fmt, mem, ops, slice, str};
6use serde::ser::{Serialize, SerializeStruct, Serializer};
7
8pub use aliu::*;
9pub use core::fmt::Write;
10pub use std::collections::VecDeque;
11
12#[allow(unused_macros)]
13macro_rules! panic {
14 ( $( $arg:tt )* ) => {{
15 debug!( $( $arg )* );
16 core::panic!();
17 }};
18}
19
20#[allow(unused_macros)]
21macro_rules! unimplemented {
22 ( $( $arg:tt )* ) => {{
23 debug!( $( $arg )* );
24 core::panic!();
25 }};
26}
27
28#[allow(unused_macros)]
29macro_rules! unreachable {
30 ( $( $arg:tt )* ) => {{
31 debug!( $( $arg )* );
32 core::panic!();
33 }};
34}
35
36#[allow(unused_macros)]
37macro_rules! println {
38 ( $( $arg:tt )* ) => {{
39 debug!( $( $arg )* );
40 }};
41}
42
43#[allow(unused_macros)]
44macro_rules! debug {
45 ($fmt:literal) => {{
46 out!($fmt);
47 }};
48 ($fmt:literal, $( $e:expr ),+ ) => {{
49 out!(@DEBUG, $fmt, $( $e ),+ );
50 }};
51 ($expr:expr) => {{
52 out!(@DEBUG, "{} = {:?}", stringify!($expr), $expr);
53 }};
54 () => {{
55 out!("Nothing to see here");
56 }};
57}
58
59#[cfg(target_arch = "wasm32")]
60pub static OUTPUT: Option<&'static (dyn Fn(String) + Sync)> = None;
61
62pub static COUNTER: AtomicUsize = AtomicUsize::new(0);
63pub const LIMIT: usize = usize::MAX;
64
65#[allow(unused_macros)]
66macro_rules! out {
67 ($str:literal) => {{
68 out!(@DEBUG, "{}", $str);
69 }};
70 (@DEBUG, $str:expr, $( $e:expr ),+ ) => {{
71 if cfg!(debug_assertions) {
72 out!(@LIMITED, core::concat!("DEBUG ({}:{}): ", $str, "\n"), file!(), line!(), $( $e ),+ );
73 }
74 }};
75 (@LOG, $str:expr, $( $e:expr ),+ ) => {{
76 out!(@CLEAN, core::concat!("LOG ({}:{}): ", $str, "\n"), file!(), line!(), $( $e ),+ );
77 }};
78 (@LIMITED, $str:expr, $( $e:expr ),+ ) => {{
79 let count = $crate::COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
80 if count > $crate::LIMIT {
81 out!(@CLEAN, "{}", "debug statement limit reached");
82 core::panic!();
83 }
84
85 out!(@CLEAN, core::concat!("{:<3} ", $str), count, $( $e ),+ );
86 }};
87 (@CLEAN, $str:expr, $( $e:expr ),+ ) => {{
88 let s = alloc::format!( $str, $( $e ),+ );
89
90 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
91 libc_print::libc_print!("{}", s);
92
93 #[cfg(test)]
94 std::print!("{}", s);
95
96 #[allow(unused_unsafe)]
97 #[cfg(target_arch = "wasm32")]
98 if let Some(func) = unsafe { core::ptr::read_volatile(&$crate::OUTPUT) } {
99 func(s);
100
101 }
102 }};
103}
104
105#[cfg(target_arch = "wasm32")]
106pub fn register_output(f: impl Fn(String) + 'static) {
107 let out = &OUTPUT as *const Option<_> as *mut Option<&'static (dyn Fn(String) + Sync)>;
108 let value: &(dyn Fn(String) + 'static) = Box::leak(Box::new(f));
109
110 unsafe { core::ptr::write_volatile(out, Some(mem::transmute(value))) };
111}
112
113macro_rules! error {
114 ($arg1:expr) => {{
115 let mut s = $arg1.to_string();
116 if cfg!(debug_assertions) {
117 s.push_str(&format!(" (in compiler at {}:{})", file!(), line!()));
118 }
119
120 $crate::util::Error::new(s, vec![])
121 }};
122
123 ($msg:expr, $loc1:expr, $msg1:expr) => {{
124 let mut s = $msg.to_string();
125 if cfg!(debug_assertions) {
126 s.push_str(&format!(" (in compiler at {}:{})", file!(), line!()));
127 }
128
129 $crate::util::Error::new(
130 s,
131 vec![$crate::util::ErrorSection {
132 location: $loc1,
133 message: $msg1.to_string(),
134 }],
135 )
136 }};
137
138 ($msg:expr, $loc1:expr, $msg1:expr, $loc2:expr, $msg2:expr) => {{
139 let mut s = $msg.to_string();
140 if cfg!(debug_assertions) {
141 s += &format!(" (in compiler at {}:{})", file!(), line!());
142 }
143
144 $crate::util::Error::new(
145 s,
146 vec![
147 $crate::util::ErrorSection {
148 location: $loc1,
149 message: $msg1.to_string(),
150 },
151 $crate::util::ErrorSection {
152 location: $loc2,
153 message: $msg2.to_string(),
154 },
155 ],
156 )
157 }};
158}
159
160#[derive(Debug, serde::Serialize)]
161pub struct ErrorSection {
162 pub location: CodeLoc,
163 pub message: String,
164}
165
166impl Into<Label> for &ErrorSection {
167 fn into(self) -> Label {
168 Label::new(self.location.file, self.location).with_message(&self.message)
169 }
170}
171
172#[derive(Debug, serde::Serialize)]
173pub struct Error {
174 pub message: String,
175 pub sections: Vec<ErrorSection>,
176}
177
178impl Error {
179 pub fn new(message: String, sections: Vec<ErrorSection>) -> Error {
180 Self {
181 message: message,
182 sections,
183 }
184 }
185
186 pub fn render(&self, files: &FileDb, out: &mut impl Write) -> fmt::Result {
187 Diagnostic::new()
188 .with_message(&self.message)
189 .with_labels(self.sections.iter().map(|x| x.into()).collect())
190 .render(files, out)
191 }
192}
193
194impl Into<Vec<Error>> for Error {
195 fn into(self) -> Vec<Error> {
196 vec![self]
197 }
198}
199
200pub const NO_FILE: CodeLoc = CodeLoc {
201 start: 0,
202 end: 0,
203 file: !0,
204};
205
206#[derive(Clone, Copy, Hash, PartialEq, Eq)]
207pub struct CodeLoc {
208 pub start: u32, pub end: u32,
210 pub file: u32,
211}
212
213impl Serialize for CodeLoc {
214 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
215 where
216 S: Serializer,
217 {
218 if self == &NO_FILE {
219 return serializer.serialize_none();
220 }
221
222 let mut state = serializer.serialize_struct("CodeLoc", 3)?;
223 state.serialize_field("start", &self.start)?;
224 state.serialize_field("end", &self.end)?;
225 state.serialize_field("file", &self.file)?;
226 return state.end();
227 }
228}
229
230impl fmt::Debug for CodeLoc {
231 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
232 write!(fmt, "{}:({},{})", self.file, self.start, self.end)
233 }
234}
235
236#[inline]
237pub fn l(start: u32, end: u32, file: u32) -> CodeLoc {
238 debug_assert!(start <= end);
239
240 CodeLoc { start, end, file }
241}
242
243impl Into<ops::Range<usize>> for CodeLoc {
244 fn into(self) -> ops::Range<usize> {
245 (self.start as usize)..(self.end as usize)
246 }
247}
248
249#[inline]
250pub fn l_from(loc1: CodeLoc, loc2: CodeLoc) -> CodeLoc {
251 if loc1 == NO_FILE {
252 return loc2;
253 }
254
255 if loc2 == NO_FILE {
256 return loc1;
257 }
258
259 debug_assert_eq!(loc1.file, loc2.file);
260 l(loc1.start, loc2.end, loc1.file)
261}
262
263pub fn align_usize(size: usize, align: usize) -> usize {
264 if size == 0 {
265 return 0;
266 }
267
268 ((size - 1) / align * align) + align
269}
270
271pub fn align_u32(size: u32, align: u32) -> u32 {
272 if size == 0 {
273 return 0;
274 }
275
276 let result = ((size - 1) / align * align) + align;
277 return result;
278}
279
280pub fn align_u64(size: u64, align: u64) -> u64 {
281 if size == 0 {
282 return 0;
283 }
284
285 ((size - 1) / align * align) + align
286}
287
288pub unsafe fn any_as_u8_slice_mut<T: Sized + Copy>(p: &mut T) -> &mut [u8] {
290 core::slice::from_raw_parts_mut(p as *mut T as *mut u8, mem::size_of::<T>())
291}
292
293pub fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
294 unsafe { core::slice::from_raw_parts(p as *const T as *const u8, mem::size_of::<T>()) }
295}
296
297pub fn u8_slice_as_any<T: Sized>(p: &[u8]) -> &T {
298 assert_eq!(mem::size_of::<T>(), p.len());
299 unsafe { &*(p.as_ptr() as *const T) }
300}
301
302pub fn u32_to_u32_tup(value: u32) -> (u32, u32) {
303 ((value >> 16) as u32, value as u32)
304}
305
306pub fn fold_binary<I, Iter: Iterator<Item = I>>(
307 mut iter: Iter,
308 mut reducer: impl FnMut(I, I) -> I,
309) -> Option<I> {
310 let first = iter.next()?;
311 let second = match iter.next() {
312 Some(s) => s,
313 None => return Some(first),
314 };
315
316 let mut source = Vec::new();
317 source.push(reducer(first, second));
318
319 loop {
320 let first = match iter.next() {
321 Some(f) => f,
322 None => break,
323 };
324
325 let val = match iter.next() {
326 Some(e) => reducer(first, e),
327 None => first,
328 };
329
330 source.push(val);
331 }
332
333 let mut target = Vec::new();
334 loop {
335 let mut iter = source.into_iter();
336
337 let first = iter.next().unwrap();
338 let second = match iter.next() {
339 Some(s) => s,
340 None => return Some(first),
341 };
342
343 target.push(reducer(first, second));
344
345 loop {
346 let first = match iter.next() {
347 Some(f) => f,
348 None => break,
349 };
350
351 let val = match iter.next() {
352 Some(e) => reducer(first, e),
353 None => first,
354 };
355
356 target.push(val);
357 }
358
359 source = target;
360 target = Vec::new();
361 }
362}
363
364pub struct Void {
384 unused: (),
385}
386
387impl Void {
388 pub fn new() -> Self {
389 return Self { unused: () };
390 }
391}
392
393impl fmt::Write for Void {
394 fn write_str(&mut self, buf: &str) -> fmt::Result {
395 Ok(())
396 }
397}
398
399static UTF8_CHAR_WIDTH: [u8; 256] = [
401 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
402 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
404 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
406 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
408 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
414 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
418
419pub struct Utf8Lossy {
420 bytes: [u8],
421}
422
423impl Utf8Lossy {
424 pub fn from_str(s: &str) -> &Utf8Lossy {
425 Utf8Lossy::from_bytes(s.as_bytes())
426 }
427
428 pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
429 unsafe { core::mem::transmute(bytes) }
431 }
432
433 pub fn chunks(&self) -> Utf8LossyChunksIter<'_> {
434 Utf8LossyChunksIter {
435 source: &self.bytes,
436 }
437 }
438}
439
440pub struct Utf8LossyChunksIter<'a> {
441 source: &'a [u8],
442}
443
444pub struct Utf8LossyChunk<'a> {
445 pub valid: &'a str,
448 pub broken: &'a [u8],
451}
452
453impl<'a> Utf8LossyChunksIter<'a> {
454 fn next(&mut self) -> Utf8LossyChunk<'a> {
455 if self.source.is_empty() {
456 return Utf8LossyChunk {
457 valid: "",
458 broken: self.source,
459 };
460 }
461
462 const TAG_CONT_U8: u8 = 128;
463 fn safe_get(xs: &[u8], i: usize) -> u8 {
464 *xs.get(i).unwrap_or(&0)
465 }
466
467 let mut i = 0;
468 while i < self.source.len() {
469 let i_ = i;
470
471 let byte = unsafe { *self.source.get_unchecked(i) };
474 i += 1;
475
476 if byte < 128 {
477 } else {
478 let w = UTF8_CHAR_WIDTH[byte as usize];
479
480 macro_rules! error {
481 () => {{
482 unsafe {
484 let r = Utf8LossyChunk {
485 valid: core::str::from_utf8_unchecked(&self.source[0..i_]),
486 broken: &self.source[i_..i],
487 };
488 self.source = &self.source[i..];
489 return r;
490 }
491 }};
492 }
493
494 match w {
495 2 => {
496 if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
497 error!();
498 }
499 i += 1;
500 }
501 3 => {
502 match (byte, safe_get(self.source, i)) {
503 (0xE0, 0xA0..=0xBF) => (),
504 (0xE1..=0xEC, 0x80..=0xBF) => (),
505 (0xED, 0x80..=0x9F) => (),
506 (0xEE..=0xEF, 0x80..=0xBF) => (),
507 _ => {
508 error!();
509 }
510 }
511 i += 1;
512 if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
513 error!();
514 }
515 i += 1;
516 }
517 4 => {
518 match (byte, safe_get(self.source, i)) {
519 (0xF0, 0x90..=0xBF) => (),
520 (0xF1..=0xF3, 0x80..=0xBF) => (),
521 (0xF4, 0x80..=0x8F) => (),
522 _ => {
523 error!();
524 }
525 }
526 i += 1;
527 if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
528 error!();
529 }
530 i += 1;
531 if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
532 error!();
533 }
534 i += 1;
535 }
536 _ => {
537 error!();
538 }
539 }
540 }
541 }
542
543 let r = Utf8LossyChunk {
544 valid: unsafe { core::str::from_utf8_unchecked(self.source) },
546 broken: &[],
547 };
548 self.source = &[];
549 r
550 }
551}
552
553pub fn string_append_utf8_lossy(string: &mut String, bytes: &[u8]) {
554 string.reserve(bytes.len());
555 let mut iter = Utf8Lossy::from_bytes(bytes).chunks();
556
557 const REPLACEMENT: &str = "\u{FFFD}";
558
559 loop {
560 let Utf8LossyChunk { valid, broken } = iter.next();
561 string.push_str(valid);
562 if !broken.is_empty() {
563 string.push_str(REPLACEMENT);
564 } else {
565 return;
566 }
567 }
568}
569
570pub fn write_utf8_lossy(mut write: impl fmt::Write, bytes: &[u8]) -> fmt::Result {
571 let mut iter = Utf8Lossy::from_bytes(bytes).chunks();
572
573 const REPLACEMENT: &str = "\u{FFFD}";
574
575 let mut total = 0;
576 loop {
577 let Utf8LossyChunk { valid, broken } = iter.next();
578 write.write_str(valid)?;
579 total += valid.len();
580 if !broken.is_empty() {
581 write.write_str(REPLACEMENT)?;
582 total += REPLACEMENT.len();
583 } else {
584 return Ok(());
585 }
586 }
587}
588
589#[allow(non_camel_case_types)]
590#[derive(Clone, Copy, PartialEq, Eq, Hash)]
591#[repr(C)]
592pub struct n32 {
593 pub data: u32,
594}
595
596impl n32 {
597 pub const NULL: n32 = n32 { data: !0 };
598
599 pub fn new(data: u32) -> Self {
600 if data == Self::NULL.data {
601 panic!("NullPointerException");
602 }
603
604 Self { data }
605 }
606
607 pub fn opt(self) -> Option<u32> {
608 if self.data == Self::NULL.data {
609 return None;
610 }
611
612 return Some(self.data);
613 }
614
615 pub fn ok_or_else<T, F>(self, f: F) -> Result<u32, T>
616 where
617 F: FnOnce() -> T,
618 {
619 if self == Self::NULL {
620 return Err(f());
621 }
622
623 return Ok(self.data);
624 }
625
626 pub fn unwrap(self) -> u32 {
627 if self == Self::NULL {
628 panic!("NullPointerException");
629 }
630
631 return self.data;
632 }
633
634 pub fn unwrap_or(self, f: u32) -> u32 {
635 if self == Self::NULL {
636 return f;
637 }
638
639 return self.data;
640 }
641
642 pub fn unwrap_or_else<F>(self, f: F) -> u32
643 where
644 F: FnOnce() -> u32,
645 {
646 if self == Self::NULL {
647 return f();
648 }
649
650 return self.data;
651 }
652}
653
654impl Into<u32> for n32 {
655 fn into(self) -> u32 {
656 if self == Self::NULL {
657 panic!("NullPointerException");
658 }
659
660 return self.data;
661 }
662}
663
664impl Into<u32> for &n32 {
665 fn into(self) -> u32 {
666 if self == &n32::NULL {
667 panic!("NullPointerException");
668 }
669
670 return self.data;
671 }
672}
673
674impl Into<usize> for n32 {
675 fn into(self) -> usize {
676 if self == Self::NULL {
677 panic!("NullPointerException");
678 }
679
680 return self.data as usize;
681 }
682}
683
684impl Into<usize> for &n32 {
685 fn into(self) -> usize {
686 if self == &n32::NULL {
687 panic!("NullPointerException");
688 }
689
690 return self.data as usize;
691 }
692}
693
694impl From<u32> for n32 {
695 fn from(data: u32) -> Self {
696 Self::new(data)
697 }
698}
699
700impl From<usize> for n32 {
701 fn from(data: usize) -> Self {
702 Self::new(data as u32)
703 }
704}
705
706impl ops::Add<u32> for n32 {
707 type Output = n32;
708
709 fn add(mut self, rhs: u32) -> n32 {
710 self.data += rhs;
711 if self == Self::NULL {
712 panic!("NullPointerException");
713 }
714 return self;
715 }
716}
717
718impl fmt::Debug for n32 {
719 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
720 if *self == Self::NULL {
721 write!(fmt, "null")
722 } else {
723 write!(fmt, "{}", self.data)
724 }
725 }
726}
727
728impl Serialize for n32 {
729 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
730 where
731 S: Serializer,
732 {
733 if *self == Self::NULL {
734 serializer.serialize_none()
735 } else {
736 serializer.serialize_u32(self.data)
737 }
738 }
739}
740
741pub struct Defer<F: FnOnce()> {
742 f: Option<F>,
743}
744
745impl<F: FnOnce()> Drop for Defer<F> {
746 fn drop(&mut self) {
747 let f = self.f.take().unwrap();
748 f();
749 }
750}
751
752pub fn defer<F: FnOnce()>(f: F) -> Defer<F> {
753 return Defer { f: Some(f) };
754}
755
756#[allow(unused_macros)]
757macro_rules! let_expr {
758 ($left:pat = $right:expr) => {{
759 if let $left = $right {
760 true
761 } else {
762 false
763 }
764 }};
765}
766
767pub struct UnsafeCell<T> {
768 t: T,
769}
770
771impl<T> UnsafeCell<T> {
772 pub const fn new(t: T) -> Self {
773 UnsafeCell { t }
774 }
775
776 pub unsafe fn get_mut(&self) -> &mut T {
777 return &mut *(&self.t as *const T as *mut T);
778 }
779}
780
781unsafe impl<T> Sync for UnsafeCell<T> {}
782unsafe impl<T: Send> Send for UnsafeCell<T> {}
783
784#[repr(C)]
785pub struct IStr {
786 pub len: usize,
787 chars: (),
788}
789
790impl PartialEq for IStr {
791 fn eq(&self, other: &Self) -> bool {
792 return self.as_str() == other.as_str();
793 }
794}
795
796impl fmt::Debug for IStr {
797 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
798 return self.as_str().fmt(fmt);
799 }
800}
801
802impl IStr {
803 pub fn new<'a>(string: &str) -> &'a mut Self {
804 return Self::with_allocator(string, Global);
805 }
806
807 pub fn with_allocator<'a>(string: &str, alloc: impl Allocator) -> &'a mut Self {
808 let (size, align) = (mem::size_of::<usize>(), mem::align_of::<usize>());
809 let layout = unsafe { Layout::from_size_align_unchecked(size + string.len(), align) };
810 let (bytes, string) = (alloc.allocate(layout).unwrap(), string.as_bytes());
811 let (i_str, len) = (bytes.as_ptr(), string.len());
812 let i_str = unsafe { &mut *((&mut (&mut *i_str)[0]) as *mut u8 as *mut IStr) };
813
814 i_str.len = len;
815 unsafe { i_str.as_bytes_mut() }.copy_from_slice(string);
816 return i_str;
817 }
818
819 pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
820 let begin = &mut self.chars as *mut () as *mut u8;
821 return slice::from_raw_parts_mut(begin, self.len);
822 }
823
824 pub fn as_str(&self) -> &str {
825 let begin = &self.chars as *const () as *const u8;
826 let slice = unsafe { slice::from_raw_parts(begin, self.len) };
827 return unsafe { str::from_utf8_unchecked(slice) };
828 }
829}
830
831pub trait CloneInto<'a> {
832 type CloneOutput;
833
834 fn clone_into_alloc(&self, alloc: &impl Allocator) -> Self::CloneOutput;
835}
836
837impl<'a, T> CloneInto<'a> for Option<T>
838where
839 T: CloneInto<'a>,
840{
841 type CloneOutput = Option<T::CloneOutput>;
842
843 fn clone_into_alloc(&self, alloc: &impl Allocator) -> Self::CloneOutput {
844 if let Some(a) = self.as_ref() {
845 return Some(a.clone_into_alloc(alloc));
846 }
847
848 return None;
849 }
850}