1use crate::{
2 compile::CompileError,
3 continuation::Continuation,
4 gc::Gc,
5 syntax::{Identifier, Span},
6 value::Value,
7};
8use derivative::Derivative;
9use std::sync::Arc;
10
11#[derive(Debug, Clone)]
13pub struct RuntimeError {
14 pub backtrace: Vec<Frame>,
15 pub kind: RuntimeErrorKind,
16}
17
18#[derive(Derivative)]
19#[derivative(Debug, Clone)]
20pub enum RuntimeErrorKind {
21 UndefinedVariable(Identifier),
22 InvalidType {
23 expected: String,
24 provided: String,
25 },
26 InvalidOperatorType {
27 provided: String,
28 },
29 WrongNumberOfArguments {
30 expected: usize,
31 provided: usize,
32 },
33 AssertEqFailed {
34 expected: String,
35 actual: String,
36 },
37 DivisionByZero,
38 CompileError(CompileError),
39 AbandonCurrentContinuation {
40 #[derivative(Debug = "ignore")]
41 args: Vec<Gc<Value>>,
42 #[derivative(Debug = "ignore")]
43 new_cont: Option<Arc<Continuation>>,
44 },
45 NoPatternsMatch,
46 Condition {
47 },
49}
50
51#[derive(Debug, Clone)]
52pub struct Frame {
53 pub proc: String,
54 pub span: Span,
55 pub repeated: usize,
56}
57
58impl Frame {
59 pub fn new(proc: String, span: Span) -> Self {
60 Self {
61 proc,
62 span,
63 repeated: 0,
64 }
65 }
66}
67
68impl RuntimeError {
69 pub fn push_frame(&mut self, proc: String, span: Span) {
70 match self.backtrace.last_mut() {
71 Some(last_frame) if last_frame.span == span && last_frame.proc == proc => {
72 last_frame.repeated += 1
73 }
74 _ => self.backtrace.push(Frame::new(proc, span)),
75 }
76 }
77
78 pub fn abandon_current_continuation(
79 args: Vec<Gc<Value>>,
80 new_cont: Option<Arc<Continuation>>,
81 ) -> Self {
82 Self {
83 backtrace: Vec::new(),
84 kind: RuntimeErrorKind::AbandonCurrentContinuation { args, new_cont },
85 }
86 }
87
88 pub fn division_by_zero() -> Self {
89 Self {
90 backtrace: Vec::new(),
91 kind: RuntimeErrorKind::DivisionByZero,
92 }
93 }
94
95 pub fn assert_eq_failed(expected: &str, actual: &str) -> Self {
96 let expected = expected.to_string();
97 let actual = actual.to_string();
98 Self {
99 backtrace: Vec::new(),
100 kind: RuntimeErrorKind::AssertEqFailed { expected, actual },
101 }
102 }
103
104 pub fn undefined_variable(ident: Identifier) -> Self {
105 Self {
106 backtrace: Vec::new(),
107 kind: RuntimeErrorKind::UndefinedVariable(ident),
108 }
109 }
110
111 pub fn invalid_type(expected: &str, provided: &str) -> Self {
112 let expected = expected.to_string();
113 let provided = provided.to_string();
114 Self {
115 backtrace: Vec::new(),
116 kind: RuntimeErrorKind::InvalidType { expected, provided },
117 }
118 }
119
120 pub fn invalid_operator_type(provided: &str) -> Self {
121 let provided = provided.to_string();
122 Self {
123 backtrace: Vec::new(),
124 kind: RuntimeErrorKind::InvalidOperatorType { provided },
125 }
126 }
127
128 pub fn wrong_num_of_args(expected: usize, provided: usize) -> Self {
129 Self {
130 backtrace: Vec::new(),
131 kind: RuntimeErrorKind::WrongNumberOfArguments { expected, provided },
132 }
133 }
134
135 pub fn no_patterns_match() -> Self {
136 Self {
137 backtrace: Vec::new(),
138 kind: RuntimeErrorKind::NoPatternsMatch,
139 }
140 }
141}
142
143impl From<CompileError> for RuntimeError {
144 fn from(ce: CompileError) -> Self {
145 Self {
146 backtrace: Vec::new(),
147 kind: RuntimeErrorKind::CompileError(ce),
148 }
149 }
150}
151
152