package mrtim.sasscompiler;

import mrtim.sasscompiler.expr.StringExpressionValue;
import mrtim.sasscompiler.grammar.SassParser;

public class MixinScopeInitialiser {

    private final SassParser.Parameter_def_listContext mixinDefParameters;
    private final SassParser.Parameter_listContext includeParameters;

    public MixinScopeInitialiser(SassParser.Parameter_def_listContext mixinDefParameters,
                                 SassParser.Parameter_listContext includeParameters) {
        this.mixinDefParameters = mixinDefParameters;
        this.includeParameters = includeParameters;
    }

    public void initialiseScope(Scope scope) {
        for (SassParser.Variable_defContext variableDef: mixinDefParameters.variable_def()) {
            scope.define(variableDef.VARIABLE().getText(), new StringExpressionValue("xxx"));
        }
    }
}

@@ -22,16 +22,64 @@
 piler;%0A%0A
+import mrtim.sasscompiler.expr.ExpressionValue;%0A
 import m
@@ -169,16 +169,81 @@
 sParser;
+%0Aimport org.antlr.v4.runtime.tree.ParseTree;%0A%0Aimport java.util.*;
 %0A%0Apublic
@@ -769,197 +769,2785 @@
     
-for (SassParser.Variable_defContext variableDef: mixinDefParameters.variable_def()) %7B%0A            scope.define(variableDef.VARIABLE().getText(), new StringExpressionValue(%22xxx%22));%0A        %7D
+List%3CString%3E paramNames = positionalParamNames(mixinDefParameters.variable_def());%0A%0A        int positionalIndex = 0;%0A%0A        Map%3CString, ExpressionValue%3E evaluatedParams = new HashMap%3C%3E();%0A        if (includeParameters != null) %7B%0A            for (SassParser.ParameterContext includeParam: includeParameters.parameter()) %7B%0A                if (isKeywordParam(includeParam)) %7B%0A                    String paramName = includeParam.named_parameter().VARIABLE().getText();%0A                    paramNames.remove(paramName);%0A                    evaluatedParams.put(paramName, extractExpressionValue(includeParam, scope));%0A                %7D%0A            %7D%0A            for (SassParser.ParameterContext includeParam: includeParameters.parameter()) %7B%0A                if (!isKeywordParam(includeParam)) %7B%0A                    evaluatedParams.put(paramNames.get(positionalIndex++), extractExpressionValue(includeParam, scope));%0A                %7D%0A            %7D%0A        %7D%0A%0A        for (SassParser.Variable_defContext variableDef: mixinDefParameters.variable_def()) %7B%0A            String variableName = variableDef.VARIABLE().getText();%0A            if (!evaluatedParams.containsKey(variableName)) %7B%0A                evaluatedParams.put(variableName, evaluateInScope(scope, variableDef.expression_list()));%0A            %7D%0A        %7D%0A%0A        for (Map.Entry%3CString, ExpressionValue%3E e: evaluatedParams.entrySet()) %7B%0A            scope.define(e.getKey(), e.getValue());%0A        %7D%0A    %7D%0A%0A    private boolean isKeywordParam(SassParser.ParameterContext includeParam) %7B%0A        return includeParam.named_parameter() != null;%0A    %7D%0A%0A    private List%3CString%3E positionalParamNames(List%3CSassParser.Variable_defContext%3E variableDefs) %7B%0A        List%3CString%3E paramNames = new ArrayList%3C%3E();%0A        for (SassParser.Variable_defContext variableDef: variableDefs) %7B%0A            paramNames.add(variableDef.VARIABLE().getText());%0A        %7D%0A        return paramNames;%0A    %7D%0A%0A    private ExpressionValue extractExpressionValue(SassParser.ParameterContext includeParam, Scope scope) %7B%0A        if (includeParam.IDENTIFIER() != null) %7B%0A            return new StringExpressionValue(includeParam.IDENTIFIER().getText());%0A        %7D%0A        else if (includeParam.value() != null) %7B%0A            return evaluateInScope(scope, includeParam.value());%0A        %7D%0A        else if (includeParam.named_parameter() != null) %7B%0A            return evaluateInScope(scope, includeParam.named_parameter().expression_list());%0A        %7D%0A        else %7B%0A            throw new IllegalArgumentException(%22Could not extract parameter value from ParameterContext: %22 + includeParam.getText());%0A        %7D%0A    %7D%0A%0A    private ExpressionValue evaluateInScope(Scope scope, ParseTree expression) %7B%0A        return new ExpressionVisitor(scope).visit(expression);
 %0A   

Deal with mixing parameters and defaults correctly