Add instantiating unit structs
This commit is contained in:
parent
7e7448fe52
commit
1d75bd6594
@ -11,7 +11,8 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{BinaryOperator, UnaryOperator},
|
abstract_tree::{BinaryOperator, UnaryOperator},
|
||||||
parse, AbstractSyntaxTree, Context, DustError, Identifier, Node, Span, Statement, Type,
|
parse, AbstractSyntaxTree, Context, DustError, Identifier, Node, Span, Statement,
|
||||||
|
StructDefinition, StructType, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Analyzes the abstract syntax tree for errors.
|
/// Analyzes the abstract syntax tree for errors.
|
||||||
@ -420,7 +421,18 @@ impl<'a> Analyzer<'a> {
|
|||||||
Statement::Nil(node) => {
|
Statement::Nil(node) => {
|
||||||
self.analyze_statement(node)?;
|
self.analyze_statement(node)?;
|
||||||
}
|
}
|
||||||
Statement::StructDefinition(_) => {}
|
Statement::StructDefinition(struct_definition) => {
|
||||||
|
let (name, r#type) = match struct_definition {
|
||||||
|
StructDefinition::Unit { name } => (
|
||||||
|
name.inner.clone(),
|
||||||
|
Type::Struct(StructType::Unit {
|
||||||
|
name: name.inner.clone(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.context.set_type(name, r#type, node.position);
|
||||||
|
}
|
||||||
Statement::UnaryOperation { operator, operand } => {
|
Statement::UnaryOperation { operator, operand } => {
|
||||||
self.analyze_statement(operand)?;
|
self.analyze_statement(operand)?;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub use dust_error::DustError;
|
|||||||
pub use identifier::Identifier;
|
pub use identifier::Identifier;
|
||||||
pub use lexer::{lex, LexError, Lexer};
|
pub use lexer::{lex, LexError, Lexer};
|
||||||
pub use parser::{parse, ParseError, Parser};
|
pub use parser::{parse, ParseError, Parser};
|
||||||
pub use r#type::Type;
|
pub use r#type::{StructType, Type};
|
||||||
pub use token::{Token, TokenKind, TokenOwned};
|
pub use token::{Token, TokenKind, TokenOwned};
|
||||||
pub use value::{Struct, Value, ValueError};
|
pub use value::{Struct, Value, ValueError};
|
||||||
pub use vm::{run, run_with_context, Vm, VmError};
|
pub use vm::{run, run_with_context, Vm, VmError};
|
||||||
|
@ -912,7 +912,7 @@ impl Display for ParseError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{abstract_tree::BinaryOperator, Identifier, StructDefinition, UnaryOperator};
|
use crate::{BinaryOperator, Identifier, StructDefinition, UnaryOperator};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use std::{
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Identifier;
|
use crate::{Identifier, Struct};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct TypeConflict {
|
pub struct TypeConflict {
|
||||||
@ -31,7 +31,6 @@ pub struct TypeConflict {
|
|||||||
pub enum Type {
|
pub enum Type {
|
||||||
Any,
|
Any,
|
||||||
Boolean,
|
Boolean,
|
||||||
Defined(Identifier),
|
|
||||||
Enum {
|
Enum {
|
||||||
name: Identifier,
|
name: Identifier,
|
||||||
type_parameters: Option<Vec<Type>>,
|
type_parameters: Option<Vec<Type>>,
|
||||||
@ -252,7 +251,6 @@ impl Display for Type {
|
|||||||
match self {
|
match self {
|
||||||
Type::Any => write!(f, "any"),
|
Type::Any => write!(f, "any"),
|
||||||
Type::Boolean => write!(f, "bool"),
|
Type::Boolean => write!(f, "bool"),
|
||||||
Type::Defined(identifier) => write!(f, "{identifier}"),
|
|
||||||
Type::Enum { variants, .. } => {
|
Type::Enum { variants, .. } => {
|
||||||
write!(f, "enum ")?;
|
write!(f, "enum ")?;
|
||||||
|
|
||||||
@ -354,6 +352,15 @@ pub enum StructType {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StructType {
|
||||||
|
pub fn instantiate(&self) -> Struct {
|
||||||
|
match self {
|
||||||
|
StructType::Unit { name } => Struct::Unit { name: name.clone() },
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for StructType {
|
impl Display for StructType {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -14,7 +14,7 @@ use serde::{
|
|||||||
Deserialize, Deserializer, Serialize,
|
Deserialize, Deserializer, Serialize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{identifier::Identifier, AbstractSyntaxTree, Context, Type, Vm, VmError};
|
use crate::{identifier::Identifier, AbstractSyntaxTree, Context, StructType, Type, Vm, VmError};
|
||||||
|
|
||||||
/// Dust value representation
|
/// Dust value representation
|
||||||
///
|
///
|
||||||
@ -699,7 +699,11 @@ impl ValueInner {
|
|||||||
}
|
}
|
||||||
ValueInner::Range(_) => Type::Range,
|
ValueInner::Range(_) => Type::Range,
|
||||||
ValueInner::String(_) => Type::String,
|
ValueInner::String(_) => Type::String,
|
||||||
ValueInner::Struct(r#struct) => Type::Defined(r#struct.name().clone()),
|
ValueInner::Struct(r#struct) => match r#struct {
|
||||||
|
Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }),
|
||||||
|
Struct::Tuple { .. } => todo!(),
|
||||||
|
Struct::Fields { .. } => todo!(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
|
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
|
||||||
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition, Type,
|
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition,
|
||||||
UnaryOperator, Value, ValueError,
|
StructType, Type, UnaryOperator, Value, ValueError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Run the source code and return the result.
|
/// Run the source code and return the result.
|
||||||
@ -378,12 +378,20 @@ impl Vm {
|
|||||||
let value_option = self.context.get_value(&identifier);
|
let value_option = self.context.get_value(&identifier);
|
||||||
|
|
||||||
if let Some(value) = value_option {
|
if let Some(value) = value_option {
|
||||||
Ok(Some(value.clone()))
|
return Ok(Some(value.clone()));
|
||||||
} else {
|
|
||||||
Err(VmError::UndefinedVariable {
|
|
||||||
identifier: Node::new(Statement::Identifier(identifier), node.position),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let type_option = self.context.get_type(&identifier);
|
||||||
|
|
||||||
|
println!("{type_option:?}");
|
||||||
|
|
||||||
|
if let Some(Type::Struct(struct_type)) = type_option {
|
||||||
|
return Ok(Some(Value::r#struct(struct_type.instantiate())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(VmError::UndefinedVariable {
|
||||||
|
identifier: Node::new(Statement::Identifier(identifier), node.position),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Statement::If { condition, body } => {
|
Statement::If { condition, body } => {
|
||||||
let condition_position = condition.position;
|
let condition_position = condition.position;
|
||||||
@ -578,9 +586,12 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
Statement::StructDefinition(struct_definition) => {
|
Statement::StructDefinition(struct_definition) => {
|
||||||
let (type_name, r#type) = match struct_definition {
|
let (type_name, r#type) = match struct_definition {
|
||||||
StructDefinition::Unit { name } => {
|
StructDefinition::Unit { name } => (
|
||||||
(name.inner.clone(), Type::Defined(name.inner.clone()))
|
name.inner.clone(),
|
||||||
}
|
Type::Struct(StructType::Unit {
|
||||||
|
name: name.inner.clone(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.context.set_type(type_name, r#type, node.position);
|
self.context.set_type(type_name, r#type, node.position);
|
||||||
@ -797,8 +808,22 @@ impl Display for VmError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::Struct;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn define_and_instantiate_unit_struct() {
|
||||||
|
let input = "struct Foo Foo";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
run(input),
|
||||||
|
Ok(Some(Value::r#struct(Struct::Unit {
|
||||||
|
name: Identifier::new("Foo")
|
||||||
|
})))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn list_index_nested() {
|
fn list_index_nested() {
|
||||||
let input = "[[1, 2], [42, 4], [5, 6]][1][0]";
|
let input = "[[1, 2], [42, 4], [5, 6]][1][0]";
|
||||||
|
Loading…
Reference in New Issue
Block a user