Begin revising built-in functions
This commit is contained in:
parent
fe1e27fd70
commit
fb78798a1d
35
dust-lang/src/abstract_tree/built_in_function_call.rs
Normal file
35
dust-lang/src/abstract_tree/built_in_function_call.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use std::{
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
io::stdin,
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
abstract_tree::{Action, Type},
|
||||||
|
context::Context,
|
||||||
|
error::RuntimeError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{AbstractNode, Expression, WithPosition};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum BuiltInFunctionCall {
|
||||||
|
ReadLine,
|
||||||
|
Sleep(Expression),
|
||||||
|
WriteLine(Expression),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractNode for BuiltInFunctionCall {
|
||||||
|
fn expected_type(&self, context: &Context) -> Result<Type, crate::error::ValidationError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context) -> Result<(), crate::error::ValidationError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
@ -5,12 +5,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AbstractNode, Action, FunctionCall, ListIndex, Logic, MapIndex, Math, SourcePosition, Type,
|
AbstractNode, Action, BuiltInFunctionCall, FunctionCall, ListIndex, Logic, MapIndex, Math,
|
||||||
ValueNode, WithPosition,
|
SourcePosition, Type, ValueNode, WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
|
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
|
||||||
FunctionCall(WithPosition<FunctionCall>),
|
FunctionCall(WithPosition<FunctionCall>),
|
||||||
Identifier(WithPosition<Identifier>),
|
Identifier(WithPosition<Identifier>),
|
||||||
MapIndex(WithPosition<Box<MapIndex>>),
|
MapIndex(WithPosition<Box<MapIndex>>),
|
||||||
@ -30,6 +31,7 @@ impl Expression {
|
|||||||
Expression::Logic(inner) => inner.position,
|
Expression::Logic(inner) => inner.position,
|
||||||
Expression::Math(inner) => inner.position,
|
Expression::Math(inner) => inner.position,
|
||||||
Expression::Value(inner) => inner.position,
|
Expression::Value(inner) => inner.position,
|
||||||
|
Expression::BuiltInFunctionCall(inner) => inner.position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,6 +55,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::Logic(logic) => logic.node.expected_type(_context),
|
Expression::Logic(logic) => logic.node.expected_type(_context),
|
||||||
Expression::Math(math) => math.node.expected_type(_context),
|
Expression::Math(math) => math.node.expected_type(_context),
|
||||||
Expression::Value(value_node) => value_node.node.expected_type(_context),
|
Expression::Value(value_node) => value_node.node.expected_type(_context),
|
||||||
|
Expression::BuiltInFunctionCall(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +77,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::Logic(logic) => logic.node.validate(context),
|
Expression::Logic(logic) => logic.node.validate(context),
|
||||||
Expression::Math(math) => math.node.validate(context),
|
Expression::Math(math) => math.node.validate(context),
|
||||||
Expression::Value(value_node) => value_node.node.validate(context),
|
Expression::Value(value_node) => value_node.node.validate(context),
|
||||||
|
Expression::BuiltInFunctionCall(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +101,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::Logic(logic) => logic.node.run(_context),
|
Expression::Logic(logic) => logic.node.run(_context),
|
||||||
Expression::Math(math) => math.node.run(_context),
|
Expression::Math(math) => math.node.run(_context),
|
||||||
Expression::Value(value_node) => value_node.node.run(_context),
|
Expression::Value(value_node) => value_node.node.run(_context),
|
||||||
|
Expression::BuiltInFunctionCall(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
value::{Function, ParsedFunction, ValueInner},
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Action, Expression, Type, WithPosition};
|
use super::{AbstractNode, Action, Expression, Type, WithPosition};
|
||||||
@ -133,20 +133,16 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
let function_context = Context::new();
|
let function_context = Context::new();
|
||||||
|
|
||||||
if let Function::Parsed(ParsedFunction {
|
for (type_parameter, type_argument) in function
|
||||||
type_parameters, ..
|
.type_parameters()
|
||||||
}) = function
|
.iter()
|
||||||
|
.map(|r#type| r#type.node.clone())
|
||||||
|
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
|
||||||
{
|
{
|
||||||
for (type_parameter, type_argument) in type_parameters
|
if let Type::Argument(identifier) = type_parameter {
|
||||||
.iter()
|
function_context.set_type(identifier, type_argument)?;
|
||||||
.map(|r#type| r#type.node.clone())
|
|
||||||
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
|
|
||||||
{
|
|
||||||
if let Type::Argument(identifier) = type_parameter {
|
|
||||||
function_context.set_type(identifier, type_argument)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function_context.inherit_data_from(&context)?;
|
function_context.inherit_data_from(&context)?;
|
||||||
function.clone().call(arguments, function_context)
|
function.clone().call(arguments, function_context)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
pub mod async_block;
|
pub mod async_block;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod built_in_function_call;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
pub mod function_call;
|
pub mod function_call;
|
||||||
pub mod if_else;
|
pub mod if_else;
|
||||||
@ -23,6 +24,7 @@ pub use self::{
|
|||||||
assignment::{Assignment, AssignmentOperator},
|
assignment::{Assignment, AssignmentOperator},
|
||||||
async_block::AsyncBlock,
|
async_block::AsyncBlock,
|
||||||
block::Block,
|
block::Block,
|
||||||
|
built_in_function_call::BuiltInFunctionCall,
|
||||||
expression::Expression,
|
expression::Expression,
|
||||||
function_call::FunctionCall,
|
function_call::FunctionCall,
|
||||||
if_else::IfElse,
|
if_else::IfElse,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
|
use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
built_in_functions::BuiltInFunction,
|
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
@ -13,7 +12,6 @@ use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueNode {
|
pub enum ValueNode {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
BuiltInFunction(BuiltInFunction),
|
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
List(Vec<Expression>),
|
List(Vec<Expression>),
|
||||||
@ -88,7 +86,6 @@ impl AbstractNode for ValueNode {
|
|||||||
fields: types,
|
fields: types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInFunction(built_in_function) => built_in_function.r#type(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(r#type)
|
Ok(r#type)
|
||||||
@ -260,9 +257,6 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
Value::structure(name, fields)
|
Value::structure(name, fields)
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInFunction(built_in_function) => {
|
|
||||||
Value::built_in_function(built_in_function)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Action::Return(value))
|
Ok(Action::Return(value))
|
||||||
@ -358,8 +352,6 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Structure { .. }, _) => Ordering::Greater,
|
(Structure { .. }, _) => Ordering::Greater,
|
||||||
(BuiltInFunction(_), BuiltInFunction(_)) => todo!(),
|
|
||||||
(BuiltInFunction(_), _) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fmt::{self, Display, Formatter},
|
|
||||||
io::stdin,
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
abstract_tree::{Action, Type, WithPos},
|
|
||||||
context::Context,
|
|
||||||
error::RuntimeError,
|
|
||||||
value::ValueInner,
|
|
||||||
Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum BuiltInFunction {
|
|
||||||
ReadLine,
|
|
||||||
Sleep,
|
|
||||||
WriteLine,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BuiltInFunction {
|
|
||||||
pub fn name(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
BuiltInFunction::ReadLine => "__READ_LINE__",
|
|
||||||
BuiltInFunction::Sleep => "__SLEEP__",
|
|
||||||
BuiltInFunction::WriteLine => "__WRITE_LINE__",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_value(self) -> Value {
|
|
||||||
Value::built_in_function(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn r#type(&self) -> Type {
|
|
||||||
match self {
|
|
||||||
BuiltInFunction::WriteLine => Type::Function {
|
|
||||||
parameter_types: vec![Type::String.with_position((0, 0))],
|
|
||||||
return_type: Box::new(Type::None.with_position((0, 0))),
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(&self, arguments: Vec<Value>, _context: &Context) -> Result<Action, RuntimeError> {
|
|
||||||
match self {
|
|
||||||
// "INT_RANDOM_RANGE" => {
|
|
||||||
// let range = arguments.get(0).unwrap();
|
|
||||||
|
|
||||||
// if let ValueInner::Range(range) = range.inner().as_ref() {
|
|
||||||
// let random = thread_rng().gen_range(range.clone());
|
|
||||||
|
|
||||||
// Ok(Action::Return(Value::integer(random)))
|
|
||||||
// } else {
|
|
||||||
// panic!("Built-in function cannot have a non-function type.")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
BuiltInFunction::ReadLine => {
|
|
||||||
let mut input = String::new();
|
|
||||||
|
|
||||||
stdin().read_line(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Action::Return(Value::string(input)))
|
|
||||||
}
|
|
||||||
BuiltInFunction::Sleep => {
|
|
||||||
if let ValueInner::Integer(milliseconds) = arguments[0].inner().as_ref() {
|
|
||||||
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Action::None)
|
|
||||||
}
|
|
||||||
BuiltInFunction::WriteLine => {
|
|
||||||
println!("{}", arguments[0]);
|
|
||||||
|
|
||||||
Ok(Action::None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for BuiltInFunction {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.name())
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,12 +5,11 @@ use std::{
|
|||||||
|
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::{built_in_functions::BuiltInFunction, error::Error};
|
use crate::error::Error;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Token<'src> {
|
pub enum Token<'src> {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
BuiltInFunction(BuiltInFunction),
|
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
String(&'src str),
|
String(&'src str),
|
||||||
@ -24,7 +23,6 @@ impl<'src> Display for Token<'src> {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Token::Boolean(boolean) => write!(f, "{boolean}"),
|
Token::Boolean(boolean) => write!(f, "{boolean}"),
|
||||||
Token::BuiltInFunction(built_in_function) => write!(f, "{built_in_function}"),
|
|
||||||
Token::Integer(integer) => write!(f, "{integer}"),
|
Token::Integer(integer) => write!(f, "{integer}"),
|
||||||
Token::Float(float) => write!(f, "{float}"),
|
Token::Float(float) => write!(f, "{float}"),
|
||||||
Token::String(string) => write!(f, "{string}"),
|
Token::String(string) => write!(f, "{string}"),
|
||||||
@ -51,11 +49,14 @@ pub enum Keyword {
|
|||||||
Map,
|
Map,
|
||||||
None,
|
None,
|
||||||
Range,
|
Range,
|
||||||
|
ReadLine,
|
||||||
|
Sleep,
|
||||||
Struct,
|
Struct,
|
||||||
Str,
|
Str,
|
||||||
Type,
|
Type,
|
||||||
Loop,
|
Loop,
|
||||||
While,
|
While,
|
||||||
|
WriteLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Keyword {
|
impl Display for Keyword {
|
||||||
@ -79,6 +80,9 @@ impl Display for Keyword {
|
|||||||
Keyword::Loop => write!(f, "loop"),
|
Keyword::Loop => write!(f, "loop"),
|
||||||
Keyword::While => write!(f, "while"),
|
Keyword::While => write!(f, "while"),
|
||||||
Keyword::Type => write!(f, "type"),
|
Keyword::Type => write!(f, "type"),
|
||||||
|
Keyword::ReadLine => write!(f, "READ_LINE"),
|
||||||
|
Keyword::Sleep => write!(f, "SLEEP"),
|
||||||
|
Keyword::WriteLine => write!(f, "WRITE_LINE"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,6 +150,7 @@ pub enum Control {
|
|||||||
Semicolon,
|
Semicolon,
|
||||||
SkinnyArrow,
|
SkinnyArrow,
|
||||||
FatArrow,
|
FatArrow,
|
||||||
|
DoubleUnderscore,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Control {
|
impl Display for Control {
|
||||||
@ -167,6 +172,7 @@ impl Display for Control {
|
|||||||
Control::DoubleDot => write!(f, ".."),
|
Control::DoubleDot => write!(f, ".."),
|
||||||
Control::SkinnyArrow => write!(f, "->"),
|
Control::SkinnyArrow => write!(f, "->"),
|
||||||
Control::FatArrow => write!(f, "=>"),
|
Control::FatArrow => write!(f, "=>"),
|
||||||
|
Control::DoubleUnderscore => write!(f, "__"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,6 +278,7 @@ pub fn lexer<'src>() -> impl Parser<
|
|||||||
just("..").to(Control::DoubleDot),
|
just("..").to(Control::DoubleDot),
|
||||||
just(".").to(Control::Dot),
|
just(".").to(Control::Dot),
|
||||||
just("$").to(Control::Dollar),
|
just("$").to(Control::Dollar),
|
||||||
|
just("__").to(Control::DoubleUnderscore),
|
||||||
))
|
))
|
||||||
.map(Token::Control);
|
.map(Token::Control);
|
||||||
|
|
||||||
@ -294,26 +301,14 @@ pub fn lexer<'src>() -> impl Parser<
|
|||||||
just("type").to(Keyword::Type),
|
just("type").to(Keyword::Type),
|
||||||
just("loop").to(Keyword::Loop),
|
just("loop").to(Keyword::Loop),
|
||||||
just("while").to(Keyword::While),
|
just("while").to(Keyword::While),
|
||||||
|
just("READ_LINE").to(Keyword::ReadLine),
|
||||||
|
just("SLEEP").to(Keyword::Sleep),
|
||||||
|
just("WRITE_LINE").to(Keyword::WriteLine),
|
||||||
))
|
))
|
||||||
.map(Token::Keyword);
|
.map(Token::Keyword);
|
||||||
|
|
||||||
let built_in_function = choice((
|
|
||||||
just(BuiltInFunction::ReadLine.name()).to(BuiltInFunction::ReadLine),
|
|
||||||
just(BuiltInFunction::Sleep.name()).to(BuiltInFunction::Sleep),
|
|
||||||
just(BuiltInFunction::WriteLine.name()).to(BuiltInFunction::WriteLine),
|
|
||||||
))
|
|
||||||
.map(Token::BuiltInFunction);
|
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
boolean,
|
boolean, float, integer, string, keyword, identifier, control, operator,
|
||||||
float,
|
|
||||||
integer,
|
|
||||||
string,
|
|
||||||
keyword,
|
|
||||||
identifier,
|
|
||||||
control,
|
|
||||||
operator,
|
|
||||||
built_in_function,
|
|
||||||
))
|
))
|
||||||
.map_with(|token, state| (token, state.span()))
|
.map_with(|token, state| (token, state.span()))
|
||||||
.padded()
|
.padded()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
pub mod abstract_tree;
|
pub mod abstract_tree;
|
||||||
pub mod built_in_functions;
|
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
|
@ -255,16 +255,22 @@ pub fn parser<'src>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let built_in_function = {
|
let built_in_function_call = just(Token::Control(Control::DoubleUnderscore))
|
||||||
select! {
|
.ignore_then(choice((
|
||||||
Token::BuiltInFunction(built_in_function) => built_in_function,
|
just(Token::Keyword(Keyword::ReadLine)).to(BuiltInFunctionCall::ReadLine),
|
||||||
}
|
just(Token::Keyword(Keyword::Sleep))
|
||||||
}
|
.ignore_then(expression.clone())
|
||||||
.map_with(|built_in_function, state| {
|
.map(|expression| BuiltInFunctionCall::Sleep(expression)),
|
||||||
Expression::Value(
|
just(Token::Keyword(Keyword::WriteLine))
|
||||||
ValueNode::BuiltInFunction(built_in_function).with_position(state.span()),
|
.ignore_then(expression.clone())
|
||||||
)
|
.map(|expression| BuiltInFunctionCall::WriteLine(expression)),
|
||||||
});
|
)))
|
||||||
|
.then_ignore(just(Token::Control(Control::DoubleUnderscore)))
|
||||||
|
.map_with(|built_in_function_call, state| {
|
||||||
|
Expression::BuiltInFunctionCall(
|
||||||
|
Box::new(built_in_function_call).with_position(state.span()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let structure_field = identifier
|
let structure_field = identifier
|
||||||
.clone()
|
.clone()
|
||||||
@ -307,7 +313,6 @@ pub fn parser<'src>(
|
|||||||
range.clone(),
|
range.clone(),
|
||||||
structure_instance.clone(),
|
structure_instance.clone(),
|
||||||
parsed_function.clone(),
|
parsed_function.clone(),
|
||||||
built_in_function.clone(),
|
|
||||||
list.clone(),
|
list.clone(),
|
||||||
map.clone(),
|
map.clone(),
|
||||||
basic_value.clone(),
|
basic_value.clone(),
|
||||||
@ -475,11 +480,11 @@ pub fn parser<'src>(
|
|||||||
));
|
));
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
|
built_in_function_call,
|
||||||
logic_math_indexes_and_function_calls,
|
logic_math_indexes_and_function_calls,
|
||||||
range,
|
range,
|
||||||
structure_instance,
|
structure_instance,
|
||||||
parsed_function,
|
parsed_function,
|
||||||
built_in_function,
|
|
||||||
list,
|
list,
|
||||||
map,
|
map,
|
||||||
basic_value,
|
basic_value,
|
||||||
@ -588,7 +593,7 @@ pub fn parser<'src>(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{built_in_functions::BuiltInFunction, lexer::lex};
|
use crate::lexer::lex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -596,10 +601,20 @@ mod tests {
|
|||||||
fn built_in_function() {
|
fn built_in_function() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("__READ_LINE__").unwrap()).unwrap()[0],
|
parse(&lex("__READ_LINE__").unwrap()).unwrap()[0],
|
||||||
Statement::Expression(Expression::Value(
|
Statement::Expression(Expression::BuiltInFunctionCall(
|
||||||
ValueNode::BuiltInFunction(BuiltInFunction::ReadLine).with_position((0, 13))
|
Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 13))
|
||||||
))
|
))
|
||||||
)
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse(&lex("__WRITE_LINE 'hiya'__").unwrap()).unwrap()[0],
|
||||||
|
Statement::Expression(Expression::BuiltInFunctionCall(
|
||||||
|
Box::new(BuiltInFunctionCall::WriteLine(Expression::Value(
|
||||||
|
ValueNode::String("hiya".to_string()).with_position((13, 19))
|
||||||
|
)))
|
||||||
|
.with_position((0, 21))
|
||||||
|
))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -14,7 +14,6 @@ use stanza::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
|
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
|
||||||
built_in_functions::BuiltInFunction,
|
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
@ -62,24 +61,18 @@ impl Value {
|
|||||||
return_type: WithPosition<Type>,
|
return_type: WithPosition<Type>,
|
||||||
body: WithPosition<Block>,
|
body: WithPosition<Block>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Value(Arc::new(ValueInner::Function(Function::Parsed(
|
Value(Arc::new(ValueInner::Function(Function {
|
||||||
ParsedFunction {
|
type_parameters: type_arguments,
|
||||||
type_parameters: type_arguments,
|
parameters,
|
||||||
parameters,
|
return_type,
|
||||||
return_type,
|
body,
|
||||||
body,
|
})))
|
||||||
},
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn structure(name: WithPosition<Identifier>, fields: Vec<(Identifier, Value)>) -> Self {
|
pub fn structure(name: WithPosition<Identifier>, fields: Vec<(Identifier, Value)>) -> Self {
|
||||||
Value(Arc::new(ValueInner::Structure { name, fields }))
|
Value(Arc::new(ValueInner::Structure { name, fields }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn built_in_function(function: BuiltInFunction) -> Self {
|
|
||||||
Value(Arc::new(ValueInner::Function(Function::BuiltIn(function))))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn r#type(&self, context: &Context) -> Result<Type, ValidationError> {
|
pub fn r#type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||||
self.0.r#type(context)
|
self.0.r#type(context)
|
||||||
}
|
}
|
||||||
@ -139,12 +132,12 @@ impl Display for Value {
|
|||||||
}
|
}
|
||||||
ValueInner::Range(_) => todo!(),
|
ValueInner::Range(_) => todo!(),
|
||||||
ValueInner::String(string) => write!(f, "{string}"),
|
ValueInner::String(string) => write!(f, "{string}"),
|
||||||
ValueInner::Function(Function::Parsed(ParsedFunction {
|
ValueInner::Function(Function {
|
||||||
type_parameters: type_arguments,
|
type_parameters: type_arguments,
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
})) => {
|
}) => {
|
||||||
if !type_arguments.is_empty() {
|
if !type_arguments.is_empty() {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
|
|
||||||
@ -167,8 +160,8 @@ impl Display for Value {
|
|||||||
|
|
||||||
write!(f, "): {} {:?}", return_type.node, body.node)
|
write!(f, "): {} {:?}", return_type.node, body.node)
|
||||||
}
|
}
|
||||||
ValueInner::Function(Function::BuiltIn(built_in_function)) => {
|
ValueInner::Function(function) => {
|
||||||
write!(f, "{built_in_function}")
|
write!(f, "{function}")
|
||||||
}
|
}
|
||||||
ValueInner::Structure { name, fields } => {
|
ValueInner::Structure { name, fields } => {
|
||||||
let mut table = create_table();
|
let mut table = create_table();
|
||||||
@ -231,18 +224,13 @@ impl ValueInner {
|
|||||||
ValueInner::Map(_) => Type::Map,
|
ValueInner::Map(_) => Type::Map,
|
||||||
ValueInner::Range(_) => Type::Range,
|
ValueInner::Range(_) => Type::Range,
|
||||||
ValueInner::String(_) => Type::String,
|
ValueInner::String(_) => Type::String,
|
||||||
ValueInner::Function(function) => match function {
|
ValueInner::Function(function) => Type::Function {
|
||||||
Function::Parsed(parsed_function) => Type::Function {
|
parameter_types: function
|
||||||
parameter_types: parsed_function
|
.parameters
|
||||||
.parameters
|
.iter()
|
||||||
.iter()
|
.map(|(_, r#type)| r#type.clone())
|
||||||
.map(|(_, r#type)| r#type.clone())
|
.collect(),
|
||||||
.collect(),
|
return_type: Box::new(function.return_type.clone()),
|
||||||
return_type: Box::new(parsed_function.return_type.clone()),
|
|
||||||
},
|
|
||||||
Function::BuiltIn(built_in_function) => {
|
|
||||||
built_in_function.clone().as_value().r#type(context)?
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ValueInner::Structure { name, .. } => {
|
ValueInner::Structure { name, .. } => {
|
||||||
if let Some(r#type) = context.get_type(&name.node)? {
|
if let Some(r#type) = context.get_type(&name.node)? {
|
||||||
@ -321,34 +309,29 @@ impl Ord for ValueInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Function {
|
pub struct Function {
|
||||||
Parsed(ParsedFunction),
|
type_parameters: Vec<WithPosition<Type>>,
|
||||||
BuiltIn(BuiltInFunction),
|
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
||||||
|
return_type: WithPosition<Type>,
|
||||||
|
body: WithPosition<Block>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
|
pub fn type_parameters(&self) -> &Vec<WithPosition<Type>> {
|
||||||
|
&self.type_parameters
|
||||||
|
}
|
||||||
|
|
||||||
pub fn call(self, arguments: Vec<Value>, context: Context) -> Result<Action, RuntimeError> {
|
pub fn call(self, arguments: Vec<Value>, context: Context) -> Result<Action, RuntimeError> {
|
||||||
let action = match self {
|
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) {
|
||||||
Function::Parsed(ParsedFunction {
|
context.set_value(identifier.clone(), value)?;
|
||||||
parameters, body, ..
|
}
|
||||||
}) => {
|
|
||||||
for ((identifier, _), value) in parameters.into_iter().zip(arguments.into_iter()) {
|
|
||||||
context.set_value(identifier.clone(), value)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.node.run(&context)?
|
self.body.node.run(&context)
|
||||||
}
|
|
||||||
Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(action)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
impl Display for Function {
|
||||||
pub struct ParsedFunction {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
pub type_parameters: Vec<WithPosition<Type>>,
|
todo!()
|
||||||
pub parameters: Vec<(Identifier, WithPosition<Type>)>,
|
}
|
||||||
pub return_type: WithPosition<Type>,
|
|
||||||
pub body: WithPosition<Block>,
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user