From bdc34cb10e6cfdee2d6815ec6e348b43e3910778 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 8 Oct 2024 22:56:01 -0400 Subject: [PATCH] Begin adding functions to the language --- dust-lang/src/built_in_function.rs | 7 ++++++ dust-lang/src/chunk.rs | 4 +-- dust-lang/src/instruction.rs | 4 ++- dust-lang/src/lexer.rs | 3 ++- dust-lang/src/lib.rs | 4 ++- dust-lang/src/parser.rs | 39 ++++++++++++++++++++++++++++-- dust-lang/src/token.rs | 11 ++++++++- dust-lang/src/value.rs | 22 ++++++++++++----- 8 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 dust-lang/src/built_in_function.rs diff --git a/dust-lang/src/built_in_function.rs b/dust-lang/src/built_in_function.rs new file mode 100644 index 0000000..f541d00 --- /dev/null +++ b/dust-lang/src/built_in_function.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum BuiltInFunction { + String, + WriteLine, +} diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index 4995ab2..751ab9c 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -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>, @@ -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, diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index 39abbcc..dfde385 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -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 { diff --git a/dust-lang/src/lexer.rs b/dust-lang/src/lexer.rs index 21320d8..54268bf 100644 --- a/dust-lang/src/lexer.rs +++ b/dust-lang/src/lexer.rs @@ -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, diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 215811f..9edcebb 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -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 { diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index d30a70f..b15a197 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -21,7 +21,7 @@ pub fn parse(source: &str) -> Result { .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 { 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), diff --git a/dust-lang/src/token.rs b/dust-lang/src/token.rs index 9a31fff..0728ff5 100644 --- a/dust-lang/src/token.rs +++ b/dust-lang/src/token.rs @@ -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"), diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index f8cb65b..bcba5e2 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -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>(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), Map(HashMap), @@ -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 {