Add types to functions and improve calls
This commit is contained in:
parent
2527cc2de7
commit
2864bee057
@ -132,6 +132,10 @@ impl Chunk {
|
|||||||
operations
|
operations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn constants(&self) -> &[Option<Value>] {
|
||||||
|
&self.constants
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> {
|
pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
|
|
||||||
@ -333,6 +337,7 @@ impl Local {
|
|||||||
pub struct ChunkDisassembler<'a> {
|
pub struct ChunkDisassembler<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
chunk: &'a Chunk,
|
chunk: &'a Chunk,
|
||||||
|
source: Option<&'a str>,
|
||||||
width: usize,
|
width: usize,
|
||||||
styled: bool,
|
styled: bool,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
@ -375,12 +380,19 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
chunk,
|
chunk,
|
||||||
|
source: None,
|
||||||
width: Self::default_width(),
|
width: Self::default_width(),
|
||||||
styled: false,
|
styled: false,
|
||||||
indent: 0,
|
indent: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn source(&mut self, source: &'a str) -> &mut Self {
|
||||||
|
self.source = Some(source);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn width(&mut self, width: usize) -> &mut Self {
|
pub fn width(&mut self, width: usize) -> &mut Self {
|
||||||
self.width = width;
|
self.width = width;
|
||||||
|
|
||||||
@ -439,6 +451,17 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
|
|
||||||
push(self.name, self.styled);
|
push(self.name, self.styled);
|
||||||
|
|
||||||
|
if let Some(source) = self.source {
|
||||||
|
let length = if source.len() < self.width {
|
||||||
|
source.len() - 2
|
||||||
|
} else {
|
||||||
|
self.width - 2
|
||||||
|
};
|
||||||
|
let source_line = format!("\"{}\"", &source[..length]).dimmed();
|
||||||
|
|
||||||
|
push(&source_line, false);
|
||||||
|
}
|
||||||
|
|
||||||
let info_line = format!(
|
let info_line = format!(
|
||||||
"{} instructions, {} constants, {} locals",
|
"{} instructions, {} constants, {} locals",
|
||||||
self.chunk.instructions.len(),
|
self.chunk.instructions.len(),
|
||||||
@ -518,10 +541,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
for (index, value_option) in self.chunk.constants.iter().enumerate() {
|
for (index, value_option) in self.chunk.constants.iter().enumerate() {
|
||||||
let value_display = value_option
|
let value_display = value_option
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|value| match value {
|
.map(|value| value.to_string())
|
||||||
Value::Primitive(value_data) => value_data.to_string(),
|
|
||||||
Value::Object(_) => "object".to_string(),
|
|
||||||
})
|
|
||||||
.unwrap_or("empty".to_string());
|
.unwrap_or("empty".to_string());
|
||||||
let trucated_length = 8;
|
let trucated_length = 8;
|
||||||
let with_elipsis = trucated_length - 3;
|
let with_elipsis = trucated_length - 3;
|
||||||
@ -535,15 +555,16 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
|
|
||||||
if let Some(function_disassembly) =
|
if let Some(function_disassembly) =
|
||||||
value_option.as_ref().and_then(|value| match value {
|
value_option.as_ref().and_then(|value| match value {
|
||||||
Value::Primitive(value_data) => value_data.as_function().map(|function| {
|
Value::Function(function) => Some(
|
||||||
function
|
function
|
||||||
.chunk
|
.chunk()
|
||||||
.disassembler("function")
|
.disassembler("function")
|
||||||
.styled(self.styled)
|
.styled(self.styled)
|
||||||
.indent(self.indent + 1)
|
.indent(self.indent + 1)
|
||||||
.width(self.width)
|
.width(self.width)
|
||||||
.disassemble()
|
.disassemble(),
|
||||||
}),
|
),
|
||||||
|
Value::Primitive(_) => None,
|
||||||
Value::Object(_) => None,
|
Value::Object(_) => None,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -95,6 +95,10 @@ impl<'src> Lexer<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn source(&self) -> &'src str {
|
||||||
|
self.source
|
||||||
|
}
|
||||||
|
|
||||||
pub fn skip_to(&mut self, position: usize) {
|
pub fn skip_to(&mut self, position: usize) {
|
||||||
self.position = position;
|
self.position = position;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
mem::replace,
|
mem::{replace, take},
|
||||||
num::{ParseFloatError, ParseIntError},
|
num::{ParseFloatError, ParseIntError},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -8,8 +8,8 @@ use colored::Colorize;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, LexError, Lexer,
|
AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Identifier, Instruction, LexError,
|
||||||
Operation, Span, Token, TokenKind, TokenOwned, Type, Value,
|
Lexer, Operation, Span, Token, TokenKind, TokenOwned, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
||||||
@ -36,12 +36,17 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
|||||||
pub struct Parser<'src> {
|
pub struct Parser<'src> {
|
||||||
chunk: Chunk,
|
chunk: Chunk,
|
||||||
lexer: Lexer<'src>,
|
lexer: Lexer<'src>,
|
||||||
|
|
||||||
current_register: u8,
|
current_register: u8,
|
||||||
|
|
||||||
current_token: Token<'src>,
|
current_token: Token<'src>,
|
||||||
current_position: Span,
|
current_position: Span,
|
||||||
|
|
||||||
previous_token: Token<'src>,
|
previous_token: Token<'src>,
|
||||||
previous_position: Span,
|
previous_position: Span,
|
||||||
|
|
||||||
parsed_expression: bool,
|
parsed_expression: bool,
|
||||||
|
latest_value_type: Option<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Parser<'src> {
|
impl<'src> Parser<'src> {
|
||||||
@ -63,6 +68,7 @@ impl<'src> Parser<'src> {
|
|||||||
previous_token: Token::Eof,
|
previous_token: Token::Eof,
|
||||||
previous_position: Span(0, 0),
|
previous_position: Span(0, 0),
|
||||||
parsed_expression: false,
|
parsed_expression: false,
|
||||||
|
latest_value_type: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +148,8 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> {
|
fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> {
|
||||||
|
self.latest_value_type = Some(value.r#type());
|
||||||
|
|
||||||
let constant_index = self.chunk.push_constant(value, position)?;
|
let constant_index = self.chunk.push_constant(value, position)?;
|
||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
@ -165,6 +173,7 @@ impl<'src> Parser<'src> {
|
|||||||
position,
|
position,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.latest_value_type = Some(Type::Boolean);
|
||||||
self.parsed_expression = true;
|
self.parsed_expression = true;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -954,34 +963,26 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_return(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
fn parse_return(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
||||||
let start = self.current_position.0;
|
|
||||||
|
|
||||||
if !allowed.explicit_return {
|
if !allowed.explicit_return {
|
||||||
return Err(ParseError::UnexpectedReturn {
|
return Err(ParseError::UnexpectedReturn {
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = self.current_position.0;
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let has_return_value = if !matches!(
|
let has_return_value = if matches!(
|
||||||
self.current_token,
|
self.current_token,
|
||||||
Token::Semicolon | Token::RightCurlyBrace
|
Token::Semicolon | Token::RightCurlyBrace
|
||||||
) {
|
) {
|
||||||
self.parse_statement(
|
false
|
||||||
Allowed {
|
} else {
|
||||||
assignment: false,
|
self.parse_expression()?;
|
||||||
explicit_return: false,
|
|
||||||
implicit_return: false,
|
|
||||||
},
|
|
||||||
Context::None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let end = self.current_position.1;
|
let end = self.current_position.1;
|
||||||
|
|
||||||
self.emit_instruction(Instruction::r#return(has_return_value), Span(start, end));
|
self.emit_instruction(Instruction::r#return(has_return_value), Span(start, end));
|
||||||
@ -1060,6 +1061,8 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
function_parser.expect(Token::LeftParenthesis)?;
|
function_parser.expect(Token::LeftParenthesis)?;
|
||||||
|
|
||||||
|
let mut value_parameters: Option<Vec<(Identifier, Type)>> = None;
|
||||||
|
|
||||||
while function_parser.current_token != Token::RightParenthesis {
|
while function_parser.current_token != Token::RightParenthesis {
|
||||||
let start = function_parser.current_position.0;
|
let start = function_parser.current_position.0;
|
||||||
let is_mutable = function_parser.allow(Token::Mut)?;
|
let is_mutable = function_parser.allow(Token::Mut)?;
|
||||||
@ -1086,6 +1089,12 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
let end = function_parser.current_position.1;
|
let end = function_parser.current_position.1;
|
||||||
|
|
||||||
|
if let Some(value_parameters) = value_parameters.as_mut() {
|
||||||
|
value_parameters.push((parameter.clone(), r#type.clone()));
|
||||||
|
} else {
|
||||||
|
value_parameters = Some(vec![(parameter.clone(), r#type.clone())]);
|
||||||
|
};
|
||||||
|
|
||||||
function_parser.chunk.declare_local(
|
function_parser.chunk.declare_local(
|
||||||
parameter,
|
parameter,
|
||||||
Some(r#type),
|
Some(r#type),
|
||||||
@ -1119,7 +1128,13 @@ impl<'src> Parser<'src> {
|
|||||||
self.current_token = function_parser.current_token;
|
self.current_token = function_parser.current_token;
|
||||||
self.current_position = function_parser.current_position;
|
self.current_position = function_parser.current_position;
|
||||||
|
|
||||||
let function = Value::function(function_parser.chunk);
|
let return_type = take(&mut self.latest_value_type).map(Box::new);
|
||||||
|
let function_type = FunctionType {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
};
|
||||||
|
let function = Value::function(function_parser.chunk, function_type);
|
||||||
let function_end = self.current_position.1;
|
let function_end = self.current_position.1;
|
||||||
|
|
||||||
self.lexer.skip_to(function_end);
|
self.lexer.skip_to(function_end);
|
||||||
@ -1131,6 +1146,17 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_call(&mut self) -> Result<(), ParseError> {
|
fn parse_call(&mut self) -> Result<(), ParseError> {
|
||||||
|
let last_instruction = self.chunk.get_last_instruction()?.0;
|
||||||
|
|
||||||
|
if !last_instruction.is_expression() {
|
||||||
|
return Err(ParseError::ExpectedExpression {
|
||||||
|
found: self.previous_token.to_owned(),
|
||||||
|
position: self.previous_position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = self.current_position.0;
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let function_register = self.current_register;
|
let function_register = self.current_register;
|
||||||
@ -1143,14 +1169,7 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
let register = self.current_register;
|
let register = self.current_register;
|
||||||
|
|
||||||
self.parse(
|
self.parse_expression()?;
|
||||||
Precedence::None,
|
|
||||||
Allowed {
|
|
||||||
assignment: false,
|
|
||||||
explicit_return: false,
|
|
||||||
implicit_return: false,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if self.current_register == register {
|
if self.current_register == register {
|
||||||
return Err(ParseError::ExpectedExpression {
|
return Err(ParseError::ExpectedExpression {
|
||||||
@ -1162,11 +1181,15 @@ impl<'src> Parser<'src> {
|
|||||||
argument_count += 1;
|
argument_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let end = self.current_position.1;
|
||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
Instruction::call(function_register, argument_count),
|
Instruction::call(function_register, argument_count),
|
||||||
self.current_position,
|
Span(start, end),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.parsed_expression = true;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,20 +191,17 @@ impl Type {
|
|||||||
}
|
}
|
||||||
(
|
(
|
||||||
Type::Function(FunctionType {
|
Type::Function(FunctionType {
|
||||||
name: left_name,
|
|
||||||
type_parameters: left_type_parameters,
|
type_parameters: left_type_parameters,
|
||||||
value_parameters: left_value_parameters,
|
value_parameters: left_value_parameters,
|
||||||
return_type: left_return,
|
return_type: left_return,
|
||||||
}),
|
}),
|
||||||
Type::Function(FunctionType {
|
Type::Function(FunctionType {
|
||||||
name: right_name,
|
|
||||||
type_parameters: right_type_parameters,
|
type_parameters: right_type_parameters,
|
||||||
value_parameters: right_value_parameters,
|
value_parameters: right_value_parameters,
|
||||||
return_type: right_return,
|
return_type: right_return,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
if left_name != right_name
|
if left_return != right_return
|
||||||
|| left_return != right_return
|
|
||||||
|| left_type_parameters != right_type_parameters
|
|| left_type_parameters != right_type_parameters
|
||||||
|| left_value_parameters != right_value_parameters
|
|| left_value_parameters != right_value_parameters
|
||||||
{
|
{
|
||||||
@ -419,7 +416,6 @@ impl Ord for Type {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct FunctionType {
|
pub struct FunctionType {
|
||||||
pub name: Identifier,
|
|
||||||
pub type_parameters: Option<Vec<Identifier>>,
|
pub type_parameters: Option<Vec<Identifier>>,
|
||||||
pub value_parameters: Option<Vec<(Identifier, Type)>>,
|
pub value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||||
pub return_type: Option<Box<Type>>,
|
pub return_type: Option<Box<Type>>,
|
||||||
@ -433,11 +429,11 @@ impl Display for FunctionType {
|
|||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
|
|
||||||
for (index, type_parameter) in type_parameters.iter().enumerate() {
|
for (index, type_parameter) in type_parameters.iter().enumerate() {
|
||||||
write!(f, "{type_parameter}")?;
|
if index > 0 {
|
||||||
|
|
||||||
if index != type_parameters.len() - 1 {
|
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write!(f, "{type_parameter}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
@ -447,11 +443,11 @@ impl Display for FunctionType {
|
|||||||
|
|
||||||
if let Some(value_parameters) = &self.value_parameters {
|
if let Some(value_parameters) = &self.value_parameters {
|
||||||
for (index, (identifier, r#type)) in value_parameters.iter().enumerate() {
|
for (index, (identifier, r#type)) in value_parameters.iter().enumerate() {
|
||||||
write!(f, "{identifier}: {type}")?;
|
if index > 0 {
|
||||||
|
|
||||||
if index != value_parameters.len() - 1 {
|
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write!(f, "{identifier}: {type}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ use serde::{
|
|||||||
Deserialize, Deserializer, Serialize, Serializer,
|
Deserialize, Deserializer, Serialize, Serializer,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Chunk, RangeableType, Span, Type, Vm, VmError};
|
use crate::{Chunk, FunctionType, RangeableType, Span, Type, Vm, VmError};
|
||||||
|
|
||||||
/// Dust value representation
|
/// Dust value representation
|
||||||
///
|
///
|
||||||
@ -39,6 +39,7 @@ use crate::{Chunk, RangeableType, Span, Type, Vm, VmError};
|
|||||||
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Primitive(Primitive),
|
Primitive(Primitive),
|
||||||
|
Function(Function),
|
||||||
Object(Object),
|
Object(Object),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,8 +60,11 @@ impl Value {
|
|||||||
Value::Primitive(Primitive::Float(value))
|
Value::Primitive(Primitive::Float(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(body: Chunk) -> Self {
|
pub fn function(body: Chunk, r#type: FunctionType) -> Self {
|
||||||
Value::Primitive(Primitive::Function(Function { chunk: body }))
|
Value::Primitive(Primitive::Function(Function {
|
||||||
|
chunk: body,
|
||||||
|
r#type: Type::Function(r#type),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn integer<T: Into<i64>>(into_i64: T) -> Self {
|
pub fn integer<T: Into<i64>>(into_i64: T) -> Self {
|
||||||
@ -79,9 +83,14 @@ impl Value {
|
|||||||
Value::Primitive(Primitive::String(to_string.to_string()))
|
Value::Primitive(Primitive::String(to_string.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_function(&self) -> bool {
|
||||||
|
matches!(self, Value::Function(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> Type {
|
pub fn r#type(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(data) => data.r#type(),
|
Value::Primitive(data) => data.r#type(),
|
||||||
|
Value::Function(function) => function.r#type().clone(),
|
||||||
Value::Object(Object::List {
|
Value::Object(Object::List {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
@ -231,6 +240,7 @@ impl Value {
|
|||||||
pub fn display(&self, vm: &Vm, position: Span) -> Result<String, ValueError> {
|
pub fn display(&self, vm: &Vm, position: Span) -> Result<String, ValueError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(primitive) => Ok(primitive.to_string()),
|
Value::Primitive(primitive) => Ok(primitive.to_string()),
|
||||||
|
Value::Function(function) => Ok(function.to_string()),
|
||||||
Value::Object(object) => object.display(vm, position),
|
Value::Object(object) => object.display(vm, position),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,6 +300,7 @@ impl Clone for Value {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(data) => Value::Primitive(data.clone()),
|
Value::Primitive(data) => Value::Primitive(data.clone()),
|
||||||
|
Value::Function(function) => Value::Function(function.clone()),
|
||||||
Value::Object(object) => Value::Object(object.clone()),
|
Value::Object(object) => Value::Object(object.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +310,8 @@ impl Display for Value {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(primitive) => write!(f, "{primitive}"),
|
Value::Primitive(primitive) => write!(f, "{primitive}"),
|
||||||
Value::Object(_) => write!(f, "object"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
|
Value::Object(object) => write!(f, "{object}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,6 +320,7 @@ impl Serialize for Value {
|
|||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(data) => data.serialize(serializer),
|
Value::Primitive(data) => data.serialize(serializer),
|
||||||
|
Value::Function(function) => function.serialize(serializer),
|
||||||
Value::Object(object) => object.serialize(serializer),
|
Value::Object(object) => object.serialize(serializer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,7 +384,7 @@ impl Primitive {
|
|||||||
Primitive::Boolean(_) => Type::Boolean,
|
Primitive::Boolean(_) => Type::Boolean,
|
||||||
Primitive::Byte(_) => Type::Byte,
|
Primitive::Byte(_) => Type::Byte,
|
||||||
Primitive::Character(_) => Type::Character,
|
Primitive::Character(_) => Type::Character,
|
||||||
Primitive::Function(Function { .. }) => todo!(),
|
Primitive::Function(Function { r#type, .. }) => r#type.clone(),
|
||||||
Primitive::Float(_) => Type::Float,
|
Primitive::Float(_) => Type::Float,
|
||||||
Primitive::Integer(_) => Type::Integer,
|
Primitive::Integer(_) => Type::Integer,
|
||||||
Primitive::Range(range) => range.r#type(),
|
Primitive::Range(range) => range.r#type(),
|
||||||
@ -643,7 +656,32 @@ impl Ord for Primitive {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub chunk: Chunk,
|
chunk: Chunk,
|
||||||
|
r#type: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Function {
|
||||||
|
pub fn new(chunk: Chunk, r#type: Type) -> Self {
|
||||||
|
Self { chunk, r#type }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chunk(&self) -> &Chunk {
|
||||||
|
&self.chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_chunk(self) -> Chunk {
|
||||||
|
self.chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn r#type(&self) -> &Type {
|
||||||
|
&self.r#type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Function {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.r#type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -894,6 +932,16 @@ impl Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Object {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Object::List { start, end, .. } => {
|
||||||
|
write!(f, "List [R{}..=R{}]", start, end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueError {
|
pub enum ValueError {
|
||||||
CannotAdd(Value, Value),
|
CannotAdd(Value, Value),
|
||||||
@ -918,6 +966,7 @@ impl Display for ValueError {
|
|||||||
let get_value_display = |value: &Value| -> String {
|
let get_value_display = |value: &Value| -> String {
|
||||||
match value {
|
match value {
|
||||||
Value::Primitive(primitive) => primitive.to_string(),
|
Value::Primitive(primitive) => primitive.to_string(),
|
||||||
|
Value::Function(function) => function.to_string(),
|
||||||
Value::Object(_) => "Object".to_string(),
|
Value::Object(_) => "Object".to_string(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -378,11 +378,11 @@ impl Vm {
|
|||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
let mut function_vm = Vm::new(function.chunk);
|
let mut function_vm = Vm::new(function.take_chunk());
|
||||||
let first_argument_index = function_index + 1;
|
let first_argument_index = function_index + 1;
|
||||||
let last_argument_index = first_argument_index + argument_count;
|
let last_argument_index = first_argument_index + argument_count;
|
||||||
|
|
||||||
for argument_index in first_argument_index..=last_argument_index {
|
for argument_index in first_argument_index..last_argument_index {
|
||||||
let argument = self.empty(argument_index, position)?;
|
let argument = self.empty(argument_index, position)?;
|
||||||
|
|
||||||
function_vm.stack.push(Register::Value(argument));
|
function_vm.stack.push(Register::Value(argument));
|
||||||
@ -392,13 +392,15 @@ impl Vm {
|
|||||||
|
|
||||||
if let Some(value) = return_value {
|
if let Some(value) = return_value {
|
||||||
self.set(function_index, value, position)?;
|
self.set(function_index, value, position)?;
|
||||||
|
} else {
|
||||||
|
self.empty(function_index, position)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::Return => {
|
Operation::Return => {
|
||||||
let should_return_value = instruction.b_as_boolean();
|
let should_return_value = instruction.b_as_boolean();
|
||||||
let top_of_stack = (self.stack.len() - 1) as u8;
|
|
||||||
|
|
||||||
return if should_return_value {
|
return if should_return_value {
|
||||||
|
let top_of_stack = (self.stack.len() - 1) as u8;
|
||||||
let value = self.empty(top_of_stack, position)?;
|
let value = self.empty(top_of_stack, position)?;
|
||||||
|
|
||||||
Ok(Some(value))
|
Ok(Some(value))
|
||||||
|
@ -60,13 +60,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_and_display(source: &str, pretty_print: bool) {
|
fn parse_and_display(source: &str, styled: bool) {
|
||||||
match parse(source) {
|
match parse(source) {
|
||||||
Ok(chunk) => println!(
|
Ok(chunk) => println!(
|
||||||
"{}",
|
"{}",
|
||||||
chunk
|
chunk
|
||||||
.disassembler("Dust CLI Input")
|
.disassembler("Dust CLI Input")
|
||||||
.styled(pretty_print)
|
.source(source)
|
||||||
|
.styled(styled)
|
||||||
.disassemble()
|
.disassemble()
|
||||||
),
|
),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user