Skip to content

Commit 7818431

Browse files
authored
Merge 57786b4 into 30d7035
2 parents 30d7035 + 57786b4 commit 7818431

File tree

2 files changed

+175
-87
lines changed

2 files changed

+175
-87
lines changed

compiler/noirc_frontend/src/elaborator/types.rs

+83-83
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ impl<'context> Elaborator<'context> {
622622

623623
let length = stmt.expression;
624624
let span = self.interner.expr_span(&length);
625-
let result = self.try_eval_array_length_id(length, span);
625+
let result = try_eval_array_length_id(self.interner, length, span);
626626

627627
match result.map(|length| length.try_into()) {
628628
Ok(Ok(length_value)) => return length_value,
@@ -633,88 +633,6 @@ impl<'context> Elaborator<'context> {
633633
0
634634
}
635635

636-
fn try_eval_array_length_id(
637-
&self,
638-
rhs: ExprId,
639-
span: Span,
640-
) -> Result<u128, Option<ResolverError>> {
641-
// Arbitrary amount of recursive calls to try before giving up
642-
let fuel = 100;
643-
self.try_eval_array_length_id_with_fuel(rhs, span, fuel)
644-
}
645-
646-
fn try_eval_array_length_id_with_fuel(
647-
&self,
648-
rhs: ExprId,
649-
span: Span,
650-
fuel: u32,
651-
) -> Result<u128, Option<ResolverError>> {
652-
if fuel == 0 {
653-
// If we reach here, it is likely from evaluating cyclic globals. We expect an error to
654-
// be issued for them after name resolution so issue no error now.
655-
return Err(None);
656-
}
657-
658-
match self.interner.expression(&rhs) {
659-
HirExpression::Literal(HirLiteral::Integer(int, false)) => {
660-
int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span }))
661-
}
662-
HirExpression::Ident(ident, _) => {
663-
if let Some(definition) = self.interner.try_definition(ident.id) {
664-
match definition.kind {
665-
DefinitionKind::Global(global_id) => {
666-
let let_statement = self.interner.get_global_let_statement(global_id);
667-
if let Some(let_statement) = let_statement {
668-
let expression = let_statement.expression;
669-
self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1)
670-
} else {
671-
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
672-
}
673-
}
674-
_ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
675-
}
676-
} else {
677-
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
678-
}
679-
}
680-
HirExpression::Infix(infix) => {
681-
let lhs = self.try_eval_array_length_id_with_fuel(infix.lhs, span, fuel - 1)?;
682-
let rhs = self.try_eval_array_length_id_with_fuel(infix.rhs, span, fuel - 1)?;
683-
684-
match infix.operator.kind {
685-
BinaryOpKind::Add => Ok(lhs + rhs),
686-
BinaryOpKind::Subtract => Ok(lhs - rhs),
687-
BinaryOpKind::Multiply => Ok(lhs * rhs),
688-
BinaryOpKind::Divide => Ok(lhs / rhs),
689-
BinaryOpKind::Equal => Ok((lhs == rhs) as u128),
690-
BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128),
691-
BinaryOpKind::Less => Ok((lhs < rhs) as u128),
692-
BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128),
693-
BinaryOpKind::Greater => Ok((lhs > rhs) as u128),
694-
BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128),
695-
BinaryOpKind::And => Ok(lhs & rhs),
696-
BinaryOpKind::Or => Ok(lhs | rhs),
697-
BinaryOpKind::Xor => Ok(lhs ^ rhs),
698-
BinaryOpKind::ShiftRight => Ok(lhs >> rhs),
699-
BinaryOpKind::ShiftLeft => Ok(lhs << rhs),
700-
BinaryOpKind::Modulo => Ok(lhs % rhs),
701-
}
702-
}
703-
HirExpression::Cast(cast) => {
704-
let lhs = self.try_eval_array_length_id_with_fuel(cast.lhs, span, fuel - 1)?;
705-
let lhs_value = Value::Field(lhs.into());
706-
let evaluated_value =
707-
Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, self.interner)
708-
.map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?;
709-
710-
evaluated_value
711-
.to_u128()
712-
.ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span }))
713-
}
714-
_other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
715-
}
716-
}
717-
718636
pub fn unify(
719637
&mut self,
720638
actual: &Type,
@@ -1851,6 +1769,88 @@ impl<'context> Elaborator<'context> {
18511769
}
18521770
}
18531771

1772+
pub fn try_eval_array_length_id(
1773+
interner: &NodeInterner,
1774+
rhs: ExprId,
1775+
span: Span,
1776+
) -> Result<u128, Option<ResolverError>> {
1777+
// Arbitrary amount of recursive calls to try before giving up
1778+
let fuel = 100;
1779+
try_eval_array_length_id_with_fuel(interner, rhs, span, fuel)
1780+
}
1781+
1782+
fn try_eval_array_length_id_with_fuel(
1783+
interner: &NodeInterner,
1784+
rhs: ExprId,
1785+
span: Span,
1786+
fuel: u32,
1787+
) -> Result<u128, Option<ResolverError>> {
1788+
if fuel == 0 {
1789+
// If we reach here, it is likely from evaluating cyclic globals. We expect an error to
1790+
// be issued for them after name resolution so issue no error now.
1791+
return Err(None);
1792+
}
1793+
1794+
match interner.expression(&rhs) {
1795+
HirExpression::Literal(HirLiteral::Integer(int, false)) => {
1796+
int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span }))
1797+
}
1798+
HirExpression::Ident(ident, _) => {
1799+
if let Some(definition) = interner.try_definition(ident.id) {
1800+
match definition.kind {
1801+
DefinitionKind::Global(global_id) => {
1802+
let let_statement = interner.get_global_let_statement(global_id);
1803+
if let Some(let_statement) = let_statement {
1804+
let expression = let_statement.expression;
1805+
try_eval_array_length_id_with_fuel(interner, expression, span, fuel - 1)
1806+
} else {
1807+
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
1808+
}
1809+
}
1810+
_ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
1811+
}
1812+
} else {
1813+
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
1814+
}
1815+
}
1816+
HirExpression::Infix(infix) => {
1817+
let lhs = try_eval_array_length_id_with_fuel(interner, infix.lhs, span, fuel - 1)?;
1818+
let rhs = try_eval_array_length_id_with_fuel(interner, infix.rhs, span, fuel - 1)?;
1819+
1820+
match infix.operator.kind {
1821+
BinaryOpKind::Add => Ok(lhs + rhs),
1822+
BinaryOpKind::Subtract => Ok(lhs - rhs),
1823+
BinaryOpKind::Multiply => Ok(lhs * rhs),
1824+
BinaryOpKind::Divide => Ok(lhs / rhs),
1825+
BinaryOpKind::Equal => Ok((lhs == rhs) as u128),
1826+
BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128),
1827+
BinaryOpKind::Less => Ok((lhs < rhs) as u128),
1828+
BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128),
1829+
BinaryOpKind::Greater => Ok((lhs > rhs) as u128),
1830+
BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128),
1831+
BinaryOpKind::And => Ok(lhs & rhs),
1832+
BinaryOpKind::Or => Ok(lhs | rhs),
1833+
BinaryOpKind::Xor => Ok(lhs ^ rhs),
1834+
BinaryOpKind::ShiftRight => Ok(lhs >> rhs),
1835+
BinaryOpKind::ShiftLeft => Ok(lhs << rhs),
1836+
BinaryOpKind::Modulo => Ok(lhs % rhs),
1837+
}
1838+
}
1839+
HirExpression::Cast(cast) => {
1840+
let lhs = try_eval_array_length_id_with_fuel(interner, cast.lhs, span, fuel - 1)?;
1841+
let lhs_value = Value::Field(lhs.into());
1842+
let evaluated_value =
1843+
Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, interner)
1844+
.map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?;
1845+
1846+
evaluated_value
1847+
.to_u128()
1848+
.ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span }))
1849+
}
1850+
_other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
1851+
}
1852+
}
1853+
18541854
/// Gives an error if a user tries to create a mutable reference
18551855
/// to an immutable variable.
18561856
fn verify_mutable_reference(interner: &NodeInterner, rhs: ExprId) -> Result<(), ResolverError> {

tooling/lsp/src/requests/hover.rs

+92-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ use fm::FileMap;
55
use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind};
66
use noirc_frontend::{
77
ast::Visibility,
8+
elaborator::types::try_eval_array_length_id,
89
hir::def_map::ModuleId,
9-
hir_def::{stmt::HirPattern, traits::Trait},
10-
macros_api::{NodeInterner, StructId},
10+
hir_def::{expr::HirArrayLiteral, stmt::HirPattern, traits::Trait},
11+
macros_api::{HirExpression, HirLiteral, NodeInterner, StructId},
1112
node_interner::{
12-
DefinitionId, DefinitionKind, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId,
13+
DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId,
1314
},
1415
Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable,
1516
};
@@ -166,24 +167,107 @@ fn format_trait(id: TraitId, args: &ProcessRequestCallbackArgs) -> String {
166167
fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String {
167168
let global_info = args.interner.get_global(id);
168169
let definition_id = global_info.definition_id;
170+
let definition = args.interner.definition(definition_id);
169171
let typ = args.interner.definition_type(definition_id);
170172

171173
let mut string = String::new();
172174
if format_parent_module(ReferenceId::Global(id), args, &mut string) {
173175
string.push('\n');
174176
}
177+
175178
string.push_str(" ");
179+
if definition.comptime {
180+
string.push_str("comptime ");
181+
}
182+
if definition.mutable {
183+
string.push_str("mut ");
184+
}
176185
string.push_str("global ");
177186
string.push_str(&global_info.ident.0.contents);
178187
string.push_str(": ");
179188
string.push_str(&format!("{}", typ));
189+
190+
// See if we can figure out what's the global's value
191+
if let Some(stmt) = args.interner.get_global_let_statement(id) {
192+
if let Some(value) = get_global_value(args.interner, stmt.expression) {
193+
string.push_str(" = ");
194+
string.push_str(&value);
195+
}
196+
}
197+
180198
string.push_str(&go_to_type_links(&typ, args.interner, args.files));
181199

182200
append_doc_comments(args.interner, ReferenceId::Global(id), &mut string);
183201

184202
string
185203
}
186204

205+
fn get_global_value(interner: &NodeInterner, expr: ExprId) -> Option<String> {
206+
let span = interner.expr_span(&expr);
207+
208+
// Globals as array lengths are extremely common, so we try that first.
209+
if let Ok(result) = try_eval_array_length_id(interner, expr, span) {
210+
return Some(result.to_string());
211+
}
212+
213+
match interner.expression(&expr) {
214+
HirExpression::Literal(literal) => match literal {
215+
HirLiteral::Array(hir_array_literal) => {
216+
get_global_array_value(interner, hir_array_literal, false)
217+
}
218+
HirLiteral::Slice(hir_array_literal) => {
219+
get_global_array_value(interner, hir_array_literal, true)
220+
}
221+
HirLiteral::Bool(value) => Some(value.to_string()),
222+
HirLiteral::Integer(field_element, _) => Some(field_element.to_string()),
223+
HirLiteral::Str(string) => Some(format!("{:?}", string)),
224+
HirLiteral::FmtStr(..) => None,
225+
HirLiteral::Unit => Some("()".to_string()),
226+
},
227+
HirExpression::Tuple(values) => {
228+
get_exprs_global_value(interner, &values).map(|value| format!("({})", value))
229+
}
230+
_ => None,
231+
}
232+
}
233+
234+
fn get_global_array_value(
235+
interner: &NodeInterner,
236+
literal: HirArrayLiteral,
237+
is_slice: bool,
238+
) -> Option<String> {
239+
match literal {
240+
HirArrayLiteral::Standard(values) => {
241+
get_exprs_global_value(interner, &values).map(|value| {
242+
if is_slice {
243+
format!("&[{}]", value)
244+
} else {
245+
format!("[{}]", value)
246+
}
247+
})
248+
}
249+
HirArrayLiteral::Repeated { repeated_element, length } => {
250+
get_global_value(interner, repeated_element).map(|value| {
251+
if is_slice {
252+
format!("&[{}; {}]", value, length)
253+
} else {
254+
format!("[{}; {}]", value, length)
255+
}
256+
})
257+
}
258+
}
259+
}
260+
261+
fn get_exprs_global_value(interner: &NodeInterner, exprs: &[ExprId]) -> Option<String> {
262+
let strings: Vec<String> =
263+
exprs.iter().filter_map(|value| get_global_value(interner, *value)).collect();
264+
if strings.len() == exprs.len() {
265+
Some(strings.join(", "))
266+
} else {
267+
None
268+
}
269+
}
270+
187271
fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String {
188272
let func_meta = args.interner.function_meta(&id);
189273
let func_name_definition_id = args.interner.definition(func_meta.name.id);
@@ -263,6 +347,10 @@ fn format_alias(id: TypeAliasId, args: &ProcessRequestCallbackArgs) -> String {
263347

264348
fn format_local(id: DefinitionId, args: &ProcessRequestCallbackArgs) -> String {
265349
let definition_info = args.interner.definition(id);
350+
if let DefinitionKind::Global(global_id) = &definition_info.kind {
351+
return format_global(*global_id, args);
352+
}
353+
266354
let DefinitionKind::Local(expr_id) = definition_info.kind else {
267355
panic!("Expected a local reference to reference a local definition")
268356
};
@@ -629,7 +717,7 @@ mod hover_tests {
629717
"two/src/lib.nr",
630718
Position { line: 15, character: 25 },
631719
r#" one::subone
632-
global some_global: Field"#,
720+
global some_global: Field = 2"#,
633721
)
634722
.await;
635723
}

0 commit comments

Comments
 (0)