1
0

Finish function syntax

This commit is contained in:
Jeff 2023-12-12 18:21:16 -05:00
parent e1a7c3ff72
commit b91e23fef3
14 changed files with 12449 additions and 12171 deletions

View File

@ -1,4 +1,4 @@
fib <(int) -> int> = fn |i| { fib = (fn i <int>) <int> {
if i <= 1 { if i <= 1 {
1 1
} else { } else {

View File

@ -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()))

View 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),
}))
}
}
}

View File

@ -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)
} }
} }
} }

View File

@ -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)
", ",
) )

View 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"),
}
}
}

View File

@ -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" => {

View File

@ -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
View 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
}

View File

@ -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))))))))))))

View File

@ -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,
), ),

View File

@ -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",

View File

@ -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