public Object convertParam(List<AlgorithmTreeNode> nodesToCompile, Class<?> clazz, String operationParam) throws SyntaxNodeException { ParameterConverter converter = parameterConverters.get(clazz); if (converter == null) { IOpenSourceCodeModule errorSource = nodesToCompile.get(0).getAlgorithmRow().getOperation() .asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError(String.format("Compilation failure. Can't convert parameter %s to type %s", operationParam, clazz.toString()), errorSource); } return converter.convert(nodesToCompile, operationParam); }
public IOpenSourceCodeModule getSourceModule() { return sourceNode.getAlgorithmRow().getOperation().asSourceCodeModule(); }
private void checkRowValue(StringValue operation, String columnName, StringValue columnValue, ValueNecessity columnNecessity) throws SyntaxNodeException { if (columnNecessity == ValueNecessity.REQUIRED && columnValue.isEmpty()) { IOpenSourceCodeModule source = columnValue.asSourceCodeModule(); if (source.getUri() == null) { // Column <columnName> is absent. Point to <operation> cell instead. String errMsg = String.format("%s is required for operation \"%s\"!", columnName, operation); throw SyntaxNodeExceptionUtils.createError(errMsg, operation.asSourceCodeModule()); } else { // Column <columnName> exists but still is empty. Point to empty <columnValue> cell. String errMsg = String.format("Operation must have value in %s!", columnName); throw SyntaxNodeExceptionUtils.createError(errMsg, source); } } if (columnNecessity == ValueNecessity.PROHIBITED && !columnValue.isEmpty()) { String errMsg = String.format("Operation must not have value in %s!", columnName); throw SyntaxNodeExceptionUtils.createError(errMsg, columnValue.asSourceCodeModule()); } }
private void preprocessConversionStep(List<AlgorithmTreeNode> nodesToCompile, ConversionRuleStep conversionStep) throws SyntaxNodeException { assert nodesToCompile.size() > 0; assert conversionStep != null; String operationType = conversionStep.getOperationType(); if (operationType.startsWith("!") && !operationType.equals(OperationType.CHECK_LABEL.toString())) { OperationPreprocessor preprocessor = operationPreprocessors.get(operationType); if (preprocessor == null) { IOpenSourceCodeModule errorSource = nodesToCompile.get(0) .getAlgorithmRow() .getOperation() .asSourceCodeModule(); throw SyntaxNodeExceptionUtils .createError(String.format("Unknown compilation instruction %s", operationType), errorSource); } else { preprocessor.preprocess(nodesToCompile, conversionStep); } } }
private SuitablityAsReturn analyzeSequence(List<AlgorithmTreeNode> nodesToAnalyze) throws SyntaxNodeException { SuitablityAsReturn result = SuitablityAsReturn.RETURN; for (int i = 0, linkedNodesGroupSize; i < nodesToAnalyze.size(); i += linkedNodesGroupSize) { linkedNodesGroupSize = AlgorithmCompilerTool.getLinkedNodesGroupSize(nodesToAnalyze, i); if (linkedNodesGroupSize == 1) { result = analyzeNode(nodesToAnalyze.get(i)); } else { result = analyzeGroup(nodesToAnalyze.subList(i, i + linkedNodesGroupSize)); } if (result == SuitablityAsReturn.RETURN && i + linkedNodesGroupSize < nodesToAnalyze.size()) { IOpenSourceCodeModule errorSource = nodesToAnalyze.get(i + linkedNodesGroupSize).getAlgorithmRow() .getOperation().asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError("Unreachable code. Operations after RETURN not allowed.", errorSource); } } return result; }
protected void checkRowName(TableRow row, String expectedName) throws SyntaxNodeException { SubValue sv = row.get(NAMES)[0]; if (!expectedName.equalsIgnoreCase(sv.getString())) { String msg = "Expects " + expectedName + " here!"; throw SyntaxNodeExceptionUtils.createError(msg, sv.getStringValue().asSourceCodeModule()); } }
/** * * @param labelName * @param labeledOperation * @throws BoundError */ public void registerNewLabel(String labelName, AlgorithmTreeNode sourceNode) throws SyntaxNodeException { if (isLabelRegistered(labelName)) { IOpenSourceCodeModule errorSource = sourceNode.getAlgorithmRow().getOperation().asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError("Such label has been already declared : \"" + labelName + "\".", errorSource); } else { existingLables.put(labelName, sourceNode); } }
public String getSourceUri() { return sourceNode.getAlgorithmRow().getOperation().asSourceCodeModule().getUri(); }
@Override public List<RuntimeOperation> getOperations(List<AlgorithmTreeNode> nodesToCompile, ConversionRuleStep conversionStep) throws Exception { String labelName = (String) parameterConverter.convertParam(nodesToCompile, String.class, conversionStep.getOperationParam1()); if (!currentCompileContext.isLabelRegistered(labelName)) { IOpenSourceCodeModule errorSource = nodesToCompile.get(0).getAlgorithmRow().getOperation().asSourceCodeModule(); String errorMessage = String.format("Such label is not available from this place: \"%s\".", labelName); throw SyntaxNodeExceptionUtils.createError(errorMessage, errorSource); } return null; } }
/** * @param candidateNodes * @param instruction * @return The {@link org.openl.rules.tbasic.AlgorithmTreeNode} that suits the given instruction name * * @throws SyntaxNodeException */ public static AlgorithmTreeNode extractOperationNode(List<AlgorithmTreeNode> candidateNodes, String instruction) throws SyntaxNodeException { AlgorithmTreeNode operationNode = null; // Get the name of the operation: e.g. VAR, IF, WHILE, etc // String operationName = extractOperationName(instruction); for (AlgorithmTreeNode node : candidateNodes) { if (isOperationNode(operationName, node)) { operationNode = node; } } if (operationNode == null) { IOpenSourceCodeModule errorSource = candidateNodes.get(0).getAlgorithmRow().getOperation() .asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError(String.format("Compilation failure. Can't find %s in operations sequence %s", operationName, candidateNodes), errorSource); } return operationNode; }
private List<RuntimeOperation> compileNestedNodes(List<AlgorithmTreeNode> nodesToProcess) throws Exception { final List<RuntimeOperation> emittedOperations = new ArrayList<RuntimeOperation>(); SyntaxNodeExceptionCollector syntaxNodeExceptionCollector = new SyntaxNodeExceptionCollector(); // process nodes by groups of linked nodes for (int i = 0, linkedNodesGroupSize; i < nodesToProcess.size(); i += linkedNodesGroupSize) { if (hasUnreachableCode(nodesToProcess, i)) { IOpenSourceCodeModule errorSource = nodesToProcess.get(i + 1).getAlgorithmRow().getOperation() .asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError("Unreachable code. Operations after BREAK,CONTINUE not allowed.", errorSource); } linkedNodesGroupSize = AlgorithmCompilerTool.getLinkedNodesGroupSize(nodesToProcess, i); final List<AlgorithmTreeNode> nodesToCompile = nodesToProcess.subList(i, i + linkedNodesGroupSize); syntaxNodeExceptionCollector.run(new Runnable() { @Override public void run() throws Exception { emittedOperations.addAll(compileLinkedNodesGroup(nodesToCompile)); } }); } syntaxNodeExceptionCollector.throwIfAny("Compilation fails!"); return emittedOperations; }
@Override protected MatchNode buildTree(List<TableRow> rows, MatchNode[] nodes) throws SyntaxNodeException { MatchNode rootNode = new MatchNode(-1); for (int i = getSpecialRowCount(); i < rows.size(); i++) { MatchNode node = nodes[i]; TableRow row = rows.get(i); SubValue nameSV = row.get(NAMES)[0]; int indent = nameSV.getIndent(); if (indent == 0) { rootNode.add(node); } else { String msg = "Sub node are prohibited here!"; throw SyntaxNodeExceptionUtils.createError(msg, nameSV.getStringValue().asSourceCodeModule()); } } return rootNode; }
@Override protected MatchNode buildTree(List<TableRow> rows, MatchNode[] nodes) throws SyntaxNodeException { MatchNode rootNode = new MatchNode(-1); for (int i = getSpecialRowCount(); i < rows.size(); i++) { MatchNode node = nodes[i]; TableRow row = rows.get(i); SubValue nameSV = row.get(NAMES)[0]; int indent = nameSV.getIndent(); if (indent == 0) { rootNode.add(node); } else { String msg = "Sub node are prohibited here!"; throw SyntaxNodeExceptionUtils.createError(msg, nameSV.getStringValue().asSourceCodeModule()); } } return rootNode; }
private void analyzeReturnCorrectness() throws SyntaxNodeException { if (functionBody.size() > 0) { int i = 0; for (AlgorithmTreeNode algorithmTreeNode : functionBody){ StringValue operation = algorithmTreeNode.getAlgorithmRow().getOperation(); if (operation != null && TBasicSpecificationKey.RETURN.toString().equals(operation.toString())){ SuitablityAsReturn status = new ReturnAnalyzer(getReturnType(), compiler).analyze(functionBody.get(i) .getChildren()); if (status == SuitablityAsReturn.NONE) { IOpenSourceCodeModule errorSource = functionBody.get(i).getAlgorithmRow() .getOperation().asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError("The method must return value of type '" + getReturnType().getDisplayName(INamedThing.REGULAR) + "'", errorSource); } } i++; } } }
/** * @param candidateNodes * @param instruction * @return * @throws SyntaxNodeException */ public static StringValue getCellContent(List<AlgorithmTreeNode> candidateNodes, String instruction) throws SyntaxNodeException { // Field of the AlgorithmRow.class, that also is the column in the TBasic table // String fieldName = extractFieldName(instruction); IOpenField codeField = JavaOpenClass.getOpenClass(AlgorithmRow.class).getField(fieldName); if (codeField == null) { IOpenSourceCodeModule errorSource = candidateNodes.get(0).getAlgorithmRow().getOperation() .asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError(String.format("Compilation failure. Can't find '%s' field", fieldName), errorSource); } // Get the operation node from the candidate nodes, that suits to the given instruction // AlgorithmTreeNode executionNode = extractOperationNode(candidateNodes, instruction); return (StringValue) codeField.get(executionNode.getAlgorithmRow(), null); }
private void checkTreeChildren(MatchNode parent, List<TableRow> rows) throws SyntaxNodeException { int childCount = 0; int childLeafs = 0; for (MatchNode child : parent.getChildren()) { if (child.isLeaf()) { childLeafs++; } childCount++; } if (childCount == childLeafs) { // No children or all are leafs return; } if (childCount == 1 && childLeafs == 0) { // check child for (MatchNode child : parent.getChildren()) { checkTreeChildren(child, rows); } } else { String msg = "All sub nodes must be leaves! Sub nodes are allowed for single child only."; throw SyntaxNodeExceptionUtils.createError(msg, rows.get(parent.getRowIndex()).get(NAMES)[0].getStringValue().asSourceCodeModule()); } }
public IOpenClass getTypeOfField(StringValue fieldContent) { // TODO: make rational type detecting(without creating of // CompositeMethod) IOpenSourceCodeModule src = fieldContent.asSourceCodeModule(); OpenL openl = context.getOpenL(); IMethodSignature signature = header.getSignature(); return OpenLCellExpressionsCompiler .makeMethodWithUnknownType(openl, src, "cell_" + fieldContent.getValue(), signature, thisTargetClass, getAlgorithmBindingContext()) .getMethod() .getType(); }
private SuitablityAsReturn analyzeNode(AlgorithmTreeNode nodeToAnalyze) throws SyntaxNodeException { if (TBasicSpecificationKey.RETURN.toString().equals(nodeToAnalyze.getSpecificationKeyword())) { if (hasTypeAsReturn(nodeToAnalyze.getAlgorithmRow().getCondition())) { return SuitablityAsReturn.RETURN; } else { IOpenSourceCodeModule errorSource = nodeToAnalyze.getAlgorithmRow().getCondition().asSourceCodeModule(); throw SyntaxNodeExceptionUtils.createError("Incorrect return type. Return type of function declared as '" + returnType.getDisplayName(INamedThing.REGULAR) + "'", errorSource); } } else if (canBeGrouped(nodeToAnalyze)) { // for loops and single IF without ELSE return SuitablityAsReturn.NONE; } else if (hasTypeAsReturn(nodeToAnalyze.getAlgorithmRow().getAction())) { return SuitablityAsReturn.SUITABLE; } else { return SuitablityAsReturn.NONE; } }
@Override protected void parseSpecialRows(IBindingContext bindingContext, ColumnMatch columnMatch) throws SyntaxNodeException { super.parseSpecialRows(bindingContext, columnMatch); IOpenClass retType = columnMatch.getHeader().getType(); Class<?> retClass = retType.getInstanceClass(); if (retClass != int.class && retClass != Integer.class) { String msg = "Score algorithm supports int or Integer return type only!"; // String uri = // columnMatch.getTableSyntaxNode().getTableBody().getGridTable().getUri(0, // 0); String uri = columnMatch.getSourceUrl(); throw SyntaxNodeExceptionUtils.createError(msg, new StringSourceCodeModule(null, uri)); } int retValuesCount = columnMatch.getReturnValues().length; // score TableRow scoreRow = columnMatch.getRows().get(ROW_SCORE_IDX); SubValue operationSV = scoreRow.get(OPERATION)[0]; if (!"".equals(operationSV.getString())) { String msg = "Column " + OPERATION + " of special row " + ROW_SCORE + " must be empty!"; throw SyntaxNodeExceptionUtils.createError(msg, operationSV.getStringValue().asSourceCodeModule()); } // score(s) Object[] objScores = parseValues(bindingContext, columnMatch, scoreRow, JavaOpenClass.getOpenClass(Integer.class)); int[] scores = new int[retValuesCount]; for (int i = 0; i < retValuesCount; i++) { scores[i] = (Integer) objScores[i]; } columnMatch.setColumnScores(scores); }
protected Object[] parseValues(IBindingContext bindingContext, ColumnMatch columnMatch, TableRow row, IOpenClass openClass) throws SyntaxNodeException { SubValue[] subValues = row.get(VALUES); Object[] result = new Object[subValues.length]; for (int i = 0; i < subValues.length; i++) { SubValue sv = subValues[i]; String s = sv.getString(); try { ConstantOpenField constantOpenField = RuleRowHelper.findConstantField(bindingContext, s); if (constantOpenField != null && constantOpenField.getValue() != null) { setMetaInfoForConstant(bindingContext, columnMatch, sv, s, constantOpenField); result[i] = RuleRowHelper.castConstantToExpectedType(bindingContext, constantOpenField, openClass); } else { IString2DataConvertor converter = String2DataConvertorFactory.getConvertor(openClass.getInstanceClass()); result[i] = converter.parse(s, null); } } catch (Exception ex) { TextInterval location = LocationUtils.createTextInterval(s); throw SyntaxNodeExceptionUtils.createError(ex, location, sv.getStringValue().asSourceCodeModule()); } } return result; }