add sin
cos
tan
to stdlib and make sure you cant redeclare a stdlib fn (#497)
more tests Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -1287,7 +1287,8 @@ impl Parser {
|
||||
let current_token = self.get_token(index)?;
|
||||
|
||||
// Make sure they are not assigning a variable to a reserved keyword.
|
||||
if current_token.token_type == TokenType::Keyword {
|
||||
// Or a stdlib function.
|
||||
if current_token.token_type == TokenType::Keyword || self.stdlib.fns.contains_key(¤t_token.value) {
|
||||
return Err(KclError::Syntax(KclErrorDetails {
|
||||
source_ranges: vec![current_token.into()],
|
||||
message: format!(
|
||||
@ -1399,7 +1400,8 @@ impl Parser {
|
||||
}
|
||||
|
||||
// Make sure they are not assigning a variable to a reserved keyword.
|
||||
if argument_token.token_type == TokenType::Keyword {
|
||||
// Or a stdlib function.
|
||||
if argument_token.token_type == TokenType::Keyword || self.stdlib.fns.contains_key(&argument_token.value) {
|
||||
return Err(KclError::Syntax(KclErrorDetails {
|
||||
source_ranges: vec![argument_token.clone().into()],
|
||||
message: format!(
|
||||
@ -3287,6 +3289,19 @@ e
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_stdlib_in_fn_name() {
|
||||
let some_program_string = r#"fn cos = () {}"#;
|
||||
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let result = parser.ast();
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"syntax: KclErrorDetails { source_ranges: [SourceRange([3, 6])], message: "Cannot assign a variable to a reserved keyword: cos" }"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_keyword_in_fn_args() {
|
||||
let some_program_string = r#"fn thing = (let) => {
|
||||
@ -3302,6 +3317,21 @@ e
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_stdlib_in_fn_args() {
|
||||
let some_program_string = r#"fn thing = (cos) => {
|
||||
return 1
|
||||
}"#;
|
||||
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let result = parser.ast();
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"syntax: KclErrorDetails { source_ranges: [SourceRange([12, 15])], message: "Cannot assign a variable to a reserved keyword: cos" }"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyword_ok_in_fn_args_return() {
|
||||
let some_program_string = r#"fn thing = (param) => {
|
||||
|
70
src/wasm-lib/kcl/src/std/math.rs
Normal file
70
src/wasm-lib/kcl/src/std/math.rs
Normal file
@ -0,0 +1,70 @@
|
||||
//! Functions related to mathematics.
|
||||
|
||||
use anyhow::Result;
|
||||
use derive_docs::stdlib;
|
||||
use schemars::JsonSchema;
|
||||
|
||||
use crate::{errors::KclError, executor::MemoryItem, std::Args};
|
||||
|
||||
/// Computes the cosine of a number (in radians).
|
||||
pub fn cos(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||
let num = args.get_number()?;
|
||||
let result = inner_cos(num)?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Computes the sine of a number (in radians).
|
||||
#[stdlib {
|
||||
name = "cos",
|
||||
}]
|
||||
fn inner_cos(num: f64) -> Result<f64, KclError> {
|
||||
Ok(num.cos())
|
||||
}
|
||||
|
||||
/// Computes the sine of a number (in radians).
|
||||
pub fn sin(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||
let num = args.get_number()?;
|
||||
let result = inner_sin(num)?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Computes the sine of a number (in radians).
|
||||
#[stdlib {
|
||||
name = "sin",
|
||||
}]
|
||||
fn inner_sin(num: f64) -> Result<f64, KclError> {
|
||||
Ok(num.sin())
|
||||
}
|
||||
|
||||
/// Computes the tangent of a number (in radians).
|
||||
pub fn tan(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||
let num = args.get_number()?;
|
||||
let result = inner_tan(num)?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Computes the tangent of a number (in radians).
|
||||
#[stdlib {
|
||||
name = "tan",
|
||||
}]
|
||||
fn inner_tan(num: f64) -> Result<f64, KclError> {
|
||||
Ok(num.tan())
|
||||
}
|
||||
|
||||
/// Return the value of `pi`.
|
||||
pub fn pi(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||
let result = inner_pi()?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Return the value of `pi`.
|
||||
#[stdlib {
|
||||
name = "pi",
|
||||
}]
|
||||
fn inner_pi() -> Result<f64, KclError> {
|
||||
Ok(std::f64::consts::PI)
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
//! Functions implemented for language execution.
|
||||
|
||||
pub mod extrude;
|
||||
pub mod math;
|
||||
pub mod segment;
|
||||
pub mod sketch;
|
||||
pub mod utils;
|
||||
@ -61,6 +62,10 @@ impl StdLib {
|
||||
Box::new(crate::std::sketch::Close),
|
||||
Box::new(crate::std::sketch::Arc),
|
||||
Box::new(crate::std::sketch::BezierCurve),
|
||||
Box::new(crate::std::math::Cos),
|
||||
Box::new(crate::std::math::Sin),
|
||||
Box::new(crate::std::math::Tan),
|
||||
Box::new(crate::std::math::Pi),
|
||||
];
|
||||
|
||||
let mut fns = HashMap::new();
|
||||
@ -122,6 +127,21 @@ impl<'a> Args<'a> {
|
||||
)?))
|
||||
}
|
||||
|
||||
fn get_number(&self) -> Result<f64, KclError> {
|
||||
let first_value = self
|
||||
.args
|
||||
.first()
|
||||
.ok_or_else(|| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a number as the first argument, found `{:?}`", self.args),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?
|
||||
.get_json_value()?;
|
||||
|
||||
parse_json_number_as_f64(&first_value, self.source_range)
|
||||
}
|
||||
|
||||
fn get_number_array(&self) -> Result<Vec<f64>, KclError> {
|
||||
let mut numbers: Vec<f64> = Vec::new();
|
||||
for arg in &self.args {
|
||||
|
Reference in New Issue
Block a user