Begin new type checking system
This commit is contained in:
parent
60ba9853ed
commit
8db95b237c
@ -68,7 +68,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
let parameter_expression_pairs = parameters.iter().zip(arguments.iter());
|
let parameter_expression_pairs = parameters.iter().zip(arguments.iter());
|
||||||
let mut variables = function_context.variables_mut()?;
|
let mut variables = function_context.variables_mut()?;
|
||||||
|
|
||||||
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)?;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ pub mod remove;
|
|||||||
pub mod select;
|
pub mod select;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
|
pub mod r#type;
|
||||||
pub mod r#use;
|
pub mod r#use;
|
||||||
pub mod value_node;
|
pub mod value_node;
|
||||||
pub mod r#while;
|
pub mod r#while;
|
||||||
@ -34,8 +35,8 @@ pub mod r#yield;
|
|||||||
pub use {
|
pub use {
|
||||||
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
||||||
function_call::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment,
|
function_call::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment,
|
||||||
insert::*, logic::*, math::*, r#for::*, r#match::*, r#use::*, r#while::*, r#yield::*,
|
insert::*, logic::*, math::*, r#for::*, r#match::*, r#type::*, r#use::*, r#while::*,
|
||||||
remove::*, select::*, statement::*, transform::*, value_node::*,
|
r#yield::*, remove::*, select::*, statement::*, transform::*, value_node::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
56
src/abstract_tree/type.rs
Normal file
56
src/abstract_tree/type.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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 enum Type {
|
||||||
|
Boolean,
|
||||||
|
Float,
|
||||||
|
Function,
|
||||||
|
Integer,
|
||||||
|
List,
|
||||||
|
Map,
|
||||||
|
String,
|
||||||
|
Table,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for Type {
|
||||||
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "type", node)?;
|
||||||
|
|
||||||
|
let r#type = match &source[node.byte_range()] {
|
||||||
|
"bool" => Type::Boolean,
|
||||||
|
"float" => Type::Float,
|
||||||
|
"fn" => Type::Function,
|
||||||
|
"int" => Type::Integer,
|
||||||
|
"list" => Type::List,
|
||||||
|
"map" => Type::Map,
|
||||||
|
"string" => Type::String,
|
||||||
|
"table" => Type::Table,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "bool, fn, int, list, map, string or table",
|
||||||
|
actual: node.kind(),
|
||||||
|
location: node.start_position(),
|
||||||
|
relevant_source: source[node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(r#type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
|
||||||
|
match self {
|
||||||
|
Type::Boolean => Ok(Value::String("bool".to_string())),
|
||||||
|
Type::Float => Ok(Value::String("float".to_string())),
|
||||||
|
Type::Function => Ok(Value::String("fn".to_string())),
|
||||||
|
Type::Integer => Ok(Value::String("int".to_string())),
|
||||||
|
Type::List => Ok(Value::String("list".to_string())),
|
||||||
|
Type::Map => Ok(Value::String("map".to_string())),
|
||||||
|
Type::String => Ok(Value::String("string".to_string())),
|
||||||
|
Type::Table => Ok(Value::String("table".to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ use tree_sitter::Node;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
||||||
Table, Value, ValueType,
|
Table, Type, Value, ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -91,26 +91,35 @@ impl AbstractTree for ValueNode {
|
|||||||
ValueType::Map(child_nodes)
|
ValueType::Map(child_nodes)
|
||||||
}
|
}
|
||||||
"function" => {
|
"function" => {
|
||||||
let parameters_node = child.child_by_field_name("parameters");
|
|
||||||
let parameters = if let Some(node) = parameters_node {
|
|
||||||
let mut parameter_list = Vec::new();
|
let mut parameter_list = Vec::new();
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
for index in 0..node.child_count() {
|
while index < node.child_count() {
|
||||||
let child_node = node.child(index).unwrap();
|
let current_node = node.child(index).unwrap();
|
||||||
|
let next_node = node.child(index + 1);
|
||||||
|
|
||||||
if child_node.is_named() {
|
if current_node.kind() == "identifier" {
|
||||||
let parameter = Identifier::from_syntax_node(source, child_node)?;
|
let parameter = Identifier::from_syntax_node(source, current_node)?;
|
||||||
|
|
||||||
parameter_list.push(parameter);
|
if let Some(next_node) = next_node {
|
||||||
|
if next_node.kind() == "type_definition" {
|
||||||
|
let r#type = Type::from_syntax_node(source, next_node)?;
|
||||||
|
|
||||||
|
parameter_list.push((parameter, r#type));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(parameter_list)
|
index += 2
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
};
|
|
||||||
let body_node = child.child_by_field_name("body").unwrap();
|
let body_node = child.child_by_field_name("body").unwrap();
|
||||||
let body = Block::from_syntax_node(source, body_node)?;
|
let body = Block::from_syntax_node(source, body_node)?;
|
||||||
|
let parameters = if parameter_list.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(parameter_list)
|
||||||
|
};
|
||||||
|
|
||||||
ValueType::Function(Function::new(parameters, body))
|
ValueType::Function(Function::new(parameters, body))
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,23 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Block, Identifier};
|
use crate::{Block, Identifier, Type};
|
||||||
|
|
||||||
#[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: Option<Vec<Identifier>>,
|
parameters: Option<Vec<(Identifier, Type)>>,
|
||||||
body: Box<Block>,
|
body: Box<Block>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(parameters: Option<Vec<Identifier>>, body: Block) -> Self {
|
pub fn new(parameters: Option<Vec<(Identifier, Type)>>, body: Block) -> Self {
|
||||||
Function {
|
Function {
|
||||||
parameters,
|
parameters,
|
||||||
body: Box::new(body),
|
body: Box::new(body),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identifiers(&self) -> &Option<Vec<Identifier>> {
|
pub fn identifiers(&self) -> &Option<Vec<(Identifier, Type)>> {
|
||||||
&self.parameters
|
&self.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ValueType,
|
Function, List, Map, Table, Type, ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
@ -44,6 +44,20 @@ pub enum Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
pub fn r#type(&self) -> Type {
|
||||||
|
match self {
|
||||||
|
Value::List(_) => Type::List,
|
||||||
|
Value::Map(_) => Type::Map,
|
||||||
|
Value::Table(_) => Type::Table,
|
||||||
|
Value::Function(_) => Type::Function,
|
||||||
|
Value::String(_) => Type::String,
|
||||||
|
Value::Float(_) => Type::Float,
|
||||||
|
Value::Integer(_) => todo!(),
|
||||||
|
Value::Boolean(_) => todo!(),
|
||||||
|
Value::Empty => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
ValueType::from(self)
|
ValueType::from(self)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ Function Call
|
|||||||
Complex Function
|
Complex Function
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|message number| => {
|
|message:str number:int| => {
|
||||||
(output message)
|
(output message)
|
||||||
(output number)
|
(output number)
|
||||||
}
|
}
|
||||||
@ -74,9 +74,10 @@ Complex Function
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(identifier_list
|
|
||||||
(identifier)
|
(identifier)
|
||||||
(identifier))
|
(type_definition)
|
||||||
|
(identifier)
|
||||||
|
(type_definition)
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
|
@ -39,16 +39,6 @@ module.exports = grammar({
|
|||||||
optional(';'),
|
optional(';'),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
return: $ => seq(
|
|
||||||
'return',
|
|
||||||
$.expression,
|
|
||||||
),
|
|
||||||
|
|
||||||
use: $ => seq(
|
|
||||||
'use',
|
|
||||||
$.string,
|
|
||||||
),
|
|
||||||
|
|
||||||
expression: $ => prec.right(choice(
|
expression: $ => prec.right(choice(
|
||||||
$._expression_kind,
|
$._expression_kind,
|
||||||
seq('(', $._expression_kind, ')'),
|
seq('(', $._expression_kind, ')'),
|
||||||
@ -258,8 +248,37 @@ module.exports = grammar({
|
|||||||
$.expression,
|
$.expression,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
return: $ => seq(
|
||||||
|
'return',
|
||||||
|
$.expression,
|
||||||
|
),
|
||||||
|
|
||||||
|
use: $ => seq(
|
||||||
|
'use',
|
||||||
|
$.string,
|
||||||
|
),
|
||||||
|
|
||||||
|
type_definition: $ => choice(
|
||||||
|
'bool',
|
||||||
|
'fn',
|
||||||
|
'int',
|
||||||
|
'list',
|
||||||
|
'map',
|
||||||
|
'str',
|
||||||
|
'table',
|
||||||
|
),
|
||||||
|
|
||||||
function: $ => seq(
|
function: $ => seq(
|
||||||
field('parameters', optional($.identifier_list)),
|
optional(seq(
|
||||||
|
'|',
|
||||||
|
field('parameter', repeat(seq(
|
||||||
|
$.identifier,
|
||||||
|
':',
|
||||||
|
$.type_definition,
|
||||||
|
optional(',')
|
||||||
|
))),
|
||||||
|
'|',
|
||||||
|
)),
|
||||||
'=>',
|
'=>',
|
||||||
field('body', $.block),
|
field('body', $.block),
|
||||||
),
|
),
|
||||||
|
@ -123,32 +123,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"return": {
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "return"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "expression"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"use": {
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "use"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"expression": {
|
"expression": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 0,
|
"value": 0,
|
||||||
@ -1073,24 +1047,124 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"return": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "return"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "expression"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"use": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "use"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type_definition": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "fn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "table"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"function": {
|
"function": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
|
||||||
"name": "parameters",
|
|
||||||
"content": {
|
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "|"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "FIELD",
|
||||||
|
"name": "parameter",
|
||||||
|
"content": {
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "identifier_list"
|
"name": "identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ":"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type_definition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ","
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "BLANK"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "|"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
|
@ -172,12 +172,24 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"parameters": {
|
"parameter": {
|
||||||
"multiple": false,
|
"multiple": true,
|
||||||
"required": false,
|
"required": false,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "identifier_list",
|
"type": ",",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": ":",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "type_definition",
|
||||||
"named": true
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -549,6 +561,11 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "type_definition",
|
||||||
|
"named": true,
|
||||||
|
"fields": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "use",
|
"type": "use",
|
||||||
"named": true,
|
"named": true,
|
||||||
@ -769,6 +786,10 @@
|
|||||||
"type": "bash",
|
"type": "bash",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "bool",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "columns",
|
"type": "columns",
|
||||||
"named": false
|
"named": false
|
||||||
@ -801,6 +822,10 @@
|
|||||||
"type": "float",
|
"type": "float",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "fn",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "for",
|
"type": "for",
|
||||||
"named": false
|
"named": false
|
||||||
@ -833,6 +858,10 @@
|
|||||||
"type": "insert",
|
"type": "insert",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "int",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"named": true
|
"named": true
|
||||||
@ -845,6 +874,14 @@
|
|||||||
"type": "length",
|
"type": "length",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "list",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "map",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "match",
|
"type": "match",
|
||||||
"named": false
|
"named": false
|
||||||
@ -909,6 +946,10 @@
|
|||||||
"type": "sh",
|
"type": "sh",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "str",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"named": true
|
"named": true
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user