Finish function syntax
This commit is contained in:
parent
e1a7c3ff72
commit
b91e23fef3
@ -1,4 +1,4 @@
|
||||
fib <(int) -> int> = fn |i| {
|
||||
fib = (fn i <int>) <int> {
|
||||
if i <= 1 {
|
||||
1
|
||||
} else {
|
||||
|
@ -51,20 +51,14 @@ impl AbstractTree for FunctionCall {
|
||||
for (argument, r#type) in argument_type_pairs {
|
||||
let argument_type = argument.expected_type(context)?;
|
||||
|
||||
if let Type::Function { return_type, .. } = argument_type {
|
||||
r#type.check(&return_type)?;
|
||||
} else {
|
||||
r#type.check(&argument_type)?;
|
||||
}
|
||||
r#type.check(&argument_type)?;
|
||||
}
|
||||
}
|
||||
|
||||
let function_call = FunctionCall {
|
||||
Ok(FunctionCall {
|
||||
function_expression,
|
||||
arguments,
|
||||
};
|
||||
|
||||
Ok(function_call)
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||
@ -137,7 +131,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
evaluate(
|
||||
"
|
||||
foobar <(str) -> str> = fn |message| { message }
|
||||
foobar = (fn message <str>) <str> { message }
|
||||
(foobar 'Hiya')
|
||||
",
|
||||
),
|
||||
@ -150,11 +144,11 @@ mod tests {
|
||||
assert_eq!(
|
||||
evaluate(
|
||||
"
|
||||
foobar <(() -> str) -> str> = fn |cb| {
|
||||
foobar = (fn cb <() -> str>) <str> {
|
||||
(cb)
|
||||
}
|
||||
|
||||
(foobar fn || { 'Hiya' })
|
||||
(foobar (fn) <str> { 'Hiya' })
|
||||
",
|
||||
),
|
||||
Ok(Value::String("Hiya".to_string()))
|
||||
|
83
src/abstract_tree/function_declaration.rs
Normal file
83
src/abstract_tree/function_declaration.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{AbstractTree, Block, Function, Identifier, Map, Result, Type, TypeDefinition, Value};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct FunctionDeclaration {
|
||||
name: Option<Identifier>,
|
||||
r#type: Option<Type>,
|
||||
parameters: Vec<Identifier>,
|
||||
body: Block,
|
||||
}
|
||||
|
||||
impl AbstractTree for FunctionDeclaration {
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||
let name_node = node.child_by_field_name("name");
|
||||
let name = if let Some(child) = name_node {
|
||||
Some(Identifier::from_syntax_node(source, child, context)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let type_definition_node = node.child_by_field_name("type");
|
||||
let type_definition = if let Some(child) = type_definition_node {
|
||||
Some(TypeDefinition::from_syntax_node(source, child, context)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut parameters = Vec::new();
|
||||
|
||||
if node.child_by_field_name("parameters").is_some() {
|
||||
for index in 3..node.child_count() - 2 {
|
||||
let child = node.child(index).unwrap();
|
||||
|
||||
if child.is_named() {
|
||||
let parameter = Identifier::from_syntax_node(source, child, context)?;
|
||||
|
||||
parameters.push(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let body_node = node.child_by_field_name("body").unwrap();
|
||||
let body = Block::from_syntax_node(source, body_node, context)?;
|
||||
|
||||
Ok(FunctionDeclaration {
|
||||
name,
|
||||
r#type: type_definition.map(|defintion| defintion.take_inner()),
|
||||
parameters,
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&self, _source: &str, context: &Map) -> Result<Value> {
|
||||
let value = Value::Function(Function::new(
|
||||
self.parameters.clone(),
|
||||
self.body.clone(),
|
||||
self.r#type.clone(),
|
||||
));
|
||||
|
||||
if let Some(name) = &self.name {
|
||||
let key = name.inner().clone();
|
||||
|
||||
context.set(key, value, self.r#type.clone())?;
|
||||
|
||||
Ok(Value::Empty)
|
||||
} else {
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||
if self.name.is_some() {
|
||||
Ok(Type::Empty)
|
||||
} else {
|
||||
Ok(self.r#type.clone().unwrap_or(Type::Function {
|
||||
parameter_types: vec![Type::Any; self.parameters.len()],
|
||||
return_type: Box::new(Type::Any),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
@ -42,8 +42,8 @@ impl AbstractTree for Identifier {
|
||||
}
|
||||
|
||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||
if let Some((value, _)) = context.variables()?.get(&self.0) {
|
||||
Ok(value.r#type())
|
||||
if let Some((_value, r#type)) = context.variables()?.get(&self.0) {
|
||||
Ok(r#type.clone())
|
||||
} else {
|
||||
for built_in_function in BUILT_IN_FUNCTIONS {
|
||||
if self.0 == built_in_function.name() {
|
||||
@ -51,7 +51,7 @@ impl AbstractTree for Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Type::Any)
|
||||
Ok(Type::Empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ mod tests {
|
||||
let test = evaluate(
|
||||
"
|
||||
x = [1 2 3]
|
||||
y <() -> int> = fn || { 0 }
|
||||
y = (fn) <int> { 0 }
|
||||
x:(y)
|
||||
",
|
||||
)
|
||||
|
217
src/abstract_tree/type_definition.rs
Normal file
217
src/abstract_tree/type_definition.rs
Normal file
@ -0,0 +1,217 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{AbstractTree, Error, Map, Result, Value};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct TypeDefinition {
|
||||
r#type: Type,
|
||||
}
|
||||
|
||||
impl TypeDefinition {
|
||||
pub fn new(r#type: Type) -> Self {
|
||||
Self { r#type }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Type {
|
||||
&self.r#type
|
||||
}
|
||||
|
||||
pub fn take_inner(self) -> Type {
|
||||
self.r#type
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for TypeDefinition {
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||
Error::expect_syntax_node(source, "type_definition", node)?;
|
||||
|
||||
let type_node = node.child(1).unwrap();
|
||||
let r#type = Type::from_syntax_node(source, type_node, context)?;
|
||||
|
||||
Ok(TypeDefinition { r#type })
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||
self.r#type.run(source, context)
|
||||
}
|
||||
|
||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||
self.r#type.expected_type(context)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TypeDefinition {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "<{}>", self.r#type)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Type {
|
||||
Any,
|
||||
Boolean,
|
||||
Empty,
|
||||
Float,
|
||||
Function {
|
||||
parameter_types: Vec<Type>,
|
||||
return_type: Box<Type>,
|
||||
},
|
||||
Integer,
|
||||
List(Box<Type>),
|
||||
Map,
|
||||
Number,
|
||||
String,
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn check(&self, other: &Type) -> Result<()> {
|
||||
match (self, other) {
|
||||
(Type::Any, _)
|
||||
| (_, Type::Any)
|
||||
| (Type::Boolean, Type::Boolean)
|
||||
| (Type::Empty, Type::Empty)
|
||||
| (Type::Float, Type::Float)
|
||||
| (Type::Integer, Type::Integer)
|
||||
| (Type::Map, Type::Map)
|
||||
| (Type::Number, Type::Number)
|
||||
| (Type::Number, Type::Integer)
|
||||
| (Type::Number, Type::Float)
|
||||
| (Type::Integer, Type::Number)
|
||||
| (Type::Float, Type::Number)
|
||||
| (Type::String, Type::String) => Ok(()),
|
||||
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
||||
self_item_type.check(&other_item_type)
|
||||
}
|
||||
(
|
||||
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 {
|
||||
self_parameter_type.check(&other_parameter_type)?;
|
||||
}
|
||||
|
||||
self_return_type.check(other_return_type)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::TypeCheck {
|
||||
expected: self.clone(),
|
||||
actual: other.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTree for Type {
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||
Error::expect_syntax_node(source, "type", node)?;
|
||||
|
||||
let type_node = node.child(0).unwrap();
|
||||
|
||||
let r#type = match type_node.kind() {
|
||||
"[" => {
|
||||
let item_type_node = node.child(1).unwrap();
|
||||
let item_type = Type::from_syntax_node(source, item_type_node, context)?;
|
||||
|
||||
Type::List(Box::new(item_type))
|
||||
}
|
||||
"any" => Type::Any,
|
||||
"bool" => Type::Boolean,
|
||||
"float" => Type::Float,
|
||||
"(" => {
|
||||
let child_count = node.child_count();
|
||||
let mut parameter_types = Vec::new();
|
||||
|
||||
for index in 1..child_count - 2 {
|
||||
let child = node.child(index).unwrap();
|
||||
|
||||
if child.is_named() {
|
||||
let parameter_type = Type::from_syntax_node(source, child, context)?;
|
||||
|
||||
parameter_types.push(parameter_type);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
return_type: Box::new(return_type),
|
||||
}
|
||||
}
|
||||
"int" => Type::Integer,
|
||||
"map" => Type::Map,
|
||||
"num" => Type::Number,
|
||||
"str" => Type::String,
|
||||
_ => {
|
||||
return Err(Error::UnexpectedSyntaxNode {
|
||||
expected: "any, bool, float, fn, int, list, map, num or str",
|
||||
actual: type_node.kind(),
|
||||
location: type_node.start_position(),
|
||||
relevant_source: source[type_node.byte_range()].to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
Ok(r#type)
|
||||
}
|
||||
|
||||
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||
Ok(Value::Empty)
|
||||
}
|
||||
|
||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||
Ok(Type::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Type {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Type::Any => write!(f, "any"),
|
||||
Type::Boolean => write!(f, "bool"),
|
||||
Type::Empty => write!(f, "empty"),
|
||||
Type::Float => write!(f, "float"),
|
||||
Type::Function {
|
||||
parameter_types,
|
||||
return_type,
|
||||
} => {
|
||||
write!(f, "(")?;
|
||||
|
||||
for parameter_type in parameter_types {
|
||||
write!(f, "{parameter_type}")?;
|
||||
|
||||
if parameter_type != parameter_types.last().unwrap() {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, ")")?;
|
||||
write!(f, " -> {return_type}")
|
||||
}
|
||||
Type::Integer => write!(f, "int"),
|
||||
Type::List(item_type) => write!(f, "[{item_type}]"),
|
||||
Type::Map => write!(f, "map"),
|
||||
Type::Number => write!(f, "num"),
|
||||
Type::String => write!(f, "str"),
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ use tree_sitter::Node;
|
||||
|
||||
use crate::{
|
||||
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
||||
Type, Value,
|
||||
Type, TypeDefinition, Value,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
@ -31,21 +31,38 @@ impl AbstractTree for ValueNode {
|
||||
"function" => {
|
||||
let child_count = child.child_count();
|
||||
let mut parameters = Vec::new();
|
||||
let mut parameter_types = Vec::new();
|
||||
|
||||
for index in 2..child_count - 1 {
|
||||
let child = child.child(index).unwrap();
|
||||
|
||||
if child.is_named() {
|
||||
if child.kind() == "identifier" {
|
||||
let identifier = Identifier::from_syntax_node(source, child, context)?;
|
||||
|
||||
parameters.push(identifier);
|
||||
}
|
||||
|
||||
if child.kind() == "type_definition" {
|
||||
let type_definition =
|
||||
TypeDefinition::from_syntax_node(source, child, context)?;
|
||||
|
||||
parameter_types.push(type_definition.take_inner());
|
||||
}
|
||||
}
|
||||
|
||||
let return_type_node = child.child(child_count - 2).unwrap();
|
||||
let return_type =
|
||||
TypeDefinition::from_syntax_node(source, return_type_node, context)?;
|
||||
|
||||
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))
|
||||
let r#type = Type::Function {
|
||||
parameter_types,
|
||||
return_type: Box::new(return_type.take_inner()),
|
||||
};
|
||||
|
||||
ValueNode::Function(Function::new(parameters, body, Some(r#type)))
|
||||
}
|
||||
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
||||
"string" => {
|
||||
|
@ -78,36 +78,7 @@ impl Function {
|
||||
let value = expression.run(source, context)?;
|
||||
let value_type = value.r#type();
|
||||
|
||||
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()?;
|
||||
}
|
||||
};
|
||||
argument_type.check(&value_type)?;
|
||||
|
||||
let key = identifier.inner().clone();
|
||||
|
||||
@ -118,36 +89,7 @@ impl Function {
|
||||
|
||||
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()?;
|
||||
}
|
||||
};
|
||||
return_type.check(&return_value.r#type())?;
|
||||
|
||||
Ok(return_value)
|
||||
}
|
||||
|
29
std/list.ds
Normal file
29
std/list.ds
Normal file
@ -0,0 +1,29 @@
|
||||
contains <([any], any) -> bool> = fn |list, target| {
|
||||
for item in list {
|
||||
if item == target {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
find <([any], any) -> bool> = fn |list, target| {
|
||||
for item in list {
|
||||
if item == target {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reverse <([any]) -> [any]> = fn |list| {
|
||||
new_list = []
|
||||
index = (length list) - 1;
|
||||
|
||||
while index >= 0 {
|
||||
new_list += list:index
|
||||
index -= 1
|
||||
}
|
||||
|
||||
new_list
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
================================================================================
|
||||
Simple Function
|
||||
Anonymous Function
|
||||
================================================================================
|
||||
|
||||
fn || { "Hiya" }
|
||||
(fn) <str> { "Hiya" }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -11,6 +11,8 @@ fn || { "Hiya" }
|
||||
(expression
|
||||
(value
|
||||
(function
|
||||
(type_definition
|
||||
(type))
|
||||
(block
|
||||
(statement
|
||||
(expression
|
||||
@ -18,10 +20,12 @@ fn || { "Hiya" }
|
||||
(string))))))))))
|
||||
|
||||
================================================================================
|
||||
Function Assignment
|
||||
Function Declaration
|
||||
================================================================================
|
||||
|
||||
foobar <(str) -> str> = fn |text| { text }
|
||||
foobar = (fn x <int>, y <int>) <int> {
|
||||
x + y
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -29,20 +33,28 @@ foobar <(str) -> str> = fn |text| { text }
|
||||
(statement
|
||||
(assignment
|
||||
(identifier)
|
||||
(type_definition
|
||||
(type
|
||||
(type)
|
||||
(type)))
|
||||
(assignment_operator)
|
||||
(statement
|
||||
(expression
|
||||
(value
|
||||
(function
|
||||
(identifier)
|
||||
(type_definition
|
||||
(type))
|
||||
(identifier)
|
||||
(type_definition
|
||||
(type))
|
||||
(type_definition
|
||||
(type))
|
||||
(block
|
||||
(statement
|
||||
(expression
|
||||
(identifier)))))))))))
|
||||
(math
|
||||
(expression
|
||||
(identifier))
|
||||
(math_operator)
|
||||
(expression
|
||||
(identifier)))))))))))))
|
||||
|
||||
================================================================================
|
||||
Function Call
|
||||
@ -62,42 +74,6 @@ Function Call
|
||||
(value
|
||||
(string)))))))
|
||||
|
||||
================================================================================
|
||||
Complex Function
|
||||
================================================================================
|
||||
|
||||
fn |message number| {
|
||||
(output message)
|
||||
(output number)
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(root
|
||||
(statement
|
||||
(expression
|
||||
(value
|
||||
(function
|
||||
(identifier)
|
||||
(identifier)
|
||||
(block
|
||||
(statement
|
||||
(expression
|
||||
(function_call
|
||||
(expression
|
||||
(identifier
|
||||
(built_in_function)))
|
||||
(expression
|
||||
(identifier)))))
|
||||
(statement
|
||||
(expression
|
||||
(function_call
|
||||
(expression
|
||||
(identifier
|
||||
(built_in_function)))
|
||||
(expression
|
||||
(identifier)))))))))))
|
||||
|
||||
================================================================================
|
||||
Complex Function Call
|
||||
================================================================================
|
||||
@ -138,50 +114,3 @@ 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))))))))))))
|
||||
|
@ -69,9 +69,9 @@ module.exports = grammar({
|
||||
|
||||
value: $ =>
|
||||
choice(
|
||||
$.function,
|
||||
$.integer,
|
||||
$.float,
|
||||
$.function,
|
||||
$.string,
|
||||
$.boolean,
|
||||
$.list,
|
||||
@ -352,15 +352,17 @@ module.exports = grammar({
|
||||
|
||||
function: $ =>
|
||||
seq(
|
||||
'(',
|
||||
'fn',
|
||||
'|',
|
||||
repeat(
|
||||
seq(
|
||||
$.identifier,
|
||||
$.type_definition,
|
||||
optional(','),
|
||||
),
|
||||
),
|
||||
'|',
|
||||
')',
|
||||
$.type_definition,
|
||||
$.block,
|
||||
),
|
||||
|
||||
|
@ -196,6 +196,10 @@
|
||||
"value": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "function"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "integer"
|
||||
@ -204,10 +208,6 @@
|
||||
"type": "SYMBOL",
|
||||
"name": "float"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "function"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "string"
|
||||
@ -1149,11 +1149,11 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "fn"
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "|"
|
||||
"value": "fn"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
@ -1164,6 +1164,10 @@
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "type_definition"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
@ -1181,7 +1185,11 @@
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "|"
|
||||
"value": ")"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "type_definition"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
|
@ -167,6 +167,10 @@
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "type_definition",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -810,10 +814,6 @@
|
||||
"type": "{",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "|",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "||",
|
||||
"named": false
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user