You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<spanclass="lineno" id=line6></span><spanclass="small_keyword" title="end of body">done</span>
457
474
<spanclass="lineno" id=line7></span> }
458
-
</pre></p><p>Now we have a simple sink, which just prints everything it reads:
475
+
</pre></p></div><h2id='The_sink_h'><imgsrc='/share/src/web/images/minus.gif' id='The sink' onclick='toggle(this,"The_sink_d")' alt='+'/> 1.2 The sink</h2><divid='The_sink_d' style='display:block'>
476
+
<p>Now we have a simple sink, which just prints everything it reads:
459
477
</p><preclass='inclusion'>
460
478
examples/ex1.flx</pre>
461
479
<p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> sink (inp: %<<spanclass="library" title="binding of C int type">int</span>) () {
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="library" title="Type with one values (), the empty tuple">unit</span> -> <spanclass="library" title="Type with one values (), the empty tuple">unit</span>
470
488
</pre></p><p>which is the type required to spawn fibre from a coroutine.
471
-
</p><p>Now we have a transducer which writes the square of every integer it reads.
489
+
</p></div><h2id='The_transducer_h'><imgsrc='/share/src/web/images/minus.gif' id='The transducer' onclick='toggle(this,"The_transducer_d")' alt='+'/> 1.3 The transducer</h2><divid='The_transducer_d' style='display:block'>
490
+
<p>Now we have a transducer which writes the square of every integer it reads.
472
491
</p><preclass='inclusion'>
473
492
examples/ex1.flx</pre>
474
493
<p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> squarer (inp: %<<spanclass="library" title="binding of C int type">int</span>, out: %><spanclass="library" title="binding of C int type">int</span>) () {
</pre></p><p>This procedure drops through, but it cannot return control, because
492
512
there is nowhere to return it to, so it has, in effect, committed
493
513
suicide implicitly.
494
-
</p><p>Now we need have four components so we need three channels to connect them:
514
+
</p></div><h2id='The_runner_h'><imgsrc='/share/src/web/images/minus.gif' id='The runner' onclick='toggle(this,"The_runner_d")' alt='+'/> 1.5 The runner</h2><divid='The_runner_d' style='display:block'>
515
+
<p>Now we need have four components so we need three channels to connect them:
495
516
</p><preclass='inclusion'>
496
517
examples/ex1.flx</pre>
497
518
<p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> run_pipeline() {
</pre></p><p>Here is the complete program: <ahref="https://github.com/felix-lang/felix-lang.github.io/blob/main/examples/ex1.flx">ex1.flx</a>
519
-
</p></div><h1id='Using_the_chip_DSSL_h'><imgsrc='/share/src/web/images/minus.gif' id='Using the chip DSSL' onclick='toggle(this,"Using_the_chip_DSSL_d")' alt='+'/> 2 Using the chip DSSL</h1><divid='Using_the_chip_DSSL_d' style='display:block'>
540
+
</p></div></div><h1id='Using_the_chip_DSSL_h'><imgsrc='/share/src/web/images/minus.gif' id='Using the chip DSSL' onclick='toggle(this,"Using_the_chip_DSSL_d")' alt='+'/> 2 Using the chip DSSL</h1><divid='Using_the_chip_DSSL_d' style='display:block'>
520
541
<p>The code above involves a bit of boilerplate so I'm going to show you how to do the
521
542
same job using the <em>chip</em> DSSL. A DSSL is a unique feature of Felix which allows
522
543
the <em>user</em> to define an extension to the existing language, which has an application
</pre></p><p>For any functional programmers around, a pipeline is semantically identical
605
626
to a Monad.
606
-
</p></div><h1id='The_concept_of_fibration_h'><imgsrc='/share/src/web/images/minus.gif' id='The concept of fibration' onclick='toggle(this,"The_concept_of_fibration_d")' alt='+'/> 3 The concept of fibration</h1><divid='The_concept_of_fibration_d' style='display:block'>
627
+
</p><h2id='How_does_it_stop?_h'><imgsrc='/share/src/web/images/minus.gif' id='How does it stop?' onclick='toggle(this,"How_does_it_stop?_d")' alt='+'/> 2.1 How does it stop?</h2><divid='How_does_it_stop?_d' style='display:block'>
628
+
<p>It is clear, because I told you, that we put the <code>limiter</code> into the pipeline so it terminates.
629
+
So the <code>limiter</code> commits suicide by dropping off the end after a certain number of data transfers.
630
+
But the other three components are infinite loops, so how does the system terminate?
631
+
</p><p>First consider the transducer <code>squarer</code> tries to write to the limiter, but alas, it is dead?
632
+
The write stalls, and we say the fibre is <em>blocked</em> or being vulgar, <em>constipated</em>.
633
+
And now, since it is blocked, it cannot read the input from the <code>source</code>, so it too is blocked.
634
+
</p><p>The <code>sink</code> on the other hand has a different problem: it is trying to read from the <code>limiter</code>
635
+
but the limiter is dead, so there is no input coming: the sink is said to be <code>starved</code>.
636
+
</p><p>There are therefore <em>no active fibres</em> so the system terminates.
637
+
I will emphasise this point heavily because these are the correct termination semantics.
638
+
There is another language with processes and channels, namely <code>golang</code>.
639
+
Unfortunately <code>golang</code> got the termination semantics completely wrong.
640
+
in addition, <code>golang</code> channel semantics are also wrong because channels can be closed
641
+
and a reader can detect if a writer closed the channel.
642
+
</p><p>Although this is not possible in Felix, you can write the option type <code>opt</code> and use
643
+
the <code>None</code> case to signal end of data. In fact, in Felix you can write <em>any</em>
644
+
type down a channel, even channels!
645
+
</p></div></div><h1id='Felix_is_a_coroutine_h'><imgsrc='/share/src/web/images/minus.gif' id='Felix is a coroutine' onclick='toggle(this,"Felix_is_a_coroutine_d")' alt='+'/> 3 Felix is a coroutine</h1><divid='Felix_is_a_coroutine_d' style='display:block'>
646
+
<p>Most programming language generate programs which consist of single top level procedure,
647
+
for example <code>main()</code> in C. It is a subroutine called by the startup code which in turn
648
+
was invoked by the operating system.
649
+
</p><p>Felix, as usual, is different. For a start, Felix generates libraries, in fact the
650
+
default is a shared library. So in fact, what you think is mainline code running
651
+
is in fact just the initialisation code for the library. You can also
652
+
add a procedure <code>flx_main()</code> to your code and that will also be run after
653
+
the initialisation of the library.
654
+
</p><p>However there is something else different: the Felix mainline code is not
655
+
a subroutine, it is a coroutine!
656
+
</p></div><h1id='The_concept_of_fibration_h'><imgsrc='/share/src/web/images/minus.gif' id='The concept of fibration' onclick='toggle(this,"The_concept_of_fibration_d")' alt='+'/> 4 The concept of fibration</h1><divid='The_concept_of_fibration_d' style='display:block'>
607
657
<p>A <em>coroutine system</em> is a collection of processes called <em>fibres</em>
0 commit comments