1
0

Implement function declarations

This commit is contained in:
Jeff 2023-11-30 09:30:25 -05:00
parent 57b06df9c2
commit 0ee26dcf0d
18 changed files with 8782 additions and 12865 deletions

View File

@ -1,408 +0,0 @@
module.exports = grammar({
name: "dust",
word: $ => $.identifier,
extras: $ => [/\s/, $._comment],
rules: {
root: $ =>
prec(1, repeat1($.statement)),
_comment: $ => /[#][^#\n]*[#|\n]/,
block: $ =>
seq(
optional("async"),
"{",
repeat1($.statement),
"}",
),
statement: $ =>
prec.left(
seq(
choice(
$.assignment,
$.block,
$.expression,
$.for,
$.if_else,
$.index_assignment,
$.match,
$.return,
$.use,
$.while,
),
optional(";"),
),
),
expression: $ =>
prec.right(
choice(
$._expression_kind,
seq(
"(",
$._expression_kind,
")",
),
),
),
_expression_kind: $ =>
prec.right(
choice(
$.function_call,
$.identifier,
$.index,
$.logic,
$.math,
$.value,
$.yield,
),
),
_expression_list: $ =>
repeat1(
prec.right(
seq(
$.expression,
optional(","),
),
),
),
identifier: $ =>
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
value: $ =>
choice(
$.integer,
$.float,
$.string,
$.boolean,
$.list,
$.function,
$.table,
$.map,
),
integer: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
float: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
".",
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
string: $ =>
/("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
boolean: $ =>
choice("true", "false"),
list: $ =>
seq(
"[",
repeat(
prec.left(
seq(
$.expression,
optional(","),
),
),
),
"]",
),
map: $ =>
seq(
"{",
repeat(
seq(
$.identifier,
"=",
$.statement,
optional(","),
),
),
"}",
),
index: $ =>
prec.left(
1,
seq(
$.expression,
":",
$.expression,
optional(
seq("..", $.expression),
),
),
),
math: $ =>
prec.left(
seq(
$.expression,
$.math_operator,
$.expression,
),
),
math_operator: $ =>
choice("+", "-", "*", "/", "%"),
logic: $ =>
prec.right(
seq(
$.expression,
$.logic_operator,
$.expression,
),
),
logic_operator: $ =>
choice(
"==",
"!=",
"&&",
"||",
">",
"<",
">=",
"<=",
),
assignment: $ =>
seq(
field(
"identifier",
$.identifier,
),
optional(
field(
"type",
$.type_definition,
),
),
field(
"assignment_operator",
$.assignment_operator,
),
field("statement", $.statement),
),
index_assignment: $ =>
seq(
$.index,
$.assignment_operator,
$.statement,
),
assignment_operator: $ =>
prec.right(
choice("=", "+=", "-="),
),
if_else: $ =>
prec.right(
seq(
$.if,
repeat($.else_if),
optional($.else),
),
),
if: $ =>
seq("if", $.expression, $.block),
else_if: $ =>
seq(
"else if",
$.expression,
$.block,
),
else: $ => seq("else", $.block),
match: $ =>
prec.right(
seq(
"match",
$.expression,
repeat1(
seq(
$.expression,
"=>",
$.block,
),
),
),
),
while: $ =>
seq(
"while",
$.expression,
$.block,
),
for: $ =>
seq(
choice("for", "async for"),
$.identifier,
"in",
$.expression,
$.block,
),
identifier_list: $ =>
prec.right(
choice(
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
),
),
),
table: $ =>
prec.right(
seq(
"table",
$.identifier_list,
$.expression,
),
),
return: $ =>
seq("return", $.expression),
use: $ => seq("use", $.string),
type_definition: $ =>
seq("<", $.type, ">"),
type: $ =>
prec.right(
choice(
"any",
"bool",
"float",
seq(
"fn",
repeat(
seq(
$.type,
optional(","),
),
),
optional(seq("->", $.type)),
),
"int",
seq("list", $.type),
"map",
"num",
"str",
),
),
function: $ =>
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
$.block,
),
function_call: $ =>
prec.right(
1,
seq(
"(",
$.expression,
optional($._expression_list),
")",
),
),
yield: $ =>
prec.left(
seq(
$.expression,
"->",
"(",
$.expression,
optional($._expression_list),
")",
),
),
},
});

View File

@ -1,9 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, Type, TypeDefinition, Value};
AbstractTree, Error, Function, Identifier, Map, Result, Statement, Type, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment { pub struct Assignment {
@ -24,23 +22,25 @@ impl AbstractTree for Assignment {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "assignment", node)?; Error::expect_syntax_node(source, "assignment", node)?;
let identifier_node = node.child_by_field_name("identifier").unwrap(); let child_count = node.child_count();
let identifier_node = node.child(0).unwrap();
let identifier = Identifier::from_syntax_node(source, identifier_node, context)?; let identifier = Identifier::from_syntax_node(source, identifier_node, context)?;
let type_node = node.child_by_field_name("type"); let type_node = node.child(1);
let type_definition = if let Some(type_node) = type_node { let type_definition = if let Some(type_node) = type_node {
if type_node.kind() == "type_defintion" {
Some(TypeDefinition::from_syntax_node( Some(TypeDefinition::from_syntax_node(
source, type_node, context, source, type_node, context,
)?) )?)
} else { } else {
None None
}
} else {
None
}; };
let operator_node = node let operator_node = node.child(child_count - 2).unwrap().child(0).unwrap();
.child_by_field_name("assignment_operator")
.unwrap()
.child(0)
.unwrap();
let operator = match operator_node.kind() { let operator = match operator_node.kind() {
"=" => AssignmentOperator::Equal, "=" => AssignmentOperator::Equal,
"+=" => AssignmentOperator::PlusEqual, "+=" => AssignmentOperator::PlusEqual,
@ -55,7 +55,7 @@ impl AbstractTree for Assignment {
} }
}; };
let statement_node = node.child_by_field_name("statement").unwrap(); let statement_node = node.child(child_count - 1).unwrap();
let statement = Statement::from_syntax_node(source, statement_node, context)?; let statement = Statement::from_syntax_node(source, statement_node, context)?;
if let Some(type_definition) = &type_definition { if let Some(type_definition) = &type_definition {
@ -145,22 +145,11 @@ impl AbstractTree for Assignment {
AssignmentOperator::Equal => value, AssignmentOperator::Equal => value,
}; };
let new_value = if let Some(type_definition) = &self.type_definition { if let Some(type_definition) = &self.type_definition {
let new_value_type = new_value.r#type(context)?; let new_value_type = new_value.r#type(context)?;
type_definition.runtime_check(&new_value_type, context)?; type_definition.runtime_check(&new_value_type, context)?;
if let Value::Function(function) = new_value {
Value::Function(Function::new(
function.parameters().clone(),
function.body().clone(),
))
} else {
new_value
} }
} else {
new_value
};
context.variables_mut()?.insert(key.clone(), new_value); context.variables_mut()?.insert(key.clone(), new_value);

View File

@ -49,7 +49,7 @@ impl AbstractTree for Expression {
} }
_ => { _ => {
return Err(Error::UnexpectedSyntaxNode { return Err(Error::UnexpectedSyntaxNode {
expected: "value, identifier, index, math, logic, function_call or yield", expected: "value_node, identifier, index, math, logic, function_call or yield",
actual: child.kind(), actual: child.kind(),
location: child.start_position(), location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(), relevant_source: source[child.byte_range()].to_string(),

View File

@ -77,14 +77,14 @@ impl AbstractTree for FunctionCall {
let mut function_context = Map::clone_from(context)?; let mut function_context = Map::clone_from(context)?;
let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter()); let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter());
for (identifier, expression) in parameter_expression_pairs { for ((identifier, _type), expression) in parameter_expression_pairs {
let key = identifier.clone().take_inner(); let key = identifier.clone().take_inner();
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
function_context.variables_mut()?.insert(key, value); function_context.variables_mut()?.insert(key, value);
} }
function.run(source, &mut function_context) function.body().run(source, &mut function_context)
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> { fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {

View File

@ -0,0 +1,111 @@
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: 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(
"
fn foo <fn int -> int> = |x| { x }
(foo 42)
",
)
.unwrap();
assert_eq!(Value::Integer(42), test);
}
}

View File

@ -89,22 +89,29 @@ mod tests {
use crate::evaluate; use crate::evaluate;
#[test] #[test]
fn evaluate_list_index() { fn list_index() {
let test = evaluate("x = [1 [2] 3] x:1:0").unwrap(); let test = evaluate("x = [1 [2] 3] x:1:0").unwrap();
assert_eq!(Value::Integer(2), test); assert_eq!(Value::Integer(2), test);
} }
#[test] #[test]
fn evaluate_map_index() { fn map_index() {
let test = evaluate("x = {y = {z = 2}} x:y:z").unwrap(); let test = evaluate("x = {y = {z = 2}} x:y:z").unwrap();
assert_eq!(Value::Integer(2), test); assert_eq!(Value::Integer(2), test);
} }
#[test] #[test]
fn evaluate_complex_index() { fn complex_index() {
let test = evaluate("x = [1 2 3]; y = || { 0 } x:((y))").unwrap(); let test = evaluate(
"
x = [1 2 3]
y <fn -> int> || { 0 }
x:((y))
",
)
.unwrap();
assert_eq!(Value::Integer(1), test); assert_eq!(Value::Integer(1), test);
} }

View File

@ -11,6 +11,7 @@ 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;
@ -26,9 +27,10 @@ pub mod r#while;
pub mod r#yield; pub mod r#yield;
pub use { pub use {
assignment::*, block::*, expression::*, function_call::*, identifier::*, if_else::*, index::*, assignment::*, block::*, expression::*, function_call::*, function_declaration::*,
index_assignment::IndexAssignment, logic::*, math::*, r#for::*, r#match::*, r#use::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment, logic::*, math::*,
r#while::*, r#yield::*, statement::*, type_defintion::*, value_node::*, r#for::*, r#match::*, r#use::*, r#while::*, r#yield::*, statement::*, type_defintion::*,
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, IfElse, IndexAssignment, Map, Match, AbstractTree, Assignment, Block, Error, Expression, For, FunctionDeclaration, IfElse,
Result, TypeDefinition, Use, Value, While, IndexAssignment, Map, Match, Result, TypeDefinition, Use, Value, While,
}; };
/// Abstract representation of a statement. /// Abstract representation of a statement.
@ -12,6 +12,7 @@ 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>),
@ -36,7 +37,10 @@ impl AbstractTree for Statement {
Ok(Statement::Return(Expression::from_syntax_node(source, expression_node, context)?)) Ok(Statement::Return(Expression::from_syntax_node(source, expression_node, context)?))
}, },
"expression" => Ok(Self::Expression(Expression::from_syntax_node( "expression" => Ok(Statement::Expression(Expression::from_syntax_node(
source, child, context
)?)),
"function_declaration" => Ok(Statement::FunctionDeclaration(FunctionDeclaration::from_syntax_node(
source, child, context 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(
@ -72,6 +76,9 @@ 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),
@ -87,6 +94,9 @@ 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

@ -61,6 +61,34 @@ impl TypeDefinition {
self_defintion.runtime_check(other_definition, context) self_defintion.runtime_check(other_definition, context)
} }
(
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 {
TypeDefinition::new(self_parameter_type.clone()).runtime_check(
&TypeDefinition::new(other_parameter_type.clone()),
context,
)?;
}
TypeDefinition::new(self_return_type.as_ref().clone()).runtime_check(
&TypeDefinition::new(other_return_type.as_ref().clone()),
context,
)?;
Ok(())
}
_ => Err(Error::RuntimeTypeCheck { _ => Err(Error::RuntimeTypeCheck {
expected: self.clone(), expected: self.clone(),
actual: other.clone(), actual: other.clone(),

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table, AbstractTree, Error, Expression, Identifier, List, Map, Result, Statement, Table, Type,
Type, TypeDefinition, Value, TypeDefinition, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -21,12 +21,11 @@ pub enum ValueNode {
column_names: Vec<Identifier>, column_names: Vec<Identifier>,
rows: Box<Expression>, rows: Box<Expression>,
}, },
Function(Function),
} }
impl AbstractTree for ValueNode { impl AbstractTree for ValueNode {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
debug_assert_eq!("value", node.kind()); Error::expect_syntax_node(source, "value", node)?;
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
let value_node = match child.kind() { let value_node = match child.kind() {
@ -101,11 +100,9 @@ impl AbstractTree for ValueNode {
ValueNode::Map(child_nodes) ValueNode::Map(child_nodes)
} }
"function" => ValueNode::Function(Function::from_syntax_node(source, child, context)?),
_ => { _ => {
return Err(Error::UnexpectedSyntaxNode { return Err(Error::UnexpectedSyntaxNode {
expected: expected: "string, integer, float, boolean, list, table, map, or empty",
"string, integer, float, boolean, list, table, map, function or empty",
actual: child.kind(), actual: child.kind(),
location: child.start_position(), location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(), relevant_source: source[child.byte_range()].to_string(),
@ -175,7 +172,6 @@ impl AbstractTree for ValueNode {
Value::Table(table) Value::Table(table)
} }
ValueNode::Function(function) => Value::Function(function.clone()),
}; };
Ok(value) Ok(value)
@ -214,7 +210,6 @@ impl AbstractTree for ValueNode {
column_names: _, column_names: _,
rows: _, rows: _,
} => TypeDefinition::new(Type::Table), } => TypeDefinition::new(Type::Table),
ValueNode::Function(function) => return function.expected_type(context),
}; };
Ok(type_definition) Ok(type_definition)

View File

@ -150,34 +150,6 @@ mod tests {
assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
} }
#[test]
fn evaluate_table() {
let mut table = Table::new(vec!["messages".to_string(), "numbers".to_string()]);
table
.insert(vec![Value::String("hiya".to_string()), Value::Integer(42)])
.unwrap();
table
.insert(vec![Value::String("foo".to_string()), Value::Integer(57)])
.unwrap();
table
.insert(vec![Value::String("bar".to_string()), Value::Float(99.99)])
.unwrap();
assert_eq!(
evaluate(
"
table |messages numbers| [
['hiya', 42]
['foo', 57]
['bar', 99.99]
]
"
),
Ok(Value::Table(table))
);
}
#[test] #[test]
fn evaluate_if() { fn evaluate_if() {
assert_eq!( assert_eq!(

View File

@ -1,58 +1,39 @@
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, Error, Identifier, Map, Result, TypeDefinition, Value}; use crate::{Block, Identifier, TypeDefinition};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Function { pub struct Function {
parameters: Vec<Identifier>, parameters: Vec<(Identifier, TypeDefinition)>,
body: Block, body: Block,
return_type: TypeDefinition,
} }
impl Function { impl Function {
pub fn new(parameters: Vec<Identifier>, body: Block) -> Self { pub fn new(
Self { parameters, body } parameters: Vec<(Identifier, TypeDefinition)>,
body: Block,
return_type: TypeDefinition,
) -> Self {
Self {
parameters,
body,
return_type,
}
} }
pub fn parameters(&self) -> &Vec<Identifier> { pub fn parameters(&self) -> &Vec<(Identifier, TypeDefinition)> {
&self.parameters &self.parameters
} }
pub fn body(&self) -> &Block { pub fn body(&self) -> &Block {
&self.body &self.body
} }
}
impl AbstractTree for Function { pub fn return_type(&self) -> &TypeDefinition {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { &self.return_type
Error::expect_syntax_node(source, "function", node)?;
let child_count = node.child_count();
let mut parameters = Vec::new();
for index in 1..child_count - 2 {
let child = node.child(index).unwrap();
if child.is_named() {
let identifier = Identifier::from_syntax_node(source, child, context)?;
parameters.push(identifier);
}
}
let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node, context)?;
Ok(Function { parameters, body })
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
self.body.run(source, context)
}
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
Value::Function(self.clone()).r#type(context)
} }
} }

View File

@ -1,37 +0,0 @@
================================================================================
Simple Function Call
================================================================================
(output 'hi')
--------------------------------------------------------------------------------
(root
(statement
(expression
(function_call
(expression
(identifier))
(expression
(value
(string)))))))
================================================================================
Nested Function Call
================================================================================
(assert_equal (random_integer) 4)
--------------------------------------------------------------------------------
(root
(statement
(expression
(function_call
(expression
(identifier))
(expression
(identifier))
(expression
(value
(integer)))))))

View File

@ -2,48 +2,23 @@
Simple Function Simple Function
================================================================================ ================================================================================
|| { "Hiya" } foo <fn -> str> || { "Hiya" }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
(root (root
(statement (statement
(expression (function_declaration
(value
(function
(block
(statement
(expression
(value
(string))))))))))
================================================================================
Function Assignment
================================================================================
x <fn num -> str> = |number| { "Hiya" }
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier) (identifier)
(type_definition (type_definition
(type (type
(type)
(type))) (type)))
(assignment_operator)
(statement
(expression
(value
(function (function
(identifier)
(block (block
(statement (statement
(expression (expression
(value (value
(string)))))))))))) (string)))))))))
================================================================================ ================================================================================
Function Call Function Call
@ -67,7 +42,7 @@ Function Call
Complex Function Complex Function
================================================================================ ================================================================================
|message number| { foobar <fn str num> |message number| {
(output message) (output message)
(output number) (output number)
} }
@ -76,8 +51,12 @@ Complex Function
(root (root
(statement (statement
(expression (function_declaration
(value (identifier)
(type_definition
(type
(type)
(type)))
(function (function
(identifier) (identifier)
(identifier) (identifier)
@ -95,7 +74,7 @@ Complex Function
(expression (expression
(identifier)) (identifier))
(expression (expression
(identifier))))))))))) (identifier))))))))))
================================================================================ ================================================================================
Complex Function Call Complex Function Call

View File

@ -27,6 +27,7 @@ module.exports = grammar({
$.block, $.block,
$.expression, $.expression,
$.for, $.for,
$.function_declaration,
$.if_else, $.if_else,
$.index_assignment, $.index_assignment,
$.match, $.match,
@ -83,8 +84,6 @@ module.exports = grammar({
$.string, $.string,
$.boolean, $.boolean,
$.list, $.list,
$.function,
$.table,
$.map, $.map,
), ),
@ -231,21 +230,10 @@ module.exports = grammar({
assignment: $ => assignment: $ =>
seq( seq(
field(
'identifier',
$.identifier, $.identifier,
), optional($.type_definition),
optional(
field(
'type',
$.type_definition,
),
),
field(
'assignment_operator',
$.assignment_operator, $.assignment_operator,
), $.statement,
field('statement', $.statement),
), ),
index_assignment: $ => index_assignment: $ =>
@ -328,15 +316,6 @@ module.exports = grammar({
), ),
), ),
table: $ =>
prec.right(
seq(
'table',
$.identifier_list,
$.expression,
),
),
return: $ => return: $ =>
seq('return', $.expression), seq('return', $.expression),
@ -350,6 +329,7 @@ module.exports = grammar({
choice( choice(
'any', 'any',
'bool', 'bool',
'float',
seq( seq(
'fn', 'fn',
repeat( repeat(
@ -368,6 +348,13 @@ module.exports = grammar({
), ),
), ),
function_declaration: $ =>
seq(
$.identifier,
$.type_definition,
$.function,
),
function: $ => function: $ =>
seq( seq(
'|', '|',

View File

@ -74,6 +74,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "for" "name": "for"
}, },
{
"type": "SYMBOL",
"name": "function_declaration"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "if_else" "name": "if_else"
@ -237,14 +241,6 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "list" "name": "list"
}, },
{
"type": "SYMBOL",
"name": "function"
},
{
"type": "SYMBOL",
"name": "table"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "map" "name": "map"
@ -700,23 +696,15 @@
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "FIELD",
"name": "identifier",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "identifier" "name": "identifier"
}
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
"type": "FIELD",
"name": "type",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "type_definition" "name": "type_definition"
}
}, },
{ {
"type": "BLANK" "type": "BLANK"
@ -724,21 +712,13 @@
] ]
}, },
{ {
"type": "FIELD",
"name": "assignment_operator",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "assignment_operator" "name": "assignment_operator"
}
}, },
{ {
"type": "FIELD",
"name": "statement",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "statement" "name": "statement"
} }
}
] ]
}, },
"index_assignment": { "index_assignment": {
@ -992,27 +972,6 @@
] ]
} }
}, },
"table": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "table"
},
{
"type": "SYMBOL",
"name": "identifier_list"
},
{
"type": "SYMBOL",
"name": "expression"
}
]
}
},
"return": { "return": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -1070,6 +1029,10 @@
"type": "STRING", "type": "STRING",
"value": "bool" "value": "bool"
}, },
{
"type": "STRING",
"value": "float"
},
{ {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -1156,6 +1119,23 @@
] ]
} }
}, },
"function_declaration": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "type_definition"
},
{
"type": "SYMBOL",
"name": "function"
}
]
},
"function": { "function": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [

View File

@ -2,48 +2,29 @@
{ {
"type": "assignment", "type": "assignment",
"named": true, "named": true,
"fields": { "fields": {},
"assignment_operator": { "children": {
"multiple": false, "multiple": true,
"required": true, "required": true,
"types": [ "types": [
{ {
"type": "assignment_operator", "type": "assignment_operator",
"named": true "named": true
}
]
}, },
"identifier": {
"multiple": false,
"required": true,
"types": [
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
}
]
}, },
"statement": {
"multiple": false,
"required": true,
"types": [
{ {
"type": "statement", "type": "statement",
"named": true "named": true
}
]
}, },
"type": {
"multiple": false,
"required": false,
"types": [
{ {
"type": "type_definition", "type": "type_definition",
"named": true "named": true
} }
] ]
} }
}
}, },
{ {
"type": "assignment_operator", "type": "assignment_operator",
@ -201,16 +182,24 @@
} }
}, },
{ {
"type": "identifier_list", "type": "function_declaration",
"named": true, "named": true,
"fields": {}, "fields": {},
"children": { "children": {
"multiple": true, "multiple": true,
"required": false, "required": true,
"types": [ "types": [
{
"type": "function",
"named": true
},
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
},
{
"type": "type_definition",
"named": true
} }
] ]
} }
@ -450,6 +439,10 @@
"type": "for", "type": "for",
"named": true "named": true
}, },
{
"type": "function_declaration",
"named": true
},
{ {
"type": "if_else", "type": "if_else",
"named": true "named": true
@ -477,25 +470,6 @@
] ]
} }
}, },
{
"type": "table",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "expression",
"named": true
},
{
"type": "identifier_list",
"named": true
}
]
}
},
{ {
"type": "type", "type": "type",
"named": true, "named": true,
@ -557,10 +531,6 @@
"type": "float", "type": "float",
"named": true "named": true
}, },
{
"type": "function",
"named": true
},
{ {
"type": "integer", "type": "integer",
"named": true "named": true
@ -576,10 +546,6 @@
{ {
"type": "string", "type": "string",
"named": true "named": true
},
{
"type": "table",
"named": true
} }
] ]
} }
@ -750,6 +716,10 @@
"type": "float", "type": "float",
"named": true "named": true
}, },
{
"type": "float",
"named": false
},
{ {
"type": "fn", "type": "fn",
"named": false "named": false
@ -806,10 +776,6 @@
"type": "string", "type": "string",
"named": true "named": true
}, },
{
"type": "table",
"named": false
},
{ {
"type": "true", "type": "true",
"named": false "named": false

File diff suppressed because it is too large Load Diff