translator: reference reassignment, elvis operator, tests

This commit is contained in:
e5l
2016-07-21 17:22:38 +03:00
parent 3a02c42d50
commit 74a22ed4f9
4 changed files with 59 additions and 39 deletions
@@ -94,8 +94,11 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
val receiverName = expr.receiverExpression.text
val selectorExpr = expr.selectorExpression!!
val receiver = variableManager.getLLVMvalue(receiverName)
var receiver = variableManager.getLLVMvalue(receiverName)
if (receiver != null) {
if (receiver.pointer == 2) {
receiver = codeBuilder.loadAndGetVariable(receiver)
}
return evaluateMemberMethodOrField(receiver, selectorExpr.text, scopeDepth, expr.lastChild)
}
@@ -110,7 +113,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
else -> throw UnsupportedOperationException()
}
private fun evaluatenameReferenceExpression(expr: KtNameReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
val field = classScope!!.companionFieldsIndex[fieldName]
@@ -175,8 +178,8 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) {
is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluatenameReferenceExpression(expr, scopeDepth + 1, classScope)
else variableManager.getLLVMvalue(expr.firstChild.text)
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, scopeDepth + 1, classScope)
else variableManager.getLLVMvalue(expr.firstChild.text)
}
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
@@ -275,12 +278,19 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
}).toList()
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? {
val store = codeBuilder.getNewVariable(function.type)
codeBuilder.allocStaticVar(store)
store.pointer++
val result = codeBuilder.getNewVariable(function.type)
result.pointer++
codeBuilder.allocStaticVar(result)
result.pointer += 1
result.pointer++
codeBuilder.storeVariable(result, store)
val args = ArrayList<LLVMSingleValue>()
args.add(result)
args.add(store)
args.addAll(names)
codeBuilder.addLLVMCode(LLVMCall(
@@ -316,46 +326,38 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return executeBinaryExpression(operator, expr.operationReference, left, right, scopeDepth)
}
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int): LLVMVariable {
val result = addPrimitiveBinaryOperation(operator, referenceName, left, right)
if (left.type is LLVMReferenceType && left.pointer > 0 && right.pointer > 0) {
variableManager.addVariable((left as LLVMVariable).kotlinName!!, result, scopeDepth)
}
return result
}
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int)
= addPrimitiveBinaryOperation(operator, referenceName, left, right)
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
val condition = left.type!!.operatorEq(left, LLVMVariable("", LLVMNullType()))
val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable)
val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType()))
val conditionResult = codeBuilder.getNewVariable(condition.variableType)
codeBuilder.addAssignment(conditionResult, condition)
val elvisResult = codeBuilder.getNewVariable(left.type!!, pointer = left.pointer)
codeBuilder.allocStackVar(elvisResult)
elvisResult.pointer++
val thenLabel = codeBuilder.getNewLabel(prefix = "elvis")
val elseLabel = codeBuilder.getNewLabel(prefix = "elvis")
val endLabel = codeBuilder.getNewLabel(prefix = "elvis")
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
codeBuilder.addCondition(conditionResult, elseLabel, thenLabel)
codeBuilder.markWithLabel(thenLabel)
codeBuilder.storeVariable(elvisResult, left)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel)
val right = evaluateExpression(expr.lastChild, scopeDepth + 1)
var right = evaluateExpression(expr.lastChild, scopeDepth + 1)
if (right != null) {
codeBuilder.storeVariable(elvisResult, right)
right = codeBuilder.loadAndGetVariable(right as LLVMVariable)
codeBuilder.storeVariable(left, right)
}
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(endLabel)
return elvisResult
return left
}
private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
@@ -371,7 +373,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ ->
if (firstOp.type is LLVMReferenceType)
firstOp.type!!.operatorEq(firstOp, secondOp)
firstOp.type!!.operatorEq(firstNativeOp, secondOp)
else
firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EXCLEQ -> firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp)
@@ -385,10 +387,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result
}
if (firstOp.type is LLVMReferenceType && firstOp.pointer > 0 && secondOp.pointer > 0) {
return secondOp as LLVMVariable
}
val result = firstOp as LLVMVariable
codeBuilder.storeVariable(result, secondNativeOp)
return result
@@ -564,10 +562,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return null
}
private fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
is LLVMStringType -> codeBuilder.storeString(to, from, 0)
else -> codeBuilder.copyVariableValue(to, from)
}
private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? {
val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!!
@@ -584,7 +578,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
allocVar.kotlinName = identifier
variableManager.addVariable(identifier, allocVar, scopeDepth)
copyVariable(assignExpression, allocVar)
codeBuilder.copyVariable(assignExpression, allocVar)
} else {
assignExpression.kotlinName = identifier
variableManager.addVariable(identifier, assignExpression, scopeDepth)
@@ -601,9 +595,8 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
reference.pointer += 1
codeBuilder.storeNull(reference)
val result = codeBuilder.loadAndGetVariable(reference)
variableManager.addVariable(identifier, result, scopeDepth)
variableManager.addVariable(identifier, reference, scopeDepth)
return null
}
@@ -620,12 +613,16 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
private fun evaluateReturnInstruction(element: PsiElement, scopeDepth: Int): LLVMVariable? {
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
val retVar = evaluateExpression(next, scopeDepth)
var retVar = evaluateExpression(next, scopeDepth)
val type = retVar?.type ?: LLVMVoidType()
when (type) {
is LLVMReferenceType -> {
codeBuilder.storeVariable(returnType!!, retVar!!)
if (retVar!!.pointer == 2) {
retVar = codeBuilder.loadAndGetVariable(retVar as LLVMVariable)
}
codeBuilder.storeVariable(returnType!!, retVar)
codeBuilder.addAnyReturn(LLVMVoidType())
}
is LLVMVoidType -> {
@@ -147,6 +147,11 @@ class LLVMBuilder(val arm: Boolean) {
localCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
}
fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
is LLVMStringType -> storeString(to, from, 0)
else -> copyVariableValue(to, from)
}
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1)
addVariableByRef(allocVar, llvmVariable, store)
@@ -0,0 +1,2 @@
elvis_test_1(0) == 0
elvis_test_1(2) == 1
@@ -0,0 +1,16 @@
class MyClass(val i: Int)
fun elvis_test_1(x: Int): Int {
var z: MyClass? = null
if (x > 1) {
z = MyClass(1)
} else {
}
val y = z ?: return 0
return 1
}