some simple bytecodes!

This commit is contained in:
Scott Richmond 2024-12-15 17:54:40 -05:00
parent 86aea78c21
commit eff2ed90d5
5 changed files with 224 additions and 224 deletions

View File

@ -1,47 +0,0 @@
use crate::compiler::Chunk;
use crate::parser::Ast;
use crate::spans::Spanned;
use imbl::{HashMap, Vector};
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone, Debug, PartialEq)]
pub struct LBox {
pub name: usize,
pub cell: RefCell<Value>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LFn {
pub name: &'static str,
pub body: Vec<Spanned<Ast>>,
pub doc: Option<&'static str>,
pub enclosing: Vec<(usize, Value)>,
pub has_run: bool,
pub input: &'static str,
pub src: &'static str,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Nil,
Boolean(bool),
Keyword(usize), // use an idx, rather than a raw index
Interned(usize),
FnDecl(usize),
String(Rc<String>),
Number(f64),
List(Box<Vector<Value>>),
Dict(Box<HashMap<&'static str, Value>>),
Box(Rc<LBox>),
Fn(Rc<RefCell<LFn>>),
}
impl Value {
fn show(&self, ctx: &Chunk) -> String {
use Value::*;
match &self {
Nil => format!("nil"),
}
}
}

193
src/old_value.rs Normal file
View File

@ -0,0 +1,193 @@
use crate::base::*;
use crate::parser::*;
use crate::spans::*;
use imbl::*;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use struct_scalpel::Dissectible;
#[derive(Clone, Debug)]
pub struct Fn<'src> {
pub name: String,
pub body: &'src Vec<Spanned<Ast>>,
pub doc: Option<String>,
pub enclosing: Vec<(String, Value<'src>)>,
pub has_run: bool,
pub input: &'static str,
pub src: &'static str,
}
#[derive(Debug, Dissectible)]
pub enum Value<'src> {
Nil,
Placeholder,
Boolean(bool),
Number(f64),
Keyword(&'static str),
InternedString(&'static str),
AllocatedString(Rc<String>),
// on the heap for now
Tuple(Rc<Vec<Self>>),
Args(Rc<Vec<Self>>),
List(Vector<Self>),
Dict(HashMap<&'static str, Self>),
Box(&'static str, Rc<RefCell<Self>>),
Fn(Rc<RefCell<Fn<'src>>>),
FnDecl(&'static str),
Base(BaseFn<'src>),
Recur(Vec<Self>),
// Set(HashSet<Self>),
// Sets are hard
// Sets require Eq
// Eq is not implemented on f64, because NaNs
// We could use ordered_float::NotNan
// Let's defer that
// We're not really using sets in Ludus
// Other things we're not implementing yet:
// pkgs, nses, tests
}
impl<'src> Clone for Value<'src> {
fn clone(&self) -> Value<'src> {
match self {
Value::Nil => Value::Nil,
Value::Boolean(b) => Value::Boolean(*b),
Value::InternedString(s) => Value::InternedString(s),
Value::AllocatedString(s) => Value::AllocatedString(s.clone()),
Value::Keyword(s) => Value::Keyword(s),
Value::Number(n) => Value::Number(*n),
Value::Tuple(t) => Value::Tuple(t.clone()),
Value::Args(a) => Value::Args(a.clone()),
Value::Fn(f) => Value::Fn(f.clone()),
Value::FnDecl(name) => Value::FnDecl(name),
Value::List(l) => Value::List(l.clone()),
Value::Dict(d) => Value::Dict(d.clone()),
Value::Box(name, b) => Value::Box(name, b.clone()),
Value::Placeholder => Value::Placeholder,
Value::Base(b) => Value::Base(b.clone()),
Value::Recur(..) => unreachable!(),
}
}
}
impl fmt::Display for Value<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Nil => write!(f, "nil"),
Value::Boolean(b) => write!(f, "{b}"),
Value::Number(n) => write!(f, "{n}"),
Value::Keyword(k) => write!(f, ":{k}"),
Value::InternedString(s) => write!(f, "\"{s}\""),
Value::AllocatedString(s) => write!(f, "\"{s}\""),
Value::Fn(fun) => write!(f, "fn {}", fun.borrow().name),
Value::FnDecl(name) => write!(f, "fn {name}"),
Value::Tuple(t) | Value::Args(t) => write!(
f,
"({})",
t.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::List(l) => write!(
f,
"[{}]",
l.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::Dict(d) => write!(
f,
"#{{{}}}",
d.iter()
.map(|(k, v)| format!(":{k} {v}"))
.collect::<Vec<_>>()
.join(", ")
),
Value::Box(name, value) => {
write!(
f,
"box {}: [{}]",
name,
&value.try_borrow().unwrap().to_string()
)
}
Value::Placeholder => write!(f, "_"),
Value::Base(..) => unreachable!(),
Value::Recur(..) => unreachable!(),
}
}
}
impl Value<'_> {
pub fn bool(&self) -> bool {
!matches!(self, Value::Nil | Value::Boolean(false))
}
}
impl<'src> PartialEq for Value<'src> {
fn eq(&self, other: &Value<'src>) -> bool {
match (self, other) {
// value equality types
(Value::Nil, Value::Nil) => true,
(Value::Boolean(x), Value::Boolean(y)) => x == y,
(Value::Number(x), Value::Number(y)) => x == y,
(Value::InternedString(x), Value::InternedString(y)) => x == y,
(Value::AllocatedString(x), Value::AllocatedString(y)) => x == y,
(Value::InternedString(x), Value::AllocatedString(y)) => *x == **y,
(Value::AllocatedString(x), Value::InternedString(y)) => **x == *y,
(Value::Keyword(x), Value::Keyword(y)) => x == y,
(Value::Tuple(x), Value::Tuple(y)) => x == y,
(Value::List(x), Value::List(y)) => x == y,
(Value::Dict(x), Value::Dict(y)) => x == y,
// reference equality types
(Value::Fn(x), Value::Fn(y)) => {
Rc::<RefCell<Fn<'_>>>::as_ptr(x) == Rc::<RefCell<Fn<'_>>>::as_ptr(y)
}
(Value::Box(_, x), Value::Box(_, y)) => {
Rc::<RefCell<Value<'_>>>::as_ptr(x) == Rc::<RefCell<Value<'_>>>::as_ptr(y)
}
_ => false,
}
}
}
impl Eq for Value<'_> {}
impl Value<'_> {
pub fn interpolate(&self) -> String {
match self {
Value::Nil => String::new(),
Value::Boolean(b) => format!("{b}"),
Value::Number(n) => format!("{n}"),
Value::Keyword(k) => format!(":{k}"),
Value::AllocatedString(s) => format!("{s}"),
Value::InternedString(s) => s.to_string(),
Value::Box(_, x) => x.borrow().interpolate(),
Value::Tuple(xs) => xs
.iter()
.map(|x| x.interpolate())
.collect::<Vec<_>>()
.join(", "),
Value::List(xs) => xs
.iter()
.map(|x| x.interpolate())
.collect::<Vec<_>>()
.join(", "),
Value::Dict(xs) => xs
.iter()
.map(|(k, v)| format!(":{} {}", k, v.interpolate()))
.collect::<Vec<_>>()
.join(", "),
Value::Fn(x) => format!("fn {}", x.borrow().name),
Value::FnDecl(name) => format!("fn {name}"),
Value::Placeholder => unreachable!(),
Value::Args(_) => unreachable!(),
Value::Recur(_) => unreachable!(),
Value::Base(_) => unreachable!(),
}
}
}

View File

@ -1,193 +1,47 @@
use crate::base::*;
use crate::parser::*;
use crate::spans::*;
use imbl::*;
use crate::compiler::Chunk;
use crate::parser::Ast;
use crate::spans::Spanned;
use imbl::{HashMap, Vector};
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use struct_scalpel::Dissectible;
#[derive(Clone, Debug)]
pub struct Fn<'src> {
pub name: String,
pub body: &'src Vec<Spanned<Ast>>,
pub doc: Option<String>,
pub enclosing: Vec<(String, Value<'src>)>,
#[derive(Clone, Debug, PartialEq)]
pub struct LBox {
pub name: usize,
pub cell: RefCell<Value>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LFn {
pub name: &'static str,
pub body: Vec<Spanned<Ast>>,
pub doc: Option<&'static str>,
pub enclosing: Vec<(usize, Value)>,
pub has_run: bool,
pub input: &'static str,
pub src: &'static str,
}
#[derive(Debug, Dissectible)]
pub enum Value<'src> {
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Nil,
Placeholder,
Boolean(bool),
Keyword(usize), // use an idx, rather than a raw index
Interned(usize),
FnDecl(usize),
String(Rc<String>),
Number(f64),
Keyword(&'static str),
InternedString(&'static str),
AllocatedString(Rc<String>),
// on the heap for now
Tuple(Rc<Vec<Self>>),
Args(Rc<Vec<Self>>),
List(Vector<Self>),
Dict(HashMap<&'static str, Self>),
Box(&'static str, Rc<RefCell<Self>>),
Fn(Rc<RefCell<Fn<'src>>>),
FnDecl(&'static str),
Base(BaseFn<'src>),
Recur(Vec<Self>),
// Set(HashSet<Self>),
// Sets are hard
// Sets require Eq
// Eq is not implemented on f64, because NaNs
// We could use ordered_float::NotNan
// Let's defer that
// We're not really using sets in Ludus
// Other things we're not implementing yet:
// pkgs, nses, tests
List(Box<Vector<Value>>),
Dict(Box<HashMap<&'static str, Value>>),
Box(Rc<LBox>),
Fn(Rc<RefCell<LFn>>),
}
impl<'src> Clone for Value<'src> {
fn clone(&self) -> Value<'src> {
match self {
Value::Nil => Value::Nil,
Value::Boolean(b) => Value::Boolean(*b),
Value::InternedString(s) => Value::InternedString(s),
Value::AllocatedString(s) => Value::AllocatedString(s.clone()),
Value::Keyword(s) => Value::Keyword(s),
Value::Number(n) => Value::Number(*n),
Value::Tuple(t) => Value::Tuple(t.clone()),
Value::Args(a) => Value::Args(a.clone()),
Value::Fn(f) => Value::Fn(f.clone()),
Value::FnDecl(name) => Value::FnDecl(name),
Value::List(l) => Value::List(l.clone()),
Value::Dict(d) => Value::Dict(d.clone()),
Value::Box(name, b) => Value::Box(name, b.clone()),
Value::Placeholder => Value::Placeholder,
Value::Base(b) => Value::Base(b.clone()),
Value::Recur(..) => unreachable!(),
}
}
}
impl fmt::Display for Value<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Nil => write!(f, "nil"),
Value::Boolean(b) => write!(f, "{b}"),
Value::Number(n) => write!(f, "{n}"),
Value::Keyword(k) => write!(f, ":{k}"),
Value::InternedString(s) => write!(f, "\"{s}\""),
Value::AllocatedString(s) => write!(f, "\"{s}\""),
Value::Fn(fun) => write!(f, "fn {}", fun.borrow().name),
Value::FnDecl(name) => write!(f, "fn {name}"),
Value::Tuple(t) | Value::Args(t) => write!(
f,
"({})",
t.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::List(l) => write!(
f,
"[{}]",
l.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::Dict(d) => write!(
f,
"#{{{}}}",
d.iter()
.map(|(k, v)| format!(":{k} {v}"))
.collect::<Vec<_>>()
.join(", ")
),
Value::Box(name, value) => {
write!(
f,
"box {}: [{}]",
name,
&value.try_borrow().unwrap().to_string()
)
}
Value::Placeholder => write!(f, "_"),
Value::Base(..) => unreachable!(),
Value::Recur(..) => unreachable!(),
}
}
}
impl Value<'_> {
pub fn bool(&self) -> bool {
!matches!(self, Value::Nil | Value::Boolean(false))
}
}
impl<'src> PartialEq for Value<'src> {
fn eq(&self, other: &Value<'src>) -> bool {
match (self, other) {
// value equality types
(Value::Nil, Value::Nil) => true,
(Value::Boolean(x), Value::Boolean(y)) => x == y,
(Value::Number(x), Value::Number(y)) => x == y,
(Value::InternedString(x), Value::InternedString(y)) => x == y,
(Value::AllocatedString(x), Value::AllocatedString(y)) => x == y,
(Value::InternedString(x), Value::AllocatedString(y)) => *x == **y,
(Value::AllocatedString(x), Value::InternedString(y)) => **x == *y,
(Value::Keyword(x), Value::Keyword(y)) => x == y,
(Value::Tuple(x), Value::Tuple(y)) => x == y,
(Value::List(x), Value::List(y)) => x == y,
(Value::Dict(x), Value::Dict(y)) => x == y,
// reference equality types
(Value::Fn(x), Value::Fn(y)) => {
Rc::<RefCell<Fn<'_>>>::as_ptr(x) == Rc::<RefCell<Fn<'_>>>::as_ptr(y)
}
(Value::Box(_, x), Value::Box(_, y)) => {
Rc::<RefCell<Value<'_>>>::as_ptr(x) == Rc::<RefCell<Value<'_>>>::as_ptr(y)
}
_ => false,
}
}
}
impl Eq for Value<'_> {}
impl Value<'_> {
pub fn interpolate(&self) -> String {
match self {
Value::Nil => String::new(),
Value::Boolean(b) => format!("{b}"),
Value::Number(n) => format!("{n}"),
Value::Keyword(k) => format!(":{k}"),
Value::AllocatedString(s) => format!("{s}"),
Value::InternedString(s) => s.to_string(),
Value::Box(_, x) => x.borrow().interpolate(),
Value::Tuple(xs) => xs
.iter()
.map(|x| x.interpolate())
.collect::<Vec<_>>()
.join(", "),
Value::List(xs) => xs
.iter()
.map(|x| x.interpolate())
.collect::<Vec<_>>()
.join(", "),
Value::Dict(xs) => xs
.iter()
.map(|(k, v)| format!(":{} {}", k, v.interpolate()))
.collect::<Vec<_>>()
.join(", "),
Value::Fn(x) => format!("fn {}", x.borrow().name),
Value::FnDecl(name) => format!("fn {name}"),
Value::Placeholder => unreachable!(),
Value::Args(_) => unreachable!(),
Value::Recur(_) => unreachable!(),
Value::Base(_) => unreachable!(),
impl Value {
fn show(&self, ctx: &Chunk) -> String {
use Value::*;
match &self {
Nil => format!("nil"),
}
}
}