1
0
dust/dust-lang/src/value.rs

557 lines
17 KiB
Rust
Raw Normal View History

2024-02-25 18:49:26 +00:00
use std::{
2024-02-25 19:26:22 +00:00
cmp::Ordering,
2024-02-28 23:36:47 +00:00
collections::BTreeMap,
2024-03-06 20:36:58 +00:00
fmt::{self, Display, Formatter},
2024-03-17 21:39:39 +00:00
io::stdin,
2024-02-25 18:49:26 +00:00
ops::Range,
sync::{Arc, OnceLock},
2024-03-20 21:38:40 +00:00
thread,
time::Duration,
2024-02-25 18:49:26 +00:00
};
2024-03-18 12:15:30 +00:00
use rand::{thread_rng, Rng};
2024-03-08 03:20:59 +00:00
use stanza::{
renderer::{console::Console, Renderer},
style::{HAlign, MinWidth, Styles},
table::Table,
};
2024-03-06 22:32:31 +00:00
use crate::{
abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPosition},
2024-03-09 03:34:17 +00:00
context::Context,
2024-03-18 12:15:30 +00:00
error::{RuntimeError, ValidationError},
2024-03-06 22:32:31 +00:00
};
2024-02-25 18:49:26 +00:00
#[derive(Clone, Debug, PartialEq)]
pub struct Value(Arc<ValueInner>);
impl Value {
pub fn inner(&self) -> &Arc<ValueInner> {
&self.0
}
pub fn boolean(boolean: bool) -> Self {
Value(Arc::new(ValueInner::Boolean(boolean)))
}
pub fn float(float: f64) -> Self {
Value(Arc::new(ValueInner::Float(float)))
}
pub fn integer(integer: i64) -> Self {
Value(Arc::new(ValueInner::Integer(integer)))
}
2024-02-26 21:27:01 +00:00
pub fn list(list: Vec<Value>) -> Self {
2024-02-25 18:49:26 +00:00
Value(Arc::new(ValueInner::List(list)))
}
2024-02-28 23:36:47 +00:00
pub fn map(map: BTreeMap<Identifier, Value>) -> Self {
Value(Arc::new(ValueInner::Map(map)))
}
2024-02-25 18:49:26 +00:00
pub fn range(range: Range<i64>) -> Self {
Value(Arc::new(ValueInner::Range(range)))
}
pub fn string(string: String) -> Self {
Value(Arc::new(ValueInner::String(string)))
2024-02-25 18:49:26 +00:00
}
2024-03-17 05:26:05 +00:00
pub fn function(
2024-03-17 11:31:45 +00:00
parameters: Vec<(Identifier, WithPosition<Type>)>,
return_type: WithPosition<Type>,
body: WithPosition<Block>,
2024-03-17 05:26:05 +00:00
) -> Self {
2024-03-09 03:34:17 +00:00
Value(Arc::new(ValueInner::Function(Function::Parsed(
ParsedFunction {
parameters,
return_type,
body,
},
))))
2024-03-08 21:14:47 +00:00
}
2024-03-19 23:16:33 +00:00
pub fn structure(name: Identifier, fields: Vec<(Identifier, Value)>) -> Self {
Value(Arc::new(ValueInner::Structure { name, fields }))
}
2024-03-09 11:55:19 +00:00
pub fn built_in_function(function: BuiltInFunction) -> Self {
Value(Arc::new(ValueInner::Function(Function::BuiltIn(function))))
}
2024-03-19 22:31:52 +00:00
pub fn r#type(&self, context: &Context) -> Result<Type, ValidationError> {
2024-03-20 12:36:18 +00:00
self.0.r#type(context)
2024-03-06 22:32:31 +00:00
}
2024-03-17 20:59:52 +00:00
pub fn as_boolean(&self) -> Option<bool> {
2024-02-25 19:26:22 +00:00
if let ValueInner::Boolean(boolean) = self.0.as_ref() {
2024-03-17 20:59:52 +00:00
Some(*boolean)
} else {
None
2024-03-09 13:10:54 +00:00
}
}
2024-03-07 17:29:07 +00:00
pub fn as_list(&self) -> Option<&Vec<Value>> {
if let ValueInner::List(list) = self.inner().as_ref() {
Some(list)
} else {
None
}
}
pub fn as_integer(&self) -> Option<i64> {
if let ValueInner::Integer(integer) = self.inner().as_ref() {
Some(*integer)
} else {
None
}
}
2024-03-06 20:36:58 +00:00
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
2024-03-08 03:20:59 +00:00
fn create_table() -> Table {
Table::with_styles(Styles::default().with(HAlign::Centred).with(MinWidth(3)))
}
2024-03-06 20:36:58 +00:00
match self.inner().as_ref() {
2024-03-08 21:14:47 +00:00
ValueInner::Boolean(boolean) => write!(f, "{boolean}"),
ValueInner::Float(float) => write!(f, "{float}"),
ValueInner::Integer(integer) => write!(f, "{integer}"),
ValueInner::List(list) => {
2024-03-08 03:20:59 +00:00
let mut table = create_table();
for value in list {
table = table.with_row([value.to_string()]);
}
write!(f, "{}", Console::default().render(&table))
}
2024-03-08 21:14:47 +00:00
ValueInner::Map(map) => {
2024-03-08 03:20:59 +00:00
let mut table = create_table();
2024-03-07 21:19:24 +00:00
for (identifier, value) in map {
2024-03-08 03:20:59 +00:00
table = table.with_row([identifier.as_str(), &value.to_string()]);
2024-03-07 21:19:24 +00:00
}
2024-03-08 03:20:59 +00:00
write!(f, "{}", Console::default().render(&table))
2024-03-07 21:19:24 +00:00
}
2024-03-08 21:14:47 +00:00
ValueInner::Range(_) => todo!(),
ValueInner::String(string) => write!(f, "{string}"),
2024-03-09 03:34:17 +00:00
ValueInner::Function(Function::Parsed(ParsedFunction {
2024-03-08 21:14:47 +00:00
parameters,
return_type,
body,
2024-03-09 03:34:17 +00:00
})) => {
2024-03-08 21:14:47 +00:00
write!(f, "(")?;
for (identifier, r#type) in parameters {
2024-03-17 10:26:12 +00:00
write!(f, "{identifier}: {}", r#type.node)?;
2024-03-08 21:14:47 +00:00
}
2024-03-08 03:20:59 +00:00
2024-03-17 05:26:05 +00:00
write!(f, "): {} {:?}", return_type.node, body.node)
2024-03-08 21:14:47 +00:00
}
2024-03-09 03:34:17 +00:00
ValueInner::Function(Function::BuiltIn(built_in_function)) => {
write!(f, "{built_in_function}")
}
2024-03-19 23:33:02 +00:00
ValueInner::Structure { name, fields } => {
let mut table = create_table();
for (identifier, value) in fields {
table = table.with_row([identifier.as_str(), &value.to_string()]);
}
write!(f, "{name}\n{}", Console::default().render(&table))
}
2024-03-06 20:36:58 +00:00
}
}
2024-02-25 19:26:22 +00:00
}
impl Eq for Value {}
impl PartialOrd for Value {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Value {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.as_ref().cmp(other.0.as_ref())
}
2024-02-25 18:49:26 +00:00
}
#[derive(Clone, Debug, PartialEq)]
pub enum ValueInner {
Boolean(bool),
Float(f64),
2024-03-08 21:14:47 +00:00
Function(Function),
2024-02-25 18:49:26 +00:00
Integer(i64),
2024-02-26 21:27:01 +00:00
List(Vec<Value>),
2024-02-28 23:36:47 +00:00
Map(BTreeMap<Identifier, Value>),
2024-02-25 18:49:26 +00:00
Range(Range<i64>),
String(String),
2024-03-19 22:31:52 +00:00
Structure {
name: Identifier,
2024-03-19 23:16:33 +00:00
fields: Vec<(Identifier, Value)>,
2024-03-19 22:31:52 +00:00
},
2024-02-25 18:49:26 +00:00
}
2024-03-20 12:36:18 +00:00
impl ValueInner {
pub fn r#type(&self, context: &Context) -> Result<Type, ValidationError> {
let r#type = match self {
ValueInner::Boolean(_) => Type::Boolean,
ValueInner::Float(_) => Type::Float,
ValueInner::Integer(_) => Type::Integer,
ValueInner::List(values) => {
let mut types = Vec::with_capacity(values.len());
for value in values {
types.push(value.r#type(context)?);
}
Type::ListExact(types)
}
ValueInner::Map(_) => Type::Map,
ValueInner::Range(_) => Type::Range,
ValueInner::String(_) => Type::String,
ValueInner::Function(function) => match function {
Function::Parsed(parsed_function) => Type::Function {
parameter_types: parsed_function
.parameters
.iter()
.map(|(_, r#type)| r#type.node.clone())
.collect(),
return_type: Box::new(parsed_function.return_type.node.clone()),
},
Function::BuiltIn(built_in_function) => built_in_function.r#type(),
},
ValueInner::Structure { name, .. } => {
if let Some(r#type) = context.get_type(name)? {
r#type
} else {
return Err(ValidationError::TypeNotFound(name.clone()));
}
}
};
Ok(r#type)
}
}
2024-02-25 19:26:22 +00:00
impl Eq for ValueInner {}
impl PartialOrd for ValueInner {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ValueInner {
fn cmp(&self, other: &Self) -> Ordering {
use ValueInner::*;
match (self, other) {
(Boolean(left), Boolean(right)) => left.cmp(right),
(Boolean(_), _) => Ordering::Greater,
(Float(left), Float(right)) => left.total_cmp(right),
(Float(_), _) => Ordering::Greater,
(Integer(left), Integer(right)) => left.cmp(right),
(Integer(_), _) => Ordering::Greater,
(List(left), List(right)) => left.cmp(right),
(List(_), _) => Ordering::Greater,
2024-02-28 23:36:47 +00:00
(Map(left), Map(right)) => left.cmp(right),
(Map(_), _) => Ordering::Greater,
2024-02-25 19:26:22 +00:00
(Range(left), Range(right)) => {
let start_cmp = left.start.cmp(&right.start);
if start_cmp.is_eq() {
left.end.cmp(&right.end)
} else {
start_cmp
}
}
(Range(_), _) => Ordering::Greater,
(String(left), String(right)) => left.cmp(right),
(String(_), _) => Ordering::Greater,
2024-03-08 21:14:47 +00:00
(Function(left), Function(right)) => left.cmp(right),
(Function(_), _) => Ordering::Greater,
2024-03-19 22:31:52 +00:00
(
Structure {
name: left_name,
fields: left_fields,
},
Structure {
name: right_name,
fields: right_fields,
},
) => {
let name_cmp = left_name.cmp(right_name);
if name_cmp.is_eq() {
left_fields.cmp(right_fields)
} else {
name_cmp
}
}
(Structure { .. }, _) => Ordering::Greater,
2024-02-25 19:26:22 +00:00
}
}
}
2024-03-08 21:14:47 +00:00
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
2024-03-09 03:34:17 +00:00
pub enum Function {
Parsed(ParsedFunction),
BuiltIn(BuiltInFunction),
}
2024-03-09 13:10:54 +00:00
impl Function {
2024-03-17 05:26:05 +00:00
pub fn call(self, arguments: Vec<Value>, context: Context) -> Result<Action, RuntimeError> {
2024-03-09 13:10:54 +00:00
let action = match self {
Function::Parsed(ParsedFunction {
parameters, body, ..
}) => {
for ((identifier, _), value) in parameters.into_iter().zip(arguments.into_iter()) {
context.set_value(identifier.clone(), value)?;
}
2024-03-17 05:26:05 +00:00
body.node.run(&context)?
2024-03-09 13:10:54 +00:00
}
Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?,
};
Ok(action)
}
}
2024-03-09 03:34:17 +00:00
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ParsedFunction {
2024-03-17 11:31:45 +00:00
parameters: Vec<(Identifier, WithPosition<Type>)>,
return_type: WithPosition<Type>,
body: WithPosition<Block>,
2024-03-08 21:14:47 +00:00
}
2024-03-09 03:34:17 +00:00
2024-03-18 12:15:30 +00:00
static INT_PARSE: OnceLock<Value> = OnceLock::new();
static INT_RANDOM_RANGE: OnceLock<Value> = OnceLock::new();
static READ_LINE: OnceLock<Value> = OnceLock::new();
static WRITE_LINE: OnceLock<Value> = OnceLock::new();
2024-03-20 21:38:40 +00:00
static SLEEP: OnceLock<Value> = OnceLock::new();
2024-03-18 12:15:30 +00:00
2024-03-20 21:38:40 +00:00
pub const BUILT_IN_FUNCTIONS: [BuiltInFunction; 5] = [
2024-03-18 12:15:30 +00:00
BuiltInFunction::IntParse,
BuiltInFunction::IntRandomRange,
BuiltInFunction::ReadLine,
BuiltInFunction::WriteLine,
2024-03-20 21:38:40 +00:00
BuiltInFunction::Sleep,
2024-03-18 12:15:30 +00:00
];
2024-03-09 03:34:17 +00:00
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum BuiltInFunction {
2024-03-18 12:15:30 +00:00
IntParse,
IntRandomRange,
2024-03-17 21:39:39 +00:00
ReadLine,
2024-03-18 12:15:30 +00:00
WriteLine,
2024-03-20 21:38:40 +00:00
Sleep,
2024-03-09 03:34:17 +00:00
}
impl BuiltInFunction {
2024-03-18 12:15:30 +00:00
pub fn name(&self) -> &'static str {
match self {
BuiltInFunction::IntParse => "parse",
BuiltInFunction::IntRandomRange => "random_range",
BuiltInFunction::ReadLine => "read_line",
BuiltInFunction::WriteLine => "write_line",
2024-03-20 21:38:40 +00:00
BuiltInFunction::Sleep => "sleep",
2024-03-18 12:15:30 +00:00
}
2024-03-09 11:55:19 +00:00
}
2024-03-18 12:15:30 +00:00
pub fn value(&self) -> Value {
match self {
BuiltInFunction::IntParse => {
INT_PARSE.get_or_init(|| Value::built_in_function(BuiltInFunction::IntParse))
}
BuiltInFunction::IntRandomRange => INT_RANDOM_RANGE
.get_or_init(|| Value::built_in_function(BuiltInFunction::IntRandomRange)),
BuiltInFunction::ReadLine => {
READ_LINE.get_or_init(|| Value::built_in_function(BuiltInFunction::ReadLine))
}
BuiltInFunction::WriteLine => {
WRITE_LINE.get_or_init(|| Value::built_in_function(BuiltInFunction::WriteLine))
}
2024-03-20 21:38:40 +00:00
BuiltInFunction::Sleep => {
SLEEP.get_or_init(|| Value::built_in_function(BuiltInFunction::Sleep))
}
2024-03-18 12:15:30 +00:00
}
.clone()
2024-03-17 21:39:39 +00:00
}
2024-03-09 11:55:19 +00:00
pub fn r#type(&self) -> Type {
2024-03-09 03:34:17 +00:00
match self {
2024-03-18 12:15:30 +00:00
BuiltInFunction::IntParse => Type::Function {
parameter_types: vec![Type::String],
return_type: Box::new(Type::Integer),
},
BuiltInFunction::IntRandomRange => Type::Function {
parameter_types: vec![Type::Range],
return_type: Box::new(Type::Integer),
2024-03-09 03:34:17 +00:00
},
2024-03-17 21:39:39 +00:00
BuiltInFunction::ReadLine => Type::Function {
parameter_types: Vec::with_capacity(0),
return_type: Box::new(Type::String),
},
2024-03-18 12:15:30 +00:00
BuiltInFunction::WriteLine => Type::Function {
parameter_types: vec![Type::Any],
return_type: Box::new(Type::None),
},
2024-03-20 21:38:40 +00:00
BuiltInFunction::Sleep => Type::Function {
parameter_types: vec![Type::Integer],
return_type: Box::new(Type::None),
},
2024-03-09 03:34:17 +00:00
}
}
2024-03-19 22:31:52 +00:00
pub fn call(&self, arguments: Vec<Value>, context: &Context) -> Result<Action, RuntimeError> {
2024-03-09 03:34:17 +00:00
match self {
2024-03-18 12:15:30 +00:00
BuiltInFunction::IntParse => {
let string = arguments.get(0).unwrap();
2024-03-09 03:34:17 +00:00
2024-03-20 12:36:18 +00:00
if let ValueInner::String(_string) = string.inner().as_ref() {
2024-03-18 12:15:30 +00:00
// let integer = string.parse();
todo!()
// Ok(Action::Return(Value::integer(integer)))
} else {
2024-03-19 22:31:52 +00:00
let mut actual = Vec::with_capacity(arguments.len());
for value in arguments {
let r#type = value.r#type(context)?;
actual.push(r#type);
}
2024-03-18 12:15:30 +00:00
Err(RuntimeError::ValidationFailure(
ValidationError::WrongArguments {
expected: vec![Type::String],
2024-03-19 22:31:52 +00:00
actual,
2024-03-18 12:15:30 +00:00
},
))
}
}
BuiltInFunction::IntRandomRange => {
let range = arguments.get(0).unwrap();
if let ValueInner::Range(range) = range.inner().as_ref() {
let random = thread_rng().gen_range(range.clone());
Ok(Action::Return(Value::integer(random)))
} else {
panic!("Built-in function cannot have a non-function type.")
}
2024-03-09 03:34:17 +00:00
}
2024-03-17 21:39:39 +00:00
BuiltInFunction::ReadLine => {
let mut input = String::new();
stdin().read_line(&mut input)?;
Ok(Action::Return(Value::string(input)))
}
2024-03-18 12:15:30 +00:00
BuiltInFunction::WriteLine => {
println!("{}", arguments[0]);
2024-03-20 21:38:40 +00:00
Ok(Action::None)
}
BuiltInFunction::Sleep => {
if let ValueInner::Integer(milliseconds) = arguments[0].inner().as_ref() {
thread::sleep(Duration::from_millis(*milliseconds as u64));
}
2024-03-18 12:15:30 +00:00
Ok(Action::None)
}
2024-03-09 03:34:17 +00:00
}
}
}
impl Display for BuiltInFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
2024-03-18 12:15:30 +00:00
BuiltInFunction::IntParse => write!(f, "(input : int) : str {{ *MAGIC* }}"),
BuiltInFunction::IntRandomRange => write!(f, "(input: range) : int {{ *MAGIC* }}"),
2024-03-17 22:03:43 +00:00
BuiltInFunction::ReadLine => write!(f, "() : str {{ *MAGIC* }}"),
2024-03-18 12:15:30 +00:00
BuiltInFunction::WriteLine => write!(f, "(to_output : any) : none {{ *MAGIC* }}"),
2024-03-20 21:38:40 +00:00
BuiltInFunction::Sleep => write!(f, "(milliseconds : int) : none {{ *MAGIC* }}"),
2024-03-09 03:34:17 +00:00
}
}
}
2024-03-17 21:39:39 +00:00
2024-03-18 12:15:30 +00:00
static INT: OnceLock<Value> = OnceLock::new();
2024-03-17 22:03:43 +00:00
static IO: OnceLock<Value> = OnceLock::new();
2024-03-20 21:38:40 +00:00
static THREAD: OnceLock<Value> = OnceLock::new();
2024-03-17 22:03:43 +00:00
2024-03-20 21:38:40 +00:00
pub const BUILT_IN_MODULES: [BuiltInModule; 3] =
[BuiltInModule::Int, BuiltInModule::Io, BuiltInModule::Thread];
2024-03-18 12:15:30 +00:00
pub enum BuiltInModule {
2024-03-20 21:38:40 +00:00
Int,
2024-03-17 21:39:39 +00:00
Io,
2024-03-20 21:38:40 +00:00
Thread,
2024-03-17 21:39:39 +00:00
}
2024-03-18 12:15:30 +00:00
impl BuiltInModule {
pub fn name(&self) -> &'static str {
match self {
2024-03-20 21:38:40 +00:00
BuiltInModule::Int => "int",
2024-03-18 12:15:30 +00:00
BuiltInModule::Io => "io",
2024-03-20 21:38:40 +00:00
BuiltInModule::Thread => "thread",
2024-03-18 12:15:30 +00:00
}
}
2024-03-17 22:03:43 +00:00
pub fn value(self) -> Value {
match self {
2024-03-20 21:38:40 +00:00
BuiltInModule::Int => {
2024-03-17 22:03:43 +00:00
let mut properties = BTreeMap::new();
2024-03-17 21:39:39 +00:00
2024-03-18 12:15:30 +00:00
properties.insert(
Identifier::new("parse"),
Value::built_in_function(BuiltInFunction::IntParse),
);
properties.insert(
Identifier::new("random_range"),
Value::built_in_function(BuiltInFunction::IntRandomRange),
);
INT.get_or_init(|| Value::map(properties)).clone()
}
BuiltInModule::Io => {
let mut properties = BTreeMap::new();
properties.insert(
Identifier::new("read_line"),
Value::built_in_function(BuiltInFunction::ReadLine),
);
properties.insert(
Identifier::new("write_line"),
Value::built_in_function(BuiltInFunction::WriteLine),
);
2024-03-17 21:39:39 +00:00
2024-03-17 22:03:43 +00:00
IO.get_or_init(|| Value::map(properties)).clone()
}
2024-03-20 21:38:40 +00:00
BuiltInModule::Thread => {
let mut properties = BTreeMap::new();
properties.insert(
Identifier::new("sleep"),
Value::built_in_function(BuiltInFunction::Sleep),
);
THREAD.get_or_init(|| Value::map(properties)).clone()
}
2024-03-17 22:03:43 +00:00
}
}
2024-03-17 21:39:39 +00:00
2024-03-17 22:03:43 +00:00
pub fn r#type(self) -> Type {
2024-03-18 12:15:30 +00:00
Type::Map
2024-03-17 21:39:39 +00:00
}
}