mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-29 10:03:22 +03:00
Interpreter.
This commit is contained in:
parent
bac534fed4
commit
f2c016782f
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -1561,6 +1561,21 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-interpreter"
|
||||
version = "2.3.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"indexmap 2.6.0",
|
||||
"leo-ast",
|
||||
"leo-errors",
|
||||
"leo-parser",
|
||||
"leo-passes",
|
||||
"leo-span",
|
||||
"snarkvm",
|
||||
"snarkvm-circuit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-lang"
|
||||
version = "2.3.1"
|
||||
@ -1577,6 +1592,7 @@ dependencies = [
|
||||
"leo-ast",
|
||||
"leo-compiler",
|
||||
"leo-errors",
|
||||
"leo-interpreter",
|
||||
"leo-package",
|
||||
"leo-retriever",
|
||||
"leo-span",
|
||||
|
13
Cargo.toml
13
Cargo.toml
@ -38,6 +38,7 @@ members = [
|
||||
"compiler/span",
|
||||
"docs/grammar",
|
||||
"errors",
|
||||
"interpreter",
|
||||
"leo/package",
|
||||
"tests/test-framework",
|
||||
"utils/disassembler",
|
||||
@ -60,6 +61,10 @@ version = "2.3.1"
|
||||
path = "./errors"
|
||||
version = "2.3.1"
|
||||
|
||||
[workspace.dependencies.leo-interpreter]
|
||||
path = "./interpreter"
|
||||
version = "2.3.0"
|
||||
|
||||
[workspace.dependencies.leo-package]
|
||||
path = "./leo/package"
|
||||
version = "2.3.1"
|
||||
@ -84,6 +89,9 @@ version = "2.3.1"
|
||||
version = "0.1.24"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.colored]
|
||||
version = "2.0"
|
||||
|
||||
[workspace.dependencies.indexmap]
|
||||
version = "2.6"
|
||||
features = [ "serde" ]
|
||||
@ -99,6 +107,7 @@ default-features = false
|
||||
version = "1.11.1"
|
||||
|
||||
[workspace.dependencies.snarkvm]
|
||||
# path = "../SnarkVM"
|
||||
version = "1.0.0"
|
||||
|
||||
[workspace.dependencies.serde]
|
||||
@ -145,6 +154,9 @@ workspace = true
|
||||
[dependencies.leo-errors]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-interpreter]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-package]
|
||||
workspace = true
|
||||
|
||||
@ -165,6 +177,7 @@ version = "4.5"
|
||||
features = [ "derive", "env", "color", "unstable-styles" ]
|
||||
|
||||
[dependencies.colored]
|
||||
workspace = true
|
||||
version = "2.0"
|
||||
|
||||
[dependencies.dotenvy]
|
||||
|
@ -22,7 +22,7 @@
|
||||
use crate::{Token, tokenizer::*};
|
||||
|
||||
use leo_ast::*;
|
||||
use leo_errors::{Result, emitter::Handler};
|
||||
use leo_errors::{ParserError, Result, emitter::Handler};
|
||||
use leo_span::{Span, span::BytePos};
|
||||
|
||||
use snarkvm::prelude::Network;
|
||||
@ -49,3 +49,25 @@ pub fn parse<N: Network>(
|
||||
|
||||
tokens.parse_program()
|
||||
}
|
||||
|
||||
pub fn parse_expression<N: Network>(handler: &Handler, node_builder: &NodeBuilder, source: &str) -> Result<Expression> {
|
||||
let mut context = ParserContext::<N>::new(handler, node_builder, crate::tokenize(source, BytePos(0))?);
|
||||
|
||||
let expression = context.parse_expression()?;
|
||||
if context.token.token == Token::Eof {
|
||||
Ok(expression)
|
||||
} else {
|
||||
Err(ParserError::unexpected(context.token.token, Token::Eof, context.token.span).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_statement<N: Network>(handler: &Handler, node_builder: &NodeBuilder, source: &str) -> Result<Statement> {
|
||||
let mut context = ParserContext::<N>::new(handler, node_builder, crate::tokenize(source, BytePos(0))?);
|
||||
|
||||
let statement = context.parse_statement()?;
|
||||
if context.token.token == Token::Eof {
|
||||
Ok(statement)
|
||||
} else {
|
||||
Err(ParserError::unexpected(context.token.token, Token::Eof, context.token.span).into())
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ impl SourceMap {
|
||||
}
|
||||
|
||||
/// Find the source file containing `pos`.
|
||||
fn find_source_file(&self, pos: BytePos) -> Option<Rc<SourceFile>> {
|
||||
pub fn find_source_file(&self, pos: BytePos) -> Option<Rc<SourceFile>> {
|
||||
Some(self.inner.borrow().source_files[self.find_source_file_index(pos)?].clone())
|
||||
}
|
||||
|
||||
|
50
errors/src/errors/interpreter_halt.rs
Normal file
50
errors/src/errors/interpreter_halt.rs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use leo_span::Span;
|
||||
|
||||
/// Represents the interpreter halting, which should not be considered an
|
||||
/// actual runtime error.
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub struct InterpreterHalt {
|
||||
/// Optional Span where the halt occurred.
|
||||
span: Option<Span>,
|
||||
|
||||
/// User visible message.
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl InterpreterHalt {
|
||||
pub fn new(message: String) -> Self {
|
||||
InterpreterHalt { span: None, message }
|
||||
}
|
||||
|
||||
pub fn new_spanned(message: String, span: Span) -> Self {
|
||||
InterpreterHalt { span: Some(span), message }
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InterpreterHalt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.message)
|
||||
}
|
||||
}
|
@ -37,6 +37,9 @@ pub use self::flattener::*;
|
||||
pub mod loop_unroller;
|
||||
pub use self::loop_unroller::*;
|
||||
|
||||
pub mod interpreter_halt;
|
||||
pub use self::interpreter_halt::*;
|
||||
|
||||
/// Contains the Package error definitions.
|
||||
pub mod package;
|
||||
pub use self::package::*;
|
||||
@ -70,6 +73,8 @@ pub enum LeoError {
|
||||
/// Represents a Compiler Error in a Leo Error.
|
||||
#[error(transparent)]
|
||||
CompilerError(#[from] CompilerError),
|
||||
#[error(transparent)]
|
||||
InterpreterHalt(#[from] InterpreterHalt),
|
||||
/// Represents a Package Error in a Leo Error.
|
||||
#[error(transparent)]
|
||||
PackageError(#[from] PackageError),
|
||||
@ -118,6 +123,7 @@ impl LeoError {
|
||||
UtilError(error) => error.error_code(),
|
||||
LastErrorCode(_) => unreachable!(),
|
||||
Anyhow(_) => "SnarkVM Error".to_string(), // todo: implement error codes for snarkvm errors.
|
||||
InterpreterHalt(_) => "Interpreter Halt".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +144,7 @@ impl LeoError {
|
||||
UtilError(error) => error.exit_code(),
|
||||
LastErrorCode(code) => *code,
|
||||
Anyhow(_) => 11000, // todo: implement exit codes for snarkvm errors.
|
||||
InterpreterHalt(_) => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
interpreter/Cargo.toml
Normal file
46
interpreter/Cargo.toml
Normal file
@ -0,0 +1,46 @@
|
||||
[package]
|
||||
name = "leo-interpreter"
|
||||
version = "2.3.0"
|
||||
authors = [ "The Leo Team <leo@provable.com>" ]
|
||||
description = "Interpreter for the Leo programming language"
|
||||
homepage = "https://leo-lang.org"
|
||||
repository = "https://github.com/ProvableHQ/leo"
|
||||
keywords = [
|
||||
"aleo",
|
||||
"cryptography",
|
||||
"leo",
|
||||
"programming-language",
|
||||
"zero-knowledge"
|
||||
]
|
||||
categories = [ "compilers", "cryptography", "web-programming" ]
|
||||
include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
|
||||
license = "GPL-3.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.69"
|
||||
|
||||
[dependencies.snarkvm-circuit]
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies.snarkvm]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-ast]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-passes]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-errors]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-parser]
|
||||
workspace = true
|
||||
|
||||
[dependencies.leo-span]
|
||||
workspace = true
|
||||
|
||||
[dependencies.colored]
|
||||
workspace = true
|
||||
|
||||
[dependencies.indexmap]
|
||||
workspace = true
|
2778
interpreter/src/cursor.rs
Normal file
2778
interpreter/src/cursor.rs
Normal file
File diff suppressed because it is too large
Load Diff
270
interpreter/src/lib.rs
Normal file
270
interpreter/src/lib.rs
Normal file
@ -0,0 +1,270 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{collections::HashMap, fmt::Display, fs, path::Path};
|
||||
|
||||
use colored::*;
|
||||
|
||||
use snarkvm::prelude::TestnetV0;
|
||||
|
||||
use leo_ast::{Ast, Node as _, NodeBuilder};
|
||||
|
||||
use leo_passes::{Pass as _, SymbolTableCreator, TypeChecker, TypeTable};
|
||||
|
||||
use leo_span::{Span, source_map::FileName, symbol::with_session_globals};
|
||||
|
||||
use leo_errors::{CompilerError, InterpreterHalt, LeoError, Result, emitter::Handler};
|
||||
|
||||
mod cursor;
|
||||
use cursor::*;
|
||||
|
||||
pub struct Interpreter {
|
||||
cursor: Cursor<'static>,
|
||||
cursor_initial: Cursor<'static>,
|
||||
actions: Vec<InterpreterAction>,
|
||||
handler: Handler,
|
||||
node_builder: NodeBuilder,
|
||||
breakpoints: Vec<Breakpoint>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Breakpoint {
|
||||
program: String,
|
||||
line: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InterpreterAction {
|
||||
LeoInterpretInto(String),
|
||||
LeoInterpretOver(String),
|
||||
Into,
|
||||
Over,
|
||||
Step,
|
||||
Breakpoint(Breakpoint),
|
||||
Run,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new<'a, P: 'a + AsRef<Path>>(source_files: impl IntoIterator<Item = &'a P>) -> Result<Self> {
|
||||
Self::new_impl(&mut source_files.into_iter().map(|p| p.as_ref()))
|
||||
}
|
||||
|
||||
fn get_ast(path: &Path, handler: &Handler, node_builder: &NodeBuilder) -> Result<Ast> {
|
||||
let text = fs::read_to_string(path).map_err(|e| CompilerError::file_read_error(&path, e))?;
|
||||
let filename = FileName::Real(path.to_path_buf());
|
||||
let source_file = with_session_globals(|s| s.source_map.new_source(&text, filename));
|
||||
leo_parser::parse_ast::<TestnetV0>(handler, node_builder, &text, source_file.start_pos)
|
||||
}
|
||||
|
||||
fn new_impl(source_files: &mut dyn Iterator<Item = &Path>) -> Result<Self> {
|
||||
let handler = Handler::default();
|
||||
let node_builder = Default::default();
|
||||
let mut cursor: Cursor<'_> = Cursor::default();
|
||||
for path in source_files {
|
||||
let ast = Self::get_ast(path, &handler, &node_builder)?;
|
||||
let symbol_table = SymbolTableCreator::do_pass((&ast, &handler))?;
|
||||
let type_table = TypeTable::default();
|
||||
TypeChecker::<TestnetV0>::do_pass((
|
||||
&ast,
|
||||
&handler,
|
||||
symbol_table,
|
||||
&type_table,
|
||||
10, // conditional_block_max_depth
|
||||
false, // disable_conditional_branch_type_checking
|
||||
))?;
|
||||
// TODO: This leak is silly.
|
||||
let ast = Box::leak(Box::new(ast));
|
||||
for (&program, scope) in ast.ast.program_scopes.iter() {
|
||||
for (name, function) in scope.functions.iter() {
|
||||
cursor.functions.insert(GlobalId { program, name: *name }, function);
|
||||
}
|
||||
|
||||
for (name, composite) in scope.structs.iter() {
|
||||
cursor.structs.insert(
|
||||
GlobalId { program, name: *name },
|
||||
composite.members.iter().map(|member| member.identifier.name).collect(),
|
||||
);
|
||||
}
|
||||
|
||||
for (name, _mapping) in scope.structs.iter() {
|
||||
cursor.mappings.insert(GlobalId { program, name: *name }, HashMap::new());
|
||||
}
|
||||
|
||||
for (name, const_declaration) in scope.consts.iter() {
|
||||
cursor.frames.push(Frame {
|
||||
step: 0,
|
||||
element: Element::Expression(&const_declaration.value),
|
||||
user_initiated: false,
|
||||
});
|
||||
cursor.over()?;
|
||||
let value = cursor.values.pop().unwrap();
|
||||
cursor.globals.insert(GlobalId { program, name: *name }, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let cursor_initial = cursor.clone();
|
||||
|
||||
Ok(Interpreter { cursor, cursor_initial, handler, node_builder, actions: Vec::new(), breakpoints: Vec::new() })
|
||||
}
|
||||
|
||||
fn action(&mut self, act: InterpreterAction) -> Result<Option<Value>> {
|
||||
use InterpreterAction::*;
|
||||
|
||||
let ret = match &act {
|
||||
LeoInterpretInto(s) | LeoInterpretOver(s) => {
|
||||
let s = s.trim();
|
||||
if s.ends_with(';') {
|
||||
let statement = leo_parser::parse_statement::<TestnetV0>(&self.handler, &self.node_builder, s)
|
||||
.map_err(|_e| {
|
||||
LeoError::InterpreterHalt(InterpreterHalt::new("failed to parse statement".into()))
|
||||
})?;
|
||||
// TOOD: This leak is silly.
|
||||
let stmt = Box::leak(Box::new(statement));
|
||||
self.cursor.frames.push(Frame { step: 0, element: Element::Statement(stmt), user_initiated: true });
|
||||
} else {
|
||||
let expression = leo_parser::parse_expression::<TestnetV0>(&self.handler, &self.node_builder, s)
|
||||
.map_err(|_e| {
|
||||
LeoError::InterpreterHalt(InterpreterHalt::new("failed to parse expression".into()))
|
||||
})?;
|
||||
// TOOD: This leak is silly.
|
||||
let expr = Box::leak(Box::new(expression));
|
||||
expr.set_span(Default::default());
|
||||
self.cursor.frames.push(Frame {
|
||||
step: 0,
|
||||
element: Element::Expression(expr),
|
||||
user_initiated: true,
|
||||
});
|
||||
};
|
||||
|
||||
if matches!(act, LeoInterpretOver(..)) { self.cursor.over()? } else { self.cursor.step()? }
|
||||
}
|
||||
|
||||
Step => self.cursor.whole_step()?,
|
||||
|
||||
Into => self.cursor.step()?,
|
||||
|
||||
Over => self.cursor.over()?,
|
||||
|
||||
Breakpoint(breakpoint) => {
|
||||
self.breakpoints.push(breakpoint.clone());
|
||||
StepResult { finished: false, value: None }
|
||||
}
|
||||
|
||||
Run => {
|
||||
while !self.cursor.frames.is_empty() {
|
||||
self.cursor.step()?;
|
||||
}
|
||||
StepResult { finished: false, value: None }
|
||||
}
|
||||
};
|
||||
|
||||
self.actions.push(act);
|
||||
|
||||
Ok(ret.value)
|
||||
}
|
||||
|
||||
pub fn view_current(&self) -> Option<impl Display> {
|
||||
if let Some(span) = self.current_span() {
|
||||
if span != Default::default() {
|
||||
return with_session_globals(|s| s.source_map.contents_of_span(span));
|
||||
}
|
||||
}
|
||||
|
||||
Some(match self.cursor.frames.last()?.element {
|
||||
Element::Statement(statement) => format!("{statement}"),
|
||||
Element::Expression(expression) => format!("{expression}"),
|
||||
Element::Block { block, .. } => format!("{block}"),
|
||||
Element::Empty => tc_fail!(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn view_current_in_context(&self) -> Option<impl Display> {
|
||||
let span = self.current_span()?;
|
||||
if span == Default::default() {
|
||||
return None;
|
||||
}
|
||||
with_session_globals(|s| {
|
||||
let source_file = s.source_map.find_source_file(span.lo)?;
|
||||
let first_span = Span::new(source_file.start_pos, span.lo);
|
||||
let last_span = Span::new(span.hi, source_file.end_pos);
|
||||
Some(format!(
|
||||
"{}{}{}",
|
||||
s.source_map.contents_of_span(first_span)?,
|
||||
s.source_map.contents_of_span(span)?.red(),
|
||||
s.source_map.contents_of_span(last_span)?,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn current_span(&self) -> Option<Span> {
|
||||
self.cursor.frames.last().map(|f| f.element.span())
|
||||
}
|
||||
}
|
||||
|
||||
const INSTRUCTIONS: &str = "
|
||||
This is the Leo Interpreter. You probably want to start by running a function or transition.
|
||||
For instance
|
||||
#into program.aleo/main()
|
||||
Once a function is running, commands include
|
||||
#into to evaluate into the next expression or statement;
|
||||
#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.
|
||||
You may also use one letter abbreviations for these commands, such as #i.
|
||||
Finally, you may simply enter expressions or statements on the command line
|
||||
to evaluate. For instance, if you want to see the value of a variable w:
|
||||
w
|
||||
If you want to set w to a new value:
|
||||
w = z + 2u8;
|
||||
";
|
||||
|
||||
pub fn interpret(filenames: &[String]) -> Result<()> {
|
||||
let mut interpreter = Interpreter::new(filenames.iter())?;
|
||||
let mut buffer = String::new();
|
||||
println!("{}", INSTRUCTIONS);
|
||||
loop {
|
||||
buffer.clear();
|
||||
if let Some(v) = interpreter.view_current_in_context() {
|
||||
println!("{v}");
|
||||
} else if let Some(v) = interpreter.view_current() {
|
||||
println!("{v}");
|
||||
}
|
||||
std::io::stdin().read_line(&mut buffer).expect("read_line");
|
||||
let action = match buffer.trim() {
|
||||
"#i" | "#into" => InterpreterAction::Into,
|
||||
"#s" | "#step" => InterpreterAction::Step,
|
||||
"#o" | "#over" => InterpreterAction::Over,
|
||||
"#r" | "#run" => InterpreterAction::Run,
|
||||
"#q" | "#quit" => return Ok(()),
|
||||
s => {
|
||||
if let Some(rest) = s.strip_prefix("#into ").or(s.strip_prefix("#i ")) {
|
||||
InterpreterAction::LeoInterpretInto(rest.trim().into())
|
||||
} else {
|
||||
InterpreterAction::LeoInterpretOver(s.trim().into())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match interpreter.action(action) {
|
||||
Ok(Some(value)) => println!("result: {value}"),
|
||||
Ok(None) => {}
|
||||
Err(LeoError::InterpreterHalt(interpreter_halt)) => println!("Halted: {interpreter_halt}"),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
@ -82,6 +82,11 @@ enum Commands {
|
||||
#[clap(flatten)]
|
||||
command: LeoBuild,
|
||||
},
|
||||
#[clap(about = "Interpret the current package")]
|
||||
Interpret {
|
||||
#[clap(flatten)]
|
||||
command: LeoInterpret,
|
||||
},
|
||||
#[clap(about = "Add a new on-chain or local dependency to the current package.")]
|
||||
Add {
|
||||
#[clap(flatten)]
|
||||
@ -138,6 +143,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
|
||||
Commands::Account { command } => command.try_execute(context),
|
||||
Commands::New { command } => command.try_execute(context),
|
||||
Commands::Build { command } => command.try_execute(context),
|
||||
Commands::Interpret { command } => command.try_execute(context),
|
||||
Commands::Query { command } => command.try_execute(context),
|
||||
Commands::Clean { command } => command.try_execute(context),
|
||||
Commands::Deploy { command } => command.try_execute(context),
|
||||
|
42
leo/cli/commands/interpret.rs
Normal file
42
leo/cli/commands/interpret.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Deploys an Aleo program.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct LeoInterpret {
|
||||
#[clap(long)]
|
||||
pub(crate) files: Vec<String>,
|
||||
}
|
||||
|
||||
impl Command for LeoInterpret {
|
||||
type Input = ();
|
||||
type Output = ();
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
leo_interpreter::interpret(&self.files)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -35,6 +35,9 @@ pub use example::LeoExample;
|
||||
pub mod execute;
|
||||
pub use execute::LeoExecute;
|
||||
|
||||
pub mod interpret;
|
||||
pub use interpret::LeoInterpret;
|
||||
|
||||
pub mod query;
|
||||
pub use query::LeoQuery;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user