SomMeri / less4j

Less language is an extension of css and less4j compiles it into regular css. Less adds several dynamic features into css: variables, expressions, nested rules, and so on. Less was designed to be compatible with css and any correct css file is also correct less file.
145 stars 47 forks source link

Issue with mixin evaluation #275

Closed twhoff closed 9 years ago

twhoff commented 9 years ago

Description

Again using the for-loop logic as an example, this code should compile and run but doesn't:

    @list: one, two, three;
    @number: 2;

    .for(@i, @n) {
        should-get-executed: and-did;
        .-each(@i)
    }
    .for(@n)     when (isnumber(@n)) {
        .for(1, @n)
    }
    .for(@i, @n) when not (@i = @n)  {
        .for((@i + ((@n - @i) / abs(@n - @i))), @n);
    }
    .for(@array)   when (default()) {
        .for-impl_(length(@array))
    }
    .for-impl_(@i) when (@i > 1)    {.for-impl_((@i - 1))}
    .for-impl_(@i)                  {
        should-not-get-executed: but-did;
        .-each(extract(@array, @i));
    }

   // CALL THE .for() MIXIN HERE WITH ONLY A NUMER FOR THE PARAMETER
    .for(@number); .-each(@val) {
        val: @val;
    }

Error:

Caused by: com.github.sommeri.less4j.Less4jException: Could not compile less. 1 error(s) occurred:
ERROR 35:14 Wrong argument type to function 'extract', expected LIST_EXPRESSION saw number.
 34:     @list: one, two three;
 35:     @number: 2;
 36: 

Explanation:

So calling the .for() mixin with a number as the parameter should execute the .for(@n) when (isnumber(@n)) mixin based on pattern matching.

Comment out the following line:

.-each(extract(@array, @i));

You can see in the pattern matching for the .for() mixin is work (ie, it does not output the "should-not-get-executed: but-did;" line) - however it seems it is still evaluating the .-each() mixin in the same scope, which is causing the error.

This compiles fine under the less compiler, so I believe this is a bug.

SomMeri commented 9 years ago

Nice catch, thank you for bug reports.

Simplified example:

    .for(@n)  when (isnumber(@n)) {
        isnumber: true;
    }
    .for(@array) when (default()) {
        should-not-get-executed: but-did;
        //.-each(extract(@array, length(@array))); //un-comment to get error
    }

@list: one, two, three;
.we {   
    @number: 2;
    .for(@number); 
    .-each(@val) {
        val: @val;
    }
}

It is trying to compile .for(@array) despite it not being in output.