Skip to content

Commit

Permalink
Made add standard external function
Browse files Browse the repository at this point in the history
  • Loading branch information
bvssvni committed Sep 20, 2019
1 parent ec96e00 commit 1204046
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 52 deletions.
8 changes: 8 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2906,6 +2906,14 @@ impl BinOpExpression {

fn into_expression(self) -> Expression {
match self.op {
BinOp::Add => Expression::Call(Box::new(Call {
alias: None,
name: crate::ADD.clone(),
args: vec![self.left, self.right],
custom_source: None,
f_index: Cell::new(FnIndex::None),
source_range: self.source_range,
})),
BinOp::Dot => Expression::Call(Box::new(Call {
alias: None,
name: crate::DOT.clone(),
Expand Down
52 changes: 52 additions & 0 deletions src/dyon_std/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,58 @@ const HTTP_SUPPORT_DISABLED: &'static str = "Http support is disabled";
#[cfg(not(feature = "file"))]
const FILE_SUPPORT_DISABLED: &'static str = "File support is disabled";

pub(crate) fn add(rt: &mut Runtime) -> Result<(), String> {
let b = rt.stack.pop().expect(TINVOTS);
let a = rt.stack.pop().expect(TINVOTS);
let r = match (rt.resolve(&a), rt.resolve(&b)) {
(&Variable::F64(a, ref sec), &Variable::F64(b, _)) =>
Variable::F64(a + b, sec.clone()),
(&Variable::Vec4(a), &Variable::Vec4(b)) =>
Variable::Vec4(vecmath::vec4_add(a, b)),
(&Variable::Vec4(a), &Variable::F64(b, _)) => {
let b = b as f32;
Variable::Vec4([a[0] + b, a[1] + b, a[2] + b, a[3] + b])
}
(&Variable::F64(a, _), &Variable::Vec4(b)) => {
let a = a as f32;
Variable::Vec4([a + b[0], a + b[1], a + b[2], a + b[3]])
}
(&Variable::Mat4(ref a), &Variable::Mat4(ref b)) =>
Variable::Mat4(Box::new(vecmath::mat4_add(**a, **b))),
(&Variable::F64(a, _), &Variable::Mat4(ref b)) => {
let a = a as f32;
Variable::Mat4(Box::new([
[b[0][0] + a, b[0][1] + a, b[0][2] + a, b[0][3] + a],
[b[1][0] + a, b[1][1] + a, b[1][2] + a, b[1][3] + a],
[b[2][0] + a, b[2][1] + a, b[2][2] + a, b[2][3] + a],
[b[3][0] + a, b[3][1] + a, b[3][2] + a, b[3][3] + a]
]))
}
(&Variable::Mat4(ref b), &Variable::F64(a, _)) => {
let a = a as f32;
Variable::Mat4(Box::new([
[b[0][0] + a, b[0][1] + a, b[0][2] + a, b[0][3] + a],
[b[1][0] + a, b[1][1] + a, b[1][2] + a, b[1][3] + a],
[b[2][0] + a, b[2][1] + a, b[2][2] + a, b[2][3] + a],
[b[3][0] + a, b[3][1] + a, b[3][2] + a, b[3][3] + a]
]))
}
(&Variable::Bool(a, ref sec), &Variable::Bool(b, _)) =>
Variable::Bool(a || b, sec.clone()),
(&Variable::Str(ref a), &Variable::Str(ref b)) => {
let mut res = String::with_capacity(a.len() + b.len());
res.push_str(a);
res.push_str(b);
Variable::Str(Arc::new(res))
}
(&Variable::Link(ref a), &Variable::Link(ref b)) =>
Variable::Link(Box::new(a.add(b))),
_ => return Err("Expected `f64`, `vec4`, `mat4`, `bool`, `str` or `link`".into())
};
rt.stack.push(r);
Ok(())
}

pub(crate) fn not(rt: &mut Runtime) -> Result<(), String> {
let b = rt.stack.pop().expect(TINVOTS);
let b = match *rt.resolve(&b) {
Expand Down
13 changes: 13 additions & 0 deletions src/lib.dyon
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,19 @@ fn min(array: [f64]) -> f64 { ... }
/// Returns NaN if array is empty.
fn max(array: [f64]) -> f64 { ... }

/// Addition.
fn add(a: any, b: any) -> any { ... }
(f64, f64) -> f64
(vec4, vec4) -> vec4
(vec4, f64) -> vec4
(f64, vec4) -> vec4
(mat4, mat4) -> mat4
(f64, mat4) -> mat4
(mat4, f64) -> mat4
(bool, bool) -> bool
(str, str) -> str
(link, link) -> link

/// Returns the length of 4D vector.
fn norm(v: vec4) -> f64 { ... }

Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub use mat4::Mat4;
pub const TINVOTS: &str = "There is no value on the stack";

lazy_static!{
pub(crate) static ref ADD: Arc<String> = Arc::new("add".into());
pub(crate) static ref DOT: Arc<String> = Arc::new("dot".into());
pub(crate) static ref CROSS: Arc<String> = Arc::new("cross".into());
pub(crate) static ref NOT: Arc<String> = Arc::new("not".into());
Expand Down Expand Up @@ -371,6 +372,23 @@ impl Module {

let mut m = Module::empty();
m.ns("std");
m.add_str("add", add, Dfn {
lts: vec![Lt::Default; 2],
tys: vec![Any; 2],
ret: Any,
ext: vec![
(vec![F64, F64], F64),
(vec![Vec4, Vec4], Vec4),
(vec![Vec4, F64], Vec4),
(vec![F64, Vec4], Vec4),
(vec![Mat4, Mat4], Mat4),
(vec![F64, Mat4], Mat4),
(vec![Mat4, F64], Mat4),
(vec![Bool, Bool], Bool),
(vec![Str, Str], Str),
(vec![Link, Link], Link),
]
});
m.add_str("not", not, Dfn::nl(vec![Bool], Bool));
m.add_str("neg", neg, Dfn{
lts: vec![Lt::Default], tys: vec![Any], ret: Any,
Expand Down
1 change: 1 addition & 0 deletions src/lifetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub fn check(
use ast::BinOp::*;

match nodes[i].binops[0] {
Add => Node::rewrite_binop(i, crate::ADD.clone(), &mut nodes),
Dot => Node::rewrite_binop(i, crate::DOT.clone(), &mut nodes),
Cross => Node::rewrite_binop(i, crate::CROSS.clone(), &mut nodes),
_ => {}
Expand Down
68 changes: 63 additions & 5 deletions src/lifetime/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,60 @@ impl Node {
nodes[ch].kind = Kind::CallArg;
}

pub fn rewrite_binop(i: usize, name: Arc<String>, nodes: &mut [Node]) {
pub fn rewrite_binop(i: usize, name: Arc<String>, nodes: &mut Vec<Node>) {
nodes[i].kind = Kind::Call;
nodes[i].names.push(name);
nodes[i].binops.clear();
let left = nodes[i].children[0];
let right = nodes[i].children[1];
nodes[left].kind = Kind::CallArg;
nodes[right].kind = Kind::CallArg;

let old_left = nodes[i].children[0];
let old_right = nodes[i].children[1];

let left = nodes.len();
nodes.push(Node {
kind: Kind::CallArg,
names: vec![],
ty: None,
declaration: None,
alias: None,
mutable: false,
try: false,
grab_level: 0,
source: nodes[old_left].source,
start: nodes[old_left].start,
end: nodes[old_left].end,
lifetime: None,
op: None,
binops: vec![],
lts: vec![],
parent: Some(i),
children: vec![old_left],
});
let right = nodes.len();
nodes.push(Node {
kind: Kind::CallArg,
names: vec![],
ty: None,
declaration: None,
alias: None,
mutable: false,
try: false,
grab_level: 0,
source: nodes[old_right].source,
start: nodes[old_right].start,
end: nodes[old_right].end,
lifetime: None,
op: None,
binops: vec![],
lts: vec![],
parent: Some(i),
children: vec![old_right],
});

nodes[old_left].parent = Some(left);
nodes[old_right].parent = Some(right);

nodes[i].children[0] = left;
nodes[i].children[1] = right;
}

#[allow(dead_code)]
Expand Down Expand Up @@ -516,6 +562,18 @@ pub fn convert_meta_data(
let i = *parents.last().unwrap();
nodes[i].binops.push(BinOp::AndAlso);
}
"+" => {
let i = *parents.last().unwrap();
nodes[i].binops.push(BinOp::Add);
}
"-" => {
let i = *parents.last().unwrap();
nodes[i].binops.push(BinOp::Sub);
}
"||" => {
let i = *parents.last().unwrap();
nodes[i].binops.push(BinOp::OrElse);
}
_ => {}
}
}
Expand Down
52 changes: 5 additions & 47 deletions src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2513,7 +2513,6 @@ impl Runtime {
let v = match (self.resolve(&left), self.resolve(&right)) {
(&Variable::F64(a, ref sec), &Variable::F64(b, _)) => {
Variable::F64(match binop.op {
Add => a + b,
Sub => a - b,
Mul => a * b,
Div => a / b,
Expand All @@ -2527,14 +2526,13 @@ impl Runtime {
}
(&Variable::Vec4(a), &Variable::Vec4(b)) => {
match binop.op {
Add => Variable::Vec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]]),
Sub => Variable::Vec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]]),
Mul => Variable::Vec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]]),
Div => Variable::Vec4([a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3]]),
Rem => Variable::Vec4([a[0] % b[0], a[1] % b[1], a[2] % b[2], a[3] % b[3]]),
Pow => Variable::Vec4([a[0].powf(b[0]), a[1].powf(b[1]),
a[2].powf(b[2]), a[3].powf(b[3])]),
AndAlso | OrElse | Dot | Cross => return Err(self.module.error(binop.source_range,
_ => return Err(self.module.error(binop.source_range,
&format!("{}\nUnknown operator `{:?}` for `vec4` and `vec4`",
self.stack_trace(),
binop.op.symbol_bool()), self)),
Expand All @@ -2543,14 +2541,13 @@ impl Runtime {
(&Variable::Vec4(a), &Variable::F64(b, _)) => {
let b = b as f32;
match binop.op {
Add => Variable::Vec4([a[0] + b, a[1] + b, a[2] + b, a[3] + b]),
Sub => Variable::Vec4([a[0] - b, a[1] - b, a[2] - b, a[3] - b]),
Mul => Variable::Vec4([a[0] * b, a[1] * b, a[2] * b, a[3] * b]),
Div => Variable::Vec4([a[0] / b, a[1] / b, a[2] / b, a[3] / b]),
Rem => Variable::Vec4([a[0] % b, a[1] % b, a[2] % b, a[3] % b]),
Pow => Variable::Vec4([a[0].powf(b), a[1].powf(b),
a[2].powf(b), a[3].powf(b)]),
AndAlso | OrElse | Dot | Cross => return Err(self.module.error(binop.source_range,
_ => return Err(self.module.error(binop.source_range,
&format!("{}\nUnknown operator `{:?}` for `vec4` and `f64`",
self.stack_trace(),
binop.op.symbol_bool()), self)),
Expand All @@ -2559,24 +2556,22 @@ impl Runtime {
(&Variable::F64(a, _), &Variable::Vec4(b)) => {
let a = a as f32;
match binop.op {
Add => Variable::Vec4([a + b[0], a + b[1], a + b[2], a + b[3]]),
Sub => Variable::Vec4([a - b[0], a - b[1], a - b[2], a - b[3]]),
Mul => Variable::Vec4([a * b[0], a * b[1], a * b[2], a * b[3]]),
Div => Variable::Vec4([a / b[0], a / b[1], a / b[2], a / b[3]]),
Rem => Variable::Vec4([a % b[0], a % b[1], a % b[2], a % b[3]]),
Pow => Variable::Vec4([a.powf(b[0]), a.powf(b[1]),
a.powf(b[2]), a.powf(b[3])]),
AndAlso | OrElse | Dot | Cross => return Err(self.module.error(binop.source_range,
_ => return Err(self.module.error(binop.source_range,
&format!("{}\nUnknown operator `{:?}` for `f64` and `vec4`",
self.stack_trace(),
binop.op.symbol_bool()), self)),
}
}
(&Variable::Mat4(ref a), &Variable::Mat4(ref b)) => {
use vecmath::{mat4_add, mat4_sub, col_mat4_mul};
use vecmath::{mat4_sub, col_mat4_mul};

match binop.op {
Add => Variable::Mat4(Box::new(mat4_add(**a, **b))),
Sub => Variable::Mat4(Box::new(mat4_sub(**a, **b))),
Mul => Variable::Mat4(Box::new(col_mat4_mul(**a, **b))),
_ => return Err(self.module.error(binop.source_range,
Expand All @@ -2588,12 +2583,6 @@ impl Runtime {
(&Variable::F64(a, _), &Variable::Mat4(ref b)) => {
let a = a as f32;
match binop.op {
Add => Variable::Mat4(Box::new([
[b[0][0] + a, b[0][1] + a, b[0][2] + a, b[0][3] + a],
[b[1][0] + a, b[1][1] + a, b[1][2] + a, b[1][3] + a],
[b[2][0] + a, b[2][1] + a, b[2][2] + a, b[2][3] + a],
[b[3][0] + a, b[3][1] + a, b[3][2] + a, b[3][3] + a]
])),
Sub => Variable::Mat4(Box::new([
[a - b[0][0], a - b[0][1], a - b[0][2], a - b[0][3]],
[a - b[1][0], a - b[1][1], a - b[1][2], a - b[1][3]],
Expand All @@ -2615,12 +2604,6 @@ impl Runtime {
(&Variable::Mat4(ref b), &Variable::F64(a, _)) => {
let a = a as f32;
match binop.op {
Add => Variable::Mat4(Box::new([
[b[0][0] + a, b[0][1] + a, b[0][2] + a, b[0][3] + a],
[b[1][0] + a, b[1][1] + a, b[1][2] + a, b[1][3] + a],
[b[2][0] + a, b[2][1] + a, b[2][2] + a, b[2][3] + a],
[b[3][0] + a, b[3][1] + a, b[3][2] + a, b[3][3] + a]
])),
Sub => Variable::Mat4(Box::new([
[b[0][0] - a, b[0][1] - a, b[0][2] - a, b[0][3] - a],
[b[1][0] - a, b[1][1] - a, b[1][2] - a, b[1][3] - a],
Expand Down Expand Up @@ -2652,7 +2635,7 @@ impl Runtime {
}
(&Variable::Bool(a, ref sec), &Variable::Bool(b, _)) => {
Variable::Bool(match binop.op {
Add | OrElse => a || b,
OrElse => a || b,
// Boolean subtraction with lazy precedence.
Sub => a && !b,
Mul | AndAlso => a && b,
Expand All @@ -2663,31 +2646,6 @@ impl Runtime {
binop.op.symbol_bool()), self))
}, sec.clone())
}
(&Variable::Str(ref a), &Variable::Str(ref b)) => {
match binop.op {
Add => {
let mut res = String::with_capacity(a.len() + b.len());
res.push_str(a);
res.push_str(b);
Variable::Str(Arc::new(res))
}
_ => return self.err(binop.source_range,
"This operation can not be used with strings")
}
}
(&Variable::Str(_), _) =>
return self.err(binop.source_range,
"The right argument must be a string. \
Try the `str` function"),
(&Variable::Link(ref a), &Variable::Link(ref b)) => {
match binop.op {
Add => {
Variable::Link(Box::new(a.add(b)))
}
_ => return self.err(binop.source_range,
"This operation can not be used with links")
}
}
_ => return Err(self.module.error(binop.source_range, &format!(
"{}\nInvalid type for binary operator `{:?}`, \
expected numbers, vec4s, bools or strings",
Expand Down

0 comments on commit 1204046

Please sign in to comment.