mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
wip
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
use std::hash::{Hash as HashTrait, Hasher};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
hash::{Hash as HashTrait, Hasher},
|
||||
};
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
@@ -48,6 +51,24 @@ impl Module {
|
||||
|
||||
assembly_lines.map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
pub fn ptr_to_index(&self) -> HashMap<Pointer, usize> {
|
||||
let mut res = HashMap::<Pointer, usize>::new();
|
||||
|
||||
for (i, defn) in self.definitions.iter().enumerate() {
|
||||
res.insert(defn.pointer.clone(), i);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn get<'a>(
|
||||
&'a self,
|
||||
ptr_to_index: &HashMap<Pointer, usize>,
|
||||
ptr: &Pointer,
|
||||
) -> &'a DefinitionContent {
|
||||
&self.definitions[*ptr_to_index.get(ptr).unwrap()].content
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Module {
|
||||
@@ -112,7 +133,7 @@ impl std::fmt::Display for DefinitionContent {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub struct FnMeta {
|
||||
pub name: String,
|
||||
pub content_hashable: ContentHashable,
|
||||
@@ -150,7 +171,7 @@ impl std::fmt::Display for FnMeta {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub struct Hash(pub [u8; 32]);
|
||||
|
||||
impl std::fmt::Display for Hash {
|
||||
@@ -167,7 +188,7 @@ impl std::fmt::Display for Hash {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub enum ContentHashable {
|
||||
#[default]
|
||||
Empty,
|
||||
@@ -228,6 +249,7 @@ impl std::fmt::Display for Function {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Class {
|
||||
pub metadata: FnMeta,
|
||||
pub constructor: Value,
|
||||
pub prototype: Value,
|
||||
pub static_: Value,
|
||||
@@ -237,6 +259,7 @@ impl std::fmt::Display for Class {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
writeln!(f, "class {{")?;
|
||||
|
||||
writeln!(f, " metadata: {},", self.metadata)?;
|
||||
writeln!(f, " constructor: {},", self.constructor)?;
|
||||
|
||||
write!(f, " prototype: ")?;
|
||||
|
||||
@@ -580,6 +580,11 @@ impl<'a> AssemblyParser<'a> {
|
||||
self.parse_exact("class {");
|
||||
self.parse_optional_whitespace();
|
||||
|
||||
self.parse_exact("metadata: ");
|
||||
let metadata = self.assemble_fn_meta();
|
||||
self.parse_exact(",");
|
||||
self.parse_optional_whitespace();
|
||||
|
||||
self.parse_exact("constructor: ");
|
||||
let constructor = self.assemble_value();
|
||||
self.parse_exact(",");
|
||||
@@ -598,6 +603,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
self.parse_exact("}");
|
||||
|
||||
Class {
|
||||
metadata,
|
||||
constructor,
|
||||
prototype,
|
||||
static_,
|
||||
|
||||
@@ -386,155 +386,31 @@ pub fn collapse_pointers_of_pointers(module: &mut Module) {
|
||||
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn calculate_content_hashes(module: &mut Module, _diagnostics: &mut Vec<Diagnostic>) {
|
||||
let mut fn_to_meta = HashMap::<Pointer, Pointer>::new();
|
||||
let ptr_to_index = module.ptr_to_index();
|
||||
|
||||
let mut ptr_to_src_meta = HashMap::<Pointer, (Hash, Vec<Value>)>::new();
|
||||
let mut meta_to_fn = HashMap::<Pointer, Pointer>::new();
|
||||
let mut src_and_deps_map = HashMap::<Pointer, (Hash, Vec<Value>)>::new();
|
||||
|
||||
for defn in &module.definitions {
|
||||
match &defn.content {
|
||||
DefinitionContent::Function(fn_) => {
|
||||
if let Some(metadata) = &fn_.metadata {
|
||||
fn_to_meta.insert(defn.pointer.clone(), metadata.clone());
|
||||
meta_to_fn.insert(metadata.clone(), defn.pointer.clone());
|
||||
if let Some(src_meta) = find_src_metadata(module, &ptr_to_index, defn) {
|
||||
ptr_to_src_meta.insert(defn.pointer.clone(), src_meta);
|
||||
|
||||
if let DefinitionContent::Function(fn_) = &defn.content {
|
||||
if let Some(metadata_ptr) = &fn_.metadata {
|
||||
meta_to_fn.insert(metadata_ptr.clone(), defn.pointer.clone());
|
||||
}
|
||||
}
|
||||
DefinitionContent::FnMeta(fn_meta) => match &fn_meta.content_hashable {
|
||||
ContentHashable::Empty => {}
|
||||
ContentHashable::Src(src_hash, deps) => {
|
||||
src_and_deps_map.insert(defn.pointer.clone(), (src_hash.clone(), deps.clone()));
|
||||
}
|
||||
ContentHashable::Content(_) => {}
|
||||
},
|
||||
DefinitionContent::Value(_) => {}
|
||||
DefinitionContent::Lazy(_) => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
for defn in &mut module.definitions {
|
||||
match &mut defn.content {
|
||||
DefinitionContent::Function(_) => {}
|
||||
DefinitionContent::FnMeta(fn_meta) => {
|
||||
let fn_ptr = meta_to_fn.get(&defn.pointer).unwrap().clone();
|
||||
|
||||
let mut full_deps = vec![PointerOrBuiltin::Pointer(fn_ptr.clone())];
|
||||
let mut deps_included = HashSet::<PointerOrBuiltin>::new();
|
||||
deps_included.insert(PointerOrBuiltin::Pointer(fn_ptr.clone()));
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < full_deps.len() {
|
||||
let dep = full_deps[i].clone();
|
||||
|
||||
let ptr_dep = match dep {
|
||||
PointerOrBuiltin::Pointer(p) => p,
|
||||
PointerOrBuiltin::Builtin(_) => {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let meta_ptr = fn_to_meta.get(&ptr_dep).unwrap();
|
||||
let (_, sub_deps) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Pointer(p.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Pointer(p.clone()));
|
||||
}
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Builtin(b.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Builtin(b.clone()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let mut dep_to_index = HashMap::<PointerOrBuiltin, usize>::new();
|
||||
|
||||
for (i, dep) in full_deps.iter().enumerate() {
|
||||
dep_to_index.insert(dep.clone(), i);
|
||||
}
|
||||
|
||||
let mut links = Vec::<Vec<usize>>::new();
|
||||
|
||||
for dep in &full_deps {
|
||||
let mut link = Vec::<usize>::new();
|
||||
|
||||
match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let meta_ptr = fn_to_meta.get(ptr_dep).unwrap();
|
||||
let (_, sub_deps) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Pointer(p.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Builtin(b.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PointerOrBuiltin::Builtin(_) => {}
|
||||
};
|
||||
|
||||
links.push(link);
|
||||
}
|
||||
|
||||
let mut content_trace = "{deps:".to_string();
|
||||
|
||||
content_trace.push_str(&make_array_string(&full_deps, |dep| match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let meta_ptr = fn_to_meta.get(ptr_dep).unwrap();
|
||||
let (src_hash, _) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
src_hash.to_string()
|
||||
}
|
||||
PointerOrBuiltin::Builtin(b) => b.to_string(),
|
||||
}));
|
||||
|
||||
content_trace.push_str(",links:");
|
||||
|
||||
content_trace.push_str(&make_array_string(&links, |link| {
|
||||
make_array_string(link, |i| i.to_string())
|
||||
}));
|
||||
|
||||
content_trace.push('}');
|
||||
|
||||
// dbg!((fn_ptr, full_deps, links, content_trace));
|
||||
|
||||
let mut k = Keccak::v256();
|
||||
k.update(content_trace.as_bytes());
|
||||
|
||||
let mut content_hash_data = [0u8; 32];
|
||||
k.finalize(&mut content_hash_data);
|
||||
|
||||
let content_hash = Hash(content_hash_data);
|
||||
|
||||
*fn_meta = FnMeta {
|
||||
name: take(&mut fn_meta.name),
|
||||
content_hashable: ContentHashable::Content(content_hash),
|
||||
};
|
||||
}
|
||||
DefinitionContent::FnMeta(fn_meta) => update_metadata(
|
||||
&ptr_to_src_meta,
|
||||
meta_to_fn.get(&defn.pointer).unwrap(),
|
||||
fn_meta,
|
||||
),
|
||||
DefinitionContent::Value(_) => {}
|
||||
DefinitionContent::Lazy(_) => {}
|
||||
}
|
||||
@@ -567,3 +443,163 @@ where
|
||||
result.push(']');
|
||||
result
|
||||
}
|
||||
|
||||
fn find_src_metadata(
|
||||
module: &Module,
|
||||
ptr_to_index: &HashMap<Pointer, usize>,
|
||||
defn: &Definition,
|
||||
) -> Option<(Hash, Vec<Value>)> {
|
||||
match &defn.content {
|
||||
DefinitionContent::Function(fn_) => {
|
||||
let metadata_ptr = match &fn_.metadata {
|
||||
Some(ptr) => ptr,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let src_meta = match module.get(ptr_to_index, metadata_ptr) {
|
||||
DefinitionContent::FnMeta(fn_meta) => match &fn_meta.content_hashable {
|
||||
ContentHashable::Src(src_hash, deps) => (src_hash.clone(), deps.clone()),
|
||||
_ => return None,
|
||||
},
|
||||
_ => panic!("metadata_ptr did not point to metadata"),
|
||||
};
|
||||
|
||||
Some(src_meta)
|
||||
}
|
||||
DefinitionContent::FnMeta(_fn_meta) => None,
|
||||
DefinitionContent::Value(value) => match value {
|
||||
Value::Class(class) => {
|
||||
let src_meta = match &class.metadata.content_hashable {
|
||||
ContentHashable::Src(src_hash, deps) => (src_hash.clone(), deps.clone()),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(src_meta)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
DefinitionContent::Lazy(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn update_metadata(
|
||||
ptr_to_src_meta: &HashMap<Pointer, (Hash, Vec<Value>)>,
|
||||
fn_ptr: &Pointer,
|
||||
fn_meta: &mut FnMeta,
|
||||
) {
|
||||
let mut full_deps = vec![PointerOrBuiltin::Pointer(fn_ptr.clone())];
|
||||
let mut deps_included = HashSet::<PointerOrBuiltin>::new();
|
||||
deps_included.insert(PointerOrBuiltin::Pointer(fn_ptr.clone()));
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < full_deps.len() {
|
||||
let dep = full_deps[i].clone();
|
||||
|
||||
let ptr_dep = match dep {
|
||||
PointerOrBuiltin::Pointer(p) => p,
|
||||
PointerOrBuiltin::Builtin(_) => {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let (_, sub_deps) = ptr_to_src_meta.get(&ptr_dep).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Pointer(p.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Pointer(p.clone()));
|
||||
}
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Builtin(b.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Builtin(b.clone()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let mut dep_to_index = HashMap::<PointerOrBuiltin, usize>::new();
|
||||
|
||||
for (i, dep) in full_deps.iter().enumerate() {
|
||||
dep_to_index.insert(dep.clone(), i);
|
||||
}
|
||||
|
||||
let mut links = Vec::<Vec<usize>>::new();
|
||||
|
||||
for dep in &full_deps {
|
||||
let mut link = Vec::<usize>::new();
|
||||
|
||||
match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let (_, sub_deps) = ptr_to_src_meta.get(ptr_dep).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Pointer(p.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Builtin(b.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PointerOrBuiltin::Builtin(_) => {}
|
||||
};
|
||||
|
||||
links.push(link);
|
||||
}
|
||||
|
||||
let mut content_trace = "{deps:".to_string();
|
||||
|
||||
content_trace.push_str(&make_array_string(&full_deps, |dep| match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let (src_hash, _) = ptr_to_src_meta.get(ptr_dep).unwrap();
|
||||
src_hash.to_string()
|
||||
}
|
||||
PointerOrBuiltin::Builtin(b) => b.to_string(),
|
||||
}));
|
||||
|
||||
content_trace.push_str(",links:");
|
||||
|
||||
content_trace.push_str(&make_array_string(&links, |link| {
|
||||
make_array_string(link, |i| i.to_string())
|
||||
}));
|
||||
|
||||
content_trace.push('}');
|
||||
|
||||
// dbg!((fn_ptr, full_deps, links, content_trace));
|
||||
|
||||
let mut k = Keccak::v256();
|
||||
k.update(content_trace.as_bytes());
|
||||
|
||||
let mut content_hash_data = [0u8; 32];
|
||||
k.finalize(&mut content_hash_data);
|
||||
|
||||
let content_hash = Hash(content_hash_data);
|
||||
|
||||
*fn_meta = FnMeta {
|
||||
name: take(&mut fn_meta.name),
|
||||
content_hashable: ContentHashable::Content(content_hash),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ use swc_ecma_ast::EsVersion;
|
||||
use swc_ecma_parser::{Syntax, TsConfig};
|
||||
|
||||
use crate::asm::{
|
||||
Class, Definition, DefinitionContent, FnLine, Instruction, Lazy, Module, Number, Object, Pointer,
|
||||
Register, Value,
|
||||
Class, ContentHashable, Definition, DefinitionContent, FnLine, FnMeta, Instruction, Lazy, Module,
|
||||
Number, Object, Pointer, Register, Value,
|
||||
};
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticReporter};
|
||||
use crate::expression_compiler::{CompiledExpression, ExpressionCompiler};
|
||||
@@ -18,6 +18,7 @@ use crate::ident::Ident;
|
||||
use crate::name_allocator::{ident_from_str, NameAllocator};
|
||||
use crate::scope::OwnerId;
|
||||
use crate::scope_analysis::{class_to_owner_id, ScopeAnalysis};
|
||||
use crate::src_hash::src_hash;
|
||||
use crate::static_expression_compiler::StaticExpressionCompiler;
|
||||
|
||||
struct DiagnosticCollector {
|
||||
@@ -877,6 +878,13 @@ impl ModuleCompiler {
|
||||
}
|
||||
|
||||
let class_value = Value::Class(Box::new(Class {
|
||||
metadata: FnMeta {
|
||||
name: ident.map_or_else(String::new, |ident| ident.sym.to_string()),
|
||||
content_hashable: ContentHashable::Src(
|
||||
src_hash(&self.source, class.span),
|
||||
self.scope_analysis.get_deps(class.span),
|
||||
),
|
||||
},
|
||||
constructor,
|
||||
prototype: Value::Object(Box::new(prototype)),
|
||||
static_: Value::Object(Box::new(static_)),
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
asm::{self, Builtin, FnLine, Function, Number, Pointer, Register, Value},
|
||||
asm::{self, Builtin, FnLine, FnMeta, Function, Number, Pointer, Register, Value},
|
||||
instruction::Instruction,
|
||||
name_allocator::RegAllocator,
|
||||
};
|
||||
@@ -72,6 +72,7 @@ pub struct KFunction {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Class {
|
||||
pub metadata: FnMeta,
|
||||
pub constructor: Kal,
|
||||
pub prototype: Kal,
|
||||
pub static_: Kal,
|
||||
@@ -136,6 +137,7 @@ impl Kal {
|
||||
.collect(),
|
||||
})),
|
||||
Value::Class(class) => Kal::Class(Box::new(Class {
|
||||
metadata: class.metadata.clone(),
|
||||
constructor: Kal::from_value(&class.constructor),
|
||||
prototype: Kal::from_value(&class.prototype),
|
||||
static_: Kal::from_value(&class.static_),
|
||||
@@ -209,6 +211,7 @@ impl Kal {
|
||||
}))),
|
||||
Kal::Function(_) => None,
|
||||
Kal::Class(class) => Some(Value::Class(Box::new(asm::Class {
|
||||
metadata: class.metadata.clone(),
|
||||
constructor: class.constructor.try_to_value()?,
|
||||
prototype: class.prototype.try_to_value()?,
|
||||
static_: class.static_.try_to_value()?,
|
||||
@@ -783,6 +786,7 @@ impl FnState {
|
||||
Kal::Object(Box::new(Object { properties }))
|
||||
}
|
||||
Value::Class(class) => Kal::Class(Box::new(Class {
|
||||
metadata: class.metadata.clone(),
|
||||
constructor: self.eval_arg(&mut class.constructor),
|
||||
prototype: self.eval_arg(&mut class.prototype),
|
||||
static_: self.eval_arg(&mut class.static_),
|
||||
|
||||
Reference in New Issue
Block a user