Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
I
inox
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
LARA
inox
Commits
432a768b
Commit
432a768b
authored
9 years ago
by
Regis Blanc
Browse files
Options
Downloads
Patches
Plain Diff
add some doc for new xlang features
parent
04229951
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/sphinx/xlang.rst
+94
-31
94 additions, 31 deletions
src/sphinx/xlang.rst
with
94 additions
and
31 deletions
src/sphinx/xlang.rst
+
94
−
31
View file @
432a768b
...
...
@@ -39,35 +39,16 @@ The above example illustrates three new features introduced by XLang:
3. Assignments
You can use Scala variables with a few restrictions. The variables can only be
declared and used locally in the same function, and inner functions cannot
close over them. XLang introduces the possibility to use sequences of
expressions (blocks) -- a feature not available in :ref:`Pure Scala
<purescala>`, where you're only option is a sequence of ``val`` which
essentially introduce nested ``let`` declarations.
.. warning::
Be careful when combining variables with nested functions from PureScala. Leon
will reject code with nested functions accessing a variable from an outside scope:
.. code-block:: scala
def foo(x: Int) = {
var a = 12
def bar(y: Int): Int = {
a = a + 1
a + y
}
bar(17)
}
The problem with such code is the complications involved in representing closures as
they need a pointer to an environment containing the variables. Leon is only able
to handle closures with ``val``, where it is sufficient to explicitly pass the values
as parameters.
declared and used locally, no variable declaration outside of a function body.
There is also support for variables in case classes constructors. XLang
introduces the possibility to use sequences of expressions (blocks) -- a
feature not available in :ref:`Pure Scala <purescala>`, where you're only
option is a sequence of ``val`` which essentially introduce nested ``let``
declarations.
While loops
***********
-----------
You can use the ``while`` keyword. While loops usually combine the ability to
declare variables and make a sequence of assignments in order to compute
...
...
@@ -123,7 +104,7 @@ verification condition is used to prove the invariant on initialization of the
loop.
Arrays
******
------
PureScala supports functional arrays, that is, the operations ``apply`` and
``updated`` which do not modify an array but only returns some result. In
...
...
@@ -146,8 +127,7 @@ XLang adds the usual ``update`` operation on arrays:
a(1) = 10
a(1) //10
There are some limitations with what you can do with arrays. Leon simply
rewrite arrays using ``update`` operation as assignment of function arrays
Leon simply rewrite arrays using ``update`` operation as assignment of function arrays
using ``updated``. This leverages the built-in algorithm for functional array
and rely on the elimination procedure for assignments. Concretely, it would
transform the above on the following equivalent implementation:
...
...
@@ -161,8 +141,91 @@ transform the above on the following equivalent implementation:
Then Leon would apply the same process as for any other XLang program.
Due to the way Leon handles side-effects, you cannot update arrays passed
to a function as a parameter.
Mutable Objects
---------------
A restricted form of mutable classes is supported via case classes with ``var``
arguments:
.. code-block:: scala
case class A(var x: Int)
def f(): Int = {
val a = new A(10)
a.x = 13
a.x
}
Mutable case classes are behaving similarly to ``Array``, and are handled with a
rewriting, where each field updates becomes essentially a copy of the object with
the modified parameter changed.
Aliasing
--------
With mutable data structures comes the problem of aliasing. In Leon, we
maintain the invariant that in any scope, there is at most one pointer to some
mutable structure. Leon will issue an error if you try to create an alias to
some mutable structure in the same scope:
.. code-block:: scala
val a = Array(1,2,3,4)
val b = a //error: illegal aliasing
b(0) = 10
assert(a(0) == 10)
However, Leon correctly supports aliasing mutable structures when passing it
as a parameter to a function (assuming its scope is not shared with the call
site, i.e. not a nested function). Essentially you can do:
.. code-block:: scala
case class A(var x: Int)
def updateA(a: A): Unit = {
a.x = 14
}
def f(): Unit = {
val a = A(10)
updateA(a)
assert(a.x == 14)
}
The function ``updateA`` will have the side effect of updating its argument
``a`` and this will be visible at the call site.
Annotations for Imperative Programming
--------------------------------------
XLang introduces the special function ``old`` that can be used in postconditions to
talk about the value of a variable before the execution of the block. When you refer to a variable
or mutable structure in a post-condition, leon will always consider the current value of
the object, so that in the case of a post-condition this would refer to the final value of the
object. Using ``old``, you can refer to the original value of the variable and check some
properties:
.. code-block:: scala
case class A(var x: Int)
def inc(a: A): Unit = {
a.x = a.x + 1
} ensuring(_ => a.x == old(a).x + 1)
``old`` can be wrapped around any identifier that is affected by the body. You can also use
``old`` for variables in scope, in case of nested functions:
.. code-block:: scala
def f(): Int = {
var x = 0
def inc(): Unit = {
x = x + 1
} ensuring(_ => x == old(x) + 1)
inc(); inc();
assert(x == 2)
}
Epsilon
-------
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment