Commit Graph

4521 Commits

Author SHA1 Message Date
hellerve
729d654a87 core: fix SDL for newer versions 2020-10-15 13:14:31 +02:00
Erik Svedäng
772051ede9
Merge pull request #939 from scolsen/reify
Enhance type reflection
2020-10-06 19:54:47 +02:00
Erik Svedäng
f34cf47693
Merge pull request #938 from hellerve/veit/better-eq
Expand comparables in dynamic =
2020-10-03 22:18:26 +02:00
scottolsen
4519b77161 Promote type's matching on types of Carp types
This is necessary to ensure we distinguish between the symbol "Type" as
returned by `type` from the type/module "Type" potentially defined by a
user:

```
(deftype Type)
(type Type)
=> Module
(type (type 1))
=> Type
;; Even though the symbol conflicts with the module defined above,
;; subsequent calls to type return the correct result.
(type (type (type 1)))
=> ()
```
2020-10-03 12:48:59 -04:00
scottolsen
1206ad2309 Update 2020-10-02 18:03:34 -04:00
scottolsen
25839de02d Enhance type reflection; get types of values, get kinds
Extends Carp's support for type reflection by returning types for
values as well as bindings.

`type` now also returns a valid Carp expression/s-expression and so its
output can be used as input to dynamic functions and macros (prior to
this commit, `type` printed the type to the REPL but did not return a
meaningful expression in Carp).

Here are a few illustrations of the behavior:

```
(def x 1)
;; type now returns an s-expression/symbol
(type x)
=> Int
;; It also works on values
(type 1)
=> Int
(type 2b)
=> Byte
(type "foo")
=> (Ref String <StaticLifetime>)
;; It works on more complex values as well
(type Maybe)
=> Module
(type Maybe.Just)
(Fn [a] (Maybe a) <StaticLifetime>)
;; reports honestly about polymorphism
(type (Maybe.Nothing))
=> (Maybe a)
(type (Pair.init 1 2))
=> (Pair Int Int)
;; What about the type of types?
(type (type 2))
=> Type
;; Or the type of types of types?
(type (type (type 2)))
=> ()
;; One more time!
(type (type (type (type 2))))
=> ()
;; so, () is the fixpoint of type, and is reached after two applications
(type zero)
;; the type of an interface is all of its implementations
=> (((Fn [] (Array a) <StaticLifetime>) (Fn [] Bool <StaticLifetime>) (Fn
[] Byte <StaticLifetime>) (Fn [] Char <StaticLifetime>) (Fn [] Double
<StaticLifetime>) (Fn [] Float <StaticLifetime>) (Fn [] Int
<StaticLifetime>) (Fn [] Int16 <StaticLifetime>) (Fn [] Int32
<StaticLifetime>) (Fn [] Int64 <StaticLifetime>) (Fn [] Int8
<StaticLifetime>) (Fn [] Long <StaticLifetime>) (Fn [] (Maybe a)
<StaticLifetime>) (Fn [] (Pair a b) <StaticLifetime>) (Fn [] (Quadruple
a b c d) <StaticLifetime>) (Fn [] String <StaticLifetime>) (Fn []
(Triple a b c) <StaticLifetime>) (Fn [] Uint16 <StaticLifetime>) (Fn []
Uint32 <StaticLifetime>) (Fn [] Uint64 <StaticLifetime>) (Fn [] Uint8
<StaticLifetime>)))
```

As shown in the example above, this change also includes a cosmetic
update to the representation of lifetime variables, which are surrounded
in <> to distinguish them from type variables.

This commit also adds a new `kind` primitive that reports on the kind of
a binding or value:

```
(def x 3)
(kind x)
=> Base
(kind 2)
=> Base
(kind Maybe.Just)
=> Higher
(kind (Maybe.Just 2))
=> Higher
```

`kind` and `type` both support interactive development in the repl, for
example, a user can rely on `kind` to check the kind of a type they plan
on using in an interface that demands a higher-kinded argument.

Likewise, they both also support developing macros based on type
information.
2020-10-02 17:48:58 -04:00
hellerve
309a8c2a23 commands: add length check to list and arry = 2020-10-02 18:38:53 +02:00
hellerve
be13979027 commands: expand comparables in = 2020-10-02 17:22:12 +02:00
Erik Svedäng
bb80a2acbb
Merge pull request #935 from scolsen/macro-doc
Make `doc` take a rest parameter of strings
2020-10-02 09:04:57 +02:00
Erik Svedäng
21de495620
Merge pull request #937 from scolsen/doc-def-dynamic
Add DefDynamic to getPath
2020-10-02 08:59:01 +02:00
scottolsen
0d43b492e5 Add DefDynamic to getPath
getPath returns the path of a form. The DefDynamic case was missing from
the function's definition, resulting in failures when calling functions
such as the meta set primitive on dynamic defs. This change fixes such
issues.
2020-10-01 16:46:53 -04: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
4cd1c08ca1
Merge pull request #932 from hellerve/veit/remove-scratch
Remove scratch file
2020-09-27 20:21:37 +02:00
hellerve
34a081627f remove scratch file 2020-09-27 18:54:26 +02:00
Erik Svedäng
ba394330dd
Merge pull request #929 from MuhammedZakir/MuhammedZakir-patch-1
Test Mac Github actions build
2020-09-27 10:07:10 +02:00
Muhammed Zakir
7e591804a8
Move env command before cache 2020-09-25 10:39:15 +00:00
Muhammed Zakir
d38c6b706e
Move action-cache before action-setup-haskell 2020-09-25 10:13:20 +00:00
Muhammed Zakir
c6caa3aeff
set stack version to 2.3.1 instead of latest 2020-09-24 17:51:20 +00:00
Muhammed Zakir
73ce5860b0
Test github action mac build 2020-09-24 17:28:09 +00:00
Erik Svedäng
7420efe702
Merge pull request #926 from scolsen/language-guide-interfaces-update
Add docs on interfaces and `implements`
2020-09-21 22:28:20 +02:00
Erik Svedang
e43f4eb93d Nicer name? 2020-09-21 22:26:39 +02:00
Erik Svedang
d8410f4000 Disable macOS release for now. 2020-09-21 22:13:04 +02:00
Erik Svedang
33f2cb5906 Try releasing on Linux instead. 2020-09-21 22:04:34 +02:00
scottolsen
af62b6f1b8 Add docs on interfaces and implements
Interfaces are now explicitly implemented using the `implements` key
word (in the past, implementation of an interface was implicit based on
matching names and function signatures).

This commit updates the language guide to account for this change and
includes an illustrative example to provide guidance on using
interfaces.
2020-09-21 15:59:13 -04:00
Erik Svedang
06de06dd3d Remove a bunch of code. 2020-09-21 21:51:59 +02:00
Erik Svedang
900c839409 Try again. 2020-09-21 21:37:17 +02:00
Erik Svedang
456eadd077 Fix script. 2020-09-21 21:25:06 +02:00
Erik Svedang
3ab1e26efe More advanced haskell setup. 2020-09-21 21:23:37 +02:00
Erik Svedang
7b23549491 Just try building instead. 2020-09-21 21:15:24 +02:00
Erik Svedang
caecfa70d0 First attempt at a release script (for macOS). 2020-09-21 20:11:36 +02: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
Erik Svedäng
4dd61db153 Merge branch 'master' of https://github.com/carp-lang/Carp 2020-08-26 20:44:22 +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
8ffaa908e5 eval: add comment about forcing trick in eval 2020-08-25 10:31:53 +02:00
hellerve
ef355b91d8 core: use static array for args 2020-08-24 11:20:52 +02:00
Erik Svedäng
1dd7723a5e
Merge pull request #914 from scolsen/prelude-last-fix
Ensure command last calls handle empty lists
2020-08-23 20:32:10 +02:00
Scott Olsen
f2e798cf9a Ensure command last calls handle empty lists
The `last` command relies on Haskell's `Prelude.last`--which will crash
on an empty list input. We report an error for incorrect input to last,
but we didn't handle the empty list case. This small change to our
pattern match ensures errors in carp code produce Carp's last command
error rather than causing `Prelude.last` to throw an error on empty list
input.
2020-08-21 17:58:39 -04: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
Erik Svedäng
c1e33e28a7
Merge pull request #912 from jacereda/fixpathdocs
Fix Path docs.
2020-08-16 12:15:31 +02:00
Jorge Acereda
fcef6af3f4 Fix Path docs. 2020-08-13 21:08:21 +02: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
dd561f579d
Merge pull request #908 from vyp/fix-docs
docs: fix some typos and minor grammatical errors
2020-08-02 22:27:55 +02:00
xd1le
d1da7af2bc docs: fix some typos and minor grammatical errors 2020-07-26 08:30:37 +10:00