Add type check error; Add parameter syntax

This commit is contained in:
Jeff 2023-11-28 10:29:42 -05:00
parent 2bd4ccb40d
commit 43d46cb289
9 changed files with 6464 additions and 6584 deletions

View File

@ -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']

View File

@ -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(),

View File

@ -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}."
),
} }
} }
} }

View File

@ -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> {
let mut parameters = Vec::new(); Error::expect_syntax_node(source, "function", node)?;
let mut previous_identifier = None;
for index in 1..node.child_count() - 2 { let child_count = node.child_count();
let mut parameters = Vec::new();
for index in 1..child_count - 2 {
let parameter_node = {
let child = node.child(index).unwrap(); 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)?; 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)) 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 {

View File

@ -76,10 +76,12 @@ Complex Function
(expression (expression
(value (value
(function (function
(parameter
(identifier) (identifier)
(type) (type))
(parameter
(identifier) (identifier)
(type) (type))
(block (block
(statement (statement
(expression (expression

View File

@ -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(','),

View File

@ -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",
"name": "return_type",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "type" "name": "type"
}
}, },
{ {
"type": "BLANK" "type": "BLANK"
@ -1190,16 +1186,12 @@
] ]
}, },
{ {
"type": "FIELD",
"name": "body",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "block" "name": "block"
} }
}
] ]
}, },
"_function_parameters": { "parameter": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {

View File

@ -184,34 +184,17 @@
{ {
"type": "function", "type": "function",
"named": true, "named": true,
"fields": { "fields": {},
"body": { "children": {
"multiple": false, "multiple": true,
"required": true, "required": true,
"types": [ "types": [
{ {
"type": "block", "type": "block",
"named": true "named": true
}
]
}, },
"return_type": {
"multiple": false,
"required": false,
"types": [
{ {
"type": "type", "type": "parameter",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "identifier",
"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