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 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 value = expression.run(source, context)?;
|
||||
|
||||
|
@ -26,6 +26,7 @@ pub mod remove;
|
||||
pub mod select;
|
||||
pub mod statement;
|
||||
pub mod transform;
|
||||
pub mod r#type;
|
||||
pub mod r#use;
|
||||
pub mod value_node;
|
||||
pub mod r#while;
|
||||
@ -34,8 +35,8 @@ pub mod r#yield;
|
||||
pub use {
|
||||
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
||||
function_call::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment,
|
||||
insert::*, logic::*, math::*, r#for::*, r#match::*, r#use::*, r#while::*, r#yield::*,
|
||||
remove::*, select::*, statement::*, transform::*, value_node::*,
|
||||
insert::*, logic::*, math::*, r#for::*, r#match::*, r#type::*, r#use::*, r#while::*,
|
||||
r#yield::*, remove::*, select::*, statement::*, transform::*, value_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::{
|
||||
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)]
|
||||
@ -91,26 +91,35 @@ impl AbstractTree for ValueNode {
|
||||
ValueType::Map(child_nodes)
|
||||
}
|
||||
"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() {
|
||||
let child_node = node.child(index).unwrap();
|
||||
while index < node.child_count() {
|
||||
let current_node = node.child(index).unwrap();
|
||||
let next_node = node.child(index + 1);
|
||||
|
||||
if child_node.is_named() {
|
||||
let parameter = Identifier::from_syntax_node(source, child_node)?;
|
||||
if current_node.kind() == "identifier" {
|
||||
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)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
index += 2
|
||||
}
|
||||
|
||||
let body_node = child.child_by_field_name("body").unwrap();
|
||||
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))
|
||||
}
|
||||
|
@ -2,23 +2,23 @@ use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Block, Identifier};
|
||||
use crate::{Block, Identifier, Type};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Function {
|
||||
parameters: Option<Vec<Identifier>>,
|
||||
parameters: Option<Vec<(Identifier, Type)>>,
|
||||
body: Box<Block>,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn new(parameters: Option<Vec<Identifier>>, body: Block) -> Self {
|
||||
pub fn new(parameters: Option<Vec<(Identifier, Type)>>, body: Block) -> Self {
|
||||
Function {
|
||||
parameters,
|
||||
body: Box::new(body),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identifiers(&self) -> &Option<Vec<Identifier>> {
|
||||
pub fn identifiers(&self) -> &Option<Vec<(Identifier, Type)>> {
|
||||
&self.parameters
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Types that represent runtime values.
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
Function, List, Map, Table, ValueType,
|
||||
Function, List, Map, Table, Type, ValueType,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
@ -44,6 +44,20 @@ pub enum 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 {
|
||||
ValueType::from(self)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ Function Call
|
||||
Complex Function
|
||||
================================================================================
|
||||
|
||||
|message number| => {
|
||||
|message:str number:int| => {
|
||||
(output message)
|
||||
(output number)
|
||||
}
|
||||
@ -74,9 +74,10 @@ Complex Function
|
||||
(expression
|
||||
(value
|
||||
(function
|
||||
(identifier_list
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier)
|
||||
(type_definition)
|
||||
(identifier)
|
||||
(type_definition)
|
||||
(block
|
||||
(statement
|
||||
(expression
|
||||
|
@ -39,16 +39,6 @@ module.exports = grammar({
|
||||
optional(';'),
|
||||
)),
|
||||
|
||||
return: $ => seq(
|
||||
'return',
|
||||
$.expression,
|
||||
),
|
||||
|
||||
use: $ => seq(
|
||||
'use',
|
||||
$.string,
|
||||
),
|
||||
|
||||
expression: $ => prec.right(choice(
|
||||
$._expression_kind,
|
||||
seq('(', $._expression_kind, ')'),
|
||||
@ -258,8 +248,37 @@ module.exports = grammar({
|
||||
$.expression,
|
||||
)),
|
||||
|
||||
return: $ => seq(
|
||||
'return',
|
||||
$.expression,
|
||||
),
|
||||
|
||||
use: $ => seq(
|
||||
'use',
|
||||
$.string,
|
||||
),
|
||||
|
||||
type_definition: $ => choice(
|
||||
'bool',
|
||||
'fn',
|
||||
'int',
|
||||
'list',
|
||||
'map',
|
||||
'str',
|
||||
'table',
|
||||
),
|
||||
|
||||
function: $ => seq(
|
||||
field('parameters', optional($.identifier_list)),
|
||||
optional(seq(
|
||||
'|',
|
||||
field('parameter', repeat(seq(
|
||||
$.identifier,
|
||||
':',
|
||||
$.type_definition,
|
||||
optional(',')
|
||||
))),
|
||||
'|',
|
||||
)),
|
||||
'=>',
|
||||
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": {
|
||||
"type": "PREC_RIGHT",
|
||||
"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": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "parameters",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier_list"
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "|"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "parameter",
|
||||
"content": {
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "type_definition"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "|"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
|
@ -172,12 +172,24 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": {
|
||||
"multiple": false,
|
||||
"parameter": {
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier_list",
|
||||
"type": ",",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": ":",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "type_definition",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@ -549,6 +561,11 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "type_definition",
|
||||
"named": true,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"type": "use",
|
||||
"named": true,
|
||||
@ -769,6 +786,10 @@
|
||||
"type": "bash",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "bool",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "columns",
|
||||
"named": false
|
||||
@ -801,6 +822,10 @@
|
||||
"type": "float",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "fn",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "for",
|
||||
"named": false
|
||||
@ -833,6 +858,10 @@
|
||||
"type": "insert",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"named": true
|
||||
@ -845,6 +874,14 @@
|
||||
"type": "length",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "map",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "match",
|
||||
"named": false
|
||||
@ -909,6 +946,10 @@
|
||||
"type": "sh",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "str",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"named": true
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user