Implement new function syntax
This commit is contained in:
parent
7f1b53aabe
commit
d6c679c0b3
@ -1,4 +1,4 @@
|
|||||||
create_random_numbers = <fn int> |count| {
|
create_random_numbers <(int)> = fn |count| {
|
||||||
numbers = []
|
numbers = []
|
||||||
|
|
||||||
while (length numbers) < count {
|
while (length numbers) < count {
|
||||||
|
@ -4,26 +4,26 @@ all_cards = {
|
|||||||
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
||||||
}
|
}
|
||||||
|
|
||||||
is_ready_to_solve = <fn map -> bool> |cards| {
|
is_ready_to_solve <(map) -> bool> = fn |cards| {
|
||||||
((length cards:suspects) == 1)
|
((length cards:suspects) == 1)
|
||||||
&& ((length cards:rooms) == 1)
|
&& ((length cards:rooms) == 1)
|
||||||
&& ((length cards:weapons) == 1)
|
&& ((length cards:weapons) == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
take_turn = <fn str str map -> map> |opponent_card current_room cards| {
|
take_turn <(map str str) -> map> = fn |cards opponent_card current_room| {
|
||||||
(remove_card opponent_card cards)
|
cards = (remove_card opponent_card cards)
|
||||||
(make_guess current_room cards)
|
cards = (make_guess current_room cards)
|
||||||
cards
|
cards
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_card = <fn str map> |opponent_card cards| {
|
remove_card <(map str) -> map> = fn |cards opponent_card| {
|
||||||
(output opponent_card cards)
|
|
||||||
cards:rooms -= opponent_card
|
cards:rooms -= opponent_card
|
||||||
cards:suspects -= opponent_card
|
cards:suspects -= opponent_card
|
||||||
cards:weapons -= opponent_card
|
cards:weapons -= opponent_card
|
||||||
|
cards
|
||||||
}
|
}
|
||||||
|
|
||||||
make_guess = <fn str map> |current_room cards| {
|
make_guess <(map str)> = fn |cards current_room| {
|
||||||
if (is_ready_to_solve cards) {
|
if (is_ready_to_solve cards) {
|
||||||
(output 'It was '
|
(output 'It was '
|
||||||
+ cards:suspects:0
|
+ cards:suspects:0
|
||||||
@ -41,12 +41,14 @@ make_guess = <fn str map> |current_room cards| {
|
|||||||
+ (random cards:weapons)
|
+ (random cards:weapons)
|
||||||
+ '.')
|
+ '.')
|
||||||
}
|
}
|
||||||
|
cards
|
||||||
}
|
}
|
||||||
|
|
||||||
(take_turn 'Rope' 'Kitchen'
|
all_cards
|
||||||
(take_turn 'Library' 'Kitchen'
|
-> (take_turn 'Rope' 'Kitchen')
|
||||||
(take_turn 'Conservatory' 'Kitchen'
|
-> (take_turn 'Library' 'Kitchen')
|
||||||
(take_turn 'White' 'Kitchen'
|
-> (take_turn 'Conservatory' 'Kitchen')
|
||||||
(take_turn 'Green' 'Kitchen'
|
-> (take_turn 'White' 'Kitchen')
|
||||||
(take_turn 'Knife' 'Kitchen' all_cards))))))
|
-> (take_turn 'Green' 'Kitchen')
|
||||||
|
-> (take_turn 'Knife' 'Kitchen')
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
fib = <fn int -> int> |i| {
|
fib <(int) -> int> = fn |i| {
|
||||||
if i <= 1 {
|
if i <= 1 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
data = (from_json (read 'examples/assets/jq_data.json'))
|
data = (from_json (read 'examples/assets/jq_data.json'))
|
||||||
|
|
||||||
new_data = [];
|
new_data = []
|
||||||
|
|
||||||
for commit_data in data {
|
for commit_data in data {
|
||||||
new_data += {
|
new_data += {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
1 -> (output)
|
1 -> (output)
|
||||||
|
|
||||||
add_one = <fn [int] -> [int]> |numbers| {
|
add_one <([int]) -> [int]> = fn |numbers| {
|
||||||
new_numbers = []
|
new_numbers = []
|
||||||
|
|
||||||
for number in numbers {
|
for number in numbers {
|
||||||
|
9
scripts/test.fish
Executable file
9
scripts/test.fish
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/fish
|
||||||
|
# Build the project in debug mode.
|
||||||
|
|
||||||
|
cd tree-sitter-dust/
|
||||||
|
tree-sitter generate --debug-build --no-bindings
|
||||||
|
tree-sitter test
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
cargo test
|
@ -71,7 +71,12 @@ impl AbstractTree for Assignment {
|
|||||||
if let Type::List(item_type) = type_definition.inner() {
|
if let Type::List(item_type) = type_definition.inner() {
|
||||||
let item_type_definition = TypeDefinition::new(*item_type.clone());
|
let item_type_definition = TypeDefinition::new(*item_type.clone());
|
||||||
|
|
||||||
item_type_definition.check(&identifier_type, context, node, source)?;
|
item_type_definition.check(
|
||||||
|
&identifier_type,
|
||||||
|
context,
|
||||||
|
identifier_node,
|
||||||
|
source,
|
||||||
|
)?;
|
||||||
item_type_definition.check(
|
item_type_definition.check(
|
||||||
&statement_type,
|
&statement_type,
|
||||||
context,
|
context,
|
||||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, Map, Result, TypeDefinition, Value, ValueNode, BUILT_IN_FUNCTIONS,
|
AbstractTree, Error, Map, Result, Type, TypeDefinition, Value, ValueNode, BUILT_IN_FUNCTIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::expression::Expression;
|
use super::expression::Expression;
|
||||||
@ -41,19 +41,27 @@ impl AbstractTree for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let function_type = function_expression.expected_type(context)?;
|
let function_type = function_expression.expected_type(context)?.take_inner();
|
||||||
|
|
||||||
|
if let Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type,
|
||||||
|
} = function_type
|
||||||
|
{
|
||||||
|
let argument_type_pairs = arguments.iter().zip(parameter_types.iter());
|
||||||
|
|
||||||
|
for (argument, r#type) in argument_type_pairs {
|
||||||
|
let argument_type = argument.expected_type(context)?;
|
||||||
|
|
||||||
|
r#type.check(argument_type.inner(), context, node, source)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let function_call = FunctionCall {
|
let function_call = FunctionCall {
|
||||||
function_expression,
|
function_expression,
|
||||||
arguments,
|
arguments,
|
||||||
};
|
};
|
||||||
|
|
||||||
function_type.check(
|
|
||||||
&function_call.expected_type(context)?,
|
|
||||||
context,
|
|
||||||
node,
|
|
||||||
source,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(function_call)
|
Ok(function_call)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +106,9 @@ impl AbstractTree for FunctionCall {
|
|||||||
match &self.function_expression {
|
match &self.function_expression {
|
||||||
Expression::Value(value_node) => {
|
Expression::Value(value_node) => {
|
||||||
if let ValueNode::Function(function) = value_node {
|
if let ValueNode::Function(function) = value_node {
|
||||||
Ok(function.return_type().clone())
|
let return_type = function.return_type()?.clone();
|
||||||
|
|
||||||
|
Ok(TypeDefinition::new(return_type))
|
||||||
} else {
|
} else {
|
||||||
value_node.expected_type(context)
|
value_node.expected_type(context)
|
||||||
}
|
}
|
||||||
@ -107,9 +117,9 @@ impl AbstractTree for FunctionCall {
|
|||||||
let function_name = identifier.inner();
|
let function_name = identifier.inner();
|
||||||
|
|
||||||
if let Some(value) = context.variables()?.get(function_name) {
|
if let Some(value) = context.variables()?.get(function_name) {
|
||||||
let return_type = value.as_function()?.return_type();
|
let return_type = value.as_function()?.return_type()?.clone();
|
||||||
|
|
||||||
Ok(return_type.clone())
|
Ok(TypeDefinition::new(return_type))
|
||||||
} else {
|
} else {
|
||||||
self.function_expression.expected_type(context)
|
self.function_expression.expected_type(context)
|
||||||
}
|
}
|
||||||
@ -132,7 +142,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate(
|
evaluate(
|
||||||
"
|
"
|
||||||
foobar = <fn str -> str> |message| { message }
|
foobar <(str) -> str> = fn |message| { message }
|
||||||
(foobar 'Hiya')
|
(foobar 'Hiya')
|
||||||
",
|
",
|
||||||
),
|
),
|
||||||
@ -140,6 +150,22 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn evaluate_callback() {
|
||||||
|
assert_eq!(
|
||||||
|
evaluate(
|
||||||
|
"
|
||||||
|
foobar <(() -> str) -> str> = fn |cb| {
|
||||||
|
(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
(foobar fn || { 'Hiya' })
|
||||||
|
",
|
||||||
|
),
|
||||||
|
Ok(Value::String("Hiya".to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_built_in_function_call() {
|
fn evaluate_built_in_function_call() {
|
||||||
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));
|
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));
|
||||||
|
@ -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 <() -> int> = fn || { 0 }
|
||||||
x:(y)
|
x:(y)
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,6 @@ pub enum Type {
|
|||||||
Map,
|
Map,
|
||||||
Number,
|
Number,
|
||||||
String,
|
String,
|
||||||
Table,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
@ -92,8 +91,7 @@ impl Type {
|
|||||||
| (Type::Number, Type::Float)
|
| (Type::Number, Type::Float)
|
||||||
| (Type::Integer, Type::Number)
|
| (Type::Integer, Type::Number)
|
||||||
| (Type::Float, Type::Number)
|
| (Type::Float, Type::Number)
|
||||||
| (Type::String, Type::String)
|
| (Type::String, Type::String) => Ok(()),
|
||||||
| (Type::Table, Type::Table) => Ok(()),
|
|
||||||
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
||||||
self_item_type.check(&other_item_type, context, node, source)
|
self_item_type.check(&other_item_type, context, node, source)
|
||||||
}
|
}
|
||||||
@ -145,20 +143,26 @@ impl AbstractTree for Type {
|
|||||||
"any" => Type::Any,
|
"any" => Type::Any,
|
||||||
"bool" => Type::Boolean,
|
"bool" => Type::Boolean,
|
||||||
"float" => Type::Float,
|
"float" => Type::Float,
|
||||||
"fn" => {
|
"(" => {
|
||||||
let child_count = node.child_count();
|
let child_count = node.child_count();
|
||||||
let mut parameter_types = Vec::new();
|
let mut parameter_types = Vec::new();
|
||||||
|
|
||||||
for index in 1..child_count - 2 {
|
for index in 1..child_count - 2 {
|
||||||
let parameter_type_node = node.child(index).unwrap();
|
let child = node.child(index).unwrap();
|
||||||
let parameter_type =
|
|
||||||
Type::from_syntax_node(source, parameter_type_node, context)?;
|
if child.is_named() {
|
||||||
|
let parameter_type = Type::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
parameter_types.push(parameter_type);
|
parameter_types.push(parameter_type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let return_type_node = node.child(child_count - 1).unwrap();
|
let final_node = node.child(child_count - 1).unwrap();
|
||||||
let return_type = Type::from_syntax_node(source, return_type_node, context)?;
|
let return_type = if final_node.is_named() {
|
||||||
|
Type::from_syntax_node(source, final_node, context)?
|
||||||
|
} else {
|
||||||
|
Type::Empty
|
||||||
|
};
|
||||||
|
|
||||||
Type::Function {
|
Type::Function {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
@ -215,7 +219,6 @@ impl Display for Type {
|
|||||||
Type::Map => write!(f, "map"),
|
Type::Map => write!(f, "map"),
|
||||||
Type::Number => write!(f, "num"),
|
Type::Number => write!(f, "num"),
|
||||||
Type::String => write!(f, "str"),
|
Type::String => write!(f, "str"),
|
||||||
Type::Table => write!(f, "table"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ 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, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
||||||
Type, TypeDefinition, Value,
|
Type, TypeDefinition, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,10 +18,6 @@ pub enum ValueNode {
|
|||||||
List(Vec<Expression>),
|
List(Vec<Expression>),
|
||||||
Empty,
|
Empty,
|
||||||
Map(BTreeMap<String, Statement>),
|
Map(BTreeMap<String, Statement>),
|
||||||
Table {
|
|
||||||
column_names: Vec<Identifier>,
|
|
||||||
rows: Box<Expression>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for ValueNode {
|
impl AbstractTree for ValueNode {
|
||||||
@ -32,7 +28,25 @@ 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)?),
|
"function" => {
|
||||||
|
let child_count = child.child_count();
|
||||||
|
let mut parameters = Vec::new();
|
||||||
|
|
||||||
|
for index in 2..child_count - 1 {
|
||||||
|
let child = child.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.is_named() {
|
||||||
|
let identifier = Identifier::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
|
parameters.push(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_node = child.child(child_count - 1).unwrap();
|
||||||
|
let body = Block::from_syntax_node(source, body_node, context)?;
|
||||||
|
|
||||||
|
ValueNode::Function(Function::new(parameters, body, None))
|
||||||
|
}
|
||||||
"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;
|
||||||
@ -54,30 +68,6 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
ValueNode::List(expressions)
|
ValueNode::List(expressions)
|
||||||
}
|
}
|
||||||
"table" => {
|
|
||||||
let identifier_list_node = child.child(1).unwrap();
|
|
||||||
let identifier_count = identifier_list_node.child_count();
|
|
||||||
let mut column_names = Vec::with_capacity(identifier_count);
|
|
||||||
|
|
||||||
for index in 0..identifier_count {
|
|
||||||
let identifier_node = identifier_list_node.child(index).unwrap();
|
|
||||||
|
|
||||||
if identifier_node.is_named() {
|
|
||||||
let identifier =
|
|
||||||
Identifier::from_syntax_node(source, identifier_node, context)?;
|
|
||||||
|
|
||||||
column_names.push(identifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let expression_node = child.child(2).unwrap();
|
|
||||||
let expression = Expression::from_syntax_node(source, expression_node, context)?;
|
|
||||||
|
|
||||||
ValueNode::Table {
|
|
||||||
column_names,
|
|
||||||
rows: Box::new(expression),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"map" => {
|
"map" => {
|
||||||
let mut child_nodes = BTreeMap::new();
|
let mut child_nodes = BTreeMap::new();
|
||||||
let mut current_key = "".to_string();
|
let mut current_key = "".to_string();
|
||||||
@ -104,7 +94,7 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "string, integer, float, boolean, list, table, map, or empty",
|
expected: "string, integer, float, boolean, list, map, 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(),
|
||||||
@ -149,32 +139,6 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
Value::Map(map)
|
Value::Map(map)
|
||||||
}
|
}
|
||||||
ValueNode::Table {
|
|
||||||
column_names,
|
|
||||||
rows: row_expression,
|
|
||||||
} => {
|
|
||||||
let mut headers = Vec::with_capacity(column_names.len());
|
|
||||||
let mut rows = Vec::new();
|
|
||||||
|
|
||||||
for identifier in column_names {
|
|
||||||
let name = identifier.inner().clone();
|
|
||||||
|
|
||||||
headers.push(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
let _row_values = row_expression.run(source, context)?;
|
|
||||||
let row_values = _row_values.as_list()?.items();
|
|
||||||
|
|
||||||
for value in row_values.iter() {
|
|
||||||
let row = value.as_list()?.items().clone();
|
|
||||||
|
|
||||||
rows.push(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
let table = Table::from_raw_parts(headers, rows);
|
|
||||||
|
|
||||||
Value::Table(table)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
@ -184,7 +148,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::Function(function) => TypeDefinition::new(function.r#type().clone()),
|
||||||
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) => {
|
||||||
@ -210,10 +174,6 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
ValueNode::Empty => TypeDefinition::new(Type::Any),
|
ValueNode::Empty => TypeDefinition::new(Type::Any),
|
||||||
ValueNode::Map(_) => TypeDefinition::new(Type::Map),
|
ValueNode::Map(_) => TypeDefinition::new(Type::Map),
|
||||||
ValueNode::Table {
|
|
||||||
column_names: _,
|
|
||||||
rows: _,
|
|
||||||
} => TypeDefinition::new(Type::Table),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(type_definition)
|
Ok(type_definition)
|
||||||
|
11
src/error.rs
11
src/error.rs
@ -268,21 +268,10 @@ impl fmt::Display for Error {
|
|||||||
match self {
|
match self {
|
||||||
AssertEqualFailed { expected, actual } => {
|
AssertEqualFailed { expected, actual } => {
|
||||||
write!(f, "Equality assertion failed")?;
|
write!(f, "Equality assertion failed")?;
|
||||||
|
|
||||||
if expected.is_table() {
|
|
||||||
write!(f, "\n{expected}\n")?;
|
|
||||||
} else {
|
|
||||||
write!(f, " {expected} ")?;
|
write!(f, " {expected} ")?;
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "does not equal")?;
|
write!(f, "does not equal")?;
|
||||||
|
|
||||||
if actual.is_table() {
|
|
||||||
write!(f, "\n{actual}")
|
|
||||||
} else {
|
|
||||||
write!(f, " {actual}.")
|
write!(f, " {actual}.")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
AssertFailed => write!(
|
AssertFailed => write!(
|
||||||
f,
|
f,
|
||||||
"Assertion failed. A false value was passed to \"assert\"."
|
"Assertion failed. A false value was passed to \"assert\"."
|
||||||
|
@ -1,33 +1,31 @@
|
|||||||
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::{
|
use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value};
|
||||||
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 {
|
||||||
parameters: Vec<(Identifier, TypeDefinition)>,
|
parameters: Vec<Identifier>,
|
||||||
body: Block,
|
body: Block,
|
||||||
return_type: TypeDefinition,
|
r#type: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(
|
pub fn new(parameters: Vec<Identifier>, body: Block, r#type: Option<Type>) -> Self {
|
||||||
parameters: Vec<(Identifier, TypeDefinition)>,
|
let r#type = r#type.unwrap_or(Type::Function {
|
||||||
body: Block,
|
parameter_types: vec![Type::Any; parameters.len()],
|
||||||
return_type: TypeDefinition,
|
return_type: Box::new(Type::Any),
|
||||||
) -> Self {
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
parameters,
|
parameters,
|
||||||
body,
|
body,
|
||||||
return_type,
|
r#type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parameters(&self) -> &Vec<(Identifier, TypeDefinition)> {
|
pub fn parameters(&self) -> &Vec<Identifier> {
|
||||||
&self.parameters
|
&self.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,104 +33,125 @@ impl Function {
|
|||||||
&self.body
|
&self.body
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type(&self) -> &TypeDefinition {
|
pub fn r#type(&self) -> &Type {
|
||||||
&self.return_type
|
&self.r#type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> TypeDefinition {
|
pub fn return_type(&self) -> Result<&Type> {
|
||||||
let mut parameter_types = Vec::with_capacity(self.parameters.len());
|
match &self.r#type {
|
||||||
|
Type::Function {
|
||||||
for (_, type_definition) in &self.parameters {
|
parameter_types: _,
|
||||||
parameter_types.push(type_definition.inner().clone());
|
return_type,
|
||||||
|
} => Ok(return_type.as_ref()),
|
||||||
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition::new(Type::Function {
|
|
||||||
parameter_types,
|
|
||||||
return_type: Box::new(self.return_type.inner().clone()),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, arguments: &[Expression], source: &str, context: &Map) -> Result<Value> {
|
pub fn call(&self, arguments: &[Expression], source: &str, context: &Map) -> Result<Value> {
|
||||||
let function_context = Map::clone_from(context)?;
|
let function_context = Map::clone_from(context)?;
|
||||||
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
|
|
||||||
|
|
||||||
for ((identifier, type_definition), expression) in parameter_argument_pairs {
|
let (parameter_types, return_type) = if let Type::Function {
|
||||||
let key = identifier.inner();
|
parameter_types,
|
||||||
|
return_type,
|
||||||
|
} = &self.r#type
|
||||||
|
{
|
||||||
|
(parameter_types, return_type)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.parameters.len() != arguments.len() {
|
||||||
|
return Err(Error::ExpectedArgumentAmount {
|
||||||
|
function_name: "",
|
||||||
|
expected: self.parameters.len(),
|
||||||
|
actual: arguments.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let parameter_argument_pairs = self
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.zip(parameter_types.iter())
|
||||||
|
.zip(arguments.iter());
|
||||||
|
|
||||||
|
for ((identifier, argument_type), expression) in parameter_argument_pairs {
|
||||||
let value = expression.run(source, context)?;
|
let value = expression.run(source, context)?;
|
||||||
|
|
||||||
println!("{key} {value}");
|
match argument_type {
|
||||||
|
Type::Any => {}
|
||||||
|
Type::Boolean => {
|
||||||
|
value.as_boolean()?;
|
||||||
|
}
|
||||||
|
Type::Empty => {
|
||||||
|
value.as_empty()?;
|
||||||
|
}
|
||||||
|
Type::Float => {
|
||||||
|
value.as_float()?;
|
||||||
|
}
|
||||||
|
Type::Function { .. } => {
|
||||||
|
value.as_function()?;
|
||||||
|
}
|
||||||
|
Type::Integer => {
|
||||||
|
value.as_integer()?;
|
||||||
|
}
|
||||||
|
Type::List(_) => {
|
||||||
|
value.as_list()?;
|
||||||
|
}
|
||||||
|
Type::Map => {
|
||||||
|
value.as_map()?;
|
||||||
|
}
|
||||||
|
Type::Number => {
|
||||||
|
value.as_number()?;
|
||||||
|
}
|
||||||
|
Type::String => {
|
||||||
|
value.as_string()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function_context.variables_mut()?.insert(key.clone(), value);
|
let key = identifier.inner().clone();
|
||||||
|
|
||||||
|
function_context.variables_mut()?.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_value = self.body.run(source, &function_context)?;
|
let return_value = self.body.run(source, &function_context)?;
|
||||||
|
|
||||||
|
match return_type.as_ref() {
|
||||||
|
Type::Any => {}
|
||||||
|
Type::Boolean => {
|
||||||
|
return_value.as_boolean()?;
|
||||||
|
}
|
||||||
|
Type::Empty => {
|
||||||
|
return_value.as_empty()?;
|
||||||
|
}
|
||||||
|
Type::Float => {
|
||||||
|
return_value.as_float()?;
|
||||||
|
}
|
||||||
|
Type::Function { .. } => {
|
||||||
|
return_value.as_function()?;
|
||||||
|
}
|
||||||
|
Type::Integer => {
|
||||||
|
return_value.as_integer()?;
|
||||||
|
}
|
||||||
|
Type::List(_) => {
|
||||||
|
return_value.as_list()?;
|
||||||
|
}
|
||||||
|
Type::Map => {
|
||||||
|
return_value.as_map()?;
|
||||||
|
}
|
||||||
|
Type::Number => {
|
||||||
|
return_value.as_number()?;
|
||||||
|
}
|
||||||
|
Type::String => {
|
||||||
|
return_value.as_string()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(return_value)
|
Ok(return_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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: Type::Function {
|
|
||||||
parameter_types: Vec::with_capacity(0),
|
|
||||||
return_type: Box::new(Type::Empty),
|
|
||||||
},
|
|
||||||
actual: type_definition.take_inner(),
|
|
||||||
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!(f, "{}", Value::Function(self.clone()))?;
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Function {{ parameters: {:?}, body: {:?} }}",
|
"Function {{ parameters: {:?}, body: {:?} }}",
|
||||||
@ -140,21 +159,3 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Types that represent runtime values.
|
//! Types that represent runtime values.
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
Function, List, Map, Table, Type, TypeDefinition,
|
Function, List, Map, Type, TypeDefinition,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
@ -32,7 +32,6 @@ pub mod table;
|
|||||||
pub enum Value {
|
pub enum Value {
|
||||||
List(List),
|
List(List),
|
||||||
Map(Map),
|
Map(Map),
|
||||||
Table(Table),
|
|
||||||
Function(Function),
|
Function(Function),
|
||||||
String(String),
|
String(String),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
@ -67,8 +66,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Map(_) => Type::Map,
|
Value::Map(_) => Type::Map,
|
||||||
Value::Table(_) => Type::Table,
|
Value::Function(function) => return Ok(TypeDefinition::new(function.r#type().clone())),
|
||||||
Value::Function(function) => return Ok(function.r#type()),
|
|
||||||
Value::String(_) => Type::String,
|
Value::String(_) => Type::String,
|
||||||
Value::Float(_) => Type::Float,
|
Value::Float(_) => Type::Float,
|
||||||
Value::Integer(_) => Type::Integer,
|
Value::Integer(_) => Type::Integer,
|
||||||
@ -79,10 +77,6 @@ impl Value {
|
|||||||
Ok(TypeDefinition::new(r#type))
|
Ok(TypeDefinition::new(r#type))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_table(&self) -> bool {
|
|
||||||
matches!(self, Value::Table(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_string(&self) -> bool {
|
pub fn is_string(&self) -> bool {
|
||||||
matches!(self, Value::String(_))
|
matches!(self, Value::String(_))
|
||||||
}
|
}
|
||||||
@ -201,16 +195,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::Table`.
|
|
||||||
pub fn as_table(&self) -> Result<&Table> {
|
|
||||||
match self {
|
|
||||||
Value::Table(table) => Ok(table),
|
|
||||||
value => Err(Error::ExpectedTable {
|
|
||||||
actual: value.clone(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Borrows the value stored in `self` as `Function`, or returns `Err` if
|
/// Borrows the value stored in `self` as `Function`, or returns `Err` if
|
||||||
/// `self` is not a `Value::Function`.
|
/// `self` is not a `Value::Function`.
|
||||||
pub fn as_function(&self) -> Result<&Function> {
|
pub fn as_function(&self) -> Result<&Function> {
|
||||||
@ -231,18 +215,6 @@ impl Value {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an owned table, either by cloning or converting the inner value.
|
|
||||||
pub fn to_table(&self) -> Result<Table> {
|
|
||||||
match self {
|
|
||||||
Value::Table(table) => Ok(table.clone()),
|
|
||||||
Value::List(list) => Ok(Table::from(list)),
|
|
||||||
Value::Map(map) => Result::from(map),
|
|
||||||
value => Err(Error::ExpectedTable {
|
|
||||||
actual: value.clone(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for &Value {
|
impl Default for &Value {
|
||||||
@ -398,7 +370,6 @@ impl PartialEq for Value {
|
|||||||
(Value::String(left), Value::String(right)) => left == right,
|
(Value::String(left), Value::String(right)) => left == right,
|
||||||
(Value::List(left), Value::List(right)) => left == right,
|
(Value::List(left), Value::List(right)) => left == right,
|
||||||
(Value::Map(left), Value::Map(right)) => left == right,
|
(Value::Map(left), Value::Map(right)) => left == right,
|
||||||
(Value::Table(left), Value::Table(right)) => left == right,
|
|
||||||
(Value::Function(left), Value::Function(right)) => left == right,
|
(Value::Function(left), Value::Function(right)) => left == right,
|
||||||
(Value::Empty, Value::Empty) => true,
|
(Value::Empty, Value::Empty) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -435,8 +406,6 @@ impl Ord for Value {
|
|||||||
(Value::List(_), _) => Ordering::Greater,
|
(Value::List(_), _) => Ordering::Greater,
|
||||||
(Value::Map(left), Value::Map(right)) => left.cmp(right),
|
(Value::Map(left), Value::Map(right)) => left.cmp(right),
|
||||||
(Value::Map(_), _) => Ordering::Greater,
|
(Value::Map(_), _) => Ordering::Greater,
|
||||||
(Value::Table(left), Value::Table(right)) => left.cmp(right),
|
|
||||||
(Value::Table(_), _) => Ordering::Greater,
|
|
||||||
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
||||||
(Value::Function(_), _) => Ordering::Greater,
|
(Value::Function(_), _) => Ordering::Greater,
|
||||||
(Value::Empty, Value::Empty) => Ordering::Equal,
|
(Value::Empty, Value::Empty) => Ordering::Equal,
|
||||||
@ -467,7 +436,6 @@ impl Serialize for Value {
|
|||||||
}
|
}
|
||||||
Value::Empty => todo!(),
|
Value::Empty => todo!(),
|
||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Map(inner) => inner.serialize(serializer),
|
||||||
Value::Table(inner) => inner.serialize(serializer),
|
|
||||||
Value::Function(inner) => inner.serialize(serializer),
|
Value::Function(inner) => inner.serialize(serializer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +457,6 @@ impl Display for Value {
|
|||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
}
|
}
|
||||||
Value::Map(map) => write!(f, "{map}"),
|
Value::Map(map) => write!(f, "{map}"),
|
||||||
Value::Table(table) => write!(f, "{table}"),
|
|
||||||
Value::Function(function) => write!(f, "{function}"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,6 @@ impl Display for Table {
|
|||||||
string
|
string
|
||||||
}
|
}
|
||||||
Value::Map(map) => format!("Map ({} items)", map.variables().unwrap().len()),
|
Value::Map(map) => format!("Map ({} items)", map.variables().unwrap().len()),
|
||||||
Value::Table(table) => format!("Table ({} items)", table.len()),
|
|
||||||
Value::Function(_) => "Function".to_string(),
|
Value::Function(_) => "Function".to_string(),
|
||||||
Value::Empty => "Empty".to_string(),
|
Value::Empty => "Empty".to_string(),
|
||||||
value => value.to_string(),
|
value => value.to_string(),
|
||||||
@ -234,7 +233,6 @@ impl From<&Value> for Table {
|
|||||||
Value::List(list) => Self::from(list),
|
Value::List(list) => Self::from(list),
|
||||||
Value::Empty => Table::new(Vec::with_capacity(0)),
|
Value::Empty => Table::new(Vec::with_capacity(0)),
|
||||||
Value::Map(map) => Result::<Table>::from(map).unwrap(),
|
Value::Map(map) => Result::<Table>::from(map).unwrap(),
|
||||||
Value::Table(table) => table.clone(),
|
|
||||||
Value::Function(function) => {
|
Value::Function(function) => {
|
||||||
let mut table = Table::new(vec!["function".to_string()]);
|
let mut table = Table::new(vec!["function".to_string()]);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
Simple Function
|
Simple Function
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
<fn -> str> || { "Hiya" }
|
fn || { "Hiya" }
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -11,9 +11,6 @@ Simple Function
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(type_definition
|
|
||||||
(type
|
|
||||||
(type)))
|
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
@ -24,7 +21,7 @@ Simple Function
|
|||||||
Function Assignment
|
Function Assignment
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
foobar = <fn -> str> |text| { text }
|
foobar <(str) -> str> = fn |text| { text }
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -32,14 +29,15 @@ foobar = <fn -> str> |text| { text }
|
|||||||
(statement
|
(statement
|
||||||
(assignment
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(type_definition
|
||||||
|
(type
|
||||||
|
(type)
|
||||||
|
(type)))
|
||||||
(assignment_operator)
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(type_definition
|
|
||||||
(type
|
|
||||||
(type)))
|
|
||||||
(identifier)
|
(identifier)
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
@ -68,7 +66,7 @@ Function Call
|
|||||||
Complex Function
|
Complex Function
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
<fn str num> |message number| {
|
fn |message number| {
|
||||||
(output message)
|
(output message)
|
||||||
(output number)
|
(output number)
|
||||||
}
|
}
|
||||||
@ -80,10 +78,6 @@ Complex Function
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(type_definition
|
|
||||||
(type
|
|
||||||
(type)
|
|
||||||
(type)))
|
|
||||||
(identifier)
|
(identifier)
|
||||||
(identifier)
|
(identifier)
|
||||||
(block
|
(block
|
||||||
@ -142,3 +136,50 @@ Complex Function Call
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer)))))))))))
|
(integer)))))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Callback Function
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
foobar <(() -> str) -> str> = fn |cb| {
|
||||||
|
(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
(foobar fn || { 'Hiya' })
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(root
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(type_definition
|
||||||
|
(type
|
||||||
|
(type
|
||||||
|
(type))
|
||||||
|
(type)))
|
||||||
|
(assignment_operator)
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(function
|
||||||
|
(identifier)
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(function_call
|
||||||
|
(expression
|
||||||
|
(identifier))))))))))))
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(function_call
|
||||||
|
(expression
|
||||||
|
(identifier))
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(function
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(string))))))))))))
|
||||||
|
@ -308,22 +308,6 @@ module.exports = grammar({
|
|||||||
$.block,
|
$.block,
|
||||||
),
|
),
|
||||||
|
|
||||||
identifier_list: $ =>
|
|
||||||
prec.right(
|
|
||||||
choice(
|
|
||||||
seq(
|
|
||||||
'|',
|
|
||||||
repeat(
|
|
||||||
seq(
|
|
||||||
$.identifier,
|
|
||||||
optional(','),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'|',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
return: $ =>
|
return: $ =>
|
||||||
prec.right(
|
prec.right(
|
||||||
seq('return', $.expression),
|
seq('return', $.expression),
|
||||||
@ -341,13 +325,14 @@ module.exports = grammar({
|
|||||||
'bool',
|
'bool',
|
||||||
'float',
|
'float',
|
||||||
seq(
|
seq(
|
||||||
'fn',
|
'(',
|
||||||
repeat(
|
repeat(
|
||||||
seq(
|
seq(
|
||||||
$.type,
|
$.type,
|
||||||
optional(','),
|
optional(','),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
')',
|
||||||
optional(seq('->', $.type)),
|
optional(seq('->', $.type)),
|
||||||
),
|
),
|
||||||
'int',
|
'int',
|
||||||
@ -360,7 +345,7 @@ module.exports = grammar({
|
|||||||
|
|
||||||
function: $ =>
|
function: $ =>
|
||||||
seq(
|
seq(
|
||||||
$.type_definition,
|
'fn',
|
||||||
'|',
|
'|',
|
||||||
repeat(
|
repeat(
|
||||||
seq(
|
seq(
|
||||||
|
@ -960,52 +960,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"identifier_list": {
|
|
||||||
"type": "PREC_RIGHT",
|
|
||||||
"value": 0,
|
|
||||||
"content": {
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "|"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "REPEAT",
|
|
||||||
"content": {
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "identifier"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": ","
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "|"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"return": {
|
"return": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 0,
|
"value": 0,
|
||||||
@ -1076,7 +1030,7 @@
|
|||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "fn"
|
"value": "("
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
@ -1102,6 +1056,10 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ")"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
@ -1165,12 +1123,9 @@
|
|||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "STRING",
|
||||||
"name": "type_definition"
|
"value": "fn"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "|"
|
"value": "|"
|
||||||
@ -1208,8 +1163,6 @@
|
|||||||
"name": "block"
|
"name": "block"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"function_call": {
|
"function_call": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
|
@ -162,10 +162,6 @@
|
|||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "type_definition",
|
|
||||||
"named": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user