Refine Map interface for stability
This commit is contained in:
parent
c736e3be8f
commit
74dd455ae4
@ -36,18 +36,6 @@ impl AbstractTree for Assignment {
|
|||||||
|
|
||||||
let statement_node = syntax_node.child(child_count - 1).unwrap();
|
let statement_node = syntax_node.child(child_count - 1).unwrap();
|
||||||
let statement = Statement::from_syntax(statement_node, source, context)?;
|
let statement = Statement::from_syntax(statement_node, source, context)?;
|
||||||
let statement_type = statement.expected_type(context)?;
|
|
||||||
|
|
||||||
let variable_key = identifier.inner().clone();
|
|
||||||
let variable_type = if let Some(definition) = &type_definition {
|
|
||||||
definition.inner().clone()
|
|
||||||
} else {
|
|
||||||
statement_type
|
|
||||||
};
|
|
||||||
|
|
||||||
if let AssignmentOperator::Equal = operator {
|
|
||||||
context.set_type(variable_key, variable_type)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
identifier,
|
identifier,
|
||||||
@ -59,21 +47,11 @@ impl AbstractTree for Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, source: &str, context: &Map) -> Result<()> {
|
fn check_type(&self, source: &str, context: &Map) -> Result<()> {
|
||||||
let variables = context.variables()?;
|
|
||||||
let established_type = variables
|
|
||||||
.get(self.identifier.inner())
|
|
||||||
.map(|(_value, _type)| _type);
|
|
||||||
let actual_type = self.statement.expected_type(context)?;
|
let actual_type = self.statement.expected_type(context)?;
|
||||||
|
|
||||||
if let Some(type_definition) = &self.type_definition {
|
if let Some(type_definition) = &self.type_definition {
|
||||||
match self.operator {
|
match self.operator {
|
||||||
AssignmentOperator::Equal => {
|
AssignmentOperator::Equal => {
|
||||||
if let Some(r#type) = established_type {
|
|
||||||
r#type.check(&actual_type).map_err(|error| {
|
|
||||||
error.at_source_position(source, self.syntax_position)
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_definition
|
type_definition
|
||||||
.inner()
|
.inner()
|
||||||
.check(&actual_type)
|
.check(&actual_type)
|
||||||
@ -97,13 +75,7 @@ impl AbstractTree for Assignment {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self.operator {
|
match self.operator {
|
||||||
AssignmentOperator::Equal => {
|
AssignmentOperator::Equal => {}
|
||||||
if let Some(r#type) = established_type {
|
|
||||||
r#type.check(&actual_type).map_err(|error| {
|
|
||||||
error.at_source_position(source, self.syntax_position)
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssignmentOperator::PlusEqual => {
|
AssignmentOperator::PlusEqual => {
|
||||||
if let Type::List(item_type) = self.identifier.expected_type(context)? {
|
if let Type::List(item_type) = self.identifier.expected_type(context)? {
|
||||||
item_type.check(&actual_type).map_err(|error| {
|
item_type.check(&actual_type).map_err(|error| {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{env::args, sync::OnceLock};
|
use std::{collections::BTreeMap, env::args, sync::OnceLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -89,10 +89,7 @@ impl BuiltInValue {
|
|||||||
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)),
|
||||||
BuiltInValue::Random => RANDOM.get_or_init(|| {
|
BuiltInValue::Random => RANDOM.get_or_init(|| {
|
||||||
let random_context = Map::new();
|
let mut random_context = BTreeMap::new();
|
||||||
|
|
||||||
{
|
|
||||||
let mut variables = random_context.variables_mut().unwrap();
|
|
||||||
|
|
||||||
for built_in_function in [
|
for built_in_function in [
|
||||||
BuiltInFunction::RandomBoolean,
|
BuiltInFunction::RandomBoolean,
|
||||||
@ -104,17 +101,13 @@ impl BuiltInValue {
|
|||||||
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();
|
let r#type = built_in_function.r#type();
|
||||||
|
|
||||||
variables.insert(key, (value, r#type));
|
random_context.insert(key, (value, r#type));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Map(random_context)
|
Value::Map(Map::with_variables(random_context))
|
||||||
}),
|
}),
|
||||||
BuiltInValue::String => STRING.get_or_init(|| {
|
BuiltInValue::String => STRING.get_or_init(|| {
|
||||||
let string_context = Map::new();
|
let mut string_context = BTreeMap::new();
|
||||||
|
|
||||||
{
|
|
||||||
let mut variables = string_context.variables_mut().unwrap();
|
|
||||||
|
|
||||||
for string_function in string_functions() {
|
for string_function in string_functions() {
|
||||||
let key = string_function.name().to_string();
|
let key = string_function.name().to_string();
|
||||||
@ -123,11 +116,10 @@ impl BuiltInValue {
|
|||||||
)));
|
)));
|
||||||
let r#type = string_function.r#type();
|
let r#type = string_function.r#type();
|
||||||
|
|
||||||
variables.insert(key, (value, r#type));
|
string_context.insert(key, (value, r#type));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Map(string_context)
|
Value::Map(Map::with_variables(string_context))
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,10 +115,6 @@ impl AbstractTree for FunctionNode {
|
|||||||
|
|
||||||
function_context.clone_complex_values_from(context)?;
|
function_context.clone_complex_values_from(context)?;
|
||||||
|
|
||||||
for (identifier, r#type) in parameters.iter().zip(parameter_types.iter()) {
|
|
||||||
function_context.set_type(identifier.inner().clone(), r#type.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let body_node = node.child(child_count - 1).unwrap();
|
let body_node = node.child(child_count - 1).unwrap();
|
||||||
let body = Block::from_syntax(body_node, source, &function_context)?;
|
let body = Block::from_syntax(body_node, source, &function_context)?;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use std::{
|
|||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
sync::{Arc, RwLock, RwLockReadGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{value::Value, Result, Structure, Type};
|
use crate::{value::Value, Result, Structure, Type};
|
||||||
@ -32,6 +32,13 @@ impl Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_variables(variables: BTreeMap<String, (Value, Type)>) -> Self {
|
||||||
|
Map {
|
||||||
|
variables: Arc::new(RwLock::new(variables)),
|
||||||
|
structure: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clone_from(other: &Self) -> Result<Self> {
|
pub fn clone_from(other: &Self) -> Result<Self> {
|
||||||
let mut new_map = BTreeMap::new();
|
let mut new_map = BTreeMap::new();
|
||||||
|
|
||||||
@ -48,7 +55,8 @@ impl Map {
|
|||||||
pub fn clone_complex_values_from(&self, other: &Self) -> Result<()> {
|
pub fn clone_complex_values_from(&self, other: &Self) -> Result<()> {
|
||||||
for (key, (value, r#type)) in other.variables()?.iter() {
|
for (key, (value, r#type)) in other.variables()?.iter() {
|
||||||
if value.is_function() {
|
if value.is_function() {
|
||||||
self.variables_mut()?
|
self.variables
|
||||||
|
.write()?
|
||||||
.insert(key.clone(), (value.clone(), r#type.clone()));
|
.insert(key.clone(), (value.clone(), r#type.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,10 +68,6 @@ impl Map {
|
|||||||
Ok(self.variables.read()?)
|
Ok(self.variables.read()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variables_mut(&self) -> Result<RwLockWriteGuard<BTreeMap<String, (Value, Type)>>> {
|
|
||||||
Ok(self.variables.write()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
|
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
|
||||||
log::info!("Setting variable {key} = {value}");
|
log::info!("Setting variable {key} = {value}");
|
||||||
|
|
||||||
@ -76,12 +80,6 @@ impl Map {
|
|||||||
Ok(previous)
|
Ok(previous)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_type(&self, key: String, r#type: Type) -> Result<Option<(Value, Type)>> {
|
|
||||||
let previous = self.variables.write()?.insert(key, (Value::none(), r#type));
|
|
||||||
|
|
||||||
Ok(previous)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unset_all(&self) -> Result<()> {
|
pub fn unset_all(&self) -> Result<()> {
|
||||||
for (_key, (value, r#_type)) in self.variables.write()?.iter_mut() {
|
for (_key, (value, r#_type)) in self.variables.write()?.iter_mut() {
|
||||||
*value = Value::none();
|
*value = Value::none();
|
||||||
|
Loading…
Reference in New Issue
Block a user