-
Notifications
You must be signed in to change notification settings - Fork 0
Builtins
There is now limited support for linking to external libraries and native C code, it's only at compile time currently, and the following functionality is provided:
the built-in function rand takes a floating point number between 0.0 and 1.0 and returns
a floating point number in the same range. It is in no way cryptographically secure and
uses the most basic RNG algorithm I could find, but it works.
For writing tests.
Mostly this is implemented by F Natural in the standard preamble but there is a
core built-in that either sets a flag for later (if --assertions-accumulate) or
directly exits with a non-zero exit status. Support in the parser recognises the
function assert(condition) and provides it with filename and line number to report
before calling the built-in, and support in the main run-time will exit with a non-zero
status when the program has finished if --assertions-accumulate and the aforementioned flag was set.
The built-in ord(char) returns the integer Unicode code point for the char, and conversely
chr(number) returns the char at that Unicode point.
There are a number of I/O facilities implemented as built-ins, namely:
-
putc(char)puts a character to the standard output. -
fputc(file, char)puts a character to the open file handle. -
getc()returns the next character from stdin. -
fgetc(file)returns the next character from the file. -
putn(number)writes the number to stdout. -
fputn(file, number)writes the number to the file. -
putv(any)writes any type of argument (unformatted) to stdout. -
fputv(file, any)writes any type of argument (unformatted) to the file. -
puts(string)puts the string of characters to stdout. -
fputs(file, string)puts the string of characters to the file. -
gets()reads the next line from stdin up toEOFor'\n'and returns it, discarding any newline. -
fgets(file)same asgetsbut for the argument file. -
open(string, io_mode)attempts to open the file in the given mode. Returns atry(string, opaque file handle)where the string is the error if any, see below forio_modeandtry. -
openmem()opens an in-memory buffer (usingopen_memstream (3)) and returns atry(string, opaque file handle). The result should always be asuccess. All the normal file write operations can be performed on the file handle and will append to the buffer. Anyfgetson the file handle will return any new data in the buffer since the last time it was called.fgetcis currently not implemented for buffers and will cause a run-time error. See below fortry. -
close(file)closes the file if open. It is a no-op if the file is already closed. This operation also works on the file handles returned byopenmem. Returnstrue. -
opendir(path)attempts to open the argument directory name for reading. returns atryof a string error message or an opaque directory handle. -
readdir(dir)attempts to read the next entry from the open directory handle, returns amaybe(string)of the file name. -
closedir(dir)closes the directory handle. It is a no-op if the handle is already closed. Returnstrue. -
ftype(path)returns a try of a string error message and aftype_type
Garbage collection will close any open file handles that are un-referenced, but you should still be careful
to close at least write handles, which will flush the data to disk, as there is no guarantee that there will
be a garbage collection before the program exits. For that reason the ioutils.fn namespace provides some
monad-style utilities that can open and close file handles for you.
To support the i/o built-ins there are a few new types, one is a generic opaque type
implemented in core that can be sub-typed. That is
used to describe file and directory handles (as well as database and statement handles for the sqlite extension).
Another is a try type which is like maybe but treats failure as more of an error. It is defined in the preamble as:
typedef try(#f, #s) { failure(#f) | success(#s) }
which allows flexibility in the type of error value (string error message or integer error code are obvious alternatives).
io_mode is a simple enum:
typedef io_mode { io_read | io_write | io_append }
ftype_type is another simple enum
typedef ftype_type {
ftype_socket // socket
| ftype_symlink // symbolic link
| ftype_regular // regular file
| ftype_block // block device
| ftype_dir // directory
| ftype_char // character device
| ftype_fifo // named pipe
}
Lightweight database access.
-
sqlite3_open(string)returns atryof a string error message and an opaque database handle (see i/o above fortry). -
sqlite3_close(db_handle)closes the database handle, if it is still open, always returnstruecurrently. -
sqlite3_prepare(db_handle, string)prepares an sql statement for execution. returns a try of an integer error code and an opaque stmt_handle. -
sqlite3_bind(stmt_handle, list(basic_type))binds the arguments to the statement. -
sqlite3_fetch(stmt_handle)executes the statement and/or returns the next row as amaybe(list(basic_type)). -
sqlite3_finalize(stmt_handle)frees resources associated with the handle. Called automatically when the handle is garbage-collected, but it's a good idea to call it manually if you're creating a lot of statements. -
sqlite3_close(db_handle)closes the database handle if it is still open.
The basic_type mentioned above is defined in the preamble as
typedef basic_type { basic_null | basic_number(number) | basic_string(string) | basic_char(char) }
The argv(n) function returns the nth command-line argument passed to the executable after the file being executed. So the script
only has access to arguments after that point on the command line. The first such argument is index 0. The result is a maybe(string)
which is nothing if the index is out of range.
Read-only access to the environment is provided by getenv which takes the string name of the environment variable
and returns a maybe(string) of the value.
A few utilities for de-structuring complex numbers. Any argument number is acceptable, non-complex numbers are treated as complex with a zero imaginary part. Probably I should at least add a function to construct a complex number from polar co-ordinates, but it's not there yet.
-
com_realreturns the real part of a complex number. -
com_imagreturns the imaginary part of a complex number. The result is still imaginary, to convert to a real number divide by1i. -
com_magreturns the magnitude (polar co-ordinate system) of the complex number. -
com_thetareturns the angle (polar co-ordinate system) of the complex number in radians.
A function that returns the Unicode general category for any Unicode character. The set of categories is defined in the preamble as
typedef unicode_general_category_type {
GC_Ll | GC_Lm | GC_Lo | GC_Lt | GC_Lu |
GC_Mc | GC_Me | GC_Mn |
GC_Nd | GC_Nl | GC_No |
GC_Pc | GC_Pd | GC_Pe | GC_Pf | GC_Pi | GC_Po | GC_Ps |
GC_Sc | GC_Sk | GC_Sm | GC_So |
GC_Zl | GC_Zp | GC_Zs |
GC_Cc | GC_Cf | GC_Co | GC_Cs | GC_Cn
}
The builtin unicode_category has a type signature of char -> unicode_general_category_type. You can read a description of the categories
on wikipedia.
Under the hood this is done with a huge lookup table of byte codes. I can only really justify having this table because it's also used by the parser.
Building on the unicode support above, there are builtins for the following tests. Each one accepts a character and returns a boolean:
- isalnum
- isalpha
- isascii
- isblank
- isclose
- iscntrl
- isdigit
- isgraph
- islower
- isnumber
- isopen
- isprint
- ispunct
- isspace
- issymbol
- isupper
- isvalid
- isxdigit
a simple builtin that takes an integer exit status and exits the program with that status.
Next: Operators

CEKF(s) a.k.a. F Natural a.k.a F♮