Simplify "run" function

This commit is contained in:
Jeff 2024-08-11 21:42:16 -04:00
parent de30f241a8
commit f2c0786bfb
2 changed files with 35 additions and 80 deletions

View File

@ -10,12 +10,10 @@ use crate::{
ValueError, ValueError,
}; };
pub fn run<'src>( pub fn run(source: &str) -> Result<Option<Value>, DustError> {
source: &'src str,
context: &mut Context,
) -> Result<Option<Value>, DustError<'src>> {
let abstract_syntax_tree = parse(source)?; let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree, context); let mut context = Context::new();
let mut analyzer = Analyzer::new(&abstract_syntax_tree, &mut context);
analyzer analyzer
.analyze() .analyze()
@ -26,7 +24,7 @@ pub fn run<'src>(
let mut vm = Vm::new(abstract_syntax_tree); let mut vm = Vm::new(abstract_syntax_tree);
vm.run(context) vm.run(&mut context)
.map_err(|vm_error| DustError::VmError { vm_error, source }) .map_err(|vm_error| DustError::VmError { vm_error, source })
} }
@ -629,223 +627,181 @@ mod tests {
fn to_string() { fn to_string() {
let input = "to_string(42)"; let input = "to_string(42)";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::string("42".to_string()))));
run(input, &mut Context::new()),
Ok(Some(Value::string("42".to_string())))
);
} }
#[test] #[test]
fn r#if() { fn r#if() {
let input = "if true { 1 }"; let input = "if true { 1 }";
assert_eq!(run(input, &mut Context::new()), Ok(None)); assert_eq!(run(input), Ok(None));
} }
#[test] #[test]
fn if_else() { fn if_else() {
let input = "if false { 1 } else { 2 }"; let input = "if false { 1 } else { 2 }";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::integer(2))));
} }
#[test] #[test]
fn if_else_if() { fn if_else_if() {
let input = "if false { 1 } else if true { 2 }"; let input = "if false { 1 } else if true { 2 }";
assert_eq!(run(input, &mut Context::new()), Ok(None)); assert_eq!(run(input), Ok(None));
} }
#[test] #[test]
fn if_else_if_else() { fn if_else_if_else() {
let input = "if false { 1 } else if false { 2 } else { 3 }"; let input = "if false { 1 } else if false { 2 } else { 3 }";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::integer(3))));
} }
#[test] #[test]
fn while_loop() { fn while_loop() {
let input = "x = 0; while x < 5 { x += 1; } x"; let input = "x = 0; while x < 5 { x += 1; } x";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(5)))); assert_eq!(run(input), Ok(Some(Value::integer(5))));
} }
#[test] #[test]
fn add_assign() { fn add_assign() {
let input = "x = 1; x += 1; x"; let input = "x = 1; x += 1; x";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::integer(2))));
} }
#[test] #[test]
fn or() { fn or() {
let input = "true || false"; let input = "true || false";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn map_equal() { fn map_equal() {
let input = "{ y = 'foo' } == { y = 'foo' }"; let input = "{ y = 'foo' } == { y = 'foo' }";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn integer_equal() { fn integer_equal() {
let input = "42 == 42"; let input = "42 == 42";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn modulo() { fn modulo() {
let input = "42 % 2"; let input = "42 % 2";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(0)))); assert_eq!(run(input), Ok(Some(Value::integer(0))));
} }
#[test] #[test]
fn divide() { fn divide() {
let input = "42 / 2"; let input = "42 / 2";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::integer(21))));
run(input, &mut Context::new()),
Ok(Some(Value::integer(21)))
);
} }
#[test] #[test]
fn less_than() { fn less_than() {
let input = "2 < 3"; let input = "2 < 3";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn less_than_or_equal() { fn less_than_or_equal() {
let input = "42 <= 42"; let input = "42 <= 42";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn greater_than() { fn greater_than() {
let input = "2 > 3"; let input = "2 > 3";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(false))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(false)))
);
} }
#[test] #[test]
fn greater_than_or_equal() { fn greater_than_or_equal() {
let input = "42 >= 42"; let input = "42 >= 42";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn integer_saturating_add() { fn integer_saturating_add() {
let input = "9223372036854775807 + 1"; let input = "9223372036854775807 + 1";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::integer(i64::MAX))));
run(input, &mut Context::new()),
Ok(Some(Value::integer(i64::MAX)))
);
} }
#[test] #[test]
fn integer_saturating_sub() { fn integer_saturating_sub() {
let input = "-9223372036854775808 - 1"; let input = "-9223372036854775808 - 1";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::integer(i64::MIN))));
run(input, &mut Context::new()),
Ok(Some(Value::integer(i64::MIN)))
);
} }
#[test] #[test]
fn multiply() { fn multiply() {
let input = "2 * 3"; let input = "2 * 3";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(6)))); assert_eq!(run(input), Ok(Some(Value::integer(6))));
} }
#[test] #[test]
fn boolean() { fn boolean() {
let input = "true"; let input = "true";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn is_even() { fn is_even() {
let input = "is_even(42)"; let input = "is_even(42)";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(true))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(true)))
);
} }
#[test] #[test]
fn is_odd() { fn is_odd() {
let input = "is_odd(42)"; let input = "is_odd(42)";
assert_eq!( assert_eq!(run(input), Ok(Some(Value::boolean(false))));
run(input, &mut Context::new()),
Ok(Some(Value::boolean(false)))
);
} }
#[test] #[test]
fn length() { fn length() {
let input = "length([1, 2, 3])"; let input = "length([1, 2, 3])";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::integer(3))));
} }
#[test] #[test]
fn list_access() { fn list_access() {
let input = "[1, 2, 3].1"; let input = "[1, 2, 3].1";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::integer(2))));
} }
#[test] #[test]
fn add() { fn add() {
let input = "1 + 2"; let input = "1 + 2";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::integer(3))));
} }
#[test] #[test]
fn add_multiple() { fn add_multiple() {
let input = "1 + 2 + 3"; let input = "1 + 2 + 3";
assert_eq!(run(input, &mut Context::new()), Ok(Some(Value::integer(6)))); assert_eq!(run(input), Ok(Some(Value::integer(6))));
} }
} }

View File

@ -1,7 +1,7 @@
use std::fs::read_to_string; use std::fs::read_to_string;
use clap::Parser; use clap::Parser;
use dust_lang::{run, Context}; use dust_lang::run;
#[derive(Parser)] #[derive(Parser)]
struct Cli { struct Cli {
@ -13,21 +13,20 @@ struct Cli {
fn main() { fn main() {
let args = Cli::parse(); let args = Cli::parse();
let mut context = Context::new();
if let Some(command) = &args.command { if let Some(command) = &args.command {
run_and_display_errors(command, &mut context); run_and_display_errors(command);
} else if let Some(path) = &args.path { } else if let Some(path) = &args.path {
let source = read_to_string(path).expect("Failed to read file"); let source = read_to_string(path).expect("Failed to read file");
run_and_display_errors(&source, &mut context) run_and_display_errors(&source)
} else { } else {
panic!("No command or path provided"); panic!("No command or path provided");
}; };
} }
fn run_and_display_errors(source: &str, variables: &mut Context) { fn run_and_display_errors(source: &str) {
match run(source, variables) { match run(source) {
Ok(return_value) => { Ok(return_value) => {
if let Some(value) = return_value { if let Some(value) = return_value {
println!("{}", value); println!("{}", value);