tinyscript 0.6.1

Tiny, C-like scripting language.
Documentation
// Copyright © 2025 Stephan Kunz
//! [`LiteralParselet`] handles any language literal like 'true' and 'false'

use crate::{
	compilation::{
		Lexer, Parser,
		error::CompilationError,
		token::{Token, TokenKind},
	},
	execution::{Chunk, op_code::OpCode},
};

use super::PrefixParselet;

#[derive(Clone)]
pub struct LiteralParselet;

impl PrefixParselet for LiteralParselet {
	fn parse(
		&self,
		_lexer: &mut Lexer,
		parser: &mut Parser,
		chunk: &mut Chunk,
		_token: Token,
	) -> Result<(), CompilationError> {
		let kind = parser.current().kind;

		match kind {
			TokenKind::False => {
				parser.emit_byte(OpCode::False as u8, chunk);
				Ok(())
			}
			TokenKind::Nil => {
				parser.emit_byte(OpCode::Nil as u8, chunk);
				Ok(())
			}
			TokenKind::True => {
				parser.emit_byte(OpCode::True as u8, chunk);
				Ok(())
			}
			_ => Err(CompilationError::Unreachable {
				file: file!().into(),
				line: line!(),
			}),
		}
	}
}

#[cfg(test)]
mod tests {
	use alloc::{collections::btree_map::BTreeMap, string::String};

	use super::*;

	// check, that the auto traits are available
	const fn is_normal<T: Sized + Send + Sync>() {}

	#[test]
	const fn normal_types() {
		is_normal::<&LiteralParselet>();
		is_normal::<LiteralParselet>();
	}

	#[test]
	fn parse_rejects_non_literal_current_token() {
		// A freshly-constructed Parser has `current` set to `Token::none()`
		// (`TokenKind::None`), which is not True/False/Nil. `LiteralParselet`
		// is only registered for those three kinds, so this branch is
		// otherwise unreachable through the public `Runtime` API.
		let enums = BTreeMap::<String, i8>::new();
		let mut lexer = Lexer::new(&enums, "");
		let mut parser = Parser::new();
		let mut chunk = Chunk::default();
		let token = parser.current();
		let result = LiteralParselet.parse(&mut lexer, &mut parser, &mut chunk, token);
		assert!(matches!(result, Err(CompilationError::Unreachable { .. })));
	}
}