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;
(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 {
self.lex_numeric()?
} else if "-Infinity" == self.peek_chars(9) {

View File

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

View File

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