translator: add skeleton for if expression; LLVMLabel, LLVMBooleanType, fix resolving operators return type, fix comparison operators

This commit is contained in:
Alexey Stepanov
2016-07-13 10:11:13 +03:00
parent 947c144eef
commit 3aa0d3021e
10 changed files with 147 additions and 65 deletions
@@ -169,12 +169,11 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
return args
}
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMNode {
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
val left = evaluateExpression(expr.firstChild, scopeDepth) as LLVMSingleValue? ?: throw UnsupportedOperationException("Wrong binary exception")
val right = evaluateExpression(expr.lastChild, scopeDepth) as LLVMSingleValue? ?: throw UnsupportedOperationException("Wrong binary exception")
val operator = expr.operationToken
val newVar = codeBuilder.getNewVariable(LLVMIntType())
return codeBuilder.addPrimitiveBinaryOperation(operator, newVar, left, right)
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
@@ -196,10 +195,32 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
KtTokens.VAL_KEYWORD -> evaluateValExpression(element, scopeDepth)
KtTokens.VAR_KEYWORD -> evaluateValExpression(element, scopeDepth)
KtTokens.IF_KEYWORD -> evaluateIfExpression(element, scopeDepth)
else -> null
}
}
private fun evaluateIfExpression(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
var getBrackets = element.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val condition = getBrackets.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
getBrackets = condition.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val thenExpression = getBrackets.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val elseExpression = thenExpression.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
return executeCondition(condition.firstChild as KtBinaryExpression, thenExpression.firstChild, elseExpression.firstChild, scopeDepth + 1)
}
private fun executeCondition(condition: KtBinaryExpression, thenExpression: PsiElement, elseExpression: PsiElement?, scopeDepth: Int): LLVMVariable? {
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
val thenLabel = codeBuilder.getNewLabel()
val elseLabel = codeBuilder.getNewLabel()
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
return null
}
private fun evaluateValExpression(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
val identifier = element.getNextSiblingIgnoringWhitespaceAndComments()
val eq = identifier?.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
@@ -7,6 +7,7 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMBuilder {
private var llvmCode: StringBuilder = StringBuilder()
private var variableCount = 0
private var labelCount = 0
init {
initBuilder()
@@ -22,6 +23,11 @@ class LLVMBuilder {
return LLVMVariable("%var$variableCount", type, kotlinName = kotlinName, pointer = pointer)
}
fun getNewLabel(): LLVMLabel {
labelCount++
return LLVMLabel("%label$labelCount")
}
fun addLLVMCode(code: String) {
llvmCode.appendln(code)
}
@@ -43,13 +49,19 @@ class LLVMBuilder {
else -> throw UnsupportedOperationException()
}
fun addPrimitiveBinaryOperation(operation: IElementType, resultOp: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
fun addPrimitiveBinaryOperation(operation: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
val firstNativeOp = receiveNativeValue(firstOp)
val secondNativeOp = receiveNativeValue(secondOp)
val llvmExpression = when (operation) {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(resultOp, firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(resultOp, firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(resultOp, firstNativeOp, secondNativeOp)
KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(firstNativeOp, secondNativeOp)
KtTokens.LT -> firstOp.type!!.operatorLt(firstNativeOp, secondNativeOp)
KtTokens.GT -> firstOp.type!!.operatorGt(firstNativeOp, secondNativeOp)
KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp)
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ -> firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EXCLEQ -> firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp)
KtTokens.EQ -> {
val result = firstOp as LLVMVariable
storeVariable(result, secondNativeOp)
@@ -57,7 +69,7 @@ class LLVMBuilder {
}
else -> throw UnsupportedOperationException("Unknown binary operator")
}
val resultOp = getNewVariable(llvmExpression.variableType)
addAssignment(resultOp, llvmExpression)
return resultOp
@@ -124,6 +136,10 @@ class LLVMBuilder {
return target
}
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) {
llvmCode.appendln("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel")
}
fun createClass(name: String, fields: List<LLVMVariable>) {
val code = "%class.$name = type { ${fields.map { it.type }.joinToString()} }"
llvmCode.appendln(code)
@@ -0,0 +1,6 @@
package org.kotlinnative.translator.llvm
class LLVMLabel(val label: String) : LLVMNode() {
override fun toString(): String = label
}
@@ -7,7 +7,7 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
"${if (declare) "declare" else "define"} $returnType @$name(${
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
"${s.getType()} %${s.label}"
}?.joinToString() })"
}?.joinToString()})"
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
"Int" -> LLVMIntType()
@@ -0,0 +1,43 @@
package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
class LLVMBooleanType() : LLVMType() {
//TODO switch by types: int + double = int
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "sub nsw i1 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "mul nsw i1 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "add nsw i1 $firstOp, $secondOp")
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp slt i1 $firstOp, $secondOp")
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sgt i1 $firstOp, $secondOp")
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sle i1 $firstOp, $secondOp")
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sge i1 $firstOp, $secondOp")
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp eq i1 $firstOp, $secondOp")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp ne i1 $firstOp, $secondOp")
override val align = 4
override val size: Byte = 1
override fun toString() = "i1"
}
@@ -2,26 +2,25 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMCharType() : LLVMType() {
override fun operatorLt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp slt i8 $firstOp, $secondOp")
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp slt i8 $firstOp, $secondOp")
override fun operatorGt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sgt i8 $firstOp, $secondOp")
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sgt i8 $firstOp, $secondOp")
override fun operatorLeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sle i8 $firstOp, $secondOp")
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sle i8 $firstOp, $secondOp")
override fun operatorGeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sge i8 $firstOp, $secondOp")
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sge i8 $firstOp, $secondOp")
override fun operatorEq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp eq i8 $firstOp, $secondOp")
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp eq i8 $firstOp, $secondOp")
override fun operatorNeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp ne i8 $firstOp, $secondOp")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp ne i8 $firstOp, $secondOp")
override val align = 1
override val size: Byte = 1
@@ -2,21 +2,20 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMDoubleType() : LLVMType() {
//TODO switch by types: int + double = int
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fsub double i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fmul double i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
override val align = 8
@@ -2,40 +2,40 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMIntType() : LLVMType() {
//TODO switch by types: int + double = int
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "mul nsw i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
override fun operatorLt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp slt i32 $firstOp, $secondOp")
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp slt i32 $firstOp, $secondOp")
override fun operatorGt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sgt i32 $firstOp, $secondOp")
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression {
return LLVMExpression(LLVMBooleanType(), "icmp sgt i32 $firstOp, $secondOp")
}
override fun operatorLeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sle i32 $firstOp, $secondOp")
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sle i32 $firstOp, $secondOp")
override fun operatorGeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sge i32 $firstOp, $secondOp")
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sge i32 $firstOp, $secondOp")
override fun operatorEq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp eq i32 $firstOp, $secondOp")
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp eq i32 $firstOp, $secondOp")
override fun operatorNeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp ne i32 $firstOp, $secondOp")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp ne i32 $firstOp, $secondOp")
override val align = 4
override val size: Byte = 4
@@ -2,26 +2,25 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMShortType() : LLVMType() {
override fun operatorLt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp slt i16 $firstOp, $secondOp")
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp slt i16 $firstOp, $secondOp")
override fun operatorGt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sgt i16 $firstOp, $secondOp")
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sgt i16 $firstOp, $secondOp")
override fun operatorLeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sle i16 $firstOp, $secondOp")
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sle i16 $firstOp, $secondOp")
override fun operatorGeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp sge i16 $firstOp, $secondOp")
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp sge i16 $firstOp, $secondOp")
override fun operatorEq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp eq i16 $firstOp, $secondOp")
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp eq i16 $firstOp, $secondOp")
override fun operatorNeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "icmp ne i16 $firstOp, $secondOp")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp ne i16 $firstOp, $secondOp")
override val size: Byte = 2
override val align = 2
@@ -3,19 +3,18 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
abstract class LLVMType() : Cloneable {
open fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorLt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorGt(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorLeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorGeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorEq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorNeq(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
fun makeClone() = clone()