*Gerbil* is a fast implementation of a [[Scheme]] that is built on top of Gambit Scheme. It sports an advanced macro system similar to Racket (formerly PLT Scheme).
# ➕Benefits
Gerbil has a state of the art macro system and is built on top of state of the art runtime that, when written properly, can be nearly as fast as C code.
# Docs
Core documentation lives at [cons.io](https://cons.io).
## Additional Notes
`fixnum?` types are register-sized integer types. In Gerbil, they are implemented and documented by [Gambit](https://gambitscheme.org/latest/manual/#Fixnum-specific-operations). Fixnums are limited to 62-bits before overflowing into the "big int" implementations
Similarly, `flonum?` are floating point numbers
Dates are handled by [SRFI 19](https://srfi.schemers.org/srfi-19/srfi-19.html).
`...` repeats the pattern that immediately proceed it.
## Enhancements to Official Docs
`stx-identifier` creates a new identifier with the context of its first argument. The identifier is created by "symbolizing" the remaining arguments with `make-symbol` (which is defined in `gerbil/runtime/util`).
To import modules for `syntax-eval` (in `:std/sugar`), you can include a `(phi: +1 :package/path)` clause in the `(import)`. Note, that any native bindings (ie. C FFI) cannot be used.
Alternatively, `(import (for-syntax ...))` or `(import (for-template ..)` have the equivalent semantics as `phi: +1` and `phi: -1` respectively.
## Imports
Imports are pretty straightforward, there's a special syntax that utilizes a `:` prefix to indicate whether the import relative or should use the `GERBIL_PATH` or the stdlib to search for a module. I *believe* these are hardcoded with the build scripts, so they *are not paths* even if they look like they are. They are also *not* keywords, unlike in [[Clojure]] and [[Common Lisp]].
In order to use libraries during macro expansion time (commonly called phi +1), you must use a `for-syntax` or `phi: +1` form. They are functionally equivalent as far as I can tell.
Example:
```scheme
(import
; these are more or less equivalent
; I would expect this code to fail though, obviously
(for-syntax :std/iter)
(phi: +1 :std/iter))
```
## Generics
The std lib docs for generics are almost completely unwritten. Refer to the [tutorial](https://cons.io/guide/intro.html#generics) for information on how they work.
Some details that are not necessarily called out anywhere:
- Generic methods dispatch at runtime
- This has performance implications
- Interfaces are generally better because they dispatch at expand/compile time
## Cothreads and Coroutines
Both are cooperative (ie. require using `yield` or resume), `cothread` gets it's own dedicated context while `coroutine` inherits whatever context is in the current continuation when the thread is resumed.
What is a context here?
## Building
```shell
./configure \
--enable-dynamic-clib \
--enable-trust-c-tco \
--enable march=native \
--enable-single-host && \
make -j12
```
## Symbols
Symbols can have *spaces* in them!
Use the syntax `'|word word|` to get a symbol with a space. Alternatively, use a plain string with `(make-symbol)`.
## S3 Client Updates
# 🪵Dev Log / Projects
## AWS S3 Client
I've made progress in re-implementing `list-buckets` and `create-bucket!` for the S3 client. Exceptions are *mostly* handled for free with `request/error` macro, which raises if the response code is >300 or <200.
`list-buckets` was surprisingly difficult, as the `sxml` utilities did not want to behave with the formatted XML. Perhaps I'm just naive to how they're supposed to work, but I had to fight with the list structure output by `sxml-find` a bit.
`create-bucket!` will, unsurprisingly, error if you try to create a bucket that already exists. This will be caught by the above mentioned macro and turned into an `error` call with appropriate irritants and extra info. The content of the response looks like:
```xml
<Error>
<Code>BucketAlreadyExists</Code>
<Message>Bucket already exists</Message>
<Resource>my-bucket-2</Resource>
<RequestId>NotYetImplemented</RequestId>
</Error>
```
I may attempt extract the info and include it in the exception in the future.
> [!info] Update: I'm doing this now
I've submitted a DRAFT PR with the S3 client implementation and got some review comments (which have already been addressed). I need to go back and handle all failure cases (200 response, failure message in body) for `copy-to!` before we can merge it.
- [x] Handle `Ok 200` failure response in `copy-to!` ✅ 2023-10-19
- [x] Identify what error message looks like ✅ 2023-10-19
- [x] Implement error handling ✅ 2023-10-19
There were some bugs with the interface that I'm now fixing, but it turns out the keyword portion of the interface form hasn't been exercised and has bug(s). I'm working on debugging this now, but it's difficult because it's hard to understand what is expected. I've nailed the failure down to the `:std/interface` file (`src/std/interface.ss`) in `unchecked-method-arguments-in`. It's a not-too-complicated macro that grabs the identifiers for method arguments and then generates a lambda that calls the underlying method for you with those args. The `unchecked-` part is because we drop any contract checks here, so this will need to be changed before we have expansion-time checks.
## CBOR
I've started working on implementing a [CBOR](https://www.rfc-editor.org/rfc/rfc8949.html) (RFC 8949) (de)serializer for Gerbil Scheme.
Look at `:std/actor` v18/io for examples to do a "jumptable" with a vector of lambdas.
Struggled a bit with `defsyntax` and other macro definition tools but realized I was overthinking and didn't really *need* to do much processing in the macro itself, I can simply use normal functions.
### Progress
- [x] Basic features
- [ ] Gerbil-specific tag directory
- It's unclear what I will actually have in here besides s-expr, pair, list and the built-in primitives
- [ ] CBOR test vector-based tests
## LSP
[[Language Server Protocol]] implementation that is Gerbil Scheme specific.
Has a sizeable bounty.
Being worked on by `drewc`.
## `@doc`
A macro/special form to link source code to documentation or embed docs directly in source (depending on preferences.)
Being worked on by `drewc`.
# Modules
> how can I list all functions/variables/classes/etc in a module?
> "Modules" are really just expander contexts. An expander context is, basically, a map of identifier names to identifier values. `(gx#expander-context-table cxt)` is the table that has that mapping.