Cleanup
[splendini.git] / README.txt
blob3e3fc902dad3bec7615f14d9f3d426389f6c8175
1 splendini
2 =========
4 splendini is a programing language. Here is a sample session; building instructions are further down:
7 1 : 1
8 1=> 1
10 2 : Type(1)
11 2=> MInt
13 3 : a
14 3=> a
16 4 : Type(a)
17 4=> Symbol
19 5 : "hello world"
20 5=> "hello world"
22 6 : Type("hello world")
23 6=> String
25 7 : Type(Type(1))
26 7=> Symbol
28 8 : Type(Type(a))
29 8=> Symbol
31 9 : Type(Type("hello world"))
32 9=> Symbol
34 10 : f(a,1)
35 10=> f(a, 1)
37 11 : Type(f(a,1))
38 11=> f
40 12 : 1.1
41 12=> 1.100000000000000
43 13 : Type(1.1)
44 13=> MReal
46 14 : Type(a)
47 14=> Symbol
49 15 : Set(a, 1.1)
50 15=> 1.100000000000000
52 16 : a
53 16=> 1.100000000000000
55 17 : Type(a)
56 17=> MReal
58 18 : Type(Quote(a))
59 18=> Symbol
61 19 : Add(1,1)
62 19=> 2
64 20 : Type(Add(1,1))
65 20=> MInt
67 21 : Add(1,1.)
68 21=> 2.000000000000000
70 22 : Type(Add(1,1.))
71 22=> MReal
73 23 : Function(x, Add(x,1))
74 23=> Function(List(x), Add(x, 1))
76 24 : Type(Function(x, Add(x,1)))
77 24=> Function
79 25 : Set(f, Function(x, Add(x,1)))
80 25=> Function(List(x), Add(x, 1))
82 26 : f(1)
83 26=> 2
85 27 : Function(x, Add(x,1))(1)
86 27=> 2
88 28 : IsSame(1,1)
89 28=> True
91 29 : IsSame(a,a)
92 29=> True
94 30 : IsSame(a,b)
95 30=> False
97 31 : IsSame(Type(a),Type(b))
98 31=> False
100 32 : a
101 32=> 1.100000000000000
103 33 : b
104 33=> b
106 34 : Quote(a)
107 34=> a
109 35 : IsSame(Type(Quote(a)),Type(b))
110 35=> True
112 36 : If(True, "yes", "no")
113 36=> "yes"
115 37 : If(False, "yes", "no")
116 37=> "no"
118 38 : If(True, 1)
119 38=> 1
121 39 : If(False, 1)
122 39=> Null
124 40 : test
125 40=> test
127 41 : Type(test)
128 41=> Symbol
130 42 : If(test, 1)
131 42=> If(test, 1)
133 43 : If(test, 1, 2)
134 43=> If(test, 1, 2)
136 44 : If(test, 1, 2, 3)
137 44=> 3
139 45 : And(True, False)
140 45=> False
142 46 : Or(True, False)
143 46=> True
145 47 : Not(True)
146 47=> False
148 48 : Sequence(Set(a,0), Set(a, Add(a, 2)), a)
149 48=> 2
151 49 : Length(g(1,2,3))
152 49=> 3
154 50 : Length("Hello")
155 50=> 5
157 51 : Part(g(1,2,3), 1)
158 51=> 1
160 52 : Part(g(1,2,3), -1)
161 52=> 3
163 53 : Part(g(1,2,3), 0)
164 53=> g
166 54 : Set(a,0)
167 54=> 0
169 55 : Clear(a)
170 55=> 0
172 56 : a
173 56=> a
175 57 : Type(a)
176 57=> Symbol
178 58 : Set(a,0)
179 58=> 0
181 59 : Loop(Set(a, Add(a, 2)), List(10))
182 59=> Null
184 60 : a
185 60=> 20
187 61 : Timing(Loop(Set(a, Add(a, 2)), List(1000000)))
188 61=> List(0.805185079574585, Null)
190 62 : a
191 62=> 2000020
193 63 : Done
198 Some nice stuff:
199 ================
202 1 : Set(f, Function(a, If(Not(IsSymbol(a)), Quote(f)(a), Print("Hi");a)))
203 1=> InterpretedFunction(List(a), If(Not(IsSymbol(a)), Quote(f)(a), Sequence(Print("Hi"), a)), StaticScope)
205 2 : f(sym)
207 2=> sym
209 3 : f(a)
211 3=> a
215 Closuers (Let):
216 =================
218 1 : {inc, dec} = Let({{b, 10}}, {Function({}, SetGlobal(b, b + 1)), Function({}, SetGlobal(b, b + -1))})
219 1=> List(Function(List(), SetGlobal(b, Add(b, 1)), StaticScope), Function(List(), SetGlobal(b, Add(b, -1)), StaticScope))
221 2 : inc()
222 2=> 11
224 3 : inc()
225 3=> 12
227 4 : dec()
228 4=> 11
230 5 : dec()
231 5=> 10
233 6 : dec()
234 6=> 9
236 ------------
239 1 : i=0;j=0; Block({{i,1}}, Print(i); Print(j); i = 2; j = 2; Print(i); Print(j)); {i,j}
244 1=> List(0, 2)
246 % Block[{{var1, val1},..}, body]
247 % Block works by temprarily blocking all variables var1.. given and uses the value val1 in place. Also Block does not scope any variables in it's body (as does Let) except those given in var1...
250 ------------
252 24 : i=0;{Table(i, {i, 1, 2}),i}
253 24=> List(List(1, 2), 0)
255 25 : j=0;{Table(j=i, {i, 1, 2}),i}
256 25=> List(List(1, 2), 0)
258 26 : j
259 26=> 2
261 % Table/Loop use Block for scoping the itator variable.
263 ----------------
266 1 : i = 0; Let({},i=1)
267 1=> 1
269 2 : i
270 2=> 0
272 3 : i = 0; Let({},Set(i,1,GlobalFrame))
273 3=> 1
275 4 : i
276 4=> 1
278 5 : i = 0; Let({}, Let({{frame, Context()}}, Set(i,1, frame)); i)
279 5=> 1
281 6 : i
282 6=> 0
284 7 : i = 0; Let({}, Let({},SetGlobal(i,1)) )
285 7=> 1
287 8 : i
288 8=> 1
290 % the difference between SetGlobal and Set with a context is that SetGlobal walks 
291 % up the frames, looks for the variable name and sets it's value (scheme set!).
292 % Set sets the value of the variable in a context specified. 
293 % SetGlobal and Set with a context are also useful within a Function.
295 Let over Lambda over Let over Lambda:
296 ======================================
298 (http://www.letoverlambda.com/textmode.cl/guest/chap2.html#sec_4, Doug Hoyte)
300 1 : {togle, counterClass} = Let(
301         {{direction, "up"}},
302         toggleCounter = Function({},
303                 SetGlobal(direction, If(direction === "up", "down", "up"))
304         );
305         counterClass = Let(
306                 {{counter, 0}},
307                 Function({},
308                         SetGlobal(counter, If(direction === "up",
309                                 counter + 1,
310                                 counter + -1
311                         ))
312                 )
313         );
314         {toggleCounter, counterClass}
317 1=> List(Function(List(), Set(direction, If(IsSame(direction, "up"), "down", "up")), StaticScope), Function(List(), If(IsSame(direction, "up"), Set(counter, Add(counter, 1)), Set(counter, Add(counter, -1))), StaticScope))
319 2 : counterClass()
320 2=> 1
322 3 : counterClass()
323 3=> 2
325 4 : counterClass()
326 4=> 3
328 5 : togle()
329 5=> "down"
331 6 : counterClass()
332 6=> 2
334 7 : counterClass()
335 7=> 1
337 8 : counterClass()
338 8=> 0
340 9 : counterClass()
341 9=> -1
343 10 : togle()
344 10=> "up"
346 11 : counterClass()
347 11=> 0
349 12 : counterClass()
350 12=> 1
354 Tailrecursive :
355 ===============
357 1 : Import(Load(ToFileName({"Scripts", "NumberTheory.spl"})))
358 1=> List(GoldenRatio, Fibonacci)
360 2 : Timing(Fibonacci(100000);)
361 2=> List(1.107151985168457, Null)
363 Set(fib,
364         Function(
365             List(n, i, f0, f1),
366             If( Equal(i, n), 
367                 f0,
368                 fib(n, Add(i, 1), f1, Add(f0, f1))
369             )
370         )
371     )
373 Set(Fibonacci,
374     Function(
375         n,
376         %If( And( IsInteger(n), IsPositive(n)),
377         If( And( IsNumberExact(n), GreaterEqual(n, 0)),
378             fib(n, 0, 0, 1)
379         ,
380             Quote(Fibonacci)(n)
381         )
382     )
383 )   
385 Load Library Functions:
386 =======================
387 /* example_dll.h
388 #include "uex.h"
390 extern ue_p pfTest(ue_p state);
392 /* example_dll.c
393 #include "example_dll.h"
395 ue_p pfTest(const ue_p state) {
396     ue_p u = ue_mk_String("Hello World!");
397     return u;
401 //gcc -c -I/home/sigint/git/splendini/uexLib -Wall -Werror -fpic example_dll.c
402 //gcc -shared -o libexample_dll.so example_dll.o
404 1 : Test = LoadLibraryFunction("pfTest", "/home/sigint/git/buildSpl/libexample_dll.so")
405 1=> LibraryFunction("pfTest", "/home/sigint/git/buildSpl/libexample_dll.so")
407 2 : Test()
408 2=> "Hello World!"
411 OptimizeExpressions:
412 ====================
413 1 : Timing(Table(Add(i,1),{i,1,100000});)
414 1=> List(0.191010951995850, Null)
416 2 : oe = OptimizeExpression(Table(Add(i,1),{i,1,100000}))
417 2=> Table(Add(i, 1), List(i, 1, 100000))
419 3 : Timing(Evaluate(oe);)
420 3=> List(0.120177984237671, Null)
422 OptimizeExpression works by replacing the symbol Add with the actual
423 system function Add and thus save the lookup of the code in every iteration.
426 Memorization:
427 =============
428 1 : fib = Function(n, If(n <= 2, 1, fib(n + -1) + fib(n + -2)))
429 1=> InterpretedFunction(List(n), If(LessEqual(n, 2), 1, Add(fib(Add(n, -1)), fib(Add(n, -2)))), StaticScope, Frame$313)
431 2 : Timing(fib(24))
432 2=> List(0.708318948745728, 46368)
434 3 : Timing(fib(23))
435 3=> List(0.445200204849243, 28657)
437 4 : memo = Function(fn, Let({ht = LookupData({{},{}}, False)}, Function(key, val = LookupDataFind(ht, key); If(val=!=False, val, LookupDataAdd(ht, {key, fn(key)})))));
439 5 : fib = memo(fib)
440 5=> InterpretedFunction(List(key), Sequence(Set(val, LookupDataFind(ht, key)), If(IsNotSame(val, False), val, LookupDataAdd(ht, List(key, fn(key))))), StaticScope, Frame$316)
442 6 : Timing(fib(24))
443 6=> List(0.004889965057373, 46368)
445 7 : Timing(fib(23))
446 7=> List(0.000065088272095, 28657)
448 8 : memoInspect = Function(fn, Let({ht = LookupData({{},{}}, False)}, Function(key, val = LookupDataFind(ht, key); If(val=!=False, val, r = LookupDataAdd(ht, {key, fn(key)}); Print(ht);r))));
450 9 : fib = Function(n, If(n <= 2, 1, fib(n + -1) + fib(n + -2)))
451 9=> InterpretedFunction(List(n), If(LessEqual(n, 2), 1, Add(fib(Add(n, -1)), fib(Add(n, -2)))), StaticScope, Frame$318)
453 10 : fib = memoInspect(fib)
454 10=> InterpretedFunction(List(key), Sequence(Set(val, LookupDataFind(ht, key)), If(IsNotSame(val, False), val, Sequence(Sequence(Set(r, LookupDataAdd(ht, List(key, fn(key)))), Print(ht)), r))), StaticScope, Frame$320)
456 11 : fib(10)
457 LookupData(List(List(2), List(1)), False)
458 LookupData(List(List(2, 1), List(1, 1)), False)
459 LookupData(List(List(2, 1, 3), List(1, 1, 2)), False)
460 LookupData(List(List(2, 1, 3, 4), List(1, 1, 2, 3)), False)
461 LookupData(List(List(2, 1, 3, 4, 5), List(1, 1, 2, 3, 5)), False)
462 LookupData(List(List(2, 1, 3, 4, 5, 6), List(1, 1, 2, 3, 5, 8)), False)
463 LookupData(List(List(2, 1, 3, 4, 5, 6, 7), List(1, 1, 2, 3, 5, 8, 13)), False)
464 LookupData(List(List(2, 1, 3, 4, 5, 6, 7, 8), List(1, 1, 2, 3, 5, 8, 13, 21)), False)
465 LookupData(List(List(2, 1, 3, 4, 5, 6, 7, 8, 9), List(1, 1, 2, 3, 5, 8, 13, 21, 34)), False)
466 LookupData(List(List(2, 1, 3, 4, 5, 6, 7, 8, 9, 10), List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)), False)
467 11=> 55
469 12 : fib(9)
470 12=> 34
472 % A function that is implemented with sub functions (e.g. system Fibonacci) can only cache function calls but not self calls of internal functions.
474 13 : Fibonacci = memoInspect( Fibonacci)
475 13=> InterpretedFunction(List(key), Sequence(Set(val, LookupDataFind(ht, key)), If(IsNotSame(val, False), val, Sequence(Sequence(Set(r, LookupDataAdd(ht, List(key, fn(key)))), Print(ht)), r))), StaticScope, Frame$322)
477 14 : Fibonacci(10)
478 LookupData(List(List(10), List(55)), False)
479 14=> 55
481 15 : Fibonacci(10)
482 15=> 55
484 16 : Fibonacci(9)
485 LookupData(List(List(10, 9), List(55, 34)), False)
486 16=> 34
490 Macros:
491 ========
492 $ Maxros do two things: 1) they transform code 2) the transformed code is evaluated.
493 $ Since this functionality is available already there is no special Macro command.
494 $ The transformation function (i.e. the macro) should have a Quote attribute.
495 $ When you call the tranformation function on arguments the transformed code is
496 $ emitted. The code then is evaluated.
498 1 : when = Function({test, body}, Quote(If)(test, body));
500 2 : AttributesAdd(when, QuoteAll);
502 3 : when(False, Print("Should not print"); 1)
503 3=> If(False, Sequence(Print("Should not print"), 1))
505 4 : Evaluate(when(False, Print("Should not print"); 1) )
507 5 : when(True, Print("Should print"); 1)
508 5=> If(True, Sequence(Print("Should print"), 1))
510 6 : Evaluate( when(True, Print("Should print"); 1) )
511 Should print
512 6=> 1
514 $ Second example:
515 1 : let = Function({bindings, body},
516         Quote(Apply)(
517                 Quote(Function)(Map(Function(x, Part(x,1)), bindings), body),
518                 Map(Function(x, Part(x,2)), bindings)
519         )
521 AttributesAdd(let, QuoteAll);
523 2 : let({{x,1},{y,1}},x+y)
524 2=> Apply(Function(List(x, y), Add(x, y)), List(1, 1))
526 3 : Evaluate(let({{x,1},{y,1}},x+y))
527 3=> 2
529 4 : {x,y}
530 4=> List(x, y)
532 5 : w = let({{b,100}}, Function(a, SetGlobal(b, a+b)))
533 5=> Apply(Function(List(b), Function(a, SetGlobal(b, Add(a, b)))), List(100))
535 6 : w = Evaluate(let({{b,100}}, Function(a, SetGlobal(b, a+b))))
536 6=> InterpretedFunction(List(a), SetGlobal(b, Add(a, b)), StaticScope, Frame$154)
538 7 : w(1)
539 7=> 101
541 8 : w(10)
542 8=> 111
544 9 : w(-100)
545 9=> 11
547 % writinng this in a set of functions:
549 1 : Macro = Function({macrofun}, MacroData(AttributesAdd(macrofun, QuoteAll)));
551 2 : MacroExpand = Function(md, Apply(md[0][1], md));
553 3 : MacroEvaluate = Function(md, Evaluate(MacroExpand(md)));
555 4 : let = Macro(
556         Function({bindings, body},
557                 Quote(Apply)(
558                         Quote(Function)(Map(Function(x, Part(x,1)), bindings), body),
559                         Map(Function(x, Part(x,2)), bindings)
560                 )
561         )
562         );
564 5 : MacroExpand(let({{x,1},{y,1}}, x+y))
565 5=> Apply(Function(List(x, y), Add(x, y)), List(1, 1))
567 6 : MacroEvaluate(let({{x,1},{y,1}}, x+y))
568 6=> 2
571 Building splendini:
572 --------------------
573 This is documented in the build.OSNAME files
576 Run test suite:
577 ---------------
578 cmake -DCMAKE_BUILD_TYPE=Debug ../splendini/
579 make
580 make test
582 Code coverage (after 'make test'):
583 ----------------------------------
584 ctest -D ExperimentalCoverage
586 for a single file (e.g.):
588 gcov uexLib/CMakeFiles/uexLib.dir/uex.c.o
591 Splint:
592 -------
593 splint -memchecks -I/usr/local/include -I./uexLib/ -I./uexLanguage/  uexLib/*.c uexLanguage/*.c main.c
595 valgrind:
596 ---------
597 valgrind --track-origins=yes --leak-check=full --show-reachable=yes --suppressions=../splendini/boehm-gc.suppressions  ./splendiniCore test.spl >& vlgTest
599 cat test.spl 
600 done