add support for vectors as operands to math operations
This commit is contained in:
parent
5b7d9586ea
commit
37c575748b
|
@ -178,6 +178,8 @@ macro_rules! def_fns {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod fns {
|
pub mod fns {
|
||||||
|
use core::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
use alloc::{format, vec::Vec};
|
use alloc::{format, vec::Vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -261,33 +263,48 @@ pub mod fns {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn binary_math_op(
|
||||||
|
vm: &mut Vm,
|
||||||
|
args: FnArgs,
|
||||||
|
on_number_number: fn(f32, f32) -> f32,
|
||||||
|
on_vec_vec: fn(Vec4, Vec4) -> Vec4,
|
||||||
|
) -> Result<Value, Exception> {
|
||||||
|
static WRONG_ARG: &str = "arguments to binary math operators may be numbers, vecs, or rgba, and must be of the same type";
|
||||||
|
match args.get(vm, 0) {
|
||||||
|
Value::Number(x) => Ok(Value::Number(on_number_number(
|
||||||
|
x,
|
||||||
|
args.get_number(vm, 1, WRONG_ARG)?,
|
||||||
|
))),
|
||||||
|
Value::Vec4(x) => Ok(Value::Vec4(on_vec_vec(x, args.get_vec4(vm, 1, WRONG_ARG)?))),
|
||||||
|
Value::Rgba(x) => Ok(Value::Rgba(
|
||||||
|
on_vec_vec(x.into(), args.get_rgba(vm, 1, WRONG_ARG)?.into()).into(),
|
||||||
|
)),
|
||||||
|
_ => Err(vm.create_exception(WRONG_ARG)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
pub fn add(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||||
let a = args.get_number(vm, 0, "arguments to `+` must be numbers")?;
|
binary_math_op(vm, args, <f32 as Add>::add, <Vec4 as Add>::add)
|
||||||
let b = args.get_number(vm, 1, "arguments to `+` must be numbers")?;
|
|
||||||
Ok(Value::Number(a + b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
pub fn sub(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||||
let a = args.get_number(vm, 0, "arguments to `-` must be numbers")?;
|
binary_math_op(vm, args, <f32 as Sub>::sub, <Vec4 as Sub>::sub)
|
||||||
let b = args.get_number(vm, 1, "arguments to `-` must be numbers")?;
|
|
||||||
Ok(Value::Number(a - b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
pub fn mul(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||||
let a = args.get_number(vm, 0, "arguments to `*` must be numbers")?;
|
binary_math_op(vm, args, <f32 as Mul>::mul, <Vec4 as Mul>::mul)
|
||||||
let b = args.get_number(vm, 1, "arguments to `*` must be numbers")?;
|
|
||||||
Ok(Value::Number(a * b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn div(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
pub fn div(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||||
let a = args.get_number(vm, 0, "arguments to `/` must be numbers")?;
|
binary_math_op(vm, args, <f32 as Div>::div, <Vec4 as Div>::div)
|
||||||
let b = args.get_number(vm, 1, "arguments to `/` must be numbers")?;
|
|
||||||
Ok(Value::Number(a / b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn neg(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
pub fn neg(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||||
let x = args.get_number(vm, 0, "`-` can only work with numbers")?;
|
match args.get(vm, 0) {
|
||||||
Ok(Value::Number(-x))
|
Value::Number(x) => Ok(Value::Number(-x)),
|
||||||
|
Value::Vec4(x) => Ok(Value::Vec4(-x)),
|
||||||
|
_ => Err(vm.create_exception("`-` can only work with numbers and vectors")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::{bytecode::TagId, compiler::ClosureSpec, system::ChunkId};
|
use crate::{bytecode::TagId, compiler::ClosureSpec, system::ChunkId};
|
||||||
|
@ -97,6 +99,17 @@ pub struct Vec4 {
|
||||||
pub w: f32,
|
pub w: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<f32> for Vec4 {
|
||||||
|
fn from(value: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
x: value,
|
||||||
|
y: value,
|
||||||
|
z: value,
|
||||||
|
w: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec2> for Vec4 {
|
impl From<Vec2> for Vec4 {
|
||||||
fn from(value: Vec2) -> Self {
|
fn from(value: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -108,6 +121,82 @@ impl From<Vec2> for Vec4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Rgba> for Vec4 {
|
||||||
|
fn from(value: Rgba) -> Self {
|
||||||
|
Self {
|
||||||
|
x: value.r,
|
||||||
|
y: value.g,
|
||||||
|
z: value.b,
|
||||||
|
w: value.a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: self.x + rhs.x,
|
||||||
|
y: self.y + rhs.y,
|
||||||
|
z: self.z + rhs.z,
|
||||||
|
w: self.w + rhs.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: self.x - rhs.x,
|
||||||
|
y: self.y - rhs.y,
|
||||||
|
z: self.z - rhs.z,
|
||||||
|
w: self.w - rhs.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: self.x * rhs.x,
|
||||||
|
y: self.y * rhs.y,
|
||||||
|
z: self.z * rhs.z,
|
||||||
|
w: self.w * rhs.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: self.x / rhs.x,
|
||||||
|
y: self.y / rhs.y,
|
||||||
|
z: self.z / rhs.z,
|
||||||
|
w: self.w / rhs.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
z: -self.z,
|
||||||
|
w: -self.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Rgba {
|
pub struct Rgba {
|
||||||
|
@ -117,6 +206,17 @@ pub struct Rgba {
|
||||||
pub a: f32,
|
pub a: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec4> for Rgba {
|
||||||
|
fn from(value: Vec4) -> Self {
|
||||||
|
Self {
|
||||||
|
r: value.x,
|
||||||
|
g: value.y,
|
||||||
|
b: value.z,
|
||||||
|
a: value.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: This is not a pointer, because IDs are safer and easier to clone.
|
// NOTE: This is not a pointer, because IDs are safer and easier to clone.
|
||||||
//
|
//
|
||||||
// Since this only ever refers to refs inside the current VM, there is no need to walk through all
|
// Since this only ever refers to refs inside the current VM, there is no need to walk through all
|
||||||
|
|
Loading…
Reference in a new issue