I have modified Felix so now each file is parsed and desugared, then the 
assembly produced
concatenated. Previously the algorithm was this:
  
let asms = (do actual desugaring state) in
let include_files = from the state in

let  asms = List.fold_left begin fun asms file ->
      let curpath, stmts = Flx_colns.include_file state.syms curpath file in
      desugar_stmts state curpath stmts :: asms
    end
    [asms] include_files
  in
List.concat asms
 
so basically, this is a recursive descent, pushing the root first, then down the
left side of the tree. My new code generates this:


//PROCEDURE <5998:> _init_: Resume method
con_t *_init_::resume(){
  FLX_START_SWITCH
      PTF _i3390_v3390_sep  = PTF sep;
      PTF sep  = (_a2728t_22326)("/");
  _i5836_p5836__init_(FLX_FPAR_PASS_ONLY);
      PTF INSTALL_ROOT_TOPDIR  = PTF _i5808_v5808_INSTALL_ROOT_TOPDIR;
      PTF INSTALL_ROOT  = PTF _i5809_v5809_INSTALL_ROOT;

which you can see is bugged (we copy sep before initialising it). Sep is the 
filename
separator. There's also a call to a module initialisation routine which is 
plat/config.
The code is for "flx" so this is kind of important :)

Here's the order of the packed code:

Processed file std/version output len=2
Processed file std/lexer output len=5
Processed file std/avl output len=2
Processed file std/darray output len=4
Processed file std/varray output len=5
Processed file std/array output len=3
Processed file std/list output len=6
Processed file std/string output len=18
Processed file std/carray output len=3
Processed file std/slice output len=1
Processed file std/option output len=2
Processed file std/pointer output len=3
Processed file std/filename output len=2  <**** FIRST
Processed file std/stdout output len=3
Processed file std/textio output len=2
Processed file std/cstdio output len=3
Processed file std/categ output len=3
Processed file std/control output len=3
Processed file std/cstdlib output len=3
Processed file plat/filename output len=2  <**** SECOND
Processed file std/env output len=2
Processed file std/dynlink output len=2
Processed file std/system output len=2
Processed file std/typing output len=3
Processed file std/c_hack output len=2
Processed file std/debug output len=3
Processed file std/arith_casts output len=3
Processed file std/float_math output len=22
Processed file std/float_format output len=6
Processed file std/mixedint output len=2
Processed file std/char output len=14
Processed file std/number output len=4
Processed file std/real output len=1
Processed file std/int output len=87
Processed file std/bool output len=6
Processed file std/address output len=7
Processed file std/flx_tclass output len=38
Processed file std/__init__ output len=0
Processed file plat/float output len=9
Processed file plat/arithmax output len=1
Processed file std/ctypesets output len=17
Processed file plat/ctypedefs output len=44
Processed file plat/flx_ctypes output len=12
Processed file std output len=20
Processed file plat/config output len=2
Processed file build/release-optimized/src/flx/flx output len=1044

The global code in each file will be initialised in the above order.
Each module has an _init_ procedure and a call to it is generated.
Some inlining occurs so in the mainline you may see the actual text of
the initialisation. The problem is here in std/filename:

include "plat/filename.flx";
module Filename { val sep = Plat_Filename::sep; ....

and plat/filename.flx:

// GENERATED DURING CONFIGURATION
module Plat_Filename { val sep = "/"; }

which are done in that order (see above).

My new algorithm is:

    while List.length (!unprocessed) > 0 do
      let candidate = List.hd (!unprocessed) in
      let candidate = strip_extension candidate in
      unprocessed := List.tl (!unprocessed);
      if not (List.mem candidate (!processed)) then
      begin
        processed := candidate :: !processed;
        let stmts = parse_file state candidate in
        let desugar_state = Flx_desugar.make_desugar_state module_name 
state.syms in
        let include_files, asms =
          Flx_desugar.desugar_stmts desugar_state (Filename.dirname candidate ) 
stmts
        in
        List.iter (fun s ->
          if not (List.mem s (!processed)) && not (List.mem s (!unprocessed))
          then begin
            print_endline ("Add Include file: " ^ s);
            unprocessed := s :: (!unprocessed)
          end
        )
        include_files
        ;
        outputs := (candidate,asms) :: (!outputs)
     end
    done;

Now the thing is: NEITHER algorithm is right. The both ensure that if A uses B 
and B
hasn't been handled yet, B is done before A. But then if C comes along and 
needs B,
it is too late. Recursive descent on a tree is a topological sort, on a DAG it 
isn't.

The question is: what to do: the old code only worked by a fluke. It used to be
the "sep" was a MACRO to prevent this problem, because the real problem
is that you cannot assume an ordering of initialisation, except within a single
file. In theory, you can't even assume library files are initialised before your
program (What happens if you make P an include file? .. then all bets are off).

So I actually broke the rules myself here.

I.e. I thought my new algorithm was broke cause it wasn't a topological sort
but the real problem is the library is broke :)

[Of course a top sort would fix this one .. :]


--
john skaller
skal...@users.sourceforge.net





------------------------------------------------------------------------------
Centralized Desktop Delivery: Dell and VMware Reference Architecture
Simplifying enterprise desktop deployment and management using
Dell EqualLogic storage and VMware View: A highly scalable, end-to-end
client virtualization framework. Read more!
http://p.sf.net/sfu/dell-eql-dev2dev
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to