closure
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// Test script to verify error positioning
|
||||
"no"();
|
||||
var a := 5;
|
||||
var b := "hello";
|
||||
print 0;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
closure :: fn() do
|
||||
value := "Closure";
|
||||
internal :: fn() do
|
||||
print value;
|
||||
return value;
|
||||
end
|
||||
return internal;
|
||||
end
|
||||
|
||||
internal := closure();
|
||||
internal();
|
||||
@@ -6,23 +6,26 @@
|
||||
//func_name :: fn(param: Number, param2: String) {param is Int} do
|
||||
func_name :: fn(param: Int, param2: String) do
|
||||
print param;
|
||||
cavallo := 5;
|
||||
print cavallo;
|
||||
while cavallo < 10 do
|
||||
cavallo = cavallo + 1;
|
||||
print cavallo;
|
||||
print param2;
|
||||
while param < param2 do
|
||||
param = param + 1;
|
||||
print param;
|
||||
print param2;
|
||||
//break;
|
||||
end
|
||||
if True then do
|
||||
if False then do
|
||||
print "this shoul be stop";
|
||||
return False;
|
||||
return "Hahahaha";
|
||||
end
|
||||
print "this shoud be un other stop";
|
||||
return 42;
|
||||
//return 42;
|
||||
for i := 11; i <= 21; i = i + 1; do
|
||||
print i;
|
||||
print "hello";
|
||||
break;
|
||||
end
|
||||
|
||||
return False or True;
|
||||
end
|
||||
|
||||
func_name(1,2)
|
||||
func_name(1,20)
|
||||
|
||||
@@ -11,10 +11,20 @@ end
|
||||
|
||||
function_fatcoty_factory :: fn() do
|
||||
print "Function Factory Factory";
|
||||
function_factory
|
||||
return function_factory;
|
||||
end
|
||||
|
||||
//function();
|
||||
//function_factory()();
|
||||
function_fatcoty_factory()()();
|
||||
//function_fatcoty_factory()()();
|
||||
clock()
|
||||
|
||||
closure :: fn() do
|
||||
value = "Closure";
|
||||
internal :: fn() do
|
||||
print value;
|
||||
end
|
||||
return internal;
|
||||
end
|
||||
|
||||
closure()
|
||||
|
||||
+73
-50
@@ -33,7 +33,15 @@ where
|
||||
impl EvaluateInterpreter<Expr> for Interpreter {
|
||||
fn evaluate(&mut self, expr: Expr) -> LoxResult<BaseValue> {
|
||||
match expr {
|
||||
Expr::Literal { value } => Ok(value),
|
||||
Expr::Literal { value } => match value {
|
||||
BaseValue::Function(mut func) => {
|
||||
func.closure = Some(self.enviorment.clone());
|
||||
println!("Closure created");
|
||||
println!("current enviorment: {:?}", self.enviorment);
|
||||
Ok(BaseValue::Function(func))
|
||||
}
|
||||
_ => Ok(value),
|
||||
},
|
||||
Expr::Identifier { name } => self.enviorment.get(&name),
|
||||
Expr::Binary {
|
||||
left,
|
||||
@@ -120,15 +128,34 @@ impl Interpreter {
|
||||
match function {
|
||||
BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)),
|
||||
BaseValue::Function(func) => {
|
||||
func.parameters
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, par)| {
|
||||
let value = evaluated_arguments.get(index).unwrap();
|
||||
self.enviorment.declare(par.0.clone(), value.clone())
|
||||
})
|
||||
.collect::<LoxResult<Vec<BaseValue>>>()?;
|
||||
self.evaluate(func.body)
|
||||
// Save the current environment
|
||||
let saved_env = self.enviorment.clone();
|
||||
|
||||
// If the function captured a closure, use it as the base environment
|
||||
if let Some(closure_env) = func.closure {
|
||||
self.enviorment = closure_env;
|
||||
}
|
||||
|
||||
// Push a new scope for the function's parameters
|
||||
self.enviorment.push_new_scope();
|
||||
|
||||
// Declare parameters in the new scope
|
||||
for (index, par) in func.parameters.iter().enumerate() {
|
||||
let value = evaluated_arguments.get(index).unwrap();
|
||||
self.enviorment.declare(par.0.clone(), value.clone())?;
|
||||
}
|
||||
|
||||
// Execute the function body
|
||||
let result = match self.evaluate(func.body) {
|
||||
Ok(value) => Ok(value),
|
||||
Err(LoxError::Return { value, .. }) => Ok(value),
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
|
||||
// Restore the original environment (cleanup is automatic)
|
||||
self.enviorment = saved_env;
|
||||
|
||||
result
|
||||
}
|
||||
_ => runtime_error(
|
||||
source_slice.clone(),
|
||||
@@ -194,21 +221,11 @@ impl Interpreter {
|
||||
name, initializer, ..
|
||||
} => {
|
||||
let value = match initializer {
|
||||
Some(expr_node) => match &expr_node.node {
|
||||
Expr::Literal { value } => {
|
||||
if value.is_callable() {
|
||||
value.clone()
|
||||
} else {
|
||||
value.clone()
|
||||
}
|
||||
}
|
||||
_ => self.evaluate(*expr_node)?,
|
||||
},
|
||||
Some(expr_node) => self.evaluate(*expr_node)?,
|
||||
None => BaseValue::Nil,
|
||||
};
|
||||
self.enviorment.declare(name.clone(), value)
|
||||
}
|
||||
|
||||
Stmt::VarAssigment { name, value, .. } => {
|
||||
let result = self.evaluate(*value)?;
|
||||
self.enviorment.set(name.clone(), result)
|
||||
@@ -223,10 +240,18 @@ impl Interpreter {
|
||||
Stmt::While {
|
||||
condition, body, ..
|
||||
} => {
|
||||
let mut ret = BaseValue::Nil;
|
||||
while self.evaluate(*condition.clone())?.is_truthy() {
|
||||
self.evaluate(*body.clone())?;
|
||||
match self.evaluate(*body.clone()) {
|
||||
Ok(val) => ret = val,
|
||||
Err(LoxError::Return { value, .. }) => {
|
||||
ret = value;
|
||||
break;
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
}
|
||||
Ok(BaseValue::Nil)
|
||||
Ok(ret)
|
||||
}
|
||||
Stmt::For {
|
||||
variable,
|
||||
@@ -235,7 +260,6 @@ impl Interpreter {
|
||||
body,
|
||||
..
|
||||
} => {
|
||||
self.enviorment.push_new_scope();
|
||||
let source_slice = variable.source_slice.clone();
|
||||
let val = self.evaluate(*variable)?;
|
||||
if !matches!(val, BaseValue::Number(..)) {
|
||||
@@ -243,7 +267,14 @@ impl Interpreter {
|
||||
}
|
||||
let mut ret = BaseValue::Nil;
|
||||
while self.evaluate(*condition.clone())?.is_truthy() {
|
||||
ret = self.evaluate(*body.clone())?;
|
||||
match self.evaluate(*body.clone()) {
|
||||
Ok(val) => ret = val,
|
||||
Err(LoxError::Return { value, .. }) => {
|
||||
ret = value;
|
||||
break;
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
self.evaluate(*increment.clone())?;
|
||||
}
|
||||
|
||||
@@ -294,34 +325,26 @@ impl Interpreter {
|
||||
|
||||
fn evaluate_block(&mut self, statements: Vec<AstNode<Stmt>>) -> LoxResult<BaseValue> {
|
||||
self.enviorment.push_new_scope();
|
||||
let (elements, final_expr) = match statements.split_last() {
|
||||
Some((stmt, body)) => match &stmt.node {
|
||||
Stmt::Expression { expression, .. } => (body, Some(expression)),
|
||||
Stmt::Return { expression, .. } => (body, Some(expression)),
|
||||
_ => (statements.as_slice(), None),
|
||||
},
|
||||
|
||||
None => {
|
||||
(&[][..], None) // Blocco vuoto
|
||||
}
|
||||
};
|
||||
|
||||
// Ora elements è sempre disponibile
|
||||
for statement in elements.iter() {
|
||||
self.evaluate((*statement).clone())?;
|
||||
}
|
||||
let mut result = Ok(BaseValue::Nil);
|
||||
for statement in statements.iter() {
|
||||
let node = statement.node.clone();
|
||||
match node {
|
||||
Stmt::Return { expression, .. } => {
|
||||
let value = self.evaluate(*expression)?;
|
||||
|
||||
// Gestisci l'espressione finale se presente
|
||||
match final_expr {
|
||||
Some(expr) => {
|
||||
let res = self.evaluate(*expr.clone());
|
||||
self.enviorment.pop_scope();
|
||||
res
|
||||
}
|
||||
None => {
|
||||
self.enviorment.pop_scope();
|
||||
Ok(BaseValue::Nil)
|
||||
}
|
||||
result = Err(LoxError::Return {
|
||||
source_slice: statement.source_slice.clone(),
|
||||
value: value,
|
||||
return_label: "Hi".to_string(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
_ => result = self.evaluate((*statement).clone()),
|
||||
};
|
||||
}
|
||||
self.enviorment.pop_scope();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -138,6 +138,7 @@ pub enum Stmt {
|
||||
},
|
||||
Return {
|
||||
expression: Box<AstNode<Expr>>,
|
||||
label: String,
|
||||
return_value: Box<BaseValue>,
|
||||
},
|
||||
Block {
|
||||
@@ -219,7 +220,12 @@ impl Display for Stmt {
|
||||
Stmt::Return {
|
||||
expression,
|
||||
return_value,
|
||||
} => write!(f, "Return({}) -> {:?};", expression.node, return_value),
|
||||
label,
|
||||
} => write!(
|
||||
f,
|
||||
"Return({}, {}) -> {:?};",
|
||||
expression.node, label, return_value
|
||||
),
|
||||
Stmt::Block {
|
||||
statements,
|
||||
label,
|
||||
@@ -327,7 +333,12 @@ impl Debug for Stmt {
|
||||
Stmt::Return {
|
||||
expression,
|
||||
return_value,
|
||||
} => write!(f, "Return({:?}) -> {:?};", expression.node, return_value),
|
||||
label,
|
||||
} => write!(
|
||||
f,
|
||||
"Return({:?}, {}) -> {:?};",
|
||||
expression.node, label, return_value
|
||||
),
|
||||
Stmt::Block {
|
||||
label,
|
||||
statements,
|
||||
|
||||
@@ -26,6 +26,11 @@ pub enum LoxError {
|
||||
expected: String,
|
||||
found: String,
|
||||
},
|
||||
Return {
|
||||
source_slice: SourceSlice,
|
||||
value: BaseValue,
|
||||
return_label: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Configuration for error display formatting
|
||||
@@ -84,6 +89,13 @@ impl LoxError {
|
||||
} => {
|
||||
format!("expected {}, found {}", expected, found)
|
||||
}
|
||||
LoxError::Return {
|
||||
value,
|
||||
return_label,
|
||||
..
|
||||
} => {
|
||||
format!("return value: {} and label: {}", value, return_label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +106,11 @@ impl LoxError {
|
||||
LoxError::ParseError { source_slice, .. } => Some(source_slice.clone()),
|
||||
LoxError::IoError { .. } => None,
|
||||
LoxError::TypeMismatch { source_slice, .. } => Some(source_slice.clone()),
|
||||
LoxError::Return {
|
||||
value,
|
||||
return_label,
|
||||
..
|
||||
} => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +121,7 @@ impl LoxError {
|
||||
LoxError::ParseError { .. } => "parse error",
|
||||
LoxError::IoError { .. } => "io error",
|
||||
LoxError::TypeMismatch { .. } => "type error",
|
||||
LoxError::Return { .. } => "return error",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,6 +414,20 @@ impl fmt::Display for LoxError {
|
||||
found
|
||||
)
|
||||
}
|
||||
LoxError::Return {
|
||||
value,
|
||||
return_label,
|
||||
source_slice,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"Return error at {}:{}: value `{}`, label `{}`",
|
||||
source_slice.start_position.line + 1,
|
||||
source_slice.start_position.column + 1,
|
||||
value,
|
||||
return_label
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ fn get_keyword_token(word: &str) -> Option<TokenType> {
|
||||
"in" => Some(TokenType::In),
|
||||
"print" => Some(TokenType::Print),
|
||||
"return" => Some(TokenType::Return),
|
||||
"break" => Some(TokenType::Break),
|
||||
"super" => Some(TokenType::Super),
|
||||
"this" => Some(TokenType::This),
|
||||
"true" => Some(TokenType::True),
|
||||
|
||||
+51
-21
@@ -2,7 +2,7 @@ use crate::{
|
||||
common::{
|
||||
ast::{AstNode, Expr, Stmt},
|
||||
base_value::{BaseValue, LoxFunction},
|
||||
lox_result::{parse_error, runtime_error, LoxResult},
|
||||
lox_result::{parse_error, runtime_error, LoxError, LoxResult},
|
||||
},
|
||||
frontend::{
|
||||
source_registry::SourceSlice,
|
||||
@@ -24,7 +24,7 @@ impl Parser {
|
||||
let mut statements = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
while !self.is_at_end() {
|
||||
match self.statement() {
|
||||
match self.statement(None) {
|
||||
Ok(stmt) => {
|
||||
statements.push(stmt.clone());
|
||||
}
|
||||
@@ -42,11 +42,12 @@ impl Parser {
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
match (&self.peek().token_type, &self.peek_next().token_type) {
|
||||
(TokenType::Print, _) => self.print_statement(),
|
||||
(TokenType::Return, _) => self.return_statement(),
|
||||
(TokenType::StartBlock, _) => self.block_statement(),
|
||||
(TokenType::Return, _) => self.return_statement(label),
|
||||
(TokenType::Break, _) => self.return_statement(Some("loop".to_string())),
|
||||
(TokenType::StartBlock, _) => self.block_statement(label),
|
||||
(TokenType::Var, TokenType::Identifier) => {
|
||||
self.advance();
|
||||
self.var_statement()
|
||||
@@ -68,11 +69,7 @@ impl Parser {
|
||||
let condition = self.expression()?;
|
||||
self.consume(TokenType::Semicolon, "Expected ';' after for condition")?;
|
||||
let increment = self.assignment_statement()?;
|
||||
|
||||
self.consume(TokenType::StartBlock, "Expected 'do' after for range")?;
|
||||
|
||||
let body = self.statement()?;
|
||||
self.consume(TokenType::EndBlock, "Expected 'end' after for body")?;
|
||||
let body = self.statement(Some("loop".to_string()))?;
|
||||
|
||||
let end_slice = self.previous().source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
@@ -118,7 +115,7 @@ impl Parser {
|
||||
// self.advance();
|
||||
// self.consume(TokenType::In, "Expect 'in' after for variable.")?;
|
||||
// let iterable = self.expression()?;
|
||||
// let body = self.statement()?;
|
||||
// let body = self.statement(None)?;
|
||||
// let end_slice = body.source_slice.clone();
|
||||
// let combined_slice = SourceSlice::from_positions(
|
||||
// start_slice.source_id,
|
||||
@@ -139,7 +136,7 @@ impl Parser {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let condition = self.expression()?;
|
||||
let body = self.statement()?;
|
||||
let body = self.statement(Some("loop".to_string()))?;
|
||||
let end_slice = body.source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
start_slice.source_id,
|
||||
@@ -161,7 +158,7 @@ impl Parser {
|
||||
self.advance(); // consume 'if'
|
||||
let condition = self.expression()?;
|
||||
self.consume(TokenType::Then, "Expect 'then' after if condition.")?;
|
||||
let then_branch = self.statement()?;
|
||||
let then_branch = self.statement(None)?;
|
||||
let mut elif_branches = Vec::new();
|
||||
let mut last_slice = then_branch.source_slice.clone();
|
||||
|
||||
@@ -169,14 +166,14 @@ impl Parser {
|
||||
self.advance(); // consume 'elif'
|
||||
let elif_condition = self.expression()?;
|
||||
self.consume(TokenType::Then, "Expect 'then' after elif condition.")?;
|
||||
let elif_branch = self.statement()?;
|
||||
let elif_branch = self.statement(None)?;
|
||||
last_slice = elif_branch.source_slice.clone();
|
||||
elif_branches.push((Box::new(elif_condition), Box::new(elif_branch)));
|
||||
}
|
||||
|
||||
let else_branch = if self.peek().token_type == TokenType::Else {
|
||||
self.advance(); // consume 'else'
|
||||
let else_stmt = self.statement()?;
|
||||
let else_stmt = self.statement(None)?;
|
||||
last_slice = else_stmt.source_slice.clone();
|
||||
Some(Box::new(else_stmt))
|
||||
} else {
|
||||
@@ -259,7 +256,7 @@ impl Parser {
|
||||
self.consume(TokenType::RightBrace, "Expected '}' after guard expression")?;
|
||||
}
|
||||
|
||||
let body = self.statement()?;
|
||||
let body = self.statement(None)?;
|
||||
let node = AstNode {
|
||||
node: Expr::Literal {
|
||||
value: BaseValue::Function(LoxFunction {
|
||||
@@ -370,12 +367,13 @@ impl Parser {
|
||||
))
|
||||
}
|
||||
|
||||
fn block_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn block_statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let mut statements = Vec::new();
|
||||
|
||||
while self.peek().token_type != TokenType::EndBlock && !self.is_at_end() {
|
||||
let stmt = self.statement()?;
|
||||
let stmt = self.statement(label.clone())?;
|
||||
let should_break = matches!(stmt.node, Stmt::Expression { .. });
|
||||
statements.push(stmt);
|
||||
if should_break {
|
||||
@@ -389,10 +387,15 @@ impl Parser {
|
||||
start_slice.start_position,
|
||||
end_slice.end_position,
|
||||
);
|
||||
let label_str = if let Some(label) = label {
|
||||
label
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
Ok(AstNode::new(
|
||||
Stmt::Block {
|
||||
statements: Box::new(statements),
|
||||
label: String::default(),
|
||||
label: label_str,
|
||||
return_value: Box::new(BaseValue::Nil),
|
||||
},
|
||||
combined_slice,
|
||||
@@ -429,10 +432,31 @@ impl Parser {
|
||||
))
|
||||
}
|
||||
|
||||
fn return_statement(&mut self) -> LoxResult<AstNode<Stmt>> {
|
||||
fn return_statement(&mut self, label: Option<String>) -> LoxResult<AstNode<Stmt>> {
|
||||
let start_slice = self.peek().source_slice.clone();
|
||||
self.advance();
|
||||
let expr = self.expression()?;
|
||||
let expr = match self.expression() {
|
||||
Ok(expr) => expr,
|
||||
Err(LoxError::ParseError {
|
||||
message,
|
||||
source_slice,
|
||||
}) => {
|
||||
if message == "Expect expression." {
|
||||
AstNode {
|
||||
node: Expr::Literal {
|
||||
value: BaseValue::Nil,
|
||||
},
|
||||
source_slice: start_slice.clone(),
|
||||
}
|
||||
} else {
|
||||
return Err(LoxError::ParseError {
|
||||
message,
|
||||
source_slice,
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let semicolon = self.consume(TokenType::Semicolon, "Expect ';' after return value.")?;
|
||||
let end_slice = semicolon.source_slice.clone();
|
||||
let combined_slice = SourceSlice::from_positions(
|
||||
@@ -440,10 +464,16 @@ impl Parser {
|
||||
start_slice.start_position,
|
||||
end_slice.end_position,
|
||||
);
|
||||
let label_str = if let Some(label) = label {
|
||||
label
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
Ok(AstNode::new(
|
||||
Stmt::Return {
|
||||
expression: Box::new(expr),
|
||||
return_value: Box::new(BaseValue::Nil),
|
||||
label: label_str,
|
||||
},
|
||||
combined_slice,
|
||||
))
|
||||
|
||||
@@ -57,6 +57,7 @@ pub enum TokenType {
|
||||
Is,
|
||||
Print,
|
||||
Return,
|
||||
Break,
|
||||
Super,
|
||||
This,
|
||||
Var,
|
||||
@@ -92,6 +93,7 @@ impl fmt::Display for TokenType {
|
||||
TokenType::Or => write!(f, "or"),
|
||||
TokenType::Print => write!(f, "print"),
|
||||
TokenType::Return => write!(f, "return"),
|
||||
TokenType::Break => write!(f, "break"),
|
||||
TokenType::Super => write!(f, "super"),
|
||||
TokenType::This => write!(f, "this"),
|
||||
TokenType::Var => write!(f, "var"),
|
||||
|
||||
@@ -190,6 +190,7 @@ impl Token {
|
||||
TokenType::Or => "OR",
|
||||
TokenType::Print => "PRINT",
|
||||
TokenType::Return => "RETURN",
|
||||
TokenType::Break => "BREAK",
|
||||
TokenType::Super => "SUPER",
|
||||
TokenType::This => "THIS",
|
||||
TokenType::Var => "VAR",
|
||||
@@ -232,6 +233,7 @@ impl Token {
|
||||
| TokenType::Or
|
||||
| TokenType::Print
|
||||
| TokenType::Return
|
||||
| TokenType::Break
|
||||
| TokenType::Super
|
||||
| TokenType::This
|
||||
| TokenType::Var
|
||||
|
||||
+18
-92
@@ -30,109 +30,35 @@ fn main() -> LoxResult<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let (stage, file_path, debug) = parse_args(&args);
|
||||
println!("running {file_path:?}");
|
||||
let mut lox = LoxInterpreter::new(debug);
|
||||
|
||||
let _ = match file_path {
|
||||
let res = match file_path {
|
||||
Some(path) => lox.run_file(&path, stage),
|
||||
None => lox.run_prompt(stage),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
res
|
||||
}
|
||||
|
||||
fn parse_args(args: &[String]) -> (ExecutionStage, Option<String>, bool) {
|
||||
if args.len() == 1 {
|
||||
// Solo il nome del programma: modalità interattiva completa
|
||||
(ExecutionStage::Full, None, false)
|
||||
} else if args.len() == 2 {
|
||||
// Un argomento: potrebbe essere file o flag
|
||||
let arg = &args[1];
|
||||
if arg == "--tokens" || arg == "--ast" || arg == "--full" || arg == "--debug" {
|
||||
// Flag senza file: modalità interattiva
|
||||
let stage = match arg.as_str() {
|
||||
"--tokens" => ExecutionStage::Tokens,
|
||||
"--ast" => ExecutionStage::Ast,
|
||||
"--full" => ExecutionStage::Full,
|
||||
"--debug" => ExecutionStage::Full,
|
||||
_ => ExecutionStage::Full,
|
||||
};
|
||||
let debug = arg == "--debug";
|
||||
(stage, None, debug)
|
||||
} else {
|
||||
// File senza flag: esecuzione completa del file
|
||||
(ExecutionStage::Full, Some(arg.clone()), false)
|
||||
println!("{args:?}");
|
||||
|
||||
let mut stage = ExecutionStage::Full;
|
||||
let mut file_path = None;
|
||||
let mut debug = false;
|
||||
|
||||
for arg in args.iter().skip(1) {
|
||||
match arg.as_str() {
|
||||
"-t" | "--tokens" => stage = ExecutionStage::Tokens,
|
||||
"-a" | "--ast" => stage = ExecutionStage::Ast,
|
||||
"-f" | "--full" => stage = ExecutionStage::Full,
|
||||
"-d" | "--debug" => debug = true,
|
||||
_ => file_path = Some(arg.clone()),
|
||||
}
|
||||
} else if args.len() == 3 {
|
||||
// Due argomenti: potrebbero essere flag + file o due flag
|
||||
let mut debug = false;
|
||||
let mut stage = ExecutionStage::Full;
|
||||
let mut file_path = None;
|
||||
|
||||
for arg in &args[1..3] {
|
||||
if arg == "--debug" {
|
||||
debug = true;
|
||||
} else if arg == "--tokens" || arg == "--ast" || arg == "--full" {
|
||||
stage = match arg.as_str() {
|
||||
"--tokens" => ExecutionStage::Tokens,
|
||||
"--ast" => ExecutionStage::Ast,
|
||||
"--full" => ExecutionStage::Full,
|
||||
_ => ExecutionStage::Full,
|
||||
};
|
||||
} else if !arg.starts_with("--") {
|
||||
file_path = Some(arg.clone());
|
||||
} else {
|
||||
eprintln!(
|
||||
"Unknown flag: {}. Use --tokens, --ast, --full, or --debug",
|
||||
arg
|
||||
);
|
||||
eprintln!(
|
||||
"Usage: {} [--tokens|--ast|--full] [--debug] [script]",
|
||||
args[0]
|
||||
);
|
||||
std::process::exit(64);
|
||||
}
|
||||
}
|
||||
|
||||
(stage, file_path, debug)
|
||||
} else if args.len() == 4 {
|
||||
// Tre argomenti: flag + flag + file
|
||||
let mut debug = false;
|
||||
let mut stage = ExecutionStage::Full;
|
||||
let mut file_path = None;
|
||||
|
||||
for arg in &args[1..4] {
|
||||
if arg == "--debug" {
|
||||
debug = true;
|
||||
} else if arg == "--tokens" || arg == "--ast" || arg == "--full" {
|
||||
stage = match arg.as_str() {
|
||||
"--tokens" => ExecutionStage::Tokens,
|
||||
"--ast" => ExecutionStage::Ast,
|
||||
"--full" => ExecutionStage::Full,
|
||||
_ => ExecutionStage::Full,
|
||||
};
|
||||
} else if !arg.starts_with("--") {
|
||||
file_path = Some(arg.clone());
|
||||
} else {
|
||||
eprintln!(
|
||||
"Unknown flag: {}. Use --tokens, --ast, --full, or --debug",
|
||||
arg
|
||||
);
|
||||
eprintln!(
|
||||
"Usage: {} [--tokens|--ast|--full] [--debug] [script]",
|
||||
args[0]
|
||||
);
|
||||
std::process::exit(64);
|
||||
}
|
||||
}
|
||||
|
||||
(stage, file_path, debug)
|
||||
} else {
|
||||
eprintln!(
|
||||
"Usage: {} [--tokens|--ast|--full] [--debug] [script]",
|
||||
args[0]
|
||||
);
|
||||
std::process::exit(64);
|
||||
}
|
||||
|
||||
(stage, file_path, debug)
|
||||
}
|
||||
|
||||
struct LoxInterpreter {
|
||||
|
||||
Reference in New Issue
Block a user