* feat: add box templates and box type
This commit adds an implementation of Boxes, memory manged heap
allocated values.
Boxes are implemented as C pointers, with no additional structure but
are treated as structs in Carp. To facilitate this, we need to add them
as a clause to our special type emissions (TypesToC) as they'd otherwise
be emitted like other struct types.
Co-authored-by: Veit Heller <veit@veitheller.de>
* fix: slight memory management fix for Box
Make sure we free the box!
* test: add tests for box (including memory checks)
* Revert "fix: Ignore clang nitpick"
This reverts commit 70ec6d46d4.
* fix: update example/functor.carp
Now that a builtin type named Box exists, the definitions in this file
cause a conflict. I've renamed the "Box" type in the functor example to
remove the conflict.
* feat: add Box.peek
Box.peek allows users to transform a reference to a box into a a
reference to the box's contained value. The returned reference will have
the same lifetime as the box. This function allows callers to manipulate
the value in a box without re-allocation, for example:
```clojure
(deftype Num [val Int])
(let-do [box (Box.init (Num.init 0))]
(Num.set-val! (Box.peek &box) 1)
@(Num.val (Box.peek &box)))
```
This commit also includes tests for Box.peek.
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
* feat: implement blit on ByteOrder
ByteOrder is effectively just an enum that indicates desired endianness.
We can freely copy it around without penalty.
Co-authored-by: Veit Heller <veit@veitheller.de>
Co-authored-by: Erik Svedäng <erik@coherence.io>
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
* feat: add feof and ferror
These are C stdio functions that enable programmers to determine if a
file read resulted in an error or EOF encounter.
We can use these to power a definition of IO.fgetc, which is currently
not defined.
* feat: implement missing IO.fgetc
IO defined a function, fgetc (distinct from IO.Raw.fgetc) which actually
produced invalid code, since the name was not overridden and C does not
define IO_fgetc.
There was also a TODO to handle EOF conditions; so, I've implemented the
function, checking for EOF and error conditions using the Raw stdio
wrappers. IO.fgetc returns a Char in Success on success and an error
string on failure.
* refactor: distinguish EOF from errors in IO.fgetc
We now report whether or not the error encountered in fgetc was EOF.
Note that we don't yet report on the contents of other errors.
* feat: add box templates and box type
This commit adds an implementation of Boxes, memory manged heap
allocated values.
Boxes are implemented as C pointers, with no additional structure but
are treated as structs in Carp. To facilitate this, we need to add them
as a clause to our special type emissions (TypesToC) as they'd otherwise
be emitted like other struct types.
Co-authored-by: Veit Heller <veit@veitheller.de>
* fix: slight memory management fix for Box
Make sure we free the box!
* test: add tests for box (including memory checks)
* Revert "fix: Ignore clang nitpick"
This reverts commit 70ec6d46d4.
* fix: update example/functor.carp
Now that a builtin type named Box exists, the definitions in this file
cause a conflict. I've renamed the "Box" type in the functor example to
remove the conflict.
* feat: add Box.peek
Box.peek allows users to transform a reference to a box into a a
reference to the box's contained value. The returned reference will have
the same lifetime as the box. This function allows callers to manipulate
the value in a box without re-allocation, for example:
```clojure
(deftype Num [val Int])
(let-do [box (Box.init (Num.init 0))]
(Num.set-val! (Box.peek &box) 1)
@(Num.val (Box.peek &box)))
```
This commit also includes tests for Box.peek.
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
* feat: add c-name meta key for code emission overrides
This commit adds a new special compiler meta key, c-name, that enables
users to explicitly c the C identifier Carp should emit for a given
symbol. For now, it is only explicitly supported for Def and Defn forms.
For example:
```clojure
(defn foo-bar [] 2)
(c-name foo-bar "foo_bar")
```
Will cause foo-bar in emitted C code to be emitted as `foo_bar` instead
of `foo_MINUS_bar`.
I've also refactored some of the meta code to be a bit more principled
about keys that are understood by the compiler.
* docs: update CInterop docs
Adds a section on using the c-name meta field to override identifiers
exclusively defined in Carp. Also performs some minor editorial.
Co-authored-by: Veit Heller <veit@veitheller.de>
Co-authored-by: Erik Svedäng <erik@coherence.io>
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
* feat: add Dynamic.String.to-array
Adds a new dynamic function that converts a string to an array of
strings, one for each character in the string. In other words, it's the
same as Dynamic.String.to-list but the result is an array structure
instead of a list.
It's also significantly faster than to-list on large inputs. The current
implementation of Dynamic.String.to-list takes long to process large
inputs, presumably because of its recursive behavior and multiple calls
to cons (I'm currently investigating this) (e.g. use read-file then try
calling to-list, you may need to wait a while). Contrarily, to-array is
nearly instantaneous even when the input string is large. This is
because it leverages Haskell's `splitOn` directly, which, when given an
empty delimiter, (which is the case for the empty string), splits the
entire input sequence. Because "" is the empty list for a string in
Haskell's representation, calling split-on with "" results in the
splitting behavior. The output also includes the delimiting case, so we
drop it using cdr.
* test: add test for Dynamic.String.to-array
This fixes an issue where by types with fields registered in modules
weren't emitted with their module paths. This makes the behavior between
RegisterTypeWithoutFields and RegisterTypeWithFields the same. They both
account for the current module path in which the type is registered and
output the emitted typedef appropriately.
This fix also eliminates the need for a workaround in core/Pattern.carp.
We previously had to register MatchResult with an override because of
the old behavior, but now the override is no longer needed (since
MatchResult is defined as PatternMatchResult in its source header). The
call (register MatchResult) within (defmodule Pattern) emits
"PatternMatchResult" by default since we now account for module paths
for registered types.
* feat: add box templates and box type
This commit adds an implementation of Boxes, memory manged heap
allocated values.
Boxes are implemented as C pointers, with no additional structure but
are treated as structs in Carp. To facilitate this, we need to add them
as a clause to our special type emissions (TypesToC) as they'd otherwise
be emitted like other struct types.
Co-authored-by: Veit Heller <veit@veitheller.de>
* fix: slight memory management fix for Box
Make sure we free the box!
* test: add tests for box (including memory checks)
* Revert "fix: Ignore clang nitpick"
This reverts commit 70ec6d46d4.
* fix: update example/functor.carp
Now that a builtin type named Box exists, the definitions in this file
cause a conflict. I've renamed the "Box" type in the functor example to
remove the conflict.
* feat: add Box.peek
Box.peek allows users to transform a reference to a box into a a
reference to the box's contained value. The returned reference will have
the same lifetime as the box. This function allows callers to manipulate
the value in a box without re-allocation, for example:
```clojure
(deftype Num [val Int])
(let-do [box (Box.init (Num.init 0))]
(Num.set-val! (Box.peek &box) 1)
@(Num.val (Box.peek &box)))
```
This commit also includes tests for Box.peek.
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
Co-authored-by: Veit Heller <veit@veitheller.de>
Co-authored-by: Erik Svedäng <erik@coherence.io>
Co-authored-by: TimDeve <TimDeve@users.noreply.github.com>
These macros apply an operation to the current value of a variable and
then set the variable to the result of the application. They are
effectively sugar for writing `(set! <var> (<op> <var> <val>))` and
should be familiar to those who have programmed in imperative languages
like C.
In Carp, all the underlying operations these macros use are interfaces,
so one can flexibly use them for more than just numeric types.
Example usage:
```clojure
(let-do [dial 0]
;; crank it up to 11!
(while-do (dial < 12)
(++ dial))
dial)
;; expanded
(let-do [dial 0]
;; crank it up to 11!
(while-do (dial < 12)
(set! dial (inc dial)))
dial)
```
* feat: Add additional ignore macros
This commit adds two new ignore macros, ignore*, which wraps an
arbitrary number of forms in calls to `ignore` and ignore-do, which
wraps an arbitrary number of forms in ignore, then bundles the whole in
a do call, effectively executing each form only for side effects and
ignoring all results.
* docs: Update ignore* docs
Link to `ignore` doc
Co-authored-by: Veit Heller <veit@veitheller.de>
* fix: Call ignore* in ignore-do
ignore-all was an old name that no longer exists!
* test: Add test for ignore-do
Co-authored-by: Veit Heller <veit@veitheller.de>
* refactor: Tiny cleanup before we begin
* refactor: Moved module finding to its own local function
* feat: save-docs-internal is now a binary command
* feat: This seems to work
* fix: Cleaned up the code, save-docs now emit one module per file listed
* feat!: implemented Pattern.match which returns start and end indizes of the first match
* fix: Pattern.match now returns correct end index
* feat: moved Pattern.match-str and Pattern.find from C to Carp code
* chore: fix build after merges
* chore: fix build after merges
* feat: moved Pattern.find-all from C to Carp code
* feat: Pattern.global-match-str no longer relies on Pattern.global-match
* docs: updated for Pattern.global-match
* fix: moved str/prn functions into sub module
* fix: removed unused functions from carp_pattern.h (using cflow)
* feat!: renamed (Pattern.global-match) to (Pattern.match-all-groups)
* fix: unit test
* fix: some functions renamed to match Carp style
Co-authored-by: guberatsie <gunnar.bernhardt@siemens.com>
* feat: generalized (and) and (or) to handle any number of parameters
* feat!: removed (and*) and (or*) macros
* chore: worked around compiler issue for unit test
* fix: unit test in ./test/macro.carp
Co-authored-by: guberatsie <gunnar.bernhardt@siemens.com>
* feat!: implemented String.ascii-to-lower and String.ascii-to-upper
* fix: corrected docstrings
* fix: added unit test for ascii-to-lower and ascii-to-upper
* fix: moved tolower- and toupper from String to Byte module
Co-authored-by: guberatsie <gunnar.bernhardt@siemens.com>
* fix: render submodules in html docs
* fix: also render deeply nested modules
* feat: no prefixes in nested submodule doc rendering
* fix: fix text alignment of module index for sdl
* feat: make submodules expandable
* chore: Abuse deftemplate to get rid of Address
* chore: Avoid semicolon at end of define
* fix: address should be useable as an argument to a HOF
* chore: adapt examples to new address signature
* fix: Remove Address from typeOf
* fix: Remove more uses of Address
* fix: Remove more mentions of address in the Haskell code
* fix: Remove test that ensure you can't take the address of non-symbols
* refactor: Moved `address` to Pointer.carp
* refactor: Move address into Pointer module
Co-authored-by: Jorge Acereda <jacereda@gmail.com>
* chore: Re-format Haskell code
* fix: Unify aupdate and aupdate! with other update functions
* fix: Re-add comment
* fix: Also make StaticArray.aupdate! adhere to the normal update signature
* fix: Failing test
* feat: add 'when' functions for Maybe and Result
These functions enable users to execute some side-effecting function
(one that returns unit and take no arguments) based on the contents of a
Maybe or Result.
`when-success`: Executes a side-effect when given a `Result.Success`
`when-error`: Executes a side-effect when given a `Result.Error`
`when-just`: Executes a side-effect when given a `Maybe.Just`
`when-nothing`: Executes a side-effect when given a `Maybe.Nothing`
* docs: add Control to core lib doc generation
* feat: Add support for emitting literal C
This commit adds a new Obj type, C, as well as a command for emitting C
literals (which are represented by this object).
This is necessary for circumstances in which Carp's handling of
templates and emission orders prevents interop with C. For example, the
c11 macro static_assert must only take a string literal in its second
position. However, Carp's memory management will typically assign a
string literal (in Carp) to an anonymous variable, which makes them
impossible to use with static_assert. The new emit-c command will
support this use case:
```
(static-assert 0 (Unsafe.emit-c "\"message!\""))
```
The literal string "message!" will be emitted in the compiler's C output
in the position corresponding to the macro call.
We also add a special type for c literals, CTy, to prevent conflating
them with Strings. This helps maintainers define clear boundaries and
express what interop code requires the use of literal C.
Likewise, we need to emit `c_code` to represent this type in C. This
wouldn't be necessary except that Carp sometimes auto-generates
functions that refer to Carp types in their C equivalents, so we need
this for completeness. It is typed as the void pointer.
N.B. That the command is not yet exposed in Carp in this commit.
Thanks to @TimDeve for recommending the name emit-c!
* feat: Add preproc command and add emit-c to Unsafe module
This commit adds the preproc command, which enables users to emit
arbitrary C in the compilers emitted C output.
The C emitted by calls to preproc will be appended to the output after
include directives but prior to any other emissions. One can use it to
call preprocessor directives in C, define helper functions etc.
preproc takes a C type value as an argument and must be used in
conjunction with emit-c. Both functions are added to the Unsafe module
to signal their dangerousness.
One can use `register` in combination with preproc to define code
entirely in Carp and obviate the need of additional header files. For
example:
```
(Unsafe.preproc (Unsafe.emit-c "#define FOO 0"))
(Unsafe.preproc (Unsafe.emit-c "void foo() { printf(\"%d\\n\", 1); }"))
(register FOO Int)
(register foo (Fn [] ()))
(defn main []
(do (foo)
(IO.println &(fmt "%d" FOO))))
```
The prior example emits C that defines a FOO macro and foo function,
which are both referenced in the main function emitted by Carps normal
processing. Here's what the output looks like:
```
// .. several other includes emitted by the compiler...
void foo() { printf("%d\n", 1); }
//Types:
// Depth 3
typedef struct {
union {
struct {
Long member0;
} Just;
// Nothing
char __dummy;
} u;
char _tag;
} Maybe__Long;
```
The C passed to preproc calls is emitted prior to Carps other emissions,
ensuring the user has access to these definitions before any Carp code
is called.
* docs: Add documentation on emit-c and preproc
* feat: add macros for emitting C compiler directives
This suite of macros uses the `Unsafe.emit-c` and `Unsafe.preproc`
functions to provide macros for emitting common C compiler directives,
such as #ifdef, #define, #pragma and others.
* refactor: Groups Dynamic together in Macros.carp
* fix: Fixes doc for `hidden` referring to the wrong symbol
* feat: Adds defn- & def- macros
Adding these macros as a shortand for declaring a def or defn and making
them `hidden` and `private`, useful to keep things internal to a module.
* test: Adds expected error output tests for def- & defn-
* refactor: Changes position of Module and Interface section in LanguageGuide
Trying to introduce concepts in the same order they are referred to in
the examples: structs > modules > interfaces.
* docs: Adds private & hidden section in the LanguageGuide
* refactor: move Context updates into functions
Previously, we had a lot of instances of updating Context records
directly, replacing environments where needed. This commit replaces
those hand-written record setting instances with functions, which should
allow us to more gracefully abstract over any preprocessing we should
have to do and help ensure we're updating contexts in the right way.
* refactor: replace inline context manipulation in primitives
Like the commit that altered Eval before it, this commit leverages
Context functions to remove a bunch of inline record field setting code
and direct env manipulation.
* refactor: replace generic binder lookups with contextual ones
* refactor: move true and false XObjs into Obj.hs
Previously, trueXObj and falseXObj were defined in Commands.hs, but
since they're just literal constructed XObj values, I feel Obj.hs is a
more appropriate home for them and makes them more widely accessible to
other modules without needing to import Commands.
* refactor: model symbol qualification requirements at typelevel
This commit refactors the Qualify module to express symbol qualification
at type level. In the past, all functions operated on SymPaths. In some
cases, the functions operated on paths that *were not yet qualified* and
so the functions would perform qualification inline. Contrarily, other
functions like define received XObjs (from another part of the codebase
entirely!) that were already fully qualified, and so it would be a grave
mistake to re-qualify them.
In the general case, it's difficult or impossible to tell across modules
whether or not a given SymPath is coming in qualified or unqualified,
which can easily lead to mistakes of double-qualification, e.g.
transforming `Foo.bar` into `Foo.Foo.bar`.
Modelling qualification in the type system enables us to avoid the
problem by distinguishing between unqualified and qualified paths. A
function receiving an SymPath can safely qualify it, whereas a function
receiving a QualifiedPath should not further qualify the path. This
helps better express and ensure constraints across modules.
In addition, this commit also refactors a few functions where there was
opportunity to do so.
* refactor: remove eval call from `doc`
This can lead to problems where a doc call intended to be evaluated
later (in a macro body) is evaluated *immediately* resulting in a
binding being added to the wrong scope (see the function reverse in
core).
The reason this behavior crops up now is that a special case for
evaluating module contexts was removed last commit--this special case
caused problems of its own, and the real root of things stems from the
unnecessary eval call. Generally, evaling a doc call provides no benefit
other than making evaluation of the meta set immediate in the repl,
which is easy enough for one to do on one's own by calling eval where
needed.
* refactor: use do notation to clarify case qualification
* refactor: rename runQualified to unQualified
@eriksvedang pointed out the `run` prefix typically denotes a monad. As
`Qualified` is not monadic (no monad instance defined) we drop the `r`
to ensure we don't mislead readers.
* refactor: convert a few more binds to do notation
Do notation is generally clearer in cases where we use mapM, etc. We can
also leverage liftM frequently in the qualification functions to
transform a Qualified xobj back into an xobj for further use.
* refactor: temporarily restore special case in meta set
Meta set disallows setting the meta of a prefixed, absolute path such as
`Foo.bar`. It only allows relative, unqualified paths `bar` and uses the
current context to determine the appropriate module.
If we eventually throw and error from envInsertAt, we can remove this
special case. I intend to do that later, but for now we'll keep the
special case to make for a more pleasant user experience.