setting top level values

This commit is contained in:
Michael Benfield 2024-11-21 13:29:00 -08:00
parent 334881cef5
commit 94638be01a
2 changed files with 32 additions and 18 deletions

View File

@ -245,6 +245,8 @@ pub struct Cursor<'a> {
/// Consts are stored here.
pub globals: HashMap<GlobalId, Value>,
pub user_values: HashMap<Symbol, Value>,
pub mappings: HashMap<GlobalId, HashMap<Value, Value>>,
/// For each struct type, we only need to remember the names of its members, in order.
@ -271,6 +273,7 @@ impl<'a> Cursor<'a> {
values: Default::default(),
functions: Default::default(),
globals: Default::default(),
user_values: Default::default(),
mappings: Default::default(),
structs: Default::default(),
contexts: Default::default(),
@ -310,16 +313,15 @@ impl<'a> Cursor<'a> {
}
fn lookup(&self, name: Symbol) -> Option<Value> {
let Some(context) = self.contexts.last() else {
panic!("lookup requires a context");
};
let option_value = context.names.get(&name);
if let Some(context) = self.contexts.last() {
let option_value =
context.names.get(&name).or_else(|| self.globals.get(&GlobalId { program: context.program, name }));
if option_value.is_some() {
return option_value.cloned();
}
};
self.globals.get(&GlobalId { program: context.program, name }).cloned()
self.user_values.get(&name).cloned()
}
pub fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
@ -340,6 +342,14 @@ impl<'a> Cursor<'a> {
self.functions.get(&GlobalId { program, name }).cloned()
}
fn set_variable(&mut self, symbol: Symbol, value: Value) {
if self.contexts.len() > 0 {
self.contexts.set(symbol, value);
} else {
self.user_values.insert(symbol, value);
}
}
/// Execute the whole step of the current Element.
///
/// That is, perform a step, and then finish all statements and expressions that have been pushed,
@ -462,7 +472,7 @@ impl<'a> Cursor<'a> {
Statement::Assign(assign) if step == 1 => {
let value = self.values.pop().unwrap();
let Expression::Identifier(id) = &assign.place else { tc_fail!() };
self.contexts.set(id.name, value);
self.set_variable(id.name, value);
true
}
Statement::Block(block) => return Ok(self.step_block(block, false, step)),
@ -494,7 +504,7 @@ impl<'a> Cursor<'a> {
}
Statement::Const(const_) if step == 1 => {
let value = self.pop_value()?;
self.contexts.set(const_.place.name, value);
self.set_variable(const_.place.name, value);
true
}
Statement::Definition(definition) if step == 0 => {
@ -504,7 +514,7 @@ impl<'a> Cursor<'a> {
Statement::Definition(definition) if step == 1 => {
let value = self.pop_value()?;
match &definition.place {
Expression::Identifier(id) => self.contexts.set(id.name, value),
Expression::Identifier(id) => self.set_variable(id.name, value),
Expression::Tuple(tuple) => {
let Value::Tuple(rhs) = value else {
tc_fail!();
@ -513,7 +523,7 @@ impl<'a> Cursor<'a> {
let Expression::Identifier(id) = name else {
tc_fail!();
};
self.contexts.set(id.name, val);
self.set_variable(id.name, val);
}
}
_ => tc_fail!(),
@ -542,7 +552,7 @@ impl<'a> Cursor<'a> {
true
} else {
let new_start = start.inc_wrapping();
self.contexts.set(iteration.variable.name, start);
self.set_variable(iteration.variable.name, start);
self.frames.push(Frame {
step: 0,
element: Element::Block { block: &iteration.block, function_body: false },
@ -906,15 +916,15 @@ impl<'a> Cursor<'a> {
FunctionVariant::Leo(function) => {
assert!(function.variant == Variant::AsyncFunction);
let len = self.values.len();
let values_iter = self.values.drain(len - function.input.len()..);
let values: Vec<Value> = self.values.drain(len - function.input.len()..).collect();
self.contexts.push(
gid.program,
self.signer,
true, // is_async
);
let param_names = function.input.iter().map(|input| input.identifier.name);
for (name, value) in param_names.zip(values_iter) {
self.contexts.set(name, value);
for (name, value) in param_names.zip(values) {
self.set_variable(name, value);
}
self.frames.last_mut().unwrap().step = 1;
self.frames.push(Frame {
@ -995,7 +1005,7 @@ impl<'a> Cursor<'a> {
self.contexts.push(function_program, caller, is_async);
let param_names = function.input.iter().map(|input| input.identifier.name);
for (name, value) in param_names.zip(arguments) {
self.contexts.set(name, value);
self.set_variable(name, value);
}
self.frames.push(Frame {
step: 0,

View File

@ -399,11 +399,14 @@ Once a function is running, commands include
#step to take one step towards evaluating the current expression or statement;
#over to complete evaluating the current expression or statement;
#run to finish evaluating
#quit to exit the interpreter.
#quit to quit the interpreter.
You can set a breakpoint with
#break program_name line_number
When executing Aleo VM code, you can print the value of a register like this:
#print 2
You may also use one letter abbreviations for these commands, such as #i.
You may simply enter expressions or statements on the command line
@ -541,6 +544,7 @@ pub fn interpret(
}
std::io::stdin().read_line(&mut buffer).expect("read_line");
let action = match buffer.trim() {
"" => continue,
"#i" | "#into" => InterpreterAction::Into,
"#s" | "#step" => InterpreterAction::Step,
"#o" | "#over" => InterpreterAction::Over,