Improve positioning
This commit is contained in:
parent
3224c04f72
commit
46419956bd
80
Cargo.lock
generated
80
Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.9"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@ -96,9 +96,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.86"
|
||||
version = "1.0.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
|
||||
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -121,9 +121,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.2"
|
||||
version = "4.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651"
|
||||
checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -143,9 +143,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.0"
|
||||
version = "4.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
|
||||
checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@ -243,15 +243,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.6"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
@ -302,9 +302,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -420,9 +420,9 @@ checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.50"
|
||||
version = "2.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
|
||||
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -499,7 +499,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -534,17 +534,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
"windows_aarch64_gnullvm 0.52.4",
|
||||
"windows_aarch64_msvc 0.52.4",
|
||||
"windows_i686_gnu 0.52.4",
|
||||
"windows_i686_msvc 0.52.4",
|
||||
"windows_x86_64_gnu 0.52.4",
|
||||
"windows_x86_64_gnullvm 0.52.4",
|
||||
"windows_x86_64_msvc 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -561,9 +561,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
@ -579,9 +579,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
@ -597,9 +597,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
@ -615,9 +615,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
@ -633,9 +633,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
@ -651,9 +651,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
@ -669,9 +669,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
|
@ -126,7 +126,9 @@ mod tests {
|
||||
None,
|
||||
AssignmentOperator::Assign,
|
||||
Positioned {
|
||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
||||
node: Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||
),
|
||||
position: (0, 0),
|
||||
},
|
||||
)
|
||||
@ -152,7 +154,9 @@ mod tests {
|
||||
None,
|
||||
AssignmentOperator::AddAssign,
|
||||
Positioned {
|
||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(41))),
|
||||
node: Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(41)).positioned((0..1).into()),
|
||||
),
|
||||
position: (0, 0),
|
||||
},
|
||||
)
|
||||
@ -178,7 +182,9 @@ mod tests {
|
||||
None,
|
||||
AssignmentOperator::SubAssign,
|
||||
Positioned {
|
||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(1))),
|
||||
node: Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()),
|
||||
),
|
||||
position: (0, 0),
|
||||
},
|
||||
)
|
||||
@ -201,7 +207,9 @@ mod tests {
|
||||
}),
|
||||
AssignmentOperator::Assign,
|
||||
Positioned {
|
||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
||||
node: Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||
),
|
||||
position: (0, 0),
|
||||
},
|
||||
)
|
||||
|
@ -61,9 +61,15 @@ mod tests {
|
||||
#[test]
|
||||
fn run_returns_value_of_final_statement() {
|
||||
let block = Block::new(vec![
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(1))),
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(2))),
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
||||
Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()),
|
||||
),
|
||||
Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(2)).positioned((0..1).into()),
|
||||
),
|
||||
Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||
),
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
@ -75,8 +81,12 @@ mod tests {
|
||||
#[test]
|
||||
fn expected_type_returns_type_of_final_statement() {
|
||||
let block = Block::new(vec![
|
||||
Statement::Expression(Expression::Value(ValueNode::String("42".to_string()))),
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
||||
Statement::Expression(
|
||||
Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()),
|
||||
),
|
||||
Statement::Expression(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||
),
|
||||
]);
|
||||
|
||||
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
|
||||
|
@ -83,11 +83,12 @@ mod tests {
|
||||
fn simple_if() {
|
||||
assert_eq!(
|
||||
IfElse::new(
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
||||
Block::new(vec![Statement::Expression(Expression::Value(
|
||||
ValueNode::String("foo".to_string())
|
||||
),)])
|
||||
.positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||
Block::new(vec![Statement::Expression(
|
||||
Expression::Value(ValueNode::String("foo".to_string()))
|
||||
.positioned((0..0).into())
|
||||
)])
|
||||
.positioned((0..0).into()),
|
||||
None
|
||||
)
|
||||
.run(&Context::new()),
|
||||
@ -99,16 +100,18 @@ mod tests {
|
||||
fn simple_if_else() {
|
||||
assert_eq!(
|
||||
IfElse::new(
|
||||
Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
|
||||
Block::new(vec![Statement::Expression(Expression::Value(
|
||||
ValueNode::String("foo".to_string())
|
||||
))])
|
||||
.positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()),
|
||||
Block::new(vec![Statement::Expression(
|
||||
Expression::Value(ValueNode::String("foo".to_string()))
|
||||
.positioned((0..0).into())
|
||||
)])
|
||||
.positioned((0..0).into()),
|
||||
Some(
|
||||
Block::new(vec![Statement::Expression(Expression::Value(
|
||||
ValueNode::String("bar".to_string())
|
||||
))])
|
||||
.positioned((0, 0))
|
||||
Block::new(vec![Statement::Expression(
|
||||
Expression::Value(ValueNode::String("bar".to_string()))
|
||||
.positioned((0..0).into())
|
||||
)])
|
||||
.positioned((0..0).into())
|
||||
)
|
||||
)
|
||||
.run(&Context::new()),
|
||||
|
@ -139,8 +139,8 @@ mod tests {
|
||||
#[test]
|
||||
fn equal() {
|
||||
assert!(Logic::Equal(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -153,8 +153,8 @@ mod tests {
|
||||
#[test]
|
||||
fn not_equal() {
|
||||
assert!(Logic::NotEqual(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -167,8 +167,8 @@ mod tests {
|
||||
#[test]
|
||||
fn greater() {
|
||||
assert!(Logic::Greater(
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -181,8 +181,8 @@ mod tests {
|
||||
#[test]
|
||||
fn less() {
|
||||
assert!(Logic::Less(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -195,8 +195,8 @@ mod tests {
|
||||
#[test]
|
||||
fn greater_or_equal() {
|
||||
assert!(Logic::GreaterOrEqual(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(41)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(41)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -206,8 +206,8 @@ mod tests {
|
||||
.unwrap());
|
||||
|
||||
assert!(Logic::GreaterOrEqual(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -220,8 +220,8 @@ mod tests {
|
||||
#[test]
|
||||
fn less_or_equal() {
|
||||
assert!(Logic::LessOrEqual(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -231,8 +231,8 @@ mod tests {
|
||||
.unwrap());
|
||||
|
||||
assert!(Logic::LessOrEqual(
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -245,8 +245,8 @@ mod tests {
|
||||
#[test]
|
||||
fn and() {
|
||||
assert!(Logic::And(
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -259,8 +259,8 @@ mod tests {
|
||||
#[test]
|
||||
fn or() {
|
||||
assert!(Logic::Or(
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
|
||||
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||
Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()),
|
||||
)
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
@ -273,7 +273,7 @@ mod tests {
|
||||
#[test]
|
||||
fn not() {
|
||||
assert!(
|
||||
Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)))
|
||||
Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()))
|
||||
.run(&Context::new())
|
||||
.unwrap()
|
||||
.as_return_value()
|
||||
|
@ -13,6 +13,8 @@ pub mod r#type;
|
||||
pub mod value_node;
|
||||
pub mod r#while;
|
||||
|
||||
use chumsky::span::{SimpleSpan, Span};
|
||||
|
||||
pub use self::{
|
||||
assignment::{Assignment, AssignmentOperator},
|
||||
block::Block,
|
||||
@ -47,10 +49,10 @@ pub trait AbstractTree: Sized {
|
||||
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
|
||||
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
|
||||
|
||||
fn positioned(self, position: (usize, usize)) -> Positioned<Self> {
|
||||
fn positioned(self, span: SimpleSpan) -> Positioned<Self> {
|
||||
Positioned {
|
||||
node: self,
|
||||
position,
|
||||
position: (span.start(), span.end()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,16 @@ use crate::{
|
||||
error::{RuntimeError, ValidationError},
|
||||
};
|
||||
|
||||
use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While};
|
||||
use super::{
|
||||
AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Positioned, Type, While,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Statement {
|
||||
Assignment(Assignment),
|
||||
Block(Block),
|
||||
Break,
|
||||
Expression(Expression),
|
||||
Expression(Positioned<Expression>),
|
||||
IfElse(IfElse),
|
||||
Loop(Loop),
|
||||
While(While),
|
||||
@ -22,7 +24,7 @@ impl AbstractTree for Statement {
|
||||
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
||||
Statement::Block(block) => block.expected_type(_context),
|
||||
Statement::Break => Ok(Type::None),
|
||||
Statement::Expression(expression) => expression.expected_type(_context),
|
||||
Statement::Expression(expression) => expression.node.expected_type(_context),
|
||||
Statement::IfElse(if_else) => if_else.expected_type(_context),
|
||||
Statement::Loop(r#loop) => r#loop.expected_type(_context),
|
||||
Statement::While(r#while) => r#while.expected_type(_context),
|
||||
@ -34,7 +36,7 @@ impl AbstractTree for Statement {
|
||||
Statement::Assignment(assignment) => assignment.validate(_context),
|
||||
Statement::Block(block) => block.validate(_context),
|
||||
Statement::Break => Ok(()),
|
||||
Statement::Expression(expression) => expression.validate(_context),
|
||||
Statement::Expression(expression) => expression.node.validate(_context),
|
||||
Statement::IfElse(if_else) => if_else.validate(_context),
|
||||
Statement::Loop(r#loop) => r#loop.validate(_context),
|
||||
Statement::While(r#while) => r#while.validate(_context),
|
||||
@ -46,7 +48,7 @@ impl AbstractTree for Statement {
|
||||
Statement::Assignment(assignment) => assignment.run(_context),
|
||||
Statement::Block(block) => block.run(_context),
|
||||
Statement::Break => Ok(Action::Break),
|
||||
Statement::Expression(expression) => expression.run(_context),
|
||||
Statement::Expression(expression) => expression.node.run(_context),
|
||||
Statement::IfElse(if_else) => if_else.run(_context),
|
||||
Statement::Loop(r#loop) => r#loop.run(_context),
|
||||
Statement::While(r#while) => r#while.run(_context),
|
||||
|
14
src/error.rs
14
src/error.rs
@ -19,7 +19,7 @@ pub enum Error {
|
||||
span: (usize, usize),
|
||||
},
|
||||
Runtime(RuntimeError),
|
||||
Validation(ValidationError),
|
||||
Validation(ValidationError, (usize, usize)),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
@ -46,9 +46,15 @@ impl Error {
|
||||
.finish()
|
||||
}
|
||||
Error::Runtime(_) => todo!(),
|
||||
Error::Validation(validation_error) => {
|
||||
let mut report =
|
||||
Report::build(ReportKind::Custom("Validation Error", Color::White), (), 0);
|
||||
Error::Validation(validation_error, position) => {
|
||||
let mut report = Report::build(
|
||||
ReportKind::Custom("Validation Error: The code was not run.", Color::White),
|
||||
(),
|
||||
0,
|
||||
)
|
||||
.with_label(
|
||||
Label::new(position.0..position.1).with_message("Error found in this item."),
|
||||
);
|
||||
|
||||
match validation_error {
|
||||
ValidationError::ExpectedBoolean => {
|
||||
|
@ -35,9 +35,10 @@ impl Interpreter {
|
||||
.iter()
|
||||
.filter_map(|statement| {
|
||||
statement
|
||||
.node
|
||||
.validate(&self.context)
|
||||
.err()
|
||||
.map(|validation_error| Error::Validation(validation_error))
|
||||
.map(|validation_error| Error::Validation(validation_error, statement.position))
|
||||
})
|
||||
.collect::<Vec<Error>>();
|
||||
|
||||
@ -48,7 +49,7 @@ impl Interpreter {
|
||||
let mut value = None;
|
||||
|
||||
for statement in statements {
|
||||
value = match statement.run(&self.context) {
|
||||
value = match statement.node.run(&self.context) {
|
||||
Ok(action) => match action {
|
||||
Action::Break => None,
|
||||
Action::Return(value) => Some(value),
|
||||
|
@ -12,7 +12,7 @@ pub type DustParser<'src> = Boxed<
|
||||
'src,
|
||||
'src,
|
||||
ParserInput<'src>,
|
||||
Vec<Statement>,
|
||||
Vec<Positioned<Statement>>,
|
||||
extra::Err<Rich<'src, Token<'src>, SimpleSpan>>,
|
||||
>;
|
||||
|
||||
@ -21,7 +21,7 @@ pub type ParserInput<'src> =
|
||||
|
||||
pub fn parse<'src>(
|
||||
tokens: &'src [(Token<'src>, SimpleSpan)],
|
||||
) -> Result<Vec<Statement>, Vec<Error>> {
|
||||
) -> Result<Vec<Positioned<Statement>>, Vec<Error>> {
|
||||
parser()
|
||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||
.into_result()
|
||||
@ -111,6 +111,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
just(Token::Control(Control::Colon)).ignore_then(r#type)
|
||||
});
|
||||
|
||||
let positioned_type =
|
||||
type_specification.map_with(|r#type, state| r#type.positioned(state.span()));
|
||||
|
||||
let statement = recursive(|statement| {
|
||||
let block = statement
|
||||
.clone()
|
||||
@ -122,6 +125,10 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
)
|
||||
.map(|statements| Block::new(statements));
|
||||
|
||||
let positioned_block = block
|
||||
.clone()
|
||||
.map_with(|block, state| block.positioned(state.span()));
|
||||
|
||||
let expression = recursive(|expression| {
|
||||
let identifier_expression = identifier
|
||||
.clone()
|
||||
@ -154,10 +161,17 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
|
||||
let map_assignment = identifier
|
||||
.clone()
|
||||
.then(type_specification.clone().or_not())
|
||||
.then(
|
||||
type_specification
|
||||
.map_with(|r#type, state| r#type.positioned(state.span()))
|
||||
.clone()
|
||||
.or_not(),
|
||||
)
|
||||
.then_ignore(just(Token::Operator(Operator::Assign)))
|
||||
.then(expression.clone())
|
||||
.map(|((identifier, r#type), expression)| (identifier, r#type, expression));
|
||||
.map_with(|((identifier, r#type), expression), state| {
|
||||
(identifier, r#type, expression.positioned(state.span()))
|
||||
});
|
||||
|
||||
let map = map_assignment
|
||||
.separated_by(just(Token::Control(Control::Comma)).or_not())
|
||||
@ -180,11 +194,11 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
)
|
||||
.then(type_specification.clone())
|
||||
.then(block.clone())
|
||||
.map(|((parameters, return_type), body)| {
|
||||
.map_with(|((parameters, return_type), body), state| {
|
||||
Expression::Value(ValueNode::Function {
|
||||
parameters,
|
||||
return_type,
|
||||
body,
|
||||
return_type: return_type.positioned(state.span()),
|
||||
body: body.positioned(state.span()),
|
||||
})
|
||||
})
|
||||
.boxed();
|
||||
@ -216,7 +230,8 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
just(Token::Control(Control::ParenOpen)),
|
||||
just(Token::Control(Control::ParenClose)),
|
||||
),
|
||||
));
|
||||
))
|
||||
.map_with(|expression, state| expression.positioned(state.span()));
|
||||
|
||||
use Operator::*;
|
||||
|
||||
@ -280,6 +295,7 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
|
||||
choice((
|
||||
function,
|
||||
function_call,
|
||||
range,
|
||||
logic_math_and_index,
|
||||
identifier_expression,
|
||||
@ -290,17 +306,22 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
.boxed()
|
||||
});
|
||||
|
||||
let positioned_expression = expression
|
||||
.clone()
|
||||
.map_with(|expression, state| expression.positioned(state.span()));
|
||||
|
||||
let expression_statement = expression
|
||||
.clone()
|
||||
.map_with(|expression, state| Statement::expression(expression, state.span()))
|
||||
.map_with(|expression, state| {
|
||||
Statement::Expression(expression.positioned(state.span()))
|
||||
})
|
||||
.boxed();
|
||||
|
||||
let r#break =
|
||||
just(Token::Keyword("break")).map_with(|_, state| Statement::r#break(state.span()));
|
||||
let r#break = just(Token::Keyword("break")).to(Statement::Break);
|
||||
|
||||
let assignment = identifier
|
||||
.clone()
|
||||
.then(type_specification.clone().or_not())
|
||||
.then(positioned_type.clone().or_not())
|
||||
.then(choice((
|
||||
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
|
||||
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
|
||||
@ -308,16 +329,18 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
)))
|
||||
.then(statement.clone())
|
||||
.map_with(|(((identifier, r#type), operator), statement), state| {
|
||||
Statement::assignment(
|
||||
Assignment::new(identifier, r#type, operator, statement),
|
||||
state.span(),
|
||||
)
|
||||
Statement::Assignment(Assignment::new(
|
||||
identifier,
|
||||
r#type,
|
||||
operator,
|
||||
statement.positioned(state.span()),
|
||||
))
|
||||
})
|
||||
.boxed();
|
||||
|
||||
let block_statement = block
|
||||
.clone()
|
||||
.map_with(|block, state| Statement::block(block, state.span()));
|
||||
.map_with(|block, state| Statement::Block(block));
|
||||
|
||||
let r#loop = statement
|
||||
.clone()
|
||||
@ -328,29 +351,24 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
|
||||
just(Token::Control(Control::CurlyClose)),
|
||||
)
|
||||
.map_with(|statements, state| Statement::r#loop(Loop::new(statements), state.span()))
|
||||
.map_with(|statements, state| Statement::Loop(Loop::new(statements)))
|
||||
.boxed();
|
||||
|
||||
let r#while = just(Token::Keyword("while"))
|
||||
.ignore_then(expression.clone())
|
||||
.then(block.clone())
|
||||
.map_with(|(expression, block), state| {
|
||||
Statement::r#while(While::new(expression, block), state.span())
|
||||
});
|
||||
.map_with(|(expression, block), state| Statement::While(While::new(expression, block)));
|
||||
|
||||
let if_else = just(Token::Keyword("if"))
|
||||
.ignore_then(expression.clone())
|
||||
.then(block.clone())
|
||||
.ignore_then(positioned_expression.clone())
|
||||
.then(positioned_block.clone())
|
||||
.then(
|
||||
just(Token::Keyword("else"))
|
||||
.ignore_then(block.clone())
|
||||
.ignore_then(positioned_block.clone())
|
||||
.or_not(),
|
||||
)
|
||||
.map_with(|((if_expression, if_block), else_block), state| {
|
||||
Statement::if_else(
|
||||
IfElse::new(if_expression, if_block, else_block),
|
||||
state.span(),
|
||||
)
|
||||
Statement::IfElse(IfElse::new(if_expression, if_block, else_block))
|
||||
})
|
||||
.boxed();
|
||||
|
||||
@ -367,13 +385,15 @@ pub fn parser<'src>() -> DustParser<'src> {
|
||||
.boxed()
|
||||
});
|
||||
|
||||
statement.repeated().collect().boxed()
|
||||
statement
|
||||
.map_with(|statement, state| statement.positioned(state.span()))
|
||||
.repeated()
|
||||
.collect()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use tests::statement::StatementInner;
|
||||
|
||||
use crate::lexer::lex;
|
||||
|
||||
use super::*;
|
||||
|
Loading…
Reference in New Issue
Block a user