Remove generic position from nodes and replace with Spans
This commit is contained in:
parent
35eca1f7b4
commit
1fe26e0296
@ -13,8 +13,8 @@ important than safety and ease of use.
|
||||
### Effortless Concurrency
|
||||
|
||||
Rust promises *fearless* concurrency, and Dust takes it a step further by making concurrency as
|
||||
simple as possible. Dust is organized into **statements**, and any sequence of statements can be
|
||||
run concurrently by simply adding the `async` keyword before the block of statements.
|
||||
*effortless* as possible. Dust is organized into **statements**, and any sequence of statements can
|
||||
be run concurrently by simply adding the `async` keyword before the block of statements.
|
||||
|
||||
```dust
|
||||
# This function will count from 0 to 9, sleeping for an increasing amount of
|
||||
@ -28,7 +28,7 @@ count_slowly = fn (
|
||||
sleep_time = i * multiplier;
|
||||
|
||||
thread.sleep(sleep_time)
|
||||
thread.write_line(i as str)
|
||||
io.write_line(i as str)
|
||||
|
||||
i += 1
|
||||
}
|
||||
|
@ -5,21 +5,21 @@ use std::{
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Identifier, Type, Value};
|
||||
use crate::{Identifier, Span, Type, Value};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct AbstractSyntaxTree<P> {
|
||||
pub nodes: VecDeque<Node<P>>,
|
||||
pub struct AbstractSyntaxTree {
|
||||
pub nodes: VecDeque<Node>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Node<P> {
|
||||
pub statement: Statement<P>,
|
||||
pub position: P,
|
||||
pub struct Node {
|
||||
pub statement: Statement,
|
||||
pub position: Span,
|
||||
}
|
||||
|
||||
impl<P> Node<P> {
|
||||
pub fn new(operation: Statement<P>, position: P) -> Self {
|
||||
impl Node {
|
||||
pub fn new(operation: Statement, position: Span) -> Self {
|
||||
Self {
|
||||
statement: operation,
|
||||
position,
|
||||
@ -27,39 +27,39 @@ impl<P> Node<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Display for Node<P> {
|
||||
impl Display for Node {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.statement)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum Statement<P> {
|
||||
pub enum Statement {
|
||||
// Top-level statements
|
||||
Assign(Box<Node<P>>, Box<Node<P>>),
|
||||
Assign(Box<Node>, Box<Node>),
|
||||
|
||||
// Expressions
|
||||
Add(Box<Node<P>>, Box<Node<P>>),
|
||||
Add(Box<Node>, Box<Node>),
|
||||
BuiltInFunctionCall {
|
||||
function: BuiltInFunction,
|
||||
type_arguments: Option<Vec<Node<P>>>,
|
||||
value_arguments: Option<Vec<Node<P>>>,
|
||||
type_arguments: Option<Vec<Node>>,
|
||||
value_arguments: Option<Vec<Node>>,
|
||||
},
|
||||
FunctionCall {
|
||||
function: Box<Node<P>>,
|
||||
type_arguments: Option<Vec<Node<P>>>,
|
||||
value_arguments: Option<Vec<Node<P>>>,
|
||||
function: Box<Node>,
|
||||
type_arguments: Option<Vec<Node>>,
|
||||
value_arguments: Option<Vec<Node>>,
|
||||
},
|
||||
PropertyAccess(Box<Node<P>>, Box<Node<P>>),
|
||||
List(Vec<Node<P>>),
|
||||
Multiply(Box<Node<P>>, Box<Node<P>>),
|
||||
PropertyAccess(Box<Node>, Box<Node>),
|
||||
List(Vec<Node>),
|
||||
Multiply(Box<Node>, Box<Node>),
|
||||
|
||||
// Hard-coded values
|
||||
Constant(Value),
|
||||
Identifier(Identifier),
|
||||
}
|
||||
|
||||
impl<P> Statement<P> {
|
||||
impl Statement {
|
||||
pub fn expected_type(&self, variables: &HashMap<Identifier, Value>) -> Option<Type> {
|
||||
match self {
|
||||
Statement::Add(left, _) => left.statement.expected_type(variables),
|
||||
@ -77,7 +77,7 @@ impl<P> Statement<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Display for Statement<P> {
|
||||
impl Display for Statement {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Statement::Assign(left, right) => write!(f, "{left} = {right}"),
|
||||
|
@ -7,7 +7,7 @@
|
||||
/// - `Analyzer` struct
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{AbstractSyntaxTree, Identifier, Node, Statement, Type, Value};
|
||||
use crate::{AbstractSyntaxTree, Identifier, Node, Span, Statement, Type, Value};
|
||||
|
||||
/// Analyzes the abstract syntax tree for errors.
|
||||
///
|
||||
@ -22,10 +22,10 @@ use crate::{AbstractSyntaxTree, Identifier, Node, Statement, Type, Value};
|
||||
///
|
||||
/// assert!(result.is_err());
|
||||
/// ```
|
||||
pub fn analyze<P: Clone>(
|
||||
abstract_tree: &AbstractSyntaxTree<P>,
|
||||
pub fn analyze(
|
||||
abstract_tree: &AbstractSyntaxTree,
|
||||
variables: &HashMap<Identifier, Value>,
|
||||
) -> Result<(), AnalyzerError<P>> {
|
||||
) -> Result<(), AnalyzerError> {
|
||||
let analyzer = Analyzer::new(abstract_tree, variables);
|
||||
|
||||
analyzer.analyze()
|
||||
@ -44,14 +44,14 @@ pub fn analyze<P: Clone>(
|
||||
/// let result = analyzer.analyze();
|
||||
///
|
||||
/// assert!(result.is_err());
|
||||
pub struct Analyzer<'a, P> {
|
||||
abstract_tree: &'a AbstractSyntaxTree<P>,
|
||||
pub struct Analyzer<'a> {
|
||||
abstract_tree: &'a AbstractSyntaxTree,
|
||||
variables: &'a HashMap<Identifier, Value>,
|
||||
}
|
||||
|
||||
impl<'a, P: Clone> Analyzer<'a, P> {
|
||||
impl<'a> Analyzer<'a> {
|
||||
pub fn new(
|
||||
abstract_tree: &'a AbstractSyntaxTree<P>,
|
||||
abstract_tree: &'a AbstractSyntaxTree,
|
||||
variables: &'a HashMap<Identifier, Value>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -60,7 +60,7 @@ impl<'a, P: Clone> Analyzer<'a, P> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze(&self) -> Result<(), AnalyzerError<P>> {
|
||||
pub fn analyze(&self) -> Result<(), AnalyzerError> {
|
||||
for node in &self.abstract_tree.nodes {
|
||||
self.analyze_node(node)?;
|
||||
}
|
||||
@ -68,7 +68,7 @@ impl<'a, P: Clone> Analyzer<'a, P> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn analyze_node(&self, node: &Node<P>) -> Result<(), AnalyzerError<P>> {
|
||||
fn analyze_node(&self, node: &Node) -> Result<(), AnalyzerError> {
|
||||
match &node.statement {
|
||||
Statement::Add(left, right) => {
|
||||
if let Some(Type::Integer) | Some(Type::Float) =
|
||||
@ -166,11 +166,11 @@ impl<'a, P: Clone> Analyzer<'a, P> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum AnalyzerError<P> {
|
||||
ExpectedFunction { position: P },
|
||||
ExpectedIdentifier { actual: Node<P> },
|
||||
ExpectedIntegerOrFloat { actual: Node<P> },
|
||||
UnexpectedIdentifier { identifier: Node<P> },
|
||||
pub enum AnalyzerError {
|
||||
ExpectedFunction { position: Span },
|
||||
ExpectedIdentifier { actual: Node },
|
||||
ExpectedIntegerOrFloat { actual: Node },
|
||||
UnexpectedIdentifier { identifier: Node },
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -39,7 +39,7 @@ use crate::{
|
||||
/// }),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn parse(input: &str) -> Result<AbstractSyntaxTree<Span>, ParseError> {
|
||||
pub fn parse(input: &str) -> Result<AbstractSyntaxTree, ParseError> {
|
||||
let lexer = Lexer::new(input);
|
||||
let mut parser = Parser::new(lexer);
|
||||
let mut nodes = VecDeque::new();
|
||||
@ -80,7 +80,7 @@ pub fn parse(input: &str) -> Result<AbstractSyntaxTree<Span>, ParseError> {
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// nodes,
|
||||
/// Into::<VecDeque<Node<Span>>>::into([
|
||||
/// Into::<VecDeque<Node>>::into([
|
||||
/// Node {
|
||||
/// statement: Statement::Assign(
|
||||
/// Box::new(Node {
|
||||
@ -110,7 +110,7 @@ impl<'src> Parser<'src> {
|
||||
Parser { lexer, current }
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> Result<Node<Span>, ParseError> {
|
||||
pub fn parse(&mut self) -> Result<Node, ParseError> {
|
||||
self.parse_node(0)
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ impl<'src> Parser<'src> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_node(&mut self, precedence: u8) -> Result<Node<Span>, ParseError> {
|
||||
fn parse_node(&mut self, precedence: u8) -> Result<Node, ParseError> {
|
||||
let left_node = self.parse_primary()?;
|
||||
let left_start = left_node.position.0;
|
||||
|
||||
@ -181,7 +181,7 @@ impl<'src> Parser<'src> {
|
||||
Ok(left_node)
|
||||
}
|
||||
|
||||
fn parse_primary(&mut self) -> Result<Node<Span>, ParseError> {
|
||||
fn parse_primary(&mut self) -> Result<Node, ParseError> {
|
||||
match self.current.clone() {
|
||||
(Token::Boolean(boolean), span) => {
|
||||
self.next_token()?;
|
||||
|
@ -12,7 +12,7 @@ use serde::{
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
|
||||
use crate::{identifier::Identifier, AbstractSyntaxTree, Type, Vm, VmError};
|
||||
use crate::{identifier::Identifier, AbstractSyntaxTree, Span, Type, Vm, VmError};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Value(Arc<ValueInner>);
|
||||
@ -551,7 +551,7 @@ pub struct Function {
|
||||
pub name: Identifier,
|
||||
pub type_parameters: Option<Vec<Type>>,
|
||||
pub value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||
pub body: AbstractSyntaxTree<()>,
|
||||
pub body: AbstractSyntaxTree,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
@ -560,7 +560,7 @@ impl Function {
|
||||
_type_arguments: Option<Vec<Type>>,
|
||||
value_arguments: Option<Vec<Value>>,
|
||||
variables: &HashMap<Identifier, Value>,
|
||||
) -> Result<Option<Value>, VmError<()>> {
|
||||
) -> Result<Option<Value>, VmError> {
|
||||
let mut new_variables = variables.clone();
|
||||
|
||||
if let (Some(value_parameters), Some(value_arguments)) =
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
pub fn run(
|
||||
input: &str,
|
||||
variables: &mut HashMap<Identifier, Value>,
|
||||
) -> Result<Option<Value>, VmError<Span>> {
|
||||
) -> Result<Option<Value>, VmError> {
|
||||
let abstract_syntax_tree = parse(input)?;
|
||||
let analyzer = Analyzer::new(&abstract_syntax_tree, variables);
|
||||
|
||||
@ -19,19 +19,19 @@ pub fn run(
|
||||
vm.run(variables)
|
||||
}
|
||||
|
||||
pub struct Vm<P> {
|
||||
abstract_tree: AbstractSyntaxTree<P>,
|
||||
pub struct Vm {
|
||||
abstract_tree: AbstractSyntaxTree,
|
||||
}
|
||||
|
||||
impl<P: Copy> Vm<P> {
|
||||
pub fn new(abstract_tree: AbstractSyntaxTree<P>) -> Self {
|
||||
impl Vm {
|
||||
pub fn new(abstract_tree: AbstractSyntaxTree) -> Self {
|
||||
Self { abstract_tree }
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
&mut self,
|
||||
variables: &mut HashMap<Identifier, Value>,
|
||||
) -> Result<Option<Value>, VmError<P>> {
|
||||
) -> Result<Option<Value>, VmError> {
|
||||
let mut previous_value = None;
|
||||
|
||||
while let Some(node) = self.abstract_tree.nodes.pop_front() {
|
||||
@ -43,9 +43,9 @@ impl<P: Copy> Vm<P> {
|
||||
|
||||
fn run_node(
|
||||
&self,
|
||||
node: Node<P>,
|
||||
node: Node,
|
||||
variables: &mut HashMap<Identifier, Value>,
|
||||
) -> Result<Option<Value>, VmError<P>> {
|
||||
) -> Result<Option<Value>, VmError> {
|
||||
match node.statement {
|
||||
Statement::Add(left, right) => {
|
||||
let left_span = left.position;
|
||||
@ -158,13 +158,7 @@ impl<P: Copy> Vm<P> {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(function
|
||||
.clone()
|
||||
.call(None, value_parameters, variables)
|
||||
.map_err(|error| VmError::FunctionCallFailed {
|
||||
error: Box::new(error),
|
||||
position: function_position,
|
||||
})?)
|
||||
Ok(function.clone().call(None, value_parameters, variables)?)
|
||||
}
|
||||
Statement::Identifier(_) => Ok(None),
|
||||
Statement::List(nodes) => {
|
||||
@ -178,7 +172,7 @@ impl<P: Copy> Vm<P> {
|
||||
Err(VmError::ExpectedValue { position: span })
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<Value>, VmError<P>>>()?;
|
||||
.collect::<Result<Vec<Value>, VmError>>()?;
|
||||
|
||||
Ok(Some(Value::list(values)))
|
||||
}
|
||||
@ -244,54 +238,40 @@ impl<P: Copy> Vm<P> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum VmError<P> {
|
||||
AnaylyzerError(AnalyzerError<P>),
|
||||
pub enum VmError {
|
||||
AnaylyzerError(AnalyzerError),
|
||||
ParseError(ParseError),
|
||||
ValueError(ValueError),
|
||||
|
||||
// Anaylsis Failures
|
||||
// These should be prevented by running the analyzer before the VM
|
||||
BuiltInFunctionCallFailed(BuiltInFunctionError),
|
||||
ExpectedIdentifier {
|
||||
position: P,
|
||||
},
|
||||
ExpectedIdentifierOrInteger {
|
||||
position: P,
|
||||
},
|
||||
ExpectedInteger {
|
||||
position: P,
|
||||
},
|
||||
ExpectedList {
|
||||
position: P,
|
||||
},
|
||||
ExpectedValue {
|
||||
position: P,
|
||||
},
|
||||
FunctionCallFailed {
|
||||
error: Box<VmError<()>>,
|
||||
position: P,
|
||||
},
|
||||
ExpectedIdentifier { position: Span },
|
||||
ExpectedIdentifierOrInteger { position: Span },
|
||||
ExpectedInteger { position: Span },
|
||||
ExpectedList { position: Span },
|
||||
ExpectedValue { position: Span },
|
||||
}
|
||||
|
||||
impl<P> From<BuiltInFunctionError> for VmError<P> {
|
||||
impl From<BuiltInFunctionError> for VmError {
|
||||
fn from(v: BuiltInFunctionError) -> Self {
|
||||
Self::BuiltInFunctionCallFailed(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<AnalyzerError<P>> for VmError<P> {
|
||||
fn from(error: AnalyzerError<P>) -> Self {
|
||||
impl From<AnalyzerError> for VmError {
|
||||
fn from(error: AnalyzerError) -> Self {
|
||||
Self::AnaylyzerError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<ParseError> for VmError<P> {
|
||||
impl From<ParseError> for VmError {
|
||||
fn from(error: ParseError) -> Self {
|
||||
Self::ParseError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<ValueError> for VmError<P> {
|
||||
impl From<ValueError> for VmError {
|
||||
fn from(error: ValueError) -> Self {
|
||||
Self::ValueError(error)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user