Skip to content

Instantly share code, notes, and snippets.

@jorendorff
Last active February 3, 2020 19:12
Show Gist options
  • Save jorendorff/acd3a48598980072909dad4d754a790d to your computer and use it in GitHub Desktop.
Save jorendorff/acd3a48598980072909dad4d754a790d to your computer and use it in GitHub Desktop.
// ================================================================================================
// Types that describe stack slots
struct Value;
struct NewObjectValue;
struct PackedArrayValue;
struct FunctionValue;
struct StringValue;
struct UninitializedMagic;
// ================================================================================================
// Types that describe the stack
struct Stack1<S, A>(S, A);
type Stack2<S, A, B> = Stack1<Stack1<S, A>, B>;
//...
// A separate type is used to type-check extremely special stack
// entries that shouldn't be consumed as if they were just values.
struct StackWithGosubData<S>(S); // the gosub return address is Very Not A Value
struct StackWithReference<S>(S); // assignment targets can be 0, 1, or 2 stack slots
// ================================================================================================
// Trait that describes anything that can be (safely) converted to bytecode
trait Emittable<StackBefore> {
type StackAfter;
fn write_to(&self, &mut BytecodeWriter);
}
// ================================================================================================
// Examples of stuff you can emit
// 1. individual bytecode instructions (and these can be macro-generated)
struct GetElem; // Representing the JSOp::GetElem opcode
impl<S> Emittable<Stack2<S, Value, Value>> for GetElem {
type StackAfter = Stack1<S, Value>;
fn write_to(&self, out: &mut BytecodeWriter) {
out.get_elem();
}
}
// 2. at least concatenation, maybe other combinators
struct Concat<A: Emittable, B: Emittable>(A, B);
impl<A, B> Emittable<S0> for Concat<A, B>
where
A: Emittable<S0>,
B: Emittable<<A as Emittable<S0>>::StackAfter>,
{
type StackAfter = <B as Emittable<<A as Emittable<S0>>::StackAfter>>::StackAfter;
//...
}
// 3. certain AST node types (expressions, statements)
struct GetValueOfExpr<'a>(&'a ast::Expression);
// Expressions always have the same effect on the stack: read nothing, push 1 value
impl<'a, S> Emittable<S> for GetValueOfExpr<'a> {
type StackAfter = Stack1<S, Value>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment