| author | |
| committer | |
| log | 91e93a9d73b3caa20e42a0a904802393924c405f |
| tree | 53bb8692a45fd848c0677a61378cf91d9e177757 |
| parent | f93117a51b8aae4a8477e086bfe87c61caf63c1b |
34 files changed, 362 insertions(+), 255 deletions(-)
Cargo.lock+80-2| ... | ... | @@ -69,6 +69,7 @@ dependencies = [ |
| 69 | 69 | name = "ast" |
| 70 | 70 | version = "0.1.0" |
| 71 | 71 | dependencies = [ |
| 72 | "log", | |
| 72 | 73 | "miette", |
| 73 | 74 | "num", |
| 74 | 75 | "thiserror", |
| ... | ... | @@ -174,6 +175,7 @@ dependencies = [ |
| 174 | 175 | "clap", |
| 175 | 176 | "js_ast", |
| 176 | 177 | "js_printer", |
| 178 | "log", | |
| 177 | 179 | "miette", |
| 178 | 180 | "parser", |
| 179 | 181 | "sema", |
| ... | ... | @@ -197,6 +199,15 @@ dependencies = [ |
| 197 | 199 | "windows-sys", |
| 198 | 200 | ] |
| 199 | 201 | |
| 202 | [[package]] | |
| 203 | name = "form_urlencoded" | |
| 204 | version = "1.2.1" | |
| 205 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 206 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" | |
| 207 | dependencies = [ | |
| 208 | "percent-encoding", | |
| 209 | ] | |
| 210 | ||
| 200 | 211 | [[package]] |
| 201 | 212 | name = "gimli" |
| 202 | 213 | version = "0.28.1" |
| ... | ... | @@ -215,6 +226,16 @@ version = "0.3.3" |
| 215 | 226 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 216 | 227 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" |
| 217 | 228 | |
| 229 | [[package]] | |
| 230 | name = "idna" | |
| 231 | version = "0.5.0" | |
| 232 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 233 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" | |
| 234 | dependencies = [ | |
| 235 | "unicode-bidi", | |
| 236 | "unicode-normalization", | |
| 237 | ] | |
| 238 | ||
| 218 | 239 | [[package]] |
| 219 | 240 | name = "is-terminal" |
| 220 | 241 | version = "0.4.10" |
| ... | ... | @@ -237,11 +258,10 @@ name = "js_ast" |
| 237 | 258 | version = "0.1.0" |
| 238 | 259 | dependencies = [ |
| 239 | 260 | "ast", |
| 261 | "log", | |
| 240 | 262 | "miette", |
| 241 | 263 | "num", |
| 242 | "parser", | |
| 243 | 264 | "thiserror", |
| 244 | "tokenizer", | |
| 245 | 265 | ] |
| 246 | 266 | |
| 247 | 267 | [[package]] |
| ... | ... | @@ -266,6 +286,15 @@ version = "0.4.12" |
| 266 | 286 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 267 | 287 | checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" |
| 268 | 288 | |
| 289 | [[package]] | |
| 290 | name = "log" | |
| 291 | version = "0.0.0" | |
| 292 | dependencies = [ | |
| 293 | "miette", | |
| 294 | "thiserror", | |
| 295 | "url", | |
| 296 | ] | |
| 297 | ||
| 269 | 298 | [[package]] |
| 270 | 299 | name = "memchr" |
| 271 | 300 | version = "2.7.1" |
| ... | ... | @@ -415,12 +444,19 @@ name = "parser" |
| 415 | 444 | version = "0.1.0" |
| 416 | 445 | dependencies = [ |
| 417 | 446 | "ast", |
| 447 | "log", | |
| 418 | 448 | "miette", |
| 419 | 449 | "num", |
| 420 | 450 | "thiserror", |
| 421 | 451 | "tokenizer", |
| 422 | 452 | ] |
| 423 | 453 | |
| 454 | [[package]] | |
| 455 | name = "percent-encoding" | |
| 456 | version = "2.3.1" | |
| 457 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 458 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" | |
| 459 | ||
| 424 | 460 | [[package]] |
| 425 | 461 | name = "proc-macro2" |
| 426 | 462 | version = "1.0.76" |
| ... | ... | @@ -560,14 +596,36 @@ dependencies = [ |
| 560 | 596 | "syn", |
| 561 | 597 | ] |
| 562 | 598 | |
| 599 | [[package]] | |
| 600 | name = "tinyvec" | |
| 601 | version = "1.6.0" | |
| 602 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 603 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" | |
| 604 | dependencies = [ | |
| 605 | "tinyvec_macros", | |
| 606 | ] | |
| 607 | ||
| 608 | [[package]] | |
| 609 | name = "tinyvec_macros" | |
| 610 | version = "0.1.1" | |
| 611 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 612 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | |
| 613 | ||
| 563 | 614 | [[package]] |
| 564 | 615 | name = "tokenizer" |
| 565 | 616 | version = "0.1.0" |
| 566 | 617 | dependencies = [ |
| 618 | "log", | |
| 567 | 619 | "miette", |
| 568 | 620 | "thiserror", |
| 569 | 621 | ] |
| 570 | 622 | |
| 623 | [[package]] | |
| 624 | name = "unicode-bidi" | |
| 625 | version = "0.3.15" | |
| 626 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 627 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" | |
| 628 | ||
| 571 | 629 | [[package]] |
| 572 | 630 | name = "unicode-ident" |
| 573 | 631 | version = "1.0.12" |
| ... | ... | @@ -580,12 +638,32 @@ version = "0.1.5" |
| 580 | 638 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 581 | 639 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" |
| 582 | 640 | |
| 641 | [[package]] | |
| 642 | name = "unicode-normalization" | |
| 643 | version = "0.1.22" | |
| 644 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 645 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" | |
| 646 | dependencies = [ | |
| 647 | "tinyvec", | |
| 648 | ] | |
| 649 | ||
| 583 | 650 | [[package]] |
| 584 | 651 | name = "unicode-width" |
| 585 | 652 | version = "0.1.11" |
| 586 | 653 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 587 | 654 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" |
| 588 | 655 | |
| 656 | [[package]] | |
| 657 | name = "url" | |
| 658 | version = "2.5.0" | |
| 659 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 660 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" | |
| 661 | dependencies = [ | |
| 662 | "form_urlencoded", | |
| 663 | "idna", | |
| 664 | "percent-encoding", | |
| 665 | ] | |
| 666 | ||
| 589 | 667 | [[package]] |
| 590 | 668 | name = "utf8parse" |
| 591 | 669 | version = "0.2.1" |
Cargo.toml+3-1| ... | ... | @@ -9,11 +9,12 @@ repository = "https://github.com/lino-levan/blight" |
| 9 | 9 | resolver = "2" |
| 10 | 10 | members = [ |
| 11 | 11 | "crates/ast", |
| 12 | "crates/sema", | |
| 13 | 12 | "crates/cli", |
| 14 | 13 | "crates/js_ast", |
| 15 | 14 | "crates/js_printer", |
| 15 | "crates/log", | |
| 16 | 16 | "crates/parser", |
| 17 | "crates/sema", | |
| 17 | 18 | "crates/tokenizer", |
| 18 | 19 | ] |
| 19 | 20 | |
| ... | ... | @@ -22,3 +23,4 @@ clap = { version = "4.4.12", features = ["derive"] } |
| 22 | 23 | miette = { version = "5.10.0", features = ["fancy"] } |
| 23 | 24 | thiserror = "1.0.53" |
| 24 | 25 | num = "0.4.1" |
| 26 | url = "2.2.2" |
crates/ast/Cargo.toml+2-1| ... | ... | @@ -11,4 +11,5 @@ miette.workspace = true |
| 11 | 11 | thiserror.workspace = true |
| 12 | 12 | num.workspace = true |
| 13 | 13 | |
| 14 | tokenizer = { path = "../tokenizer" } | |
| 14 | tokenizer = { path = "../tokenizer" } # Do not depend on the tokenizer | |
| 15 | log = { path = "../log" } |
crates/ast/ast.rs+19-17| ... | ... | @@ -1,9 +1,7 @@ |
| 1 | use tokenizer::Loc; | |
| 1 | use log::Range; | |
| 2 | 2 | |
| 3 | use crate::{ | |
| 4 | types::{Literal, Type}, | |
| 5 | BinaryOperator, UnaryOperator, | |
| 6 | }; | |
| 3 | use crate::types::{Literal, Type}; | |
| 4 | use crate::{BinaryOperator, UnaryOperator}; | |
| 7 | 5 | |
| 8 | 6 | #[derive(Debug, Clone)] |
| 9 | 7 | pub enum BuiltinId { |
| ... | ... | @@ -36,7 +34,7 @@ pub struct VarDecl { |
| 36 | 34 | pub init: Expr, |
| 37 | 35 | pub is_constant: bool, |
| 38 | 36 | pub is_pub: bool, |
| 39 | pub loc: Loc, | |
| 37 | pub range: Range, | |
| 40 | 38 | pub comment: Option<DocComment>, |
| 41 | 39 | } |
| 42 | 40 | |
| ... | ... | @@ -47,27 +45,31 @@ pub struct FnDecl { |
| 47 | 45 | pub params: Vec<Param>, |
| 48 | 46 | pub body: Expr, |
| 49 | 47 | pub is_pub: bool, |
| 50 | pub loc: Loc, | |
| 48 | pub range: Range, | |
| 51 | 49 | pub comment: Option<DocComment>, |
| 52 | 50 | } |
| 53 | 51 | |
| 54 | 52 | #[derive(Debug, Clone)] |
| 55 | 53 | pub struct Expr { |
| 56 | 54 | pub data: ExprData, |
| 57 | pub loc: Loc, | |
| 55 | pub range: Range, | |
| 58 | 56 | pub comment: Option<Comment>, |
| 59 | 57 | } |
| 60 | 58 | |
| 61 | 59 | impl Expr { |
| 62 | pub fn new(data: ExprData, loc: Loc, comment: Option<Comment>) -> Self { | |
| 63 | Self { data, loc, comment } | |
| 60 | pub fn new(data: ExprData, range: Range, comment: Option<Comment>) -> Self { | |
| 61 | Self { | |
| 62 | data, | |
| 63 | range, | |
| 64 | comment, | |
| 65 | } | |
| 64 | 66 | } |
| 65 | 67 | } |
| 66 | 68 | |
| 67 | 69 | #[derive(Debug, Clone)] |
| 68 | 70 | pub struct DocComment { |
| 69 | 71 | pub data: String, |
| 70 | pub loc: Loc, | |
| 72 | pub range: Range, | |
| 71 | 73 | } |
| 72 | 74 | |
| 73 | 75 | #[derive(Debug, PartialEq, Clone)] |
| ... | ... | @@ -86,10 +88,10 @@ impl Comment { |
| 86 | 88 | result |
| 87 | 89 | } |
| 88 | 90 | |
| 89 | pub fn to_doc_comment(self, loc: Loc) -> DocComment { | |
| 91 | pub fn to_doc_comment(self, range: Range) -> DocComment { | |
| 90 | 92 | DocComment { |
| 91 | 93 | data: self.data, |
| 92 | loc, | |
| 94 | range, | |
| 93 | 95 | } |
| 94 | 96 | } |
| 95 | 97 | } |
| ... | ... | @@ -113,21 +115,21 @@ impl DocComment { |
| 113 | 115 | } |
| 114 | 116 | |
| 115 | 117 | #[derive(Debug, Clone)] |
| 116 | pub struct BlockWithLoc { | |
| 118 | pub struct BlockWithRange { | |
| 117 | 119 | pub block: Block, |
| 118 | pub loc: Loc, | |
| 120 | pub range: Range, | |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | 123 | #[derive(Debug, Clone)] |
| 122 | 124 | pub struct If { |
| 123 | 125 | pub condition: Box<Expr>, |
| 124 | pub yes: BlockWithLoc, | |
| 126 | pub yes: BlockWithRange, | |
| 125 | 127 | pub no: Option<BlockOrIf>, |
| 126 | 128 | } |
| 127 | 129 | |
| 128 | 130 | #[derive(Debug, Clone)] |
| 129 | 131 | pub enum BlockOrIf { |
| 130 | Block(BlockWithLoc), | |
| 132 | Block(BlockWithRange), | |
| 131 | 133 | If(Box<If>), |
| 132 | 134 | } |
| 133 | 135 |
crates/ast/types.rs-74| ... | ... | @@ -120,80 +120,6 @@ pub fn merge_types(a: Type, b: Type) -> Result<Type> { |
| 120 | 120 | Err(TypeError::new(format!("TODO: Implement type merging for {} and {}", a, b)).into()) |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | // pub fn coerce_type(target: Type, source: Type) -> Result<Type> { | |
| 124 | // match source { | |
| 125 | // Type::Any => return Ok(target), | |
| 126 | // _ => {} | |
| 127 | // } | |
| 128 | // match target { | |
| 129 | // Type::Infer => Ok(source), | |
| 130 | // Type::Any => Ok(Type::Any), | |
| 131 | ||
| 132 | // Type::Literal(_) => unreachable!(), | |
| 133 | ||
| 134 | // Type::Int => match source { | |
| 135 | // Type::Int => Ok(Type::Int), | |
| 136 | // Type::Float => Ok(Type::Int), | |
| 137 | // Type::Literal(value) => { | |
| 138 | // if value.fract() != 0.0 { | |
| 139 | // Err( | |
| 140 | // TypeError::new(format!("Numeric Literal '{}' is not an integer", value)) | |
| 141 | // .into(), | |
| 142 | // ) | |
| 143 | // } else if value > i32::MAX.into() || value < i32::MIN.into() { | |
| 144 | // Err(TypeError::new(format!( | |
| 145 | // "Numeric Literal '{}' is out of range for an integer ({}..{})", | |
| 146 | // value, | |
| 147 | // i32::MIN, | |
| 148 | // i32::MAX | |
| 149 | // )) | |
| 150 | // .into()) | |
| 151 | // } else { | |
| 152 | // Ok(Type::Int) | |
| 153 | // } | |
| 154 | // } | |
| 155 | // t => Err(TypeError::new(format!("Cannot coerce {} to int", t)).into()), | |
| 156 | // }, | |
| 157 | ||
| 158 | // Type::BigInt => match source { | |
| 159 | // Type::Int => Ok(Type::Int), | |
| 160 | // Type::Float => Ok(Type::Int), | |
| 161 | // Type::NumberLiteral(value) => { | |
| 162 | // if value.fract() != 0.0 { | |
| 163 | // Err( | |
| 164 | // TypeError::new(format!("Numeric Literal '{}' is not an integer", value)) | |
| 165 | // .into(), | |
| 166 | // ) | |
| 167 | // } else { | |
| 168 | // Ok(Type::BigInt) | |
| 169 | // } | |
| 170 | // } | |
| 171 | // t => Err(TypeError::new(format!("Cannot coerce {} to int", t)).into()), | |
| 172 | // }, | |
| 173 | ||
| 174 | // Type::Float => match source { | |
| 175 | // Type::Int => Ok(Type::Float), | |
| 176 | // Type::Float => Ok(Type::Float), | |
| 177 | // Type::NumberLiteral(value) => { | |
| 178 | // if value.fract() == 0.0 && value <= f64::MAX.into() && value >= f64::MIN.into() { | |
| 179 | // Ok(Type::Float) | |
| 180 | // } else { | |
| 181 | // Err(TypeError::new(format!("Numeric Literal")).into()) | |
| 182 | // } | |
| 183 | // } | |
| 184 | // _ => Err(TypeError::new(format!("Cannot coerce int to float")).into()), | |
| 185 | // }, | |
| 186 | ||
| 187 | // other => { | |
| 188 | // if other == source { | |
| 189 | // Ok(other) | |
| 190 | // } else { | |
| 191 | // Err(TypeError::new(format!("Cannot coerce {} to {}", source, other)).into()) | |
| 192 | // } | |
| 193 | // } | |
| 194 | // } | |
| 195 | // } | |
| 196 | ||
| 197 | 123 | #[derive(Error, Diagnostic, Debug)] |
| 198 | 124 | #[error("TypeError")] |
| 199 | 125 | pub struct TypeError { |
crates/cli/Cargo.toml+1| ... | ... | @@ -18,3 +18,4 @@ parser = { path = "../parser" } |
| 18 | 18 | js_ast = { path = "../js_ast" } |
| 19 | 19 | js_printer = { path = "../js_printer" } |
| 20 | 20 | sema = { path = "../sema" } |
| 21 | log = { path = "../log" } |
crates/js_ast/Cargo.toml+1-2| ... | ... | @@ -12,5 +12,4 @@ thiserror.workspace = true |
| 12 | 12 | num.workspace = true |
| 13 | 13 | |
| 14 | 14 | ast = { path = "../ast" } |
| 15 | tokenizer = { path = "../tokenizer" } # TODO: move Loc out of the tokenizer | |
| 16 | parser = { path = "../parser" } # TODO: move Loc out of the tokenizer | |
| 15 | log = { path = "../log" } |
crates/js_ast/convert/block_convert_context.rs+8-8| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | use crate::js_ast::*; |
| 2 | 2 | use ast::*; |
| 3 | use log::Range; | |
| 3 | 4 | use std::collections::{HashMap, HashSet}; |
| 4 | 5 | use std::vec; |
| 5 | use tokenizer::Loc; | |
| 6 | 6 | |
| 7 | 7 | use super::tree_shake_statement_list; |
| 8 | 8 | |
| ... | ... | @@ -198,33 +198,33 @@ impl BlockConvertContext { |
| 198 | 198 | } |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | pub fn new_js_assignment_statement(expr: JsExpr, target: String, loc: Loc) -> JsStatement { | |
| 201 | pub fn new_js_assignment_statement(expr: JsExpr, target: String, range: Range) -> JsStatement { | |
| 202 | 202 | JsStatement::new( |
| 203 | JsStatementData::Expression(new_js_assignment_expr(expr, target, loc.clone())), | |
| 204 | loc, | |
| 203 | JsStatementData::Expression(new_js_assignment_expr(expr, target, range.clone())), | |
| 204 | range, | |
| 205 | 205 | None, |
| 206 | 206 | ) |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | pub fn new_js_assignment_expr(expr: JsExpr, target: String, loc: Loc) -> JsExpr { | |
| 209 | pub fn new_js_assignment_expr(expr: JsExpr, target: String, range: Range) -> JsExpr { | |
| 210 | 210 | JsExpr::new( |
| 211 | 211 | JsExprData::Binary { |
| 212 | 212 | op: BinaryOperator::Assign, |
| 213 | 213 | left: Box::new(JsExpr::new( |
| 214 | 214 | JsExprData::Identifier(target), |
| 215 | loc.clone(), | |
| 215 | range.clone(), | |
| 216 | 216 | None, |
| 217 | 217 | )), |
| 218 | 218 | right: Box::new(expr), |
| 219 | 219 | }, |
| 220 | loc, | |
| 220 | range, | |
| 221 | 221 | None, |
| 222 | 222 | ) |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | 225 | impl Into<JsBlock> for BlockConvertContext { |
| 226 | 226 | fn into(self) -> JsBlock { |
| 227 | JsBlock::new(self.into(), Loc::EMPTY) | |
| 227 | JsBlock::new(self.into(), Range::EMPTY) | |
| 228 | 228 | } |
| 229 | 229 | } |
| 230 | 230 |
crates/js_ast/convert/convert_valid_block.rs+6-7| ... | ... | @@ -3,18 +3,18 @@ use super::BlockConvertContext; |
| 3 | 3 | use super::IsValidJSExpression; |
| 4 | 4 | use crate::js_ast::*; |
| 5 | 5 | use ast::*; |
| 6 | use tokenizer::Loc; | |
| 6 | use log::Range; | |
| 7 | 7 | |
| 8 | pub fn convert_valid_block(ctx: &mut BlockConvertContext, block: Block, loc: Loc) -> JsExpr { | |
| 8 | pub fn convert_valid_block(ctx: &mut BlockConvertContext, block: Block, range: Range) -> JsExpr { | |
| 9 | 9 | debug_assert!( |
| 10 | 10 | block.is_valid_js_expression(), |
| 11 | 11 | "must call convert_valid_block with valid js expression" |
| 12 | 12 | ); |
| 13 | 13 | |
| 14 | 14 | let len = block.statements.len(); |
| 15 | let loc = loc; | |
| 15 | let range = range; | |
| 16 | 16 | let block_expr = match len { |
| 17 | 0 => JsExpr::new(JsExprData::Null, loc.clone(), None), | |
| 17 | 0 => JsExpr::new(JsExprData::Null, range.clone(), None), | |
| 18 | 18 | // a block expression with a single expression is just that expression |
| 19 | 19 | 1 => convert_valid_statement_to_expr(ctx, block.statements.into_iter().next().unwrap()), |
| 20 | 20 | // Since blocks are not valid expressions in JS, we create a |
| ... | ... | @@ -24,14 +24,13 @@ pub fn convert_valid_block(ctx: &mut BlockConvertContext, block: Block, loc: Loc |
| 24 | 24 | for statement in block.statements.into_iter() { |
| 25 | 25 | items.push(convert_valid_statement_to_expr(ctx, statement)); |
| 26 | 26 | } |
| 27 | JsExpr::new(JsExprData::Comma { items }, loc.clone(), None) | |
| 27 | JsExpr::new(JsExprData::Comma { items }, range.clone(), None) | |
| 28 | 28 | } |
| 29 | _ => todo!(), | |
| 30 | 29 | }; |
| 31 | 30 | |
| 32 | 31 | // a block without implicit return is to be type void, so we wrap in a void expression |
| 33 | 32 | if !block.has_implicit_return && len > 0 { |
| 34 | JsExpr::new(JsExprData::Void(Box::new(block_expr)), loc, None) | |
| 33 | JsExpr::new(JsExprData::Void(Box::new(block_expr)), range, None) | |
| 35 | 34 | } else { |
| 36 | 35 | block_expr |
| 37 | 36 | } |
crates/js_ast/convert/convert_valid_expr.rs+14-14| ... | ... | @@ -16,28 +16,28 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 16 | 16 | "must call convert_valid_expr with valid js expression (use hoist instead)" |
| 17 | 17 | ); |
| 18 | 18 | |
| 19 | let loc = expr.loc; | |
| 19 | let range = expr.range; | |
| 20 | 20 | let comment = expr.comment; |
| 21 | 21 | |
| 22 | 22 | match expr.data { |
| 23 | 23 | ExprData::Identifier(str) => JsExpr::new( |
| 24 | 24 | JsExprData::Identifier(ctx.remap_identifier(&str)), |
| 25 | loc, | |
| 25 | range, | |
| 26 | 26 | comment, |
| 27 | 27 | ), |
| 28 | 28 | |
| 29 | 29 | ExprData::Literal(Literal::Bool(value)) => { |
| 30 | JsExpr::new(JsExprData::Bool(value), loc, comment) | |
| 30 | JsExpr::new(JsExprData::Bool(value), range, comment) | |
| 31 | 31 | } |
| 32 | 32 | ExprData::Literal(Literal::Number(value)) => { |
| 33 | JsExpr::new(JsExprData::Number(value), loc, comment) | |
| 33 | JsExpr::new(JsExprData::Number(value), range, comment) | |
| 34 | 34 | } |
| 35 | 35 | ExprData::Literal(Literal::String(value)) => { |
| 36 | JsExpr::new(JsExprData::String(value), loc, comment) | |
| 36 | JsExpr::new(JsExprData::String(value), range, comment) | |
| 37 | 37 | } |
| 38 | ExprData::Literal(Literal::Void) => JsExpr::new(JsExprData::Null, loc, comment), | |
| 38 | ExprData::Literal(Literal::Void) => JsExpr::new(JsExprData::Null, range, comment), | |
| 39 | 39 | |
| 40 | ExprData::Block(block) => convert_valid_block(ctx, block, loc), | |
| 40 | ExprData::Block(block) => convert_valid_block(ctx, block, range), | |
| 41 | 41 | |
| 42 | 42 | ExprData::Binary { op, left, right } => { |
| 43 | 43 | let left = convert_valid_expr(ctx, *left); |
| ... | ... | @@ -48,7 +48,7 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 48 | 48 | left: Box::new(left), |
| 49 | 49 | right: Box::new(right), |
| 50 | 50 | }, |
| 51 | loc, | |
| 51 | range, | |
| 52 | 52 | comment, |
| 53 | 53 | ) |
| 54 | 54 | } |
| ... | ... | @@ -59,12 +59,12 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 59 | 59 | op, |
| 60 | 60 | value: Box::new(value), |
| 61 | 61 | }, |
| 62 | loc, | |
| 62 | range, | |
| 63 | 63 | comment, |
| 64 | 64 | ) |
| 65 | 65 | } |
| 66 | 66 | ExprData::Fn { body, params, .. } => { |
| 67 | process_function_to_arrow(ctx, *body, params, loc, comment) | |
| 67 | process_function_to_arrow(ctx, *body, params, range, comment) | |
| 68 | 68 | } |
| 69 | 69 | ExprData::Builtin { id, arguments } => match id { |
| 70 | 70 | BuiltinId::Raw => { |
| ... | ... | @@ -74,10 +74,10 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 74 | 74 | ExprData::Literal(Literal::String(s)) => s, |
| 75 | 75 | _ => panic!("raw expects a string"), |
| 76 | 76 | }; |
| 77 | JsExpr::new(JsExprData::Raw(str), loc, comment) | |
| 77 | JsExpr::new(JsExprData::Raw(str), range, comment) | |
| 78 | 78 | } |
| 79 | 79 | }, |
| 80 | ExprData::If(expr) => convert_valid_if(ctx, expr, loc, comment), | |
| 80 | ExprData::If(expr) => convert_valid_if(ctx, expr, range, comment), | |
| 81 | 81 | |
| 82 | 82 | ExprData::Call { base, arguments } => { |
| 83 | 83 | let base = convert_valid_expr(ctx, *base); |
| ... | ... | @@ -90,7 +90,7 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 90 | 90 | base: Box::new(base), |
| 91 | 91 | arguments, |
| 92 | 92 | }, |
| 93 | loc, | |
| 93 | range, | |
| 94 | 94 | comment, |
| 95 | 95 | ) |
| 96 | 96 | } |
| ... | ... | @@ -106,7 +106,7 @@ pub fn convert_valid_expr(ctx: &mut BlockConvertContext, expr: Expr) -> JsExpr { |
| 106 | 106 | index: Box::new(convert_valid_expr(ctx, *field)), |
| 107 | 107 | }, |
| 108 | 108 | }, |
| 109 | loc, | |
| 109 | range, | |
| 110 | 110 | comment, |
| 111 | 111 | ), |
| 112 | 112 |
crates/js_ast/convert/convert_valid_if.rs+6-6| ... | ... | @@ -4,13 +4,13 @@ use super::BlockConvertContext; |
| 4 | 4 | use crate::convert::IsValidJSExpression; |
| 5 | 5 | use crate::js_ast::*; |
| 6 | 6 | use ast::*; |
| 7 | use tokenizer::Loc; | |
| 7 | use log::Range; | |
| 8 | 8 | |
| 9 | 9 | /// Convert a valid blight if statement to a JS expression |
| 10 | 10 | pub fn convert_valid_if( |
| 11 | 11 | ctx: &mut BlockConvertContext, |
| 12 | 12 | expr: If, |
| 13 | loc: Loc, | |
| 13 | range: Range, | |
| 14 | 14 | comment: Option<Comment>, |
| 15 | 15 | ) -> JsExpr { |
| 16 | 16 | debug_assert!( |
| ... | ... | @@ -19,10 +19,10 @@ pub fn convert_valid_if( |
| 19 | 19 | ); |
| 20 | 20 | let condition = convert_valid_expr(ctx, *expr.condition); |
| 21 | 21 | |
| 22 | let yes = convert_valid_block(ctx, expr.yes.block, expr.yes.loc); | |
| 22 | let yes = convert_valid_block(ctx, expr.yes.block, expr.yes.range); | |
| 23 | 23 | let no = match expr.no { |
| 24 | Some(BlockOrIf::Block(b)) => Some(convert_valid_block(ctx, b.block, b.loc)), | |
| 25 | Some(BlockOrIf::If(else_if)) => Some(convert_valid_if(ctx, *else_if, Loc::EMPTY, None)), | |
| 24 | Some(BlockOrIf::Block(b)) => Some(convert_valid_block(ctx, b.block, b.range)), | |
| 25 | Some(BlockOrIf::If(else_if)) => Some(convert_valid_if(ctx, *else_if, Range::EMPTY, None)), | |
| 26 | 26 | None => None, |
| 27 | 27 | }; |
| 28 | 28 | |
| ... | ... | @@ -32,7 +32,7 @@ pub fn convert_valid_if( |
| 32 | 32 | yes: Box::new(yes), |
| 33 | 33 | no: no.map(Box::new), |
| 34 | 34 | }, |
| 35 | loc, | |
| 35 | range, | |
| 36 | 36 | comment, |
| 37 | 37 | ) |
| 38 | 38 | } |
crates/js_ast/convert/convert_valid_statement.rs+2-2| ... | ... | @@ -27,6 +27,6 @@ pub fn convert_valid_statement_to_expr( |
| 27 | 27 | /// TODO(@paperdave): Replace this with Into<JsStatement> for JsExpr |
| 28 | 28 | pub fn convert_valid_statement(ctx: &mut BlockConvertContext, statement: Statement) -> JsStatement { |
| 29 | 29 | let expr = convert_valid_statement_to_expr(ctx, statement); |
| 30 | let loc = expr.loc.clone(); | |
| 31 | JsStatement::new(JsStatementData::Expression(expr), loc, None) | |
| 30 | let range = expr.range.clone(); | |
| 31 | JsStatement::new(JsStatementData::Expression(expr), range, None) | |
| 32 | 32 | } |
crates/js_ast/convert/hoist_block_to_expr.rs+5-5| ... | ... | @@ -3,7 +3,7 @@ use super::process_statement; |
| 3 | 3 | use super::BlockConvertContext; |
| 4 | 4 | use crate::js_ast::*; |
| 5 | 5 | use ast::*; |
| 6 | use tokenizer::Loc; | |
| 6 | use log::Range; | |
| 7 | 7 | |
| 8 | 8 | /// This block hoist is used when we have a block in an expression context. |
| 9 | 9 | /// |
| ... | ... | @@ -30,7 +30,7 @@ use tokenizer::Loc; |
| 30 | 30 | pub fn hoist_block_to_expr( |
| 31 | 31 | ctx: &mut BlockConvertContext, |
| 32 | 32 | block: Block, |
| 33 | loc: Loc, | |
| 33 | range: Range, | |
| 34 | 34 | comment: Option<Comment>, |
| 35 | 35 | ) -> Option<JsExpr> { |
| 36 | 36 | debug_assert!( |
| ... | ... | @@ -57,7 +57,7 @@ pub fn hoist_block_to_expr( |
| 57 | 57 | _ => unreachable!(), |
| 58 | 58 | } |
| 59 | 59 | } |
| 60 | _ => JsExpr::new(JsExprData::Null, loc.clone(), None), | |
| 60 | _ => JsExpr::new(JsExprData::Null, range.clone(), None), | |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | 63 | ctx.add_statement(JsStatement::new( |
| ... | ... | @@ -66,13 +66,13 @@ pub fn hoist_block_to_expr( |
| 66 | 66 | init: Some(result), |
| 67 | 67 | is_constant: false, |
| 68 | 68 | }), |
| 69 | loc.clone(), | |
| 69 | range.clone(), | |
| 70 | 70 | comment, |
| 71 | 71 | )); |
| 72 | 72 | |
| 73 | 73 | Some(JsExpr::new( |
| 74 | 74 | JsExprData::Identifier(temporary.get(&ctx)), |
| 75 | loc, | |
| 75 | range, | |
| 76 | 76 | None, |
| 77 | 77 | )) |
| 78 | 78 | } |
crates/js_ast/convert/hoist_block_to_js_block.rs+6-6| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use crate::js_ast::*; |
| 2 | 2 | use ast::*; |
| 3 | use tokenizer::Loc; | |
| 3 | use log::Range; | |
| 4 | 4 | |
| 5 | 5 | use super::*; |
| 6 | 6 | |
| ... | ... | @@ -22,7 +22,7 @@ use super::*; |
| 22 | 22 | pub fn hoist_block_to_js_block( |
| 23 | 23 | ctx: &mut BlockConvertContext, |
| 24 | 24 | block: Block, |
| 25 | loc: Loc, | |
| 25 | range: Range, | |
| 26 | 26 | target: &TempId, |
| 27 | 27 | did_assign: &mut bool, |
| 28 | 28 | ) -> JsBlock { |
| ... | ... | @@ -34,11 +34,11 @@ pub fn hoist_block_to_js_block( |
| 34 | 34 | if block.is_valid_js_expression() { |
| 35 | 35 | return JsBlock::new( |
| 36 | 36 | vec![new_js_assignment_statement( |
| 37 | convert_valid_block(ctx, block, loc.clone()), | |
| 37 | convert_valid_block(ctx, block, range.clone()), | |
| 38 | 38 | target.get(ctx), |
| 39 | loc.clone(), | |
| 39 | range.clone(), | |
| 40 | 40 | )], |
| 41 | loc, | |
| 41 | range, | |
| 42 | 42 | ); |
| 43 | 43 | } |
| 44 | 44 | |
| ... | ... | @@ -59,7 +59,7 @@ pub fn hoist_block_to_js_block( |
| 59 | 59 | child.add_statement(new_js_assignment_statement( |
| 60 | 60 | expr, |
| 61 | 61 | target.get(ctx), |
| 62 | loc.clone(), | |
| 62 | range.clone(), | |
| 63 | 63 | )); |
| 64 | 64 | } |
| 65 | 65 | _ => {} |
crates/js_ast/convert/hoist_expr.rs+14-10| ... | ... | @@ -18,7 +18,7 @@ pub fn hoist_expr_if_needed(ctx: &mut BlockConvertContext, expr: Expr) -> Option |
| 18 | 18 | let init = hoist_expr_contents(ctx, expr)?; |
| 19 | 19 | |
| 20 | 20 | let id = ctx.generate_temp_id("_"); |
| 21 | let loc = init.loc.clone(); | |
| 21 | let range = init.range.clone(); | |
| 22 | 22 | |
| 23 | 23 | ctx.add_statement(JsStatement::new( |
| 24 | 24 | JsStatementData::Declaration(JSDeclaration { |
| ... | ... | @@ -26,11 +26,15 @@ pub fn hoist_expr_if_needed(ctx: &mut BlockConvertContext, expr: Expr) -> Option |
| 26 | 26 | init: Some(init), |
| 27 | 27 | is_constant: true, |
| 28 | 28 | }), |
| 29 | loc.clone(), | |
| 29 | range.clone(), | |
| 30 | 30 | None, |
| 31 | 31 | )); |
| 32 | 32 | |
| 33 | Some(JsExpr::new(JsExprData::Identifier(id.get(&ctx)), loc, None)) | |
| 33 | Some(JsExpr::new( | |
| 34 | JsExprData::Identifier(id.get(&ctx)), | |
| 35 | range, | |
| 36 | None, | |
| 37 | )) | |
| 34 | 38 | } |
| 35 | 39 | |
| 36 | 40 | /// Returning `None` from this means that the expression is noreturn, and that |
| ... | ... | @@ -51,7 +55,7 @@ pub fn hoist_expr_contents(ctx: &mut BlockConvertContext, expr: Expr) -> Option< |
| 51 | 55 | left: Box::new(left), |
| 52 | 56 | right: Box::new(right), |
| 53 | 57 | }, |
| 54 | expr.loc, | |
| 58 | expr.range, | |
| 55 | 59 | expr.comment, |
| 56 | 60 | )) |
| 57 | 61 | } |
| ... | ... | @@ -63,7 +67,7 @@ pub fn hoist_expr_contents(ctx: &mut BlockConvertContext, expr: Expr) -> Option< |
| 63 | 67 | op, |
| 64 | 68 | value: Box::new(value), |
| 65 | 69 | }, |
| 66 | expr.loc, | |
| 70 | expr.range, | |
| 67 | 71 | expr.comment, |
| 68 | 72 | )) |
| 69 | 73 | } |
| ... | ... | @@ -85,24 +89,24 @@ pub fn hoist_expr_contents(ctx: &mut BlockConvertContext, expr: Expr) -> Option< |
| 85 | 89 | index: Box::new(field), |
| 86 | 90 | }, |
| 87 | 91 | }, |
| 88 | expr.loc, | |
| 92 | expr.range, | |
| 89 | 93 | expr.comment, |
| 90 | 94 | )) |
| 91 | 95 | } |
| 92 | 96 | |
| 93 | ExprData::Block(block) => hoist_block_to_expr(ctx, block, expr.loc, expr.comment), | |
| 97 | ExprData::Block(block) => hoist_block_to_expr(ctx, block, expr.range, expr.comment), | |
| 94 | 98 | |
| 95 | 99 | ExprData::If(_) => hoist_if_expr(ctx, expr), |
| 96 | 100 | |
| 97 | 101 | ExprData::Return(maybe_expr) => { |
| 98 | let loc = expr.loc.clone(); | |
| 102 | let range = expr.range.clone(); | |
| 99 | 103 | let return_value = match maybe_expr { |
| 100 | 104 | Some(expr) => Some(hoist_expr_if_needed(ctx, *expr)?), |
| 101 | 105 | None => None, |
| 102 | 106 | }; |
| 103 | 107 | ctx.add_statement(JsStatement::new( |
| 104 | 108 | JsStatementData::Return(return_value), |
| 105 | loc, | |
| 109 | range, | |
| 106 | 110 | None, |
| 107 | 111 | )); |
| 108 | 112 | None |
| ... | ... | @@ -120,7 +124,7 @@ pub fn hoist_expr_contents(ctx: &mut BlockConvertContext, expr: Expr) -> Option< |
| 120 | 124 | base: Box::new(base), |
| 121 | 125 | arguments, |
| 122 | 126 | }, |
| 123 | expr.loc, | |
| 127 | expr.range, | |
| 124 | 128 | expr.comment, |
| 125 | 129 | )) |
| 126 | 130 | } |
crates/js_ast/convert/hoist_if.rs+9-9| ... | ... | @@ -6,7 +6,7 @@ use super::IsValidJSExpression; |
| 6 | 6 | use super::TempId; |
| 7 | 7 | use crate::js_ast::*; |
| 8 | 8 | use ast::*; |
| 9 | use tokenizer::Loc; | |
| 9 | use log::Range; | |
| 10 | 10 | |
| 11 | 11 | pub fn hoist_if_expr(ctx: &mut BlockConvertContext, expr: Expr) -> Option<JsExpr> { |
| 12 | 12 | let data = match expr.data { |
| ... | ... | @@ -22,7 +22,7 @@ pub fn hoist_if_expr(ctx: &mut BlockConvertContext, expr: Expr) -> Option<JsExpr |
| 22 | 22 | init: None, |
| 23 | 23 | is_constant: false, |
| 24 | 24 | }), |
| 25 | expr.loc.clone(), | |
| 25 | expr.range.clone(), | |
| 26 | 26 | None, |
| 27 | 27 | )); |
| 28 | 28 | |
| ... | ... | @@ -40,35 +40,35 @@ pub fn hoist_if_expr(ctx: &mut BlockConvertContext, expr: Expr) -> Option<JsExpr |
| 40 | 40 | |
| 41 | 41 | ctx.add_statement(JsStatement::new( |
| 42 | 42 | JsStatementData::If(js_if), |
| 43 | expr.loc.clone(), | |
| 43 | expr.range.clone(), | |
| 44 | 44 | None, |
| 45 | 45 | )); |
| 46 | 46 | |
| 47 | 47 | if did_assign { |
| 48 | 48 | Some(JsExpr::new( |
| 49 | 49 | JsExprData::Identifier(temporary.get(&ctx)), |
| 50 | expr.loc, | |
| 50 | expr.range, | |
| 51 | 51 | expr.comment, |
| 52 | 52 | )) |
| 53 | 53 | } else { |
| 54 | 54 | decl.delete(ctx); |
| 55 | Some(JsExpr::new(JsExprData::Null, expr.loc, expr.comment)) | |
| 55 | Some(JsExpr::new(JsExprData::Null, expr.range, expr.comment)) | |
| 56 | 56 | } |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | pub fn hoist_if_branch( |
| 60 | 60 | ctx: &mut BlockConvertContext, |
| 61 | yes: BlockWithLoc, | |
| 61 | yes: BlockWithRange, | |
| 62 | 62 | no: Option<BlockOrIf>, |
| 63 | 63 | condition: JsExpr, |
| 64 | 64 | did_assign: &mut bool, |
| 65 | 65 | temporary: &TempId, |
| 66 | 66 | ) -> JsIf { |
| 67 | let yes = hoist_block_to_js_block(ctx, yes.block, yes.loc, &temporary, did_assign); | |
| 67 | let yes = hoist_block_to_js_block(ctx, yes.block, yes.range, &temporary, did_assign); | |
| 68 | 68 | |
| 69 | 69 | let no = match no { |
| 70 | 70 | Some(BlockOrIf::Block(no)) => Some(JsElse::Block(hoist_block_to_js_block( |
| 71 | ctx, no.block, no.loc, &temporary, did_assign, | |
| 71 | ctx, no.block, no.range, &temporary, did_assign, | |
| 72 | 72 | ))), |
| 73 | 73 | Some(BlockOrIf::If(else_if)) => { |
| 74 | 74 | // If the condition of this block has a side effect, we need to |
| ... | ... | @@ -99,7 +99,7 @@ pub fn hoist_if_branch( |
| 99 | 99 | did_assign, |
| 100 | 100 | temporary, |
| 101 | 101 | )), |
| 102 | Loc::EMPTY, | |
| 102 | Range::EMPTY, | |
| 103 | 103 | None, |
| 104 | 104 | )); |
| 105 | 105 |
crates/js_ast/convert/is_valid_js_expression.rs+1-1| ... | ... | @@ -75,7 +75,7 @@ impl IsValidJSExpression for BlockOrIf { |
| 75 | 75 | } |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | impl IsValidJSExpression for BlockWithLoc { | |
| 78 | impl IsValidJSExpression for BlockWithRange { | |
| 79 | 79 | fn is_valid_js_expression(&self) -> bool { |
| 80 | 80 | self.block.is_valid_js_expression() |
| 81 | 81 | } |
crates/js_ast/convert/process_function.rs+5-5| ... | ... | @@ -5,13 +5,13 @@ use super::BlockConvertContext; |
| 5 | 5 | use super::IsValidJSExpression; |
| 6 | 6 | use crate::js_ast::*; |
| 7 | 7 | use ast::*; |
| 8 | use tokenizer::Loc; | |
| 8 | use log::Range; | |
| 9 | 9 | |
| 10 | 10 | pub fn process_function_to_arrow( |
| 11 | 11 | ctx: &mut BlockConvertContext, |
| 12 | 12 | body: Expr, |
| 13 | 13 | params: Vec<Param>, |
| 14 | loc: Loc, | |
| 14 | range: Range, | |
| 15 | 15 | comment: Option<Comment>, |
| 16 | 16 | ) -> JsExpr { |
| 17 | 17 | // A block that is a valid expression will just become |
| ... | ... | @@ -34,7 +34,7 @@ pub fn process_function_to_arrow( |
| 34 | 34 | if let Some(expr) = child.take_last_statement_if_expr() { |
| 35 | 35 | child.add_statement(JsStatement::new( |
| 36 | 36 | JsStatementData::Return(Some(expr)), |
| 37 | loc.clone(), | |
| 37 | range.clone(), | |
| 38 | 38 | None, |
| 39 | 39 | )); |
| 40 | 40 | } |
| ... | ... | @@ -44,7 +44,7 @@ pub fn process_function_to_arrow( |
| 44 | 44 | if let Some(expr) = hoist_expr_if_needed(&mut child, body) { |
| 45 | 45 | child.add_statement(JsStatement::new( |
| 46 | 46 | JsStatementData::Return(Some(expr)), |
| 47 | loc.clone(), | |
| 47 | range.clone(), | |
| 48 | 48 | None, |
| 49 | 49 | )); |
| 50 | 50 | } |
| ... | ... | @@ -59,7 +59,7 @@ pub fn process_function_to_arrow( |
| 59 | 59 | params: params.into_iter().map(|x| x.name).collect(), |
| 60 | 60 | body: Box::new(body), |
| 61 | 61 | }, |
| 62 | loc.clone(), | |
| 62 | range.clone(), | |
| 63 | 63 | comment.map(|x| x.into()), |
| 64 | 64 | ) |
| 65 | 65 | } |
crates/js_ast/convert/process_statement.rs+6-6| ... | ... | @@ -35,7 +35,7 @@ pub fn process_statement(ctx: &mut BlockConvertContext, statement: Statement) -> |
| 35 | 35 | } else { |
| 36 | 36 | JsStatementData::Declaration(decl_data) |
| 37 | 37 | }, |
| 38 | decl.loc, | |
| 38 | decl.range, | |
| 39 | 39 | decl.comment.map(|x| x.into()), |
| 40 | 40 | ); |
| 41 | 41 | |
| ... | ... | @@ -45,10 +45,10 @@ pub fn process_statement(ctx: &mut BlockConvertContext, statement: Statement) -> |
| 45 | 45 | } |
| 46 | 46 | Statement::Expr(expr) => { |
| 47 | 47 | if let Some(expr) = hoist_expr_contents(ctx, expr) { |
| 48 | let loc = expr.loc.clone(); | |
| 48 | let range = expr.range.clone(); | |
| 49 | 49 | ctx.add_statement(JsStatement::new( |
| 50 | 50 | JsStatementData::Expression(expr), |
| 51 | loc, | |
| 51 | range, | |
| 52 | 52 | None, |
| 53 | 53 | )); |
| 54 | 54 | Some(()) |
| ... | ... | @@ -60,7 +60,7 @@ pub fn process_statement(ctx: &mut BlockConvertContext, statement: Statement) -> |
| 60 | 60 | name, |
| 61 | 61 | params, |
| 62 | 62 | body, |
| 63 | loc, | |
| 63 | range, | |
| 64 | 64 | comment, |
| 65 | 65 | is_pub, |
| 66 | 66 | .. |
| ... | ... | @@ -71,7 +71,7 @@ pub fn process_statement(ctx: &mut BlockConvertContext, statement: Statement) -> |
| 71 | 71 | ctx, |
| 72 | 72 | body, |
| 73 | 73 | params, |
| 74 | loc.clone(), | |
| 74 | range.clone(), | |
| 75 | 75 | None, |
| 76 | 76 | )); |
| 77 | 77 | |
| ... | ... | @@ -87,7 +87,7 @@ pub fn process_statement(ctx: &mut BlockConvertContext, statement: Statement) -> |
| 87 | 87 | } else { |
| 88 | 88 | JsStatementData::Declaration(decl_data) |
| 89 | 89 | }, |
| 90 | loc, | |
| 90 | range, | |
| 91 | 91 | comment.map(|x| x.into()), |
| 92 | 92 | )); |
| 93 | 93 |
crates/js_ast/convert/side_effects.rs+1-1| ... | ... | @@ -84,7 +84,7 @@ impl HasSideEffects for BlockOrIf { |
| 84 | 84 | } |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | impl HasSideEffects for BlockWithLoc { | |
| 87 | impl HasSideEffects for BlockWithRange { | |
| 88 | 88 | fn has_side_effects(&self) -> bool { |
| 89 | 89 | self.block.has_side_effects() |
| 90 | 90 | } |
crates/js_ast/js_ast.rs+18-10| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | use ast::{BinaryOperator, Comment, UnaryOperator}; |
| 2 | use log::Range; | |
| 2 | 3 | use num::bigint::BigInt; |
| 3 | use tokenizer::Loc; | |
| 4 | 4 | |
| 5 | 5 | #[derive(Debug, PartialEq, Clone)] |
| 6 | 6 | pub struct JsExpr { |
| 7 | 7 | pub data: JsExprData, |
| 8 | pub loc: Loc, | |
| 8 | pub range: Range, | |
| 9 | 9 | pub comment: Option<Comment>, |
| 10 | 10 | } |
| 11 | 11 | |
| ... | ... | @@ -74,7 +74,7 @@ pub enum JsExprData { |
| 74 | 74 | #[derive(Debug, PartialEq, Clone)] |
| 75 | 75 | pub struct JsStatement { |
| 76 | 76 | pub data: JsStatementData, |
| 77 | pub loc: Loc, | |
| 77 | pub range: Range, | |
| 78 | 78 | pub comment: Option<Comment>, |
| 79 | 79 | } |
| 80 | 80 | |
| ... | ... | @@ -133,12 +133,16 @@ pub struct JSNamedExport { |
| 133 | 133 | #[derive(Debug, PartialEq, Clone)] |
| 134 | 134 | pub struct JsBlock { |
| 135 | 135 | pub statements: Vec<JsStatement>, |
| 136 | pub loc: Loc, | |
| 136 | pub range: Range, | |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | 139 | impl JsExpr { |
| 140 | pub fn new(data: JsExprData, loc: Loc, comment: Option<Comment>) -> Self { | |
| 141 | Self { data, loc, comment } | |
| 140 | pub fn new(data: JsExprData, range: Range, comment: Option<Comment>) -> Self { | |
| 141 | Self { | |
| 142 | data, | |
| 143 | range, | |
| 144 | comment, | |
| 145 | } | |
| 142 | 146 | } |
| 143 | 147 | |
| 144 | 148 | pub fn is_literal(&self) -> bool { |
| ... | ... | @@ -167,14 +171,18 @@ impl JsExprData { |
| 167 | 171 | } |
| 168 | 172 | |
| 169 | 173 | impl JsBlock { |
| 170 | pub fn new(statements: Vec<JsStatement>, loc: Loc) -> Self { | |
| 171 | Self { statements, loc } | |
| 174 | pub fn new(statements: Vec<JsStatement>, range: Range) -> Self { | |
| 175 | Self { statements, range } | |
| 172 | 176 | } |
| 173 | 177 | } |
| 174 | 178 | |
| 175 | 179 | impl JsStatement { |
| 176 | pub fn new(data: JsStatementData, loc: Loc, comment: Option<Comment>) -> Self { | |
| 177 | Self { data, loc, comment } | |
| 180 | pub fn new(data: JsStatementData, range: Range, comment: Option<Comment>) -> Self { | |
| 181 | Self { | |
| 182 | data, | |
| 183 | range, | |
| 184 | comment, | |
| 185 | } | |
| 178 | 186 | } |
| 179 | 187 | } |
| 180 | 188 |
crates/log/Cargo.toml created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | [package] | |
| 2 | name = "log" | |
| 3 | edition = "2021" | |
| 4 | ||
| 5 | [lib] | |
| 6 | path="./log.rs" | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | miette.workspace = true | |
| 10 | thiserror.workspace = true | |
| 11 | url.workspace = true |
crates/log/log.rs created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | use std::{fs, path::Path, rc::Rc}; | |
| 2 | ||
| 3 | use miette::{IntoDiagnostic, Result}; | |
| 4 | use url::Url; | |
| 5 | ||
| 6 | #[derive(Debug, PartialEq, Clone, Copy)] | |
| 7 | pub struct Range { | |
| 8 | pub start: usize, | |
| 9 | pub length: usize, | |
| 10 | } | |
| 11 | ||
| 12 | impl Range { | |
| 13 | /// TODO(@paperdave): Remove this. every usage of this is incorrect. | |
| 14 | pub const EMPTY: Range = Range { | |
| 15 | start: 0, | |
| 16 | length: 0, | |
| 17 | }; | |
| 18 | ||
| 19 | pub fn new(start: usize, length: usize) -> Self { | |
| 20 | Self { start, length } | |
| 21 | } | |
| 22 | ||
| 23 | pub fn len(&self) -> usize { | |
| 24 | self.length | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | // TODO(@lino-levan): make this loggable nicely | |
| 29 | #[derive(Debug, Clone)] | |
| 30 | pub struct Message<'a> { | |
| 31 | pub source: &'a Source, | |
| 32 | pub range: Range, | |
| 33 | pub message: String, | |
| 34 | pub notes: Vec<Note<'a>>, | |
| 35 | } | |
| 36 | ||
| 37 | #[derive(Debug, Clone)] | |
| 38 | pub struct Note<'a> { | |
| 39 | pub location: Option<RangeAndSource<'a>>, | |
| 40 | pub message: String, | |
| 41 | } | |
| 42 | ||
| 43 | #[derive(Debug, Clone)] | |
| 44 | pub struct RangeAndSource<'a> { | |
| 45 | pub range: Range, | |
| 46 | pub source: &'a Source, | |
| 47 | } | |
| 48 | ||
| 49 | #[derive(Debug)] | |
| 50 | pub struct Source { | |
| 51 | pub url: Url, | |
| 52 | pub code: String, | |
| 53 | } | |
| 54 | ||
| 55 | impl Source { | |
| 56 | pub fn new(url: Url, source_code: String) -> Rc<Self> { | |
| 57 | Rc::new(Source { | |
| 58 | url, | |
| 59 | code: source_code, | |
| 60 | }) | |
| 61 | } | |
| 62 | ||
| 63 | pub fn from_file(path: &Path) -> Result<Rc<Self>> { | |
| 64 | let source_code = fs::read_to_string(path).into_diagnostic()?; | |
| 65 | let url = Url::from_file_path(path).unwrap(); | |
| 66 | Ok(Rc::new(Source { | |
| 67 | code: source_code, | |
| 68 | url, | |
| 69 | })) | |
| 70 | } | |
| 71 | ||
| 72 | pub fn from_url(url: Url) -> Result<Rc<Self>> { | |
| 73 | match url.scheme() { | |
| 74 | "file" => { | |
| 75 | // TODO: how to return this error, into_diagnostic() doesn't exist | |
| 76 | let file_path = url.to_file_path().unwrap(); | |
| 77 | let source_code = fs::read_to_string(file_path).into_diagnostic()?; | |
| 78 | Ok(Rc::new(Source { | |
| 79 | code: source_code, | |
| 80 | url, | |
| 81 | })) | |
| 82 | } | |
| 83 | _ => { | |
| 84 | todo!("Fetch from URL: {}", url) | |
| 85 | } | |
| 86 | } | |
| 87 | } | |
| 88 | } |
crates/parser/Cargo.toml+1| ... | ... | @@ -13,3 +13,4 @@ num.workspace = true |
| 13 | 13 | |
| 14 | 14 | ast = { path = "../ast" } |
| 15 | 15 | tokenizer = { path = "../tokenizer" } |
| 16 | log = { path = "../log" } |
crates/parser/parse_declaration.rs+3-2| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use ast::{DocComment, Type, VarDecl}; |
| 2 | use log::Range; | |
| 2 | 3 | use miette::Result; |
| 3 | use tokenizer::{Loc, TokenType}; | |
| 4 | use tokenizer::TokenType; | |
| 4 | 5 | |
| 5 | 6 | use crate::parse_expr::parse_expr; |
| 6 | 7 | use crate::parse_type::parse_type; |
| ... | ... | @@ -45,6 +46,6 @@ pub fn parse_declaration( |
| 45 | 46 | is_constant, |
| 46 | 47 | is_pub, |
| 47 | 48 | comment, |
| 48 | loc: Loc::new(start, p.index - start), | |
| 49 | range: Range::new(start, p.index - start), | |
| 49 | 50 | }) |
| 50 | 51 | } |
crates/parser/parse_doc_comment.rs+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | use ast::DocComment; |
| 2 | use tokenizer::{Loc, TokenType}; | |
| 2 | use log::Range; | |
| 3 | use tokenizer::TokenType; | |
| 3 | 4 | |
| 4 | 5 | use crate::Parser; |
| 5 | 6 | |
| ... | ... | @@ -10,7 +11,7 @@ pub fn maybe_read_doc_comment(p: &mut Parser) -> Option<DocComment> { |
| 10 | 11 | p.next(); |
| 11 | 12 | Some(DocComment { |
| 12 | 13 | data, |
| 13 | loc: Loc::new(start, p.index - start), | |
| 14 | range: Range::new(start, p.index - start), | |
| 14 | 15 | }) |
| 15 | 16 | } |
| 16 | 17 | _ => None, |
crates/parser/parse_expr.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | use ast::Associativity::*; |
| 2 | 2 | use ast::{BinaryOperator, Expr, ExprData, OperatorLevel}; |
| 3 | use log::Range; | |
| 3 | 4 | use miette::Result; |
| 4 | use tokenizer::Loc; | |
| 5 | 5 | |
| 6 | 6 | use crate::parse_expr_basic::parse_expr_basic; |
| 7 | 7 | use crate::Parser; |
| ... | ... | @@ -94,7 +94,7 @@ fn parse_expr_binary( |
| 94 | 94 | left: Box::new(left), |
| 95 | 95 | right: Box::new(right), |
| 96 | 96 | }, |
| 97 | Loc::new(start, p.index - start), | |
| 97 | Range::new(start, p.index - start), | |
| 98 | 98 | None, |
| 99 | 99 | )) |
| 100 | 100 | } |
crates/parser/parse_expr_basic.rs+19-18| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use ast::{BuiltinId, Expr, ExprData, Literal, UnaryOperator}; |
| 2 | use log::Range; | |
| 2 | 3 | use miette::Result; |
| 3 | use tokenizer::{Loc, TokenType}; | |
| 4 | use tokenizer::TokenType; | |
| 4 | 5 | |
| 5 | 6 | use crate::{ |
| 6 | 7 | parse_block::parse_block, parse_call_arguments::parse_call_arguments, parse_expr::parse_expr, |
| ... | ... | @@ -15,7 +16,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 15 | 16 | _ = p.next(); |
| 16 | 17 | Expr::new( |
| 17 | 18 | ExprData::Literal(Literal::Number(number.clone())), |
| 18 | Loc::new(start, p.index - start), | |
| 19 | Range::new(start, p.index - start), | |
| 19 | 20 | comments, |
| 20 | 21 | ) |
| 21 | 22 | } |
| ... | ... | @@ -23,7 +24,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 23 | 24 | _ = p.next(); |
| 24 | 25 | Expr::new( |
| 25 | 26 | ExprData::Literal(Literal::String(string.clone())), |
| 26 | Loc::new(start, p.index - start), | |
| 27 | Range::new(start, p.index - start), | |
| 27 | 28 | comments, |
| 28 | 29 | ) |
| 29 | 30 | } |
| ... | ... | @@ -31,7 +32,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 31 | 32 | _ = p.next(); |
| 32 | 33 | Expr::new( |
| 33 | 34 | ExprData::Literal(Literal::Bool(true)), |
| 34 | Loc::new(start, p.index - start), | |
| 35 | Range::new(start, p.index - start), | |
| 35 | 36 | comments, |
| 36 | 37 | ) |
| 37 | 38 | } |
| ... | ... | @@ -39,7 +40,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 39 | 40 | _ = p.next(); |
| 40 | 41 | Expr::new( |
| 41 | 42 | ExprData::Literal(Literal::Bool(false)), |
| 42 | Loc::new(start, p.index - start), | |
| 43 | Range::new(start, p.index - start), | |
| 43 | 44 | comments, |
| 44 | 45 | ) |
| 45 | 46 | } |
| ... | ... | @@ -47,7 +48,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 47 | 48 | _ = p.next(); |
| 48 | 49 | Expr::new( |
| 49 | 50 | ExprData::Literal(Literal::Void), |
| 50 | Loc::new(start, p.index - start), | |
| 51 | Range::new(start, p.index - start), | |
| 51 | 52 | comments, |
| 52 | 53 | ) |
| 53 | 54 | } |
| ... | ... | @@ -60,14 +61,14 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 60 | 61 | let arguments = parse_call_arguments(p)?; |
| 61 | 62 | Expr::new( |
| 62 | 63 | ExprData::Builtin { id, arguments }, |
| 63 | Loc::new(identifier_start, p.index - identifier_start), | |
| 64 | Range::new(identifier_start, p.index - identifier_start), | |
| 64 | 65 | comments, |
| 65 | 66 | ) |
| 66 | 67 | } else { |
| 67 | 68 | return Err(p |
| 68 | 69 | .error_at( |
| 69 | 70 | format!("Built-in function '{}' must be called", name), |
| 70 | Loc::new(identifier_start, p.index - identifier_start), | |
| 71 | Range::new(identifier_start, p.index - identifier_start), | |
| 71 | 72 | ) |
| 72 | 73 | .into()); |
| 73 | 74 | } |
| ... | ... | @@ -75,14 +76,14 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 75 | 76 | return Err(p |
| 76 | 77 | .error_at( |
| 77 | 78 | format!("Non-existant built-in: '{}'", name), |
| 78 | Loc::new(identifier_start, p.index - identifier_start), | |
| 79 | Range::new(identifier_start, p.index - identifier_start), | |
| 79 | 80 | ) |
| 80 | 81 | .into()); |
| 81 | 82 | } |
| 82 | 83 | } else { |
| 83 | 84 | Expr::new( |
| 84 | 85 | ExprData::Identifier(name), |
| 85 | Loc::new(identifier_start, p.index - identifier_start), | |
| 86 | Range::new(identifier_start, p.index - identifier_start), | |
| 86 | 87 | comments, |
| 87 | 88 | ) |
| 88 | 89 | } |
| ... | ... | @@ -99,7 +100,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 99 | 100 | |
| 100 | 101 | return Ok(Some(Expr::new( |
| 101 | 102 | ExprData::Return(inner), |
| 102 | Loc::new(start, p.index - start), | |
| 103 | Range::new(start, p.index - start), | |
| 103 | 104 | comments, |
| 104 | 105 | ))); |
| 105 | 106 | } |
| ... | ... | @@ -107,13 +108,13 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 107 | 108 | |
| 108 | 109 | Some(TokenType::If) => Expr::new( |
| 109 | 110 | ExprData::If(parse_expr_if(p)?), |
| 110 | Loc::new(start, p.index - start), | |
| 111 | Range::new(start, p.index - start), | |
| 111 | 112 | comments, |
| 112 | 113 | ), |
| 113 | 114 | |
| 114 | 115 | Some(TokenType::OpenBrace) => Expr::new( |
| 115 | 116 | ExprData::Block(parse_block(p)?), |
| 116 | Loc::new(start, p.index - start), | |
| 117 | Range::new(start, p.index - start), | |
| 117 | 118 | comments, |
| 118 | 119 | ), |
| 119 | 120 | |
| ... | ... | @@ -142,7 +143,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 142 | 143 | }, |
| 143 | 144 | value: Box::new(parse_expr_basic(p)?), |
| 144 | 145 | }, |
| 145 | Loc::new(start, p.index - start), | |
| 146 | Range::new(start, p.index - start), | |
| 146 | 147 | comments, |
| 147 | 148 | ) |
| 148 | 149 | } |
| ... | ... | @@ -162,7 +163,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 162 | 163 | p.next(); |
| 163 | 164 | Expr::new( |
| 164 | 165 | ExprData::Literal(Literal::String(name)), |
| 165 | Loc::new(field_start, p.index - field_start), | |
| 166 | Range::new(field_start, p.index - field_start), | |
| 166 | 167 | None, |
| 167 | 168 | ) |
| 168 | 169 | } |
| ... | ... | @@ -175,7 +176,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 175 | 176 | base: Box::new(expr), |
| 176 | 177 | field: Box::new(field), |
| 177 | 178 | }, |
| 178 | Loc::new(field_start, p.index - field_start), | |
| 179 | Range::new(field_start, p.index - field_start), | |
| 179 | 180 | None, |
| 180 | 181 | ); |
| 181 | 182 | } |
| ... | ... | @@ -188,7 +189,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 188 | 189 | base: Box::new(expr), |
| 189 | 190 | arguments, |
| 190 | 191 | }, |
| 191 | Loc::new(expr_start, p.index - expr_start), | |
| 192 | Range::new(expr_start, p.index - expr_start), | |
| 192 | 193 | None, |
| 193 | 194 | ); |
| 194 | 195 | } |
| ... | ... | @@ -202,7 +203,7 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> { |
| 202 | 203 | base: Box::new(expr), |
| 203 | 204 | field: Box::new(index), |
| 204 | 205 | }, |
| 205 | Loc::new(expr_start, p.index - expr_start), | |
| 206 | Range::new(expr_start, p.index - expr_start), | |
| 206 | 207 | None, |
| 207 | 208 | ); |
| 208 | 209 | } else { |
crates/parser/parse_expr_if.rs+8-7| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | use ast::{BlockOrIf, BlockWithLoc, If}; | |
| 1 | use ast::{BlockOrIf, BlockWithRange, If}; | |
| 2 | use log::Range; | |
| 2 | 3 | use miette::Result; |
| 3 | use tokenizer::{Loc, TokenType}; | |
| 4 | use tokenizer::TokenType; | |
| 4 | 5 | |
| 5 | 6 | use crate::parse_block::parse_block; |
| 6 | 7 | use crate::parse_expr::parse_expr; |
| ... | ... | @@ -30,9 +31,9 @@ pub fn parse_expr_if(p: &mut Parser) -> Result<If> { |
| 30 | 31 | let yes = match p.peek() { |
| 31 | 32 | Some(TokenType::OpenBrace) => { |
| 32 | 33 | let block_start = p.index; |
| 33 | BlockWithLoc { | |
| 34 | BlockWithRange { | |
| 34 | 35 | block: parse_block(p)?, |
| 35 | loc: Loc::new(block_start, p.index - block_start), | |
| 36 | range: Range::new(block_start, p.index - block_start), | |
| 36 | 37 | } |
| 37 | 38 | } |
| 38 | 39 | _ => { |
| ... | ... | @@ -49,14 +50,14 @@ pub fn parse_expr_if(p: &mut Parser) -> Result<If> { |
| 49 | 50 | Some(TokenType::OpenBrace) => { |
| 50 | 51 | let block_start = p.index; |
| 51 | 52 | // let comments = p.take_comments(); |
| 52 | Some(BlockOrIf::Block(BlockWithLoc { | |
| 53 | Some(BlockOrIf::Block(BlockWithRange { | |
| 53 | 54 | block: parse_block(p)?, |
| 54 | loc: Loc::new(block_start, p.index - block_start), | |
| 55 | range: Range::new(block_start, p.index - block_start), | |
| 55 | 56 | })) |
| 56 | 57 | } |
| 57 | 58 | Some(TokenType::If) => { |
| 58 | 59 | // TODO(@paperdave): Save location for the if |
| 59 | // let loc = p.loc(); | |
| 60 | // let range = p.range(); | |
| 60 | 61 | // let comments = p.take_comments(); |
| 61 | 62 | Some(BlockOrIf::If(Box::new(parse_expr_if(p)?))) |
| 62 | 63 | } |
crates/parser/parse_fn_declaration.rs+4-3| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use ast::{DocComment, Expr, ExprData, FnDecl, Type}; |
| 2 | use log::Range; | |
| 2 | 3 | use miette::Result; |
| 3 | use tokenizer::{Loc, TokenType}; | |
| 4 | use tokenizer::TokenType; | |
| 4 | 5 | |
| 5 | 6 | use crate::parse_block::parse_block; |
| 6 | 7 | use crate::parse_expr::parse_expr; |
| ... | ... | @@ -93,7 +94,7 @@ pub fn parse_fn_declaration( |
| 93 | 94 | let block = parse_block(p)?; |
| 94 | 95 | Expr::new( |
| 95 | 96 | ExprData::Block(block), |
| 96 | Loc::new(block_start, p.index - block_start), | |
| 97 | Range::new(block_start, p.index - block_start), | |
| 97 | 98 | None, |
| 98 | 99 | ) |
| 99 | 100 | } |
| ... | ... | @@ -121,6 +122,6 @@ pub fn parse_fn_declaration( |
| 121 | 122 | body, |
| 122 | 123 | is_pub, |
| 123 | 124 | comment, |
| 124 | loc: Loc::new(start, p.index - start), | |
| 125 | range: Range::new(start, p.index - start), | |
| 125 | 126 | }) |
| 126 | 127 | } |
crates/parser/parse_statement.rs+2-2| ... | ... | @@ -18,7 +18,7 @@ pub fn parse_statement(p: &mut Parser) -> Result<Statement> { |
| 18 | 18 | if p.has_comments() { |
| 19 | 19 | // this implies that comments are immediately after the doc |
| 20 | 20 | return Err(p |
| 21 | .error_at(format!("Unattached doc comment"), doc_comment.loc) | |
| 21 | .error_at(format!("Unattached doc comment"), doc_comment.range) | |
| 22 | 22 | .into()); |
| 23 | 23 | } |
| 24 | 24 | } |
| ... | ... | @@ -58,7 +58,7 @@ pub fn parse_statement(p: &mut Parser) -> Result<Statement> { |
| 58 | 58 | Some(_) => { |
| 59 | 59 | if let Some(doc_comment) = m_doc_comment { |
| 60 | 60 | Err(p |
| 61 | .error_at(format!("Unattached doc comment"), doc_comment.loc) | |
| 61 | .error_at(format!("Unattached doc comment"), doc_comment.range) | |
| 62 | 62 | .into()) |
| 63 | 63 | } else { |
| 64 | 64 | Ok(Statement::Expr(parse_expr(p)?)) |
crates/parser/parser.rs+8-7| ... | ... | @@ -14,13 +14,14 @@ mod parse_type; |
| 14 | 14 | |
| 15 | 15 | use ast::Comment; |
| 16 | 16 | use ast::Module; |
| 17 | use log::Range; | |
| 17 | 18 | use miette::Diagnostic; |
| 18 | 19 | use miette::Result; |
| 19 | 20 | use parse_module::parse_module; |
| 20 | 21 | use thiserror::Error; |
| 21 | 22 | use tokenizer::tokenize; |
| 23 | use tokenizer::Token; | |
| 22 | 24 | use tokenizer::TokenType; |
| 23 | use tokenizer::{Loc, Token}; | |
| 24 | 25 | |
| 25 | 26 | pub fn parse(tokens: Vec<Token>) -> Result<Module> { |
| 26 | 27 | let mut p = Parser::new(tokens); |
| ... | ... | @@ -37,12 +38,12 @@ pub fn parse_from_string(string: String) -> Result<Module> { |
| 37 | 38 | pub struct ParseError { |
| 38 | 39 | #[help] |
| 39 | 40 | error: String, |
| 40 | loc: Option<Loc>, | |
| 41 | range: Option<Range>, | |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | impl ParseError { |
| 44 | pub fn new(error: String, loc: Option<Loc>) -> ParseError { | |
| 45 | ParseError { error, loc } | |
| 45 | pub fn new(error: String, range: Option<Range>) -> ParseError { | |
| 46 | ParseError { error, range } | |
| 46 | 47 | } |
| 47 | 48 | } |
| 48 | 49 | |
| ... | ... | @@ -89,7 +90,7 @@ impl Parser { |
| 89 | 90 | |
| 90 | 91 | loop { |
| 91 | 92 | let token = self.tokens[self.cursor].clone(); |
| 92 | self.index = token.loc.start; | |
| 93 | self.index = token.range.start; | |
| 93 | 94 | match token.variant { |
| 94 | 95 | TokenType::Comment(comment) => { |
| 95 | 96 | self.comments.push(comment); |
| ... | ... | @@ -144,7 +145,7 @@ impl Parser { |
| 144 | 145 | ParseError::new(error, None) |
| 145 | 146 | } |
| 146 | 147 | |
| 147 | fn error_at(&self, error: String, loc: Loc) -> ParseError { | |
| 148 | ParseError::new(error, Some(loc)) | |
| 148 | fn error_at(&self, error: String, range: Range) -> ParseError { | |
| 149 | ParseError::new(error, Some(range)) | |
| 149 | 150 | } |
| 150 | 151 | } |
crates/tokenizer/Cargo.toml+2| ... | ... | @@ -9,3 +9,5 @@ path="./tokenizer.rs" |
| 9 | 9 | [dependencies] |
| 10 | 10 | miette.workspace = true |
| 11 | 11 | thiserror.workspace = true |
| 12 | ||
| 13 | log = { path = "../log" } |
crates/tokenizer/tokenizer.rs+4-25| ... | ... | @@ -1,28 +1,7 @@ |
| 1 | use log::Range; | |
| 1 | 2 | use miette::{Diagnostic, Result}; |
| 2 | 3 | use thiserror::Error; |
| 3 | 4 | |
| 4 | #[derive(Debug, PartialEq, Clone)] | |
| 5 | pub struct Loc { | |
| 6 | pub start: usize, | |
| 7 | pub length: usize, | |
| 8 | } | |
| 9 | ||
| 10 | impl Loc { | |
| 11 | /// TODO(@paperdave): Remove this. every usage of this is incorrect. | |
| 12 | pub const EMPTY: Loc = Loc { | |
| 13 | start: 0, | |
| 14 | length: 0, | |
| 15 | }; | |
| 16 | ||
| 17 | pub fn new(start: usize, length: usize) -> Self { | |
| 18 | Self { start, length } | |
| 19 | } | |
| 20 | ||
| 21 | pub fn len(&self) -> usize { | |
| 22 | self.length | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | 5 | #[derive(Error, Diagnostic, Debug)] |
| 27 | 6 | #[error("UnknownCharacter")] |
| 28 | 7 | struct UnknownCharacter { |
| ... | ... | @@ -162,19 +141,19 @@ impl std::fmt::Display for TokenType { |
| 162 | 141 | #[derive(Debug, Clone)] |
| 163 | 142 | pub struct Token { |
| 164 | 143 | pub variant: TokenType, |
| 165 | pub loc: Loc, | |
| 144 | pub range: Range, | |
| 166 | 145 | } |
| 167 | 146 | |
| 168 | 147 | impl Token { |
| 169 | 148 | pub fn new(variant: TokenType, start: usize, length: usize) -> Self { |
| 170 | 149 | Self { |
| 171 | 150 | variant, |
| 172 | loc: Loc::new(start, length), | |
| 151 | range: Range::new(start, length), | |
| 173 | 152 | } |
| 174 | 153 | } |
| 175 | 154 | } |
| 176 | 155 | |
| 177 | // TODO(@paperdave): rewrite this to not use a Vec<Token>. we probably dont need it. also store Loc | |
| 156 | // TODO(@paperdave): rewrite this to not use a Vec<Token>. we probably dont need it. also store Range | |
| 178 | 157 | pub fn tokenize(content: String) -> Result<Vec<Token>> { |
| 179 | 158 | let mut tokens: Vec<Token> = Vec::new(); |
| 180 | 159 | let mut chars = content.chars().enumerate().peekable(); |