translator: add support range operator (..)
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
/** An iterator over a sequence of values of type `Byte`. */
|
||||||
|
public abstract class ByteIterator {
|
||||||
|
final fun next() = nextByte()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextByte(): Byte
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Char`. */
|
||||||
|
public abstract class CharIterator {
|
||||||
|
final fun next() = nextChar()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextChar(): Char
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Short`. */
|
||||||
|
public abstract class ShortIterator {
|
||||||
|
final fun next() = nextShort()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextShort(): Short
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Int`. */
|
||||||
|
class IntIterator(first: Int, last: Int, val step: Int) {
|
||||||
|
private var next = first
|
||||||
|
private val finalElement = last
|
||||||
|
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
|
||||||
|
|
||||||
|
fun hasNext(): Boolean = hasNext
|
||||||
|
|
||||||
|
fun nextInt(): Int {
|
||||||
|
val value = next
|
||||||
|
if (value == finalElement) {
|
||||||
|
hasNext = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next += step
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Long`. */
|
||||||
|
public abstract class LongIterator {
|
||||||
|
final fun next() = nextLong()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextLong(): Long
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Float`. */
|
||||||
|
public abstract class FloatIterator {
|
||||||
|
final fun next() = nextFloat()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextFloat(): Float
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Double`. */
|
||||||
|
public abstract class DoubleIterator {
|
||||||
|
final fun next() = nextDouble()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextDouble(): Double
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterator over a sequence of values of type `Boolean`. */
|
||||||
|
public abstract class BooleanIterator {
|
||||||
|
final fun next() = nextBoolean()
|
||||||
|
|
||||||
|
/** Returns the next value in the sequence without boxing. */
|
||||||
|
public abstract fun nextBoolean(): Boolean
|
||||||
|
|
||||||
|
public abstract fun hasNext(): Boolean
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* A progression of values of type `Int`.
|
||||||
|
*/
|
||||||
|
public open class IntProgression
|
||||||
|
constructor
|
||||||
|
(
|
||||||
|
start: Int,
|
||||||
|
endInclusive: Int,
|
||||||
|
val step: Int
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
if (step == 0) {
|
||||||
|
println("Step must be non-zero.")
|
||||||
|
assert(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first element in the progression.
|
||||||
|
*/
|
||||||
|
public val first: Int = start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last element in the progression.
|
||||||
|
*/
|
||||||
|
public val last: Int = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toInt()
|
||||||
|
|
||||||
|
|
||||||
|
fun iterator(): IntIterator = IntIterator(first, last, step)
|
||||||
|
|
||||||
|
/** Checks if the progression is empty. */
|
||||||
|
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
|
||||||
|
|
||||||
|
//[TODO] equals
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * (31 * first + last) + step)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates IntProgression within the specified bounds of a closed range.
|
||||||
|
|
||||||
|
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
|
||||||
|
* In order to go backwards the [step] must be negative.
|
||||||
|
*/
|
||||||
|
public fun fromClosedRange(rangeStart: Int, rangeEnd: Int, step: Int): IntProgression = IntProgression(rangeStart, rangeEnd, step)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
public class IntRange(val start: Int, val endInclusive: Int) {
|
||||||
|
val progression = IntProgression(start, endInclusive, 1)
|
||||||
|
val first: Int
|
||||||
|
val last: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.first = progression.first
|
||||||
|
this.last = progression.last
|
||||||
|
}
|
||||||
|
|
||||||
|
fun contains(value: Int): Boolean = first <= value && value <= last
|
||||||
|
|
||||||
|
fun isEmpty(): Boolean = first > last
|
||||||
|
|
||||||
|
fun iterator(): IntIterator = progression.iterator()
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * first + last)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// a mod b (in arithmetical sense)
|
||||||
|
private fun mod(a: Int, b: Int): Int {
|
||||||
|
val mod = a % b
|
||||||
|
return if (mod >= 0) mod else mod + b
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mod(a: Long, b: Long): Long {
|
||||||
|
val mod = a % b
|
||||||
|
return if (mod >= 0) mod else mod + b
|
||||||
|
}
|
||||||
|
|
||||||
|
// (a - b) mod c
|
||||||
|
private fun differenceModulo(a: Int, b: Int, c: Int): Int {
|
||||||
|
return mod(mod(a, c) - mod(b, c), c)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun differenceModulo(a: Long, b: Long, c: Long): Long {
|
||||||
|
return mod(mod(a, c) - mod(b, c), c)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
|
||||||
|
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
|
||||||
|
* [step].
|
||||||
|
*
|
||||||
|
* No validation on passed parameters is performed. The given parameters should satisfy the condition: either
|
||||||
|
* `step > 0` and `start >= end`, or `step < 0` and`start >= end`.
|
||||||
|
* @param start first element of the progression
|
||||||
|
* @param end ending bound for the progression
|
||||||
|
* @param step increment, or difference of successive elements in the progression
|
||||||
|
* @return the final element of the progression
|
||||||
|
* @suppress
|
||||||
|
*/
|
||||||
|
fun getProgressionLastElement(start: Int, end: Int, step: Int): Int {
|
||||||
|
if (step > 0) {
|
||||||
|
return end - differenceModulo(end, start, step)
|
||||||
|
} else if (step < 0) {
|
||||||
|
return end + differenceModulo(start, end, -step)
|
||||||
|
} else {
|
||||||
|
println("Step is zero.")
|
||||||
|
assert(false)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
|
||||||
|
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
|
||||||
|
* [step].
|
||||||
|
*
|
||||||
|
* No validation on passed parameters is performed. The given parameters should satisfy the condition: either
|
||||||
|
* `step > 0` and `start >= end`, or `step < 0` and`start >= end`.
|
||||||
|
* @param start first element of the progression
|
||||||
|
* @param end ending bound for the progression
|
||||||
|
* @param step increment, or difference of successive elements in the progression
|
||||||
|
* @return the final element of the progression
|
||||||
|
* @suppress
|
||||||
|
*/
|
||||||
|
internal fun getProgressionLastElement(start: Long, end: Long, step: Long): Long {
|
||||||
|
if (step > 0) {
|
||||||
|
return end - differenceModulo(end, start, step)
|
||||||
|
} else if (step < 0) {
|
||||||
|
return end + differenceModulo(start, end, -step)
|
||||||
|
} else {
|
||||||
|
println("Step is zero.")
|
||||||
|
assert(false)
|
||||||
|
return -1L
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -785,6 +785,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
codeBuilder.storeVariable(firstOp, resultOp)
|
codeBuilder.storeVariable(firstOp, resultOp)
|
||||||
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
|
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
|
||||||
}
|
}
|
||||||
|
".." -> {
|
||||||
|
val descriptor = state.classes["IntRange"]
|
||||||
|
val arguments = listOf(firstOp, secondNativeOp)
|
||||||
|
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type!! })
|
||||||
|
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments)
|
||||||
|
return LLVMExpression(result!!.type!!, "load ${descriptor.type}** $result, align ${descriptor.type.align}", pointer = 1)
|
||||||
|
}
|
||||||
else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})")
|
else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -863,7 +870,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
}
|
}
|
||||||
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp)
|
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp)
|
||||||
}
|
}
|
||||||
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
|
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType, pointer = llvmExpression.pointer)
|
||||||
codeBuilder.addAssignment(resultOp, llvmExpression)
|
codeBuilder.addAssignment(resultOp, llvmExpression)
|
||||||
return resultOp
|
return resultOp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.kotlinnative.translator.llvm
|
|||||||
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
|
|
||||||
class LLVMExpression(val variableType: LLVMType, val llvmCode: String) : LLVMNode() {
|
class LLVMExpression(val variableType: LLVMType, val llvmCode: String, val pointer: Int = 0) : LLVMNode() {
|
||||||
|
|
||||||
override fun toString(): String = llvmCode
|
override fun toString(): String = llvmCode
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user