diff --git a/experiments/MemLayout/.idea/vcs.xml b/experiments/MemLayout/.idea/vcs.xml new file mode 100644 index 00000000000..b2bdec2d71b --- /dev/null +++ b/experiments/MemLayout/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/experiments/MemLayout/.idea/workspace.xml b/experiments/MemLayout/.idea/workspace.xml new file mode 100644 index 00000000000..cce7a8cb22f --- /dev/null +++ b/experiments/MemLayout/.idea/workspace.xml @@ -0,0 +1,747 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1472818752311 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/experiments/translator/README.md b/experiments/translator/README.md index c18661729e9..5778ef83e0e 100644 --- a/experiments/translator/README.md +++ b/experiments/translator/README.md @@ -28,7 +28,7 @@ Assembled the translator can be found in the following folder $ java -jar $(PATH_TO_TRANSLATOR_JAR) -I $(PATH_TO_KOTLIB) $(KOTLIN_SOURCES) where - $(PATH_TO_TRANSLATOR_JAR) - path to jar, which you got in building step, by default it `build/libs/translator-1.0.jar` - - $(PATH_TO_KOTLIB) - path to standart kotlin lib, by default it `../kotstd/kt` + - $(PATH_TO_KOTLIB) - path to standard kotlin lib, by default it `./kotstd/include` - $(KOTLIN_SOURCES) - the different files that you want to compile ### Optional arguments diff --git a/experiments/translator/kotstd/Makefile b/experiments/translator/kotstd/Makefile new file mode 100644 index 00000000000..fdd6cf55107 --- /dev/null +++ b/experiments/translator/kotstd/Makefile @@ -0,0 +1,49 @@ + +BUILD_DIR=$(PWD)/build +INCLUDE_DIR=$(PWD)/include +LIB_ARM_DIR=$(PWD)/lib/arm +LIB_X86_DIR=$(PWD)/lib/x86 +LIBC=$(PWD)/libc + +KT=$(PWD)/../translator/build/libs/translator-1.0.jar +LLINK=llvm-link-3.6 +CC=clang-3.6 + +CCFLAGS_ARM=-g -S -Wall -m32 -emit-llvm -nostdlib -ffreestanding -march=armv7-m -mthumb -flto -O0 -target arm-none-eabi -DARM +CCFLAGS=-g -O0 -S -Wall -emit-llvm -nostdlib -ffreestanding +CCFLAGS_DEBUG=-g -O0 -S -Wall -emit-llvm -nostdlib -ffreestanding -DDBG +LLINK_FLAGS=-S + +KT_ALL_DEPS=java -jar $(KT) +LLINK_ALL_DEPS=$(LLINK) $(LLINK_FLAGS) $(filter %.ll,$^) > $@ + +all: memory $(BUILD_DIR) $(BUILD_DIR)/stdlib_arm.ll $(BUILD_DIR)/stdlib_x86.ll +debug: memory_debug $(BUILD_DIR) $(BUILD_DIR)/stdlib_arm.ll $(BUILD_DIR)/stdlib_x86.ll + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(BUILD_DIR)/stdlib_x86.ll: $(LIB_X86_DIR)/*.ll + $(LLINK_ALL_DEPS) + +$(BUILD_DIR)/stdlib_arm.ll: $(LIB_ARM_DIR)/*.ll + $(LLINK_ALL_DEPS) + +$(BUILD_DIR)/classes_x86.ll: $(INCLUDE_DIR)/*.kt + $(KT_ALL_DEPS) -o $@ $(filter %.kt,$^) + +$(BUILD_DIR)/classes_arm.ll: $(INCLUDE_DIR)/*.kt + $(KT_ALL_DEPS) --arm -o $@ $(filter %.kt,$^) + +memory: + $(CC) $(CCFLAGS) $(LIBC)/memory.c -o $(LIB_X86_DIR)/memory.ll + $(CC) $(CCFLAGS_ARM) $(LIBC)/memory.c -o $(LIB_ARM_DIR)/memory.ll + +memory_debug: + $(CC) $(CCFLAGS_DEBUG) $(LIBC)/memory.c -o $(LIB_X86_DIR)/memory.ll + +clean: + rm -rf $(BUILD_DIR) + +.PHONY: all clean + diff --git a/experiments/translator/kotstd/include/Assert.kt b/experiments/translator/kotstd/include/Assert.kt new file mode 100644 index 00000000000..fc253e0f13e --- /dev/null +++ b/experiments/translator/kotstd/include/Assert.kt @@ -0,0 +1,8 @@ +package kotlin + +external fun assert_c(value: Boolean) + +fun assert(value: Boolean) { + println(value) + assert_c(value) +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/BooleanArray.kt b/experiments/translator/kotstd/include/BooleanArray.kt new file mode 100644 index 00000000000..7df7eb81e46 --- /dev/null +++ b/experiments/translator/kotstd/include/BooleanArray.kt @@ -0,0 +1,121 @@ +package kotlin + +external fun kotlinclib_boolean_size(): Int + +class BooleanArray(var size: Int) { + val data: Int + + /** Returns the number of elements in the array. */ + //size: Int + + init { + this.data = malloc_array(kotlinclib_boolean_size() * this.size) + var index = 0 + while (index < this.size) { + set(index, false) + index = index + 1 + } + } + + /** Returns the array element at the given [index]. This method can be called using the index operator. */ + operator fun get(index: Int): Boolean { + val res = kotlinclib_get_byte(this.data, index) == 1.toByte() + return res + } + + + /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ + operator fun set(index: Int, value: Boolean) { + if (value == true) { + kotlinclib_set_byte(this.data, index, 1.toByte()) + } else { + kotlinclib_set_byte(this.data, index, 0.toByte()) + } + } + + + fun clone(): BooleanArray { + val newInstance = BooleanArray(this.size) + var index = 0 + while (index < this.size) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance + } +} + +fun BooleanArray.print() { + var index = 0 + print('[') + while (index < size) { + print(get(index)) + index++ + if (index < size){ + print(';') + print(' ') + } + } + print(']') +} + +fun BooleanArray.println() { + this.print() + //println() +} + + +fun BooleanArray.copyOf(newSize: Int): BooleanArray { + val newInstance = BooleanArray(newSize) + var index = 0 + val end = if (newSize > this.size) this.size else newSize + while (index < end) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + while (index < newSize) { + newInstance.set(index, false) + index = index + 1 + } + + return newInstance +} + +fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray { + val newInstance = BooleanArray(toIndex - fromIndex) + var index = fromIndex + while (index < toIndex) { + val value = this.get(index) + newInstance.set(index - fromIndex, value) + index = index + 1 + } + + return newInstance +} + +operator fun BooleanArray.plus(element: Boolean): BooleanArray { + val index = size + val result = this.copyOf(index + 1) + result[index] = element + return result +} + +operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { + val thisSize = size + val arraySize = elements.size + val resultSize = thisSize + arraySize + val newInstance = this.copyOf(resultSize) + var index = thisSize + + while (index < resultSize) { + val value = elements.get(index - thisSize) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/ByteArray.kt b/experiments/translator/kotstd/include/ByteArray.kt new file mode 100644 index 00000000000..8952a07eb1f --- /dev/null +++ b/experiments/translator/kotstd/include/ByteArray.kt @@ -0,0 +1,121 @@ +package kotlin + +external fun malloc_array(size: Int): Int +external fun kotlinclib_get_byte(src: Int, index: Int): Byte +external fun kotlinclib_set_byte(src: Int, index: Int, value: Byte) +external fun kotlinclib_byte_size(): Int + + +class ByteArray(var size: Int) { + val data: Int + + /** Returns the number of elements in the array. */ + //size: Int + + init { + this.data = malloc_array(kotlinclib_byte_size() * this.size) + var index = 0 + + while (index < this.size) { + set(index, 0) + index = index + 1 + } + } + + /** Returns the array element at the given [index]. This method can be called using the index operator. */ + operator fun get(index: Int): Byte { + return kotlinclib_get_byte(this.data, index) + } + + + /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ + operator fun set(index: Int, value: Byte) { + kotlinclib_set_byte(this.data, index, value) + } + + + fun clone(): ByteArray { + val newInstance = ByteArray(this.size) + var index = 0 + while (index < this.size) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance + } + +} + +fun ByteArray.print() { + var index = 0 + print('[') + while (index < size) { + print(get(index)) + index++ + if (index < size){ + print(';') + print(' ') + } + } + print(']') +} + +fun ByteArray.println() { + this.print() + //println() +} + +fun ByteArray.copyOf(newSize: Int): ByteArray { + val newInstance = ByteArray(newSize) + var index = 0 + val end = if (newSize > this.size) this.size else newSize + while (index < end) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + while (index < newSize) { + newInstance.set(index, 0) + index = index + 1 + } + + return newInstance +} + +fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray { + val newInstance = ByteArray(toIndex - fromIndex) + var index = fromIndex + while (index < toIndex) { + val value = this.get(index) + newInstance.set(index - fromIndex, value) + index = index + 1 + } + + return newInstance +} + +operator fun ByteArray.plus(element: Byte): ByteArray { + val index = size + val result = this.copyOf(index + 1) + result[index] = element + return result +} + +operator fun ByteArray.plus(elements: ByteArray): ByteArray { + val thisSize = size + val arraySize = elements.size + val resultSize = thisSize + arraySize + val newInstance = this.copyOf(resultSize) + var index = thisSize + + while (index < resultSize) { + val value = elements.get(index - thisSize) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/CodedInputStream.kt b/experiments/translator/kotstd/include/CodedInputStream.kt new file mode 100644 index 00000000000..bb5b6e47cae --- /dev/null +++ b/experiments/translator/kotstd/include/CodedInputStream.kt @@ -0,0 +1,216 @@ +/** + * Created by Dmitry Savvinov on 7/6/16. + * + * Hides details of work with Protobuf encoding + * + * Note that CodedInputStream reads protobuf-defined types from stream (such as int32, sint32, etc), + * while CodedOutputStream has methods for writing Kotlin-types (such as Boolean, Int, Long, Short, etc) + * + */ + +// TODO: refactor correctness checks into readTag +class CodedInputStream(val buffer: ByteArray) { + val inputStream: KotlinInputStream + init { + inputStream = KotlinInputStream(buffer) + } + + fun mark() { + inputStream.mark() + } + + fun reset() { + inputStream.reset() + } + + fun readInt32(expectedFieldNumber: Int): Int { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + val actualFieldNumber = WireFormat.getTagFieldNumber(tag) + val actualWireType = WireFormat.getTagWireType(tag) + checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType) + return readInt32NoTag() + } + + // Note that unsigned integer types are stored as their signed counterparts with top bit + // simply stored in the sign bit - similar to Java's protobuf implementation. Hence, all + // methods reading unsigned ints simply redirect call to corresponding signed-reading method + fun readUInt32(expectedFieldNumber: Int): Int { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readUInt32NoTag() + } + + fun readUInt32NoTag(): Int { + return readInt32NoTag() + } + + fun readInt64(expectedFieldNumber: Int): Long { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readInt64NoTag() + } + + // See note on unsigned integers implementations above + fun readUInt64(expectedFieldNumber: Int): Long { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readUInt64NoTag() + } + + fun readUInt64NoTag(): Long { + return readInt64NoTag() + } + + fun readBool(expectedFieldNumber: Int): Boolean { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readBoolNoTag() + } + + fun readBoolNoTag(): Boolean { + val readValue = readInt32NoTag() + val boolValue = when (readValue) { + 0 -> false + 1 -> true + else -> false + } + return boolValue + } + + // Reading enums is like reading one int32 number. Caller is responsible for converting this ordinal to enum-object + fun readEnum(expectedFieldNumber: Int): Int { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readEnumNoTag() + } + + fun readEnumNoTag(): Int { + return readUInt32NoTag() + } + + fun readSInt32(expectedFieldNumber: Int): Int { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readSInt32NoTag() + } + + fun readSInt32NoTag(): Int { + return readZigZag32NoTag() + } + + fun readSInt64(expectedFieldNumber: Int): Long { + val tag = readTag(expectedFieldNumber, WireType.VARINT) + return readSInt64NoTag() + } + + fun readSInt64NoTag(): Long { + return readZigZag64NoTag() + } + fun readBytes(expectedFieldNumber: Int): ByteArray { + val tag = readTag(expectedFieldNumber, WireType.LENGTH_DELIMITED) + return readBytesNoTag() + } + + fun readBytesNoTag(): ByteArray { + val length = readInt32NoTag() + return readRawBytes(length) + } + + /** ============ Utility methods ================== + * They are left non-private for cases when one wants to implement her/his own protocol format. + * Then she/he can re-use low-level methods for operating with raw values, that are not annotated with Protobuf tags. + */ + + fun checkFieldCorrectness( + expectedFieldNumber: Int, + actualFieldNumber: Int, + expectedWireType: WireType, + actualWireType: WireType) { + if (expectedFieldNumber != actualFieldNumber) { + return + } + + if (expectedWireType.id != actualWireType.id) { + return + } + } + + fun readRawBytes(count: Int): ByteArray { + val ba = ByteArray(count) + var i = 0 + while (i < count) { + ba[i] = inputStream.read().toByte() + i++ + } + return ba + } + + // reads tag. Note that it returns 0 for the end of message! + fun readTag(expectedFieldNumber: Int, expectedWireType: WireType): Int { + if (isAtEnd()) { + return 0 // we can safely return 0 as sign of end of message, because 0-tags are illegal + } + val tag = readInt32NoTag() + if (tag == 0) { // if we somehow had read 0-tag, then message is corrupted + return 0 + } + + val actualFieldNumber = WireFormat.getTagFieldNumber(tag) + val actualWireType = WireFormat.getTagWireType(tag) + checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, expectedWireType, actualWireType) + return tag + } + + // reads varint not larger than 32-bit integer according to protobuf varint-encoding + fun readInt32NoTag(): Int { + var done: Boolean = false + var result: Long = 0 + var step: Int = 0 + while (!done) { + val byte: Int = inputStream.read().toInt() + result = result or + ( + (byte and WireFormat.VARINT_INFO_BITS_MASK).toLong() + shl + (WireFormat.VARINT_INFO_BITS_COUNT * step) + ).toLong() + step++ + if ((byte and WireFormat.VARINT_UTIL_BIT_MASK) == 0) { + done = true + } + } + return result.toInt() + } + + // reads varint not larger than 64-bit integer according to protobuf varint-encoding + fun readInt64NoTag(): Long { + var done: Boolean = false + var result: Long = 0 + var step: Int = 0 + while (!done) { + val byte: Int = inputStream.read().toInt() + result = result or + ( + (byte and WireFormat.VARINT_INFO_BITS_MASK).toLong() + shl + (WireFormat.VARINT_INFO_BITS_COUNT * step) + ) + step++ + if ((byte and WireFormat.VARINT_UTIL_BIT_MASK) == 0 /* || byte == -1 ???? */) { + done = true + } + } + return result + } + + // reads zig-zag encoded integer not larger than 32-bit long + fun readZigZag32NoTag(): Int { + val value = readInt32NoTag() + return (value ushr 1) xor (-(value and 1)) // bit magic for decoding zig-zag number + } + + // reads zig-zag encoded integer not larger than 64-bit long + fun readZigZag64NoTag(): Long { + val value = readInt64NoTag() + return (value ushr 1) xor (-(value and 1L)) // bit magic for decoding zig-zag number + } + + // checks if at least one more byte can be read from underlying input stream + fun isAtEnd(): Boolean { + return inputStream.isAtEnd() + } +} diff --git a/experiments/translator/kotstd/include/CodedOutputStream.kt b/experiments/translator/kotstd/include/CodedOutputStream.kt new file mode 100644 index 00000000000..9c40747b99c --- /dev/null +++ b/experiments/translator/kotstd/include/CodedOutputStream.kt @@ -0,0 +1,167 @@ +/** + * Created by user on 7/6/16. + */ + +class CodedOutputStream(val buffer: ByteArray) { + val output = KotlinOutputStream(buffer) + + fun toByteArray(): ByteArray { + return buffer + } + + fun writeTag(fieldNumber: Int, type: WireType) { + val tag = (fieldNumber shl 3) or type.id + writeRawVarint32(tag) + } + + fun writeInt32(fieldNumber: Int, value: Int) { + writeTag(fieldNumber, WireType.VARINT) + writeInt32NoTag(value) + } + + fun writeInt32NoTag(value: Int) { + if (value < 0) { // sign-extend negative values + writeRawVarint64(value.toLong()) + return + } + writeRawVarint32(value) + } + + // Note that unsigned integer types are stored as their signed counterparts with top bit + // simply stored in the sign bit - similar to Java's protobuf implementation. Hence, all + // methods, writing unsigned ints simply redirect call to corresponding signed-writing method + fun writeUInt32(fieldNumber: Int, value: Int) { + writeTag(fieldNumber, WireType.VARINT) + writeUInt32NoTag(value) + } + + fun writeUInt32NoTag(value: Int) { + writeRawVarint32(value) + } + + fun writeInt64(fieldNumber: Int, value: Long) { + writeTag(fieldNumber, WireType.VARINT) + writeInt64NoTag(value) + } + + fun writeInt64NoTag(value: Long) { + writeRawVarint64(value) + } + + // See notes on unsigned integers implementation above + fun writeUInt64(fieldNumber: Int, value: Long) { + writeTag(fieldNumber, WireType.VARINT) + writeUInt64NoTag(value) + } + + fun writeUInt64NoTag(value: Long) { + writeRawVarint64(value) + } + + fun writeBool(fieldNumber: Int, value: Boolean) { + writeTag(fieldNumber, WireType.VARINT) + writeBoolNoTag(value) + } + + fun writeBoolNoTag(value: Boolean) { + writeRawVarint32(if (value) 1 else 0) + } + + // Writing enums is like writing one int32 number. Caller is responsible for converting enum-object to ordinal + fun writeEnum(fieldNumber: Int, value: Int) { + writeTag(fieldNumber, WireType.VARINT) + writeEnumNoTag(value) + } + + fun writeEnumNoTag(value: Int) { + writeRawVarint32(value) + } + + fun writeSInt32(fieldNumber: Int, value: Int) { + writeTag(fieldNumber, WireType.VARINT) + writeSInt32NoTag(value) + } + + fun writeSInt32NoTag(value: Int) { + writeUInt32NoTag((value shl 1) xor (value shr 31)) + } + + fun writeSInt64(fieldNumber: Int, value: Long) { + writeTag(fieldNumber, WireType.VARINT) + writeSInt64NoTag(value) + } + + fun writeSInt64NoTag(value: Long) { + writeUInt64NoTag((value shl 1) xor (value shr 63)) + } + + fun writeBytes(fieldNumber: Int, value: ByteArray) { + if (value.size == 0) { + return + } + writeTag(fieldNumber, WireType.LENGTH_DELIMITED) + writeBytesNoTag(value) + } + + fun writeBytesNoTag(value: ByteArray) { + writeRawVarint32(value.size) + output.write(value) + } + + /** ============ Utility methods ================== + * They are left non-private for cases when one wants to implement her/his own protocol format. + * Then she/he can re-use low-level methods for operating with raw values, that are not annotated with Protobuf tags. + */ + + fun writeRawVarint32(value: Int) { + var curValue: Int = value + + // we have at most 32 information bits. With overhead of 1 bit per 7 bits we need at most 5 bytes for encoding + val res = ByteArray(5) + + var resSize = 0 + do { + // encode current 7 bits + var curByte = (curValue and WireFormat.VARINT_INFO_BITS_MASK) + + // discard encoded bits. Note that unsigned shift is needed for cases with negative numbers + curValue = curValue ushr WireFormat.VARINT_INFO_BITS_COUNT + + // check if there will be next byte in encoding and set util bit if needed + if (curValue != 0) { + curByte = curByte or WireFormat.VARINT_UTIL_BIT_MASK + } + + res[resSize] = curByte.toByte() + resSize++ + } while (curValue != 0) + output.write(res, 0, resSize) + } + + fun writeRawVarint64(value: Long) { + var curValue: Long = value + + // we have at most 64 information bits. With overhead of 1 bit per 7 bits we need at most 10 bytes for encoding + val res = ByteArray(10) + + var resSize = 0 + do { + // encode current 7 bits + var curByte = (curValue and WireFormat.VARINT_INFO_BITS_MASK.toLong()) + + // discard encoded bits. Note that unsigned shift is needed for cases with negative numbers + curValue = curValue ushr WireFormat.VARINT_INFO_BITS_COUNT + + // check if there will be next byte and set util bit if needed + if (curValue != 0L) { + curByte = curByte or WireFormat.VARINT_UTIL_BIT_MASK.toLong() + } + + res[resSize] = curByte.toByte() + resSize++ + } while(curValue != 0L) + output.write(res, 0, resSize) + } + + +} diff --git a/experiments/translator/kotstd/include/Console.kt b/experiments/translator/kotstd/include/Console.kt new file mode 100644 index 00000000000..c4077be14d4 --- /dev/null +++ b/experiments/translator/kotstd/include/Console.kt @@ -0,0 +1,171 @@ +package kotlin + +/* +* Library for console interaction +*/ + +external fun kotlinclib_print_int(message: Int) +external fun kotlinclib_print_long(message: Long) +external fun kotlinclib_print_byte(message: Byte) +external fun kotlinclib_print_short(message: Short) +external fun kotlinclib_print_char(message: Char) +external fun kotlinclib_print_boolean(message: Boolean) +external fun kotlinclib_print_float(message: Float) +external fun kotlinclib_print_double(message: Double) +external fun kotlinclib_print_string(message: String) +external fun kotlinclib_println_int(message: Int) +external fun kotlinclib_println_long(message: Long) +external fun kotlinclib_println_byte(message: Byte) +external fun kotlinclib_println_short(message: Short) +external fun kotlinclib_println_char(message: Char) +external fun kotlinclib_println_boolean(message: Boolean) +external fun kotlinclib_println_float(message: Float) +external fun kotlinclib_println_double(message: Double) +external fun kotlinclib_println_string(message: String) +external fun kotlinclib_println() + +/** Prints the given message to the standard output stream. */ +fun print(message: Int) { + kotlinclib_print_int(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Long) { + kotlinclib_print_long(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Byte) { + kotlinclib_print_byte(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Short) { + kotlinclib_print_short(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Char) { + kotlinclib_print_char(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Boolean) { + kotlinclib_print_boolean(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Float) { + kotlinclib_print_float(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: Double) { + kotlinclib_print_double(message) +} + +/** Prints the given message to the standard output stream. */ +fun print(message: String) { + kotlinclib_print_string(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun print(message: ByteArray) { + message.print() +} + +/** Prints the given message and newline to the standard output stream. */ +fun print(message: BooleanArray) { + message.print() +} + +/** Prints the given message and newline to the standard output stream. */ +fun print(message: IntArray) { + message.print() +} + +/** Prints the given message and newline to the standard output stream. */ +fun print(message: LongArray) { + message.print() +} + +/** Prints the given message and newline to the standard output stream. */ +fun print(message: ShortArray) { + message.print() +} + + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Int) { + kotlinclib_println_int(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Long) { + kotlinclib_println_long(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Byte) { + kotlinclib_println_byte(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Short) { + kotlinclib_println_short(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Char) { + kotlinclib_println_char(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Boolean) { + kotlinclib_println_boolean(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Float) { + kotlinclib_println_float(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: Double) { + kotlinclib_println_double(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: String) { + kotlinclib_println_string(message) +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: ByteArray) { + message.println() +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: BooleanArray) { + message.println() +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: IntArray) { + message.println() +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: LongArray) { + message.println() +} + +/** Prints the given message and newline to the standard output stream. */ +fun println(message: ShortArray) { + message.println() +} + +/** Prints newline to the standard output stream. */ +fun println() { + kotlinclib_println() +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/IntArray.kt b/experiments/translator/kotstd/include/IntArray.kt new file mode 100644 index 00000000000..09767b162b9 --- /dev/null +++ b/experiments/translator/kotstd/include/IntArray.kt @@ -0,0 +1,195 @@ +package kotlin + +external fun kotlinclib_get_int(src: Int, index: Int): Int +external fun kotlinclib_set_int(src: Int, index: Int, value: Int) +external fun kotlinclib_int_size(): Int + + +class IntArray(var size: Int) { + val data: Int + + /** Returns the number of elements in the array. */ + //size: Int + + init { + this.data = malloc_array(kotlinclib_int_size() * this.size) + var index = 0 + while (index < this.size) { + set(index, 0) + index = index + 1 + } + } + + /** Returns the array element at the given [index]. This method can be called using the index operator. */ + operator fun get(index: Int): Int { + return kotlinclib_get_int(this.data, index) + } + + + /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ + operator fun set(index: Int, value: Int) { + kotlinclib_set_int(this.data, index, value) + } + + + fun clone(): IntArray { + val newInstance = IntArray(this.size) + var index = 0 + while (index < this.size) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance + } + +} + +fun IntArray.print() { + var index = 0 + print('[') + while (index < size) { + print(get(index)) + index++ + if (index < size) { + print(';') + print(' ') + } + } + print(']') +} + +fun IntArray.println() { + this.print() + //println() +} + +fun IntArray.copyOf(newSize: Int): IntArray { + val newInstance = IntArray(newSize) + var index = 0 + val end = if (newSize > this.size) this.size else newSize + while (index < end) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + while (index < newSize) { + newInstance.set(index, 0) + index = index + 1 + } + + return newInstance +} + +fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray { + val newInstance = IntArray(toIndex - fromIndex) + var index = fromIndex + while (index < toIndex) { + val value = this.get(index) + newInstance.set(index - fromIndex, value) + index = index + 1 + } + + return newInstance +} + +operator fun IntArray.plus(element: Int): IntArray { + val index = size + val result = this.copyOf(index + 1) + result[index] = element + return result +} + +operator fun IntArray.plus(elements: IntArray): IntArray { + val thisSize = size + val arraySize = elements.size + val resultSize = thisSize + arraySize + val newInstance = this.copyOf(resultSize) + var index = thisSize + + while (index < resultSize) { + val value = elements.get(index - thisSize) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance +} + +fun IntArray.max(from: Int = 0): Int { + var result = from + var i = from + while (i < size - 1) { + result = if (get(i) > get(result)) i else result + i++ + } + + return get(result) +} + +fun IntArray.min(from: Int = 0): Int { + var result = from + var i = from + while (i < size - 1) { + result = if (this.get(i) < this.get(result)) i else result + i++ + } + + return this.get(result) +} + +fun IntArray.sum(): Int { + var result = 0 + var i = 0 + while (i < size - 1) { + result += this.get(i) + i++ + } + + return result +} + +fun IntArray.sort(): IntArray { + val result = this.clone() + var i = 0 + while (i < size - 1) { + result[i] = this.max(i) + i++ + } + + return result +} + +fun IntArray.mean(): Int = + this.sum() / this.size + +fun IntArray.median(): Int = + this.sort()[this.size / 2] + +fun IntArray.filter(predicate: (Int) -> Boolean): IntArray { + var resultSize = 0 + var i = 0 + while (i < size - 1) { + if (predicate(get(i))) { + resultSize++ + } + + i++ + } + + val result = IntArray(resultSize) + var j = 0 + i = 0 + while (i < size - 1) { + if (predicate(get(i))) { + result[j] = get(i) + j++ + } + + i++ + } + + return result +} diff --git a/experiments/translator/kotstd/include/Iterators.kt b/experiments/translator/kotstd/include/Iterators.kt new file mode 100644 index 00000000000..836b06babe9 --- /dev/null +++ b/experiments/translator/kotstd/include/Iterators.kt @@ -0,0 +1,94 @@ +package kotlin.collections + +/** 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 + + final fun next() = nextInt () + + 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 +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/KotlinInputStream.kt b/experiments/translator/kotstd/include/KotlinInputStream.kt new file mode 100644 index 00000000000..ee2c40aa387 --- /dev/null +++ b/experiments/translator/kotstd/include/KotlinInputStream.kt @@ -0,0 +1,25 @@ +/** + * Created by user on 8/8/16. + */ + +class KotlinInputStream(val buffer: ByteArray) { + var pos = 0 + var mark_ = 0 + + fun read(): Byte { + pos += 1 + return buffer[pos - 1] + } + + fun isAtEnd(): Boolean { + return pos >= buffer.size + } + + fun mark() { + mark_ = pos + } + + fun reset() { + pos = mark_ + } +} diff --git a/experiments/translator/kotstd/include/KotlinOutputStream.kt b/experiments/translator/kotstd/include/KotlinOutputStream.kt new file mode 100644 index 00000000000..51f80aaf766 --- /dev/null +++ b/experiments/translator/kotstd/include/KotlinOutputStream.kt @@ -0,0 +1,20 @@ +/** + * Created by user on 8/8/16. + */ + +class KotlinOutputStream(val buffer: ByteArray) { + var pos = 0 + + fun write (data: ByteArray) { + write(data, 0, data.size) + } + + fun write (data: ByteArray, begin: Int, size: Int) { + var i = begin + while (i < begin + size) { + buffer[pos] = data[i] + pos += 1 + i++ + } + } +} diff --git a/experiments/translator/kotstd/include/LongArray.kt b/experiments/translator/kotstd/include/LongArray.kt new file mode 100644 index 00000000000..f8ae4fe7d03 --- /dev/null +++ b/experiments/translator/kotstd/include/LongArray.kt @@ -0,0 +1,118 @@ +package kotlin + +external fun kotlinclib_get_long(src: Int, index: Int): Long +external fun kotlinclib_set_long(src: Int, index: Int, value: Long) +external fun kotlinclib_long_size(): Int + + +class LongArray(var size: Int) { + val data: Int + + /** Returns the number of elements in the array. */ + //size: Int + + init { + this.data = malloc_array(kotlinclib_long_size() * this.size) + var index = 0 + while (index < this.size) { + set(index, 0) + index = index + 1 + } + } + + /** Returns the array element at the given [index]. This method can be called using the index operator. */ + operator fun get(index: Int): Long { + return kotlinclib_get_long(this.data, index) + } + + + /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ + operator fun set(index: Int, value: Long) { + kotlinclib_set_long(this.data, index, value) + } + + + fun clone(): LongArray { + val newInstance = LongArray(this.size) + var index = 0 + while (index < this.size) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance + } +} + +fun LongArray.print() { + var index = 0 + print('[') + while (index < size) { + print(get(index)) + index++ + if (index < size) { + print(';') + print(' ') + } + } + print(']') +} + +fun LongArray.println() { + this.print() + //println() +} + +fun LongArray.copyOf(newSize: Int): LongArray { + val newInstance = LongArray(newSize) + var index = 0 + val end = if (newSize > this.size) this.size else newSize + while (index < end) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + while (index < newSize) { + newInstance.set(index, 0) + index = index + 1 + } + + return newInstance +} + +fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray { + val newInstance = LongArray(toIndex - fromIndex) + var index = fromIndex + while (index < toIndex) { + val value = this.get(index) + newInstance.set(index - fromIndex, value) + index = index + 1 + } + + return newInstance +} + +operator fun LongArray.plus(element: Long): LongArray { + val index = size + val result = this.copyOf(index + 1) + result[index] = element + return result +} + +operator fun LongArray.plus(elements: LongArray): LongArray { + val thisSize = size + val arraySize = elements.size + val resultSize = thisSize + arraySize + val newInstance = this.copyOf(resultSize) + var index = thisSize + + while (index < resultSize) { + val value = elements.get(index - thisSize) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/Primitives.kt b/experiments/translator/kotstd/include/Primitives.kt new file mode 100644 index 00000000000..3da2e500545 --- /dev/null +++ b/experiments/translator/kotstd/include/Primitives.kt @@ -0,0 +1,251 @@ +package kotlin + +external fun kotlinclib_byteToChar(value: Byte): Char +external fun kotlinclib_byteToShort(value: Byte): Short +external fun kotlinclib_byteToInt(value: Byte): Int +external fun kotlinclib_byteToLong(value: Byte): Long +external fun kotlinclib_byteToFloat(value: Byte): Float +external fun kotlinclib_byteToDouble(value: Byte): Double + + +fun Byte.toByte(): Byte { + return this +} + +fun Byte.toInt(): Int { + return kotlinclib_byteToInt(this) +} + +fun Byte.toChar(): Char { + return kotlinclib_byteToChar(this) +} + +fun Byte.toShort(): Short { + return kotlinclib_byteToShort(this) +} + +fun Byte.toLong(): Long { + return kotlinclib_byteToLong(this) +} + +fun Byte.toFloat(): Float { + return kotlinclib_byteToFloat(this) +} + +fun Byte.toDouble(): Double { + return kotlinclib_byteToDouble(this) +} + +external fun kotlinclib_charToByte(value: Char): Byte +external fun kotlinclib_charToShort(value: Char): Short +external fun kotlinclib_charToInt(value: Char): Int +external fun kotlinclib_charToLong(value: Char): Long +external fun kotlinclib_charToFloat(value: Char): Float +external fun kotlinclib_charToDouble(value: Char): Double + + +fun Char.toByte(): Byte { + return kotlinclib_charToByte(this) +} + +fun Char.toInt(): Int { + return kotlinclib_charToInt(this) +} + +fun Char.toChar(): Char { + return this +} + +fun Char.toShort(): Short { + return kotlinclib_charToShort(this) +} + +fun Char.toLong(): Long { + return kotlinclib_charToLong(this) +} + +fun Char.toFloat(): Float { + return kotlinclib_charToFloat(this) +} + +fun Char.toDouble(): Double { + return kotlinclib_charToDouble(this) +} + +external fun kotlinclib_doubleToByte(value: Double): Byte +external fun kotlinclib_doubleToChar(value: Double): Char +external fun kotlinclib_doubleToShort(value: Double): Short +external fun kotlinclib_doubleToInt(value: Double): Int +external fun kotlinclib_doubleToLong(value: Double): Long +external fun kotlinclib_doubleToFloat(value: Double): Float + +fun Double.toByte(): Byte { + return kotlinclib_doubleToByte(this) +} + +fun Double.toChar(): Char { + return kotlinclib_doubleToChar(this) +} + +fun Double.toShort(): Short { + return kotlinclib_doubleToShort(this) +} + +fun Double.toInt(): Int { + return kotlinclib_doubleToInt(this) +} + +fun Double.toLong(): Long { + return kotlinclib_doubleToLong(this) +} + +fun Double.toFloat(): Float { + return kotlinclib_doubleToFloat(this) +} + +fun Double.toDouble(): Double { + return this +} + + +external fun kotlinclib_floatToByte(value: Float): Byte +external fun kotlinclib_floatToChar(value: Float): Char +external fun kotlinclib_floatToShort(value: Float): Short +external fun kotlinclib_floatToInt(value: Float): Int +external fun kotlinclib_floatToLong(value: Float): Long +external fun kotlinclib_floatToDouble(value: Float): Double + +fun Float.toByte(): Byte { + return kotlinclib_floatToByte(this) +} + +fun Float.toChar(): Char { + return kotlinclib_floatToChar(this) +} + +fun Float.toShort(): Short { + return kotlinclib_floatToShort(this) +} + +fun Float.toInt(): Int { + return kotlinclib_floatToInt(this) +} + +fun Float.toLong(): Long { + return kotlinclib_floatToLong(this) +} + +fun Float.toFloat(): Float { + return this +} + +fun Float.toDouble(): Double { + return kotlinclib_floatToDouble(this) +} + + +external fun kotlinclib_intToByte(value: Int): Byte +external fun kotlinclib_intToChar(value: Int): Char +external fun kotlinclib_intToShort(value: Int): Short +external fun kotlinclib_intToLong(value: Int): Long +external fun kotlinclib_intToFloat(value: Int): Float +external fun kotlinclib_intToDouble(value: Int): Double + +fun Int.toByte(): Byte { + return kotlinclib_intToByte(this) +} + +fun Int.toInt(): Int { + return this +} + +fun Int.toChar(): Char { + return kotlinclib_intToChar(this) +} + +fun Int.toShort(): Short { + return kotlinclib_intToShort(this) +} + +fun Int.toLong(): Long { + return kotlinclib_intToLong(this) +} + +fun Int.toFloat(): Float { + return kotlinclib_intToFloat(this) +} + +fun Int.toDouble(): Double { + return kotlinclib_intToDouble(this) +} + +external fun kotlinclib_longToByte(value: Long): Byte +external fun kotlinclib_longToChar(value: Long): Char +external fun kotlinclib_longToShort(value: Long): Short +external fun kotlinclib_longToInt(value: Long): Int +external fun kotlinclib_longToFloat(value: Long): Float +external fun kotlinclib_longToDouble(value: Long): Double + +fun Long.toByte(): Byte { + return kotlinclib_longToByte(this) +} + +fun Long.toLong(): Long { + return this +} + +fun Long.toChar(): Char { + return kotlinclib_longToChar(this) +} + +fun Long.toShort(): Short { + return kotlinclib_longToShort(this) +} + +fun Long.toInt(): Int { + return kotlinclib_longToInt(this) +} + +fun Long.toFloat(): Float { + return kotlinclib_longToFloat(this) +} + +fun Long.toDouble(): Double { + return kotlinclib_longToDouble(this) +} + +external fun kotlinclib_shortToByte(value: Short): Byte +external fun kotlinclib_shortToChar(value: Short): Char +external fun kotlinclib_shortToInt(value: Short): Int +external fun kotlinclib_shortToLong(value: Short): Long +external fun kotlinclib_shortToFloat(value: Short): Float +external fun kotlinclib_shortToDouble(value: Short): Double + + +fun Short.toByte(): Byte { + return kotlinclib_shortToByte(this) +} + +fun Short.toInt(): Int { + return kotlinclib_shortToInt(this) +} + +fun Short.toChar(): Char { + return kotlinclib_shortToChar(this) +} + +fun Short.toShort(): Short { + return this +} + +fun Short.toLong(): Long { + return kotlinclib_shortToLong(this) +} + +fun Short.toFloat(): Float { + return kotlinclib_shortToFloat(this) +} + +fun Short.toDouble(): Double { + return kotlinclib_shortToDouble(this) +} diff --git a/experiments/translator/kotstd/include/Progressions.kt b/experiments/translator/kotstd/include/Progressions.kt new file mode 100644 index 00000000000..ec9bbb3ec09 --- /dev/null +++ b/experiments/translator/kotstd/include/Progressions.kt @@ -0,0 +1,50 @@ +package kotlin + +/** + * 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) + } +} diff --git a/experiments/translator/kotstd/include/Ranges.kt b/experiments/translator/kotstd/include/Ranges.kt new file mode 100644 index 00000000000..4c12faa5e3d --- /dev/null +++ b/experiments/translator/kotstd/include/Ranges.kt @@ -0,0 +1,25 @@ +package kotlin.ranges + +import kotlin.IntProgression +import kotlin.collections.IntIterator + +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) + +} diff --git a/experiments/translator/kotstd/include/ShortArray.kt b/experiments/translator/kotstd/include/ShortArray.kt new file mode 100644 index 00000000000..3d1cf82a40e --- /dev/null +++ b/experiments/translator/kotstd/include/ShortArray.kt @@ -0,0 +1,120 @@ +package kotlin + +external fun kotlinclib_get_short(src: Int, index: Int): Short +external fun kotlinclib_set_short(src: Int, index: Int, value: Short) +external fun kotlinclib_short_size(): Int + + +class ShortArray(var size: Int) { + val data: Int + + /** Returns the number of elements in the array. */ + //size: Int + + init { + this.data = malloc_array(kotlinclib_short_size() * this.size) + var index = 0 + while (index < this.size) { + set(index, 0) + index = index + 1 + } + } + + /** Returns the array element at the given [index]. This method can be called using the index operator. */ + operator fun get(index: Int): Short { + return kotlinclib_get_short(this.data, index) + } + + + /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ + operator fun set(index: Int, value: Short) { + kotlinclib_set_short(this.data, index, value) + } + + + fun clone(): ShortArray { + val newInstance = ShortArray(this.size) + var index = 0 + while (index < this.size) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance + } + +} + +fun ShortArray.print() { + var index = 0 + print('[') + while (index < size) { + print(get(index)) + index++ + if (index < size) { + print(';') + print(' ') + } + } + print(']') +} + +fun ShortArray.println() { + this.print() + //println() +} + + +fun ShortArray.copyOf(newSize: Int): ShortArray { + val newInstance = ShortArray(newSize) + var index = 0 + val end = if (newSize > this.size) this.size else newSize + while (index < end) { + val value = this.get(index) + newInstance.set(index, value) + index = index + 1 + } + + while (index < newSize) { + newInstance.set(index, 0) + index = index + 1 + } + + return newInstance +} + +fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray { + val newInstance = ShortArray(toIndex - fromIndex) + var index = fromIndex + while (index < toIndex) { + val value = this.get(index) + newInstance.set(index - fromIndex, value) + index = index + 1 + } + + return newInstance +} + +operator fun ShortArray.plus(element: Short): ShortArray { + val index = size + val result = this.copyOf(index + 1) + result[index] = element + return result +} + +operator fun ShortArray.plus(elements: ShortArray): ShortArray { + val thisSize = size + val arraySize = elements.size + val resultSize = thisSize + arraySize + val newInstance = this.copyOf(resultSize) + var index = thisSize + + while (index < resultSize) { + val value = elements.get(index - thisSize) + newInstance.set(index, value) + index = index + 1 + } + + return newInstance +} \ No newline at end of file diff --git a/experiments/translator/kotstd/include/WireFormat.kt b/experiments/translator/kotstd/include/WireFormat.kt new file mode 100644 index 00000000000..d43c6e37003 --- /dev/null +++ b/experiments/translator/kotstd/include/WireFormat.kt @@ -0,0 +1,164 @@ + +object WireFormat { + // couple of constants for magic numbers + val TAG_TYPE_BITS: Int = 3 + val TAG_TYPE_MASK: Int = (1 shl TAG_TYPE_BITS) - 1 + val VARINT_INFO_BITS_COUNT: Int = 7 + val VARINT_INFO_BITS_MASK: Int = 0b01111111 // mask for separating lowest 7 bits, where actual information stored + val VARINT_UTIL_BIT_MASK: Int = 0b10000000 // mask for separating highest bit, that indicates next byte presence + val FIXED_32_BYTE_SIZE: Int = 4 + val FIXED_64_BYTE_SIZE: Int = 8 + + fun getTagWireType(tag: Int): WireType { + return WireType.from((tag and TAG_TYPE_MASK).toByte()) + } + + fun getTagFieldNumber(tag: Int): Int { + return tag ushr TAG_TYPE_BITS + } + + // TODO: refactor casts into function overloading as soon as translator will support it + fun getTagSize(fieldNumber: Int, wireType: WireType): Int { + return getVarint32Size((fieldNumber shl 3) or wireType.id) + } + + fun getVarint32Size(value: Int): Int { + var curValue = value + var size = 0 + do { + size += 1 + curValue = curValue ushr VARINT_INFO_BITS_COUNT + } while (curValue != 0) + return size + } + + fun getVarint64Size(value: Long): Int { + var curValue = value + var size = 0 + do { + size += 1 + curValue = curValue ushr VARINT_INFO_BITS_COUNT + }while (curValue != 0L) + return size + } + + fun getZigZag32Size(value: Int): Int { + return getVarint32Size((value shl 1) xor (value shr 31)) + } + + fun getZigZag64Size(value: Long): Int { + return getVarint64Size((value shl 1) xor (value shr 63)) + } + + fun getInt32Size(fieldNumber: Int, value: Int): Int { + return getTagSize(fieldNumber, WireType.VARINT) + getInt32SizeNoTag(value) + } + + fun getInt32SizeNoTag(value: Int): Int { + if (value < 0) { + return getVarint64Size(value.toLong()) + } + return getVarint32Size(value) + } + + fun getUInt32Size(fieldNumber: Int, value: Int): Int { + return getTagSize(fieldNumber, WireType.VARINT) + getUInt32SizeNoTag(value) + } + + fun getUInt32SizeNoTag(value: Int): Int { + return getVarint32Size(value) + } + + fun getInt64Size(fieldNumber: Int, value: Long): Int { + return getTagSize(fieldNumber, WireType.VARINT) + getUInt64SizeNoTag(value) + } + + fun getInt64SizeNoTag(value: Long): Int { + return getVarint64Size(value) + } + + fun getUInt64Size(fieldNumber: Int, value: Long): Int { + return getInt64Size(fieldNumber, value) + } + + fun getUInt64SizeNoTag(value: Long): Int { + return getVarint64Size(value) + } + + fun getBoolSize(fieldNumber: Int, value: Boolean): Int { + val intValue = if (value) 1 else 0 + return getInt32Size(fieldNumber, intValue) + } + + fun getBoolSizeNoTag(value: Boolean): Int { + val intValue = if (value) 1 else 0 + return getInt32SizeNoTag(intValue) + } + + fun getEnumSize(fieldNumber: Int, value: Int): Int { + return getInt32Size(fieldNumber, value) + } + + fun getEnumSizeNoTag(value: Int): Int { + return getInt32SizeNoTag(value) + } + + fun getSInt32Size(fieldNumber: Int, value: Int): Int { + return getTagSize(fieldNumber, WireType.VARINT) + getZigZag32Size(value) + } + + fun getSInt32SizeNoTag(value: Int): Int { + return getZigZag32Size(value) + } + + fun getSInt64Size(fieldNumber: Int, value: Long): Int { + return getTagSize(fieldNumber, WireType.VARINT) + getZigZag64Size(value) + } + + fun getSInt64SizeNoTag(value: Long): Int { + return getZigZag64Size(value) + } + + fun getFixed32Size(fieldNumber: Int, value: Int): Int { + return getTagSize(fieldNumber, WireType.FIX_32) + FIXED_32_BYTE_SIZE + } + + fun getFixed32SizeNoTag(value: Int): Int { + return FIXED_32_BYTE_SIZE + } + + fun getFixed64Size(fieldNumber: Int, value: Long): Int { + return getTagSize(fieldNumber, WireType.FIX_64) + FIXED_64_BYTE_SIZE + } + + fun getFixed64SizeNoTag(value: Long): Int { + return FIXED_64_BYTE_SIZE + } + + fun getDoubleSize(fieldNumber: Int, value: Double): Int { + return getTagSize(fieldNumber, WireType.FIX_64) + FIXED_64_BYTE_SIZE + } + + fun getDoubleSizeNoTag(value: Double): Int { + return FIXED_64_BYTE_SIZE + } + + fun getFloatSize(fieldNumber: Int, value: Float): Int { + return getTagSize(fieldNumber, WireType.FIX_32) + FIXED_32_BYTE_SIZE + } + + fun getFloatSizeNoTag(value: Float): Int { + return FIXED_32_BYTE_SIZE + } + + fun getBytesSize(fieldNumber: Int, value: ByteArray): Int { + if (value.size == 0) + return 0 + var size = 0 + return value.size + getTagSize(fieldNumber, WireType.LENGTH_DELIMITED) + getVarint32Size(value.size) + } + + fun getBytesSizeNoTag(value: ByteArray): Int { + return value.size + getVarint32Size(value.size) + } +} diff --git a/experiments/translator/kotstd/include/WireType.kt b/experiments/translator/kotstd/include/WireType.kt new file mode 100644 index 00000000000..4ffc150fa68 --- /dev/null +++ b/experiments/translator/kotstd/include/WireType.kt @@ -0,0 +1,29 @@ +/** + * Created by Dmitry Savvinov on 7/6/16. + * Enum for possible WireTypes. + * See details at [official Google reference](https://developers.google.com/protocol-buffers/docs/encoding#structure) + */ + +enum class WireType(val id: Int) { + VARINT(0), // int32, int64, uint32, uint64, sint32, sint64, bool, enum + FIX_64(1), // fixed64, sfixed64, double + LENGTH_DELIMITED(2), // string, bytes, embedded messages, packed repeated fields + START_GROUP(3), // groups (deprecated) + END_GROUP(4), // groups (deprecated) + FIX_32(5), // fixed32, sfixed32, float + UNDEFINED(6); // indicates error when parsing from Int + + companion object { + fun from (value: Byte): WireType { + return when (value) { + 0.toByte() -> VARINT + 1.toByte() -> FIX_64 + 2.toByte() -> LENGTH_DELIMITED + 3.toByte() -> START_GROUP + 4.toByte() -> END_GROUP + 5.toByte() -> FIX_32 + else -> UNDEFINED + } + } + } +} diff --git a/experiments/translator/kotstd/include/progressionUtil.kt b/experiments/translator/kotstd/include/progressionUtil.kt new file mode 100644 index 00000000000..a03312f71e4 --- /dev/null +++ b/experiments/translator/kotstd/include/progressionUtil.kt @@ -0,0 +1,71 @@ +package kotlin + +// 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 + } +} diff --git a/experiments/translator/kotstd/libc/array_c.c b/experiments/translator/kotstd/libc/array_c.c new file mode 100644 index 00000000000..8b80a3534cc --- /dev/null +++ b/experiments/translator/kotstd/libc/array_c.c @@ -0,0 +1,32 @@ +extern char *malloc(int size); + +int malloc_array(int x) { + return (int) malloc(x); +} + +char kotlinclib_get_byte(int data, int index) { + return *((char *) data + index); +} + +void kotlinclib_set_byte(int data, int index, char value) { + char *ptr = (char *) data; + *(ptr + index) = value; +} + +int kotlinclib_get_int(int data, int index) { + return *((int *) data + index); +} + +void kotlinclib_set_int(int data, int index, int value) { + int *ptr = (int *) data; + *(ptr + index) = value; +} + +short kotlinclib_get_short(int data, int index) { + return *((short *) data + index); +} + +void kotlinclib_set_short(int data, int index, short value) { + short *ptr = (short *) data; + *(ptr + index) = value; +} \ No newline at end of file diff --git a/experiments/translator/kotstd/libc/assert_c.c b/experiments/translator/kotstd/libc/assert_c.c new file mode 100644 index 00000000000..e526eaaca41 --- /dev/null +++ b/experiments/translator/kotstd/libc/assert_c.c @@ -0,0 +1,9 @@ +#include +#include + +void assert_c(int value) { + if (!value) { + printf("Exception in thread \"main\" java.lang.AssertionError: Assertion failed\n"); + abort(); + } +} \ No newline at end of file diff --git a/experiments/translator/kotstd/libc/memory.c b/experiments/translator/kotstd/libc/memory.c new file mode 100644 index 00000000000..18844c7c0ef --- /dev/null +++ b/experiments/translator/kotstd/libc/memory.c @@ -0,0 +1,82 @@ + +#define STATIC_AREA_SIZE 30000 +#define DYNAMIC_AREA_SIZE 30000 + +#define STATIC_HEAP 0 +#define DYNAMIC_HEAP 1 + +#ifdef ARM + +char static_area[STATIC_AREA_SIZE]; +char dynamic_area[DYNAMIC_AREA_SIZE]; + +char* heaps[2] = { + (char*) static_area, + (char*) dynamic_area +}; + +int heap_tails[2] = {0, 0}; +int active_heap = STATIC_HEAP; + +int dynamic_heap_consume = 0; +int dynamic_heap_max = 0; + +#else +char* malloc(int); +#endif + +#ifdef DBG + static int total = 0; + int printf(const char * restrict format, ... ); +#endif + +char* malloc_heap(int size) { +#ifdef ARM + char* ptr = heaps[active_heap] + heap_tails[active_heap]; + heap_tails[active_heap] += size; + + return ptr; + +#else + #ifdef DBG + total = total + size; + printf("Alloc [%d] TOTAL: [%d]\n", size, total); + #endif + return malloc(size); +#endif +} + +void set_active_heap(int heap) { +#ifdef ARM + active_heap = heap; +#endif +} + +void clean_dynamic_heap() { +#ifdef ARM + dynamic_heap_consume += heap_tails[DYNAMIC_HEAP]; + if (heap_tails[DYNAMIC_HEAP] > dynamic_heap_max) { + dynamic_heap_max = heap_tails[DYNAMIC_HEAP]; + } + + heap_tails[DYNAMIC_HEAP] = 0; +#endif +} + +#ifdef ARM +int dynamic_heap_tail() { + return heap_tails[DYNAMIC_HEAP]; +} + +int static_heap_tail() { + return heap_tails[STATIC_HEAP]; +} + +int dynamic_heap_max_bytes() { + return dynamic_heap_max; +} + +int dynamic_heap_total() { + return dynamic_heap_consume; +} +#endif diff --git a/experiments/translator/kotstd/libc/primitives_c.c b/experiments/translator/kotstd/libc/primitives_c.c new file mode 100644 index 00000000000..5f1eb3c2f52 --- /dev/null +++ b/experiments/translator/kotstd/libc/primitives_c.c @@ -0,0 +1,57 @@ +#define MAKE_CONVERT(from, from_type, to, to_type) to_type kotlinclib_ ## from ## To ## to ( from_type value ) { return (to_type) value;} + + +MAKE_CONVERT(int, int, Byte, char) +MAKE_CONVERT(int, int, Char, char) +MAKE_CONVERT(int, int, Short, short) +MAKE_CONVERT(int, int, Long, long) +MAKE_CONVERT(int, int, Float, float) +MAKE_CONVERT(int, int, Double, double) + + +MAKE_CONVERT(byte, char, Char, char) +MAKE_CONVERT(byte, char, Short, short) +MAKE_CONVERT(byte, char, Int, int) +MAKE_CONVERT(byte, char, Long, long) +MAKE_CONVERT(byte, char, Float, float) +MAKE_CONVERT(byte, char, Double, double) + + +MAKE_CONVERT(char, char, Byte, char) +MAKE_CONVERT(char, char, Short, short) +MAKE_CONVERT(char, char, Int, int) +MAKE_CONVERT(char, char, Long, long) +MAKE_CONVERT(char, char, Float, float) +MAKE_CONVERT(char, char, Double, double) + + +MAKE_CONVERT(short, short, Byte, char) +MAKE_CONVERT(short, short, Char, char) +MAKE_CONVERT(short, short, Int, int) +MAKE_CONVERT(short, short, Long, long) +MAKE_CONVERT(short, short, Float, float) +MAKE_CONVERT(short, short, Double, double) + + +MAKE_CONVERT(long, long, Byte, char) +MAKE_CONVERT(long, long, Char, char) +MAKE_CONVERT(long, long, Short, short) +MAKE_CONVERT(long, long, Int, int) +MAKE_CONVERT(long, long, Float, float) +MAKE_CONVERT(long, long, Double, double) + + +MAKE_CONVERT(float, float, Byte, char) +MAKE_CONVERT(float, float, Char, char) +MAKE_CONVERT(float, float, Short, short) +MAKE_CONVERT(float, float, Int, int) +MAKE_CONVERT(float, float, Long, long) +MAKE_CONVERT(float, float, Double, double) + + +MAKE_CONVERT(double, double, Byte, char) +MAKE_CONVERT(double, double, Char, char) +MAKE_CONVERT(double, double, Short, short) +MAKE_CONVERT(double, double, Int, int) +MAKE_CONVERT(double, double, Long, long) +MAKE_CONVERT(double, double, Float, float) \ No newline at end of file diff --git a/experiments/translator/translate.sh b/experiments/translator/translate.sh new file mode 100755 index 00000000000..2eb68f20216 --- /dev/null +++ b/experiments/translator/translate.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +java -jar $DIR/build/libs/translator-1.0.jar -I $DIR/kotstd/include $@