mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 17:40:52 +01:00
Interpretation timeout
This commit is contained in:
parent
58bb2fd60f
commit
b7153d68b7
@ -12,15 +12,24 @@ pub struct Context<'a> {
|
||||
angle_unit: String,
|
||||
precision: u32,
|
||||
sum_n_value: Option<i128>,
|
||||
timeout: Option<u32>,
|
||||
start_time: std::time::SystemTime,
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
pub fn new(symbol_table: &'a mut SymbolTable, angle_unit: &str, precision: u32) -> Self {
|
||||
pub fn new(
|
||||
symbol_table: &'a mut SymbolTable,
|
||||
angle_unit: &str,
|
||||
precision: u32,
|
||||
timeout: Option<u32>,
|
||||
) -> Self {
|
||||
Context {
|
||||
angle_unit: angle_unit.into(),
|
||||
symbol_table,
|
||||
precision,
|
||||
sum_n_value: None,
|
||||
timeout: timeout,
|
||||
start_time: std::time::SystemTime::now(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +91,12 @@ fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkNum, CalcErr
|
||||
}
|
||||
|
||||
fn eval_expr(context: &mut Context, expr: &Expr, unit: &str) -> Result<KalkNum, CalcError> {
|
||||
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
|
||||
if elapsed.as_secs() >= timeout as u64 {
|
||||
return Err(CalcError::TimedOut);
|
||||
}
|
||||
}
|
||||
|
||||
match expr {
|
||||
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right, unit),
|
||||
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr, unit),
|
||||
@ -352,7 +367,7 @@ mod tests {
|
||||
.insert(DEG_RAD_UNIT.clone())
|
||||
.insert(RAD_DEG_UNIT.clone());
|
||||
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION);
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION, None);
|
||||
context.interpret(vec![stmt])
|
||||
}
|
||||
|
||||
@ -428,8 +443,8 @@ mod tests {
|
||||
deg_symbol_table
|
||||
.insert(DEG_RAD_UNIT.clone())
|
||||
.insert(RAD_DEG_UNIT.clone());
|
||||
let mut rad_context = Context::new(&mut rad_symbol_table, "rad", PRECISION);
|
||||
let mut deg_context = Context::new(&mut deg_symbol_table, "deg", PRECISION);
|
||||
let mut rad_context = Context::new(&mut rad_symbol_table, "rad", PRECISION, None);
|
||||
let mut deg_context = Context::new(&mut deg_symbol_table, "deg", PRECISION, None);
|
||||
|
||||
assert!(cmp(
|
||||
rad_context
|
||||
@ -452,7 +467,7 @@ mod tests {
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
symbol_table.insert(var_decl("x", literal(1f64)));
|
||||
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION);
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION, None);
|
||||
assert_eq!(
|
||||
context.interpret(vec![stmt]).unwrap().unwrap().to_f64(),
|
||||
1f64
|
||||
@ -473,7 +488,7 @@ mod tests {
|
||||
fn test_var_decl() {
|
||||
let stmt = var_decl("x", literal(1f64));
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
Context::new(&mut symbol_table, "rad", PRECISION)
|
||||
Context::new(&mut symbol_table, "rad", PRECISION, None)
|
||||
.interpret(vec![stmt])
|
||||
.unwrap();
|
||||
|
||||
@ -492,7 +507,7 @@ mod tests {
|
||||
binary(var("x"), TokenKind::Plus, literal(2f64)),
|
||||
));
|
||||
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION);
|
||||
let mut context = Context::new(&mut symbol_table, "rad", PRECISION, None);
|
||||
assert_eq!(
|
||||
context.interpret(vec![stmt]).unwrap().unwrap().to_f64(),
|
||||
3f64
|
||||
|
@ -24,6 +24,7 @@ pub struct Context {
|
||||
pos: usize,
|
||||
symbol_table: SymbolTable,
|
||||
angle_unit: String,
|
||||
timeout: Option<u32>,
|
||||
/// This is true whenever the parser is currently parsing a unit declaration.
|
||||
/// It is necessary to keep track of this in order to know when to find (figure out) units that haven't been defined yet.
|
||||
/// Unit names are instead treated as variables.
|
||||
@ -43,6 +44,7 @@ impl Context {
|
||||
pos: 0,
|
||||
symbol_table: SymbolTable::new(),
|
||||
angle_unit: DEFAULT_ANGLE_UNIT.into(),
|
||||
timeout: None,
|
||||
parsing_unit_decl: false,
|
||||
unit_decl_base_unit: None,
|
||||
parsing_identifier_stmt: false,
|
||||
@ -60,6 +62,12 @@ impl Context {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_timeout(mut self, timeout: Option<u32>) -> Self {
|
||||
self.timeout = timeout;
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Context {
|
||||
@ -75,6 +83,7 @@ pub enum CalcError {
|
||||
InvalidNumberLiteral(String),
|
||||
InvalidOperator,
|
||||
InvalidUnit,
|
||||
TimedOut,
|
||||
UnexpectedToken(TokenKind, TokenKind),
|
||||
UndefinedFn(String),
|
||||
UndefinedVar(String),
|
||||
@ -95,8 +104,12 @@ pub fn eval(
|
||||
context.contains_equal_sign = input.contains("=");
|
||||
let statements = parse(context, input)?;
|
||||
|
||||
let mut interpreter =
|
||||
interpreter::Context::new(&mut context.symbol_table, &context.angle_unit, precision);
|
||||
let mut interpreter = interpreter::Context::new(
|
||||
&mut context.symbol_table,
|
||||
&context.angle_unit,
|
||||
precision,
|
||||
context.timeout,
|
||||
);
|
||||
interpreter.interpret(statements)
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,9 @@ fn default_action(context: &Context) {
|
||||
} else {
|
||||
get_env_angle_unit()
|
||||
};
|
||||
let mut parser_context = parser::Context::new().set_angle_unit(&angle_unit);
|
||||
let mut parser_context = parser::Context::new()
|
||||
.set_angle_unit(&angle_unit)
|
||||
.set_timeout(Some(5));
|
||||
let precision = context.int_flag("precision").unwrap_or(53isize) as u32;
|
||||
|
||||
if let Ok(input_file_path) = context.string_flag("input-file") {
|
||||
|
@ -35,6 +35,7 @@ fn print_calc_err(err: CalcError) {
|
||||
InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
|
||||
InvalidOperator => format!("Invalid operator."),
|
||||
InvalidUnit => format!("Invalid unit."),
|
||||
TimedOut => format!("Operation took too long."),
|
||||
UnexpectedToken(got, expected) => {
|
||||
format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user