Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 113 additions & 79 deletions stdlib/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,106 @@ use techscript_runtime::{
RuntimeContext,
};

fn abs(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
match &args[0] {
RuntimeValue::Int(i) => Ok(RuntimeValue::Int(i.abs())),
RuntimeValue::Float(f) => Ok(RuntimeValue::Float(f.abs())),
other => Err(RuntimeError::new(
RuntimeErrorKind::TypeMismatch {
expected: "Int or Float".to_string(),
found: other.runtime_type().to_string(),
},
None,
None,
)),
}
}

fn sin(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.sin()))
}

fn cos(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.cos()))
}

fn tan(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.tan()))
}

fn log(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.ln()))
}

fn exp(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.exp()))
}

fn sqrt(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.sqrt()))
}

fn pow(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let base = args[0].try_into_float()?;
let exponent = args[1].try_into_float()?;
Ok(RuntimeValue::Float(base.powf(exponent)))
}

fn floor(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.floor()))
}

fn ceil(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.ceil()))
}

fn round(_ctx: &mut RuntimeContext, args: Vec<RuntimeValue>) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.round()))
}

fn random(
_ctx: &mut RuntimeContext,
_args: Vec<RuntimeValue>,
) -> Result<RuntimeValue, RuntimeError> {
use std::cell::Cell;
use std::time::SystemTime;
thread_local! {
static SEED: Cell<u64> = Cell::new({
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64
});
}
let next_seed = SEED.with(|cell| {
let current = cell.get();
let next = current
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
cell.set(next);
next
});
let rand_float = (next_seed as f64) / (u64::MAX as f64);
Ok(RuntimeValue::Float(rand_float))
}

fn to_float(
_ctx: &mut RuntimeContext,
args: Vec<RuntimeValue>,
) -> Result<RuntimeValue, RuntimeError> {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f))
}

impl StdlibRegistry {
pub fn register_math(&mut self) {
let mut exports: HashMap<String, Rc<dyn techscript_runtime::function::Callable>> =
Expand All @@ -17,18 +117,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "abs".to_string(),
arity: 1,
callback: |_ctx, args| match &args[0] {
RuntimeValue::Int(i) => Ok(RuntimeValue::Int(i.abs())),
RuntimeValue::Float(f) => Ok(RuntimeValue::Float(f.abs())),
other => Err(RuntimeError::new(
RuntimeErrorKind::TypeMismatch {
expected: "Int or Float".to_string(),
found: other.runtime_type().to_string(),
},
None,
None,
)),
},
callback: abs,
}),
);

Expand All @@ -37,10 +126,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "sin".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.sin()))
},
callback: sin,
}),
);

Expand All @@ -49,10 +135,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "cos".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.cos()))
},
callback: cos,
}),
);

Expand All @@ -61,10 +144,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "tan".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.tan()))
},
callback: tan,
}),
);

Expand All @@ -73,10 +153,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "log".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.ln()))
},
callback: log,
}),
);

Expand All @@ -85,10 +162,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "exp".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.exp()))
},
callback: exp,
}),
);

Expand All @@ -97,10 +171,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "sqrt".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.sqrt()))
},
callback: sqrt,
}),
);

Expand All @@ -109,11 +180,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "pow".to_string(),
arity: 2,
callback: |_ctx, args| {
let base = args[0].try_into_float()?;
let exponent = args[1].try_into_float()?;
Ok(RuntimeValue::Float(base.powf(exponent)))
},
callback: pow,
}),
);

Expand All @@ -122,10 +189,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "floor".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.floor()))
},
callback: floor,
}),
);

Expand All @@ -134,10 +198,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "ceil".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.ceil()))
},
callback: ceil,
}),
);

Expand All @@ -146,10 +207,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "round".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f.round()))
},
callback: round,
}),
);

Expand All @@ -158,28 +216,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "random".to_string(),
arity: 0,
callback: |_ctx, _args| {
use std::cell::Cell;
use std::time::SystemTime;
thread_local! {
static SEED: Cell<u64> = Cell::new({
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64
});
}
let next_seed = SEED.with(|cell| {
let current = cell.get();
let next = current
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
cell.set(next);
next
});
let rand_float = (next_seed as f64) / (u64::MAX as f64);
Ok(RuntimeValue::Float(rand_float))
},
callback: random,
}),
);

Expand All @@ -188,10 +225,7 @@ impl StdlibRegistry {
Rc::new(StdFunction {
name: "to_float".to_string(),
arity: 1,
callback: |_ctx, args| {
let f = args[0].try_into_float()?;
Ok(RuntimeValue::Float(f))
},
callback: to_float,
}),
);

Expand Down
Loading