Implement new built-in values
This commit is contained in:
parent
f136cafb41
commit
976cb7de3f
62
Cargo.lock
generated
62
Cargo.lock
generated
@ -367,7 +367,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -396,13 +396,13 @@ checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.75"
|
||||
version = "0.1.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
|
||||
checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -574,7 +574,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -671,7 +671,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1114,7 +1114,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1135,7 +1135,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1146,7 +1146,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2125,7 +2125,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2221,7 +2221,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2401,18 +2401,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.71"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
||||
checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -2656,7 +2656,7 @@ checksum = "5a32af5427251d2e4be14fc151eabe18abb4a7aad5efee7044da9f096c906a43"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2735,14 +2735,14 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.108"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||
checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -2757,7 +2757,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2911,9 +2911,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.43"
|
||||
version = "2.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
|
||||
checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2965,22 +2965,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.52"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d"
|
||||
checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.52"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3"
|
||||
checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3108,7 +3108,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3288,7 +3288,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -3322,7 +3322,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -3917,7 +3917,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -30,11 +30,11 @@ make_guess = (cards <map>, current_room <str>) <none> {
|
||||
} else {
|
||||
output(
|
||||
'I question '
|
||||
+ random(cards:suspects)
|
||||
+ random:from(cards:suspects)
|
||||
+ ' in the '
|
||||
+ current_room
|
||||
+ ' with the '
|
||||
+ random(cards:weapons)
|
||||
+ random:from(cards:weapons)
|
||||
+ '.'
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
data = from_json(read('examples/assets/jq_data.json'))
|
||||
data = json:parse(fs:read('examples/assets/jq_data.json'))
|
||||
|
||||
new_data = []
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
foo_or_bar = match random_boolean() {
|
||||
foo_or_bar = match random:boolean() {
|
||||
true => "foo"
|
||||
false => "bar"
|
||||
}
|
||||
|
||||
num = match random_integer() {
|
||||
num = match random:integer() {
|
||||
1 => "one",
|
||||
2 => { "two" },
|
||||
* => "neither",
|
||||
|
@ -1,5 +1,5 @@
|
||||
raw_data = read('examples/assets/seaCreatures.json')
|
||||
sea_creatures = from_json(raw_data)
|
||||
raw_data = fs:read('examples/assets/seaCreatures.json')
|
||||
sea_creatures = json:parse(raw_data)
|
||||
|
||||
data = {
|
||||
creatures = []
|
||||
|
3
examples/threads.ds
Normal file
3
examples/threads.ds
Normal file
@ -0,0 +1,3 @@
|
||||
handle = thread:spawn("my_thread", {
|
||||
|
||||
})
|
@ -83,8 +83,6 @@ impl AbstractTree for Assignment {
|
||||
AssignmentOperator::Equal => {}
|
||||
AssignmentOperator::PlusEqual => {
|
||||
if let Type::List(item_type) = identifier_type {
|
||||
println!("{item_type} {statement_type}");
|
||||
|
||||
item_type
|
||||
.check(&statement_type)
|
||||
.map_err(|error| error.at_node(statement_node, source))?;
|
||||
|
@ -6,12 +6,16 @@ use tree_sitter::Node;
|
||||
use crate::{AbstractTree, BuiltInFunction, Function, List, Map, Result, Type, Value};
|
||||
|
||||
static ARGS: OnceLock<Value> = OnceLock::new();
|
||||
static FS: OnceLock<Value> = OnceLock::new();
|
||||
static JSON: OnceLock<Value> = OnceLock::new();
|
||||
static RANDOM: OnceLock<Value> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum BuiltInValue {
|
||||
Args,
|
||||
AssertEqual,
|
||||
Fs,
|
||||
Json,
|
||||
Length,
|
||||
Output,
|
||||
Random,
|
||||
@ -22,6 +26,8 @@ impl BuiltInValue {
|
||||
match self {
|
||||
BuiltInValue::Args => Type::list_of(Type::String),
|
||||
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
|
||||
BuiltInValue::Fs => Type::Map,
|
||||
BuiltInValue::Json => Type::Map,
|
||||
BuiltInValue::Length => BuiltInFunction::Length.r#type(),
|
||||
BuiltInValue::Output => BuiltInFunction::Output.r#type(),
|
||||
BuiltInValue::Random => Type::Map,
|
||||
@ -38,6 +44,32 @@ impl BuiltInValue {
|
||||
BuiltInValue::AssertEqual => {
|
||||
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
|
||||
}
|
||||
BuiltInValue::Fs => FS.get_or_init(|| {
|
||||
let fs_context = Map::new();
|
||||
|
||||
fs_context
|
||||
.set(
|
||||
"read".to_string(),
|
||||
Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Value::Map(fs_context)
|
||||
}),
|
||||
BuiltInValue::Json => JSON.get_or_init(|| {
|
||||
let json_context = Map::new();
|
||||
|
||||
json_context
|
||||
.set(
|
||||
"parse".to_string(),
|
||||
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Value::Map(json_context)
|
||||
}),
|
||||
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
|
||||
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
|
||||
BuiltInValue::Random => RANDOM.get_or_init(|| {
|
||||
@ -46,7 +78,12 @@ impl BuiltInValue {
|
||||
{
|
||||
let mut variables = random_context.variables_mut().unwrap();
|
||||
|
||||
for built_in_function in [BuiltInFunction::RandomBoolean] {
|
||||
for built_in_function in [
|
||||
BuiltInFunction::RandomBoolean,
|
||||
BuiltInFunction::RandomFloat,
|
||||
BuiltInFunction::RandomFrom,
|
||||
BuiltInFunction::RandomInteger,
|
||||
] {
|
||||
let key = built_in_function.name().to_string();
|
||||
let value = Value::Function(Function::BuiltIn(built_in_function));
|
||||
let r#type = built_in_function.r#type();
|
||||
@ -66,6 +103,8 @@ impl AbstractTree for BuiltInValue {
|
||||
let built_in_value = match node.kind() {
|
||||
"args" => BuiltInValue::Args,
|
||||
"assert_equal" => BuiltInValue::AssertEqual,
|
||||
"fs" => BuiltInValue::Fs,
|
||||
"json" => BuiltInValue::Json,
|
||||
"length" => BuiltInValue::Length,
|
||||
"output" => BuiltInValue::Output,
|
||||
"random" => BuiltInValue::Random,
|
||||
|
@ -78,13 +78,13 @@ impl AbstractTree for FunctionCall {
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||
let value = match &self.function_expression {
|
||||
let (name, value) = match &self.function_expression {
|
||||
FunctionExpression::Identifier(identifier) => {
|
||||
let key = identifier.inner();
|
||||
let variables = context.variables()?;
|
||||
|
||||
if let Some((value, _)) = variables.get(key) {
|
||||
value.clone()
|
||||
(Some(key.clone()), value.clone())
|
||||
} else {
|
||||
return Err(Error::FunctionIdentifierNotFound(
|
||||
identifier.inner().clone(),
|
||||
@ -92,11 +92,11 @@ impl AbstractTree for FunctionCall {
|
||||
}
|
||||
}
|
||||
FunctionExpression::FunctionCall(function_call) => {
|
||||
function_call.run(source, context)?
|
||||
(None, function_call.run(source, context)?)
|
||||
}
|
||||
FunctionExpression::Value(value_node) => value_node.run(source, context)?,
|
||||
FunctionExpression::Index(index) => index.run(source, context)?,
|
||||
FunctionExpression::Yield(r#yield) => r#yield.run(source, context)?,
|
||||
FunctionExpression::Value(value_node) => (None, value_node.run(source, context)?),
|
||||
FunctionExpression::Index(index) => (None, index.run(source, context)?),
|
||||
FunctionExpression::Yield(r#yield) => (None, r#yield.run(source, context)?),
|
||||
};
|
||||
|
||||
let mut arguments = Vec::with_capacity(self.arguments.len());
|
||||
@ -107,7 +107,18 @@ impl AbstractTree for FunctionCall {
|
||||
arguments.push(value);
|
||||
}
|
||||
|
||||
value.as_function()?.call(&arguments, source, context)
|
||||
if let Some(name) = &name {
|
||||
context.set(name.to_string(), value.clone(), None)?;
|
||||
}
|
||||
|
||||
value
|
||||
.as_function()
|
||||
.map_err(|error| {
|
||||
println!("{name:?}");
|
||||
|
||||
error
|
||||
})?
|
||||
.call(name, &arguments, source, context)
|
||||
}
|
||||
|
||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||
|
@ -1,9 +1,6 @@
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
fs::read_to_string,
|
||||
};
|
||||
use std::fs::read_to_string;
|
||||
|
||||
use rand::random;
|
||||
use rand::{random, thread_rng, Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Error, Map, Result, Type, Value};
|
||||
@ -12,19 +9,27 @@ use crate::{Error, Map, Result, Type, Value};
|
||||
pub enum BuiltInFunction {
|
||||
AssertEqual,
|
||||
FsRead,
|
||||
JsonParse,
|
||||
Length,
|
||||
Output,
|
||||
RandomBoolean,
|
||||
Length,
|
||||
RandomFloat,
|
||||
RandomFrom,
|
||||
RandomInteger,
|
||||
}
|
||||
|
||||
impl BuiltInFunction {
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
BuiltInFunction::AssertEqual => "assert_equal",
|
||||
BuiltInFunction::FsRead => "fs_read",
|
||||
BuiltInFunction::FsRead => "read",
|
||||
BuiltInFunction::JsonParse => "parse",
|
||||
BuiltInFunction::Length => "length",
|
||||
BuiltInFunction::Output => "output",
|
||||
BuiltInFunction::RandomBoolean => "boolean",
|
||||
BuiltInFunction::Length => "length",
|
||||
BuiltInFunction::RandomFloat => "float",
|
||||
BuiltInFunction::RandomFrom => "from",
|
||||
BuiltInFunction::RandomInteger => "integer",
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,9 +37,13 @@ impl BuiltInFunction {
|
||||
match self {
|
||||
BuiltInFunction::AssertEqual => Type::function(vec![Type::Any, Type::Any], Type::None),
|
||||
BuiltInFunction::FsRead => Type::function(vec![Type::String], Type::String),
|
||||
BuiltInFunction::JsonParse => Type::function(vec![Type::String], Type::Any),
|
||||
BuiltInFunction::Length => Type::function(vec![Type::Collection], Type::Integer),
|
||||
BuiltInFunction::Output => Type::function(vec![Type::Any], Type::None),
|
||||
BuiltInFunction::RandomBoolean => Type::function(vec![], Type::Boolean),
|
||||
BuiltInFunction::Length => Type::function(vec![Type::Collection], Type::Integer),
|
||||
BuiltInFunction::RandomFloat => Type::function(vec![], Type::Float),
|
||||
BuiltInFunction::RandomFrom => Type::function(vec![Type::Collection], Type::Any),
|
||||
BuiltInFunction::RandomInteger => Type::function(vec![], Type::Integer),
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,19 +65,13 @@ impl BuiltInFunction {
|
||||
|
||||
Ok(Value::String(file_content))
|
||||
}
|
||||
BuiltInFunction::Output => {
|
||||
BuiltInFunction::JsonParse => {
|
||||
Error::expect_argument_amount(self, 1, arguments.len())?;
|
||||
|
||||
let value = arguments.first().unwrap();
|
||||
let string = arguments.first().unwrap().as_string()?;
|
||||
let value = serde_json::from_str(&string)?;
|
||||
|
||||
println!("{value}");
|
||||
|
||||
Ok(Value::none())
|
||||
}
|
||||
BuiltInFunction::RandomBoolean => {
|
||||
Error::expect_argument_amount(self, 0, arguments.len())?;
|
||||
|
||||
Ok(Value::Boolean(random()))
|
||||
Ok(value)
|
||||
}
|
||||
BuiltInFunction::Length => {
|
||||
Error::expect_argument_amount(self, 1, arguments.len())?;
|
||||
@ -88,12 +91,50 @@ impl BuiltInFunction {
|
||||
|
||||
Ok(Value::Integer(length as i64))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BuiltInFunction::Output => {
|
||||
Error::expect_argument_amount(self, 1, arguments.len())?;
|
||||
|
||||
impl Display for BuiltInFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.r#type())
|
||||
let value = arguments.first().unwrap();
|
||||
|
||||
println!("{value}");
|
||||
|
||||
Ok(Value::none())
|
||||
}
|
||||
BuiltInFunction::RandomBoolean => {
|
||||
Error::expect_argument_amount(self, 0, arguments.len())?;
|
||||
|
||||
Ok(Value::Boolean(random()))
|
||||
}
|
||||
BuiltInFunction::RandomFloat => {
|
||||
Error::expect_argument_amount(self, 0, arguments.len())?;
|
||||
|
||||
Ok(Value::Float(random()))
|
||||
}
|
||||
BuiltInFunction::RandomFrom => {
|
||||
Error::expect_argument_amount(self, 1, arguments.len())?;
|
||||
|
||||
let value = arguments.first().unwrap();
|
||||
|
||||
if let Ok(list) = value.as_list() {
|
||||
let items = list.items();
|
||||
|
||||
if items.len() == 0 {
|
||||
Ok(Value::none())
|
||||
} else {
|
||||
let random_index = thread_rng().gen_range(0..items.len());
|
||||
let random_value = items.get(random_index).cloned().unwrap_or_default();
|
||||
|
||||
Ok(random_value)
|
||||
}
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
BuiltInFunction::RandomInteger => {
|
||||
Error::expect_argument_amount(self, 0, arguments.len())?;
|
||||
|
||||
Ok(Value::Integer(random()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,20 +17,28 @@ pub enum Function {
|
||||
impl Display for Function {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Function::BuiltIn(inner) => write!(f, "{inner}"),
|
||||
Function::ContextDefined(inner) => write!(f, "{inner}"),
|
||||
Function::BuiltIn(built_in_function) => write!(f, "{}", built_in_function.r#type()),
|
||||
Function::ContextDefined(context_defined_function) => {
|
||||
write!(f, "{}", context_defined_function.r#type())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn call(&self, arguments: &[Value], source: &str, outer_context: &Map) -> Result<Value> {
|
||||
pub fn call(
|
||||
&self,
|
||||
name: Option<String>,
|
||||
arguments: &[Value],
|
||||
source: &str,
|
||||
outer_context: &Map,
|
||||
) -> Result<Value> {
|
||||
match self {
|
||||
Function::BuiltIn(built_in_function) => {
|
||||
built_in_function.call(arguments, source, outer_context)
|
||||
}
|
||||
Function::ContextDefined(context_defined_function) => {
|
||||
context_defined_function.call(arguments, source, outer_context)
|
||||
context_defined_function.call(name, arguments, source, outer_context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,15 +98,10 @@ impl AbstractTree for Function {
|
||||
.check(&body.expected_type(&function_context)?)
|
||||
.map_err(|error| error.at_node(body_node, source))?;
|
||||
|
||||
let r#type = Type::Function {
|
||||
parameter_types,
|
||||
return_type: Box::new(return_type.take_inner()),
|
||||
};
|
||||
let r#type = Type::function(parameter_types, return_type.take_inner());
|
||||
|
||||
Ok(Self::ContextDefined(ContextDefinedFunction::new(
|
||||
parameters,
|
||||
body,
|
||||
Some(r#type),
|
||||
parameters, body, r#type,
|
||||
)))
|
||||
}
|
||||
|
||||
@ -122,12 +125,7 @@ pub struct ContextDefinedFunction {
|
||||
}
|
||||
|
||||
impl ContextDefinedFunction {
|
||||
pub fn new(parameters: Vec<Identifier>, body: Block, r#type: Option<Type>) -> Self {
|
||||
let r#type = r#type.unwrap_or(Type::Function {
|
||||
parameter_types: vec![Type::Any; parameters.len()],
|
||||
return_type: Box::new(Type::Any),
|
||||
});
|
||||
|
||||
pub fn new(parameters: Vec<Identifier>, body: Block, r#type: Type) -> Self {
|
||||
Self {
|
||||
parameters,
|
||||
body,
|
||||
@ -157,49 +155,32 @@ impl ContextDefinedFunction {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&self, arguments: &[Value], source: &str, outer_context: &Map) -> Result<Value> {
|
||||
let context = Map::clone_from(outer_context)?;
|
||||
pub fn call(
|
||||
&self,
|
||||
name: Option<String>,
|
||||
arguments: &[Value],
|
||||
source: &str,
|
||||
outer_context: &Map,
|
||||
) -> Result<Value> {
|
||||
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
|
||||
let function_context = Map::clone_from(outer_context)?;
|
||||
|
||||
for (identifier, value) in parameter_argument_pairs {
|
||||
let key = identifier.inner().clone();
|
||||
|
||||
context.set(key, value.clone(), None)?;
|
||||
function_context.set(key, value.clone(), None)?;
|
||||
}
|
||||
|
||||
let return_value = self.body.run(source, &context)?;
|
||||
if let Some(name) = name {
|
||||
function_context.set(
|
||||
name,
|
||||
Value::Function(Function::ContextDefined(self.clone())),
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
|
||||
let return_value = self.body.run(source, &function_context)?;
|
||||
|
||||
Ok(return_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ContextDefinedFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(")?;
|
||||
|
||||
let (parameter_types, return_type) = if let Type::Function {
|
||||
parameter_types,
|
||||
return_type,
|
||||
} = &self.r#type
|
||||
{
|
||||
(parameter_types, return_type)
|
||||
} else {
|
||||
return Err(fmt::Error);
|
||||
};
|
||||
|
||||
for (index, (parameter, r#type)) in self
|
||||
.parameters
|
||||
.iter()
|
||||
.zip(parameter_types.iter())
|
||||
.enumerate()
|
||||
{
|
||||
write!(f, "{} <{}>", parameter.inner(), r#type)?;
|
||||
|
||||
if index != self.parameters.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, ") -> {}", return_type)
|
||||
}
|
||||
}
|
||||
|
@ -514,14 +514,11 @@ mod blocks {
|
||||
}
|
||||
}
|
||||
|
||||
mod std {
|
||||
mod built_in_values {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn load_std() {
|
||||
assert_eq!(
|
||||
interpret("std:read"),
|
||||
Ok(Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)))
|
||||
);
|
||||
fn args() {
|
||||
assert!(interpret("args").is_ok_and(|value| value.is_list()));
|
||||
}
|
||||
}
|
||||
|
@ -441,6 +441,8 @@ module.exports = grammar({
|
||||
'args',
|
||||
'assert_equal',
|
||||
'env',
|
||||
'fs',
|
||||
'json',
|
||||
'length',
|
||||
'output',
|
||||
'random',
|
||||
|
@ -1412,6 +1412,14 @@
|
||||
"type": "STRING",
|
||||
"value": "env"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "fs"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "json"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "length"
|
||||
|
@ -804,6 +804,10 @@
|
||||
"type": "for",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "fs",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
@ -824,6 +828,10 @@
|
||||
"type": "integer",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "json",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "length",
|
||||
"named": false
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user