Implement context
This commit is contained in:
parent
d997bbd08a
commit
90c0304af5
@ -114,12 +114,11 @@ impl BuiltInValue {
|
||||
let key = fs_function.name().to_string();
|
||||
let value =
|
||||
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(|| {
|
||||
let mut json_context = BTreeMap::new();
|
||||
@ -128,12 +127,11 @@ impl BuiltInValue {
|
||||
let key = json_function.name().to_string();
|
||||
let value =
|
||||
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::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
|
||||
@ -148,12 +146,11 @@ impl BuiltInValue {
|
||||
] {
|
||||
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();
|
||||
|
||||
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(|| {
|
||||
let mut string_context = BTreeMap::new();
|
||||
@ -163,12 +160,11 @@ impl BuiltInValue {
|
||||
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
|
||||
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))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -86,21 +86,13 @@ impl AbstractTree for Index {
|
||||
Value::Map(map) => {
|
||||
let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index {
|
||||
let key = identifier.inner();
|
||||
let value = map
|
||||
.variables()?
|
||||
.get(key)
|
||||
.map(|(value, _)| value.clone())
|
||||
.unwrap_or_default();
|
||||
let value = map.get(key).unwrap_or_default();
|
||||
|
||||
(key.clone(), value)
|
||||
} else {
|
||||
let index_value = self.index.run(source, context)?;
|
||||
let key = index_value.as_string()?;
|
||||
let value = map
|
||||
.variables()?
|
||||
.get(key.as_str())
|
||||
.map(|(value, _)| value.clone())
|
||||
.unwrap_or_default();
|
||||
let value = map.get(key.as_str()).unwrap_or_default();
|
||||
|
||||
(key.clone(), value)
|
||||
};
|
||||
@ -108,7 +100,7 @@ impl AbstractTree for Index {
|
||||
if value.is_none() {
|
||||
Err(RuntimeError::VariableIdentifierNotFound(key))
|
||||
} else {
|
||||
Ok(value)
|
||||
Ok(value.clone())
|
||||
}
|
||||
}
|
||||
Value::String(string) => {
|
||||
|
@ -43,7 +43,7 @@ impl AbstractTree for IndexAssignment {
|
||||
}
|
||||
|
||||
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 {
|
||||
identifier.inner()
|
||||
} else {
|
||||
|
@ -242,7 +242,7 @@ impl AbstractTree for ValueNode {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
let actual = statement.expected_type(context)?;
|
||||
|
||||
@ -294,13 +294,13 @@ impl AbstractTree for ValueNode {
|
||||
Value::Option(option_value)
|
||||
}
|
||||
ValueNode::Map(key_statement_pairs, _) => {
|
||||
let map = Map::new();
|
||||
let mut map = Map::new();
|
||||
|
||||
{
|
||||
for (key, (statement, _)) in key_statement_pairs {
|
||||
let value = statement.run(source, context)?;
|
||||
|
||||
map.set(key.clone(), value)?;
|
||||
map.set(key.clone(), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ impl Callable for BuiltInFunction {
|
||||
let length = if let Ok(list) = value.as_list() {
|
||||
list.items().len()
|
||||
} else if let Ok(map) = value.as_map() {
|
||||
map.variables()?.len()
|
||||
map.len()
|
||||
} else if let Ok(str) = value.as_string() {
|
||||
str.chars().count()
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
sync::{Arc, RwLock, RwLockReadGuard},
|
||||
};
|
||||
|
||||
use crate::{error::rw_lock_error::RwLockError, Type, Value};
|
||||
@ -16,6 +16,7 @@ pub enum ValueData {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
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> {
|
||||
let mut new_variables = HashMap::new();
|
||||
|
||||
|
@ -11,7 +11,7 @@ pub use runtime_error::RuntimeError;
|
||||
pub use syntax_error::SyntaxError;
|
||||
pub use validation_error::ValidationError;
|
||||
|
||||
use tree_sitter::{LanguageError, Point};
|
||||
use tree_sitter::LanguageError;
|
||||
|
||||
use std::fmt::{self, Formatter};
|
||||
|
||||
@ -69,11 +69,7 @@ impl fmt::Display for Error {
|
||||
Validation(error) => write!(f, "Validation error: {error}"),
|
||||
Runtime(error) => write!(f, "Runtime error: {error}"),
|
||||
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)
|
||||
}
|
||||
|
@ -5,8 +5,12 @@
|
||||
//! You can use this library externally by calling either of the "interpret"
|
||||
//! functions or by constructing your own Interpreter.
|
||||
pub use crate::{
|
||||
abstract_tree::*, built_in_functions::BuiltInFunction, context::Context, error::Error,
|
||||
interpret::*, value::*,
|
||||
abstract_tree::*,
|
||||
built_in_functions::BuiltInFunction,
|
||||
context::{Context, ValueData},
|
||||
error::Error,
|
||||
interpret::*,
|
||||
value::*,
|
||||
};
|
||||
|
||||
pub use tree_sitter::Node as SyntaxNode;
|
||||
|
52
src/main.rs
52
src/main.rs
@ -11,7 +11,7 @@ use reedline::{
|
||||
|
||||
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.
|
||||
#[derive(Parser, Debug)]
|
||||
@ -50,11 +50,11 @@ fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let args = Args::parse();
|
||||
let context = Map::new();
|
||||
let context = Context::new();
|
||||
|
||||
if let Some(input) = args.input {
|
||||
context
|
||||
.set("input".to_string(), Value::string(input))
|
||||
.set_value("input".to_string(), Value::string(input))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ fn main() {
|
||||
let file_contents = read_to_string(path).unwrap();
|
||||
|
||||
context
|
||||
.set("input".to_string(), Value::string(file_contents))
|
||||
.set_value("input".to_string(), Value::string(file_contents))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -117,11 +117,11 @@ fn main() {
|
||||
}
|
||||
|
||||
struct DustHighlighter {
|
||||
context: Map,
|
||||
context: Context,
|
||||
}
|
||||
|
||||
impl DustHighlighter {
|
||||
fn new(context: Map) -> Self {
|
||||
fn new(context: Context) -> Self {
|
||||
Self { context }
|
||||
}
|
||||
}
|
||||
@ -130,36 +130,27 @@ const HIGHLIGHT_TERMINATORS: [char; 8] = [' ', ':', '(', ')', '{', '}', '[', ']'
|
||||
|
||||
impl Highlighter for DustHighlighter {
|
||||
fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText {
|
||||
fn highlight_identifier(styled: &mut StyledText, word: &str, map: &Map) -> bool {
|
||||
for (key, (value, _type)) in map.variables().unwrap().iter() {
|
||||
let mut styled = StyledText::new();
|
||||
|
||||
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 {
|
||||
styled.push((Style::new().bold(), word.to_string()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Value::Map(nested_map) = value {
|
||||
return highlight_identifier(styled, word, nested_map);
|
||||
}
|
||||
word_is_highlighted = true;
|
||||
}
|
||||
|
||||
for built_in_value in built_in_values() {
|
||||
if built_in_value.name() == word {
|
||||
styled.push((Style::new().bold(), word.to_string()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
word_is_highlighted = true;
|
||||
}
|
||||
|
||||
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 {
|
||||
let final_char = word.chars().last().unwrap();
|
||||
|
||||
@ -239,11 +230,11 @@ impl Prompt for StarshipPrompt {
|
||||
}
|
||||
|
||||
pub struct DustCompleter {
|
||||
context: Map,
|
||||
context: Context,
|
||||
}
|
||||
|
||||
impl DustCompleter {
|
||||
fn new(context: Map) -> Self {
|
||||
fn new(context: Context) -> Self {
|
||||
DustCompleter { context }
|
||||
}
|
||||
}
|
||||
@ -302,7 +293,7 @@ impl Completer for DustCompleter {
|
||||
}
|
||||
|
||||
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) {
|
||||
suggestions.push(Suggestion {
|
||||
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) {
|
||||
suggestions.push(Suggestion {
|
||||
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 keybindings = default_emacs_keybindings();
|
||||
|
||||
|
197
src/value/map.rs
197
src/value/map.rs
@ -1,136 +1,73 @@
|
||||
use serde::{
|
||||
de::{MapAccess, Visitor},
|
||||
ser::SerializeMap,
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stanza::{
|
||||
renderer::{console::Console, Renderer},
|
||||
style::{HAlign, Styles},
|
||||
table::{Row, Table},
|
||||
};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::BTreeMap,
|
||||
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.
|
||||
///
|
||||
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
|
||||
/// to one another.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Map {
|
||||
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>,
|
||||
structure: Option<Structure>,
|
||||
inner: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
/// Creates a new instace.
|
||||
pub fn new() -> Self {
|
||||
Map {
|
||||
variables: Arc::new(RwLock::new(BTreeMap::new())),
|
||||
structure: None,
|
||||
inner: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_structure(structure: Structure) -> Self {
|
||||
let mut variables = BTreeMap::new();
|
||||
|
||||
for (key, (value_option, r#type)) in structure.inner() {
|
||||
variables.insert(
|
||||
key.clone(),
|
||||
(
|
||||
value_option.clone().unwrap_or(Value::none()),
|
||||
r#type.clone(),
|
||||
),
|
||||
);
|
||||
pub fn with_values(variables: BTreeMap<String, Value>) -> Self {
|
||||
Map { inner: variables }
|
||||
}
|
||||
|
||||
Map {
|
||||
variables: Arc::new(RwLock::new(variables)),
|
||||
structure: Some(structure),
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
pub fn with_variables(variables: BTreeMap<String, (Value, Type)>) -> Self {
|
||||
Map {
|
||||
variables: Arc::new(RwLock::new(variables)),
|
||||
structure: None,
|
||||
}
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
|
||||
self.inner.iter()
|
||||
}
|
||||
|
||||
pub fn clone_from(other: &Self) -> Result<Self, RwLockError> {
|
||||
let mut new_map = BTreeMap::new();
|
||||
|
||||
for (key, (value, r#type)) in other.variables()?.iter() {
|
||||
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
|
||||
pub fn get(&self, key: &str) -> Option<&Value> {
|
||||
self.inner.get(key)
|
||||
}
|
||||
|
||||
Ok(Map {
|
||||
variables: Arc::new(RwLock::new(new_map)),
|
||||
structure: other.structure.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn variables(
|
||||
&self,
|
||||
) -> 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> {
|
||||
log::info!("Setting variable {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 set(&mut self, key: String, value: Value) {
|
||||
self.inner.insert(key, value);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
for (key, (value, r#type)) in variables {
|
||||
for (key, value) in &self.inner {
|
||||
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(
|
||||
Styles::default(),
|
||||
vec![
|
||||
key.into(),
|
||||
list.as_text_table().into(),
|
||||
r#type.to_string().into(),
|
||||
map.as_text_table().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 {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let renderer = Console::default();
|
||||
@ -181,63 +92,3 @@ impl Display for Map {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ impl Value {
|
||||
Value::Map(map) => {
|
||||
let mut identifier_types = Vec::new();
|
||||
|
||||
for (key, (value, _)) in map.variables().unwrap().iter() {
|
||||
for (key, value) in map.iter() {
|
||||
identifier_types.push((
|
||||
Identifier::new(key.clone()),
|
||||
TypeSpecification::new(value.r#type()),
|
||||
@ -858,10 +858,10 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let map = Map::new();
|
||||
let mut map = Map::new();
|
||||
|
||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||
map.set(key, value).unwrap();
|
||||
map.set(key, value);
|
||||
}
|
||||
|
||||
Ok(Value::Map(map))
|
||||
|
@ -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("y".to_string(), Value::Integer(2)).unwrap();
|
||||
map.set("x".to_string(), Value::Integer(1));
|
||||
map.set("y".to_string(), Value::Integer(2));
|
||||
|
||||
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("y".to_string(), Value::Integer(2)).unwrap();
|
||||
map.set("x".to_string(), Value::Integer(1));
|
||||
map.set("y".to_string(), Value::Integer(2));
|
||||
|
||||
assert_eq!(Ok(Value::Map(map)), result);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
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()));
|
||||
}
|
||||
@ -16,7 +16,7 @@ const FORMATTED_BLOCK: &str = "{
|
||||
|
||||
#[test]
|
||||
fn format_block() {
|
||||
let mut interpreter = Interpreter::new(Map::new());
|
||||
let mut interpreter = Interpreter::new(Context::new());
|
||||
|
||||
assert_eq!(
|
||||
interpreter.format("{1 2 3}"),
|
||||
@ -34,7 +34,7 @@ const FORMATTED_MAP: &str = "{
|
||||
|
||||
#[test]
|
||||
fn format_map() {
|
||||
let mut interpreter = Interpreter::new(Map::new());
|
||||
let mut interpreter = Interpreter::new(Context::new());
|
||||
|
||||
assert_eq!(
|
||||
interpreter.format("{{x=1 y <int> = 2}}"),
|
||||
@ -49,7 +49,7 @@ const FORMATTED_FUNCTION: &str = "(x <int>) <num> {
|
||||
|
||||
#[test]
|
||||
fn format_function() {
|
||||
let mut interpreter = Interpreter::new(Map::new());
|
||||
let mut interpreter = Interpreter::new(Context::new());
|
||||
assert_eq!(
|
||||
interpreter.format("( x< int > )<num>{x/2}"),
|
||||
Ok(FORMATTED_FUNCTION.to_string())
|
||||
|
@ -89,9 +89,9 @@ fn function_context_captures_functions() {
|
||||
|
||||
#[test]
|
||||
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!(
|
||||
interpret(
|
||||
|
@ -17,7 +17,7 @@ fn simple_structure() {
|
||||
|
||||
#[test]
|
||||
fn new_structure() {
|
||||
let result = interpret(
|
||||
let _result = interpret(
|
||||
"
|
||||
Coords = struct {
|
||||
x <float> = 0.0
|
||||
@ -35,7 +35,9 @@ fn new_structure() {
|
||||
|
||||
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!()
|
||||
}
|
||||
|
@ -69,11 +69,10 @@ fn empty_list() {
|
||||
|
||||
#[test]
|
||||
fn map() {
|
||||
let map = Map::new();
|
||||
let mut map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1)).unwrap();
|
||||
map.set("foo".to_string(), Value::string("bar".to_string()))
|
||||
.unwrap();
|
||||
map.set("x".to_string(), Value::Integer(1));
|
||||
map.set("foo".to_string(), Value::string("bar".to_string()));
|
||||
|
||||
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
||||
}
|
||||
@ -85,11 +84,10 @@ fn empty_map() {
|
||||
|
||||
#[test]
|
||||
fn map_types() {
|
||||
let map = Map::new();
|
||||
let mut map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1)).unwrap();
|
||||
map.set("foo".to_string(), Value::string("bar".to_string()))
|
||||
.unwrap();
|
||||
map.set("x".to_string(), Value::Integer(1));
|
||||
map.set("foo".to_string(), Value::string("bar".to_string()));
|
||||
|
||||
assert_eq!(
|
||||
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
||||
|
Loading…
Reference in New Issue
Block a user