Gets the register and prototype of a local or global variable if it already exists.
(
vref: &VarRef,
table: &HashMapWithIds<SymbolKey, SymbolPrototype, u8>,
make_register: MKR,
scope: RegisterScope,
)
| 88 | |
| 89 | /// Gets the register and prototype of a local or global variable if it already exists. |
| 90 | fn get_var<MKR>( |
| 91 | vref: &VarRef, |
| 92 | table: &HashMapWithIds<SymbolKey, SymbolPrototype, u8>, |
| 93 | make_register: MKR, |
| 94 | scope: RegisterScope, |
| 95 | ) -> Result<(Register, SymbolPrototype)> |
| 96 | where |
| 97 | MKR: FnOnce(u8) -> std::result::Result<Register, bytecode::OutOfRegistersError>, |
| 98 | { |
| 99 | let key = SymbolKey::from(&vref.name); |
| 100 | match table.get(&key) { |
| 101 | Some((SymbolPrototype::Array(info), reg)) => { |
| 102 | if !vref.accepts(info.subtype) { |
| 103 | return Err(Error::IncompatibleTypeAnnotationInReference(vref.clone())); |
| 104 | } |
| 105 | |
| 106 | let reg = make_register(reg).map_err(|_| Error::OutOfRegisters(scope))?; |
| 107 | Ok((reg, SymbolPrototype::Array(*info))) |
| 108 | } |
| 109 | |
| 110 | Some((SymbolPrototype::Scalar(etype), reg)) => { |
| 111 | if !vref.accepts(*etype) { |
| 112 | return Err(Error::IncompatibleTypeAnnotationInReference(vref.clone())); |
| 113 | } |
| 114 | |
| 115 | let reg = make_register(reg).map_err(|_| Error::OutOfRegisters(scope))?; |
| 116 | Ok((reg, SymbolPrototype::Scalar(*etype))) |
| 117 | } |
| 118 | |
| 119 | None => Err(Error::UndefinedSymbol(vref.clone(), scope)), |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | /// Defines a new local or global variable (or array) and assigns a register to it. |
| 124 | /// |
no test coverage detected