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};
|
||||
|
||||
#[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,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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"),
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user