[][src]Struct chrysanthemum::compile::CContext

pub struct CContext {
    pub b: Builder,
    pub typetable: FnvHashMap<TypeDef, Word>,
    pub consts: FnvHashMap<Lit, Word>,
    pub symtable: Vec<FnvHashMap<String, VarBinding>>,
}

Compilation context, containing the SPIRV builder and such.

Fields

b: Builder

SPIR-V builder. Sticking something in it involves no caching or anything, so to get rid of duplicate decl's we also have...

typetable: FnvHashMap<TypeDef, Word>

A type table, that maps type definitions to their decl's in the builder.

consts: FnvHashMap<Lit, Word>

Constants, maps literal values to declared words.

symtable: Vec<FnvHashMap<String, VarBinding>>

Here's the actual scoping mechanism, a stack of name -> Word associations that go from variable or parameter names to the associated Word.

Methods

impl CContext[src]

pub fn new() -> Self[src]

pub fn push_scope(&mut self)[src]

Pushes a new scope to the symbol table.

pub fn bind_var(&mut self, name: &str, address: Word, typedef: Word)[src]

Binds the variable to the current scope. Will overwrite any previous binding. That's fine.

Panics if no scope.

pub fn lookup_var(&self, name: &str) -> &VarBinding[src]

Returns the Word bound to the given var name, or panics if not found. All unknown vars should get caught by the validation step.

pub fn pop_scope(&mut self)[src]

Pops the top scope from the symbol table. Panics on underflow.

TODO: Just use Rust's scoping and destruction to do this? Meh.

pub fn define_const(&mut self, vl: Lit) -> Word[src]

Defines a constant for a literal value

pub fn get_type(&self, t: &TypeDef) -> Word[src]

Panics if the type does not exist.

TODO: Should this take a name and a VContext instead of a TypeDef?

pub fn add_type(&mut self, typedef: &TypeDef) -> Word[src]

Add a type to the type table, recursively if necessary. Will also actually build the type into the SPIR-V builder.

Returns the Word that is a handle to the defined type. If the type already exists, it will not duplicate it, just return the previous word.

We do not track the types' names here, just the signatures, so two identical type defs will get coalesced to one. This may or may not be a good idea, debugging might want separate types referring to the same name.

If we DO want to do that (and I'm leaning towards yes) we need to add the various OpName instructions here.

pub fn compile_expr(&mut self, e: &Expr, ctx: &VContext) -> Result<Word, Error>[src]

Returns the Word holding the result fo the expression.

pub fn compile_inferred_binop(
    &mut self,
    op: Op,
    t1: &TypeDef,
    t2: &TypeDef,
    e1: Word,
    e2: Word
) -> Word
[src]

Infers the proper instruction to emit based on the types given and the op, and outputs the appropriate instruction, returning its result address. So we can use + to add floats or vec4's and it works correctly.

Panics if the types are not correct, such as adding a float and a bool.

pub fn compile_inferred_uniop(&mut self, op: UOp, t: &TypeDef, e: Word) -> Word[src]

Same as compile_inferred_binop but for unary operations

pub fn compile_function(
    &mut self,
    ctx: &VContext,
    def: &FunctionDef
) -> Result<(), Error>
[src]

Auto Trait Implementations

Blanket Implementations

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]