1
0

Add function test

This commit is contained in:
Jeff 2024-10-19 01:58:30 -04:00
parent b7153df9be
commit 6bcc5b1555
4 changed files with 64 additions and 2 deletions

View File

@ -125,6 +125,10 @@ impl<'src> Lexer<'src> {
self.position += 2; self.position += 2;
(Token::MinusEqual, Span(self.position - 2, self.position)) (Token::MinusEqual, Span(self.position - 2, self.position))
} else if let Some('>') = second_char {
self.position += 2;
(Token::ArrowThin, Span(self.position - 2, self.position))
} else if let Some('0'..='9') = second_char { } else if let Some('0'..='9') = second_char {
self.lex_numeric()? self.lex_numeric()?
} else if "-Infinity" == self.peek_chars(9) { } else if "-Infinity" == self.peek_chars(9) {

View File

@ -1111,6 +1111,20 @@ impl<'src> Parser<'src> {
} }
function_parser.advance()?; function_parser.advance()?;
let return_type = if function_parser.allow(Token::ArrowThin)? {
let r#type = function_parser.parse_type_from(
function_parser.current_token,
function_parser.current_position,
)?;
function_parser.advance()?;
Some(Box::new(r#type))
} else {
None
};
function_parser.expect(Token::LeftCurlyBrace)?; function_parser.expect(Token::LeftCurlyBrace)?;
while function_parser.current_token != Token::RightCurlyBrace { while function_parser.current_token != Token::RightCurlyBrace {
@ -1131,7 +1145,6 @@ impl<'src> Parser<'src> {
self.current_token = function_parser.current_token; self.current_token = function_parser.current_token;
self.current_position = function_parser.current_position; self.current_position = function_parser.current_position;
let return_type = take(&mut self.latest_value_type).map(Box::new);
let function_type = FunctionType { let function_type = FunctionType {
type_parameters: None, type_parameters: None,
value_parameters, value_parameters,
@ -1300,6 +1313,11 @@ struct ParseRule<'a> {
impl From<&Token<'_>> for ParseRule<'_> { impl From<&Token<'_>> for ParseRule<'_> {
fn from(token: &Token) -> Self { fn from(token: &Token) -> Self {
match token { match token {
Token::ArrowThin => ParseRule {
prefix: Some(Parser::expect_expression),
infix: None,
precedence: Precedence::None,
},
Token::Async => todo!(), Token::Async => todo!(),
Token::Bang => ParseRule { Token::Bang => ParseRule {
prefix: Some(Parser::parse_unary), prefix: Some(Parser::parse_unary),

View File

@ -38,6 +38,7 @@ pub enum Token<'src> {
While, While,
// Symbols // Symbols
ArrowThin,
BangEqual, BangEqual,
Bang, Bang,
Colon, Colon,
@ -84,6 +85,7 @@ impl<'src> Token<'src> {
Token::Integer(text) => text.len(), Token::Integer(text) => text.len(),
Token::String(text) => text.len() + 2, Token::String(text) => text.len() + 2,
Token::Async => 5, Token::Async => 5,
Token::ArrowThin => 2,
Token::Bool => 4, Token::Bool => 4,
Token::Break => 5, Token::Break => 5,
Token::Else => 4, Token::Else => 4,
@ -144,6 +146,7 @@ impl<'src> Token<'src> {
Token::Integer(text) => text, Token::Integer(text) => text,
Token::String(text) => text, Token::String(text) => text,
Token::Async => "async", Token::Async => "async",
Token::ArrowThin => "->",
Token::Bool => "bool", Token::Bool => "bool",
Token::Break => "break", Token::Break => "break",
Token::Else => "else", Token::Else => "else",
@ -195,6 +198,7 @@ impl<'src> Token<'src> {
pub fn to_owned(&self) -> TokenOwned { pub fn to_owned(&self) -> TokenOwned {
match self { match self {
Token::ArrowThin => TokenOwned::ArrowThin,
Token::Async => TokenOwned::Async, Token::Async => TokenOwned::Async,
Token::BangEqual => TokenOwned::BangEqual, Token::BangEqual => TokenOwned::BangEqual,
Token::Bang => TokenOwned::Bang, Token::Bang => TokenOwned::Bang,
@ -255,6 +259,7 @@ impl<'src> Token<'src> {
pub fn kind(&self) -> TokenKind { pub fn kind(&self) -> TokenKind {
match self { match self {
Token::ArrowThin => TokenKind::ArrowThin,
Token::Async => TokenKind::Async, Token::Async => TokenKind::Async,
Token::BangEqual => TokenKind::BangEqual, Token::BangEqual => TokenKind::BangEqual,
Token::Bang => TokenKind::Bang, Token::Bang => TokenKind::Bang,
@ -359,6 +364,7 @@ impl<'src> Token<'src> {
impl<'src> Display for Token<'src> { impl<'src> Display for Token<'src> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Token::ArrowThin => write!(f, "->"),
Token::Async => write!(f, "async"), Token::Async => write!(f, "async"),
Token::BangEqual => write!(f, "!="), Token::BangEqual => write!(f, "!="),
Token::Bang => write!(f, "!"), Token::Bang => write!(f, "!"),
@ -436,6 +442,7 @@ pub enum TokenOwned {
String(String), String(String),
// Keywords // Keywords
Async,
Bool, Bool,
Break, Break,
Else, Else,
@ -452,7 +459,7 @@ pub enum TokenOwned {
While, While,
// Symbols // Symbols
Async, ArrowThin,
Bang, Bang,
BangEqual, BangEqual,
Colon, Colon,
@ -490,6 +497,7 @@ pub enum TokenOwned {
impl Display for TokenOwned { impl Display for TokenOwned {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
TokenOwned::ArrowThin => Token::ArrowThin.fmt(f),
TokenOwned::Async => Token::Async.fmt(f), TokenOwned::Async => Token::Async.fmt(f),
TokenOwned::Bang => Token::Bang.fmt(f), TokenOwned::Bang => Token::Bang.fmt(f),
TokenOwned::BangEqual => Token::BangEqual.fmt(f), TokenOwned::BangEqual => Token::BangEqual.fmt(f),
@ -581,6 +589,7 @@ pub enum TokenKind {
While, While,
// Symbols // Symbols
ArrowThin,
BangEqual, BangEqual,
Bang, Bang,
Colon, Colon,
@ -619,6 +628,7 @@ pub enum TokenKind {
impl Display for TokenKind { impl Display for TokenKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
TokenKind::ArrowThin => Token::ArrowThin.fmt(f),
TokenKind::Async => Token::Async.fmt(f), TokenKind::Async => Token::Async.fmt(f),
TokenKind::Bang => Token::Bang.fmt(f), TokenKind::Bang => Token::Bang.fmt(f),
TokenKind::BangEqual => Token::BangEqual.fmt(f), TokenKind::BangEqual => Token::BangEqual.fmt(f),

View File

@ -316,6 +316,36 @@ fn equality_assignment_short() {
assert_eq!(run(source), Ok(Some(Value::boolean(true)))); assert_eq!(run(source), Ok(Some(Value::boolean(true))));
} }
#[test]
fn function() {
let source = "fn(a: int, b: int) -> int { a + b }";
assert_eq!(
run(source),
Ok(Some(Value::function(
Chunk::with_data(
vec![
(Instruction::add(2, 0, 1), Span(30, 31)),
(Instruction::r#return(true), Span(34, 35)),
],
vec![],
vec![
Local::new(Identifier::new("a"), Some(Type::Integer), false, 0, 0),
Local::new(Identifier::new("b"), Some(Type::Integer), false, 0, 1)
]
),
FunctionType {
type_parameters: None,
value_parameters: Some(vec![
(Identifier::new("a"), Type::Integer),
(Identifier::new("b"), Type::Integer)
]),
return_type: Some(Box::new(Type::Integer)),
}
)))
);
}
#[test] #[test]
fn greater() { fn greater() {
let source = "1 > 2"; let source = "1 > 2";