Commit Graph

1065 Commits

Author SHA1 Message Date
Veit Heller
2023c93d62
feat: Quasiquotation (#1129)
* feat: quasiquotation

* test: add tests for quasiquotation

* fix: fix typo in call to doc

* fix: do not evaluate quasiquote too eagerly

* test: pull quasiquote test into macro

* docs: fix unquote example with better constant

* feat: add quasiquote literals

* refactor: simplify reader macros
2021-01-15 10:50:04 +01:00
Veit Heller
02936cc74c
feat: Derive (#1120)
* core: add derive

* fix: fix errors with set!

Notably, don't type check dynamic bindings (which can be set to
whatever) and eliminate a hang that resulted from not handling an error
at the end of the `set!` call. Also refactors some of the code in
efforts to make it a bit cleaner.

Also adds an error when `set!` can't find the variable one calls set!
on.

* feat: better derive

* test: add error test for derive

* document derive

* add derive to core documentation to generate

* core: add derive

* fix: fix errors with set!

Notably, don't type check dynamic bindings (which can be set to
whatever) and eliminate a hang that resulted from not handling an error
at the end of the `set!` call. Also refactors some of the code in
efforts to make it a bit cleaner.

Also adds an error when `set!` can't find the variable one calls set!
on.

* feat: better derive

* document derive

* feat: first completely working version of derive

* feat: make name of derivable customizable (thanks @scolsen)

* refactor: implement doc edits provided by @scolsen

* feat: change argument order for derive

* fix: change deriver error test

* test: add derive tests

* fix: change order of derive back

* docs: fix typo in derive document

Co-authored-by: scottolsen <scg.olsen@gmail.com>
2021-01-15 10:48:34 +01:00
Veit Heller
926eb08b03
macros: try fixing #1030 (#1117) 2021-01-11 13:21:29 +01:00
jacereda
0c6eae63c8
feat: Reduce binary size with more compact exhaustiveness error reporting (#1112) 2021-01-05 07:22:43 +01:00
Charlotte Koch
45288cd69e
feat: Recognize the NetBSD platform. (#1109) 2021-01-03 13:22:56 +01:00
Veit Heller
ff30fbc26e
feat: add Map.merge (#1106)
* feat: add Map.merge

* refactor: simplify ref in Map.merge
2021-01-03 13:20:46 +01:00
Efi
c1fe094885
feat: Add "rest" function to Array (#1099)
* feat: Add "rest" function to Array

* typo

* Update core/Array.carp
2020-12-24 16:19:53 +01:00
Scott Olsen
856171ef16
Support defining types in modules (BREAKING) (#1084)
* fix: don't set the inner env to globals in type mods

Previously, we set the inner environment of a type generated module to
the global env in cases where the overarching context didn't have an
inner env. This leads to problems where by the recognition of modules is
inconsistent, and one can't use the names of types as submodules in
certain circumstances.

This commit fixes that issue.

* refactor: refactor primitiveDefmodule

This refactor fixes a issues with meta information on submodules, for
instance, sigs on submodule functions used to result in a compiler error
about ambiguous identifiers. This fixes that.

Unfortunately, I don't have a precise idea about what exactly was wrong
with the original definition of this function. My suspicion is that the
recursion originally altered submodule paths in the wrong way, but I'm
not certain. In any case it's fixed.

* fix: ensure macros are expanded in the correct module

Previously, macro expansions folded over all forms after the top level
form, without performing any context updates on encountered
`defmodules`. This created an issue in which macro calls that produced
new bindings, "meta stubs", were *hoisted* out of submodules and into
the top-level module, creating duplicate definitions.

This commit fixes that issue by adding a special case for defmodule in
macroExpand.

* fix: ensure submodules and globals don't conflict

Previously, our module lookups during new module definition always
eventually fell back to the global environment, which caused submodules
that happen to share a name with a global module to be confused with the
global module. This change fixes that, so now one can define both
`Dynamic` (global) and `Foo.Dynamic` without issue.

* fix: remove old prefixes from vector tests

Commit 7b7cb5d1e replaced /= with a generic function. However, the
vector tests still called the specific Vector variants of this function,
which were removed when the generic was introduced. After recent
changes, these calls are now (correctly) identified as erroneous. My
guess is that they only worked in the past because of problems with our
lookups.

* chore: format code

* feat!: support defining types in modules

This commit adds support for defining types (using deftype) in modules.
Previously, all types were hoisted to the top level of the type
environment. After this commit, the type environment supports defining
nested modules just like the value env, so, calling the following:

```
(defmodule Foo (deftype Bar Baz))
```

Adds the following to the type env:

```
Foo : Module = {
    Bar : Type
}
```

and the following to the value env:

```
Foo : Module = {
    Bar : Module = {
        Baz : (Fn [] Foo.Bar)
        copy : (Fn [(Ref Foo.Bar q)] Foo.Bar)
        delete : (Fn [Foo.Bar] ())
        get-tag : (Fn [(Ref Foo.Bar q)] Int)
        prn : (Fn [(Ref Foo.Bar q)] String)
        str : (Fn [(Ref Foo.Bar q)] String)
    }
}

```

Such a type is *distinct* from any type defined at the top level that
happens to also have the name `Bar`.

This commit also updates info and tests to account for types in modules.

BREAKING CHANGE: This change is breaking since it alters the names of
types that were previously defined in modules. A good example of this is
the `Id` type in the `Color` module. Previously, one could refer to this
type by simply typing `Id` since it was hoisted to the top level. Now it
*must* be referred to by `Color.Id` since `Id` at the top level of the
type env and `Color.Id` (Id in the color module) are considered to be
distinct types.

* chore: format code

* refactor: use concat instead of intercalate

* chore: remove excess parentheses

* chore: Add todo to return IO () in printIfFound
2020-12-22 13:27:57 +01:00
Erik Svedäng
6f7aeaff73
feat: 'delete' interface (deciding whether a type is managed or not) (#1061)
* feat: 'delete' interface (deciding whether a type is managed or not)

* refactor: Move implements function to Interface module

* feat: Automatically implement 'delete' for types defined with `deftype`

* fix: Don't implement `delete` for Pointer

* refactor: Clarify `memberInfo` function

* fix: Also check if function types are managed

* fix: Implement 'delete' for String and StaticArray.

* fix: Manage String and Pattern. Tests run!

* feat: Add `managed?` primitive

* docs: Note about primitiveIsManaged

* test: Basic test cases for managed / nonmanaged external types

* test: Make sure `managed?` primitive works

* test: Inactivate sanitizer since we're creating leaks intentionally

* feat: Removed 'isExternalType' function

* refactor: Decide if struct member takes ref or not when printing

..based on blitable interface, and 'prn' implemntation

* refactor: Use 'blit' everywhere

* refactor: Implement `strTakesRefOrNot` in terms of `memberStrCallingConvention`

* refactor: Use `remove` over `filter not`
2020-12-20 21:21:14 +01:00
Efi
a9efa19886
Window manager flags and events for SDL (#1081)
* Added Window events

* Added SDL_SetWindowSize

* feat: Add window manager event catching using deftemplate

* Update core/SDL.carp

* Update core/SDL.carp

* Update core/SDL.carp
2020-12-20 12:12:29 +01:00
Veit Heller
5ad1d227f3
Add automatic map resizing (#1071)
* core: add map resizing

* add set resizing

* do not shrink if under dflt-size
2020-12-19 22:20:52 +01:00
Erik Svedäng
40d55562df
fix: Pointer str & prn (#1060)
* fix: Make `str` work for (Pointer a) types

* test: Make sure that the Pointer.str compiles

* fix: Remove test case, keep function around to make sure it compiles
2020-12-09 06:19:07 +01:00
Scott Olsen
9a8c8582f2
feat: add Dynamic.mod (#1051) 2020-12-03 19:24:52 +01:00
Tim Dévé
ac4231d005
docs: Expands docs around C function pointers (#1038)
* docs: Generates HTML docs for Function core module

* docs: Adds lifetime information in Function module

* docs: Adds callback section to C Interop

* docs: Corrects typos in Function docs
2020-12-01 10:44:03 +01:00
Scott Olsen
892a972660
Pointer: Add utility functions (#1012)
* Pointer: Add utility functions

This commit adds a few more utility functions to `Pointer.carp`.

- Pointer.set-unsafe: Sets the value of a pointer to some arbitrary Carp
  value, without type checking. Users need to ensure this operation is
  safe.
- Pointer.set: Sets the value of a pointer to a value of type t to a
  value that has the same type.
- Pointer.cast: Casts a pointer to a value of type t to a pointer to a
  value of type `a`--the argument passed is ignored, it is only used to
  determine the type to cast to.
- Pointer.leak: Copies a Carp reference to a new pointer to the same
  value. This creates a leak since Carp will not automatically clean up
  this memory.
- Pointer.free: Frees a pointer p. Users need to ensure calls to this
  function are safe and do not produce errors like a double free.
  Intended for use with leak.

Here's an example of some of these functions in action:

```
(defn foo []
  (let-do [p (Pointer.leak "leaky")] ;; create a new pointer
    (ignore (Pointer.set p @"foo")) ;; set the pointer to "foo"
    (println* (Pointer.to-value p)) ;; convert to a Carp val to print
    (Pointer.free p) ;; finally, free it.
    0))
(foo)
=> Compiled to 'out/Untitled' (executable)
foo
0
```

And the C of interest:

```
int foo() {
    int _35;
    /* let */ {
        static String _6 = "leaky";
        String *_6_ref = &_6;
        String* _7 = Pointer_leak__String(_6_ref);
        String* p = _7;
        /* let */ {
            static String _15 = "foo";
            String *_15_ref = &_15;
            String _16 = String_copy(_15_ref);
            String* _17 = Pointer_set__String(p, _16);
            String* _ = _17;
            /* () */
        }
        String _26 = Pointer_to_MINUS_value__String(p);
        String _27 = StringCopy_str(_26);
        String* _28 = &_27; // ref
        IO_println(_28);
        Pointer_free__String(p);
        int _34 = 0;
        _35 = _34;
        String_delete(_27);
    }
    return _35;
}
```

As mentioned, and as w/ other Pointer functions users need to ensure the
safety of these operations themselves. For example, calling `free` on
`p` twice in the example above produces the expected double free:

```
(defn foo []
  (let-do [p (Pointer.leak "leaky")] ;; create a new pointer
    (ignore (Pointer.set p @"foo")) ;; set the pointer to "foo"
    (println* (Pointer.to-value p)) ;; convert to a Carp val to print
    (Pointer.free p) ;; finally, free it.
    (Pointer.free p) ;; !Double free!
    0))
(foo)
Compiled to 'out/Untitled' (executable)
foo
Untitled(38328,0x10d9a1dc0) malloc: *** error for object 0x7feb86c01790:
pointer being freed was not allocated
Untitled(38328,0x10d9a1dc0) malloc: *** set a breakpoint in
malloc_error_break to debug
[RUNTIME ERROR] '"out/Untitled"' exited with return value -6.
```

Still, these should come in handy in rare cases in which users need to
circumvent the type checker or borrow checker.

diff --git a/core/Pointer.carp b/core/Pointer.carp
index a662c636..4f29d587 100644
--- a/core/Pointer.carp
+++ b/core/Pointer.carp
@@ -20,6 +20,29 @@ The user will have to ensure themselves that this is a safe operation.")
   (doc from-long "converts a long integer to a pointer.")
   (deftemplate from-long (Fn [Long] (Ptr p)) "$p* $NAME(Long p)" " $DECL { return ($p*)p; }")

+  (doc set-unsafe
+    "Sets the value of a pointer."
+    "The user will have to ensure this operation is safe.")
+  (deftemplate set-unsafe (Fn [(Ptr p) (Ref a b)] (Ptr p)) "$p* $NAME($p* p, void* a)" "$DECL { *p = *($p*)a; return p;}")
+
+  (doc cast
+     "Cast a pointer to type p to a pointer to type a."
+     "The value of the `a` argument is ignored.")
+  (deftemplate cast (Fn [(Ptr p) a] (Ptr a)) "$a* $NAME($p* p, $a a)" "$DECL { *($a*)p = CARP_MALLOC(sizeof($a)); return ($a*)p;}")
+
+  (doc leak
+     "Allocate a new pointer that's a copy of the value of `Ref`"
+     "The Carp borrow checker won't delete this pointer. You will need to delete it manually by calling `Pointer.free`.")
+  (deftemplate leak (Fn [(Ref a b)] (Ptr a)) "$a* $NAME($a* r)" "$DECL { void *leak = CARP_MALLOC(sizeof($a)); memcpy(leak, r, sizeof($a)); return ($a*)leak;}")
+
+  (doc free
+     "Free a pointer."
+     "Users need to manually verify that this operation is safe.")
+  (deftemplate free (Fn [(Ptr p)] Unit) "void $NAME($p* p)" "$DECL {CARP_FREE(p);}")
+
+  (doc set "Sets the value of a pointer.")
+  (deftemplate set (Fn [(Ptr p) p] (Ptr p)) "$p* $NAME($p* p, $p a)" "$DECL { *p = a; return p;}")
+
   (defn inc [a] (Pointer.add a 1l))
   (implements inc Pointer.inc)
   (defn dec [a] (Pointer.sub a 1l))

* Pointer: Change signature of leak to make it more sensible

Instead of `leak` copying a previously allocated value, it now takes
(unmanaged) ownership of a fresh value and allocates. This makes more
sense semantically, as we're just instantiating a new pointer that won't
be managed by Carp and will leak unless freed explicitly.

Thanks to @TimDeve for the suggestion!

* Pointer: Improve apis on set and alloc

- Rename set-unsafe to align w/ naming conventions
  Most unsafe functions are prefixed with `unsafe`, not suffixed.
- Rename leak to `unsafe-alloc` to better convey its semantics (leak
  also already exists as `Unsafe.leak`.
- Remove `cast` since its use is covered by `Unsafe.coerce`.

Thanks to TimDeve and hellerve for the suggestions!

* Pointer: Make unsafe-set take ownership

* Pointer: Correctly cast in unsafe-alloc; add unsafe-realloc

Here's a short illustration of why we need `realloc` even though we
already have `Pointer.add`:

```
(defn foo []
  (let-do [p (Pointer.unsafe-alloc 2)]
    (set! p (Pointer.add p (Pointer.width (Pointer.unsafe-alloc @"foo"))))
    (ignore (Pointer.unsafe-set p @"foo"))
    (println* (Pointer.to-value (the (Ptr String) (Unsafe.coerce p))))
    (Pointer.free p)
    0))
```

This function seems fine at first glance, but since `add` returns a new
pointer, `p` is reset to the new pointer, the reference to the original
is lost, and `free` is called on a value that was never actually
allocated since `add` does not malloc.

Using unsafe-realloc, we can avoid the additional allocation:

```
(defn foo []
  (let-do [p (Pointer.unsafe-alloc 2)]
    (Pointer.unsafe-realloc p @"foo")
    (ignore (Pointer.unsafe-set p @"foo"))
    (println* (Pointer.to-value (the (Ptr String) (Unsafe.coerce p))))
    (Pointer.free p)
    0))
```

The allocation is what we care about here. One still needs to use
`Unsafe.coerce` since as far as the Carp compiler is concerned, `p` is
still a (Ptr Int) even though the corresponding c has cast it silently
to a `String` in order to reallocate.

* Pointer: Change signature of unsafe-set to align with set!

* Pointer: Change signature of `set` to align with `set!`

* Pointer: Remove unsafe-realloc

* Pointer: Update docs for unsafe-alloc and free

* System: Remove System.free

Pointer.free serves a similar function, and is more restrictive, so
we'll remove System.free. One can use `delete` or cast to a pointer and
free that way.See PR #1012 for further discussion.
2020-11-30 07:06:04 +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
wltsmrz
8c07bda22a
Use CARP_MALLOC throughout carp_stdint (#1024) 2020-11-27 10:19:32 +01:00
rrruko
e3af878e2a
Return reference from unsafe-first/unsafe-last (#1027)
* core: return Array.unsafe-first as reference (#970)

* core: return Array.unsafe-last as reference (#970)

* Make examples and tests build
2020-11-27 10:19:06 +01:00
Tim Dévé
36f41e39a7
Adds Function.unsafe-ptr & Function.unsafe-env-ptr (#1026)
This functions are useful with binding callback based C APIs
2020-11-27 10:17:29 +01:00
Scott Olsen
f1ea2b39ef
Unit: Add implementations of = (#1017) 2020-11-24 19:31:53 +01:00
Scott Olsen
eb85906e52
Meta set fix and refactor (#1008)
* Meta: Fix hangs on calls to meta functions

This commit fixes a subtle bug whereby setting the meta of an existing
binder would cause hangs. Ultimately, this still points to an underlying
issue in our Lookup code that causes such loops, but for now this at
least fixes the hang introduced by the doc call in `core/Tuples.carp`
(see issue #842).

The primary fix seems to be related to setting the parentEnv in a case
in which we failed to do so in `Eval.hs`. Additionally, our meta setting
macros call `eval` which causes them to be evaluated *immediately after*
expansion, causing them to be evaluated in the incorrect context in the
Tuples.carp case.

Additionally:

- Refactored primitiveMetaSet and primitiveMeta to make them cleaner.
- Only set `implements` early when we're certain we won't accidentally
  overwrite the interface.
- Generalize DocStub to `MetaStub` so that it may be used for forward
  meta declarations of any kind.

* Macros: Don't eval meta-set! macros

Calling eval in the body of the meta-set! macros can cause them to be
evaluated before anticipated, possibly setting the meta on a binding in
the incorrect environment. An exemplary case of this issue existed in
`Tuples.carp` (also fixed in this commit) whereby the generated
defmodule for a tuple type called doc, which was evaluated *before* the
emitted module, resulting in overwrites of global name docs instead of
the expected module function.

We retain `evals` in macros that are more useful in the repl, such as
`print-doc`. If a user wants to evaluated one of the meta-set macros in
the REPL, they'll need to add a call to eval.

* Macros: Restore calls to eval

Turns out the meta-set! macros *do* require calls to eval, unlike I
reported in the previous commit. This commit restores those and replaces
the `doc` call in `Tuples.carp` with a direct `meta-set!` to ensure we
have docs for those functions.

Also fixed a small error in implements primitive.

* Primitives: Refactor i->inner in primitiveImplements
2020-11-24 19:27:34 +01:00
jacereda
9520caf658
Replace return by pure. (#1009)
* Replace return by pure.

* Remove commandHelp again.
2020-11-24 06:09:15 +01:00
Erik Svedäng
a873099640
chore: Move some examples to test/produces-output (#989)
* chore: Moved examples that work more as tests to folder 'test/produces-output'

* fix: Corrections to the release script

* fix: Correct filename on Windows

* fix: Move more files around

* fix: Remove check-malloc example

* fix: Apparently unicode example does not work

* chore: Move nested_lambdas.carp back to examples

* chore: Remove .DS_Store files

* fix: Bring back unicode test

* test: Make sure benchmark compile (had to remove mandelbrot and n-bodies)

* fix: Replacement implementation of clock_gettime on Windows

* chore: Trigger CI

* fix: Define CLOCK_REALTIME

Co-authored-by: Erik Svedang <erik@Eriks-iMac.local>
2020-11-23 06:30:43 +01:00
jacereda
244df27942
Unicode fixes (#994)
* Some compilers (tcc) will complain switching on const values.

* Fix unicode example when compiling with -std=c99.
2020-11-22 06:45:26 +01:00
Scott Olsen
c1e794c4cc
More Unit type member enhancements (#986)
* Emit/Deftype: Add a few more special cases for Unit members

There were a few gaps remaining in our handling of Unit types as members
of user defined types, most notably, generic setters weren't handling
Units appropriately. This commit adds special checks for Unit types in
generic setters, and also accounts for a Unit refs:

- Specialize generic setter functions against Unit members
- Specialize calls to str/prn against Unit members in StructUtils
  (rather than accessing the struct member, which doesn't exist in the
  Unit case, we simple call Unit's prn function (added in the next
  commit).
- Don't bind references to Unit values to variables. This fixes an error
  whereby a reference to a Unit would generate invalid C such as:
  `void* _9 = &;`
  Likewise, we omit references to Units from function arguments just as
  we omit Unit values.

* Unit: Add Unit type implementations for common interfaces.

Now that Unit can be used as a member type it is subject to several
interfaces, such as prn, that it previously hadn't implemented.

This commit adds Unit.carp to core which implements `prn`, `copy`, and
`zero` for the Unit type.

* Deftype: Return null pointers for Unit getters

This is *hopefully* one of the final updates needed to fully support
Unit's as member types. Getters for fields of such types have no struct
member to read, but are expected to return a void pointer; so we return
a NULL void pointer instead.

This commit also updates our emissions for function calls to prevent
assigning the results of functions with Unit and (Ref Unit) return types
to variables.

* Emit: Filter void args from lambda calls

Just as we filter void argument types from other function calls, we now
filter them from calls to lambdas.
2020-11-21 05:57:03 +01:00
Erik Svedäng
f3eebf1aba docs: Try adding some docs to retrigger github action 2020-11-18 22:53:13 +01:00
Erik Svedäng
2f302aa046
Merge pull request #973 from jacereda/fix-suffix
Fix suffix docs and implementation, simplify prefix.
2020-11-17 23:59:46 +01:00
Jorge Acereda
e4d4a345b8 Fix suffix docs and implementation, simplify prefix. 2020-11-17 23:42:03 +01:00
Erik Svedäng
4e943bd506
Merge pull request #942 from hellerve/veit/reseed
Call Random.reseed at program start
2020-11-17 22:29:58 +01:00
Jorge Acereda
2d91f49600 Fix crash reported in #923. 2020-11-16 23:46:16 +01:00
Erik Svedäng
fe9b07927a feat: Bring back the original (problematic) function 2020-11-11 06:58:41 +01:00
Erik Svedang
47dfd5900b fix: Make nameOfPolymorphicFunction not add so suffix to external functions 2020-11-10 23:14:26 +01:00
Tim Dévé
4971be73f4 Moves scripts in scripts folder 2020-11-09 10:51:11 +00:00
Tim Dévé
9a3870afe4 Adds unsafe-raw to StaticArray module 2020-11-07 17:49:41 +00:00
hellerve
acce3a471c register-type: fix for void 2020-11-05 16:49:32 +01:00
Erik Svedäng
7f4594c63f
Merge pull request #947 from TimDeve/split-str-out-of-stdint
Moves StdInt functions with dependency on String into String.carp
2020-10-26 21:20:43 +01:00
Tim Dévé
cbda258fcc Moves StdInt functions with dependency on String into String.carp
This allows to import StdInt.carp by itself in --no-core situations
2020-10-26 19:14:50 +00: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
0059729cc9
Merge pull request #944 from hellerve/veit/fix-sdl
Fix SDL for newer versions
2020-10-16 07:16:31 +02:00
hellerve
a3dd41ee25 docs: fix typo in Quadruple docs 2020-10-15 15:16:37 +02:00
hellerve
729d654a87 core: fix SDL for newer versions 2020-10-15 13:14:31 +02:00
hellerve
1e04da3dac core: call Random.reseed at program start 2020-10-14 15:31:26 +02: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
Erik Svedäng
ec20679440
Merge pull request #918 from hellerve/veit/static-args
core: use static array for args
2020-08-26 20:57:56 +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
hellerve
ef355b91d8 core: use static array for args 2020-08-24 11:20:52 +02:00
Scott Olsen
af1d0065e2 Index arguments from 0 in with-copy
Indexing from zero is consistent with the rest of Carp's indexing
behavior, so this should make the function more predictable. I've also
added a note to the docs about this.
2020-08-18 22:52:56 -04:00
scottolsen
3a82e7d5c0 Rename proxy->with-copy, update docs
with-copy better communicates that this macro will produce a function
that performs a copy--it doesn't cover the fact that it creates a
references to an anonymous function...but there's only so much we can
cover in a name.

I've also updated the documentation.
2020-08-10 17:59:26 -04:00
scottolsen
14a3d9b5ab Support introspection on external functions
Like the previous two commits, this commit extends support for
reflection to yet another type, externally registered functions,
allowing us to support calls such as `(arity Int.+)`.
2020-08-10 17:56:28 -04:00
scottolsen
33a7f51c7b Support introspecting primitives
Just as the prior commit added support for capturing the arity of
registered commands, this one captures the arity of registered
primitives, enabling one to make calls such as `(arity defmacro)`, etc.

I have also moved the dummy argument name function into Util.hs since
it's used in both Commands.hs and Primitives.hs.
2020-08-10 17:06:46 -04:00
scottolsen
607d0c0664 Support introspection of commands
Previously, the command xobjs did not capture the arity of their
definitions. After this commit, they do, which enables us to surface
useful information about commands in reflective modules such as
core/Introspection.

Calls such as `(arity Dynamic.+)` and `(arity Dynamic.load)` will work
after this change.
2020-08-10 15:57:55 -04:00
scottolsen
6327f51c73 Add a proxy macro for generating functions for higher-orders
It's a fairly common pattern in Carp to call a higher-order function on
some structure of values, such as an Array. However, these structures,
and their members, all have lifetimes under Carp's memory management
model, which means they expect functions that are mapped over them to
take *a reference to a value* rather than a pure value. Array.reduce is
one example of such a "referential" higher-order, the type of its
function argument is:

```
(Fn [a, (Ref b c)] a)
```

That is, this function takes some pure initial value, then expects to be
called against the members of an array, which are *references* to the
values that are alive throughout the Array's lifetime.

However, one often wants to use a function that operates on pure values
in such contexts, such as +, which forces the programmer to write
anonymous functions that handle copying referenced values to pass them
to the underlying "pure" function:

```
(Array.reduce &(fn [x y] (+ x @y)) 0 &[1 2 3])
```

So, in using some high-order function over some structure in Carp one
usually has to do two things:

1. Wrap the function in a ref
2. Handle copying references into values in order to pass them into some
   simpler function that can also be used outside of memory-bound
   contexts.

The `proxy` macro captures this pattern. It wraps a given function in a
referenced anonymous function and copies an argument of that function at
a designated position before calling the underlying function. For
example, with `proxy`, the above example becomes:

```
(Array.reduce (proxy + 2) 0 &[1 2 3])
```

The macro effectively gives a name to a common pattern--typically it
will only save the programmer a few characters, but it perhaps makes the
act of using a "function that doesn't care about references" in a
reference dominant context more apparent.

One can also use the macro to develop more specialized macros for
certain higher-orders, since these usually dictate where copying must be
performed. For instance, the `Array.reduce` function argument always
expects the referenced value to occur in the second position, thus one
could write:

```
(defmacro reducer [function] (eval (list proxy function 2)))
```

Then the above code becomes even simpler:

```
(Array.reducer (reducer +) 0 &[1 2 3])
```

Which roughly means, "use the + function (which has no concept of
references) in this reference dependent context".

N.B. The examples using `+` won't work as of now due to current bugs
related to calling `arity` directly on an interface--but a synonym for
plus `add` defined as an explicit function will make all the above work
as expected.
2020-08-07 17:12:43 -04: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
Erik Svedäng
5f8e9318b2
Merge pull request #906 from hellerve/veit/string-from-bytes
Add String.from-bytes
2020-07-13 14:09:07 +02:00
Erik Svedäng
027a189c1e
Merge pull request #905 from hellerve/veit/bit-interfaces
make bit-* interfaces
2020-07-13 14:08:41 +02:00
Erik Svedäng
0a2a2d257f
Merge pull request #894 from jacereda/addc
Added add-c to include additional compilation units in the compiler i…
2020-07-13 14:07:53 +02:00
hellerve
3b8b668bdf core: fix syntax error 2020-07-08 22:00:43 +02:00
hellerve
57a5226a62 core: make sure string is null-terminated in String.from-bytes 2020-07-08 21:56:15 +02:00
hellerve
91b220c051 core: add String.from-bytes 2020-07-08 21:56:14 +02:00
hellerve
06607c2203 core: make bit-* interfaces 2020-07-08 21:11:28 +02:00
Erik Svedäng
28873e92d0
Merge pull request #896 from hellerve/veit/unreachable
Add unreachable
2020-07-03 09:42:14 +02:00
Jorge Acereda
d6aa71702e Add header/lib for OpenGL on each platform. 2020-06-29 11:57:06 +02:00
Jorge Acereda
134d9a5b02 Implement load-stack. 2020-06-28 19:53:43 +02:00
Jorge Acereda
0d7533e887 Register additional modules in project. 2020-06-27 21:48:46 +02: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
Erik Svedäng
73bb5735c1
Merge pull request #893 from scolsen/private
Implement Privacy Checking
2020-06-22 20:51:08 +02:00
Jorge Acereda
e6cf941187 Added add-c to include additional compilation units in the compiler invocation. 2020-06-21 17:22:24 +02:00
scottolsen
b94b49bf86 Implement private
Even though `private?` has been around for a while, and we document the
behavior of `private` as marking a binding as private to a module--it
was never implemented as far as I can tell.

This implements private by adding a simple check to the evaluator. If a
binding is found in the global context, we check if it's marked as
private. If so, we inform the user that it can't be called from outside
of its module.

Note that we don't perform this check if the binding is found in the
internal env, since that means it's a function called within the same
module and thus is ok (even if marked as private).

After this change, something like the following works, granting us
proper encapsulation:

```
;; File Foo.carp
(deftype Foo [bar Int])

(private Foo.bar)

(defmodule Foo
  (defn get [foo]
    (Foo.bar foo))
)

;; Enter REPL
(load "Foo.carp")
(Foo.bar &(Foo.init 1))
The binding: Foo.bar is private; it may only be used within the module
that defines it. at REPL:1:2.
@(Foo.get &(Foo.init 1))
Compiled to 'out/Untitled' (executable)
1
=> 0
```

N.B. I also had to remove a private declaration from fmt-internal--this
declaration didn't really make much sense anyway, as fmt-internal is a
global function, so module-based privacy is not enforceable.
2020-06-19 10:30:55 -04:00
scottolsen
da3be90b55 Merge branch 'master' of https://github.com/carp-lang/Carp into opaque 2020-06-19 09:18:34 -04:00
Erik Svedäng
15bdf38f23
Merge pull request #888 from hellerve/veit/phantoms
core: add Phantom
2020-06-19 09:30:42 +02:00
Basile Pesin
3b258badce Added some of GLFW constants 2020-06-18 23:19:31 +02:00
scottolsen
b63f981575 Update Opaque docs; fix typos 2020-06-18 09:57:28 -04:00
scottolsen
204ebc85e4 Load the Opaque type 2020-06-17 18:16:58 -04:00
scottolsen
b3a5ab8622 Add the Opaque type
The opaque type is an uninhabited type with no constructors.  Opaque can
be used to force some abstract type to range over a type constructor
without concerning oneself with the inhabitant of the constructor--in
other words, it may be used to enable a type to work for all inhabitants
and can express relationships between types. It can facillitate generic
programming.

Consider an example:

```
;; The type of indicies over containers of a single type argument
(deftype (Index (f Opaque) b) [at b])

(definterface tabulate (Fn [(Ref (Fn [(Index (f Opaque) b)] c))] (f c)))
(definterface positions (f (Index (f Opaque) b)))

(implements tabulate tabulate)
(defn tabulate [h]
  (fmap h @&positions))

(deftype (Tuple a) [x a y a])

(defmodule Tuple
  (sig positions (Tuple (Index (Tuple Opaque) Bool)))
  (def positions (Tuple.init (Index.init true) (Index.init false)))
)
```

In the above example, the Opaque type allows us to define tabulate
generically defined over Tuples without having to ensure their
inhabitants match, allowing us to fully determine the resulting values
type via tabulate's function argument. Without Opaque, Index would
contain a generic type which would be unreseolved upon the call to
`tabulate`. It allows us to ensure the `positions` we call are the
positions of the correct constructor type `f` wihtout worrying having to
restrict ourselves to only calling `Indexes` over an `f` of a specific
type  (e.g. `(f a)`)--in other words, it allows us to constrain
functions by constructor types only.

Thanks to Opaque, tabulate can generate an `(Array Int)`, `(Array
Bool)`, `(Array String)` all solely dependent on the return type of `h`.
2020-06-17 18:14:23 -04:00
hellerve
1d0944a187 core: add docs for phantom 2020-06-17 19:06:49 +02:00
hellerve
e5fd0e73f9 core: add phantom 2020-06-14 12:16:45 +02:00
Jorge Acereda
6656d96791 Add pkgconfigflags. 2020-06-01 21:34:12 +02:00
Jorge Acereda
5db1f0101f Remove braces so different clang-formats output the same. 2020-05-30 09:32:50 +02:00
Jorge Acereda
543a90ffa0 Add joinLines. 2020-05-30 09:19:26 +02:00
scottolsen
383f400a32 Fix length checks, use or 2020-05-27 15:22:42 -04:00
scottolsen
095866e45f Add length checks to struct? and sumtype? for safety 2020-05-27 15:03:10 -04:00
scottolsen
b0d9a34375 Update Introspect to work with the s-expr command 2020-05-27 13:33:43 -04:00
hellerve
357d28a167 core: update doc of cond 2020-05-26 21:50:26 +02:00
Erik Svedäng
bbb7920332
Merge pull request #815 from hellerve/veit/fix-776
Make Array.range safe
2020-05-26 20:55:16 +02:00
Erik Svedäng
bf4fed793a
Merge pull request #833 from hellerve/veit/fix-830
Autogenerate Tuple types and document
2020-05-26 20:51:46 +02:00
Scott Olsen
9b9aa76b59 Improve introspection support for interfaces
Previously, introspecting an interface only returned `definterface` and
its name. We now return the form corresponding to the interface's types
signature, which enables us to introspect more effectively; e.g.
returning the appropriate arity of an interface.
2020-05-24 17:02:35 -04:00
hellerve
229264f7d1 core: update dcostring for range-or-default 2020-05-24 12:51:11 +02:00
hellerve
be8424657d core: rename unsafe-range to range-or-default 2020-05-24 12:26:18 +02:00
hellerve
9be2b8e4fb core: autogenerate Tuple types and document 2020-05-24 11:49:27 +02:00
Erik Svedäng
ea372b1728
Merge pull request #827 from jacereda/cmdline-eval
Command line switches to evaluate code
2020-05-24 11:45:44 +02:00
Scott Olsen
4a29c6a998 Rename s-exp -> s-expr 2020-05-23 15:42:32 -04:00
Jorge Acereda
b681cf2644 Detect __builtin_x_overflow() based on __GNUC__ macro. 2020-05-23 19:03:07 +02:00