mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-15 00:18:06 -05:00
Represent register taking
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
use num_bigint::BigInt;
|
||||
use valuescript_common::InstructionByte;
|
||||
|
||||
use crate::assembler::ValueType;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Module {
|
||||
pub export_default: Value,
|
||||
@@ -163,32 +165,74 @@ impl std::fmt::Display for Class {
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
|
||||
pub enum Register {
|
||||
Return,
|
||||
This,
|
||||
Named(String),
|
||||
Ignore,
|
||||
pub struct Register {
|
||||
pub take: bool,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn as_name(&self) -> String {
|
||||
match self {
|
||||
Register::Return => "return".to_string(),
|
||||
Register::This => "this".to_string(),
|
||||
Register::Named(name) => name.clone(),
|
||||
Register::Ignore => "ignore".to_string(),
|
||||
pub fn return_(take: bool) -> Self {
|
||||
Register {
|
||||
take,
|
||||
name: "return".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn this(take: bool) -> Self {
|
||||
Register {
|
||||
take,
|
||||
name: "this".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn named(take: bool, name: String) -> Self {
|
||||
Register { take, name }
|
||||
}
|
||||
|
||||
pub fn ignore(take: bool) -> Self {
|
||||
Register {
|
||||
take,
|
||||
name: "ignore".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_return(&self) -> bool {
|
||||
return self.name == "return";
|
||||
}
|
||||
|
||||
pub fn is_this(&self) -> bool {
|
||||
return self.name == "this";
|
||||
}
|
||||
|
||||
pub fn is_named(&self) -> bool {
|
||||
match self.name.as_str() {
|
||||
"return" | "this" | "ignore" => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
return self.name == "ignore";
|
||||
}
|
||||
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
if self.take {
|
||||
ValueType::TakeRegister
|
||||
} else {
|
||||
ValueType::Register
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Register {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Register::Return => write!(f, "%return"),
|
||||
Register::This => write!(f, "%this"),
|
||||
Register::Named(name) => write!(f, "%{}", name),
|
||||
Register::Ignore => write!(f, "%ignore"),
|
||||
write!(f, "%")?;
|
||||
|
||||
if self.take {
|
||||
write!(f, "!")?;
|
||||
}
|
||||
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ impl Assembler {
|
||||
fn value(&mut self, value: &Value) {
|
||||
match value {
|
||||
Value::Register(register) => {
|
||||
self.output.push(ValueType::Register as u8);
|
||||
self.output.push(register.value_type() as u8);
|
||||
self.register(register);
|
||||
}
|
||||
Value::Number(number) => self.number(*number),
|
||||
@@ -294,19 +294,22 @@ impl Assembler {
|
||||
}
|
||||
|
||||
fn lookup_register(&mut self, register: &Register) -> u8 {
|
||||
match register {
|
||||
Register::Return => 0,
|
||||
Register::This => 1,
|
||||
Register::Named(_) => match self.fn_data.register_map.get(register) {
|
||||
match register.name.as_str() {
|
||||
"return" => 0,
|
||||
"this" => 1,
|
||||
"ignore" => 0xff,
|
||||
_ => match self.fn_data.register_map.get(®ister.name) {
|
||||
Some(index) => *index,
|
||||
None => {
|
||||
// TODO: Support >255 registers
|
||||
let index = (self.fn_data.register_map.len() as u8) + 2;
|
||||
self.fn_data.register_map.insert(register.clone(), index);
|
||||
self
|
||||
.fn_data
|
||||
.register_map
|
||||
.insert(register.name.clone(), index);
|
||||
index
|
||||
}
|
||||
},
|
||||
Register::Ignore => 0xff,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +410,7 @@ impl Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
enum ValueType {
|
||||
pub enum ValueType {
|
||||
End = 0x00,
|
||||
Void = 0x01,
|
||||
Undefined = 0x02,
|
||||
@@ -423,12 +426,13 @@ enum ValueType {
|
||||
// Instance = 0x0c,
|
||||
Pointer = 0x0d,
|
||||
Register = 0x0e,
|
||||
// External = 0x0f,
|
||||
TakeRegister = 0x0f,
|
||||
Builtin = 0x10,
|
||||
Class = 0x11,
|
||||
Lazy = 0x12,
|
||||
BigInt = 0x13,
|
||||
GeneratorFunction = 0x14,
|
||||
// External = TBD,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Clone)]
|
||||
@@ -480,7 +484,7 @@ impl LocationMap {
|
||||
|
||||
#[derive(Default)]
|
||||
struct AssemblerFnData {
|
||||
register_map: HashMap<Register, u8>,
|
||||
register_map: HashMap<String, u8>,
|
||||
register_count_pos: usize,
|
||||
labels_map: LocationMap,
|
||||
}
|
||||
|
||||
@@ -415,11 +415,13 @@ impl<'a> AssemblyParser<'a> {
|
||||
panic!("Expected this to be impossible");
|
||||
}
|
||||
|
||||
let take = self.parse_one_of(&["!", ""]) == "!";
|
||||
|
||||
let param_name = self.parse_identifier();
|
||||
|
||||
function
|
||||
.parameters
|
||||
.push(Register::Named(param_name.clone()));
|
||||
.push(Register::named(take, param_name.clone()));
|
||||
|
||||
next = self.parse_one_of(&[",", ")"]);
|
||||
|
||||
@@ -811,14 +813,10 @@ impl<'a> AssemblyParser<'a> {
|
||||
fn assemble_register(&mut self) -> Register {
|
||||
self.parse_optional_whitespace();
|
||||
self.parse_exact("%");
|
||||
let take = self.parse_one_of(&["!", ""]) == "!";
|
||||
let name = self.parse_identifier();
|
||||
|
||||
match name.as_str() {
|
||||
"return" => Register::Return,
|
||||
"this" => Register::This,
|
||||
"ignore" => Register::Ignore,
|
||||
_ => Register::Named(name),
|
||||
}
|
||||
return Register { take, name };
|
||||
}
|
||||
|
||||
fn assemble_builtin(&mut self) -> Builtin {
|
||||
|
||||
@@ -87,7 +87,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
match expr {
|
||||
This(_) => {
|
||||
return self.inline(Value::Register(Register::This), target_register);
|
||||
return self.inline(Value::Register(Register::this(false)), target_register);
|
||||
}
|
||||
Array(array_exp) => {
|
||||
return self.array_expression(array_exp, target_register);
|
||||
@@ -1307,7 +1307,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
self.fnc.push(Instruction::Yield(
|
||||
Value::Register(dst.clone()),
|
||||
Register::Ignore,
|
||||
Register::ignore(false),
|
||||
));
|
||||
|
||||
self.fnc.label(next_label);
|
||||
@@ -1572,7 +1572,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
name: self
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate(&format!("{}_initialized", register.as_name())),
|
||||
.allocate(&format!("{}_initialized", register.name)),
|
||||
};
|
||||
|
||||
self.fnc.push(Instruction::OpTripleNe(
|
||||
|
||||
@@ -313,7 +313,7 @@ impl FunctionCompiler {
|
||||
swc_ecma_ast::BlockStmtOrExpr::Expr(expr) => {
|
||||
let mut expression_compiler = ExpressionCompiler { fnc: self };
|
||||
|
||||
expression_compiler.compile(expr, Some(Register::Return));
|
||||
expression_compiler.compile(expr, Some(Register::return_(false)));
|
||||
}
|
||||
},
|
||||
Functionish::Constructor(member_initializers_assembly, _class_span, constructor) => {
|
||||
@@ -467,7 +467,7 @@ impl FunctionCompiler {
|
||||
Some(expr) => {
|
||||
let mut expression_compiler = ExpressionCompiler { fnc: self };
|
||||
|
||||
let compiled = expression_compiler.compile(expr, Some(Register::Return));
|
||||
let compiled = expression_compiler.compile(expr, Some(Register::return_(false)));
|
||||
self.use_(compiled);
|
||||
}
|
||||
}
|
||||
@@ -676,7 +676,7 @@ impl FunctionCompiler {
|
||||
.param
|
||||
{
|
||||
Some(_) => self.allocate_numbered_reg("_error"),
|
||||
None => Register::Ignore,
|
||||
None => Register::ignore(false),
|
||||
};
|
||||
|
||||
catch_error_reg = Some(reg.clone());
|
||||
@@ -695,12 +695,11 @@ impl FunctionCompiler {
|
||||
let snap_registers: HashSet<Register> = self.get_mutated_registers(try_.block.span);
|
||||
|
||||
for reg in snap_registers {
|
||||
let reg_name = match ® {
|
||||
Register::Named(name) => name,
|
||||
_ => continue,
|
||||
};
|
||||
if !reg.is_named() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let snap_reg = self.allocate_reg_fresh(&format!("snap_{}", reg_name));
|
||||
let snap_reg = self.allocate_reg_fresh(&format!("snap_{}", reg.name));
|
||||
|
||||
self.push(Instruction::Mov(
|
||||
Value::Register(reg.clone()),
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::asm::{
|
||||
Definition, DefinitionContent, Instruction, InstructionOrLabel, Pointer, Register, Value,
|
||||
};
|
||||
use crate::asm::{Definition, DefinitionContent, Instruction, InstructionOrLabel, Pointer, Value};
|
||||
|
||||
pub struct ImportPattern {
|
||||
pub pointer: Pointer,
|
||||
@@ -31,8 +29,14 @@ impl ImportPattern {
|
||||
};
|
||||
|
||||
let (path_value, is_star) = match first_instruction {
|
||||
Instruction::Import(path, Register::Return) => (path, false),
|
||||
Instruction::ImportStar(path, Register::Return) => (path, true),
|
||||
Instruction::Import(path, reg) => match reg.name.as_str() {
|
||||
"return" => (path, false),
|
||||
_ => return None,
|
||||
},
|
||||
Instruction::ImportStar(path, reg) => match reg.name.as_str() {
|
||||
"return" => (path, true),
|
||||
_ => return None,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@@ -67,15 +71,16 @@ impl ImportPattern {
|
||||
};
|
||||
|
||||
match second_instruction {
|
||||
Instruction::Sub(
|
||||
Value::Register(Register::Return),
|
||||
Value::String(name),
|
||||
Register::Return,
|
||||
) => Some(ImportPattern {
|
||||
pointer: definition.pointer.clone(),
|
||||
path: path.clone(),
|
||||
kind: ImportKind::Name(name.clone()),
|
||||
}),
|
||||
Instruction::Sub(Value::Register(obj), Value::String(name), target) => {
|
||||
match obj.name == "return" && target.name == "return" {
|
||||
true => Some(ImportPattern {
|
||||
pointer: definition.pointer.clone(),
|
||||
path: path.clone(),
|
||||
kind: ImportKind::Name(name.clone()),
|
||||
}),
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::asm::{Instruction, Register, Value};
|
||||
use crate::asm::{Instruction, Value};
|
||||
|
||||
pub fn instruction_mutates_this(instruction: &Instruction) -> bool {
|
||||
use Instruction::*;
|
||||
@@ -50,17 +50,15 @@ pub fn instruction_mutates_this(instruction: &Instruction) -> bool {
|
||||
| ConstSubCall(_, _, _, reg)
|
||||
| ThisSubCall(_, _, _, reg)
|
||||
| Cat(_, reg)
|
||||
| Yield(_, reg) => reg == &Register::This,
|
||||
| Yield(_, reg) => reg.is_this(),
|
||||
|
||||
Next(iter, res) => iter == &Register::This || res == &Register::This,
|
||||
UnpackIterRes(_, value_reg, done_reg) => {
|
||||
value_reg == &Register::This || done_reg == &Register::This
|
||||
}
|
||||
Next(iter, res) => iter.is_this() || res.is_this(),
|
||||
UnpackIterRes(_, value_reg, done_reg) => value_reg.is_this() || done_reg.is_this(),
|
||||
|
||||
Apply(_, ctx, _, reg) | SubCall(ctx, _, _, reg) | YieldStar(ctx, reg) => {
|
||||
reg == &Register::This
|
||||
reg.is_this()
|
||||
|| match ctx {
|
||||
Value::Register(reg) => reg == &Register::This,
|
||||
Value::Register(reg) => reg.is_this(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,17 +408,17 @@ impl ModuleCompiler {
|
||||
body: match orig_name.sym.to_string() == "default" {
|
||||
true => vec![InstructionOrLabel::Instruction(Instruction::Import(
|
||||
Value::String(src.value.to_string()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
))],
|
||||
false => vec![
|
||||
InstructionOrLabel::Instruction(Instruction::ImportStar(
|
||||
Value::String(src.value.to_string()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
)),
|
||||
InstructionOrLabel::Instruction(Instruction::Sub(
|
||||
Value::Register(Register::Return),
|
||||
Value::Register(Register::return_(false)),
|
||||
Value::String(orig_name.sym.to_string()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
)),
|
||||
],
|
||||
},
|
||||
@@ -501,7 +501,7 @@ impl ModuleCompiler {
|
||||
content: DefinitionContent::Lazy(Lazy {
|
||||
body: vec![InstructionOrLabel::Instruction(Instruction::ImportStar(
|
||||
Value::String(src),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
))],
|
||||
}),
|
||||
});
|
||||
@@ -574,12 +574,12 @@ impl ModuleCompiler {
|
||||
body: vec![
|
||||
InstructionOrLabel::Instruction(Instruction::ImportStar(
|
||||
Value::String(import_path.clone()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
)),
|
||||
InstructionOrLabel::Instruction(Instruction::Sub(
|
||||
Value::Register(Register::Return),
|
||||
Value::Register(Register::return_(false)),
|
||||
Value::String(external_name),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
)),
|
||||
],
|
||||
}),
|
||||
@@ -609,7 +609,7 @@ impl ModuleCompiler {
|
||||
content: DefinitionContent::Lazy(Lazy {
|
||||
body: vec![InstructionOrLabel::Instruction(Instruction::Import(
|
||||
Value::String(import_path.clone()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
))],
|
||||
}),
|
||||
});
|
||||
@@ -638,7 +638,7 @@ impl ModuleCompiler {
|
||||
content: DefinitionContent::Lazy(Lazy {
|
||||
body: vec![InstructionOrLabel::Instruction(Instruction::ImportStar(
|
||||
Value::String(import_path.clone()),
|
||||
Register::Return,
|
||||
Register::return_(false),
|
||||
))],
|
||||
}),
|
||||
});
|
||||
@@ -728,8 +728,11 @@ impl ModuleCompiler {
|
||||
let key_asm = ec.fnc.use_(compiled_key);
|
||||
let value_asm = ec.fnc.use_(compiled_value);
|
||||
|
||||
ec.fnc
|
||||
.push(Instruction::SubMov(key_asm, value_asm, Register::This));
|
||||
ec.fnc.push(Instruction::SubMov(
|
||||
key_asm,
|
||||
value_asm,
|
||||
Register::this(false),
|
||||
));
|
||||
}
|
||||
swc_ecma_ast::ClassMember::PrivateProp(private_prop) => {
|
||||
self.todo(private_prop.span, "private props")
|
||||
|
||||
@@ -125,28 +125,28 @@ pub struct RegAllocator {
|
||||
impl RegAllocator {
|
||||
pub fn allocate(&mut self, based_on_name: &str) -> Register {
|
||||
let name = self.alloc.allocate(&based_on_name.to_string());
|
||||
Register::Named(name)
|
||||
Register::named(false, name)
|
||||
}
|
||||
|
||||
pub fn allocate_fresh(&mut self, based_on_name: &str) -> Register {
|
||||
let name = self.alloc.allocate_fresh(&based_on_name.to_string());
|
||||
Register::Named(name)
|
||||
Register::named(false, name)
|
||||
}
|
||||
|
||||
pub fn allocate_numbered(&mut self, prefix: &str) -> Register {
|
||||
let name = self.alloc.allocate_numbered(&prefix.to_string());
|
||||
Register::Named(name)
|
||||
Register::named(false, name)
|
||||
}
|
||||
|
||||
pub fn allocate_numbered_fresh(&mut self, prefix: &str) -> Register {
|
||||
let name = self.alloc.allocate_numbered_fresh(&prefix.to_string());
|
||||
Register::Named(name)
|
||||
Register::named(false, name)
|
||||
}
|
||||
|
||||
pub fn release(&mut self, reg: &Register) {
|
||||
match reg {
|
||||
Register::Named(name) => self.alloc.release(name),
|
||||
_ => panic!("Can't release non-named register"),
|
||||
match reg.is_named() {
|
||||
true => self.alloc.release(®.name),
|
||||
false => panic!("Can't release non-named register"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ impl TargetAccessor {
|
||||
|
||||
return match expr {
|
||||
Ident(ident) => TargetAccessor::compile_ident(ec, ident),
|
||||
This(_) => TargetAccessor::Register(Register::This),
|
||||
This(_) => TargetAccessor::Register(Register::this(false)),
|
||||
Member(member) => {
|
||||
let obj = TargetAccessor::compile(ec, &member.obj, false);
|
||||
let subscript = ec.member_prop(&member.prop, None);
|
||||
@@ -189,7 +189,7 @@ impl TargetAccessor {
|
||||
|
||||
pub fn targets_this(&self) -> bool {
|
||||
return match self {
|
||||
TargetAccessor::Register(reg) => reg == &Register::This,
|
||||
TargetAccessor::Register(reg) => reg == &Register::this(false),
|
||||
TargetAccessor::Nested(nta) => nta.obj.targets_this(),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user