Rewrote value storage and implemented class instantiation
* Probably not the last time. * Object-like things (functions, classes, etc...) are stored as ref-counted cells. * Separate data structure for native functions. * with_callable() method on value to run specific code on objects that are callable * Instance type added. * Instance construction implemented
This commit is contained in:
parent
85e9c7db38
commit
d8dba3ac5f
8 changed files with 274 additions and 100 deletions
src/interpreter
|
@ -1,6 +1,11 @@
|
|||
use std::{cell::RefCell, fmt::Display, rc::Rc};
|
||||
|
||||
use super::{Callable, class::Class};
|
||||
use super::{
|
||||
class::{Class, ClassRef, Instance},
|
||||
functions::Function,
|
||||
native_fn::NativeFunction,
|
||||
Callable,
|
||||
};
|
||||
|
||||
/// A value being handled by the interpreter.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -9,8 +14,50 @@ pub enum Value {
|
|||
Boolean(bool),
|
||||
String(String),
|
||||
Number(f64),
|
||||
Callable(Rc<RefCell<dyn Callable>>),
|
||||
Class(Class),
|
||||
Object(Rc<RefCell<Object>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Object {
|
||||
NativeFunction(NativeFunction),
|
||||
LoxFunction(Function),
|
||||
Class(ClassRef),
|
||||
Instance(Instance),
|
||||
}
|
||||
|
||||
/* -------------------- *
|
||||
* Value implementation *
|
||||
* -------------------- */
|
||||
|
||||
impl Value {
|
||||
/// Check whether a value is truthy or not.
|
||||
pub fn is_truthy(&self) -> bool {
|
||||
match self {
|
||||
Self::Nil => false,
|
||||
Self::Boolean(b) => *b,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Run some code using the callable object wrapped inside a value.
|
||||
/// If the value is not callable, an error function will be called
|
||||
/// instead.
|
||||
pub fn with_callable<Fok, Ferr, Rt>(&self, fok: Fok, ferr: Ferr) -> Rt
|
||||
where
|
||||
Fok: FnOnce(&dyn Callable) -> Rt,
|
||||
Ferr: FnOnce() -> Rt,
|
||||
{
|
||||
let obj = match self {
|
||||
Value::Object(obj_ref) => obj_ref.borrow(),
|
||||
_ => return ferr(),
|
||||
};
|
||||
match &*obj {
|
||||
Object::NativeFunction(func) => fok(func),
|
||||
Object::LoxFunction(func) => fok(func),
|
||||
Object::Class(class) => fok(class),
|
||||
Object::Instance(_) => ferr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Value {
|
||||
|
@ -32,19 +79,52 @@ impl Display for Value {
|
|||
Value::Boolean(b) => b.fmt(f),
|
||||
Value::String(s) => s.fmt(f),
|
||||
Value::Number(n) => n.fmt(f),
|
||||
Value::Callable(c) => f.write_str(&c.borrow().to_string()),
|
||||
Value::Class(c) => f.write_str(&c.to_string()),
|
||||
Value::Object(obj) => obj.borrow().fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
/// Check whether a value is truthy or not.
|
||||
pub fn is_truthy(&self) -> bool {
|
||||
impl From<NativeFunction> for Value {
|
||||
fn from(value: NativeFunction) -> Self {
|
||||
Value::Object(Rc::new(RefCell::new(Object::NativeFunction(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Function> for Value {
|
||||
fn from(value: Function) -> Self {
|
||||
Value::Object(Rc::new(RefCell::new(Object::LoxFunction(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Class> for Value {
|
||||
fn from(value: Class) -> Self {
|
||||
Value::from(Rc::new(RefCell::new(value)))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClassRef> for Value {
|
||||
fn from(value: ClassRef) -> Self {
|
||||
Value::Object(Rc::new(RefCell::new(Object::Class(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Instance> for Value {
|
||||
fn from(value: Instance) -> Self {
|
||||
Value::Object(Rc::new(RefCell::new(Object::Instance(value))))
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------- *
|
||||
* Object implementation *
|
||||
* --------------------- */
|
||||
|
||||
impl Display for Object {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Nil => false,
|
||||
Self::Boolean(b) => *b,
|
||||
_ => true,
|
||||
Object::NativeFunction(func) => func.fmt(f),
|
||||
Object::LoxFunction(func) => func.fmt(f),
|
||||
Object::Class(cls) => cls.borrow().fmt(f),
|
||||
Object::Instance(inst) => inst.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue