Skip to content

Commit

Permalink
change AST
Browse files Browse the repository at this point in the history
  • Loading branch information
evan-schott committed Sep 26, 2023
1 parent f6ea2b3 commit e8ec821
Show file tree
Hide file tree
Showing 683 changed files with 5,575 additions and 5,242 deletions.
8 changes: 4 additions & 4 deletions compiler/ast/src/passes/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
}

fn visit_program_scope(&mut self, input: &'a ProgramScope) {
input.structs.values().for_each(|function| self.visit_struct(function));
input.structs.iter().for_each(|(_, c)| (self.visit_struct(&c)));

input.mappings.values().for_each(|mapping| self.visit_mapping(mapping));
input.mappings.iter().for_each(|(_, c)| (self.visit_mapping(&c)));

input.functions.values().for_each(|function| self.visit_function(function));
input.functions.iter().for_each(|(_, c)| (self.visit_function(&c)));

input.consts.values().for_each(|constant| self.visit_const(constant));
input.consts.iter().for_each(|(_, c)| (self.visit_const(&c)));
}

fn visit_import(&mut self, input: &'a Program) {
Expand Down
17 changes: 8 additions & 9 deletions compiler/ast/src/program/program_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use crate::{DefinitionStatement, Function, Mapping, ProgramId, Struct};

use indexmap::IndexMap;
use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
Expand All @@ -28,14 +27,14 @@ use std::fmt;
pub struct ProgramScope {
/// The program id of the program scope.
pub program_id: ProgramId,
/// A map from const names to const definitions.
pub consts: IndexMap<Symbol, DefinitionStatement>,
/// A map from struct names to struct definitions.
pub structs: IndexMap<Symbol, Struct>,
/// A map from mapping names to mapping definitions.
pub mappings: IndexMap<Symbol, Mapping>,
/// A map from function names to function definitions.
pub functions: IndexMap<Symbol, Function>,
/// A vector of const definitions
pub consts: Vec<(Symbol, DefinitionStatement)>,
/// A vector of struct definitions.
pub structs: Vec<(Symbol, Struct)>,
/// A vector of mapping definitions.
pub mappings: Vec<(Symbol, Mapping)>,
/// A vector of function definitions.
pub functions: Vec<(Symbol, Function)>,
/// The span associated with the program scope.
pub span: Span,
}
Expand Down
16 changes: 8 additions & 8 deletions compiler/parser/src/parser/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,28 +138,28 @@ impl ParserContext<'_> {
self.expect(&Token::LeftCurly)?;

// Parse the body of the program scope.
let mut consts = IndexMap::new();
let mut functions = IndexMap::new();
let mut structs = IndexMap::new();
let mut mappings = IndexMap::new();
let mut consts: Vec<(Symbol, DefinitionStatement)> = Vec::new();
let mut functions: Vec<(Symbol, Function)> = Vec::new();
let mut structs: Vec<(Symbol, Struct)> = Vec::new();
let mut mappings: Vec<(Symbol, Mapping)> = Vec::new();

while self.has_next() {
match &self.token.token {
Token::Const => {
let definition = self.parse_const_definition_statement()?;
consts.insert(Symbol::intern(&definition.place.to_string()), definition);
consts.push((Symbol::intern(&definition.place.to_string()), definition));
}
Token::Struct | Token::Record => {
let (id, struct_) = self.parse_struct()?;
structs.insert(id, struct_);
structs.push((id, struct_));
}
Token::Mapping => {
let (id, mapping) = self.parse_mapping()?;
mappings.insert(id, mapping);
mappings.push((id, mapping));
}
Token::At | Token::Function | Token::Transition | Token::Inline => {
let (id, function) = self.parse_function()?;
functions.insert(id, function);
functions.push((id, function));
}
Token::RightCurly => break,
_ => {
Expand Down
11 changes: 6 additions & 5 deletions compiler/passes/src/code_generation/visit_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ impl<'a> CodeGenerator<'a> {
&order
.into_iter()
.map(|name| {
match program_scope.structs.get(&name) {
match program_scope.structs.iter().find(|(identifier, _)| *identifier == name) {
// If the struct is found, it is a local struct.
Some(struct_) => self.visit_struct_or_record(struct_),
Some((_, struct_)) => self.visit_struct_or_record(struct_),
// If the struct is not found, it is an imported struct.
None => String::new(),
}
Expand All @@ -76,16 +76,17 @@ impl<'a> CodeGenerator<'a> {
program_string.push('\n');

// Visit each mapping in the Leo AST and produce an Aleo mapping declaration.
program_string.push_str(&program_scope.mappings.values().map(|mapping| self.visit_mapping(mapping)).join("\n"));
program_string
.push_str(&program_scope.mappings.iter().map(|(_, mapping)| self.visit_mapping(mapping)).join("\n"));

// Visit each function in the program scope and produce an Aleo function.
// Note that in the function inlining pass, we reorder the functions such that they are in post-order.
// In other words, a callee function precedes its caller function in the program scope.
program_string.push_str(
&program_scope
.functions
.values()
.map(|function| {
.iter()
.map(|(_, function)| {
// Set the `is_transition_function` flag.
self.is_transition_function = matches!(function.variant, Variant::Transition);

Expand Down
4 changes: 1 addition & 3 deletions compiler/passes/src/function_inlining/function_inliner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ use crate::{Assigner, AssignmentRenamer, CallGraph};
use leo_ast::{Function, NodeBuilder};
use leo_span::Symbol;

use indexmap::IndexMap;

pub struct FunctionInliner<'a> {
/// A counter used to create unique NodeIDs.
pub(crate) node_builder: &'a NodeBuilder,
Expand All @@ -29,7 +27,7 @@ pub struct FunctionInliner<'a> {
/// A wrapper around an Assigner used to create unique variable assignments.
pub(crate) assignment_renamer: AssignmentRenamer<'a>,
/// A map of reconstructed functions in the current program scope.
pub(crate) reconstructed_functions: IndexMap<Symbol, Function>,
pub(crate) reconstructed_functions: Vec<(Symbol, Function)>,
}

impl<'a> FunctionInliner<'a> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/passes/src/function_inlining/inline_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl ExpressionReconstructor for FunctionInliner<'_> {

// Lookup the reconstructed callee function.
// Since this pass processes functions in post-order, the callee function is guaranteed to exist in `self.reconstructed_functions`
let callee = self.reconstructed_functions.get(&function_name).unwrap();
let (_, callee) = self.reconstructed_functions.iter().find(|(symbol, _)| *symbol == function_name).unwrap();

// Inline the callee function, if required, otherwise, return the call expression.
match callee.variant {
Expand Down
5 changes: 3 additions & 2 deletions compiler/passes/src/function_inlining/inline_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ impl ProgramReconstructor for FunctionInliner<'_> {
for function_name in order.into_iter() {
// None: If `function_name` is not in `input.functions`, then it must be an external function.
// TODO: Check that this is indeed an external function. Requires a redesign of the symbol table.
if let Some(function) = input.functions.remove(&function_name) {
if let Some(pos) = input.functions.iter().position(|(symbol, _)| *symbol == function_name) {
let (_, function) = input.functions.remove(pos);
// Reconstruct the function.
let reconstructed_function = self.reconstruct_function(function);
// Add the reconstructed function to the mapping.
self.reconstructed_functions.insert(function_name, reconstructed_function);
self.reconstructed_functions.push((function_name, reconstructed_function));
}
}
// Check that `input.functions` is empty.
Expand Down
8 changes: 4 additions & 4 deletions compiler/passes/src/type_checking/check_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {

fn visit_program_scope(&mut self, input: &'a ProgramScope) {
// Typecheck each const definition, and append to symbol table.
input.consts.values().for_each(|c| self.visit_definition(c));
input.consts.iter().for_each(|(_, c)| self.visit_definition(c));

// Typecheck each struct definition.
input.structs.values().for_each(|function| self.visit_struct(function));
input.structs.iter().for_each(|(_, function)| self.visit_struct(function));

// Check that the struct dependency graph does not have any cycles.
if let Err(DiGraphError::CycleDetected(path)) = self.struct_graph.post_order() {
Expand All @@ -66,7 +66,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {

// Typecheck each mapping definition.
let mut mapping_count = 0;
for mapping in input.mappings.values() {
for (_, mapping) in input.mappings.iter() {
self.visit_mapping(mapping);
mapping_count += 1;
}
Expand All @@ -81,7 +81,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {

// Typecheck each function definitions.
let mut transition_count = 0;
for function in input.functions.values() {
for (_, function) in input.functions.iter() {
self.visit_function(function);
if matches!(function.variant, Variant::Transition) {
transition_count += 1;
Expand Down
12 changes: 6 additions & 6 deletions tests/expectations/compiler/address/binary.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: ced2082a8e348b1aa0808f4c72fa4fb4ab5fc664e573e33a203f2683879dfeca
type_checked_symbol_table: a0dfc2822cd2ba34228b9388c5f8f05f5ff5add4283a622c3615093172118f8f
unrolled_symbol_table: a0dfc2822cd2ba34228b9388c5f8f05f5ff5add4283a622c3615093172118f8f
initial_ast: 04550d41d558a8221debb06748e0b8fa5c3a44a9a19ab1aa240ee493d8375c5f
unrolled_ast: 04550d41d558a8221debb06748e0b8fa5c3a44a9a19ab1aa240ee493d8375c5f
ssa_ast: a89da602f8ea12cdbc514e8f8d36925ee1316d843d2ab9032f342e34999715b5
flattened_ast: ec037f86300ab54c3c2b3737b20219273662a7af8317570e8a47851d5534def1
inlined_ast: ec037f86300ab54c3c2b3737b20219273662a7af8317570e8a47851d5534def1
dce_ast: 24bfb9378b2938ba93f2fec694eb732805757ed5eab9dca84e4a2bb60eef890e
initial_ast: 9664200de8c9812b186d2ff812daffd2face7428a44d5cbeb13dfb7ce8872212
unrolled_ast: 9664200de8c9812b186d2ff812daffd2face7428a44d5cbeb13dfb7ce8872212
ssa_ast: e746950f3fff8f33da2ded27eca842c9c06d1fd79179f15a8cd6419731763d17
flattened_ast: c05f4406379a59b9eb427aeaa7628ebbe514eed9be8a14dc091118540ff1b07a
inlined_ast: c05f4406379a59b9eb427aeaa7628ebbe514eed9be8a14dc091118540ff1b07a
dce_ast: 93c8238a0217e94351cebb7efed5231eefc56a9c078757f1ef4846f79ff852af
bytecode: e434c09cee27a5dfb5a4e9e9fd26aa2ba6e7f0653fad3a4f2a7d85983ba559c9
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/address/branch.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: af38ae3d646149a4d9313a419619ad336e2483d6e11877216ab2076dfff872ac
type_checked_symbol_table: 489037ec216d778e85678b6c9ddd7c3ed22e40d5481c7eda82b732dcff1f27cf
unrolled_symbol_table: 489037ec216d778e85678b6c9ddd7c3ed22e40d5481c7eda82b732dcff1f27cf
initial_ast: 04d5726d5a3396a3db532b4321017774efb61f1b9861ad57a0b8419195873d61
unrolled_ast: 04d5726d5a3396a3db532b4321017774efb61f1b9861ad57a0b8419195873d61
ssa_ast: e9b1ad5c99751ccf64115635afeb1867bf110b4149d25782767f20c75ca093d5
flattened_ast: 9da4ff48f25003fca246b3e2e8cd699cc959bd1efbd61ce5d082add656943edb
inlined_ast: 9da4ff48f25003fca246b3e2e8cd699cc959bd1efbd61ce5d082add656943edb
dce_ast: 9da4ff48f25003fca246b3e2e8cd699cc959bd1efbd61ce5d082add656943edb
initial_ast: 9e59685d91c6c9fdcc228de5999e4d39dc9168da3ed5c89f056922e024aa2c3d
unrolled_ast: 9e59685d91c6c9fdcc228de5999e4d39dc9168da3ed5c89f056922e024aa2c3d
ssa_ast: a7e4061adbbf42146e030a61dddf95c470c49e7b057fe78c0759d164b9a2b9f8
flattened_ast: 609733026a5ef45b21530fb959cd9727d828e22b9594aa25b32cd391b99c5751
inlined_ast: 609733026a5ef45b21530fb959cd9727d828e22b9594aa25b32cd391b99c5751
dce_ast: 609733026a5ef45b21530fb959cd9727d828e22b9594aa25b32cd391b99c5751
bytecode: da1b0a83a17b801368b0a583b158d88d9d807a33000c8e89e82da123c8041aea
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/address/equal.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: b665474dcaa4c7a4b2eb7a513f4cff8ba3b673a65465db206b134799acd0bd93
type_checked_symbol_table: f385833c35da9d545935068b126557a8bfe7a03da8278004ad0c60286ed7ec46
unrolled_symbol_table: f385833c35da9d545935068b126557a8bfe7a03da8278004ad0c60286ed7ec46
initial_ast: ba81f837919cdca552162716525402e29e28706fac8c52ba72e9423904e1733d
unrolled_ast: ba81f837919cdca552162716525402e29e28706fac8c52ba72e9423904e1733d
ssa_ast: 321a46cf0978fc605a5280dc17850acfd5c04d9e771403a50221a4e95c50042a
flattened_ast: e832091fe40a4fcd51edc8ccdeb677074d44499035411b7b69efa55a6f46d7d7
inlined_ast: e832091fe40a4fcd51edc8ccdeb677074d44499035411b7b69efa55a6f46d7d7
dce_ast: e832091fe40a4fcd51edc8ccdeb677074d44499035411b7b69efa55a6f46d7d7
initial_ast: 963bf114080a4e23de87d18b97bd2fb2cd9dc208c0108d60f7b10cb14ef62b9b
unrolled_ast: 963bf114080a4e23de87d18b97bd2fb2cd9dc208c0108d60f7b10cb14ef62b9b
ssa_ast: 43b715ca1253c5169c23b0e3d66445f35f88a638e6f451ac720dc6c1169e78ee
flattened_ast: 15431dc3dc1e3f5a5dc76db36ef0fba3ba01236cfb7d8576c2b09f08c6d1a55a
inlined_ast: 15431dc3dc1e3f5a5dc76db36ef0fba3ba01236cfb7d8576c2b09f08c6d1a55a
dce_ast: 15431dc3dc1e3f5a5dc76db36ef0fba3ba01236cfb7d8576c2b09f08c6d1a55a
bytecode: bde2653fac0393940c5400272e53492228206e50abb36ce080b95043003ee976
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/address/ternary.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: b665474dcaa4c7a4b2eb7a513f4cff8ba3b673a65465db206b134799acd0bd93
type_checked_symbol_table: f5626319ada04af53a186ac6d1bfef2fd7cd3a16890ea8cc4000e4abd4be2335
unrolled_symbol_table: f5626319ada04af53a186ac6d1bfef2fd7cd3a16890ea8cc4000e4abd4be2335
initial_ast: 9b70e13a29035f7fa83d1e8a521073331f5646dc840d22db0ed592bc3b212a45
unrolled_ast: 9b70e13a29035f7fa83d1e8a521073331f5646dc840d22db0ed592bc3b212a45
ssa_ast: 77304b3918ec7fa2502b0bf713c7927c3ff1b19c509ae1bf39fbd1995be16cda
flattened_ast: c5167a1d18e0504b6f6dac0476eebaf6309e17b28103d28a3913dbf88823fb27
inlined_ast: c5167a1d18e0504b6f6dac0476eebaf6309e17b28103d28a3913dbf88823fb27
dce_ast: c5167a1d18e0504b6f6dac0476eebaf6309e17b28103d28a3913dbf88823fb27
initial_ast: 64eb4536462d3555e330b14ad313f544810d537b69207631c7dfe9a61430e270
unrolled_ast: 64eb4536462d3555e330b14ad313f544810d537b69207631c7dfe9a61430e270
ssa_ast: a7adbd0c8ef7246edf6b284ad9fa810b6658d9c054a05b798d5148a5710e03b5
flattened_ast: de5a5ee66c02dca8d14ab68f25b511b1b350280f53185b765678ec35062d8f52
inlined_ast: de5a5ee66c02dca8d14ab68f25b511b1b350280f53185b765678ec35062d8f52
dce_ast: de5a5ee66c02dca8d14ab68f25b511b1b350280f53185b765678ec35062d8f52
bytecode: c0b90b7f7e80041dc1a314c1a87290534936018fb001c6e1291266a02393c6f2
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/boolean/and.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
initial_ast: 1a5df1e8689e978fe0eb065029c8258d907214d723465d994b74cb371f556cbb
unrolled_ast: 1a5df1e8689e978fe0eb065029c8258d907214d723465d994b74cb371f556cbb
ssa_ast: 3464adaf13ff6ba9cdaefabe8219cf237719a5d4c3c80a23e2fbe583d43014f8
flattened_ast: c8976f4aa3eb6595d97b6bf9b6a97ee46a9356df5dbe4c84b92ca341c85f71c8
inlined_ast: c8976f4aa3eb6595d97b6bf9b6a97ee46a9356df5dbe4c84b92ca341c85f71c8
dce_ast: c8976f4aa3eb6595d97b6bf9b6a97ee46a9356df5dbe4c84b92ca341c85f71c8
initial_ast: 3265a864ebf6cee136f8f25ea46ee3f2603d2c901e530ba003be2561dfd1d35a
unrolled_ast: 3265a864ebf6cee136f8f25ea46ee3f2603d2c901e530ba003be2561dfd1d35a
ssa_ast: 3a6d7deab2672b59c9c8c002083fb5afe468f3c5aad547432bd0d64053ce7d56
flattened_ast: 3b9d138f87ad775fb7c29c7502e0ace65a267f90837539768a8f195b12253ce3
inlined_ast: 3b9d138f87ad775fb7c29c7502e0ace65a267f90837539768a8f195b12253ce3
dce_ast: 3b9d138f87ad775fb7c29c7502e0ace65a267f90837539768a8f195b12253ce3
bytecode: 134904b86b96581876c2ca0c6ead651dda0dc9f2fb6dc583400133410b7deede
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/boolean/conditional.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
initial_ast: f35faa11be8649fe7256533cfc837ee19c3a3753326221b34691c6115eab6b10
unrolled_ast: f35faa11be8649fe7256533cfc837ee19c3a3753326221b34691c6115eab6b10
ssa_ast: f179597e05fcaf6c8d50b82b3fe7442ff8a8efaf23ddc7606f8be781e79f6264
flattened_ast: e47d8f898fa9ddff0cd386b34b673397fb46ed1f3fef7248ce45efff22ddbe5e
inlined_ast: e47d8f898fa9ddff0cd386b34b673397fb46ed1f3fef7248ce45efff22ddbe5e
dce_ast: e47d8f898fa9ddff0cd386b34b673397fb46ed1f3fef7248ce45efff22ddbe5e
initial_ast: 8efd0122df9ffa846d000b00650fc04b56c4d6d738724445e6d4b9cb6c88dd43
unrolled_ast: 8efd0122df9ffa846d000b00650fc04b56c4d6d738724445e6d4b9cb6c88dd43
ssa_ast: a4596eef066dce712ca7791b06d702027d858de97ed66a1cb3c3c88951c038c9
flattened_ast: db52ea6031729813f58d4c01cba89cf710be8984504c0ce7ae1231cfb38cd0a6
inlined_ast: db52ea6031729813f58d4c01cba89cf710be8984504c0ce7ae1231cfb38cd0a6
dce_ast: db52ea6031729813f58d4c01cba89cf710be8984504c0ce7ae1231cfb38cd0a6
bytecode: 56a9fa48a00d1b38b6f60a93ef2168b2c0ce9c23ba3cb7bffa40debfc1b16180
warnings: ""
12 changes: 6 additions & 6 deletions tests/expectations/compiler/boolean/equal.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ outputs:
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
initial_ast: 8008d8df74d782dd7316d07d4d16b8952b9323a3b79d2bea053fdb991180e818
unrolled_ast: 8008d8df74d782dd7316d07d4d16b8952b9323a3b79d2bea053fdb991180e818
ssa_ast: 5d8f7a71d4908e5e8f2358b56e0d5e9bc705f86e48824f05e6029bbb2379c80a
flattened_ast: ffc655b0c8de61ebe2a0e6e41146f689935f8dd8c860b08b55f945e04cdad715
inlined_ast: ffc655b0c8de61ebe2a0e6e41146f689935f8dd8c860b08b55f945e04cdad715
dce_ast: ffc655b0c8de61ebe2a0e6e41146f689935f8dd8c860b08b55f945e04cdad715
initial_ast: 8f65629c29718efd2b2dfe7b3063d21717bdca904561676ecbfb5759bde3ef2d
unrolled_ast: 8f65629c29718efd2b2dfe7b3063d21717bdca904561676ecbfb5759bde3ef2d
ssa_ast: 5b9c0a55f066b305ca1a741d26012a09b2cd0e64b8d4e6016127e5160c557c4e
flattened_ast: f1409b99d5f5dc6b15b8d13fa1c523151fb2c6052717115833e6701d331eb1a2
inlined_ast: f1409b99d5f5dc6b15b8d13fa1c523151fb2c6052717115833e6701d331eb1a2
dce_ast: f1409b99d5f5dc6b15b8d13fa1c523151fb2c6052717115833e6701d331eb1a2
bytecode: 2332d5b7ed9910dc65c885e1aeedbbde00e02d95a55caa300a9cb72456707034
warnings: ""
Loading

0 comments on commit e8ec821

Please sign in to comment.