translator: add default functions arguments

This commit is contained in:
Alexey Stepanov
2016-08-22 12:27:18 +03:00
parent 97ed193587
commit 2088315ed1
5 changed files with 126 additions and 8 deletions
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getFunctionResolvedCallWithAs
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
@@ -23,6 +26,7 @@ import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.*
import java.rmi.UnexpectedException
import java.util.*
import kotlin.comparisons.compareBy
abstract class BlockCodegen(val state: TranslationState, val variableManager: VariableManager, val codeBuilder: LLVMBuilder) {
@@ -402,20 +406,28 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
val names = parseArgList(expr, scopeDepth)
var names = parseArgList(expr, scopeDepth)
var name = expr.firstChild.firstChild.text
val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression)
val resolvedCall = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)
val functionDescriptor = expr.getFunctionResolvedCallWithAssert(state.bindingContext).candidateDescriptor
val arguments = resolvedCall!!.valueArguments.toSortedMap(compareBy { it.index }).values
val external = state.externalFunctions.containsKey(name)
val function = "$name${if (names.size > 0 && !external) LLVMType.mangleFunctionArguments(names) else ""}"
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
val function = "$name${if (!external) LLVMType.mangleFunctionTypes(functionArguments) else ""}"
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) {
val descriptor = state.functions[function] ?: state.externalFunctions[function] ?: return null
names = parseNamedValueArguments(arguments, descriptor.defaultValues, scopeDepth)
val args = loadArgsIfRequired(names, descriptor.args)
return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args)
}
if (state.classes.containsKey(name) || classScope?.structName == name) {
val descriptor = state.classes[name] ?: classScope ?: return null
val detectedConstructor = LLVMType.mangleFunctionArguments(names)
val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments)
val args = loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
}
@@ -545,21 +557,36 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return result
}
private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): ArrayList<LLVMSingleValue> {
private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): List<LLVMSingleValue> {
val args = expr.getValueArgumentsInParentheses()
return parseValueArguments(args, scopeDepth)
}
private fun parseValueArguments(args: List<ValueArgument>, scopeDepth: Int): ArrayList<LLVMSingleValue> {
private fun parseValueArguments(args: List<ValueArgument>, scopeDepth: Int): List<LLVMSingleValue> {
val result = ArrayList<LLVMSingleValue>()
for (arg in args) {
val currentExpression = evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue
result.add(currentExpression)
result.add(parseOneValueArgument(arg, scopeDepth))
}
return result
}
fun parseOneValueArgument(arg: ValueArgument, scopeDepth: Int): LLVMSingleValue {
return evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue
}
private fun parseNamedValueArguments(args: MutableCollection<ResolvedValueArgument>, defaultValues: List<KtExpression?>, scopeDepth: Int): List<LLVMSingleValue> =
args.mapIndexed(fun(i: Int, value: ResolvedValueArgument): LLVMSingleValue {
return when (value) {
is DefaultValueArgument -> evaluateExpression(defaultValues[i], scopeDepth)!!
else -> {
val expr = ((value as ExpressionValueArgument).valueArgument as KtValueArgument).getArgumentExpression()!!
evaluateExpression(expr, scopeDepth)!!
}
}
}).toList()
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable? {
val operator = expr.operationToken
if (operator == KtTokens.ELVIS) {
@@ -1,9 +1,15 @@
package org.kotlinnative.translator
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.LLVMFunctionType
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
@@ -26,6 +32,7 @@ class FunctionCodegen(state: TranslationState,
val fullName: String
get() = functionNamePrefix + name
val external: Boolean
val defaultValues: List<KtExpression?>
init {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
@@ -50,6 +57,19 @@ class FunctionCodegen(state: TranslationState,
state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType)
}
defaultValues = mutableListOf()
val valueParameters = descriptor.valueParameters
for (index in valueParameters.indices) {
val parameterDescriptor = valueParameters[index]
if (parameterDescriptor.declaresDefaultValue()) {
val initializer = (parameterDescriptor.source as KotlinSourceElement).psi
val defaultValue = (initializer as KtParameter).defaultValue
defaultValues.add(defaultValue!!)
} else {
defaultValues.add(null)
}
}
val retType = returnType!!.type
when (retType) {
is LLVMReferenceType -> {
@@ -39,7 +39,10 @@ abstract class LLVMType() : Cloneable {
companion object {
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
"_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}"
mangleFunctionTypes(names.map { it.type!! })
fun mangleFunctionTypes(names: List<LLVMType>) =
if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.mangle() })}" else ""
}
}
@@ -0,0 +1,9 @@
function_default_arguments_1_mixed() == 76
function_default_arguments_1_last_missed_Int(23) == 977
function_default_arguments_1_last_present_Int(25) == 54
function_default_arguments_1_position_third_only_Int(19) == 716
function_default_arguments_1_position_all_reverse_Int(17) == 126
function_default_arguments_1_position_all_right_order_Int(17) == 126
function_default_arguments_1_position_all_default_Int(27) ==8268
function_default_arguments_1_all_position() == 194
function_default_arguments_1_add_class_arg() == 314
@@ -0,0 +1,59 @@
class function_default_arguments_1_argClass(val classArgument: Int)
fun function_default_arguments_1_add(x: Int, t: function_default_arguments_1_argClass = function_default_arguments_1_argClass(124), y: Int = 53, z: Int = 777): Int {
return x + y
}
fun function_default_arguments_1_add_class(x: Int, t: function_default_arguments_1_argClass = function_default_arguments_1_argClass(124), y: Int = 53, z: Int = 777): Int {
return x + t.classArgument
}
fun function_default_arguments_1_add_class_arg(): Int {
return function_default_arguments_1_add_class(190)
}
fun function_default_arguments_1_mixed(): Int {
return function_default_arguments_1_add(23, t = function_default_arguments_1_argClass(29), z = 8)
}
fun function_default_arguments_1_last_missed_fun(z: Int, u: Int = 954): Int {
return z + u
}
fun function_default_arguments_1_last_missed(x: Int): Int {
return function_default_arguments_1_last_missed_fun(x)
}
fun function_default_arguments_1_last_present(x: Int): Int {
return function_default_arguments_1_last_missed_fun(x, 29)
}
fun function_default_arguments_1_position_fun(first: Int, second: Int = 324
, third: Int = 2531): Int {
return first + 2 * second + 3 * third
}
fun function_default_arguments_1_position_third_only(x: Int): Int {
return function_default_arguments_1_position_fun(11, third = x)
}
fun function_default_arguments_1_position_all_reverse(x: Int): Int {
return function_default_arguments_1_position_fun(11, third = x, second = 32)
}
fun function_default_arguments_1_position_all_right_order(x: Int): Int {
return function_default_arguments_1_position_fun(11, second = 32, third = x)
}
fun function_default_arguments_1_position_all_default(x: Int): Int {
return function_default_arguments_1_position_fun(x)
}
fun function_default_arguments_1_all_position_fun(first: Int = 31, second: Int = 32
, third: Int = 33): Int {
return first + 2 * second + 3 * third
}
fun function_default_arguments_1_all_position(): Int {
return function_default_arguments_1_all_position_fun()
}