pub mod primitives {
use crate::compiler::value::primitives::Primitive::{Boolean, Integer, MyString};
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
#[derive(Eq, PartialEq, Clone, Debug)]
pub enum Primitive {
Boolean(bool),
Integer(i32),
MyString(String),
}
impl Display for Primitive {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Boolean(false) => Display::fmt("false", f),
Boolean(true) => Display::fmt("true", f),
Integer(value) => Display::fmt(value, f),
MyString(value) => {
if value.len() == 1 && value.chars().next().unwrap().is_whitespace() {
Display::fmt(value, f)
} else {
Display::fmt(&format!("\"{}\"", value), f)
}
}
}
}
}
impl Hash for Primitive {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Boolean(false) => state.write_i8(0),
Boolean(true) => state.write_i8(1),
Integer(value) => state.write_i32(*value),
MyString(value) => value.hash(state),
}
}
}
#[macro_export]
macro_rules! primitive_to_string {
($x:expr) => {
if let MyString(string) = $x {
string
} else {
panic!("Expected string")
}
};
}
}
pub mod parameters {
use crate::compiler::value::values::Value;
use crate::compiler::value::values::Value::PrimitiveValue;
use crate::parameter_is_constant;
use crate::parameter_is_variable;
use crate::parameter_to_constant;
#[derive(Eq, PartialEq, Hash, Debug, Clone)]
pub enum Parameter {
Constant(Value),
Variable(String),
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Variable {
pub index: usize,
pub name: String,
pub initialized: bool,
}
impl Variable {
pub fn new(name: String) -> Variable {
Variable {
index: 0,
name,
initialized: false,
}
}
}
pub fn parameter_vectors_match(lhs: &[Parameter], rhs: &[Parameter]) -> bool {
return lhs.len() == rhs.len()
&& lhs.iter().zip(rhs).all(|(l, r)| match l {
Parameter::Constant(val) => {
parameter_is_constant!(r)
&& val.eq(&PrimitiveValue(parameter_to_constant!(r).clone()))
}
Parameter::Variable(_) => {
parameter_is_variable!(r)
}
});
}
#[macro_export]
macro_rules! parameter_is_constant {
($x:expr) => {{
use $crate::compiler::value::parameters::Parameter::Constant;
if let Constant(_) = $x {
true
} else {
false
}
}};
}
#[macro_export]
macro_rules! parameter_to_constant {
($x:expr) => {{
use $crate::compiler::value::parameters::Parameter::Constant;
use $crate::compiler::value::values::Value::PrimitiveValue;
if let Constant(PrimitiveValue(result)) = $x {
result
} else {
panic!("Expected constant")
}
}};
}
#[macro_export]
macro_rules! parameter_is_variable {
($x:expr) => {{
use $crate::compiler::value::parameters::Parameter::Variable;
if let Variable(_) = $x {
true
} else {
false
}
}};
}
#[macro_export]
macro_rules! parameter_to_variable {
($x:expr) => {{
use $crate::compiler::value::parameters::Parameter::Variable;
if let Variable(result) = $x {
result
} else {
panic!("Expected constant")
}
}};
}
}
pub mod values {
use crate::compiler::value::parameters::{Parameter, Variable};
use crate::compiler::value::primitives::Primitive;
use crate::compiler::value::primitives::Primitive::{Boolean, Integer, MyString};
use crate::compiler::value::values::Value::{
FunctionNameValue, PrimitiveValue, Tuple, TypedValueInstance,
};
use crate::runtime::compiled_script::Bytecode;
use crate::{
value_is_boolean, value_is_integer, value_is_string, value_to_boolean, value_to_integer,
value_to_string,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Value {
PrimitiveValue(Primitive),
FunctionNameValue(String),
Tuple(Vec<Value>),
TypedValueInstance(Rc<RefCell<TypedValue>>),
}
#[derive(Eq, PartialEq, Debug, Clone, Default)]
pub struct TypedValue {
pub(crate) name: String,
pub(crate) fields: HashMap<String, Primitive>,
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PrimitiveValue(p) => std::fmt::Display::fmt(p, f),
FunctionNameValue(name) => Display::fmt(format!("Fun({})", name).as_str(), f),
Tuple(vec) => {
let len = vec.len();
Display::fmt("(", f)?;
for (count, value) in vec.iter().enumerate() {
Display::fmt(&format!("{}", value), f)?;
if count < len - 1 {
Display::fmt(", ", f)?;
}
}
Display::fmt(")", f)?;
Ok(())
}
TypedValueInstance(value) => {
write!(f, "{}[", value.borrow().name)?;
for (field_name, value) in &value.borrow().fields {
write!(f, "{}:{},", field_name, value)?;
}
write!(f, "]")?;
Ok(())
}
}
}
}
impl Primitive {
pub(crate) fn equals(&self, value: &Value) -> bool {
match self {
Boolean(this) => value_is_boolean!(value) && value_to_boolean!(value) == this,
Integer(this) => value_is_integer!(value) && value_to_integer!(value) == this,
MyString(this) => value_is_string!(value) && value_to_string!(value) == this,
}
}
}
#[macro_export]
macro_rules! integer_to_value {
($x:expr) => {{
use $crate::compiler::value::primitives::Primitive::Integer;
use $crate::compiler::value::values::Value::PrimitiveValue;
PrimitiveValue(Integer($x))
}};
}
#[macro_export]
macro_rules! value_to_integer {
($x:expr) => {{
if let PrimitiveValue(Integer(result)) = $x {
result
} else {
panic!("Expected integer, got {:?}", $x)
}
}};
}
#[macro_export]
macro_rules! value_is_integer {
($x:expr) => {{
if let PrimitiveValue(Integer(_)) = $x {
true
} else {
false
}
}};
}
#[macro_export]
macro_rules! boolean_to_value {
($x:expr) => {{
use $crate::compiler::value::primitives::Primitive::Boolean;
use $crate::compiler::value::values::Value::PrimitiveValue;
PrimitiveValue(Boolean($x))
}};
}
#[macro_export]
macro_rules! value_is_boolean {
($x:expr) => {{
if let PrimitiveValue(Boolean(_)) = $x {
true
} else {
false
}
}};
}
#[macro_export]
macro_rules! value_to_boolean {
($x:expr) => {{
use $crate::compiler::value::primitives::Primitive::Boolean;
use $crate::compiler::value::values::Value::PrimitiveValue;
if let PrimitiveValue(Boolean(result)) = $x {
result
} else {
panic!("Expected boolean")
}
}};
}
#[macro_export]
macro_rules! string_to_value {
($x:expr) => {{
use $crate::compiler::value::primitives::Primitive::MyString;
use $crate::compiler::value::values::Value::PrimitiveValue;
PrimitiveValue(MyString($x))
}};
}
#[macro_export]
macro_rules! value_to_string {
($x:expr) => {{
use $crate::compiler::value::primitives::Primitive::MyString;
use $crate::compiler::value::values::Value::PrimitiveValue;
if let PrimitiveValue(MyString(result)) = $x {
result
} else {
panic!("Expected string")
}
}};
}
#[macro_export]
macro_rules! value_is_string {
($x:expr) => {{
if let PrimitiveValue(MyString(_)) = $x {
true
} else {
false
}
}};
}
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
PrimitiveValue(value) => value.hash(state),
FunctionNameValue(value) => value.hash(state),
Tuple(value) => value.hash(state),
TypedValueInstance(value) => {
value.borrow().name.hash(state);
for (key, value) in &value.borrow().fields {
key.hash(state);
value.hash(state);
}
}
}
}
}
#[macro_export]
macro_rules! vector_to_value {
($x:expr) => {{
use $crate::compiler::value::values::Value::Tuple;
Tuple($x)
}};
}
#[macro_export]
macro_rules! value_to_tuple {
($x:expr) => {{
use $crate::compiler::value::values::Value::Tuple;
if let Tuple(tuple_object) = $x {
tuple_object
} else {
panic!("Expected tuple")
}
}};
}
#[macro_export]
macro_rules! value_is_tuple {
($x:expr) => {{
use $crate::compiler::value::values::Value::Tuple;
if let Tuple(_) = $x {
true
} else {
false
}
}};
}
#[macro_export]
macro_rules! empty_tuple_value {
() => {{
use $crate::compiler::value::values::Value;
use $crate::vector_to_value;
vector_to_value!(vec![] as Vec<Value>)
}};
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FunctionDefinitionObject {
pub formal_arguments: Vec<Parameter>,
pub constants: Vec<Value>,
pub variables: Vec<Variable>,
pub bytecode: Bytecode,
pub name: String,
}
impl FunctionDefinitionObject {
pub fn new(name: String) -> FunctionDefinitionObject {
FunctionDefinitionObject {
formal_arguments: Vec::new(),
constants: Vec::new(),
variables: Vec::new(),
bytecode: Bytecode::new(),
name,
}
}
}
impl Default for FunctionDefinitionObject {
fn default() -> Self {
Self::new("".to_string())
}
}
impl Display for FunctionDefinitionObject {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(
&format!(
"FunctionDefinitionObject: {}({:?})",
self.name, self.formal_arguments
),
f,
)
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FunctionValuesObject {
pub values: HashMap<Vec<Value>, Value>,
}
impl FunctionValuesObject {
pub(crate) fn new() -> Self {
FunctionValuesObject {
values: HashMap::new(),
}
}
pub(crate) fn set_value(&mut self, domain_value: Vec<Value>, codomain_value: Value) {
self.values.insert(domain_value, codomain_value);
}
pub fn get_value(&self, domain_value: &Vec<Value>) -> Option<Value> {
self.values.get(domain_value).cloned()
}
}
impl Hash for FunctionValuesObject {
fn hash<H: Hasher>(&self, _state: &mut H) {
todo!()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct TypeDefinition {
pub name: String, pub fields: Vec<(String, String)>, }
}