Commit Graph

151 Commits

Author SHA1 Message Date
Scott Olsen
35edce70cd
feat: add c-name meta field (#1398)
* 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>
2022-03-18 09:34:45 +01:00
Scott Olsen
bd553fb78e
feat: add assignment operator macros (#1320)
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)
```
2021-09-27 10:15:54 +02:00
Scott Olsen
c9967ddf6e
feat: Add additional ignore macros (#1300)
* 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>
2021-08-23 20:31:10 +02:00
Veit Heller
97c0b5a61b
docs: make doc work on top level and document macros (#1265) 2021-07-01 09:42:37 +02:00
Erik Svedäng
09c91c7f90
feat: Emit docs for top level bindings (#1253)
* 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
2021-06-28 19:56:59 +02:00
guberathome
0d15a57d0e
(and) and (or) now handle any number of parameters (#1251)
* 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>
2021-06-20 21:44:04 +02:00
Veit Heller
f90d677993
feat: add Unsafe.C.asm (#1206) 2021-05-03 15:14:26 +02:00
Scott Olsen
d3f8d83c77
feat: add macros for emitting C compiler directives (#1182)
* 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.
2021-03-09 10:43:44 +01:00
Tim Dévé
19c1a4c557
feat: Adds defn- and def- macros (#1174)
* 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
2021-03-03 08:57:36 +01:00
Scott Olsen
8263a0da64
refactor: Context and Qualify (#1170)
* 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.
2021-02-14 21:53:42 +01:00
Veit Heller
dacc13560b
feat: add dynamic Map type (#1168)
* feat: add dynamic map prototype

* feat: feature parity for dynamic map

* docs: document dynamic map

* test: add dynamic map tests

* fix: defdynamics are handled in getBinderDescription

* test: i forgot to add dynamic tests, whoops
2021-02-11 09:12:58 +01:00
Veit Heller
384c41909d
feat: add deprecation meta (#1136)
* feat: add deprecation meta

* refactor: print only deprecated

* refactor: add argument to deprecated

* fix: make deprecated work early on
2021-01-26 13:22:50 +01:00
Veit Heller
5e39f665f1
feat: add dynamic-type command (#1148)
* feat: add dynamic-type command

* refactor: use symbols for dynamic-type
2021-01-26 13:22:26 +01:00
Veit Heller
8c1999d656
feat: add fstr (#1142)
* feat: add fstr

* test: add fstr test

* fix: memory error in test

* fix: fix backslash parser

* feat: add octal escape literals
2021-01-26 06:18:16 +01:00
Veit Heller
926eb08b03
macros: try fixing #1030 (#1117) 2021-01-11 13:21:29 +01:00
Erik Svedäng
f78fd16a71
refactor: Move code out of Macros.carp into other files (#1014)
* refactor: Move code out of Macros.carp into other files

* fix: Move back some macros needed in --no-core mode

* refactor: Remove weird 'evaluate' macros

* fix: Put back more macros

* fix: Remove transitive loading of Macros.carp

* refactor: Remove ArrayMacros.carp and put 'for' at top of Array.carp instead

* refactor: More splitting up

* refactor: Move back save-docs

* fix: Moved back some stuff

Co-authored-by: Erik Svedang <erik@Eriks-iMac.local>
2020-11-28 12:53:18 +01:00
Tim Dévé
c0bfc07192 Makes last argument to inline-c optional 2020-10-26 18:20:01 +00:00
Tim Dévé
0a7550484f Fixes inline-c 2020-10-26 18:07:46 +00:00
Erik Svedäng
cd175511fa
Merge pull request #933 from hellerve/veit/doc-typo-fix
macros: fix typo in curry* docs
2020-10-12 20:42:12 +02:00
Jorge Acereda
58a61dd42e Add support for cross-compilation. 2020-10-10 20:01:18 +02:00
hellerve
21c2043e3e macros: fix typo in curry* docs 2020-10-06 21:44:15 +02:00
scottolsen
d93985d7e7 Make doc take a rest parameter of strings
Carp preserves tabulation and other whitespace in strings, as it should.
This sometimes results in awkward code indentation when it comes to long
doc strings that exceed 80 characters. Often, one has to continue the
string on a newline, but needs to avoid adding tabs to prevent Carp from
rendering them in the output.

This change alters the behavior of doc to take a series of strings as a
rest parameter instead, allowing for neater organization in the source,
for example, after this change the following long doc string for
compose:

~~~
    "Returns the composition of two functions `f` and `g` for functions of any
arity; concretely, returns a function accepting the correct number of
arguments for `g`, applies `g` to those arguments, then applies `f` to the
result.

If you only need to compose functions that take a single argument (unary arity)
see `comp`. Comp also generates the form that corresponds to the composition,
compose contrarily evaluates 'eagerly' and returns a computed symbol.

For exmaple:

```
;; a silly composition
((compose empty take) 3 [1 2 3 4 5])
;; => []

(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))
;; => 'carp'

;; comp for comparison
((comp (curry + 1) (curry + 2)) 4)
;; => (+ 1 (+ 2 4))
```"
~~~

becomes:

~~~
       "Returns the composition of two functions `f` and `g` for functions of any"
       "arity; concretely, returns a function accepting the correct number of"
       "arguments for `g`, applies `g` to those arguments, then applies `f` to the"
       "result."
       ""
       "If you only need to compose functions that take a single argument (unary arity)"
       "see `comp`. Comp also generates the form that corresponds to the composition,"
       "compose contrarily evaluates 'eagerly' and returns a computed symbol."
       "```"
       ";; a silly composition"
       "((compose empty take) 3 [1 2 3 4 5])"
       ";; => []"
       ""
       "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))"
       ";; => 'carp'"
       ""
       ";; comp for comparison"
       "((comp (curry + 1) (curry + 2)) 4)"
       ";; => (+ 1 (+ 2 4))"
       "```")
~~~

And the output remains the same; this just enables better alignment in
the source file.

The strings passed to doc are newline separated by default, but one can
circumvent this behavior by passing a bool along with the string as
follows:

~~~
(doc foo
     ("My amazing doc " false)
     "continues on one line."
     ""
     "And then another.")
~~~

The above doc string will result in the following output:

~~~
My amazing doc continues on one line.

And then another.
~~~

Of course, the original behavior of doc also remains valid, so if one
prefers to use the old indentation-mixed single string format, one still
can!

This change also reformats the doc strings in macro to utilize the new
rest parameter and make the source a bit neater.
2020-10-01 11:41:05 -04:00
Erik Svedäng
87a49f66ff
Merge pull request #921 from hellerve/veit/doto
Add doto and doto-ref
2020-08-26 20:58:12 +02:00
hellerve
984994513d core: fix docstrings for doto* 2020-08-26 18:20:34 +02:00
hellerve
ac6979fcbb macros: add doto and doto-ref 2020-08-25 11:58:20 +02:00
scottolsen
88dc929904 Add gensym-local dynamic function
gensym-local is similar to gensym-with, with it's arguments reversed.
That is, rather than allowing the user to specify a custom qualifier, it
allows the user to specify a custom counter (or any symbol) and appends
this to the default gensym `gensym-generated` symbol.

This enables one to, e.g. map over an array and generate symbols:

```
(map gensym-local (map Symbol.from [1 2 3]))
=> (gensym-generated1 gensym-generated2 gensym-generated3)
```

Theoretically, passing `gensym` as-is to `map` would accomplish this
using the global gensym-counter, but the counter is not incremented on
subsequent calls. This function gives users more flexibility as well.
2020-08-07 17:08:59 -04:00
hellerve
43951a4c9f core: use abort in unreachable 2020-06-26 18:57:06 +02:00
hellerve
fb3ef6a47f core: add Bool.zero 2020-06-23 12:26:53 +02:00
hellerve
a96f774bc5 core: add unreachable 2020-06-23 12:19:14 +02:00
hellerve
357d28a167 core: update doc of cond 2020-05-26 21:50:26 +02:00
hellerve
9be2b8e4fb core: autogenerate Tuple types and document 2020-05-24 11:49:27 +02:00
Erik Svedäng
099d242d1f
Merge pull request #820 from hellerve/veit/fix-818
macros: fix hidden?, private?, and annotate?
2020-05-20 22:32:32 +02:00
hellerve
cc19bdc917 macros: fix hidden?, private?, and annotate? 2020-05-20 10:04:05 +02:00
scottolsen
39e9836452 Add an implements? macro
This macro simply returns true or false if a binding implements a given
interface.
2020-05-19 16:53:15 -04:00
Scott Olsen
5cd786c732 Add an implements-all macro
This macro adds implements forms for functions with the same name as a
given list of interfaces in a given module.
2020-05-15 12:46:35 -04:00
Dhananjay Balan
05bf39827b Add signal.h on FreeBSD platforms
The SIGNAL definitions are in signal.h, this also adds a macro freebsd-only, in the style of other platform-only macros.
2020-05-13 16:10:00 +02:00
Nils 'Linkie Pi' Reid
43c64d5ed1 Fix the inline-c macro to avoid using a reserved keyword as parameter. 2020-05-11 10:58:24 +02:00
Nils 'Linkie Pi' Reid
a8032f3b72 Readded inline-c as a macro of deftemplate. 2020-05-08 15:17:34 +02:00
hellerve
4e711a4eb0 core: add docs for any? and all? 2020-05-05 15:19:43 +02:00
hellerve
80d1086cb7 tests: better dynamic tests 2020-05-05 15:09:18 +02:00
hellerve
5838136f83 core: rename dynor and dynand and check in docs 2020-05-04 23:47:06 +02:00
hellerve
a761b561e3 all: use dynor and dynand 2020-05-01 12:50:31 +02:00
Erik Svedäng
8e04cb476e Renamed Dynamic.String.join and Dynamic.Symbol.join to concat. 2020-04-30 13:32:54 +02:00
scottolsen
ac87e8fbdc Add tests for dynamic functions
I accidentally broke `curry`, what better incentive for writing some
tests than preventing my own future silly mistakes :)

I also added and-internal because we cannot perform direct comparisons
on lists--so, instead we build member-wise comparisons by zipping, then
reduce the result using and.
2020-04-24 17:00:30 -04:00
scottolsen
3cbe0e8c79 Fix dynamic curry regression
I accidentally committed a change to the definition of curry that
severly alters how it functions! This commit fixed that, and adds a test
so that I don't unwittingly break it again :)
2020-04-24 15:38:22 -04:00
Scott Olsen
4c8726808d Fix order of append in filter, quote in curry*
Originally, curry* required double quoting function arguments in some
cases, due to an eval and lack of quotes in the function body it
produces. This is not ideal, as having to type ''(form) is quite
esoteric. Now we handle the extra quoting in the function itself, so
that only one quote is required.

I also fixed the order of filter (which was reversing results).
2020-04-21 23:09:25 -04:00
scottolsen
338b1624b2 Add several utility functions to Macros.carp
This commit adds several dynamic utility functions in the spirit of map,
zip, et al, including:

- Compose (composer for functions of any airty, that evaluate
  immediately (unlike comp)
- empty (returns the empty value for a structure [] or ())
- unreduce (builds a list of values)
- filter (filters a list of values)
- take (returns the first x members of a list)

I also removed a quote in collect-into that's no longer necessary after
the evaluator refactor.
2020-04-21 19:03:53 -04:00
scottolsen
2fd7a1fe40 Restrict map to mapping only (not zipping)
We currently define two dynamic functions, map and zip. Each performs
the traditional operation given by these names, however, map, emulated
clojure's map, which would selectively apply map or zip depending on the
number of lists passed as arguments. This change removes that selection,
making the execution of map more predicatable.
2020-04-21 09:41:42 -04:00
Scott Olsen
ba0bfe7ed7 Return length comparison directly in empty? 2020-04-19 12:07:06 -04:00
Scott Olsen
0c512c5eaf Use append in apply
No need for extra functions :)
2020-04-19 12:04:26 -04:00