translator: add for loops, tests

This commit is contained in:
Alexey Stepanov
2016-08-24 10:01:24 +03:00
parent 7067288cf4
commit f354d191dd
5 changed files with 66 additions and 0 deletions
@@ -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")
@@ -0,0 +1 @@
for_1_simple() == 165
@@ -0,0 +1 @@
range_operator_1() == 165
@@ -0,0 +1,7 @@
fun for_1_simple(): Int {
var sum = 0
for (i in 10..20) {
sum += i
}
return sum
}
@@ -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
}