|
2 | 2 |
|
3 | 3 | Compile and run Constraint Handling Rules (CHR) in JavaScript. |
4 | 4 |
|
| 5 | +CHR.js is a just-in-time (JIT) compiler for Constraint Handling Rules, embedded in JavaScript. For better runtime performance it supports ahead-of-time (AOT) compilation too, either by its command line tool `chrjs` or [babel-plugin-chr](https://github.com/fnogatz/babel-plugin-chr), a plugin for Babel. |
| 6 | + |
5 | 7 | ## Getting Started |
6 | 8 |
|
7 | 9 | The [online version at chrjs.net](http://chrjs.net/) is the easiest way to generate a constraint solver. Just enter your Constraint Handling Rules, try adding some constraints, and download the generated solver code. |
8 | 10 |
|
9 | | -## Install |
10 | | - |
11 | | - npm install chr |
12 | | - |
13 | | -## Usage as CLI |
14 | | - |
15 | | -If you install CHR.js via npm it will create a new `chrjs` executable: |
16 | | - |
17 | | - $ chrjs /path/to/your.chr > /created/constrainthandler.js |
18 | | - |
19 | | -If no path is specified, `chrjs` reads from stdin. |
20 | | - |
21 | | -## Usage with node.js |
22 | | - |
23 | | -The CHR.js module can be used programmatically: |
24 | | - |
25 | | - var chrjs = require('chr') |
26 | | - |
27 | | - var code = chrjs.transform('a ==> b') |
28 | | - chrjs.transformFile('path.chr', function(err, code) { |
29 | | - console.log(code) |
30 | | - }) |
31 | | - |
32 | 11 | ## Example |
33 | 12 |
|
34 | | -Consider the following CHR source code, which generates all fibonacci numbers upto a given index `N` as constraints of the form `fib(Number,Value)`: |
35 | | - |
36 | | - upto(N), fib(A,AV), fib(B,BV) ==> B === A+1, B < N | fib(B+1,AV+BV); |
37 | | - |
38 | | -The CHR source code can be compiled to JavaScript by the use of the `chrjs` command: |
39 | | - |
40 | | - $ echo 'upto(N), fib(A,AV), fib(B,BV) ==> B === A+1, B < N | fib(B+1,AV+BV);' | chrjs > fib.js |
41 | | - |
42 | | -The generated JavaScript code has references to `chr/runtime` components, so make sure it is available. Open a REPL to play with the generated `fib.js`: |
43 | | - |
44 | | - $ node |
45 | | - > var konsole = require('chr/console') // for graphical representation |
46 | | - > var CHR = require('./fib.js') // load the generated source |
47 | | - > CHR.fib(1,1) // the first fibonacci is 0 |
48 | | - > CHR.fib(2,1) // the second is 1 |
49 | | - > konsole(CHR.Store) // print the content of the |
50 | | - ┌────────────┐ // constraint store |
51 | | - │ Constraint │ |
52 | | - ├────────────┤ |
53 | | - │ fib(1,1) │ |
54 | | - ├────────────┤ |
55 | | - │ fib(2,1) │ |
56 | | - └────────────┘ |
57 | | - > CHR.upto(5) // generate the first 5 fibs |
58 | | - > konsole(CHR.Store) // print the content of the |
59 | | - ┌────────────┐ // constraint store again |
60 | | - │ Constraint │ |
61 | | - ├────────────┤ |
62 | | - │ fib(1,1) │ |
63 | | - ├────────────┤ |
64 | | - │ fib(2,1) │ |
65 | | - ├────────────┤ |
66 | | - │ upto(5) │ |
67 | | - ├────────────┤ |
68 | | - │ fib(3,2) │ |
69 | | - ├────────────┤ |
70 | | - │ fib(4,3) │ |
71 | | - ├────────────┤ |
72 | | - │ fib(5,5) │ |
73 | | - └────────────┘ |
74 | | - > CHR.fib(6,8).fib(7,13) // constraints allow chaining |
75 | | - > CHR.Store.reset() // clear the constraint store |
76 | | - |
77 | | -More example CHR scripts are provided in the project's `/examples` directory or at [chrjs.net](http://chrjs.net/). |
| 13 | +The following CHR rule generates all fibonacci numbers upto a given index `Max` as constraints of the form `fib(Number,Value)`. |
| 14 | + |
| 15 | + upto(Max), fib(A,AV), fib(B,BV) ==> B === A+1, B < Max | fib(B+1,AV+BV) |
| 16 | + |
| 17 | +The CHR rule can be used in JavaScript after declaring it via the `chr()` function, like in this example: |
| 18 | + |
| 19 | + |
| 20 | + var CHR = require('chr') // load the module |
| 21 | + var konsole = require('chr/console') // little tool for graphical |
| 22 | + // representations |
| 23 | + |
| 24 | + var chr = CHR() // create new handler |
| 25 | + |
| 26 | + // add the rule |
| 27 | + chr('upto(Max), fib(A,AV), fib(B,BV) ==> B === A+1, B < Max | fib(B+1,AV+BV)') |
| 28 | + |
| 29 | + konsole.log(chr.Store) // print the content of the |
| 30 | + // constraint store |
| 31 | + /* results in: |
| 32 | + ┌────────────┐ |
| 33 | + │ Constraint │ |
| 34 | + ├────────────┤ |
| 35 | + │ (empty) │ |
| 36 | + └────────────┘ |
| 37 | + */ |
| 38 | + |
| 39 | + chr.fib(1,1) // the first fibonacci is 1 |
| 40 | + chr.fib(2,1) // the second is 1 |
| 41 | + |
| 42 | + konsole.log(chr.Store) // both have been stored |
| 43 | + /* results in: |
| 44 | + ┌────────────┐ |
| 45 | + │ Constraint │ |
| 46 | + ├────────────┤ |
| 47 | + │ fib(1,1) │ |
| 48 | + ├────────────┤ |
| 49 | + │ fib(2,1) │ |
| 50 | + └────────────┘ |
| 51 | + */ |
| 52 | + |
| 53 | + // now generate the fibonaccis upto the 5th element |
| 54 | + chr.upto(5) |
| 55 | + konsole.log(chr.Store) |
| 56 | + /* results in: |
| 57 | + ┌────────────┐ |
| 58 | + │ Constraint │ |
| 59 | + ├────────────┤ |
| 60 | + │ fib(1,1) │ |
| 61 | + ├────────────┤ |
| 62 | + │ fib(2,1) │ |
| 63 | + ├────────────┤ |
| 64 | + │ upto(5) │ |
| 65 | + ├────────────┤ |
| 66 | + │ fib(3,2) │ |
| 67 | + ├────────────┤ |
| 68 | + │ fib(4,3) │ |
| 69 | + ├────────────┤ |
| 70 | + │ fib(5,5) │ |
| 71 | + └────────────┘ |
| 72 | + */ |
| 73 | + |
| 74 | +More example CHR scripts are provided at [chrjs.net](http://chrjs.net/). |
| 75 | + |
| 76 | +Defining CHR rules in this way, they are compiled at runtime, that means we use a just-in-time (JIT) compilation. However, for performance reasons, we encourage the use of an ahead-of-time (AOT) compiler as presented in the [next section](#aot-compilation). |
| 77 | + |
| 78 | +## AOT Compilation |
| 79 | + |
| 80 | +The easiest way to precompile your JavaScript source code with embedded Constraint Handling Rules is by using [babel-plugin-chr](https://github.com/fnogatz/babel-plugin-chr), a plugin for [Babel](http://babeljs.io/): |
| 81 | + |
| 82 | + npm install babel-plugin-chr |
| 83 | + babel --plugins chr script.js |
| 84 | + |
| 85 | +However, CHR.js itself provides a command line tool to compile scripts that are dominated by Constraint Handling Rules: |
| 86 | + |
| 87 | + chrjs script.chr > script.js |
| 88 | + |
| 89 | +Please note, that the given `.chr` files must be of the following form, where CHR rules are the main elements and arbitrary JavaScript code must be placed in a preamble section: |
| 90 | + |
| 91 | + { |
| 92 | + // preamble |
| 93 | + // code in this block can be used in the rules' guards and bodies |
| 94 | + |
| 95 | + function print (v) { |
| 96 | + console.log(v) |
| 97 | + } |
| 98 | + |
| 99 | + function pred (v) { |
| 100 | + return v < 5 |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + print_num @ num(v) ==> ${ () => print(v) } |
| 105 | + generate_nums @ num(v) ==> ${ () => pred(v) } | num(v+1) |
| 106 | + |
| 107 | +Functions ecapsulated in `${ ... }` are evaluated at rule application, as for JIT compilation too. |
78 | 108 |
|
79 | 109 | ## Background |
80 | 110 |
|
81 | | -CHR.js was realized as a project as part of the Masters programme in Computer Science at the University of Ulm. Its Project Report with additional information about its architecture can be found online: https://fnogatz.github.io/paper-now-chrjs/. |
| 111 | +CHR.js was realized as a part of my Master Thesis in Computer Science at the University of Ulm, Germany. Its Project Report for a prototype implementation (versions `0.x`) with additional information about its architecture can be found online: https://fnogatz.github.io/paper-now-chrjs/. |
82 | 112 |
|
83 | 113 | The implementation is based on the compilation scheme presented in the paper [CHR for imperative host languages](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.149.8471) (2008; Peter Van Weert, Pieter Wuille, Tom Schrijvers, Bart Demoen). As of yet basically none of the mentioned optimizations have been implemented. |
84 | | - |
85 | | -A list of open points for improving can be found in the [wiki](https://github.com/fnogatz/CHR.js/wiki/Todo) and the [project report](https://fnogatz.github.io/paper-now-chrjs/#summary). |
|
0 commit comments