...
 
Commits (968)
Clean System Files
*.abc
*.bc
*.o
*.tcl
*.prj
*.prp
*.exe
a.out
* Time Profile.pcl
_Tests
_Tests.*
test:
test-nightly:
before_script:
- install_clean.sh bundle-complete && apt-get update -qq && apt-get install -y -qq build-essential
- install_clean.sh bundle-complete
- apt-get update -qq
- apt-get install -y -qq build-essential git coreutils libmariadb-dev libsnappy-dev libsqlite3-dev
- make -C src/cdeps install
- git clone https://gitlab.science.ru.nl/clean-compiler-and-rts/compiler tests/linux64/compiler
- make -C tests/linux64/compiler/main/Unix
- make -j -C tests/linux64/compiler/backendC/CleanCompilerSources -f Makefile.linux64
- mkdir -p tests/linux64/compiler/backend/Clean\ System\ Files
- ln -fs ../../backendC/CleanCompilerSources/backend.a tests/linux64/compiler/backend/Clean\ System\ Files/backend_library
image: "camilstaps/clean:nightly"
script:
- make -C tests/linux64
- COCLPATH=./compiler make -C tests/linux64 run
- cleantest -r testproperties --options '-IL;Dynamics;-d;src/libraries/OS-Independent;-P;OutputTestEvents;-T;Tests 100000;-T;MaxStringLength 500;-T;Bent;-C;-h;-C;100m;-r' --junit junit.xml
artifacts:
when: always
paths:
- junit.xml
reports:
junit: junit.xml
# Clean documentation
Cloogle indexes documentation of the syntax elements it stores, through
functions in `Clean.Doc`. Docblocks are comments that start with `/**` and have
a leading asterisk on every line (leading whitespace is ignored). The first
part of the docblock is taken as a general description. Below the description,
documentation fields can be added with `@`. Currently, documentation fields
should have only one line.
An example is below:
```clean
/**
* Apply a function to every element in a list.
*
* @param The function
* @param The list
* @result The new list
*/
map :: (a -> b) [a] -> [b]
```
`@result` can be given multiple times for tuples.
For short documentation items, doclines, starting with `//*` can be used. When
documenting a constructor, or record field, they should be placed *after* the
item they document. For example:
```clean
/**
* A date in the Gregorian calendar
*/
:: Date =
{ day :: Int //* The day of the month, starting with 1
, month :: Int //* The month (January is 1)
, year :: Int //* The year
}
```
To add several lines of documentation to a constructor or record field, several
doclines can be used:
```clean
:: MyType
= MyConstructor args // ...
//* This constructor may require some more explanation,
//* which is added on several lines.
```
Doclines can also be added *above* a function, type, or class definition:
```clean
//* The identity function.
id :: .a -> .a
```
## Markup in documentation
Some simple Markdown-inspired markup is allowed in documentation:
- `` `foo` `` renders `foo` in monospaced font.
- Code blocks can be surrounded by `` ``` `` on separate lines. The start of a
code block can indicate the language (for highlighting purposes), as in
`` ```clean ``.
- `{{bar}}` marks `bar` as a defined entity (that can be searched for).
- Double newlines distinguish paragraphs; single newlines are ignored unless
followed by a hyphen.
## Documentation fields
The tables below describe which fields and documentation types can be used for
different syntax elements, and what they should document. An extension, to
document test properties, is discussed below.
What fields are accepted for what syntax elements is defined by the records in
`Clean.Doc`; how they are parsed in the instances of the generic function
`docBlockToDoc`. The below is merely a convenient representation of the same
information.
| | Description | `@param` | `@result` | `@type` | `@var` | `@representation` | `@throws` | `@complexity`
|--------------|-------------|----------|-----------|---------|--------|-------------------|-----------|--------------
| Class | ![][y] | ![][y]<sup>1</sup> | ![][y]<sup>1</sup> | | ![][y] | |
| Class member | ![][y] | ![][y] | ![][y] | | | | ![][y] | ![][y]
| Constructor | ![][y] | | | | | | |
| Function | ![][y] | ![][y] | ![][y] | | | | ![][y] | ![][y]
| Generic | ![][y] | ![][y] | ![][y] | | ![][y] | | |
| Instance | ![][y] | | | | | | |
| Macro | ![][y] | ![][y] | ![][y] | ![][y]<sup>2</sup> | | | |
| Module | ![][y] | | | | | | |
| Record field | ![][y] | | | | | | |
| Type | ![][y] | | | | ![][y] | ![][y], for type synonyms | |
<sup>1: only for shorthand classes like `class zero a :: a`, where there is no
other place for the documentation of the class member.</sup>
<sup>2: for simple macros (depending on what the type deriver in
`Clean.Types.CoclTransform` can do), Cloogle will derive the type if it is not
given.</sup>
| Field | Description
|-------------------|-------------
| `@complexity` | E.g. "O(n log n)".
| `@param` | Parameters of a function(-like). Name a parameter using `@param name: description`.
| `@representation` | The representation of a synonym type.
| `@result` | The result of a function.
| `@return` | A deprecated synonym of `@result`.
| `@throws` | iTasks exceptions that can be thrown.
| `@type` | The type of a macro (without name and `::`).
| `@var` | Type variables of types, classes and generics.
### Property documentation
With [clean-test-properties][]' `testproperties` tool, [Gast][] test programs
can be generated with properties from docblocks. For this, several additional
fields can be used, which are further documented by [clean-test-properties][].
Our [standards](STANDARDS.md) require the use of tabs for indentation and spaces
for outlining. Because with properties code is included in documentation blocks,
using tabs for indentation would lead to tabs after spaces. To avoid this, we
use four spaces in this context instead. For example:
```clean
/**
* @property correctness: A.xs :: Set a:
* minList (toList xs) == findMin xs
*/
```
[clean-test-properties]: https://gitlab.science.ru.nl/clean-and-itasks/clean-test-properties
[Gast]: https://gitlab.science.ru.nl/clean-and-itasks/gast
[y]: http://i.stack.imgur.com/iro5J.png
......@@ -24,15 +24,22 @@ abbreviation should be written using only capitals (e.g. GUI,SQL,HTTP).
Function names should be written in lowerCamelCase. By starting types and
constructors with a capital and functions without one, the difference between
a constructor and a function is immediately clear for the reader of a program.
Generic function names should normally start with `g`, and the next character
should be a capital.
## Module names
For modules, the same guidelines apply as for naming types. Names should be
informative and preferably short. When a library module is not meant for direct
imports by end users, but should only used by experts in modules that for
example provide a more friendly interface, you should prefix the name of that
module with an underscore character (`_`) or place it in a separate `Internal`
submodule.
informative and preferably short.
- When a library module is not meant for direct imports by end users, but
should only used by experts in modules that for example provide a more
friendly interface, you should prefix the name of that module with an
underscore character (`_`) or place it in a separate `Internal` submodule.
- When a module (mainly) provides generic functions for functionality that
could also be reasonably implemented differently, it should be prefixed with
`Gen`.
## Argument order
......@@ -63,11 +70,11 @@ id x = x
```
Several JavaDoc like parameters are supported such as `@param`, `@result`,
`@type`, `@var` and `@representation`. More info about this can be found
[here](https://github.com/clean-cloogle/Cloogle#clean-documentation).
We use `@complexity` for the complexity order. Some other special fields are
used, like `@gin-icon`, but one should be reluctant with inventing new field
names. If there is a general use case, adding it can be discussed.
`@type`, `@var` and `@representation`. More info about this can be found in
[DOCUMENTATION.md](DOCUMENTATION.md). We use `@complexity` for the complexity
order. Some other special fields are used, like `@gin-icon`, but one should be
reluctant with inventing new field names. If there is a general use case,
adding it can be discussed.
## Layout
......@@ -89,12 +96,14 @@ collisions, adhere to the following conventions:
Implementation modules may import anything they like.
## Implementing class instances and generic derives
## Implementing class instances and generic derives
Clean Platform should, where applicable, provide instances for the types it provides for classes defined in StdEnv, Gast, and Platform itself.
The applicable instances for the _general_ classes should be exported in the module of the type and not of the class.
This means that for example the `Functor` instance of `Maybe` should be defined in `Data.Maybe` and not in `Data.Functor`.
For _specific_ classes the instances for types should be exported in submodules.
For example, `JSONEncode` for `Map` should be exported in `Data.Map.JSONEncode` and not in `Data.Map` nor in `Text.JSON`.
For example, `JSONEncode` for `Map` should be exported in `Data.Map.GenJSON` and not in `Data.Map` nor in `Text.GenJSON`.
This rule also holds for types that have multiple valid instances such as the `Monoid` for `Int`.
_general_ classes are:
......@@ -103,15 +112,16 @@ _general_ classes are:
- [ ] `Monoid, Semigroup` from `Data.Monoid`
- [ ] `Monad` from `Control.Monad` and applicable monads from `Control.Monad.*`
- [ ] `Applicative, Alternative` from `Control.Applicative`
- [ ] `gEq{|*|}` from `Data.Generics.GenEq`
- [ ] `gDefault{|*|}` from `Data.Generics.GenDefault`
- [ ] `GenFDomain` from `Data.Generics.GenFDomain`
- [ ] `gEq{|*|}` from `Data.GenEq`
- [ ] `gDefault{|*|}` from `Data.GenDefault`
- [ ] `GenFDomain` from `Data.GenFDomain`
- [ ] everything from `StdOverloaded`
- [ ] ...
_specific_ classes are for example:
- [ ] `JSONEncode, JSONDecode` from `Text.JSON`
- [ ] `ggen, genShow` from `Gast`
- [ ] ...
......
CC=gcc
OBJS:=systemsignal.o
all: $(OBJS)
install: $(OBJS)
mkdir -p ../libraries/OS-Independent/Clean\ System\ Files/
cp -v $(OBJS) ../libraries/OS-Independent/Clean\ System\ Files/
#include <stdlib.h>
#include <signal.h>
static long signal_state[NSIG] = {0};
#ifdef _WIN32
static void signal_handler(int sig)
{
#else
static void signal_handler(int sig, siginfo_t *si, void *unused)
{
(void)si;
(void)unused;
#endif
signal_state[sig] = 1;
}
void signal_install(long signum, long *ok, long *handler)
{
#ifdef _WIN32
*ok = signal(signum, signal_handler) == SIG_ERR;
#else
struct sigaction act;
act.sa_flags = SA_SIGINFO;
sigemptyset(&act.sa_mask);
act.sa_sigaction = signal_handler;
*ok = sigaction(signum, &act, NULL);
#endif
*handler = signum;
}
void signal_poll(long handler, long *ok, long *state, long *handlerr)
{
*ok = 1;
if(0 < handler && handler < NSIG){
*handlerr = handler;
*state = signal_state[handler];
signal_state[handler] = 0;
*ok = 0;
}
}
int signal_ignore(long signum)
{
return signal(signum, SIG_IGN) == SIG_ERR;
}
......@@ -4,6 +4,7 @@ Environments
EnvironmentName: Clean Platform
EnvironmentPaths
Path: {Application}\Libraries\StdEnv
Path: {Application}\Platform\src\libaries\Platform-x86
Path: {Application}\Platform\src\libraries\OS-Independent
Path: {Application}\Platform\src\libraries\OS-Independent\Data
Path: {Application}\Platform\src\libraries\OS-Independent\Database
......
......@@ -4,6 +4,7 @@
Path: {Application}/lib/StdEnv
Path: {Application}/lib/Generics
Path: {Application}/lib/StdLib
Path: {Application}/lib/clean-platform/Platform-x86
Path: {Application}/lib/clean-platform/OS-Independent
Path: {Application}/lib/clean-platform/OS-Independent/Data
Path: {Application}/lib/clean-platform/OS-Independent/Database
......
......@@ -4,6 +4,7 @@
Path: {Application}/lib/StdEnv
Path: {Application}/lib/Generics
Path: {Application}/lib/StdLib
Path: {Application}/lib/clean-platform/Platform-x86
Path: {Application}/lib/clean-platform/OS-Independent
Path: {Application}/lib/clean-platform/OS-Independent/Data
Path: {Application}/lib/clean-platform/OS-Independent/Database
......
module client
import StdEnv
import Data.Error
import Data.Maybe
import Network.IP
import System.Socket
import System.Socket.Ipv4
Start :: *World -> (MaybeOSError String, *World)
Start w
= case socket SocketStream w of
(Error e, w) = (Error e, w)
(Ok sockfd, w)
#! (merr, sockfd) = connect {ipv4_socket_port=8124,ipv4_socket_addr=Just (fromString "127.0.0.1")} sockfd
| isError merr = (liftError merr, w)
#! (merr, sockfd) = recv 128 [] sockfd
| isError merr = (merr, w)
# (Ok msg) = merr
# (merr, w) = close sockfd w
| isError merr = (liftError merr, w)
= (Ok msg, w)
module server
import StdDebug
import StdEnv
import Data.Error
import Data.Maybe
import System.Socket
import System.Socket.Ipv4
Start :: *World -> (MaybeOSError (), *World)
Start w
= case socket SocketStream w of
(Error e, w) = (Error e, w)
(Ok sockfd, w)
#! (merr, sockfd) = bind {ipv4_socket_port=8124,ipv4_socket_addr=Nothing} sockfd
| isError merr = (merr, w)
#! (merr, sockfd) = listen 3 sockfd
| isError merr = (merr, w)
= case accept sockfd of
(Error e, sockfd) = (Error e, w)
(Ok (sock, addr), sockfd)
# (merr, sock) = send "Hello world!" [] sock
| isError merr = (liftError merr, w)
# (merr, w) = close sock w
| isError merr = (merr, w)
# (merr, w) = close sockfd w
| isError merr = (merr, w)
= (Ok (), w)
#include <stdio.h>
#include <stddef.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#endif
int main(void)
{
printf("AF_INET :== %lu\n", AF_INET);
#ifdef linux
printf("AF_UNIX :== %lu\n", AF_UNIX);
#endif
printf("AF_INET6 :== %lu\n", AF_INET6);
printf("AF_IPX :== %lu\n", AF_IPX);
printf("AF_APPLETALK :== %lu\n", AF_APPLETALK);
printf("AF_IRDA :== %lu\n", AF_IRDA);
printf("SOCK_STREAM :== %lu\n", SOCK_STREAM);
printf("SOCK_DGRAM :== %lu\n", SOCK_DGRAM);
printf("MSG_DONTROUTE :== %lu\n", MSG_DONTROUTE);
printf("MSG_OOB :== %lu\n", MSG_OOB);
printf("MSG_PEEK :== %lu\n", MSG_PEEK);
printf("MSG_WAITALL :== %lu\n", MSG_WAITALL);
printf("\nsockaddr_in offsets:\n");
printf("sin_family: %lu\n", offsetof(struct sockaddr_in, sin_family));
printf("sin_port: %lu\n", offsetof(struct sockaddr_in, sin_port));
printf("sin_addr: %lu\n", offsetof(struct sockaddr_in, sin_addr));
printf("in_addr offsets:\n");
printf("s_addr: %lu\n", offsetof(struct in_addr, s_addr));
#ifdef linux
printf("\nsockaddr_un offsets:\n");
printf("sun_family: %lu\n", offsetof(struct sockaddr_un, sun_family));
printf("sun_path: %lu\n", offsetof(struct sockaddr_un, sun_path));
#endif
printf("\nsockaddr_in6 offsets:\n");
printf("sin6_family: %lu\n",
offsetof(struct sockaddr_in6, sin6_family));
printf("sin6_port: %lu\n", offsetof(struct sockaddr_in6, sin6_port));
printf("sin6_flowinfo: %lu\n",
offsetof(struct sockaddr_in6, sin6_flowinfo));
printf("sin6_addr: %lu\n", offsetof(struct sockaddr_in6, sin6_addr));
printf("sin6_scope_id: %lu\n",
offsetof(struct sockaddr_in6, sin6_scope_id));
printf("in6_addr offsets:\n");
printf("s6_addr: %lu\n", offsetof(struct in6_addr, s6_addr));
#ifdef _WIN32
printf("sizeof(WSADATA): %lu\n", sizeof(WSADATA));
#endif
return 0;
}
definition module System.OS
OS_NAME :== "Android (32-bit)"
OS_PATH_SEPARATOR :== '/'
OS_NEWLINE :== "\n"
IF_POSIX_OR_WINDOWS posix windows :== posix
IF_WINDOWS win other :== other
IF_WINDOWS32 win other :== other
IF_WINDOWS64 win other :== other
IF_POSIX posix other :== posix
IF_LINUX linux other :== linux
IF_LINUX32 linux other :== linux
IF_LINUX64 linux other :== other
IF_MAC mac other :== other
IF_ANDROID android other :== android
implementation module System.OS
definition module System._Platform
import System.Platform
//* @type Platform
CURRENT_PLATFORM :== Android32
implementation module System._Platform
definition module System.OS
OS_NAME :== "Android (64-bit)"
OS_PATH_SEPARATOR :== '/'
OS_NEWLINE :== "\n"
IF_POSIX_OR_WINDOWS posix windows :== posix
IF_WINDOWS win other :== other
IF_WINDOWS32 win other :== other
IF_WINDOWS64 win other :== other
IF_POSIX posix other :== posix
IF_LINUX linux other :== linux
IF_LINUX32 linux other :== other
IF_LINUX64 linux other :== linux
IF_MAC mac other :== other
IF_ANDROID android other :== android
implementation module System.OS
definition module System._Platform
import System.Platform
//* @type Platform
CURRENT_PLATFORM :== Android64
implementation module System._Platform
definition module System._Posix
from System._Pointer import :: Pointer
from StdInt import IF_INT_64_OR_32
from System.Time import :: Tm
WNOHANG :== 0x00000001
WUNTRACED :== 0x00000002
MAXPATHLEN :== 1024
DIRENT_D_NAME_OFFSET :== 19
S_IFMT :== 0170000
S_IFIFO :== 0010000
S_IFCHR :== 0020000
S_IFDIR :== 0040000
S_IFBLK :== 0060000
S_IFREG :== 0100000
S_IFLNK :== 0120000
S_IFSOCK :== 0140000
S_IFWHT :== 0160000
STDIN_FILENO :== 0
STDOUT_FILENO :== 1
STDERR_FILENO :== 2
FIONREAD :== 0x541B
F_SETFD :== 2
O_CLOEXEC :== 02000000
//Posix API calls
errno :: !*w -> (!Int,!*w)
strerr :: !Int -> Pointer
stat :: !{#Char} !{#Char} !*w -> (!Int,!*w)
unlink :: !{#Char} !*w -> (!Int,!*w)
fork :: !*w -> (!Int,!*w)
execvp :: !{#Char} !{#Pointer} !*w -> (!Int,!*w)
waitpid :: !Int !{#Int} !Int !*w -> (!Int,!*w)
exit :: !Int !*w -> (!.a,!*w)
getcwd :: !{#Char} !Int !*w -> (!Pointer,!*w)
chdir :: !{#Char} !*w -> (!Int,!*w)
mkdir :: !{#Char} !Int !*w -> (!Int,!*w)
rmdir :: !{#Char} !*w -> (!Int,!*w)
rename :: !{#Char} !{#Char} !*w -> (!Int,!*w)
opendir :: !{#Char} !*w -> (!Pointer,!*w)
closedir :: !Pointer !*w -> (!Int,!*w)
readdir :: !Pointer !*w -> (!Pointer,!*w)
pipe :: !Pointer !*w -> (!Int, !*w)
dup2 :: !Int !Int !*w -> (!Int, !*w)
close :: !Int !*w -> (!Int, !*w)
ioctl :: !Int !Int !Pointer !*w -> (!Int, !*w)
// variant requiring an argument as third parameter
fcntlArg :: !Int !Int !Int !*w -> (!Int, !*w)
read :: !Int !Pointer !Int !*w -> (!Int, !*w)
write :: !Int !{#Char} !Int !*w -> (!Int, !*w)
select_ :: !Int !Pointer !Pointer !Pointer !Pointer !*w -> (!Int, !*w)
kill :: !Int !Int !*w -> (!Int, !*w)
//Memory (impure)
malloc :: !Int -> Pointer
free :: !Pointer -> Int
freeSt :: !Pointer !*w -> *w
memcpy_string_to_pointer :: !Pointer !{#Char} !Int -> Pointer
//Posix datastructures
:: Stat =
{ st_dev :: !Int
, st_ino :: !Int
, st_mode :: !Int
, st_nlink :: !Int
, st_uid :: !Int
, st_gid :: !Int
, st_rdev :: !Int
, st_size :: !Int
, st_blocks :: !Int
, st_blksize :: !Int
, st_ctimespec :: !Int
, st_mtimespec :: !Int
, st_atimespec :: !Int
}
//Mapping to/from byte arrays
unpackStat :: !{#Char} -> Stat
sizeOfStat :: Int
implementation module System._Posix
import System._Pointer, System.Time
import StdInt
errno :: !*w -> (!Int,!*w)
errno world = (getErrno,world)
where
getErrno :: Int
getErrno = readInt4S errnoAddr 0
errnoAddr :: Pointer
errnoAddr = code {
ccall __errno ":p"
}
strerr :: !Int -> Pointer
strerr world = code {
ccall strerror "I:p"
}
stat :: !{#Char} !{#Char} !*w -> (!Int,!*w)
stat path buf world = code {
ccall stat "ss:I:A"
}
unlink :: !{#Char} !*w -> (!Int,!*w)
unlink path world = code {
ccall unlink "s:I:A"
}
fork :: !*w -> (!Int,!*w)
fork world = code {
ccall fork ":I:A"
}
execvp :: !{#Char} !{#Pointer} !*w -> (!Int,!*w)
execvp name argv world = code {
ccall execvp "sA:I:A"
}
waitpid :: !Int !{#Int} !Int !*w -> (!Int,!*w)
waitpid pid status_p options world = code {
ccall waitpid "IAI:I:A"
}
exit :: !Int !*w -> (!.a,!*w)
exit num world = code {
ccall exit "I:p:A"
}
getcwd :: !{#Char} !Int !*w -> (!Pointer,!*w)
getcwd buf size_t world = code {
ccall getcwd "sI:p:A"
}
chdir :: !{#Char} !*w -> (!Int,!*w)
chdir name world = code {
ccall chdir "s:I:A"
}
mkdir :: !{#Char} !Int !*w -> (!Int,!*w)
mkdir name mode world = code {
ccall mkdir "sI:I:A"
}
rmdir :: !{#Char} !*w -> (!Int,!*w)
rmdir name world = code {
ccall rmdir "s:I:A"
}
rename :: !{#Char} !{#Char} !*w -> (!Int,!*w)
rename old new world = code {
ccall rename "ss:I:A"
}
opendir :: !{#Char} !*w -> (!Pointer,!*w)
opendir path world = code {
ccall opendir "s:p:A"
}
closedir :: !Pointer !*w -> (!Int,!*w)
closedir dir world = code {
ccall closedir "p:I:A"
}
readdir :: !Pointer !*w -> (!Pointer,!*w)
readdir dir world = code {
ccall readdir "p:p:A"
}
pipe :: !Pointer !*w -> (!Int, !*w)
pipe arr world = code {
ccall pipe "p:I:A"
}
dup2 :: !Int !Int !*w -> (!Int, !*w)
dup2 old new world = code {
ccall dup2 "II:I:A"
}
close :: !Int !*w -> (!Int, !*w)
close fd world = code {
ccall close "I:I:A"
}
ioctl :: !Int !Int !Pointer !*w -> (!Int, !*w)
ioctl fd op ptr world = code {
ccall ioctl "IIp:I:A"
}
fcntlArg :: !Int !Int !Int !*w -> (!Int, !*w)
fcntlArg fd op arg world = code {
ccall fcntl "III:I:A"
}
read :: !Int !Pointer !Int !*w -> (!Int, !*w)
read fd buffer nBuffer world = code {
ccall read "IpI:I:A"
}
write :: !Int !{#Char} !Int !*w -> (!Int, !*w)
write fd buffer nBuffer world = code {
ccall write "IsI:I:A"
}
select_ :: !Int !Pointer !Pointer !Pointer !Pointer !*w -> (!Int, !*w)
select_ nfds readfds writefds exceptfds timeout world = code {
ccall select "Ipppp:I:A"
}
kill :: !Int !Int !*w -> (!Int, !*w)
kill pid sig world = code {
ccall kill "II:I:A"
}
malloc :: !Int -> Pointer
malloc num = code {
ccall malloc "p:p"
}
free :: !Pointer -> Int
free ptr = code {
ccall free "p:I"
}
freeSt :: !Pointer !*w -> *w
freeSt ptr world = code {
ccall free "p:V:A"
}
memcpy_string_to_pointer :: !Pointer !{#Char} !Int -> Pointer
memcpy_string_to_pointer p s n = code {
ccall memcpy "psp:p"
}
//Mapping to/from byte arrays
unpackStat :: !{#Char} -> Stat
unpackStat s =
{ st_dev = IF_INT_64_OR_32 (unpackInt8 s 0) (unpackInt4S s 0 /*8 bytes*/)
, st_ino = IF_INT_64_OR_32 (unpackInt8 s 8) (unpackInt4S s 96)
, st_mode = IF_INT_64_OR_32 (unpackInt4S s 24) (unpackInt4S s 16)
, st_nlink = IF_INT_64_OR_32 (unpackInt8 s 16) (unpackInt4S s 20)
, st_uid = IF_INT_64_OR_32 (unpackInt4S s 28) (unpackInt4S s 24)
, st_gid = IF_INT_64_OR_32 (unpackInt4S s 32) (unpackInt4S s 28)
, st_rdev = IF_INT_64_OR_32 (unpackInt8 s 40) (unpackInt4S s 32 /*8 bytes*/)
, st_size = IF_INT_64_OR_32 (unpackInt8 s 48) (unpackInt4S s 44)
, st_blocks = IF_INT_64_OR_32 (unpackInt8 s 64) (unpackInt4S s 64)
, st_blksize = IF_INT_64_OR_32 (unpackInt8 s 56) (unpackInt4S s 56)
, st_atimespec = IF_INT_64_OR_32 (unpackInt8 s 72 /*16 bytes*/) (unpackInt4S s 72 /*8 bytes*/)
, st_mtimespec = IF_INT_64_OR_32 (unpackInt8 s 88 /*16 bytes*/) (unpackInt4S s 80 /*8 bytes*/)
, st_ctimespec = IF_INT_64_OR_32 (unpackInt8 s 104 /*16 bytes*/) (unpackInt4S s 88 /*8 bytes*/)
}
sizeOfStat :: Int
sizeOfStat = 104
definition module Clean.Doc
/**
* Parsing and storing Clean documentation
*/
import StdGeneric
from StdOverloaded import class toString
from Data.Either import :: Either
from Data.GenDefault import generic gDefault
from Data.Maybe import :: Maybe
from Clean.Types import :: Type
/**
* A wrapper around the {{`String`}} type which makes sure that multi-line
* documentation blocks get trimmed w.r.t. whitespace.
*/
:: MultiLineString =: MultiLine String
class docDescription d :: !d -> Maybe Description
class docComplexity d :: !d -> Maybe String
class docParams d :: !d -> [ParamDoc]
class docVars d :: !d -> [Description]
class docResults d :: !d -> [Description]
class docType d :: !d -> Maybe Type
class docThrows d :: !d -> [Description]
class docMembers d :: !d -> [Maybe ClassMemberDoc]
class docFields d :: !d -> Maybe [Maybe Description]
class docConstructors d :: !d -> Maybe [Maybe ConstructorDoc]
class docRepresentation d :: !d -> Maybe (Maybe Description)
class docPropertyBootstrap d :: !d -> Maybe PropertyBootstrapDoc
class docPropertyTestWith d :: !d -> [PropertyVarInstantiation]
class docPropertyTestGenerators d :: !d -> [PropertyTestGenerator]
class docProperties d :: !d -> [Property]
class docPreconditions d :: !d -> [String]
/**
* Documentation of a Clean module.
*/
:: ModuleDoc =
{ description :: !Maybe Description
, property_bootstrap :: !Maybe PropertyBootstrapDoc //* For generating unit tests with clean-test-properties
, property_test_with :: ![PropertyVarInstantiation] //* With which types to test the properties
, property_test_generators :: ![PropertyTestGenerator]
//* Functions to generate values of types for which Gast's {{`ggen`}} is not good enough, like {{`Map`}}
}
instance docDescription ModuleDoc
instance docPropertyBootstrap ModuleDoc
instance docPropertyTestWith ModuleDoc
instance docPropertyTestGenerators ModuleDoc
derive gDefault ModuleDoc, PropertyBootstrapDoc
//* Belongs to `property_bootstrap` in `ModuleDoc`.
:: PropertyBootstrapDoc =
{ bootstrap_content :: !MultiLineString
, bootstrap_without_default_imports :: !Bool
//* Don't generate a default set of imports (e.g. to avoid name clashes with Gast)
}
/**
* Documentation of a Clean function.
*/
:: FunctionDoc =
{ description :: !Maybe Description
, complexity :: !Maybe String //* E.g. "O(n log n)"
, params :: ![ParamDoc] //* Descriptions of the parameters
, vars :: ![Description] //* Descriptions of the type variables (for generics)
, results :: ![Description] //* Descriptions of the result(s, for tuples)
, type :: !Maybe Type //* The type (for macros)
, throws :: ![Description] //* The exceptions it may throw (iTasks)
, properties :: ![Property] //* Properties of this function
, property_test_with :: ![PropertyVarInstantiation] //* With which types to test the properties
, preconditions :: ![String] //* Preconditions for the properties
}
instance docDescription FunctionDoc
instance docComplexity FunctionDoc
instance docParams FunctionDoc
instance docVars FunctionDoc
instance docResults FunctionDoc
instance docType FunctionDoc
instance docThrows FunctionDoc
instance docProperties FunctionDoc
instance docPropertyTestWith FunctionDoc
instance docPreconditions FunctionDoc
/**
* Documentation of a class instance.
*/
:: InstanceDoc =
{ description :: !Maybe Description
, complexity :: !Maybe String //* E.g. "O(n log n)"
, properties :: ![Property] //* Properties of this instance
, property_test_with :: ![PropertyVarInstantiation] //* With which types to test the properties
, preconditions :: ![String] //* Preconditions for the properties
}
instance docDescription InstanceDoc
instance docComplexity InstanceDoc
instance docProperties InstanceDoc
instance docPropertyTestWith InstanceDoc
instance docPreconditions InstanceDoc
/**
* Documentation of a function parameter.
*/
:: ParamDoc =
{ name :: !Maybe String //* An optional name for the parameter
, description :: !Maybe Description //* An optional description
}
instance toString ParamDoc
instance docDescription ParamDoc
/**
* A property of a function.
* Typically, the property can be tested with Gast.
*
* - `ForAll`: the right-hand side (the third argument) holds for all values of
* the arguments (the second argument). The first argument is the name.
*/
:: Property
= ForAll !String ![(String,Type)] !String
/**
* When a property type contains type variables, a `PropertyVarInstantiation`
* can be used to instantiate those variables when generating test cases.
*/
:: PropertyVarInstantiation = PropertyVarInstantiation !(!String, !Type)
/**
* A test generator generates values of some type. There are different ways to
* write test generators:
*
* - `PTG_Function`: The first argument is the function type of the generator,
* for instance `[(k,v)] -> {{Map}} k v`. This receives arguments of type
* `[(k,v)]` and transforms them into generated values of type `Map k v`. The
* second argument is the Clean implementation, which should assume the
* generator is called `gen` (e.g.: `gen elems = ...`).
* - `PTG_List`: The first argument is the type for which values are to be
* generated (e.g.: `Int`). The second argument is a Clean expression for a
* list of that type (e.g.: `[0..10]`).
*/
:: PropertyTestGenerator
= PTG_Function !Type !String
| PTG_List !Type !String
derive gDefault FunctionDoc, InstanceDoc, Property, PropertyVarInstantiation, PropertyTestGenerator
/**
* Documentation of a Clean class member.
* For an explanation of the fields, see the documentation on {{`FunctionDoc`}}.
*/
:: ClassMemberDoc =
{ description :: !Maybe Description
, complexity :: !Maybe String
, params :: ![ParamDoc]
, results :: ![Description]
, type :: !Maybe Type
, throws :: ![Description]
}
instance docDescription ClassMemberDoc
instance docComplexity ClassMemberDoc
instance docParams ClassMemberDoc
instance docResults ClassMemberDoc
instance docType ClassMemberDoc
instance docThrows ClassMemberDoc
derive gDefault ClassMemberDoc