juancarlospaco / nim-contra

Lightweight Self-Documenting Design by Contract Programming and Security Hardened mode.
https://dev.to/juancarlospaco/design-by-contract-immutability-side-effects-and-gulag-44fk
MIT License
54 stars 3 forks source link

README falsely claims {.compiletime.} example doesn't work for Contracts #3

Open Udiknedormin opened 4 years ago

Udiknedormin commented 4 years ago

README states that the following Contracts example code:

import contracts
from math import sqrt, floor
proc isqrt[T: SomeInteger](x: T): T {.contractual.} =
  require:
    x >= 0
  ensure:
    result * result <= x
    (result+1) * (result+1) > x
  body:
    (T)(x.toBiggestFloat().sqrt().floor().toBiggestInt())

echo isqrt(18)
echo isqrt(-8)

Fails with Error: request to generate code for .compileTime proc: isqrt adding compiletime pragma.

However, that is not true:

import contracts
from math import sqrt, floor
proc isqrt[T: SomeInteger](x: T): T {.contractual, compiletime.} =
  require:
    x >= 0
  ensure:
    result * result <= x
    (result+1) * (result+1) > x
  body:
    (T)(x.toBiggestFloat().sqrt().floor().toBiggestInt())

static:
  echo isqrt(18)
  echo isqrt(-8)
$ nim c -r example.nim
4
stack trace: (most recent call last)
(...)/example.nim(14, 13) example
(...)/.nimble/pkgs/contracts-0.1.0/contracts/contexts/contractConds.nim(19, 36) isqrt
(...)/.nimble/pkgs/contracts-0.1.0/contracts/contexts/contractConds.nim(19, 36) Error: unhandled exception: broke 'x >= 0' promised at (...)/example(5, 6) [PreConditionError]

^ the above compile-time error is exactly what is expected from the compile-time execution of that function

The error stated in the README only arises for the following code:

import contracts
from math import sqrt, floor
proc isqrt[T: SomeInteger](x: T): T {.contractual, compiletime.} =
  require:
    x >= 0
  ensure:
    result * result <= x
    (result+1) * (result+1) > x
  body:
    (T)(x.toBiggestFloat().sqrt().floor().toBiggestInt())

echo isqrt(18)  # calling compiletime proc at runtime here!
echo isqrt(-8)  # will ALWAYS raise
                # `Error: request to generate code for .compileTime proc: isqrt`
                # even without using Contracts

...however, that code raises the very same warning with no contracts whatsoever:

$ cat example.nim 
from math import sqrt, floor

proc isqrt[T: SomeInteger](x: T): T {.compiletime.} =
  (T)(x.toBiggestFloat().sqrt().floor().toBiggestInt())

echo isqrt(18)
echo isqrt(-8)

$ nim c example.nim
(...)/example.nim(6, 6) Error: request to generate code for .compileTime proc: isqrt