in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/functions/handlers/collectionFunctions/MapFunctionHandlers.kt [120:220]
override fun doFunction(
arguments: Arguments,
editor: VimEditor,
context: ExecutionContext,
vimContext: VimLContext
): VimDataType {
val expr1 = arguments[0]
val expr2 = arguments[1]
if (expr1 !is VimList && expr1 !is VimDictionary && expr1 !is VimString && expr1 !is VimBlob) {
throw exExceptionMessage("E1250", "${name}()")
}
val funcref = expr2 as? VimFuncref
val expression = if (funcref != null) {
null
} else if (expr2 is VimFloat) {
// Vim doesn't normally convert Float to String
SimpleExpression(expr2)
} else {
val string = expr2.toVimString()
if (string.value.isEmpty()) {
throw exExceptionMessage("E15", string.value)
}
injector.vimscriptParser.parseExpression(string.value)
}
if (funcref == null && expression == null) {
throw exExceptionMessage("E1250", "${name}()")
}
when (expr1) {
is VimList -> {
val source = getSource(expr1)
val target = getTarget(expr1)
if (target.isLocked) {
throw exExceptionMessage("E741", "${name}() argument")
}
var writeIndex = 0
for ((index, value) in source.values.withIndex()) {
val result = processItem(VimInt(index), value, funcref, expression, editor, context, vimContext)
if (result != null) {
if (target.values.size > index && target.values[index].isLocked) {
throw exExceptionMessage("E741", "${name}() argument")
}
target.values[writeIndex++] = result
}
else {
// TODO: Validate index values
target.values.removeAt(writeIndex)
}
}
return target
}
is VimDictionary -> {
val source = getSource(expr1)
val target = getTarget(expr1)
if (target.isLocked) {
throw exExceptionMessage("E741", "${name}() argument")
}
for ((k, v) in source.dictionary.entries) {
val result = processItem(k, v, funcref, expression, editor, context, vimContext)
if (result != null) {
if (target.dictionary[k]?.isLocked == true) {
throw exExceptionMessage("E741", "${name}() argument")
}
target.dictionary[k] = result
}
else {
target.dictionary.remove(k)
}
}
return target
}
is VimString -> {
val string = buildString {
// We don't need to use getSource here - we'll never modify expr1
for ((index, ch) in expr1.value.withIndex()) {
val result =
processItem(VimInt(index), VimString(ch.toString()), funcref, expression, editor, context, vimContext)
if (result != null) {
if (result !is VimString) {
throw exExceptionMessage("E928")
}
append(result.value)
}
}
}
return VimString(string)
}
is VimBlob -> TODO()
else -> throw exExceptionMessage("E1250", "${name}()")
}
}