Hash :
b293807e
Author :
Thomas de Grivel
Date :
2024-10-13T09:39:11
KC3 is a programming language with meta-programmation and a graph database embedded into the language. It aims to be the language for semantic programming, and programming the semantic web.
This is a development branch, see KC3 v0.1.13 for a stable release.
KC3 is currently a programming language project, inspired by C, Elixir and Common Lisp. It could be described as C with Elixir modules, pattern matching, and a semantic object system. The idea is to plug modules, closures, pattern matching, a graph database and metaprogramming into C99 with an extremely small set of dependencies.
Supported operating systems (additional dependencies) :
Supported architectures :
Join us on kmx.io Discord server !
# install build tools
sudo apt install pkg-config clang libtool-bin make ruby time
# install dependencies
sudo apt install libffi-dev libbsd-dev libevent-dev
# install demo dependencies
sudo apt install glew libfreetype-dev libsdl2-dev libxkbcommon-dev
# use clang
export CC=clang
git clone https://git.kmx.io/kc3-lang/kc3.git
cd kc3
git submodule init
git submodule update
cd fonts
git submodule init
git submodule update
cd ..
./configure
make
LD_LIBRARY_PATH
. ./env
make lib_links
make demo_gl
Press Q to quit, F for fullscreen, Left and Right arrows to move through sequences.
Other targets exist :
make demo_gl_asan
make gdb_demo_gl
make lldb_demo_gl
make demo
Press Q to quit, Left and Right arrows to move through sequences.
Other targets exist :
make demo_asan
make gdb_demo
make lldb_demo
make test_httpd
make test
All the tests will be run. More specific targets exist :
make test_libkc3
make test_ikc3
make test_libkc3_asan
make test_ikc3_asan
make test_asan
ikc3/.libs/ikc3
make gdb_ikc3
make gdb_test
make gen
./update_sources
Don’t forget to commit your files and the modified sources.mk and sources.sh files.
KC3 is implemented using libkc3 a small C99 library implementing the core of the language.
The library includes a parser and an interpreter for KC3 code in C structures.
Support for large integers provided by libtommath.
Support for C function calls provided by libffi.
Modules are saved as facts databases.
The parser is recursive descent.
The AST is represented as KC3 data structures and can be meta-programmed in C.
Under development.
Interactive shell. Terminal I/O provided by linenoise.
Example :
$ make test
$ ikc3/ikc3
ikc3> ikc3> 1 + 1
2
ikc3> 2 + 2
4
ikc3> 3 + 3
6
ikc3> 1 +
ikc3> 1
2
ikc3> double = fn (x) { x * 2 }
fn (x) { x * 2 }
ikc3> double
fn (x) { x * 2 }
ikc3> double(1)
2
ikc3> double(2)
4
ikc3> double(3)
6
ikc3> double(4)
8
ikc3> List.map([1, 2, 3, 4], double)
[2, 4, 6, 8]
ikc3> List.reverse(List.map([1, 2, 3, 4], double))
[8, 6, 4, 2]
The List.map
and List.reverse
functions are defined in
lib/kc3/0.1/list.kc3
and can be modified in real time.
For example, without closing ikc3 let’s redefine List.reverse
,
open an editor and change the line in lib/kc3/0.1/list.kc3
from
def reverse = fn {
(x) { reverse(x, ()) }
([], acc) { acc }
([a | b], acc) { reverse(b, [a | acc]) }
}
to
def reverse = fn {
(x) { reverse(x, ()) }
([], acc) { [:reversed | acc] }
([a | b], acc) { reverse(b, [a | acc]) }
}
}}
and check the results of the last command (up key) in ikc3/ikc3 :
ikc3> List.reverse(List.map([1, 2, 3, 4], double))
[:reversed, 8, 6, 4, 2]
Don’t forget to revert the changes to list.kc3
.
KC3 maps are key-value stores, you can use any tag as a key and associate a value to it.
You can use destructuring to access KC3 maps :
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a = %{}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> %{id: id, title: "My title", message: message} = a
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> id
1
ikc3> message
"Hello, world !"
You can use the dot syntax to access map values from a Sym
key :
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a.id
1
ikc3> a.message
"Hello, world !"
You can also use the KC3.access
function for the same result :
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> access(a, :id)
1
ikc3> access(a, :message)
"Hello, world !"
ikc3
fully supports Unicode :
Some unicode characters :
ikc3> '\U+1B2FB'
'𛋻'
ikc3> '𐅀'
'𐅀'
ikc3> '🤩'
'🤩'
ikc3>
ikc3> a = 1 + 100000000000000000000000000000000
100000000000000000000000000000001
ikc3> a * a
10000000000000000000000000000000200000000000000000000000000000001
ikc3>
Ratios are made with a couple of large integers : the numerator which can be any number, and the denominator which has to be positive. They represent fractions of integral numbers. They are written with a slash and no space.
ikc3> 1/2 + 2/3
7/6
ikc3> 1/2 * 2/3
1/3
ikc3> 1/2 / 2/3
3/4
ikc3> 1/2 - 2/3
-1/6
Complex numbers are constructed using the operator +i
on any kind of
numbers (unsigned, signed, float, ratios, and even other complex
numbers). For instance, you can write a +i b
where a
and b
are
real numbers.
ikc3> 1 +i 2
1 +i 2
ikc3> 1 +i 2 + 2 +i 3
3 +i 5
ikc3> (1 +i 2) * (2 +i 3)
-4 +i 7
ikc3> (1 +i 2) / (2 +i 3)
0 +i 0
ikc3> (1/1 +i 2/1) / (2 +i 3)
8/13 +i 1/13
As you can see integer division is not producing ratios. That might change in future releases.
Lists are marked with brackets []
.
Regular lists can be :
[1 | []]
→ [1]
[1, 2, 3]
[1, 2 | [3, 4]]
→ [1, 2, 3, 4]
[]
Regular lists end with the empty list : [1] == [1 | []]
.
You can also contruct dotted lists like in Common Lisp where the next list pointer is an arbitrary form. E.g. :
[1 | 2]
[1, 2, 3 | 4]
[[] | 1]
All these list formats are supported in pattern matching.
The KC3 pattern matching principles come from Erlang and Elixir.
All tag data structures in KC3 can be pattern matched using the equal
sign (=
) against litteral values containing identifiers. All
identifiers are supposed to be new bindings when using pattern matching
in KC3. If you want to use an identifier’s value in pattern matching you
must use the pin operator (^
). Variables can be assigned a new value
from either side of the equal sign and from inside a tag data structure,
which is called destructuring.
Examples :
ikc3> a = 1
1
ikc3> a = 2
2
ikc3> a
2
ikc3> ^ a = 1
void
ikc3> ^ a = 2
2
ikc3> ^ a = b
2
ikc3> b
2
To use destructuring just type the litteral value you want to match and put identifiers (variable names) where you want a variable matching the value on the other side of the equal sign. This is the most visual approach possible to text-based value matching : the data is constantly matched to litterals that show their type to the programmer. This is really helpful when writing large programs that need to scale in the way of abstractions. Let the data flow in the code through visual types.
Examples :
ikc3> [x, y | z] = List.reverse([1, 2, 3, 4])
[4, 3, 2, 1]
ikc3> x
4
ikc3> y
3
ikc3> z
[2, 1]
KC3 macros are like Common Lisp macros with Elixir pattern-matching.
Macros are like functions but start with macro
instead of fn
and
their arguments do not get evaluated. However they get pattern matched
and the full power of the pattern matcher is available for arguments
destructuring. Use a map if you want named arguments. Use a list if you
want &rest arguments, use a block if you want a &body argument.
When evaluated, a macro call returns a tag which is in turn evaluated in the calling site lexical environment. This allows for DSLs and custom control structures to be defined in KC3.
Many basic operations in KC3 are defined as macros : error handling,
free operations with unwind-protect
, graph database operations like
Facts.with
.
Conditionals in KC3 are like in Ruby, for example :
ikc3> if true && true
ikc3> 1 + 1
ikc3> 2 + 2
ikc3> end
4
ikc3> if true && false
ikc3> 1 + 1
ikc3> 2 + 2
ikc3> else
ikc3> 3 + 3
ikc3> 4 + 4
ikc3> end
8
A KC3 if
statement always return a value. If the condition is true, the
first (then) block gets evaluated. If the condition is false the second
block gets evaluated. If the condition is false and an else
block is
not provided, then void
gets returned.
One liner examples with then
:
ikc3> if 42 then 100 else 101 end
100
ikc3> if 0 then 100 else 101 end
101
Example :
ikc3> defmodule Example do
ikc3> def three = 3
ikc3> def double = fn (x) do x * 2 end
ikc3> def double_tuple = macro (x) do {x, x} end
ikc3> def operator_double = %KC3.Operator{sym: :double, symbol_value: fn (x) { x * 2 }
ikc3> end
Example
ikc3> Example.three
3
ikc3> Example.double
fn (x) do x * 2 end
ikc3> Example.double(21)
42
ikc3> Example.double_tuple(:ok)
{:ok, :ok}
ikc3> double 21
42
The Facts module allows read and write access to a graph database containing facts : triples of subject, predicate, object.
Examples for querying the KC3 database containing all definitions of the interpreter :
ikc3> Facts.with_tags(Facts.env_facts(), KC3, :operator, ?,
fn (fact) { puts(fact.object); :ok })
operator_eq
operator_gt
operator_lt
[...]
:ok
Script interpreter. Works the same as ikc3 but is not interactive and does not output results.
HTTP daemon, use make test_httpd
.
The http daemon is defined in httpd/httpd.c
and
lib/kc3/0.1/httpd.kc3
.
The http daemon is a static file server listing directories and serving files for display or download (Web 1.0).
(Macro) fn (x) { x }
\n
) (TAG_VOID: 1, TAG_TUPLE: (1+ (max (height tuple->tags))))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
# KC3 v0.1.14
KC3 is a programming language with meta-programmation and a graph
database embedded into the language. It aims to be the language
for semantic programming, and programming the semantic web.
This is a development branch, see
[KC3 v0.1.13](https://git.kmx.io/kc3-lang/kc3/_tree/v0.1.13/)
for a stable release.
KC3 is currently a programming language project, inspired by C, Elixir
and Common Lisp. It could be described as C with Elixir modules,
pattern matching, and a semantic object system. The idea is to plug
modules, closures, pattern matching, a graph database and
metaprogramming into C99 with an extremely small set of dependencies.
Supported operating systems (additional dependencies) :
- BSD
- Linux (libbsd, libmd)
- MacOS X (libmd)
- Windows (MSys2)
Supported architectures :
- aarch64 (arm64, Apple M1, Apple M2)
- amd64
- i386
- sparc64
## Discord invite
[Join us on kmx.io Discord server !](https://discord.gg/A4MWkpUDsG)
## Usage
### Install dependencies
#### Debian / Ubuntu / PopOS / Mint
```
# install build tools
sudo apt install pkg-config clang libtool-bin make ruby time
# install dependencies
sudo apt install libffi-dev libbsd-dev libevent-dev
# install demo dependencies
sudo apt install glew libfreetype-dev libsdl2-dev libxkbcommon-dev
# use clang
export CC=clang
```
### Compilation
```sh
git clone https://git.kmx.io/kc3-lang/kc3.git
cd kc3
git submodule init
git submodule update
cd fonts
git submodule init
git submodule update
cd ..
./configure
make
```
### Add the sources to `LD_LIBRARY_PATH`
```sh
. ./env
```
### Create symlinks to libs
```sh
make lib_links
```
### Running the OpenGL demo
```sh
make demo_gl
```
Press Q to quit, F for fullscreen, Left and Right arrows to move
through sequences.
Other targets exist :
```sh
make demo_gl_asan
make gdb_demo_gl
make lldb_demo_gl
```
### Running the Cairo demo
```sh
make demo
```
Press Q to quit, Left and Right arrows to move through sequences.
Other targets exist :
```sh
make demo_asan
make gdb_demo
make lldb_demo
```
### Running the HTTPd demo
```sh
make test_httpd
```
### Running the tests
```sh
make test
```
All the tests will be run. More specific targets exist :
```sh
make test_libkc3
make test_ikc3
make test_libkc3_asan
make test_ikc3_asan
make test_asan
```
### Running ikc3
```sh
ikc3/.libs/ikc3
```
### Running gdb
```sh
make gdb_ikc3
make gdb_test
```
### Adding or removing files from the source tree
```sh
make gen
./update_sources
```
Don't forget to commit your files and the modified sources.mk and
sources.sh files.
## Structure
### libkc3
KC3 is implemented using libkc3 a small C99 library implementing the core
of the language.
The library includes a parser and an interpreter for KC3 code in C
structures.
Support for large integers provided by
[libtommath](https://github.com/libtom/libtommath).
Support for C function calls provided by
[libffi](https://github.com/libffi/libffi).
Modules are saved as facts databases.
#### Parser
The parser is recursive descent.
#### AST
The AST is represented as KC3 data structures and can be meta-programmed
in C.
#### Interpreter
Under development.
### ikc3
Interactive shell. Terminal I/O provided by
[linenoise](https://github.com/antirez/linenoise/tree/1.0).
Example :
```
$ make test
$ ikc3/ikc3
ikc3> ikc3> 1 + 1
2
ikc3> 2 + 2
4
ikc3> 3 + 3
6
ikc3> 1 +
ikc3> 1
2
ikc3> double = fn (x) { x * 2 }
fn (x) { x * 2 }
ikc3> double
fn (x) { x * 2 }
ikc3> double(1)
2
ikc3> double(2)
4
ikc3> double(3)
6
ikc3> double(4)
8
ikc3> List.map([1, 2, 3, 4], double)
[2, 4, 6, 8]
ikc3> List.reverse(List.map([1, 2, 3, 4], double))
[8, 6, 4, 2]
```
The `List.map` and `List.reverse` functions are defined in
`lib/kc3/0.1/list.kc3` and can be modified in real time.
For example, without closing ikc3 let's redefine `List.reverse`,
open an editor and change the line in `lib/kc3/0.1/list.kc3` from
```
def reverse = fn {
(x) { reverse(x, ()) }
([], acc) { acc }
([a | b], acc) { reverse(b, [a | acc]) }
}
```
to
```
def reverse = fn {
(x) { reverse(x, ()) }
([], acc) { [:reversed | acc] }
([a | b], acc) { reverse(b, [a | acc]) }
}
}}
```
and check the results of the last command (up key) in ikc3/ikc3 :
```
ikc3> List.reverse(List.map([1, 2, 3, 4], double))
[:reversed, 8, 6, 4, 2]
```
Don't forget to revert the changes to `list.kc3`.
#### Maps
KC3 maps are key-value stores, you can use any tag as a key and
associate a value to it.
You can use destructuring to access KC3 maps :
```
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a = %{}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> %{id: id, title: "My title", message: message} = a
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> id
1
ikc3> message
"Hello, world !"
```
You can use the dot syntax to access map values from a `Sym` key :
```
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a.id
1
ikc3> a.message
"Hello, world !"
```
You can also use the `KC3.access` function for the same result :
```
ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> access(a, :id)
1
ikc3> access(a, :message)
"Hello, world !"
```
#### Unicode characters
`ikc3` fully supports Unicode :
Some unicode characters :
```
ikc3> '\U+1B2FB'
'𛋻'
ikc3> '𐅀'
'𐅀'
ikc3> '🤩'
'🤩'
ikc3>
```
#### Large integers
```
ikc3> a = 1 + 100000000000000000000000000000000
100000000000000000000000000000001
ikc3> a * a
10000000000000000000000000000000200000000000000000000000000000001
ikc3>
```
#### Ratios
Ratios are made with a couple of large integers : the numerator
which can be any number, and the denominator which has to be positive.
They represent fractions of integral numbers.
They are written with a slash and no space.
```
ikc3> 1/2 + 2/3
7/6
ikc3> 1/2 * 2/3
1/3
ikc3> 1/2 / 2/3
3/4
ikc3> 1/2 - 2/3
-1/6
```
#### Complex numbers
Complex numbers are constructed using the operator `+i` on any kind of
numbers (unsigned, signed, float, ratios, and even other complex
numbers). For instance, you can write `a +i b` where `a` and `b` are
real numbers.
```
ikc3> 1 +i 2
1 +i 2
ikc3> 1 +i 2 + 2 +i 3
3 +i 5
ikc3> (1 +i 2) * (2 +i 3)
-4 +i 7
ikc3> (1 +i 2) / (2 +i 3)
0 +i 0
ikc3> (1/1 +i 2/1) / (2 +i 3)
8/13 +i 1/13
```
As you can see integer division is not producing ratios.
That might change in future releases.
#### Lists
Lists are marked with brackets `[]`.
Regular lists can be :
- an element and a list : `[1 | []]` → `[1]`
- multiple elements : `[1, 2, 3]`
- multiple elements and a list : `[1, 2 | [3, 4]]` → `[1, 2, 3, 4]`
- the empty list : `[]`
Regular lists end with the empty list : `[1] == [1 | []]`.
You can also contruct dotted lists like in Common Lisp where
the next list pointer is an arbitrary form. E.g. :
- an element and an element : `[1 | 2]`
- multiple elements and an element : `[1, 2, 3 | 4]`
- the empty list and an element : `[[] | 1]`
All these list formats are supported in pattern matching.
#### Pattern matching and destructuring
The KC3 pattern matching principles come from Erlang and Elixir.
All tag data structures in KC3 can be pattern matched using the equal
sign (`=`) against litteral values containing identifiers. All
identifiers are supposed to be new bindings when using pattern matching
in KC3. If you want to use an identifier's value in pattern matching you
must use the _pin operator_ (`^`). Variables can be assigned a new value
from either side of the equal sign and from inside a tag data structure,
which is called _destructuring_.
Examples :
```
ikc3> a = 1
1
ikc3> a = 2
2
ikc3> a
2
ikc3> ^ a = 1
void
ikc3> ^ a = 2
2
ikc3> ^ a = b
2
ikc3> b
2
```
To use destructuring just type the litteral value you want to match and
put identifiers (variable names) where you want a variable matching the
value on the other side of the equal sign. This is the most visual
approach possible to text-based value matching : the data is constantly
matched to litterals that show their type to the programmer. This is
really helpful when writing large programs that need to scale in the way
of abstractions. Let the data flow in the code through visual types.
Examples :
```
ikc3> [x, y | z] = List.reverse([1, 2, 3, 4])
[4, 3, 2, 1]
ikc3> x
4
ikc3> y
3
ikc3> z
[2, 1]
```
#### Macros
KC3 macros are like Common Lisp macros with Elixir pattern-matching.
Macros are like functions but start with `macro` instead of `fn` and
their arguments do not get evaluated. However they get pattern matched
and the full power of the pattern matcher is available for arguments
destructuring. Use a map if you want named arguments. Use a list if you
want &rest arguments, use a block if you want a &body argument.
When evaluated, a macro call returns a tag which is in turn evaluated
in the calling site lexical environment. This allows for DSLs and custom
control structures to be defined in KC3.
Many basic operations in KC3 are defined as macros : error handling,
free operations with `unwind-protect`, graph database operations like
`Facts.with`.
#### If, then, else.
Conditionals in KC3 are like in Ruby, for example :
```
ikc3> if true && true
ikc3> 1 + 1
ikc3> 2 + 2
ikc3> end
4
ikc3> if true && false
ikc3> 1 + 1
ikc3> 2 + 2
ikc3> else
ikc3> 3 + 3
ikc3> 4 + 4
ikc3> end
8
```
A KC3 `if` statement always return a value. If the condition is true, the
first (then) block gets evaluated. If the condition is false the second
block gets evaluated. If the condition is false and an `else` block is
not provided, then `void` gets returned.
One liner examples with `then` :
```
ikc3> if 42 then 100 else 101 end
100
ikc3> if 0 then 100 else 101 end
101
```
## defmodule and def
Example :
```
ikc3> defmodule Example do
ikc3> def three = 3
ikc3> def double = fn (x) do x * 2 end
ikc3> def double_tuple = macro (x) do {x, x} end
ikc3> def operator_double = %KC3.Operator{sym: :double, symbol_value: fn (x) { x * 2 }
ikc3> end
Example
ikc3> Example.three
3
ikc3> Example.double
fn (x) do x * 2 end
ikc3> Example.double(21)
42
ikc3> Example.double_tuple(:ok)
{:ok, :ok}
ikc3> double 21
42
```
#### Facts
The Facts module allows read and write access to a graph database
containing facts : triples of subject, predicate, object.
Examples for querying the KC3 database containing all definitions of
the interpreter :
```
ikc3> Facts.with_tags(Facts.env_facts(), KC3, :operator, ?,
fn (fact) { puts(fact.object); :ok })
operator_eq
operator_gt
operator_lt
[...]
:ok
```
### kc3s
Script interpreter. Works the same as ikc3 but is not interactive
and does not output results.
### HTTPd
HTTP daemon, use `make test_httpd`.
The http daemon is defined in `httpd/httpd.c` and
`lib/kc3/0.1/httpd.kc3`.
The http daemon is a static file server listing directories and
serving files for display or download (Web 1.0).
## TODO
- [DONE] facts database in KC3
- [DONE] new database (Ptr)
- [DONE] add_tags
- [DONE] remove_tags
- [DONE] with_tags
- [DONE] with
- fx v0.2.0
- [DONE] file explorer
- [DONE] preview files
- [DONE] text
- [DONE] image
- [DONE] video
- [DONE] audio
- [DONE] binary (hexdump -C)
- tags
- create
- POST "/tag/:tag/*path"
- delete
- DELETE "/tag/:tag/*path"
- recursive
- properties
- [DONE] create
- [DONE] POST "/property/:property/:value/*path"
- [DONE] delete
- [DONE] DELETE "/property/:property/:value/*path
- recursive
- HTTPd v0.2.0
- dynamic pages (MVC)
- [DONE] controllers
- [DONE] ./app/controllers/
- [DONE] templates
- [DONE] ./app/templates/
- dynamic router
- [DONE] Str.starts_with?(url, route.path)
- HTTPd.Router.get("/user/:id/articles/*slug/edit", UserArticlesController.show)
- [DONE] views
- [DONE] ./app/views/
- libkc3
- [DONE] evaluation order for && and ||
- operators dispatch
- list of matching operators (facts_with)
- base-specific big floats
- macro cast : `(Macro) fn (x) { x }`
- pretty printer
- [DONE] indent
- 80 columns (`\n`)
- tags
- walker
- height function `(TAG_VOID: 1, TAG_TUPLE: (1+ (max (height tuple->tags))))`
- has_ident
- collect_idents
- facts
- negative facts : 4 + 2n = not 3 + 2n
- with ignore variables
- math
- arbitrary precision floating point numbers (decimals)
- map
- [DONE] access
- [DONE] get (get key value)
- put (return a new map)
- struct
- [DONE] access
- [DONE] get
- put
- enums
- unions
- errors (setjmp, longjmp)
- stacktrace
- ffi ?
- libdwarf
- control structures
- when
- unless
- switch/case/cond
- unwind protect
- functions
- return
- livebook
- gaussian
- buf_sha256
- buf_popen
- tests