Add support in the parser for the various Math syscalls

This commit is contained in:
2025-12-06 21:49:10 -07:00
parent 0ea58e4921
commit ab7b36ac22
2 changed files with 131 additions and 16 deletions

View File

@@ -4,7 +4,7 @@ mod test;
pub mod sys_call; pub mod sys_call;
pub mod tree_node; pub mod tree_node;
use crate::sys_call::System; use crate::sys_call::{Math, System};
use quick_error::quick_error; use quick_error::quick_error;
use std::io::SeekFrom; use std::io::SeekFrom;
use sys_call::SysCall; use sys_call::SysCall;
@@ -1649,6 +1649,7 @@ impl<'a> Parser<'a> {
let invocation = self.invocation()?; let invocation = self.invocation()?;
match invocation.name.node.as_str() { match invocation.name.node.as_str() {
// System SysCalls
"yield" => { "yield" => {
check_length(self, &invocation.arguments, 0)?; check_length(self, &invocation.arguments, 0)?;
Ok(SysCall::System(sys_call::System::Yield)) Ok(SysCall::System(sys_call::System::Yield))
@@ -1822,6 +1823,119 @@ impl<'a> Parser<'a> {
expr, expr,
))) )))
} }
// Math SysCalls
"acos" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Acos(boxed!(tmp))))
}
"asin" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Asin(boxed!(tmp))))
}
"atan" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Atan(boxed!(expr))))
}
"atan2" => {
check_length(self, &invocation.arguments, 2)?;
let mut args = invocation.arguments.into_iter();
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Atan2(boxed!(arg1), boxed!(arg2))))
}
"abs" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Abs(boxed!(expr))))
}
"ceil" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Ceil(boxed!(arg))))
}
"cos" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Cos(boxed!(arg))))
}
"floor" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Floor(boxed!(arg))))
}
"log" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Log(boxed!(arg))))
}
"max" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Max(boxed!(arg1), boxed!(arg2))))
}
"min" => {
check_length(self, &invocation.arguments, 2)?;
let mut args = invocation.arguments.into_iter();
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Min(boxed!(arg1), boxed!(arg2))))
}
"rand" => {
check_length(self, &invocation.arguments, 0)?;
Ok(SysCall::Math(Math::Rand))
}
"sin" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Sin(boxed!(arg))))
}
"sqrt" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Sqrt(boxed!(arg))))
}
"tan" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Tan(boxed!(arg))))
}
"trunc" => {
check_length(self, &invocation.arguments, 1)?;
let mut args = invocation.arguments.into_iter();
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
Ok(SysCall::Math(Math::Trunc(boxed!(arg))))
}
_ => Err(Error::UnsupportedKeyword( _ => Err(Error::UnsupportedKeyword(
self.current_span(), self.current_span(),
self.current_token.clone().ok_or(Error::UnexpectedEOF)?, self.current_token.clone().ok_or(Error::UnexpectedEOF)?,

View File

@@ -10,67 +10,67 @@ documented! {
/// `acos r? a(r?|num)` /// `acos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).acos();` /// `(number|var).acos();`
Acos(LiteralOrVariable), Acos(Box<Spanned<Expression>>),
/// Returns the angle in radians whose sine is the specified number. /// Returns the angle in radians whose sine is the specified number.
/// ## IC10 /// ## IC10
/// `asin r? a(r?|num)` /// `asin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).asin();` /// `(number|var).asin();`
Asin(LiteralOrVariable), Asin(Box<Spanned<Expression>>),
/// Returns the angle in radians whose tangent is the specified number. /// Returns the angle in radians whose tangent is the specified number.
/// ## IC10 /// ## IC10
/// `atan r? a(r?|num)` /// `atan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).atan();` /// `(number|var).atan();`
Atan(LiteralOrVariable), Atan(Box<Spanned<Expression>>),
/// Returns the angle in radians whose tangent is the quotient of the specified numbers. /// Returns the angle in radians whose tangent is the quotient of the specified numbers.
/// ## IC10 /// ## IC10
/// `atan2 r? a(r?|num) b(r?|num)` /// `atan2 r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).atan2((number|var));` /// `(number|var).atan2((number|var));`
Atan2(LiteralOrVariable, LiteralOrVariable), Atan2(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Gets the absolute value of a number. /// Gets the absolute value of a number.
/// ## IC10 /// ## IC10
/// `abs r? a(r?|num)` /// `abs r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).abs();` /// `(number|var).abs();`
Abs(LiteralOrVariable), Abs(Box<Spanned<Expression>>),
/// Rounds a number up to the nearest whole number. /// Rounds a number up to the nearest whole number.
/// ## IC10 /// ## IC10
/// `ceil r? a(r?|num)` /// `ceil r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).ceil();` /// `(number|var).ceil();`
Ceil(LiteralOrVariable), Ceil(Box<Spanned<Expression>>),
/// Returns the cosine of the specified angle in radians. /// Returns the cosine of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `cos r? a(r?|num)` /// `cos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).cos();` /// `(number|var).cos();`
Cos(LiteralOrVariable), Cos(Box<Spanned<Expression>>),
/// Rounds a number down to the nearest whole number. /// Rounds a number down to the nearest whole number.
/// ## IC10 /// ## IC10
/// `floor r? a(r?|num)` /// `floor r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).floor();` /// `(number|var).floor();`
Floor(LiteralOrVariable), Floor(Box<Spanned<Expression>>),
/// Computes the natural logarithm of a number. /// Computes the natural logarithm of a number.
/// ## IC10 /// ## IC10
/// `log r? a(r?|num)` /// `log r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).log();` /// `(number|var).log();`
Log(LiteralOrVariable), Log(Box<Spanned<Expression>>),
/// Computes the maximum of two numbers. /// Computes the maximum of two numbers.
/// ## IC10 /// ## IC10
/// `max r? a(r?|num) b(r?|num)` /// `max r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).max((number|var));` /// `(number|var).max((number|var));`
Max(LiteralOrVariable, LiteralOrVariable), Max(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Computes the minimum of two numbers. /// Computes the minimum of two numbers.
/// ## IC10 /// ## IC10
/// `min r? a(r?|num) b(r?|num)` /// `min r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).min((number|var));` /// `(number|var).min((number|var));`
Min(LiteralOrVariable, LiteralOrVariable), Min(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Gets a random number between 0 and 1. /// Gets a random number between 0 and 1.
/// ## IC10 /// ## IC10
/// `rand r?` /// `rand r?`
@@ -82,25 +82,25 @@ documented! {
/// `sin r? a(r?|num)` /// `sin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).sin();` /// `(number|var).sin();`
Sin(LiteralOrVariable), Sin(Box<Spanned<Expression>>),
/// Computes the square root of a number. /// Computes the square root of a number.
/// ## IC10 /// ## IC10
/// `sqrt r? a(r?|num)` /// `sqrt r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).sqrt();` /// `(number|var).sqrt();`
Sqrt(LiteralOrVariable), Sqrt(Box<Spanned<Expression>>),
/// Returns the tangent of the specified angle in radians. /// Returns the tangent of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `tan r? a(r?|num)` /// `tan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).tan();` /// `(number|var).tan();`
Tan(LiteralOrVariable), Tan(Box<Spanned<Expression>>),
/// Truncates a number by removing the decimal portion. /// Truncates a number by removing the decimal portion.
/// ## IC10 /// ## IC10
/// `trunc r? a(r?|num)` /// `trunc r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).trunc();` /// `(number|var).trunc();`
Trunc(LiteralOrVariable), Trunc(Box<Spanned<Expression>>),
} }
} }
@@ -231,6 +231,7 @@ impl std::fmt::Display for System {
} }
} }
#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
/// This represents built in functions that cannot be overwritten, but can be invoked by the user as functions. /// This represents built in functions that cannot be overwritten, but can be invoked by the user as functions.
pub enum SysCall { pub enum SysCall {