pure-c / purec

C backend for PureScript
232 stars 8 forks source link

Error due to redifinition of local variables #18

Closed felixSchl closed 6 years ago

felixSchl commented 6 years ago

PureScript test "passing/1991.purs" is not passing because the currently generated C code redefines local variables (#12)

Without the inlineVariables optimization pass in the PureScript JS codegen, it spits out code looking similar to this:

var foldMap = function ($copy_dictSemigroup) {
    return function ($copy_f) {
        return function ($copy_v) {
            var $tco_var_dictSemigroup = $copy_dictSemigroup;
            var $tco_var_f = $copy_f;
            var $tco_done = false;
            var $tco_result;
            function $tco_loop(dictSemigroup, f, v) {
                var $2 = f;
                var $3 = v;
                var f1 = $2;
                if ($3.length === 5) {
                    var $4 = $3[0];
                    var a = $4;
                    var $5 = $3[1];
                    var b = $5;
                    var $6 = $3[2];
                    var c = $6;
                    var $7 = $3[3];
                    var d = $7;
                    var $8 = $3[4];
                    var e = $8;
                    $tco_done = true;
                    return Data_Semigroup.append(dictSemigroup)(f1(a))(Data_Semigroup.append(dictSemigroup)(f1(b))(Data_Semigroup.append(dictSemigroup)(f1(c))(Data_Semigroup.append(dictSemigroup)(f1(d))(f1(e)))));
                };
                var f1 = $2;
                var xs = $3;
                $tco_var_dictSemigroup = dictSemigroup;
                $tco_var_f = f1;
                $copy_v = xs;
                return;
            };
            while (!$tco_done) {
                $tco_result = $tco_loop($tco_var_dictSemigroup, $tco_var_f, $copy_v);
            };
            return $tco_result;
        };
    };
};

JavaScript doesn't care that e.g. f1 gets redefined at will, but we're not so fortunate in C. I think we should be able to generate unoptimized code that still compiles. We could forward declare variable introductions on a per-block level and then assign to them later. This rewrite pass would run on the initially generated AST.

felixSchl commented 6 years ago

Fixed by running a pass over the AST that hoists variable declarations to the top of blocks (https://github.com/pure-c/pure-c/blob/7bc2a52ce211b5ac27c620d263b287a8933a48b7/src/Language/PureScript/CodeGen/C.purs#L742-L804)