use self::operands::{DynamicId, DynamicReferenceId, SpanId};
use super::scope::ScopeId;
use crate::engine::code::bytecode::Instruction;
use crate::engine::compiler::names::NameId;
use crate::engine::value::{JsString, PrimitiveValue as Value};
use crate::source::SourceOffset;
use std::rc::Rc;
pub(in crate::engine::compiler) type FunctionId = usize;
#[derive(Debug)]
pub(in crate::engine::compiler) enum IrConstant {
Primitive(Value),
AtomString(JsString),
RegExp {
pattern: JsString,
program: Rc<oxide_regexp::CompiledRegExp>,
},
TemplateObject {
cooked: Vec<Option<JsString>>,
raw: Vec<JsString>,
},
Child(FunctionId),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::engine::compiler) enum IdentifierAccess {
Get,
GetOrUndefined,
Delete,
Initialize,
InitializeDerivedThis,
Put,
AnnexBPut,
Set,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::engine::compiler) enum IdentifierReferenceAccess {
Prepare,
Get,
Call,
Set,
PostPut,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::engine::compiler) enum PrivateFieldAccess {
Get,
GetKeepReceiver,
Put,
Define,
In,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::engine::compiler) enum CallArguments {
Fixed(u16),
Spread,
}
#[derive(Debug)]
pub(in crate::engine::compiler) enum IrOp {
Bytecode(Instruction),
ImportMeta {
span: SpanId,
scope: ScopeId,
},
EnterScope(ScopeId),
PrepareCatchScope(ScopeId),
LeaveScope(ScopeId),
ParameterInitializationEnd,
TemplateCall {
argument_count: usize,
method: bool,
},
EvalCall {
arguments: CallArguments,
scope: ScopeId,
environment: Option<u16>,
},
PushConstant(u32),
MakeClosure(u32),
GlobalSet(u16),
CapturedLexicalSet(u16),
DynamicIdentifier {
access: IdentifierAccess,
operand: DynamicId,
},
DynamicIdentifierReference {
access: IdentifierReferenceAccess,
operand: DynamicReferenceId,
},
Identifier {
name: NameId,
span: SpanId,
scope: ScopeId,
access: IdentifierAccess,
},
IdentifierReference {
name: NameId,
span: SpanId,
scope: ScopeId,
access: IdentifierReferenceAccess,
},
PrivateField {
name: NameId,
span: SpanId,
scope: ScopeId,
access: PrivateFieldAccess,
},
}
#[derive(Debug)]
pub(in crate::engine::compiler) struct SpannedIrOp {
pub(in crate::engine::compiler) op: IrOp,
pub(in crate::engine::compiler) pc_site: Option<SourceOffset>,
}
impl IrOp {
pub(in crate::engine::compiler) fn stack_effect(&self) -> (usize, usize) {
match self {
Self::Bytecode(instruction) => instruction.stack_effect(),
Self::ImportMeta { .. } => (0, 1),
Self::EnterScope(_)
| Self::PrepareCatchScope(_)
| Self::LeaveScope(_)
| Self::ParameterInitializationEnd => (0, 0),
Self::TemplateCall {
argument_count,
method,
} => (argument_count + usize::from(*method) + 1, 1),
Self::EvalCall { arguments, .. } => match arguments {
CallArguments::Fixed(argument_count) => (usize::from(*argument_count) + 1, 1),
CallArguments::Spread => (2, 1),
},
Self::PushConstant(_) | Self::MakeClosure(_) => (0, 1),
Self::GlobalSet(_) | Self::CapturedLexicalSet(_) => (1, 1),
Self::DynamicIdentifier { access, .. } => match access {
IdentifierAccess::Get
| IdentifierAccess::GetOrUndefined
| IdentifierAccess::Delete => (0, 1),
IdentifierAccess::Initialize
| IdentifierAccess::InitializeDerivedThis
| IdentifierAccess::Put
| IdentifierAccess::AnnexBPut => (1, 0),
IdentifierAccess::Set => (1, 1),
},
Self::DynamicIdentifierReference { access, .. }
| Self::IdentifierReference { access, .. } => match access {
IdentifierReferenceAccess::Prepare => (0, 1),
IdentifierReferenceAccess::Get | IdentifierReferenceAccess::Call => (0, 2),
IdentifierReferenceAccess::Set => (2, 1),
IdentifierReferenceAccess::PostPut => (3, 1),
},
Self::Identifier {
access:
IdentifierAccess::Get | IdentifierAccess::GetOrUndefined | IdentifierAccess::Delete,
..
} => (0, 1),
Self::Identifier {
access:
IdentifierAccess::Initialize
| IdentifierAccess::InitializeDerivedThis
| IdentifierAccess::Put
| IdentifierAccess::AnnexBPut,
..
} => (1, 0),
Self::Identifier {
access: IdentifierAccess::Set,
..
} => (1, 1),
Self::PrivateField { access, .. } => match access {
PrivateFieldAccess::Get | PrivateFieldAccess::In => (1, 1),
PrivateFieldAccess::GetKeepReceiver => (1, 2),
PrivateFieldAccess::Put => (2, 0),
PrivateFieldAccess::Define => (2, 1),
},
}
}
}
pub(in crate::engine::compiler) mod function;
pub(in crate::engine::compiler) mod operands;