From c295fdfe14b71b6b7c36a42364460562933f1e16 Mon Sep 17 00:00:00 2001 From: Alastair Reid Date: Tue, 16 Jun 2026 10:21:07 +0100 Subject: [PATCH 1/2] Fix free variable calculation The handling of '__let x = e1 __in e2' (which, like in OCaml lets you assign to a temporary variable in the middle of an expression), was not handling the fact that the scope of the variable 'x' is just 'e2'. In particular, the :metadata command was sometimes listing these variables as global variables that are assigned to by a function instead of ignoring them (because they are local variables). --- libISA/isa_visitor.ml | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/libISA/isa_visitor.ml b/libISA/isa_visitor.ml index 9f2b7f97..25213b10 100644 --- a/libISA/isa_visitor.ml +++ b/libISA/isa_visitor.ml @@ -59,6 +59,19 @@ class type isaVisitor = method leave_scope : Ident.t list -> unit end +(****************************************************************) +(** {2 Nested scope handler} *) +(****************************************************************) + +(** Handle nested scope by adding a nested scope level with + * list of variables `ls` that are introduced by `f`. + *) +let with_locals (vis : isaVisitor) (ls : Ident.t list) (f : 'a -> 'b) (x: 'a) : 'b = + vis#enter_scope ls; + let result = f x in + vis#leave_scope ls; + result + (****************************************************************) (** {2 ISA visitor functions} *) (****************************************************************) @@ -185,9 +198,11 @@ and visit_expr (vis : isaVisitor) (x : expr) : expr = let v' = visit_var vis Definition v in let t' = visit_type vis t in let e' = visit_expr vis e in - let b' = visit_expr vis b in - if v == v' && t == t' && e == e' && b == b' then x - else Expr_Let (v', t', e', b') + with_locals vis [v] (fun _ -> + let b' = visit_expr vis b in + if v == v' && t == t' && e == e' && b == b' then x + else Expr_Let (v', t', e', b') + ) () | Expr_Assert (e1, e2, loc) -> let e1' = visit_expr vis e1 in let e2' = visit_expr vis e2 in @@ -382,12 +397,6 @@ and visit_lexpr (vis : isaVisitor) (x : lexpr) : lexpr = in doVisit vis (vis#vlexpr x) aux x -let with_locals (vis : isaVisitor) (ls : Ident.t list) (f : 'a -> 'b) (x: 'a) : 'b = - vis#enter_scope ls; - let result = f x in - vis#leave_scope ls; - result - let rec locals_of_declitem (x : decl_item) : Ident.t list = match x with | DeclItem_Var (v, _) -> [ v ] From aa6a39c792a1591044e9e6de0c862f5027dc6277 Mon Sep 17 00:00:00 2001 From: Alastair Reid Date: Tue, 16 Jun 2026 10:53:18 +0100 Subject: [PATCH 2/2] Test for free variable fix --- tests/lit/dependencies/nocheck_00.isa | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/lit/dependencies/nocheck_00.isa diff --git a/tests/lit/dependencies/nocheck_00.isa b/tests/lit/dependencies/nocheck_00.isa new file mode 100644 index 00000000..2abd2438 --- /dev/null +++ b/tests/lit/dependencies/nocheck_00.isa @@ -0,0 +1,9 @@ +// RUN: %iii --batchmode --exec=":dependencies %t.json" %s +// RUN: not grep temporary_variable %t.json + +// Copyright (C) 2026-2026 Intel Corporation + +function FUT1(i : {0..15}) -> {1..256} +begin + return __let temporary_variable : {1..16} := i+1 __in temporary_variable * temporary_variable; +end