mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
wip2
This commit is contained in:
@@ -2,7 +2,7 @@ use std::mem::take;
|
||||
|
||||
use swc_common::Spanned;
|
||||
|
||||
use crate::asm::{Array, Instruction, Label, Number, Object, Register, Value};
|
||||
use crate::asm::{Array, Class, Instruction, Label, Number, Object, Register, Value};
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticReporter};
|
||||
use crate::function_compiler::{FunctionCompiler, Functionish};
|
||||
use crate::ident::Ident as CrateIdent;
|
||||
@@ -1232,38 +1232,31 @@ impl<'a, 'fnc> ExpressionCompiler<'a, 'fnc> {
|
||||
ident: &CrateIdent,
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
let fn_as_owner_id = match self.fnc.mc.scope_analysis.lookup(ident) {
|
||||
Some(name) => match name.type_ == NameType::Function {
|
||||
true => match name.id {
|
||||
// TODO: This is a bit of a hack, it might break...
|
||||
// functions have an owner id, and the name id should
|
||||
// have the same span... at least it does now
|
||||
NameId::Span(span) => Some(OwnerId::Span(span)),
|
||||
_ => None, // Internal error?
|
||||
},
|
||||
false => None,
|
||||
},
|
||||
let name = match self.fnc.mc.scope_analysis.lookup(ident) {
|
||||
Some(name) => name,
|
||||
_ => {
|
||||
self.internal_error(
|
||||
ident.span,
|
||||
&format!("Failed to lookup identifier `{}`", ident.sym),
|
||||
);
|
||||
|
||||
None
|
||||
return self.simple_ident(ident);
|
||||
}
|
||||
};
|
||||
|
||||
let value = self.fnc.lookup_value(ident).unwrap_or_default();
|
||||
match name.type_ {
|
||||
NameType::Function => {
|
||||
let owner_id = match name.id {
|
||||
// TODO: This is a bit of a hack, it might break...
|
||||
// functions have an owner id, and the name id should
|
||||
// have the same span... at least it does now
|
||||
NameId::Span(span) => OwnerId::Span(span),
|
||||
_ => return self.simple_ident(ident), // Internal error?
|
||||
};
|
||||
|
||||
let name = match self.fnc.lookup(ident) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Value::Undefined.to_ce();
|
||||
}
|
||||
};
|
||||
let value = name.value.clone();
|
||||
|
||||
match fn_as_owner_id {
|
||||
Some(owner_id) => {
|
||||
// TODO: name.captures?
|
||||
let capture_params = self.fnc.mc.scope_analysis.get_register_captures(&owner_id);
|
||||
|
||||
match capture_params.len() {
|
||||
@@ -1277,24 +1270,78 @@ impl<'a, 'fnc> ExpressionCompiler<'a, 'fnc> {
|
||||
),
|
||||
}
|
||||
}
|
||||
None => match value {
|
||||
Value::Register(reg) => {
|
||||
if name.mutations.is_empty() {
|
||||
// Just use the register for the variable if it's not mutated
|
||||
return Value::Register(reg).to_ce();
|
||||
}
|
||||
// NameType::Class => {
|
||||
// let owner_id = match name.id {
|
||||
// // TODO: This is a bit of a hack, it might break...
|
||||
// // classes have an owner id, and the name id should
|
||||
// // have the same span... at least it does now
|
||||
// NameId::Span(span) => OwnerId::Span(span),
|
||||
// _ => return self.simple_ident(ident), // Internal error?
|
||||
// };
|
||||
|
||||
// Otherwise, we need to capture the current value for the result of the expression
|
||||
let new_reg = self.fnc.allocate_tmp();
|
||||
// let value = name.value.clone();
|
||||
// let ctor_captures = self.fnc.mc.scope_analysis.get_register_captures(&owner_id);
|
||||
|
||||
self
|
||||
.fnc
|
||||
.push(Instruction::Mov(Value::Register(reg), new_reg.clone()));
|
||||
// if ctor_captures.is_empty() {
|
||||
// // Note: We're relying on the fact that all captures in the class will get included on the
|
||||
// // constructor here. This is a bit conceptually inaccurate, but it arises because of the
|
||||
// // confusion between the identity of the class and its constructor.
|
||||
// return value.to_ce();
|
||||
// }
|
||||
|
||||
CompiledExpression::new(Value::Register(new_reg.clone()), vec![new_reg])
|
||||
// let mut nested_registers = Vec::<Register>::new();
|
||||
|
||||
// let mut ctor = self.capturing_fn_ref(
|
||||
// ident.span,
|
||||
// Some(ident.sym.to_string()),
|
||||
// &value,
|
||||
// &ctor_captures,
|
||||
// target_register,
|
||||
// );
|
||||
|
||||
// ctor.release_checker.has_unreleased_registers = false;
|
||||
// nested_registers.append(&mut ctor.nested_registers);
|
||||
|
||||
// let class = Class {
|
||||
// constructor: ctor.value,
|
||||
// prototype: todo!(),
|
||||
// static_: todo!(),
|
||||
// };
|
||||
|
||||
// CompiledExpression::new(Value::Class(Box::new(class)), nested_registers)
|
||||
// }
|
||||
_ => self.simple_ident(ident),
|
||||
}
|
||||
}
|
||||
|
||||
// Here 'simple' means 'not capturing'
|
||||
pub fn simple_ident(&mut self, ident: &CrateIdent) -> CompiledExpression {
|
||||
let value = self.fnc.lookup_value(ident).unwrap_or_default();
|
||||
|
||||
let name = match self.fnc.lookup(ident) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Value::Undefined.to_ce();
|
||||
}
|
||||
};
|
||||
|
||||
match value {
|
||||
Value::Register(reg) => {
|
||||
if name.mutations.is_empty() {
|
||||
// Just use the register for the variable if it's not mutated
|
||||
return Value::Register(reg).to_ce();
|
||||
}
|
||||
_ => value.to_ce(),
|
||||
},
|
||||
|
||||
// Otherwise, we need to capture the current value for the result of the expression
|
||||
let new_reg = self.fnc.allocate_tmp();
|
||||
|
||||
self
|
||||
.fnc
|
||||
.push(Instruction::Mov(Value::Register(reg), new_reg.clone()));
|
||||
|
||||
CompiledExpression::new(Value::Register(new_reg.clone()), vec![new_reg])
|
||||
}
|
||||
_ => value.to_ce(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use swc_common::Spanned;
|
||||
use valuescript_common::BUILTIN_NAMES;
|
||||
|
||||
use crate::{
|
||||
asm::{Builtin, Register, Value},
|
||||
asm::{Builtin, Pointer, Register, Value},
|
||||
constants::CONSTANTS,
|
||||
diagnostic::{DiagnosticContainer, DiagnosticReporter},
|
||||
ident::Ident,
|
||||
@@ -74,6 +74,7 @@ pub struct ScopeAnalysis {
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
pub pointer_allocator: PointerAllocator,
|
||||
pub reg_allocators: HashMap<OwnerId, RegAllocator>,
|
||||
pub pointer_to_name_id: HashMap<Pointer, NameId>,
|
||||
}
|
||||
|
||||
impl DiagnosticContainer for ScopeAnalysis {
|
||||
@@ -189,6 +190,11 @@ impl ScopeAnalysis {
|
||||
origin_ident: &Ident,
|
||||
tdz_end: Option<swc_common::BytePos>,
|
||||
) {
|
||||
let pointer = match &value {
|
||||
Value::Pointer(p) => Some(p.clone()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let name = Name {
|
||||
id: match type_ {
|
||||
NameType::This => NameId::This(origin_ident.span),
|
||||
@@ -234,10 +240,33 @@ impl ScopeAnalysis {
|
||||
|
||||
scope.set(
|
||||
&origin_ident.sym,
|
||||
name.id,
|
||||
name.id.clone(),
|
||||
origin_ident.span,
|
||||
&mut self.diagnostics,
|
||||
);
|
||||
|
||||
if let Some(pointer) = pointer {
|
||||
self.pointer_to_name_id.insert(pointer, name.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_captures_for_value(&mut self, value: &Value) -> Vec<NameId> {
|
||||
let p = match value {
|
||||
Value::Pointer(p) => p,
|
||||
_ => return vec![],
|
||||
};
|
||||
|
||||
let name_id = match self.pointer_to_name_id.get(p) {
|
||||
Some(name_id) => name_id.clone(),
|
||||
None => return vec![],
|
||||
};
|
||||
|
||||
let owner_id = match self.name_id_to_owner_id(&name_id) {
|
||||
Some(owner_id) => owner_id,
|
||||
None => return vec![],
|
||||
};
|
||||
|
||||
self.get_register_captures(&owner_id)
|
||||
}
|
||||
|
||||
fn insert_pointer_name(
|
||||
@@ -1738,13 +1767,13 @@ impl ScopeAnalysis {
|
||||
}
|
||||
};
|
||||
|
||||
if name.type_ == NameType::Function {
|
||||
if let NameType::Function | NameType::Class = name.type_ {
|
||||
match name_id {
|
||||
NameId::Span(span) => Some(OwnerId::Span(*span)),
|
||||
NameId::This(_) => {
|
||||
self.diagnostics.push(Diagnostic::internal_error(
|
||||
swc_common::DUMMY_SP,
|
||||
"NameId::This should not be associated with NameType::Function",
|
||||
"NameId::This should not be associated with NameType::Function/Class",
|
||||
));
|
||||
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user