mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-22 13:08:35 +01:00
Configurable max recursion depth
This commit is contained in:
parent
0573a1e9f4
commit
eccdf88b74
@ -28,6 +28,10 @@ fn main() {
|
|||||||
Flag::new("angle-unit", FlagType::String)
|
Flag::new("angle-unit", FlagType::String)
|
||||||
.description("Unit used for angles, either rad or deg. This can also be specified using an environment variable with the name 'ANGLE_UNIT'.")
|
.description("Unit used for angles, either rad or deg. This can also be specified using an environment variable with the name 'ANGLE_UNIT'.")
|
||||||
.alias("a"),
|
.alias("a"),
|
||||||
|
)
|
||||||
|
.flag(
|
||||||
|
Flag::new("max-recursion-depth", FlagType::Int)
|
||||||
|
.description("The maximum allowed recursion depth. This is used to avoid crashes."),
|
||||||
);
|
);
|
||||||
|
|
||||||
app.run(args);
|
app.run(args);
|
||||||
@ -54,6 +58,9 @@ fn default_action(context: &Context) {
|
|||||||
let precision = context
|
let precision = context
|
||||||
.int_flag("precision")
|
.int_flag("precision")
|
||||||
.unwrap_or(output::DEFAULT_PRECISION as isize) as u32;
|
.unwrap_or(output::DEFAULT_PRECISION as isize) as u32;
|
||||||
|
if let Ok(max_recursion_depth) = context.int_flag("max-recursion-depth") {
|
||||||
|
parser_context = parser_context.set_max_recursion_depth(max_recursion_depth as u32);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(input_file_path) = get_input_file_by_name("default") {
|
if let Some(input_file_path) = get_input_file_by_name("default") {
|
||||||
load_input_file(&input_file_path, precision, &mut parser_context);
|
load_input_file(&input_file_path, precision, &mut parser_context);
|
||||||
|
@ -318,7 +318,7 @@ fn analyse_binary(
|
|||||||
(Expr::Var(identifier), right) => {
|
(Expr::Var(identifier), right) => {
|
||||||
let right = analyse_expr(context, right)?;
|
let right = analyse_expr(context, right)?;
|
||||||
analyse_var(context, identifier, None, Some(right))
|
analyse_var(context, identifier, None, Some(right))
|
||||||
},
|
}
|
||||||
(left, right) => Ok(Expr::Binary(
|
(left, right) => Ok(Expr::Binary(
|
||||||
Box::new(analyse_expr(context, left)?),
|
Box::new(analyse_expr(context, left)?),
|
||||||
TokenKind::Power,
|
TokenKind::Power,
|
||||||
|
@ -9,7 +9,7 @@ use crate::symbol_table::SymbolTable;
|
|||||||
use crate::{as_number_or_zero, numerical};
|
use crate::{as_number_or_zero, numerical};
|
||||||
use crate::{float, prelude};
|
use crate::{float, prelude};
|
||||||
|
|
||||||
const DEFAULT_MAX_RECURSION_DEPTH: u32 = 128;
|
pub const DEFAULT_MAX_RECURSION_DEPTH: u32 = 256;
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
pub symbol_table: &'a mut SymbolTable,
|
pub symbol_table: &'a mut SymbolTable,
|
||||||
@ -49,6 +49,12 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_max_recursion_depth(mut self, depth: u32) -> Self {
|
||||||
|
self.max_recursion_depth = depth;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn interpret(
|
pub fn interpret(
|
||||||
&mut self,
|
&mut self,
|
||||||
statements: Vec<Stmt>,
|
statements: Vec<Stmt>,
|
||||||
@ -791,12 +797,12 @@ fn eval_comprehension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let condition = eval_expr(context, condition, None);
|
let condition = eval_expr(context, condition, None);
|
||||||
match condition {
|
match condition {
|
||||||
Ok(KalkValue::Boolean(boolean)) => {
|
Ok(KalkValue::Boolean(boolean)) => {
|
||||||
if boolean && vars.len() == 1 {
|
if boolean && vars.len() == 1 {
|
||||||
values.push(eval_expr(context, left, None));
|
values.push(eval_expr(context, left, None));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(err) => values.push(Err(err)),
|
Err(err) => values.push(Err(err)),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ pub struct Context {
|
|||||||
unit_decl_base_unit: Option<String>,
|
unit_decl_base_unit: Option<String>,
|
||||||
other_radix: Option<u8>,
|
other_radix: Option<u8>,
|
||||||
current_stmt_start_pos: usize,
|
current_stmt_start_pos: usize,
|
||||||
|
max_recursion_depth: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@ -48,6 +49,7 @@ impl Context {
|
|||||||
unit_decl_base_unit: None,
|
unit_decl_base_unit: None,
|
||||||
other_radix: None,
|
other_radix: None,
|
||||||
current_stmt_start_pos: 0,
|
current_stmt_start_pos: 0,
|
||||||
|
max_recursion_depth: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
parse(&mut context, crate::prelude::INIT).unwrap();
|
parse(&mut context, crate::prelude::INIT).unwrap();
|
||||||
@ -70,6 +72,12 @@ impl Context {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_max_recursion_depth(mut self, depth: u32) -> Self {
|
||||||
|
self.max_recursion_depth = Some(depth);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = evaluate)]
|
#[wasm_bindgen(js_name = evaluate)]
|
||||||
#[cfg(not(feature = "rug"))]
|
#[cfg(not(feature = "rug"))]
|
||||||
pub fn js_eval(&mut self, input: &str) -> Result<Option<CalculationResult>, JsValue> {
|
pub fn js_eval(&mut self, input: &str) -> Result<Option<CalculationResult>, JsValue> {
|
||||||
@ -107,6 +115,11 @@ pub fn eval(
|
|||||||
precision,
|
precision,
|
||||||
context.timeout.map(|timeout| timeout as u128),
|
context.timeout.map(|timeout| timeout as u128),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(max_recursion_depth) = context.max_recursion_depth {
|
||||||
|
interpreter = interpreter.set_max_recursion_depth(max_recursion_depth);
|
||||||
|
}
|
||||||
|
|
||||||
let result = interpreter.interpret(statements);
|
let result = interpreter.interpret(statements);
|
||||||
if let Ok(Some(mut num)) = result {
|
if let Ok(Some(mut num)) = result {
|
||||||
num.set_radix(context.other_radix.unwrap_or(10));
|
num.set_radix(context.other_radix.unwrap_or(10));
|
||||||
@ -644,7 +657,8 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
// vector/group, otherwise it's an expression like sqrt4,
|
// vector/group, otherwise it's an expression like sqrt4,
|
||||||
// which should be parsed as a factor, to allow eg. sqrt2x.
|
// which should be parsed as a factor, to allow eg. sqrt2x.
|
||||||
let mut arguments = if match_token(context, TokenKind::OpenBrace)
|
let mut arguments = if match_token(context, TokenKind::OpenBrace)
|
||||||
|| match_token(context, TokenKind::OpenParenthesis) {
|
|| match_token(context, TokenKind::OpenParenthesis)
|
||||||
|
{
|
||||||
match parse_primary(context)? {
|
match parse_primary(context)? {
|
||||||
Expr::Vector(arguments) => arguments,
|
Expr::Vector(arguments) => arguments,
|
||||||
Expr::Group(argument) => vec![*argument],
|
Expr::Group(argument) => vec![*argument],
|
||||||
|
Loading…
Reference in New Issue
Block a user