Add type check error; Add parameter syntax
This commit is contained in:
parent
2bd4ccb40d
commit
43d46cb289
@ -1,4 +1,4 @@
|
|||||||
all_cards = {
|
all_cards <map> = {
|
||||||
rooms = ['Library' 'Kitchen' 'Conservatory']
|
rooms = ['Library' 'Kitchen' 'Conservatory']
|
||||||
suspects = ['White' 'Green' 'Scarlett']
|
suspects = ['White' 'Green' 'Scarlett']
|
||||||
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
||||||
|
@ -30,28 +30,36 @@ impl Type {
|
|||||||
| (Type::Map, Type::Map)
|
| (Type::Map, Type::Map)
|
||||||
| (Type::String, Type::String)
|
| (Type::String, Type::String)
|
||||||
| (Type::Table, Type::Table) => Ok(()),
|
| (Type::Table, Type::Table) => Ok(()),
|
||||||
(Type::Boolean, _) => Err(Error::ExpectedBoolean {
|
(Type::Boolean, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Boolean,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::Float, _) => Err(Error::ExpectedFloat {
|
(Type::Float, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Float,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::Function, _) => Err(Error::ExpectedFunction {
|
(Type::Function, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Function,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::Integer, _) => Err(Error::ExpectedInteger {
|
(Type::Integer, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Integer,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::List, _) => Err(Error::ExpectedList {
|
(Type::List, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::List,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::Map, _) => Err(Error::ExpectedMap {
|
(Type::Map, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Map,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::String, _) => Err(Error::ExpectedString {
|
(Type::String, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::String,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
(Type::Table, _) => Err(Error::ExpectedTable {
|
(Type::Table, _) => Err(Error::TypeCheck {
|
||||||
|
expected: Type::Table,
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@ -76,7 +84,7 @@ impl AbstractTree for Type {
|
|||||||
"table" => Type::Table,
|
"table" => Type::Table,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "bool, fn, int, list, map, string or table",
|
expected: "any, bool, float, fn, int, list, map, str or table",
|
||||||
actual: node.kind(),
|
actual: node.kind(),
|
||||||
location: node.start_position(),
|
location: node.start_position(),
|
||||||
relevant_source: source[node.byte_range()].to_string(),
|
relevant_source: source[node.byte_range()].to_string(),
|
||||||
|
11
src/error.rs
11
src/error.rs
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use tree_sitter::{Node, Point};
|
use tree_sitter::{Node, Point};
|
||||||
|
|
||||||
use crate::{value::Value, Identifier};
|
use crate::{value::Value, Identifier, Type};
|
||||||
|
|
||||||
use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time};
|
use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time};
|
||||||
|
|
||||||
@ -20,6 +20,11 @@ pub enum Error {
|
|||||||
relevant_source: String,
|
relevant_source: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
TypeCheck {
|
||||||
|
expected: Type,
|
||||||
|
actual: Value,
|
||||||
|
},
|
||||||
|
|
||||||
/// The 'assert' macro did not resolve successfully.
|
/// The 'assert' macro did not resolve successfully.
|
||||||
AssertEqualFailed {
|
AssertEqualFailed {
|
||||||
expected: Value,
|
expected: Value,
|
||||||
@ -351,6 +356,10 @@ impl fmt::Display for Error {
|
|||||||
Syntax { source, location } => {
|
Syntax { source, location } => {
|
||||||
write!(f, "Syntax error at {location}, this is not valid: {source}")
|
write!(f, "Syntax error at {location}, this is not valid: {source}")
|
||||||
}
|
}
|
||||||
|
TypeCheck { expected, actual } => write!(
|
||||||
|
f,
|
||||||
|
"Type check error. Expected a {expected} but got {actual}."
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,32 +20,41 @@ impl Function {
|
|||||||
|
|
||||||
impl AbstractTree for Function {
|
impl AbstractTree for Function {
|
||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "function", node)?;
|
||||||
|
|
||||||
|
let child_count = node.child_count();
|
||||||
let mut parameters = Vec::new();
|
let mut parameters = Vec::new();
|
||||||
let mut previous_identifier = None;
|
|
||||||
|
|
||||||
for index in 1..node.child_count() - 2 {
|
for index in 1..child_count - 2 {
|
||||||
let child = node.child(index).unwrap();
|
let parameter_node = {
|
||||||
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
if child.kind() == "identifier" {
|
if child.is_named() {
|
||||||
previous_identifier = Some(Identifier::from_syntax_node(source, child)?);
|
child
|
||||||
}
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if child.kind() == "type" {
|
Error::expect_syntax_node(source, "parameter", parameter_node)?;
|
||||||
let identifier = previous_identifier.take().unwrap();
|
|
||||||
let r#type = Type::from_syntax_node(source, child)?;
|
|
||||||
|
|
||||||
parameters.push((identifier, r#type))
|
let identifier_node = parameter_node.child(0).unwrap();
|
||||||
}
|
let identifier = Identifier::from_syntax_node(source, identifier_node)?;
|
||||||
|
|
||||||
|
let type_node = parameter_node.child(1).unwrap();
|
||||||
|
let r#type = Type::from_syntax_node(source, type_node)?;
|
||||||
|
|
||||||
|
parameters.push((identifier, r#type))
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_type_node = node.child_by_field_name("return_type");
|
let return_type_node = node.child(child_count - 2).unwrap();
|
||||||
let return_type = if let Some(child) = return_type_node {
|
let return_type = if return_type_node.is_named() {
|
||||||
Some(Type::from_syntax_node(source, child)?)
|
Some(Type::from_syntax_node(source, return_type_node)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let body_node = node.child_by_field_name("body").unwrap();
|
let body_node = node.child(child_count - 1).unwrap();
|
||||||
let body = Block::from_syntax_node(source, body_node)?;
|
let body = Block::from_syntax_node(source, body_node)?;
|
||||||
|
|
||||||
Ok(Function {
|
Ok(Function {
|
||||||
|
@ -76,10 +76,12 @@ Complex Function
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(function
|
(function
|
||||||
(identifier)
|
(parameter
|
||||||
(type)
|
(identifier)
|
||||||
(identifier)
|
(type))
|
||||||
(type)
|
(parameter
|
||||||
|
(identifier)
|
||||||
|
(type))
|
||||||
(block
|
(block
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
|
@ -276,13 +276,13 @@ module.exports = grammar({
|
|||||||
|
|
||||||
function: $ => seq(
|
function: $ => seq(
|
||||||
'|',
|
'|',
|
||||||
field('parameters', repeat($._function_parameters)),
|
repeat($.parameter),
|
||||||
'|',
|
'|',
|
||||||
optional(field('return_type', $.type)),
|
optional($.type),
|
||||||
field('body', $.block),
|
$.block,
|
||||||
),
|
),
|
||||||
|
|
||||||
_function_parameters: $ => seq(
|
parameter: $ => seq(
|
||||||
$.identifier,
|
$.identifier,
|
||||||
$.type,
|
$.type,
|
||||||
optional(','),
|
optional(','),
|
||||||
|
@ -1166,7 +1166,7 @@
|
|||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "_function_parameters"
|
"name": "parameter"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1177,12 +1177,8 @@
|
|||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
"type": "SYMBOL",
|
||||||
"name": "return_type",
|
"name": "type"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "type"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "BLANK"
|
||||||
@ -1190,16 +1186,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "FIELD",
|
"type": "SYMBOL",
|
||||||
"name": "body",
|
"name": "block"
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "block"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"_function_parameters": {
|
"parameter": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
|
@ -184,34 +184,17 @@
|
|||||||
{
|
{
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"named": true,
|
"named": true,
|
||||||
"fields": {
|
"fields": {},
|
||||||
"body": {
|
|
||||||
"multiple": false,
|
|
||||||
"required": true,
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"type": "block",
|
|
||||||
"named": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"return_type": {
|
|
||||||
"multiple": false,
|
|
||||||
"required": false,
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"type": "type",
|
|
||||||
"named": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "block",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "parameter",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -455,6 +438,25 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {}
|
"fields": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "parameter",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "type",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "return",
|
"type": "return",
|
||||||
"named": true,
|
"named": true,
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user