Remove function_declaration module

This commit is contained in:
Jeff 2023-12-01 22:54:25 -05:00
parent ae05e942f2
commit 31979364eb
13 changed files with 10989 additions and 9245 deletions

View File

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

View File

@ -108,7 +108,7 @@ mod tests {
assert_eq!( assert_eq!(
evaluate( evaluate(
" "
foobar <fn str -> str> |message| { message } foobar = <fn str -> str> |message| { message }
(foobar 'Hiya') (foobar 'Hiya')
", ",
), ),

View File

@ -1,111 +0,0 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Block, Error, Function, Identifier, Map, Result, Type, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionDeclaration {
name: Identifier,
type_definition: TypeDefinition,
function: Function,
}
impl AbstractTree for FunctionDeclaration {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "function_declaration", node)?;
let name_node = node.child(0).unwrap();
let name = Identifier::from_syntax_node(source, name_node, context)?;
let type_node = node.child(1).unwrap();
let type_definition = TypeDefinition::from_syntax_node(source, type_node, context)?;
let (parameter_types, return_type) = if let Type::Function {
parameter_types,
return_type,
} = type_definition.inner()
{
(parameter_types, return_type)
} else {
return Err(Error::TypeCheck {
expected: TypeDefinition::new(Type::Function {
parameter_types: Vec::with_capacity(0),
return_type: Box::new(Type::Empty),
}),
actual: type_definition,
location: type_node.start_position(),
source: source[type_node.byte_range()].to_string(),
});
};
let function = {
let function_node = node.child(2).unwrap();
Error::expect_syntax_node(source, "function", function_node)?;
let child_count = function_node.child_count();
let mut parameters = Vec::new();
for index in 1..child_count - 2 {
let child = function_node.child(index).unwrap();
let parameter_index = parameters.len();
let parameter_type = parameter_types.get(parameter_index).unwrap_or(&Type::Empty);
if child.is_named() {
let identifier = Identifier::from_syntax_node(source, child, context)?;
parameters.push((identifier, TypeDefinition::new(parameter_type.clone())));
}
}
let body_node = function_node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node, context)?;
Function::new(
parameters,
body,
TypeDefinition::new(return_type.as_ref().clone()),
)
};
Ok(FunctionDeclaration {
name,
type_definition,
function,
})
}
fn run(&self, _source: &str, context: &Map) -> Result<Value> {
let key = self.name.inner();
context
.variables_mut()?
.insert(key.clone(), Value::Function(self.function.clone()));
Ok(Value::Empty)
}
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::new(Type::Empty))
}
}
#[cfg(test)]
mod tests {
use crate::{evaluate, Value};
#[test]
fn simple_function_declaration() {
let test = evaluate(
"
foo <fn int -> int> |x| { x }
(foo 42)
",
)
.unwrap();
assert_eq!(Value::Integer(42), test);
}
}

View File

@ -107,7 +107,7 @@ mod tests {
let test = evaluate( let test = evaluate(
" "
x = [1 2 3] x = [1 2 3]
y <fn -> int> || { 0 } y = <fn -> int> || { 0 }
x:(y) x:(y)
", ",
) )

View File

@ -11,7 +11,6 @@ pub mod block;
pub mod expression; pub mod expression;
pub mod r#for; pub mod r#for;
pub mod function_call; pub mod function_call;
pub mod function_declaration;
pub mod identifier; pub mod identifier;
pub mod if_else; pub mod if_else;
pub mod index; pub mod index;
@ -27,10 +26,9 @@ pub mod r#while;
pub mod r#yield; pub mod r#yield;
pub use { pub use {
assignment::*, block::*, expression::*, function_call::*, function_declaration::*, assignment::*, block::*, expression::*, function_call::*, identifier::*, if_else::*, index::*,
identifier::*, if_else::*, index::*, index_assignment::IndexAssignment, logic::*, math::*, index_assignment::IndexAssignment, logic::*, math::*, r#for::*, r#match::*, r#use::*,
r#for::*, r#match::*, r#use::*, r#while::*, r#yield::*, statement::*, type_defintion::*, r#while::*, r#yield::*, statement::*, type_defintion::*, value_node::*,
value_node::*,
}; };
use tree_sitter::Node; use tree_sitter::Node;

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Assignment, Block, Error, Expression, For, FunctionDeclaration, IfElse, AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match,
IndexAssignment, Map, Match, Result, TypeDefinition, Use, Value, While, Result, TypeDefinition, Use, Value, While,
}; };
/// Abstract representation of a statement. /// Abstract representation of a statement.
@ -12,7 +12,6 @@ pub enum Statement {
Assignment(Box<Assignment>), Assignment(Box<Assignment>),
Return(Expression), Return(Expression),
Expression(Expression), Expression(Expression),
FunctionDeclaration(FunctionDeclaration),
IfElse(Box<IfElse>), IfElse(Box<IfElse>),
Match(Match), Match(Match),
While(Box<While>), While(Box<While>),
@ -40,9 +39,6 @@ impl AbstractTree for Statement {
"expression" => Ok(Statement::Expression(Expression::from_syntax_node( "expression" => Ok(Statement::Expression(Expression::from_syntax_node(
source, child, context source, child, context
)?)), )?)),
"function_declaration" => Ok(Statement::FunctionDeclaration(FunctionDeclaration::from_syntax_node(
source, child, context
)?)),
"if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( "if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node(
source, child, context source, child, context
)?))), )?))),
@ -76,9 +72,6 @@ impl AbstractTree for Statement {
Statement::Assignment(assignment) => assignment.run(source, context), Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Return(expression) => expression.run(source, context), Statement::Return(expression) => expression.run(source, context),
Statement::Expression(expression) => expression.run(source, context), Statement::Expression(expression) => expression.run(source, context),
Statement::FunctionDeclaration(function_declaration) => {
function_declaration.run(source, context)
}
Statement::IfElse(if_else) => if_else.run(source, context), Statement::IfElse(if_else) => if_else.run(source, context),
Statement::Match(r#match) => r#match.run(source, context), Statement::Match(r#match) => r#match.run(source, context),
Statement::While(r#while) => r#while.run(source, context), Statement::While(r#while) => r#while.run(source, context),
@ -94,9 +87,6 @@ impl AbstractTree for Statement {
Statement::Assignment(assignment) => assignment.expected_type(context), Statement::Assignment(assignment) => assignment.expected_type(context),
Statement::Return(expression) => expression.expected_type(context), Statement::Return(expression) => expression.expected_type(context),
Statement::Expression(expression) => expression.expected_type(context), Statement::Expression(expression) => expression.expected_type(context),
Statement::FunctionDeclaration(function_declaration) => {
function_declaration.expected_type(context)
}
Statement::IfElse(if_else) => if_else.expected_type(context), Statement::IfElse(if_else) => if_else.expected_type(context),
Statement::Match(r#match) => r#match.expected_type(context), Statement::Match(r#match) => r#match.expected_type(context),
Statement::While(r#while) => r#while.expected_type(context), Statement::While(r#while) => r#while.expected_type(context),

View File

@ -4,14 +4,15 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Error, Expression, Identifier, List, Map, Result, Statement, Table, Type, AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table,
TypeDefinition, Value, Type, TypeDefinition, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum ValueNode { pub enum ValueNode {
Boolean(String), Boolean(String),
Float(String), Float(String),
Function(Function),
Integer(String), Integer(String),
String(String), String(String),
List(Vec<Expression>), List(Vec<Expression>),
@ -31,6 +32,7 @@ impl AbstractTree for ValueNode {
let value_node = match child.kind() { let value_node = match child.kind() {
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()), "boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
"float" => ValueNode::Float(source[child.byte_range()].to_string()), "float" => ValueNode::Float(source[child.byte_range()].to_string()),
"function" => ValueNode::Function(Function::from_syntax_node(source, child, context)?),
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()), "integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
"string" => { "string" => {
let without_quotes = child.start_byte() + 1..child.end_byte() - 1; let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
@ -117,6 +119,7 @@ impl AbstractTree for ValueNode {
let value = match self { let value = match self {
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()), ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()), ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
ValueNode::Function(function) => Value::Function(function.clone()),
ValueNode::Integer(value_source) => Value::Integer(value_source.parse().unwrap()), ValueNode::Integer(value_source) => Value::Integer(value_source.parse().unwrap()),
ValueNode::String(value_source) => Value::String(value_source.parse().unwrap()), ValueNode::String(value_source) => Value::String(value_source.parse().unwrap()),
ValueNode::List(expressions) => { ValueNode::List(expressions) => {
@ -181,6 +184,7 @@ impl AbstractTree for ValueNode {
let type_definition = match self { let type_definition = match self {
ValueNode::Boolean(_) => TypeDefinition::new(Type::Boolean), ValueNode::Boolean(_) => TypeDefinition::new(Type::Boolean),
ValueNode::Float(_) => TypeDefinition::new(Type::Float), ValueNode::Float(_) => TypeDefinition::new(Type::Float),
ValueNode::Function(function) => Value::Function(function.clone()).r#type(context)?,
ValueNode::Integer(_) => TypeDefinition::new(Type::Integer), ValueNode::Integer(_) => TypeDefinition::new(Type::Integer),
ValueNode::String(_) => TypeDefinition::new(Type::String), ValueNode::String(_) => TypeDefinition::new(Type::String),
ValueNode::List(expressions) => { ValueNode::List(expressions) => {

View File

@ -1,8 +1,11 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Expression, Identifier, Map, Result, TypeDefinition, Value}; use crate::{
AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Function { pub struct Function {
@ -59,6 +62,65 @@ impl Function {
} }
} }
impl AbstractTree for Function {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "function", node)?;
let type_node = node.child(0).unwrap();
let type_definition = TypeDefinition::from_syntax_node(source, type_node, context)?;
let (parameter_types, return_type) = if let Type::Function {
parameter_types,
return_type,
} = type_definition.inner()
{
(parameter_types, return_type)
} else {
return Err(Error::TypeCheck {
expected: TypeDefinition::new(Type::Function {
parameter_types: Vec::with_capacity(0),
return_type: Box::new(Type::Empty),
}),
actual: type_definition,
location: type_node.start_position(),
source: source[type_node.byte_range()].to_string(),
});
};
let child_count = node.child_count();
let mut parameters = Vec::new();
for index in 2..child_count - 2 {
let child = node.child(index).unwrap();
let parameter_index = parameters.len();
let parameter_type = parameter_types.get(parameter_index).unwrap_or(&Type::Empty);
if child.is_named() {
let identifier = Identifier::from_syntax_node(source, child, context)?;
parameters.push((identifier, TypeDefinition::new(parameter_type.clone())));
}
}
let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node, context)?;
Ok(Function::new(
parameters,
body,
TypeDefinition::new(return_type.as_ref().clone()),
))
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
Ok(Value::Function(self.clone()))
}
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
Value::Function(self.clone()).r#type(context)
}
}
impl Display for Function { impl Display for Function {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!( write!(
@ -68,3 +130,21 @@ impl Display for Function {
) )
} }
} }
#[cfg(test)]
mod tests {
use crate::{evaluate, Value};
#[test]
fn simple_function_declaration() {
let test = evaluate(
"
foo = <fn int -> int> |x| { x }
(foo 42)
",
)
.unwrap();
assert_eq!(Value::Integer(42), test);
}
}

View File

@ -2,23 +2,49 @@
Simple Function Simple Function
================================================================================ ================================================================================
foo <fn -> str> || { "Hiya" } <fn -> str> || { "Hiya" }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
(root (root
(statement (statement
(function_declaration (expression
(identifier) (value
(function
(type_definition (type_definition
(type (type
(type))) (type)))
(function
(block (block
(statement (statement
(expression (expression
(value (value
(string))))))))) (string))))))))))
================================================================================
Function Assignment
================================================================================
foobar = <fn -> str> |text| { text }
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(function
(type_definition
(type
(type)))
(identifier)
(block
(statement
(expression
(identifier)))))))))))
================================================================================ ================================================================================
Function Call Function Call
@ -41,7 +67,7 @@ Function Call
Complex Function Complex Function
================================================================================ ================================================================================
foobar <fn str num> |message number| { <fn str num> |message number| {
(output message) (output message)
(output number) (output number)
} }
@ -50,13 +76,13 @@ foobar <fn str num> |message number| {
(root (root
(statement (statement
(function_declaration (expression
(identifier) (value
(function
(type_definition (type_definition
(type (type
(type) (type)
(type))) (type)))
(function
(identifier) (identifier)
(identifier) (identifier)
(block (block
@ -71,7 +97,7 @@ foobar <fn str num> |message number| {
(function_call (function_call
(identifier) (identifier)
(expression (expression
(identifier)))))))))) (identifier)))))))))))
================================================================================ ================================================================================
Complex Function Call Complex Function Call

View File

@ -27,7 +27,6 @@ module.exports = grammar({
$.block, $.block,
$.expression, $.expression,
$.for, $.for,
$.function_declaration,
$.if_else, $.if_else,
$.index_assignment, $.index_assignment,
$.match, $.match,
@ -69,6 +68,7 @@ module.exports = grammar({
choice( choice(
$.integer, $.integer,
$.float, $.float,
$.function,
$.string, $.string,
$.boolean, $.boolean,
$.list, $.list,
@ -223,6 +223,7 @@ module.exports = grammar({
), ),
logic_operator: $ => logic_operator: $ =>
prec.left(
choice( choice(
'==', '==',
'!=', '!=',
@ -233,6 +234,7 @@ module.exports = grammar({
'>=', '>=',
'<=', '<=',
), ),
),
assignment: $ => assignment: $ =>
seq( seq(
@ -323,7 +325,9 @@ module.exports = grammar({
), ),
return: $ => return: $ =>
prec.right(
seq('return', $.expression), seq('return', $.expression),
),
use: $ => seq('use', $.string), use: $ => seq('use', $.string),
@ -354,14 +358,9 @@ module.exports = grammar({
), ),
), ),
function_declaration: $ =>
seq(
$.identifier,
$.type_definition,
$.function,
),
function: $ => function: $ =>
seq(
$.type_definition,
seq( seq(
'|', '|',
repeat( repeat(
@ -373,6 +372,7 @@ module.exports = grammar({
'|', '|',
$.block, $.block,
), ),
),
function_call: $ => function_call: $ =>
prec.right( prec.right(

View File

@ -74,10 +74,6 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "for" "name": "for"
}, },
{
"type": "SYMBOL",
"name": "function_declaration"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "if_else" "name": "if_else"
@ -199,6 +195,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "float" "name": "float"
}, },
{
"type": "SYMBOL",
"name": "function"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "string" "name": "string"
@ -686,6 +686,9 @@
} }
}, },
"logic_operator": { "logic_operator": {
"type": "PREC_LEFT",
"value": 0,
"content": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
@ -721,6 +724,7 @@
"value": "<=" "value": "<="
} }
] ]
}
}, },
"assignment": { "assignment": {
"type": "SEQ", "type": "SEQ",
@ -1003,6 +1007,9 @@
} }
}, },
"return": { "return": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -1014,6 +1021,7 @@
"name": "expression" "name": "expression"
} }
] ]
}
}, },
"use": { "use": {
"type": "SEQ", "type": "SEQ",
@ -1153,24 +1161,14 @@
] ]
} }
}, },
"function_declaration": { "function": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "type_definition" "name": "type_definition"
}, },
{ {
"type": "SYMBOL",
"name": "function"
}
]
},
"function": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -1210,6 +1208,8 @@
"name": "block" "name": "block"
} }
] ]
}
]
}, },
"function_call": { "function_call": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",

View File

@ -162,6 +162,10 @@
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
},
{
"type": "type_definition",
"named": true
} }
] ]
} }
@ -185,29 +189,6 @@
] ]
} }
}, },
{
"type": "function_declaration",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "function",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
},
{ {
"type": "if", "type": "if",
"named": true, "named": true,
@ -443,10 +424,6 @@
"type": "for", "type": "for",
"named": true "named": true
}, },
{
"type": "function_declaration",
"named": true
},
{ {
"type": "if_else", "type": "if_else",
"named": true "named": true
@ -535,6 +512,10 @@
"type": "float", "type": "float",
"named": true "named": true
}, },
{
"type": "function",
"named": true
},
{ {
"type": "integer", "type": "integer",
"named": true "named": true

File diff suppressed because it is too large Load Diff