diff --git a/src/builtins/bitwise.rs b/src/builtins/bitwise.rs new file mode 100644 index 0000000..572ea5d --- /dev/null +++ b/src/builtins/bitwise.rs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use crate::ast::Expr; +use crate::builtins; +use crate::builtins::utils::{ensure_args_count, ensure_numeric}; + +use crate::lexer::Span; +use crate::value::{Float, Value}; + +use std::collections::HashMap; + +use anyhow::Result; + +pub fn register(m: &mut HashMap<&'static str, builtins::BuiltinFcn>) { + m.insert("bits.and", and); + m.insert("bits.and", lsh); + m.insert("bits.negate", negate); + m.insert("bits.or", or); + m.insert("bits.rsh", rsh); + m.insert("bits.xor", xor); +} + +fn and(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.and"; + ensure_args_count(span, name, params, args, 2)?; + + let v1 = ensure_numeric(name, ¶ms[0], &args[0])?; + let v2 = ensure_numeric(name, ¶ms[1], &args[1])?; + + if v1 != v1.floor() || v2 != v2.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v1 = v1 as i64; + let v2 = v2 as i64; + Ok(Value::from_float((v1 & v2) as Float)) +} + +fn lsh(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.lsh"; + ensure_args_count(span, name, params, args, 2)?; + + let v1 = ensure_numeric(name, ¶ms[0], &args[0])?; + let v2 = ensure_numeric(name, ¶ms[1], &args[1])?; + + if v1 != v1.floor() || v2 != v2.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v1 = v1 as i64; + let v2 = v2 as i64; + Ok(Value::from_float((v1 << v2) as Float)) +} + +fn negate(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.negate"; + ensure_args_count(span, name, params, args, 1)?; + + let v = ensure_numeric(name, ¶ms[0], &args[0])?; + + if v != v.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v = v as i64; + Ok(Value::from_float((!v) as Float)) +} + +fn or(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.or"; + ensure_args_count(span, name, params, args, 2)?; + + let v1 = ensure_numeric(name, ¶ms[0], &args[0])?; + let v2 = ensure_numeric(name, ¶ms[1], &args[1])?; + + if v1 != v1.floor() || v2 != v2.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v1 = v1 as i64; + let v2 = v2 as i64; + Ok(Value::from_float((v1 | v2) as Float)) +} + +fn rsh(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.rsh"; + ensure_args_count(span, name, params, args, 2)?; + + let v1 = ensure_numeric(name, ¶ms[0], &args[0])?; + let v2 = ensure_numeric(name, ¶ms[1], &args[1])?; + + if v1 != v1.floor() || v2 != v2.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v1 = v1 as i64; + let v2 = v2 as i64; + Ok(Value::from_float((v1 >> v2) as Float)) +} + +fn xor(span: &Span, params: &[Expr], args: &[Value]) -> Result { + let name = "bits.xor"; + ensure_args_count(span, name, params, args, 2)?; + + let v1 = ensure_numeric(name, ¶ms[0], &args[0])?; + let v2 = ensure_numeric(name, ¶ms[1], &args[1])?; + + if v1 != v1.floor() || v2 != v2.floor() { + return Ok(Value::Undefined); + } + + // TODO: precision + let v1 = v1 as i64; + let v2 = v2 as i64; + Ok(Value::from_float((v1 ^ v2) as Float)) +} diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 5562779..aab8450 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -3,6 +3,7 @@ mod aggregates; mod arrays; +mod bitwise; pub mod comparison; mod debugging; pub mod numbers; @@ -36,7 +37,7 @@ lazy_static! { strings::register(&mut m); //regex::register(&mut m); //glob::register(&mut m); - //bitwise::register(&mut m); + bitwise::register(&mut m); //conversions::register(&mut m); //units::register(&mut m); types::register(&mut m);