Merge branch 'master' into master

This commit is contained in:
Alias Qli 2021-05-27 00:20:07 +08:00 committed by GitHub
commit 81fc2edbe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
180 changed files with 3043 additions and 784 deletions

View File

@ -9,9 +9,6 @@ on:
branches:
- master
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
jobs:
build:
runs-on: ubuntu-latest

View File

@ -12,7 +12,6 @@ on:
env:
SCHEME: chez
IDRIS2_TESTS_CG: chez
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
jobs:
@ -27,7 +26,7 @@ jobs:
run: |
brew install chezscheme
brew install coreutils
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
- name: Build Idris 2 from bootstrap
run: make bootstrap && make install
shell: bash
@ -54,7 +53,7 @@ jobs:
run: |
brew install chezscheme
brew install coreutils
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
- name: Build self-hosted
run: make all && make install
@ -83,7 +82,7 @@ jobs:
# brew install gambit-scheme
# CURRENTDIR=$(find /usr/local/Cellar/gambit-scheme -type l -name current)
# echo "::add-path::${CURRENTDIR}/bin"
# echo "::add-path::$HOME/.idris2/bin"
# echo "$HOME/.idris2/bin" >> $GITHUB_PATH
# chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
# - name: Test gambit
# run: cd tests/gambit/bitops001/ && ./run idris2

View File

@ -51,6 +51,7 @@ jobs:
uses: github/super-linter@v3
env:
VALIDATE_ALL_CODEBASE: false
VALIDATE_CPP: false # C files predate linting
VALIDATE_JSCPD: false # erroneously complains about docs/requirements.txt
VALIDATE_JAVASCRIPT_STANDARD: false #requires camel-casing
DEFAULT_BRANCH: master

View File

@ -12,7 +12,6 @@ on:
- main
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
IDRIS2_VERSION: 0.3.0 # For previous-version build
SCHEME: scheme
@ -33,7 +32,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y chezscheme
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
- name: Build from bootstrap
run: make bootstrap && make install
- name: Artifact Bootstrapped Idris2
@ -53,7 +52,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y racket
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
- name: Build from bootstrap
run: make bootstrap-racket && make install
- name: Artifact Bootstrapped Idris2
@ -73,7 +72,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y chezscheme
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
- name: Cache Chez Previous Version
id: previous-version-cache
uses: actions/cache@v2
@ -120,7 +119,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y chezscheme
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
- name: Build self-hosted
run: make all && make install
@ -144,7 +143,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y racket
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
- name: Build self-hosted
run: make all && make install
@ -168,7 +167,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y chezscheme
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
- name: Build from previous version
run: make all && make install && make clean
@ -199,7 +198,7 @@ jobs:
- name: Install build dependencies
run: |
sudo apt-get install -y chezscheme
echo "::add-path::$HOME/.idris2/bin"
echo "$HOME/.idris2/bin" >> $GITHUB_PATH
chmod +x $HOME/.idris2/bin/idris2 $HOME/.idris2/bin/idris2_app/*
- name: Build API
run: make install-api

View File

@ -14,7 +14,6 @@ env:
SCHEME: scheme
IDRIS2_TESTS_CG: chez
CC: gcc
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
jobs:
build:
@ -29,7 +28,7 @@ jobs:
run: |
git clone --depth 1 https://github.com/cisco/ChezScheme
c:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm tar make"
echo "::set-env name=PWD::$(c:\msys64\usr\bin\cygpath -u $(pwd))"
echo "PWD=$(c:\msys64\usr\bin\cygpath -u $(pwd))" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Configure and Build Chez Scheme
run: |
c:\msys64\usr\bin\bash -l -c "cd $env:PWD && cd ChezScheme && ./configure --threads && make"
@ -37,10 +36,10 @@ jobs:
run: |
$chez="$(pwd)\ChezScheme\ta6nt\bin\ta6nt"
$idris="$(pwd)\.idris2"
echo "::add-path::$chez"
echo "::add-path::$idris\bin"
echo "::set-env name=IDRIS_PREFIX::$idris"
echo "::set-env name=PREFIX::$(c:\msys64\usr\bin\cygpath -u $idris)"
echo "$chez" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "$idris\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "IDRIS_PREFIX=$idris" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "PREFIX=$(c:\msys64\usr\bin\cygpath -u $idris)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Test Scheme
run: |
scheme --version

View File

@ -11,7 +11,8 @@ Library changes:
command line options, to `contrib`.
* Monad transformers in `Control.Monad` where restructured
and several new transformer types where added.
* `Data.Colist` and `Data.Colist1` where added to `base`.
* `Data.Colist` and `Data.Colist1` were added to `base`.
* Add `Data.SnocList` to base and `data SnocList` to `Prelude.Types`.
* `Data.Bits`, an interface for bitwise operations, was added to `base`.
* Interfaces `Bifoldable` and `Bitraversable` were added to the `prelude`.
* Interface `Data.Contravariant` for contravariant functors was added
@ -29,6 +30,8 @@ Syntax changes:
implicit parameters and give multiplicities for parameters. The old syntax
is still available for compatibility purposes but will be removed in the
future.
* Add support for SnocList syntax: `[< 1, 2, 3]` desugars into `Lin :< 1 :< 2 :< 3`
and their semantic highlighting.
Compiler changes:

View File

@ -10,7 +10,7 @@ The requirements are:
- A Scheme compiler; either Chez Scheme (default), or Racket.
- `bash`, with `realpath`. On Linux, you probably already have this.
On a Mac, you can install this with `brew install coreutils`.
On a macOS, you can install this with `brew install coreutils`.
On FreeBSD, OpenBSD and NetBSD, you can install `realpath` and `GNU make`
using a package manager. For instance, on OpenBSD you can install all of them
with `pkg_add coreutils gmake` command.

View File

@ -4,7 +4,7 @@ Idris 2
[![Documentation Status](https://readthedocs.org/projects/idris2/badge/?version=latest)](https://idris2.readthedocs.io/en/latest/?badge=latest)
[![Windows Status](https://github.com/idris-lang/Idris2/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/idris-lang/Idris2/actions/workflows/ci-windows.yml)
[![Ubuntu Status](https://github.com/idris-lang/Idris2/actions/workflows/ci-ubuntu-combined.yml/badge.svg)](https://github.com/idris-lang/Idris2/actions/workflows/ci-ubuntu-combined.yml)
[![MacOS Status](https://github.com/idris-lang/Idris2/actions/workflows/ci-macos-combined.yml/badge.svg)](https://github.com/idris-lang/Idris2/actions/workflows/ci-macos-combined.yml)
[![macOS Status](https://github.com/idris-lang/Idris2/actions/workflows/ci-macos-combined.yml/badge.svg)](https://github.com/idris-lang/Idris2/actions/workflows/ci-macos-combined.yml)
[![Nix Status](https://github.com/idris-lang/Idris2/actions/workflows/ci-nix.yml/badge.svg)](https://github.com/idris-lang/Idris2/actions/workflows/ci-nix.yml)
[Idris 2](https://idris-lang.org/) is a purely functional programming language

View File

@ -7,22 +7,12 @@ if [ -z "$SCHEME" ]; then
exit 1
fi
case $(uname -s) in
OpenBSD | FreeBSD | NetBSD)
REALPATH="grealpath"
;;
*)
REALPATH="realpath"
;;
esac
if ! command -v "$REALPATH" >/dev/null; then
echo "$REALPATH is required for Chez code generator."
exit 1
if [ "$(uname)" = Darwin ]; then
DIR=$(zsh -c 'printf %s "$0:A:h"' "$0")
else
DIR=$(dirname "$(readlink -f -- "$0")")
fi
DIR=$(dirname "$($REALPATH "$0")")
LD_LIBRARY_PATH="$DIR/idris2_app":$LD_LIBRARY_PATH
PATH="$DIR/idris2_app":$PATH
export LD_LIBRARY_PATH PATH

View File

@ -2,28 +2,12 @@
set -e # exit on any error
if [ -z "$IDRIS2_VERSION" ]; then
echo "Required IDRIS2_VERSION env is not set."
exit 1
fi
echo "Bootstrapping IDRIS2_VERSION=$IDRIS2_VERSION"
case $(uname -s) in
OpenBSD | FreeBSD | NetBSD)
REALPATH="grealpath"
;;
*)
REALPATH="realpath"
;;
esac
if ! command -v "$REALPATH" >/dev/null; then
echo "$REALPATH is required for Racket code generator."
exit 1
if [ "$(uname)" = Darwin ]; then
DIR=$(zsh -c 'printf %s "$0:A:h"' "$0")
else
DIR=$(dirname "$(readlink -f -- "$0")")
fi
DIR=$(dirname "$($REALPATH "$0")")
LD_LIBRARY_PATH="$DIR/idris2_app":$LD_LIBRARY_PATH
PATH="$DIR/idris2_app":$PATH
export LD_LIBRARY_PATH PATH

View File

@ -0,0 +1,106 @@
**********************
Debugging The Compiler
**********************
Performance
===========
The compiler has the ``--timing`` flag to dump timing information collected during operation.
The output documents, in reverse chronological order, the cumulative time taken for the operation (and sub operations) to complete.
Sub levels are indicated by successive repetitions of ``+``.
Logging
=======
The compiler logs various categories of information during operation at various levels.
Log levels are characterised by two things:
+ a dot-separated path of ever finer topics of interest e.g. scope.let
+ a natural number corresponding to the verbosity level e.g. 5
If the user asks for some logs by writing::
%logging "scope" 5
they will get all of the logs whose path starts with `scope` and whose
verbosity level is less or equal to `5`. By combining different logging
directives, users can request information about everything (with a low
level of details) and at the same time focus on a particular subsystem
they want to get a lot of information about. For instance:::
%logging 1
%logging "scope.let" 10
will deliver basic information about the various phases the compiler goes
through and deliver a lot of information about scope-checking let binders.
You can set the logging level at the command line using::
--log <level>
and through the REPL using::
:log <string category> <level>
:logging <string category> <level>
The supported logging categories can be found using the command line flag::
--help logging
REPL Commands
=============
To see more debug information from the REPL there are several options one can set.
.. csv-table:: Logging Categories
:header: "command", "description"
:widths: 20, 20
``:di <name>``, show debugging information for a name
``:set showimplicits``, show values of implicit arguments
Compiler Flags
==============
There are several 'hidden' compiler flags that can help expose Idris' inner workings.
.. csv-table:: Logging Categories
:header: "command", "description"
:widths: 20, 20
``--dumpcases <file>``, dump case trees to the given file
``--dumplifted <file>``, dump lambda lifted trees to the given file
``--dumpanf <file>``, dump ANF to the given file
``--dumpvmcode <file>``, dump VM Code to the given file
``--debug-elab-check``, do more elaborator checks (currently conversion in LinearCheck)
Output Formats
==============
Debug Output
------------
Calling ``:di <name>`` dumps debugging information about the selected term.
Specifically dumped are:
.. csv-table:: Debugging Information
:header: "topic", "description"
:widths: 20, 20
Full Name(s), The fully qualified name of the term.
Multiplicity, The terms multiplicity.
Erasable Arguments, Things that are erased.
Detaggable argument types,
Specialised arguments,
Inferrable arguments,
Compiled version,
Compile time linked terms,
Runtime linked terms,
Flags,
Size change graph,

View File

@ -22,3 +22,4 @@ This is a placeholder, to get set up with readthedocs.
literate
overloadedlit
builtins
debugging

View File

@ -90,7 +90,7 @@ which you can run:
$ ./build/exec/hello
Hello world
(On Macos you may first need to install realpath: ```brew install coreutils```)
(On macOS you may first need to install realpath: ```brew install coreutils```)
Please note that the dollar sign ``$`` indicates the shell prompt!
Some useful options to the Idris command are:

View File

@ -737,13 +737,26 @@ Note that the constructor names are the same for each — constructor
names (in fact, names in general) can be overloaded, provided that
they are declared in different namespaces (see Section
:ref:`sect-namespaces`), and will typically be resolved according to
their type. As syntactic sugar, any type with the constructor names
their type. As syntactic sugar, any implementation of the names
``Nil`` and ``::`` can be written in list form. For example:
- ``[]`` means ``Nil``
- ``[1,2,3]`` means ``1 :: 2 :: 3 :: Nil``
Similarly, any implementation of the names ``Lin`` and ``:<`` can be
written in **snoc**-list form:
- ``[<]`` mean ``Lin``
- ``[< 1, 2, 3]`` means ``Lin :< 1 :< 2 :< 3``.
and the prelude includes a pre-defined datatype for snoc-lists:
.. code-block:: idris
data SnocList a = Lin | (:<) (SnocList a) a
The library also defines a number of functions for manipulating these
types. ``map`` is overloaded both for ``List`` and ``Vect`` (we'll see more
details of precisely how later when we cover interfaces in

View File

@ -73,7 +73,7 @@ modules =
Idris.Desugar.Mutual,
Idris.Env,
Idris.Doc.HTML,
Idris.DocString,
Idris.Doc.String,
Idris.Driver,
Idris.Error,
Idris.ModTree,

View File

@ -16,6 +16,7 @@ export
data Buffer : Type where [external]
%foreign "scheme:blodwen-buffer-size"
"C:idris2_getBufferSize, libidris2_support, idris_buffer.h"
"node:lambda:b => BigInt(b.length)"
prim__bufferSize : Buffer -> Int
@ -24,6 +25,7 @@ rawSize : HasIO io => Buffer -> io Int
rawSize buf = pure (prim__bufferSize buf)
%foreign "scheme:blodwen-new-buffer"
"C:idris2_newBuffer, libidris2_support, idris_buffer.h"
"node:lambda:s=>Buffer.alloc(Number(s))"
prim__newBuffer : Int -> PrimIO Buffer
@ -36,16 +38,22 @@ newBuffer size
-- then pure Nothing
-- else pure $ Just $ MkBuffer buf size 0
-- might be needed if we do this in C...
%foreign "scheme:blodwen-buffer-free"
"C:idris2_freeBuffer, libidris2_support, idris_buffer.h"
"node:lambda:buf=>undefined"
prim__freeBuffer : Buffer -> PrimIO ()
export
freeBuffer : HasIO io => Buffer -> io ()
freeBuffer buf = pure ()
freeBuffer buf = primIO (prim__freeBuffer buf)
%foreign "scheme:blodwen-buffer-setbyte"
"C:idris2_setBufferByte, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,value)=>buf.writeUInt8(Number(value), Number(offset))"
prim__setByte : Buffer -> Int -> Int -> PrimIO ()
%foreign "scheme:blodwen-buffer-setbyte"
"C:idris2_setBufferByte, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,value)=>buf.writeUInt8(Number(value), Number(offset))"
prim__setBits8 : Buffer -> Int -> Bits8 -> PrimIO ()
@ -61,10 +69,12 @@ setBits8 buf loc val
= primIO (prim__setBits8 buf loc val)
%foreign "scheme:blodwen-buffer-getbyte"
"C:idris2_getBufferByte, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset)=>BigInt(buf.readUInt8(Number(offset)))"
prim__getByte : Buffer -> Int -> PrimIO Int
%foreign "scheme:blodwen-buffer-getbyte"
"C:idris2_getBufferByte, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset)=>BigInt(buf.readUInt8(Number(offset)))"
prim__getBits8 : Buffer -> Int -> PrimIO Bits8
@ -149,6 +159,7 @@ getInt32 buf loc
= primIO (prim__getInt32 buf loc)
%foreign "scheme:blodwen-buffer-setint"
"C:idris2_setBufferInt, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,value)=>buf.writeInt64(Number(value), Number(offset))"
prim__setInt : Buffer -> Int -> Int -> PrimIO ()
@ -158,6 +169,7 @@ setInt buf loc val
= primIO (prim__setInt buf loc val)
%foreign "scheme:blodwen-buffer-getint"
"C:idris2_getBufferInt, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset)=>BigInt(buf.readInt64(Number(offset)))"
prim__getInt : Buffer -> Int -> PrimIO Int
@ -167,6 +179,7 @@ getInt buf loc
= primIO (prim__getInt buf loc)
%foreign "scheme:blodwen-buffer-setdouble"
"C:idris2_setBufferDouble, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,value)=>buf.writeDoubleLE(value, Number(offset))"
prim__setDouble : Buffer -> Int -> Double -> PrimIO ()
@ -176,6 +189,7 @@ setDouble buf loc val
= primIO (prim__setDouble buf loc val)
%foreign "scheme:blodwen-buffer-getdouble"
"C:idris2_getBufferDouble, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset)=>buf.readDoubleLE(Number(offset))"
prim__getDouble : Buffer -> Int -> PrimIO Double
@ -190,6 +204,7 @@ export
stringByteLength : String -> Int
%foreign "scheme:blodwen-buffer-setstring"
"C:idris2_setBufferString, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,value)=>buf.write(value, Number(offset),buf.length - Number(offset), 'utf-8')"
prim__setString : Buffer -> Int -> String -> PrimIO ()
@ -199,6 +214,7 @@ setString buf loc val
= primIO (prim__setString buf loc val)
%foreign "scheme:blodwen-buffer-getstring"
"C:idris2_getBufferString, libidris2_support, idris_buffer.h"
"node:lambda:(buf,offset,len)=>buf.slice(Number(offset), Number(offset+len)).toString('utf-8')"
prim__getString : Buffer -> Int -> Int -> PrimIO String
@ -221,6 +237,7 @@ bufferData buf
%foreign "scheme:blodwen-buffer-copydata"
"C:idris2_copyBuffer, libidris2_support, idris_buffer.h"
"node:lambda:(b1,o1,length,b2,o2)=>b1.copy(b2,Number(o2), Number(o1), Number(o1+length))"
prim__copyData : Buffer -> Int -> Int -> Buffer -> Int -> PrimIO ()
@ -230,11 +247,11 @@ copyData : HasIO io => (src : Buffer) -> (start, len : Int) ->
copyData src start len dest loc
= primIO (prim__copyData src start len dest loc)
%foreign "C:idris2_readBufferData,libidris2_support"
%foreign "C:idris2_readBufferData, libidris2_support, idris_buffer.h"
"node:lambda:(f,b,l,m) => BigInt(require('fs').readSync(f.fd,b,Number(l), Number(m)))"
prim__readBufferData : FilePtr -> Buffer -> Int -> Int -> PrimIO Int
%foreign "C:idris2_writeBufferData,libidris2_support"
%foreign "C:idris2_writeBufferData, libidris2_support, idris_buffer.h"
"node:lambda:(f,b,l,m) => BigInt(require('fs').writeSync(f.fd,b,Number(l), Number(m)))"
prim__writeBufferData : FilePtr -> Buffer -> Int -> Int -> PrimIO Int

View File

@ -17,13 +17,15 @@ data Fin : (n : Nat) -> Type where
FZ : Fin (S k)
FS : Fin k -> Fin (S k)
||| Cast between Fins with equal indices
||| Coerce between Fins with equal indices
public export
cast : {n : Nat} -> (0 eq : m = n) -> Fin m -> Fin n
cast {n = S _} eq FZ = FZ
cast {n = Z} eq FZ impossible
cast {n = S _} eq (FS k) = FS (cast (succInjective _ _ eq) k)
cast {n = Z} eq (FS k) impossible
coerce : {n : Nat} -> (0 eq : m = n) -> Fin m -> Fin n
coerce {n = S _} eq FZ = FZ
coerce {n = Z} eq FZ impossible
coerce {n = S _} eq (FS k) = FS (coerce (succInjective _ _ eq) k)
coerce {n = Z} eq (FS k) impossible
%transform "coerce-identity" coerce = replace {p = Fin}
export
Uninhabited (Fin Z) where
@ -221,19 +223,21 @@ namespace Equality
transitive FZ FZ = FZ
transitive (FS prf) (FS prg) = FS (transitive prf prg)
||| Pointwise equality is compatible with cast
||| Pointwise equality is compatible with coerce
export
castEq : {k : Fin m} -> (0 eq : m = n) -> cast eq k ~~~ k
castEq {k = FZ} Refl = FZ
castEq {k = FS k} Refl = FS (castEq _)
coerceEq : {k : Fin m} -> (0 eq : m = n) -> coerce eq k ~~~ k
coerceEq {k = FZ} Refl = FZ
coerceEq {k = FS k} Refl = FS (coerceEq _)
||| The actual proof used by cast is irrelevant
||| The actual proof used by coerce is irrelevant
export
congCast : {0 n, q : Nat} -> {k : Fin m} -> {l : Fin p} ->
{0 eq1 : m = n} -> {0 eq2 : p = q} ->
k ~~~ l ->
cast eq1 k ~~~ cast eq2 l
congCast eq = transitive (castEq _) (transitive eq $ symmetric $ castEq _)
congCoerce : {0 n, q : Nat} -> {k : Fin m} -> {l : Fin p} ->
{0 eq1 : m = n} -> {0 eq2 : p = q} ->
k ~~~ l ->
coerce eq1 k ~~~ coerce eq2 l
congCoerce eq
= transitive (coerceEq _)
$ transitive eq $ symmetric $ coerceEq _
||| Last is congruent wrt index equality
export

104
libs/base/Data/SnocList.idr Normal file
View File

@ -0,0 +1,104 @@
||| A Reversed List
module Data.SnocList
import Decidable.Equality
import Data.List
%default total
infixl 7 <><
infixr 6 <>>
||| 'fish': Action of lists on snoc-lists
public export
(<><) : SnocList a -> List a -> SnocList a
sx <>< [] = sx
sx <>< (x :: xs) = sx :< x <>< xs
||| 'chips': Action of snoc-lists on lists
public export
(<>>) : SnocList a -> List a -> List a
Lin <>> xs = xs
(sx :< x) <>> xs = sx <>> x :: xs
Cast (SnocList a) (List a) where
cast sx = sx <>> []
Cast (List a) (SnocList a) where
cast xs = Lin <>< xs
||| Transform to a list but keeping the contents in the spine order (term depth).
public export
asList : SnocList type -> List type
asList = (reverse . cast)
public export
Eq a => Eq (SnocList a) where
(==) Lin Lin = True
(==) (sx :< x) (sy :< y) = x == y && sx == sy
(==) _ _ = False
public export
Ord a => Ord (SnocList a) where
compare Lin Lin = EQ
compare Lin (sx :< x) = LT
compare (sx :< x) Lin = GT
compare (sx :< x) (sy :< y)
= case compare sx sy of
EQ => compare x y
c => c
||| True iff input is Lin
public export
isLin : SnocList a -> Bool
isLin Lin = True
isLin (sx :< x) = False
||| True iff input is (:<)
public export
isSnoc : SnocList a -> Bool
isSnoc Lin = False
isSnoc (sx :< x) = True
public export
(++) : (sx, sy : SnocList a) -> SnocList a
(++) sx Lin = sx
(++) sx (sy :< y) = (sx ++ sy) :< y
public export
length : SnocList a -> Nat
length Lin = Z
length (sx :< x) = length sx + 1
export
Show a => Show (SnocList a) where
show xs = "[< " ++ show' "" xs ++ "]"
where
show' : String -> SnocList a -> String
show' acc Lin = acc
show' acc (Lin :< x)= show x ++ acc
show' acc (xs :< x) = show' (", " ++ show x ++ acc) xs
public export
Functor SnocList where
map f Lin = Lin
map f (sx :< x) = (map f sx) :< (f x)
public export
Semigroup (SnocList a) where
(<+>) = (++)
public export
Monoid (SnocList a) where
neutral = Lin
||| Check if something is a member of a list using the default Boolean equality.
public export
elem : Eq a => a -> SnocList a -> Bool
elem x Lin = False
elem x (sx :< y) = x == y || elem x sx

View File

@ -5,7 +5,7 @@ import Data.List
import Data.Strings
support : String -> String
support fn = "C:" ++ fn ++ ", libidris2_support"
support fn = "C:" ++ fn ++ ", libidris2_support, idris_support.h"
libc : String -> String
libc fn = "C:" ++ fn ++ ", libc 6"
@ -15,12 +15,10 @@ libc fn = "C:" ++ fn ++ ", libc 6"
%foreign "scheme,racket:blodwen-sleep"
support "idris2_sleep"
-- "C:idris2_sleep, libidris2_support"
prim__sleep : Int -> PrimIO ()
%foreign "scheme,racket:blodwen-usleep"
support "idris2_usleep"
-- "C:idris2_usleep, libidris2_support"
prim__usleep : Int -> PrimIO ()
export
@ -33,12 +31,14 @@ usleep sec = primIO (prim__usleep sec)
-- Get the number of arguments
%foreign "scheme:blodwen-arg-count"
"node:lambda:() => process.argv.length"
support "idris2_getArgCount"
"node:lambda:() => BigInt(process.argv.length)"
prim__getArgCount : PrimIO Int
-- Get argument number `n`
%foreign "scheme:blodwen-arg"
"node:lambda:n => process.argv[n]"
support "idris2_getArg"
"node:lambda:n => process.argv[(Number(n))]"
prim__getArg : Int -> PrimIO String
export
@ -113,6 +113,14 @@ export
time : HasIO io => io Integer
time = pure $ cast !(primIO prim__time)
%foreign support "idris2_getPID"
prim__getPID : PrimIO Int
||| Get the ID of the currently running process.
export
getPID : HasIO io => io Int
getPID = primIO prim__getPID
%foreign libc "exit"
"node:lambda:c => process.exit(Number(c))"
prim__exit : Int -> PrimIO ()

View File

@ -81,36 +81,42 @@ isClockMandatory GCReal = Optional
isClockMandatory _ = Mandatory
%foreign "scheme:blodwen-clock-time-monotonic"
"C:clockTimeMonotonic"
prim__clockTimeMonotonic : PrimIO OSClock
clockTimeMonotonic : IO OSClock
clockTimeMonotonic = fromPrim prim__clockTimeMonotonic
%foreign "scheme:blodwen-clock-time-utc"
"C:clockTimeUtc"
prim__clockTimeUtc : PrimIO OSClock
clockTimeUtc : IO OSClock
clockTimeUtc = fromPrim prim__clockTimeUtc
%foreign "scheme:blodwen-clock-time-process"
"C:clockTimeProcess"
prim__clockTimeProcess : PrimIO OSClock
clockTimeProcess : IO OSClock
clockTimeProcess = fromPrim prim__clockTimeProcess
%foreign "scheme:blodwen-clock-time-thread"
"C:clockTimeThread"
prim__clockTimeThread : PrimIO OSClock
clockTimeThread : IO OSClock
clockTimeThread = fromPrim prim__clockTimeThread
%foreign "scheme:blodwen-clock-time-gccpu"
"C:clockTimeGcCpu"
prim__clockTimeGcCpu : PrimIO OSClock
clockTimeGcCpu : IO OSClock
clockTimeGcCpu = fromPrim prim__clockTimeGcCpu
%foreign "scheme:blodwen-clock-time-gcreal"
"C:clockTimeGcReal"
prim__clockTimeGcReal : PrimIO OSClock
clockTimeGcReal : IO OSClock
@ -126,6 +132,7 @@ fetchOSClock GCReal = clockTimeGcReal
fetchOSClock Duration = clockTimeMonotonic
%foreign "scheme:blodwen-is-time?"
"C:clockValid"
prim__osClockValid : OSClock -> PrimIO Int
||| A test to determine the status of optional clocks.
@ -133,12 +140,14 @@ osClockValid : OSClock -> IO Int
osClockValid clk = fromPrim (prim__osClockValid clk)
%foreign "scheme:blodwen-clock-second"
"C:clockSecond"
prim__osClockSecond : OSClock -> PrimIO Bits64
osClockSecond : OSClock -> IO Bits64
osClockSecond clk = fromPrim (prim__osClockSecond clk)
%foreign "scheme:blodwen-clock-nanosecond"
"C:clockNanosecond"
prim__osClockNanosecond : OSClock -> PrimIO Bits64
osClockNanosecond : OSClock -> IO Bits64

View File

@ -7,9 +7,9 @@ DirPtr : Type
DirPtr = AnyPtr
support : String -> String
support fn = "C:" ++ fn ++ ", libidris2_support"
support fn = "C:" ++ fn ++ ", libidris2_support, idris_directory.h"
%foreign support "idris2_fileErrno"
%foreign "C:idris2_fileErrno, libidris2_support, idris_file.h"
"node:support:fileErrno,support_system_file"
prim__fileErrno : PrimIO Int

View File

@ -16,10 +16,7 @@ FilePtr : Type
FilePtr = AnyPtr
support : String -> String
support fn = "C:" ++ fn ++ ", libidris2_support"
libc : String -> String
libc fn = "C:" ++ fn ++ ", libc 6"
support fn = "C:" ++ fn ++ ", libidris2_support, idris_file.h"
%foreign support "idris2_openFile"
"node:support:openFile,support_system_file"
@ -97,7 +94,7 @@ prim__stdout : FilePtr
"node:lambda:x=>({fd:2, buffer: Buffer.alloc(0), name:'<stderr>', eof: false})"
prim__stderr : FilePtr
%foreign libc "chmod"
%foreign "C:chmod, libc 6, sys/stat.h"
"node:support:chmod,support_system_file"
prim__chmod : String -> Int -> PrimIO Int

View File

@ -15,7 +15,7 @@ export
isWindows : Bool
isWindows = os `elem` ["windows", "mingw32", "cygwin32"]
%foreign "C:idris2_getNProcessors, libidris2_support"
%foreign "C:idris2_getNProcessors, libidris2_support, idris_support.h"
prim__getNProcessors : PrimIO Int
export

252
libs/base/System/Signal.idr Normal file
View File

@ -0,0 +1,252 @@
||| Signal raising and handling.
|||
||| NOTE that there are important differences between
||| what can be done out-of-box in Windows and POSIX based
||| operating systems. This module tries to honor both
||| by putting things only available in POSIX environments
||| into appropriately named namespaces or data types.
module System.Signal
import Data.Fuel
import Data.List
import Data.List.Elem
%default total
signalFFI : String -> String
signalFFI fn = "C:" ++ fn ++ ", libidris2_support, idris_signal.h"
--
-- Signals
--
%foreign signalFFI "sighup"
prim__sighup : Int
%foreign signalFFI "sigint"
prim__sigint : Int
%foreign signalFFI "sigabrt"
prim__sigabrt : Int
%foreign signalFFI "sigquit"
prim__sigquit : Int
%foreign signalFFI "sigill"
prim__sigill : Int
%foreign signalFFI "sigsegv"
prim__sigsegv : Int
%foreign signalFFI "sigtrap"
prim__sigtrap : Int
%foreign signalFFI "sigfpe"
prim__sigfpe : Int
%foreign signalFFI "sigusr1"
prim__sigusr1 : Int
%foreign signalFFI "sigusr2"
prim__sigusr2 : Int
public export
data PosixSignal = ||| Hangup (i.e. controlling terminal closed)
SigHUP
| ||| Quit
SigQUIT
| ||| Trap (as used by debuggers)
SigTRAP
| SigUser1
| SigUser2
export
Eq PosixSignal where
SigHUP == SigHUP = True
SigQUIT == SigQUIT = True
SigTRAP == SigTRAP = True
SigUser1 == SigUser1 = True
SigUser2 == SigUser2 = True
_ == _ = False
public export
data Signal = ||| Interrupt (e.g. ctrl+c pressed)
SigINT
| ||| Abnormal termination
SigABRT
| ||| Ill-formed instruction
SigILL
| ||| Segmentation fault
SigSEGV
| ||| Floating-point error
SigFPE
| ||| Signals only available on POSIX operating systems
SigPosix PosixSignal
export
Eq Signal where
SigINT == SigINT = True
SigABRT == SigABRT = True
SigILL == SigILL = True
SigSEGV == SigSEGV = True
SigFPE == SigFPE = True
SigPosix x == SigPosix y = x == y
_ == _ = False
signalCode : Signal -> Int
signalCode SigINT = prim__sigint
signalCode SigABRT = prim__sigabrt
signalCode SigILL = prim__sigill
signalCode SigSEGV = prim__sigsegv
signalCode SigFPE = prim__sigfpe
signalCode (SigPosix SigHUP ) = prim__sighup
signalCode (SigPosix SigQUIT ) = prim__sigquit
signalCode (SigPosix SigTRAP ) = prim__sigtrap
signalCode (SigPosix SigUser1) = prim__sigusr1
signalCode (SigPosix SigUser2) = prim__sigusr2
toSignal : Int -> Maybe Signal
toSignal (-1) = Nothing
toSignal x = lookup x codes
where
codes : List (Int, Signal)
codes = [
(prim__sigint , SigINT)
, (prim__sigabrt, SigABRT)
, (prim__sigill , SigILL)
, (prim__sigsegv, SigSEGV)
, (prim__sigfpe , SigFPE)
, (prim__sighup , SigPosix SigHUP)
, (prim__sigquit, SigPosix SigQUIT)
, (prim__sigtrap, SigPosix SigTRAP)
, (prim__sigusr1, SigPosix SigUser1)
, (prim__sigusr2, SigPosix SigUser2)
]
--
-- Signal Handling
--
%foreign signalFFI "ignore_signal"
prim__ignoreSignal : Int -> PrimIO Int
%foreign signalFFI "default_signal"
prim__defaultSignal : Int -> PrimIO Int
%foreign signalFFI "collect_signal"
prim__collectSignal : Int -> PrimIO Int
%foreign signalFFI "handle_next_collected_signal"
prim__handleNextCollectedSignal : PrimIO Int
%foreign signalFFI "send_signal"
prim__sendSignal : Int -> Int -> PrimIO Int
%foreign signalFFI "raise_signal"
prim__raiseSignal : Int -> PrimIO Int
%foreign "C:idris2_getErrno, libidris2_support, idris_support.h"
prim__getErrorNo : PrimIO Int
||| An Error represented by a code. See
||| relevant `errno` documentation.
||| https://man7.org/linux/man-pages/man3/errno.3.html
public export
data SignalError = Error Int
getError : HasIO io => io SignalError
getError = Error <$> primIO prim__getErrorNo
isError : Int -> Bool
isError (-1) = True
isError _ = False
||| Ignore the given signal.
||| Be careful doing this, as most signals have useful
||| default behavior -- you might want to set the signal
||| to its default behavior instead with `defaultSignal`.
export
ignoreSignal : HasIO io => Signal -> io (Either SignalError ())
ignoreSignal sig = do
res <- primIO $ prim__ignoreSignal (signalCode sig)
case isError res of
False => pure $ Right ()
True => Left <$> getError
||| Use the default handler for the given signal.
||| You can use this function to unset custom
||| handling of a signal.
export
defaultSignal : HasIO io => Signal -> io (Either SignalError ())
defaultSignal sig = do
res <- primIO $ prim__defaultSignal (signalCode sig)
case isError res of
False => pure $ Right ()
True => Left <$> getError
||| Collect the given signal.
|||
||| This replaces the existing handling of the given signal
||| and instead results in Idris collecting occurrences of
||| the signal until you call `handleNextCollectedSignal`.
|||
||| First, call `collectSignal` for any number of signals.
||| Then, call `handleNextCollectedSignal` in each main loop
||| of your program to retrieve (and mark as handled) the next
||| signal that was collected, if any.
|||
||| Multiple signals will be collected and can then be retrieved
||| in the order they were received by multiple calls to
||| `handleNextCollectedSignal`.
|||
||| You can call `handleManyCollectedSignals` to get a List of
||| pending signals instead of retrieving them one at a time.
export
collectSignal : HasIO io => Signal -> io (Either SignalError ())
collectSignal sig = do
res <- primIO $ prim__collectSignal (signalCode sig)
case isError res of
False => pure $ Right ()
True => Left <$> getError
||| Get next collected signal under the pretense of handling it.
|||
||| Calling this "marks" the signal as handled so the next time
||| this function is called you will retrieve the next unhandled
||| signal instead of the same signal again.
|||
||| You get back Nothing if there are no pending signals.
export
handleNextCollectedSignal : HasIO io => io (Maybe Signal)
handleNextCollectedSignal =
toSignal <$> primIO prim__handleNextCollectedSignal
||| Get many collected signals and mark them as handled.
|||
||| Use `forever` as your fuel if you don't want or need to
||| retain totality. Alternatively, pick a max number to
||| retrieve and use `limit/1` as your fuel.
export
handleManyCollectedSignals : HasIO io => Fuel -> io (List Signal)
handleManyCollectedSignals Dry = pure []
handleManyCollectedSignals (More fuel) = do
Just next <- handleNextCollectedSignal
| Nothing => pure []
pure $ next :: !(handleManyCollectedSignals fuel)
||| Send a signal to the current process.
export
raiseSignal : HasIO io => Signal -> io (Either SignalError ())
raiseSignal sig = do
res <- primIO $ prim__raiseSignal (signalCode sig)
case isError res of
False => pure $ Right ()
True => Left <$> getError
namespace Posix
||| Send a signal to a POSIX process using a PID to identify the process.
export
sendSignal : HasIO io => Signal -> (pid : Int) -> io (Either SignalError ())
sendSignal sig pid = do
res <- primIO $ prim__sendSignal pid (signalCode sig)
case isError res of
False => pure $ Right ()
True => Left <$> getError

View File

@ -48,6 +48,7 @@ modules = Control.App,
Data.IOArray.Prims,
Data.IORef,
Data.List,
Data.SnocList,
Data.List.Elem,
Data.List.Views,
Data.List.Quantifiers,
@ -82,10 +83,11 @@ modules = Control.App,
Language.Reflection.TTImp,
System,
System.Concurrency,
System.Clock,
System.Concurrency,
System.Directory,
System.File,
System.FFI,
System.File,
System.Info,
System.REPL
System.REPL,
System.Signal

View File

@ -1,4 +1,4 @@
||| Utilities functions for contitionally delaying values.
||| Utilities functions for conditionally delaying values.
module Control.Delayed
||| Type-level function for a conditionally infinite type.

View File

@ -180,7 +180,7 @@ natToFinToNat (S k) (LTESucc lte) = cong S (natToFinToNat k lte)
||| as illustated by the relations with the `last` function.
public export
(+) : {m, n : Nat} -> Fin m -> Fin (S n) -> Fin (m + n)
(+) FZ y = cast (cong S $ plusCommutative n (pred m)) (weakenN (pred m) y)
(+) FZ y = coerce (cong S $ plusCommutative n (pred m)) (weakenN (pred m) y)
(+) (FS x) y = FS (x + y)
||| Multiplication of `Fin`s as bounded naturals.
@ -200,7 +200,7 @@ finToNatPlusHomo : {m, n : Nat} -> (x : Fin m) -> (y : Fin (S n)) ->
finToNat (x + y) = finToNat x + finToNat y
finToNatPlusHomo FZ _
= finToNatQuotient $ transitive
(castEq _)
(coerceEq _)
(weakenNNeutral _ _)
finToNatPlusHomo (FS x) y = cong S (finToNatPlusHomo x y)
@ -221,7 +221,7 @@ export
plusPreservesLast : (m, n : Nat) -> Fin.last {n=m} + Fin.last {n} = Fin.last
plusPreservesLast Z n
= homoPointwiseIsEqual $ transitive
(castEq _)
(coerceEq _)
(weakenNNeutral _ _)
plusPreservesLast (S m) n = cong FS (plusPreservesLast m n)
@ -238,7 +238,7 @@ multPreservesLast (S m) n = Calc $
export
plusSuccRightSucc : {m, n : Nat} -> (left : Fin m) -> (right : Fin (S n)) ->
FS (left + right) ~~~ left + FS right
plusSuccRightSucc FZ right = FS $ congCast reflexive
plusSuccRightSucc FZ right = FS $ congCoerce reflexive
plusSuccRightSucc (FS left) right = FS $ plusSuccRightSucc left right
-- Relations to `Fin`-specific `shift` and `weaken`
@ -247,7 +247,7 @@ export
shiftAsPlus : {m, n : Nat} -> (k : Fin (S m)) ->
shift n k ~~~ last {n} + k
shiftAsPlus {n=Z} k =
symmetric $ transitive (castEq _) (weakenNNeutral _ _)
symmetric $ transitive (coerceEq _) (weakenNNeutral _ _)
shiftAsPlus {n=S n} k = FS (shiftAsPlus k)
export
@ -267,15 +267,15 @@ weakenNOfPlus :
{m, n : Nat} -> (k : Fin m) -> (l : Fin (S n)) ->
weakenN w (k + l) ~~~ weakenN w k + l
weakenNOfPlus FZ l
= transitive (congWeakenN (castEq _))
= transitive (congWeakenN (coerceEq _))
$ transitive (weakenNPlusHomo l)
$ symmetric (castEq _)
$ symmetric (coerceEq _)
weakenNOfPlus (FS k) l = FS (weakenNOfPlus k l)
-- General addition properties (continued)
export
plusZeroLeftNeutral : (k : Fin (S n)) -> FZ + k ~~~ k
plusZeroLeftNeutral k = transitive (castEq _) (weakenNNeutral _ k)
plusZeroLeftNeutral k = transitive (coerceEq _) (weakenNNeutral _ k)
export
congPlusLeft : {m, n, p : Nat} -> {k : Fin m} -> {l : Fin n} ->

View File

@ -23,6 +23,7 @@ data StringIterator : String -> Type where [external]
-- to avoid subverting the linearity guarantees of withString.
%foreign
"scheme:blodwen-string-iterator-new"
"C:stringIteratorNew"
"javascript:stringIterator:new"
private
fromString : (str : String) -> StringIterator str
@ -37,6 +38,7 @@ withString str f = f (fromString str)
||| iterator `it`
%foreign
"scheme:blodwen-string-iterator-to-string"
"C:stringIteratorToString"
"javascript:stringIterator:toString"
export
withIteratorString : (str : String)
@ -61,6 +63,7 @@ data UnconsResult : String -> Type where
-- (e.g. byte offset into an UTF-8 string).
%foreign
"scheme:blodwen-string-iterator-next"
"C:stringIteratorNext"
"javascript:stringIterator:next"
export
uncons : (str : String) -> (1 it : StringIterator str) -> UnconsResult str

View File

@ -0,0 +1,23 @@
||| Additional functions about vectors
module Data.Vect.Extra
import Data.Vect
import Data.Fin
import Data.Vect.Elem
||| Version of `map` with access to the current position
public export
mapWithPos : (f : Fin n -> a -> b) -> Vect n a -> Vect n b
mapWithPos f [] = []
mapWithPos f (x :: xs) = f 0 x :: mapWithPos (f . FS) xs
||| Version of `map` with runtime-irrelevant information that the
||| argument is an element of the vector
public export
mapWithElem : (xs : Vect n a)
-> (f : (x : a) -> (0 pos : x `Elem` xs) -> b)
-> Vect n b
mapWithElem [] f = []
mapWithElem (x :: xs) f
= f x Here :: mapWithElem xs
(\x,pos => f x (There pos))

View File

@ -0,0 +1,8 @@
||| Additional properties and lemmata to do with Vect
module Data.Vect.Properties
import public Data.Vect.Properties.Tabulate
import public Data.Vect.Properties.Index
import public Data.Vect.Properties.Foldr
import public Data.Vect.Properties.Map
import public Data.Vect.Properties.Fin

View File

@ -0,0 +1,44 @@
module Data.Vect.Properties.Fin
import Data.Vect
import Data.Vect.Elem
import Data.Vect.Extra
import Data.Fin
import Data.Nat
||| Witnesses non-empty runtime-irrelevant vectors. Analogous to Data.List.NonEmpty
public export
data NonEmpty : Vect n a -> Type where
IsNonEmpty : NonEmpty (x :: xs)
||| eta-law (extensionality) of head-tail cons
export
etaCons : (xs : Vect (S n) a) -> head xs :: tail xs = xs
etaCons (x :: xs) = Refl
||| Inhabitants of `Fin n` witness `NonZero n`
export
finNonZero : Fin n -> NonZero n
finNonZero FZ = SIsNonZero
finNonZero (FS i) = SIsNonZero
||| Inhabitants of `Fin n` witness runtime-irrelevant vectors of length `n` aren't empty
export
finNonEmpty : (0 xs : Vect n a) -> NonZero n -> NonEmpty xs
finNonEmpty xs SIsNonZero = replace {p = NonEmpty} (etaCons xs) IsNonEmpty
||| Cast an index into a runtime-irrelevant `Vect` into the position
||| of the corresponding element
public export
finToElem : (0 xs : Vect n a) -> (i : Fin n) -> (index i xs) `Elem` xs
finToElem {n } xs i with (finNonEmpty xs $ finNonZero i)
finToElem {n = S n} (x :: xs) FZ | IsNonEmpty = Here
finToElem {n = S n} (x :: xs) (FS i) | IsNonEmpty = There (finToElem xs i)
||| Analogus to `indexNaturality`, but morhisms can (irrelevantly) know the context
export
indexNaturalityWithElem : (i : Fin n) -> (xs : Vect n a) -> (f : (x : a) -> (0 pos : x `Elem` xs) -> b)
-> index i (mapWithElem xs f) = f (index i xs) (finToElem xs i)
indexNaturalityWithElem {n } i xs f with (finNonEmpty xs (finNonZero i))
indexNaturalityWithElem {n = _} FZ (x :: xs) f | IsNonEmpty = Refl
indexNaturalityWithElem {n = _} (FS i) (x :: xs) f | IsNonEmpty = indexNaturalityWithElem i xs _

View File

@ -0,0 +1,120 @@
|||
|||
||| foldr is the unique solution to the equation:
|||
||| h f e [] = e
||| h f e (x :: xs) = x `h` (foldr f e xs)
|||
||| (This fact is called 'the universal property of foldr'.)
|||
||| Since the prelude defines foldr tail-recursively, this fact isn't immediate
||| and we need some lemmata to prove it.
module Data.Vect.Properties.Foldr
import Data.Vect
import Data.Vect.Elem
import Data.Fin
import Data.Nat
import Data.Nat.Order
import Syntax.PreorderReasoning
import Syntax.PreorderReasoning.Generic
import Decidable.Order
||| A function H : forall n. Vect n A -> B preserving the structure of vectors over A
public export
record VectHomomorphismProperty {0 A, B : Type} (F : A -> B -> B) (E : B) (H : forall n . Vect n A -> B) where
constructor ShowVectHomomorphismProperty
nil : H [] = E
cons : {0 n : Nat} -> (x : A) -> (xs : Vect n A) -> H (x :: xs) = x `F` (H xs)
||| There is an extensionally unique function preserving the vector structure
export
nilConsInitiality :
(f : a -> b -> b) -> (e : b)
-> (h1, h2 : forall n . Vect n a -> b)
-> (prf1 : VectHomomorphismProperty f e h1)
-> (prf2 : VectHomomorphismProperty f e h2)
-> (xs : Vect n a) -> h1 xs = h2 xs
nilConsInitiality f e h1 h2 prf1 prf2 [] = Calc $
|~ h1 []
~~ e ...(prf1.nil)
~~ h2 [] ...(sym prf2.nil)
nilConsInitiality f e h1 h2 prf1 prf2 (x :: xs) = Calc $
|~ h1 (x :: xs)
~~ (x `f` (h1 xs)) ...(prf1.cons _ _)
~~ (x `f` (h2 xs)) ...(cong (x `f`) $ nilConsInitiality f e h1 h2 prf1 prf2 xs)
~~ h2 (x :: xs) ...(sym $ prf2.cons _ _)
||| extensionality is a congruence with respect to Data.Vect.foldrImpl
foldrImplExtensional :
(f : a -> b -> b) -> (e : b)
-> (go1, go2 : b -> b)
-> ((y : b) -> go1 y = go2 y)
-> (xs : Vect n a)
-> foldrImpl f e go1 xs = foldrImpl f e go2 xs
foldrImplExtensional f e go1 go2 ext [] = ext e
foldrImplExtensional f e go1 go2 ext (x :: xs) =
foldrImplExtensional f e _ _
(\y => ext (f x y))
xs
||| foldrImpl f e x : (b -> -) -> - is natural
foldrImplNaturality : (f : a -> b -> b) -> (e : b) -> (xs : Vect n a) -> (go1, go2 : b -> b)
-> foldrImpl f e (go1 . go2) xs = go1 (foldrImpl f e go2 xs)
foldrImplNaturality f e [] go1 go2 = Refl
foldrImplNaturality f e (x :: xs) go1 go2 = foldrImplNaturality f e xs go1 (go2 . (f x))
||| Our tail-recursive foldr preserves the vector structure
export
foldrVectHomomorphism : VectHomomorphismProperty f e (foldr f e)
foldrVectHomomorphism = ShowVectHomomorphismProperty
{ nil = Refl
, cons = \x, xs => Calc $
|~ foldr f e (x :: xs)
~~ foldrImpl f e (id . (f x)) xs ...(Refl)
~~ foldrImpl f e ((f x) . id) xs ...(foldrImplExtensional f e _ _ (\y => Refl) xs)
~~ f x (foldrImpl f e id xs) ...(foldrImplNaturality f e xs (f x) _)
~~ f x (foldr f e xs) ...(Refl)
}
||| foldr is the unique function preserving the vector structure
export
foldrUniqueness : (h : forall n . Vect n a -> b) -> VectHomomorphismProperty f e h -> (xs : Vect n a) -> h xs = foldr f e xs
foldrUniqueness {f} h prf xs = irrelevantEq $
nilConsInitiality f e h (foldr f e) prf foldrVectHomomorphism xs
||| Each summand is `LTE` the sum
export
sumIsGTEtoParts : {x : Nat} -> (xs : Vect n Nat) -> (x `Elem` xs) -> sum xs `GTE` x
sumIsGTEtoParts (x :: xs) Here
= CalcWith $
|~ x
~~ x + 0 ...(sym $ plusZeroRightNeutral _)
<~ x + (sum xs) ...(plusLteMonotoneLeft x 0 _ LTEZero)
~~ sum (x :: xs) ...(sym $ (foldrVectHomomorphism {f = plus} {e = 0}).cons _ _)
sumIsGTEtoParts {x} (y :: xs) (There later)
= CalcWith $
|~ x
<~ sum xs ...(sumIsGTEtoParts {x} xs later)
~~ 0 + sum xs ...(Refl)
<~ y + (sum xs) ...(plusLteMonotoneRight (sum xs) 0 y LTEZero)
~~ sum (y :: xs) ...(sym $ (foldrVectHomomorphism {f = plus} {e = 0}).cons _ _)
||| `sum : Vect n Nat -> Nat` is monotone
export
sumMonotone : {n : Nat} -> (xs, ys : Vect n Nat)
-> (prf : (i : Fin n) -> index i xs `LTE` index i ys)
-> (sum xs `LTE` sum ys)
sumMonotone [] [] prf = LTEZero
sumMonotone (x :: xs) (y :: ys) prf =
let prf' = sumMonotone xs ys (\i => prf (FS i))
in CalcWith $
|~ sum (x :: xs)
~~ x + sum xs ...((foldrVectHomomorphism {f = plus} {e = 0}).cons x xs)
<~ y + sum ys ...(plusLteMonotone (prf 0) prf')
~~ sum (y :: ys) ...(sym $ (foldrVectHomomorphism {f = plus} {e = 0}).cons y ys)

View File

@ -0,0 +1,61 @@
||| Properties of Data.Vect.index
module Data.Vect.Properties.Index
import Data.Vect.Properties.Tabulate
import Data.Vect
import Data.Vect.Elem
import Data.Fin
import Syntax.PreorderReasoning
||| Recall an element by its position, as we may not have the element
||| at runtime
public export
recallElem : {xs : Vect n a} -> x `Elem` xs -> a
recallElem {xs = x :: _ } Here = x
recallElem {xs = _ :: xs} (There later) = recallElem later
||| Recalling by a position of `x` does yield `x`
export
recallElemSpec : (pos : x `Elem` xs) -> recallElem pos = x
recallElemSpec Here = Refl
recallElemSpec (There later) = recallElemSpec later
||| `index i : Vect n a -> a` is a natural transformation
export
indexNaturality : (i : Fin n) -> (f : a -> b) -> (xs : Vect n a)
-> index i (map f xs) = f (index i xs)
indexNaturality FZ f (x :: xs) = Refl
indexNaturality (FS x) f (_ :: xs) = indexNaturality x f xs
||| Replication tabulates the constant function
export
indexReplicate : (i : Fin n) -> (x : a)
-> index i (replicate n x) = x
indexReplicate FZ x = Refl
indexReplicate (FS i) x = indexReplicate i x
||| `range` tabulates the identity function (by definition)
export
indexRange : (i : Fin n) -> index i (range {len = n}) === i
indexRange i = irrelevantEq $ indexTabulate id i
||| Inductive step auxiliary lemma for indexTranspose
indexZipWith_Cons : (i : Fin n) -> (xs : Vect n a) -> (xss : Vect n (Vect m a))
-> index i (zipWith (::) xs xss)
= (index i xs) :: (index i xss)
indexZipWith_Cons FZ (x :: _ ) (xs:: _ ) = Refl
indexZipWith_Cons (FS i) (_ :: xs) (_ :: xss) = indexZipWith_Cons i xs xss
||| The `i`-th vector in a transposed matrix is the vector of `i`-th components
export
indexTranspose : (xss : Vect m (Vect n a)) -> (i : Fin n)
-> index i (transpose xss) = map (index i) xss
indexTranspose [] i = indexReplicate i []
indexTranspose (xs :: xss) i = Calc $
|~ index i (transpose (xs :: xss))
~~ index i (zipWith (::) xs (transpose xss)) ...(Refl)
~~ index i xs :: index i (transpose xss) ...(indexZipWith_Cons i xs (transpose xss))
~~ index i xs :: map (index i) xss ...(cong (index i xs ::)
$ indexTranspose xss i)

View File

@ -0,0 +1,79 @@
||| Properties of Data.Vect.map
module Data.Vect.Properties.Map
import Data.Vect.Properties.Tabulate
import Data.Vect.Properties.Index
import Data.Vect.Properties.Foldr
import Data.Vect
import Data.Vect.Elem
import Data.Fin
import Data.Vect.Extra
import Syntax.PreorderReasoning
||| `map` functoriality: identity preservation
export
mapId : (xs : Vect n a) -> map Prelude.id xs = xs
mapId xs = vectorExtensionality _ _ \i => indexNaturality _ _ _
||| `mapWtihPos f` represents post-composition the tabulated function `f`
export
indexMapWithPos : (f : Fin n -> a -> b) -> (xs : Vect n a) -> (i : Fin n)
-> index i (mapWithPos f xs) = f i (index i xs)
indexMapWithPos f (x :: _ ) FZ = Refl
indexMapWithPos f (_ :: xs) (FS i) = indexMapWithPos _ _ _
||| `tabulate : (Fin n ->) -> Vect n` is a natural transformation
export
mapTabulate : (f : a -> b) -> (g : Fin n -> a)
-> tabulate (f . g) = map f (tabulate g)
mapTabulate f g = irrelevantEq $
vectorExtensionality _ _ \i => Calc $
|~ index i (tabulate (f . g))
~~ f (g i) ...(indexTabulate _ _)
~~ f (index i $ tabulate g) ...(cong f (sym $ indexTabulate _ _))
~~ index i (map f $ tabulate g) ...(sym $ indexNaturality _ _ _)
||| Tabulating with the constant function is replication
export
tabulateConstantly : (x : a) -> Fin.tabulate {len} (const x) === replicate len x
tabulateConstantly x = irrelevantEq $
vectorExtensionality _ _ \i => Calc $
|~ index i (Fin.tabulate (const x))
~~ x ...(indexTabulate _ _)
~~ index i (replicate _ x) ...(sym $ indexReplicate _ _)
||| It's enough that two functions agree on the elements of a vector for the maps to agree
export
mapRestrictedExtensional : (f, g : a -> b) -> (xs : Vect n a)
-> (prf : (i : Fin n) -> f (index i xs) = g (index i xs))
-> map f xs = map g xs
mapRestrictedExtensional f g xs prf = vectorExtensionality _ _ \i => Calc $
|~ index i (map f xs)
~~ f (index i xs) ...( indexNaturality _ _ _)
~~ g (index i xs) ...(prf _)
~~ index i (map g xs) ...(sym $ indexNaturality _ _ _)
||| function extensionality is a congruence wrt map
export
mapExtensional : (f, g : a -> b)
-> (prf : (x : a) -> f x = g x)
-> (xs : Vect n a)
-> map f xs = map g xs
mapExtensional f g prf xs = mapRestrictedExtensional f g xs (\i => prf (index i xs))
||| map-fusion property for vectors up to function extensionality
export
mapFusion : (f : b -> c) -> (g : a -> b) -> (xs : Vect n a)
-> map f (map g xs) = map (f . g) xs
mapFusion f g [] = Refl
mapFusion f g (x :: xs) = cong (f $ g x ::) $ mapFusion f g xs
||| function extensionality is a congruence wrt mapWithElem
export
mapWithElemExtensional : (xs : Vect n a) -> (f, g : (x : a) -> (0 _ : x `Elem` xs) -> b)
-> ((x : a) -> (0 pos : x `Elem` xs) -> f x pos = g x pos)
-> mapWithElem xs f = mapWithElem xs g
mapWithElemExtensional [] f g prf = Refl
mapWithElemExtensional (x :: xs) f g prf = cong2 (::) (prf x Here) (mapWithElemExtensional xs _ _ (\x,pos => prf x (There pos)))

View File

@ -0,0 +1,37 @@
||| Tabulation gives a bijection between functions `f : Fin n -> a`
||| (up to extensional equality) and vectors `tabulate f : Vect n a`.
module Data.Vect.Properties.Tabulate
import Data.Vect
import Data.Fin
||| Vectors are uniquely determined by their elements
export
vectorExtensionality
: (xs, ys : Vect n a) -> (ext : (i : Fin n) -> index i xs = index i ys)
-> xs = ys
vectorExtensionality [] [] ext = Refl
vectorExtensionality (x :: xs) (y :: ys) ext =
cong2 (::)
(ext FZ)
(vectorExtensionality xs ys (\i => ext (FS i)))
||| Extensionally equivalent functions tabulate to the same vector
export
tabulateExtensional
: {n : Nat} -> (f, g : Fin n -> a) -> (ext : (i : Fin n) -> f i = g i)
-> tabulate f = tabulate g
tabulateExtensional {n = 0 } f g ext = Refl
tabulateExtensional {n = S n} f g ext =
cong2 (::) (ext FZ) (tabulateExtensional (f . FS) (g . FS) (\ i => ext $ FS i))
||| Taking an index amounts to applying the tabulated function
export
indexTabulate : {n : Nat} -> (f : Fin n -> a) -> (i : Fin n) -> index i (tabulate f) = f i
indexTabulate f FZ = Refl
indexTabulate f (FS i) = indexTabulate (f . FS) i
||| The empty vector represents the unique function `Fin 0 -> a`
export
emptyInitial : (v : Vect 0 a) -> v = []
emptyInitial [] = Refl

View File

@ -113,7 +113,13 @@ modules = Control.ANSI,
Data.Validated,
Data.Vect.Binary,
Data.Vect.Properties,
Data.Vect.Properties.Tabulate,
Data.Vect.Properties.Index,
Data.Vect.Properties.Foldr,
Data.Vect.Properties.Map,
Data.Vect.Properties.Fin,
Data.Vect.Extra,
Data.Vect.Sort,
Data.Void,

View File

@ -7,146 +7,146 @@ import Network.Socket.Data
-- From sys/socket.h
%foreign "C:close,libidris2_support"
%foreign "C:close, libc 6"
export
prim__socket_close : (sockdes : SocketDescriptor) -> PrimIO Int
%foreign "C:listen,libc 6"
%foreign "C:listen, libc 6"
export
prim__socket_listen : (sockfd : SocketDescriptor) -> (backlog : Int) -> PrimIO Int
-- From idris_net.h
%foreign "C:idrnet_socket,libidris2_support"
%foreign "C:idrnet_socket, libidris2_support, idris_net.h"
export
prim__idrnet_socket : (domain, type, protocol : Int) -> PrimIO Int
%foreign "C:idrnet_bind,libidris2_support"
%foreign "C:idrnet_bind, libidris2_support, idris_net.h"
export
prim__idrnet_bind : (sockfd : SocketDescriptor) -> (family, socket_type : Int) ->
(host : String) -> (port : Port) -> PrimIO Int
%foreign "C:idrnet_connect,libidris2_support"
%foreign "C:idrnet_connect, libidris2_support, idris_net.h"
export
prim__idrnet_connect : (sockfd : SocketDescriptor) -> (family, socket_type : Int) ->
(host : String) -> (port : Port) -> PrimIO Int
%foreign "C:idrnet_sockaddr_family,libidris2_support"
%foreign "C:idrnet_sockaddr_family, libidris2_support, idris_net.h"
export
prim__idrnet_sockaddr_family : (sockaddr : AnyPtr) -> PrimIO Int
%foreign "C:idrnet_sockaddr_ipv4,libidris2_support"
%foreign "C:idrnet_sockaddr_ipv4, libidris2_support, idris_net.h"
export
prim__idrnet_sockaddr_ipv4 : (sockaddr : AnyPtr) -> PrimIO String
%foreign "C:idrnet_sockaddr_unix,libidris2_support"
%foreign "C:idrnet_sockaddr_unix, libidris2_support, idris_net.h"
export
prim__idrnet_sockaddr_unix : (sockaddr : AnyPtr) -> PrimIO String
%foreign "C:idrnet_sockaddr_ipv4_port,libidris2_support"
%foreign "C:idrnet_sockaddr_ipv4_port, libidris2_support, idris_net.h"
export
prim__idrnet_sockaddr_ipv4_port : (sockaddr : AnyPtr) -> PrimIO Int
%foreign "C:idrnet_sockaddr_port,libidris2_support"
%foreign "C:idrnet_sockaddr_port, libidris2_support, idris_net.h"
export
prim__idrnet_sockaddr_port : (sockfd : SocketDescriptor) -> PrimIO Int
%foreign "C:idrnet_create_sockaddr,libidris2_support"
%foreign "C:idrnet_create_sockaddr, libidris2_support, idris_net.h"
export
prim__idrnet_create_sockaddr : PrimIO AnyPtr
%foreign "C:idrnet_accept,libidris2_support"
%foreign "C:idrnet_accept, libidris2_support, idris_net.h"
export
prim__idrnet_accept : (sockfd : SocketDescriptor) -> (sockaddr : AnyPtr) -> PrimIO Int
%foreign "C:idrnet_send,libidris2_support"
%foreign "C:idrnet_send, libidris2_support, idris_net.h"
export
prim__idrnet_send : (sockfd : SocketDescriptor) -> (dataString : String) -> PrimIO Int
%foreign "C:idrnet_send_buf,libidris2_support"
%foreign "C:idrnet_send_buf, libidris2_support, idris_net.h"
export
prim__idrnet_send_buf : (sockfd : SocketDescriptor) -> (dataBuffer : AnyPtr) -> (len : Int) -> PrimIO Int
%foreign "C:idrnet_recv,libidris2_support"
%foreign "C:idrnet_recv, libidris2_support, idris_net.h"
export
prim__idrnet_recv : (sockfd : SocketDescriptor) -> (len : Int) -> PrimIO AnyPtr
%foreign "C:idrnet_recv_buf,libidris2_support"
%foreign "C:idrnet_recv_buf, libidris2_support, idris_net.h"
export
prim__idrnet_recv_buf : (sockfd : SocketDescriptor) -> (buf : AnyPtr) -> (len : Int) -> PrimIO Int
%foreign "C:idrnet_sendto,libidris2_support"
%foreign "C:idrnet_sendto, libidris2_support, idris_net.h"
export
prim__idrnet_sendto : (sockfd : SocketDescriptor) -> (dataString,host : String) ->
(port : Port) -> (family : Int) -> PrimIO Int
%foreign "C:idrnet_sendto_buf,libidris2_support"
%foreign "C:idrnet_sendto_buf, libidris2_support, idris_net.h"
export
prim__idrnet_sendto_buf : (sockfd : SocketDescriptor) -> (dataBuf : AnyPtr) ->
(buf_len : Int) -> (host : String) -> (port : Port) ->
(family : Int) -> PrimIO Int
%foreign "C:idrnet_recvfrom,libidris2_support"
%foreign "C:idrnet_recvfrom, libidris2_support, idris_net.h"
export
prim__idrnet_recvfrom : (sockfd : SocketDescriptor) -> (len : Int) -> PrimIO AnyPtr
%foreign "C:idrnet_recvfrom_buf,libidris2_support"
%foreign "C:idrnet_recvfrom_buf, libidris2_support, idris_net.h"
export
prim__idrnet_recvfrom_buf : (sockfd : SocketDescriptor) -> (buf : AnyPtr) -> (len : Int) -> PrimIO AnyPtr
%foreign "C:idrnet_get_recv_res,libidris2_support"
%foreign "C:idrnet_get_recv_res, libidris2_support, idris_net.h"
export
prim__idrnet_get_recv_res : (res_struct : AnyPtr) -> PrimIO Int
%foreign "C:idrnet_get_recv_payload,libidris2_support"
%foreign "C:idrnet_get_recv_payload, libidris2_support, idris_net.h"
export
prim__idrnet_get_recv_payload : (res_struct : AnyPtr) -> PrimIO String
%foreign "C:idrnet_free_recv_struct,libidris2_support"
%foreign "C:idrnet_free_recv_struct, libidris2_support, idris_net.h"
export
prim__idrnet_free_recv_struct : (res_struct : AnyPtr) -> PrimIO ()
%foreign "C:idrnet_get_recvfrom_res,libidris2_support"
%foreign "C:idrnet_get_recvfrom_res, libidris2_support, idris_net.h"
export
prim__idrnet_get_recvfrom_res : (res_struct : AnyPtr) -> PrimIO Int
%foreign "C:idrnet_get_recvfrom_payload,libidris2_support"
%foreign "C:idrnet_get_recvfrom_payload, libidris2_support, idris_net.h"
export
prim__idrnet_get_recvfrom_payload : (res_struct : AnyPtr) -> PrimIO String
%foreign "C:idrnet_get_recvfrom_sockaddr,libidris2_support"
%foreign "C:idrnet_get_recvfrom_sockaddr, libidris2_support, idris_net.h"
export
prim__idrnet_get_recvfrom_sockaddr : (res_struct : AnyPtr) -> PrimIO AnyPtr
%foreign "C:idrnet_free_recvfrom_struct,libidris2_support"
%foreign "C:idrnet_free_recvfrom_struct, libidris2_support, idris_net.h"
export
prim__idrnet_free_recvfrom_struct : (res_struct : AnyPtr) -> PrimIO ()
%foreign "C:idrnet_geteagain,libidris2_support"
%foreign "C:idrnet_geteagain, libidris2_support, idris_net.h"
export
prim__idrnet_geteagain : PrimIO Int
%foreign "C:idrnet_errno,libidris2_support"
%foreign "C:idrnet_errno, libidris2_support, idris_net.h"
export
prim__idrnet_errno : PrimIO Int
%foreign "C:idrnet_malloc,libidris2_support"
%foreign "C:idrnet_malloc, libidris2_support, idris_net.h"
export
prim__idrnet_malloc : (size : Int) -> PrimIO AnyPtr
%foreign "C:idrnet_free,libidris2_support"
%foreign "C:idrnet_free, libidris2_support, idris_net.h"
export
prim__idrnet_free : (ptr : AnyPtr) -> PrimIO ()
%foreign "C:idrnet_peek,libidris2_support"
%foreign "C:idrnet_peek, libidris2_support, idris_net.h"
export
prim__idrnet_peek : (ptr : AnyPtr) -> (offset : {-Unsigned-} Int) -> PrimIO {-Unsigned-} Int
%foreign "C:idrnet_poke,libidris2_support"
%foreign "C:idrnet_poke, libidris2_support, idris_net.h"
export
prim__idrnet_poke : (ptr : AnyPtr) -> (offset : {-Unsigned-} Int) ->
(val : Int {- should be Char? -}) -> PrimIO ()

View File

@ -48,7 +48,7 @@ BACKLOG : Int
BACKLOG = 20
-- Repeat to avoid a dependency cycle
%foreign "C:idrnet_geteagain,libidris2_support"
%foreign "C:idrnet_geteagain, libidris2_support, idris_net.h"
prim__idrnet_geteagain : PrimIO Int
export
@ -61,10 +61,10 @@ EAGAIN =
-- ---------------------------------------------------------------- [ Error Code ]
-- repeat without export to avoid dependency cycles
%foreign "C:idrnet_errno,libidris2_support"
%foreign "C:idrnet_errno, libidris2_support, idris_net.h"
prim__idrnet_errno : PrimIO Int
%foreign "C:isNull,libidris2_support"
%foreign "C:isNull, libidris2_support, idris_support.h"
prim__idrnet_isNull : (ptr : AnyPtr) -> PrimIO Int
@ -113,16 +113,16 @@ Show SocketFamily where
-- This is a bit of a hack to get the OS-dependent magic constants out of C and
-- into Idris without having to faff around on the preprocessor on the Idris
-- side.
%foreign "C:idrnet_af_unspec,libidris2_support"
%foreign "C:idrnet_af_unspec, libidris2_support, idris_net.h"
prim__idrnet_af_unspec : PrimIO Int
%foreign "C:idrnet_af_unix,libidris2_support"
%foreign "C:idrnet_af_unix, libidris2_support, idris_net.h"
prim__idrnet_af_unix : PrimIO Int
%foreign "C:idrnet_af_inet,libidris2_support"
%foreign "C:idrnet_af_inet, libidris2_support, idris_net.h"
prim__idrnet_af_inet : PrimIO Int
%foreign "C:idrnet_af_inet6,libidris2_support"
%foreign "C:idrnet_af_inet6, libidris2_support, idris_net.h"
prim__idrnet_af_inet6 : PrimIO Int
export

View File

@ -169,3 +169,14 @@ data List a =
(::) a (List a)
%name List xs, ys, zs
||| Snoc lists.
public export
data SnocList a =
||| Empty snoc-list
Lin
| ||| A non-empty snoc-list, consisting of the rest of the snoc-list and the final element.
(:<) (SnocList a) a
%name SnocList sx, sy, sz

View File

@ -69,7 +69,7 @@ export
onCollect : Ptr t -> (Ptr t -> IO ()) -> IO (GCPtr t)
onCollect ptr c = fromPrim (prim__onCollect ptr (\x => toPrim (c x)))
%foreign "C:idris2_getString, libidris2_support"
%foreign "C:idris2_getString, libidris2_support, idris_support.h"
"javascript:lambda:x=>x"
export
prim__getString : Ptr String -> String
@ -79,11 +79,11 @@ prim__putChar : Char -> (1 x : %World) -> IORes ()
%foreign "C:getchar,libc 6"
%extern prim__getChar : (1 x : %World) -> IORes Char
%foreign "C:idris2_getStr,libidris2_support"
%foreign "C:idris2_getStr, libidris2_support, idris_support.h"
"node:support:getStr,support_system_file"
prim__getStr : PrimIO String
%foreign "C:idris2_putStr,libidris2_support"
%foreign "C:idris2_putStr, libidris2_support, idris_support.h"
"node:lambda:x=>process.stdout.write(x)"
prim__putStr : String -> PrimIO ()
@ -133,7 +133,7 @@ export
threadWait : (1 threadID : ThreadID) -> IO ()
threadWait threadID = fromPrim (prim__threadWait threadID)
%foreign "C:idris2_readString, libidris2_support"
%foreign "C:idris2_readString, libidris2_support, idris_support.h"
export
prim__getErrno : Int

View File

@ -11,6 +11,7 @@ infixr 4 ||
-- List and String operators
infixr 7 ::, ++
infixl 7 :<
-- Functor/Applicative/Monad/Algebra operators
infixl 1 >>=, =<<, >>, >=>, <=<, <&>

View File

@ -416,6 +416,7 @@ Traversable List where
-- If you need to concatenate strings at compile time, use Prelude.concat.
%foreign
"scheme:string-concat"
"C:fastConcat"
"javascript:lambda:(xs)=>''.concat(...__prim_idris2js_array(xs))"
export
fastConcat : List String -> String
@ -543,6 +544,7 @@ pack (x :: xs) = strCons x (pack xs)
%foreign
"scheme:string-pack"
"C:fastPack"
"javascript:lambda:(xs)=>''.concat(...__prim_idris2js_array(xs))"
export
fastPack : List Char -> String
@ -569,6 +571,7 @@ unpack str = unpack' (prim__cast_IntegerInt (natToInteger (length str)) - 1) str
-- If you need to unpack strings at compile time, use Prelude.unpack.
%foreign
"scheme:string-unpack"
"C:fastUnpack"
"javascript:lambda:(str)=>__prim_js2idris_array(Array.from(str))"
export
fastUnpack : String -> List Char

View File

@ -70,12 +70,12 @@ export %inline
toPrim : (1 act : IO a) -> PrimIO a
toPrim (MkIO fn) = fn
%foreign "C:idris2_isNull, libidris2_support"
%foreign "C:idris2_isNull, libidris2_support, idris_support.h"
"javascript:lambda:x=>x===undefined||x===null?1n:0n"
export
prim__nullAnyPtr : AnyPtr -> Int
%foreign "C:idris2_getNull,libidris2_support"
%foreign "C:idris2_getNull, libidris2_support, idris_support.h"
export
prim__getNullAnyPtr : AnyPtr

View File

@ -609,6 +609,10 @@ nfToCFType _ _ (NPrimVal _ Bits8Type) = pure CFUnsigned8
nfToCFType _ _ (NPrimVal _ Bits16Type) = pure CFUnsigned16
nfToCFType _ _ (NPrimVal _ Bits32Type) = pure CFUnsigned32
nfToCFType _ _ (NPrimVal _ Bits64Type) = pure CFUnsigned64
nfToCFType _ _ (NPrimVal _ Int8Type) = pure CFInt8
nfToCFType _ _ (NPrimVal _ Int16Type) = pure CFInt16
nfToCFType _ _ (NPrimVal _ Int32Type) = pure CFInt32
nfToCFType _ _ (NPrimVal _ Int64Type) = pure CFInt64
nfToCFType _ False (NPrimVal _ StringType) = pure CFString
nfToCFType fc True (NPrimVal _ StringType)
= throw (GenericMsg fc "String not allowed in a foreign struct")

View File

@ -33,7 +33,7 @@ compileCObjectFile {asLibrary} sourceFile objectFile =
let libraryFlag = if asLibrary then "-fpic " else ""
let runccobj = cc ++ " -c " ++ libraryFlag ++ sourceFile ++
let runccobj = cc ++ " -Werror -c " ++ libraryFlag ++ sourceFile ++
" -o " ++ objectFile ++ " " ++
"-I" ++ fullprefix_dir dirs "refc " ++
"-I" ++ fullprefix_dir dirs "include"
@ -56,12 +56,13 @@ compileCFile {asShared} objectFile outFile =
let sharedFlag = if asShared then "-shared " else ""
let runcc = cc ++ " " ++ sharedFlag ++ objectFile ++
let runcc = cc ++ " -Werror " ++ sharedFlag ++ objectFile ++
" -o " ++ outFile ++ " " ++
fullprefix_dir dirs "lib" </> "libidris2_support.a" ++ " " ++
"-lidris2_refc " ++
"-L" ++ fullprefix_dir dirs "refc " ++
clibdirs (lib_dirs dirs)
clibdirs (lib_dirs dirs) ++
"-lm"
log "compiler.refc.cc" 10 runcc
0 <- coreLift $ system runcc

View File

@ -14,6 +14,7 @@ import Data.List
import Libraries.Data.DList
import Data.Nat
import Data.Strings
import Libraries.Data.SortedSet
import Data.Vect
import System
@ -74,49 +75,15 @@ cName n = assert_total $ idris_crash ("INTERNAL ERROR: Unsupported name in C bac
-- not really total but this way this internal error does not contaminate everything else
escapeChar : Char -> String
escapeChar '\DEL' = "127"
escapeChar '\NUL' = "0"
escapeChar '\SOH' = "1"
escapeChar '\STX' = "2"
escapeChar '\ETX' = "3"
escapeChar '\EOT' = "4"
escapeChar '\ENQ' = "5"
escapeChar '\ACK' = "6"
escapeChar '\BEL' = "7"
escapeChar '\BS' = "8"
escapeChar '\HT' = "9"
escapeChar '\LF' = "10"
escapeChar '\VT' = "11"
escapeChar '\FF' = "12"
escapeChar '\CR' = "13"
escapeChar '\SO' = "14"
escapeChar '\SI' = "15"
escapeChar '\DLE' = "16"
escapeChar '\DC1' = "17"
escapeChar '\DC2' = "18"
escapeChar '\DC3' = "19"
escapeChar '\DC4' = "20"
escapeChar '\NAK' = "21"
escapeChar '\SYN' = "22"
escapeChar '\ETB' = "23"
escapeChar '\CAN' = "24"
escapeChar '\EM' = "25"
escapeChar '\SUB' = "26"
escapeChar '\ESC' = "27"
escapeChar '\FS' = "28"
escapeChar '\GS' = "29"
escapeChar '\RS' = "30"
escapeChar '\US' = "31"
escapeChar c = show c
-- escapeChar '\\' = "'\\\\'"
-- escapeChar c = show c
escapeChar c = if isAlphaNum c || isNL c
then show c
else "(char)" ++ show (ord c)
cStringQuoted : String -> String
cStringQuoted cs = strCons '"' (showCString (unpack cs) "\"")
where
showCChar : Char -> String -> String
showCChar '\\' = ("bkslash" ++)
showCChar '\\' = ("\\\\" ++)
showCChar c
= if c < chr 32
then (("\\x" ++ leftPad '0' 2 (asHex (cast c))) ++ "\"\"" ++)
@ -131,12 +98,11 @@ where
cConstant : Constant -> String
cConstant (I x) = "(Value*)makeInt32("++ show x ++")" -- (constant #:type 'i32 #:val " ++ show x ++ ")"
cConstant (BI x) = "(Value*)makeInt64("++ show x ++")" --"(constant #:type 'i64 #:val " ++ show x ++ ")"
cConstant (Db x) = "(Value*)makeDouble("++ show x ++")"--"(constant #:type 'double #:val " ++ show x ++ ")"
cConstant (Ch x) = "(Value*)makeChar("++ escapeChar x ++")" --"(constant #:type 'char #:val " ++ escapeChar x ++ ")"
cConstant (I x) = "(Value*)makeInt32("++ show x ++")"
cConstant (BI x) = "(Value*)makeInt64("++ show x ++")"
cConstant (Db x) = "(Value*)makeDouble("++ show x ++")"
cConstant (Ch x) = "(Value*)makeChar("++ escapeChar x ++")"
cConstant (Str x) = "(Value*)makeString("++ cStringQuoted x ++")"
-- = "(constant #:type 'string #:val " ++ cStringQuoted x ++ ")"
cConstant WorldVal = "(Value*)makeWorld()"
cConstant IntType = "i32"
cConstant IntegerType = "i64"
@ -144,10 +110,10 @@ cConstant StringType = "string"
cConstant CharType = "char"
cConstant DoubleType = "double"
cConstant WorldType = "f32"
cConstant (B8 x) = "(Value*)makeInt8("++ show x ++")" --"(constant #:type 'i64 #:val " ++ show x ++ ")"
cConstant (B16 x) = "(Value*)makeInt16("++ show x ++")" --"(constant #:type 'i64 #:val " ++ show x ++ ")"
cConstant (B32 x) = "(Value*)makeInt32("++ show x ++")" --"(constant #:type 'i64 #:val " ++ show x ++ ")"
cConstant (B64 x) = "(Value*)makeInt64("++ show x ++")" --"(constant #:type 'i64 #:val " ++ show x ++ ")"
cConstant (B8 x) = "(Value*)makeInt8("++ show x ++")"
cConstant (B16 x) = "(Value*)makeInt16("++ show x ++")"
cConstant (B32 x) = "(Value*)makeInt32("++ show x ++")"
cConstant (B64 x) = "(Value*)makeInt64("++ show x ++")"
cConstant Bits8Type = "Bits8"
cConstant Bits16Type = "Bits16"
cConstant Bits32Type = "Bits32"
@ -165,8 +131,8 @@ extractConstant (B8 x) = show x
extractConstant (B16 x) = show x
extractConstant (B32 x) = show x
extractConstant (B64 x) = show x
extractConstant c = "unable_to_extract constant >>" ++ cConstant c ++ "<<"
extractConstant c = assert_total $ idris_crash ("INTERNAL ERROR: Unable to extract constant: " ++ cConstant c)
-- not really total but this way this internal error does not contaminate everything else
||| Generate scheme for a plain function.
plainOp : String -> List String -> String
@ -212,7 +178,7 @@ cOp StrIndex [x, i] = "strIndex(" ++ x ++ ", " ++ i ++ ")"
cOp StrCons [x, y] = "strCons(" ++ x ++ ", " ++ y ++ ")"
cOp StrAppend [x, y] = "strAppend(" ++ x ++ ", " ++ y ++ ")"
cOp StrSubstr [x, y, z] = "strSubstr(" ++ x ++ ", " ++ y ++ ", " ++ z ++ ")"
cOp BelieveMe [_, _, x] = x
cOp BelieveMe [_, _, x] = "newReference(" ++ x ++ ")"
cOp Crash [_, msg] = "idris2_crash(" ++ msg ++ ");"
cOp fn args = plainOp (show fn) (toList args)
@ -262,7 +228,8 @@ toPrim pn@(NS _ n)
(n == UN "prim__onCollectAny", OnCollectAny)
]
(Unknown pn)
toPrim pn = Unknown pn -- todo: crash rather than generate garbage?
toPrim pn = assert_total $ idris_crash ("INTERNAL ERROR: Unknown primitive: " ++ cName pn)
-- not really total but this way this internal error does not contaminate everything else
varName : AVar -> String
@ -273,7 +240,7 @@ data ArgCounter : Type where
data FunctionDefinitions : Type where
data TemporaryVariableTracker : Type where
data IndentLevel : Type where
data ExternalLibs : Type where
data HeaderFiles : Type where
------------------------------------------------------------------------
-- Output generation: using a difference list for efficient append
@ -371,15 +338,12 @@ freeTmpVars = do
[] => pure ()
addExternalLib : {auto e : Ref ExternalLibs (List String)}
-> String
-> Core ()
addExternalLib extLib = do
libs <- get ExternalLibs
case elem extLib libs of
True => pure () -- library already in list
False => do
put ExternalLibs (extLib :: libs)
addHeader : {auto h : Ref HeaderFiles (SortedSet String)}
-> String
-> Core ()
addHeader header = do
headerFiles <- get HeaderFiles
put HeaderFiles $ insert header headerFiles
@ -432,14 +396,6 @@ cArgsVectANF : {0 arity : Nat} -> Vect arity AVar -> Core (Vect arity String)
cArgsVectANF [] = pure []
cArgsVectANF (x :: xs) = pure $ (varName x) :: !(cArgsVectANF xs)
showEitherStringInt : Either String Int -> String
showEitherStringInt (Left s) = s
showEitherStringInt (Right i) = show i
toIntEitherStringInt : Either String Int -> Int -> Int
toIntEitherStringInt (Left s) k = k
toIntEitherStringInt (Right i) _ = i
integer_switch : List AConstAlt -> Bool
integer_switch [] = True
integer_switch (MkAConstAlt c _ :: _) =
@ -489,7 +445,6 @@ mutual
-> Core $ ()
copyConstructors _ [] _ _ _ = pure ()
copyConstructors sc ((MkAConAlt n _ mTag args body) :: xs) constrFieldVar retValVar k = do
--(restConstructionCopy, restBody) <- copyConstructors sc xs constrFieldVar retValVar (S k)
(tag', name') <- getNameTag mTag n
emit EmptyFC $ constrFieldVar ++ "[" ++ show k ++ "].tag = " ++ tag' ++ ";"
emit EmptyFC $ constrFieldVar ++ "[" ++ show k ++ "].name = " ++ name' ++ ";"
@ -647,7 +602,6 @@ mutual
let returnLine = "(Value*)makeClosureFromArglist(" ++ f_ptr_name ++ ", " ++ arglist ++ ")"
pure $ MkRS returnLine returnLine
cStatementsFromANF (AApp fc _ closure arg) =
-- pure $ "apply_closure(" ++ varName closure ++ ", " ++ varName arg ++ ")"
pure $ MkRS ("apply_closure(" ++ varName closure ++ ", " ++ varName arg ++ ")")
("tailcall_apply_closure(" ++ varName closure ++ ", " ++ varName arg ++ ")")
cStatementsFromANF (ALet fc var value body) = do
@ -669,8 +623,6 @@ mutual
fillConstructorArgs constr args 0
pure $ MkRS ("(Value*)" ++ constr) ("(Value*)" ++ constr)
--fillingStatements <- fillConstructorArgs constr args 0
--pure $ (statement1 :: fillingStatements, "(Value*)" ++ constr ++ ";")
cStatementsFromANF (AOp fc _ op args) = do
argsVec <- cArgsVectANF args
let opStatement = cOp op argsVec
@ -708,15 +660,11 @@ mutual
increaseIndentation
newTemporaryVariableLevel
defaultAssignment <- cStatementsFromANF d
-- traverse_ (\l => emit EmptyFC (l) ) defaultBody
emit EmptyFC $ switchReturnVar ++ " = " ++ nonTailCall defaultAssignment ++ ";"
freeTmpVars
decreaseIndentation
emit EmptyFC $ " }"
emit EmptyFC $ "}"
-- let defaultBlock = []
-- ++ (map (\s => s) defaultBody)
-- ++ [defaultLastLine1, defaultLastLine2]
emit EmptyFC $ "free(" ++ constructorField ++ ");"
pure $ MkRS switchReturnVar switchReturnVar
cStatementsFromANF (AConstCase fc sc alts def) = do
@ -748,25 +696,6 @@ mutual
readCCPart : Char -> String -> (String, String)
readCCPart b x =
let (cc, def) = break (== b) x
in (cc, drop 1 def)
where
drop : Int -> String -> String
drop headLength s =
let len = cast (length s)
subStrLen = len - headLength in
strSubstr headLength subStrLen s
extractFFILocation : (lang:String) -> List String -> Maybe (String, String)
extractFFILocation targetLang [] = Nothing
extractFFILocation targetLang (def :: defs) =
let (thisLang,pos) = readCCPart ':' def in
case targetLang == thisLang of
True => Just (readCCPart ',' pos)
False => extractFFILocation targetLang defs
addCommaToList : List String -> List String
addCommaToList [] = []
addCommaToList (x :: xs) = (" " ++ x) :: map (", " ++) xs
@ -789,24 +718,25 @@ getArgsNrList [] _ = []
getArgsNrList (x :: xs) k = k :: getArgsNrList xs (S k)
cTypeOfCFType : CFType -> Core $ String
cTypeOfCFType CFUnit = pure $ "void"
cTypeOfCFType CFInt = pure $ "int"
cTypeOfCFType CFUnsigned8 = pure $ "uint8_t"
cTypeOfCFType CFUnsigned16 = pure $ "uint16_t"
cTypeOfCFType CFUnsigned32 = pure $ "uint32_t"
cTypeOfCFType CFUnsigned64 = pure $ "uint64_t"
cTypeOfCFType CFString = pure $ "char *"
cTypeOfCFType CFDouble = pure $ "double"
cTypeOfCFType CFChar = pure $ "char"
cTypeOfCFType CFPtr = pure $ "void *"
cTypeOfCFType CFGCPtr = pure $ "void *"
cTypeOfCFType CFBuffer = pure $ "void *"
cTypeOfCFType CFWorld = pure $ "void *"
cTypeOfCFType (CFFun x y) = pure $ "void *"
cTypeOfCFType (CFIORes x) = pure $ "void *"
cTypeOfCFType (CFStruct x ys) = pure $ "void *"
cTypeOfCFType (CFUser x ys) = pure $ "void *"
cTypeOfCFType : CFType -> String
cTypeOfCFType CFUnit = "void"
cTypeOfCFType CFInt = "int"
cTypeOfCFType CFUnsigned8 = "uint8_t"
cTypeOfCFType CFUnsigned16 = "uint16_t"
cTypeOfCFType CFUnsigned32 = "uint32_t"
cTypeOfCFType CFUnsigned64 = "uint64_t"
cTypeOfCFType CFString = "char *"
cTypeOfCFType CFDouble = "double"
cTypeOfCFType CFChar = "char"
cTypeOfCFType CFPtr = "void *"
cTypeOfCFType CFGCPtr = "void *"
cTypeOfCFType CFBuffer = "void *"
cTypeOfCFType CFWorld = "void *"
cTypeOfCFType (CFFun x y) = "void *"
cTypeOfCFType (CFIORes x) = "void *"
cTypeOfCFType (CFStruct x ys) = "void *"
cTypeOfCFType (CFUser x ys) = "void *"
cTypeOfCFType n = assert_total $ idris_crash ("INTERNAL ERROR: Unknonw FFI type in C backend: " ++ show n)
varNamesFromList : List ty -> Nat -> List String
varNamesFromList str k = map (("var_" ++) . show) (getArgsNrList str k)
@ -814,7 +744,7 @@ varNamesFromList str k = map (("var_" ++) . show) (getArgsNrList str k)
createFFIArgList : List CFType
-> Core $ List (String, String, CFType)
createFFIArgList cftypeList = do
sList <- traverse cTypeOfCFType cftypeList
let sList = map cTypeOfCFType cftypeList
let varList = varNamesFromList cftypeList 1
pure $ zip3 sList varList cftypeList
@ -823,7 +753,7 @@ emitFDef : {auto oft : Ref OutfileText Output}
-> (funcName:Name)
-> (arglist:List (String, String, CFType))
-> Core ()
emitFDef funcName [] = emit EmptyFC $ cName funcName ++ "(void)"
emitFDef funcName [] = emit EmptyFC $ "Value *" ++ cName funcName ++ "(void)"
emitFDef funcName ((varType, varName, varCFType) :: xs) = do
emit EmptyFC $ "Value *" ++ cName funcName
emit EmptyFC "("
@ -847,10 +777,12 @@ extractValue CFPtr varName = "((Value_Pointer*)" ++ varName ++ ")->p"
extractValue CFGCPtr varName = "((Value_GCPointer*)" ++ varName ++ ")->p->p"
extractValue CFBuffer varName = "((Value_Buffer*)" ++ varName ++ ")->buffer"
extractValue CFWorld varName = "(Value_World*)" ++ varName
extractValue (CFFun x y) varName = "Value* " ++ varName ++ "/* function pointer not implemented */"
extractValue (CFFun x y) varName = "(Value_Closure*)" ++ varName
extractValue (CFIORes x) varName = extractValue x varName
extractValue (CFStruct x xs) varName = "Value* " ++ varName ++ "/* struct access not implemented */"
extractValue (CFUser x xs) varName = "Value* " ++ varName
extractValue (CFStruct x xs) varName = assert_total $ idris_crash ("INTERNAL ERROR: Struct access not implemented: " ++ varName)
-- not really total but this way this internal error does not contaminate everything else
extractValue (CFUser x xs) varName = "(Value*)" ++ varName
extractValue n _ = assert_total $ idris_crash ("INTERNAL ERROR: Unknonw FFI type in C backend: " ++ show n)
packCFType : (cfType:CFType) -> (varName:String) -> String
packCFType CFUnit varName = "NULL"
@ -869,7 +801,8 @@ packCFType CFWorld varName = "makeWorld(" ++ varName ++ ")"
packCFType (CFFun x y) varName = "makeFunction(" ++ varName ++ ")"
packCFType (CFIORes x) varName = packCFType x varName
packCFType (CFStruct x xs) varName = "makeStruct(" ++ varName ++ ")"
packCFType (CFUser x xs) varName = "makeCustomUser(" ++ varName ++ ")"
packCFType (CFUser x xs) varName = varName
packCFType n _ = assert_total $ idris_crash ("INTERNAL ERROR: Unknonw FFI type in C backend: " ++ show n)
discardLastArgument : List ty -> List ty
discardLastArgument [] = []
@ -881,7 +814,7 @@ createCFunctions : {auto c : Ref Ctxt Defs}
-> {auto t : Ref TemporaryVariableTracker (List (List String))}
-> {auto oft : Ref OutfileText Output}
-> {auto il : Ref IndentLevel Nat}
-> {auto e : Ref ExternalLibs (List String)}
-> {auto h : Ref HeaderFiles (SortedSet String)}
-> Name
-> ANFDef
-> Core ()
@ -924,13 +857,12 @@ createCFunctions n (MkACon tag arity nt) = do
emit EmptyFC $ ( "// Constructor tag " ++ show tag ++ " arity " ++ show arity) -- Nothing to compile here
createCFunctions n (MkAForeign ccs fargs (CFIORes ret)) = do
case extractFFILocation "C" ccs of
Nothing => case extractFFILocation "scheme" ccs of
Nothing => pure ()
(Just (fctName, lib)) => emit EmptyFC $ "// call ffi to a scheme substitute for " ++ fctName
(Just (fctName, lib)) => do
addExternalLib lib
createCFunctions n (MkAForeign ccs fargs ret) = do
case parseCC ["C"] ccs of
Just (_, fctName :: extLibOpts) => do
case extLibOpts of
[lib, header] => addHeader header
_ => pure ()
otherDefs <- get FunctionDefinitions
let fnDef = "Value *" ++ (cName n) ++ "(" ++ showSep ", " (replicate (length fargs) "Value *") ++ ");"
fn_arglist <- functionDefSignatureArglist n
@ -958,67 +890,59 @@ createCFunctions n (MkAForeign ccs fargs (CFIORes ret)) = do
increaseIndentation
emit EmptyFC $ " // ffi call to " ++ fctName
case ret of
CFUnit => do
CFIORes CFUnit => do
emit EmptyFC $ fctName
++ "("
++ showSep ", " (map (\(_, vn, vt) => extractValue vt vn) (discardLastArgument typeVarNameArgList))
++ ");"
emit EmptyFC "return NULL;"
decreaseIndentation
emit EmptyFC "}\n"
_ => do
emit EmptyFC $ !(cTypeOfCFType ret) ++ " retVal = " ++ fctName
CFIORes ret => do
emit EmptyFC $ cTypeOfCFType ret ++ " retVal = " ++ fctName
++ "("
++ showSep ", " (map (\(_, vn, vt) => extractValue vt vn) (discardLastArgument typeVarNameArgList))
++ ");"
emit EmptyFC $ "return (Value*)" ++ packCFType ret "retVal" ++ ";"
decreaseIndentation
emit EmptyFC "}\n"
_ => do
emit EmptyFC $ cTypeOfCFType ret ++ " retVal = " ++ fctName
++ "("
++ showSep ", " (map (\(_, vn, vt) => extractValue vt vn) typeVarNameArgList)
++ ");"
emit EmptyFC $ "return (Value*)" ++ packCFType ret "retVal" ++ ";"
-- decreaseIndentation
-- emit EmptyFC "}"
--put FunctionDefinitions ((fn ++ ";\n") :: (fn' ++ ";\n") :: otherDefs)
--ffiString n fctName lib fargs (CFIORes ret)
createCFunctions n (MkAForeign ccs fargs ret) = pure () -- unable to deal with return values that are not CFIORes
createCFunctions n (MkAError exp) = do
fn <- functionDefSignature n []
fn' <- functionDefSignatureArglist n
otherDefs <- get FunctionDefinitions
put FunctionDefinitions (fn :: fn' :: otherDefs)
--(statements, assignment) <- cStatementsFromANF exp
emit EmptyFC $ fn
++ "\n{"
++ "fprintf(stderr, \"Error in " ++ (cName n) ++ "\");\n"
++ "exit(-1);\n"
++ "return NULL;"
++ "\n}"
pure ()
decreaseIndentation
emit EmptyFC "}"
_ => assert_total $ idris_crash ("INTERNAL ERROR: FFI not found for " ++ cName n)
-- not really total but this way this internal error does not contaminate everything else
createCFunctions n (MkAError exp) = assert_total $ idris_crash ("INTERNAL ERROR: Error with expression: " ++ show exp)
-- not really total but this way this internal error does not contaminate everything else
header : {auto c : Ref Ctxt Defs}
-> {auto f : Ref FunctionDefinitions (List String)}
-> {auto o : Ref OutfileText Output}
-> {auto il : Ref IndentLevel Nat}
-> {auto e : Ref ExternalLibs (List String)}
-> {auto h : Ref HeaderFiles (SortedSet String)}
-> Core ()
header = do
let initLines = [ "#include <runtime.h>"
, "/* automatically generated using the Idris2 C Backend */"
, "#include <idris_support.h> // for libidris2_support"]
extLibs <- get ExternalLibs
let extLibLines = map (\lib => "// add header(s) for library: " ++ lib ++ "\n") extLibs
traverse_ (\l => log "compiler.refc" 20 $ " header for " ++ l ++ " needed") extLibs
, "/* automatically generated using the Idris2 C Backend */"]
let headerFiles = Libraries.Data.SortedSet.toList !(get HeaderFiles)
let headerLines = map (\h => "#include <" ++ h ++ ">\n") headerFiles
fns <- get FunctionDefinitions
update OutfileText (appendL (initLines ++ extLibLines ++ ["\n// function definitions"] ++ fns))
update OutfileText (appendL (initLines ++ headerLines ++ ["\n// function definitions"] ++ fns))
footer : {auto il : Ref IndentLevel Nat} -> {auto f : Ref OutfileText Output} -> Core ()
footer : {auto il : Ref IndentLevel Nat}
-> {auto f : Ref OutfileText Output}
-> {auto h : Ref HeaderFiles (SortedSet String)}
-> Core ()
footer = do
emit EmptyFC ""
emit EmptyFC " // main function"
emit EmptyFC "int main()"
emit EmptyFC "int main(int argc, char *argv[])"
emit EmptyFC "{"
if contains "idris_support.h" !(get HeaderFiles)
then emit EmptyFC " idris2_setArgs(argc, argv);"
else pure ()
emit EmptyFC " Value *mainExprVal = __mainExpression_0();"
emit EmptyFC " trampoline(mainExprVal);"
emit EmptyFC " return 0; // bye bye"
@ -1040,7 +964,7 @@ generateCSourceFile defs outn =
_ <- newRef FunctionDefinitions []
_ <- newRef TemporaryVariableTracker []
_ <- newRef OutfileText DList.Nil
_ <- newRef ExternalLibs []
_ <- newRef HeaderFiles empty
_ <- newRef IndentLevel 0
traverse_ (uncurry createCFunctions) defs
header -- added after the definition traversal in order to add all encountered function defintions

View File

@ -177,6 +177,10 @@ data Structs : Type where
cftySpec : FC -> CFType -> Core String
cftySpec fc CFUnit = pure "void"
cftySpec fc CFInt = pure "int"
cftySpec fc CFInt8 = pure "integer-8"
cftySpec fc CFInt16 = pure "integer-16"
cftySpec fc CFInt32 = pure "integer-32"
cftySpec fc CFInt64 = pure "integer-64"
cftySpec fc CFUnsigned8 = pure "unsigned-8"
cftySpec fc CFUnsigned16 = pure "unsigned-16"
cftySpec fc CFUnsigned32 = pure "unsigned-32"
@ -349,22 +353,11 @@ startChezPreamble = unlines
, ""
, "set -e # exit on any error"
, ""
, "case $(uname -s) in "
, " OpenBSD | FreeBSD | NetBSD)"
, " REALPATH=\"grealpath\" "
, " ;; "
, " "
, " *) "
, " REALPATH=\"realpath\" "
, " ;; "
, "esac "
, ""
, "if ! command -v \"$REALPATH\" >/dev/null; then "
, " echo \"$REALPATH is required for Chez code generator.\""
, " exit 1 "
, "fi "
, ""
, "DIR=$(dirname \"$($REALPATH \"$0\")\")"
, "if [ \"$(uname)\" = Darwin ]; then"
, " DIR=$(zsh -c 'printf %s \"$0:A:h\"' \"$0\")"
, "else"
, " DIR=$(dirname \"$(readlink -f -- \"$0\")\")"
, "fi"
, "" -- so that the preamble ends with a newline
]
@ -388,7 +381,7 @@ startChezWinSh chez appdir target = unlines
, ""
, "set -e # exit on any error"
, ""
, "DIR=$(dirname \"$(realpath \"$0\")\")"
, "DIR=$(dirname \"$(readlink -f -- \"$0\")\")"
, "CHEZ=$(cygpath \"" ++ chez ++"\")"
, "export PATH=\"$DIR/" ++ appdir ++ "\":$PATH"
, "\"$CHEZ\" --script \"$DIR/" ++ target ++ "\" \"$@\""

View File

@ -78,7 +78,7 @@ startChezWinSh chez appDirSh targetSh = unlines
, ""
, "set -e # exit on any error"
, ""
, "DIR=$(dirname \"$(realpath \"$0\")\")"
, "DIR=$(dirname \"$(readlink -f -- \"$0\")\")"
, "CHEZ=$(cygpath \"" ++ chez ++"\")"
, "export PATH=\"$DIR/" ++ appDirSh ++ "\":$PATH"
, "\"$CHEZ\" --program \"$DIR/" ++ targetSh ++ "\" \"$@\""

View File

@ -152,6 +152,10 @@ cType fc t = throw (GenericMsg fc ("Can't pass argument of type " ++ show t ++
cftySpec : FC -> CFType -> Core String
cftySpec fc CFUnit = pure "void"
cftySpec fc CFInt = pure "int"
cftySpec fc CFInt8 = pure "char"
cftySpec fc CFInt16 = pure "short"
cftySpec fc CFInt32 = pure "int"
cftySpec fc CFInt64 = pure "long"
cftySpec fc CFUnsigned8 = pure "unsigned-char"
cftySpec fc CFUnsigned16 = pure "unsigned-short"
cftySpec fc CFUnsigned32 = pure "unsigned-int"

View File

@ -119,6 +119,10 @@ data Done : Type where
cftySpec : FC -> CFType -> Core String
cftySpec fc CFUnit = pure "_void"
cftySpec fc CFInt = pure "_int"
cftySpec fc CFInt8 = pure "_int8"
cftySpec fc CFInt16 = pure "_int16"
cftySpec fc CFInt32 = pure "_int32"
cftySpec fc CFInt64 = pure "_int64"
cftySpec fc CFUnsigned8 = pure "_uint8"
cftySpec fc CFUnsigned16 = pure "_uint16"
cftySpec fc CFUnsigned32 = pure "_uint32"
@ -330,22 +334,12 @@ startRacket racket appdir target = unlines
, ""
, "set -e # exit on any error"
, ""
, "case $(uname -s) in "
, " OpenBSD | FreeBSD | NetBSD)"
, " REALPATH=\"grealpath\" "
, " ;; "
, " "
, " *) "
, " REALPATH=\"realpath\" "
, " ;; "
, "esac "
, "if [ \"$(uname)\" = Darwin ]; then"
, " DIR=$(zsh -c 'printf %s \"$0:A:h\"' \"$0\")"
, "else"
, " DIR=$(dirname \"$(readlink -f -- \"$0\")\")"
, "fi"
, ""
, "if ! command -v \"$REALPATH\" >/dev/null; then "
, " echo \"$REALPATH is required for Racket code generator.\""
, " exit 1 "
, "fi "
, ""
, "DIR=$(dirname \"$($REALPATH \"$0\")\")"
, "export LD_LIBRARY_PATH=\"$DIR/" ++ appdir ++ "\":$LD_LIBRARY_PATH"
, racket ++ "\"$DIR/" ++ target ++ "\" \"$@\""
]
@ -364,7 +358,7 @@ startRacketWinSh racket appdir target = unlines
, ""
, "set -e # exit on any error"
, ""
, "DIR=$(dirname \"$(realpath \"$0\")\")"
, "DIR=$(dirname \"$(readlink -f -- \"$0\")\")"
, "export PATH=\"$DIR/" ++ appdir ++ "\":$PATH"
, racket ++ "\"" ++ target ++ "\" \"$@\""
]

View File

@ -176,7 +176,7 @@ writeTTCFile : (HasNames extra, TTC extra) =>
writeTTCFile b file_in
= do file <- toFullNames file_in
toBuf b "TT2"
toBuf b (version file)
toBuf @{Wasteful} b (version file)
toBuf b (ifaceHash file)
toBuf b (importHashes file)
toBuf b (imported file)
@ -203,7 +203,7 @@ readTTCFile readall file as b
= do hdr <- fromBuf b
chunk <- get Bin
when (hdr /= "TT2") $ corrupt ("TTC header in " ++ file ++ " " ++ show hdr)
ver <- fromBuf b
ver <- fromBuf @{Wasteful} b
checkTTCVersion file ver ttcVersion
ifaceHash <- fromBuf b
importHashes <- fromBuf b

View File

@ -153,6 +153,10 @@ public export
data CFType : Type where
CFUnit : CFType
CFInt : CFType
CFInt8 : CFType
CFInt16 : CFType
CFInt32 : CFType
CFInt64 : CFType
CFUnsigned8 : CFType
CFUnsigned16 : CFType
CFUnsigned32 : CFType
@ -346,6 +350,10 @@ export
Show CFType where
show CFUnit = "Unit"
show CFInt = "Int"
show CFInt8 = "Int_8"
show CFInt16 = "Int_16"
show CFInt32 = "Int_32"
show CFInt64 = "Int_64"
show CFUnsigned8 = "Bits_8"
show CFUnsigned16 = "Bits_16"
show CFUnsigned32 = "Bits_32"

View File

@ -1172,6 +1172,15 @@ clearCtxt
resetElab : Options -> Options
resetElab = record { elabDirectives = defaultElab }
export
getFieldNames : Context -> Namespace -> List Name
getFieldNames ctxt recNS
= let nms = resolvedAs ctxt in
keys $ flip filterBy nms $ \ n =>
case isRF n of
Nothing => False
Just (ns, field) => ns == recNS
-- Find similar looking names in the context
getSimilarNames : {auto c : Ref Ctxt Defs} -> Name -> Core (List String)
getSimilarNames nm = case userNameRoot nm of

View File

@ -2,6 +2,7 @@ module Core.Context.Log
import Core.Context
import Core.Options
import Data.Strings
import Libraries.Data.StringMap
@ -9,7 +10,45 @@ import System.Clock
%default covering
-- Log message with a term, translating back to human readable names first
-- if this function is called, then logging must be enabled.
%inline
export
logString : String -> Nat -> String -> Core ()
logString "" n msg = coreLift $ putStrLn
$ "LOG " ++ show n ++ ": " ++ msg
logString str n msg = coreLift $ putStrLn
$ "LOG " ++ str ++ ":" ++ show n ++ ": " ++ msg
%inline
export
logString' : LogLevel -> String -> Core ()
logString' lvl =
logString (fastAppend (intersperse "." (topics lvl)) ++ ":")
(verbosity lvl)
export
logging' : {auto c : Ref Ctxt Defs} ->
LogLevel -> Core Bool
logging' lvl = do
opts <- getSession
pure $ verbosity lvl == 0 || (logEnabled opts && keepLog lvl (logLevel opts))
export
unverifiedLogging : {auto c : Ref Ctxt Defs} ->
String -> Nat -> Core Bool
unverifiedLogging str Z = pure True
unverifiedLogging str n = do
opts <- getSession
pure $ logEnabled opts && keepLog (mkUnverifiedLogLevel str n) (logLevel opts)
%inline
export
logging : {auto c : Ref Ctxt Defs} ->
(s : String) -> {auto 0 _ : KnownTopic s} ->
Nat -> Core Bool
logging str n = unverifiedLogging str n
||| Log message with a term, translating back to human readable names first.
export
logTerm : {vars : _} ->
{auto c : Ref Ctxt Defs} ->
@ -17,21 +56,16 @@ logTerm : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Term vars -> Core ()
logTerm str n msg tm
= do opts <- getSession
let lvl = mkLogLevel (logEnabled opts) str n
if keepLog lvl (logEnabled opts) (logLevel opts)
then do tm' <- toFullNames tm
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm'
else pure ()
= when !(logging str n)
$ do tm' <- toFullNames tm
logString str n $ msg ++ ": " ++ show tm'
export
log' : {auto c : Ref Ctxt Defs} ->
LogLevel -> Lazy String -> Core ()
log' lvl msg
= do opts <- getSession
if keepLog lvl (logEnabled opts) (logLevel opts)
then coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
else pure ()
= when !(logging' lvl)
$ logString' lvl msg
||| Log a message with the given log level. Use increasingly
||| high log level numbers for more granular logging.
@ -41,21 +75,19 @@ log : {auto c : Ref Ctxt Defs} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Core ()
log str n msg
= do let lvl = mkLogLevel (logEnabled !getSession) str n
log' lvl msg
= when !(logging str n)
$ logString str n msg
export
unverifiedLogC : {auto c : Ref Ctxt Defs} ->
(s : String) ->
Nat -> Core String -> Core ()
unverifiedLogC str n cmsg
= do opts <- getSession
let lvl = mkUnverifiedLogLevel (logEnabled opts) str n
if keepLog lvl (logEnabled opts) (logLevel opts)
then do msg <- cmsg
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
else pure ()
= when !(unverifiedLogging str n)
$ do msg <- cmsg
logString str n msg
%inline
export
logC : {auto c : Ref Ctxt Defs} ->
(s : String) ->
@ -63,11 +95,16 @@ logC : {auto c : Ref Ctxt Defs} ->
Nat -> Core String -> Core ()
logC str = unverifiedLogC str
nano : Integer
nano = 1000000000
micro : Integer
micro = 1000000
export
logTimeOver : Integer -> Core String -> Core a -> Core a
logTimeOver nsecs str act
= do clock <- coreLift (clockTime Process)
let nano = 1000000000
let t = seconds clock * nano + nanoseconds clock
res <- act
clock <- coreLift (clockTime Process)
@ -78,7 +115,7 @@ logTimeOver nsecs str act
do str' <- str
coreLift $ putStrLn $ "TIMING " ++ str' ++ ": " ++
show (time `div` nano) ++ "." ++
addZeros (unpack (show ((time `mod` nano) `div` 1000000))) ++
addZeros (unpack (show ((time `mod` nano) `div` micro))) ++
"s"
pure res
where
@ -94,7 +131,6 @@ logTimeWhen : {auto c : Ref Ctxt Defs} ->
logTimeWhen p str act
= if p
then do clock <- coreLift (clockTime Process)
let nano = 1000000000
let t = seconds clock * nano + nanoseconds clock
res <- act
clock <- coreLift (clockTime Process)
@ -103,7 +139,7 @@ logTimeWhen p str act
assert_total $ -- We're not dividing by 0
coreLift $ putStrLn $ "TIMING " ++ str ++ ": " ++
show (time `div` nano) ++ "." ++
addZeros (unpack (show ((time `mod` nano) `div` 1000000))) ++
addZeros (unpack (show ((time `mod` nano) `div` micro))) ++
"s"
pure res
else act
@ -118,7 +154,6 @@ logTimeRecord' : {auto c : Ref Ctxt Defs} ->
String -> Core a -> Core a
logTimeRecord' key act
= do clock <- coreLift (clockTime Process)
let nano = 1000000000
let t = seconds clock * nano + nanoseconds clock
res <- act
clock <- coreLift (clockTime Process)
@ -163,10 +198,9 @@ showTimeRecord
showTimeLog : (String, (Bool, Integer)) -> Core ()
showTimeLog (key, (_, time))
= do coreLift $ putStr (key ++ ": ")
let nano = 1000000000
assert_total $ -- We're not dividing by 0
coreLift $ putStrLn $ show (time `div` nano) ++ "." ++
addZeros (unpack (show ((time `mod` nano) `div` 1000000))) ++
addZeros (unpack (show ((time `mod` nano) `div` micro))) ++
"s"
export

View File

@ -227,6 +227,14 @@ Hashable CFType where
h `hashWithSalt` 15 `hashWithSalt` n `hashWithSalt` fs
CFUser n xs =>
h `hashWithSalt` 16 `hashWithSalt` n `hashWithSalt` xs
CFInt8 =>
h `hashWithSalt` 17
CFInt16 =>
h `hashWithSalt` 18
CFInt32 =>
h `hashWithSalt` 19
CFInt64 =>
h `hashWithSalt` 20
export
Hashable Constant where

View File

@ -91,6 +91,12 @@ isSourceName (CaseBlock _ _) = False
isSourceName (WithBlock _ _) = False
isSourceName (Resolved _) = False
export
isRF : Name -> Maybe (Namespace, String)
isRF (NS ns n) = map (mapFst (ns <.>)) (isRF n)
isRF (RF n) = Just (emptyNS, n)
isRF _ = Nothing
export
isUN : Name -> Maybe String
isUN (UN str) = Just str

View File

@ -1200,29 +1200,25 @@ logNF : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Env Term vars -> NF vars -> Core ()
logNF str n msg env tmnf
= do opts <- getSession
let lvl = mkLogLevel (logEnabled opts) str n
when (keepLog lvl (logEnabled opts) (logLevel opts)) $
do defs <- get Ctxt
tm <- quote defs env tmnf
tm' <- toFullNames tm
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm'
= when !(logging str n) $
do defs <- get Ctxt
tm <- quote defs env tmnf
tm' <- toFullNames tm
logString str n (msg ++ ": " ++ show tm')
-- Log message with a term, reducing holes and translating back to human
-- readable names first
export
logTermNF' : {vars : _} ->
{auto c : Ref Ctxt Defs} ->
LogLevel -> Lazy String -> Env Term vars -> Term vars -> Core ()
logTermNF' lvl msg env tm
= do opts <- getSession
when (keepLog lvl (logEnabled opts) (logLevel opts)) $
do defs <- get Ctxt
tmnf <- normaliseHoles defs env tm
tm' <- toFullNames tmnf
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm'
(s : String) ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Env Term vars -> Term vars -> Core ()
logTermNF' str n msg env tm
= do defs <- get Ctxt
tmnf <- normaliseHoles defs env tm
tm' <- toFullNames tmnf
logString str n (msg ++ ": " ++ show tm')
export
logTermNF : {vars : _} ->
@ -1231,8 +1227,7 @@ logTermNF : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Env Term vars -> Term vars -> Core ()
logTermNF str n msg env tm
= do let lvl = mkLogLevel (logEnabled !getSession) str n
logTermNF' lvl msg env tm
= when !(logging str n) $ logTermNF' str n msg env tm
export
logGlue : {vars : _} ->
@ -1241,14 +1236,11 @@ logGlue : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Env Term vars -> Glued vars -> Core ()
logGlue str n msg env gtm
= do opts <- getSession
let lvl = mkLogLevel (logEnabled opts) str n
when (keepLog lvl (logEnabled opts) (logLevel opts)) $
do defs <- get Ctxt
tm <- getTerm gtm
tm' <- toFullNames tm
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm'
= when !(logging str n) $
do defs <- get Ctxt
tm <- getTerm gtm
tm' <- toFullNames tm
logString str n (msg ++ ": " ++ show tm')
export
logGlueNF : {vars : _} ->
@ -1257,15 +1249,12 @@ logGlueNF : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> Env Term vars -> Glued vars -> Core ()
logGlueNF str n msg env gtm
= do opts <- getSession
let lvl = mkLogLevel (logEnabled opts) str n
when (keepLog lvl (logEnabled opts) (logLevel opts)) $
do defs <- get Ctxt
tm <- getTerm gtm
tmnf <- normaliseHoles defs env tm
tm' <- toFullNames tmnf
coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm'
= when !(logging str n) $
do defs <- get Ctxt
tm <- getTerm gtm
tmnf <- normaliseHoles defs env tm
tm' <- toFullNames tmnf
logString str n (msg ++ ": " ++ show tm')
export
logEnv : {vars : _} ->
@ -1274,27 +1263,22 @@ logEnv : {vars : _} ->
{auto 0 _ : KnownTopic s} ->
Nat -> String -> Env Term vars -> Core ()
logEnv str n msg env
= do opts <- getSession
when (logEnabled opts &&
keepLog lvl (logEnabled opts) (logLevel opts)) $ do
coreLift (putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg)
= when !(logging str n) $
do logString str n msg
dumpEnv env
where
lvl : LogLevel
lvl = mkLogLevel True str n
dumpEnv : {vs : List Name} -> Env Term vs -> Core ()
dumpEnv [] = pure ()
dumpEnv {vs = x :: _} (Let _ c val ty :: bs)
= do logTermNF' lvl (msg ++ ": let " ++ show x) bs val
logTermNF' lvl (msg ++ ":" ++ show c ++ " " ++
show x) bs ty
= do logTermNF' str n (msg ++ ": let " ++ show x) bs val
logTermNF' str n (msg ++ ":" ++ show c ++ " " ++ show x) bs ty
dumpEnv bs
dumpEnv {vs = x :: _} (b :: bs)
= do logTermNF' lvl (msg ++ ":" ++ show (multiplicity b) ++ " " ++
show (piInfo b) ++ " " ++
show x) bs (binderType b)
= do logTermNF' str n (msg ++ ":" ++ show (multiplicity b) ++ " " ++
show (piInfo b) ++ " " ++
show x) bs (binderType b)
dumpEnv bs
replace' : {auto c : Ref Ctxt Defs} ->
{vars : _} ->

View File

@ -8,6 +8,8 @@ import Libraries.Data.StringTrie
import Data.Strings
import Data.These
import Libraries.Text.PrettyPrint.Prettyprinter
import Libraries.Text.PrettyPrint.Prettyprinter.Util
import Libraries.Text.PrettyPrint.Prettyprinter.Render.String
%default total
@ -35,128 +37,140 @@ import Libraries.Text.PrettyPrint.Prettyprinter
-- INDIVIDUAL LOG LEVEL
public export
knownTopics : List (String,String)
knownTopics : List (String, Maybe String)
knownTopics = [
("auto", "some documentation of this option"),
("builtin.Natural", "some documentation of this option"),
("builtin.Natural.addTransform", "some documentation of this option"),
("builtin.NaturalToInteger", "some documentation of this option"),
("builtin.NaturalToInteger.addTransforms", "some documentation of this option"),
("builtin.IntegerToNatural", "some documentation of this option"),
("builtin.IntegerToNatural.addTransforms", "some documentation of this option"),
("compile.casetree", "some documentation of this option"),
("compile.casetree.clauses", "some documentation of this option"),
("compile.casetree.getpmdef", "some documentation of this option"),
("compile.casetree.intermediate", "some documentation of this option"),
("compile.casetree.pick", "some documentation of this option"),
("compile.casetree.partition", "some documentation of this option"),
("compiler.inline.eval", "some documentation of this option"),
("compiler.refc", "some documentation of this option"),
("compiler.refc.cc", "some documentation of this option"),
("compiler.scheme.chez", "some documentation of this option"),
("coverage", "some documentation of this option"),
("coverage.empty", "some documentation of this option"),
("coverage.missing", "some documentation of this option"),
("coverage.recover", "some documentation of this option"),
("declare.data", "some documentation of this option"),
("declare.data.constructor", "some documentation of this option"),
("declare.data.parameters", "some documentation of this option"),
("declare.def", "some documentation of this option"),
("declare.def.clause", "some documentation of this option"),
("declare.def.clause.impossible", "some documentation of this option"),
("declare.def.clause.with", "some documentation of this option"),
("declare.def.impossible", "some documentation of this option"),
("declare.def.lhs", "some documentation of this option"),
("declare.def.lhs.implicits", "some documentation of this option"),
("declare.param", "some documentation of this option"),
("declare.record", "some documentation of this option"),
("declare.record.field", "some documentation of this option"),
("declare.record.projection", "some documentation of this option"),
("declare.record.projection.prefix", "some documentation of this option"),
("declare.type", "some documentation of this option"),
("desugar.idiom", "some documentation of this option"),
("doc.record", "some documentation of this option"),
("elab", "some documentation of this option"),
("elab.ambiguous", "some documentation of this option"),
("elab.app.lhs", "some documentation of this option"),
("elab.as", "some documentation of this option"),
("elab.bindnames", "some documentation of this option"),
("elab.binder", "some documentation of this option"),
("elab.case", "some documentation of this option"),
("elab.def.local", "some documentation of this option"),
("elab.delay", "some documentation of this option"),
("elab.hole", "some documentation of this option"),
("elab.implicits", "some documentation of this option"),
("elab.implementation", "some documentation of this option"),
("elab.interface", "some documentation of this option"),
("elab.interface.default", "some documentation of this option"),
("elab.local", "some documentation of this option"),
("elab.prun", "some documentation of this option"),
("elab.prune", "some documentation of this option"),
("elab.record", "some documentation of this option"),
("elab.retry", "some documentation of this option"),
("elab.rewrite", "some documentation of this option"),
("elab.unify", "some documentation of this option"),
("elab.update", "some documentation of this option"),
("elab.with", "some documentation of this option"),
("eval.casetree", "some documentation of this option"),
("eval.casetree.stuck", "some documentation of this option"),
("eval.eta", "some documentation of this option"),
("eval.stuck", "some documentation of this option"),
("idemode.hole", "some documentation of this option"),
("ide-mode.highlight", "some documentation of this option"),
("ide-mode.highlight.alias", "some documentation of this option"),
("ide-mode.send", "some documentation of this option"),
("import", "some documentation of this option"),
("import.file", "some documentation of this option"),
("interaction.casesplit", "some documentation of this option"),
("interaction.generate", "some documentation of this option"),
("interaction.search", "some documentation of this option"),
("metadata.names", "some documentation of this option"),
("module.hash", "some documentation of this option"),
("quantity", "some documentation of this option"),
("quantity.hole", "some documentation of this option"),
("quantity.hole.update", "some documentation of this option"),
("repl.eval", "some documentation of this option"),
("specialise", "some documentation of this option"),
("totality", "some documentation of this option"),
("totality.positivity", "some documentation of this option"),
("totality.termination", "some documentation of this option"),
("totality.termination.calc", "some documentation of this option"),
("totality.termination.guarded", "some documentation of this option"),
("totality.termination.sizechange", "some documentation of this option"),
("totality.termination.sizechange.checkCall", "some documentation of this option"),
("totality.termination.sizechange.checkCall.inPath", "some documentation of this option"),
("totality.termination.sizechange.checkCall.inPathNot.restart", "some documentation of this option"),
("totality.termination.sizechange.checkCall.inPathNot.return", "some documentation of this option"),
("totality.termination.sizechange.inPath", "some documentation of this option"),
("totality.termination.sizechange.isTerminating", "some documentation of this option"),
("totality.termination.sizechange.needsChecking", "some documentation of this option"),
("transform.lhs", "some documentation of this option"),
("transform.rhs", "some documentation of this option"),
("ttc.read", "some documentation of this option"),
("ttc.write", "some documentation of this option"),
("typesearch.equiv", "some documentation of this option"),
("unelab.case", "some documentation of this option"),
("unify", "some documentation of this option"),
("unify.application", "some documentation of this option"),
("unify.binder", "some documentation of this option"),
("unify.constant", "some documentation of this option"),
("unify.constraint", "some documentation of this option"),
("unify.delay", "some documentation of this option"),
("unify.equal", "some documentation of this option"),
("unify.head", "some documentation of this option"),
("unify.hole", "some documentation of this option"),
("unify.instantiate", "some documentation of this option"),
("unify.invertible", "some documentation of this option"),
("unify.meta", "some documentation of this option"),
("unify.noeta", "some documentation of this option"),
("unify.postpone", "some documentation of this option"),
("unify.retry", "some documentation of this option"),
("unify.search", "some documentation of this option"),
("unify.unsolved", "some documentation of this option")
("auto", Nothing),
("builtin.Natural", Nothing),
("builtin.Natural.addTransform", Nothing),
("builtin.NaturalToInteger", Nothing),
("builtin.NaturalToInteger.addTransforms", Nothing),
("builtin.IntegerToNatural", Nothing),
("builtin.IntegerToNatural.addTransforms", Nothing),
("compile.casetree", Nothing),
("compile.casetree.clauses", Nothing),
("compile.casetree.getpmdef", Nothing),
("compile.casetree.intermediate", Nothing),
("compile.casetree.pick", Nothing),
("compile.casetree.partition", Nothing),
("compiler.inline.eval", Nothing),
("compiler.refc", Nothing),
("compiler.refc.cc", Nothing),
("compiler.scheme.chez", Nothing),
("coverage", Nothing),
("coverage.empty", Nothing),
("coverage.missing", Nothing),
("coverage.recover", Nothing),
("declare.data", Nothing),
("declare.data.constructor", Nothing),
("declare.data.parameters", Nothing),
("declare.def", Nothing),
("declare.def.clause", Nothing),
("declare.def.clause.impossible", Nothing),
("declare.def.clause.with", Nothing),
("declare.def.impossible", Nothing),
("declare.def.lhs", Nothing),
("declare.def.lhs.implicits", Nothing),
("declare.param", Nothing),
("declare.record", Nothing),
("declare.record.field", Nothing),
("declare.record.projection", Nothing),
("declare.record.projection.prefix", Nothing),
("declare.type", Nothing),
("desugar.idiom", Nothing),
("doc.record", Nothing),
("elab", Nothing),
("elab.ambiguous", Nothing),
("elab.app.lhs", Nothing),
("elab.as", Nothing),
("elab.bindnames", Nothing),
("elab.binder", Nothing),
("elab.case", Nothing),
("elab.def.local", Nothing),
("elab.delay", Nothing),
("elab.hole", Nothing),
("elab.implicits", Nothing),
("elab.implementation", Nothing),
("elab.interface", Nothing),
("elab.interface.default", Nothing),
("elab.local", Nothing),
("elab.prun", Nothing),
("elab.prune", Nothing),
("elab.record", Nothing),
("elab.retry", Nothing),
("elab.rewrite", Nothing),
("elab.unify", Nothing),
("elab.update", Nothing),
("elab.with", Nothing),
("eval.casetree", Nothing),
("eval.casetree.stuck", Nothing),
("eval.eta", Nothing),
("eval.stuck", Nothing),
("idemode.hole", Nothing),
("ide-mode.highlight", Nothing),
("ide-mode.highlight.alias", Nothing),
("ide-mode.send", Nothing),
("import", Nothing),
("import.file", Nothing),
("interaction.casesplit", Nothing),
("interaction.generate", Nothing),
("interaction.search", Nothing),
("metadata.names", Nothing),
("module.hash", Nothing),
("quantity", Nothing),
("quantity.hole", Nothing),
("quantity.hole.update", Nothing),
("repl.eval", Nothing),
("specialise", Nothing),
("totality", Nothing),
("totality.positivity", Nothing),
("totality.termination", Nothing),
("totality.termination.calc", Nothing),
("totality.termination.guarded", Nothing),
("totality.termination.sizechange", Nothing),
("totality.termination.sizechange.checkCall", Nothing),
("totality.termination.sizechange.checkCall.inPath", Nothing),
("totality.termination.sizechange.checkCall.inPathNot.restart", Nothing),
("totality.termination.sizechange.checkCall.inPathNot.return", Nothing),
("totality.termination.sizechange.inPath", Nothing),
("totality.termination.sizechange.isTerminating", Nothing),
("totality.termination.sizechange.needsChecking", Nothing),
("transform.lhs", Nothing),
("transform.rhs", Nothing),
("ttc.read", Nothing),
("ttc.write", Nothing),
("typesearch.equiv", Nothing),
("unelab.case", Nothing),
("unify", Nothing),
("unify.application", Nothing),
("unify.binder", Nothing),
("unify.constant", Nothing),
("unify.constraint", Nothing),
("unify.delay", Nothing),
("unify.equal", Nothing),
("unify.head", Nothing),
("unify.hole", Nothing),
("unify.instantiate", Nothing),
("unify.invertible", Nothing),
("unify.meta", Nothing),
("unify.noeta", Nothing),
("unify.postpone", Nothing),
("unify.retry", Nothing),
("unify.search", Nothing),
("unify.unsolved", Nothing)
]
export
helpTopics : String
helpTopics = show $ vcat $ map helpTopic knownTopics
where
helpTopic : (String, Maybe String) -> Doc ()
helpTopic (str, mblurb)
= let title = "+" <++> pretty str
blurb = maybe [] ((::[]) . indent 2 . reflow) mblurb
in vcat (title :: blurb)
public export
KnownTopic : String -> Type
KnownTopic s = IsJust (lookup s knownTopics)
@ -184,16 +198,15 @@ mkLogLevel' ps n = MkLogLevel (maybe [] forget ps) n
||| Use this function to create user defined loglevels, for instance, during
||| elaborator reflection.
export
mkUnverifiedLogLevel : Bool -> (s : String) -> Nat -> LogLevel
mkUnverifiedLogLevel False _ = mkLogLevel' Nothing
mkUnverifiedLogLevel _ "" = mkLogLevel' Nothing
mkUnverifiedLogLevel _ ps = mkLogLevel' (Just (split (== '.') ps))
mkUnverifiedLogLevel : (s : String) -> Nat -> LogLevel
mkUnverifiedLogLevel "" = mkLogLevel' Nothing
mkUnverifiedLogLevel ps = mkLogLevel' (Just (split (== '.') ps))
||| Like `mkUnverifiedLogLevel` but with a compile time check that
||| the passed string is a known topic.
export
mkLogLevel : Bool -> (s : String) -> {auto 0 _ : KnownTopic s} -> Nat -> LogLevel
mkLogLevel b s = mkUnverifiedLogLevel b s
mkLogLevel : (s : String) -> {auto 0 _ : KnownTopic s} -> Nat -> LogLevel
mkLogLevel s = mkUnverifiedLogLevel s
||| The unsafe constructor should only be used in places where the topic has already
||| been appropriately processed.
@ -239,7 +252,7 @@ parseLogLevel str = do
ns = tail nns in
case ns of
[] => pure (MkLogLevel [], n)
[ns] => pure (mkUnverifiedLogLevel True n, ns)
[ns] => pure (mkUnverifiedLogLevel n, ns)
_ => Nothing
lvl <- parsePositive n
pure $ c (fromInteger lvl)
@ -268,9 +281,9 @@ insertLogLevel (MkLogLevel ps n) = insert ps n
||| We keep a log if there is a prefix of its path associated to a larger number
||| in the LogLevels.
export
keepLog : LogLevel -> Bool -> LogLevels -> Bool
keepLog (MkLogLevel _ Z) _ _ = True
keepLog (MkLogLevel path n) enabled levels = enabled && go path levels where
keepLog : LogLevel -> LogLevels -> Bool
keepLog (MkLogLevel _ Z) _ = True
keepLog (MkLogLevel path n) levels = go path levels where
go : List String -> StringTrie Nat -> Bool
go path (MkStringTrie current) = here || there where

View File

@ -758,6 +758,10 @@ TTC CFType where
toBuf b (CFUser n a) = do tag 14; toBuf b n; toBuf b a
toBuf b CFGCPtr = tag 15
toBuf b CFBuffer = tag 16
toBuf b CFInt8 = tag 17
toBuf b CFInt16 = tag 18
toBuf b CFInt32 = tag 19
toBuf b CFInt64 = tag 20
fromBuf b
= case !getTag of
@ -778,6 +782,10 @@ TTC CFType where
14 => do n <- fromBuf b; a <- fromBuf b; pure (CFUser n a)
15 => pure CFGCPtr
16 => pure CFBuffer
17 => pure CFInt8
18 => pure CFInt16
19 => pure CFInt32
20 => pure CFInt64
_ => corrupt "CFType"
export

View File

@ -11,6 +11,7 @@ import Core.Value
import Control.Monad.State
import Libraries.Data.NameMap
import Libraries.Data.SortedMap
import Data.List
%default covering
@ -438,27 +439,41 @@ initArgs (S k)
args' <- initArgs k
pure (Just (arg, Same) :: args')
data Explored : Type where
-- Cached results of exploring the size change graph, so that if we visit a
-- node again, we don't have to re-explore the whole thing
SizeChanges : Type
SizeChanges = SortedMap (Name, List (Maybe Arg)) Terminating
-- Traverse the size change graph. When we reach a point we've seen before,
-- at least one of the arguments must have got smaller, otherwise it's
-- potentially non-terminating
checkSC : {auto a : Ref APos Arg} ->
{auto c : Ref Ctxt Defs} ->
{auto e : Ref Explored SizeChanges} ->
Defs ->
Name -> -- function we're checking
List (Maybe (Arg, SizeChange)) -> -- functions arguments and change
List (Name, List (Maybe Arg)) -> -- calls we've seen so far
Core Terminating
checkSC defs f args path
= do log "totality.termination.sizechange" 7 $ "Checking Size Change Graph: " ++ show !(toFullNames f)
= do exp <- get Explored
log "totality.termination.sizechange" 7 $ "Checking Size Change Graph: " ++ show !(toFullNames f)
let pos = (f, map (map Builtin.fst) args)
if pos `elem` path
then do log "totality.termination.sizechange.inPath" 8 $ "Checking arguments: " ++ show !(toFullNames f)
toFullNames $ checkDesc (mapMaybe (map Builtin.snd) args) path
else case !(lookupCtxtExact f (gamma defs)) of
Nothing => do log "totality.termination.sizechange.isTerminating" 8 $ "Size Change Graph is Terminating for: " ++ show !(toFullNames f)
pure IsTerminating
Just def => do log "totality.termination.sizechange.needsChecking" 8 $ "Size Change Graph needs traversing: " ++ show !(toFullNames f)
continue (sizeChange def) (pos :: path)
case lookup pos exp of
Just done => pure done -- already explored this bit of tree
Nothing =>
if pos `elem` path
then do log "totality.termination.sizechange.inPath" 8 $ "Checking arguments: " ++ show !(toFullNames f)
res <- toFullNames $ checkDesc (mapMaybe (map Builtin.snd) args) path
put Explored (insert pos res exp)
pure res
else case !(lookupCtxtExact f (gamma defs)) of
Nothing => do log "totality.termination.sizechange.isTerminating" 8 $ "Size Change Graph is Terminating for: " ++ show !(toFullNames f)
pure IsTerminating
Just def => do log "totality.termination.sizechange.needsChecking" 8 $ "Size Change Graph needs traversing: " ++ show !(toFullNames f)
continue (sizeChange def) (pos :: path)
where
-- Look for something descending in the list of size changes
checkDesc : List SizeChange -> List (Name, List (Maybe Arg)) -> Terminating
@ -488,14 +503,14 @@ checkSC defs f args path
checkCall : List (Name, List (Maybe Arg)) -> SCCall -> Core Terminating
checkCall path sc
= do let inpath = fnCall sc `elem` map fst path
Just gdef <- lookupCtxtExact (fnCall sc) (gamma defs)
= do Just gdef <- lookupCtxtExact (fnCall sc) (gamma defs)
| Nothing => pure IsTerminating -- nothing to check
let Unchecked = isTerminating (totality gdef)
| IsTerminating => pure IsTerminating
| _ => pure (NotTerminating (BadCall [fnCall sc]))
log "totality.termination.sizechange.checkCall" 8 $ "CheckCall Size Change Graph: " ++ show !(toFullNames (fnCall sc))
term <- checkSC defs (fnCall sc) (mkArgs (fnArgs sc)) path
let inpath = fnCall sc `elem` map fst path
if not inpath
then case term of
NotTerminating (RecPath _) =>
@ -505,7 +520,9 @@ checkSC defs f args path
-- function was the top level thing we were checking)
do log "totality.termination.sizechange.checkCall.inPathNot.restart" 9 $ "ReChecking Size Change Graph: " ++ show !(toFullNames (fnCall sc))
args' <- initArgs (length (fnArgs sc))
checkSC defs (fnCall sc) args' path
t <- checkSC defs (fnCall sc) args' path
setTerminating emptyFC (fnCall sc) t
pure t
t => do log "totality.termination.sizechange.checkCall.inPathNot.return" 9 $ "Have result: " ++ show !(toFullNames (fnCall sc))
pure t
else do log "totality.termination.sizechange.checkCall.inPath" 9 $ "Have Result: " ++ show !(toFullNames (fnCall sc))
@ -535,6 +552,7 @@ calcTerminating loc n
do let ty = type def
a <- newRef APos firstArg
args <- initArgs !(getArity defs [] ty)
e <- newRef Explored empty
checkSC defs n args []
bad => pure bad
where

View File

@ -623,64 +623,70 @@ checkNoGuards : {auto u : Ref UST UState} ->
checkNoGuards = checkUserHoles False
export
dumpHole' : {auto u : Ref UST UState} ->
{auto c : Ref Ctxt Defs} ->
LogLevel -> (hole : Int) -> Core ()
dumpHole' lvl hole
dumpHole : {auto u : Ref UST UState} ->
{auto c : Ref Ctxt Defs} ->
(s : String) ->
{auto 0 _ : KnownTopic s} ->
Nat -> (hole : Int) -> Core ()
dumpHole str n hole
= do ust <- get UST
defs <- get Ctxt
sopts <- getSession
when (keepLog lvl (logEnabled sopts) (logLevel sopts)) $ do
defs <- get Ctxt
case !(lookupCtxtExact (Resolved hole) (gamma defs)) of
Nothing => pure ()
Just gdef => case (definition gdef, type gdef) of
(Guess tm envb constraints, ty) =>
do log' lvl $ "!" ++ show !(getFullName (Resolved hole)) ++ " : " ++
show !(toFullNames !(normaliseHoles defs [] ty))
log' lvl $ "\t = " ++ show !(normaliseHoles defs [] tm)
++ "\n\twhen"
traverse_ dumpConstraint constraints
(Hole _ p, ty) =>
log' lvl $ "?" ++ show (fullname gdef) ++ " : " ++
show !(normaliseHoles defs [] ty)
++ if implbind p then " (ImplBind)" else ""
++ if invertible gdef then " (Invertible)" else ""
(BySearch _ _ _, ty) =>
log' lvl $ "Search " ++ show hole ++ " : " ++
show !(toFullNames !(normaliseHoles defs [] ty))
(PMDef _ args t _ _, ty) =>
log' (withVerbosity 4 lvl) $
"Solved: " ++ show hole ++ " : " ++
show !(normalise defs [] ty) ++
" = " ++ show !(normalise defs [] (Ref emptyFC Func (Resolved hole)))
(ImpBind, ty) =>
log' (withVerbosity 4 lvl) $
"Bound: " ++ show hole ++ " : " ++
show !(normalise defs [] ty)
(Delayed, ty) =>
log' (withVerbosity 4 lvl) $
"Delayed elaborator : " ++
show !(normalise defs [] ty)
_ => pure ()
defs <- get Ctxt
case !(lookupCtxtExact (Resolved hole) (gamma defs)) of
Nothing => pure ()
Just gdef => case (definition gdef, type gdef) of
(Guess tm envb constraints, ty) =>
do logString str n $
"!" ++ show !(getFullName (Resolved hole)) ++ " : "
++ show !(toFullNames !(normaliseHoles defs [] ty))
++ "\n\t = "
++ show !(normaliseHoles defs [] tm)
++ "\n\twhen"
traverse_ dumpConstraint constraints
(Hole _ p, ty) =>
logString str n $
"?" ++ show (fullname gdef) ++ " : "
++ show !(normaliseHoles defs [] ty)
++ if implbind p then " (ImplBind)" else ""
++ if invertible gdef then " (Invertible)" else ""
(BySearch _ _ _, ty) =>
logString str n $
"Search " ++ show hole ++ " : " ++
show !(toFullNames !(normaliseHoles defs [] ty))
(PMDef _ args t _ _, ty) =>
log str 4 $
"Solved: " ++ show hole ++ " : " ++
show !(normalise defs [] ty) ++
" = " ++ show !(normalise defs [] (Ref emptyFC Func (Resolved hole)))
(ImpBind, ty) =>
log str 4 $
"Bound: " ++ show hole ++ " : " ++
show !(normalise defs [] ty)
(Delayed, ty) =>
log str 4 $
"Delayed elaborator : " ++
show !(normalise defs [] ty)
_ => pure ()
where
dumpConstraint : Int -> Core ()
dumpConstraint n
dumpConstraint cid
= do ust <- get UST
defs <- get Ctxt
case lookup n (constraints ust) of
case lookup cid (constraints ust) of
Nothing => pure ()
Just Resolved => log' lvl "\tResolved"
Just Resolved => logString str n "\tResolved"
Just (MkConstraint _ lazy env x y) =>
do log' lvl $ "\t " ++ show !(toFullNames !(quote defs env x))
++ " =?= " ++ show !(toFullNames !(quote defs env y))
do logString str n $
"\t " ++ show !(toFullNames !(quote defs env x))
++ " =?= " ++ show !(toFullNames !(quote defs env y))
empty <- clearDefs defs
log' (withVerbosity 5 lvl)
$ "\t from " ++ show !(toFullNames !(quote empty env x))
++ " =?= " ++ show !(toFullNames !(quote empty env y)) ++
if lazy then "\n\t(lazy allowed)" else ""
log str 5 $
"\t from " ++ show !(toFullNames !(quote empty env x))
++ " =?= " ++ show !(toFullNames !(quote empty env y))
++ if lazy then "\n\t(lazy allowed)" else ""
Just (MkSeqConstraint _ _ xs ys) =>
log' lvl $ "\t\t" ++ show xs ++ " =?= " ++ show ys
logString str n $ "\t\t" ++ show xs ++ " =?= " ++ show ys
export
dumpConstraints : {auto u : Ref UST UState} ->
@ -694,11 +700,9 @@ dumpConstraints str n all
= do ust <- get UST
defs <- get Ctxt
sopts <- getSession
let lvl = mkLogLevel (logEnabled sopts) str n
when (keepLog lvl (logEnabled sopts) (logLevel sopts)) $
do let hs = toList (guesses ust) ++
toList (if all then holes ust else currentHoles ust)
case hs of
[] => pure ()
_ => do log' lvl "--- CONSTRAINTS AND HOLES ---"
traverse_ (dumpHole' lvl) (map fst hs)
when !(logging str n) $ do
let hs = toList (guesses ust) ++
toList (if all then holes ust else currentHoles ust)
unless (isNil hs) $
do logString str n "--- CONSTRAINTS AND HOLES ---"
traverse_ (dumpHole str n) (map fst hs)

View File

@ -46,6 +46,17 @@ export
Show DirCommand where
show LibDir = "--libdir"
||| Help topics
public export
data HelpTopic
=
||| Interactive debugging topics
HelpLogging
recogniseHelpTopic : String -> Maybe HelpTopic
recogniseHelpTopic "logging" = pure HelpLogging
recogniseHelpTopic _ = Nothing
||| CLOpt - possible command line options
public export
data CLOpt
@ -75,7 +86,7 @@ data CLOpt
||| Display Idris version
Version |
||| Display help text
Help |
Help (Maybe HelpTopic) |
||| Suppress the banner
NoBanner |
||| Run Idris 2 in quiet mode
@ -271,7 +282,7 @@ options = [MkOpt ["--check", "-c"] [] [CheckOnly]
optSeparator,
MkOpt ["--version", "-v"] [] [Version]
(Just "Display version string"),
MkOpt ["--help", "-h", "-?"] [] [Help]
MkOpt ["--help", "-h", "-?"] [Optional "topic"] (\ tp => [Help (tp >>= recogniseHelpTopic)])
(Just "Display help text"),
-- Internal debugging options

View File

@ -16,7 +16,7 @@ import Libraries.Data.StringMap
import Libraries.Data.String.Extra
import Libraries.Data.ANameMap
import Idris.DocString
import Idris.Doc.String
import Idris.Syntax
import Idris.Elab.Implementation
@ -69,6 +69,12 @@ import Libraries.Data.String.Extra
public export
data Side = LHS | AnyExpr
export
Eq Side where
LHS == LHS = True
AnyExpr == AnyExpr = True
_ == _ = False
export
extendSyn : {auto s : Ref Syn SyntaxInfo} ->
SyntaxInfo -> Core ()
@ -190,24 +196,24 @@ mutual
= if lowerFirst nm || nm == "_"
then do whenJust (isConcreteFC prefFC) \nfc
=> addSemanticDecorations [(nfc, Bound, Just n)]
pure $ ILam fc rig !(traverse (desugar side ps) p)
(Just n) !(desugarB side ps argTy)
!(desugar side (n :: ps) scope)
else pure $ ILam EmptyFC rig !(traverse (desugar side ps) p)
(Just (MN "lamc" 0)) !(desugarB side ps argTy) $
pure $ ILam fc rig !(traverse (desugar AnyExpr ps) p)
(Just n) !(desugarB AnyExpr ps argTy)
!(desugar AnyExpr (n :: ps) scope)
else pure $ ILam EmptyFC rig !(traverse (desugar AnyExpr ps) p)
(Just (MN "lamc" 0)) !(desugarB AnyExpr ps argTy) $
ICase fc (IVar EmptyFC (MN "lamc" 0)) (Implicit fc False)
[snd !(desugarClause ps True (MkPatClause fc pat scope []))]
desugarB side ps (PLam fc rig p (PRef _ n@(MN _ _)) argTy scope)
= pure $ ILam fc rig !(traverse (desugar side ps) p)
(Just n) !(desugarB side ps argTy)
!(desugar side (n :: ps) scope)
= pure $ ILam fc rig !(traverse (desugar AnyExpr ps) p)
(Just n) !(desugarB AnyExpr ps argTy)
!(desugar AnyExpr (n :: ps) scope)
desugarB side ps (PLam fc rig p (PImplicit _) argTy scope)
= pure $ ILam fc rig !(traverse (desugar side ps) p)
Nothing !(desugarB side ps argTy)
!(desugar side ps scope)
= pure $ ILam fc rig !(traverse (desugar AnyExpr ps) p)
Nothing !(desugarB AnyExpr ps argTy)
!(desugar AnyExpr ps scope)
desugarB side ps (PLam fc rig p pat argTy scope)
= pure $ ILam EmptyFC rig !(traverse (desugar side ps) p)
(Just (MN "lamc" 0)) !(desugarB side ps argTy) $
= pure $ ILam EmptyFC rig !(traverse (desugar AnyExpr ps) p)
(Just (MN "lamc" 0)) !(desugarB AnyExpr ps argTy) $
ICase fc (IVar EmptyFC (MN "lamc" 0)) (Implicit fc False)
[snd !(desugarClause ps True (MkPatClause fc pat scope []))]
desugarB side ps (PLet fc rig (PRef prefFC n) nTy nVal scope [])
@ -321,7 +327,10 @@ mutual
desugarB side ps (PDotted fc x)
= pure $ IMustUnify fc UserDotted !(desugarB side ps x)
desugarB side ps (PImplicit fc) = pure $ Implicit fc True
desugarB side ps (PInfer fc) = pure $ Implicit fc False
desugarB side ps (PInfer fc)
= do when (side == LHS) $
throw (GenericMsg fc "? is not a valid pattern")
pure $ Implicit fc False
desugarB side ps (PMultiline fc indent lines)
= addFromString fc !(expandString side ps fc !(trimMultiline fc indent lines))
desugarB side ps (PString fc strs)
@ -344,6 +353,8 @@ mutual
pure val
desugarB side ps (PList fc nilFC args)
= expandList side ps nilFC args
desugarB side ps (PSnocList fc nilFC args)
= expandSnocList side ps nilFC (reverse args)
desugarB side ps (PPair fc l r)
= do l' <- desugarB side ps l
r' <- desugarB side ps r
@ -439,6 +450,18 @@ mutual
= pure $ apply (IVar consFC (UN "::"))
[!(desugarB side ps x), !(expandList side ps nilFC xs)]
expandSnocList
: {auto s : Ref Syn SyntaxInfo} ->
{auto b : Ref Bang BangData} ->
{auto c : Ref Ctxt Defs} ->
{auto u : Ref UST UState} ->
{auto m : Ref MD Metadata} ->
Side -> List Name -> (nilFC : FC) -> List (FC, PTerm) -> Core RawImp
expandSnocList side ps nilFC [] = pure (IVar nilFC (UN "Lin"))
expandSnocList side ps nilFC ((consFC, x) :: xs)
= pure $ apply (IVar consFC (UN ":<"))
[!(expandSnocList side ps nilFC xs) , !(desugarB side ps x)]
addFromString : {auto c : Ref Ctxt Defs} ->
FC -> RawImp -> Core RawImp
addFromString fc tm

View File

@ -12,7 +12,7 @@ import Libraries.Text.PrettyPrint.Prettyprinter
import Libraries.Text.PrettyPrint.Prettyprinter.Render.HTML
import Libraries.Text.PrettyPrint.Prettyprinter.SimpleDocTree
import Idris.DocString
import Idris.Doc.String
import Idris.Package.Types
import Idris.Pretty
import Idris.Version

View File

@ -1,4 +1,4 @@
module Idris.DocString
module Idris.Doc.String
import Core.Context
import Core.Context.Log
@ -233,25 +233,59 @@ getDocsForName fc n
, annotate Declarations $ vcat $ map (indent 2) docs]]
pure (vcat (params ++ constraints ++ meths ++ insts))
getFieldDoc : Name -> Core (Doc IdrisDocAnn)
getFieldDoc nm
= do syn <- get Syn
defs <- get Ctxt
Just def <- lookupCtxtExact nm (gamma defs)
-- should never happen, since we know that the DCon exists:
| Nothing => pure Empty
ty <- resugar [] =<< normaliseHoles defs [] (type def)
let prettyName = pretty (nameRoot nm)
let projDecl = hsep [ fun nm prettyName, colon, prettyTerm ty ]
let [(_, str)] = lookupName nm (docstrings syn)
| _ => pure projDecl
pure $ annotate (Decl nm)
$ vcat [ projDecl
, annotate DocStringBody $ vcat (reflowDoc str)
]
getFieldsDoc : Name -> Core (List (Doc IdrisDocAnn))
getFieldsDoc recName
= do let (Just ns, n) = displayName recName
| _ => pure []
let recNS = ns <.> mkNamespace n
defs <- get Ctxt
let fields = getFieldNames (gamma defs) recNS
syn <- get Syn
case fields of
[] => pure []
[proj] => pure [header "Projection" <++> annotate Declarations !(getFieldDoc proj)]
projs => pure [vcat [header "Projections"
, annotate Declarations $
vcat $ map (indent 2) $ !(traverse getFieldDoc projs)]]
getExtra : Name -> GlobalDef -> Core (List (Doc IdrisDocAnn))
getExtra n d
= do syn <- get Syn
let [] = lookupName n (ifaces syn)
| [ifacedata] => pure <$> getIFaceDoc ifacedata
| _ => pure [] -- shouldn't happen, we've resolved ambiguity by now
case definition d of
PMDef _ _ _ _ _
=> pure [showTotal n (totality d)]
TCon _ _ _ _ _ _ cons _
=> do let tot = [showTotal n (totality d)]
cdocs <- traverse (getDConDoc <=< toFullNames) cons
let cdoc = case cdocs of
[] => []
[doc] => [header "Constructor" <++> annotate Declarations doc]
docs => [vcat [header "Constructors"
, annotate Declarations $ vcat $ map (indent 2) docs]]
pure (tot ++ cdoc)
_ => pure []
getExtra n d = do
do syn <- get Syn
let [] = lookupName n (ifaces syn)
| [ifacedata] => pure <$> getIFaceDoc ifacedata
| _ => pure [] -- shouldn't happen, we've resolved ambiguity by now
case definition d of
PMDef _ _ _ _ _ => pure [showTotal n (totality d)]
TCon _ _ _ _ _ _ cons _ =>
do let tot = [showTotal n (totality d)]
cdocs <- traverse (getDConDoc <=< toFullNames) cons
cdoc <- case cdocs of
[] => pure []
[doc] => pure
$ (header "Constructor" <++> annotate Declarations doc)
:: !(getFieldsDoc n)
docs => pure [vcat [header "Constructors"
, annotate Declarations $
vcat $ map (indent 2) docs]]
pure (tot ++ cdoc)
_ => pure []
showCategory : GlobalDef -> Doc IdrisDocAnn -> Doc IdrisDocAnn
showCategory d = case definition d of
@ -287,6 +321,7 @@ getDocsForPTerm (PPrimVal _ constant) = getDocsForPrimitive constant
getDocsForPTerm (PType _) = pure ["Type : Type\n\tThe type of all types is Type. The type of Type is Type."]
getDocsForPTerm (PString _ _) = pure ["String Literal\n\tDesugars to a fromString call"]
getDocsForPTerm (PList _ _ _) = pure ["List Literal\n\tDesugars to (::) and Nil"]
getDocsForPTerm (PSnocList _ _ _) = pure ["SnocList Literal\n\tDesugars to (:<) and Empty"]
getDocsForPTerm (PPair _ _ _) = pure ["Pair Literal\n\tDesugars to MkPair or Pair"]
getDocsForPTerm (PDPair _ _ _ _ _) = pure ["Dependant Pair Literal\n\tDesugars to MkDPair or DPair"]
getDocsForPTerm (PUnit _) = pure ["Unit Literal\n\tDesugars to MkUnit or Unit"]

View File

@ -247,9 +247,12 @@ quitOpts [] = pure True
quitOpts (Version :: _)
= do putStrLn versionMsg
pure False
quitOpts (Help :: _)
quitOpts (Help Nothing :: _)
= do putStrLn usage
pure False
quitOpts (Help (Just HelpLogging) :: _)
= do putStrLn helpTopics
pure False
quitOpts (ShowPrefix :: _)
= do putStrLn yprefix
pure False

View File

@ -49,6 +49,7 @@ toStrUpdate (UN n, term)
bracket : PTerm -> PTerm
bracket tm@(PRef _ _) = tm
bracket tm@(PList _ _ _) = tm
bracket tm@(PSnocList _ _ _) = tm
bracket tm@(PPair _ _ _) = tm
bracket tm@(PUnit _) = tm
bracket tm@(PComprehension _ _ _) = tm

View File

@ -8,7 +8,7 @@ import Core.TT
import Idris.REPL
import Idris.Syntax
import Idris.DocString
import Idris.Doc.String
import Idris.IDEMode.Commands
import Data.List

View File

@ -30,7 +30,7 @@ import Libraries.Utils.Path
import Idris.CommandLine
import Idris.Doc.HTML
import Idris.DocString
import Idris.Doc.String
import Idris.ModTree
import Idris.ProcessIdr
import Idris.REPL

View File

@ -384,7 +384,7 @@ mutual
decorateKeywords fname xs
pure (PRange fc (fst rstate) (snd rstate) y.val)
listExpr : FileName -> WithBounds t -> IndentInfo -> Rule PTerm
listExpr : FileName -> WithBounds () -> IndentInfo -> Rule PTerm
listExpr fname s indents
= do b <- bounds (do ret <- expr pnowith fname indents
decoratedSymbol fname "|"
@ -407,6 +407,26 @@ mutual
nilFC = if null xs then fc else boundToFC fname b
in PList fc nilFC (map (\ t => (boundToFC fname t, t.val)) xs))
snocListExpr : FileName -> WithBounds () -> IndentInfo -> Rule PTerm
snocListExpr fname s indents
= {- TODO: comprehension -}
do mHeadTail <- optional $ do
hd <- many $ do x <- expr pdef fname indents
b <- bounds (symbol ",")
pure (x <$ b)
tl <- expr pdef fname indents
pure (hd, tl)
{- TODO: reverse ranges -}
b <- bounds (symbol "]")
pure $
let xs : List (WithBounds PTerm)
= case mHeadTail of
Nothing => []
Just (hd,tl) => hd ++ [ tl <$ b]
fc = boundToFC fname (mergeBounds s b)
nilFC = ifThenElse (null xs) fc (boundToFC fname s)
in PSnocList fc nilFC (map (\ t => (boundToFC fname t, t.val)) xs) --)
nonEmptyTuple : FileName -> WithBounds t -> IndentInfo -> PTerm -> Rule PTerm
nonEmptyTuple fname s indents e
= do vals <- some $ do b <- bounds (symbol ",")
@ -492,7 +512,9 @@ mutual
pure (PUnquote (boundToFC fname b) b.val)
<|> do start <- bounds (symbol "(")
bracketedExpr fname start indents
<|> do start <- bounds (symbol "[")
<|> do start <- bounds (symbol "[<")
snocListExpr fname start indents
<|> do start <- bounds (symbol "[>" <|> symbol "[")
listExpr fname start indents
<|> do b <- bounds (decoratedSymbol fname "!" *> simpleExpr fname indents)
pure (PBang (virtualiseFC $ boundToFC fname b) b.val)

View File

@ -306,6 +306,8 @@ mutual
go d (PBang _ tm) = "!" <+> go d tm
go d (PIdiom _ tm) = enclose (pretty "[|") (pretty "|]") (go startPrec tm)
go d (PList _ _ xs) = brackets (group $ align $ vsep $ punctuate comma (go startPrec . snd <$> xs))
go d (PSnocList _ _ xs) = brackets {ldelim = "[<"}
(group $ align $ vsep $ punctuate comma (go startPrec . snd <$> xs))
go d (PPair _ l r) = group $ parens (go startPrec l <+> comma <+> line <+> go startPrec r)
go d (PDPair _ _ l (PImplicit _) r) = group $ parens (go startPrec l <++> pretty "**" <+> line <+> go startPrec r)
go d (PDPair _ _ l ty r) = group $ parens (go startPrec l <++> colon <++> go startPrec ty <++> pretty "**" <+> line <+> go startPrec r)

View File

@ -29,7 +29,7 @@ import Core.Unify
import Parser.Unlit
import Idris.Desugar
import Idris.DocString
import Idris.Doc.String
import Idris.Error
import Idris.IDEMode.CaseSplit
import Idris.IDEMode.Commands

View File

@ -9,7 +9,7 @@ import Core.TT
import Core.Unify
import Core.UnifyState
import Idris.DocString
import Idris.Doc.String
import Idris.Error
import Idris.IDEMode.Commands
import Idris.IDEMode.Holes

View File

@ -16,7 +16,7 @@ import Core.TT
import Core.Unify
import Idris.Desugar
import Idris.DocString
import Idris.Doc.String
import Idris.Error
import Idris.IDEMode.CaseSplit
import Idris.IDEMode.Commands

View File

@ -48,6 +48,7 @@ addBracket fc tm = if needed tm then PBracketed fc tm else tm
needed (PUnit _) = False
needed (PComprehension _ _ _) = False
needed (PList _ _ _) = False
needed (PSnocList _ _ _) = False
needed (PPrimVal _ _) = False
needed tm = True
@ -125,11 +126,16 @@ mutual
"===" => pure $ PEq fc (unbracket l) (unbracket r)
"~=~" => pure $ PEq fc (unbracket l) (unbracket r)
_ => Nothing
else if nameRoot nm == "::"
then case sugarApp (unbracket r) of
PList fc nilFC xs => pure $ PList fc nilFC ((opFC, unbracketApp l) :: xs)
_ => Nothing
else Nothing
else case nameRoot nm of
"::" => case sugarApp (unbracket r) of
PList fc nilFC xs => pure $ PList fc nilFC ((opFC, unbracketApp l) :: xs)
_ => Nothing
":<" => case sugarApp (unbracket r) of
PSnocList fc nilFC xs => pure $ PSnocList fc nilFC
-- use a snoc list here in a future version
(xs ++ [(opFC, unbracketApp l)])
_ => Nothing
_ => Nothing
sugarAppM tm =
-- refolding natural numbers if the expression is a constant
case extractNat 0 tm of
@ -141,9 +147,10 @@ mutual
"Unit" => pure $ PUnit fc
"MkUnit" => pure $ PUnit fc
_ => Nothing
else if nameRoot nm == "Nil"
then pure $ PList fc fc []
else Nothing
else case nameRoot nm of
"Nil" => pure $ PList fc fc []
"Lin" => pure $ PSnocList fc fc []
_ => Nothing
_ => Nothing
||| Put the special names (Nil, ::, Pair, Z, S, etc.) back as syntax

View File

@ -96,7 +96,8 @@ mutual
PBang : FC -> PTerm -> PTerm
PIdiom : FC -> PTerm -> PTerm
PList : (full, nilFC : FC) -> List (FC, PTerm) -> PTerm
-- ^ location of the conses
-- ^ v location of the conses/snocs
PSnocList : (full, nilFC : FC) -> List ((FC, PTerm)) -> PTerm
PPair : FC -> PTerm -> PTerm -> PTerm
PDPair : (full, opFC : FC) -> PTerm -> PTerm -> PTerm -> PTerm
PUnit : FC -> PTerm
@ -159,6 +160,7 @@ mutual
getPTermLoc (PBang fc _) = fc
getPTermLoc (PIdiom fc _) = fc
getPTermLoc (PList fc _ _) = fc
getPTermLoc (PSnocList fc _ _) = fc
getPTermLoc (PPair fc _ _) = fc
getPTermLoc (PDPair fc _ _ _ _) = fc
getPTermLoc (PUnit fc) = fc
@ -624,6 +626,8 @@ mutual
showPrec d (PIdiom _ tm) = "[|" ++ showPrec d tm ++ "|]"
showPrec d (PList _ _ xs)
= "[" ++ showSep ", " (map (showPrec d . snd) xs) ++ "]"
showPrec d (PSnocList _ _ xs)
= "[<" ++ showSep ", " (map (showPrec d . snd) xs) ++ "]"
showPrec d (PPair _ l r) = "(" ++ showPrec d l ++ ", " ++ showPrec d r ++ ")"
showPrec d (PDPair _ _ l (PImplicit _) r) = "(" ++ showPrec d l ++ " ** " ++ showPrec d r ++ ")"
showPrec d (PDPair _ _ l ty r) = "(" ++ showPrec d l ++ " : " ++ showPrec d ty ++
@ -986,6 +990,9 @@ mapPTermM f = goPTerm where
goPTerm (PList fc nilFC xs) =
PList fc nilFC <$> goPairedPTerms xs
>>= f
goPTerm (PSnocList fc nilFC xs) =
PSnocList fc nilFC <$> goPairedPTerms xs
>>= f
goPTerm (PPair fc x y) =
PPair fc <$> goPTerm x
<*> goPTerm y

View File

@ -327,6 +327,18 @@ export
neutral = empty
treeFilterBy : (Key -> Bool) -> Tree n v -> NameMap v
treeFilterBy test = loop empty where
loop : NameMap v -> Tree _ v -> NameMap v
loop acc (Leaf k v)
= let True = test k | _ => acc in
insert k v acc
loop acc (Branch2 t1 _ t2)
= loop (loop acc t1) t2
loop acc (Branch3 t1 _ t2 _ t3)
= loop (loop (loop acc t1) t2) t3
treeFilterByM : Monad m => (Key -> m Bool) -> Tree n v -> m (NameMap v)
treeFilterByM test = loop empty where
@ -342,6 +354,11 @@ treeFilterByM test = loop empty where
acc <- loop acc t2
loop acc t3
export
filterBy : (Name -> Bool) -> NameMap v -> NameMap v
filterBy test Empty = Empty
filterBy test (M _ t) = treeFilterBy test t
export
filterByM : Monad m => (Name -> m Bool) -> NameMap v -> m (NameMap v)
filterByM test Empty = pure Empty

View File

@ -22,6 +22,7 @@ data StringIterator : String -> Type where [external]
-- to avoid subverting the linearity guarantees of withString.
%foreign
"scheme:blodwen-string-iterator-new"
"C:stringIteratorNew"
"javascript:stringIterator:new"
private
fromString : (str : String) -> StringIterator str
@ -49,6 +50,7 @@ data UnconsResult : String -> Type where
-- (e.g. byte offset into an UTF-8 string).
%foreign
"scheme:blodwen-string-iterator-next"
"C:stringIteratorNext"
"javascript:stringIterator:next"
export
uncons : (str : String) -> (1 it : StringIterator str) -> UnconsResult str

View File

@ -101,8 +101,10 @@ angles : Doc ann -> Doc ann
angles = enclose langle rangle
export
brackets : Doc ann -> Doc ann
brackets = enclose lbracket rbracket
brackets : {default lbracket ldelim : Doc ann} ->
{default rbracket rdelim : Doc ann} ->
Doc ann -> Doc ann
brackets {ldelim, rdelim} = enclose ldelim rdelim
export
braces : Doc ann -> Doc ann

View File

@ -151,6 +151,27 @@ getTag {b}
-- Some useful types from the prelude
export
[Wasteful] TTC Int where
toBuf b val
= do chunk <- get Bin
if avail chunk >= 8
then
do coreLift $ setInt (buf chunk) (loc chunk) val
put Bin (appended 8 chunk)
else do chunk' <- extendBinary 8 chunk
coreLift $ setInt (buf chunk') (loc chunk') val
put Bin (appended 8 chunk')
fromBuf b
= do chunk <- get Bin
if toRead chunk >= 8
then
do val <- coreLift $ getInt (buf chunk) (loc chunk)
put Bin (incLoc 8 chunk)
pure val
else throw (TTCError (EndOfBuffer ("Int " ++ show (loc chunk, size chunk))))
export
TTC Int where
toBuf b val

View File

@ -5,7 +5,7 @@ import System.FFI
%default total
libterm : String -> String
libterm s = "C:" ++ s ++ ", libidris2_support"
libterm s = "C:" ++ s ++ ", libidris2_support, idris_term.h"
%foreign libterm "idris2_setupTerm"
prim__setupTerm : PrimIO ()

View File

@ -219,7 +219,7 @@ symbols = [",", ";", "_", "`"]
export
groupSymbols : List String
groupSymbols = [".(", -- for things such as Foo.Bar.(+)
"@{", "[|", "(", "{", "[", "`(", "`{{", "`["]
"@{", "[|", "(", "{", "[<", "[>", "[", "`(", "`{{", "`["]
export
groupClose : String -> String
@ -228,6 +228,8 @@ groupClose "@{" = "}"
groupClose "[|" = "|]"
groupClose "(" = ")"
groupClose "[" = "]"
groupClose "[<" = "]"
groupClose "[>" = "]"
groupClose "{" = "}"
groupClose "`(" = ")"
groupClose "`{{" = "}}"

View File

@ -33,17 +33,25 @@ localHelper {vars} nest env nestdecls_in func
= do est <- get EST
let f = defining est
defs <- get Ctxt
let vis = case !(lookupCtxtExact (Resolved (defining est)) (gamma defs)) of
Just gdef => visibility gdef
Nothing => Public
gdef <- lookupCtxtExact (Resolved (defining est)) (gamma defs)
let vis = maybe Public visibility gdef
let mult = maybe linear GlobalDef.multiplicity gdef
-- If the parent function is public, the nested definitions need
-- to be public too
let nestdecls =
let nestdeclsVis =
if vis == Public
then map setPublic nestdecls_in
else nestdecls_in
let defNames = definedInBlock emptyNS nestdecls
-- If the parent function is erased, then the nested definitions
-- will be erased too
let nestdeclsMult =
if mult == erased
then map setErased nestdeclsVis
else nestdeclsVis
let defNames = definedInBlock emptyNS nestdeclsMult
names' <- traverse (applyEnv f)
(nub defNames) -- binding names must be unique
-- fixes bug #115
@ -60,7 +68,7 @@ localHelper {vars} nest env nestdecls_in func
-- everything
let oldhints = localHints defs
let nestdecls = map (updateName nest') nestdecls
let nestdecls = map (updateName nest') nestdeclsMult
log "elab.def.local" 20 $ show nestdecls
traverse_ (processDecl [] nest' env') nestdecls
@ -134,6 +142,14 @@ localHelper {vars} nest env nestdecls_in func
= INamespace fc ps (map setPublic decls)
setPublic d = d
setErased : ImpDecl -> ImpDecl
setErased (IClaim fc _ v opts ty) = IClaim fc erased v opts ty
setErased (IParameters fc ps decls)
= IParameters fc ps (map setErased decls)
setErased (INamespace fc ps decls)
= INamespace fc ps (map setErased decls)
setErased d = d
export
checkLocal : {vars : _} ->
{auto c : Ref Ctxt Defs} ->

View File

@ -854,6 +854,7 @@ processDef opts nest env fc n_in cs_in
-- Dynamically rebind default totality requirement to this function's totality requirement
-- and use this requirement when processing `with` blocks
log "declare.def" 5 $ "Traversing clauses of " ++ show n ++ " with mult " ++ show mult
let treq = fromMaybe !getDefaultTotalityOption (findSetTotal (flags gdef))
cs <- withTotality treq $
traverse (checkClause mult (visibility gdef) treq

View File

@ -19,6 +19,7 @@ import TTImp.TTImp
import TTImp.Utils
import Data.List
import Data.Strings
import Libraries.Data.NameMap
%default covering
@ -267,7 +268,7 @@ processType {vars} eopts nest env fc rig vis opts (MkImpTy tfc nameFC n_in ty_ra
addNameLoc nameFC n
log "declare.type" 1 $ "Processing " ++ show n
log "declare.type" 5 $ "Checking type decl " ++ show n ++ " : " ++ show ty_raw
log "declare.type" 5 $ unwords ["Checking type decl:", show rig, show n, ":", show ty_raw]
idx <- resolveName n
-- Check 'n' is undefined

View File

@ -360,7 +360,7 @@ mutual
export
Show ImpDecl where
show (IClaim _ _ _ opts ty) = show opts ++ " " ++ show ty
show (IClaim _ c _ opts ty) = show opts ++ " " ++ show c ++ " " ++ show ty
show (IData _ _ d) = show d
show (IDef _ n cs) = "(%def " ++ show n ++ " " ++ show cs ++ ")"
show (IParameters _ ps ds)
@ -1179,9 +1179,5 @@ logRaw : {auto c : Ref Ctxt Defs} ->
{auto 0 _ : KnownTopic s} ->
Nat -> Lazy String -> RawImp -> Core ()
logRaw str n msg tm
= do opts <- getSession
let lvl = mkLogLevel (logEnabled opts) str n
if keepLog lvl (logEnabled opts) (logLevel opts)
then do coreLift $ putStrLn $ "LOG " ++ show lvl ++ ": " ++ msg
++ ": " ++ show tm
else pure ()
= when !(logging str n) $
do logString str n (msg ++ ": " ++ show tm)

217
support/c/idris_signal.c Normal file
View File

@ -0,0 +1,217 @@
#include "idris_signal.h"
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#ifdef _WIN32
#include <windows.h>
HANDLE ghMutex;
#else
#include <pthread.h>
static pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
// ring buffer style storage for collected
// signals.
static int signal_buf_cap = 0;
static int signals_in_buf = 0;
static int signal_buf_next_read_idx = 0;
static int *signal_buf = NULL;
void _init_buf() {
if (signal_buf == NULL) {
signal_buf_cap = 10;
signal_buf = malloc(sizeof(int) * signal_buf_cap);
}
}
// returns truthy or falsey (1 or 0)
int _lock() {
#ifdef _WIN32
if (ghMutex == NULL) {
ghMutex = CreateMutex(
NULL,
FALSE,
NULL);
}
DWORD dwWaitResult = WaitForSingleObject(
ghMutex,
INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
return 1;
case WAIT_ABANDONED:
return 0;
}
#else
pthread_mutex_lock(&sig_mutex);
return 1;
#endif
}
void _unlock() {
#ifdef _WIN32
ReleaseMutex(ghMutex);
#else
pthread_mutex_unlock(&sig_mutex);
#endif
}
void _collect_signal(int signum);
void _collect_signal_core(int signum) {
_init_buf();
// FIXME: allow for adjusting capacity of signal buffer
// instead of ignoring new signals when at capacity.
if (signals_in_buf == signal_buf_cap) {
return;
}
int write_idx = (signal_buf_next_read_idx + signals_in_buf) % signal_buf_cap;
signal_buf[write_idx] = signum;
signals_in_buf += 1;
#ifdef _WIN32
//re-instate signal handler
signal(signum, _collect_signal);
#endif
}
void _collect_signal(int signum) {
if (_lock()) {
_collect_signal_core(signum);
_unlock();
}
}
#ifndef _WIN32
inline struct sigaction _simple_handler(void (*handler)(int)) {
struct sigaction new_action;
new_action.sa_handler = handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
return new_action;
}
#endif
int ignore_signal(int signum) {
#ifdef _WIN32
return signal(signum, SIG_IGN) == SIG_ERR ? -1 : 0;
#else
struct sigaction handler = _simple_handler(SIG_IGN);
return sigaction(signum, &handler, NULL);
#endif
}
int default_signal(int signum) {
#ifdef _WIN32
return signal(signum, SIG_DFL) == SIG_ERR ? -1 : 0;
#else
struct sigaction handler = _simple_handler(SIG_DFL);
return sigaction(signum, &handler, NULL);
#endif
}
int collect_signal(int signum) {
#ifdef _WIN32
return signal(signum, _collect_signal) == SIG_ERR ? -1 : 0;
#else
struct sigaction handler = _simple_handler(_collect_signal);
return sigaction(signum, &handler, NULL);
#endif
}
int handle_next_collected_signal() {
if (_lock()) {
if (signals_in_buf == 0) {
return -1;
}
int next = signal_buf[signal_buf_next_read_idx];
signal_buf_next_read_idx = (signal_buf_next_read_idx + 1) % signal_buf_cap;
signals_in_buf -= 1;
_unlock();
return next;
}
return -1;
}
int raise_signal(int signum) {
return raise(signum);
}
int send_signal(int pid, int signum) {
#ifdef _WIN32
return raise_signal(signum);
#else
return kill(pid, signum);
#endif
}
int sighup() {
#ifdef _WIN32
return -1;
#else
return SIGHUP;
#endif
}
int sigint() {
return SIGINT;
}
int sigabrt() {
return SIGABRT;
}
int sigquit() {
#ifdef _WIN32
return -1;
#else
return SIGQUIT;
#endif
}
int sigill() {
return SIGILL;
}
int sigsegv() {
return SIGSEGV;
}
int sigtrap() {
#ifdef _WIN32
return -1;
#else
return SIGTRAP;
#endif
}
int sigfpe() {
return SIGFPE;
}
int sigusr1() {
#ifdef _WIN32
return -1;
#else
return SIGUSR1;
#endif
}
int sigusr2() {
#ifdef _WIN32
return -1;
#else
return SIGUSR2;
#endif
}

46
support/c/idris_signal.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef __IDRIS_SIGNAL_H
#define __IDRIS_SIGNAL_H
#include <signal.h>
int ignore_signal(int signum);
int default_signal(int signum);
// Add another signal that should be collected. All collected signals
// should be handled at the earliest convenience by calling
// get_next_pending_signal().
int collect_signal(int signum);
// when collecting signals you can get the next one that has been
// collected but not yet handled with this function.
// Returns -1 to indicate no pending signals.
int handle_next_collected_signal();
// Raise a signal to the current process.
int raise_signal(int signum);
// Send a signal to another process.
// IMPORTANT: On Windows you cannot send to other processes
// so this is implemented as `raise_signal()` which sends the signal
// to the calling process.
int send_signal(int pid, int signum);
// available signals in a cross-platform compatible way;
// omits SIGKILL and SIGSTOP because those signals cannot
// be handled in a custom way.
int sigint();
int sigill();
int sigsegv();
int sigfpe();
int sigabrt();
// Following unavailable in Windows and defined as -1 in
// this implementation so that they can be unconditionally
// defined in Idris.
int sighup();
int sigquit();
int sigtrap();
int sigusr1();
int sigusr2();
#endif

View File

@ -8,6 +8,9 @@
#include <stdlib.h>
#include <unistd.h>
int _argc;
char **_argv;
#ifdef _WIN32
extern char **_environ;
#include "windows/win_utils.h"
@ -80,6 +83,19 @@ int idris2_time() {
return time(NULL); // RTS needs to have 32 bit integers at least
}
void idris2_setArgs(int argc, char *argv[]) {
_argc = argc;
_argv = argv;
}
int idris2_getArgCount() {
return _argc;
}
char* idris2_getArg(int n) {
return _argv[n];
}
char* idris2_getEnvPair(int i) {
return *(environ + i);
}
@ -100,6 +116,14 @@ int idris2_unsetenv(const char *name) {
#endif
}
int idris2_getPID() {
#ifdef _WIN32
return win32_getPID();
#else
return getpid();
#endif
}
// get the number of processors configured
long idris2_getNProcessors() {
#ifdef _WIN32

View File

@ -17,8 +17,13 @@ void idris2_sleep(int sec);
void idris2_usleep(int usec);
int idris2_time();
int idris2_getArgCount();
void idris2_setArgs(int argc, char *argv[]);
char* idris2_getArg(int n);
char* idris2_getEnvPair(int i);
int idris2_getPID();
long idris2_getNProcessors();
#endif

View File

@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
// THis file exists to avoid clashes between windows.h and idris_rts.h
//
@ -83,6 +84,10 @@ int win32_getErrno() {
return GetLastError();
}
int win32_getPID() {
return _getpid();
}
typedef BOOL (WINAPI *LPFN_GLPI)(
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
PDWORD);

View File

@ -11,5 +11,6 @@ void win32_sleep(int ms);
int win32_modenv(const char* name, const char* value, int overwrite);
int win32_getErrno();
int win32_getPID();
long win32_getNProcessors();

View File

@ -186,6 +186,9 @@
(define (blodwen-buffer-size buf)
(bytevector-length buf))
(define (blodwen-buffer-free buf)
(void)) ; Rely on built-in memory management
(define (blodwen-buffer-setbyte buf loc val)
(bytevector-u8-set! buf loc val))

View File

@ -179,6 +179,9 @@
(define (blodwen-buffer-size buf)
(bytevector-length buf))
(define (blodwen-buffer-free buf)
(void)) ; Rely on built-in memory management
(define (blodwen-buffer-setbyte buf loc val)
(bytevector-u8-set! buf loc val))

View File

@ -10,6 +10,7 @@
#include "mathFunctions.h"
#include "runtime.h"
#include "stringOps.h"
#include "clock.h"
#include "casts.h"
#include "conCaseHelper.h"
#include "prim.h"

View File

@ -22,7 +22,7 @@ Value *cast_i32_to_Bits16(Value *input)
}
Value *cast_i32_to_Bits32(Value *input)
{
return input;
return newReference(input);
}
Value *cast_i32_to_Bits64(Value *input)
{
@ -97,7 +97,7 @@ Value *cast_i64_to_Bits32(Value *input)
Value *cast_i64_to_Bits64(Value *input)
{
return input;
return newReference(input);
}
Value *cast_i64_to_i32(Value *input)
@ -535,7 +535,7 @@ Value *cast_Bits32_to_Bits64(Value *input)
}
Value *cast_Bits32_to_i32(Value *input)
{
return input;
return newReference(input);
}
Value *cast_Bits32_to_i64(Value *input)
{
@ -617,7 +617,7 @@ Value *cast_Bits64_to_i32(Value *input)
}
Value *cast_Bits64_to_i64(Value *input)
{
return input;
return newReference(input);
}
Value *cast_Bits64_to_double(Value *input)
{

52
support/refc/clock.c Normal file
View File

@ -0,0 +1,52 @@
#include "clock.h"
#define NSEC_PER_SEC 1000000000
#define CLOCKS_PER_NSEC ((float)(CLOCKS_PER_SEC / NSEC_PER_SEC))
Value *clockTimeMonotonic()
{
return clockTimeUtc();
}
Value *clockTimeUtc()
{
return (Value *)makeInt64(time(NULL) * NSEC_PER_SEC);
}
Value *clockTimeProcess()
{
uint64_t time_ns = clock() / CLOCKS_PER_NSEC;
return (Value *)makeInt64(time_ns);
}
Value *clockTimeThread()
{
return clockTimeProcess();
}
Value *clockTimeGcCpu()
{
return NULL;
}
Value *clockTimeGcReal()
{
return NULL;
}
int clockValid(Value *clock)
{
return clock != NULL;
}
uint64_t clockSecond(Value *clock)
{
uint64_t totalNano = ((Value_Int64 *)clock)->i64;
return totalNano / NSEC_PER_SEC;
}
uint64_t clockNanosecond(Value *clock)
{
uint64_t totalNano = ((Value_Int64 *)clock)->i64;
return totalNano % NSEC_PER_SEC;
}

19
support/refc/clock.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef __IDRIS_CLOCK_H__
#define __IDRIS_CLOCK_H__
#include <time.h>
#include "cBackend.h"
Value *clockTimeMonotonic();
Value *clockTimeUtc();
Value *clockTimeProcess();
Value *clockTimeThread();
Value *clockTimeGcCpu();
Value *clockTimeGcReal();
int clockValid(Value *clock);
uint64_t clockSecond(Value *clock);
uint64_t clockNanosecond(Value *clock);
#endif

View File

@ -76,7 +76,7 @@ typedef struct
typedef struct
{
Value_header header;
char c;
unsigned char c;
} Value_Char;
typedef struct

View File

@ -7,11 +7,6 @@ double unpackDouble(Value *d)
return ((Value_Double *)d)->d;
}
Value *believe_me(Value *a, Value *b, Value *c)
{
return c;
}
/* add */
Value *add_i32(Value *x, Value *y)
{

Some files were not shown because too many files have changed in this diff Show More