Finish function syntax
This commit is contained in:
parent
e1a7c3ff72
commit
b91e23fef3
@ -1,4 +1,4 @@
|
|||||||
fib <(int) -> int> = fn |i| {
|
fib = (fn i <int>) <int> {
|
||||||
if i <= 1 {
|
if i <= 1 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,20 +51,14 @@ impl AbstractTree for FunctionCall {
|
|||||||
for (argument, r#type) in argument_type_pairs {
|
for (argument, r#type) in argument_type_pairs {
|
||||||
let argument_type = argument.expected_type(context)?;
|
let argument_type = argument.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Function { return_type, .. } = argument_type {
|
|
||||||
r#type.check(&return_type)?;
|
|
||||||
} else {
|
|
||||||
r#type.check(&argument_type)?;
|
r#type.check(&argument_type)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let function_call = FunctionCall {
|
Ok(FunctionCall {
|
||||||
function_expression,
|
function_expression,
|
||||||
arguments,
|
arguments,
|
||||||
};
|
})
|
||||||
|
|
||||||
Ok(function_call)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||||
@ -137,7 +131,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate(
|
evaluate(
|
||||||
"
|
"
|
||||||
foobar <(str) -> str> = fn |message| { message }
|
foobar = (fn message <str>) <str> { message }
|
||||||
(foobar 'Hiya')
|
(foobar 'Hiya')
|
||||||
",
|
",
|
||||||
),
|
),
|
||||||
@ -150,11 +144,11 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate(
|
evaluate(
|
||||||
"
|
"
|
||||||
foobar <(() -> str) -> str> = fn |cb| {
|
foobar = (fn cb <() -> str>) <str> {
|
||||||
(cb)
|
(cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
(foobar fn || { 'Hiya' })
|
(foobar (fn) <str> { 'Hiya' })
|
||||||
",
|
",
|
||||||
),
|
),
|
||||||
Ok(Value::String("Hiya".to_string()))
|
Ok(Value::String("Hiya".to_string()))
|
||||||
|
83
src/abstract_tree/function_declaration.rs
Normal file
83
src/abstract_tree/function_declaration.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tree_sitter::Node;
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Block, Function, Identifier, Map, Result, Type, TypeDefinition, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub struct FunctionDeclaration {
|
||||||
|
name: Option<Identifier>,
|
||||||
|
r#type: Option<Type>,
|
||||||
|
parameters: Vec<Identifier>,
|
||||||
|
body: Block,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for FunctionDeclaration {
|
||||||
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||||
|
let name_node = node.child_by_field_name("name");
|
||||||
|
let name = if let Some(child) = name_node {
|
||||||
|
Some(Identifier::from_syntax_node(source, child, context)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_definition_node = node.child_by_field_name("type");
|
||||||
|
let type_definition = if let Some(child) = type_definition_node {
|
||||||
|
Some(TypeDefinition::from_syntax_node(source, child, context)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut parameters = Vec::new();
|
||||||
|
|
||||||
|
if node.child_by_field_name("parameters").is_some() {
|
||||||
|
for index in 3..node.child_count() - 2 {
|
||||||
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.is_named() {
|
||||||
|
let parameter = Identifier::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
|
parameters.push(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_node = node.child_by_field_name("body").unwrap();
|
||||||
|
let body = Block::from_syntax_node(source, body_node, context)?;
|
||||||
|
|
||||||
|
Ok(FunctionDeclaration {
|
||||||
|
name,
|
||||||
|
r#type: type_definition.map(|defintion| defintion.take_inner()),
|
||||||
|
parameters,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, context: &Map) -> Result<Value> {
|
||||||
|
let value = Value::Function(Function::new(
|
||||||
|
self.parameters.clone(),
|
||||||
|
self.body.clone(),
|
||||||
|
self.r#type.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Some(name) = &self.name {
|
||||||
|
let key = name.inner().clone();
|
||||||
|
|
||||||
|
context.set(key, value, self.r#type.clone())?;
|
||||||
|
|
||||||
|
Ok(Value::Empty)
|
||||||
|
} else {
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
if self.name.is_some() {
|
||||||
|
Ok(Type::Empty)
|
||||||
|
} else {
|
||||||
|
Ok(self.r#type.clone().unwrap_or(Type::Function {
|
||||||
|
parameter_types: vec![Type::Any; self.parameters.len()],
|
||||||
|
return_type: Box::new(Type::Any),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -42,8 +42,8 @@ impl AbstractTree for Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||||
if let Some((value, _)) = context.variables()?.get(&self.0) {
|
if let Some((_value, r#type)) = context.variables()?.get(&self.0) {
|
||||||
Ok(value.r#type())
|
Ok(r#type.clone())
|
||||||
} else {
|
} else {
|
||||||
for built_in_function in BUILT_IN_FUNCTIONS {
|
for built_in_function in BUILT_IN_FUNCTIONS {
|
||||||
if self.0 == built_in_function.name() {
|
if self.0 == built_in_function.name() {
|
||||||
@ -51,7 +51,7 @@ impl AbstractTree for Identifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Type::Any)
|
Ok(Type::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ mod tests {
|
|||||||
let test = evaluate(
|
let test = evaluate(
|
||||||
"
|
"
|
||||||
x = [1 2 3]
|
x = [1 2 3]
|
||||||
y <() -> int> = fn || { 0 }
|
y = (fn) <int> { 0 }
|
||||||
x:(y)
|
x:(y)
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
|
217
src/abstract_tree/type_definition.rs
Normal file
217
src/abstract_tree/type_definition.rs
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tree_sitter::Node;
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Error, Map, Result, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub struct TypeDefinition {
|
||||||
|
r#type: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeDefinition {
|
||||||
|
pub fn new(r#type: Type) -> Self {
|
||||||
|
Self { r#type }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner(&self) -> &Type {
|
||||||
|
&self.r#type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_inner(self) -> Type {
|
||||||
|
self.r#type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for TypeDefinition {
|
||||||
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "type_definition", node)?;
|
||||||
|
|
||||||
|
let type_node = node.child(1).unwrap();
|
||||||
|
let r#type = Type::from_syntax_node(source, type_node, context)?;
|
||||||
|
|
||||||
|
Ok(TypeDefinition { r#type })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||||
|
self.r#type.run(source, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||||
|
self.r#type.expected_type(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TypeDefinition {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "<{}>", self.r#type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum Type {
|
||||||
|
Any,
|
||||||
|
Boolean,
|
||||||
|
Empty,
|
||||||
|
Float,
|
||||||
|
Function {
|
||||||
|
parameter_types: Vec<Type>,
|
||||||
|
return_type: Box<Type>,
|
||||||
|
},
|
||||||
|
Integer,
|
||||||
|
List(Box<Type>),
|
||||||
|
Map,
|
||||||
|
Number,
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn check(&self, other: &Type) -> Result<()> {
|
||||||
|
match (self, other) {
|
||||||
|
(Type::Any, _)
|
||||||
|
| (_, Type::Any)
|
||||||
|
| (Type::Boolean, Type::Boolean)
|
||||||
|
| (Type::Empty, Type::Empty)
|
||||||
|
| (Type::Float, Type::Float)
|
||||||
|
| (Type::Integer, Type::Integer)
|
||||||
|
| (Type::Map, Type::Map)
|
||||||
|
| (Type::Number, Type::Number)
|
||||||
|
| (Type::Number, Type::Integer)
|
||||||
|
| (Type::Number, Type::Float)
|
||||||
|
| (Type::Integer, Type::Number)
|
||||||
|
| (Type::Float, Type::Number)
|
||||||
|
| (Type::String, Type::String) => Ok(()),
|
||||||
|
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
||||||
|
self_item_type.check(&other_item_type)
|
||||||
|
}
|
||||||
|
(
|
||||||
|
Type::Function {
|
||||||
|
parameter_types: self_parameter_types,
|
||||||
|
return_type: self_return_type,
|
||||||
|
},
|
||||||
|
Type::Function {
|
||||||
|
parameter_types: other_parameter_types,
|
||||||
|
return_type: other_return_type,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let parameter_type_pairs = self_parameter_types
|
||||||
|
.iter()
|
||||||
|
.zip(other_parameter_types.iter());
|
||||||
|
|
||||||
|
for (self_parameter_type, other_parameter_type) in parameter_type_pairs {
|
||||||
|
self_parameter_type.check(&other_parameter_type)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self_return_type.check(other_return_type)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for Type {
|
||||||
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "type", node)?;
|
||||||
|
|
||||||
|
let type_node = node.child(0).unwrap();
|
||||||
|
|
||||||
|
let r#type = match type_node.kind() {
|
||||||
|
"[" => {
|
||||||
|
let item_type_node = node.child(1).unwrap();
|
||||||
|
let item_type = Type::from_syntax_node(source, item_type_node, context)?;
|
||||||
|
|
||||||
|
Type::List(Box::new(item_type))
|
||||||
|
}
|
||||||
|
"any" => Type::Any,
|
||||||
|
"bool" => Type::Boolean,
|
||||||
|
"float" => Type::Float,
|
||||||
|
"(" => {
|
||||||
|
let child_count = node.child_count();
|
||||||
|
let mut parameter_types = Vec::new();
|
||||||
|
|
||||||
|
for index in 1..child_count - 2 {
|
||||||
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.is_named() {
|
||||||
|
let parameter_type = Type::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
|
parameter_types.push(parameter_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let final_node = node.child(child_count - 1).unwrap();
|
||||||
|
let return_type = if final_node.is_named() {
|
||||||
|
Type::from_syntax_node(source, final_node, context)?
|
||||||
|
} else {
|
||||||
|
Type::Empty
|
||||||
|
};
|
||||||
|
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: Box::new(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"int" => Type::Integer,
|
||||||
|
"map" => Type::Map,
|
||||||
|
"num" => Type::Number,
|
||||||
|
"str" => Type::String,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "any, bool, float, fn, int, list, map, num or str",
|
||||||
|
actual: type_node.kind(),
|
||||||
|
location: type_node.start_position(),
|
||||||
|
relevant_source: source[type_node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(r#type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||||
|
Ok(Value::Empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
Ok(Type::Empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Type {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Type::Any => write!(f, "any"),
|
||||||
|
Type::Boolean => write!(f, "bool"),
|
||||||
|
Type::Empty => write!(f, "empty"),
|
||||||
|
Type::Float => write!(f, "float"),
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type,
|
||||||
|
} => {
|
||||||
|
write!(f, "(")?;
|
||||||
|
|
||||||
|
for parameter_type in parameter_types {
|
||||||
|
write!(f, "{parameter_type}")?;
|
||||||
|
|
||||||
|
if parameter_type != parameter_types.last().unwrap() {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, ")")?;
|
||||||
|
write!(f, " -> {return_type}")
|
||||||
|
}
|
||||||
|
Type::Integer => write!(f, "int"),
|
||||||
|
Type::List(item_type) => write!(f, "[{item_type}]"),
|
||||||
|
Type::Map => write!(f, "map"),
|
||||||
|
Type::Number => write!(f, "num"),
|
||||||
|
Type::String => write!(f, "str"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ use tree_sitter::Node;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
||||||
Type, Value,
|
Type, TypeDefinition, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -31,21 +31,38 @@ impl AbstractTree for ValueNode {
|
|||||||
"function" => {
|
"function" => {
|
||||||
let child_count = child.child_count();
|
let child_count = child.child_count();
|
||||||
let mut parameters = Vec::new();
|
let mut parameters = Vec::new();
|
||||||
|
let mut parameter_types = Vec::new();
|
||||||
|
|
||||||
for index in 2..child_count - 1 {
|
for index in 2..child_count - 1 {
|
||||||
let child = child.child(index).unwrap();
|
let child = child.child(index).unwrap();
|
||||||
|
|
||||||
if child.is_named() {
|
if child.kind() == "identifier" {
|
||||||
let identifier = Identifier::from_syntax_node(source, child, context)?;
|
let identifier = Identifier::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
parameters.push(identifier);
|
parameters.push(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if child.kind() == "type_definition" {
|
||||||
|
let type_definition =
|
||||||
|
TypeDefinition::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
|
parameter_types.push(type_definition.take_inner());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let return_type_node = child.child(child_count - 2).unwrap();
|
||||||
|
let return_type =
|
||||||
|
TypeDefinition::from_syntax_node(source, return_type_node, context)?;
|
||||||
|
|
||||||
let body_node = child.child(child_count - 1).unwrap();
|
let body_node = child.child(child_count - 1).unwrap();
|
||||||
let body = Block::from_syntax_node(source, body_node, context)?;
|
let body = Block::from_syntax_node(source, body_node, context)?;
|
||||||
|
|
||||||
ValueNode::Function(Function::new(parameters, body, None))
|
let r#type = Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: Box::new(return_type.take_inner()),
|
||||||
|
};
|
||||||
|
|
||||||
|
ValueNode::Function(Function::new(parameters, body, Some(r#type)))
|
||||||
}
|
}
|
||||||
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
||||||
"string" => {
|
"string" => {
|
||||||
|
@ -78,36 +78,7 @@ impl Function {
|
|||||||
let value = expression.run(source, context)?;
|
let value = expression.run(source, context)?;
|
||||||
let value_type = value.r#type();
|
let value_type = value.r#type();
|
||||||
|
|
||||||
match argument_type {
|
argument_type.check(&value_type)?;
|
||||||
Type::Any => {}
|
|
||||||
Type::Boolean => {
|
|
||||||
value.as_boolean()?;
|
|
||||||
}
|
|
||||||
Type::Empty => {
|
|
||||||
value.as_empty()?;
|
|
||||||
}
|
|
||||||
Type::Float => {
|
|
||||||
value.as_float()?;
|
|
||||||
}
|
|
||||||
Type::Function { .. } => {
|
|
||||||
value.as_function()?;
|
|
||||||
}
|
|
||||||
Type::Integer => {
|
|
||||||
value.as_integer()?;
|
|
||||||
}
|
|
||||||
Type::List(_) => {
|
|
||||||
value.as_list()?;
|
|
||||||
}
|
|
||||||
Type::Map => {
|
|
||||||
value.as_map()?;
|
|
||||||
}
|
|
||||||
Type::Number => {
|
|
||||||
value.as_number()?;
|
|
||||||
}
|
|
||||||
Type::String => {
|
|
||||||
value.as_string()?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let key = identifier.inner().clone();
|
let key = identifier.inner().clone();
|
||||||
|
|
||||||
@ -118,36 +89,7 @@ impl Function {
|
|||||||
|
|
||||||
let return_value = self.body.run(source, &function_context)?;
|
let return_value = self.body.run(source, &function_context)?;
|
||||||
|
|
||||||
match return_type.as_ref() {
|
return_type.check(&return_value.r#type())?;
|
||||||
Type::Any => {}
|
|
||||||
Type::Boolean => {
|
|
||||||
return_value.as_boolean()?;
|
|
||||||
}
|
|
||||||
Type::Empty => {
|
|
||||||
return_value.as_empty()?;
|
|
||||||
}
|
|
||||||
Type::Float => {
|
|
||||||
return_value.as_float()?;
|
|
||||||
}
|
|
||||||
Type::Function { .. } => {
|
|
||||||
return_value.as_function()?;
|
|
||||||
}
|
|
||||||
Type::Integer => {
|
|
||||||
return_value.as_integer()?;
|
|
||||||
}
|
|
||||||
Type::List(_) => {
|
|
||||||
return_value.as_list()?;
|
|
||||||
}
|
|
||||||
Type::Map => {
|
|
||||||
return_value.as_map()?;
|
|
||||||
}
|
|
||||||
Type::Number => {
|
|
||||||
return_value.as_number()?;
|
|
||||||
}
|
|
||||||
Type::String => {
|
|
||||||
return_value.as_string()?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(return_value)
|
Ok(return_value)
|
||||||
}
|
}
|
||||||
|
29
std/list.ds
Normal file
29
std/list.ds
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
contains <([any], any) -> bool> = fn |list, target| {
|
||||||
|
for item in list {
|
||||||
|
if item == target {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
find <([any], any) -> bool> = fn |list, target| {
|
||||||
|
for item in list {
|
||||||
|
if item == target {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse <([any]) -> [any]> = fn |list| {
|
||||||
|
new_list = []
|
||||||
|
index = (length list) - 1;
|
||||||
|
|
||||||
|
while index >= 0 {
|
||||||
|
new_list += list:index
|
||||||
|
index -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
new_list
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
================================================================================
|
================================================================================
|
||||||
Simple Function
|
Anonymous Function
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
fn || { "Hiya" }
|
(fn) <str> { "Hiya" }
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -11,6 +11,8 @@ fn || { "Hiya" }
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
|
(type_definition
|
||||||
|
(type))
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
@ -18,10 +20,12 @@ fn || { "Hiya" }
|
|||||||
(string))))))))))
|
(string))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Function Assignment
|
Function Declaration
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
foobar <(str) -> str> = fn |text| { text }
|
foobar = (fn x <int>, y <int>) <int> {
|
||||||
|
x + y
|
||||||
|
}
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -29,20 +33,28 @@ foobar <(str) -> str> = fn |text| { text }
|
|||||||
(statement
|
(statement
|
||||||
(assignment
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_definition
|
|
||||||
(type
|
|
||||||
(type)
|
|
||||||
(type)))
|
|
||||||
(assignment_operator)
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(type_definition
|
||||||
|
(type))
|
||||||
|
(identifier)
|
||||||
|
(type_definition
|
||||||
|
(type))
|
||||||
|
(type_definition
|
||||||
|
(type))
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(identifier)))))))))))
|
(math
|
||||||
|
(expression
|
||||||
|
(identifier))
|
||||||
|
(math_operator)
|
||||||
|
(expression
|
||||||
|
(identifier)))))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Function Call
|
Function Call
|
||||||
@ -62,42 +74,6 @@ Function Call
|
|||||||
(value
|
(value
|
||||||
(string)))))))
|
(string)))))))
|
||||||
|
|
||||||
================================================================================
|
|
||||||
Complex Function
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
fn |message number| {
|
|
||||||
(output message)
|
|
||||||
(output number)
|
|
||||||
}
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
(root
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(function
|
|
||||||
(identifier)
|
|
||||||
(identifier)
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(function_call
|
|
||||||
(expression
|
|
||||||
(identifier
|
|
||||||
(built_in_function)))
|
|
||||||
(expression
|
|
||||||
(identifier)))))
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(function_call
|
|
||||||
(expression
|
|
||||||
(identifier
|
|
||||||
(built_in_function)))
|
|
||||||
(expression
|
|
||||||
(identifier)))))))))))
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Complex Function Call
|
Complex Function Call
|
||||||
================================================================================
|
================================================================================
|
||||||
@ -138,50 +114,3 @@ Complex Function Call
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer)))))))))))
|
(integer)))))))))))
|
||||||
|
|
||||||
================================================================================
|
|
||||||
Callback Function
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
foobar <(() -> str) -> str> = fn |cb| {
|
|
||||||
(cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
(foobar fn || { 'Hiya' })
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
(root
|
|
||||||
(statement
|
|
||||||
(assignment
|
|
||||||
(identifier)
|
|
||||||
(type_definition
|
|
||||||
(type
|
|
||||||
(type
|
|
||||||
(type))
|
|
||||||
(type)))
|
|
||||||
(assignment_operator)
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(function
|
|
||||||
(identifier)
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(function_call
|
|
||||||
(expression
|
|
||||||
(identifier))))))))))))
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(function_call
|
|
||||||
(expression
|
|
||||||
(identifier))
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(function
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(string))))))))))))
|
|
||||||
|
@ -69,9 +69,9 @@ module.exports = grammar({
|
|||||||
|
|
||||||
value: $ =>
|
value: $ =>
|
||||||
choice(
|
choice(
|
||||||
|
$.function,
|
||||||
$.integer,
|
$.integer,
|
||||||
$.float,
|
$.float,
|
||||||
$.function,
|
|
||||||
$.string,
|
$.string,
|
||||||
$.boolean,
|
$.boolean,
|
||||||
$.list,
|
$.list,
|
||||||
@ -352,15 +352,17 @@ module.exports = grammar({
|
|||||||
|
|
||||||
function: $ =>
|
function: $ =>
|
||||||
seq(
|
seq(
|
||||||
|
'(',
|
||||||
'fn',
|
'fn',
|
||||||
'|',
|
|
||||||
repeat(
|
repeat(
|
||||||
seq(
|
seq(
|
||||||
$.identifier,
|
$.identifier,
|
||||||
|
$.type_definition,
|
||||||
optional(','),
|
optional(','),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'|',
|
')',
|
||||||
|
$.type_definition,
|
||||||
$.block,
|
$.block,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -196,6 +196,10 @@
|
|||||||
"value": {
|
"value": {
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "integer"
|
"name": "integer"
|
||||||
@ -204,10 +208,6 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "float"
|
"name": "float"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "string"
|
"name": "string"
|
||||||
@ -1149,11 +1149,11 @@
|
|||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "fn"
|
"value": "("
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "|"
|
"value": "fn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
@ -1164,6 +1164,10 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "identifier"
|
"name": "identifier"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type_definition"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
@ -1181,7 +1185,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "|"
|
"value": ")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type_definition"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
|
@ -167,6 +167,10 @@
|
|||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "type_definition",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -810,10 +814,6 @@
|
|||||||
"type": "{",
|
"type": "{",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "|",
|
|
||||||
"named": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "||",
|
"type": "||",
|
||||||
"named": false
|
"named": false
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user