Search in sources :

Example 6 with Expression

use of org.gradle.language.nativeplatform.internal.Expression in project gradle by gradle.

the class DefaultSourceIncludesResolver method resolveTokenConcatenationToTokens.

private Collection<Expression> resolveTokenConcatenationToTokens(MacroLookup visibleMacros, Expression expression, ExpressionVisitor visitor, TokenLookup tokenLookup) {
    Expression left = expression.getArguments().get(0);
    Expression right = expression.getArguments().get(1);
    Collection<Expression> leftValues = resolveExpressionToTokens(visibleMacros, left, visitor, tokenLookup);
    Collection<Expression> rightValues = resolveExpressionToTokens(visibleMacros, right, visitor, tokenLookup);
    if (leftValues.isEmpty() || rightValues.isEmpty()) {
        return Collections.emptyList();
    }
    List<Expression> expressions = new ArrayList<Expression>(leftValues.size() * rightValues.size());
    for (Expression leftValue : leftValues) {
        if (leftValue.getType() != IncludeType.IDENTIFIER) {
            if (rightValues.size() == 1) {
                Expression rightValue = rightValues.iterator().next();
                if (rightValue.getType() == IncludeType.EXPRESSIONS && rightValue.getArguments().isEmpty()) {
                    // Empty RHS
                    expressions.add(leftValue);
                    continue;
                }
            }
            // Not supported for now
            visitor.visitUnresolved();
            continue;
        }
        String leftString = leftValue.getValue();
        for (Expression rightValue : rightValues) {
            // Handle just empty string, single identifier or '(' params? ')', should handle more by parsing the tokens into an expression
            if (rightValue.getType() == IncludeType.IDENTIFIER) {
                expressions.add(new SimpleExpression(leftString + rightValue.getValue(), IncludeType.IDENTIFIER));
                continue;
            }
            if (rightValue.getType() == IncludeType.ARGS_LIST) {
                expressions.add(new ComplexExpression(IncludeType.MACRO_FUNCTION, leftString, rightValue.getArguments()));
                continue;
            }
            if (rightValue.getType() == IncludeType.EXPRESSIONS && rightValue.getArguments().isEmpty()) {
                expressions.add(new SimpleExpression(leftString, IncludeType.IDENTIFIER));
                continue;
            }
            visitor.visitUnresolved();
        }
    }
    return expressions;
}
Also used : Expression(org.gradle.language.nativeplatform.internal.Expression) ComplexExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.ComplexExpression) SimpleExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.SimpleExpression) ArrayList(java.util.ArrayList) SimpleExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.SimpleExpression) ComplexExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.ComplexExpression)

Example 7 with Expression

use of org.gradle.language.nativeplatform.internal.Expression in project gradle by gradle.

the class DefaultSourceIncludesResolver method resolveExpressionSequence.

private void resolveExpressionSequence(MacroLookup visibleMacros, Expression expression, ExpressionVisitor visitor, TokenLookup tokenLookup) {
    List<Expression> expressions = expression.getArguments();
    // Only <function-call>+ <args-list> supported
    if (expressions.size() < 2) {
        visitor.visitUnresolved();
        return;
    }
    Expression argListExpression = expressions.get(expressions.size() - 1);
    List<Expression> headExpressions = expressions.subList(0, expressions.size() - 1);
    Collection<Expression> args = resolveExpressionToTokens(visibleMacros, argListExpression, visitor, tokenLookup);
    for (Expression value : args) {
        resolveExpressionSequenceForArgs(visibleMacros, headExpressions, value, visitor, tokenLookup);
    }
}
Also used : Expression(org.gradle.language.nativeplatform.internal.Expression) ComplexExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.ComplexExpression) SimpleExpression(org.gradle.language.nativeplatform.internal.incremental.sourceparser.SimpleExpression)

Example 8 with Expression

use of org.gradle.language.nativeplatform.internal.Expression in project gradle by gradle.

the class RegexBackedCSourceParser method parseMacroFunctionDirectiveBody.

/**
 * Parse a "function-like" macro directive body. Consumes all input.
 */
private void parseMacroFunctionDirectiveBody(Buffer buffer, String macroName, Collection<MacroFunction> macroFunctions) {
    buffer.consumeWhitespace();
    List<String> paramNames = new ArrayList<String>();
    consumeParameterList(buffer, paramNames);
    if (!buffer.consume(')')) {
        // Badly form args list
        return;
    }
    Expression expression = parseDirectiveBodyExpression(buffer);
    if (expression.getType() == IncludeType.QUOTED || expression.getType() == IncludeType.SYSTEM) {
        // Returns a fixed value expression
        macroFunctions.add(new ReturnFixedValueMacroFunction(macroName, paramNames.size(), expression.getType(), expression.getValue(), Collections.<Expression>emptyList()));
        return;
    }
    if (expression.getType() == IncludeType.IDENTIFIER) {
        for (int i = 0; i < paramNames.size(); i++) {
            String name = paramNames.get(i);
            if (name.equals(expression.getValue())) {
                // Returns a parameter
                macroFunctions.add(new ReturnParameterMacroFunction(macroName, paramNames.size(), i));
                return;
            }
        }
        // References some fixed value expression, return it after macro expanding
        macroFunctions.add(new ReturnFixedValueMacroFunction(macroName, paramNames.size(), IncludeType.MACRO, expression.getValue(), Collections.<Expression>emptyList()));
        return;
    }
    if (expression.getType() != IncludeType.OTHER) {
        // Look for parameter substitutions
        if (paramNames.isEmpty() || expression.getArguments().isEmpty()) {
            // When this function has no parameters, we don't need to substitute parameters, so return the expression after macro expanding it
            // Also handle calling a zero args function, as we also don't need to substitute parameters
            expression = expression.asMacroExpansion();
            macroFunctions.add(new ReturnFixedValueMacroFunction(macroName, paramNames.size(), expression.getType(), expression.getValue(), expression.getArguments()));
            return;
        }
        List<Integer> argsMap = new ArrayList<Integer>(expression.getArguments().size());
        boolean usesArgs = mapArgs(paramNames, expression, argsMap);
        if (!usesArgs) {
            // Don't need to do parameter substitution, return the value of the expression after macro expanding it
            expression = expression.asMacroExpansion();
            macroFunctions.add(new ReturnFixedValueMacroFunction(macroName, paramNames.size(), expression.getType(), expression.getValue(), expression.getArguments()));
        } else {
            // Need to do parameter substitution, return the value of the expression after parameter substitutions and macro expanding the result
            int[] argsMapArray = new int[argsMap.size()];
            for (int i = 0; i < argsMap.size(); i++) {
                argsMapArray[i] = argsMap.get(i);
            }
            expression = expression.asMacroExpansion();
            macroFunctions.add(new ArgsMappingMacroFunction(macroName, paramNames.size(), argsMapArray, expression.getType(), expression.getValue(), expression.getArguments()));
        }
        return;
    }
    // Not resolvable. Discard the body when the expression is not resolvable
    macroFunctions.add(new UnresolveableMacroFunction(macroName, paramNames.size()));
}
Also used : ArrayList(java.util.ArrayList) Expression(org.gradle.language.nativeplatform.internal.Expression)

Example 9 with Expression

use of org.gradle.language.nativeplatform.internal.Expression in project gradle by gradle.

the class RegexBackedCSourceParser method mapArgs.

private boolean mapArgs(List<String> paramNames, Expression expression, List<Integer> argsMap) {
    boolean usesParameters = false;
    for (int i = 0; i < expression.getArguments().size(); i++) {
        Expression argument = expression.getArguments().get(i);
        if (argument.getType() == IncludeType.IDENTIFIER) {
            boolean matches = false;
            for (int j = 0; j < paramNames.size(); j++) {
                String paramName = paramNames.get(j);
                if (argument.getValue().equals(paramName)) {
                    argsMap.add(j);
                    usesParameters = true;
                    matches = true;
                    break;
                }
            }
            if (matches) {
                continue;
            }
        }
        if (argument.getArguments().isEmpty()) {
            // Don't map
            argsMap.add(ArgsMappingMacroFunction.KEEP);
            continue;
        }
        List<Integer> nestedMap = new ArrayList<Integer>(argument.getArguments().size());
        boolean argUsesParameters = mapArgs(paramNames, argument, nestedMap);
        if (argUsesParameters) {
            argsMap.add(ArgsMappingMacroFunction.REPLACE_ARGS);
            argsMap.addAll(nestedMap);
        } else {
            argsMap.add(ArgsMappingMacroFunction.KEEP);
        }
        usesParameters |= argUsesParameters;
    }
    return usesParameters;
}
Also used : Expression(org.gradle.language.nativeplatform.internal.Expression) ArrayList(java.util.ArrayList)

Example 10 with Expression

use of org.gradle.language.nativeplatform.internal.Expression in project gradle by gradle.

the class RegexBackedCSourceParser method parseIncludeOrImportDirectiveBody.

/**
 * Parses an #include/#import directive body. Consumes all input.
 */
private void parseIncludeOrImportDirectiveBody(Buffer buffer, boolean isImport, Collection<Include> includes) {
    if (!buffer.hasAny()) {
        // No include expression, ignore
        return;
    }
    if (buffer.hasIdentifierChar()) {
        // An identifier with no separator, so this is not an #include or #import directive, it is some other directive
        return;
    }
    Expression expression = parseDirectiveBodyExpression(buffer);
    if (expression.getType() == IncludeType.TOKEN_CONCATENATION || expression.getType() == IncludeType.ARGS_LIST || expression.getType() == IncludeType.EXPRESSIONS) {
        // Token concatenation is only allowed inside a #define body
        // Arbitrary tokens won't resolve to an include path
        // Treat both these cases as an unresolvable include directive
        expression = new SimpleExpression(expression.getAsSourceText(), IncludeType.OTHER);
    }
    expression = expression.asMacroExpansion();
    if (expression.getType() != IncludeType.OTHER || !expression.getValue().isEmpty()) {
        // Either a resolvable expression or a non-empty unresolvable expression, collect. Ignore includes with no value
        includes.add(IncludeWithSimpleExpression.create(expression, isImport));
    }
}
Also used : Expression(org.gradle.language.nativeplatform.internal.Expression)

Aggregations

Expression (org.gradle.language.nativeplatform.internal.Expression)13 ArrayList (java.util.ArrayList)5 ComplexExpression (org.gradle.language.nativeplatform.internal.incremental.sourceparser.ComplexExpression)4 SimpleExpression (org.gradle.language.nativeplatform.internal.incremental.sourceparser.SimpleExpression)4 Nullable (javax.annotation.Nullable)1 IncludeDirectives (org.gradle.language.nativeplatform.internal.IncludeDirectives)1 MacroFunction (org.gradle.language.nativeplatform.internal.MacroFunction)1