├── .gitignore ├── nep.lox ├── src ├── input.rs ├── expr.rs ├── main.rs ├── scanner.rs ├── parser.rs └── interpreter.rs ├── Cargo.toml ├── features.lox └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | *~ 3 | Cargo.lock 4 | .repl-history.txt 5 | .debugger-history.txt -------------------------------------------------------------------------------- /nep.lox: -------------------------------------------------------------------------------- 1 | छाप "nepal"; 2 | भार a = १२; 3 | 4 | यदि (a == १२) { 5 | छाप a; 6 | } 7 | भुमरी (भार i = १; i < १० ; i=i+१){ 8 | छाप i; 9 | } -------------------------------------------------------------------------------- /src/input.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub enum Source { 3 | Literal, 4 | File(String), 5 | } 6 | 7 | #[derive(Debug)] 8 | pub struct Input { 9 | pub source: Source, 10 | pub content: String, 11 | } 12 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crafting-interpreters-rs" 3 | version = "0.1.0" 4 | authors = ["Thomas Peters "] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | clap = "2.33" -------------------------------------------------------------------------------- /features.lox: -------------------------------------------------------------------------------- 1 | घोषणा क = सहि; 2 | छाप क; 3 | 4 | काम परीक्षण() { 5 | रिटन "प्रोगामिङ"; 6 | } 7 | 8 | छाप परीक्षण(); 9 | वर्ग चित्र { 10 | सुरु(क, ख){ 11 | यो.क = क; 12 | यो.ख = ख; 13 | } 14 | खिच() { 15 | छाप "खिच"+" फोटो " + यो.क; 16 | छाप यो.ख; 17 | } 18 | } 19 | घोषणा स = चित्र("test" ,3); 20 | स.खिच(); 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nep-Preter in Rust 2 | 3 | This interpreter was written in accordance to Crafting Interpreters Book. The scanner is Recursive Descent and the interpreter type is Tree walk interpreter. Dynamically typed language 4 | 5 | The Keywords are 6 | 7 | ``` 8 | "अनि", "वर्ग", "अरु", "गलत", "भुमरी", "कार्य", "यदि", "आलु", "वा", "छाप", "रिटन", "सुपर", "यो", "सहि", "भार", "जबसम्म" 9 | ``` 10 | 11 | Steps to run the program 12 | 13 | ``` 14 | 15 | cargo run -- filename 16 | 17 | for more information 18 | 19 | cargo run -- -h 20 | 21 | 22 | ``` 23 | 24 | Features 25 | 26 | 1. Statements 27 | 2. Variables 28 | 3. Functions and closures 29 | 4. Classes 30 | 5. Inheritance 31 | 32 | ## Some Examples 33 | 34 | ``` 35 | भार क = सहि; 36 | छाप क; 37 | 38 | काम परीक्षण() { 39 | रिटन "प्रोगामिङ"; 40 | } 41 | 42 | छाप परीक्षण(); 43 | वर्ग चित्र { 44 | सुरु(क, ख){ 45 | यो.क = क; 46 | यो.ख = ख; 47 | } 48 | खिच() { 49 | छाप "खिच"+" फोटो " + यो.क; 50 | छाप यो.ख; 51 | } 52 | } 53 | भार स = चित्र("test" ,3); 54 | स.खिच(); 55 | ``` 56 | 57 | For loop and if cases 58 | 59 | ``` 60 | छाप "nepal"; 61 | भार a = १२; 62 | 63 | यदि (a == १२) { 64 | छाप a; 65 | } 66 | भुमरी (भार i = १; i < १० ; i=i+१){ 67 | छाप i; 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /src/expr.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone)] 2 | pub enum Expr { 3 | Literal(Literal), 4 | This(SourceLocation), 5 | Unary(UnaryOp, Box), 6 | Binary(Box, BinaryOp, Box), 7 | Call(Box, SourceLocation, Vec), 8 | Get(Box, Symbol), 9 | Grouping(Box), 10 | Variable(Symbol), 11 | Assign(Symbol, Box), 12 | Logical(Box, LogicalOp, Box), 13 | Set(Box, Symbol, Box), 14 | Super(SourceLocation, Symbol), 15 | } 16 | 17 | #[derive(Debug, Clone, Copy)] 18 | pub struct SourceLocation { 19 | pub line: usize, 20 | pub col: i64, 21 | } 22 | 23 | #[derive(Debug, Clone)] 24 | pub enum LogicalOp { 25 | Or, 26 | And, 27 | } 28 | 29 | #[derive(Debug, Eq, PartialEq, Hash, Clone)] 30 | pub struct Symbol { 31 | pub name: String, 32 | pub line: usize, 33 | pub col: i64, 34 | } 35 | 36 | #[derive(Debug, Clone)] 37 | pub struct FunDecl { 38 | pub name: Symbol, 39 | pub params: Vec, 40 | pub body: Vec, 41 | } 42 | 43 | #[derive(Debug, Clone)] 44 | pub struct LambdaDecl { 45 | pub params: Vec, 46 | pub body: Vec, 47 | } 48 | 49 | #[derive(Debug, Clone)] 50 | pub struct ClassDecl { 51 | pub name: Symbol, 52 | pub superclass: Option, 53 | pub methods: Vec, 54 | } 55 | 56 | #[derive(Debug, Clone)] 57 | pub enum Stmt { 58 | Expr(Expr), 59 | FunDecl(FunDecl), 60 | ClassDecl(ClassDecl), 61 | If(Expr, Box, Option>), 62 | Print(Expr), 63 | VarDecl(Symbol, Option), 64 | Block(Vec), 65 | Return(SourceLocation, Option), 66 | While(Expr, Box), 67 | } 68 | 69 | #[derive(Debug, Copy, Clone)] 70 | pub enum UnaryOpTy { 71 | Minus, 72 | Bang, 73 | } 74 | 75 | #[derive(Debug, Copy, Clone)] 76 | pub struct UnaryOp { 77 | pub ty: UnaryOpTy, 78 | pub line: usize, 79 | pub col: i64, 80 | } 81 | 82 | #[derive(Debug, Copy, Clone)] 83 | pub enum BinaryOpTy { 84 | EqualEqual, 85 | NotEqual, 86 | Less, 87 | LessEqual, 88 | Greater, 89 | GreaterEqual, 90 | Plus, 91 | Minus, 92 | Star, 93 | Slash, 94 | } 95 | 96 | #[derive(Debug, Copy, Clone)] 97 | pub struct BinaryOp { 98 | pub ty: BinaryOpTy, 99 | pub line: usize, 100 | pub col: i64, 101 | } 102 | 103 | #[derive(Debug, Clone)] 104 | pub enum Literal { 105 | Number(f64), 106 | String(String), 107 | True, 108 | False, 109 | Nil, 110 | } 111 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate clap; 2 | 3 | use clap::{App, Arg}; 4 | 5 | use std::fs; 6 | 7 | mod expr; 8 | mod input; 9 | mod parser; 10 | mod scanner; 11 | mod interpreter; 12 | 13 | const FILENAME: &str = "file"; 14 | const INPUT: &str = "c"; 15 | 16 | fn get_input(matches: &clap::ArgMatches<'_>) -> Option { 17 | if let Some(literal_input) = matches.value_of(INPUT) { 18 | return Some(input::Input { 19 | source: input::Source::Literal, 20 | content: literal_input.to_string(), 21 | }); 22 | } 23 | 24 | if let Some(input_file) = matches.value_of(FILENAME) { 25 | match fs::read_to_string(input_file) { 26 | Ok(input) => { 27 | return Some(input::Input { 28 | source: input::Source::File(input_file.to_string()), 29 | content: nepfy(input), 30 | }); 31 | } 32 | Err(err) => { 33 | panic!("Error reading {}: {}", input_file, err); 34 | } 35 | } 36 | } 37 | 38 | None 39 | } 40 | fn nepfy(data: String) -> String { 41 | data.chars().collect::>().iter().map(|f| { 42 | let nepali_numbers = ['०','१','२','३','४','५','६','७','८','९']; 43 | if let Some(pos) = nepali_numbers.iter().position(|d| d == f ) { 44 | return char::from_digit(pos as u32,10).unwrap(); 45 | } 46 | *f 47 | }).collect::() 48 | } 49 | 50 | fn main() { 51 | 52 | 53 | let matches = App::new("nep preter") 54 | .version("1.0") 55 | .about("नेप-Preter") 56 | .author("Ashish Thapa").arg( 57 | Arg::with_name(FILENAME) 58 | .help("Please provide Filename") 59 | .required(false) 60 | .index(1), 61 | ) 62 | .arg( 63 | Arg::with_name(INPUT) 64 | .long("-c") 65 | .takes_value(true) 66 | .help("Parse String here"), 67 | ) 68 | .get_matches(); 69 | 70 | 71 | if let Some(input) = get_input(&matches) { 72 | match scanner::scan_tokens(input.content.clone()) { 73 | Ok(tokens) => { 74 | // println!("{:#?}", tokens); 75 | 76 | let stmts_maybe = parser::parse(tokens); 77 | 78 | match stmts_maybe { 79 | Ok(stmts) => { 80 | // println!("{:#?}", stmts); 81 | let mut interpreter: interpreter::Interpreter = 82 | Default::default(); 83 | let interpret_result = interpreter.interpret(&stmts); 84 | 85 | match interpret_result { 86 | Ok(_) => { 87 | std::process::exit(0); 88 | } 89 | Err(err) => { 90 | println!( 91 | "Runtime Error: {}\n\n{}", 92 | err, 93 | interpreter.format_backtrace() 94 | ); 95 | std::process::exit(-1); 96 | } 97 | } 98 | } 99 | Err(err) => { 100 | panic!("{:?} - {:?}",err,&input); 101 | } 102 | } 103 | } 104 | Err(err) => { 105 | panic!("{:?} - {:?}",err,&input); 106 | } 107 | } 108 | 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/scanner.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::fmt; 3 | 4 | #[derive(Eq, PartialEq, Debug, Copy, Clone)] 5 | pub enum TokenType { 6 | // Single-character tokens. 7 | LeftParen, 8 | RightParen, 9 | LeftBrace, 10 | RightBrace, 11 | LeftBracket, 12 | RightBracket, 13 | Comma, 14 | Dot, 15 | Minus, 16 | Plus, 17 | Semicolon, 18 | Slash, 19 | Star, 20 | 21 | // One or two character tokens. 22 | Bang, 23 | BangEqual, 24 | Equal, 25 | EqualEqual, 26 | Greater, 27 | GreaterEqual, 28 | Less, 29 | LessEqual, 30 | 31 | // Literals. 32 | Identifier, 33 | String, 34 | Number, 35 | 36 | // Keywords. 37 | And, 38 | Class, 39 | Else, 40 | False, 41 | Fun, 42 | For, 43 | If, 44 | Nil, 45 | Or, 46 | Print, 47 | Return, 48 | Super, 49 | This, 50 | True, 51 | Var, 52 | While, 53 | 54 | Eof, 55 | } 56 | 57 | #[derive(Debug, Clone)] 58 | pub enum Literal { 59 | Identifier(String), 60 | Str(String), 61 | Number(f64), 62 | } 63 | 64 | #[derive(Clone)] 65 | pub struct Token { 66 | pub ty: TokenType, 67 | pub lexeme: Vec, 68 | pub literal: Option, 69 | pub line: usize, 70 | pub col: i64, 71 | } 72 | 73 | impl fmt::Debug for Token { 74 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 75 | write!( 76 | f, 77 | "Token {{ ty: {:?}, lexeme: \"{}\", literal: {:?}, line: {:?}, col: {:?}}}", 78 | self.ty, 79 | self.lexeme.clone().iter().collect::(), 80 | self.literal, 81 | self.line, 82 | self.col 83 | ) 84 | } 85 | } 86 | 87 | pub fn scan_tokens(input: String) -> Result, Error> { 88 | let mut scanner: Scanner = Default::default(); 89 | 90 | scanner.scan_tokens(input); 91 | 92 | match scanner.err { 93 | Some(err) => Err(err), 94 | None => Ok(scanner.tokens), 95 | } 96 | } 97 | 98 | #[derive(Debug)] 99 | pub struct Error { 100 | pub what: String, 101 | pub line: usize, 102 | pub col: i64, 103 | } 104 | 105 | struct Scanner { 106 | source: Vec, 107 | tokens: Vec, 108 | err: Option, 109 | start: usize, 110 | current: usize, 111 | line: usize, 112 | col: i64, 113 | keywords: HashMap, 114 | } 115 | 116 | impl Default for Scanner { 117 | fn default() -> Scanner { 118 | Scanner { 119 | source: Vec::new(), 120 | tokens: Vec::new(), 121 | err: None, 122 | start: 0, 123 | current: 0, 124 | line: 1, 125 | col: -1, 126 | keywords: vec![ 127 | ("अनि", TokenType::And), 128 | ("वर्ग", TokenType::Class), 129 | ("अरु", TokenType::Else), 130 | ("नत्र", TokenType::Else), 131 | ("गलत", TokenType::False), 132 | ("भुमरी", TokenType::For), 133 | ("फर", TokenType::For), 134 | ("काम", TokenType::Fun), 135 | ("यदि", TokenType::If), 136 | ("आलु", TokenType::Nil), 137 | ("वा", TokenType::Or), 138 | ("छाप", TokenType::Print), 139 | ("रिटन", TokenType::Return), 140 | ("सुपर", TokenType::Super), 141 | ("यो", TokenType::This), 142 | ("सहि", TokenType::True), 143 | ("भार", TokenType::Var), 144 | ("जबसम्म", TokenType::While), 145 | 146 | ("ani", TokenType::And), 147 | ("barga", TokenType::Class), 148 | ("natra", TokenType::Else), 149 | ("galat", TokenType::False), 150 | ("bhumari", TokenType::For), 151 | ("kaam", TokenType::Fun), 152 | ("yadi", TokenType::If), 153 | ("aalu", TokenType::Nil), 154 | ("wa", TokenType::Or), 155 | ("chap", TokenType::Print), 156 | ("return", TokenType::Return), 157 | ("super", TokenType::Super), 158 | ("yo", TokenType::This), 159 | ("sahi", TokenType::True), 160 | ("ghosana", TokenType::Var), 161 | ("jabasamma", TokenType::While), 162 | ] 163 | .into_iter() 164 | .map(|(k, v)| (String::from(k), v)) 165 | .collect(), 166 | } 167 | } 168 | } 169 | 170 | impl Scanner { 171 | fn scan_tokens(&mut self, input: String) { 172 | self.source = input.chars().collect(); 173 | 174 | while !self.done() { 175 | self.start = self.current; 176 | self.scan_token(); 177 | } 178 | 179 | match self.err { 180 | Some(_) => {} 181 | None => self.tokens.push(Token { 182 | ty: TokenType::Eof, 183 | lexeme: Vec::new(), 184 | literal: None, 185 | line: self.line, 186 | col: self.col, 187 | }), 188 | } 189 | } 190 | 191 | fn advance(&mut self) -> char { 192 | self.current += 1; 193 | self.col += 1; 194 | 195 | char::from(self.source[self.current - 1]) 196 | } 197 | 198 | fn scan_token(&mut self) { 199 | let c = self.advance(); 200 | 201 | match c { 202 | '(' => self.add_token(TokenType::LeftParen), 203 | ')' => self.add_token(TokenType::RightParen), 204 | '{' => self.add_token(TokenType::LeftBrace), 205 | '}' => self.add_token(TokenType::RightBrace), 206 | '[' => self.add_token(TokenType::LeftBracket), 207 | ']' => self.add_token(TokenType::RightBracket), 208 | ',' => self.add_token(TokenType::Comma), 209 | '.' => self.add_token(TokenType::Dot), 210 | '-' => self.add_token(TokenType::Minus), 211 | '+' => self.add_token(TokenType::Plus), 212 | ';' => self.add_token(TokenType::Semicolon), 213 | '*' => self.add_token(TokenType::Star), 214 | '!' => { 215 | let matches_eq = self.matches('='); 216 | self.add_token(if matches_eq { 217 | TokenType::BangEqual 218 | } else { 219 | TokenType::Bang 220 | }) 221 | } 222 | '=' => { 223 | let matches_eq = self.matches('='); 224 | self.add_token(if matches_eq { 225 | TokenType::EqualEqual 226 | } else { 227 | TokenType::Equal 228 | }) 229 | } 230 | '<' => { 231 | let matches_eq = self.matches('='); 232 | self.add_token(if matches_eq { 233 | TokenType::LessEqual 234 | } else { 235 | TokenType::Less 236 | }) 237 | } 238 | '>' => { 239 | let matches_eq = self.matches('='); 240 | self.add_token(if matches_eq { 241 | TokenType::GreaterEqual 242 | } else { 243 | TokenType::Greater 244 | }) 245 | } 246 | '/' => { 247 | if self.matches('/') { 248 | while self.peek() != '\n' && !self.is_at_end() { 249 | self.advance(); 250 | } 251 | } else { 252 | self.add_token(TokenType::Slash) 253 | } 254 | } 255 | 'म' => { 256 | if self.matches('ु') { 257 | while self.peek() != 'ी' { 258 | self.advance(); 259 | } 260 | self.add_token(TokenType::Semicolon); 261 | self.advance(); 262 | }else{ 263 | self.identifier() 264 | } 265 | } 266 | 'm' => { 267 | let mut didfind = false; 268 | if self.matches('u') { 269 | self.advance(); 270 | if self.matches('j') == true { 271 | if self.peek() == 'i'{ 272 | self.add_token(TokenType::Semicolon); 273 | self.advance(); 274 | didfind = true; 275 | } 276 | } 277 | } 278 | if !didfind { 279 | self.identifier() 280 | } 281 | } 282 | 283 | ' ' | '\r' | '\t' => {} 284 | '\n' => { 285 | self.line += 1; 286 | self.col = 0 287 | } 288 | '"' => self.string(), 289 | _ => { 290 | if Scanner::is_decimal_digit(c) { 291 | self.number() 292 | } else if Scanner::is_alpha(c) { 293 | self.identifier() 294 | } else { 295 | println!("{} is ",c); 296 | 297 | self.err = Some(Error { 298 | what: format!("scanner can't handle {}", c), 299 | line: self.line, 300 | col: self.col, 301 | }) 302 | } 303 | } 304 | } 305 | } 306 | 307 | fn is_alpha(c: char) -> bool { 308 | c.is_alphabetic() || c == '्' 309 | } 310 | 311 | fn is_decimal_digit(c: char) -> bool { 312 | c.is_ascii_digit() 313 | } 314 | 315 | fn is_alphanumeric(c: char) -> bool { 316 | Scanner::is_alpha(c) || Scanner::is_decimal_digit(c) 317 | } 318 | 319 | fn identifier(&mut self) { 320 | while Scanner::is_alphanumeric(self.peek()) { 321 | self.advance(); 322 | } 323 | 324 | let literal_val = 325 | self.source[self.start..self.current].iter().collect::(); 326 | 327 | let token_type = match self.keywords.get(&literal_val) { 328 | Some(kw_token_type) => *kw_token_type, 329 | None => TokenType::Identifier, 330 | }; 331 | 332 | match token_type { 333 | TokenType::Identifier => self.add_token_literal( 334 | TokenType::Identifier, 335 | Some(Literal::Identifier(literal_val)), 336 | ), // book doesn't do this. why not?} 337 | _ => self.add_token(token_type), 338 | } 339 | } 340 | 341 | fn number(&mut self) { 342 | while Scanner::is_decimal_digit(self.peek()) { 343 | self.advance(); 344 | } 345 | 346 | if self.peek() == '.' && Scanner::is_decimal_digit(self.peek_next()) { 347 | self.advance(); 348 | } 349 | 350 | while Scanner::is_decimal_digit(self.peek()) { 351 | self.advance(); 352 | } 353 | 354 | let val: f64 = self.source[self.start..self.current].iter(). 355 | collect::(). 356 | parse::(). 357 | unwrap(); 358 | 359 | self.add_token_literal(TokenType::Number, Some(Literal::Number(val))) 360 | } 361 | 362 | fn string(&mut self) { 363 | while self.peek() != '"' && !self.is_at_end() { 364 | if self.peek() == '\n' { 365 | self.line += 1 366 | } 367 | self.advance(); 368 | } 369 | 370 | if self.is_at_end() { 371 | self.err = Some(Error { 372 | what: "Unterminated string".to_string(), 373 | line: self.line, 374 | col: self.col, 375 | }) 376 | } 377 | 378 | assert!(self.peek() == '"'); 379 | 380 | self.advance(); 381 | 382 | self.add_token_literal( 383 | TokenType::String, 384 | Some(Literal::Str( 385 | self.source[self.start + 1..self.current - 1].iter().collect(), 386 | )), 387 | ) 388 | } 389 | 390 | fn peek_next(&self) -> char { 391 | if self.current + 1 >= self.source.len() { 392 | '\0' 393 | } else { 394 | char::from(self.source[self.current + 1]) 395 | } 396 | } 397 | 398 | fn peek(&self) -> char { 399 | if self.is_at_end() { 400 | '\0' 401 | } else { 402 | char::from(self.source[self.current]) 403 | } 404 | } 405 | fn matches(&mut self, c: char) -> bool { 406 | if self.is_at_end() { 407 | return true; 408 | } 409 | 410 | if char::from(self.source[self.current]) != c { 411 | return false; 412 | } 413 | 414 | self.current += 1; 415 | self.col += 1; 416 | true 417 | } 418 | 419 | fn add_token(&mut self, token_type: TokenType) { 420 | self.add_token_literal(token_type, None) 421 | } 422 | 423 | fn add_token_literal(&mut self, token_type: TokenType, literal: Option) { 424 | let text = self.source[self.start..self.current].to_vec(); 425 | 426 | self.tokens.push(Token { 427 | ty: token_type, 428 | lexeme: text, 429 | literal, 430 | line: self.line, 431 | col: self.col, 432 | }) 433 | } 434 | 435 | fn done(&self) -> bool { 436 | self.err.is_some() || self.is_at_end() 437 | } 438 | 439 | fn is_at_end(&self) -> bool { 440 | self.current >= self.source.len() 441 | } 442 | } 443 | -------------------------------------------------------------------------------- /src/parser.rs: -------------------------------------------------------------------------------- 1 | use crate::expr; 2 | use crate::scanner; 3 | 4 | use std::fmt; 5 | 6 | #[derive(Default)] 7 | struct Parser { 8 | tokens: Vec, 9 | current: usize, 10 | in_fundec: bool, // in rust, booleans default to false: https://doc.rust-lang.org/std/primitive.bool.html#impl-Default 11 | } 12 | 13 | pub enum Error { 14 | UnexpectedToken(scanner::Token), 15 | TokenMismatch { 16 | expected: scanner::TokenType, 17 | found: scanner::Token, 18 | maybe_on_err_string: Option, 19 | }, 20 | MaxParamsExceeded { 21 | kind: FunctionKind, 22 | line: usize, 23 | col: i64, 24 | }, 25 | ReturnNotInFun { 26 | line: usize, 27 | col: i64, 28 | }, 29 | InvalidAssignment { 30 | line: usize, 31 | col: i64, 32 | }, 33 | TooManyArguments { 34 | line: usize, 35 | col: i64, 36 | }, 37 | ExpectedExpression { 38 | token_type: scanner::TokenType, 39 | line: usize, 40 | col: i64, 41 | }, 42 | InvalidTokenInUnaryOp { 43 | token_type: scanner::TokenType, 44 | line: usize, 45 | col: i64, 46 | }, 47 | InvalidTokenInBinaryOp { 48 | token_type: scanner::TokenType, 49 | line: usize, 50 | col: i64, 51 | }, 52 | } 53 | 54 | impl fmt::Debug for Error { 55 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 56 | match &self { 57 | Error::UnexpectedToken(tok) => write!( 58 | f, 59 | "Unexpected token {:?} at line={},col={}", 60 | tok.ty, tok.line, tok.col 61 | ), 62 | Error::TokenMismatch { 63 | maybe_on_err_string, 64 | expected, 65 | found, 66 | } => { 67 | write!( 68 | f, 69 | " expected टोकन {:?} तर भेट्टियो {:?}. रेखा={},स्नम्भ={}", 70 | expected, found.ty, found.line, found.col 71 | )?; 72 | if let Some(on_err_string) = maybe_on_err_string { 73 | write!(f, ": {}", on_err_string)?; 74 | } 75 | fmt::Result::Ok(()) 76 | } 77 | Error::MaxParamsExceeded { kind, line, col } => write!( 78 | f, 79 | "{:?} घोषणा(function) मा २५५ भन्दा बढी प्यारामिटरहरू हुन सक्दैन। रेखा={}, स्तम्भ={}", 80 | kind, line, col 81 | ), 82 | Error::ReturnNotInFun { line, col } => write!( 83 | f, 84 | "रिटर्न स्टेटमेन्ट लाइन={}, स्नम्भ={} मा कार्य (function) मा संलग्न छैन", 85 | line, col 86 | ), 87 | Error::InvalidAssignment { line, col } => { 88 | write!(f, "लाइन={}, स्नम्भ={} मा अवैध असाइनमेन्ट लक्ष्य", line, col) 89 | } 90 | Error::TooManyArguments { line, col } => write!( 91 | f, 92 | "घोषणा(function) मा २५५ भन्दा बढी प्यारामिटरहरू हुन सक्दैन। रेखा={}, स्तम्भ={}", 93 | line, col 94 | ), 95 | Error::ExpectedExpression { 96 | token_type, 97 | line, 98 | col, 99 | } => write!( 100 | f, 101 | "expected अभिव्यक्ति(expected expression), तर लाइन={}, col={} मा टोकन(Token) {:?} भेटियो", 102 | line, col, token_type 103 | ), 104 | Error::InvalidTokenInUnaryOp { 105 | token_type, 106 | line, 107 | col, 108 | } => write!( 109 | f, 110 | "अवैध टोकन in unary op {:?} at लाइन={}, स्नम्भ={}", 111 | token_type, line, col 112 | ), 113 | Error::InvalidTokenInBinaryOp { 114 | token_type, 115 | line, 116 | col, 117 | } => write!( 118 | f, 119 | "अवैध टोकन in binary op {:?} at लाइन={}, स्नम्भ={}", 120 | token_type, line, col 121 | ), 122 | } 123 | } 124 | } 125 | 126 | #[derive(Debug)] 127 | pub enum FunctionKind { 128 | Function, 129 | Method, 130 | } 131 | 132 | pub fn parse( 133 | tokens: Vec, 134 | ) -> Result, Error> { 135 | let mut p = Parser { 136 | tokens, 137 | ..Default::default() 138 | }; 139 | let stmts_or_err = p.parse(); 140 | 141 | match stmts_or_err { 142 | Ok(stmts_or_err) => { 143 | if !p.is_at_end() { 144 | let tok = &p.tokens[p.current]; 145 | Err(Error::UnexpectedToken(tok.clone())) 146 | } else { 147 | Ok(stmts_or_err) 148 | } 149 | } 150 | Err(err) => Err(err), 151 | } 152 | } 153 | 154 | impl Parser { 155 | pub fn parse(&mut self) -> Result, Error> { 156 | let mut statements = Vec::new(); 157 | 158 | while !self.is_at_end() { 159 | let stmt = self.declaration()?; 160 | statements.push(stmt); 161 | } 162 | 163 | Ok(statements) 164 | } 165 | 166 | fn declaration(&mut self) -> Result { 167 | if self.matches(scanner::TokenType::Var) { 168 | return self.var_decl(); 169 | } 170 | 171 | if self.matches(scanner::TokenType::Fun) { 172 | return Ok(expr::Stmt::FunDecl(self.fun_decl(FunctionKind::Function)?)); 173 | } 174 | 175 | if self.matches(scanner::TokenType::Class) { 176 | return self.class_decl(); 177 | } 178 | 179 | self.statement() 180 | } 181 | 182 | fn class_decl(&mut self) -> Result { 183 | let name_tok = self 184 | .consume(scanner::TokenType::Identifier, "expected class name")? 185 | .clone(); 186 | 187 | let class_symbol = expr::Symbol { 188 | name: name_tok.lexeme.iter().collect(), 189 | line: name_tok.line, 190 | col: name_tok.col, 191 | }; 192 | 193 | let superclass_maybe = if self.matches(scanner::TokenType::Less) { 194 | let superclass_tok = 195 | self.consume(scanner::TokenType::Identifier, "expected class नाम (name) .")?; 196 | Some(expr::Symbol { 197 | name: superclass_tok.lexeme.iter().collect(), 198 | line: superclass_tok.line, 199 | col: superclass_tok.col, 200 | }) 201 | } else { 202 | None 203 | }; 204 | 205 | self.consume(scanner::TokenType::LeftBrace, "expected { पछि class name")?; 206 | 207 | let mut methods = Vec::new(); 208 | while !self.check(scanner::TokenType::RightBrace) && !self.is_at_end() { 209 | methods.push(self.fun_decl(FunctionKind::Method)?); 210 | } 211 | let methods = methods; 212 | 213 | self.consume( 214 | scanner::TokenType::RightBrace, 215 | "expected } पछि class body", 216 | )?; 217 | 218 | Ok(expr::Stmt::ClassDecl(expr::ClassDecl { 219 | name: class_symbol, 220 | superclass: superclass_maybe, 221 | methods, 222 | })) 223 | } 224 | 225 | fn fun_decl(&mut self, kind: FunctionKind) -> Result { 226 | let name_tok = self 227 | .consume( 228 | scanner::TokenType::Identifier, 229 | format!("expected {:?} name", kind).as_ref(), 230 | )? 231 | .clone(); 232 | 233 | let fun_symbol = expr::Symbol { 234 | name: name_tok.lexeme.iter().collect(), 235 | line: name_tok.line, 236 | col: name_tok.col, 237 | }; 238 | 239 | let (parameters, body) = self.params_and_body(kind)?; 240 | 241 | Ok(expr::FunDecl { 242 | name: fun_symbol, 243 | params: parameters, 244 | body, 245 | }) 246 | } 247 | 248 | fn params_and_body( 249 | &mut self, 250 | kind: FunctionKind, 251 | ) -> Result<(Vec, Vec), Error> { 252 | self.consume( 253 | scanner::TokenType::LeftParen, 254 | format!("expected ( पछि {:?} name", kind).as_ref(), 255 | )?; 256 | 257 | let mut parameters = Vec::new(); 258 | 259 | if !self.check(scanner::TokenType::RightParen) { 260 | loop { 261 | if parameters.len() >= 255 { 262 | let peek_tok = self.peek(); 263 | return Err(Error::MaxParamsExceeded { 264 | kind, 265 | line: peek_tok.line, 266 | col: peek_tok.col, 267 | }); 268 | } 269 | 270 | let tok = self 271 | .consume(scanner::TokenType::Identifier, "expected प्यारामीटर(parameter) name")? 272 | .clone(); 273 | 274 | parameters.push(expr::Symbol { 275 | name: tok.lexeme.iter().collect(), 276 | line: tok.line, 277 | col: tok.col, 278 | }); 279 | 280 | if !self.matches(scanner::TokenType::Comma) { 281 | break; 282 | } 283 | } 284 | } 285 | let parameters = parameters; 286 | 287 | self.consume( 288 | scanner::TokenType::RightParen, 289 | "parameter", 290 | )?; 291 | self.consume( 292 | scanner::TokenType::LeftBrace, 293 | "expected { before function body", 294 | )?; 295 | let saved_is_in_fundec = self.in_fundec; 296 | self.in_fundec = true; 297 | let body = self.block()?; 298 | self.in_fundec = saved_is_in_fundec; 299 | 300 | Ok((parameters, body)) 301 | } 302 | 303 | fn var_decl(&mut self) -> Result { 304 | let name_token = self 305 | .consume(scanner::TokenType::Identifier, "expected भेरिएबल (variable) name")? 306 | .clone(); 307 | 308 | let maybe_initializer = if self.matches(scanner::TokenType::Equal) { 309 | Some(self.expression()?) 310 | } else { 311 | None 312 | }; 313 | 314 | self.consume( 315 | scanner::TokenType::Semicolon, 316 | "expected ; पछि भेरिएबल (variable) declaration", 317 | )?; 318 | 319 | Ok(expr::Stmt::VarDecl( 320 | expr::Symbol { 321 | name: name_token.lexeme.iter().collect(), 322 | line: name_token.line, 323 | col: name_token.col, 324 | }, 325 | maybe_initializer, 326 | )) 327 | } 328 | 329 | fn statement(&mut self) -> Result { 330 | if self.matches(scanner::TokenType::Print) { 331 | return self.print_statement(); 332 | } 333 | 334 | if self.matches(scanner::TokenType::While) { 335 | return self.while_statement(); 336 | } 337 | 338 | if self.matches(scanner::TokenType::LeftBrace) { 339 | return Ok(expr::Stmt::Block(self.block()?)); 340 | } 341 | 342 | if self.matches(scanner::TokenType::For) { 343 | return self.for_statement(); 344 | } 345 | 346 | if self.matches(scanner::TokenType::If) { 347 | return self.if_statement(); 348 | } 349 | 350 | if self.matches(scanner::TokenType::Return) { 351 | return self.return_statement(); 352 | } 353 | 354 | self.expression_statement() 355 | } 356 | 357 | fn return_statement(&mut self) -> Result { 358 | let prev_tok = self.previous().clone(); 359 | 360 | if !self.in_fundec { 361 | return Err(Error::ReturnNotInFun { 362 | line: prev_tok.line, 363 | col: prev_tok.col, 364 | }); 365 | } 366 | 367 | let maybe_retval = if !self.matches(scanner::TokenType::Semicolon) { 368 | Some(self.expression()?) 369 | } else { 370 | None 371 | }; 372 | 373 | if maybe_retval.is_some() { 374 | self.consume( 375 | scanner::TokenType::Semicolon, 376 | "expected ; पछि फर्कने (return) भ्यालु (value)", 377 | )?; 378 | } 379 | 380 | Ok(expr::Stmt::Return( 381 | expr::SourceLocation { 382 | line: prev_tok.line, 383 | col: prev_tok.col, 384 | }, 385 | maybe_retval, 386 | )) 387 | } 388 | 389 | fn for_statement(&mut self) -> Result { 390 | self.consume(scanner::TokenType::LeftParen, "expected ( पछि for.")?; 391 | 392 | let mut maybe_initializer: Option = None; 393 | if self.matches(scanner::TokenType::Semicolon) { 394 | } else if self.matches(scanner::TokenType::Var) { 395 | maybe_initializer = Some(self.var_decl()?) 396 | } else { 397 | maybe_initializer = Some(self.expression_statement()?) 398 | } 399 | let maybe_initializer = maybe_initializer; 400 | 401 | let mut maybe_condition: Option = None; 402 | if !self.check(scanner::TokenType::Semicolon) { 403 | maybe_condition = Some(self.expression()?) 404 | } 405 | let maybe_condition = maybe_condition; 406 | 407 | self.consume( 408 | scanner::TokenType::Semicolon, 409 | "expected ; पछि loop condition", 410 | )?; 411 | 412 | let maybe_increment = if !self.check(scanner::TokenType::RightParen) { 413 | Some(self.expression()?) 414 | } else { 415 | None 416 | }; 417 | 418 | self.consume( 419 | scanner::TokenType::RightParen, 420 | "expected ) पछि for clauses", 421 | )?; 422 | 423 | let mut body = self.statement()?; 424 | 425 | if let Some(increment) = maybe_increment { 426 | body = expr::Stmt::Block(vec![body, expr::Stmt::Expr(increment)]) 427 | } 428 | 429 | let condition = match maybe_condition { 430 | Some(cond) => cond, 431 | None => expr::Expr::Literal(expr::Literal::True), 432 | }; 433 | body = expr::Stmt::While(condition, Box::new(body)); 434 | 435 | if let Some(initializer) = maybe_initializer { 436 | body = expr::Stmt::Block(vec![initializer, body]) 437 | } 438 | let body = body; 439 | 440 | Ok(body) 441 | } 442 | 443 | fn while_statement(&mut self) -> Result { 444 | self.consume(scanner::TokenType::LeftParen, "expected ( पछि while")?; 445 | let cond = self.expression()?; 446 | self.consume( 447 | scanner::TokenType::RightParen, 448 | "expected ) पछि while condition", 449 | )?; 450 | let body = Box::new(self.statement()?); 451 | Ok(expr::Stmt::While(cond, body)) 452 | } 453 | 454 | fn if_statement(&mut self) -> Result { 455 | self.consume(scanner::TokenType::LeftParen, "expected ( पछि if.")?; 456 | let cond = self.expression()?; 457 | self.consume( 458 | scanner::TokenType::RightParen, 459 | "expected ) पछि if condition.", 460 | )?; 461 | let then_branch = Box::new(self.statement()?); 462 | let maybe_else_branch = if self.matches(scanner::TokenType::Else) { 463 | Some(Box::new(self.statement()?)) 464 | } else { 465 | None 466 | }; 467 | 468 | Ok(expr::Stmt::If(cond, then_branch, maybe_else_branch)) 469 | } 470 | 471 | fn block(&mut self) -> Result, Error> { 472 | let mut stmts = Vec::new(); 473 | 474 | while !self.check(scanner::TokenType::RightBrace) && !self.is_at_end() { 475 | stmts.push(self.declaration()?) 476 | } 477 | 478 | self.consume(scanner::TokenType::RightBrace, "expected } पछि block.")?; 479 | 480 | Ok(stmts) 481 | } 482 | 483 | fn print_statement(&mut self) -> Result { 484 | let expr = self.expression()?; 485 | self.consume(scanner::TokenType::Semicolon, "expected ; पछि भ्यालु (value)")?; 486 | Ok(expr::Stmt::Print(expr)) 487 | } 488 | 489 | fn expression_statement(&mut self) -> Result { 490 | let expr = self.expression()?; 491 | self.consume(scanner::TokenType::Semicolon, "expected ; पछि भ्यालु (value)")?; 492 | Ok(expr::Stmt::Expr(expr)) 493 | } 494 | 495 | fn expression(&mut self) -> Result { 496 | self.assignment() 497 | } 498 | 499 | fn assignment(&mut self) -> Result { 500 | let expr = self.or()?; 501 | 502 | if self.matches(scanner::TokenType::Equal) { 503 | let equals = self.previous().clone(); 504 | let new_value = self.assignment()?; 505 | 506 | if let expr::Expr::Variable(sym) = &expr { 507 | return Ok(expr::Expr::Assign(sym.clone(), Box::new(new_value))); 508 | } else if let expr::Expr::Get(e, attr) = expr { 509 | return Ok(expr::Expr::Set(e, attr, Box::new(new_value))); 510 | } else { 511 | return Err(Error::InvalidAssignment { 512 | line: equals.line, 513 | col: equals.col, 514 | }); 515 | } 516 | } 517 | 518 | Ok(expr) 519 | } 520 | 521 | fn or(&mut self) -> Result { 522 | let mut expr = self.and()?; 523 | 524 | while self.matches(scanner::TokenType::Or) { 525 | let right = self.and()?; 526 | expr = expr::Expr::Logical(Box::new(expr), expr::LogicalOp::Or, Box::new(right)); 527 | } 528 | 529 | Ok(expr) 530 | } 531 | 532 | fn and(&mut self) -> Result { 533 | let mut expr = self.equality()?; 534 | 535 | while self.matches(scanner::TokenType::And) { 536 | let right = self.equality()?; 537 | expr = expr::Expr::Logical(Box::new(expr), expr::LogicalOp::And, Box::new(right)); 538 | } 539 | 540 | Ok(expr) 541 | } 542 | 543 | fn comparison(&mut self) -> Result { 544 | let mut expr = self.addition()?; 545 | 546 | while self.match_one_of(vec![ 547 | scanner::TokenType::Greater, 548 | scanner::TokenType::GreaterEqual, 549 | scanner::TokenType::Less, 550 | scanner::TokenType::LessEqual, 551 | ]) { 552 | let operator_token = self.previous().clone(); 553 | let right = Box::new(self.addition()?); 554 | let binop_maybe = Parser::op_token_to_binop(&operator_token); 555 | 556 | match binop_maybe { 557 | Ok(binop) => { 558 | let left = Box::new(expr); 559 | expr = expr::Expr::Binary(left, binop, right); 560 | } 561 | Err(err) => return Err(err), 562 | } 563 | } 564 | Ok(expr) 565 | } 566 | 567 | fn addition(&mut self) -> Result { 568 | let mut expr = self.multiplication()?; 569 | 570 | while self.match_one_of(vec![scanner::TokenType::Minus, scanner::TokenType::Plus]) { 571 | let operator_token = self.previous().clone(); 572 | let right = Box::new(self.multiplication()?); 573 | let binop_maybe = Parser::op_token_to_binop(&operator_token); 574 | 575 | match binop_maybe { 576 | Ok(binop) => { 577 | let left = Box::new(expr); 578 | expr = expr::Expr::Binary(left, binop, right); 579 | } 580 | Err(err) => return Err(err), 581 | } 582 | } 583 | Ok(expr) 584 | } 585 | 586 | fn multiplication(&mut self) -> Result { 587 | let mut expr = self.unary()?; 588 | 589 | while self.match_one_of(vec![scanner::TokenType::Slash, scanner::TokenType::Star]) { 590 | let operator_token = self.previous().clone(); 591 | let right = Box::new(self.unary()?); 592 | let binop_maybe = Parser::op_token_to_binop(&operator_token); 593 | 594 | match binop_maybe { 595 | Ok(binop) => { 596 | let left = Box::new(expr); 597 | expr = expr::Expr::Binary(left, binop, right); 598 | } 599 | Err(err) => return Err(err), 600 | } 601 | } 602 | Ok(expr) 603 | } 604 | 605 | fn unary(&mut self) -> Result { 606 | if self.match_one_of(vec![scanner::TokenType::Bang, scanner::TokenType::Minus]) { 607 | let operator_token = self.previous().clone(); 608 | let right = Box::new(self.unary()?); 609 | let unary_op_maybe = Parser::op_token_to_unary_op(&operator_token); 610 | 611 | return match unary_op_maybe { 612 | Ok(unary_op) => Ok(expr::Expr::Unary(unary_op, right)), 613 | Err(err) => Err(err), 614 | }; 615 | } 616 | self.call() 617 | } 618 | 619 | fn call(&mut self) -> Result { 620 | let mut expr = self.primary()?; 621 | 622 | loop { 623 | if self.matches(scanner::TokenType::LeftParen) { 624 | expr = self.finish_call(expr)?; 625 | } else if self.matches(scanner::TokenType::Dot) { 626 | let name_tok = self 627 | .consume( 628 | scanner::TokenType::Identifier, 629 | "expected गुड (property) नाम (name) पछि '.'.", 630 | )? 631 | .clone(); 632 | expr = expr::Expr::Get( 633 | Box::new(expr), 634 | expr::Symbol { 635 | name: name_tok.lexeme.iter().collect(), 636 | line: name_tok.line, 637 | col: name_tok.col, 638 | }, 639 | ); 640 | } else { 641 | break; 642 | } 643 | } 644 | Ok(expr) 645 | } 646 | 647 | fn finish_call(&mut self, callee: expr::Expr) -> Result { 648 | let mut arguments = Vec::new(); 649 | 650 | if !self.check(scanner::TokenType::RightParen) { 651 | loop { 652 | if arguments.len() >= 255 { 653 | let peek_tok = self.peek(); 654 | return Err(Error::TooManyArguments { 655 | line: peek_tok.line, 656 | col: peek_tok.col, 657 | }); 658 | } 659 | arguments.push(self.expression()?); 660 | if !self.matches(scanner::TokenType::Comma) { 661 | break; 662 | } 663 | } 664 | } 665 | 666 | let token = self.consume( 667 | scanner::TokenType::RightParen, 668 | "expected ) पछि arguments.", 669 | )?; 670 | 671 | Ok(expr::Expr::Call( 672 | Box::new(callee), 673 | expr::SourceLocation { 674 | line: token.line, 675 | col: token.col, 676 | }, 677 | arguments, 678 | )) 679 | } 680 | 681 | fn primary(&mut self) -> Result { 682 | if self.matches(scanner::TokenType::False) { 683 | return Ok(expr::Expr::Literal(expr::Literal::False)); 684 | } 685 | if self.matches(scanner::TokenType::True) { 686 | return Ok(expr::Expr::Literal(expr::Literal::True)); 687 | } 688 | if self.matches(scanner::TokenType::Nil) { 689 | return Ok(expr::Expr::Literal(expr::Literal::Nil)); 690 | } 691 | if self.matches(scanner::TokenType::Super) { 692 | let super_tok = self.previous().clone(); 693 | self.consume(scanner::TokenType::Dot, "expected '.' पछि 'super'.")?; 694 | let method_tok = self.consume( 695 | scanner::TokenType::Identifier, 696 | "expected superclass method नाम (name) .", 697 | )?; 698 | return Ok(expr::Expr::Super( 699 | expr::SourceLocation { 700 | line: super_tok.line, 701 | col: super_tok.col, 702 | }, 703 | expr::Symbol { 704 | name: method_tok.lexeme.iter().collect(), 705 | line: method_tok.line, 706 | col: method_tok.col, 707 | }, 708 | )); 709 | } 710 | if self.matches(scanner::TokenType::Number) { 711 | match &self.previous().literal { 712 | Some(scanner::Literal::Number(n)) => { 713 | return Ok(expr::Expr::Literal(expr::Literal::Number(*n))) 714 | } 715 | Some(l) => panic!( 716 | "internal error in parser: when parsing number, found literal {:?}", 717 | l 718 | ), 719 | None => panic!("internal error in parser: when parsing number, found no literal"), 720 | } 721 | } 722 | if self.matches(scanner::TokenType::String) { 723 | match &self.previous().literal { 724 | Some(scanner::Literal::Str(s)) => { 725 | return Ok(expr::Expr::Literal(expr::Literal::String(s.clone()))) 726 | } 727 | Some(l) => panic!( 728 | "internal error in parser: when parsing string, found literal {:?}", 729 | l 730 | ), 731 | None => panic!("internal error in parser: when parsing string, found no literal"), 732 | } 733 | } 734 | if self.matches(scanner::TokenType::This) { 735 | let prev = self.previous(); 736 | return Ok(expr::Expr::This(expr::SourceLocation { 737 | line: prev.line, 738 | col: prev.col, 739 | })); 740 | } 741 | if self.matches(scanner::TokenType::Identifier) { 742 | match &self.previous().literal { 743 | Some(scanner::Literal::Identifier(s)) => { 744 | return Ok(expr::Expr::Variable(expr::Symbol { 745 | name: s.clone(), 746 | line: self.previous().line, 747 | col: self.previous().col, 748 | })) 749 | } 750 | Some(l) => panic!( 751 | "internal error in parser: when parsing identifier, found literal {:?}", 752 | l 753 | ), 754 | None => { 755 | panic!("internal error in parser: when parsing identifier, found no literal") 756 | } 757 | } 758 | } 759 | if self.matches(scanner::TokenType::LeftParen) { 760 | let expr = Box::new(self.expression()?); 761 | self.consume( 762 | scanner::TokenType::RightParen, 763 | "expected ')' पछि expression.", 764 | )?; 765 | return Ok(expr::Expr::Grouping(expr)); 766 | } 767 | 768 | Err(Error::ExpectedExpression { 769 | token_type: self.peek().ty, 770 | line: self.peek().line, 771 | col: self.peek().col, 772 | }) 773 | } 774 | 775 | fn consume( 776 | &mut self, 777 | tok: scanner::TokenType, 778 | on_err_str: &str, 779 | ) -> Result<&scanner::Token, Error> { 780 | if self.check(tok) { 781 | return Ok(self.advance()); 782 | } 783 | Err(Error::TokenMismatch { 784 | expected: tok, 785 | found: self.peek().clone(), 786 | maybe_on_err_string: Some(on_err_str.into()), 787 | }) 788 | } 789 | 790 | fn op_token_to_unary_op(tok: &scanner::Token) -> Result { 791 | match tok.ty { 792 | scanner::TokenType::Minus => Ok(expr::UnaryOp { 793 | ty: expr::UnaryOpTy::Minus, 794 | line: tok.line, 795 | col: tok.col, 796 | }), 797 | scanner::TokenType::Bang => Ok(expr::UnaryOp { 798 | ty: expr::UnaryOpTy::Bang, 799 | line: tok.line, 800 | col: tok.col, 801 | }), 802 | _ => Err(Error::InvalidTokenInUnaryOp { 803 | token_type: tok.ty, 804 | line: tok.line, 805 | col: tok.col, 806 | }), 807 | } 808 | } 809 | 810 | fn equality(&mut self) -> Result { 811 | let mut expr = self.comparison()?; 812 | 813 | while self.match_one_of(vec![ 814 | scanner::TokenType::BangEqual, 815 | scanner::TokenType::EqualEqual, 816 | ]) { 817 | let operator_token = self.previous().clone(); 818 | let right = Box::new(self.comparison()?); 819 | 820 | let binop_maybe = Parser::op_token_to_binop(&operator_token); 821 | 822 | match binop_maybe { 823 | Ok(binop) => { 824 | let left = Box::new(expr); 825 | expr = expr::Expr::Binary(left, binop, right); 826 | } 827 | Err(err) => return Err(err), 828 | } 829 | } 830 | Ok(expr) 831 | } 832 | 833 | fn op_token_to_binop(tok: &scanner::Token) -> Result { 834 | match tok.ty { 835 | scanner::TokenType::EqualEqual => Ok(expr::BinaryOp { 836 | ty: expr::BinaryOpTy::EqualEqual, 837 | line: tok.line, 838 | col: tok.col, 839 | }), 840 | scanner::TokenType::BangEqual => Ok(expr::BinaryOp { 841 | ty: expr::BinaryOpTy::NotEqual, 842 | line: tok.line, 843 | col: tok.col, 844 | }), 845 | scanner::TokenType::Less => Ok(expr::BinaryOp { 846 | ty: expr::BinaryOpTy::Less, 847 | line: tok.line, 848 | col: tok.col, 849 | }), 850 | scanner::TokenType::LessEqual => Ok(expr::BinaryOp { 851 | ty: expr::BinaryOpTy::LessEqual, 852 | line: tok.line, 853 | col: tok.col, 854 | }), 855 | scanner::TokenType::Greater => Ok(expr::BinaryOp { 856 | ty: expr::BinaryOpTy::Greater, 857 | line: tok.line, 858 | col: tok.col, 859 | }), 860 | scanner::TokenType::GreaterEqual => Ok(expr::BinaryOp { 861 | ty: expr::BinaryOpTy::GreaterEqual, 862 | line: tok.line, 863 | col: tok.col, 864 | }), 865 | scanner::TokenType::Plus => Ok(expr::BinaryOp { 866 | ty: expr::BinaryOpTy::Plus, 867 | line: tok.line, 868 | col: tok.col, 869 | }), 870 | scanner::TokenType::Minus => Ok(expr::BinaryOp { 871 | ty: expr::BinaryOpTy::Minus, 872 | line: tok.line, 873 | col: tok.col, 874 | }), 875 | scanner::TokenType::Star => Ok(expr::BinaryOp { 876 | ty: expr::BinaryOpTy::Star, 877 | line: tok.line, 878 | col: tok.col, 879 | }), 880 | scanner::TokenType::Slash => Ok(expr::BinaryOp { 881 | ty: expr::BinaryOpTy::Slash, 882 | line: tok.line, 883 | col: tok.col, 884 | }), 885 | _ => Err(Error::InvalidTokenInBinaryOp { 886 | token_type: tok.ty, 887 | line: tok.line, 888 | col: tok.col, 889 | }), 890 | } 891 | } 892 | 893 | fn match_one_of(&mut self, types: Vec) -> bool { 894 | for ty in types.iter() { 895 | if self.matches(*ty) { 896 | return true; 897 | } 898 | } 899 | false 900 | } 901 | 902 | fn matches(&mut self, ty: scanner::TokenType) -> bool { 903 | if self.check(ty) { 904 | self.advance(); 905 | return true; 906 | } 907 | false 908 | } 909 | 910 | fn check(&self, ty: scanner::TokenType) -> bool { 911 | if self.is_at_end() { 912 | return false; 913 | } 914 | 915 | self.peek().ty == ty 916 | } 917 | 918 | fn advance(&mut self) -> &scanner::Token { 919 | if !self.is_at_end() { 920 | self.current += 1 921 | } 922 | 923 | self.previous() 924 | } 925 | 926 | fn is_at_end(&self) -> bool { 927 | self.peek().ty == scanner::TokenType::Eof 928 | } 929 | 930 | fn peek(&self) -> &scanner::Token { 931 | &self.tokens[self.current] 932 | } 933 | 934 | fn previous(&self) -> &scanner::Token { 935 | &self.tokens[self.current - 1] 936 | } 937 | } 938 | -------------------------------------------------------------------------------- /src/interpreter.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::convert::TryInto; 3 | use std::sync::atomic::{AtomicBool, Ordering}; 4 | use std::sync::Arc; 5 | use std::time::{SystemTime, UNIX_EPOCH}; 6 | 7 | use crate::expr; 8 | 9 | use std::fmt; 10 | use std::fmt::Write; 11 | 12 | static INIT: &str = "सुरु"; 13 | 14 | trait Callable { 15 | fn arity(&self, interpreter: &Interpreter) -> u8; 16 | fn call(&self, interpreter: &mut Interpreter, args: &[Value]) -> Result; 17 | } 18 | 19 | #[derive(Clone)] 20 | pub struct NativeFunction { 21 | pub name: String, 22 | pub arity: u8, 23 | pub callable: fn(&mut Interpreter, &[Value]) -> Result, 24 | } 25 | 26 | impl fmt::Debug for NativeFunction { 27 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 28 | write!(f, "NativeFunction({})", self.name) 29 | } 30 | } 31 | 32 | impl Callable for NativeFunction { 33 | fn arity(&self, _interpreter: &Interpreter) -> u8 { 34 | self.arity 35 | } 36 | fn call(&self, interpreter: &mut Interpreter, args: &[Value]) -> Result { 37 | (self.callable)(interpreter, args) 38 | } 39 | } 40 | 41 | #[derive(Clone, Debug)] 42 | pub struct LoxFunction { 43 | pub id: u64, 44 | pub name: expr::Symbol, 45 | pub parameters: Vec, 46 | pub body: Vec, 47 | pub closure: Environment, 48 | pub this_binding: Option>, 49 | pub superclass: Option, 50 | pub is_initializer: bool, 51 | } 52 | 53 | impl Callable for LoxFunction { 54 | fn arity(&self, _interpreter: &Interpreter) -> u8 { 55 | self.parameters.len().try_into().unwrap() 56 | } 57 | fn call(&self, interpreter: &mut Interpreter, args: &[Value]) -> Result { 58 | let args_env: HashMap<_, _> = self 59 | .parameters 60 | .iter() 61 | .zip(args.iter()) 62 | .map(|(param, arg)| { 63 | ( 64 | param.name.clone(), 65 | ( 66 | Some(arg.clone()), 67 | SourceLocation { 68 | line: param.line, 69 | col: param.col, 70 | }, 71 | ), 72 | ) 73 | }) 74 | .collect(); 75 | 76 | let saved_env = interpreter.env.clone(); 77 | let saved_retval = interpreter.retval.clone(); 78 | let saved_enclosing_function = interpreter.enclosing_function; 79 | 80 | let mut env = self.closure.clone(); 81 | env.venv.extend(saved_env.venv.clone()); 82 | env.venv.extend(args_env); 83 | 84 | if let Some(this_val) = &self.this_binding { 85 | // this is just used for lookup on name. source location is meaningless and unused` 86 | let this_symbol = Interpreter::this_symbol(0, -1); 87 | env.venv.insert( 88 | this_symbol.name, 89 | ( 90 | Some(*this_val.clone()), 91 | SourceLocation { 92 | line: this_symbol.line, 93 | col: this_symbol.col, 94 | }, 95 | ), 96 | ); 97 | } else if let Ok(this_val) = interpreter.lookup(&Interpreter::this_symbol(0, -1)) { 98 | // this is just used for lookup on name. source location is meaningless and unused` 99 | let this_symbol = Interpreter::this_symbol(0, -1); 100 | env.venv.insert( 101 | this_symbol.name, 102 | ( 103 | Some(this_val.clone()), 104 | SourceLocation { 105 | line: this_symbol.line, 106 | col: this_symbol.col, 107 | }, 108 | ), 109 | ); 110 | } 111 | let env = env; 112 | 113 | interpreter.env = env; 114 | interpreter.enclosing_function = Some(self.id); 115 | interpreter.backtrace.push((0, self.name.name.clone())); 116 | interpreter.interpret(&self.body)?; 117 | 118 | let retval = interpreter.retval.clone(); 119 | interpreter.backtrace.pop(); 120 | interpreter.enclosing_function = saved_enclosing_function; 121 | interpreter.env = saved_env; 122 | interpreter.retval = saved_retval; 123 | 124 | match retval { 125 | Some(val) => { 126 | let val_type = type_of(&val); 127 | if self.is_initializer && val_type != Type::Nil { 128 | Err(format!( 129 | "TypeError: init should only return nil (perhaps implicitly), not {:?}", 130 | val_type 131 | )) 132 | } else { 133 | Ok(val) 134 | } 135 | } 136 | None => { 137 | if self.is_initializer { 138 | match &self.this_binding { 139 | Some(this_val) => Ok(*this_val.clone()), 140 | None => { 141 | panic!("Internal intepreter error: could not find binding for this.") 142 | } 143 | } 144 | } else { 145 | Ok(Value::Nil) 146 | } 147 | } 148 | } 149 | } 150 | } 151 | 152 | #[derive(Clone, Debug)] 153 | pub struct LoxClass { 154 | pub name: expr::Symbol, 155 | pub superclass: Option, 156 | pub id: u64, 157 | pub methods: HashMap, 158 | } 159 | 160 | impl Callable for LoxClass { 161 | fn arity(&self, interpreter: &Interpreter) -> u8 { 162 | match self.init(interpreter) { 163 | Some(initializer) => initializer.parameters.len().try_into().unwrap(), 164 | None => 0, 165 | } 166 | } 167 | fn call(&self, interpreter: &mut Interpreter, args: &[Value]) -> Result { 168 | let instance = interpreter.create_instance(&self.name, self.id); 169 | 170 | if let Some(mut initializer) = self.init(interpreter) { 171 | initializer.this_binding = Some(Box::new(instance.clone())); 172 | initializer.call(interpreter, args)?; 173 | } 174 | 175 | Ok(instance) 176 | } 177 | } 178 | 179 | impl LoxClass { 180 | fn init(&self, interpreter: &Interpreter) -> Option { 181 | self.methods 182 | .get(&String::from(INIT)) 183 | .map(|initializer_id| interpreter.get_lox_function(*initializer_id).clone()) 184 | } 185 | 186 | fn find_method( 187 | &self, 188 | method_name: &str, 189 | interpreter: &Interpreter, 190 | ) -> Option<(expr::Symbol, u64)> { 191 | if let Some(method_id) = self.methods.get(method_name) { 192 | let lox_fn = interpreter.get_lox_function(*method_id); 193 | return Some((lox_fn.name.clone(), *method_id)); 194 | } else if let Some(superclass_id) = self.superclass { 195 | return interpreter 196 | .get_lox_class(superclass_id) 197 | .find_method(method_name, interpreter); 198 | } 199 | None 200 | } 201 | } 202 | 203 | #[derive(Clone, Debug)] 204 | pub struct LoxInstance { 205 | pub class_name: expr::Symbol, 206 | pub class_id: u64, 207 | pub id: u64, 208 | pub fields: HashMap, 209 | } 210 | 211 | impl LoxInstance { 212 | fn getattr(&self, attr: &str, interpreter: &Interpreter) -> Result { 213 | match self.fields.get(attr) { 214 | Some(val) => Ok(val.clone()), 215 | None => { 216 | let cls = interpreter.get_lox_class(self.class_id); 217 | if let Some((func_name, method_id)) = cls.find_method(attr, interpreter) { 218 | return Ok(Value::LoxFunction( 219 | func_name, 220 | method_id, 221 | Some(Box::new(Value::LoxInstance( 222 | self.class_name.clone(), 223 | self.id, 224 | ))), 225 | )); 226 | } 227 | Err(format!( 228 | "AttributeError: '{}' instance has no '{}' attribute.", 229 | self.class_name.name, attr 230 | )) 231 | } 232 | } 233 | } 234 | } 235 | 236 | #[derive(Debug, Clone)] 237 | pub enum Value { 238 | Number(f64), 239 | String(String), 240 | Bool(bool), 241 | Nil, 242 | NativeFunction(NativeFunction), 243 | LoxFunction( 244 | expr::Symbol, 245 | /*id*/ u64, 246 | /*this binding*/ Option>, 247 | ), 248 | LoxClass(expr::Symbol, /*id*/ u64), 249 | LoxInstance(expr::Symbol, /*id*/ u64), 250 | List(/*id*/ u64), 251 | } 252 | 253 | fn as_callable(interpreter: &Interpreter, value: &Value) -> Option> { 254 | match value { 255 | Value::NativeFunction(f) => Some(Box::new(f.clone())), 256 | Value::LoxFunction(_, id, this_binding) => { 257 | let f = interpreter.get_lox_function(*id); 258 | let mut f_copy = f.clone(); 259 | f_copy.this_binding = this_binding.clone(); 260 | Some(Box::new(f_copy)) 261 | } 262 | Value::LoxClass(_, id) => Some(Box::new(interpreter.get_lox_class(*id).clone())), 263 | _ => None, 264 | } 265 | } 266 | 267 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] 268 | pub enum Type { 269 | Number, 270 | String, 271 | Bool, 272 | Nil, 273 | NativeFunction, 274 | LoxFunction, 275 | LoxClass, 276 | LoxInstance, 277 | List, 278 | } 279 | 280 | pub fn type_of(val: &Value) -> Type { 281 | match val { 282 | Value::Number(_) => Type::Number, 283 | Value::String(_) => Type::String, 284 | Value::Bool(_) => Type::Bool, 285 | Value::Nil => Type::Nil, 286 | Value::NativeFunction(_) => Type::NativeFunction, 287 | Value::LoxFunction(_, _, _) => Type::LoxFunction, 288 | Value::LoxClass(_, _) => Type::LoxClass, 289 | Value::LoxInstance(_, _) => Type::LoxInstance, 290 | Value::List(_) => Type::List, 291 | } 292 | } 293 | 294 | #[derive(Debug, Clone)] 295 | pub struct SourceLocation { 296 | line: usize, 297 | col: i64, 298 | } 299 | 300 | #[derive(Debug, Default, Clone)] 301 | pub struct Environment { 302 | enclosing: Option>, 303 | // SourceLocation is the location of a declaration 304 | venv: HashMap, SourceLocation)>, 305 | } 306 | 307 | pub enum LookupResult<'a> { 308 | Ok(&'a Value), 309 | UndefButDeclared(SourceLocation), 310 | UndefAndNotDeclared, 311 | } 312 | 313 | impl Environment { 314 | pub fn with_enclosing(enclosing: Environment) -> Environment { 315 | Environment { 316 | enclosing: Some(Box::new(enclosing)), 317 | venv: HashMap::new(), 318 | } 319 | } 320 | 321 | pub fn define(&mut self, sym: expr::Symbol, maybe_val: Option) { 322 | self.venv.insert( 323 | sym.name, 324 | ( 325 | maybe_val, 326 | SourceLocation { 327 | line: sym.line, 328 | col: sym.col, 329 | }, 330 | ), 331 | ); 332 | } 333 | 334 | pub fn lookup(&self, sym: &expr::Symbol) -> LookupResult { 335 | match self.venv.get(&sym.name) { 336 | Some((maybe_val, defn_source_location)) => match maybe_val { 337 | Some(val) => LookupResult::Ok(val), 338 | None => LookupResult::UndefButDeclared(SourceLocation { 339 | line: defn_source_location.line, 340 | col: defn_source_location.col, 341 | }), 342 | }, 343 | None => LookupResult::UndefAndNotDeclared, 344 | } 345 | } 346 | 347 | pub fn get(&self, sym: &expr::Symbol) -> Result<&Value, String> { 348 | match self.lookup(sym) { 349 | LookupResult::Ok(val) => Ok(val), 350 | LookupResult::UndefButDeclared(source_location) => Err(format!( 351 | "Use of undefined variable '{}' at line={},col={}.\ 352 | \nNote: {} was previously declared at line={},col={}, \ 353 | but was never defined.", 354 | &sym.name, sym.line, sym.col, &sym.name, source_location.line, source_location.col 355 | )), 356 | LookupResult::UndefAndNotDeclared => match &self.enclosing { 357 | Some(enclosing) => enclosing.get(sym), 358 | None => Err(format!( 359 | "Use of undefined variable {} at line={},col={}.\nNote: {} was never declared.", 360 | &sym.name, sym.line, sym.col, &sym.name 361 | )), 362 | }, 363 | } 364 | } 365 | 366 | pub fn assign(&mut self, sym: expr::Symbol, val: &Value) -> Result<(), String> { 367 | if self.venv.contains_key(&sym.name) { 368 | self.define(sym, Some(val.clone())); 369 | return Ok(()); 370 | } 371 | 372 | match &mut self.enclosing { 373 | Some(enclosing) => enclosing.assign(sym, val), 374 | None => Err(format!( 375 | "attempting to assign to undeclared variable at line={},col={}", 376 | sym.line, sym.col 377 | )), 378 | } 379 | } 380 | } 381 | 382 | pub struct Interpreter { 383 | pub counter: u64, 384 | pub lambda_counter: u64, 385 | pub lox_functions: HashMap, 386 | pub lox_instances: HashMap, 387 | pub lox_classes: HashMap, 388 | pub lists: HashMap>, 389 | pub env: Environment, 390 | pub globals: Environment, 391 | pub retval: Option, 392 | pub output: Vec, 393 | pub enclosing_function: Option, 394 | pub interrupted: Arc, 395 | pub backtrace: Vec<(u64, String)>, 396 | } 397 | 398 | impl Default for Interpreter { 399 | fn default() -> Interpreter { 400 | let mut globals_venv = HashMap::new(); 401 | globals_venv.insert( 402 | String::from("clock"), 403 | ( 404 | Some(Value::NativeFunction(NativeFunction { 405 | name: String::from("clock"), 406 | arity: 0, 407 | callable: |_, _| { 408 | let start = SystemTime::now(); 409 | let since_the_epoch = start.duration_since(UNIX_EPOCH).unwrap(); 410 | 411 | Ok(Value::Number(since_the_epoch.as_millis() as f64)) 412 | }, 413 | })), 414 | SourceLocation { 415 | line: 1337, 416 | col: 1337, 417 | }, 418 | ), 419 | ); 420 | globals_venv.insert( 421 | String::from("len"), 422 | ( 423 | Some(Value::NativeFunction(NativeFunction { 424 | name: String::from("len"), 425 | arity: 1, 426 | callable: |interp, values| match &values[0] { 427 | Value::String(s) => Ok(Value::Number(s.len() as f64)), 428 | Value::List(list_id) => { 429 | let elts = interp.get_list_elts(*list_id); 430 | Ok(Value::Number(elts.len() as f64)) 431 | } 432 | val => Err(format!("Object of type {:?} has no len.", type_of(val))), 433 | }, 434 | })), 435 | SourceLocation { 436 | line: 1337, 437 | col: 1337, 438 | }, 439 | ), 440 | ); 441 | globals_venv.insert( 442 | String::from("iota"), 443 | ( 444 | Some(Value::NativeFunction(NativeFunction { 445 | name: String::from("iota"), 446 | arity: 2, 447 | callable: |interpreter, values| match (&values[0], &values[1]) { 448 | (Value::Number(low), Value::Number(high)) => { 449 | let elts: Vec<_> = (*low as i64..*high as i64) 450 | .map(|x| Value::Number(x as f64)) 451 | .collect(); 452 | Ok(interpreter.create_list(elts)) 453 | } 454 | (Value::Number(_), high) => Err(format!( 455 | "invalid high argument of type {:?} in iota expression.", 456 | type_of(high) 457 | )), 458 | (low, _) => Err(format!( 459 | "invalid low argument of type {:?} in iota expression.", 460 | type_of(low) 461 | )), 462 | }, 463 | })), 464 | SourceLocation { 465 | line: 1337, 466 | col: 1337, 467 | }, 468 | ), 469 | ); 470 | 471 | globals_venv.insert( 472 | String::from("forEach"), 473 | ( 474 | Some(Value::NativeFunction(NativeFunction { 475 | name: String::from("forEach"), 476 | arity: 2, 477 | callable: |interpreter, values| match &values[0] { 478 | Value::List(list_id) => { 479 | let elts = interpreter.get_list_elts(*list_id).clone(); 480 | let maybe_callable = as_callable(interpreter, &values[1]); 481 | match maybe_callable { 482 | Some(callable) => { 483 | for elt in elts { 484 | callable.call(interpreter, &[elt])?; 485 | } 486 | Ok(Value::Nil) 487 | } 488 | None => Err(format!( 489 | "The second argument to for_each must be callable. Found {:?}.", 490 | type_of(&values[1]) 491 | )), 492 | } 493 | } 494 | val => Err(format!( 495 | "Can't call forEach on value of type {:?}.", 496 | type_of(val) 497 | )), 498 | }, 499 | })), 500 | SourceLocation { 501 | line: 1337, 502 | col: 1337, 503 | }, 504 | ), 505 | ); 506 | globals_venv.insert( 507 | String::from("map"), 508 | ( 509 | Some(Value::NativeFunction(NativeFunction { 510 | name: String::from("map"), 511 | arity: 2, 512 | callable: |interpreter, values| match &values[1] { 513 | Value::List(list_id) => { 514 | let maybe_callable = as_callable(interpreter, &values[0]); 515 | match maybe_callable { 516 | Some(callable) => { 517 | let mut res_elts = Vec::new(); 518 | let elts = interpreter.get_list_elts(*list_id).clone(); 519 | for elt in elts { 520 | res_elts.push(callable.call(interpreter, &[elt.clone()])?); 521 | } 522 | Ok(interpreter.create_list(res_elts)) 523 | } 524 | None => Err(format!( 525 | "The second argument to for_each must be callable. Found {:?}.", 526 | type_of(&values[1]) 527 | )), 528 | } 529 | } 530 | val => Err(format!( 531 | "Can't call forEach on value of type {:?}.", 532 | type_of(val) 533 | )), 534 | }, 535 | })), 536 | SourceLocation { 537 | line: 1337, 538 | col: 1337, 539 | }, 540 | ), 541 | ); 542 | 543 | let globals = Environment { 544 | enclosing: None, 545 | venv: globals_venv, 546 | }; 547 | 548 | Interpreter { 549 | counter: 0, 550 | lambda_counter: 0, 551 | lox_functions: Default::default(), 552 | lox_instances: Default::default(), 553 | lox_classes: Default::default(), 554 | lists: Default::default(), 555 | env: Default::default(), 556 | globals, 557 | retval: None, 558 | output: Default::default(), 559 | enclosing_function: None, 560 | interrupted: Arc::new(AtomicBool::new(false)), 561 | backtrace: vec![(0, "script".to_string())], 562 | } 563 | } 564 | } 565 | 566 | impl Interpreter { 567 | pub fn interpret(&mut self, stmts: &[expr::Stmt]) -> Result<(), String> { 568 | self.interrupted.store(false, Ordering::Release); 569 | for stmt in stmts { 570 | self.execute(stmt)? 571 | } 572 | Ok(()) 573 | } 574 | 575 | pub fn get_lox_function(&self, id: u64) -> &LoxFunction { 576 | match self.lox_functions.get(&id) { 577 | Some(func) => func, 578 | None => panic!( 579 | "Internal interpreter error! couldn't find an function with id {}.", 580 | id 581 | ), 582 | } 583 | } 584 | 585 | pub fn get_lox_class(&self, id: u64) -> &LoxClass { 586 | match self.lox_classes.get(&id) { 587 | Some(func) => func, 588 | None => panic!( 589 | "Internal interpreter error! couldn't find class with id {}.", 590 | id 591 | ), 592 | } 593 | } 594 | 595 | pub fn get_lox_instance(&self, id: u64) -> &LoxInstance { 596 | match self.lox_instances.get(&id) { 597 | Some(inst) => inst, 598 | None => panic!( 599 | "Internal interpreter error: could not find an instance with id {}.", 600 | id 601 | ), 602 | } 603 | } 604 | 605 | pub fn format_backtrace(&self) -> String { 606 | let lines: Vec<_> = self 607 | .backtrace 608 | .iter() 609 | .map(|(_, funname)| format!("[line ??] in {}", funname)) 610 | .collect(); 611 | format!("Backtrace (most recent call last):\n\n{}", lines.join("\n")) 612 | } 613 | 614 | fn get_list_elts(&self, list_id: u64) -> &Vec { 615 | if let Some(elts) = self.lists.get(&list_id) { 616 | elts 617 | } else { 618 | panic!( 619 | "Internal interpreter error! Couldn't find list with id {}.", 620 | list_id 621 | ); 622 | } 623 | } 624 | 625 | 626 | fn alloc_id(&mut self) -> u64 { 627 | let res = self.counter; 628 | self.counter += 1; 629 | res 630 | } 631 | 632 | fn create_list(&mut self, elts: Vec) -> Value { 633 | let list_id = self.alloc_id(); 634 | self.lists.insert(list_id, elts); 635 | Value::List(list_id) 636 | } 637 | 638 | fn create_instance(&mut self, class_name: &expr::Symbol, class_id: u64) -> Value { 639 | let inst_id = self.alloc_id(); 640 | let inst = LoxInstance { 641 | class_name: class_name.clone(), 642 | class_id, 643 | id: inst_id, 644 | fields: HashMap::new(), 645 | }; 646 | self.lox_instances.insert(inst_id, inst); 647 | Value::LoxInstance(class_name.clone(), inst_id) 648 | } 649 | 650 | fn execute(&mut self, stmt: &expr::Stmt) -> Result<(), String> { 651 | if self.retval.is_some() { 652 | return Ok(()); 653 | } 654 | 655 | match stmt { 656 | expr::Stmt::Expr(e) => match self.interpret_expr(e) { 657 | Ok(_) => Ok(()), 658 | Err(err) => Err(err), 659 | }, 660 | expr::Stmt::ClassDecl(expr::ClassDecl { 661 | name: sym, 662 | superclass: maybe_superclass, 663 | methods: stmt_methods, 664 | }) => { 665 | let class_id = self.alloc_id(); 666 | self.env 667 | .define(sym.clone(), Some(Value::LoxClass(sym.clone(), class_id))); 668 | 669 | let superclass_id = if let Some(superclass_var) = maybe_superclass { 670 | if superclass_var.name == sym.name { 671 | return Err(format!( 672 | "A class cannot inerit from itself (line={}, col={})", 673 | sym.line, sym.col 674 | )); 675 | } 676 | 677 | let superclass_val = 678 | self.interpret_expr(&expr::Expr::Variable(superclass_var.clone()))?; 679 | if let Value::LoxClass(_, id) = superclass_val { 680 | Some(id) 681 | } else { 682 | return Err(format!( 683 | "Only classes should appear as superclasses. Found {:?}.", 684 | type_of(&superclass_val) 685 | )); 686 | } 687 | } else { 688 | None 689 | }; 690 | 691 | let mut methods = HashMap::new(); 692 | for method in stmt_methods.iter() { 693 | let func_id = self.alloc_id(); 694 | 695 | methods.insert(method.name.name.clone(), func_id); 696 | 697 | let is_initializer = method.name.name == INIT; 698 | 699 | let lox_function = LoxFunction { 700 | id: func_id, 701 | name: method.name.clone(), 702 | parameters: method.params.clone(), 703 | body: method.body.clone(), 704 | closure: self.env.clone(), 705 | this_binding: None, 706 | superclass: superclass_id, 707 | is_initializer, 708 | }; 709 | 710 | self.lox_functions.insert(func_id, lox_function); 711 | } 712 | 713 | let cls = LoxClass { 714 | name: sym.clone(), 715 | superclass: superclass_id, 716 | id: class_id, 717 | methods, 718 | }; 719 | 720 | self.lox_classes.insert(class_id, cls); 721 | Ok(()) 722 | } 723 | expr::Stmt::FunDecl(expr::FunDecl { 724 | name, 725 | params: parameters, 726 | body, 727 | }) => { 728 | let func_id = self.alloc_id(); 729 | self.env.define( 730 | name.clone(), 731 | Some(Value::LoxFunction(name.clone(), func_id, None)), 732 | ); 733 | 734 | let lox_function = LoxFunction { 735 | id: func_id, 736 | name: name.clone(), 737 | parameters: parameters.clone(), 738 | body: body.clone(), 739 | closure: self.env.clone(), 740 | this_binding: None, 741 | superclass: None, 742 | is_initializer: false, 743 | }; 744 | 745 | self.lox_functions.insert(func_id, lox_function); 746 | 747 | Ok(()) 748 | } 749 | expr::Stmt::If(cond, if_true, maybe_if_false) => { 750 | if Interpreter::is_truthy(&self.interpret_expr(cond)?) { 751 | return self.execute(if_true); 752 | } 753 | if let Some(if_false) = maybe_if_false { 754 | return self.execute(if_false); 755 | } 756 | Ok(()) 757 | } 758 | expr::Stmt::Print(e) => match self.interpret_expr(e) { 759 | Ok(val) => { 760 | println!("{}", self.format_val(&val)); 761 | self.output.push(self.format_val(&val)); 762 | Ok(()) 763 | } 764 | Err(err) => Err(err), 765 | }, 766 | expr::Stmt::VarDecl(sym, maybe_expr) => { 767 | let maybe_val = match maybe_expr { 768 | Some(expr) => Some(self.interpret_expr(expr)?), 769 | None => None, 770 | }; 771 | self.env.define(sym.clone(), maybe_val); 772 | Ok(()) 773 | } 774 | expr::Stmt::Block(stmts) => { 775 | self.env = Environment::with_enclosing(self.env.clone()); 776 | 777 | for stmt in stmts.iter() { 778 | self.execute(stmt)?; 779 | } 780 | 781 | if let Some(enclosing) = self.env.enclosing.clone() { 782 | self.env = *enclosing 783 | } else { 784 | // TODO: how to do this without a runtime check? 785 | panic!("impossible"); 786 | } 787 | 788 | Ok(()) 789 | } 790 | expr::Stmt::While(cond, body) => { 791 | while Interpreter::is_truthy(&self.interpret_expr(cond)?) { 792 | self.execute(body)?; 793 | } 794 | Ok(()) 795 | } 796 | expr::Stmt::Return(_, maybe_res) => { 797 | self.retval = Some(if let Some(res) = maybe_res { 798 | self.interpret_expr(res)? 799 | } else { 800 | Value::Nil 801 | }); 802 | Ok(()) 803 | } 804 | } 805 | } 806 | 807 | fn lookup(&self, sym: &expr::Symbol) -> Result<&Value, String> { 808 | match self.env.get(sym) { 809 | Ok(val) => Ok(val), 810 | Err(_) => self.globals.get(sym), 811 | } 812 | } 813 | 814 | fn this_symbol(line: usize, col: i64) -> expr::Symbol { 815 | expr::Symbol { 816 | name: String::from("this"), 817 | line, 818 | col, 819 | } 820 | } 821 | 822 | fn interpret_expr(&mut self, expr: &expr::Expr) -> Result { 823 | if self.interrupted.load(Ordering::Acquire) { 824 | return Ok(Value::Nil); 825 | } 826 | 827 | match expr { 828 | expr::Expr::This(source_location) => match self.lookup(&Interpreter::this_symbol( 829 | source_location.line, 830 | source_location.col, 831 | )) { 832 | Ok(val) => Ok(val.clone()), 833 | Err(err) => Err(err), 834 | }, 835 | expr::Expr::Literal(lit) => Ok(Interpreter::interpret_literal(lit)), 836 | expr::Expr::Unary(op, e) => self.interpret_unary(*op, e), 837 | expr::Expr::Binary(lhs, op, rhs) => self.interpret_binary(lhs, *op, rhs), 838 | expr::Expr::Call(callee, loc, args) => self.call(callee, loc, args), 839 | expr::Expr::Get(lhs, attr) => self.getattr(lhs, &attr.name), 840 | expr::Expr::Set(lhs, attr, rhs) => self.setattr(lhs, attr, rhs), 841 | expr::Expr::Grouping(e) => self.interpret_expr(e), 842 | expr::Expr::Variable(sym) => match self.lookup(sym) { 843 | Ok(val) => Ok(val.clone()), 844 | Err(err) => Err(err), 845 | }, 846 | expr::Expr::Assign(sym, val_expr) => { 847 | let val = self.interpret_expr(val_expr)?; 848 | 849 | self.env.assign(sym.clone(), &val)?; 850 | 851 | Ok(val) 852 | } 853 | expr::Expr::Logical(left_expr, expr::LogicalOp::Or, right_expr) => { 854 | let left = self.interpret_expr(left_expr)?; 855 | if Interpreter::is_truthy(&left) { 856 | Ok(left) 857 | } else { 858 | Ok(self.interpret_expr(right_expr)?) 859 | } 860 | } 861 | expr::Expr::Logical(left_expr, expr::LogicalOp::And, right_expr) => { 862 | let left = self.interpret_expr(left_expr)?; 863 | if !Interpreter::is_truthy(&left) { 864 | Ok(left) 865 | } else { 866 | Ok(self.interpret_expr(right_expr)?) 867 | } 868 | } 869 | expr::Expr::Super(source_location, sym) => match self.enclosing_function { 870 | Some(func_id) => { 871 | let func = self.get_lox_function(func_id); 872 | match &func.superclass { 873 | Some(superclass_id) => { 874 | let superclass = self.get_lox_class(*superclass_id); 875 | if let Some((func_name, method_id)) = superclass.find_method(&sym.name, self) { 876 | let method = self.get_lox_function(method_id); 877 | Ok(Value::LoxFunction( 878 | func_name, 879 | method.id, 880 | func.this_binding.clone())) 881 | } 882 | else { 883 | Err(format!("no superclass has method {} at line={}, col={}", 884 | sym.name, source_location.line, source_location.col)) 885 | } 886 | } 887 | _ => { 888 | Err(format!("Super expression not enclosed in a method definition at line={}, col={}.", 889 | source_location.line, source_location.col)) 890 | } 891 | } 892 | } 893 | None => Err(format!( 894 | "super expression not enclosed in a function at line={}, col={}.", 895 | source_location.line, source_location.col 896 | )), 897 | }, 898 | } 899 | } 900 | 901 | 902 | fn getattr(&mut self, lhs: &expr::Expr, attr: &str) -> Result { 903 | let val = self.interpret_expr(lhs)?; 904 | match val { 905 | Value::LoxInstance(_, id) => self.get_lox_instance(id).getattr(attr, self), 906 | _ => Err(format!( 907 | "Only LoxInstance values have attributes. Found {:?}.", 908 | type_of(&val) 909 | )), 910 | } 911 | } 912 | 913 | fn setattr( 914 | &mut self, 915 | lhs_exp: &expr::Expr, 916 | attr: &expr::Symbol, 917 | rhs_exp: &expr::Expr, 918 | ) -> Result { 919 | let lhs = self.interpret_expr(lhs_exp)?; 920 | let rhs = self.interpret_expr(rhs_exp)?; 921 | match lhs { 922 | Value::LoxInstance(_, id) => match self.lox_instances.get_mut(&id) { 923 | Some(inst) => { 924 | inst.fields.insert(attr.name.clone(), rhs.clone()); 925 | Ok(rhs) 926 | } 927 | None => panic!( 928 | "Internal interpreter error: could not find instance with id {}", 929 | id 930 | ), 931 | }, 932 | _ => Err(format!( 933 | "Only LoxInstance values have attributes. Found {:?}.", 934 | type_of(&lhs) 935 | )), 936 | } 937 | } 938 | 939 | fn call( 940 | &mut self, 941 | callee_expr: &expr::Expr, 942 | loc: &expr::SourceLocation, 943 | arg_exprs: &[expr::Expr], 944 | ) -> Result { 945 | let callee = self.interpret_expr(callee_expr)?; 946 | 947 | match as_callable(self, &callee) { 948 | Some(callable) => { 949 | let maybe_args: Result, _> = arg_exprs 950 | .iter() 951 | .map(|arg| self.interpret_expr(arg)) 952 | .collect(); 953 | 954 | match maybe_args { 955 | Ok(args) => { 956 | if args.len() != callable.arity(self).into() { 957 | Err(format!( 958 | "Invalid call at line={},col={}: callee has arity {}, but \ 959 | was called with {} arguments", 960 | loc.line, 961 | loc.col, 962 | callable.arity(self), 963 | args.len() 964 | )) 965 | } else { 966 | callable.call(self, &args) 967 | } 968 | } 969 | Err(err) => Err(err), 970 | } 971 | } 972 | None => Err(format!( 973 | "value {:?} is not callable at line={},col={}", 974 | callee, loc.line, loc.col 975 | )), 976 | } 977 | } 978 | 979 | fn interpret_binary( 980 | &mut self, 981 | lhs_expr: &expr::Expr, 982 | op: expr::BinaryOp, 983 | rhs_expr: &expr::Expr, 984 | ) -> Result { 985 | let lhs = self.interpret_expr(lhs_expr)?; 986 | let rhs = self.interpret_expr(rhs_expr)?; 987 | 988 | match (&lhs, op.ty, &rhs) { 989 | (Value::Number(n1), expr::BinaryOpTy::Less, Value::Number(n2)) => { 990 | Ok(Value::Bool(n1 < n2)) 991 | } 992 | (Value::Number(n1), expr::BinaryOpTy::LessEqual, Value::Number(n2)) => { 993 | Ok(Value::Bool(n1 <= n2)) 994 | } 995 | (Value::Number(n1), expr::BinaryOpTy::Greater, Value::Number(n2)) => { 996 | Ok(Value::Bool(n1 > n2)) 997 | } 998 | (Value::Number(n1), expr::BinaryOpTy::GreaterEqual, Value::Number(n2)) => { 999 | Ok(Value::Bool(n1 >= n2)) 1000 | } 1001 | (Value::Number(n1), expr::BinaryOpTy::Plus, Value::Number(n2)) => { 1002 | Ok(Value::Number(n1 + n2)) 1003 | } 1004 | (Value::Number(n1), expr::BinaryOpTy::Minus, Value::Number(n2)) => { 1005 | Ok(Value::Number(n1 - n2)) 1006 | } 1007 | (Value::Number(n1), expr::BinaryOpTy::Star, Value::Number(n2)) => { 1008 | Ok(Value::Number(n1 * n2)) 1009 | } 1010 | (Value::Number(n1), expr::BinaryOpTy::Slash, Value::Number(n2)) => { 1011 | if *n2 != 0.0 { 1012 | Ok(Value::Number(n1 / n2)) 1013 | } else { 1014 | Err(format!( 1015 | "division by zero at line={},col={}", 1016 | op.line, op.col 1017 | )) 1018 | } 1019 | } 1020 | (Value::String(s1), expr::BinaryOpTy::Plus, Value::String(s2)) => { 1021 | Ok(Value::String(format!("{}{}", s1, s2))) 1022 | } 1023 | (Value::List(xs_id), expr::BinaryOpTy::Plus, Value::List(ys_id)) => { 1024 | let xs = self.get_list_elts(*xs_id); 1025 | let ys = self.get_list_elts(*ys_id); 1026 | let mut res = xs.clone(); 1027 | res.extend(ys.clone()); 1028 | Ok(self.create_list(res)) 1029 | } 1030 | (_, expr::BinaryOpTy::EqualEqual, _) => { 1031 | Ok(Value::Bool(Interpreter::equals(&lhs, &rhs))) 1032 | } 1033 | (_, expr::BinaryOpTy::NotEqual, _) => Ok(Value::Bool(!Interpreter::equals(&lhs, &rhs))), 1034 | _ => Err(format!( 1035 | "invalid operands in binary operator {:?} of type {:?} and {:?} at line={},col={}", 1036 | op.ty, 1037 | type_of(&lhs), 1038 | type_of(&rhs), 1039 | op.line, 1040 | op.col 1041 | )), 1042 | } 1043 | } 1044 | 1045 | fn equals(lhs: &Value, rhs: &Value) -> bool { 1046 | match (lhs, rhs) { 1047 | (Value::Number(n1), Value::Number(n2)) => (n1 - n2).abs() < f64::EPSILON, 1048 | (Value::String(s1), Value::String(s2)) => s1 == s2, 1049 | (Value::Bool(b1), Value::Bool(b2)) => b1 == b2, 1050 | (Value::Nil, Value::Nil) => true, 1051 | (_, _) => false, 1052 | } 1053 | } 1054 | 1055 | fn interpret_unary(&mut self, op: expr::UnaryOp, expr: &expr::Expr) -> Result { 1056 | let val = self.interpret_expr(expr)?; 1057 | 1058 | match (op.ty, &val) { 1059 | (expr::UnaryOpTy::Minus, Value::Number(n)) => Ok(Value::Number(-n)), 1060 | (expr::UnaryOpTy::Bang, _) => Ok(Value::Bool(!Interpreter::is_truthy(&val))), 1061 | (_, Value::String(_)) => Err(format!( 1062 | "invalid application of unary op {:?} to object of type String at line={},col={}", 1063 | op.ty, op.line, op.col 1064 | )), 1065 | (_, Value::NativeFunction(_)) => Err(format!( 1066 | "invalid application of unary op {:?} to object of type NativeFunction at line={},col={}", 1067 | op.ty, op.line, op.col 1068 | )), 1069 | (_, Value::LoxFunction(_, _, _)) => Err(format!( 1070 | "invalid application of unary op {:?} to object of type LoxFunction at line={},col={}", 1071 | op.ty, op.line, op.col 1072 | )), 1073 | (_, Value::LoxClass(_, _)) => Err(format!( 1074 | "invalid application of unary op {:?} to object of type LoxClass at line={},col={}", 1075 | op.ty, op.line, op.col 1076 | )), 1077 | (_, Value::LoxInstance(class_name, _)) => Err(format!( 1078 | "invalid application of unary op {:?} to object of type {:?} at line={},col={}", 1079 | class_name.name, op.ty, op.line, op.col 1080 | )), 1081 | (expr::UnaryOpTy::Minus, Value::Bool(_)) => Err(format!( 1082 | "invalid application of unary op {:?} to object of type Bool at line={},col={}", 1083 | op.ty, op.line, op.col 1084 | )), 1085 | (_, Value::Nil) => Err(format!( 1086 | "invalid application of unary op {:?} to nil at line={},col={}", 1087 | op.ty, op.line, op.col 1088 | )), 1089 | (_, Value::List(_)) => Err(format!( 1090 | "invalid application of unary op {:?} to list at line={},col={}", 1091 | op.ty, op.line, op.col 1092 | )), 1093 | } 1094 | } 1095 | 1096 | fn is_truthy(val: &Value) -> bool { 1097 | match val { 1098 | Value::Nil => false, 1099 | Value::Bool(b) => *b, 1100 | _ => true, 1101 | } 1102 | } 1103 | 1104 | fn interpret_literal(lit: &expr::Literal) -> Value { 1105 | match lit { 1106 | expr::Literal::Number(n) => Value::Number(*n), 1107 | expr::Literal::String(s) => Value::String(s.clone()), 1108 | expr::Literal::True => Value::Bool(true), 1109 | expr::Literal::False => Value::Bool(false), 1110 | expr::Literal::Nil => Value::Nil, 1111 | } 1112 | } 1113 | 1114 | fn format_val(&self, val: &Value) -> String { 1115 | match val { 1116 | Value::Number(n) => format!("{}", n), 1117 | Value::String(s) => format!("'{}'", s), 1118 | Value::Bool(b) => format!("{}", b), 1119 | Value::Nil => "nil".to_string(), 1120 | Value::NativeFunction(func) => format!("NativeFunction({})", func.name), 1121 | Value::LoxFunction(sym, _, _) => format!("LoxFunction({})", sym.name), 1122 | Value::LoxClass(sym, _) => format!("LoxClass({})", sym.name), 1123 | Value::LoxInstance(sym, _) => format!("LoxInstance({})", sym.name), 1124 | Value::List(list_id) => { 1125 | let mut res = String::new(); 1126 | write!(&mut res, "[").unwrap(); 1127 | let elements = self.get_list_elts(*list_id); 1128 | elements.split_last().map(|(last_elt, rest)| { 1129 | rest.iter() 1130 | .try_for_each(|elt| write!(&mut res, "{}, ", self.format_val(elt))) 1131 | .unwrap(); 1132 | write!(&mut res, "{}", self.format_val(last_elt)) 1133 | }); 1134 | write!(&mut res, "]").unwrap(); 1135 | res 1136 | } 1137 | } 1138 | } 1139 | } 1140 | --------------------------------------------------------------------------------