1
0

Begin adding functions to the language

This commit is contained in:
Jeff 2024-10-08 22:56:01 -04:00
parent dddbf77fac
commit bdc34cb10e
8 changed files with 80 additions and 14 deletions

View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInFunction {
String,
WriteLine,
}

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::{AnnotatedError, Identifier, Instruction, Operation, Span, Value};
#[derive(Clone)]
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Chunk {
instructions: Vec<(Instruction, Span)>,
constants: Vec<Option<Value>>,
@ -305,7 +305,7 @@ impl PartialEq for Chunk {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Local {
pub identifier: Identifier,
pub is_mutable: bool,

View File

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::{Chunk, Operation, Span};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Instruction(u32);
impl Instruction {

View File

@ -78,7 +78,7 @@ pub fn lex<'chars, 'src: 'chars>(
/// ]
/// )
/// ```
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
pub struct Lexer<'src> {
source: &'src str,
position: usize,
@ -532,6 +532,7 @@ impl<'src> Lexer<'src> {
"else" => Token::Else,
"false" => Token::Boolean("false"),
"float" => Token::FloatKeyword,
"fn" => Token::Fn,
"if" => Token::If,
"int" => Token::Int,
"let" => Token::Let,

View File

@ -26,7 +26,9 @@ pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Enum, Function, Struct, Value, ValueError};
pub use vm::{run, Vm, VmError};
#[derive(Clone, Copy, Debug, PartialEq)]
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Span(pub usize, pub usize);
impl Display for Span {

View File

@ -21,7 +21,7 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
.map_err(|error| DustError::Parse { error, source })?;
}
Ok(parser.chunk)
Ok(parser.take_chunk())
}
#[derive(Debug)]
@ -39,6 +39,7 @@ impl<'src> Parser<'src> {
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, ParseError> {
let (current_token, current_position) = lexer.next_token()?;
log::info!("Begin chunk");
log::info!(
"{} at {}",
current_token.to_string().bold(),
@ -57,6 +58,8 @@ impl<'src> Parser<'src> {
}
pub fn take_chunk(self) -> Chunk {
log::info!("End chunk");
self.chunk
}
@ -689,7 +692,7 @@ impl<'src> Parser<'src> {
_allow_assignment: bool,
_allow_return: bool,
) -> Result<(), ParseError> {
self.advance()?;
self.expect(TokenKind::LeftCurlyBrace)?;
self.chunk.begin_scope();
while !self.allow(TokenKind::RightCurlyBrace)? && !self.is_eof() {
@ -913,6 +916,33 @@ impl<'src> Parser<'src> {
Ok(())
}
fn parse_function(
&mut self,
_allow_assignment: bool,
_allow_return: bool,
) -> Result<(), ParseError> {
self.advance()?;
self.expect(TokenKind::LeftParenthesis)?;
let mut function_parser = Parser::new(self.lexer)?;
self.expect(TokenKind::RightParenthesis)?;
function_parser.parse_block(false, true)?;
self.previous_token = function_parser.previous_token;
self.previous_position = function_parser.previous_position;
self.current_token = function_parser.current_token;
self.current_position = function_parser.current_position;
let function = Value::function(function_parser.take_chunk());
self.emit_constant(function)?;
Ok(())
}
fn parse(&mut self, precedence: Precedence) -> Result<(), ParseError> {
let allow_assignment = precedence < Precedence::Assignment;
let allow_return = precedence == Precedence::None;
@ -1111,6 +1141,11 @@ impl From<&TokenKind> for ParseRule<'_> {
precedence: Precedence::None,
},
TokenKind::FloatKeyword => todo!(),
TokenKind::Fn => ParseRule {
prefix: Some(Parser::parse_function),
infix: None,
precedence: Precedence::None,
},
TokenKind::Greater => ParseRule {
prefix: None,
infix: Some(Parser::parse_comparison_binary),

View File

@ -1,4 +1,4 @@
//! Token and TokenOwned types.
//! Token, TokenOwned and TokenKind types.
use std::fmt::{self, Display, Formatter};
/// Source code token.
@ -22,6 +22,7 @@ pub enum Token<'src> {
Break,
Else,
FloatKeyword,
Fn,
If,
Int,
Let,
@ -82,6 +83,7 @@ impl<'src> Token<'src> {
Token::Break => 5,
Token::Else => 4,
Token::FloatKeyword => 5,
Token::Fn => 2,
Token::If => 2,
Token::Int => 3,
Token::Let => 3,
@ -146,6 +148,7 @@ impl<'src> Token<'src> {
Token::Equal => TokenOwned::Equal,
Token::Float(float) => TokenOwned::Float(float.to_string()),
Token::FloatKeyword => TokenOwned::FloatKeyword,
Token::Fn => TokenOwned::Fn,
Token::Greater => TokenOwned::Greater,
Token::GreaterEqual => TokenOwned::GreaterOrEqual,
Token::Identifier(text) => TokenOwned::Identifier(text.to_string()),
@ -203,6 +206,7 @@ impl<'src> Token<'src> {
Token::Equal => TokenKind::Equal,
Token::Float(_) => TokenKind::Float,
Token::FloatKeyword => TokenKind::FloatKeyword,
Token::Fn => TokenKind::Fn,
Token::Greater => TokenKind::Greater,
Token::GreaterEqual => TokenKind::GreaterEqual,
Token::Identifier(_) => TokenKind::Identifier,
@ -262,6 +266,7 @@ impl<'src> Display for Token<'src> {
Token::Equal => write!(f, "="),
Token::Float(value) => write!(f, "{value}"),
Token::FloatKeyword => write!(f, "float"),
Token::Fn => write!(f, "fn"),
Token::Greater => write!(f, ">"),
Token::GreaterEqual => write!(f, ">="),
Token::Identifier(value) => write!(f, "{value}"),
@ -320,6 +325,7 @@ pub enum TokenOwned {
Break,
Else,
FloatKeyword,
Fn,
If,
Int,
Let,
@ -387,6 +393,7 @@ impl Display for TokenOwned {
TokenOwned::Equal => Token::Equal.fmt(f),
TokenOwned::Float(float) => Token::Float(float).fmt(f),
TokenOwned::FloatKeyword => Token::FloatKeyword.fmt(f),
TokenOwned::Fn => Token::Fn.fmt(f),
TokenOwned::Greater => Token::Greater.fmt(f),
TokenOwned::GreaterOrEqual => Token::GreaterEqual.fmt(f),
TokenOwned::Identifier(text) => Token::Identifier(text).fmt(f),
@ -444,6 +451,7 @@ pub enum TokenKind {
Break,
Else,
FloatKeyword,
Fn,
If,
Int,
Let,
@ -510,6 +518,7 @@ impl Display for TokenKind {
TokenKind::Equal => Token::Equal.fmt(f),
TokenKind::Float => write!(f, "float value"),
TokenKind::FloatKeyword => Token::FloatKeyword.fmt(f),
TokenKind::Fn => Token::Fn.fmt(f),
TokenKind::Greater => Token::Greater.fmt(f),
TokenKind::GreaterEqual => Token::GreaterEqual.fmt(f),
TokenKind::Identifier => write!(f, "identifier"),

View File

@ -45,7 +45,7 @@ use serde::{
Deserialize, Deserializer, Serialize, Serializer,
};
use crate::{EnumType, FunctionType, Identifier, RangeableType, StructType, Type};
use crate::{Chunk, EnumType, FunctionType, Identifier, RangeableType, StructType, Type};
/// Dust value representation
///
@ -73,6 +73,10 @@ impl Value {
Value::Raw(ValueData::Float(value))
}
pub fn function(body: Chunk) -> Self {
Value::Raw(ValueData::Function(Function { body }))
}
pub fn integer<T: Into<i64>>(into_i64: T) -> Self {
Value::Raw(ValueData::Integer(into_i64.into()))
}
@ -987,6 +991,7 @@ pub enum ValueData {
Character(char),
Enum(Enum),
Float(f64),
Function(Function),
Integer(i64),
List(Vec<Value>),
Map(HashMap<Identifier, Value>),
@ -1002,6 +1007,7 @@ impl ValueData {
ValueData::Boolean(_) => Type::Boolean,
ValueData::Byte(_) => Type::Byte,
ValueData::Character(_) => Type::Character,
ValueData::Function(Function { .. }) => todo!(),
ValueData::Enum(Enum { r#type, .. }) => Type::Enum(r#type.clone()),
ValueData::Float(_) => Type::Float,
ValueData::Integer(_) => Type::Integer,
@ -1257,6 +1263,9 @@ impl Display for ValueData {
Ok(())
}
ValueData::Function(Function { .. }) => {
write!(f, "function")
}
ValueData::Integer(integer) => write!(f, "{integer}"),
ValueData::Map(pairs) => {
write!(f, "{{ ")?;
@ -1315,6 +1324,7 @@ impl PartialEq for ValueData {
(ValueData::Byte(left), ValueData::Byte(right)) => left == right,
(ValueData::Character(left), ValueData::Character(right)) => left == right,
(ValueData::Float(left), ValueData::Float(right)) => left == right,
(ValueData::Function(left), ValueData::Function(right)) => left == right,
(ValueData::Integer(left), ValueData::Integer(right)) => left == right,
(ValueData::List(left), ValueData::List(right)) => left == right,
(ValueData::Map(left), ValueData::Map(right)) => left == right,
@ -1344,6 +1354,8 @@ impl Ord for ValueData {
(ValueData::Character(_), _) => Ordering::Greater,
(ValueData::Float(left), ValueData::Float(right)) => left.partial_cmp(right).unwrap(),
(ValueData::Float(_), _) => Ordering::Greater,
(ValueData::Function(left), ValueData::Function(right)) => left.cmp(right),
(ValueData::Function(_), _) => Ordering::Greater,
(ValueData::Integer(left), ValueData::Integer(right)) => left.cmp(right),
(ValueData::Integer(_), _) => Ordering::Greater,
(ValueData::List(left), ValueData::List(right)) => left.cmp(right),
@ -1371,6 +1383,7 @@ impl Serialize for ValueData {
ValueData::Character(character) => serializer.serialize_char(*character),
ValueData::Enum(r#emum) => r#emum.serialize(serializer),
ValueData::Float(float) => serializer.serialize_f64(*float),
ValueData::Function(function) => function.serialize(serializer),
ValueData::Integer(integer) => serializer.serialize_i64(*integer),
ValueData::List(list) => list.serialize(serializer),
ValueData::Map(pairs) => {
@ -1434,11 +1447,8 @@ impl<'de> Deserialize<'de> for ValueData {
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Function {
Parsed {
name: Identifier,
r#type: FunctionType,
},
pub struct Function {
body: Chunk,
}
impl Function {