translator: fix array access operator, serialization tests, add proto runtime to kotstd

This commit is contained in:
e5l
2016-08-16 10:09:20 +03:00
parent ee657d19a5
commit e66e0dc0fd
16 changed files with 1495 additions and 781 deletions
+45 -3
View File
@@ -1,11 +1,53 @@
fun echoUsb() {
led_on()
clear_buffer()
while (true) {
val command = receive_int();
val command = receive_int()
send_int(command)
}
}
}
fun echoProto() {
led_on()
clear_buffer()
while (true) {
val route = readRoute()
go(route)
}
}
fun readRoute(): RouteRequest {
val size = receive_int()
val buffer = ByteArray(size)
val stream = CodedInputStream(buffer)
val result = RouteRequest.BuilderRouteRequest(IntArray(0), IntArray(0)).parseFrom(stream).build()
return result
}
fun go(request: RouteRequest) {
val times = request.distances
var j = 0
while (j < times.size) {
val time = times[j]
engine_forward()
wait(time)
engine_stop()
j++
}
}
//fun writeProto() {
// val msg = DirectionResponse.BuilderDirectionResponse(4242).build()
// val size = msg.getSizeNoTag()
// val buffer = ByteArray(size)
// val outputStream = CodedOutputStream(buffer)
//
// msg.writeTo(outputStream)
// sendByteArray(buffer)
// send_int(0xDDEEFF)
//}
+2 -11
View File
@@ -1,17 +1,8 @@
//fun writeProto() {
// val msg = DirectionResponse.BuilderDirectionResponse(4242).build()
// val size = msg.getSizeNoTag()
// val buffer = ByteArray(size)
// val outputStream = CodedOutputStream(buffer)
//
// msg.writeTo(outputStream)
// sendByteArray(buffer)
// send_int(0xDDEEFF)
//}
val PROGRAM_DURATION: Int = 1000
fun main() {
init()
echoUsb()
echoProto()
}
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
package carkot;
message RouteRequest {
repeated int32 distances = 1;
repeated int32 angles = 2;
}
message RouteResponse {
int32 code = 1;
}
@@ -6,8 +6,9 @@ class KotlinInputStream(val buffer: ByteArray) {
var pos = 0
fun read(): Byte {
pos += 1
return buffer[pos - 1]
val result = buffer[pos]
pos++
return result
}
fun isAtEnd(): Boolean {
+460
View File
@@ -0,0 +1,460 @@
class RouteRequest private constructor (var distances: IntArray, var angles: IntArray) {
//========== Properties ===========
//repeated int32 distances = 1
//repeated int32 angles = 2
var errorCode: Int = 0
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//repeated int32 distances = 1
if (distances.size > 0) {
output.writeTag(1, WireType.LENGTH_DELIMITED)
var arrayByteSize = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32SizeNoTag(distances[i])
i += 1
}
arrayByteSize += arraySize
} while(false)
}
output.writeInt32NoTag(arrayByteSize)
do {
var i = 0
while (i < distances.size) {
output.writeInt32NoTag (distances[i])
i += 1
}
} while(false)
}
//repeated int32 angles = 2
if (angles.size > 0) {
output.writeTag(2, WireType.LENGTH_DELIMITED)
var arrayByteSize = 0
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32SizeNoTag(angles[i])
i += 1
}
arrayByteSize += arraySize
} while(false)
}
output.writeInt32NoTag(arrayByteSize)
do {
var i = 0
while (i < angles.size) {
output.writeInt32NoTag (angles[i])
i += 1
}
} while(false)
}
}
fun mergeWith (other: RouteRequest) {
distances = distances.plus((other.distances))
angles = angles.plus((other.angles))
}
fun mergeFromWithSize (input: CodedInputStream, expectedSize: Int) {
val builder = RouteRequest.BuilderRouteRequest(IntArray(0), IntArray(0))
mergeWith(builder.parseFromWithSize(input, expectedSize).build())
}
fun mergeFrom (input: CodedInputStream) {
val builder = RouteRequest.BuilderRouteRequest(IntArray(0), IntArray(0))
mergeWith(builder.parseFrom(input).build())
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32Size(1, distances[i])
i += 1
}
size += arraySize
} while(false)
}
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32Size(2, angles[i])
i += 1
}
size += arraySize
} while(false)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32Size(1, distances[i])
i += 1
}
size += arraySize
} while(false)
}
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32Size(2, angles[i])
i += 1
}
size += arraySize
} while(false)
}
return size
}
//========== Builder ===========
class BuilderRouteRequest constructor (var distances: IntArray, var angles: IntArray) {
//========== Properties ===========
//repeated int32 distances = 1
fun setDistances(value: IntArray): RouteRequest.BuilderRouteRequest {
distances = value
return this
}
fun setdistancesByIndex(index: Int, value: Int): RouteRequest.BuilderRouteRequest {
distances[index] = value
return this
}
//repeated int32 angles = 2
fun setAngles(value: IntArray): RouteRequest.BuilderRouteRequest {
angles = value
return this
}
fun setanglesByIndex(index: Int, value: Int): RouteRequest.BuilderRouteRequest {
angles[index] = value
return this
}
var errorCode: Int = 0
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//repeated int32 distances = 1
if (distances.size > 0) {
output.writeTag(1, WireType.LENGTH_DELIMITED)
var arrayByteSize = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32SizeNoTag(distances[i])
i += 1
}
arrayByteSize += arraySize
} while(false)
}
output.writeInt32NoTag(arrayByteSize)
do {
var i = 0
while (i < distances.size) {
output.writeInt32NoTag (distances[i])
i += 1
}
} while(false)
}
//repeated int32 angles = 2
if (angles.size > 0) {
output.writeTag(2, WireType.LENGTH_DELIMITED)
var arrayByteSize = 0
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32SizeNoTag(angles[i])
i += 1
}
arrayByteSize += arraySize
} while(false)
}
output.writeInt32NoTag(arrayByteSize)
do {
var i = 0
while (i < angles.size) {
output.writeInt32NoTag (angles[i])
i += 1
}
} while(false)
}
}
//========== Mutating methods ===========
fun build(): RouteRequest {
return RouteRequest(distances, angles)
}
fun parseFieldFrom(input: CodedInputStream): Boolean {
if (input.isAtEnd()) { return false }
val tag = input.readInt32NoTag()
if (tag == 0) { return false }
val fieldNumber = WireFormat.getTagFieldNumber(tag)
val wireType = WireFormat.getTagWireType(tag)
when(fieldNumber) {
1 -> {
if (wireType != WireType.LENGTH_DELIMITED) { errorCode = 1; return false }
val expectedByteSize = input.readInt32NoTag()
var newArray = IntArray(0)
var readSize = 0
do {
var i = 0
while(readSize < expectedByteSize) {
var tmp = IntArray(1)
tmp[0] = input.readInt32NoTag()
newArray = newArray.plus(tmp)
readSize += WireFormat.getInt32SizeNoTag(tmp[0])
}
distances = newArray
} while (false)
}
2 -> {
if (wireType != WireType.LENGTH_DELIMITED) { errorCode = 1; return false }
val expectedByteSize = input.readInt32NoTag()
var newArray = IntArray(0)
var readSize = 0
do {
var i = 0
while(readSize < expectedByteSize) {
var tmp = IntArray(1)
tmp[0] = input.readInt32NoTag()
newArray = newArray.plus(tmp)
readSize += WireFormat.getInt32SizeNoTag(tmp[0])
}
angles = newArray
} while (false)
}
}
return true}
fun parseFromWithSize(input: CodedInputStream, expectedSize: Int): RouteRequest.BuilderRouteRequest {
while(getSizeNoTag() < expectedSize) {
parseFieldFrom(input)
}
if (getSizeNoTag() > expectedSize) { errorCode = 2 }
return this
}
fun parseFrom(input: CodedInputStream): RouteRequest.BuilderRouteRequest {
while(parseFieldFrom(input)) {}
return this
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32Size(1, distances[i])
i += 1
}
size += arraySize
} while(false)
}
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32Size(2, angles[i])
i += 1
}
size += arraySize
} while(false)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (distances.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < distances.size) {
arraySize += WireFormat.getInt32Size(1, distances[i])
i += 1
}
size += arraySize
} while(false)
}
if (angles.size != 0) {
do {
var arraySize = 0
var i = 0
while (i < angles.size) {
arraySize += WireFormat.getInt32Size(2, angles[i])
i += 1
}
size += arraySize
} while(false)
}
return size
}
}
}
class RouteResponse private constructor (var code: Int) {
//========== Properties ===========
//int32 code = 1
var errorCode: Int = 0
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//int32 code = 1
if (code != 0) {
output.writeInt32 (1, code)
}
}
fun mergeWith (other: RouteResponse) {
code = other.code
}
fun mergeFromWithSize (input: CodedInputStream, expectedSize: Int) {
val builder = RouteResponse.BuilderRouteResponse(0)
mergeWith(builder.parseFromWithSize(input, expectedSize).build())
}
fun mergeFrom (input: CodedInputStream) {
val builder = RouteResponse.BuilderRouteResponse(0)
mergeWith(builder.parseFrom(input).build())
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (code != 0) {
size += WireFormat.getInt32Size(1, code)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (code != 0) {
size += WireFormat.getInt32Size(1, code)
}
return size
}
//========== Builder ===========
class BuilderRouteResponse constructor (var code: Int) {
//========== Properties ===========
//int32 code = 1
fun setCode(value: Int): RouteResponse.BuilderRouteResponse {
code = value
return this
}
var errorCode: Int = 0
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//int32 code = 1
if (code != 0) {
output.writeInt32 (1, code)
}
}
//========== Mutating methods ===========
fun build(): RouteResponse {
return RouteResponse(code)
}
fun parseFieldFrom(input: CodedInputStream): Boolean {
if (input.isAtEnd()) { return false }
val tag = input.readInt32NoTag()
if (tag == 0) { return false }
val fieldNumber = WireFormat.getTagFieldNumber(tag)
val wireType = WireFormat.getTagWireType(tag)
when(fieldNumber) {
1 -> {
if (wireType != WireType.VARINT) { errorCode = 1; return false }
code = input.readInt32NoTag()
}
}
return true}
fun parseFromWithSize(input: CodedInputStream, expectedSize: Int): RouteResponse.BuilderRouteResponse {
while(getSizeNoTag() < expectedSize) {
parseFieldFrom(input)
}
if (getSizeNoTag() > expectedSize) { errorCode = 2 }
return this
}
fun parseFrom(input: CodedInputStream): RouteResponse.BuilderRouteResponse {
while(parseFieldFrom(input)) {}
return this
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (code != 0) {
size += WireFormat.getInt32Size(1, code)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (code != 0) {
size += WireFormat.getInt32Size(1, code)
}
return size
}
}
}
-1
View File
@@ -4,6 +4,5 @@ fun simpleRoute() {
while (true) {
wait(PROGRAM_DURATION)
blink()
// writeProto()
}
}
+2 -2
View File
@@ -14,10 +14,10 @@ LLINK_ALL_DEPS=$(LLINK) $(LLINK_FLAGS) $(filter %.ll,$^) > $@
all: $(BUILD_DIR)/stdlib_arm.ll $(BUILD_DIR)/stdlib_x86.ll
$(BUILD_DIR)/stdlib_x86.ll: $(BUILD_DIR)/classes_x86.ll $(LIB_X86_DIR)/*.ll
$(BUILD_DIR)/stdlib_x86.ll: $(LIB_X86_DIR)/*.ll
$(LLINK_ALL_DEPS)
$(BUILD_DIR)/stdlib_arm.ll: $(BUILD_DIR)/classes_arm.ll $(LIB_ARM_DIR)/*.ll
$(BUILD_DIR)/stdlib_arm.ll: $(LIB_ARM_DIR)/*.ll
$(LLINK_ALL_DEPS)
$(BUILD_DIR)/classes_x86.ll: $(INCLUDE_DIR)/*.kt
+208
View File
@@ -0,0 +1,208 @@
/**
* 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) // TODO: Java's realization uses hand-written buffers. Why?
}
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()
}
}
+167
View File
@@ -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
while(curValue != 0L) {
// 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++
}
output.write(res, 0, resSize)
}
}
+17
View File
@@ -0,0 +1,17 @@
/**
* Created by user on 8/8/16.
*/
class KotlinInputStream(val buffer: ByteArray) {
var pos = 0
fun read(): Byte {
val result = buffer[pos]
pos++
return result
}
fun isAtEnd(): Boolean {
return pos >= buffer.size
}
}
+20
View File
@@ -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++
}
}
}
+164
View File
@@ -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)
}
}
+29
View File
@@ -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
}
}
}
}
@@ -294,7 +294,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? {
val arrayNameVariable = evaluateReferenceExpression(expr.arrayExpression as KtReferenceExpression, scope) as LLVMVariable
val arrayNameVariable = evaluateExpression(expr.arrayExpression, scope) as LLVMVariable
return when (arrayNameVariable.type) {
is LLVMReferenceType -> {
val callMaker = state.bindingContext.get(BindingContext.CALL, expr)
@@ -303,9 +303,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
Call.CallType.ARRAY_GET_METHOD -> {
val arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get"
val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver
val expression = explicitReceiver.expression as KtReferenceExpression
val receiver = evaluateReferenceExpression(expression, scope)!! as LLVMVariable
val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable
val pureReceiver = downLoadArgument(receiver, 1)
val targetClassName = (receiver.type as LLVMReferenceType).type
@@ -1 +1,2 @@
serialization_test1_Int(1442) == 1442
serialization_test2_Int(10)
File diff suppressed because it is too large Load Diff