Begin adding functions to the language
This commit is contained in:
parent
dddbf77fac
commit
bdc34cb10e
7
dust-lang/src/built_in_function.rs
Normal file
7
dust-lang/src/built_in_function.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub enum BuiltInFunction {
|
||||||
|
String,
|
||||||
|
WriteLine,
|
||||||
|
}
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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),
|
||||||
|
@ -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"),
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user