bitwise builtins

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2023-03-04 04:38:34 -08:00
committed by Anand Krishnamoorthi
parent ec695bd22e
commit 81f6199642
2 changed files with 124 additions and 1 deletions
+122
View File
@@ -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<Value> {
let name = "bits.and";
ensure_args_count(span, name, params, args, 2)?;
let v1 = ensure_numeric(name, &params[0], &args[0])?;
let v2 = ensure_numeric(name, &params[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<Value> {
let name = "bits.lsh";
ensure_args_count(span, name, params, args, 2)?;
let v1 = ensure_numeric(name, &params[0], &args[0])?;
let v2 = ensure_numeric(name, &params[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<Value> {
let name = "bits.negate";
ensure_args_count(span, name, params, args, 1)?;
let v = ensure_numeric(name, &params[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<Value> {
let name = "bits.or";
ensure_args_count(span, name, params, args, 2)?;
let v1 = ensure_numeric(name, &params[0], &args[0])?;
let v2 = ensure_numeric(name, &params[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<Value> {
let name = "bits.rsh";
ensure_args_count(span, name, params, args, 2)?;
let v1 = ensure_numeric(name, &params[0], &args[0])?;
let v2 = ensure_numeric(name, &params[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<Value> {
let name = "bits.xor";
ensure_args_count(span, name, params, args, 2)?;
let v1 = ensure_numeric(name, &params[0], &args[0])?;
let v2 = ensure_numeric(name, &params[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))
}
+2 -1
View File
@@ -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);