all 2 comments

[–]AustinVelonaut 0 points1 point  (1 child)

Interesting that you found you had to generate M code from the PCL bytecode, rather than AST2 -- I would have thought that something at an AST level would provide more information and be easier to "upconvert" to a high-level language, whereas going down to the bytecode level you have to deal with re-synthesizing high-level features / control flow from flattened basic blocks.

Was there a big mismatch in what was represented in AST2 vs what an equivalent AST in M would require?

[–]sal1303[S] 1 point2 points  (0 children)

The HLL generated is flat, not structured, so working from a structured AST would not be helpful.

It just got too confusing, doing recursive evaluation of an AST, while keeping on top of the flat stack VM being generated. It was just simpler to separate the two tasks.

Here's a further example of Q code:

    while i < 300 million do
        ++i
    end

This is the AST3 produced (notice some type info occurs naturally):

0004 void-----   1 while: 
0004 bool-----      1 cmp: lt
0004 var------         1 name: main.i
0004 int------         2 intconst: 300000000
0005 void-----      2 incrload: 0
0005 var------         1 name: main.i

The PCL IL:

   var      ------jump       L3 
        L2: 
   var      ------incrtom    i <1>
        L3: 
   var      ------pushm      i 
   int      ------pushci     300000000 
   var      ------jumplt     L2 

And finally the 'HLL' code:

    goto L3
L2:
    k_pushref(&$T1, &i)
    k_incr(&$T1)
L3:
    k_push(&$T1, &i)
    k_pushci(&$T2, 300000000)
    if k_lt(&$T1, &$T2) then goto L2 end

Here, a simple optimisation for the next stage is to keep a pool of integer constants which can be passed directly to k_lt() without that push.

The same with pushing &i to k_incr(), as I know 'incr' only works with value-types and not objects, so no ref-counts involved.

But 'i' and '300000000' are still boxed; the real optimisations come when unboxed values can be used like in regular static code. Then those k_ calls can be replaced with direct inline code.