[fine] lets can be local or global

This commit is contained in:
John Doty 2024-01-09 09:17:37 -08:00
parent fa53841af9
commit f8f5c9bfac
2 changed files with 32 additions and 8 deletions

View file

@ -29,6 +29,7 @@ pub enum Instruction {
PushString(usize),
PushTrue,
StoreLocal(usize),
StoreModule(usize),
}
pub enum Export {
@ -308,7 +309,10 @@ fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> O
assert!(declaration.index < c.function.args);
Instruction::LoadArgument(declaration.index)
}
Location::Module => Instruction::LoadModule(declaration.index),
Location::Module => {
assert!(declaration.index < c.module.globals);
Instruction::LoadModule(declaration.index)
}
};
c.push(instruction);
@ -371,9 +375,22 @@ fn compile_let_statement(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_value: b
let environment = c.semantics.environment_of(t);
let declaration = environment.bind(tree.nth_token(1)?)?;
// NOTE: Because this is a let statement I assume it's local!
assert!(matches!(declaration.location, Location::Local));
c.push(Instruction::StoreLocal(declaration.index));
let instruction = match declaration.location {
Location::Local => {
if declaration.index >= c.function.locals {
c.function.locals = declaration.index + 1;
}
Instruction::StoreLocal(declaration.index)
}
Location::Module => {
if declaration.index >= c.module.globals {
c.module.globals = declaration.index + 1;
}
Instruction::StoreModule(declaration.index)
}
_ => panic!("unsuitable location for let declaration"),
};
c.push(instruction);
if gen_value {
c.push(Instruction::PushNothing);
}

View file

@ -424,12 +424,19 @@ impl<'a> Semantics<'a> {
None => Type::Error,
};
let base_index = match parent.location {
Location::Local => parent.base_index + parent.declarations.len(),
_ => 0,
let (location, base_index) = match parent.location {
Location::Local => (
Location::Local,
parent.base_index + parent.declarations.len(),
),
Location::Module => (
Location::Module,
parent.base_index + parent.declarations.len(),
),
Location::Argument => (Location::Local, 0),
};
let mut environment = Environment::new(Some(parent), Location::Local, base_index);
let mut environment = Environment::new(Some(parent), location, base_index);
environment.insert(name, declaration_type);
EnvironmentRef::new(environment)