use std::collections::BTreeMap;
use ecma_syntax_cat::function::ArrowBody;
use ecma_syntax_cat::identifier::Identifier;
use ecma_syntax_cat::pattern::Pattern;
use ecma_syntax_cat::statement::Statement;
use crate::env::Env;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ObjectId(u64);
impl ObjectId {
#[must_use]
pub(crate) fn new(id: u64) -> Self {
Self(id)
}
#[must_use]
pub fn raw(&self) -> u64 {
self.0
}
}
impl std::fmt::Display for ObjectId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "obj#{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FunctionId(u64);
impl FunctionId {
#[must_use]
pub(crate) fn new(id: u64) -> Self {
Self(id)
}
#[must_use]
pub fn raw(&self) -> u64 {
self.0
}
}
impl std::fmt::Display for FunctionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "fn#{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CellId(u64);
impl CellId {
#[must_use]
pub(crate) fn new(id: u64) -> Self {
Self(id)
}
#[must_use]
pub fn raw(&self) -> u64 {
self.0
}
}
impl std::fmt::Display for CellId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "cell#{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Cell {
value: Value,
mutable: bool,
}
impl Cell {
#[must_use]
pub fn new(value: Value, mutable: bool) -> Self {
Self { value, mutable }
}
#[must_use]
pub fn value(&self) -> &Value {
&self.value
}
#[must_use]
pub fn is_mutable(&self) -> bool {
self.mutable
}
#[must_use]
pub fn with_value(self, value: Value) -> Self {
Self {
value,
mutable: self.mutable,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Undefined,
Null,
Boolean(bool),
Number(f64),
String(String),
Object(ObjectId),
Function(FunctionId),
Native(NativeFn),
}
pub type NativeFn = fn(
args: Vec<Value>,
this: Value,
heap: crate::heap::Heap,
fuel: crate::fuel::Fuel,
) -> crate::outcome::EvalResult;
impl Eq for Value {}
impl std::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Undefined => f.write_str("undefined"),
Self::Null => f.write_str("null"),
Self::Boolean(b) => write!(f, "{b}"),
Self::Number(n) => write!(f, "{n}"),
Self::String(s) => write!(f, "{s:?}"),
Self::Object(id) => write!(f, "{id}"),
Self::Function(id) => write!(f, "{id}"),
Self::Native(_) => f.write_str("function [native code]"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Object {
properties: BTreeMap<String, Value>,
}
impl Object {
#[must_use]
pub fn empty() -> Self {
Self {
properties: BTreeMap::new(),
}
}
#[must_use]
pub fn from_properties(properties: BTreeMap<String, Value>) -> Self {
Self { properties }
}
#[must_use]
pub fn get(&self, key: &str) -> Option<&Value> {
self.properties.get(key)
}
#[must_use]
pub fn properties(&self) -> &BTreeMap<String, Value> {
&self.properties
}
#[must_use]
pub fn with(&self, key: String, value: Value) -> Self {
let mut next = self.properties.clone();
let _ = next.insert(key, value);
Self { properties: next }
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionDef {
name: Option<Identifier>,
params: Vec<Pattern>,
body: FunctionBody,
captured_env: Env,
is_arrow: bool,
}
impl FunctionDef {
#[must_use]
pub fn new(
name: Option<Identifier>,
params: Vec<Pattern>,
body: FunctionBody,
captured_env: Env,
is_arrow: bool,
) -> Self {
Self {
name,
params,
body,
captured_env,
is_arrow,
}
}
#[must_use]
pub fn name(&self) -> Option<&Identifier> {
self.name.as_ref()
}
#[must_use]
pub fn params(&self) -> &[Pattern] {
&self.params
}
#[must_use]
pub fn body(&self) -> &FunctionBody {
&self.body
}
#[must_use]
pub fn captured_env(&self) -> &Env {
&self.captured_env
}
#[must_use]
pub fn is_arrow(&self) -> bool {
self.is_arrow
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctionBody {
Statements(Vec<Statement>),
Arrow(Box<ArrowBody>),
}
impl FunctionBody {
#[must_use]
pub fn as_statements(&self) -> ArrowOrStatements<'_> {
match self {
Self::Statements(stmts) => ArrowOrStatements::Statements(stmts),
Self::Arrow(body) => ArrowOrStatements::Arrow(body),
}
}
}
pub enum ArrowOrStatements<'a> {
Statements(&'a [Statement]),
Arrow(&'a ArrowBody),
}