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}; use crate::{AnnotatedError, Identifier, Instruction, Operation, Span, Value};
#[derive(Clone)] #[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Chunk { pub struct Chunk {
instructions: Vec<(Instruction, Span)>, instructions: Vec<(Instruction, Span)>,
constants: Vec<Option<Value>>, 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 struct Local {
pub identifier: Identifier, pub identifier: Identifier,
pub is_mutable: bool, pub is_mutable: bool,

View File

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::{Chunk, Operation, Span}; 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); pub struct Instruction(u32);
impl Instruction { 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> { pub struct Lexer<'src> {
source: &'src str, source: &'src str,
position: usize, position: usize,
@ -532,6 +532,7 @@ impl<'src> Lexer<'src> {
"else" => Token::Else, "else" => Token::Else,
"false" => Token::Boolean("false"), "false" => Token::Boolean("false"),
"float" => Token::FloatKeyword, "float" => Token::FloatKeyword,
"fn" => Token::Fn,
"if" => Token::If, "if" => Token::If,
"int" => Token::Int, "int" => Token::Int,
"let" => Token::Let, "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 value::{Enum, Function, Struct, Value, ValueError};
pub use vm::{run, Vm, VmError}; 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); pub struct Span(pub usize, pub usize);
impl Display for Span { 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 })?; .map_err(|error| DustError::Parse { error, source })?;
} }
Ok(parser.chunk) Ok(parser.take_chunk())
} }
#[derive(Debug)] #[derive(Debug)]
@ -39,6 +39,7 @@ impl<'src> Parser<'src> {
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, ParseError> { pub fn new(mut lexer: Lexer<'src>) -> Result<Self, ParseError> {
let (current_token, current_position) = lexer.next_token()?; let (current_token, current_position) = lexer.next_token()?;
log::info!("Begin chunk");
log::info!( log::info!(
"{} at {}", "{} at {}",
current_token.to_string().bold(), current_token.to_string().bold(),
@ -57,6 +58,8 @@ impl<'src> Parser<'src> {
} }
pub fn take_chunk(self) -> Chunk { pub fn take_chunk(self) -> Chunk {
log::info!("End chunk");
self.chunk self.chunk
} }
@ -689,7 +692,7 @@ impl<'src> Parser<'src> {
_allow_assignment: bool, _allow_assignment: bool,
_allow_return: bool, _allow_return: bool,
) -> Result<(), ParseError> { ) -> Result<(), ParseError> {
self.advance()?; self.expect(TokenKind::LeftCurlyBrace)?;
self.chunk.begin_scope(); self.chunk.begin_scope();
while !self.allow(TokenKind::RightCurlyBrace)? && !self.is_eof() { while !self.allow(TokenKind::RightCurlyBrace)? && !self.is_eof() {
@ -913,6 +916,33 @@ impl<'src> Parser<'src> {
Ok(()) 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> { fn parse(&mut self, precedence: Precedence) -> Result<(), ParseError> {
let allow_assignment = precedence < Precedence::Assignment; let allow_assignment = precedence < Precedence::Assignment;
let allow_return = precedence == Precedence::None; let allow_return = precedence == Precedence::None;
@ -1111,6 +1141,11 @@ impl From<&TokenKind> for ParseRule<'_> {
precedence: Precedence::None, precedence: Precedence::None,
}, },
TokenKind::FloatKeyword => todo!(), TokenKind::FloatKeyword => todo!(),
TokenKind::Fn => ParseRule {
prefix: Some(Parser::parse_function),
infix: None,
precedence: Precedence::None,
},
TokenKind::Greater => ParseRule { TokenKind::Greater => ParseRule {
prefix: None, prefix: None,
infix: Some(Parser::parse_comparison_binary), 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}; use std::fmt::{self, Display, Formatter};
/// Source code token. /// Source code token.
@ -22,6 +22,7 @@ pub enum Token<'src> {
Break, Break,
Else, Else,
FloatKeyword, FloatKeyword,
Fn,
If, If,
Int, Int,
Let, Let,
@ -82,6 +83,7 @@ impl<'src> Token<'src> {
Token::Break => 5, Token::Break => 5,
Token::Else => 4, Token::Else => 4,
Token::FloatKeyword => 5, Token::FloatKeyword => 5,
Token::Fn => 2,
Token::If => 2, Token::If => 2,
Token::Int => 3, Token::Int => 3,
Token::Let => 3, Token::Let => 3,
@ -146,6 +148,7 @@ impl<'src> Token<'src> {
Token::Equal => TokenOwned::Equal, Token::Equal => TokenOwned::Equal,
Token::Float(float) => TokenOwned::Float(float.to_string()), Token::Float(float) => TokenOwned::Float(float.to_string()),
Token::FloatKeyword => TokenOwned::FloatKeyword, Token::FloatKeyword => TokenOwned::FloatKeyword,
Token::Fn => TokenOwned::Fn,
Token::Greater => TokenOwned::Greater, Token::Greater => TokenOwned::Greater,
Token::GreaterEqual => TokenOwned::GreaterOrEqual, Token::GreaterEqual => TokenOwned::GreaterOrEqual,
Token::Identifier(text) => TokenOwned::Identifier(text.to_string()), Token::Identifier(text) => TokenOwned::Identifier(text.to_string()),
@ -203,6 +206,7 @@ impl<'src> Token<'src> {
Token::Equal => TokenKind::Equal, Token::Equal => TokenKind::Equal,
Token::Float(_) => TokenKind::Float, Token::Float(_) => TokenKind::Float,
Token::FloatKeyword => TokenKind::FloatKeyword, Token::FloatKeyword => TokenKind::FloatKeyword,
Token::Fn => TokenKind::Fn,
Token::Greater => TokenKind::Greater, Token::Greater => TokenKind::Greater,
Token::GreaterEqual => TokenKind::GreaterEqual, Token::GreaterEqual => TokenKind::GreaterEqual,
Token::Identifier(_) => TokenKind::Identifier, Token::Identifier(_) => TokenKind::Identifier,
@ -262,6 +266,7 @@ impl<'src> Display for Token<'src> {
Token::Equal => write!(f, "="), Token::Equal => write!(f, "="),
Token::Float(value) => write!(f, "{value}"), Token::Float(value) => write!(f, "{value}"),
Token::FloatKeyword => write!(f, "float"), Token::FloatKeyword => write!(f, "float"),
Token::Fn => write!(f, "fn"),
Token::Greater => write!(f, ">"), Token::Greater => write!(f, ">"),
Token::GreaterEqual => write!(f, ">="), Token::GreaterEqual => write!(f, ">="),
Token::Identifier(value) => write!(f, "{value}"), Token::Identifier(value) => write!(f, "{value}"),
@ -320,6 +325,7 @@ pub enum TokenOwned {
Break, Break,
Else, Else,
FloatKeyword, FloatKeyword,
Fn,
If, If,
Int, Int,
Let, Let,
@ -387,6 +393,7 @@ impl Display for TokenOwned {
TokenOwned::Equal => Token::Equal.fmt(f), TokenOwned::Equal => Token::Equal.fmt(f),
TokenOwned::Float(float) => Token::Float(float).fmt(f), TokenOwned::Float(float) => Token::Float(float).fmt(f),
TokenOwned::FloatKeyword => Token::FloatKeyword.fmt(f), TokenOwned::FloatKeyword => Token::FloatKeyword.fmt(f),
TokenOwned::Fn => Token::Fn.fmt(f),
TokenOwned::Greater => Token::Greater.fmt(f), TokenOwned::Greater => Token::Greater.fmt(f),
TokenOwned::GreaterOrEqual => Token::GreaterEqual.fmt(f), TokenOwned::GreaterOrEqual => Token::GreaterEqual.fmt(f),
TokenOwned::Identifier(text) => Token::Identifier(text).fmt(f), TokenOwned::Identifier(text) => Token::Identifier(text).fmt(f),
@ -444,6 +451,7 @@ pub enum TokenKind {
Break, Break,
Else, Else,
FloatKeyword, FloatKeyword,
Fn,
If, If,
Int, Int,
Let, Let,
@ -510,6 +518,7 @@ impl Display for TokenKind {
TokenKind::Equal => Token::Equal.fmt(f), TokenKind::Equal => Token::Equal.fmt(f),
TokenKind::Float => write!(f, "float value"), TokenKind::Float => write!(f, "float value"),
TokenKind::FloatKeyword => Token::FloatKeyword.fmt(f), TokenKind::FloatKeyword => Token::FloatKeyword.fmt(f),
TokenKind::Fn => Token::Fn.fmt(f),
TokenKind::Greater => Token::Greater.fmt(f), TokenKind::Greater => Token::Greater.fmt(f),
TokenKind::GreaterEqual => Token::GreaterEqual.fmt(f), TokenKind::GreaterEqual => Token::GreaterEqual.fmt(f),
TokenKind::Identifier => write!(f, "identifier"), TokenKind::Identifier => write!(f, "identifier"),

View File

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