Pass all tests
This commit is contained in:
parent
63f648c3ac
commit
a5c5075e6b
@ -1,4 +1,4 @@
|
|||||||
use std::{fs::read_to_string, io::stdin};
|
use std::{fs::read_to_string, io::stdin, thread::sleep, time::Duration};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
@ -11,7 +11,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
use super::Type;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum BuiltInFunction {
|
pub enum BuiltInFunction {
|
||||||
@ -98,13 +98,29 @@ impl FunctionLogic for ReadFile {
|
|||||||
fn r#type() -> Type {
|
fn r#type() -> Type {
|
||||||
Type::Function {
|
Type::Function {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: None,
|
value_parameters: Some(vec![(Identifier::new("path"), Type::String)]),
|
||||||
return_type: Some(Box::new(Type::String)),
|
return_type: Some(Box::new(Type::String)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
||||||
todo!()
|
let value = if let Some(value) = context.get_value(&Identifier::new("path"))? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure("path does not exist"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let path = if let ValueInner::String(string) = value.inner().as_ref() {
|
||||||
|
string
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure("path is not a string"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let file_content = read_to_string(path)?;
|
||||||
|
|
||||||
|
Ok(Some(Value::string(file_content)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +137,11 @@ impl FunctionLogic for ReadLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
||||||
todo!()
|
let mut user_input = String::new();
|
||||||
|
|
||||||
|
stdin().read_line(&mut user_input)?;
|
||||||
|
|
||||||
|
Ok(Some(Value::string(user_input)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,13 +152,30 @@ impl FunctionLogic for Sleep {
|
|||||||
fn r#type() -> Type {
|
fn r#type() -> Type {
|
||||||
Type::Function {
|
Type::Function {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: None,
|
value_parameters: Some(vec![(Identifier::new("milliseconds"), Type::Integer)]),
|
||||||
return_type: None,
|
return_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
|
||||||
todo!()
|
let value = if let Some(value) = context.get_value(&Identifier::new("milliseconds"))? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure("milliseconds does not exist"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let milliseconds = if let ValueInner::Integer(integer) = value.inner().as_ref() {
|
||||||
|
integer
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure("milliseconds is not an integer"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(*milliseconds as u64));
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +186,7 @@ impl FunctionLogic for WriteLine {
|
|||||||
fn r#type() -> Type {
|
fn r#type() -> Type {
|
||||||
Type::Function {
|
Type::Function {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: None,
|
value_parameters: Some(vec![(Identifier::new("output"), Type::String)]),
|
||||||
return_type: None,
|
return_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +199,7 @@ impl FunctionLogic for WriteLine {
|
|||||||
ValidationError::BuiltInFunctionFailure("output does not exist"),
|
ValidationError::BuiltInFunctionFailure("output does not exist"),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let input = if let ValueInner::String(string) = value.inner().as_ref() {
|
let output = if let ValueInner::String(string) = value.inner().as_ref() {
|
||||||
string
|
string
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
@ -170,7 +207,7 @@ impl FunctionLogic for WriteLine {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("{input}");
|
println!("{output}");
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -181,13 +218,15 @@ struct JsonParse;
|
|||||||
|
|
||||||
impl FunctionLogic for JsonParse {
|
impl FunctionLogic for JsonParse {
|
||||||
fn r#type() -> Type {
|
fn r#type() -> Type {
|
||||||
Type::Function {
|
let type_t = Type::Generic {
|
||||||
type_parameters: None,
|
|
||||||
value_parameters: None,
|
|
||||||
return_type: Some(Box::new(Type::Generic {
|
|
||||||
identifier: Identifier::new("T"),
|
identifier: Identifier::new("T"),
|
||||||
concrete_type: None,
|
concrete_type: None,
|
||||||
})),
|
};
|
||||||
|
|
||||||
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: Some(vec![(Identifier::new("input"), type_t.clone())]),
|
||||||
|
return_type: Some(Box::new(type_t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,14 +47,6 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
if let Expression::Value(WithPosition {
|
|
||||||
node: ValueNode::BuiltInFunction(_),
|
|
||||||
..
|
|
||||||
}) = self.function_expression.as_ref()
|
|
||||||
{
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.function_expression.validate(context, manage_memory)?;
|
self.function_expression.validate(context, manage_memory)?;
|
||||||
|
|
||||||
if let Some(value_arguments) = &self.value_arguments {
|
if let Some(value_arguments) = &self.value_arguments {
|
||||||
@ -63,8 +55,13 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let function_node_type =
|
let function_node_type = if let Expression::Value(WithPosition {
|
||||||
if let Some(r#type) = self.function_expression.expected_type(context)? {
|
node: ValueNode::BuiltInFunction(function),
|
||||||
|
..
|
||||||
|
}) = self.function_expression.as_ref()
|
||||||
|
{
|
||||||
|
function.r#type()
|
||||||
|
} else if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedExpression(
|
||||||
@ -74,7 +71,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
if let Type::Function {
|
if let Type::Function {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters: _,
|
value_parameters,
|
||||||
return_type: _,
|
return_type: _,
|
||||||
} = function_node_type
|
} = function_node_type
|
||||||
{
|
{
|
||||||
@ -90,6 +87,30 @@ impl AbstractNode for FunctionCall {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match (value_parameters, &self.value_arguments) {
|
||||||
|
(Some(parameters), Some(arguments)) => {
|
||||||
|
if parameters.len() != arguments.len() {
|
||||||
|
return Err(ValidationError::WrongTypeArgumentCount {
|
||||||
|
actual: parameters.len(),
|
||||||
|
expected: arguments.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(parameters), None) => {
|
||||||
|
return Err(ValidationError::WrongTypeArgumentCount {
|
||||||
|
expected: parameters.len(),
|
||||||
|
actual: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(None, Some(arguments)) => {
|
||||||
|
return Err(ValidationError::WrongTypeArgumentCount {
|
||||||
|
expected: 0,
|
||||||
|
actual: arguments.len(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(None, None) => {}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
|
@ -452,7 +452,11 @@ impl InterpreterError {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
ValidationError::WrongArguments { .. } => todo!(),
|
ValidationError::WrongArguments { .. } => todo!(),
|
||||||
ValidationError::WrongTypeArgumentCount { .. } => todo!(),
|
ValidationError::WrongTypeArgumentCount { expected, actual } => {
|
||||||
|
builder = builder.with_message(format!(
|
||||||
|
"Expected {expected} arguments but got {actual}."
|
||||||
|
));
|
||||||
|
}
|
||||||
ValidationError::ExpectedIntegerFloatOrString { actual, position } => {
|
ValidationError::ExpectedIntegerFloatOrString { actual, position } => {
|
||||||
builder = builder.with_message(format!(
|
builder = builder.with_message(format!(
|
||||||
"Expected an {}, {} or {}.",
|
"Expected an {}, {} or {}.",
|
||||||
|
Loading…
Reference in New Issue
Block a user