Assertions in design by contract: Difference between revisions

m
Automated syntax highlighting fixup (second round - minor fixes)
m (syntax highlighting fixup automation)
m (Automated syntax highlighting fixup (second round - minor fixes))
Line 14:
 
You '''cannot''' read the break flag this way:
<syntaxhighlight lang="6502asm">php ;NV-BDIZC (N=negative V=overflow B=break D=decimal I=Interrupt Z=Zero C=Carry)
pla
and #%00010000
Line 21:
This is because the processor flags register doesn't actually contain the true status of the break flag. The only way to read the break flag is to read the flags value that was pushed onto the stack by the hardware itself. Fortunately, this is always at the top of the stack just after an interrupt. Unfortunately, we can't read the flags without clobbering at least one of our registers, something we can't afford to do during an interrupt of any kind. So we'll need to account for the registers we're pushing onto the stack when searching for the flags.
 
<syntaxhighlight lang="6502asm">tempPC_Lo equ $20 ;an arbitrary zero page address set aside for debugging
tempPC_Hi equ $21 ;this must be one byte higher than the previous address.
 
Line 72:
 
Precondition example:
<syntaxhighlight lang="68000devpac"> DIVU D3,D2 ;this will cause a jump to the "divide by zero trap" if D3 = 0.</syntaxhighlight>
 
Postcondition examples:
<syntaxhighlight lang="68000devpac"> ADD.L D4,D5
TRAPV ;no overflow is expected, so if it occurs call the relevant trap.</syntaxhighlight>
 
<syntaxhighlight lang="68000devpac"> LSL.W #8,D2 ;shift D2 left 8 bits.
bcc continue ;if carry clear, we're good.
trap 9 ;otherwise call trap 9, which has been defined (in this example only) to handle unexpected carries after a bit shift.
Line 86:
=={{header|Ada}}==
Ada 2012 introduced aspect specifications to the language. Aspect specifications may be used to specify characteristics about data types, procedures, functions, and tasks. Frequently used aspect specifications for procedures and functions include the ability to specify preconditions and post-conditions. Aspect specifications are written as part of a procedure or function specification such as:
<syntaxhighlight lang=Ada"ada">type Nums_Array is array (Integer range <>) of Integer;
 
procedure Sort(Arr : in out Nums_Array) with
Line 97:
 
Post conditions can also reference parameter changes made during the operation of the procedure such as the following procedure specifications for an unbounded queue:
<syntaxhighlight lang=Ada"ada"> procedure Enqueue (Item : in out Queue; Value : Element_Type) with
Post => Item.Size = Item'Old.Size + 1;
procedure Dequeue (Item : in out Queue; Value : out Element_Type) with
Line 108:
 
Type invariants can be specified using aspect clauses such as:
<syntaxhighlight lang=Ada"ada">subtype Evens is Integer range 0..Integer'Last with
Dynamic_Predicate => Evens mod 2 = 0;
 
Line 128:
{{trans|D}}
Algol W has assertions. Although pre and post conditions are not built in to the language, assertions can be used to simulate them.
<syntaxhighlight lang="algolw">begin
long real procedure averageOfAbsolutes( integer array values( * )
; integer value valuesLength
Line 156:
=={{header|D}}==
D has exceptions, errors and asserts. In Phobos there is also an enforce(). D has pre-conditions and post conditions, and struct/class invariants. Class method contracts should work correctly in object oriented code with inheritance.
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.math;
 
double averageOfAbsolutes(in int[] values) pure nothrow @safe @nogc
Line 188:
=={{header|Eiffel}}==
{{trans|D}}
<syntaxhighlight lang="eiffel"> acc: INTEGER
average_of_absolutes (values: ARRAY[INTEGER]): INTEGER
require
Line 201:
 
=={{header|Fortran}}==
Fortran offers no formal "assert" protocol, but there would be nothing to stop a programmer devising a subroutine such as <syntaxhighlight lang=Fortran"fortran"> SUBROUTINE AFFIRM(CONDITION,MESSAGE)
LOGICAL CONDITION
CHARACTER*(*) MESSAGE
Line 208:
STOP "Oops. Confusion!"
END </syntaxhighlight>
And then scattering through the source file lines such as <syntaxhighlight lang=Fortran"fortran"> CALL AFFIRM(SSQ.GE.0,"Sum of squares can't be negative.") !Perhaps two passes should be used.</syntaxhighlight>
And this could be combined with the arrangements described in [[Stack_traces#Fortran]] to provide further interesting information.
 
As written, the scheme involves an unconditional invocation of a subroutine with parameters. That overhead would be reduced by something like <syntaxhighlight lang=Fortran"fortran"> IF (SSQ.LT.0) CALL CROAK("Sum of squares can't be negative.") !Perhaps two passes should be used.</syntaxhighlight>
 
Some compilers allowed a D in column one to signify that this was a debugging statement, and a compiler option could specify that all such statements were to be treated as comments and not compiled. Probably not a good idea for statements performing checks. The code that is run with intent to produce results should be the same code that you have tested... A variation on this theme involves such debugging output being written to a file, then after modifying and recompiling, the new version's execution proceeds only while it produces the same debugging output. The reference output could be considered a (voluminous) contract, but for this to work a special testing environment is required and is not at all a Fortran standard.
Line 218:
 
FreeBASIC provides three assertions. The <code>#assert</code> preprocessor directive will cause compilation to halt with an error message if its argument evaluates to zero:
<syntaxhighlight lang="freebasic">#assert SCREENX >= 320</syntaxhighlight>
 
The macro <code>assert</code> will halt at runtime with an error message if its argument evaluates to zero:
<syntaxhighlight lang="freebasic">'compile with the -g flag
assert( Pi < 3 )</syntaxhighlight>
 
Finally, <code>assertwarn</code> is like <code>assert</code> but only prints an error message and continues running:
<syntaxhighlight lang="freebasic">'compile with the -g flag
dim as integer a = 2
assertwarn( a+a=5 )
Line 247:
 
If someone disagrees and they ''really'' want to use an "assert" they can simply roll their own:
<syntaxhighlight lang="go">func assert(t bool, s string) {
if !t {
panic(s)
Line 260:
J can load scripts expecting any non-assigned noun result to be all 1's.
If the file tautology_script.ijs contains
<syntaxhighlight lang=J"j">
NB. demonstrate properties of arithmetic
'A B C' =: 3 ?@$ 0 NB. A B and C are random floating point numbers in range [0, 1).
Line 271:
 
In next example the assertion both tests substitute when the script loads and shows how to use substitute. Infinity (_) replaces the zeros in the y argument, and the x argument is the vector zero infinity.
<syntaxhighlight lang=J"j">
substitute =: 4 : '[&.((y~:{.x)&(#!.({:x)))y'
assert _ 1 1 _ 2 -: 0 _ substitute 0 1 1 0 2
Line 278:
 
Pre-condition adverbs with example:
<syntaxhighlight lang=J"j">
Positive =: adverb define
'non-positive' assert *./ , y > 0
Line 302:
 
As a post-condition, and this is contrived because a better definition of exact_factorial would be !@:x: ,
<syntaxhighlight lang=J"j">
IntegralResult =: adverb define
RESULT =. u y
Line 332:
The ''-ea'' or ''-enableassertions'' option must be passed to the VM when running the application for this to work.<br>
Example taken from [[Perceptron#Java|Perceptron task]].
<syntaxhighlight lang="java">(...)
int feedForward(double[] inputs) {
assert inputs.length == weights.length : "weights and input length mismatch";
Line 346:
=={{header|Julia}}==
The @assert macro is used for assertions in Julia.
<syntaxhighlight lang="julia">function volumesphere(r)
@assert(r > 0, "Sphere radius must be positive")
return π * r^3 * 4.0 / 3.0
Line 353:
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">// version 1.1.2
// requires -ea JVM option
 
Line 384:
Here is an example:
 
<syntaxhighlight lang=Nim"nim">import math
 
func isqrt(n: int): int =
Line 395:
Note also that, in this case, rather than using an assertion, we could have simply specified that “n” must be a natural:
 
<syntaxhighlight lang="nim">import math
 
func isqrt(n: Natural): int =
Line 405:
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang=Perl"perl"># 20201201 added Perl programming solution
 
use strict;
Line 440:
=={{header|Phix}}==
User defined types can be used to directly implement design by contract, and disabled by "without type_check".
<!--<syntaxhighlight lang=Phix"phix">-->
<span style="color: #008080;">type</span> <span style="color: #000000;">hour</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">23</span>
Line 456:
 
You can also (since 0.8.2) use standard assert statemnents, eg
<!--<syntaxhighlight lang=Phix"phix">(phixonline)-->
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">-1</span> <span style="color: #000080;font-style:italic;">-- (try also 1)</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cannot open config file"</span><span style="color: #0000FF;">)</span>
Line 476:
This example is extremely surface-scratching.
 
<syntaxhighlight lang="racket">
#lang racket
(require racket/contract)
Line 611:
 
In this snippet, the routine repeat takes one Integer that must be greater than 1, a String and returns a String. (Note that as written, it is incorrect since it actually returns a boolean.)
<syntaxhighlight lang=perl6"raku" line>sub repeat ( Int $repeat where * > 1, Str $message, --> Str ) {
say $message x $repeat;
True # wrong return type
Line 647:
This is just a simple method of &nbsp; ''assertion''; &nbsp; more informative messages could be added in the &nbsp; '''assertion''' &nbsp; routine.
<br>A &nbsp; '''return''' &nbsp; statement could've been used instead of an &nbsp; '''exit''' &nbsp; statement to continue processing.
<syntaxhighlight lang="rexx">/*REXX program demonstrates a method on how to use assertions in design by contract.*/
parse arg top . /*obtain optional argument from the CL.*/
if top=='' | top=="," then top= 100 /*Not specified? Then use the default.*/
Line 696:
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">
require 'contracts'
include Contracts
Line 719:
=={{header|Scala}}==
Scala provides runtime assertions like Java: they are designed to be used by static analysis tools however the default compiler doesn’t perform such analyses by default. The Scala assertions (<tt>assume</tt>, <tt>require</tt>, <tt>assert</tt>, <tt>ensuring</tt>) are [http://www.scala-lang.org/api/current/index.html#scala.Predef$ Predef library] methods that are enabled by default and can be disabled using the <tt>-Xdisable-assertions</tt> runtime flag, unlike Java where assertions are disabled by default and enabled with a runtime flag. It is considered poor form to rely on assertions to validate arguments, because they can be disabled. An appropriate informative runtime exception (e.g. NullPointerException or IllegalArgumentException) should be thrown instead.
<syntaxhighlight lang=Scala"scala">object AssertionsInDesignByContract extends App {
/**
* @param ints a non-empty array of integers
Line 746:
 
=={{header|Tcl}}==
<syntaxhighlight lang="tcl"># Custom assertions; names stolen from Eiffel keywords
proc require {expression message args} {
if {![uplevel 1 [list expr $expression]]} {
Line 787:
{{libheader|Wren-assert}}
Wren doesn't support assertions natively though they (and design by contract) can be simulated using a library.
<syntaxhighlight lang="ecmascript">import "/assert" for Assert
import "/math" for Nums
 
Line 849:
=={{header|Z80 Assembly}}==
There are no built-in assertions, error handlers, etc. at the hardware level. The closest you can get is a function conditionally returning early. For example, this function for multiplication checks if the second factor equals zero or 1 before attempting to multiply.
<syntaxhighlight lang="z80">SmallMultiply:
;returns A = C * A
or a ;compares A to zero
Line 870:
zkl has exceptions. The _assert_ keyword just wraps the AssertionError exception. _assert_ takes an expression and optional message.
There are no pre/post conditionals.
<syntaxhighlight lang="zkl">fcn f(a){
_assert_((z:=g())==5,"I wanted 5, got "+z)
}</syntaxhighlight>
10,327

edits