Continue standard library
This commit is contained in:
parent
a8f840a305
commit
eaff59c88d
@ -111,8 +111,6 @@ impl AbstractNode for MapIndex {
|
|||||||
if let (ValueInner::Map(map), Expression::Identifier(identifier)) =
|
if let (ValueInner::Map(map), Expression::Identifier(identifier)) =
|
||||||
(collection.inner().as_ref(), &self.right.node)
|
(collection.inner().as_ref(), &self.right.node)
|
||||||
{
|
{
|
||||||
println!("{map:?} {identifier}");
|
|
||||||
|
|
||||||
let action = map
|
let action = map
|
||||||
.get(identifier)
|
.get(identifier)
|
||||||
.map(|value| Action::Return(value.clone()))
|
.map(|value| Action::Return(value.clone()))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
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},
|
||||||
Value,
|
Value,
|
||||||
@ -11,6 +12,7 @@ use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPosit
|
|||||||
#[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<WithPosition<Expression>>),
|
List(Vec<WithPosition<Expression>>),
|
||||||
@ -27,7 +29,7 @@ pub enum ValueNode {
|
|||||||
name: Identifier,
|
name: Identifier,
|
||||||
fields: Vec<(Identifier, WithPosition<Expression>)>,
|
fields: Vec<(Identifier, WithPosition<Expression>)>,
|
||||||
},
|
},
|
||||||
Function {
|
ParsedFunction {
|
||||||
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
||||||
return_type: WithPosition<Type>,
|
return_type: WithPosition<Type>,
|
||||||
body: WithPosition<Block>,
|
body: WithPosition<Block>,
|
||||||
@ -35,7 +37,7 @@ pub enum ValueNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for ValueNode {
|
impl AbstractNode for ValueNode {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||||
let r#type = match self {
|
let r#type = match self {
|
||||||
ValueNode::Boolean(_) => Type::Boolean,
|
ValueNode::Boolean(_) => Type::Boolean,
|
||||||
ValueNode::Float(_) => Type::Float,
|
ValueNode::Float(_) => Type::Float,
|
||||||
@ -44,7 +46,7 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut item_types = Vec::with_capacity(items.len());
|
let mut item_types = Vec::with_capacity(items.len());
|
||||||
|
|
||||||
for expression in items {
|
for expression in items {
|
||||||
item_types.push(expression.node.expected_type(_context)?);
|
item_types.push(expression.node.expected_type(context)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::ListExact(item_types)
|
Type::ListExact(item_types)
|
||||||
@ -52,7 +54,7 @@ impl AbstractNode for ValueNode {
|
|||||||
ValueNode::Map(_) => Type::Map,
|
ValueNode::Map(_) => Type::Map,
|
||||||
ValueNode::Range(_) => Type::Range,
|
ValueNode::Range(_) => Type::Range,
|
||||||
ValueNode::String(_) => Type::String,
|
ValueNode::String(_) => Type::String,
|
||||||
ValueNode::Function {
|
ValueNode::ParsedFunction {
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
..
|
..
|
||||||
@ -70,7 +72,7 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut types = Vec::with_capacity(expressions.len());
|
let mut types = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
for (identifier, expression) in expressions {
|
for (identifier, expression) in expressions {
|
||||||
let r#type = expression.node.expected_type(_context)?;
|
let r#type = expression.node.expected_type(context)?;
|
||||||
|
|
||||||
types.push((
|
types.push((
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
@ -86,6 +88,7 @@ impl AbstractNode for ValueNode {
|
|||||||
fields: types,
|
fields: types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ValueNode::BuiltInFunction(built_in_function) => built_in_function.r#type(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(r#type)
|
Ok(r#type)
|
||||||
@ -108,7 +111,7 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ValueNode::Function {
|
if let ValueNode::ParsedFunction {
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
@ -141,20 +144,11 @@ impl AbstractNode for ValueNode {
|
|||||||
fields: expressions,
|
fields: expressions,
|
||||||
} = self
|
} = self
|
||||||
{
|
{
|
||||||
let types = if let Some(r#type) = context.get_type(name)? {
|
|
||||||
if let Type::Structure {
|
if let Type::Structure {
|
||||||
name: _,
|
name: _,
|
||||||
fields: types,
|
fields: types,
|
||||||
} = r#type
|
} = name.expected_type(context)?
|
||||||
{
|
{
|
||||||
types
|
|
||||||
} else {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(ValidationError::TypeNotFound(name.clone()));
|
|
||||||
};
|
|
||||||
|
|
||||||
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
||||||
let actual_type = expression.node.expected_type(context)?;
|
let actual_type = expression.node.expected_type(context)?;
|
||||||
|
|
||||||
@ -167,6 +161,7 @@ impl AbstractNode for ValueNode {
|
|||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -214,7 +209,7 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
ValueNode::Range(range) => Value::range(range),
|
ValueNode::Range(range) => Value::range(range),
|
||||||
ValueNode::String(string) => Value::string(string),
|
ValueNode::String(string) => Value::string(string),
|
||||||
ValueNode::Function {
|
ValueNode::ParsedFunction {
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
@ -240,6 +235,9 @@ 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))
|
||||||
@ -282,12 +280,12 @@ impl Ord for ValueNode {
|
|||||||
(String(left), String(right)) => left.cmp(right),
|
(String(left), String(right)) => left.cmp(right),
|
||||||
(String(_), _) => Ordering::Greater,
|
(String(_), _) => Ordering::Greater,
|
||||||
(
|
(
|
||||||
Function {
|
ParsedFunction {
|
||||||
parameters: left_parameters,
|
parameters: left_parameters,
|
||||||
return_type: left_return,
|
return_type: left_return,
|
||||||
body: left_body,
|
body: left_body,
|
||||||
},
|
},
|
||||||
Function {
|
ParsedFunction {
|
||||||
parameters: right_parameters,
|
parameters: right_parameters,
|
||||||
return_type: right_return,
|
return_type: right_return,
|
||||||
body: right_body,
|
body: right_body,
|
||||||
@ -307,7 +305,7 @@ impl Ord for ValueNode {
|
|||||||
parameter_cmp
|
parameter_cmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Function { .. }, _) => Ordering::Greater,
|
(ParsedFunction { .. }, _) => Ordering::Greater,
|
||||||
(
|
(
|
||||||
Structure {
|
Structure {
|
||||||
name: left_name,
|
name: left_name,
|
||||||
@ -327,6 +325,8 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Structure { .. }, _) => Ordering::Greater,
|
(Structure { .. }, _) => Ordering::Greater,
|
||||||
|
(BuiltInFunction(_), BuiltInFunction(_)) => todo!(),
|
||||||
|
(BuiltInFunction(_), _) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use core::fmt;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
io::stdin,
|
io::stdin,
|
||||||
thread,
|
thread,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@ -9,48 +8,46 @@ use std::{
|
|||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Action, Type},
|
abstract_tree::{Action, Identifier, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BUILT_IN_FUNCTIONS: [BuiltInFunction; 5] = [
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
BuiltInFunction::IntParse,
|
pub struct BuiltInFunction {
|
||||||
BuiltInFunction::IntRandomRange,
|
name: WithPosition<Identifier>,
|
||||||
BuiltInFunction::ReadLine,
|
|
||||||
BuiltInFunction::WriteLine,
|
|
||||||
BuiltInFunction::Sleep,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum BuiltInFunction {
|
|
||||||
IntParse,
|
|
||||||
IntRandomRange,
|
|
||||||
ReadLine,
|
|
||||||
WriteLine,
|
|
||||||
Sleep,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltInFunction {
|
impl BuiltInFunction {
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn new(name: WithPosition<Identifier>) -> Self {
|
||||||
match self {
|
Self { name }
|
||||||
BuiltInFunction::IntParse => "parse",
|
|
||||||
BuiltInFunction::IntRandomRange => "random_range",
|
|
||||||
BuiltInFunction::ReadLine => "read_line",
|
|
||||||
BuiltInFunction::WriteLine => "write_line",
|
|
||||||
BuiltInFunction::Sleep => "sleep",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &Identifier {
|
||||||
|
&self.name.node
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_value(self) -> Value {
|
pub fn as_value(self) -> Value {
|
||||||
Value::built_in_function(self)
|
Value::built_in_function(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn r#type(&self) -> Type {
|
||||||
|
match self.name.node.as_str() {
|
||||||
|
"WRITE_LINE" => Type::Function {
|
||||||
|
parameter_types: vec![Type::String],
|
||||||
|
return_type: Box::new(Type::None),
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn call(&self, arguments: Vec<Value>, context: &Context) -> Result<Action, RuntimeError> {
|
pub fn call(&self, arguments: Vec<Value>, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
match self {
|
match self.name.node.as_str() {
|
||||||
BuiltInFunction::IntParse => {
|
"INT_PARSE" => {
|
||||||
let string = arguments.get(0).unwrap();
|
let string = arguments.get(0).unwrap();
|
||||||
|
|
||||||
if let ValueInner::String(_string) = string.inner().as_ref() {
|
if let ValueInner::String(_string) = string.inner().as_ref() {
|
||||||
@ -76,7 +73,7 @@ impl BuiltInFunction {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltInFunction::IntRandomRange => {
|
"INT_RANDOM_RANGE" => {
|
||||||
let range = arguments.get(0).unwrap();
|
let range = arguments.get(0).unwrap();
|
||||||
|
|
||||||
if let ValueInner::Range(range) = range.inner().as_ref() {
|
if let ValueInner::Range(range) = range.inner().as_ref() {
|
||||||
@ -87,37 +84,34 @@ impl BuiltInFunction {
|
|||||||
panic!("Built-in function cannot have a non-function type.")
|
panic!("Built-in function cannot have a non-function type.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltInFunction::ReadLine => {
|
"READ_LINE" => {
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
|
||||||
stdin().read_line(&mut input)?;
|
stdin().read_line(&mut input)?;
|
||||||
|
|
||||||
Ok(Action::Return(Value::string(input)))
|
Ok(Action::Return(Value::string(input)))
|
||||||
}
|
}
|
||||||
BuiltInFunction::WriteLine => {
|
"WRITE_LINE" => {
|
||||||
println!("{}", arguments[0]);
|
println!("{}", arguments[0]);
|
||||||
|
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
BuiltInFunction::Sleep => {
|
"SLEEP" => {
|
||||||
if let ValueInner::Integer(milliseconds) = arguments[0].inner().as_ref() {
|
if let ValueInner::Integer(milliseconds) = arguments[0].inner().as_ref() {
|
||||||
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for BuiltInFunction {
|
impl Display for BuiltInFunction {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
write!(f, "{}", self.name.node)
|
||||||
BuiltInFunction::IntParse => write!(f, "(input : int) : str {{ *MAGIC* }}"),
|
|
||||||
BuiltInFunction::IntRandomRange => write!(f, "(input: range) : int {{ *MAGIC* }}"),
|
|
||||||
BuiltInFunction::ReadLine => write!(f, "() : str {{ *MAGIC* }}"),
|
|
||||||
BuiltInFunction::WriteLine => write!(f, "(to_output : any) : none {{ *MAGIC* }}"),
|
|
||||||
BuiltInFunction::Sleep => write!(f, "(milliseconds : int) : none {{ *MAGIC* }}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Identifier, Type},
|
abstract_tree::{Identifier, Type},
|
||||||
built_in_functions::BUILT_IN_FUNCTIONS,
|
|
||||||
error::{RwLockPoisonError, ValidationError},
|
error::{RwLockPoisonError, ValidationError},
|
||||||
Interpreter, Value,
|
Interpreter, Value,
|
||||||
};
|
};
|
||||||
@ -14,22 +13,11 @@ static STD_CONTEXT: OnceLock<Context> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_context<'a>() -> &'a Context {
|
pub fn std_context<'a>() -> &'a Context {
|
||||||
STD_CONTEXT.get_or_init(|| {
|
STD_CONTEXT.get_or_init(|| {
|
||||||
let mut data = BTreeMap::new();
|
let context = Context::new();
|
||||||
|
|
||||||
for function in BUILT_IN_FUNCTIONS {
|
|
||||||
data.insert(
|
|
||||||
Identifier::new(function.name()),
|
|
||||||
ValueData::Value(function.as_value()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = Context::with_data(data);
|
|
||||||
let mut interpreter = Interpreter::new(context.clone());
|
let mut interpreter = Interpreter::new(context.clone());
|
||||||
|
|
||||||
interpreter.run(include_str!("../../std/io.ds")).unwrap();
|
interpreter.run(include_str!("../../std/io.ds")).unwrap();
|
||||||
|
|
||||||
context.remove(&Identifier::new("write_line")).unwrap();
|
|
||||||
|
|
||||||
context
|
context
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@ pub enum Control {
|
|||||||
Comma,
|
Comma,
|
||||||
DoubleColon,
|
DoubleColon,
|
||||||
Colon,
|
Colon,
|
||||||
|
Dollar,
|
||||||
Dot,
|
Dot,
|
||||||
DoubleDot,
|
DoubleDot,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
@ -127,6 +128,7 @@ impl Display for Control {
|
|||||||
Control::Arrow => write!(f, "->"),
|
Control::Arrow => write!(f, "->"),
|
||||||
Control::CurlyOpen => write!(f, "{{"),
|
Control::CurlyOpen => write!(f, "{{"),
|
||||||
Control::CurlyClose => write!(f, "}}"),
|
Control::CurlyClose => write!(f, "}}"),
|
||||||
|
Control::Dollar => write!(f, "$"),
|
||||||
Control::SquareOpen => write!(f, "["),
|
Control::SquareOpen => write!(f, "["),
|
||||||
Control::SquareClose => write!(f, "]"),
|
Control::SquareClose => write!(f, "]"),
|
||||||
Control::ParenOpen => write!(f, "("),
|
Control::ParenOpen => write!(f, "("),
|
||||||
@ -252,6 +254,7 @@ pub fn lexer<'src>() -> impl Parser<
|
|||||||
just(":").to(Control::Colon),
|
just(":").to(Control::Colon),
|
||||||
just("..").to(Control::DoubleDot),
|
just("..").to(Control::DoubleDot),
|
||||||
just(".").to(Control::Dot),
|
just(".").to(Control::Dot),
|
||||||
|
just("$").to(Control::Dollar),
|
||||||
))
|
))
|
||||||
.map(Token::Control);
|
.map(Token::Control);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ use chumsky::{input::SpannedInput, pratt::*, prelude::*};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::*,
|
abstract_tree::*,
|
||||||
|
built_in_functions::BuiltInFunction,
|
||||||
error::Error,
|
error::Error,
|
||||||
lexer::{Control, Keyword, Operator, Token},
|
lexer::{Control, Keyword, Operator, Token},
|
||||||
};
|
};
|
||||||
@ -212,7 +213,7 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
.with_position(state.span())
|
.with_position(state.span())
|
||||||
});
|
});
|
||||||
|
|
||||||
let function = identifier
|
let parsed_function = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(type_specification.clone())
|
.then(type_specification.clone())
|
||||||
.separated_by(just(Token::Control(Control::Comma)))
|
.separated_by(just(Token::Control(Control::Comma)))
|
||||||
@ -224,7 +225,7 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
.then(type_specification.clone())
|
.then(type_specification.clone())
|
||||||
.then(block.clone())
|
.then(block.clone())
|
||||||
.map_with(|((parameters, return_type), body), state| {
|
.map_with(|((parameters, return_type), body), state| {
|
||||||
Expression::Value(ValueNode::Function {
|
Expression::Value(ValueNode::ParsedFunction {
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body: body.with_position(state.span()),
|
body: body.with_position(state.span()),
|
||||||
@ -232,8 +233,16 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
.with_position(state.span())
|
.with_position(state.span())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let built_in_function = just(Token::Control(Control::Dollar))
|
||||||
|
.ignore_then(positioned_identifier.clone())
|
||||||
|
.map_with(|identifier, state| {
|
||||||
|
Expression::Value(ValueNode::BuiltInFunction(BuiltInFunction::new(identifier)))
|
||||||
|
.with_position(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
let atom = choice((
|
let atom = choice((
|
||||||
function.clone(),
|
built_in_function.clone(),
|
||||||
|
parsed_function.clone(),
|
||||||
identifier_expression.clone(),
|
identifier_expression.clone(),
|
||||||
basic_value.clone(),
|
basic_value.clone(),
|
||||||
list.clone(),
|
list.clone(),
|
||||||
@ -406,7 +415,8 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
structure_instance,
|
structure_instance,
|
||||||
range,
|
range,
|
||||||
logic_math_indexes_and_function_calls,
|
logic_math_indexes_and_function_calls,
|
||||||
function,
|
parsed_function,
|
||||||
|
built_in_function,
|
||||||
list,
|
list,
|
||||||
map,
|
map,
|
||||||
basic_value,
|
basic_value,
|
||||||
@ -522,6 +532,18 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn built_in_function() {
|
||||||
|
assert_eq!(
|
||||||
|
parse(&lex("$READ_LINE").unwrap()).unwrap()[0].node,
|
||||||
|
Statement::Expression(Expression::Value(ValueNode::BuiltInFunction(
|
||||||
|
BuiltInFunction::new(
|
||||||
|
Identifier::new("READ_LINE".to_string()).with_position((1, 10))
|
||||||
|
)
|
||||||
|
)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn async_block() {
|
fn async_block() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -756,7 +778,7 @@ mod tests {
|
|||||||
fn function() {
|
fn function() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("(x: int) : int { x }").unwrap()).unwrap()[0].node,
|
parse(&lex("(x: int) : int { x }").unwrap()).unwrap()[0].node,
|
||||||
Statement::Expression(Expression::Value(ValueNode::Function {
|
Statement::Expression(Expression::Value(ValueNode::ParsedFunction {
|
||||||
parameters: vec![(Identifier::new("x"), Type::Integer.with_position((4, 7)))],
|
parameters: vec![(Identifier::new("x"), Type::Integer.with_position((4, 7)))],
|
||||||
return_type: Type::Integer.with_position((11, 14)),
|
return_type: Type::Integer.with_position((11, 14)),
|
||||||
body: Block::new(vec![Statement::Expression(Expression::Identifier(
|
body: Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||||
|
@ -223,7 +223,7 @@ impl ValueInner {
|
|||||||
return_type: Box::new(parsed_function.return_type.node.clone()),
|
return_type: Box::new(parsed_function.return_type.node.clone()),
|
||||||
},
|
},
|
||||||
Function::BuiltIn(built_in_function) => {
|
Function::BuiltIn(built_in_function) => {
|
||||||
(*built_in_function).as_value().r#type(context)?
|
built_in_function.clone().as_value().r#type(context)?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ValueInner::Structure { name, .. } => {
|
ValueInner::Structure { name, .. } => {
|
||||||
|
Loading…
Reference in New Issue
Block a user