Repository: crytic/slither

Issue:
type(uint*).max causes an assert to fail
https://github.com/crytic/slither/blob/9f64778a85e749c4410a217b46687965f90b0564/slither/core/solidity_types/type_information.py#L16
Parsing Error
We're seeing the following error when running over contracts that compile correctly with solc 0.6.12.

```
Traceback (most recent call last):
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 692, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 79, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 62, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slither.py", line 100, in __init__
    self._parser.analyze_contracts()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 353, in analyze_contracts
    self._convert_to_slithir()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 499, in _convert_to_slithir
    func.generate_slithir_and_analyze()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/declarations/function.py", line 1661, in generate_slithir_and_analyze
    node.slithir_generation()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/cfg/node.py", line 707, in slithir_generation
    self._irs = convert_expression(expression, self)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 104, in convert_expression
    result = apply_ir_heuristics(result, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 1543, in apply_ir_heuristics
    irs = propagate_type_and_convert_call(irs, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 364, in propagate_type_and_convert_call
    new_ins = propagate_types(ins, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 683, in propagate_types
    ir.function.return_type = [TypeInformation(ir.arguments[0])]
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/solidity_types/type_information.py", line 16, in __init__
    assert isinstance(c, Contract)
AssertionError
ERROR:root:None
ERROR:root:Error in /home/ethsec/protocol/packages/core
ERROR:root:Traceback (most recent call last):
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 692, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 79, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 62, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slither.py", line 100, in __init__
    self._parser.analyze_contracts()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 353, in analyze_contracts
    self._convert_to_slithir()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 499, in _convert_to_slithir
    func.generate_slithir_and_analyze()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/declarations/function.py", line 1661, in generate_slithir_and_analyze
    node.slithir_generation()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/cfg/node.py", line 707, in slithir_generation
    self._irs = convert_expression(expression, self)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 104, in convert_expression
    result = apply_ir_heuristics(result, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 1543, in apply_ir_heuristics
    irs = propagate_type_and_convert_call(irs, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 364, in propagate_type_and_convert_call
    new_ins = propagate_types(ins, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 683, in propagate_types
    ir.function.return_type = [TypeInformation(ir.arguments[0])]
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/solidity_types/type_information.py", line 16, in __init__
    assert isinstance(c, Contract)
AssertionError
```

Based on the error message I'm thinking it has to do with this line in our code that isn't being correctly parsed:
```
require(a.rawValue <= uint256(type(int256).max), "Unsigned too large");
```


Discussion:
Hi @moodysalem .

Thanks for reporting this, we are working to  add the support for `type(X).max` / `type(X).min`.
Which version of slither are you using?
Whichever version Is currently published in the ToB docker image: trailofbits/eth-security-toolbox (the failing run happened earlier today). I can try to dig into the docker image to extract the version, but i figure it's fairly up to date with slither releases.
I think we had this issue solved in the `master` branch in slither. Can you try reinstalling that version in the docker? (just run `python3 setup.py install --user` after cloning this repository)
I tried cloning the repo and reinstalling slither and I got the same error.
```
Traceback (most recent call last):
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 692, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 79, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 62, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slither.py", line 100, in __init__
    self._parser.analyze_contracts()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 353, in analyze_contracts
    self._convert_to_slithir()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 499, in _convert_to_slithir
    func.generate_slithir_and_analyze()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/declarations/function.py", line 1661, in generate_slithir_and_analyze
    node.slithir_generation()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/cfg/node.py", line 707, in slithir_generation
    self._irs = convert_expression(expression, self)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 104, in convert_expression
    result = apply_ir_heuristics(result, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 1543, in apply_ir_heuristics
    irs = propagate_type_and_convert_call(irs, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 364, in propagate_type_and_convert_call
    new_ins = propagate_types(ins, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 683, in propagate_types
    ir.function.return_type = [TypeInformation(ir.arguments[0])]
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/solidity_types/type_information.py", line 16, in __init__
    assert isinstance(c, Contract)
AssertionError
ERROR:root:None
ERROR:root:Error in /home/ethsec/protocol/packages/core
ERROR:root:Traceback (most recent call last):
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 692, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 79, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/__main__.py", line 62, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slither.py", line 100, in __init__
    self._parser.analyze_contracts()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 353, in analyze_contracts
    self._convert_to_slithir()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 499, in _convert_to_slithir
    func.generate_slithir_and_analyze()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/declarations/function.py", line 1661, in generate_slithir_and_analyze
    node.slithir_generation()
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/cfg/node.py", line 707, in slithir_generation
    self._irs = convert_expression(expression, self)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 104, in convert_expression
    result = apply_ir_heuristics(result, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 1543, in apply_ir_heuristics
    irs = propagate_type_and_convert_call(irs, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 364, in propagate_type_and_convert_call
    new_ins = propagate_types(ins, node)
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/slithir/convert.py", line 683, in propagate_types
    ir.function.return_type = [TypeInformation(ir.arguments[0])]
  File "/home/ethsec/.local/lib/python3.6/site-packages/slither/core/solidity_types/type_information.py", line 16, in __init__
    assert isinstance(c, Contract)
AssertionError
```
Hi @mrice32 .

Thank you for reporting this. I believe that the issue is coming from Slither's lack of support for `type(X).max/min` (https://github.com/crytic/slither/issues/671). We are working on it

Resolving patch:
diff --git a/slither/core/solidity_types/elementary_type.py b/slither/core/solidity_types/elementary_type.py
--- a/slither/core/solidity_types/elementary_type.py
+++ b/slither/core/solidity_types/elementary_type.py
@@ -5,6 +5,7 @@
 
 
 # see https://solidity.readthedocs.io/en/v0.4.24/miscellaneous.html?highlight=grammar
+from slither.exceptions import SlitherException
 
 Int = [
     "int",
@@ -42,6 +43,9 @@
     "int256",
 ]
 
+Max_Int = {k: 2 ** (8 * i - 1) - 1 if i > 0 else 2 ** 255 - 1 for i, k in enumerate(Int)}
+Min_Int = {k: -(2 ** (8 * i - 1)) if i > 0 else -(2 ** 255) for i, k in enumerate(Int)}
+
 Uint = [
     "uint",
     "uint8",
@@ -78,6 +82,12 @@
     "uint256",
 ]
 
+Max_Uint = {k: 2 ** (8 * i) - 1 if i > 0 else 2 ** 256 - 1 for i, k in enumerate(Uint)}
+Min_Uint = {k: 0 for k in Uint}
+
+MaxValues = dict(Max_Int, **Max_Uint)
+MinValues = dict(Min_Int, **Min_Uint)
+
 Byte = [
     "byte",
     "bytes",
@@ -180,6 +190,18 @@ def storage_size(self) -> Tuple[int, bool]:
             return 32, True
         return int(self.size / 8), False
 
+    @property
+    def min(self) -> int:
+        if self.name in MinValues:
+            return MinValues[self.name]
+        raise SlitherException(f"{self.name} does not have a min value")
+
+    @property
+    def max(self) -> int:
+        if self.name in MaxValues:
+            return MaxValues[self.name]
+        raise SlitherException(f"{self.name} does not have a max value")
+
     def __str__(self):
         return self._type
 
diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py
--- a/slither/slithir/convert.py
+++ b/slither/slithir/convert.py
@@ -455,6 +455,9 @@ def _convert_type_contract(ir, slither):
         assignment.lvalue.set_type(ElementaryType("string"))
         return assignment
 
+    if isinstance(contract, ElementaryType):
+        print(contract.type)
+
     raise SlithIRError(f"type({contract.name}).{ir.variable_right} is unknown")
 
 
@@ -1411,6 +1414,12 @@ def remove_unused(result):
                 if not ins.lvalue.name in to_keep and ins != last_elem:
                     to_remove.append(ins)
                     removed = True
+            # Remove type(X) if X is an elementary type
+            # This assume that type(X) is only used with min/max
+            # If Solidity introduces other operation, we might remove this removal
+            if isinstance(ins, SolidityCall) and ins.function == SolidityFunction("type()"):
+                if isinstance(ins.arguments[0], ElementaryType):
+                    to_remove.append(ins)
 
         result = [i for i in result if not i in to_remove]
     return result
diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -4,11 +4,15 @@
     Function,
     SolidityVariable,
     SolidityVariableComposed,
+    SolidityFunction,
 )
 from slither.core.expressions import (
     AssignmentOperationType,
     UnaryOperationType,
     BinaryOperationType,
+    ElementaryTypeNameExpression,
+    CallExpression,
+    Identifier,
 )
 from slither.core.solidity_types import ArrayType, ElementaryType
 from slither.core.solidity_types.type import Type
@@ -350,6 +354,29 @@ def _post_literal(self, expression):
 
     def _post_member_access(self, expression):
         expr = get(expression.expression)
+
+        # Look for type(X).max / min
+        # Because we looked at the AST structure, we need to look into the nested expression
+        # Hopefully this is always on a direct sub field, and there is no weird construction
+        if isinstance(expression.expression, CallExpression) and expression.member_name in [
+            "min",
+            "max",
+        ]:
+            if isinstance(expression.expression.called, Identifier):
+                if expression.expression.called.value == SolidityFunction("type()"):
+                    assert len(expression.expression.arguments) == 1
+                    val = TemporaryVariable(self._node)
+                    type_expression_found = expression.expression.arguments[0]
+                    assert isinstance(type_expression_found, ElementaryTypeNameExpression)
+                    type_found = type_expression_found.type
+                    if expression.member_name == "min:":
+                        op = Assignment(val, Constant(str(type_found.min), type_found), type_found,)
+                    else:
+                        op = Assignment(val, Constant(str(type_found.max), type_found), type_found,)
+                    self._result.append(op)
+                    set_val(expression, val)
+                    return
+
         val = ReferenceVariable(self._node)
         member = Member(expr, Constant(expression.member_name), val)
         member.set_expression(expression)


Test patch:
diff --git a/tests/ast-parsing/expected/minmax-0.4.0-legacy.json b/tests/ast-parsing/expected/minmax-0.4.0-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.0-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.1-legacy.json b/tests/ast-parsing/expected/minmax-0.4.1-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.1-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.10-legacy.json b/tests/ast-parsing/expected/minmax-0.4.10-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.10-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.11-legacy.json b/tests/ast-parsing/expected/minmax-0.4.11-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.11-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.12-compact.json b/tests/ast-parsing/expected/minmax-0.4.12-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.12-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.12-legacy.json b/tests/ast-parsing/expected/minmax-0.4.12-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.12-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.13-compact.json b/tests/ast-parsing/expected/minmax-0.4.13-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.13-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.13-legacy.json b/tests/ast-parsing/expected/minmax-0.4.13-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.13-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.14-compact.json b/tests/ast-parsing/expected/minmax-0.4.14-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.14-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.14-legacy.json b/tests/ast-parsing/expected/minmax-0.4.14-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.14-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.15-compact.json b/tests/ast-parsing/expected/minmax-0.4.15-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.15-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.15-legacy.json b/tests/ast-parsing/expected/minmax-0.4.15-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.15-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.16-compact.json b/tests/ast-parsing/expected/minmax-0.4.16-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.16-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.16-legacy.json b/tests/ast-parsing/expected/minmax-0.4.16-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.16-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.17-compact.json b/tests/ast-parsing/expected/minmax-0.4.17-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.17-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.17-legacy.json b/tests/ast-parsing/expected/minmax-0.4.17-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.17-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.18-compact.json b/tests/ast-parsing/expected/minmax-0.4.18-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.18-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.18-legacy.json b/tests/ast-parsing/expected/minmax-0.4.18-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.18-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.19-compact.json b/tests/ast-parsing/expected/minmax-0.4.19-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.19-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.19-legacy.json b/tests/ast-parsing/expected/minmax-0.4.19-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.19-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.2-legacy.json b/tests/ast-parsing/expected/minmax-0.4.2-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.2-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.20-compact.json b/tests/ast-parsing/expected/minmax-0.4.20-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.20-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.20-legacy.json b/tests/ast-parsing/expected/minmax-0.4.20-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.20-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.21-compact.json b/tests/ast-parsing/expected/minmax-0.4.21-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.21-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.21-legacy.json b/tests/ast-parsing/expected/minmax-0.4.21-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.21-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.22-compact.json b/tests/ast-parsing/expected/minmax-0.4.22-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.22-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.22-legacy.json b/tests/ast-parsing/expected/minmax-0.4.22-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.22-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.23-compact.json b/tests/ast-parsing/expected/minmax-0.4.23-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.23-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.23-legacy.json b/tests/ast-parsing/expected/minmax-0.4.23-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.23-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.24-compact.json b/tests/ast-parsing/expected/minmax-0.4.24-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.24-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.24-legacy.json b/tests/ast-parsing/expected/minmax-0.4.24-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.24-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.25-compact.json b/tests/ast-parsing/expected/minmax-0.4.25-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.25-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.25-legacy.json b/tests/ast-parsing/expected/minmax-0.4.25-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.25-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.26-compact.json b/tests/ast-parsing/expected/minmax-0.4.26-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.26-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.26-legacy.json b/tests/ast-parsing/expected/minmax-0.4.26-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.26-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.3-legacy.json b/tests/ast-parsing/expected/minmax-0.4.3-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.3-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.4-legacy.json b/tests/ast-parsing/expected/minmax-0.4.4-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.4-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.5-legacy.json b/tests/ast-parsing/expected/minmax-0.4.5-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.5-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.6-legacy.json b/tests/ast-parsing/expected/minmax-0.4.6-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.6-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.7-legacy.json b/tests/ast-parsing/expected/minmax-0.4.7-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.7-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.8-legacy.json b/tests/ast-parsing/expected/minmax-0.4.8-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.8-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.4.9-legacy.json b/tests/ast-parsing/expected/minmax-0.4.9-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.4.9-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.0-compact.json b/tests/ast-parsing/expected/minmax-0.5.0-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.0-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.0-legacy.json b/tests/ast-parsing/expected/minmax-0.5.0-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.0-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.1-compact.json b/tests/ast-parsing/expected/minmax-0.5.1-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.1-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.1-legacy.json b/tests/ast-parsing/expected/minmax-0.5.1-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.1-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.10-compact.json b/tests/ast-parsing/expected/minmax-0.5.10-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.10-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.10-legacy.json b/tests/ast-parsing/expected/minmax-0.5.10-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.10-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.11-compact.json b/tests/ast-parsing/expected/minmax-0.5.11-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.11-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.11-legacy.json b/tests/ast-parsing/expected/minmax-0.5.11-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.11-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.12-compact.json b/tests/ast-parsing/expected/minmax-0.5.12-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.12-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.12-legacy.json b/tests/ast-parsing/expected/minmax-0.5.12-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.12-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.13-compact.json b/tests/ast-parsing/expected/minmax-0.5.13-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.13-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.13-legacy.json b/tests/ast-parsing/expected/minmax-0.5.13-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.13-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.14-compact.json b/tests/ast-parsing/expected/minmax-0.5.14-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.14-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.14-legacy.json b/tests/ast-parsing/expected/minmax-0.5.14-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.14-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.15-compact.json b/tests/ast-parsing/expected/minmax-0.5.15-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.15-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.15-legacy.json b/tests/ast-parsing/expected/minmax-0.5.15-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.15-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.16-compact.json b/tests/ast-parsing/expected/minmax-0.5.16-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.16-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.16-legacy.json b/tests/ast-parsing/expected/minmax-0.5.16-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.16-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.17-compact.json b/tests/ast-parsing/expected/minmax-0.5.17-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.17-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.17-legacy.json b/tests/ast-parsing/expected/minmax-0.5.17-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.17-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.2-compact.json b/tests/ast-parsing/expected/minmax-0.5.2-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.2-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.2-legacy.json b/tests/ast-parsing/expected/minmax-0.5.2-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.2-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.3-compact.json b/tests/ast-parsing/expected/minmax-0.5.3-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.3-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.3-legacy.json b/tests/ast-parsing/expected/minmax-0.5.3-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.3-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.4-compact.json b/tests/ast-parsing/expected/minmax-0.5.4-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.4-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.4-legacy.json b/tests/ast-parsing/expected/minmax-0.5.4-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.4-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.5-compact.json b/tests/ast-parsing/expected/minmax-0.5.5-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.5-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.5-legacy.json b/tests/ast-parsing/expected/minmax-0.5.5-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.5-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.6-compact.json b/tests/ast-parsing/expected/minmax-0.5.6-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.6-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.6-legacy.json b/tests/ast-parsing/expected/minmax-0.5.6-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.6-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.7-compact.json b/tests/ast-parsing/expected/minmax-0.5.7-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.7-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.7-legacy.json b/tests/ast-parsing/expected/minmax-0.5.7-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.7-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.8-compact.json b/tests/ast-parsing/expected/minmax-0.5.8-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.8-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.8-legacy.json b/tests/ast-parsing/expected/minmax-0.5.8-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.8-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.9-compact.json b/tests/ast-parsing/expected/minmax-0.5.9-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.9-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.5.9-legacy.json b/tests/ast-parsing/expected/minmax-0.5.9-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.5.9-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.0-compact.json b/tests/ast-parsing/expected/minmax-0.6.0-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.0-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.0-legacy.json b/tests/ast-parsing/expected/minmax-0.6.0-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.0-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.1-compact.json b/tests/ast-parsing/expected/minmax-0.6.1-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.1-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.1-legacy.json b/tests/ast-parsing/expected/minmax-0.6.1-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.1-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.10-compact.json b/tests/ast-parsing/expected/minmax-0.6.10-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.10-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.10-legacy.json b/tests/ast-parsing/expected/minmax-0.6.10-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.10-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.11-compact.json b/tests/ast-parsing/expected/minmax-0.6.11-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.11-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.11-legacy.json b/tests/ast-parsing/expected/minmax-0.6.11-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.11-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.12-compact.json b/tests/ast-parsing/expected/minmax-0.6.12-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.12-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.12-legacy.json b/tests/ast-parsing/expected/minmax-0.6.12-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.12-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.2-compact.json b/tests/ast-parsing/expected/minmax-0.6.2-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.2-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.2-legacy.json b/tests/ast-parsing/expected/minmax-0.6.2-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.2-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.3-compact.json b/tests/ast-parsing/expected/minmax-0.6.3-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.3-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.3-legacy.json b/tests/ast-parsing/expected/minmax-0.6.3-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.3-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.4-compact.json b/tests/ast-parsing/expected/minmax-0.6.4-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.4-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.4-legacy.json b/tests/ast-parsing/expected/minmax-0.6.4-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.4-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.5-compact.json b/tests/ast-parsing/expected/minmax-0.6.5-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.5-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.5-legacy.json b/tests/ast-parsing/expected/minmax-0.6.5-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.5-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.6-compact.json b/tests/ast-parsing/expected/minmax-0.6.6-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.6-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.6-legacy.json b/tests/ast-parsing/expected/minmax-0.6.6-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.6-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.7-compact.json b/tests/ast-parsing/expected/minmax-0.6.7-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.7-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.7-legacy.json b/tests/ast-parsing/expected/minmax-0.6.7-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.7-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.8-compact.json b/tests/ast-parsing/expected/minmax-0.6.8-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.8-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.8-legacy.json b/tests/ast-parsing/expected/minmax-0.6.8-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.8-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.9-compact.json b/tests/ast-parsing/expected/minmax-0.6.9-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.9-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.6.9-legacy.json b/tests/ast-parsing/expected/minmax-0.6.9-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.6.9-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.0-compact.json b/tests/ast-parsing/expected/minmax-0.7.0-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.0-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.0-legacy.json b/tests/ast-parsing/expected/minmax-0.7.0-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.0-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.1-compact.json b/tests/ast-parsing/expected/minmax-0.7.1-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.1-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.1-legacy.json b/tests/ast-parsing/expected/minmax-0.7.1-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.1-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.2-compact.json b/tests/ast-parsing/expected/minmax-0.7.2-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.2-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.2-legacy.json b/tests/ast-parsing/expected/minmax-0.7.2-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.2-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.3-compact.json b/tests/ast-parsing/expected/minmax-0.7.3-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.3-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.3-legacy.json b/tests/ast-parsing/expected/minmax-0.7.3-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.3-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.4-compact.json b/tests/ast-parsing/expected/minmax-0.7.4-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.4-compact.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/expected/minmax-0.7.4-legacy.json b/tests/ast-parsing/expected/minmax-0.7.4-legacy.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/minmax-0.7.4-legacy.json
@@ -0,0 +1,5 @@
+{
+  "C": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/minmax-0.4.0.sol b/tests/ast-parsing/minmax-0.4.0.sol
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/minmax-0.4.0.sol
@@ -0,0 +1,9 @@
+contract C{
+
+    function f() public{
+
+        uint a = 0; // min/max not supported yet
+
+    }
+
+}
diff --git a/tests/ast-parsing/minmax-0.6.8.sol b/tests/ast-parsing/minmax-0.6.8.sol
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/minmax-0.6.8.sol
@@ -0,0 +1,9 @@
+contract C{
+
+    function f() public{
+
+        uint a = type(uint).max;
+
+    }
+
+}
diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py
--- a/tests/test_ast_parsing.py
+++ b/tests/test_ast_parsing.py
@@ -462,6 +462,7 @@ def get_all_test() -> List[Item]:
         base_ver_idx = 0
 
         for solc_ver in solc_versions:
+
             # if it's time to move to the next base version, do it now
             if base_ver_idx + 1 < len(base_vers) and base_vers[base_ver_idx + 1] == solc_ver:
                 base_ver_idx += 1
@@ -559,7 +560,6 @@ def _generate_test(test_item: Item, skip_existing=False):
         return
 
     set_solc(test_item)
-
     sl = Slither(
         test_file,
         solc_force_legacy_json=test_item.is_legacy,
@@ -568,9 +568,9 @@ def _generate_test(test_item: Item, skip_existing=False):
     )
 
     actual = generate_output(sl)
-
+    print(f"Generate {expected_file}")
     with open(expected_file, "w") as f:
-        json.dump(actual, f, ident="  ")
+        json.dump(actual, f, indent="  ")
 
 
 if __name__ == "__main__":