2017-06-26 12:45:18 +03:00
|
|
|
## The Language
|
|
|
|
|
2017-06-26 16:58:23 +03:00
|
|
|
### Introduction
|
2017-06-26 16:50:51 +03:00
|
|
|
Carp borrows its looks from Clojure but the runtime semantics are much closer to those of ML or Rust.
|
|
|
|
Types are inferred but can be annoted for readability using the ```the``` keyword (see below).
|
2017-06-26 12:45:18 +03:00
|
|
|
|
2017-06-26 16:58:23 +03:00
|
|
|
Memory management is handled by static analysis, a value is owned by the function where it was created.
|
|
|
|
When a value is returned or passed to another function the initial function will give up ownership of it
|
|
|
|
and any subsequent use will lead to a compiler error. To temporarily lend a value to another function
|
|
|
|
(i.e. to print it) a reference must be created, using the ```ref``` special form (or the ```&``` reader macro).
|
|
|
|
|
2017-10-17 23:48:02 +03:00
|
|
|
To learn more about the details of memory management, check out [Memory.md](https://github.com/carp-lang/Carp/blob/master/docs/Memory.md)
|
2017-10-17 23:47:21 +03:00
|
|
|
|
2017-06-26 17:09:12 +03:00
|
|
|
### Comments
|
|
|
|
```
|
2017-06-26 17:14:10 +03:00
|
|
|
;; Comments begin with a semicolon and continue until the end of the line.
|
2017-06-26 17:09:12 +03:00
|
|
|
```
|
|
|
|
|
2017-06-26 12:45:18 +03:00
|
|
|
### Data Literals
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-06-26 17:09:12 +03:00
|
|
|
100 ;; Int
|
2017-12-18 19:27:51 +03:00
|
|
|
1500l ;; Long
|
2017-06-26 17:09:12 +03:00
|
|
|
3.14f ;; Float
|
|
|
|
10.0 ;; Double
|
|
|
|
true ;; Bool
|
2017-11-28 10:02:11 +03:00
|
|
|
"hello" ;; &String
|
2018-03-02 17:29:29 +03:00
|
|
|
\#"hello" ;; &Pattern
|
2017-06-26 17:09:12 +03:00
|
|
|
\e ;; Char
|
|
|
|
[1 2 3] ;; (Array Int)
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
|
|
|
|
2017-06-26 17:12:41 +03:00
|
|
|
### Type Literals
|
|
|
|
```
|
2017-06-26 17:13:24 +03:00
|
|
|
t ;; Type variables begin with a lowercase letter
|
2017-06-26 17:12:41 +03:00
|
|
|
Int
|
2017-12-18 19:27:51 +03:00
|
|
|
Long
|
2017-06-26 17:12:41 +03:00
|
|
|
Float
|
|
|
|
Double
|
|
|
|
Bool
|
|
|
|
String
|
2018-03-02 17:29:29 +03:00
|
|
|
Pattern
|
2017-06-26 17:12:41 +03:00
|
|
|
Char
|
|
|
|
(Array t)
|
|
|
|
(Fn [<arg-type1> <arg-type2> ...] <return-type>) ;; Function type
|
|
|
|
```
|
|
|
|
|
2017-06-26 12:45:18 +03:00
|
|
|
### Dynamic-only Data Literals
|
|
|
|
Right now the following data types are only available for manipulation in non-compiled code.
|
|
|
|
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-06-26 12:45:18 +03:00
|
|
|
(1 2 3) ; list
|
|
|
|
foo ; symbol
|
|
|
|
```
|
|
|
|
|
2017-12-22 17:09:53 +03:00
|
|
|
### Defining things
|
|
|
|
```
|
|
|
|
(defn function-name [<arg1> <arg2> ...] <body>) ;; Define a function (will be compiled, can't be called at the REPL)
|
|
|
|
(definterface interface-name (Fn [<t1> <t2>] <return>)) ;; Define a generic function that can have multiple implementations
|
|
|
|
(def variable-name value) ;; Define a global variable (only handles primitive constants for the moment)
|
|
|
|
(defmacro <name> [<arg1> <arg2> ...] <macro-body>) ;; Define a macro, its argument will not be evaluated when called
|
|
|
|
(defdynamic <name> [<arg1> <arg2> ...] <function-body>) ;; A function that can only be used at the REPL or during compilation
|
|
|
|
(defmodule <name> <definition1> <definition2> ...) ;; The main way to organize your program into smaller parts
|
|
|
|
```
|
|
|
|
|
2017-06-26 12:45:18 +03:00
|
|
|
### Special Forms
|
2017-11-28 10:02:11 +03:00
|
|
|
The following forms can be used in Carp source code and will be compiled to C after type checking
|
2017-12-22 17:09:53 +03:00
|
|
|
and other static analysis. The first three of them are also available in dynamic functions.
|
2017-06-26 17:17:25 +03:00
|
|
|
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-12-22 17:09:53 +03:00
|
|
|
(let [<var1> <expr1> <var2> <expr2> ...] <body>) ;; Create local bindings
|
2017-06-26 17:09:12 +03:00
|
|
|
(do <expr1> <expr2> ... <return-expression>) ;; Perform side-effecting functions, then return a value
|
|
|
|
(if <expression> <true-branch> <false-branch>) ;; Branching
|
|
|
|
(while <expression> <body>) ;; Loop until expression is false
|
|
|
|
(ref <expression>) ;; Borrow an owned value
|
2017-06-26 16:50:51 +03:00
|
|
|
(address <expression>) ;; Takes the memory address of a value, returns a C-style pointer
|
|
|
|
(set! <variable> <expression>) ;; Mutate a variable
|
|
|
|
(the Int <expression>) ;; Explicitly declare the type of an expression
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
|
|
|
|
2017-06-26 16:58:23 +03:00
|
|
|
### Reader Macros
|
|
|
|
```
|
2017-06-26 17:09:12 +03:00
|
|
|
&x ;; same as (ref x)
|
|
|
|
@x ;; same as (copy x)
|
2017-06-26 16:58:23 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
### Named Holes
|
2017-06-26 16:50:51 +03:00
|
|
|
When using a statically typed language like Carp it can sometimes be hard to know what value should
|
|
|
|
be used at a specific point in your program. In such cases the concept of 'holes' can be useful. Just
|
|
|
|
add a hole in your source code and reload (":r") to let the Carp compiler figure out what type goes there.
|
|
|
|
|
|
|
|
```
|
2018-05-20 07:04:47 +03:00
|
|
|
(StringCopy.append ?w00t @"!") ;; Will generate a type error telling you that the type of '?w00t' is String
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
|
|
|
|
2017-12-23 08:38:45 +03:00
|
|
|
### Special forms during evaluation of dynamic code
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
2017-06-26 17:09:12 +03:00
|
|
|
(quote <expression>) ;; Avoid further evaluation of the expression
|
2017-12-23 08:38:45 +03:00
|
|
|
(and) (or) (not) ;; Logical operators
|
|
|
|
```
|
|
|
|
|
|
|
|
### Dynamic functions
|
|
|
|
These can only be used at the REPL and during macro evaluation. Here's a subset with some of the most commonly used ones:
|
|
|
|
|
|
|
|
```
|
2017-06-26 17:09:12 +03:00
|
|
|
(car <collection>) ;; Return the first element of a list or array
|
|
|
|
(cdr <collection>) ;; Return all but the first element of a list or array
|
|
|
|
(cons <expr> <list>) ;; Add the value of <expr> as the first element the <list>
|
2017-12-18 19:27:51 +03:00
|
|
|
(cons-last <expr> <list>) ;; Add the value of <expr> as the last element the <list>
|
2017-06-26 17:09:12 +03:00
|
|
|
(list <expr1> <expr2> ...) ;; Create a list from a series of evaluated expressions
|
|
|
|
(array <expr1> <expr2> ...) ;; Create an array from a series of evaluated expressions
|
2017-06-26 14:45:51 +03:00
|
|
|
```
|
|
|
|
|
2017-12-22 17:09:53 +03:00
|
|
|
To see all functions available in the `Dynamic` module, enter `(info Dynamic)` at the REPL.
|
|
|
|
|
2017-06-26 16:58:23 +03:00
|
|
|
### Modules and Name Lookup
|
2017-06-26 14:45:51 +03:00
|
|
|
Functions and variables can be stored in modules which are named and can be nested. To use a symbol inside a module
|
|
|
|
you need to qualify it with the module name, like this: ```Float.cos```.
|
|
|
|
|
2017-09-06 15:43:41 +03:00
|
|
|
*Using* a module makes it possible to access its members without qualifying them:
|
2017-06-26 14:45:51 +03:00
|
|
|
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-09-06 15:43:41 +03:00
|
|
|
(use Float)
|
2017-06-26 14:45:51 +03:00
|
|
|
|
|
|
|
(defn f []
|
|
|
|
(cos 3.2f))
|
|
|
|
```
|
|
|
|
|
2017-09-06 15:43:41 +03:00
|
|
|
If there are several used modules that contain symbols with the same name, the type inferer will try to figure
|
2017-06-26 14:45:51 +03:00
|
|
|
out which one of the symbols you really mean (based on the types in your code). If it can't, it will display an error.
|
2018-05-20 10:57:51 +03:00
|
|
|
For example, both the module ```String``` and ```Array``` contain a function named 'length'. In the following code it's
|
2017-06-26 14:45:51 +03:00
|
|
|
possible to see that it's the array version that is needed, and that one will be called:
|
|
|
|
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-09-06 15:43:41 +03:00
|
|
|
(use String)
|
|
|
|
(use Array)
|
2017-06-26 14:45:51 +03:00
|
|
|
|
|
|
|
(defn f []
|
2018-05-20 10:57:51 +03:00
|
|
|
(length [1 2 3 4 5]))
|
2017-06-26 14:45:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
In the following example it's not possible to figure out which type is intended:
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-09-06 15:43:41 +03:00
|
|
|
(use String)
|
|
|
|
(use Array)
|
2017-06-26 14:45:51 +03:00
|
|
|
|
|
|
|
(defn f [x]
|
2018-05-20 10:57:51 +03:00
|
|
|
(length x))
|
2017-06-26 14:45:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
Specifying the type solves this error:
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-09-06 15:43:41 +03:00
|
|
|
(use String)
|
|
|
|
(use Array)
|
2017-06-26 14:45:51 +03:00
|
|
|
|
|
|
|
(defn f [x]
|
2018-05-20 10:57:51 +03:00
|
|
|
(String.length x))
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
### Structs
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
|
|
|
(deftype Vector2 [x Int, y Int])
|
2017-06-26 12:45:18 +03:00
|
|
|
|
2017-06-26 16:50:51 +03:00
|
|
|
(let [my-pos (Vector2.init 10 20)]
|
2017-06-26 12:45:18 +03:00
|
|
|
...)
|
|
|
|
|
|
|
|
;; A 'lens' is automatically generated for each member:
|
2017-06-26 16:50:51 +03:00
|
|
|
(Vector2.x my-pos) ;; => 10
|
|
|
|
(Vector2.set-x my-pos 30) ;; => (Vector2 30 20)
|
|
|
|
(Vector2.update-x my-pos inc) ;; => (Vector2 11 20)
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|
|
|
|
|
2017-06-26 16:58:23 +03:00
|
|
|
### C Interop
|
2017-06-26 16:50:51 +03:00
|
|
|
```
|
2017-12-18 19:27:51 +03:00
|
|
|
(system-include "math.h") ;; compiles to #include <math.h>
|
|
|
|
(local-include "math.h") ;; compiles to #include "math.h"
|
|
|
|
|
2017-11-30 23:49:24 +03:00
|
|
|
(register blah (Fn [Int Int] String)) ;; Will register the function 'blah' that takes two Int:s and returns a String
|
2017-06-26 16:50:51 +03:00
|
|
|
(register pi Double) ;; Will register the global variable 'pi' of type Double
|
2017-12-22 17:01:00 +03:00
|
|
|
|
2018-02-26 21:53:23 +03:00
|
|
|
(register blah (Fn [Int Int] String) "exit") ;; Will register the function 'blah' but use the name 'exit' in the emitted C code.
|
|
|
|
|
2017-12-22 17:01:00 +03:00
|
|
|
(register-type Apple) ;; Register an opaque C type
|
|
|
|
(register-type Banana [price Double, size Int]) ;; Register an external C-structs, this will generate getters, setters and updaters.
|
2017-06-26 12:45:18 +03:00
|
|
|
```
|