Skip to content

Commit

Permalink
Introduce CallPath to TyConstantDeclaration (FuelLabs#4219)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammadfawaz authored Mar 9, 2023
1 parent b33463d commit d735e99
Show file tree
Hide file tree
Showing 32 changed files with 364 additions and 108 deletions.
17 changes: 13 additions & 4 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1507,10 +1507,13 @@ pub fn dependency_namespace(
constants: BTreeMap<String, ConfigTimeConstant>,
engines: Engines<'_>,
) -> Result<namespace::Module, vec1::Vec1<CompileError>> {
let mut namespace = namespace::Module::default_with_constants(engines, constants)?;

// TODO: Clean this up when config-time constants v1 are removed.
let node_idx = &graph[node];
namespace.name = Some(Ident::new_no_span(node_idx.name.clone()));
let name = Some(Ident::new_no_span(node_idx.name.clone()));
let mut namespace =
namespace::Module::default_with_constants(engines, constants, name.clone())?;
namespace.is_external = true;
namespace.name = name;

// Add direct dependencies.
let mut core_added = false;
Expand Down Expand Up @@ -1540,7 +1543,13 @@ pub fn dependency_namespace(
public: true,
};
constants.insert(CONTRACT_ID_CONSTANT_NAME.to_string(), contract_id_constant);
namespace::Module::default_with_constants(engines, constants)?
let node_idx = &graph[dep_node];
let name = Some(Ident::new_no_span(node_idx.name.clone()));
let mut ns =
namespace::Module::default_with_constants(engines, constants, name.clone())?;
ns.is_external = true;
ns.name = name;
ns
}
};
namespace.insert_submodule(dep_name, dep_namespace);
Expand Down
2 changes: 1 addition & 1 deletion forc-plugins/forc-doc/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ impl Descriptor {
if !document_private_items && const_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
let item_name = const_decl.name;
let item_name = const_decl.call_path.suffix;
let attrs_opt = (!const_decl.attributes.is_empty())
.then(|| const_decl.attributes.to_html_string());

Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/abi_generation/fuel_json_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ fn generate_json_configurables(
.iter()
.map(
|TyConstantDeclaration {
name,
call_path,
type_ascription,
..
}| program_abi::Configurable {
name: name.to_string(),
name: call_path.suffix.to_string(),
application: program_abi::TypeApplication {
name: "".to_string(),
type_id: type_ascription.type_id.index(),
Expand Down
8 changes: 6 additions & 2 deletions sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,12 @@ fn connect_declaration<'eng: 'cfg, 'cfg>(
)
}
ConstantDeclaration { decl_id, .. } => {
let ty::TyConstantDeclaration { name, value, .. } = decl_engine.get_constant(decl_id);
graph.namespace.insert_constant(name, entry_node);
let ty::TyConstantDeclaration {
call_path, value, ..
} = decl_engine.get_constant(decl_id);
graph
.namespace
.insert_constant(call_path.suffix, entry_node);
if let Some(value) = &value {
connect_expression(
engines,
Expand Down
33 changes: 19 additions & 14 deletions sway-core/src/ir_generation/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,19 +201,24 @@ pub(crate) fn compile_constants(
) -> Result<(), CompileError> {
let (type_engine, decl_engine) = engines.unwrap();
for decl_name in module_ns.get_all_declared_symbols() {
compile_const_decl(
&mut LookupEnv {
type_engine,
decl_engine,
context,
md_mgr,
module,
module_ns: Some(module_ns),
function_compiler: None,
lookup: compile_const_decl,
},
decl_name,
)?;
if let Some(ty::TyDeclaration::ConstantDeclaration { decl_id, .. }) =
module_ns.symbols.get(decl_name)
{
let ty::TyConstantDeclaration { call_path, .. } = engines.de().get_constant(decl_id);
compile_const_decl(
&mut LookupEnv {
type_engine,
decl_engine,
context,
md_mgr,
module,
module_ns: Some(module_ns),
function_compiler: None,
lookup: compile_const_decl,
},
&call_path,
)?;
}
}

for submodule_ns in module_ns.submodules().values() {
Expand Down Expand Up @@ -256,7 +261,7 @@ fn compile_declarations(
function_compiler: None,
lookup: compile_const_decl,
},
&decl.name,
&decl.call_path,
)?;
}

Expand Down
58 changes: 34 additions & 24 deletions sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use crate::{
decl_engine::DeclEngine, engine_threading::*, language::ty, metadata::MetadataManager,
semantic_analysis::*, TypeEngine,
decl_engine::DeclEngine,
engine_threading::*,
language::{ty, CallPath},
metadata::MetadataManager,
semantic_analysis::*,
TypeEngine,
};

use super::{convert::convert_literal_to_constant, function::FnCompiler, types::*};
Expand All @@ -14,10 +18,7 @@ use sway_ir::{
value::Value,
Instruction,
};
use sway_types::{
ident::{BaseIdent, Ident},
span::Spanned,
};
use sway_types::{ident::Ident, span::Spanned};
use sway_utils::mapped_stack::MappedStack;

pub(crate) struct LookupEnv<'a> {
Expand All @@ -28,17 +29,19 @@ pub(crate) struct LookupEnv<'a> {
pub(crate) module: Module,
pub(crate) module_ns: Option<&'a namespace::Module>,
pub(crate) function_compiler: Option<&'a FnCompiler<'a>>,
pub(crate) lookup: fn(&mut LookupEnv, &Ident) -> Result<Option<Value>, CompileError>,
pub(crate) lookup: fn(&mut LookupEnv, &CallPath) -> Result<Option<Value>, CompileError>,
}

pub(crate) fn compile_const_decl(
env: &mut LookupEnv,
name: &Ident,
call_path: &CallPath,
) -> Result<Option<Value>, CompileError> {
// Check if it's a processed local constant.
if let Some(fn_compiler) = env.function_compiler {
let mut found_local = false;
if let Some(local_var) = fn_compiler.get_function_var(env.context, name.as_str()) {
if let Some(local_var) =
fn_compiler.get_function_var(env.context, call_path.suffix.as_str())
{
found_local = true;
if let Some(constant) = local_var.get_initializer(env.context) {
return Ok(Some(Value::new_constant(env.context, constant.clone())));
Expand Down Expand Up @@ -66,7 +69,7 @@ pub(crate) fn compile_const_decl(
}
}

if let Some(value) = fn_compiler.get_function_arg(env.context, name.as_str()) {
if let Some(value) = fn_compiler.get_function_arg(env.context, call_path.suffix.as_str()) {
found_local = true;
if value.get_constant(env.context).is_some() {
return Ok(Some(value));
Expand All @@ -80,50 +83,51 @@ pub(crate) fn compile_const_decl(

// Check if it's a processed global constant.
match (
env.module.get_global_constant(env.context, name.as_str()),
env.module
.get_global_configurable(env.context, name.as_str()),
.get_global_constant(env.context, &call_path.as_vec_string()),
env.module
.get_global_configurable(env.context, &call_path.as_vec_string()),
env.module_ns,
) {
(Some(const_val), _, _) => Ok(Some(const_val)),
(_, Some(config_val), _) => Ok(Some(config_val)),
(None, None, Some(module_ns)) => {
// See if we it's a global const and whether we can compile it *now*.
let decl = module_ns.check_symbol(name)?;
let decl = module_ns.check_symbol(&call_path.suffix)?;
let decl_name_value = match decl {
ty::TyDeclaration::ConstantDeclaration { decl_id, .. } => {
let ty::TyConstantDeclaration {
name,
call_path,
value,
is_configurable,
..
} = env.decl_engine.get_constant(decl_id);
Some((name, value, is_configurable))
Some((call_path, value, is_configurable))
}
_otherwise => None,
};
if let Some((name, Some(value), is_configurable)) = decl_name_value {
if let Some((call_path, Some(value), is_configurable)) = decl_name_value {
let const_val = compile_constant_expression(
Engines::new(env.type_engine, env.decl_engine),
env.context,
env.md_mgr,
env.module,
env.module_ns,
env.function_compiler,
&name,
&call_path,
&value,
is_configurable,
)?;
if !is_configurable {
env.module.add_global_constant(
env.context,
name.as_str().to_owned(),
call_path.as_vec_string().to_vec(),
const_val,
);
} else {
env.module.add_global_configurable(
env.context,
name.as_str().to_owned(),
call_path.as_vec_string().to_vec(),
const_val,
);
}
Expand All @@ -144,7 +148,7 @@ pub(super) fn compile_constant_expression(
module: Module,
module_ns: Option<&namespace::Module>,
function_compiler: Option<&FnCompiler>,
name: &BaseIdent,
call_path: &CallPath,
const_expr: &ty::TyExpression,
is_configurable: bool,
) -> Result<Value, CompileError> {
Expand All @@ -163,7 +167,7 @@ pub(super) fn compile_constant_expression(
Ok(Value::new_constant(context, constant_evaluated).add_metadatum(context, span_id_idx))
} else {
let config_const_name =
md_mgr.config_const_name_to_md(context, &std::rc::Rc::from(name.as_str()));
md_mgr.config_const_name_to_md(context, &std::rc::Rc::from(call_path.suffix.as_str()));
let metadata = md_combine(context, &span_id_idx, &config_const_name);
Ok(Value::new_configurable(context, constant_evaluated).add_metadatum(context, metadata))
}
Expand Down Expand Up @@ -256,12 +260,18 @@ fn const_eval_typed_expr(
}
res
}
ty::TyExpressionVariant::VariableExpression { name, .. } => match known_consts.get(name) {
// 1. Check if name is in known_consts.
ty::TyExpressionVariant::VariableExpression {
name, call_path, ..
} => match known_consts.get(name) {
// 1. Check if name/call_path is in known_consts.
Some(cvs) => Some(cvs.clone()),
None => {
let call_path = match call_path {
Some(call_path) => call_path.clone(),
None => CallPath::from(name.clone()),
};
// 2. Check if name is a global constant.
(lookup.lookup)(lookup, name)
(lookup.lookup)(lookup, &call_path)
.ok()
.flatten()
.and_then(|v| v.get_constant(lookup.context).cloned())
Expand Down
38 changes: 26 additions & 12 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ impl<'eng> FnCompiler<'eng> {
ty::TyExpressionVariant::LazyOperator { op, lhs, rhs } => {
self.compile_lazy_op(context, md_mgr, op, lhs, rhs, span_md_idx)
}
ty::TyExpressionVariant::VariableExpression { name, .. } => {
self.compile_var_expr(context, name.as_str(), span_md_idx)
}
ty::TyExpressionVariant::VariableExpression {
name, call_path, ..
} => self.compile_var_expr(context, call_path, name, span_md_idx),
ty::TyExpressionVariant::Array { contents } => {
self.compile_array_expr(context, md_mgr, contents, span_md_idx)
}
Expand Down Expand Up @@ -1604,16 +1604,22 @@ impl<'eng> FnCompiler<'eng> {
fn compile_var_expr(
&mut self,
context: &mut Context,
name: &str,
call_path: &Option<CallPath>,
name: &Ident,
span_md_idx: Option<MetadataIndex>,
) -> Result<Value, CompileError> {
let need_to_load = |ty: &Type, context: &Context| {
ty.is_unit(context) || ty.is_bool(context) || ty.is_uint(context)
};

let call_path = match call_path {
Some(call_path) => call_path.clone(),
None => CallPath::from(name.clone()),
};

// We need to check the symbol map first, in case locals are shadowing the args, other
// locals or even constants.
if let Some(var) = self.get_function_var(context, name) {
if let Some(var) = self.get_function_var(context, name.as_str()) {
let local_val = self
.current_block
.ins(context)
Expand All @@ -1636,7 +1642,7 @@ impl<'eng> FnCompiler<'eng> {
} else {
Ok(local_val)
}
} else if let Some(val) = self.function.get_arg(context, name) {
} else if let Some(val) = self.function.get_arg(context, name.as_str()) {
if val
.get_argument_type_and_byref(context)
.map_or(false, |(_ty, by_ref)| by_ref)
Expand All @@ -1649,13 +1655,19 @@ impl<'eng> FnCompiler<'eng> {
} else {
Ok(val)
}
} else if let Some(const_val) = self.module.get_global_constant(context, name) {
} else if let Some(const_val) = self
.module
.get_global_constant(context, &call_path.as_vec_string())
{
Ok(const_val)
} else if let Some(config_val) = self.module.get_global_configurable(context, name) {
} else if let Some(config_val) = self
.module
.get_global_configurable(context, &call_path.as_vec_string())
{
Ok(config_val)
} else {
Err(CompileError::InternalOwned(
format!("Unable to resolve variable '{name}'."),
format!("Unable to resolve variable '{}'.", name.as_str()),
Span::dummy(),
))
}
Expand Down Expand Up @@ -1733,7 +1745,7 @@ impl<'eng> FnCompiler<'eng> {
// globals like other const decls.
// `is_configurable` should be `false` here.
let ty::TyConstantDeclaration {
name,
call_path,
value,
is_configurable,
..
Expand All @@ -1746,11 +1758,13 @@ impl<'eng> FnCompiler<'eng> {
self.module,
None,
Some(self),
&name,
&call_path,
&value,
is_configurable,
)?;
let local_name = self.lexical_map.insert(name.as_str().to_owned());
let local_name = self
.lexical_map
.insert(call_path.suffix.as_str().to_owned());
let return_type = convert_resolved_typeid(
self.type_engine,
self.decl_engine,
Expand Down
Loading

0 comments on commit d735e99

Please sign in to comment.