It's been quite some time since I last posted, but I've been pretty busy. I 
only wasted 2 days this time wandering down the depths of the felix type system 
and name binding... *shudder*. A couple nice things this time around. flxc now 
partially uses the language independent frontend for symbol lowering. None of 
the optimizations yet though. Also managed to get trivial non-closured inner 
functions working, as demonstrated here:

    :::felix
    type int = "%i32";
    typedef bool = 2;
    fun add : int*int -> int = "%add";
    fun eq : int*int -> bool = "%eq";
    fun lnot : bool -> bool = "%lnot";
    proc exit : int = "exit";
 
    fun foo (x:int) = {
      val y = x + 1;
      fun bar (x:int) = {
        if x == 1 do
          return y;
        else
          return 3;
        done;
      }
      return bar y;
    }
    
    exit $ foo 2;

This now generates this code:

    :::llvm
    declare void @exit(i32)
    
    define i32 @foo(i32 %x) {
    entry:
      %foo.y = alloca i32                             ; <i32*> [#uses=2]
      %foo.x = alloca i32                             ; <i32*> [#uses=2]
      store i32 %x, i32* %foo.x
      %0 = load i32* %foo.x                           ; <i32> [#uses=1]
      %1 = add i32 %0, 1                              ; <i32> [#uses=1]
      store i32 %1, i32* %foo.y
      %2 = load i32* %foo.y                           ; <i32> [#uses=1]
      %3 = call i32 @foo.bar(i32 %2)                  ; <i32> [#uses=1]
      ret i32 %3
    }
    
    define i32 @foo.bar(i32 %x) {
    entry:
      %foo.bar.x = alloca i32                         ; <i32*> [#uses=2]
      store i32 %x, i32* %foo.bar.x
      %0 = load i32* %foo.bar.x                       ; <i32> [#uses=1]
      %1 = icmp eq i32 %0, 1                          ; <i1> [#uses=1]
      %2 = icmp eq i1 %1, false                       ; <i1> [#uses=1]
      br i1 %2, label %_ifdoend_1, label %else
    
    _ifdoend_1:                                       ; preds = %entry
      ret i32 3
    
    else:                                             ; preds = %entry
      ret i32 2
    }
    
    define void @0() {
    entry:
      %0 = call i32 @foo(i32 2)                       ; <i32> [#uses=1]
      call void @exit(i32 %0)
      ret void
    }

And if you optimize it with `flxc -O 1 ...`, then you'll get:

    :::llvm
    declare void @exit(i32)
    
    define i32 @foo(i32 %x) {
    entry:
      %0 = add i32 %x, 1                              ; <i32> [#uses=1]
      %1 = call i32 @foo.bar(i32 %0)                  ; <i32> [#uses=1]
      ret i32 %1
    }
    
    define i32 @foo.bar(i32 %x) {
    entry:
      %0 = icmp eq i32 %x, 1                          ; <i1> [#uses=1]
      %retval = select i1 %0, i32 2, i32 3            ; <i32> [#uses=1]
      ret i32 %retval
    }
    
    define void @0() {
    entry:
      %0 = call i32 @foo(i32 2)                       ; <i32> [#uses=1]
      call void @exit(i32 %0)
      ret void
    }
    
Which looks surprisingly readable. You'll also notice that we're prepending the 
parent's name in the llvm symbol name, so it should hopefully help with 
debugging.

------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to