Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path #308

Open
wants to merge 9 commits into
base: RWRT²
Choose a base branch
from
Open
48 changes: 48 additions & 0 deletions src/vm/builtins/builtin_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ macro_rules! impl_type {

let mut __arg_idx = 0usize;

impl_type!(@macro dict [$] $vm);
impl_type!(@macro array [$] $vm);

$(

$(
Expand Down Expand Up @@ -395,6 +398,51 @@ macro_rules! impl_type {
(@extra Key ($name:ident, $vm:ident, $args:ident, $arg_index:ident) ) => {
let $name = $args[$arg_index];
};

(@macro dict [$dollar:tt] $vm:ident) => {
macro_rules! dict {
{ $dollar($key:ident: $value:expr $dollar(,)?)* } => {
use ahash::AHashMap;
use lasso::Spur;
use crate::vm::interpreter::{ValueKey, Visibility};
let mut dict: AHashMap<Spur, (ValueKey, Visibility)> = AHashMap::new();
$dollar(
dict.insert(
$vm.intern(stringify!($key)),
(
$vm.memory.insert(StoredValue {
value: $value,
area: CodeArea {
src: crate::sources::SpwnSource::Core(Default::default()),
span: crate::sources::CodeSpan { start: 0, end: 0 }
}
}),
Visibility::Public,
)
);
)*
Value::Dict(dict)
}
}
};
(@macro array [$dollar:tt] $vm:ident) => {
macro_rules! array {
[ $dollar($value:expr $dollar(,)?)* ] => {
let mut array: Vec<$crate::vm::interpreter::ValueKey> = Vec::new();
$dollar(
array.push(
$vm.memory.insert(StoredValue {
value: $value,
area: CodeArea {
src: crate::sources::SpwnSource::Core(Default::default()),
span: crate::sources::CodeSpan { start: 0, end: 0 }
}
}),
);
)*
}
}
};
}

pub use impl_type;
44 changes: 44 additions & 0 deletions src/vm/builtins/core/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,49 @@ impl_type! {
slf.get_mut_ref(vm).insert(0, cloned);
Value::Empty
}

fn pick(Array(array) as self, quantity: Empty | Int if (>0) = {()}, Bool(duplicates) as allow_duplicates = {false}) {
use rand::prelude::*;

let mut rng = rand::thread_rng();

match quantity {
QuantityValue::Empty(_) => {
array.choose(&mut rng).map_or(Value::Maybe(None), |v| {
let value_key = vm.deep_clone_key_insert(*v);
vm.memory[value_key].value.clone()
})
},
QuantityValue::Int(q) => {
if array.is_empty() { return Ok(Value::Array(vec![])) }

if duplicates {
let mut output = vec![];
for i in 0..q.0 {
output.push(vm.deep_clone_key_insert(*array.choose(&mut rng).unwrap()))
}
Value::Array(output)
} else {
let mut cloned_array: Vec<_> = array.iter().map(|v| vm.deep_clone_key_insert(*v)).collect();
let mut output = vec![];
for i in 0..q.0.min(cloned_array.len() as i64) {
output.push(cloned_array.remove(rng.gen_range(0..cloned_array.len())))
}
Value::Array(output)
}
},
}
}

fn shuffle(Array(array) as self) {
use rand::prelude::*;

let mut rng = rand::thread_rng();

let mut cloned_array = array.iter().map(|v| vm.deep_clone_key_insert(*v)).collect::<Vec<_>>();
cloned_array.shuffle(&mut rng);

Value::Array(cloned_array)
}
}
}
31 changes: 31 additions & 0 deletions src/vm/builtins/core/builtins.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::hash::Hasher;
use std::time::SystemTime;

use crate::gd::gd_object::{GdObject, Trigger};
use crate::gd::ids::Id;
Expand Down Expand Up @@ -91,5 +92,35 @@ impl_type! {
vm.hash_value(value, &mut hasher);
Value::Int(unsafe { std::mem::transmute::<u64, i64>(hasher.finish()) })
}

fn time(Builtins as self) -> Int {
match std::time::SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(time) => Value::Float(time.as_secs_f64()),
Err(e) => {
// return Err(Runti) // not sure if there needs to be added a new error for this, idk
Value::Float(0.0)
}
}
}

fn random(Builtins as self, input: Array | Range | Empty = {()}) -> Float {
use rand::prelude::*;

let mut rng = rand::thread_rng();

match input {
InputValue::Array(array) =>
array.choose(&mut rng).map_or(Value::Maybe(None), |v| {
let value_key = vm.deep_clone_key_insert(*v);
vm.memory[value_key].value.clone()
}),
InputValue::Range(RangeDeref(start, end, step)) =>
Value::Int((start..end).step_by(step).choose(&mut rng).unwrap_or(0)),
InputValue::Empty(_) =>
Value::Float(rng.gen::<f64>()), // 0.0..1.0
_ =>
unreachable!(),
}
}
}
}
51 changes: 49 additions & 2 deletions src/vm/builtins/core/dict.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::sources::CodeArea;
use crate::vm::builtins::builtin_utils::impl_type;
use crate::vm::interpreter::Visibility;
use crate::vm::value::Value;
use crate::vm::value::{Value, StoredValue};

impl_type! {
impl Dict {
Expand All @@ -18,5 +18,52 @@ impl_type! {

// // Value::Dict(dict.clone())
// }

// what about visibility?
fn size(Dict(dict) as self) -> Int {
Value::Int(dict.len() as i64)
}

// TODO: visibility
fn keys(Dict(dict) as self) -> Array {
Value::Array(dict.keys().map(|v|
vm.memory.insert(StoredValue {
value: Value::String(vm.resolve(v).chars().collect()),
area: CodeArea { // TODO: hire a spwn dev to fix this, since I am not a spwn dev.
src: crate::sources::SpwnSource::Core(Default::default()),
span: crate::sources::CodeSpan { start: 0, end: 0 }
},
})
).collect())
}
fn values(Dict(dict) as self) -> Array {
Value::Array(dict.values().map(|v| {
vm.deep_clone_key_insert(v.0)
}).collect())
}
fn items(Dict(dict) as self) -> Array {
let mut items = vec![];

for (key, value) in &dict {
items.push(StoredValue {
value: Value::Array(vec![
vm.memory.insert(StoredValue {
value: Value::String(vm.resolve(key).chars().collect()),
area: CodeArea {
src: crate::sources::SpwnSource::Core(Default::default()),
span: crate::sources::CodeSpan { start: 0, end: 0 }
},
}),
vm.deep_clone_key_insert(value.0),
]),
area: CodeArea {
src: crate::sources::SpwnSource::Core(Default::default()),
span: crate::sources::CodeSpan { start: 0, end: 0 }
},
});
}

Value::Array(items.iter().map(|v| vm.memory.insert(v.clone())).collect())
}
}
}
5 changes: 4 additions & 1 deletion src/vm/builtins/core/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ impl_type! {
fn floor(Float(n) as self) -> Float {
Value::Float(n.floor())
}
fn trunc(Float(n) as self) -> Float {
Value::Float(n.trunc())
}

fn sqrt(Float(n) as self) -> Float {
Value::Float(n.sqrt())
}
fn log(Float(n) as self, Float(base) as base = {2.7182818284590452353602874713527}) -> Float {
fn log(Float(n) as self, Float(base) as base = {2.71828182845904523536028747135266250}) -> Float {
Value::Float(n.log(base))
}

Expand Down
13 changes: 12 additions & 1 deletion src/vm/builtins/core/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl_type! {
fn sqrt(Int(n) as self) -> Float {
Value::Float((n as f64).sqrt())
}
fn log(Int(n) as self, Float(base) as base = {2.7182818284590452353602874713527}) -> Float {
fn log(Int(n) as self, Float(base) as base = {2.71828182845904523536028747135266250}) -> Float {
Value::Float((n as f64).log(base))
}
fn clamp(Int(n) as self, Int(min) as min, Int(max) as max) -> Float {
Expand All @@ -27,5 +27,16 @@ impl_type! {
fn wrap(Int(n) as self, Int(min) as min, Int(max) as max) -> Float {
Value::Int(((n - min) % (max - min)) + min)
}
fn ordinal(Int(n) as self) -> String {
let n = n.abs();
let last_digit = n % 10;
let is_ten = n / 10 % 10 == 1;
Value::String((n.to_string() + match (last_digit, is_ten) {
(1, false) => "st",
(2, false) => "nd",
(3, false) => "rd",
(_, _) => "th",
}).chars().collect())
}
}
}
1 change: 1 addition & 0 deletions src/vm/builtins/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ pub mod error;
pub mod float;
pub mod int;
pub mod string;
pub mod path;
Loading