Fix variable context bugs

This commit is contained in:
Jeff 2024-01-09 20:38:40 -05:00
parent d8850b2d3c
commit b7db177bd2
16 changed files with 78 additions and 96 deletions

View File

@ -47,7 +47,7 @@ impl AbstractTree for Assignment {
};
if let AssignmentOperator::Equal = operator {
context.set(variable_key, Value::none(), Some(variable_type))?;
context.set_type(variable_key, variable_type)?;
}
Ok(Assignment {
@ -82,7 +82,9 @@ impl AbstractTree for Assignment {
}
AssignmentOperator::PlusEqual => {
if let Type::List(item_type) = type_definition.inner() {
item_type.check(&actual_type)?;
item_type.check(&actual_type).map_err(|error| {
error.at_source_position(source, self.syntax_position)
})?;
} else {
type_definition
.inner()
@ -98,7 +100,9 @@ impl AbstractTree for Assignment {
match self.operator {
AssignmentOperator::Equal => {
if let Some(r#type) = established_type {
r#type.check(&actual_type)?;
r#type.check(&actual_type).map_err(|error| {
error.at_source_position(source, self.syntax_position)
})?;
}
}
AssignmentOperator::PlusEqual => {
@ -141,11 +145,7 @@ impl AbstractTree for Assignment {
AssignmentOperator::Equal => value,
};
if let Some(type_defintion) = &self.type_definition {
context.set(key.clone(), new_value, Some(type_defintion.inner().clone()))?;
} else {
context.set(key.clone(), new_value, None)?;
}
context.set(key.clone(), new_value)?;
Ok(Value::none())
}

View File

@ -70,7 +70,6 @@ impl BuiltInValue {
.set(
"read".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)),
None,
)
.unwrap();
@ -83,7 +82,6 @@ impl BuiltInValue {
.set(
BuiltInFunction::JsonParse.name().to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
None,
)
.unwrap();

View File

@ -57,7 +57,7 @@ impl AbstractTree for For {
values.par_iter().try_for_each(|value| {
let iter_context = Map::clone_from(context)?;
iter_context.set(key.clone(), value.clone(), None)?;
iter_context.set(key.clone(), value.clone())?;
self.block.run(source, &iter_context).map(|_value| ())
})?;
@ -65,7 +65,7 @@ impl AbstractTree for For {
let loop_context = Map::clone_from(context)?;
for value in values.iter() {
loop_context.set(key.clone(), value.clone(), None)?;
loop_context.set(key.clone(), value.clone())?;
self.block.run(source, &loop_context)?;
}

View File

@ -54,7 +54,7 @@ impl AbstractTree for FunctionCall {
})
}
fn check_type(&self, _source: &str, context: &Map) -> Result<()> {
fn check_type(&self, source: &str, context: &Map) -> Result<()> {
let function_expression_type = self.function_expression.expected_type(context)?;
let parameter_types = match function_expression_type {
@ -65,22 +65,25 @@ impl AbstractTree for FunctionCall {
_ => {
return Err(Error::TypeCheckExpectedFunction {
actual: function_expression_type,
})
}
.at_source_position(source, self.syntax_position))
}
};
for (index, expression) in self.arguments.iter().enumerate() {
if let Some(r#type) = parameter_types.get(index) {
r#type.check(&expression.expected_type(context)?)?;
}
}
if self.arguments.len() != parameter_types.len() {
return Err(Error::ExpectedFunctionArgumentAmount {
expected: parameter_types.len(),
actual: self.arguments.len(),
}
.at_source_position(_source, self.syntax_position));
.at_source_position(source, self.syntax_position));
}
for (index, expression) in self.arguments.iter().enumerate() {
if let Some(r#type) = parameter_types.get(index) {
r#type
.check(&expression.expected_type(context)?)
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
}
}
Ok(())
@ -116,10 +119,6 @@ impl AbstractTree for FunctionCall {
arguments.push(value);
}
if let Some(name) = &name {
context.set(name.to_string(), value.clone(), None)?;
}
value.as_function()?.call(name, &arguments, source, context)
}

View File

@ -23,14 +23,13 @@ impl FunctionNode {
body: Block,
r#type: Type,
syntax_position: SyntaxPosition,
context: Map,
) -> Self {
Self {
parameters,
body,
r#type,
syntax_position,
context,
context: Map::new(),
}
}
@ -63,21 +62,20 @@ impl FunctionNode {
source: &str,
outer_context: &Map,
) -> Result<Value> {
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
self.context.clone_complex_values_from(outer_context)?;
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone();
self.context.set(key, value.clone(), None)?;
self.context.set(key, value.clone())?;
}
if let Some(name) = name {
self.context.set(
name,
Value::Function(Function::ContextDefined(self.clone())),
None,
)?;
}
@ -111,41 +109,37 @@ impl AbstractTree for FunctionNode {
}
}
let return_type_node = node.child(child_count - 2).unwrap();
let return_type = TypeDefinition::from_syntax_node(source, return_type_node, context)?;
let function_context = Map::new();
function_context.clone_complex_values_from(context)?;
for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
function_context.set(
parameter_name.inner().clone(),
Value::none(),
Some(parameter_type.clone()),
)?;
for (identifier, r#type) in parameters.iter().zip(parameter_types.iter()) {
function_context.set_type(identifier.inner().clone(), r#type.clone())?;
}
let return_type_node = node.child(child_count - 2).unwrap();
let return_type = TypeDefinition::from_syntax_node(source, return_type_node, context)?;
let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node, &function_context)?;
let r#type = Type::function(parameter_types, return_type.take_inner());
let syntax_position = node.range().into();
Ok(FunctionNode::new(
Ok(FunctionNode {
parameters,
body,
r#type,
syntax_position,
function_context,
))
context: function_context,
})
}
fn check_type(&self, source: &str, _context: &Map) -> Result<()> {
fn check_type(&self, source: &str, context: &Map) -> Result<()> {
self.context.clone_complex_values_from(context)?;
self.return_type()
.check(&self.body.expected_type(&self.context)?)
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
self.body.check_type(source, &self.context)?;
Ok(())

View File

@ -45,12 +45,8 @@ impl AbstractTree for Identifier {
}
}
fn check_type(&self, _source: &str, context: &Map) -> Result<()> {
if let Some(_) = context.variables()?.get(&self.0) {
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
Ok(())
} else {
Err(Error::VariableIdentifierNotFound(self.0.clone()))
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {

View File

@ -70,7 +70,7 @@ impl AbstractTree for IndexAssignment {
AssignmentOperator::Equal => value,
};
index_context.set(index_key.clone(), new_value, None)?;
index_context.set(index_key.clone(), new_value)?;
Ok(Value::none())
}

View File

@ -60,9 +60,9 @@ impl From<tree_sitter::Range> for SyntaxPosition {
SyntaxPosition {
start_byte: range.start_byte,
end_byte: range.end_byte,
start_row: range.start_point.row,
start_row: range.start_point.row + 1,
start_column: range.start_point.column,
end_row: range.end_point.row,
end_row: range.end_point.row + 1,
end_column: range.end_point.column,
}
}

View File

@ -232,10 +232,10 @@ impl AbstractTree for ValueNode {
let map = Map::new();
{
for (key, (statement, r#type)) in key_statement_pairs {
for (key, (statement, _)) in key_statement_pairs {
let value = statement.run(source, context)?;
map.set(key.clone(), value, r#type.clone())?;
map.set(key.clone(), value)?;
}
}

View File

@ -29,9 +29,9 @@ pub fn interpret(source: &str) -> Result<Value> {
/// # use dust_lang::*;
/// let context = Map::new();
///
/// context.set("one".into(), 1.into(), None);
/// context.set("two".into(), 2.into(), None);
/// context.set("three".into(), 3.into(), None);
/// context.set("one".into(), 1.into());
/// context.set("two".into(), 2.into());
/// context.set("three".into(), 3.into());
///
/// let dust_code = "four = 4 one + two + three + four";
///

View File

@ -64,7 +64,7 @@ fn main() {
if let Some(input) = args.input {
context
.set("input".to_string(), Value::string(input), None)
.set("input".to_string(), Value::string(input))
.unwrap();
}
@ -72,7 +72,7 @@ fn main() {
let file_contents = read_to_string(path).unwrap();
context
.set("input".to_string(), Value::string(file_contents), None)
.set("input".to_string(), Value::string(file_contents))
.unwrap();
}

View File

@ -64,13 +64,8 @@ impl Map {
Ok(self.variables.write()?)
}
pub fn set(
&self,
key: String,
value: Value,
r#type: Option<Type>,
) -> Result<Option<(Value, Type)>> {
let value_type = r#type.unwrap_or(value.r#type());
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
let value_type = value.r#type();
let previous = self
.variables
.write()?
@ -79,6 +74,12 @@ impl Map {
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<()> {
for (_key, (value, r#_type)) in self.variables.write()?.iter_mut() {
*value = Value::none();
@ -182,7 +183,7 @@ impl<'de> Visitor<'de> for MapVisitor {
{
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value, None).unwrap();
map.set(key, value).unwrap();
}
}

View File

@ -844,7 +844,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
let map = Map::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value, None).unwrap();
map.set(key, value).unwrap();
}
Ok(Value::Map(map))

View File

@ -58,10 +58,7 @@ fn function_context_does_not_capture_normal_values() {
),
Err(Error::VariableIdentifierNotFound("x".to_string()))
);
}
#[test]
fn function_context_captures_functions() {
assert_eq!(
interpret(
"
@ -72,7 +69,10 @@ fn function_context_captures_functions() {
),
Ok(Value::Integer(2))
);
}
#[test]
fn function_context_captures_functions() {
assert_eq!(
interpret(
"
@ -84,24 +84,23 @@ fn function_context_captures_functions() {
Ok(Value::Integer(2))
);
assert_eq!(
interpret(
"
foo = () <int> { bar() }
foo()
bar = () <int> { 2 }
"
),
Ok(Value::Integer(2))
);
// assert_eq!(
// interpret(
// "
// foo = () <int> { bar() }
// foo()
// bar = () <int> { 2 }
// "
// ),
// Ok(Value::Integer(2))
// );
}
#[test]
fn function_context_captures_structure_definitions() {
let map = Map::new();
map.set("name".to_string(), Value::string("bob"), None)
.unwrap();
map.set("name".to_string(), Value::string("bob")).unwrap();
assert_eq!(
interpret(

View File

@ -13,7 +13,7 @@ fn simple_type_check() {
#[test]
fn argument_count_check() {
let source = "
foo = (x <int>) <bool> {
foo = (x <int>) <int> {
x
}
foo()
@ -21,7 +21,7 @@ fn argument_count_check() {
let result = interpret(&source);
assert_eq!(
"Expected 1 arguments, but got 0. Occured at (4, 12) to (4, 17). Source: foo()",
"Expected 1 arguments, but got 0. Occured at (5, 12) to (5, 17). Source: foo()",
result.unwrap_err().to_string()
)
}

View File

@ -49,8 +49,8 @@ fn list() {
fn map() {
let map = Map::new();
map.set("x".to_string(), Value::Integer(1), None).unwrap();
map.set("foo".to_string(), Value::string("bar".to_string()), None)
map.set("x".to_string(), Value::Integer(1)).unwrap();
map.set("foo".to_string(), Value::string("bar".to_string()))
.unwrap();
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
@ -60,13 +60,8 @@ fn map() {
fn map_types() {
let map = Map::new();
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
.unwrap();
map.set(
"foo".to_string(),
Value::string("bar".to_string()),
Some(Type::String),
)
map.set("x".to_string(), Value::Integer(1)).unwrap();
map.set("foo".to_string(), Value::string("bar".to_string()))
.unwrap();
assert_eq!(