Implement function declarations
This commit is contained in:
parent
57b06df9c2
commit
0ee26dcf0d
408
grammar.js
408
grammar.js
@ -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),
|
|
||||||
")",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
});
|
|
@ -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 {
|
||||||
Some(TypeDefinition::from_syntax_node(
|
if type_node.kind() == "type_defintion" {
|
||||||
source, type_node, context,
|
Some(TypeDefinition::from_syntax_node(
|
||||||
)?)
|
source, type_node, context,
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
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);
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
@ -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> {
|
||||||
|
111
src/abstract_tree/function_declaration.rs
Normal file
111
src/abstract_tree/function_declaration.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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),
|
||||||
|
@ -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(),
|
||||||
|
@ -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)
|
||||||
|
@ -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!(
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)))))))
|
|
@ -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)
|
(function
|
||||||
(statement
|
(block
|
||||||
(expression
|
(statement
|
||||||
(value
|
(expression
|
||||||
(function
|
(value
|
||||||
(identifier)
|
(string)))))))))
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(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,26 +51,30 @@ Complex Function
|
|||||||
|
|
||||||
(root
|
(root
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(function_declaration
|
||||||
(value
|
(identifier)
|
||||||
(function
|
(type_definition
|
||||||
(identifier)
|
(type
|
||||||
(identifier)
|
(type)
|
||||||
(block
|
(type)))
|
||||||
(statement
|
(function
|
||||||
(expression
|
(identifier)
|
||||||
(function_call
|
(identifier)
|
||||||
(expression
|
(block
|
||||||
(identifier))
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(identifier)))))
|
(function_call
|
||||||
(statement
|
(expression
|
||||||
(expression
|
(identifier))
|
||||||
(function_call
|
(expression
|
||||||
(expression
|
(identifier)))))
|
||||||
(identifier))
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(identifier)))))))))))
|
(function_call
|
||||||
|
(expression
|
||||||
|
(identifier))
|
||||||
|
(expression
|
||||||
|
(identifier))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Complex Function Call
|
Complex Function Call
|
||||||
|
@ -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',
|
optional($.type_definition),
|
||||||
$.identifier,
|
$.assignment_operator,
|
||||||
),
|
$.statement,
|
||||||
optional(
|
|
||||||
field(
|
|
||||||
'type',
|
|
||||||
$.type_definition,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
field(
|
|
||||||
'assignment_operator',
|
|
||||||
$.assignment_operator,
|
|
||||||
),
|
|
||||||
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(
|
||||||
'|',
|
'|',
|
||||||
|
@ -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",
|
"type": "SYMBOL",
|
||||||
"name": "identifier",
|
"name": "identifier"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "identifier"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
"type": "SYMBOL",
|
||||||
"name": "type",
|
"name": "type_definition"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "type_definition"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "BLANK"
|
||||||
@ -724,20 +712,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
"type": "SYMBOL",
|
||||||
"name": "assignment_operator",
|
"name": "assignment_operator"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "assignment_operator"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
"type": "SYMBOL",
|
||||||
"name": "statement",
|
"name": "statement"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "statement"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -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": [
|
||||||
|
@ -2,47 +2,28 @@
|
|||||||
{
|
{
|
||||||
"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
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
},
|
"type": "identifier",
|
||||||
"identifier": {
|
"named": true
|
||||||
"multiple": false,
|
},
|
||||||
"required": true,
|
{
|
||||||
"types": [
|
"type": "statement",
|
||||||
{
|
"named": true
|
||||||
"type": "identifier",
|
},
|
||||||
"named": true
|
{
|
||||||
}
|
"type": "type_definition",
|
||||||
]
|
"named": true
|
||||||
},
|
}
|
||||||
"statement": {
|
]
|
||||||
"multiple": false,
|
|
||||||
"required": true,
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"type": "statement",
|
|
||||||
"named": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"multiple": false,
|
|
||||||
"required": false,
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"type": "type_definition",
|
|
||||||
"named": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -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
Loading…
Reference in New Issue
Block a user