add argument reading for lox
This commit is contained in:
parent
98dfbc8503
commit
97fdc89316
6 changed files with 60 additions and 8 deletions
|
@ -96,5 +96,6 @@ class Interpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var interpreter = Interpreter("bf/game_of_life.bf");
|
var bfScript = args(0);
|
||||||
|
var interpreter = Interpreter(bfScript);
|
||||||
interpreter.run();
|
interpreter.run();
|
||||||
|
|
|
@ -19,6 +19,9 @@ pub struct RunConfig {
|
||||||
/// Path to Lox source file.
|
/// Path to Lox source file.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
pub source: PathBuf,
|
pub source: PathBuf,
|
||||||
|
/// Arguments to pass to the Lox script (must be after '--').
|
||||||
|
#[arg(last = true)]
|
||||||
|
pub script_args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Available commands for the Lox interpreter
|
/// Available commands for the Lox interpreter
|
||||||
|
|
|
@ -60,12 +60,18 @@ pub struct Interpreter {
|
||||||
/// Default configuration for the interpreter, with builtin native functions.
|
/// Default configuration for the interpreter, with builtin native functions.
|
||||||
impl Default for Interpreter {
|
impl Default for Interpreter {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
Interpreter::new(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interpreter {
|
||||||
|
pub fn new(cli_args: Vec<String>) -> Self {
|
||||||
let env: Rc<RefCell<Environment>> = Default::default();
|
let env: Rc<RefCell<Environment>> = Default::default();
|
||||||
|
|
||||||
{
|
{
|
||||||
// add all native functions to global environment
|
// add all native functions to global environment
|
||||||
let mut env = env.borrow_mut();
|
let mut env = env.borrow_mut();
|
||||||
for (name, fun) in native_functions::all() {
|
for (name, fun) in native_functions::all(cli_args) {
|
||||||
env.define(name, fun);
|
env.define(name, fun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,9 +82,7 @@ impl Default for Interpreter {
|
||||||
locals: HashMap::new(),
|
locals: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Interpreter {
|
|
||||||
/// Execute a list of statements in sequence.
|
/// Execute a list of statements in sequence.
|
||||||
/// Log errors but continue execution.
|
/// Log errors but continue execution.
|
||||||
pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
|
pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
|
||||||
|
|
|
@ -53,9 +53,9 @@ pub enum RoxError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the source code in a file and scan it to tokens.
|
/// Read the source code in a file and scan it to tokens.
|
||||||
pub fn compile(source: &Path) -> Result<(), io::Error> {
|
pub fn compile(source: &Path, cli_args: Vec<String>) -> Result<(), io::Error> {
|
||||||
let input = fs::read_to_string(source)?;
|
let input = fs::read_to_string(source)?;
|
||||||
let mut interpreter = Interpreter::default();
|
let mut interpreter = Interpreter::new(cli_args);
|
||||||
|
|
||||||
run(&input, &mut interpreter);
|
run(&input, &mut interpreter);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ fn main() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = rox::compile(&compile_config.source) {
|
if let Err(e) = rox::compile(&compile_config.source, compile_config.script_args.clone())
|
||||||
|
{
|
||||||
error!(
|
error!(
|
||||||
"failed to compile {}: {}",
|
"failed to compile {}: {}",
|
||||||
&compile_config.source.to_string_lossy(),
|
&compile_config.source.to_string_lossy(),
|
||||||
|
|
|
@ -224,8 +224,47 @@ impl Callable for PromptAscii {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CliArgs {
|
||||||
|
cli_args: Vec<String>,
|
||||||
|
}
|
||||||
|
impl Callable for CliArgs {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"args".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arity(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(
|
||||||
|
&self,
|
||||||
|
_interpreter: &mut Interpreter,
|
||||||
|
args: Vec<Value>,
|
||||||
|
) -> Result<Value, CallingError> {
|
||||||
|
if args.len() != self.arity() {
|
||||||
|
return Err(CallingError::ArgumentMismatch(self.arity(), args.len()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let idx = args
|
||||||
|
.first()
|
||||||
|
.ok_or(CallingError::CallFailed("arg not readable".into()))?;
|
||||||
|
if let Value::Number(idx) = idx {
|
||||||
|
let idx: usize = idx.0 as usize;
|
||||||
|
Ok(self
|
||||||
|
.cli_args
|
||||||
|
.get(idx)
|
||||||
|
.map(|x| Value::String(x.clone()))
|
||||||
|
.unwrap_or(Value::Nil))
|
||||||
|
} else {
|
||||||
|
Err(CallingError::CallFailed(
|
||||||
|
"arg index must be a number".into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return all native functions available to the Lox interpreter
|
/// Return all native functions available to the Lox interpreter
|
||||||
pub fn all() -> Vec<(String, Value)> {
|
pub fn all(cli_args: Vec<String>) -> Vec<(String, Value)> {
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
"asciiOut".into(),
|
"asciiOut".into(),
|
||||||
|
@ -247,5 +286,9 @@ pub fn all() -> Vec<(String, Value)> {
|
||||||
"promptAscii".into(),
|
"promptAscii".into(),
|
||||||
Value::Callable((Rc::new(PromptAscii {}), CallableType::Function)),
|
Value::Callable((Rc::new(PromptAscii {}), CallableType::Function)),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"args".into(),
|
||||||
|
Value::Callable((Rc::new(CliArgs { cli_args }), CallableType::Function)),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue