Last active
February 3, 2020 19:12
-
-
Save jorendorff/acd3a48598980072909dad4d754a790d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ================================================================================================ | |
// 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