john skaller | 14 Dec 17:27 2014


Take care! 

There is a bug in the compiler causing 


to fail. When I looked at the test I saw the problem instantly.
Here's the code:

//Check generators

var cheat : int = 0;
gen f():int = {
  //print "Generator "; print cheat; endl;
  return cheat;

print "F 1="; print$ f(); endl; // 1

body """
  static int x = 0;
  int g() { ++x; return x; }

gen g : 1 -> int;

print "C 1="; print$ g(); endl; // 1

(Continue reading)

john skaller | 7 Dec 15:38 2014


So, we know the standard representation of a sum type is:

	struct _uctor_ { int variant; void *data; };

which is layout compatible with

	int * address

however there are various special representations. For example
if a variant has no argument, it's just represented by the "int" tag.
Safe, since proper use shouldn't fetch the data field for that tag.

Another special one is for a form where there are exactly two
variants, the first having no argument, then we just use

	void *data

will NULL being the first variant, and a non-null address being
the address of the second one. This is efficient but it was chosen
for a more fundamental reason than performance: it means any
"possibly NULL" C pointer has a natural representation in Felix
as a union:

	union maybe_ptr[T] = Null | Ptr of T;

In other words, a possibly NULL C pointer can not only be
considered logically equivalent to an option type with
type T a pointer, it is layout compatible with one.

Another example of this is 
(Continue reading)

john skaller | 7 Dec 14:34 2014

Re: [felix] Composition

On 07/12/2014, at 10:27 PM, srean wrote:

> This is neat. Does the dot operator and |> do the same thing ?

Sure, but the precedence is different, operator . is high precedence,
operator |> is low precedence. Similarly operator whitespace
is high precedence, operator $ is low precedence (however, $ is
right associative).

Apart from trying to remember them all .. having many operators
makes remembering the precedences almost impossible.
I'm a bit slow .. I can't even remember them for C, which I've
been writing for several decades :)

john skaller

Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
john skaller | 7 Dec 08:52 2014


Felix has a forward composition operator:

	(f \circ g) x = f (g x)

There's no reverse composition operator, because I can't think of
a suitable symbol. Operator dot (.) was used before and leads
to a nice notation:

	x . (f . g) = (x . f) . g

but it doesn't work because f. g means application of g to f.
Although this usually works for concrete types, overloading
can get it confused, and polymorphism really screws it up.
I could use

	x . (f \cdot g)

[\cdot is a fat centred dot in TeX] although the precedence isn't clear!
Consider also:

	f \circ g \cdot h . x

to see: where do the parens go?

Anyhow, i have one more thing to do in the wrapping stuff, actually
lambda lifting:

	f \circ g --> fun x => f (g x) 

Now the projections work, Felix can finally express properly what C++ can't:
(Continue reading)

john skaller | 2 Dec 22:26 2014

Re: [felix] projections

OK, next commit should handle all kinds of 
function like things passed as arguments and have
test cases named wrap-*.

I have yet to verify/get working projections of pointers to products
passed as arguments. Simple enough, just a swag more tests and
some copy/paste polymorphism.

Eventually the old wrapper generator will be deleted. For now it still
runs but shouldn't do anything except mark closures as Heap_closures.

john skaller

Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
john skaller | 30 Nov 14:03 2014


OK, I have the new wrapper generator working for primitives, struct and cstruct
constructors, and non-const union variants.

However there's a problem with projections. For a struct or record v you can write


or equivalently

	fieldname v

and also this works for a pointer. However this should work and
name the projection:

	fieldname of (T)

where T is the struct or record type but it doesn't. For tuples that would be
quite weird:

	1 of (int * long)

would be the name of the second projection. I know why it doesn't work:
the lookups only work in an application  f(x). So for the moment you will
have to manually eta-expand, that is, write the wrapper by hand like:

	struct X { x:int; };
	fun x_value_projection (X:a) => a.x;

The lookup code in the compiler (src/compiler/flx_bind/ is
extremely complex and fragile. Each context is handled separately,
(Continue reading)

john skaller | 16 Nov 17:41 2014


Felix currently allows certain non-functions to be used "as functions".

For example:

	fun f: int -> int = "$1";

is a primitive function like thing, but it is NOT a Felix function which

	fun g (x:int) => x;

actually is. When you apply these entities:

	println$ f 1, g 1;

this involves terms:

	apply (f, 1)
	apply (g, 1)

and the compiler knows that f and g are different applicable things
and uses the appropriate code to apply them: for f we get


by substitution and for g we get


[although inlining me simplify that]. No consider the function

(Continue reading)

john skaller | 11 Nov 17:09 2014


the implementation of futures relies on a hack/implementation detail
which I have disturbed reorganising the compiler.

Here's the problem: I have implemented futures by spawning an fthread
(fibre) which sends  the result down an schannel. To get the result you
read the schannel. More precisely you call a function which checks
if the result has been fetched already, if not it reads the schannel
and caches the result.

This is a "perfect" implementation of futures, however it isn't legal
in Felix because reading and schannel (and spawning an fthread)
aren't allowed in functions (or generators). They're only allowed in
procedures (and ones not nested in functions).

However Felix has some optimisations, including the ability to
convert a function

	fun f(x:D):C = ...

into a procedure equivalent to:

	proc f' (p:&C, x:D) { *p = f x; }

where the code of f is inserted rather than calling it.

That means if f is called in a procedure f' is called instead
and as long as that procedure's ancestors are procedural,
side effects including spawning fthreads and reading channels
are allowed. 

(Continue reading)

john skaller | 8 Nov 15:56 2014

Version change

I'm going to change the version number soon. No, not bump it.
The new version will be


i.e. the date of the change.

john skaller

john skaller | 7 Nov 15:22 2014


GRRR ...

~/felix>build/release/host/bin/flx --test=build/release --force test/regress/rt/type_classes-06
varray(1, 2, 3)
varray(1, 2, 3)
varray((1, 1), (2, 2), (3, 3))

~/felix>build/release/host/bin/flx --test=build/release --force --usage=prototype test/regress/rt/type_classes-06
In file included from
fatal error:
      unknown type name '_at40322'; did you mean '_at40312'?
typedef _at40322* _poly_39333t_40323;

/Users/johnskaller/.felix/cache/text/Users/johnskaller/felix/test/regress/rt/type_classes-06.hpp:40:8: note:
      '_at40312' declared here
struct _at40312;
1 error generated.
C++ command="clang++" "-fPIC" "-g" "-c" "-fno-common" "-fno-strict-aliasing" "-std=c++11" "-w"
"-Wfatal-errors" "-Wno-return-type-c-linkage" "-Wno-invalid-offsetof"
"-Ibuild/release/share/lib/rtl" "-Ibuild/release/host/lib/rtl" "-Ilib/rtl"
(Continue reading)

john skaller | 13 Oct 01:57 2014

Re: [felix] monomorphisation

On 13/10/2014, at 3:53 AM, Shayne Fletcher wrote:

> On Sun, Oct 12, 2014 at 1:04 AM, john skaller <skaller <at>> wrote:
> For example
>         reduce[T] double_rev(x:list[T]) : rev (rev x) => x;
> will not work if list[T] with T->int changes the type to list_of_int
> and the rev functions to rev_of_int
> ​Sorry, maybe not quite getting it. Surely,  T <- int, rev_{1} = rev_{2} <- rev_list_of_int. What's the
problem?​ Is it that the polymorphism of of the reduction rule has been lost?

When rev[T] of list[T] is monomorphised its "name" is changed to a new function

	rev_of_int[] of list_of_int[]

Actually it's integer index in the symbol table is changed.

More precisely, a brand new function is created which reverses
only integer list.

So the pattern matching to find things to reduce is looking for
the old "rev" function index.; It won't see the new rev_of_int index.

To fully see, if you had a reverse of a list of strings, you would get

	rev_of_string[] of (list_of_string[])
(Continue reading)