MCPcopy Index your code
hub / github.com/endbasic/endbasic / prepare_globals

Function prepare_globals

core/src/compiler/top.rs:1247–1320  ·  view source on GitHub ↗

Prepares global variables injected from outside of the compiled program. Pre-defined scalar globals are initialized to their default values (0 for numeric types, empty string for text). Pre-defined array globals are allocated with all elements set to their default values. The compiled program may read or write any of these globals. After execution, use `Vm::get_global*` methods to query the va

(
    ctx: &mut Context,
    symtable: &mut GlobalSymtable,
    global_defs: &[GlobalDef],
)

Source from the content-addressed store, hash-verified

1245/// After execution, use `Vm::get_global*` methods to query the values of these globals (and
1246/// any globals declared via `DIM SHARED` in the program itself).
1247pub(super) fn prepare_globals(
1248 ctx: &mut Context,
1249 symtable: &mut GlobalSymtable,
1250 global_defs: &[GlobalDef],
1251) -> Result<()> {
1252 let preamble_pos = LineCol { line: 0, col: 0 };
1253
1254 // Register all global defs in the symbol table and collect array globals for the preamble.
1255 let mut max_ndims: u8 = 0;
1256 let mut array_globals: Vec<(Register, &GlobalDef)> = vec![];
1257 for def in global_defs {
1258 let key = SymbolKey::from(&def.name);
1259 match &def.kind {
1260 GlobalDefKind::Array { subtype, dimensions } => {
1261 let ndims =
1262 u8::try_from(dimensions.len()).expect("Array must have at most 255 dimensions");
1263 let info = syms::ArrayInfo { subtype: *subtype, ndims: usize::from(ndims) };
1264 let reg = symtable
1265 .put_global(key, SymbolPrototype::Array(info))
1266 .map_err(|e| Error::from_syms(e, preamble_pos))?;
1267 max_ndims = max(max_ndims, ndims);
1268 array_globals.push((reg, def));
1269 }
1270
1271 GlobalDefKind::Scalar { etype, initial_value } => {
1272 let reg = symtable
1273 .put_global(key, SymbolPrototype::Scalar(*etype))
1274 .map_err(|e| Error::from_syms(e, preamble_pos))?;
1275 match initial_value {
1276 Some(datum) => {
1277 if datum.etype() != *etype {
1278 return Err(Error::TypeMismatch(preamble_pos, datum.etype(), *etype));
1279 }
1280 ctx.codegen.emit_value(reg, datum.clone(), preamble_pos)?;
1281 }
1282 None => ctx.codegen.emit_default(reg, *etype, preamble_pos),
1283 }
1284 }
1285 }
1286 }
1287
1288 // Emit the array initialization preamble, but only if any arrays were defined.
1289 //
1290 // We use a short-lived `ENTER/LEAVE` scope to borrow local registers for the dimension
1291 // temporaries without permanently consuming global register slots.
1292 if array_globals.is_empty() {
1293 // `compile` starts by popping an EOF, so make sure there is one.
1294 ctx.codegen.emit(bytecode::make_eof(), preamble_pos);
1295 return Ok(());
1296 }
1297 for (reg, def) in array_globals {
1298 let GlobalDefKind::Array { subtype, dimensions } = &def.kind else {
1299 unreachable!("array_globals only contains array defs per the loop above")
1300 };
1301
1302 let ndims = u8::try_from(dimensions.len()).unwrap();
1303 for (i, &dim) in dimensions.iter().enumerate() {
1304 let dim_u16 =

Callers 1

newMethod · 0.85

Calls 10

put_globalMethod · 0.80
pushMethod · 0.80
etypeMethod · 0.80
emit_valueMethod · 0.80
emit_defaultMethod · 0.80
emitMethod · 0.80
iterMethod · 0.80
lenMethod · 0.45
is_emptyMethod · 0.45
enumerateMethod · 0.45

Tested by

no test coverage detected