Implement context

This commit is contained in:
Jeff 2024-02-10 20:50:49 -05:00
parent d997bbd08a
commit 90c0304af5
16 changed files with 105 additions and 265 deletions

View File

@ -114,12 +114,11 @@ impl BuiltInValue {
let key = fs_function.name().to_string(); let key = fs_function.name().to_string();
let value = let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function)));
let r#type = value.r#type();
fs_context.insert(key, (value, r#type)); fs_context.insert(key, value);
} }
Value::Map(Map::with_variables(fs_context)) Value::Map(Map::with_values(fs_context))
}), }),
BuiltInValue::Json => JSON.get_or_init(|| { BuiltInValue::Json => JSON.get_or_init(|| {
let mut json_context = BTreeMap::new(); let mut json_context = BTreeMap::new();
@ -128,12 +127,11 @@ impl BuiltInValue {
let key = json_function.name().to_string(); let key = json_function.name().to_string();
let value = let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function))); Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function)));
let r#type = value.r#type();
json_context.insert(key, (value, r#type)); json_context.insert(key, value);
} }
Value::Map(Map::with_variables(json_context)) Value::Map(Map::with_values(json_context))
}), }),
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
@ -148,12 +146,11 @@ impl BuiltInValue {
] { ] {
let key = built_in_function.name().to_string(); let key = built_in_function.name().to_string();
let value = Value::Function(Function::BuiltIn(built_in_function)); let value = Value::Function(Function::BuiltIn(built_in_function));
let r#type = built_in_function.r#type();
random_context.insert(key, (value, r#type)); random_context.insert(key, value);
} }
Value::Map(Map::with_variables(random_context)) Value::Map(Map::with_values(random_context))
}), }),
BuiltInValue::Str => STRING.get_or_init(|| { BuiltInValue::Str => STRING.get_or_init(|| {
let mut string_context = BTreeMap::new(); let mut string_context = BTreeMap::new();
@ -163,12 +160,11 @@ impl BuiltInValue {
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function, string_function,
))); )));
let r#type = string_function.r#type();
string_context.insert(key, (value, r#type)); string_context.insert(key, value);
} }
Value::Map(Map::with_variables(string_context)) Value::Map(Map::with_values(string_context))
}), }),
} }
} }

View File

@ -86,21 +86,13 @@ impl AbstractTree for Index {
Value::Map(map) => { Value::Map(map) => {
let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index { let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index {
let key = identifier.inner(); let key = identifier.inner();
let value = map let value = map.get(key).unwrap_or_default();
.variables()?
.get(key)
.map(|(value, _)| value.clone())
.unwrap_or_default();
(key.clone(), value) (key.clone(), value)
} else { } else {
let index_value = self.index.run(source, context)?; let index_value = self.index.run(source, context)?;
let key = index_value.as_string()?; let key = index_value.as_string()?;
let value = map let value = map.get(key.as_str()).unwrap_or_default();
.variables()?
.get(key.as_str())
.map(|(value, _)| value.clone())
.unwrap_or_default();
(key.clone(), value) (key.clone(), value)
}; };
@ -108,7 +100,7 @@ impl AbstractTree for Index {
if value.is_none() { if value.is_none() {
Err(RuntimeError::VariableIdentifierNotFound(key)) Err(RuntimeError::VariableIdentifierNotFound(key))
} else { } else {
Ok(value) Ok(value.clone())
} }
} }
Value::String(string) => { Value::String(string) => {

View File

@ -43,7 +43,7 @@ impl AbstractTree for IndexAssignment {
} }
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> { fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let index_collection = self.index.collection.run(source, context)?; let _index_collection = self.index.collection.run(source, context)?;
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index { let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier.inner() identifier.inner()
} else { } else {

View File

@ -242,7 +242,7 @@ impl AbstractTree for ValueNode {
} }
} }
ValueNode::Map(statements, source_position) => { ValueNode::Map(statements, source_position) => {
for (key, (statement, r#type)) in statements { for (_key, (statement, r#type)) in statements {
if let Some(expected) = r#type { if let Some(expected) = r#type {
let actual = statement.expected_type(context)?; let actual = statement.expected_type(context)?;
@ -294,13 +294,13 @@ impl AbstractTree for ValueNode {
Value::Option(option_value) Value::Option(option_value)
} }
ValueNode::Map(key_statement_pairs, _) => { ValueNode::Map(key_statement_pairs, _) => {
let map = Map::new(); let mut map = Map::new();
{ {
for (key, (statement, _)) in key_statement_pairs { for (key, (statement, _)) in key_statement_pairs {
let value = statement.run(source, context)?; let value = statement.run(source, context)?;
map.set(key.clone(), value)?; map.set(key.clone(), value);
} }
} }

View File

@ -111,7 +111,7 @@ impl Callable for BuiltInFunction {
let length = if let Ok(list) = value.as_list() { let length = if let Ok(list) = value.as_list() {
list.items().len() list.items().len()
} else if let Ok(map) = value.as_map() { } else if let Ok(map) = value.as_map() {
map.variables()?.len() map.len()
} else if let Ok(str) = value.as_string() { } else if let Ok(str) = value.as_string() {
str.chars().count() str.chars().count()
} else { } else {

View File

@ -1,6 +1,6 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
sync::{Arc, RwLock}, sync::{Arc, RwLock, RwLockReadGuard},
}; };
use crate::{error::rw_lock_error::RwLockError, Type, Value}; use crate::{error::rw_lock_error::RwLockError, Type, Value};
@ -16,6 +16,7 @@ pub enum ValueData {
}, },
} }
#[derive(Clone)]
pub struct Context { pub struct Context {
inner: Arc<RwLock<HashMap<String, ValueData>>>, inner: Arc<RwLock<HashMap<String, ValueData>>>,
} }
@ -27,6 +28,10 @@ impl Context {
} }
} }
pub fn inner(&self) -> Result<RwLockReadGuard<HashMap<String, ValueData>>, RwLockError> {
Ok(self.inner.read()?)
}
pub fn inherit_from(other: &Context) -> Result<Context, RwLockError> { pub fn inherit_from(other: &Context) -> Result<Context, RwLockError> {
let mut new_variables = HashMap::new(); let mut new_variables = HashMap::new();

View File

@ -11,7 +11,7 @@ pub use runtime_error::RuntimeError;
pub use syntax_error::SyntaxError; pub use syntax_error::SyntaxError;
pub use validation_error::ValidationError; pub use validation_error::ValidationError;
use tree_sitter::{LanguageError, Point}; use tree_sitter::LanguageError;
use std::fmt::{self, Formatter}; use std::fmt::{self, Formatter};
@ -69,11 +69,7 @@ impl fmt::Display for Error {
Validation(error) => write!(f, "Validation error: {error}"), Validation(error) => write!(f, "Validation error: {error}"),
Runtime(error) => write!(f, "Runtime error: {error}"), Runtime(error) => write!(f, "Runtime error: {error}"),
ParserCancelled => write!(f, "Parsing was cancelled because the parser took too long."), ParserCancelled => write!(f, "Parsing was cancelled because the parser took too long."),
Language(error) => write!(f, "Parser failed to load language grammar."), Language(_error) => write!(f, "Parser failed to load language grammar."),
} }
} }
} }
fn get_position(position: &Point) -> String {
format!("column {}, row {}", position.row + 1, position.column)
}

View File

@ -5,8 +5,12 @@
//! You can use this library externally by calling either of the "interpret" //! You can use this library externally by calling either of the "interpret"
//! functions or by constructing your own Interpreter. //! functions or by constructing your own Interpreter.
pub use crate::{ pub use crate::{
abstract_tree::*, built_in_functions::BuiltInFunction, context::Context, error::Error, abstract_tree::*,
interpret::*, value::*, built_in_functions::BuiltInFunction,
context::{Context, ValueData},
error::Error,
interpret::*,
value::*,
}; };
pub use tree_sitter::Node as SyntaxNode; pub use tree_sitter::Node as SyntaxNode;

View File

@ -11,7 +11,7 @@ use reedline::{
use std::{borrow::Cow, fs::read_to_string, path::PathBuf, process::Command}; use std::{borrow::Cow, fs::read_to_string, path::PathBuf, process::Command};
use dust_lang::{built_in_values, Error, Interpreter, Map, Value}; use dust_lang::{built_in_values, Context, Error, Interpreter, Value, ValueData};
/// Command-line arguments to be parsed. /// Command-line arguments to be parsed.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -50,11 +50,11 @@ fn main() {
env_logger::init(); env_logger::init();
let args = Args::parse(); let args = Args::parse();
let context = Map::new(); let context = Context::new();
if let Some(input) = args.input { if let Some(input) = args.input {
context context
.set("input".to_string(), Value::string(input)) .set_value("input".to_string(), Value::string(input))
.unwrap(); .unwrap();
} }
@ -62,7 +62,7 @@ fn main() {
let file_contents = read_to_string(path).unwrap(); let file_contents = read_to_string(path).unwrap();
context context
.set("input".to_string(), Value::string(file_contents)) .set_value("input".to_string(), Value::string(file_contents))
.unwrap(); .unwrap();
} }
@ -117,11 +117,11 @@ fn main() {
} }
struct DustHighlighter { struct DustHighlighter {
context: Map, context: Context,
} }
impl DustHighlighter { impl DustHighlighter {
fn new(context: Map) -> Self { fn new(context: Context) -> Self {
Self { context } Self { context }
} }
} }
@ -130,36 +130,27 @@ const HIGHLIGHT_TERMINATORS: [char; 8] = [' ', ':', '(', ')', '{', '}', '[', ']'
impl Highlighter for DustHighlighter { impl Highlighter for DustHighlighter {
fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText { fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText {
fn highlight_identifier(styled: &mut StyledText, word: &str, map: &Map) -> bool { let mut styled = StyledText::new();
for (key, (value, _type)) in map.variables().unwrap().iter() {
for word in line.split_inclusive(&HIGHLIGHT_TERMINATORS) {
let mut word_is_highlighted = false;
for key in self.context.inner().unwrap().keys() {
if key == &word { if key == &word {
styled.push((Style::new().bold(), word.to_string())); styled.push((Style::new().bold(), word.to_string()));
return true;
} }
if let Value::Map(nested_map) = value { word_is_highlighted = true;
return highlight_identifier(styled, word, nested_map);
}
} }
for built_in_value in built_in_values() { for built_in_value in built_in_values() {
if built_in_value.name() == word { if built_in_value.name() == word {
styled.push((Style::new().bold(), word.to_string())); styled.push((Style::new().bold(), word.to_string()));
return true;
} }
word_is_highlighted = true;
} }
false
}
let mut styled = StyledText::new();
for word in line.split_inclusive(&HIGHLIGHT_TERMINATORS) {
let word_is_highlighted =
highlight_identifier(&mut styled, &word[0..word.len() - 1], &self.context);
if word_is_highlighted { if word_is_highlighted {
let final_char = word.chars().last().unwrap(); let final_char = word.chars().last().unwrap();
@ -239,11 +230,11 @@ impl Prompt for StarshipPrompt {
} }
pub struct DustCompleter { pub struct DustCompleter {
context: Map, context: Context,
} }
impl DustCompleter { impl DustCompleter {
fn new(context: Map) -> Self { fn new(context: Context) -> Self {
DustCompleter { context } DustCompleter { context }
} }
} }
@ -302,7 +293,7 @@ impl Completer for DustCompleter {
} }
if let Value::Map(map) = built_in_value.get() { if let Value::Map(map) = built_in_value.get() {
for (key, (value, _type)) in map.variables().unwrap().iter() { for (key, value) in map.iter() {
if key.contains(last_word) { if key.contains(last_word) {
suggestions.push(Suggestion { suggestions.push(Suggestion {
value: format!("{name}:{key}"), value: format!("{name}:{key}"),
@ -316,7 +307,12 @@ impl Completer for DustCompleter {
} }
} }
for (key, (value, _type)) in self.context.variables().unwrap().iter() { for (key, value_data) in self.context.inner().unwrap().iter() {
let value = match value_data {
ValueData::Value { inner, .. } => inner,
ValueData::ExpectedType { .. } => continue,
};
if key.contains(last_word) { if key.contains(last_word) {
suggestions.push(Suggestion { suggestions.push(Suggestion {
value: key.to_string(), value: key.to_string(),
@ -332,7 +328,7 @@ impl Completer for DustCompleter {
} }
} }
fn run_shell(context: Map) -> Result<(), Error> { fn run_shell(context: Context) -> Result<(), Error> {
let mut interpreter = Interpreter::new(context.clone()); let mut interpreter = Interpreter::new(context.clone());
let mut keybindings = default_emacs_keybindings(); let mut keybindings = default_emacs_keybindings();

View File

@ -1,136 +1,73 @@
use serde::{ use serde::{Deserialize, Serialize};
de::{MapAccess, Visitor},
ser::SerializeMap,
Deserialize, Serialize,
};
use stanza::{ use stanza::{
renderer::{console::Console, Renderer}, renderer::{console::Console, Renderer},
style::{HAlign, Styles}, style::{HAlign, Styles},
table::{Row, Table}, table::{Row, Table},
}; };
use std::{ use std::{
cmp::Ordering,
collections::BTreeMap, collections::BTreeMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
marker::PhantomData,
sync::{Arc, RwLock, RwLockReadGuard},
}; };
use crate::{error::rw_lock_error::RwLockError, value::Value, Structure, Type}; use crate::value::Value;
/// A collection dust variables comprised of key-value pairs. /// A collection dust variables comprised of key-value pairs.
/// ///
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared /// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
/// to one another. /// to one another.
#[derive(Clone, Debug)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Map { pub struct Map {
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>, inner: BTreeMap<String, Value>,
structure: Option<Structure>,
} }
impl Map { impl Map {
/// Creates a new instace. /// Creates a new instace.
pub fn new() -> Self { pub fn new() -> Self {
Map { Map {
variables: Arc::new(RwLock::new(BTreeMap::new())), inner: BTreeMap::new(),
structure: None,
} }
} }
pub fn from_structure(structure: Structure) -> Self { pub fn with_values(variables: BTreeMap<String, Value>) -> Self {
let mut variables = BTreeMap::new(); Map { inner: variables }
for (key, (value_option, r#type)) in structure.inner() {
variables.insert(
key.clone(),
(
value_option.clone().unwrap_or(Value::none()),
r#type.clone(),
),
);
}
Map {
variables: Arc::new(RwLock::new(variables)),
structure: Some(structure),
}
} }
pub fn with_variables(variables: BTreeMap<String, (Value, Type)>) -> Self { pub fn len(&self) -> usize {
Map { self.inner.len()
variables: Arc::new(RwLock::new(variables)),
structure: None,
}
} }
pub fn clone_from(other: &Self) -> Result<Self, RwLockError> { pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
let mut new_map = BTreeMap::new(); self.inner.iter()
for (key, (value, r#type)) in other.variables()?.iter() {
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
}
Ok(Map {
variables: Arc::new(RwLock::new(new_map)),
structure: other.structure.clone(),
})
} }
pub fn variables( pub fn get(&self, key: &str) -> Option<&Value> {
&self, self.inner.get(key)
) -> Result<RwLockReadGuard<BTreeMap<String, (Value, Type)>>, RwLockError> {
self.variables.read().map_err(|_| RwLockError)
} }
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>, RwLockError> { pub fn set(&mut self, key: String, value: Value) {
log::info!("Setting variable {key} = {value}"); self.inner.insert(key, value);
let value_type = value.r#type();
let previous = self
.variables
.write()?
.insert(key, (value, value_type.clone()));
Ok(previous)
}
pub fn set_type(
&self,
key: String,
r#type: Type,
) -> Result<Option<(Value, Type)>, RwLockError> {
log::info!("Setting type {key} = {}", r#type);
let previous = self
.variables
.write()
.map_err(|_| RwLockError)?
.insert(key, (Value::none(), r#type));
Ok(previous)
} }
pub fn as_text_table(&self) -> Table { pub fn as_text_table(&self) -> Table {
let variables = self.variables.read().unwrap().clone().into_iter();
let mut table = Table::with_styles(Styles::default().with(HAlign::Centred)); let mut table = Table::with_styles(Styles::default().with(HAlign::Centred));
for (key, (value, r#type)) in variables { for (key, value) in &self.inner {
if let Value::Map(map) = value { if let Value::Map(map) = value {
table.push_row(Row::new(
Styles::default(),
vec![key.into(), map.as_text_table().into(), "".into()],
));
} else if let Value::List(list) = value {
table.push_row(Row::new( table.push_row(Row::new(
Styles::default(), Styles::default(),
vec![ vec![
key.into(), key.into(),
list.as_text_table().into(), map.as_text_table().into(),
r#type.to_string().into(), "".to_string().into(),
], ],
)); ));
} else if let Value::List(list) = value {
table.push_row(Row::new(
Styles::default(),
vec![key.into(), list.as_text_table().into()],
));
} else { } else {
table.push_row([key, value.to_string(), r#type.to_string()]); table.push_row([key, &value.to_string()]);
}; };
} }
@ -148,32 +85,6 @@ impl Default for Map {
} }
} }
impl Eq for Map {}
impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
left.eq(right)
}
}
impl Ord for Map {
fn cmp(&self, other: &Self) -> Ordering {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
left.cmp(right)
}
}
impl PartialOrd for Map {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Display for Map { impl Display for Map {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let renderer = Console::default(); let renderer = Console::default();
@ -181,63 +92,3 @@ impl Display for Map {
f.write_str(&renderer.render(&self.as_text_table())) f.write_str(&renderer.render(&self.as_text_table()))
} }
} }
impl Serialize for Map {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let variables = self.variables.read().unwrap();
let mut map = serializer.serialize_map(Some(variables.len()))?;
for (key, (value, _type)) in variables.iter() {
map.serialize_entry(key, value)?;
}
map.end()
}
}
struct MapVisitor {
marker: PhantomData<fn() -> Map>,
}
impl MapVisitor {
fn new() -> Self {
MapVisitor {
marker: PhantomData,
}
}
}
impl<'de> Visitor<'de> for MapVisitor {
type Value = Map;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("key-value pairs")
}
fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error>
where
M: MapAccess<'de>,
{
let map = Map::new();
{
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value).unwrap();
}
}
Ok(map)
}
}
impl<'de> Deserialize<'de> for Map {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(MapVisitor::new())
}
}

View File

@ -82,7 +82,7 @@ impl Value {
Value::Map(map) => { Value::Map(map) => {
let mut identifier_types = Vec::new(); let mut identifier_types = Vec::new();
for (key, (value, _)) in map.variables().unwrap().iter() { for (key, value) in map.iter() {
identifier_types.push(( identifier_types.push((
Identifier::new(key.clone()), Identifier::new(key.clone()),
TypeSpecification::new(value.r#type()), TypeSpecification::new(value.r#type()),
@ -858,10 +858,10 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
let map = Map::new(); let mut map = Map::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? { while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value).unwrap(); map.set(key, value);
} }
Ok(Value::Map(map)) Ok(Value::Map(map))

View File

@ -92,10 +92,10 @@ fn modify_map() {
", ",
); );
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)).unwrap(); map.set("x".to_string(), Value::Integer(1));
map.set("y".to_string(), Value::Integer(2)).unwrap(); map.set("y".to_string(), Value::Integer(2));
assert_eq!(Ok(Value::Map(map)), result); assert_eq!(Ok(Value::Map(map)), result);
} }
@ -137,10 +137,10 @@ fn modify_map_values() {
", ",
); );
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)).unwrap(); map.set("x".to_string(), Value::Integer(1));
map.set("y".to_string(), Value::Integer(2)).unwrap(); map.set("y".to_string(), Value::Integer(2));
assert_eq!(Ok(Value::Map(map)), result); assert_eq!(Ok(Value::Map(map)), result);
} }

View File

@ -2,7 +2,7 @@ use dust_lang::*;
#[test] #[test]
fn format_simple_program() { fn format_simple_program() {
let mut interpreter = Interpreter::new(Map::new()); let mut interpreter = Interpreter::new(Context::new());
assert_eq!(interpreter.format("x=1"), Ok("x = 1\n".to_string())); assert_eq!(interpreter.format("x=1"), Ok("x = 1\n".to_string()));
} }
@ -16,7 +16,7 @@ const FORMATTED_BLOCK: &str = "{
#[test] #[test]
fn format_block() { fn format_block() {
let mut interpreter = Interpreter::new(Map::new()); let mut interpreter = Interpreter::new(Context::new());
assert_eq!( assert_eq!(
interpreter.format("{1 2 3}"), interpreter.format("{1 2 3}"),
@ -34,7 +34,7 @@ const FORMATTED_MAP: &str = "{
#[test] #[test]
fn format_map() { fn format_map() {
let mut interpreter = Interpreter::new(Map::new()); let mut interpreter = Interpreter::new(Context::new());
assert_eq!( assert_eq!(
interpreter.format("{{x=1 y <int> = 2}}"), interpreter.format("{{x=1 y <int> = 2}}"),
@ -49,7 +49,7 @@ const FORMATTED_FUNCTION: &str = "(x <int>) <num> {
#[test] #[test]
fn format_function() { fn format_function() {
let mut interpreter = Interpreter::new(Map::new()); let mut interpreter = Interpreter::new(Context::new());
assert_eq!( assert_eq!(
interpreter.format("( x< int > )<num>{x/2}"), interpreter.format("( x< int > )<num>{x/2}"),
Ok(FORMATTED_FUNCTION.to_string()) Ok(FORMATTED_FUNCTION.to_string())

View File

@ -89,9 +89,9 @@ fn function_context_captures_functions() {
#[test] #[test]
fn function_context_captures_structure_definitions() { fn function_context_captures_structure_definitions() {
let map = Map::new(); let mut map = Map::new();
map.set("name".to_string(), Value::string("bob")).unwrap(); map.set("name".to_string(), Value::string("bob"));
assert_eq!( assert_eq!(
interpret( interpret(

View File

@ -17,7 +17,7 @@ fn simple_structure() {
#[test] #[test]
fn new_structure() { fn new_structure() {
let result = interpret( let _result = interpret(
" "
Coords = struct { Coords = struct {
x <float> = 0.0 x <float> = 0.0
@ -35,7 +35,9 @@ fn new_structure() {
map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer)); map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer));
let expected = Value::Map(Map::from_structure(Structure::new(map))); // let expected = Value::Map(Map::from_structure(Structure::new(map)));
assert_eq!(Ok(expected), result); // assert_eq!(Ok(expected), result);
todo!()
} }

View File

@ -69,11 +69,10 @@ fn empty_list() {
#[test] #[test]
fn map() { fn map() {
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)).unwrap(); map.set("x".to_string(), Value::Integer(1));
map.set("foo".to_string(), Value::string("bar".to_string())) map.set("foo".to_string(), Value::string("bar".to_string()));
.unwrap();
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
} }
@ -85,11 +84,10 @@ fn empty_map() {
#[test] #[test]
fn map_types() { fn map_types() {
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)).unwrap(); map.set("x".to_string(), Value::Integer(1));
map.set("foo".to_string(), Value::string("bar".to_string())) map.set("foo".to_string(), Value::string("bar".to_string()));
.unwrap();
assert_eq!( assert_eq!(
interpret("{ x <int> = 1, foo <str> = 'bar' }"), interpret("{ x <int> = 1, foo <str> = 'bar' }"),