1
0

Implement new function syntax

This commit is contained in:
Jeff 2023-12-05 16:42:11 -05:00
parent 7f1b53aabe
commit d6c679c0b3
20 changed files with 9678 additions and 10024 deletions

View File

@ -1,4 +1,4 @@
create_random_numbers = <fn int> |count| {
create_random_numbers <(int)> = fn |count| {
numbers = []
while (length numbers) < count {

View File

@ -4,26 +4,26 @@ all_cards = {
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:rooms) == 1)
&& ((length cards:weapons) == 1)
}
take_turn = <fn str str map -> map> |opponent_card current_room cards| {
(remove_card opponent_card cards)
(make_guess current_room cards)
take_turn <(map str str) -> map> = fn |cards opponent_card current_room| {
cards = (remove_card opponent_card cards)
cards = (make_guess current_room cards)
cards
}
remove_card = <fn str map> |opponent_card cards| {
(output opponent_card cards)
remove_card <(map str) -> map> = fn |cards opponent_card| {
cards:rooms -= opponent_card
cards:suspects -= 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) {
(output 'It was '
+ cards:suspects:0
@ -41,12 +41,14 @@ make_guess = <fn str map> |current_room cards| {
+ (random cards:weapons)
+ '.')
}
cards
}
(take_turn 'Rope' 'Kitchen'
(take_turn 'Library' 'Kitchen'
(take_turn 'Conservatory' 'Kitchen'
(take_turn 'White' 'Kitchen'
(take_turn 'Green' 'Kitchen'
(take_turn 'Knife' 'Kitchen' all_cards))))))
all_cards
-> (take_turn 'Rope' 'Kitchen')
-> (take_turn 'Library' 'Kitchen')
-> (take_turn 'Conservatory' 'Kitchen')
-> (take_turn 'White' 'Kitchen')
-> (take_turn 'Green' 'Kitchen')
-> (take_turn 'Knife' 'Kitchen')

View File

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

View File

@ -1,6 +1,6 @@
data = (from_json (read 'examples/assets/jq_data.json'))
new_data = [];
new_data = []
for commit_data in data {
new_data += {

View File

@ -1,6 +1,6 @@
1 -> (output)
add_one = <fn [int] -> [int]> |numbers| {
add_one <([int]) -> [int]> = fn |numbers| {
new_numbers = []
for number in numbers {

9
scripts/test.fish Executable file
View 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

View File

@ -71,7 +71,12 @@ impl AbstractTree for Assignment {
if let Type::List(item_type) = type_definition.inner() {
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(
&statement_type,
context,

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
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;
@ -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 {
function_expression,
arguments,
};
function_type.check(
&function_call.expected_type(context)?,
context,
node,
source,
)?;
Ok(function_call)
}
@ -98,7 +106,9 @@ impl AbstractTree for FunctionCall {
match &self.function_expression {
Expression::Value(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 {
value_node.expected_type(context)
}
@ -107,9 +117,9 @@ impl AbstractTree for FunctionCall {
let function_name = identifier.inner();
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 {
self.function_expression.expected_type(context)
}
@ -132,7 +142,7 @@ mod tests {
assert_eq!(
evaluate(
"
foobar = <fn str -> str> |message| { message }
foobar <(str) -> str> = fn |message| { message }
(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]
fn evaluate_built_in_function_call() {
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));

View File

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

View File

@ -74,7 +74,6 @@ pub enum Type {
Map,
Number,
String,
Table,
}
impl Type {
@ -92,8 +91,7 @@ impl Type {
| (Type::Number, Type::Float)
| (Type::Integer, Type::Number)
| (Type::Float, Type::Number)
| (Type::String, Type::String)
| (Type::Table, Type::Table) => Ok(()),
| (Type::String, Type::String) => Ok(()),
(Type::List(self_item_type), Type::List(other_item_type)) => {
self_item_type.check(&other_item_type, context, node, source)
}
@ -145,20 +143,26 @@ impl AbstractTree for Type {
"any" => Type::Any,
"bool" => Type::Boolean,
"float" => Type::Float,
"fn" => {
"(" => {
let child_count = node.child_count();
let mut parameter_types = Vec::new();
for index in 1..child_count - 2 {
let parameter_type_node = node.child(index).unwrap();
let parameter_type =
Type::from_syntax_node(source, parameter_type_node, context)?;
let child = node.child(index).unwrap();
parameter_types.push(parameter_type);
if child.is_named() {
let parameter_type = Type::from_syntax_node(source, child, context)?;
parameter_types.push(parameter_type);
}
}
let return_type_node = node.child(child_count - 1).unwrap();
let return_type = Type::from_syntax_node(source, return_type_node, context)?;
let final_node = node.child(child_count - 1).unwrap();
let return_type = if final_node.is_named() {
Type::from_syntax_node(source, final_node, context)?
} else {
Type::Empty
};
Type::Function {
parameter_types,
@ -215,7 +219,6 @@ impl Display for Type {
Type::Map => write!(f, "map"),
Type::Number => write!(f, "num"),
Type::String => write!(f, "str"),
Type::Table => write!(f, "table"),
}
}
}

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
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,
};
@ -18,10 +18,6 @@ pub enum ValueNode {
List(Vec<Expression>),
Empty,
Map(BTreeMap<String, Statement>),
Table {
column_names: Vec<Identifier>,
rows: Box<Expression>,
},
}
impl AbstractTree for ValueNode {
@ -32,7 +28,25 @@ impl AbstractTree for ValueNode {
let value_node = match child.kind() {
"boolean" => ValueNode::Boolean(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()),
"string" => {
let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
@ -54,30 +68,6 @@ impl AbstractTree for ValueNode {
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" => {
let mut child_nodes = BTreeMap::new();
let mut current_key = "".to_string();
@ -104,7 +94,7 @@ impl AbstractTree for ValueNode {
}
_ => {
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(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
@ -149,32 +139,6 @@ impl AbstractTree for ValueNode {
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)
@ -184,7 +148,7 @@ impl AbstractTree for ValueNode {
let type_definition = match self {
ValueNode::Boolean(_) => TypeDefinition::new(Type::Boolean),
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::String(_) => TypeDefinition::new(Type::String),
ValueNode::List(expressions) => {
@ -210,10 +174,6 @@ impl AbstractTree for ValueNode {
}
ValueNode::Empty => TypeDefinition::new(Type::Any),
ValueNode::Map(_) => TypeDefinition::new(Type::Map),
ValueNode::Table {
column_names: _,
rows: _,
} => TypeDefinition::new(Type::Table),
};
Ok(type_definition)

View File

@ -268,20 +268,9 @@ impl fmt::Display for Error {
match self {
AssertEqualFailed { expected, actual } => {
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")?;
if actual.is_table() {
write!(f, "\n{actual}")
} else {
write!(f, " {actual}.")
}
write!(f, " {actual}.")
}
AssertFailed => write!(
f,

View File

@ -1,33 +1,31 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, TypeDefinition, Value,
};
use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Function {
parameters: Vec<(Identifier, TypeDefinition)>,
parameters: Vec<Identifier>,
body: Block,
return_type: TypeDefinition,
r#type: Type,
}
impl Function {
pub fn new(
parameters: Vec<(Identifier, TypeDefinition)>,
body: Block,
return_type: TypeDefinition,
) -> Self {
pub fn new(parameters: Vec<Identifier>, body: Block, r#type: Option<Type>) -> Self {
let r#type = r#type.unwrap_or(Type::Function {
parameter_types: vec![Type::Any; parameters.len()],
return_type: Box::new(Type::Any),
});
Self {
parameters,
body,
return_type,
r#type,
}
}
pub fn parameters(&self) -> &Vec<(Identifier, TypeDefinition)> {
pub fn parameters(&self) -> &Vec<Identifier> {
&self.parameters
}
@ -35,104 +33,125 @@ impl Function {
&self.body
}
pub fn return_type(&self) -> &TypeDefinition {
&self.return_type
pub fn r#type(&self) -> &Type {
&self.r#type
}
pub fn r#type(&self) -> TypeDefinition {
let mut parameter_types = Vec::with_capacity(self.parameters.len());
for (_, type_definition) in &self.parameters {
parameter_types.push(type_definition.inner().clone());
pub fn return_type(&self) -> Result<&Type> {
match &self.r#type {
Type::Function {
parameter_types: _,
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> {
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 key = identifier.inner();
let (parameter_types, return_type) = if let Type::Function {
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)?;
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)?;
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)
}
}
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 {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", Value::Function(self.clone()))?;
write!(
f,
"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);
}
}

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values.
use crate::{
error::{Error, Result},
Function, List, Map, Table, Type, TypeDefinition,
Function, List, Map, Type, TypeDefinition,
};
use serde::{
@ -32,7 +32,6 @@ pub mod table;
pub enum Value {
List(List),
Map(Map),
Table(Table),
Function(Function),
String(String),
Float(f64),
@ -67,8 +66,7 @@ impl Value {
}
}
Value::Map(_) => Type::Map,
Value::Table(_) => Type::Table,
Value::Function(function) => return Ok(function.r#type()),
Value::Function(function) => return Ok(TypeDefinition::new(function.r#type().clone())),
Value::String(_) => Type::String,
Value::Float(_) => Type::Float,
Value::Integer(_) => Type::Integer,
@ -79,10 +77,6 @@ impl Value {
Ok(TypeDefinition::new(r#type))
}
pub fn is_table(&self) -> bool {
matches!(self, Value::Table(_))
}
pub fn is_string(&self) -> bool {
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
/// `self` is not a `Value::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 {
@ -398,7 +370,6 @@ impl PartialEq for Value {
(Value::String(left), Value::String(right)) => left == right,
(Value::List(left), Value::List(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::Empty, Value::Empty) => true,
_ => false,
@ -435,8 +406,6 @@ impl Ord for Value {
(Value::List(_), _) => Ordering::Greater,
(Value::Map(left), Value::Map(right)) => left.cmp(right),
(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(_), _) => Ordering::Greater,
(Value::Empty, Value::Empty) => Ordering::Equal,
@ -467,7 +436,6 @@ impl Serialize for Value {
}
Value::Empty => todo!(),
Value::Map(inner) => inner.serialize(serializer),
Value::Table(inner) => inner.serialize(serializer),
Value::Function(inner) => inner.serialize(serializer),
}
}
@ -489,7 +457,6 @@ impl Display for Value {
write!(f, "]")
}
Value::Map(map) => write!(f, "{map}"),
Value::Table(table) => write!(f, "{table}"),
Value::Function(function) => write!(f, "{function}"),
}
}

View File

@ -159,7 +159,6 @@ impl Display for Table {
string
}
Value::Map(map) => format!("Map ({} items)", map.variables().unwrap().len()),
Value::Table(table) => format!("Table ({} items)", table.len()),
Value::Function(_) => "Function".to_string(),
Value::Empty => "Empty".to_string(),
value => value.to_string(),
@ -234,7 +233,6 @@ impl From<&Value> for Table {
Value::List(list) => Self::from(list),
Value::Empty => Table::new(Vec::with_capacity(0)),
Value::Map(map) => Result::<Table>::from(map).unwrap(),
Value::Table(table) => table.clone(),
Value::Function(function) => {
let mut table = Table::new(vec!["function".to_string()]);

View File

@ -2,7 +2,7 @@
Simple Function
================================================================================
<fn -> str> || { "Hiya" }
fn || { "Hiya" }
--------------------------------------------------------------------------------
@ -11,9 +11,6 @@ Simple Function
(expression
(value
(function
(type_definition
(type
(type)))
(block
(statement
(expression
@ -24,7 +21,7 @@ Simple Function
Function Assignment
================================================================================
foobar = <fn -> str> |text| { text }
foobar <(str) -> str> = fn |text| { text }
--------------------------------------------------------------------------------
@ -32,14 +29,15 @@ foobar = <fn -> str> |text| { text }
(statement
(assignment
(identifier)
(type_definition
(type
(type)
(type)))
(assignment_operator)
(statement
(expression
(value
(function
(type_definition
(type
(type)))
(identifier)
(block
(statement
@ -68,7 +66,7 @@ Function Call
Complex Function
================================================================================
<fn str num> |message number| {
fn |message number| {
(output message)
(output number)
}
@ -80,10 +78,6 @@ Complex Function
(expression
(value
(function
(type_definition
(type
(type)
(type)))
(identifier)
(identifier)
(block
@ -142,3 +136,50 @@ Complex Function Call
(expression
(value
(integer)))))))))))
================================================================================
Callback Function
================================================================================
foobar <(() -> str) -> str> = fn |cb| {
(cb)
}
(foobar fn || { 'Hiya' })
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier)
(type_definition
(type
(type
(type))
(type)))
(assignment_operator)
(statement
(expression
(value
(function
(identifier)
(block
(statement
(expression
(function_call
(expression
(identifier))))))))))))
(statement
(expression
(function_call
(expression
(identifier))
(expression
(value
(function
(block
(statement
(expression
(value
(string))))))))))))

View File

@ -308,22 +308,6 @@ module.exports = grammar({
$.block,
),
identifier_list: $ =>
prec.right(
choice(
seq(
'|',
repeat(
seq(
$.identifier,
optional(','),
),
),
'|',
),
),
),
return: $ =>
prec.right(
seq('return', $.expression),
@ -341,13 +325,14 @@ module.exports = grammar({
'bool',
'float',
seq(
'fn',
'(',
repeat(
seq(
$.type,
optional(','),
),
),
')',
optional(seq('->', $.type)),
),
'int',
@ -360,7 +345,7 @@ module.exports = grammar({
function: $ =>
seq(
$.type_definition,
'fn',
'|',
repeat(
seq(

View File

@ -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": {
"type": "PREC_RIGHT",
"value": 0,
@ -1076,7 +1030,7 @@
"members": [
{
"type": "STRING",
"value": "fn"
"value": "("
},
{
"type": "REPEAT",
@ -1102,6 +1056,10 @@
]
}
},
{
"type": "STRING",
"value": ")"
},
{
"type": "CHOICE",
"members": [
@ -1165,49 +1123,44 @@
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "type_definition"
"type": "STRING",
"value": "fn"
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "|"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"type": "STRING",
"value": "|"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
"type": "STRING",
"value": ","
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
"type": "BLANK"
}
]
}
},
{
"type": "STRING",
"value": "|"
},
{
"type": "SYMBOL",
"name": "block"
}
]
]
}
},
{
"type": "STRING",
"value": "|"
},
{
"type": "SYMBOL",
"name": "block"
}
]
},

View File

@ -162,10 +162,6 @@
{
"type": "identifier",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}

File diff suppressed because it is too large Load Diff