Initialize Rust implementation of Lox interpreter

This initial commit sets up the basic structure for a Rust
implementation of the Lox interpreter, including:

- Lexer for tokenizing source code - Parser for building AST - Basic
interpreter functionality - Environment for variable storage

The core components include source tracking, error handling, and basic
expression evaluation.
This commit is contained in:
Giulio Agostini
2025-10-03 19:07:12 +02:00
commit a7df45dc72
18 changed files with 2710 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
mod backend;
mod frontend;
mod logging;
mod prompt;
mod result;
use crate::{
backend::{
environment::Environment,
interpreter::{EvaluateInterpreter, Interpreter},
},
frontend::{
lexer::Lexer,
parser::Parser,
source_registry::{SourceFile, SourceId, SourcePosition, SourceRegistry, SourceSlice},
},
prompt::prompt_lines,
result::{LoxError, LoxResult},
};
use std::fs;
use std::{env, error::Error};
fn main() -> LoxResult<()> {
let args: Vec<String> = env::args().collect();
let mut lox = LoxInterpreter::new();
if args.len() > 2 {
eprintln!("Usage: {} [script]", args[0]);
std::process::exit(64);
} else if args.len() == 2 {
// Esegui file
lox.run_file(&args[1])?;
} else {
// Modalità interattiva
lox.run_prompt()?;
}
Ok(())
}
struct LoxInterpreter {
source_registry: SourceRegistry,
}
impl LoxInterpreter {
pub fn new() -> Self {
LoxInterpreter {
source_registry: SourceRegistry::new(),
}
}
// ✅ Pipeline funzionale per file
fn run_file(&mut self, path: &str) -> LoxResult<()> {
fs::read_to_string(path)
.map_err(|e| LoxError::IoError {
message: e.to_string(),
})
.and_then(|source| self.source_registry.add_source_string(source))
.and_then(|source_id| self.process_source(source_id))
.map(|result| println!("file {}", result))
}
// ✅ Pipeline funzionale per prompt
fn run_prompt(&mut self) -> LoxResult<()> {
println!("Lox REPL - Type 'exit' to quit");
prompt_lines(|source| self.source_registry.add_source_string(source))
.for_each(|line| println!("hi: {}", line));
Ok(())
}
fn process_source(&self, source_id: SourceId) -> LoxResult<String> {
let mut lexer = Lexer::new(
self.source_registry.get_by_id(source_id).content.clone(),
source_id,
);
let res = lexer
.scans_tokens()
.and_then(|tokens| Parser::new(tokens).parse())
.and_then(|asts| {
// println!("asts: {:?}", asts);
Ok(asts)
})
.and_then(|stmts| {
let mut env = Environment::new();
let mut interpreter = Interpreter::new(&mut env);
let mut result = None;
for stmt in stmts {
result = Some(interpreter.interpret(stmt)?);
}
match result {
Some(res) => Ok(res),
_ => Err(LoxError::RuntimeError {
source_slice: SourceSlice::default(),
message: "what?????".to_string(),
}),
}
})
.and_then(|result| Ok(format!("{}", result)))
.or_else(|err| {
err.print_with_context(&self.source_registry);
Err(err)
});
// println!("result {}", res);
res
}
}