mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 02:31:44 +03:00
Merge with testnet3.
This commit is contained in:
commit
4002ad8215
@ -16,7 +16,7 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
/// A function call expression, e.g., `foo(args)` or `Foo::bar(args)`.
|
||||
/// A function call expression, e.g.`foo(args)` or `Foo::bar(args)`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CallExpression {
|
||||
/// An expression evaluating to a callable function,
|
||||
@ -24,13 +24,23 @@ pub struct CallExpression {
|
||||
pub function: Box<Expression>, // todo: make this identifier?
|
||||
/// Expressions for the arguments passed to the functions parameters.
|
||||
pub arguments: Vec<Expression>,
|
||||
/// The name of the external program call, e.g.`bar` in `bar.leo`.
|
||||
pub external: Option<Box<Expression>>,
|
||||
/// Span of the entire call `function(arguments)`.
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Display for CallExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}(", self.function)?;
|
||||
match &self.external {
|
||||
Some(external) => {
|
||||
write!(f, "{}.leo/{}(", external, self.function)?;
|
||||
}
|
||||
None => {
|
||||
write!(f, "{}(", self.function)?;
|
||||
}
|
||||
}
|
||||
|
||||
for (i, param) in self.arguments.iter().enumerate() {
|
||||
write!(f, "{}", param)?;
|
||||
if i < self.arguments.len() - 1 {
|
||||
|
52
compiler/ast/src/functions/external.rs
Normal file
52
compiler/ast/src/functions/external.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2019-2022 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 crate::{Identifier, Node, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// A function output from an external program with type record.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct External {
|
||||
/// The name the parameter is accessible as in the function's body.
|
||||
pub identifier: Identifier,
|
||||
/// The name of the external program.
|
||||
pub program_name: Identifier,
|
||||
/// The name of the external record type.
|
||||
pub record: Identifier,
|
||||
/// The parameters span from any annotations to its type.
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl External {
|
||||
pub fn type_(&self) -> Type {
|
||||
Type::Identifier(self.record)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for External {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}: {}.leo/{}.record",
|
||||
self.identifier, self.program_name, self.record
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
crate::simple_node_impl!(External);
|
@ -14,7 +14,7 @@
|
||||
// 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 crate::{Block, FunctionInput, FunctionOutput, Identifier, Node, Tuple, Type};
|
||||
use crate::{Block, Identifier, Input, Node, Output, Tuple, Type};
|
||||
|
||||
use leo_span::Span;
|
||||
|
||||
@ -27,9 +27,9 @@ pub struct Finalize {
|
||||
/// The finalize identifier.
|
||||
pub identifier: Identifier,
|
||||
/// The finalize block's input parameters.
|
||||
pub input: Vec<FunctionInput>,
|
||||
pub input: Vec<Input>,
|
||||
/// The finalize blocks's output declaration.
|
||||
pub output: Vec<FunctionOutput>,
|
||||
pub output: Vec<Output>,
|
||||
/// The finalize block's output type.
|
||||
pub output_type: Type,
|
||||
/// The body of the function.
|
||||
@ -40,17 +40,11 @@ pub struct Finalize {
|
||||
|
||||
impl Finalize {
|
||||
/// Create a new finalize block.
|
||||
pub fn new(
|
||||
identifier: Identifier,
|
||||
input: Vec<FunctionInput>,
|
||||
output: Vec<FunctionOutput>,
|
||||
block: Block,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
pub fn new(identifier: Identifier, input: Vec<Input>, output: Vec<Output>, block: Block, span: Span) -> Self {
|
||||
let output_type = match output.len() {
|
||||
0 => Type::Unit,
|
||||
1 => output[0].type_.clone(),
|
||||
_ => Type::Tuple(Tuple(output.iter().map(|output| output.type_.clone()).collect())),
|
||||
1 => output[0].type_(),
|
||||
_ => Type::Tuple(Tuple(output.iter().map(|output| output.type_()).collect())),
|
||||
};
|
||||
|
||||
Self {
|
||||
|
@ -14,14 +14,74 @@
|
||||
// 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 crate::{Identifier, Mode, Node, Type};
|
||||
use crate::{External, Identifier, Mode, Node, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Input {
|
||||
Internal(FunctionInput),
|
||||
External(External),
|
||||
}
|
||||
|
||||
impl fmt::Display for Input {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.fmt(f),
|
||||
External(input) => input.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn type_(&self) -> Type {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.type_.clone(),
|
||||
External(input) => input.type_(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identifier(&self) -> Identifier {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.identifier,
|
||||
External(input) => input.identifier,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> Mode {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.mode,
|
||||
External(_) => Mode::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for Input {
|
||||
fn span(&self) -> Span {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.span(),
|
||||
External(input) => input.span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
use Input::*;
|
||||
match self {
|
||||
Internal(input) => input.set_span(span),
|
||||
External(input) => input.set_span(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A function parameter.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FunctionInput {
|
||||
/// The name the parameter is accessible as in the function's body.
|
||||
pub identifier: Identifier,
|
||||
|
@ -14,14 +14,64 @@
|
||||
// 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 crate::{Mode, Node, Type};
|
||||
use crate::{External, Mode, Node, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// A function parameter.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Output {
|
||||
Internal(FunctionOutput),
|
||||
External(External),
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn type_(&self) -> Type {
|
||||
match self {
|
||||
Output::Internal(output) => output.type_.clone(),
|
||||
Output::External(output) => output.type_(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> Mode {
|
||||
match self {
|
||||
Output::Internal(output) => output.mode,
|
||||
Output::External(_) => Mode::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Output {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Output::*;
|
||||
match self {
|
||||
Internal(output) => output.fmt(f),
|
||||
External(output) => output.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for Output {
|
||||
fn span(&self) -> Span {
|
||||
use Output::*;
|
||||
match self {
|
||||
Internal(output) => output.span(),
|
||||
External(output) => output.span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
use Output::*;
|
||||
match self {
|
||||
Internal(output) => output.set_span(span),
|
||||
External(output) => output.set_span(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A function output.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FunctionOutput {
|
||||
/// The mode of the function output.
|
||||
pub mode: Mode,
|
||||
|
@ -17,6 +17,9 @@
|
||||
pub mod annotation;
|
||||
pub use annotation::*;
|
||||
|
||||
pub mod external;
|
||||
pub use external::*;
|
||||
|
||||
pub mod finalize;
|
||||
pub use finalize::*;
|
||||
|
||||
@ -43,9 +46,9 @@ pub struct Function {
|
||||
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
|
||||
pub identifier: Identifier,
|
||||
/// The function's input parameters.
|
||||
pub input: Vec<FunctionInput>,
|
||||
pub input: Vec<Input>,
|
||||
/// The function's output declarations.
|
||||
pub output: Vec<FunctionOutput>,
|
||||
pub output: Vec<Output>,
|
||||
/// The function's output type.
|
||||
pub output_type: Type,
|
||||
/// The body of the function.
|
||||
@ -69,17 +72,22 @@ impl Function {
|
||||
pub fn new(
|
||||
annotations: Vec<Annotation>,
|
||||
identifier: Identifier,
|
||||
input: Vec<FunctionInput>,
|
||||
output: Vec<FunctionOutput>,
|
||||
input: Vec<Input>,
|
||||
output: Vec<Output>,
|
||||
block: Block,
|
||||
finalize: Option<Finalize>,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
// Determine the output type of the function
|
||||
let get_output_type = |output: &Output| match &output {
|
||||
Output::Internal(output) => output.type_.clone(),
|
||||
Output::External(output) => output.type_(),
|
||||
};
|
||||
|
||||
let output_type = match output.len() {
|
||||
0 => Type::Unit,
|
||||
1 => output[0].type_.clone(),
|
||||
_ => Type::Tuple(Tuple(output.iter().map(|output| output.type_.clone()).collect())),
|
||||
1 => get_output_type(&output[0]),
|
||||
_ => Type::Tuple(Tuple(output.iter().map(|output| get_output_type(output)).collect())),
|
||||
};
|
||||
|
||||
Function {
|
||||
|
@ -21,11 +21,11 @@ use leo_errors::{AstError, Result};
|
||||
|
||||
/// Input data which includes [`ProgramInput`].
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Input {
|
||||
pub struct InputData {
|
||||
pub program_input: ProgramInput,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
impl InputData {
|
||||
/// Serializes the ast into a JSON string.
|
||||
pub fn to_json_string(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string_pretty(&self).map_err(|e| AstError::failed_to_convert_ast_to_json_string(&e))?)
|
||||
|
@ -91,6 +91,7 @@ pub trait ExpressionReconstructor {
|
||||
.into_iter()
|
||||
.map(|arg| self.reconstruct_expression(arg).0)
|
||||
.collect(),
|
||||
external: input.external,
|
||||
span: input.span,
|
||||
}),
|
||||
Default::default(),
|
||||
@ -362,7 +363,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
}
|
||||
|
||||
fn reconstruct_import(&mut self, input: Program) -> Program {
|
||||
input
|
||||
self.reconstruct_program(input)
|
||||
}
|
||||
|
||||
fn reconstruct_mapping(&mut self, input: Mapping) -> Mapping {
|
||||
|
@ -31,7 +31,7 @@ pub(crate) use tokenizer::*;
|
||||
pub mod parser;
|
||||
pub use parser::*;
|
||||
|
||||
use leo_ast::{Ast, Input, ProgramInput};
|
||||
use leo_ast::{input::InputData, Ast, ProgramInput};
|
||||
use leo_errors::emitter::Handler;
|
||||
use leo_errors::Result;
|
||||
|
||||
@ -44,8 +44,8 @@ pub fn parse_ast(handler: &Handler, source: &str, start_pos: BytePos) -> Result<
|
||||
}
|
||||
|
||||
/// Parses program inputs from from the input file path and state file path
|
||||
pub fn parse_program_inputs(handler: &Handler, input_string: &str, start_pos: BytePos) -> Result<Input> {
|
||||
pub fn parse_program_inputs(handler: &Handler, input_string: &str, start_pos: BytePos) -> Result<InputData> {
|
||||
let program_input: ProgramInput = parser::parse_input(handler, input_string, start_pos)?.try_into()?;
|
||||
|
||||
Ok(Input { program_input })
|
||||
Ok(InputData { program_input })
|
||||
}
|
||||
|
@ -364,6 +364,21 @@ impl ParserContext<'_> {
|
||||
index,
|
||||
span,
|
||||
}))
|
||||
} else if self.eat(&Token::Leo) {
|
||||
// Eat an external function call.
|
||||
self.eat(&Token::Div); // todo: Make `/` a more general token.
|
||||
|
||||
// Parse function name.
|
||||
let name = self.expect_identifier()?;
|
||||
|
||||
// Parse the function call.
|
||||
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
||||
expr = Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(Expression::Identifier(name)),
|
||||
external: Some(Box::new(expr)),
|
||||
arguments,
|
||||
});
|
||||
} else {
|
||||
// Parse identifier name.
|
||||
let name = self.expect_identifier()?;
|
||||
@ -389,6 +404,7 @@ impl ParserContext<'_> {
|
||||
expr = Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(expr),
|
||||
external: None,
|
||||
arguments,
|
||||
});
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ use super::*;
|
||||
use crate::parse_ast;
|
||||
use leo_errors::{CompilerError, ParserError, ParserWarning, Result};
|
||||
use leo_span::source_map::FileName;
|
||||
use leo_span::sym;
|
||||
use leo_span::symbol::with_session_globals;
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
use std::fs;
|
||||
|
||||
@ -95,12 +95,11 @@ impl ParserContext<'_> {
|
||||
|
||||
// Parse `.leo`.
|
||||
self.expect(&Token::Dot)?;
|
||||
let leo_file_extension = self.expect_identifier()?;
|
||||
|
||||
// Throw error for non-leo files.
|
||||
if leo_file_extension.name.ne(&sym::leo) {
|
||||
return Err(ParserError::leo_imports_only(leo_file_extension, self.token.span).into());
|
||||
if !self.eat(&Token::Leo) {
|
||||
// Throw error for non-leo files.
|
||||
return Err(ParserError::leo_imports_only(self.token.span).into());
|
||||
}
|
||||
|
||||
let _end = self.expect(&Token::Semicolon)?;
|
||||
|
||||
// Tokenize and parse import file.
|
||||
@ -284,16 +283,45 @@ impl ParserContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [`FunctionInput`] AST node if the next tokens represent a function parameter.
|
||||
fn parse_function_input(&mut self) -> Result<FunctionInput> {
|
||||
/// Returns a [`Input`] AST node if the next tokens represent a function output.
|
||||
fn parse_input(&mut self) -> Result<functions::Input> {
|
||||
let mode = self.parse_mode()?;
|
||||
let (name, type_) = self.parse_typed_ident()?;
|
||||
Ok(FunctionInput {
|
||||
identifier: name,
|
||||
mode,
|
||||
type_,
|
||||
span: name.span,
|
||||
})
|
||||
let name = self.expect_identifier()?;
|
||||
self.expect(&Token::Colon)?;
|
||||
|
||||
if self.peek_is_external() {
|
||||
let external = self.expect_identifier()?;
|
||||
let mut span = name.span + external.span;
|
||||
|
||||
// Parse `.leo/`.
|
||||
self.eat(&Token::Dot);
|
||||
self.eat(&Token::Leo);
|
||||
self.eat(&Token::Div);
|
||||
|
||||
// Parse record name.
|
||||
let record = self.expect_identifier()?;
|
||||
|
||||
// Parse `.record`.
|
||||
self.eat(&Token::Dot);
|
||||
self.eat(&Token::Record);
|
||||
span = span + self.prev_token.span;
|
||||
|
||||
Ok(functions::Input::External(External {
|
||||
identifier: name,
|
||||
program_name: external,
|
||||
record,
|
||||
span,
|
||||
}))
|
||||
} else {
|
||||
let type_ = self.parse_type()?.0;
|
||||
|
||||
Ok(functions::Input::Internal(FunctionInput {
|
||||
identifier: name,
|
||||
mode,
|
||||
type_,
|
||||
span: name.span,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [`FunctionOutput`] AST node if the next tokens represent a function output.
|
||||
@ -304,6 +332,43 @@ impl ParserContext<'_> {
|
||||
Ok(FunctionOutput { mode, type_, span })
|
||||
}
|
||||
|
||||
/// Returns a [`Output`] AST node if the next tokens represent a function output.
|
||||
fn parse_output(&mut self) -> Result<Output> {
|
||||
if self.peek_is_external() {
|
||||
let external = self.expect_identifier()?;
|
||||
let mut span = external.span;
|
||||
|
||||
// Parse `.leo/`.
|
||||
self.eat(&Token::Dot);
|
||||
self.eat(&Token::Leo);
|
||||
self.eat(&Token::Div);
|
||||
|
||||
// Parse record name.
|
||||
let record = self.expect_identifier()?;
|
||||
|
||||
// Parse `.record`.
|
||||
self.eat(&Token::Dot);
|
||||
self.eat(&Token::Record);
|
||||
span = span + self.prev_token.span;
|
||||
|
||||
Ok(Output::External(External {
|
||||
identifier: Identifier::new(Symbol::intern("dummy")),
|
||||
program_name: external,
|
||||
record,
|
||||
span,
|
||||
}))
|
||||
} else {
|
||||
Ok(Output::Internal(self.parse_function_output()?))
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_is_external(&self) -> bool {
|
||||
matches!(
|
||||
(&self.token.token, self.look_ahead(1, |t| &t.token)),
|
||||
(Token::Identifier(_), Token::Dot)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if the next token is Function or if it is a Const followed by Function.
|
||||
/// Returns `false` otherwise.
|
||||
fn peek_is_function(&self) -> bool {
|
||||
@ -343,7 +408,7 @@ impl ParserContext<'_> {
|
||||
let name = self.expect_identifier()?;
|
||||
|
||||
// Parse parameters.
|
||||
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_function_input().map(Some))?;
|
||||
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
|
||||
|
||||
// Parse return type.
|
||||
let output = match self.eat(&Token::Arrow) {
|
||||
@ -351,8 +416,8 @@ impl ParserContext<'_> {
|
||||
true => {
|
||||
self.disallow_circuit_construction = true;
|
||||
let output = match self.peek_is_left_par() {
|
||||
true => self.parse_paren_comma_list(|p| p.parse_function_output().map(Some))?.0,
|
||||
false => vec![self.parse_function_output()?],
|
||||
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
||||
false => vec![self.parse_output()?],
|
||||
};
|
||||
self.disallow_circuit_construction = false;
|
||||
output
|
||||
@ -373,7 +438,7 @@ impl ParserContext<'_> {
|
||||
let identifier = self.expect_identifier()?;
|
||||
|
||||
// Parse parameters.
|
||||
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_function_input().map(Some))?;
|
||||
let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
|
||||
|
||||
// Parse return type.
|
||||
let output = match self.eat(&Token::Arrow) {
|
||||
@ -381,8 +446,8 @@ impl ParserContext<'_> {
|
||||
true => {
|
||||
self.disallow_circuit_construction = true;
|
||||
let output = match self.peek_is_left_par() {
|
||||
true => self.parse_paren_comma_list(|p| p.parse_function_output().map(Some))?.0,
|
||||
false => vec![self.parse_function_output()?],
|
||||
true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
|
||||
false => vec![self.parse_output()?],
|
||||
};
|
||||
self.disallow_circuit_construction = false;
|
||||
output
|
||||
|
@ -20,7 +20,7 @@ use leo_errors::{ParserError, Result};
|
||||
|
||||
impl ParserContext<'_> {
|
||||
/// Returns a [`ParsedInputFile`] struct filled with the data acquired in the file.
|
||||
pub(crate) fn parse_input(&mut self) -> Result<InputAst> {
|
||||
pub(crate) fn parse_input_file(&mut self) -> Result<InputAst> {
|
||||
// Allow underscores in identifiers for input record declarations.
|
||||
self.allow_identifier_underscores = true;
|
||||
let mut sections = Vec::new();
|
||||
|
@ -50,5 +50,5 @@ pub fn parse(handler: &Handler, source: &str, start_pos: BytePos) -> Result<Prog
|
||||
pub fn parse_input(handler: &Handler, source: &str, start_pos: BytePos) -> Result<InputAst> {
|
||||
let mut tokens = ParserContext::new(handler, crate::tokenize(source, start_pos)?);
|
||||
|
||||
tokens.parse_input()
|
||||
tokens.parse_input_file()
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ impl Namespace for InputNamespace {
|
||||
}
|
||||
|
||||
fn run_test(&self, test: Test) -> Result<Value, String> {
|
||||
create_session_if_not_set_then(|s| with_handler(tokenize(test, s)?, |p| p.parse_input()).map(yaml_or_fail))
|
||||
create_session_if_not_set_then(|s| with_handler(tokenize(test, s)?, |p| p.parse_input_file()).map(yaml_or_fail))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,6 +417,7 @@ impl Token {
|
||||
"increment" => Token::Increment,
|
||||
"import" => Token::Import,
|
||||
"let" => Token::Let,
|
||||
"leo" => Token::Leo,
|
||||
"mapping" => Token::Mapping,
|
||||
"public" => Token::Public,
|
||||
"record" => Token::Record,
|
||||
|
@ -130,6 +130,8 @@ pub enum Token {
|
||||
Return,
|
||||
SelfLower,
|
||||
Static,
|
||||
// For imports.
|
||||
Leo,
|
||||
|
||||
// Meta Tokens
|
||||
Eof,
|
||||
@ -213,6 +215,7 @@ impl Token {
|
||||
Token::Increment => sym::increment,
|
||||
Token::Import => sym::import,
|
||||
Token::Let => sym::Let,
|
||||
Token::Leo => sym::leo,
|
||||
Token::Mapping => sym::mapping,
|
||||
Token::Public => sym::Public,
|
||||
Token::Record => sym::record,
|
||||
@ -335,6 +338,7 @@ impl fmt::Display for Token {
|
||||
Public => write!(f, "public"),
|
||||
Return => write!(f, "return"),
|
||||
Static => write!(f, "static"),
|
||||
Leo => write!(f, "leo"),
|
||||
Eof => write!(f, "<eof>"),
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +276,10 @@ impl<'a> CodeGenerator<'a> {
|
||||
}
|
||||
|
||||
fn visit_call(&mut self, input: &'a CallExpression) -> (String, String) {
|
||||
let mut call_instruction = format!(" call {} ", input.function);
|
||||
let mut call_instruction = match &input.external {
|
||||
Some(external) => format!(" call {}.aleo/{} ", external, input.function),
|
||||
None => format!(" call {} ", input.function),
|
||||
};
|
||||
let mut instructions = String::new();
|
||||
|
||||
for argument in input.arguments.iter() {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{Circuit, CircuitMember, Function, Identifier, Mapping, Mode, Program, Type};
|
||||
use leo_ast::{functions, Circuit, CircuitMember, Function, Identifier, Mapping, Mode, Program, Type};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
@ -185,14 +185,23 @@ impl<'a> CodeGenerator<'a> {
|
||||
let register_string = format!("r{}", self.next_register);
|
||||
self.next_register += 1;
|
||||
|
||||
self.variable_mapping
|
||||
.insert(&input.identifier.name, register_string.clone());
|
||||
|
||||
let visibility = match (self.is_program_function, input.mode) {
|
||||
(true, Mode::None) => Mode::Private,
|
||||
_ => input.mode,
|
||||
let type_string = match input {
|
||||
functions::Input::Internal(input) => {
|
||||
self.variable_mapping
|
||||
.insert(&input.identifier.name, register_string.clone());
|
||||
let visibility = match (self.is_program_function, input.mode) {
|
||||
(true, Mode::None) => Mode::Private,
|
||||
_ => input.mode,
|
||||
};
|
||||
self.visit_type_with_visibility(&input.type_, visibility)
|
||||
}
|
||||
functions::Input::External(input) => {
|
||||
self.variable_mapping
|
||||
.insert(&input.identifier.name, register_string.clone());
|
||||
format!("{}.aleo/{}.record", input.program_name, input.record)
|
||||
}
|
||||
};
|
||||
let type_string = self.visit_type_with_visibility(&input.type_, visibility);
|
||||
|
||||
writeln!(function_string, " input {} as {};", register_string, type_string,)
|
||||
.expect("failed to write to string");
|
||||
}
|
||||
@ -219,16 +228,25 @@ impl<'a> CodeGenerator<'a> {
|
||||
let register_string = format!("r{}", self.next_register);
|
||||
self.next_register += 1;
|
||||
|
||||
self.variable_mapping
|
||||
.insert(&input.identifier.name, register_string.clone());
|
||||
// TODO: Dedup code.
|
||||
let type_string = match input {
|
||||
functions::Input::Internal(input) => {
|
||||
self.variable_mapping
|
||||
.insert(&input.identifier.name, register_string.clone());
|
||||
|
||||
// A finalize block defaults to public visibility.
|
||||
let visibility = match (self.is_program_function, input.mode) {
|
||||
(true, Mode::None) => Mode::Public,
|
||||
(true, mode) => mode,
|
||||
_ => unreachable!("Only program functions can have finalize blocks."),
|
||||
let visibility = match (self.is_program_function, input.mode) {
|
||||
(true, Mode::None) => Mode::Public,
|
||||
_ => input.mode,
|
||||
};
|
||||
self.visit_type_with_visibility(&input.type_, visibility)
|
||||
}
|
||||
functions::Input::External(input) => {
|
||||
self.variable_mapping
|
||||
.insert(&input.program_name.name, register_string.clone());
|
||||
format!("{}.aleo/{}.record", input.program_name, input.record)
|
||||
}
|
||||
};
|
||||
let type_string = self.visit_type_with_visibility(&input.type_, visibility);
|
||||
|
||||
writeln!(function_string, " input {} as {};", register_string, type_string,)
|
||||
.expect("failed to write to string");
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{
|
||||
AssignStatement, Block, ConditionalStatement, ConsoleFunction, ConsoleStatement, DecrementStatement,
|
||||
DefinitionStatement, Expression, FinalizeStatement, IncrementStatement, IterationStatement, Mode, ReturnStatement,
|
||||
Statement,
|
||||
DefinitionStatement, Expression, FinalizeStatement, IncrementStatement, IterationStatement, Mode, Output,
|
||||
ReturnStatement, Statement,
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
@ -52,28 +52,38 @@ impl<'a> CodeGenerator<'a> {
|
||||
.into_iter()
|
||||
.zip(self.current_function.unwrap().output.iter())
|
||||
.map(|(operand, output)| {
|
||||
let visibility = if self.is_program_function {
|
||||
match self.in_finalize {
|
||||
// If in finalize block, the default visibility is public.
|
||||
true => match output.mode {
|
||||
Mode::None => Mode::Public,
|
||||
mode => mode,
|
||||
},
|
||||
// If not in finalize block, the default visibility is private.
|
||||
false => match output.mode {
|
||||
Mode::None => Mode::Private,
|
||||
mode => mode,
|
||||
},
|
||||
match output {
|
||||
Output::Internal(output) => {
|
||||
let visibility = if self.is_program_function {
|
||||
match self.in_finalize {
|
||||
// If in finalize block, the default visibility is public.
|
||||
true => match output.mode {
|
||||
Mode::None => Mode::Public,
|
||||
mode => mode,
|
||||
},
|
||||
// If not in finalize block, the default visibility is private.
|
||||
false => match output.mode {
|
||||
Mode::None => Mode::Private,
|
||||
mode => mode,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// Only program functions have visibilities associated with their outputs.
|
||||
Mode::None
|
||||
};
|
||||
format!(
|
||||
" output {} as {};\n",
|
||||
operand,
|
||||
self.visit_type_with_visibility(&output.type_, visibility)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Only program functions have visibilities associated with their outputs.
|
||||
Mode::None
|
||||
};
|
||||
format!(
|
||||
" output {} as {};\n",
|
||||
operand,
|
||||
self.visit_type_with_visibility(&output.type_, visibility)
|
||||
)
|
||||
Output::External(output) => {
|
||||
format!(
|
||||
" output {} as {}.aleo/{}.record;\n",
|
||||
operand, output.program_name, output.record,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
.join("");
|
||||
|
||||
|
@ -30,8 +30,8 @@ impl ProgramReconstructor for Flattener<'_> {
|
||||
// Initialize `self.circuits` with the finalize's input as necessary.
|
||||
self.circuits = Default::default();
|
||||
for input in &finalize.input {
|
||||
if let Type::Identifier(circuit_name) = input.type_ {
|
||||
self.circuits.insert(input.identifier.name, circuit_name.name);
|
||||
if let Type::Identifier(circuit_name) = input.type_() {
|
||||
self.circuits.insert(input.identifier().name, circuit_name.name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,8 +71,8 @@ impl ProgramReconstructor for Flattener<'_> {
|
||||
// Initialize `self.circuits` with the function's input as necessary.
|
||||
self.circuits = Default::default();
|
||||
for input in &function.input {
|
||||
if let Type::Identifier(circuit_name) = input.type_ {
|
||||
self.circuits.insert(input.identifier.name, circuit_name.name);
|
||||
if let Type::Identifier(circuit_name) = input.type_() {
|
||||
self.circuits.insert(input.identifier().name, circuit_name.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@ impl ExpressionConsumer for StaticSingleAssigner {
|
||||
function: input.function,
|
||||
// Consume the arguments.
|
||||
arguments,
|
||||
external: input.external,
|
||||
span: input.span,
|
||||
}));
|
||||
statements.push(statement);
|
||||
|
@ -30,7 +30,7 @@ impl FunctionConsumer for StaticSingleAssigner {
|
||||
// However, for each input, we must add each symbol to the rename table.
|
||||
for input_variable in function.input.iter() {
|
||||
self.rename_table
|
||||
.update(input_variable.identifier.name, input_variable.identifier.name);
|
||||
.update(input_variable.identifier().name, input_variable.identifier().name);
|
||||
}
|
||||
|
||||
let block = Block {
|
||||
@ -49,7 +49,7 @@ impl FunctionConsumer for StaticSingleAssigner {
|
||||
// However, for each input, we must add each symbol to the rename table.
|
||||
for input_variable in finalize.input.iter() {
|
||||
self.rename_table
|
||||
.update(input_variable.identifier.name, input_variable.identifier.name);
|
||||
.update(input_variable.identifier().name, input_variable.identifier().name);
|
||||
}
|
||||
|
||||
let block = Block {
|
||||
@ -92,7 +92,11 @@ impl ProgramConsumer for StaticSingleAssigner {
|
||||
network: input.network,
|
||||
expected_input: input.expected_input,
|
||||
// TODO: Do inputs need to be processed? They are not processed in the existing compiler.
|
||||
imports: input.imports,
|
||||
imports: input
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|(name, import)| (name, self.consume_program(import)))
|
||||
.collect(),
|
||||
functions: input
|
||||
.functions
|
||||
.into_iter()
|
||||
|
@ -14,7 +14,7 @@
|
||||
// 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 leo_ast::{Function, FunctionInput, Type};
|
||||
use leo_ast::{Function, Input, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use crate::SymbolTable;
|
||||
@ -23,7 +23,7 @@ use crate::SymbolTable;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FinalizeData {
|
||||
/// The inputs to the finalize block.
|
||||
pub(crate) input: Vec<FunctionInput>,
|
||||
pub(crate) input: Vec<Input>,
|
||||
/// The output type of the finalize block.
|
||||
pub(crate) output_type: Type,
|
||||
}
|
||||
@ -38,7 +38,7 @@ pub struct FunctionSymbol {
|
||||
/// The `Span` associated with the function.
|
||||
pub(crate) span: Span,
|
||||
/// The inputs to the function.
|
||||
pub(crate) input: Vec<FunctionInput>,
|
||||
pub(crate) input: Vec<Input>,
|
||||
/// Metadata associated with the finalize block.
|
||||
pub(crate) finalize: Option<FinalizeData>,
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
.iter()
|
||||
.zip(input.arguments.iter())
|
||||
.for_each(|(expected, argument)| {
|
||||
self.visit_expression(argument, &Some(expected.type_.clone()));
|
||||
self.visit_expression(argument, &Some(expected.type_()));
|
||||
});
|
||||
|
||||
Some(ret)
|
||||
|
@ -140,28 +140,28 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
// Type check the function's parameters.
|
||||
function.input.iter().for_each(|input_var| {
|
||||
// Check that the type of input parameter is valid.
|
||||
self.assert_type_is_valid(input_var.span, &input_var.type_);
|
||||
self.assert_not_tuple(input_var.span, &input_var.type_);
|
||||
self.assert_type_is_valid(input_var.span(), &input_var.type_());
|
||||
self.assert_not_tuple(input_var.span(), &input_var.type_());
|
||||
|
||||
match self.is_program_function {
|
||||
// If the function is a program function, then check that the parameter mode is not a constant.
|
||||
true if input_var.mode == Mode::Const => self.emit_err(
|
||||
TypeCheckerError::program_function_inputs_cannot_be_const(input_var.span),
|
||||
true if input_var.mode() == Mode::Const => self.emit_err(
|
||||
TypeCheckerError::program_function_inputs_cannot_be_const(input_var.span()),
|
||||
),
|
||||
// If the function is not a program function, then check that the parameters do not have an associated mode.
|
||||
false if input_var.mode != Mode::None => self.emit_err(
|
||||
TypeCheckerError::helper_function_inputs_cannot_have_modes(input_var.span),
|
||||
false if input_var.mode() != Mode::None => self.emit_err(
|
||||
TypeCheckerError::helper_function_inputs_cannot_have_modes(input_var.span()),
|
||||
),
|
||||
_ => {} // Do nothing.
|
||||
}
|
||||
|
||||
// Check for conflicting variable names.
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
input_var.identifier.name,
|
||||
input_var.identifier().name,
|
||||
VariableSymbol {
|
||||
type_: input_var.type_.clone(),
|
||||
span: input_var.identifier.span(),
|
||||
declaration: VariableType::Input(input_var.mode),
|
||||
type_: input_var.type_(),
|
||||
span: input_var.identifier().span(),
|
||||
declaration: VariableType::Input(input_var.mode()),
|
||||
},
|
||||
) {
|
||||
self.handler.emit_err(err);
|
||||
@ -170,12 +170,17 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
// Type check the function's return type.
|
||||
function.output.iter().for_each(|output_type| {
|
||||
// Check that the type of output is valid.
|
||||
self.assert_type_is_valid(output_type.span, &output_type.type_);
|
||||
match output_type {
|
||||
Output::External(_) => {} // Do not type check external record function outputs.
|
||||
Output::Internal(output_type) => {
|
||||
// Check that the type of output is valid.
|
||||
self.assert_type_is_valid(output_type.span, &output_type.type_);
|
||||
|
||||
// Check that the mode of the output is valid.
|
||||
if output_type.mode == Mode::Const {
|
||||
self.emit_err(TypeCheckerError::cannot_have_constant_output_mode(output_type.span));
|
||||
// Check that the mode of the output is valid.
|
||||
if output_type.mode == Mode::Const {
|
||||
self.emit_err(TypeCheckerError::cannot_have_constant_output_mode(output_type.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -226,21 +231,21 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
finalize.input.iter().for_each(|input_var| {
|
||||
// Check that the type of input parameter is valid.
|
||||
self.assert_type_is_valid(input_var.span, &input_var.type_);
|
||||
self.assert_not_tuple(input_var.span, &input_var.type_);
|
||||
self.assert_type_is_valid(input_var.span(), &input_var.type_());
|
||||
self.assert_not_tuple(input_var.span(), &input_var.type_());
|
||||
|
||||
// Check that the input parameter is not constant or private.
|
||||
if input_var.mode == Mode::Const || input_var.mode == Mode::Private {
|
||||
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(input_var.span));
|
||||
if input_var.mode() == Mode::Const || input_var.mode() == Mode::Private {
|
||||
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(input_var.span()));
|
||||
}
|
||||
|
||||
// Check for conflicting variable names.
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
input_var.identifier.name,
|
||||
input_var.identifier().name,
|
||||
VariableSymbol {
|
||||
type_: input_var.type_.clone(),
|
||||
span: input_var.identifier.span(),
|
||||
declaration: VariableType::Input(input_var.mode),
|
||||
type_: input_var.type_(),
|
||||
span: input_var.identifier().span(),
|
||||
declaration: VariableType::Input(input_var.mode()),
|
||||
},
|
||||
) {
|
||||
self.handler.emit_err(err);
|
||||
@ -250,11 +255,11 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
// Type check the function's return type.
|
||||
finalize.output.iter().for_each(|output_type| {
|
||||
// Check that the type of output is valid.
|
||||
self.assert_type_is_valid(output_type.span, &output_type.type_);
|
||||
self.assert_type_is_valid(output_type.span(), &output_type.type_());
|
||||
|
||||
// Check that the mode of the output is valid.
|
||||
if output_type.mode == Mode::Const {
|
||||
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(output_type.span));
|
||||
if output_type.mode() == Mode::Const {
|
||||
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(output_type.span()));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -239,7 +239,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
.iter()
|
||||
.zip(input.arguments.iter())
|
||||
.for_each(|(expected, argument)| {
|
||||
self.visit_expression(argument, &Some(expected.type_.clone()));
|
||||
self.visit_expression(argument, &Some(expected.type_()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -249,8 +249,8 @@ create_messages!(
|
||||
|
||||
@formatted
|
||||
leo_imports_only {
|
||||
args: (name: impl Display),
|
||||
msg: format!("Invalid import call to non-leo file `{name}`."),
|
||||
args: (),
|
||||
msg: "Invalid import call to non-leo file.",
|
||||
help: Some("Only imports of Leo `.leo` files are currently supported.".to_string()),
|
||||
}
|
||||
|
||||
|
2
examples/battleship/.gitignore
vendored
Normal file
2
examples/battleship/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
outputs/
|
||||
build/
|
923
examples/battleship/README.md
Normal file
923
examples/battleship/README.md
Normal file
@ -0,0 +1,923 @@
|
||||
# Leo Battleship 🏴☠️
|
||||
|
||||
- [Summary](#summary)
|
||||
- [Build](#how-to-build)
|
||||
- [Run](#how-to-run)
|
||||
- [1. Setup](#1-setup)
|
||||
- [2. Select Player 1's Board](#2-select-player-1s-board)
|
||||
- [3. Pass to Player 2](#3-pass-to-player-2)
|
||||
- [4. Select Player 2's Board](#4-select-player-2s-board)
|
||||
- [5. Pass to Player 1](#5-pass-to-player-1)
|
||||
- [6. Player 1 Shoots First](#6-player-1-shoots-first)
|
||||
- [7. Player 2 Shoots Second](#7-player-2-shoots-second)
|
||||
- [8. Player 1 Shoots Third](#8-player-1-shoots-third)
|
||||
- [9. Player 2 Shoots Fourth](#9-player-2-shoots-fourth)
|
||||
- [10. Who Wins?](#10-who-wins)
|
||||
- [ZK Battleship Privacy](#zk-battleship-privacy)
|
||||
- [Modeling the Boards and Ships](#modeling-the-board-and-ships)
|
||||
- [Validating a Single Ship](#validating-a-single-ship-at-a-time)
|
||||
- [Validating all Ships](#validating-all-ships-together-in-a-single-board)
|
||||
- [Sequencing Game State](#ensure-that-players-and-boards-cannot-swap-mid-game)
|
||||
- [Preventing Double Moves](#ensure-that-each-player-can-only-move-once-before-the-next-player-can-move)
|
||||
- [Ensuring Valid Moves](#enforce-constraints-on-valid-moves-and-force-the-player-to-give-their-opponent-information-about-their-opponents-previous-move-in-order-to-continue-playing)
|
||||
- [Winning](#winning-the-game)
|
||||
|
||||
# Summary
|
||||
Battleship is a game where two players lay their ships into secret configurations on their respective 8x8 grids,
|
||||
and then take turns firing upon each other's board.
|
||||
The game ends when one player has sunk all of the other player's ships.
|
||||
|
||||
This application was translated into Leo from the [zk-battleship](https://github.com/demox-labs/zk-battleship) example written by the Aleo community - show them some love!
|
||||
|
||||
## How to Build
|
||||
|
||||
To compile this Leo program, run:
|
||||
```bash
|
||||
leo build
|
||||
```
|
||||
|
||||
## How to Run
|
||||
<details><summary>Commands and Playing the Game</summary>
|
||||
|
||||
|
||||
### 1. Setup
|
||||
In order to play battleship, there must be two players with two boards.
|
||||
Players will be represented by their Aleo address.
|
||||
You can use the provided player accounts or [generate your own](https://aleohq.github.io/aleo/).
|
||||
```markdown
|
||||
Player 1:
|
||||
Private Key APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm
|
||||
View Key AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6
|
||||
Address aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy
|
||||
|
||||
Player 2:
|
||||
Private Key APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH
|
||||
View Key AViewKey1hh6dvSEgeMdfseP4hfdbNYjX4grETwCuTbKnCftkpMwE
|
||||
Address aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry
|
||||
```
|
||||
|
||||
Save the keys and addresses. Set the `program.json` private_key and address to one of the newly created aleo accounts. We'll refer to this address as Player 1, and the remaining address as Player 2.
|
||||
|
||||
```json
|
||||
{
|
||||
"program": "battleship.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "Play ZK Battleship",
|
||||
"development": {
|
||||
"private_key": "APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm",
|
||||
"view_key": "AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6",
|
||||
"address": "aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Select Player 1's Board
|
||||
Now, we need to make a board as Player 1.
|
||||
See the [modeling the boards and ships](#modeling-the-board-and-ships) section for information on valid ship bitstrings and placements on the board.
|
||||
For this example, we will be using sample valid inputs.
|
||||
Initialize a new board as Player 1 with valid ship inputs and Player 2's address: `leo run initialize_board ship_5_bitstring ship_4_bitstring ship_3_bitstring ship_2_bitstring player_2_address`
|
||||
|
||||
**Run**
|
||||
```
|
||||
leo run initialize_board 34084860461056u64 551911718912u64 7u64 1157425104234217472u64 aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry
|
||||
```
|
||||
**Output**
|
||||
```bash
|
||||
➡️ Output
|
||||
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: false.private,
|
||||
_nonce: 3887646704618532506963887075433683846689834495661101507703164090915348189037group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/initialize_board'
|
||||
```
|
||||
|
||||
The output is a board_state record owned by Player 1.
|
||||
Notice that the `game_started` flag is false, as well as the composite ship configuration `ships`.
|
||||
1157459741006397447u64 to a binary bitstring becomes `0001000000010000000111111000000010000000100000001000000000000111`,
|
||||
or laid out in columns and rows:
|
||||
```
|
||||
0 0 0 1 0 0 0 0
|
||||
0 0 0 1 0 0 0 0
|
||||
0 0 0 1 1 1 1 1
|
||||
1 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 1 1 1
|
||||
```
|
||||
|
||||
### 3. Pass to Player 2
|
||||
Now, we can offer a battleship game to player 2. Run `leo run offer_battleship 'board_state.record'` with the record you just created:
|
||||
**Run**
|
||||
```
|
||||
leo run offer_battleship '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: false.private,
|
||||
_nonce: 3887646704618532506963887075433683846689834495661101507703164090915348189037group.public
|
||||
}'
|
||||
```
|
||||
|
||||
**Output**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6563064852163330630334088854834332804417910882908622526775624018226782316843group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 4374626042494973146987320062571809401151262172766172816829659487584978644457group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/offer_battleship'
|
||||
```
|
||||
|
||||
The first output record is the udpated board_state.record.
|
||||
Notice the `game_started` flag is now true.
|
||||
This board cannot be used to offer any other battleship games or accept any battleship game offers.
|
||||
Player 1 would need to initialize a new board and use that instead.
|
||||
The second output record is a dummy move.record --
|
||||
there are no fire coordinates included to play on Player 2's board,
|
||||
and no information about any previous Player 2 moves (Player 2 has not made any moves yet).
|
||||
This move.record is owned by Player 2, who must use that in combination with their own board_state.record to accept the game. Let's do that now.
|
||||
|
||||
### 4. Select Player 2's Board
|
||||
We must run the program as Player 2 now, so switch the `program.json` file to use Player 2's keys:
|
||||
```json
|
||||
{
|
||||
"program": "battleship.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "Play ZK Battleship",
|
||||
"development": {
|
||||
"private_key": "APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH",
|
||||
"view_key": "AViewKey1hh6dvSEgeMdfseP4hfdbNYjX4grETwCuTbKnCftkpMwE",
|
||||
"address": "aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
```
|
||||
|
||||
We'll create a new and different board for Player 2, and make sure to include Player 1's address as the opponent:
|
||||
**Run**
|
||||
```bash
|
||||
leo run initialize_board 31u64 2207646875648u64 224u64 9042383626829824u64 aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy
|
||||
```
|
||||
|
||||
**Output**
|
||||
```bash
|
||||
➡️ Output
|
||||
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: false.private,
|
||||
_nonce: 1549419609469324182591325047490602235361156298832591378925133482196483208807group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/initialize_board'
|
||||
```
|
||||
|
||||
Note, the output ships here is 9044591273705727u64, which in a bitstring is:
|
||||
```
|
||||
0 0 1 0 0 0 0 0
|
||||
0 0 1 0 0 0 1 0
|
||||
0 0 0 0 0 0 1 0
|
||||
0 0 0 0 0 0 1 0
|
||||
0 0 0 0 0 0 1 0
|
||||
0 0 0 0 0 0 0 0
|
||||
1 1 1 1 1 1 1 1
|
||||
```
|
||||
|
||||
### 5. Pass to Player 1
|
||||
Now, we can accept Player 1's offer. Run `leo run start_battleship 'board_state.record' 'move.record'`:
|
||||
**Run**
|
||||
```bash
|
||||
leo run start_battleship '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: false.private,
|
||||
_nonce: 1549419609469324182591325047490602235361156298832591378925133482196483208807group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 4374626042494973146987320062571809401151262172766172816829659487584978644457group.public
|
||||
}'
|
||||
```
|
||||
|
||||
**Outputs**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6222383571142756260765569201308836492199048237638652378826141459336360362251group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 3742551407126138397717446975757978589064777004441277005584760115236217735495group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/start_battleship'
|
||||
```
|
||||
|
||||
Notice the outputs here are similar to `offer_battleship`.
|
||||
A dummy move.record is owned by Player 1, and Player 2 gets a board_state.record with the `game_started` flag updated.
|
||||
However, now that Player 1 has a move.record and a started board, they can begin to play.
|
||||
|
||||
### 6. Player 1 Shoots First
|
||||
**Switch** `program.json`'s keys back to Player 1's.
|
||||
Player 1 now makes the first real move: `leo run play 'board_state.record' 'move.record' fire_coordinate`
|
||||
|
||||
**Run**
|
||||
```bash
|
||||
leo run play '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6563064852163330630334088854834332804417910882908622526775624018226782316843group.public
|
||||
}' '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 3742551407126138397717446975757978589064777004441277005584760115236217735495group.public
|
||||
}' 1u64
|
||||
```
|
||||
**Outputs**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 1u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 1474170213684980843727833284550698461565286563122422722760769547002894080093group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 1u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 5481529266389297320813092061136936339861329677911328036818179854958874588416group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/play'
|
||||
```
|
||||
|
||||
Player 1 has an updated board_state.record -- they have a new `played_tiles` bitstring,
|
||||
which corresponds to the fire coordinate they just sent to Player 2.
|
||||
You can see that the `incoming_fire_coordinate` in the move.record owned by Player 2 matches exactly the input given by Player 1.
|
||||
Player 2 can now play this move tile and respond with a fire coordinate of their own,
|
||||
and they will also let Player 1 know whether or not Player 1's fire coordinate hit or miss Player 2's ships.
|
||||
|
||||
### 7. Player 2 Shoots Second
|
||||
**Switch** `program.json` to Player 2's keys. Player 2 makes their move:
|
||||
|
||||
**Run**
|
||||
```bash
|
||||
leo run play '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6222383571142756260765569201308836492199048237638652378826141459336360362251group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 1u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 5481529266389297320813092061136936339861329677911328036818179854958874588416group.public
|
||||
}' 2048u64
|
||||
|
||||
```
|
||||
|
||||
**Outputs**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 2048u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 5254963165391133332409074172682159033621708071536429341861038147524454777097group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2048u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 1u64.private,
|
||||
_nonce: 5851606198769770675504009323414373017067582072428989801313256693053765675198group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/play'
|
||||
```
|
||||
|
||||
Player 2 now has an updated board_state.record which includes their newly updated `played_tiles`,
|
||||
only containing the fire coordinate they just sent to Player 1.
|
||||
Player 1 now owns a new move.record which includes the `hits_and_misses` field.
|
||||
This contains only the result of Player 1's previous fire coordinate they had sent to Player 2.
|
||||
It will always be a single coordinate on the 8x8 grid if it's a hit. A miss is 0u64 (8x8 grid of 0s),
|
||||
whereas a hit is the u64 equivalent of their previous fire coordinate in bitstring form.
|
||||
If you check Player 2's ships configuration, you'll note their entire bottom row is covered by two ships,
|
||||
so sample valid hits on the bottom row would be: 1u64, 2u64, 4u64, 8u64, 16u64, 32u64, 64u64, and 128u64.
|
||||
Since Player 1's first fire coordinate (1u64) was a hit, the `hits_and_misses` field is also 1u64.
|
||||
|
||||
Player 1's next move will consume this move.record, which will update Player 1's board with the hit-or-miss,
|
||||
as well as figure out the result of Player 2's fire coordinate.
|
||||
Now that Player 1 has some `played_tiles`, they can no longer choose an alread-played fire coordinate.
|
||||
For example, running `aleo run play 'board_state.record' 'move.record' 1u64` will fail, because 1u64 has already been played.
|
||||
|
||||
### 8. Player 1 Shoots Third
|
||||
**Switch** `program.json` to use Player 1's keys.
|
||||
|
||||
**Run**
|
||||
```bash
|
||||
leo run play '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 1u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 1474170213684980843727833284550698461565286563122422722760769547002894080093group.public
|
||||
}' '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2048u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 1u64.private,
|
||||
_nonce: 5851606198769770675504009323414373017067582072428989801313256693053765675198group.public
|
||||
}' 2u64
|
||||
```
|
||||
|
||||
**Outputs**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 1u64.private,
|
||||
played_tiles: 3u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 853278652528988609827041334083853520436225751739504321439524466875699631772group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 710336412388939616658264778971886770861024495941253598683184288448156545822group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/play'
|
||||
```
|
||||
|
||||
As before, both a board_state.record and move.record are created.
|
||||
The board_state.record now contains 3u64 as the `played_tiles`, which looks like this in bitstring form:
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 1
|
||||
```
|
||||
|
||||
The board_state.record `hits_and_misses` field has also been updated with the result of their previous move. The new move.record owned by Player 2 now contains information about whether Player 2's previous move was a hit or miss, as well as Player 1's new fire coordinate.
|
||||
|
||||
### 9. Player 2 Shoots Fourth
|
||||
**Switch** `program.json`'s keys to Player 2. Player 2 makes their next move:
|
||||
|
||||
**Run**
|
||||
```bash
|
||||
leo run play '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 2048u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 5254963165391133332409074172682159033621708071536429341861038147524454777097group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 710336412388939616658264778971886770861024495941253598683184288448156545822group.public
|
||||
}' 4u64
|
||||
```
|
||||
|
||||
**Outputs**
|
||||
```bash
|
||||
➡️ Outputs
|
||||
|
||||
• {
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 2052u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 1145182747531998766752104305052328886102707397061849372000385383229513301534group.public
|
||||
}
|
||||
• {
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 4u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 2u64.private,
|
||||
_nonce: 5958326936461495382488152485080596366937963499216527548334225566230682598418group.public
|
||||
}
|
||||
|
||||
✅ Executed 'battleship.aleo/play'
|
||||
```
|
||||
|
||||
### 10. Who Wins?
|
||||
Play continues back and forth between Player 1 and Player 2.
|
||||
When one player has a total of 14 flipped bits in their `hits_and_misses` field on their board_state.record,
|
||||
they have won the game.
|
||||
</details>
|
||||
|
||||
## ZK Battleship Privacy
|
||||
|
||||
How can we ensure that the ship configurations of each player remains secret,
|
||||
while being able to trustlessly and fairly play with their opponent?
|
||||
By taking advantage of selective privacy powered by zero knowledge proofs on Aleo.
|
||||
|
||||
Broadly speaking, we can follow this general strategy:
|
||||
1. Create mathematical rules for placing the ships on the board, to ensure that neither player can cheat by stacking all their ships in one place, moving them off the board, or laying them across each other.
|
||||
|
||||
2. Ensure that the players and boards that begin a game cannot be swapped out.
|
||||
|
||||
3. Ensure that each player can only move once before the next player can move.
|
||||
|
||||
4. Enforce constraints on valid moves, and force the player to give their opponent information about their opponent's previous move in order to continue playing.
|
||||
|
||||
## Modeling the board and ships
|
||||
|
||||
Most battleship representations in programs use a 64 character string or an array of arrays (8 arrays of 8 elements each) to model the board state. Unfortunately, Aleo instructions don't represent strings well yet, nor can we use for or while loops. Luckily for us, Aleo has the unsigned 64 bit integer type, or u64. To represent every space on a battleship board, from top left to bottom right, we can use each bit in a u64. For example, an empty board would be:
|
||||
0u64 =
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
|
||||
Battleship is played with 4 different ship types -- a ship of length 5, length 4, length 3, and length 2. Some versions of battleship have an extra length 3 ship or another extra ship type, however, we will stick to the most basic version for this project. In order to be a valid ship placement, a ship must be placed vertically or horizontally (no diagonals). On a physical board, a ship cannot break across rows or intersect with another ship, but ships are allowed to touch one another.
|
||||
|
||||
Similar to how we represent a board with a u64 bitstring, we can represent a ship horizontally as a bitstring. We "flip" the bits to represent a ship:
|
||||
| Length | Bitstring | u64 |
|
||||
| ------ | --------- | --- |
|
||||
| 5 | 11111 | 31u64|
|
||||
| 4 | 1111 | 15u64|
|
||||
| 3 | 111 | 7u64 |
|
||||
| 2 | 11 | 3u64 |
|
||||
|
||||
We can also represent a ship vertically as a bitstring. To show this, we need 7 "unflipped" bits (zeroes) in between the flipped bits so that the bits are adjacent vertically.
|
||||
| Length | Bitstring | u64 |
|
||||
| --- | --- | --- |
|
||||
| 5 | 1 00000001 00000001 00000001 00000001 | 4311810305u64 |
|
||||
| 4 | 1 00000001 00000001 00000001 | 16843009u64 |
|
||||
| 3 | 1 00000001 00000001 | 65793u64 |
|
||||
| 2 | 1 00000001 | 257u64 |
|
||||
|
||||
With a board model and ship bitstring models, we can now place ships on a board.
|
||||
|
||||
<details><summary>Examples of valid board configurations:</summary>
|
||||
|
||||
17870284429256033024u64
|
||||
```
|
||||
1 1 1 1 1 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
1 1 1 1 0 0 0 1
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 1
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
|
||||
16383u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 1 1 1 1 1 1
|
||||
1 1 1 1 1 1 1 1
|
||||
```
|
||||
|
||||
2157505700798988545u64
|
||||
```
|
||||
0 0 0 1 1 1 0 1
|
||||
1 1 1 1 0 0 0 1
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Examples of invalid board configurations:</summary>
|
||||
|
||||
Ships overlapping the bottom ship:
|
||||
67503903u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 1 0 0
|
||||
0 0 0 0 0 1 1 0
|
||||
0 0 0 0 0 1 1 1
|
||||
0 0 0 1 1 1 1 1
|
||||
```
|
||||
|
||||
Diagonal ships:
|
||||
9242549787790754436u64
|
||||
```
|
||||
1 0 0 0 0 0 0 0
|
||||
0 1 0 0 0 1 0 0
|
||||
0 0 1 0 0 0 1 0
|
||||
0 0 0 1 0 0 0 0
|
||||
0 0 0 1 1 0 0 0
|
||||
0 0 1 0 0 0 0 1
|
||||
0 1 0 0 0 0 1 0
|
||||
1 0 0 0 0 1 0 0
|
||||
```
|
||||
|
||||
Ships splitting across rows and columns:
|
||||
1297811850814034450u64
|
||||
```
|
||||
0 0 0 1 0 0 1 0
|
||||
0 0 0 0 0 0 1 0
|
||||
1 1 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 1
|
||||
0 0 0 1 0 0 0 0
|
||||
0 0 0 1 0 0 1 0
|
||||
0 0 0 1 0 0 1 0
|
||||
```
|
||||
</details>
|
||||
|
||||
Given these rules, our strategy will be to validate each individaul ship bitstring placement on a board, and then, if all the ships are valid, compose all the positions onto a board and validate that the board with all ships are valid. If each individual ship's position is valid, then all the ships together should be valid unless any overlapping occurs.
|
||||
|
||||
## Validating a single ship at a time
|
||||
|
||||
To follow along with the code, all verification of ship bitstrings is done in verify.aleo. We know a ship is valid if all these conditions are met:
|
||||
If horizontal:
|
||||
1. The correct number of bits is flipped (a ship of length 5 should not have 6 flipped bits)
|
||||
2. All the bits are adjacent to each other.
|
||||
3. The bits do not split a row.
|
||||
|
||||
If vertical:
|
||||
1. The correct number of bits is flipped.
|
||||
2. All the bits are adjacent to each other, vertically. This means that each flipped bit should be separated by exactly 7 unflipped bits.
|
||||
3. The bits do not split a column.
|
||||
|
||||
If a ship is valid vertically or horizontally, then we know the ship is valid. We just need to check for the bit count, the adjacency of those bits, and make sure those bits do not split a row/column. However, we can't loop through the bit string to count bits, or to make sure those bits don't break across columns. We'll need to turn to special bitwise operations and hacks.
|
||||
|
||||
<details><summary>Bit Counting</summary>
|
||||
|
||||
See the "c_bitcount" closure to follow along with the code. 50 years ago, MIT AI Laboratory published HAKMEM, which was a series of tricks and hacks to speed up processing for bitwise operations. https://w3.pppl.gov/~hammett/work/2009/AIM-239-ocr.pdf We turned to HAKMEM 169 for bitcounting inspiration, although we've tweaked our implementation to be (hopefully) easier to understand. Before diving into details, let's build some intuition.
|
||||
|
||||
Let a,b,c,d be either 0 or 1. Given a polynomial 8a + 4b + 2c + d, how do we find the summation of a + b + c + d?
|
||||
If we subtract subsets of this polynomial, we'll be left with the summation.
|
||||
Step 1: 8a + 4b + 2c + d
|
||||
Step 2: -4a - 2b - c
|
||||
Step 3: -2a - b
|
||||
Step 4: - a
|
||||
Step 5: = a + b + c + d
|
||||
This polynomial is basically a bitwise representation of a number, so given a 4 bit number, e.g. 1011 or 13u64, we can follow these instructions to get the bit count. Step 2 is just subtracting the starting number but bit shifted to the right (equivalent to dividing by 2). Step 3 bit shifts the starting number to the right twice and is subtracted, and Step 4 bit shifts thrice and is subtracted. Put another way: Start with a 4-digit binary number A. A - (A >> 1) - (A >> 2) - (A >> 3) = B.
|
||||
Step 1: 1101 = 13u64
|
||||
Step 2: -0110 = 6u64
|
||||
Step 3: -0011 = 3u64
|
||||
Step 4: -0001 = 1u64
|
||||
Step 5: =0011 = 3u64
|
||||
|
||||
To make this process work for any bit-length number, where the sum of the bits is left in groups of 4 bits, we'll need to use some bit-masking, so that the sum of one group of 4 does not interfere with the next group of 4.
|
||||
With a larger starting number, like 1111 0001 0111 0110, we will need the following bit maskings:
|
||||
```
|
||||
For A >> 1, we'll use 0111 0111 0111 .... (in u64, this is 8608480567731124087u64)
|
||||
For A >> 2, we'll use 0011 0011 0011 .... (in u64, this is 3689348814741910323u64)
|
||||
For A >> 3, we'll use 0001 0001 0001 .... (in u64, this is 1229782938247303441u64)
|
||||
```
|
||||
|
||||
For example, finding the sums of groups of 4 with a 16-bit number we'll call A to yield the bit sum number B:
|
||||
```
|
||||
A: 1111 0001 0111 0110
|
||||
A>>1: 0111 1000 1011 1011
|
||||
A>>2: 0011 1100 0101 1101
|
||||
A>>3: 0001 1110 0010 1110
|
||||
|
||||
A>>1: 0111 1000 1011 1011
|
||||
& 0111 0111 0111 0111:
|
||||
0111 0000 0011 0011
|
||||
|
||||
A>>2: 0011 1100 0101 1101
|
||||
& 0011 0011 0011 0011:
|
||||
0011 0000 0001 0001
|
||||
|
||||
A>>3: 0001 1110 0010 1110
|
||||
& 0001 0001 0001 0001:
|
||||
0001 0000 0000 0000
|
||||
|
||||
A - (A>>1 & 0111....) - (A>>2 & 0011....) - (A>>3 & 0001....):
|
||||
B: 0100 0001 0011 0010
|
||||
4 1 3 2
|
||||
```
|
||||
|
||||
The next step is to combine the summation of each of those 4-bit groups into sums of 8-bit groups. To do this, we'll use another bit trick. We will shift this number B to the right by 4 (B >> 4), and add that back to B. Then, we'll apply a bit masking of 0000 1111 0000 1111 .... (in u64, this is 1085102592571150095u64) to yield the sums of bits in groups of 8, a number we'll call C.
|
||||
```
|
||||
B: 0100 0001 0011 0010
|
||||
B>>4: 0000 0100 0001 0011
|
||||
0100 0101 0100 0101
|
||||
4 5 4 5
|
||||
|
||||
apply the bit mask
|
||||
0000 1111 0000 1111
|
||||
|
||||
C: 0000 0101 0000 0101
|
||||
0 5 0 5
|
||||
```
|
||||
|
||||
At this point, we've gone from a bit sum in groups of 4 to bit sums in groups of 8. That's great, but ultimately we want the total sum of bits in the original binary number. The final bit trick is to modulo C by 255. This is 2^8 - 1. For a bit of intuition, consider the number 1 0000 0001. If we take 1 0000 0001 mod 256, we're left with 1. If we take 1 0000 0001 mod 255, we're left with 2. Modding by 255 gives us the amount of bits _beyond_ the first 255 numbers, as 255 is the largest number that can be represented with 8 bits.
|
||||
|
||||
A full summary of abbreviated steps to get the bit count, starting with a 64 bit integer A (closely following the c_bitcount closure in the verify.aleo code):
|
||||
let A = 64 unsigned bit integer
|
||||
let B = A - (A>>1 & 8608480567731124087u64) - (A>>2 & 3689348814741910323u64) - (A>>3 & 1229782938247303441u64)
|
||||
let C = (B - B>>4) & 1085102592571150095u64
|
||||
bit count = C mod 255u64
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Adjacency Check</summary>
|
||||
|
||||
Given a ship's placement on the board and its bitstring representation (horizontally or vertically), we can determine if the bits are adjacent. Follow the c_adjacency_check closure in verify.aleo. Given the ship of length 2, we know it's horizontal bitstring is 11 (3u64) and it's vertical bitstring is 100000001 (257u64). If on the board, the ship starts at the bottom right corner, its horizontal ship placement string would be:
|
||||
3u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 1
|
||||
```
|
||||
|
||||
Vertical ship placement:
|
||||
257u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
```
|
||||
|
||||
If we move the ship to the left one column:
|
||||
Horizontal 6u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 1 1 0
|
||||
```
|
||||
|
||||
Vertical 514u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 0
|
||||
0 0 0 0 0 0 1 0
|
||||
```
|
||||
|
||||
If we move the ship up one row:
|
||||
Horizontal 768u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 1
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
|
||||
Vertical 65792u64
|
||||
```
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 1
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
|
||||
We can make the observation that the original bitstring is always shifted by a power of 2 to get to a new valid position on the board. Therefore, if we take the ship placement bitstring and divide by the ship bitstring (either horizontal or vertical), as long as the remaining number is a power of 2 (2^0, 2^1, 2^2, 2^3...), we know the ship's bits are adjacent.
|
||||
|
||||
To ensure that the remaining number is a power of 2, we can use a bit trick. See the bit trick for ensuring a bitstring is a power of 2 section.
|
||||
|
||||
In the code, you'll notice one extra step. Dividing a ship placement bitstring by a ship bitstring representation could result in 0, and then subtracting by 1 will result in an underflow. In that case, we know the ship placement is not valid, so we can set a number which is gauranteed to not be a power of 2.
|
||||
</details>
|
||||
|
||||
<details><summary>Splitting a row or column</summary>
|
||||
Follow the c_horizontal_check closure in verify.aleo to follow the code. Assume all the bits are adjacent (see the adjacency check section). The column case is trivial. We can be certain that if a ship bitstring splits columns, the division of that ship placement bitstring by its ship bitstring representation will not yield a power of 2, and it would have failed the adjacency check.
|
||||
|
||||
The horizontal case must be checked because a split row bitstring could still contain a ship with adjacent bits. To make this check easier, we will condense the 64 bitstring into an 8 bitstring by taking it modulo 255. If we assume that a bitstring is not splitting a row, then taking the ship placement bitstring modulo 255 will yield an 8 bit valid bitstring. If the original ship placement bitstring is not valid, then we will have an invalid 8 bit bitstring. E.g.:
|
||||
```
|
||||
1 1 1 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
mod 255 = 11100000 (valid)
|
||||
|
||||
```
|
||||
0 0 0 0 0 0 0 1
|
||||
1 1 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
```
|
||||
mod 255 = 11000001 (invalid)
|
||||
|
||||
How do we know the 8 bit bitstring is valid or not? We can simply do an adjacency check, as before.
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Ensuring a bitstring is a power of 2</summary>
|
||||
|
||||
Any power of 2 will have a single bit flipped. If we subtract 1 from that number, it will result in a complementary bitstring that, bitwise-anded with the original, will always result in 0.
|
||||
|
||||
E.g.
|
||||
```
|
||||
8: 1000
|
||||
8-1: 0111
|
||||
8&7: 0000 == 0
|
||||
|
||||
7: 0111
|
||||
7-1: 0110
|
||||
7&6: 0110 != 0
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Validating all ships together in a single board
|
||||
|
||||
Give individual valid ship position bitstrings, we can combine all these together into a single board using bitwise or operators. See the create_board function in verify.aleo to follow the code. Once all ships are on the board, we can count the total number of bits, which should be 14 exactly for a ship of length 5, 4, 3, and 2.
|
||||
|
||||
## Ensure that players and boards cannot swap mid-game
|
||||
|
||||
Board states are represented with the board_state record. Each board has a flag indicating whether a game has been started with the board. This flag is set when offering a battleship game to an opponent, or accepting a battleship game from an opponent. Move records are created only in 3 ways:
|
||||
1. Offering a battleship game creates a dummy move record that sets the two players to the addresses set in the board state record.
|
||||
2. Accepting a battleship game consumes the first dummy move record and checks that the move record contains the same two players as the board of the player accepting the game. Then, a new dummy move record is created and keeps the same two players.
|
||||
2. A move record must be consumed in order to play and create the next move record. There's a check to ensure the players in the move record matches the players in the board, and the players in the next move record are automatically set.
|
||||
|
||||
The only way moves _not_ matching a board can be combined is if the players begin multiple games with each other. As long as one player is honest and only accepts a single game with a particular opponent, only one set of moves can be played on one board between them.
|
||||
|
||||
## Ensure that each player can only move once before the next player can move
|
||||
|
||||
A move record must be consumed in order to create the next move record. The owner of the move record changes with each play. Player A must spend a move record in order to create a move record containing their fire coordinate, and that move record will be owned by Player B. Player B must spend that move record in order to create the next move record, which will belong to Player A.
|
||||
|
||||
## Enforce constraints on valid moves, and force the player to give their opponent information about their opponent's previous move in order to continue playing
|
||||
|
||||
A valid move for a player is a fire coordinate that has only one flipped bit in a u64. We can make sure only one bit is flipped with the powers of 2 bit trick. That single bit must be a coordinate that has not been played by that player before, which we check in board.aleo/update_played_tiles.
|
||||
|
||||
In order to give their next move to their opponent, a player must call the main.aleo/play function, which checks the opponent's fire coordinate on the current player's board. The move record being created is updated with whether that fire coordinate was a hit or a miss for the opponent.
|
||||
|
||||
## Winning the game
|
||||
|
||||
Right now, the way to check when a game has been won is to count the number of hits on your hits_and_misses field on your board_state record. Once you have 14 hits, you've won the game.
|
117
examples/battleship/imports/board.leo
Normal file
117
examples/battleship/imports/board.leo
Normal file
@ -0,0 +1,117 @@
|
||||
// Battleship boards are represented by 8x8 squares.
|
||||
// A u64 is all that is required to represent a hit or a miss on a single board.
|
||||
// Starting from the top row, left to right, a hit is 1 and a miss is 0.
|
||||
// A first move resulting in a hit in row 1, column 3 would be:
|
||||
// 00100000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
// A second u64 is needed to represent which squares have been played, with 1s being played squares and 0s being
|
||||
// unplayed squares.
|
||||
record board_state {
|
||||
owner: address,
|
||||
gates: u64,
|
||||
// The hits and misses registered on the opponent's board.
|
||||
hits_and_misses: u64,
|
||||
// The squares that have been played on the opponent's board.
|
||||
played_tiles: u64,
|
||||
// The ship bitstring representing all ship positions on your own board
|
||||
ships: u64,
|
||||
player_1: address,
|
||||
player_2: address,
|
||||
game_started: bool,
|
||||
}
|
||||
|
||||
// Returns a new board_state.
|
||||
@program
|
||||
function new_board_state(
|
||||
ships: u64,
|
||||
opponent: address,
|
||||
) -> board_state {
|
||||
return board_state {
|
||||
owner: self.caller,
|
||||
gates: 0u64,
|
||||
hits_and_misses: 0u64,
|
||||
played_tiles: 0u64,
|
||||
ships,
|
||||
player_1: self.caller,
|
||||
player_2: opponent,
|
||||
game_started: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a new board state that has been started.
|
||||
// Fails if this board has been started before.
|
||||
@program
|
||||
function start_board(
|
||||
// The record of the board to start. A board can only be started once.
|
||||
board: board_state,
|
||||
) -> board_state {
|
||||
// Ensure this board hasn't been used to start a game before.
|
||||
console.assert(!board.game_started);
|
||||
|
||||
return board_state {
|
||||
owner: board.owner,
|
||||
gates: board.gates,
|
||||
hits_and_misses: board.hits_and_misses,
|
||||
played_tiles: board.played_tiles,
|
||||
ships: board.ships,
|
||||
player_1: board.player_1,
|
||||
player_2: board.player_2,
|
||||
game_started: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a new board state record that includes all the played tiles.
|
||||
// Fails if r1 has been played before.
|
||||
@program
|
||||
function update_played_tiles(
|
||||
// The record of the board to update.
|
||||
board: board_state,
|
||||
// The u64 equivalent of a bitstring fire coordinate to send to the opponent.
|
||||
shoot: u64,
|
||||
) -> board_state {
|
||||
// Need to make sure r1 is a valid move. Only one bit of r1 should be flipped.
|
||||
let flip_bit: u64 = shoot - 1u64;
|
||||
// bitwise and operation
|
||||
let check_move: u64 = shoot & flip_bit;
|
||||
console.assert_eq(check_move, 0u64);
|
||||
|
||||
// Need to make sure r1 is a valid move given the played_tiles. no bits should overlap.
|
||||
let check_tiles: u64 = shoot & board.played_tiles;
|
||||
console.assert_eq(check_tiles, 0u64);
|
||||
|
||||
// Update played tiles.
|
||||
let played_tiles: u64 = board.played_tiles | shoot;
|
||||
|
||||
return board_state {
|
||||
owner: board.owner,
|
||||
gates: board.gates,
|
||||
hits_and_misses: board.hits_and_misses,
|
||||
played_tiles,
|
||||
ships: board.ships,
|
||||
player_1: board.player_1,
|
||||
player_2: board.player_2,
|
||||
game_started: board.game_started,
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a new board state record that includes all the hits and misses.
|
||||
@program
|
||||
function update_hits_and_misses(
|
||||
// The record of the board to update.
|
||||
board: board_state,
|
||||
// The u64 equivalent of a bitstring of whether this player's previous move was a hit or miss.
|
||||
hit_or_miss: u64,
|
||||
) -> board_state {
|
||||
// Update hits and misses.
|
||||
let hits_and_misses: u64 = board.hits_and_misses | hit_or_miss;
|
||||
|
||||
return board_state {
|
||||
owner: board.owner,
|
||||
gates: board.gates,
|
||||
hits_and_misses,
|
||||
played_tiles: board.played_tiles,
|
||||
ships: board.ships,
|
||||
player_1: board.player_1,
|
||||
player_2: board.player_2,
|
||||
game_started: board.game_started,
|
||||
};
|
||||
}
|
48
examples/battleship/imports/move.leo
Normal file
48
examples/battleship/imports/move.leo
Normal file
@ -0,0 +1,48 @@
|
||||
record move {
|
||||
owner: address,
|
||||
gates: u64,
|
||||
incoming_fire_coordinate: u64,
|
||||
player_1: address,
|
||||
player_2: address,
|
||||
// One flipped bit indicates a hit. No flipped bits indicates a miss.
|
||||
prev_hit_or_miss: u64,
|
||||
}
|
||||
|
||||
// Returns new move record owned by the opponent.
|
||||
@program
|
||||
function create_move(
|
||||
// The move record created by the opponent.
|
||||
move_record: move,
|
||||
// The u64 representation of incoming_fire_coordinate, the bitstring fire coordinate to send to the opponent.
|
||||
incoming_fire_coordinate: u64,
|
||||
// The u64 representation of prev_hit_or_miss, this player's previous fire coordinate as a hit or miss.
|
||||
prev_hit_or_miss: u64,
|
||||
) -> move {
|
||||
// A new move record should be created and owned by the opponent.
|
||||
let one_is_owner: bool = move_record.player_1 == move_record.owner;
|
||||
let opponent: address = one_is_owner ? move_record.player_2 : move_record.player_1;
|
||||
|
||||
return move {
|
||||
owner: opponent,
|
||||
gates: move_record.gates,
|
||||
incoming_fire_coordinate,
|
||||
player_1: move_record.player_2,
|
||||
player_2: move_record.player_1,
|
||||
prev_hit_or_miss,
|
||||
};
|
||||
}
|
||||
|
||||
// Returns the move record owned by the opponent.
|
||||
// Note, this move record contains dummy fire coordinates and previous hit or miss.
|
||||
@program
|
||||
function start_game(player_2: address) -> move {
|
||||
return move {
|
||||
owner: player_2,
|
||||
gates: 0u64,
|
||||
incoming_fire_coordinate: 0u64,
|
||||
player_1: self.caller,
|
||||
player_2: player_2,
|
||||
prev_hit_or_miss: 0u64,
|
||||
};
|
||||
}
|
||||
|
125
examples/battleship/imports/verify.leo
Normal file
125
examples/battleship/imports/verify.leo
Normal file
@ -0,0 +1,125 @@
|
||||
// Returns the number of flipped bits.
|
||||
// E.g. 17870283321406128128u64, in binary 11111000 00000000 00000000 00000000 00000000 00000000 00000000 00000000,
|
||||
// returns 5u64;
|
||||
function bitcount(bits: u64) -> u64 {
|
||||
let r1: u64 = bits / 2u64;
|
||||
let r2: u64 = bits / 4u64;
|
||||
let r3: u64 = bits / 8u64;
|
||||
|
||||
let r4: u64 = r1 & 8608480567731124087u64;
|
||||
let r5: u64 = r2 & 3689348814741910323u64;
|
||||
let r6: u64 = r3 & 1229782938247303441u64;
|
||||
|
||||
let r7: u64 = bits - r4 - r5 - r6;
|
||||
|
||||
let r8: u64 = r7 / 16u64;
|
||||
let r9: u64 = r7 + r8;
|
||||
let r10: u64 = r9 & 1085102592571150095u64;
|
||||
let r11: u64 = r10 % 255u64;
|
||||
|
||||
return r11;
|
||||
}
|
||||
|
||||
// Returns boolean of whether all the flipped bits in location are "adjacent". Horizontally, this means all flipped bits are
|
||||
// directly next to each other (111). Vertically, this means all flipped bits are separated by 7 unflipped bits
|
||||
// (10000000100000001).
|
||||
function adjacency_check(
|
||||
// The u64 representation of a ship's placement in an 8x8 grid.
|
||||
ship: u64,
|
||||
// The u64 representation of a ship's bitstring, either horizontally or vertically.
|
||||
// E.g. a ship of length 3's bit string horizontally would be: 000111 = 7u64. Vertically, the bit string would be:
|
||||
// 10000000100000001 = 65793u64.
|
||||
orientation: u64,
|
||||
) -> bool {
|
||||
// This may result in 0.
|
||||
let division: u64 = ship / orientation;
|
||||
|
||||
// subtracting 1 from 0 will cause an underflow, so we should check for this edge case.
|
||||
let is_eq: bool = division == 0u64;
|
||||
|
||||
// if the above division resulted in 0, we know the adjacency check should return false.
|
||||
// Setting to r4 to 3 (11) will guarantee failure here.
|
||||
let ternary: u64 = is_eq ? 3u64 : division;
|
||||
let subtraction: u64 = ternary - 1u64;
|
||||
let and: u64 = subtraction & ternary;
|
||||
|
||||
let bits_are_adjacent: bool = and == 0u64;
|
||||
|
||||
return bits_are_adjacent;
|
||||
}
|
||||
|
||||
// Returns boolean of whether adjacent flipped bits don't split a row of size 8.
|
||||
// E.g. 111000000 has adjacent flipped bits but splits a row: 00000001 11000000
|
||||
function horizontal_check(
|
||||
// The u64 representation of a ship's placement in an 8x8 grid.
|
||||
ship: u64,
|
||||
// The u64 representation of a ship's bitstring horizontally.
|
||||
horizontal: u64,
|
||||
) -> bool {
|
||||
let remainder: u64 = ship % 255u64;
|
||||
// This may result in 0.
|
||||
let division: u64 = remainder / horizontal;
|
||||
|
||||
// Subtracting 1 from 0 will cause an underflow.
|
||||
let is_eq: bool = division == 0u64;
|
||||
|
||||
// Setting to 3 will guarantee failure.
|
||||
let ternary: u64 = is_eq ? 3u64 : division;
|
||||
let subtraction: u64 = ternary - 1u64;
|
||||
let and: u64 = subtraction & ternary;
|
||||
|
||||
let bits_split_row: bool = and == 0u64;
|
||||
|
||||
return bits_split_row;
|
||||
}
|
||||
|
||||
// Returns `true` if the ship placement is valid.
|
||||
@program
|
||||
function validate_ship(
|
||||
// The u64 representation of a ship's placement in an 8x8 grid.
|
||||
ship: u64,
|
||||
// The length of the placed ship.
|
||||
length: u64,
|
||||
// The u64 equivalent of a ship's horizontal bitstring representation.
|
||||
horizontal: u64,
|
||||
// The u64 equivalent of a ship's vertical bitstring representation.
|
||||
vertical: u64,
|
||||
) -> bool {
|
||||
// Check bitcount -- all other validations depend on the bitcount being correct.
|
||||
let num_bits: u64 = bitcount(ship);
|
||||
console.assert_eq(num_bits, length);
|
||||
|
||||
// Check horizontal bits of ship.
|
||||
let is_adjacent: bool = adjacency_check(ship, horizontal); // True if bits are adjacent horizontally.
|
||||
let is_horizontal: bool = horizontal_check(ship, horizontal); // True if those horizontal bits are not split across rows.
|
||||
let valid_horizontal: bool = is_adjacent && is_horizontal; // True if bits are adjacent horizontally and not split across rows.
|
||||
|
||||
// Check vertical bits of ship.
|
||||
let valid_vertical: bool = adjacency_check(ship, vertical); // True if bits are adjacent vertically.
|
||||
|
||||
let ship_is_valid: bool = valid_horizontal || valid_vertical; // Ship is valid if it is vertically or horizontally valid.
|
||||
|
||||
return ship_is_valid;
|
||||
}
|
||||
|
||||
// Returns the u64 representation of all the ships' placements in an 8x8 grid. This function will fail
|
||||
// if any of the ship placements overlap each other.
|
||||
@program
|
||||
function create_board(
|
||||
// The u64 representation of a carrier's placement in an 8x8 grid. Length = 5.
|
||||
carrier: u64,
|
||||
// The u64 representation of a battleship's placement in an 8x8 grid. Length = 4.
|
||||
battleship: u64,
|
||||
// The u64 representation of a cruiser's placement in an 8x8 grid. Length = 3.
|
||||
cruiser: u64,
|
||||
// The u64 representation of a destroyer's placement in an 8x8 grid. Length = 2.
|
||||
destroyer: u64,
|
||||
) -> u64 {
|
||||
// Bitwise combine the ship placements together
|
||||
let ships: u64 = carrier | battleship | cruiser | destroyer;
|
||||
|
||||
let num_bits: u64 = bitcount(ships);
|
||||
console.assert_eq(num_bits, 14u64); // Given 4 individually-valid ships, a valid combination should yield exactly 14 flipped bits.
|
||||
|
||||
return ships;
|
||||
}
|
4
examples/battleship/inputs/battleship.in
Normal file
4
examples/battleship/inputs/battleship.in
Normal file
@ -0,0 +1,4 @@
|
||||
// The program input for battleship/src/main.leo
|
||||
[main]
|
||||
public a: u32 = 1u32;
|
||||
b: u32 = 2u32;
|
11
examples/battleship/program.json
Normal file
11
examples/battleship/program.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"program": "battleship.aleo",
|
||||
"version": "0.0.0",
|
||||
"description": "Play ZK Battleship",
|
||||
"development": {
|
||||
"private_key": "APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm",
|
||||
"view_key": "AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6",
|
||||
"address": "aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
216
examples/battleship/run.sh
Executable file
216
examples/battleship/run.sh
Executable file
@ -0,0 +1,216 @@
|
||||
#!/bin/bash
|
||||
# First check that Leo is installed.
|
||||
if ! command -v leo &> /dev/null
|
||||
then
|
||||
echo "leo is not installed."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Follow along in the README.md for a detailed explanation of each step.
|
||||
|
||||
# 1. Setup
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm\",
|
||||
\"view_key\": \"AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6\",
|
||||
\"address\": \"aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
# 2. Select Player 1's Board
|
||||
leo run initialize_board 34084860461056u64 551911718912u64 7u64 1157425104234217472u64 aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry
|
||||
|
||||
# 3. Pass to Player 2
|
||||
leo run offer_battleship '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: false.private,
|
||||
_nonce: 3887646704618532506963887075433683846689834495661101507703164090915348189037group.public
|
||||
}'
|
||||
|
||||
# 4. Select Player 2's Board
|
||||
(
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH\",
|
||||
\"view_key\": \"AViewKey1hh6dvSEgeMdfseP4hfdbNYjX4grETwCuTbKnCftkpMwE\",
|
||||
\"address\": \"aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
leo run initialize_board 31u64 2207646875648u64 224u64 9042383626829824u64 aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy
|
||||
)
|
||||
|
||||
# 5. Pass to Player 1
|
||||
leo run start_battleship '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: false.private,
|
||||
_nonce: 1549419609469324182591325047490602235361156298832591378925133482196483208807group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 4374626042494973146987320062571809401151262172766172816829659487584978644457group.public
|
||||
}'
|
||||
|
||||
# 6. Player 1 Shoots First
|
||||
(
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm\",
|
||||
\"view_key\": \"AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6\",
|
||||
\"address\": \"aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
leo run play '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6563064852163330630334088854834332804417910882908622526775624018226782316843group.public
|
||||
}' '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 0u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 3742551407126138397717446975757978589064777004441277005584760115236217735495group.public
|
||||
}' 1u64
|
||||
)
|
||||
|
||||
# 7. Player 2 Shoots Second
|
||||
(
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH\",
|
||||
\"view_key\": \"AViewKey1hh6dvSEgeMdfseP4hfdbNYjX4grETwCuTbKnCftkpMwE\",
|
||||
\"address\": \"aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
leo run play '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 0u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 6222383571142756260765569201308836492199048237638652378826141459336360362251group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 1u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 5481529266389297320813092061136936339861329677911328036818179854958874588416group.public
|
||||
}' 2048u64
|
||||
)
|
||||
|
||||
# 8. Player 1 Shoots Third
|
||||
(
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkpGKaJY47BXb6knSqmT3JZnBUEGBDFAWz2nMVSsjwYpJmm\",
|
||||
\"view_key\": \"AViewKey1fSyEPXxfPFVgjL6qcM9izWRGrhSHKXyN3c64BNsAjnA6\",
|
||||
\"address\": \"aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
leo run play '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 1u64.private,
|
||||
ships: 1157459741006397447u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
game_started: true.private,
|
||||
_nonce: 1474170213684980843727833284550698461565286563122422722760769547002894080093group.public
|
||||
}' '{
|
||||
owner: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2048u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
prev_hit_or_miss: 1u64.private,
|
||||
_nonce: 5851606198769770675504009323414373017067582072428989801313256693053765675198group.public
|
||||
}' 2u64
|
||||
)
|
||||
|
||||
# 9. Player 2 Shoots Fourth
|
||||
(
|
||||
echo "{
|
||||
\"program\": \"battleship.aleo\",
|
||||
\"version\": \"0.0.0\",
|
||||
\"description\": \"\",
|
||||
\"development\": {
|
||||
\"private_key\": \"APrivateKey1zkp86FNGdKxjgAdgQZ967bqBanjuHkAaoRe19RK24ZCGsHH\",
|
||||
\"view_key\": \"AViewKey1hh6dvSEgeMdfseP4hfdbNYjX4grETwCuTbKnCftkpMwE\",
|
||||
\"address\": \"aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry\"
|
||||
},
|
||||
\"license\": \"MIT\"
|
||||
}" > program.json
|
||||
|
||||
leo run play '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
hits_and_misses: 0u64.private,
|
||||
played_tiles: 2048u64.private,
|
||||
ships: 9044591273705727u64.private,
|
||||
player_1: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
player_2: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
game_started: true.private,
|
||||
_nonce: 5254963165391133332409074172682159033621708071536429341861038147524454777097group.public
|
||||
}' '{
|
||||
owner: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
gates: 0u64.private,
|
||||
incoming_fire_coordinate: 2u64.private,
|
||||
player_1: aleo15g9c69urtdhvfml0vjl8px07txmxsy454urhgzk57szmcuttpqgq5cvcdy.private,
|
||||
player_2: aleo1wyvu96dvv0auq9e4qme54kjuhzglyfcf576h0g3nrrmrmr0505pqd6wnry.private,
|
||||
prev_hit_or_miss: 0u64.private,
|
||||
_nonce: 710336412388939616658264778971886770861024495941253598683184288448156545822group.public
|
||||
}' 4u64
|
||||
)
|
106
examples/battleship/src/main.leo
Normal file
106
examples/battleship/src/main.leo
Normal file
@ -0,0 +1,106 @@
|
||||
// The 'battleship.leo' program.
|
||||
import board.leo;
|
||||
import move.leo;
|
||||
import verify.leo;
|
||||
|
||||
// Returns a new record representing a new game of battleship.
|
||||
@program
|
||||
function initialize_board(
|
||||
// The u64 representation of a carrier's placement in an 8x8 grid. Length = 5.
|
||||
carrier: u64,
|
||||
// The u64 representation of a battleship's placement in an 8x8 grid. Length = 4.
|
||||
battleship: u64,
|
||||
// The u64 representation of a cruiser's placement in an 8x8 grid. Length = 3.
|
||||
cruiser: u64,
|
||||
// The u64 representation of a destroyer's placement in an 8x8 grid. Length = 2.
|
||||
destroyer: u64,
|
||||
// The address of the opponent.
|
||||
player: address,
|
||||
) -> board.leo/board_state.record {
|
||||
// Verify that each individual ship placement bitstring is valid.
|
||||
let valid_carrier: bool = verify.leo/validate_ship(carrier, 5u64, 31u64, 4311810305u64);
|
||||
console.assert(valid_carrier);
|
||||
|
||||
let valid_battleship: bool = verify.leo/validate_ship(battleship, 4u64, 15u64, 16843009u64);
|
||||
console.assert(valid_battleship);
|
||||
|
||||
let valid_cruiser: bool = verify.leo/validate_ship(cruiser, 3u64, 7u64, 65793u64);
|
||||
console.assert(valid_cruiser);
|
||||
|
||||
let valid_destroyer: bool = verify.leo/validate_ship(destroyer, 2u64, 3u64, 257u64);
|
||||
console.assert(valid_destroyer);
|
||||
|
||||
// Create the board with all the ship placements combined.
|
||||
let board: u64 = verify.leo/create_board(carrier, battleship, cruiser, destroyer);
|
||||
|
||||
// Initialize the board state record.
|
||||
let state: board_state = board.leo/new_board_state(board, player);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Returns an updated board state record that has been started. This board cannot be used to start any other games.
|
||||
// Returns a dummy move record owned by the opponent.
|
||||
// This function commits a given board to a game with an opponent and creates the initial dummy move.
|
||||
@program
|
||||
function offer_battleship(
|
||||
// The board record to start a game with.
|
||||
board: board.leo/board_state.record,
|
||||
) -> (board.leo/board_state.record, move.leo/move.record) {
|
||||
let state: board_state = board.leo/start_board(board);
|
||||
let dummy: move = move.leo/start_game(board.player_2);
|
||||
|
||||
return (state, dummy);
|
||||
}
|
||||
|
||||
// Returns updated board_state.record that has been started and can no longer be used to join or start new games.
|
||||
// Returns dummy move record owned by the opponent.
|
||||
@program
|
||||
function start_battleship(
|
||||
// The board record to play the game with.
|
||||
board: board.leo/board_state.record,
|
||||
// The move record to play to begin the game. This should be the dummy move record created from offer_battleship.
|
||||
move_start: move.leo/move.record,
|
||||
) -> (board.leo/board_state.record, move.leo/move.record) {
|
||||
// Validate that the move players and board players match each other.
|
||||
console.assert_eq(board.player_1, move_start.player_2);
|
||||
console.assert_eq(board.player_2, move_start.player_1);
|
||||
|
||||
let state: board_state = board.leo/start_board(board);
|
||||
let dummy: move = move.leo/start_game(board.player_2);
|
||||
|
||||
return (state, dummy);
|
||||
}
|
||||
|
||||
// Returns updated board record.
|
||||
// Returns new move record owned by opponent.
|
||||
@program
|
||||
function play(
|
||||
// The board record to update.
|
||||
board: board.leo/board_state.record,
|
||||
// The incoming move from the opponent.
|
||||
move_incoming: move.leo/move.record,
|
||||
// The u64 equivalent of the bitwise representation of the next coordinate to play on the opponent's board.
|
||||
shoot: u64,
|
||||
) -> (board.leo/board_state.record, move.leo/move.record) {
|
||||
// Verify the board has been started. This prevents players from starting a game and then creating
|
||||
// a brand new board to play with.
|
||||
console.assert(board.game_started);
|
||||
|
||||
// Validate that the move players and board players match each other.
|
||||
console.assert_eq(board.player_1, move_incoming.player_2);
|
||||
console.assert_eq(board.player_2, move_incoming.player_1);
|
||||
|
||||
// Play coordinate on own board. Will fail if not a valid move.
|
||||
let hit_or_miss: board_state = board.leo/update_played_tiles(board, shoot);
|
||||
|
||||
// Update own board with result of last shot.
|
||||
let next_board: board_state = board.leo/update_hits_and_misses(hit_or_miss, move_incoming.prev_hit_or_miss);
|
||||
|
||||
// Assess whether incoming fire coordinate is a hit.
|
||||
let is_hit: u64 = move_incoming.incoming_fire_coordinate & board.ships;
|
||||
|
||||
let next_move: move = move.leo/create_move(move_incoming, shoot, is_hit);
|
||||
|
||||
return (next_board, next_move);
|
||||
}
|
0
examples/helloworld/imports/point.leo
Normal file
0
examples/helloworld/imports/point.leo
Normal file
@ -27,7 +27,6 @@ use leo_span::symbol::with_session_globals;
|
||||
use aleo::commands::Build as AleoBuild;
|
||||
|
||||
use clap::StructOpt;
|
||||
use colored::Colorize;
|
||||
use indexmap::IndexMap;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -275,14 +274,10 @@ fn compile_leo_file(
|
||||
.map_err(CliError::failed_to_load_instructions)?;
|
||||
|
||||
// Prepare the path string.
|
||||
let path_string = format!("(in \"{}\")", aleo_file_path.display());
|
||||
let _path_string = format!("(in \"{}\")", aleo_file_path.display());
|
||||
|
||||
// Log the build as successful.
|
||||
tracing::info!(
|
||||
"compiled '{}' into Aleo instructions {}",
|
||||
file_name,
|
||||
path_string.dimmed()
|
||||
);
|
||||
tracing::info!("Compiled '{}' into Aleo instructions", file_name,);
|
||||
|
||||
Ok(symbol_table.circuits)
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ impl Command for Deploy {
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Call the `aleo node` command from the Aleo SDK.
|
||||
println!();
|
||||
let command = AleoDeploy::try_parse_from([ALEO_CLI_COMMAND]).map_err(CliError::failed_to_parse_aleo_node)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_aleo_node)?;
|
||||
|
||||
|
@ -71,6 +71,7 @@ impl Command for Node {
|
||||
}
|
||||
|
||||
// Call the `aleo node` command from the Aleo SDK.
|
||||
println!();
|
||||
let command = AleoNode::try_parse_from(&arguments).map_err(CliError::failed_to_parse_aleo_node)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_aleo_node)?;
|
||||
|
||||
|
@ -86,6 +86,7 @@ impl Command for Run {
|
||||
if self.compiler_options.offline {
|
||||
arguments.push(String::from("--offline"));
|
||||
}
|
||||
println!();
|
||||
let command = AleoRun::try_parse_from(&arguments).map_err(CliError::failed_to_parse_aleo_run)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_aleo_run)?;
|
||||
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: ef995e1b03c6e17ab0a2f908f4cd7957ea281fdc38834cbaed1dac75086b6eef
|
||||
initial_ast: 74111c6007aa40eb2a994d3714e0957f54863e3f28e84a1d65026d8a6ba96c45
|
||||
unrolled_ast: 74111c6007aa40eb2a994d3714e0957f54863e3f28e84a1d65026d8a6ba96c45
|
||||
ssa_ast: 19e71c476a02d508dd74b3a480961e509811a0159aa91c6f22d054c84ef821f0
|
||||
flattened_ast: 730b7aeb357218b32fecb9e2e1eb38fa2f3231071102956b1a11565ec994c91b
|
||||
initial_ast: 60aca426daf9ba37188e78c4038830dc721f2544b371287c706eae9c679369e2
|
||||
unrolled_ast: 60aca426daf9ba37188e78c4038830dc721f2544b371287c706eae9c679369e2
|
||||
ssa_ast: ffb0fe310fd41b870adaadb055a6866d90a28b2d15675dc8b8b7a05d103b9ef3
|
||||
flattened_ast: 00ea8a92ad75e87178b948dd45de6e701d58f9d68a3129f9c9ed85610a35f41a
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8a386677fc570d7f57e8e5259334608ddef2d04d55e1aea9aa591c1d95bc84b7
|
||||
initial_ast: 9148ad7f9de7c5bad3ad096ef2c9156d11364229232531510ce6dfd05fed1839
|
||||
unrolled_ast: 9148ad7f9de7c5bad3ad096ef2c9156d11364229232531510ce6dfd05fed1839
|
||||
ssa_ast: 9c561ee9a8e1d2411f61c20a950d7cb666f214504ccfb57f12df9bda217118dd
|
||||
flattened_ast: 6d9d96e670166c6bcf22c0a415e9b31c4e6a4728588a1328db931943af24de92
|
||||
initial_ast: 2057e381209aacbb5f7679c3748c5669fe8e5c6e3c2dc0884445129b310dd8de
|
||||
unrolled_ast: 2057e381209aacbb5f7679c3748c5669fe8e5c6e3c2dc0884445129b310dd8de
|
||||
ssa_ast: 74bf56b2e3cb0f39e34e429e00035546354f63e514506a71b0dc09a0ce10e822
|
||||
flattened_ast: 21ba244f2fca28ee8139d9c7c93d905e9165baeaa0c4d19c909e9ca1dc5b168e
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 7223f540c91cd639cc122936a41fc896f821e2d57c9f6f086eb4d555dc9c9217
|
||||
initial_ast: 984b0062c1c2710920f61c2c01254ecd451e88594c8ddec6ab3fe60a3b6bf40e
|
||||
unrolled_ast: 984b0062c1c2710920f61c2c01254ecd451e88594c8ddec6ab3fe60a3b6bf40e
|
||||
ssa_ast: 6ec9e9f3f2b308055a8bc7fb6467270504f5cea4371bf8e897a250966e48b1e9
|
||||
flattened_ast: be2fde3a85189d931c76091d31a7eda0b147745a58ea5e90bbd3516758159857
|
||||
initial_ast: 7f6c228ca30ad15e4d2fb0d8c1030c0c89cffe4cd592d9a9b85e2f9658cf5dab
|
||||
unrolled_ast: 7f6c228ca30ad15e4d2fb0d8c1030c0c89cffe4cd592d9a9b85e2f9658cf5dab
|
||||
ssa_ast: dad403b3b1c2d302c8e06b15afe87117a3809e17fb20c17d95348850c2bd6090
|
||||
flattened_ast: a014cbddcd80de26e1a5fa463ee253af4e9a6ced76b9f225534587e7fae2f322
|
||||
|
@ -5,7 +5,7 @@ outputs:
|
||||
- output:
|
||||
- initial_input_ast: 5cb9782988c5736339747224b8ed4a38ee869231d131a55515cfa1f98de065cc
|
||||
- initial_input_ast: 079946da42e7c73ef17f4385e8ca310259a5e0f1e6471abee30b6175f413e480
|
||||
initial_ast: 147420ccb81a27cec8f8317bca208aef21b46219dc75e1f967fbc3482c30ea30
|
||||
unrolled_ast: 147420ccb81a27cec8f8317bca208aef21b46219dc75e1f967fbc3482c30ea30
|
||||
ssa_ast: 80979f0c0496857d1931e5f4d36bfa7e65e71ea4d95d8baba06b4203d9a2f6c1
|
||||
flattened_ast: dd38d7d95e4c974fe18b78ca7c4127ed327b0877a5847b47fa3e954a14e94fb5
|
||||
initial_ast: 16d9d56e3e3ea77b9155cf64a6c79469f0115fa4afcd157289c3b5313a6bf380
|
||||
unrolled_ast: 16d9d56e3e3ea77b9155cf64a6c79469f0115fa4afcd157289c3b5313a6bf380
|
||||
ssa_ast: b15b8ea256e969644b29e1eddcef7f795c2ae4fa39d7b22f4bc0ef6b4544a9b0
|
||||
flattened_ast: 69a909d1769d57390df47742afe613b795626f5f601ea410eae76945857d739c
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: f049b2866e2ec8e876ccaa3221109137b3d895d7ebfa0917506009861c15c687
|
||||
- initial_input_ast: e047d07a8d39dbab50f3b02256ff7a58f9ba2a8b9128ef7f79867add3fd4416e
|
||||
- initial_input_ast: 5dd6a99b2d55a543947f75934bbbc7f32ab8478a5b1a567e6c917aaa1800d4ec
|
||||
initial_ast: c1068c7526ed38b32a16d2b7904f184af3e685fe909524d100448b4b74db20bc
|
||||
unrolled_ast: c1068c7526ed38b32a16d2b7904f184af3e685fe909524d100448b4b74db20bc
|
||||
ssa_ast: 1284bdb8af4f441f2ef8a017d30c80ef018c40ad2d3edfb62e8a44b8dde7456f
|
||||
flattened_ast: 16b548d170575c2646dbf5585a66410f111577baf27f93c7e4621b791a63676a
|
||||
initial_ast: 6c3577e8555c2e47b24e5599aea21b417ef4e1a09ba08391caa2335c9cbf5379
|
||||
unrolled_ast: 6c3577e8555c2e47b24e5599aea21b417ef4e1a09ba08391caa2335c9cbf5379
|
||||
ssa_ast: e6db1a1540fd341f651de401faeae13790ebf087667cee54a3e3a749baccaac0
|
||||
flattened_ast: f53398d8adc2ae8703535963f4e99bf880642232b51e63dfce71b76efe808bcc
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: 7a6c45e7cac800efe7f8d73af2fb9e926f49c62073a5cb13c463670ca0234ff7
|
||||
- initial_input_ast: 0ac5a86e326e8f5f561e1030162ee1a307bdf56425abe3cafe38b8bda4aad86b
|
||||
- initial_input_ast: 9eebe7b8b91000400e94d9513f5be1c50c51207e0e5105248f68789e74aa82c5
|
||||
initial_ast: b05ffaa1c5f53b6554d685557606710657817f5fe5a6de2b3dff4ce20426699f
|
||||
unrolled_ast: b05ffaa1c5f53b6554d685557606710657817f5fe5a6de2b3dff4ce20426699f
|
||||
ssa_ast: 5d166a4ff1741b1130c4d8818444473bcf7ee8fd915f13df0568ea7a238976dd
|
||||
flattened_ast: 677d26faf130b3e947577ec07ce4221badb04867fc4fd07fec38fdf55dd52aa1
|
||||
initial_ast: 1e0768370b05b457606c489f079b7d69d61f8364f606c003f3a27eb015fb2870
|
||||
unrolled_ast: 1e0768370b05b457606c489f079b7d69d61f8364f606c003f3a27eb015fb2870
|
||||
ssa_ast: bb8eb614f4922393c678cd290f53e76c3e7b5ca498e7a8eb066dc2b59c968c70
|
||||
flattened_ast: 7762192411e8d269a91c099925df5d23fcd930a59aa8119bc0d0ef86c0e849c9
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: f049b2866e2ec8e876ccaa3221109137b3d895d7ebfa0917506009861c15c687
|
||||
- initial_input_ast: e047d07a8d39dbab50f3b02256ff7a58f9ba2a8b9128ef7f79867add3fd4416e
|
||||
- initial_input_ast: 5dd6a99b2d55a543947f75934bbbc7f32ab8478a5b1a567e6c917aaa1800d4ec
|
||||
initial_ast: f399e79c79f74ef3da53a264324b275d6e820ae0942aa61305fadfd37e1cd482
|
||||
unrolled_ast: f399e79c79f74ef3da53a264324b275d6e820ae0942aa61305fadfd37e1cd482
|
||||
ssa_ast: 5d81d7d85c433c988b0577172cca792d0e4f5c3cac420f6eb624d012587e2d3d
|
||||
flattened_ast: ffc0a94a0212e64c06dfc3e39fc346b11acf8e29a33135ea41214ce2e2b7bdfa
|
||||
initial_ast: dcb75947a83d758e1129f8e9c8acac23445175fd9b713f455a64a075b9b22eb4
|
||||
unrolled_ast: dcb75947a83d758e1129f8e9c8acac23445175fd9b713f455a64a075b9b22eb4
|
||||
ssa_ast: bbd2a981628e8e7a572eb8bcabad77fa0d7db8c259c6783031a49ec6c60efb96
|
||||
flattened_ast: a88d8bbfc4bb2b94700869c8646a04faf2ed1cc72685b952f4f5157235d5ad5e
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: f049b2866e2ec8e876ccaa3221109137b3d895d7ebfa0917506009861c15c687
|
||||
- initial_input_ast: e047d07a8d39dbab50f3b02256ff7a58f9ba2a8b9128ef7f79867add3fd4416e
|
||||
- initial_input_ast: 5dd6a99b2d55a543947f75934bbbc7f32ab8478a5b1a567e6c917aaa1800d4ec
|
||||
initial_ast: e42cb810be0717104eae244acdc53f95ea37a739554ee0978a9b693bc93a92a3
|
||||
unrolled_ast: e42cb810be0717104eae244acdc53f95ea37a739554ee0978a9b693bc93a92a3
|
||||
ssa_ast: ffffd952b1e2cd9f35fa84b65d52c9177de1be81c9ac90204f7737166e805f65
|
||||
flattened_ast: b10035dd45fabd6d2f76b84e1d6c7051658f968c2dbfdb4fadd5d11766989f64
|
||||
initial_ast: d26dbb6f0ebeab08c4b96f40b97e9d3f90e4afbda410da2bf44046c7f8d4b739
|
||||
unrolled_ast: d26dbb6f0ebeab08c4b96f40b97e9d3f90e4afbda410da2bf44046c7f8d4b739
|
||||
ssa_ast: 935f510986a42c0fbabb1143a92e20d13b025f903278d2bdb59ebe69e4e0dee7
|
||||
flattened_ast: f1bb513e7c53f0a62d3147b47bd6a93f0a67f2ad02fc93000229283071d61631
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: 6da90d928d023c26a92106b9ef3bbf3d6e1ee2fcf67b16aa9c8477477cb4b064
|
||||
- initial_input_ast: d82ff0fb53ab27ed095ea5bbb4e118fbde50d4508caed65cb8029ad7441ef0fd
|
||||
- initial_input_ast: 07a295a1403e9020a1fb03ddcaf92b18a3237d1d4ad70b1549db77f1e2d1e6b0
|
||||
initial_ast: 79a70f233888d2d8040892c75993e0ee543cf2e0580bb48fb26d2ea434779433
|
||||
unrolled_ast: 79a70f233888d2d8040892c75993e0ee543cf2e0580bb48fb26d2ea434779433
|
||||
ssa_ast: e303fb7679c44ee8ca24597af136b2b5f2eabdc778cc9539c9029e58242a6292
|
||||
flattened_ast: 81ceed9d1bfb8f7e8c7284d456286489cb198ff4f8270ef31d5b632afead1215
|
||||
initial_ast: da9c528bc9e8e66ded4039a07f8126faa611d78f057eaea291be616ba83631b9
|
||||
unrolled_ast: da9c528bc9e8e66ded4039a07f8126faa611d78f057eaea291be616ba83631b9
|
||||
ssa_ast: 90b3e5210fb372c270b93c462a25be0b2ea44802136a6bf2e3179e05334893d5
|
||||
flattened_ast: a2229e04ce6fd04fd20a08eab36d29da02ef24f8a3f2870c111ddb4ce0eda5c3
|
||||
|
@ -7,7 +7,7 @@ outputs:
|
||||
- initial_input_ast: f049b2866e2ec8e876ccaa3221109137b3d895d7ebfa0917506009861c15c687
|
||||
- initial_input_ast: e047d07a8d39dbab50f3b02256ff7a58f9ba2a8b9128ef7f79867add3fd4416e
|
||||
- initial_input_ast: 5dd6a99b2d55a543947f75934bbbc7f32ab8478a5b1a567e6c917aaa1800d4ec
|
||||
initial_ast: 881a81aea7b6779e5075e88bdff48739d34bb303ef2e037f4459aa96777eb30e
|
||||
unrolled_ast: 881a81aea7b6779e5075e88bdff48739d34bb303ef2e037f4459aa96777eb30e
|
||||
ssa_ast: 527aa0d4483de722a0e1b9d11336b402fa7944e003892a51d2ae3c74acc3248c
|
||||
flattened_ast: 03a8cdde887d1c556a568d291dc8901b6eed765d507ee82727576edf05a6ce64
|
||||
initial_ast: 542e4b787820da86029a2d091fbd1c4f550d5c79ebe00aa3a8d0c4791fe75bf2
|
||||
unrolled_ast: 542e4b787820da86029a2d091fbd1c4f550d5c79ebe00aa3a8d0c4791fe75bf2
|
||||
ssa_ast: d81976651a4f5467eddb86cad6139ea40cc30811544b929fd9cc232510921751
|
||||
flattened_ast: 30d5332085a4dad240b2b59e3c005d839ae3d13ac5705d03aa7989e792c71f10
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: d6ea059c4a9c0394d538bbc34b56f762226d75fe3655475bfb6cab78c0479657
|
||||
unrolled_ast: d6ea059c4a9c0394d538bbc34b56f762226d75fe3655475bfb6cab78c0479657
|
||||
ssa_ast: 40b30a4ce233c28c60f9f7d05df0fdfeb6a6ca34000757a4f738cbbcad629c59
|
||||
flattened_ast: 3a4845ad0923ff344ef60ce26dad1ac5d424f89c82977a5967baa0884385d942
|
||||
initial_ast: 399e5c01eac6776b8f22bd1804d979cf56914f6d2e0c1e24c3296287daa4b030
|
||||
unrolled_ast: 399e5c01eac6776b8f22bd1804d979cf56914f6d2e0c1e24c3296287daa4b030
|
||||
ssa_ast: c303a8ad534e6172946c7b39bcb6f45fe28e9c9e33f018bae1b783698c992521
|
||||
flattened_ast: dfeaca780c19e422dc1b54b111daf9ddf99338747dad148333eb49f64a54e659
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8fbdc7881fb5e917ccec6859b63f376841069ddada687114f1ff6f364e282e8c
|
||||
initial_ast: 935321dac8ae215562c7bfd5a61e6f753d5ac28482ab3b4959e09606e3e139c3
|
||||
unrolled_ast: 935321dac8ae215562c7bfd5a61e6f753d5ac28482ab3b4959e09606e3e139c3
|
||||
ssa_ast: 6c6f83690c46e2633c54f370eabff03bc7a83f87d2c715dfc16ff8e9c9eb429e
|
||||
flattened_ast: 07db7f71c5fe89b1adf16160a62a5b45916602121b3e6039c9fed19e0c74b5d4
|
||||
initial_ast: 2682cb2889f0cb90c9cce25a9568b3c5ab110ca57e18a81e323b76cb7783436f
|
||||
unrolled_ast: 2682cb2889f0cb90c9cce25a9568b3c5ab110ca57e18a81e323b76cb7783436f
|
||||
ssa_ast: 4a197c73ea1b81a777c81f5d2b07097d931a760b39e32aa453af8187ac0c6340
|
||||
flattened_ast: 85f663133486589eb5c754ecae07ae645b45df26216a39a19cbd62f1c9725eb5
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 00ae278f2e47685455a873498a580f06abfcb7bae93cc5844c2616a7da7d03db
|
||||
initial_ast: a94e6ddf6a6d4711f93ee4796d74ade5525c060709fc5ec3174fc75b2f22da1a
|
||||
unrolled_ast: a94e6ddf6a6d4711f93ee4796d74ade5525c060709fc5ec3174fc75b2f22da1a
|
||||
ssa_ast: e0faa26023feac3c025773f0d48b6c199b01d477e490e3dae47ccaebffde5c28
|
||||
flattened_ast: 3998a8b5bfbef98ab1b2702b5d826a56681f02d503cd78351ca72ba0bf6da113
|
||||
initial_ast: ce017104a41591f5c5e5ed2893922df2cf28c22522729e8bbed5998090a72cd8
|
||||
unrolled_ast: ce017104a41591f5c5e5ed2893922df2cf28c22522729e8bbed5998090a72cd8
|
||||
ssa_ast: 5e31a762306b5928c8899e504c7430221c09f49b8490eab1e3171f84ea9a0c75
|
||||
flattened_ast: 529d582e6b4910c70e30aec56190cad7b51ca512f216cf2784d420a0cae0841c
|
||||
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 6f105b81caca7b2268ee9ac70dcb674b02e48d8a29b026aa94c2cb12c46789cc
|
||||
initial_ast: b9f8e6b1ae0f57caff61df33ff2ed4b01a5fc0d63b8b2665fb5b1a51ad328c20
|
||||
unrolled_ast: b9f8e6b1ae0f57caff61df33ff2ed4b01a5fc0d63b8b2665fb5b1a51ad328c20
|
||||
ssa_ast: e74d211efe5f9307eb7468be5328e602d5a24570cd89e2baf2380d43b8e13781
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8d27a137e4677982055885ce77e8982228972abc6ed4ca1638d04c3183d19e07
|
||||
initial_ast: 0794be1b37a9427e23aa22110bbaa681591db003a82261c5e061627b67325093
|
||||
unrolled_ast: 0794be1b37a9427e23aa22110bbaa681591db003a82261c5e061627b67325093
|
||||
ssa_ast: cd94223532a0d279db96857167a3088db1c780a3eab2b8d1bc36c3252064f7cd
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 06ca750e19583956979968f4f3fa54ae1e11219af80c88b2722ca4a169b48751
|
||||
- initial_input_ast: bdf478032fd867197166feec39cb6c567c15c78a9b0ce919730dc36ed5fdfac2
|
||||
initial_ast: 3bb4a339efa4ee13910a9d124bfa9accfabb3f0ee2ea26bb0fc801bf3060f665
|
||||
unrolled_ast: 3bb4a339efa4ee13910a9d124bfa9accfabb3f0ee2ea26bb0fc801bf3060f665
|
||||
ssa_ast: b3d3761e28a85e547e9577d3e7daeb5e342561cdfb99d29b95e41a6ad5436fc1
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370005]: expected -> -- found '{'\n --> compiler-test:3:17\n |\n 3 | function main() {\n | ^"
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: fea9fe8b6d89ea2018cac145aeebb2240a195f9cf3586ee60558e81791e9ebd0
|
||||
initial_ast: c622fa0ba9993d1fd88da65aae2d2c6ec68f529a136dafc989a1da601e994a18
|
||||
unrolled_ast: c622fa0ba9993d1fd88da65aae2d2c6ec68f529a136dafc989a1da601e994a18
|
||||
ssa_ast: 5b0162059ae3278dd27cf6b715fe8924be7e53baf749b64b3ce03a9c2d75a955
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 987814f874125b118371952a4d882da2c78ee2c441d8fb228372ec0c8f2c5aad
|
||||
initial_ast: 5ad90e127767873141d0ffb7aece1ea35cf0596a4af53a4445de27913896bef8
|
||||
unrolled_ast: 5ad90e127767873141d0ffb7aece1ea35cf0596a4af53a4445de27913896bef8
|
||||
ssa_ast: ae242f83b3e82979d257a6836ba17250486777f637807408ecd74bfa3f6424c1
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 7f94df9586954921fa1d2a86514669de35d102d4544fde34645d042810684363
|
||||
initial_ast: b040faf711350fd0a4d5a0f2d24683f3b276cf1e602ed068a419c619bd98b415
|
||||
unrolled_ast: b040faf711350fd0a4d5a0f2d24683f3b276cf1e602ed068a419c619bd98b415
|
||||
ssa_ast: 3c46e4cb77e816db36878101b84ebba44b6f832620834b9ad79972cda5ab7f76
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370005]: expected -> -- found '{'\n --> compiler-test:3:17\n |\n 3 | function main() {\n | ^"
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370009]: unexpected string: expected 'formatted static_string', found 'hello'\n --> compiler-test:5:17\n |\n 5 | console.log(hello);\n | ^^^^^"
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8d6ceebb7eec5992baf2e10dd8b859dd823a066e40289d5fa2a3df24a0dc56f0
|
||||
initial_ast: 8903fd80b2bf02ed5e96b14441b83d69a09ccf670961ab5213cc2f5e131684db
|
||||
unrolled_ast: 8903fd80b2bf02ed5e96b14441b83d69a09ccf670961ab5213cc2f5e131684db
|
||||
ssa_ast: 34934d9d302a1f80cb9ee60fb1f59e74447f4e343aff1590eacd839480033b60
|
||||
flattened_ast: 97bc52775c1f822ccc2ce947e6fac88e31bf5af2abd960016c8cae8497fd9142
|
||||
initial_ast: 7755af48fa14f5417f90b6fb47183c13e1e7cad87f03f29d42392f4ed7bd9148
|
||||
unrolled_ast: 7755af48fa14f5417f90b6fb47183c13e1e7cad87f03f29d42392f4ed7bd9148
|
||||
ssa_ast: 4b709f402c946a428b40b34860589ea14be881b4c070f77e45f19184092936cf
|
||||
flattened_ast: b7672e04d6dc9bb26d9eaf5204b1a916d7dd9650549386df261c9fc8da2750d3
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 63a3ca615379adca59155029f240686c68b95ad4885f23971dffba3444880f46
|
||||
initial_ast: 7849140c0e36a400e527c807b6d64b68ec0b862f5f3669763a2fa30fdcb7367a
|
||||
unrolled_ast: 7849140c0e36a400e527c807b6d64b68ec0b862f5f3669763a2fa30fdcb7367a
|
||||
ssa_ast: 47dd7ea513bd2a911f75cca9a49a87a827f2a222b3c4efeda6e4f5362c7277ad
|
||||
flattened_ast: d41851bc8eb88d9b2bd825f6e1b5f29e20d12e92e35e482b9a4e2a862149337d
|
||||
initial_ast: 810699ddd2296418131f85e365a05a658f5465b60a59d8d3c7f1b4a26f3ff53b
|
||||
unrolled_ast: 810699ddd2296418131f85e365a05a658f5465b60a59d8d3c7f1b4a26f3ff53b
|
||||
ssa_ast: a42d38d13dd2122f19d2c1b7d53435435bce745375bf5c34b36b6f1777bc9443
|
||||
flattened_ast: ee52d27410e90f82ef478fa07287784c8ca0cc0d5ce42bb8497f10d41e2f819d
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8762f4e3aa37b05e762fbfce76fe6904854e68b4f6c41b3151f2c472c172a50a
|
||||
initial_ast: 58354a3f130aec878f279494196abb9be21000e78e2ef07d81993cecba7012ee
|
||||
unrolled_ast: 58354a3f130aec878f279494196abb9be21000e78e2ef07d81993cecba7012ee
|
||||
ssa_ast: 1576837d18755a2506a96b7ff6fe1283a39c21e1517a1042200a2e46bf71a5da
|
||||
flattened_ast: 8c7685683d896be857be3a6e1a0083433da0018de9fae4c2fc35729c0e968a43
|
||||
initial_ast: 7796c77f0ec58a43c13a2f8687d332dd8b2a7934a9a8be13652d5c9dca96a791
|
||||
unrolled_ast: 7796c77f0ec58a43c13a2f8687d332dd8b2a7934a9a8be13652d5c9dca96a791
|
||||
ssa_ast: d30f3848317014603ca50f5c84e452bdfc79c00c99bf1f36631a7b2dc0851f43
|
||||
flattened_ast: 402c17304ff28f7fab7bcb5a8bd8dca98264f38d92ec1646bafbc5a6593b8ec3
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: b638b226aa80d9c8720c2abc5fef167a2903a7e46c0a15a10d85c9a9bf73ba13
|
||||
initial_ast: acf1332b3e50018dd9c08f0e2eeed37a1c5a0f08aa8ee5150992dcc51ec4703e
|
||||
unrolled_ast: acf1332b3e50018dd9c08f0e2eeed37a1c5a0f08aa8ee5150992dcc51ec4703e
|
||||
ssa_ast: b64d34803f1cd84be4335ae4b73ebb75415d195fff8638845f02c27512d74d6a
|
||||
flattened_ast: e3a01e1c1960b51f05f9e364d48ac27d854e8e7a67cfdaa963a4f5d7a604de1a
|
||||
initial_ast: e3400c48c510d33df5b886ca06d03fe0ae83e890624cb0d4711a0ab0802987f4
|
||||
unrolled_ast: e3400c48c510d33df5b886ca06d03fe0ae83e890624cb0d4711a0ab0802987f4
|
||||
ssa_ast: 9f5ad967cc8e49e4b88def2bf82ca153613df0777ba01bff0c3dad3bb0c012d0
|
||||
flattened_ast: a1d8289fcfbecad1b22dd5c27cb45a75581e5d04d099fc9ad60ce138ca4562b4
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8762f4e3aa37b05e762fbfce76fe6904854e68b4f6c41b3151f2c472c172a50a
|
||||
initial_ast: f2c00b12d62a178bbd497d3b97e8c82524b7017841b4981bdb22c0659c424ae4
|
||||
unrolled_ast: f2c00b12d62a178bbd497d3b97e8c82524b7017841b4981bdb22c0659c424ae4
|
||||
ssa_ast: 2a7ea14ba791f357e277f0a2a1d8f787eddfb49dd34ddec1666f3ff555bc5e98
|
||||
flattened_ast: 9c88fbcb38c6494f4b5ff3d418b9dd69eb9fd739469bf3080edb4f6407b30a4c
|
||||
initial_ast: 7103a45a5480a7f30dac3d08f4d8bd103ee4bd09728a4a8bc72e055e7e82290d
|
||||
unrolled_ast: 7103a45a5480a7f30dac3d08f4d8bd103ee4bd09728a4a8bc72e055e7e82290d
|
||||
ssa_ast: 2727a59b3d316203883ac50184dc5302f0457073df9c18dca3c03f5397c35544
|
||||
flattened_ast: f847f470fe5e31816f55b855f8424dac03e9fea7f2691814554dc0364b7dfa2c
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: b638b226aa80d9c8720c2abc5fef167a2903a7e46c0a15a10d85c9a9bf73ba13
|
||||
initial_ast: d42dde2e874e4f99efd01efe1e4961f61d6f8cff46e30c038fbd0a3735e00bd3
|
||||
unrolled_ast: d42dde2e874e4f99efd01efe1e4961f61d6f8cff46e30c038fbd0a3735e00bd3
|
||||
ssa_ast: 2b365232f1fb9e7dd576fa2fcb172d86f058be4544f353b96ddb6ceb9e245379
|
||||
flattened_ast: 6c6dd818ff24551f5f36e704f476247308f5afe578c1aee16712c7c8409fdeff
|
||||
initial_ast: dfd7aa65428709ddb83336f29a0aa7c4562e52d4855ca12b76203bfec52c2d23
|
||||
unrolled_ast: dfd7aa65428709ddb83336f29a0aa7c4562e52d4855ca12b76203bfec52c2d23
|
||||
ssa_ast: 0ee87241ef943f70de6d75bfe531f60c7542d3cb17318c5d0f12d5011a6bc014
|
||||
flattened_ast: 29711b6b312e9495ab5d0044e369f98634ee1a962b82958aadac245b3ddfa390
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 8762f4e3aa37b05e762fbfce76fe6904854e68b4f6c41b3151f2c472c172a50a
|
||||
initial_ast: 9826202bb36bcfcaa5d89d31de7c26a8e17bdcb1f858c924272c7b781e7aa1c8
|
||||
unrolled_ast: 9826202bb36bcfcaa5d89d31de7c26a8e17bdcb1f858c924272c7b781e7aa1c8
|
||||
ssa_ast: 71fcb33cb7d7af8f6f92c24e252973c0d1f062c09644a5326f4926ac86a5476b
|
||||
flattened_ast: 1bc3c6d850b3b9ea858cc44206cbfae54b5c082eea6500ea248e2ca263c8bb5c
|
||||
initial_ast: fd40b8ebbb75b41c1b6b7ad11b3a3c32faf08b31fe5b96270b1d28f95bb99a5a
|
||||
unrolled_ast: fd40b8ebbb75b41c1b6b7ad11b3a3c32faf08b31fe5b96270b1d28f95bb99a5a
|
||||
ssa_ast: 65ec356acb6ab71462925da6226ff2e0842d1e8421e70ab476801c0ecc24c52e
|
||||
flattened_ast: bab304fe421d35178e0018cc513e4f25b5ce69cf8bc9d1bf01b20ea6161ef929
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: b638b226aa80d9c8720c2abc5fef167a2903a7e46c0a15a10d85c9a9bf73ba13
|
||||
initial_ast: 142d39ab2813fecc19a096468315f242e72a9c586d1532fc96386e107678b47e
|
||||
unrolled_ast: 142d39ab2813fecc19a096468315f242e72a9c586d1532fc96386e107678b47e
|
||||
ssa_ast: 4c518161bd0e20e4fa6de1750fa52a62d07a09b8b93427257644d7a7f869c919
|
||||
flattened_ast: 7743fbb072340a5e48e4ce17c240b1e73198cae3a0bf635edc465afec96094f8
|
||||
initial_ast: 1f15a920d9eb3128245064ee1ff19fdb6e5dc0095ad67ec6e791b121cb98c265
|
||||
unrolled_ast: 1f15a920d9eb3128245064ee1ff19fdb6e5dc0095ad67ec6e791b121cb98c265
|
||||
ssa_ast: 8e72da7f56ae155a4a9b05f5cc51c18edf77b90e51122742b5164862397ef818
|
||||
flattened_ast: 9924bdd85dd2ace14e0830f91650fa71b51203a863116dbada0100a818b9d8b8
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 5ea1607a031b1eaecb1b6aac13dae8c78f3fc15c5f9c7d8db94001539426f7eb
|
||||
initial_ast: edce2be4d936b46d3d6601182db3463a7c0153bc7f7bdee70d1ef472bb64fcf3
|
||||
unrolled_ast: edce2be4d936b46d3d6601182db3463a7c0153bc7f7bdee70d1ef472bb64fcf3
|
||||
ssa_ast: 30974184b79ce16214677e84e1d35739b030359f7472e02256a803259cd43481
|
||||
flattened_ast: eab2a17522833f8e9b0a48b87434e6340b7daf61b4cb32ee0d8212703986edb1
|
||||
initial_ast: baeb24b1f31b4aa82a6897fa17042f17fc3d3488010763ae7d51c53735fa6687
|
||||
unrolled_ast: baeb24b1f31b4aa82a6897fa17042f17fc3d3488010763ae7d51c53735fa6687
|
||||
ssa_ast: cb68431db2ab894183ea0c2ab10763d5ff248dd38e6357d2d0727283fb523b2f
|
||||
flattened_ast: 32dd2281edd7383e8699c7b011a7f70ae2ac51d7096e6524a03e515da1d43c3a
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 43e7c413d898dd18070456e6875adbf73a93f3cd2703fc7f6bc7c793d8063bbd
|
||||
initial_ast: a2eab8ce0e64bf860f4dcdb417456472ae3e6ab589f10671610bfbc9d6286daf
|
||||
unrolled_ast: a2eab8ce0e64bf860f4dcdb417456472ae3e6ab589f10671610bfbc9d6286daf
|
||||
ssa_ast: e319d34bc5f262473ef97591576d27331dba26c8973efd22dfeb61d799b0916a
|
||||
flattened_ast: 23e2785a4e80347990da3ed6734fefe1c6268ff152ca70f2fdaeddb075c296cd
|
||||
initial_ast: 73f059d09937d69534aeecb3c2e1e85926eaec2d6b609a303d32a9b44e2e2996
|
||||
unrolled_ast: 73f059d09937d69534aeecb3c2e1e85926eaec2d6b609a303d32a9b44e2e2996
|
||||
ssa_ast: 109520afec3da0053b566aaa754dee1ca6a492bcf3d92ef389d5bac80649a664
|
||||
flattened_ast: 5293dfaaa403841e50f7851ac74055e7ac96155ed8641134c739e05a75144fa1
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: e3f5a66af9a0c987403e9ff8c0e084c127a374827259aca0e5b8f877a72700cf
|
||||
initial_ast: 3854d622a8991b3f900e9e77c60950c14541a9cfa13ff28914a1367e43cedc83
|
||||
unrolled_ast: 3854d622a8991b3f900e9e77c60950c14541a9cfa13ff28914a1367e43cedc83
|
||||
ssa_ast: c82824e8ef89e7aedd84a7aa0e958044f3a7b763a573a0977d2ea7a0cba9289d
|
||||
flattened_ast: 39803ccdd17079915cc9b899419fce48775f1cfe2d15040379ca1b0fa5008beb
|
||||
initial_ast: c9d9523624ef7ef1f2d83802edf9b74864239d1161337f1e8f65a1ed337721c7
|
||||
unrolled_ast: c9d9523624ef7ef1f2d83802edf9b74864239d1161337f1e8f65a1ed337721c7
|
||||
ssa_ast: 280bbfb0de512b77bad9b62dfb4bb883ca744edda97957df2336c4a52d2e38f6
|
||||
flattened_ast: 03e0b32e1c56093aadd4a1af4ac3b0f3d398b756a10440594e62cf2c4bc01240
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: e4ca07cbf83cbb0689e77f23f535f3e207b95e02ced7b97c0e54181109e4e435
|
||||
initial_ast: 31b03ee1a972ed7ff5af17ff19daa091ec7ebbb4cb8e04dc57cd300bb5dde887
|
||||
unrolled_ast: 31b03ee1a972ed7ff5af17ff19daa091ec7ebbb4cb8e04dc57cd300bb5dde887
|
||||
ssa_ast: 278b4c43b0cd54c4781f17024baa960961fe58ea0deb3ccfb0330760ab518649
|
||||
flattened_ast: b25e798d5951c3f9133fb1a793f8950dc6128aca49149175800ad740c3167e55
|
||||
initial_ast: 9b31d4f47de0c315601754df1f7460938a382a4de56aa7b3b285c2f4004583e5
|
||||
unrolled_ast: 9b31d4f47de0c315601754df1f7460938a382a4de56aa7b3b285c2f4004583e5
|
||||
ssa_ast: 85649cecc12100009fd032e3d8f4b7a1e1f14abd50f4a78de691e02bfad6dcef
|
||||
flattened_ast: 1ee55ed5def4045f0a4790efa8e3fb73b5816c3ce2d5f47cc3bc13ad2acb353d
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: bd66a8c48fe434715d1d19ca0c60e77b4f2b8ec92f4b0a785277774a2074a804
|
||||
initial_ast: 22116947f0e502345f67deea4376392a6d5a7a1c147dcd4d58d3bda0ddfb245b
|
||||
unrolled_ast: 22116947f0e502345f67deea4376392a6d5a7a1c147dcd4d58d3bda0ddfb245b
|
||||
ssa_ast: ee76b847a759607f4ba1f4e896b67434442e0af2f7e666c14cbbed9c3a6c0086
|
||||
flattened_ast: 4ba31b085167ff9a5ec622d5a41e21d8443d767046795d1545a26cbd3655e639
|
||||
initial_ast: 26c0866267e8a0fc6906f8a3ae58065d25eebf680203bc6389279a994a36bbd7
|
||||
unrolled_ast: 26c0866267e8a0fc6906f8a3ae58065d25eebf680203bc6389279a994a36bbd7
|
||||
ssa_ast: 93a00777cab8fd569c02c1912bde13423ba76969fda194cfb90d53c33b7b7d62
|
||||
flattened_ast: 6ce624bb4854f15c293eb1bf648c7e78eba27170967d6ac256882521a18a6714
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: bd66a8c48fe434715d1d19ca0c60e77b4f2b8ec92f4b0a785277774a2074a804
|
||||
initial_ast: 992d7b50e675edb82bcbad04d90276b8caeaccd815aea3eee972589e4bfb789a
|
||||
unrolled_ast: 992d7b50e675edb82bcbad04d90276b8caeaccd815aea3eee972589e4bfb789a
|
||||
ssa_ast: b4defa34c9d548db0f4cddb89da478b4ddf522227d8edb513fad7b6ff09451fa
|
||||
flattened_ast: 0c0ca9e6d949f089e03fea84caf72d5ac1ccbdbfd10ae169fd5fff5032d6d166
|
||||
initial_ast: f6b19cef14fa836f6819cf82f8d9698f6de23b53ceac435c87ce255e513fff67
|
||||
unrolled_ast: f6b19cef14fa836f6819cf82f8d9698f6de23b53ceac435c87ce255e513fff67
|
||||
ssa_ast: 5852258fec031000d4718bda4fd974b3a2af7d732110b243fa8fa32e84857329
|
||||
flattened_ast: 92ce201c50776daf40223fa264a5192fd09fc622041595f3609b62e6cd98b4a9
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: bd66a8c48fe434715d1d19ca0c60e77b4f2b8ec92f4b0a785277774a2074a804
|
||||
initial_ast: f6c4fd99998e9c3bbd97aa8778435493b4e68cdb60fe21d3a5dcb1251225c5f2
|
||||
unrolled_ast: f6c4fd99998e9c3bbd97aa8778435493b4e68cdb60fe21d3a5dcb1251225c5f2
|
||||
ssa_ast: f4aa21d116f7f2043d0acce34d88a0fd36dc6c341ea1a453490fd58774ebaefc
|
||||
flattened_ast: d2d42db9bcdefdd583835d4b4f774f37515bffcd47194c34736cac8ef1dbc228
|
||||
initial_ast: 20fb9299a9f207d435ea934cbd422d55d59dc9f0eecc36cb8e4f1bbe69ade5c4
|
||||
unrolled_ast: 20fb9299a9f207d435ea934cbd422d55d59dc9f0eecc36cb8e4f1bbe69ade5c4
|
||||
ssa_ast: 6a87bf46edb6e628df6e90b0b047d1b73d8dba988fa95c78b5e90b125a881d33
|
||||
flattened_ast: ef158133de6b391389947e54e61fb8891f4288296b3a84bf98208126cf3b1c6a
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 19bd7efeaa5dee077b8d47a087ceadc2ba287507268fd8586f4e6f5881b71c39
|
||||
initial_ast: fa924a57d700de68e1ec3250bba4d5b66f05c4404d9fccc3821928a3296a2ba8
|
||||
unrolled_ast: fa924a57d700de68e1ec3250bba4d5b66f05c4404d9fccc3821928a3296a2ba8
|
||||
ssa_ast: 688654fb76e7de8d9af8b5e7071b6b5fc3c641be793125b7144657eb8ed20d13
|
||||
flattened_ast: 5d79e9163a1b400164035e9a57f73452ee1b6a19bcdf39f0df6f84b82d62922c
|
||||
initial_ast: a89c4aa81cb743f8c9e39e52164d0022f8c9992afb8447c3d92503779227feeb
|
||||
unrolled_ast: a89c4aa81cb743f8c9e39e52164d0022f8c9992afb8447c3d92503779227feeb
|
||||
ssa_ast: 73adc4582ce761cd706c31116e715c055339c4d6e93558a0692c0f0d2bfc1901
|
||||
flattened_ast: 326a9ba3e0a88d4b791741fdf4c5b9e1ab3238e3035897a7dad2cf59e29c0491
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 38e152ef2d3449f93d8c1858a916854228a76dd18885b01cb4a88c14d84308bf
|
||||
initial_ast: 628cfcf0a7118c904ab9a439f7b8ac2b08bd3cb10a279c063a1a3b06f90a2a23
|
||||
unrolled_ast: 628cfcf0a7118c904ab9a439f7b8ac2b08bd3cb10a279c063a1a3b06f90a2a23
|
||||
ssa_ast: 3c1b3bcc67a6e0dc844db16acab349d5062eacea4f5a2ae20ad87703fc99f2f3
|
||||
flattened_ast: 8cbd286f80ac99a06f7e1036e2f6003cccdea160976fc8a871737fa06ca28469
|
||||
initial_ast: c9acdeb2f208ff412391a81e9889a792a03d205eacc0ce34ecc4ea5e51d1058a
|
||||
unrolled_ast: c9acdeb2f208ff412391a81e9889a792a03d205eacc0ce34ecc4ea5e51d1058a
|
||||
ssa_ast: 4b8c3dec168259f154f4843715c941cb69a3871eab56e1b0c6d887c0372ecdbe
|
||||
flattened_ast: 3cd47d58daa5dfc91ddfefbe8ac9894dbdd03342256f1b133179059db36927fa
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 413788ce5f6dc8aa19af5360bedfca93c33a2a6464ede476e59b75e84a8a4e4a
|
||||
initial_ast: ffb7af0061b540e44f78074c007cab0f1024bb6fdf4378023852091cc0004dfe
|
||||
unrolled_ast: ffb7af0061b540e44f78074c007cab0f1024bb6fdf4378023852091cc0004dfe
|
||||
ssa_ast: ae3042732a5634b573b186c5d4ff4f3ab44826f80cc2ab56502fd1f5ba6798eb
|
||||
flattened_ast: 6405e7d5970889065c3723a8c5ee9372d976895fd01a93e5aeb065e7fcf7e228
|
||||
initial_ast: a16185f52d2f134eb1bc83861f7b39c98643f5cfd606162cad77c5f289b2c2ff
|
||||
unrolled_ast: a16185f52d2f134eb1bc83861f7b39c98643f5cfd606162cad77c5f289b2c2ff
|
||||
ssa_ast: f32d13bb403718640f27796d03629ce52df97f0dc118216740fd64cb0b5f03fb
|
||||
flattened_ast: 9ed30a1845263307b94893d899599ceacf5a38be76056701e539c3a6d248f042
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: d88a843c0a3851c805f7eeae282a16b12eba4febde134aa0ea86415f6561565d
|
||||
initial_ast: a8258c9fd04f95521349955f7a6180e25054bc5e984c7b2fc1e412ae1f516bbd
|
||||
unrolled_ast: a8258c9fd04f95521349955f7a6180e25054bc5e984c7b2fc1e412ae1f516bbd
|
||||
ssa_ast: 90934ba26a01d3be3d4e884120033e27f7f296750def5c0654b7fce651a3ef7c
|
||||
flattened_ast: f56c9ba1a0c50ef0dd3eeaacb3cc757d49ea99d8c861284ffeb90c758eb43db3
|
||||
initial_ast: 55576dafd5e447c30ca8a9eedd2732903d7781dd4384894b7f37bdd7773f3339
|
||||
unrolled_ast: 55576dafd5e447c30ca8a9eedd2732903d7781dd4384894b7f37bdd7773f3339
|
||||
ssa_ast: 22d4a8aa55dacc1e06e515ea9afd92c164fb779864daf720c170ff46adcddcf5
|
||||
flattened_ast: d1a43581b7432032ed765bcd6795323bc5103d42505b7852ea3256739d9ea642
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 1bd243c2ca8a51ee50f45823a283d506ee506e168e5332af8c271ef6b52468a4
|
||||
initial_ast: ad6b130a938f0dd5155f90e983a7214c374c497b8c1e00cee75ccb7e763f257a
|
||||
unrolled_ast: ad6b130a938f0dd5155f90e983a7214c374c497b8c1e00cee75ccb7e763f257a
|
||||
ssa_ast: 7f6d8438a23f92d9330b8d7e66df96a73e21fb3145b7a9500d2010e075092e5b
|
||||
flattened_ast: 862d1165b3c7226dfa5dfecac9bc5a24e5bcc6633fb8d08d1eb71b935436b52d
|
||||
initial_ast: ca07155862559dcbcd8a9df352440d2f1b0cb3071004afc8418ae6f5b25b4ce9
|
||||
unrolled_ast: ca07155862559dcbcd8a9df352440d2f1b0cb3071004afc8418ae6f5b25b4ce9
|
||||
ssa_ast: 4e17bb648d103c6438c3c5776fd7157018c0139016d561de21a8768d7f9d5538
|
||||
flattened_ast: 9b4cf2b763504d9d1d0c143145ec9bd27195d973b872079d319ffaee6a6210ec
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 38e152ef2d3449f93d8c1858a916854228a76dd18885b01cb4a88c14d84308bf
|
||||
initial_ast: 21a67a09172cc2d79d483c7ab97a5a38ed8e132fb362116d2dae237323d0b67a
|
||||
unrolled_ast: 21a67a09172cc2d79d483c7ab97a5a38ed8e132fb362116d2dae237323d0b67a
|
||||
ssa_ast: f3d5d47b6b4588ef0908f272dadc91e834e9dfd9e075c9680bc6942064871f3b
|
||||
flattened_ast: 614cf33119a13bd0d119940508582276fba62ec5d20cbc59a49ba0f73c39bfaa
|
||||
initial_ast: 25c34196a4c6cf173abcfbe96d4639c86613daf52628b0b93d3ab81823923c98
|
||||
unrolled_ast: 25c34196a4c6cf173abcfbe96d4639c86613daf52628b0b93d3ab81823923c98
|
||||
ssa_ast: eb1e51c0f21d76621d2c9ac6c2c68808e5c62b71dd8678b60e4e14adc8a640d7
|
||||
flattened_ast: 462a11d950a3aded9e17de27c105b3d6a7a194299f6ac017eea30b37e65817c0
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: c0c942faa92a5c747fab2d776e6dd0067de317c69003493147610a09878843c4
|
||||
initial_ast: 89a950aac426837a580bde73fc49d51dabcd39a167f43f4dee74a0ffa0aade3f
|
||||
unrolled_ast: 89a950aac426837a580bde73fc49d51dabcd39a167f43f4dee74a0ffa0aade3f
|
||||
ssa_ast: 6f0bfcd1860dbdcbc23040af7d352071f3053ca30c8c0b4b8ecdeef34b6298b3
|
||||
flattened_ast: 2d249b0b10f86062157324741829894c0456bfca51237b68e9b5fab8b7aac51d
|
||||
initial_ast: 246d9f598a2420e00b4e3d42ddf69040e31cada19e6a10c8f00fd3c5736cc566
|
||||
unrolled_ast: 246d9f598a2420e00b4e3d42ddf69040e31cada19e6a10c8f00fd3c5736cc566
|
||||
ssa_ast: c25b4ee0ddabe79a2df19b021cd6e73ce0f3a2f371560bc3a2111ae526b416be
|
||||
flattened_ast: bac91a0a759bf24fe756eba8c967e64430d2cdae364550b1046972b4f952c74f
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: ea8e9817122af3fa825b175438a1af4943d31c5c893a3af31b96964f80ec5850
|
||||
initial_ast: d15977d2a3812dfab405f8cf8e4c433739f01c47c8e09b8f5cd336970e903c24
|
||||
unrolled_ast: d15977d2a3812dfab405f8cf8e4c433739f01c47c8e09b8f5cd336970e903c24
|
||||
ssa_ast: a66f5b52e55ce6aee628567a23c0aa117737953ae04f27d4225a38675cb85dfd
|
||||
flattened_ast: b84e80bbcf1ada93dac226719598f58acca65cb043b9e9742bf5db23c3b9150a
|
||||
initial_ast: 1acd222d2540f9e6a51328da90ff6b90fe0ebbd799a194e9281244a2cc3a5bf2
|
||||
unrolled_ast: 1acd222d2540f9e6a51328da90ff6b90fe0ebbd799a194e9281244a2cc3a5bf2
|
||||
ssa_ast: 766725b5f9b3b0578f46c4ad6c71a45da1d649409a00124e44cb09ad57a4914b
|
||||
flattened_ast: df0ab0f368c765ddddc8254870ca552cf454e8166c2e1ef146a99fb131d14dff
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 30267abd65849fc218532e602d0e60eefb1dd235972106400258e3d9e54c2c10
|
||||
initial_ast: f2caf99b19f3d57ac03d5f051206cab69ac40dd07891e44b09c64affb7658dd0
|
||||
unrolled_ast: f2caf99b19f3d57ac03d5f051206cab69ac40dd07891e44b09c64affb7658dd0
|
||||
ssa_ast: 40de64d16cd1574dee019f40a50207e16045b96e21116b315fb76c5081debb38
|
||||
flattened_ast: 7a13ea9790d3f7b1606344d47115d9e2270762ca99e81e025ec8a9d4e5901376
|
||||
initial_ast: e8aff155e0e2df199f735fde15c2c83fcf885867fc3ba9a7f27ad09beeaaeda3
|
||||
unrolled_ast: e8aff155e0e2df199f735fde15c2c83fcf885867fc3ba9a7f27ad09beeaaeda3
|
||||
ssa_ast: 3f3f8da4d645c04d2ba4272012106b9fdcc6d76c64321c4d8d0bbdb49fcdd7a4
|
||||
flattened_ast: c49bf9a53a2cf0c0c87f95d79268d95f6ff9d2ef5167f28615cc860247fe4d3b
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 413788ce5f6dc8aa19af5360bedfca93c33a2a6464ede476e59b75e84a8a4e4a
|
||||
initial_ast: 04d6f99bfb619e3ef30beb1c8182a6c38afecbecd39bd10b49424feabbd49814
|
||||
unrolled_ast: 04d6f99bfb619e3ef30beb1c8182a6c38afecbecd39bd10b49424feabbd49814
|
||||
ssa_ast: 5d584c4d01f1a3e7b255250829dc170d34ed43952cdc098a4f7666d052a45771
|
||||
flattened_ast: 312295ab386878c3ecb6f2ca267da0662ba4f9b1cadf761e253101725993ef14
|
||||
initial_ast: 57fa51e0ed71fff7bc2601b90d506293efbdb0b4b7155b65feed8e8c6682609c
|
||||
unrolled_ast: 57fa51e0ed71fff7bc2601b90d506293efbdb0b4b7155b65feed8e8c6682609c
|
||||
ssa_ast: 9ffa84a1979072a17ab2358246b47e2629e3f15d051cab15d4c70577701f4a4e
|
||||
flattened_ast: a8ac0f95f6ef0c6f1e4df7313b09f9117bcae2e8930fce9c52dad3ed208b79ce
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: e0d887adc24d86b1ddd1b6b7fee99e39c4def4850dc6afa7765a2d45089d39cd
|
||||
initial_ast: 01a8cd34a5f5e06c35d0687d5e552ef56058d9b8ade32d5c35602028b1d71483
|
||||
unrolled_ast: 01a8cd34a5f5e06c35d0687d5e552ef56058d9b8ade32d5c35602028b1d71483
|
||||
ssa_ast: 96f77e5aa7b01f8afe5679048eb7bb9567473a72095bd690f6a3a7636e6b2b15
|
||||
flattened_ast: 65683c8b503159cda6a4c47c5c0f9ab4e6afa7c4bbf82ce6028e46a844055007
|
||||
initial_ast: 6f0badefc2b52349c6ba3aaf16dc9e911668dbf04d42d6fa9ddd6a40aa7374cc
|
||||
unrolled_ast: 6f0badefc2b52349c6ba3aaf16dc9e911668dbf04d42d6fa9ddd6a40aa7374cc
|
||||
ssa_ast: a8f7e053ccabac1b0183febfda356f5c12981298af5a23380d61cf704d92db5a
|
||||
flattened_ast: 95bc317c202aa857167f545409663d20de720485398b61acfb1f73db45a60e9c
|
||||
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372036]: Cannot use a `finalize` statement without a `finalize` block.\n --> compiler-test:4:5\n |\n 4 | finalize(a, b);\n | ^^^^^^^^^^^^^^\nError [ETYC0372044]: Function must contain a `finalize` statement on all execution paths.\n --> compiler-test:8:1\n |\n 8 | function bar(a: u8, b: u8) -> u8 {\n 9 | return a + b;\n 10 | } finalize(a: u8, b: u8) -> u8 {\n | ^\nError [ETYC0372032]: Only program functions can have a `finalize` block.\n --> compiler-test:10:3\n |\n 10 | } finalize(a: u8, b: u8) -> u8 {\n 11 | return a + b;\n 12 | }\n | ^\n |\n = Remove the `finalize` block or add a `@program` annotation to the function.\nError [ETYC0372032]: Only program functions can have a `finalize` block.\n --> compiler-test:17:3\n |\n 17 | } finalize (receiver: address, amount: u64) {\n 18 | increment(account, receiver, amount);\n 19 | }\n | ^\n |\n = Remove the `finalize` block or add a `@program` annotation to the function.\nError [ETYC0372005]: Unknown variable `account`\n --> compiler-test:18:15\n |\n 18 | increment(account, receiver, amount);\n | ^^^^^^^\nError [ETYC0372004]: Could not determine the type of `account`\n --> compiler-test:18:15\n |\n 18 | increment(account, receiver, amount);\n | ^^^^^^^\n"
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: e4d86cd0b7831c3de0304190f5af8f1ef7d8e29d1bdacb6d35381ba0e479d6ab
|
||||
unrolled_ast: e4d86cd0b7831c3de0304190f5af8f1ef7d8e29d1bdacb6d35381ba0e479d6ab
|
||||
ssa_ast: e4d86cd0b7831c3de0304190f5af8f1ef7d8e29d1bdacb6d35381ba0e479d6ab
|
||||
flattened_ast: 0ba4b1ecf6e5ebe0c7b7ed0ba10d9830902d7a492c2000fef2cf67e4b43b063a
|
||||
initial_ast: 9498c048747706d4478783a2801179d84243099c3867cb437f4141bf873fc381
|
||||
unrolled_ast: 9498c048747706d4478783a2801179d84243099c3867cb437f4141bf873fc381
|
||||
ssa_ast: 9498c048747706d4478783a2801179d84243099c3867cb437f4141bf873fc381
|
||||
flattened_ast: 30e7fb13033f0a61d999026dbeafff5fe3938e4b6ed2cb709fc0a38ce98c8c57
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: 8d3492275b704c017c6b9053d267e54ac3374934423cb2b8c5e55bb7e8ecc033
|
||||
unrolled_ast: 8d3492275b704c017c6b9053d267e54ac3374934423cb2b8c5e55bb7e8ecc033
|
||||
ssa_ast: 6c17d90ec3d2b7acf165ca2ab04e30bf8a49cb3d110ee38e7130eeaa9b0754ee
|
||||
flattened_ast: 4633594269a408f79ac385ab5d4b41b2b8b9cc69c29ea6d96761be5bd64fe2ef
|
||||
initial_ast: 4fcaf4a3cc781ca66c4ed30d4704bfa5bc31715a9cce6c12c3b45ba13deebb5c
|
||||
unrolled_ast: 4fcaf4a3cc781ca66c4ed30d4704bfa5bc31715a9cce6c12c3b45ba13deebb5c
|
||||
ssa_ast: d511fa6a72cca8b7370691502a92837faac71965312b63e55ce372271720612a
|
||||
flattened_ast: a085ceac6974fb2a2cbf32de9775e0dbe3c1ca1e1ad184141a8794df6f7bef32
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: 743ef643d0205706e875c7eb3a4fc5866e8a3e6b6c43388c36be418a0f37773c
|
||||
unrolled_ast: 743ef643d0205706e875c7eb3a4fc5866e8a3e6b6c43388c36be418a0f37773c
|
||||
ssa_ast: 743ef643d0205706e875c7eb3a4fc5866e8a3e6b6c43388c36be418a0f37773c
|
||||
flattened_ast: 7678967d822f0d82683ca4c01410377bd53e3ce78da126d0c07b651722c23be4
|
||||
initial_ast: 20577705e80224f486f237ba98fb33550fec7fb0a724eb9c339067a561d426e6
|
||||
unrolled_ast: 20577705e80224f486f237ba98fb33550fec7fb0a724eb9c339067a561d426e6
|
||||
ssa_ast: 20577705e80224f486f237ba98fb33550fec7fb0a724eb9c339067a561d426e6
|
||||
flattened_ast: 6babfacc82c1283848fc1926ca778d6a3c7a46148cfe93fec13927ed31bd950a
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: e742fe16a7df15d6f9c6b514f28746a9a5a48fda7e0bf6628601e84782878dd1
|
||||
initial_ast: 9ff7652fd6e9f8eb98218202fb58e54821adba09548e1826382934d4c3a63ce6
|
||||
unrolled_ast: 9ff7652fd6e9f8eb98218202fb58e54821adba09548e1826382934d4c3a63ce6
|
||||
ssa_ast: 1f75b9481a40777666cc514bebec6847dd678229c3800e54211cfc36bfa6fc95
|
||||
flattened_ast: 344e01d295321c1bfdbd4938d061e61c4f2785c37650eeab097a19ed129b2f28
|
||||
initial_ast: 93f6ddf8a363f5846f4ea0be8a8ee9872b99244753cbb62f448a44f5ba1c3851
|
||||
unrolled_ast: 93f6ddf8a363f5846f4ea0be8a8ee9872b99244753cbb62f448a44f5ba1c3851
|
||||
ssa_ast: a9f3714757132157a0057d73a2a9b32e353e33225ca725ecdb7765cce7ed5eab
|
||||
flattened_ast: c92cb99ac45cef4e57c5509164f694e5dfc83ce36f751079deb09f64043079fe
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: e0516243c09ed592d62da2f5db28b9c23d62a65a2d1d2f36994af7a5200ef832
|
||||
unrolled_ast: e0516243c09ed592d62da2f5db28b9c23d62a65a2d1d2f36994af7a5200ef832
|
||||
ssa_ast: dd25b1abb6b78fa6fac53f5d2c27d9b183728441b9a796a5b24e4d8be238e604
|
||||
flattened_ast: 6a0e4a111f150fd817ba4ba9e4b507395fb7f79993c816ba0d0a8207b6b8ce9c
|
||||
initial_ast: 5f0666623644b5df97e5cde9c2f83d697f42560b9c6aab3ff77b591ef6583726
|
||||
unrolled_ast: 5f0666623644b5df97e5cde9c2f83d697f42560b9c6aab3ff77b591ef6583726
|
||||
ssa_ast: e25f8b8ac74f74a74d4229341c046c8d05a07612bd2787d097cdd2ae02c7d57d
|
||||
flattened_ast: e4cf9a17967fc3971f82cd7e1bec5a241794ec081d99b73b278022b236f14198
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: d25b5d30496f06387198d06e44a771e142f8e6592347c3849a8b3b957287f1b6
|
||||
initial_ast: 1b616bafa5e8d7e18cb435f89aa62aa35289c5c8905053a74d496b3bb06b3c2b
|
||||
unrolled_ast: 1b616bafa5e8d7e18cb435f89aa62aa35289c5c8905053a74d496b3bb06b3c2b
|
||||
ssa_ast: 95d5f10d34e333921b12624ee57d50e965ae6c28ec576da7e46f0083df2f6e8c
|
||||
flattened_ast: 261ec4ae28babea5b332c340e87275bb78139d5ed3e7fc619c7618638ad32cd7
|
||||
initial_ast: b719757474b3ca863d3589924673e4e9074570fe1b95bbc08ab1c9ddece99810
|
||||
unrolled_ast: b719757474b3ca863d3589924673e4e9074570fe1b95bbc08ab1c9ddece99810
|
||||
ssa_ast: 833917e3a7251bd51c4572068c44fb86eefc973a38c4931a762817d94bfb739f
|
||||
flattened_ast: 3d8bf8350b63dd967ca2af254b3ceaa77e5c197d40f79354a6591500f2a8a695
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: aa1909b07d93826301b19607129d9ad58c8fed3666d19a3a8c7d5e6cabd4a784
|
||||
unrolled_ast: aa1909b07d93826301b19607129d9ad58c8fed3666d19a3a8c7d5e6cabd4a784
|
||||
ssa_ast: 74728731fc75c801b3b5cf5d9e568f465b0ee0e881947a6420f98cc8766aeb8b
|
||||
flattened_ast: 4d2bcb0ab5e016ac03baf3014ad284206671ad93b1b121ec063cfde3cc681c9b
|
||||
initial_ast: 9ba8e38f07e0d133ee261029fee8cd25de5f96266aafc0818331c32005811270
|
||||
unrolled_ast: 9ba8e38f07e0d133ee261029fee8cd25de5f96266aafc0818331c32005811270
|
||||
ssa_ast: fac7c287e7a169ee00ffcb5c2595baaa83f3a278f56b916a326689fc28c13fef
|
||||
flattened_ast: 79f8da1f08d9a0ef53d222eac163d59eaf9a0d54d3c72f7dc75a0bc7947ce16c
|
||||
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372038]: Function must return a value.\n --> compiler-test:3:1\n |\n 3 | function main() -> u8 {}\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n"
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: b00084908a0b08097b22f8f05d51960654857e02955744b489d6e65a626631af
|
||||
unrolled_ast: b00084908a0b08097b22f8f05d51960654857e02955744b489d6e65a626631af
|
||||
ssa_ast: cfbfe34e206a21d620942225fac473873d3b19ce8ac7cdbf35d5416aa6845f33
|
||||
flattened_ast: 090fe1adcae13655d8e3909ab9044b66d4d13a9688d1ad8259cd76aed7cce5c5
|
||||
initial_ast: 2ffe06e486343ec47a09a4d3f88413f5cb9e5f4acdc1ae6160fc6bc68f09ea08
|
||||
unrolled_ast: 2ffe06e486343ec47a09a4d3f88413f5cb9e5f4acdc1ae6160fc6bc68f09ea08
|
||||
ssa_ast: bf465100cd883d58a7ee65375addf869c7c8048601e50dba2fae60a5ebe89979
|
||||
flattened_ast: 307ca5456c46e1d42eb91eda8a70f02983381bfb8eaaa2a43e295595c0f17d6d
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: d00c57417aab0ef501832ca09df8aee8d06b2d90c98e9eaa6220bc9d03bfb13b
|
||||
unrolled_ast: d00c57417aab0ef501832ca09df8aee8d06b2d90c98e9eaa6220bc9d03bfb13b
|
||||
ssa_ast: d00c57417aab0ef501832ca09df8aee8d06b2d90c98e9eaa6220bc9d03bfb13b
|
||||
flattened_ast: d00c57417aab0ef501832ca09df8aee8d06b2d90c98e9eaa6220bc9d03bfb13b
|
||||
initial_ast: cec556a96e40d2958f1338d14b17336f48459bcd7796656fe65a0d2f39e8d6b7
|
||||
unrolled_ast: cec556a96e40d2958f1338d14b17336f48459bcd7796656fe65a0d2f39e8d6b7
|
||||
ssa_ast: cec556a96e40d2958f1338d14b17336f48459bcd7796656fe65a0d2f39e8d6b7
|
||||
flattened_ast: cec556a96e40d2958f1338d14b17336f48459bcd7796656fe65a0d2f39e8d6b7
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user