feat: 搭建内建函数原型链框架
This commit is contained in:
Generated
+2
-1
@@ -781,10 +781,12 @@ dependencies = [
|
||||
name = "oxide_kernel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"dashmap",
|
||||
"hashbrown 0.14.5",
|
||||
"oxide_compiler",
|
||||
"oxide_parser",
|
||||
"oxide_vm",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
@@ -808,7 +810,6 @@ dependencies = [
|
||||
"fast-float",
|
||||
"hashbrown 0.14.5",
|
||||
"oxide_compiler",
|
||||
"oxide_kernel",
|
||||
"oxide_parser",
|
||||
"proptest",
|
||||
"rustc-hash",
|
||||
|
||||
@@ -9,6 +9,8 @@ description = "OxideJS - Shared kernel (CodeForge, ShapeForge, IcForge, StringFo
|
||||
[dependencies]
|
||||
oxide_compiler = { path = "../oxide_compiler" }
|
||||
oxide_parser = { path = "../oxide_parser" }
|
||||
oxide_vm = { path = "../oxide_vm" }
|
||||
bumpalo.workspace = true
|
||||
dashmap.workspace = true
|
||||
hashbrown.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
use oxide_vm::mem::P;
|
||||
use oxide_vm::object::JsObject;
|
||||
use oxide_vm::value::JsValue;
|
||||
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::Interner;
|
||||
|
||||
pub struct BuiltinWorld {
|
||||
pub object_proto: P<JsObject>,
|
||||
pub array_proto: P<JsObject>,
|
||||
pub function_proto: P<JsObject>,
|
||||
pub string_proto: P<JsObject>,
|
||||
pub number_proto: P<JsObject>,
|
||||
pub boolean_proto: P<JsObject>,
|
||||
pub error_proto: P<JsObject>,
|
||||
pub symbol_proto: P<JsObject>,
|
||||
pub object_constructor: P<JsObject>,
|
||||
pub array_constructor: P<JsObject>,
|
||||
pub function_constructor: P<JsObject>,
|
||||
pub string_constructor: P<JsObject>,
|
||||
pub number_constructor: P<JsObject>,
|
||||
pub boolean_constructor: P<JsObject>,
|
||||
pub error_constructor: P<JsObject>,
|
||||
pub symbol_constructor: P<JsObject>,
|
||||
}
|
||||
|
||||
fn intern_label(interner: &Interner, label: &str) -> u32 {
|
||||
interner.intern(label).0
|
||||
}
|
||||
|
||||
fn make_pair(
|
||||
string_forge: &Interner,
|
||||
shape_forge: &ShapeForge,
|
||||
name: &str,
|
||||
si_prototype: u32,
|
||||
si_constructor: u32,
|
||||
si_name: u32,
|
||||
) -> (P<JsObject>, P<JsObject>) {
|
||||
intern_label(string_forge, name);
|
||||
|
||||
let mut proto = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
let mut ctor = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
|
||||
let proto_shape = shape_forge.make_shape(EMPTY_SHAPE_ID, si_constructor);
|
||||
proto.set_shape_id(proto_shape);
|
||||
proto.set_prop_count(1);
|
||||
|
||||
let ctor_shape1 = shape_forge.make_shape(EMPTY_SHAPE_ID, si_prototype);
|
||||
let ctor_shape2 = shape_forge.make_shape(ctor_shape1, si_name);
|
||||
ctor.set_shape_id(ctor_shape2);
|
||||
ctor.set_prop_count(2);
|
||||
ctor.set_function(true);
|
||||
|
||||
proto.set_inline_prop(0, JsValue::undefined());
|
||||
ctor.set_inline_prop(0, JsValue::undefined());
|
||||
ctor.set_inline_prop(1, JsValue::undefined());
|
||||
|
||||
(P::new(proto), P::new(ctor))
|
||||
}
|
||||
|
||||
impl BuiltinWorld {
|
||||
pub fn new(string_forge: &Interner, shape_forge: &ShapeForge) -> Self {
|
||||
let si_prototype = intern_label(string_forge, "prototype");
|
||||
let si_constructor = intern_label(string_forge, "constructor");
|
||||
let si_name = intern_label(string_forge, "name");
|
||||
intern_label(string_forge, "length");
|
||||
intern_label(string_forge, "toString");
|
||||
intern_label(string_forge, "valueOf");
|
||||
|
||||
let (object_proto, object_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Object",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (array_proto, array_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Array",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (function_proto, function_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Function",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (string_proto, string_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"String",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (number_proto, number_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Number",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (boolean_proto, boolean_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Boolean",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (error_proto, error_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Error",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
let (symbol_proto, symbol_constructor) = make_pair(
|
||||
string_forge,
|
||||
shape_forge,
|
||||
"Symbol",
|
||||
si_prototype,
|
||||
si_constructor,
|
||||
si_name,
|
||||
);
|
||||
|
||||
Self {
|
||||
object_proto,
|
||||
array_proto,
|
||||
function_proto,
|
||||
string_proto,
|
||||
number_proto,
|
||||
boolean_proto,
|
||||
error_proto,
|
||||
symbol_proto,
|
||||
object_constructor,
|
||||
array_constructor,
|
||||
function_constructor,
|
||||
string_constructor,
|
||||
number_constructor,
|
||||
boolean_constructor,
|
||||
error_constructor,
|
||||
symbol_constructor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::Interner;
|
||||
|
||||
fn make_world() -> BuiltinWorld {
|
||||
let sf = Interner::new();
|
||||
let sh = ShapeForge::new();
|
||||
BuiltinWorld::new(&sf, &sh)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_protos_valid() {
|
||||
let w = make_world();
|
||||
let protos = [
|
||||
&w.object_proto,
|
||||
&w.array_proto,
|
||||
&w.function_proto,
|
||||
&w.string_proto,
|
||||
&w.number_proto,
|
||||
&w.boolean_proto,
|
||||
&w.error_proto,
|
||||
&w.symbol_proto,
|
||||
];
|
||||
for p in protos {
|
||||
assert!(
|
||||
p.shape_id() > EMPTY_SHAPE_ID,
|
||||
"proto should have a non-empty shape"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_constructors_valid() {
|
||||
let w = make_world();
|
||||
assert!(w.object_constructor.is_function());
|
||||
assert!(w.array_constructor.is_function());
|
||||
assert!(w.function_constructor.is_function());
|
||||
assert!(w.string_constructor.is_function());
|
||||
assert!(w.number_constructor.is_function());
|
||||
assert!(w.boolean_constructor.is_function());
|
||||
assert!(w.error_constructor.is_function());
|
||||
assert!(w.symbol_constructor.is_function());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prototypes_are_not_functions() {
|
||||
let w = make_world();
|
||||
assert!(!w.object_proto.is_function());
|
||||
assert!(!w.array_proto.is_function());
|
||||
assert!(!w.function_proto.is_function());
|
||||
assert!(!w.string_proto.is_function());
|
||||
assert!(!w.number_proto.is_function());
|
||||
assert!(!w.boolean_proto.is_function());
|
||||
assert!(!w.error_proto.is_function());
|
||||
assert!(!w.symbol_proto.is_function());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_protos_have_null_proto() {
|
||||
let w = make_world();
|
||||
assert!(w.object_proto.proto().is_null());
|
||||
assert!(w.array_proto.proto().is_null());
|
||||
assert!(w.function_proto.proto().is_null());
|
||||
assert!(w.string_proto.proto().is_null());
|
||||
assert!(w.number_proto.proto().is_null());
|
||||
assert!(w.boolean_proto.proto().is_null());
|
||||
assert!(w.error_proto.proto().is_null());
|
||||
assert!(w.symbol_proto.proto().is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shapes_populated() {
|
||||
let w = make_world();
|
||||
assert!(
|
||||
w.object_constructor.shape_id() > EMPTY_SHAPE_ID,
|
||||
"constructor should have prototype + name shape"
|
||||
);
|
||||
assert!(
|
||||
w.object_proto.shape_id() > EMPTY_SHAPE_ID,
|
||||
"prototype should have constructor shape"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#![doc = "OxideJS - Shared kernel (CodeForge, ShapeForge, IcForge, StringForge, BuiltinWorld)"]
|
||||
|
||||
pub mod builtin;
|
||||
pub mod code_forge;
|
||||
pub mod prop_forge;
|
||||
pub mod shape_forge;
|
||||
|
||||
@@ -8,7 +8,6 @@ description = "OxideJS - Register-based VM with epoch arena memory"
|
||||
|
||||
[dependencies]
|
||||
oxide_compiler = { path = "../oxide_compiler" }
|
||||
oxide_kernel = { path = "../oxide_kernel" }
|
||||
bumpalo.workspace = true
|
||||
hashbrown.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
|
||||
@@ -14,6 +14,13 @@ impl<T> P<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Self(Arc::new(value))
|
||||
}
|
||||
|
||||
pub fn from_arena(value: &T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Self(Arc::new(value.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for P<T> {
|
||||
|
||||
Reference in New Issue
Block a user