Skip to content

Commit

Permalink
[move-lang] Support named addresses in interface file generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Todd Nowacki authored and bors-libra committed Jul 7, 2021
1 parent 7043ed5 commit 293f5bc
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 48 deletions.
29 changes: 26 additions & 3 deletions language/move-lang/src/command_line/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use crate::{
use move_command_line_common::files::{
extension_equals, find_filenames, MOVE_COMPILED_EXTENSION, MOVE_EXTENSION, SOURCE_MAP_EXTENSION,
};
use move_core_types::language_storage::ModuleId as CompiledModuleId;
use std::{
collections::BTreeMap,
fs,
fs::File,
io::{Read, Write},
Expand All @@ -33,6 +35,7 @@ pub struct Compiler<'a, 'b> {
deps: &'a [String],
interface_files_dir_opt: Option<String>,
pre_compiled_lib: Option<&'b FullyCompiledProgram>,
compiled_module_named_address_mapping: BTreeMap<CompiledModuleId, String>,
flags: Flags,
}

Expand Down Expand Up @@ -87,6 +90,7 @@ impl<'a, 'b> Compiler<'a, 'b> {
deps,
interface_files_dir_opt: None,
pre_compiled_lib: None,
compiled_module_named_address_mapping: BTreeMap::new(),
flags: Flags::empty(),
}
}
Expand Down Expand Up @@ -124,6 +128,15 @@ impl<'a, 'b> Compiler<'a, 'b> {
self
}

pub fn set_compiled_module_named_address_mapping(
mut self,
compiled_module_named_address_mapping: BTreeMap<CompiledModuleId, String>,
) -> Self {
assert!(self.compiled_module_named_address_mapping.is_empty());
self.compiled_module_named_address_mapping = compiled_module_named_address_mapping;
self
}

pub fn run<const TARGET: Pass>(
self,
) -> anyhow::Result<(
Expand All @@ -135,10 +148,15 @@ impl<'a, 'b> Compiler<'a, 'b> {
deps,
interface_files_dir_opt,
pre_compiled_lib,
compiled_module_named_address_mapping,
flags,
} = self;
let mut deps = deps.to_vec();
generate_interface_files_for_deps(&mut deps, interface_files_dir_opt)?;
generate_interface_files_for_deps(
&mut deps,
interface_files_dir_opt,
&compiled_module_named_address_mapping,
)?;
let compilation_env = CompilationEnv::new(flags);
let (source_text, pprog_and_comments_res) =
parse_program(&compilation_env, targets, &deps)?;
Expand Down Expand Up @@ -516,8 +534,11 @@ pub fn output_compiled_units(
fn generate_interface_files_for_deps(
deps: &mut Vec<String>,
interface_files_dir_opt: Option<String>,
named_address_mapping: &BTreeMap<CompiledModuleId, String>,
) -> anyhow::Result<()> {
if let Some(dir) = generate_interface_files(deps, interface_files_dir_opt, true)? {
if let Some(dir) =
generate_interface_files(deps, interface_files_dir_opt, named_address_mapping, true)?
{
deps.push(dir)
}
Ok(())
Expand All @@ -526,6 +547,7 @@ fn generate_interface_files_for_deps(
pub fn generate_interface_files(
mv_file_locations: &[String],
interface_files_dir_opt: Option<String>,
named_address_mapping: &BTreeMap<CompiledModuleId, String>,
separate_by_hash: bool,
) -> anyhow::Result<Option<String>> {
let mv_files = {
Expand Down Expand Up @@ -571,7 +593,8 @@ pub fn generate_interface_files(
};

for mv_file in mv_files {
let (id, interface_contents) = interface_generator::write_file_to_string(&mv_file)?;
let (id, interface_contents) =
interface_generator::write_file_to_string(named_address_mapping, &mv_file)?;
let addr_dir = dir_path!(all_addr_dir.clone(), format!("{}", id.address()));
let file_path = file_path!(addr_dir.clone(), format!("{}", id.name()), MOVE_EXTENSION);
// it's possible some files exist but not others due to multithreaded environments
Expand Down
2 changes: 2 additions & 0 deletions language/move-lang/src/command_line/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ pub const TEST_SHORT: &str = "t";
pub const COLOR_MODE_ENV_VAR: &str = "COLOR_MODE";

pub const MOVE_COMPILED_INTERFACES_DIR: &str = "mv_interfaces";

pub const COMPILED_NAMED_ADDRESS_MAPPING: &str = "compiled-module-address-name";
109 changes: 64 additions & 45 deletions language/move-lang/src/interface_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ macro_rules! push {
/// Generate the text for the "interface" file of a compiled module. This "interface" is the
/// publically visible contents of the CompiledModule, represented in source language syntax
/// Additionally, it returns the module id (address+name) of the module that was deserialized
pub fn write_file_to_string(compiled_module_file_input_path: &str) -> Result<(ModuleId, String)> {
pub fn write_file_to_string(
named_address_mapping: &BTreeMap<ModuleId, String>,
compiled_module_file_input_path: &str,
) -> Result<(ModuleId, String)> {
let file_contents = fs::read(compiled_module_file_input_path)?;
let module = CompiledModule::deserialize(&file_contents).map_err(|e| {
anyhow!(
Expand All @@ -38,21 +41,33 @@ pub fn write_file_to_string(compiled_module_file_input_path: &str) -> Result<(Mo
e
)
})?;
write_module_to_string(&module)
write_module_to_string(named_address_mapping, &module)
}

pub fn write_module_to_string(module: &CompiledModule) -> Result<(ModuleId, String)> {
pub fn write_module_to_string(
named_address_mapping: &BTreeMap<ModuleId, String>,
module: &CompiledModule,
) -> Result<(ModuleId, String)> {
let mut out = String::new();

let id = module.self_id();
if let Some(addr_name) = named_address_mapping.get(&id) {
push_line!(
out,
format!(
"address {} = {};",
addr_name,
AddressBytes::new(id.address().to_u8())
)
);
}
push_line!(
out,
format!("address {} {{", AddressBytes::new(id.address().to_u8()),)
format!("module {} {{", write_module_id(named_address_mapping, &id))
);
push_line!(out, format!("module {} {{", id.name()));
push_line!(out, "");

let mut context = Context::new(&module);
let mut context = Context::new(module);
let mut members = vec![];

for fdecl in module.friend_decls() {
Expand Down Expand Up @@ -90,26 +105,19 @@ pub fn write_module_to_string(module: &CompiledModule) -> Result<(ModuleId, Stri

let has_uses = !context.uses.is_empty();
for (module_id, alias) in context.uses {
if module_id.name().as_str() == alias {
push_line!(
out,
format!(
" use {}::{};",
AddressBytes::new(module_id.address().to_u8()),
module_id.name()
)
);
let use_ = if module_id.name().as_str() == alias {
format!(
" use {};",
write_module_id(named_address_mapping, &module_id),
)
} else {
push_line!(
out,
format!(
" use {}::{} as {};",
AddressBytes::new(module_id.address().to_u8()),
module_id.name(),
alias
)
);
}
format!(
" use {} as {};",
write_module_id(named_address_mapping, &module_id),
alias
)
};
push_line!(out, use_);
}
if has_uses {
push_line!(out, "");
Expand All @@ -119,7 +127,6 @@ pub fn write_module_to_string(module: &CompiledModule) -> Result<(ModuleId, Stri
push_line!(out, members.join("\n"));
}
push_line!(out, "}");
push_line!(out, "}");
Ok((id, out))
}

Expand All @@ -137,18 +144,42 @@ impl<'a> Context<'a> {
counts: BTreeMap::new(),
}
}

fn module_alias(&mut self, module_id: ModuleId) -> &String {
let module_name = module_id.name().to_owned().into_string();
let counts = &mut self.counts;
self.uses.entry(module_id).or_insert_with(|| {
let count = *counts
.entry(module_name.clone())
.and_modify(|c| *c += 1)
.or_insert(0);
if count == 0 {
module_name
} else {
format!("{}_{}", module_name, count)
}
})
}
}

const DISCLAIMER: &str =
"// NOTE: Functions are 'native' for simplicity. They may or may not be native in actuality.";

fn write_module_id(named_address_mapping: &BTreeMap<ModuleId, String>, id: &ModuleId) -> String {
format!(
"{}::{}",
named_address_mapping
.get(id)
.cloned()
.unwrap_or_else(|| format!("{}", AddressBytes::new(id.address().to_u8()))),
id.name(),
)
}

fn write_friend_decl(ctx: &mut Context, fdecl: &ModuleHandle) -> String {
format!(
" friend {}::{};",
ctx.module
.address_identifier_at(fdecl.address)
.short_str_lossless(),
ctx.module.identifier_at(fdecl.name),
" friend {};",
ctx.module_alias(ctx.module.module_id_for_handle(fdecl))
)
}

Expand Down Expand Up @@ -345,20 +376,8 @@ fn write_struct_handle_type(ctx: &mut Context, idx: StructHandleIndex) -> String
let struct_handle = ctx.module.struct_handle_at(idx);
let struct_module_handle = ctx.module.module_handle_at(struct_handle.module);
let struct_module_id = ctx.module.module_id_for_handle(struct_module_handle);
let struct_module_name = struct_module_id.name().to_string();

let counts = &mut ctx.counts;
let module_alias = ctx.uses.entry(struct_module_id).or_insert_with(|| {
let count = *counts
.entry(struct_module_name.clone())
.and_modify(|c| *c += 1)
.or_insert(0);
if count == 0 {
struct_module_name
} else {
format!("{}_{}", struct_module_name, count)
}
});
let module_alias = ctx.module_alias(struct_module_id).clone();

format!(
"{}::{}",
module_alias,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use resource_viewer::{AnnotatedMoveStruct, AnnotatedMoveValue, MoveValueAnnotato

use anyhow::{anyhow, bail, Result};
use std::{
collections::BTreeMap,
convert::{TryFrom, TryInto},
fs,
path::{Path, PathBuf},
Expand Down Expand Up @@ -336,6 +337,7 @@ impl OnDiskStateView {
.into_string()
.unwrap(),
),
&BTreeMap::new(),
false,
)?;
Ok(())
Expand Down

0 comments on commit 293f5bc

Please sign in to comment.