1
0

Pass function tests; Fix recursion

This commit is contained in:
Jeff 2024-02-18 04:48:45 -05:00
parent d4a5424ad5
commit a52eadc5ad
6 changed files with 37 additions and 25 deletions

View File

@ -3,8 +3,8 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, SyntaxError, ValidationError}, error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, AssignmentOperator, Format, Identifier, SourcePosition, Statement, SyntaxNode, AbstractTree, AssignmentOperator, Format, Function, Identifier, SourcePosition, Statement,
Type, TypeSpecification, Value, SyntaxNode, Type, TypeSpecification, Value,
}; };
/// Variable assignment, including add-assign and subtract-assign operations. /// Variable assignment, including add-assign and subtract-assign operations.
@ -149,6 +149,12 @@ impl AbstractTree for Assignment {
AssignmentOperator::Equal => right, AssignmentOperator::Equal => right,
}; };
if let Value::Function(Function::ContextDefined(function_node)) = &new_value {
function_node
.context()
.set_value(self.identifier.clone(), new_value.clone())?;
}
context.set_value(self.identifier.clone(), new_value)?; context.set_value(self.identifier.clone(), new_value)?;
Ok(Value::none()) Ok(Value::none())

View File

@ -94,6 +94,8 @@ impl AbstractTree for FunctionCall {
} }
fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> { fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> {
self.function_expression.validate(_source, context)?;
let function_expression_type = self.function_expression.expected_type(context)?; let function_expression_type = self.function_expression.expected_type(context)?;
let parameter_types = if let Type::Function { let parameter_types = if let Type::Function {
@ -117,6 +119,8 @@ impl AbstractTree for FunctionCall {
} }
for (index, expression) in self.arguments.iter().enumerate() { for (index, expression) in self.arguments.iter().enumerate() {
expression.validate(_source, context)?;
if let Some(expected) = parameter_types.get(index) { if let Some(expected) = parameter_types.get(index) {
let actual = expression.expected_type(context)?; let actual = expression.expected_type(context)?;
@ -178,8 +182,6 @@ impl AbstractTree for FunctionCall {
call_context.set_value(identifier.clone(), value)?; call_context.set_value(identifier.clone(), value)?;
} }
println!("{}", call_context);
function_node.body().run(source, &call_context) function_node.body().run(source, &call_context)
} }
} }

View File

@ -89,6 +89,8 @@ impl AbstractTree for IfElse {
} }
if let Some(block) = &self.else_block { if let Some(block) = &self.else_block {
block.validate(_source, context)?;
let actual = block.expected_type(context)?; let actual = block.expected_type(context)?;
if !expected.accepts(&actual) { if !expected.accepts(&actual) {

View File

@ -91,8 +91,11 @@ impl Context {
pub fn with_variables_from(other: &Context) -> Result<Context, RwLockError> { pub fn with_variables_from(other: &Context) -> Result<Context, RwLockError> {
let mut new_variables = BTreeMap::new(); let mut new_variables = BTreeMap::new();
for (identifier, value_data) in other.inner.read()?.iter() { for (identifier, (value_data, counter)) in other.inner.read()?.iter() {
new_variables.insert(identifier.clone(), value_data.clone()); let (allowances, _runtime_uses) = counter.get_counts()?;
let new_counter = UsageCounter::with_counts(allowances, 0);
new_variables.insert(identifier.clone(), (value_data.clone(), new_counter));
} }
Ok(Context { Ok(Context {
@ -123,30 +126,20 @@ impl Context {
pub fn inherit_from(&self, other: &Context) -> Result<(), RwLockError> { pub fn inherit_from(&self, other: &Context) -> Result<(), RwLockError> {
let mut self_variables = self.inner.write()?; let mut self_variables = self.inner.write()?;
for (identifier, (value_data, _counter)) in other.inner.read()?.iter() { for (identifier, (value_data, counter)) in other.inner.read()?.iter() {
let (allowances, _runtime_uses) = counter.get_counts()?;
let new_counter = UsageCounter::with_counts(allowances, 0);
if let ValueData::Value(value) = value_data { if let ValueData::Value(value) = value_data {
if value.is_function() { if value.is_function() {
self_variables.insert( self_variables.insert(identifier.clone(), (value_data.clone(), new_counter));
identifier.clone(),
(value_data.clone(), UsageCounter::new()),
);
} }
} } else if let ValueData::TypeHint(r#type) = value_data {
if let ValueData::TypeHint(r#type) = value_data {
if r#type.is_function() { if r#type.is_function() {
self_variables.insert( self_variables.insert(identifier.clone(), (value_data.clone(), new_counter));
identifier.clone(),
(value_data.clone(), UsageCounter::new()),
);
} }
} } else if let ValueData::TypeDefinition(_) = value_data {
self_variables.insert(identifier.clone(), (value_data.clone(), new_counter));
if let ValueData::TypeDefinition(_) = value_data {
self_variables.insert(
identifier.clone(),
(value_data.clone(), UsageCounter::new()),
);
} }
} }

View File

@ -16,6 +16,13 @@ impl UsageCounter {
}))) })))
} }
pub fn with_counts(allowances: usize, runtime_uses: usize) -> UsageCounter {
UsageCounter(Arc::new(RwLock::new(UsageCounterInner {
allowances,
runtime_uses,
})))
}
pub fn get_counts(&self) -> Result<(usize, usize), RwLockError> { pub fn get_counts(&self) -> Result<(usize, usize), RwLockError> {
let inner = self.0.read()?; let inner = self.0.read()?;
Ok((inner.allowances, inner.runtime_uses)) Ok((inner.allowances, inner.runtime_uses))

View File

@ -115,6 +115,8 @@ fn function_context_captures_structure_definitions() {
#[test] #[test]
fn recursion() { fn recursion() {
env_logger::builder().is_test(true).try_init().unwrap();
assert_eq!( assert_eq!(
interpret( interpret(
" "