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)
|
||||
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})")
|
||||
}
|
||||
}
|
||||
@@ -863,7 +870,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
}
|
||||
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp)
|
||||
}
|
||||
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
|
||||
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType, pointer = llvmExpression.pointer)
|
||||
codeBuilder.addAssignment(resultOp, llvmExpression)
|
||||
return resultOp
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.kotlinnative.translator.llvm
|
||||
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user