Skip to content

Commit 709412c

Browse files
committed
Introduce IrError as its own interpreter error
1 parent 48153db commit 709412c

21 files changed

+677
-191
lines changed

crates/rune-languageserver/src/state.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ impl State {
161161
display_to_error,
162162
);
163163
}
164-
// TODO: match the source id with the document that has the error.
165164
rune::LoadErrorKind::CompileError(error) => {
166165
report(
167166
&sources,
@@ -172,6 +171,16 @@ impl State {
172171
display_to_error,
173172
);
174173
}
174+
rune::LoadErrorKind::QueryError(error) => {
175+
report(
176+
&sources,
177+
&mut by_url,
178+
error.span(),
179+
source_id,
180+
error,
181+
display_to_error,
182+
);
183+
}
175184
rune::LoadErrorKind::LinkError(error) => match error {
176185
rune::LinkerError::MissingFunction { hash, spans } => {
177186
for (span, _) in spans {

crates/rune-wasm/src/lib.rs

+15
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,21 @@ async fn inner_compile(input: String, budget: usize) -> CompileResult {
229229
message: error.to_string(),
230230
});
231231
}
232+
rune::LoadErrorKind::QueryError(error) => {
233+
let span = error.span();
234+
235+
let start =
236+
Position::from(source.position_to_unicode_line_char(span.start));
237+
let end =
238+
Position::from(source.position_to_unicode_line_char(span.end));
239+
240+
diagnostics.push(Diagnostic {
241+
kind: DiagnosticKind::Error,
242+
start,
243+
end,
244+
message: error.to_string(),
245+
});
246+
}
232247
rune::LoadErrorKind::LinkError(error) => match error {
233248
rune::LinkerError::MissingFunction { hash, spans } => {
234249
for (span, _) in spans {

crates/rune/src/compile_error.rs

+45-53
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use crate::ast;
2-
use crate::ir_value::IrValue;
32
use crate::unit_builder::UnitBuilderError;
4-
use crate::{ParseError, ParseErrorKind, Spanned};
5-
use runestick::{AccessError, CompileMeta, Item, SourceId, Span, TypeInfo, TypeOf};
3+
use crate::{
4+
IrError, IrErrorKind, ParseError, ParseErrorKind, QueryError, QueryErrorKind, Spanned,
5+
};
6+
use runestick::{CompileMeta, Item, SourceId, Span};
67
use std::error;
78
use std::fmt;
89
use std::io;
910
use std::path::PathBuf;
1011
use thiserror::Error;
1112

1213
/// A compile result.
13-
pub type CompileResult<T, E = CompileError> = std::result::Result<T, E>;
14+
pub type CompileResult<T> = std::result::Result<T, CompileError>;
1415

1516
/// An error raised during compiling.
1617
#[derive(Debug)]
@@ -32,7 +33,7 @@ impl CompileError {
3233
}
3334
}
3435

35-
/// Get the kind of the cmopile error.
36+
/// Get the kind of the compile error.
3637
pub fn kind(&self) -> &CompileErrorKind {
3738
&self.kind
3839
}
@@ -75,29 +76,6 @@ impl CompileError {
7576
CompileError::new(spanned, CompileErrorKind::ConstError { msg })
7677
}
7778

78-
/// An error raised when we expect a certain constant value but get another.
79-
pub fn const_expected<S, E>(spanned: S, actual: &IrValue) -> Self
80-
where
81-
S: Spanned,
82-
E: TypeOf,
83-
{
84-
CompileError::new(
85-
spanned,
86-
CompileErrorKind::ConstExpectedValue {
87-
expected: E::type_info(),
88-
actual: actual.type_info(),
89-
},
90-
)
91-
}
92-
93-
/// Construct an access error.
94-
pub fn access<S>(spanned: S, error: AccessError) -> Self
95-
where
96-
S: Spanned,
97-
{
98-
Self::new(spanned, CompileErrorKind::AccessError { error })
99-
}
100-
10179
/// Construct an experimental error.
10280
///
10381
/// This should be used when an experimental feature is used which hasn't
@@ -149,37 +127,57 @@ impl From<UnitBuilderError> for CompileError {
149127
}
150128
}
151129

130+
impl From<IrError> for CompileError {
131+
fn from(error: IrError) -> Self {
132+
CompileError {
133+
span: error.span(),
134+
kind: CompileErrorKind::IrError {
135+
error: error.into_kind(),
136+
},
137+
}
138+
}
139+
}
140+
141+
impl From<QueryError> for CompileError {
142+
fn from(error: QueryError) -> Self {
143+
CompileError {
144+
span: error.span(),
145+
kind: CompileErrorKind::QueryError {
146+
error: error.into_kind(),
147+
},
148+
}
149+
}
150+
}
151+
152152
/// Error when encoding AST.
153153
#[derive(Debug, Error)]
154154
pub enum CompileErrorKind {
155-
/// An access error raised during compilation, usually happens during
156-
/// constant evaluation.
157-
#[error("access error: {error}")]
158-
AccessError {
159-
/// The source error.
160-
#[source]
161-
error: AccessError,
162-
},
163155
/// An internal encoder invariant was broken.
164156
#[error("internal compiler error: {msg}")]
165157
Internal {
166158
/// The message of the internal error.
167159
msg: &'static str,
168160
},
161+
/// Encountered an ir error.
162+
#[error("ir error: {error}")]
163+
IrError {
164+
/// The source error.
165+
#[source]
166+
error: IrErrorKind,
167+
},
168+
/// Encountered a query error.
169+
#[error("query error: {error}")]
170+
QueryError {
171+
/// The source error.
172+
#[source]
173+
error: QueryErrorKind,
174+
},
169175
/// A constant evaluation errored.
170176
#[error("error during constant evaluation: {msg}")]
171177
ConstError {
172178
/// Message describing the error.
173179
msg: &'static str,
174180
},
175-
/// A constant evaluation errored.
176-
#[error("expected a value of type {expected} but got {actual}")]
177-
ConstExpectedValue {
178-
/// The expected value.
179-
expected: TypeInfo,
180-
/// The value we got instead.
181-
actual: TypeInfo,
182-
},
183181
/// Trying to use an experimental feature which was not enabled.
184182
#[error("experimental feature: {msg}")]
185183
Experimental {
@@ -400,9 +398,6 @@ pub enum CompileErrorKind {
400398
/// The pattern is not supported as a binding.
401399
#[error("not a valid binding")]
402400
UnsupportedBinding,
403-
/// Error raised when trying to use a break outside of a loop.
404-
#[error("break outside of supported loop")]
405-
BreakOutsideOfLoop,
406401
/// Attempting to use a float in a match pattern.
407402
#[error("floating point numbers cannot be used in patterns")]
408403
MatchFloatInPattern,
@@ -442,10 +437,7 @@ pub enum CompileErrorKind {
442437
/// The number that was an unsupported tuple index.
443438
number: ast::Number,
444439
},
445-
/// Trying to treat a non-constant expression as constant.
446-
#[error("not a constant expression")]
447-
NotConst,
448-
/// Trying to process a cycle of constants.
449-
#[error("constant cycle detected")]
450-
ConstCycle,
440+
/// Error raised when trying to use a break outside of a loop.
441+
#[error("break outside of loop")]
442+
BreakOutsideOfLoop,
451443
}

crates/rune/src/compiler.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ pub fn compile_with_options(
137137
Ok(true) => (),
138138
Ok(false) => break,
139139
Err((source_id, error)) => {
140-
worker.errors.push(LoadError::new(source_id, error));
140+
worker
141+
.errors
142+
.push(LoadError::new(source_id, CompileError::from(error)));
141143
}
142144
}
143145
}

crates/rune/src/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ impl EmitDiagnostics for LoadError {
335335

336336
error.span()
337337
}
338+
LoadErrorKind::QueryError(error) => error.span(),
338339
};
339340

340341
if let Some(e) = self.kind().source() {

crates/rune/src/eval/ir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ impl Eval<&Ir> for IrInterpreter<'_> {
1212
IrKind::Binary(ir_binary) => self.eval(ir_binary, used),
1313
IrKind::Decl(ir_decl) => self.eval(ir_decl, used),
1414
IrKind::Set(ir_set) => self.eval(ir_set, used),
15+
IrKind::Assign(ir_assign) => self.eval(ir_assign, used),
1516
IrKind::Template(ir_template) => self.eval(ir_template, used),
1617
IrKind::Name(name) => Ok(self.resolve_var(name.as_ref(), ir.span(), used)?),
1718
IrKind::Target(ir_target) => Ok(self.scopes.get_target(ir_target)?),

crates/rune/src/eval/ir_assign.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use crate::eval::prelude::*;
2+
3+
impl Eval<&IrAssign> for IrInterpreter<'_> {
4+
type Output = IrValue;
5+
6+
fn eval(&mut self, ir_assign: &IrAssign, used: Used) -> Result<Self::Output, EvalOutcome> {
7+
self.budget.take(ir_assign)?;
8+
let value = self.eval(&*ir_assign.value, used)?;
9+
10+
self.scopes.mut_target(&ir_assign.target, move |t| {
11+
ir_assign.op.assign(ir_assign, t, value)
12+
})?;
13+
14+
Ok(IrValue::Unit)
15+
}
16+
}

crates/rune/src/eval/ir_binary.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,23 @@ impl Eval<&IrBinary> for IrInterpreter<'_> {
5050
}
5151
IrBinaryOp::Shl => {
5252
let b = u32::try_from(b).map_err(|_| {
53-
CompileError::const_error(
54-
&ir_binary.rhs,
55-
"cannot be converted to shift operand",
56-
)
53+
IrError::custom(&ir_binary.rhs, "cannot be converted to shift operand")
5754
})?;
5855

5956
let n = a
6057
.checked_shl(b)
61-
.ok_or_else(|| CompileError::const_error(span, "integer shift overflow"))?;
58+
.ok_or_else(|| IrError::custom(span, "integer shift overflow"))?;
6259

6360
return Ok(IrValue::Integer(n));
6461
}
6562
IrBinaryOp::Shr => {
6663
let b = u32::try_from(b).map_err(|_| {
67-
CompileError::const_error(
68-
&ir_binary.rhs,
69-
"cannot be converted to shift operand",
70-
)
64+
IrError::custom(&ir_binary.rhs, "cannot be converted to shift operand")
7165
})?;
7266

73-
let n = a.checked_shr(b).ok_or_else(|| {
74-
CompileError::const_error(span, "integer shift underflow")
75-
})?;
67+
let n = a
68+
.checked_shr(b)
69+
.ok_or_else(|| IrError::custom(span, "integer shift underflow"))?;
7670

7771
return Ok(IrValue::Integer(n));
7872
}
@@ -109,7 +103,7 @@ fn checked_int(
109103
op: impl FnOnce(i64, i64) -> Option<i64>,
110104
msg: &'static str,
111105
span: Span,
112-
) -> Result<IrValue, CompileError> {
113-
let n = op(a, b).ok_or_else(|| CompileError::const_error(span, msg))?;
106+
) -> Result<IrValue, IrError> {
107+
let n = op(a, b).ok_or_else(|| IrError::custom(span, msg))?;
114108
Ok(IrValue::Integer(n))
115109
}

crates/rune/src/eval/ir_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl Eval<&IrLoop> for IrInterpreter<'_> {
3535
return Ok(value);
3636
}
3737

38-
return Err(EvalOutcome::from(CompileError::const_error(
38+
return Err(EvalOutcome::from(IrError::custom(
3939
span,
4040
"break with value is not supported for unconditional loops",
4141
)));

crates/rune/src/eval/ir_template.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ impl Eval<&IrTemplate> for IrInterpreter<'_> {
3030
write!(buf, "{}", b).unwrap();
3131
}
3232
IrValue::String(s) => {
33-
let s = s
34-
.borrow_ref()
35-
.map_err(|e| CompileError::access(ir_template, e))?;
33+
let s = s.borrow_ref().map_err(IrError::access(ir_template))?;
3634
buf.push_str(&*s);
3735
}
3836
_ => {

crates/rune/src/eval/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use crate::ir::IrPat;
22
use crate::ir_interpreter::IrInterpreter;
33
use crate::ir_value::IrValue;
4-
use crate::{CompileError, ParseError, Spanned};
4+
use crate::{IrError, QueryError, Spanned};
55
use runestick::Span;
66

77
mod ir;
8+
mod ir_assign;
89
mod ir_binary;
910
mod ir_branches;
1011
mod ir_break;
@@ -71,7 +72,7 @@ where
7172
let value = compiler
7273
.eval(self, used)?
7374
.into_bool()
74-
.map_err(|actual| CompileError::const_expected::<_, bool>(span, &actual))?;
75+
.map_err(|actual| IrError::expected::<_, bool>(span, &actual))?;
7576

7677
Ok(value)
7778
}
@@ -82,7 +83,7 @@ impl Matches for IrPat {
8283
&self,
8384
compiler: &mut IrInterpreter<'_>,
8485
value: IrValue,
85-
used: Used,
86+
_used: Used,
8687
spanned: S,
8788
) -> Result<bool, EvalOutcome>
8889
where
@@ -102,7 +103,7 @@ pub(crate) enum EvalOutcome {
102103
/// Encountered ast that is not a constant expression.
103104
NotConst(Span),
104105
/// A compile error.
105-
Error(CompileError),
106+
Error(IrError),
106107
/// Break until the next loop, or the optional label.
107108
Break(Span, EvalBreak),
108109
}
@@ -117,14 +118,14 @@ impl EvalOutcome {
117118
}
118119
}
119120

120-
impl From<CompileError> for EvalOutcome {
121-
fn from(error: CompileError) -> Self {
121+
impl From<IrError> for EvalOutcome {
122+
fn from(error: IrError) -> Self {
122123
Self::Error(error)
123124
}
124125
}
125126

126-
impl From<ParseError> for EvalOutcome {
127-
fn from(error: ParseError) -> Self {
127+
impl From<QueryError> for EvalOutcome {
128+
fn from(error: QueryError) -> Self {
128129
Self::Error(error.into())
129130
}
130131
}

crates/rune/src/eval/prelude.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pub(crate) use crate::eval::{ConstAs, Eval, EvalBreak, EvalOutcome, Matches, Use
44
pub(crate) use crate::ir::*;
55
pub(crate) use crate::ir_interpreter::IrInterpreter;
66
pub(crate) use crate::ir_value::IrValue;
7-
pub(crate) use crate::CompileError;
8-
pub(crate) use crate::Spanned;
7+
pub(crate) use crate::{IrError, Spanned};
98
pub(crate) use runestick::{Shared, Span};
109
pub(crate) use std::convert::TryFrom;

0 commit comments

Comments
 (0)