From f354d191dd5f227a84ffb68a01206f642980b505 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Wed, 24 Aug 2016 10:01:24 +0300 Subject: [PATCH] translator: add for loops, tests --- .../kotlinnative/translator/BlockCodegen.kt | 47 +++++++++++++++++++ .../src/test/kotlin/tests/input/for_1.txt | 1 + .../kotlin/tests/input/range_operator_1.txt | 1 + .../src/test/kotlin/tests/kotlin/for_1.kt | 7 +++ .../kotlin/tests/kotlin/range_operator_1.kt | 10 ++++ 5 files changed, 66 insertions(+) create mode 100644 translator/src/test/kotlin/tests/input/for_1.txt create mode 100644 translator/src/test/kotlin/tests/input/range_operator_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/for_1.kt create mode 100644 translator/src/test/kotlin/tests/kotlin/range_operator_1.kt diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index d0622c89968..c728555f0d0 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -811,6 +811,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp) KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp) KtTokens.MUL -> firstOp.type!!.operatorTimes(firstNativeOp, secondNativeOp) + KtTokens.DIV -> firstOp.type!!.operatorDiv(firstNativeOp, secondNativeOp) KtTokens.LT -> firstOp.type!!.operatorLt(firstNativeOp, secondNativeOp) KtTokens.GT -> firstOp.type!!.operatorGt(firstNativeOp, secondNativeOp) KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp) @@ -896,10 +897,56 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth) KtTokens.IF_KEYWORD -> evaluateIfOperator(element.context as KtIfExpression, scopeDepth, isExpression = false) KtTokens.WHILE_KEYWORD -> evaluateWhileOperator(element.context as KtWhileExpression, scopeDepth) + KtTokens.FOR_KEYWORD -> evaluateForOperator(element.context as KtForExpression, scopeDepth) else -> null } } + private fun evaluateForOperator(expr: KtForExpression, scopeDepth: Int): LLVMVariable? { + val range = evaluateExpression(expr.loopRange, scopeDepth + 1)!! + val conditionLabel = codeBuilder.getNewLabel(prefix = "for_condition") + val bodyLabel = codeBuilder.getNewLabel(prefix = "for_body") + val exitLabel = codeBuilder.getNewLabel(prefix = "for_exit") + val rangeTypeName = (range.type as LLVMReferenceType).type + + val descriptor = state.classes[rangeTypeName] + val method = descriptor!!.methods["$rangeTypeName.iterator"] ?: throw UnexpectedException("$rangeTypeName.iterator") + val returnType = method.returnType!!.type + val returnTypeName = (returnType as LLVMReferenceType).type + val iteratorDescriptor = state.classes[returnTypeName] + val nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.nextInt"] ?: throw UnexpectedException("$returnTypeName.hasNext") + + val conditionIterator = evaluateFunctionCallExpression(LLVMVariable("$rangeTypeName.iterator", returnType, scope = LLVMVariableScope()), listOf(range))!! + val iteratorThisArgument = codeBuilder.loadArgumentIfRequired(conditionIterator, LLVMVariable("type", descriptor.type, pointer = 1)) + codeBuilder.addUnconditionalJump(conditionLabel) + codeBuilder.markWithLabel(conditionLabel) + var conditionResult = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.hasNext", LLVMBooleanType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!! + + while (conditionResult.pointer > 0) { + conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable) + } + + codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) + + codeBuilder.addUnconditionalJump(bodyLabel) + codeBuilder.markWithLabel(bodyLabel) + val currentParameter = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.nextInt", LLVMIntType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!! + + val allocVar = variableManager.receiveVariable(expr.loopParameter!!.name!!, nextDescriptor.returnType!!.type, LLVMRegisterScope(), pointer = + nextDescriptor.returnType!!.pointer) + variableManager.addVariable(expr.loopParameter!!.name!!, allocVar, scopeDepth + 1) + codeBuilder.allocStackVar(allocVar) + allocVar.pointer++ + allocVar.kotlinName = expr.loopParameter!!.name!! + + addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, currentParameter) + + evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1) + codeBuilder.markWithLabel(exitLabel) + + return null + } + private fun evaluateWhenItem(item: KtWhenEntry, target: LLVMSingleValue, resultVariable: LLVMVariable, elseLabel: LLVMLabel, endLabel: LLVMLabel, isElse: Boolean, scopeDepth: Int) { val successConditionsLabel = codeBuilder.getNewLabel(prefix = "when_condition_success") var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition") diff --git a/translator/src/test/kotlin/tests/input/for_1.txt b/translator/src/test/kotlin/tests/input/for_1.txt new file mode 100644 index 00000000000..3fa1d39457b --- /dev/null +++ b/translator/src/test/kotlin/tests/input/for_1.txt @@ -0,0 +1 @@ +for_1_simple() == 165 diff --git a/translator/src/test/kotlin/tests/input/range_operator_1.txt b/translator/src/test/kotlin/tests/input/range_operator_1.txt new file mode 100644 index 00000000000..3e48da2bc65 --- /dev/null +++ b/translator/src/test/kotlin/tests/input/range_operator_1.txt @@ -0,0 +1 @@ +range_operator_1() == 165 diff --git a/translator/src/test/kotlin/tests/kotlin/for_1.kt b/translator/src/test/kotlin/tests/kotlin/for_1.kt new file mode 100644 index 00000000000..a540d0fe8ef --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/for_1.kt @@ -0,0 +1,7 @@ +fun for_1_simple(): Int { + var sum = 0 + for (i in 10..20) { + sum += i + } + return sum +} \ No newline at end of file diff --git a/translator/src/test/kotlin/tests/kotlin/range_operator_1.kt b/translator/src/test/kotlin/tests/kotlin/range_operator_1.kt new file mode 100644 index 00000000000..f9625d7bf92 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/range_operator_1.kt @@ -0,0 +1,10 @@ +fun range_operator_1(): Int { + val progression = 10..20 + val a = progression.iterator() + var result = 0 + while (a.hasNext()) { + val nxt = a.nextInt() + result += nxt + } + return result +} \ No newline at end of file