translator: object field default initialization

This commit is contained in:
e5l
2016-08-12 18:14:33 +03:00
parent f25733223e
commit bd1198bca7
20 changed files with 997 additions and 43 deletions
+4
View File
@@ -22,6 +22,7 @@ KT=$(TRANSLATOR_DIR)/build/libs/translator-1.0.jar
LD=arm-none-eabi-ld
OBJ_COPY=arm-none-eabi-objcopy
GDB=arm-none-eabi-gdb
PROTOC=$(PWD)/../proto/build/protoc
LL=llc-3.6
LLINK=llvm-link-3.6
@@ -73,6 +74,9 @@ $(LIB_DIR)/app.ll: $(SRC_DIR)/**/*.kt $(SRC_DIR)/*.kt
$(KT):
cd $(TRANSLATOR_DIR) && ./gradlew jar
proto:
$(PROTOC) -I$(SRC_DIR)/proto --kotlin_out=$(SRC_DIR)/proto_src $(SRC_DIR)/proto/*.proto
flash: $(CAR_FMW_BIN)
$(ST_DIR)/st-flash write $(CAR_FMW_BIN) 0x8000000
+8
View File
@@ -0,0 +1,8 @@
external fun VCP_init()
external fun send_int(i: Int)
external fun send_buffer(size: Int, pointer: Int)
fun sendByteArray(arr: ByteArray) {
send_buffer(arr.size, arr.data)
}
+1
View File
@@ -3,4 +3,5 @@ fun init() {
time_init()
engine_init()
leds_init()
VCP_init()
}
+11
View File
@@ -1,5 +1,16 @@
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)
}
fun main() {
init()
writeProto()
simpleRoute()
}
+21
View File
@@ -0,0 +1,21 @@
syntax = "proto3";
package carkot;
option java_package = "proto.car";
option java_outer_classname = "Direction";
message DirectionRequest {
enum Command {
stop = 0;
forward = 1;
backward = 2;
left = 3;
right = 4;
}
Command command = 1;
int32 sid = 2;
}
message DirectionResponse {
int32 code = 1;
}
@@ -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: Int = 0
var step: Int = 0
while (!done) {
val byte: Int = inputStream.read().toInt()
result = result or
(
(byte and WireFormat.VARINT_INFO_BITS_MASK)
shl
(WireFormat.VARINT_INFO_BITS_COUNT * step)
)
step++
if ((byte and WireFormat.VARINT_UTIL_BIT_MASK) == 0) {
done = true
}
}
return result
}
// 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 shr 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 shr 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()
}
}
@@ -0,0 +1,153 @@
/**
* 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
writeInt32NoTag(tag)
}
fun writeInt32(fieldNumber: Int, value: Int) {
writeTag(fieldNumber, WireType.VARINT)
writeInt32NoTag(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) {
writeInt32(fieldNumber, value)
}
fun writeUInt32NoTag(value: Int) {
writeInt32NoTag(value)
}
fun writeInt64(fieldNumber: Int, value: Long) {
writeTag(fieldNumber, WireType.VARINT)
writeInt64NoTag(value)
}
// See notes on unsigned integers implementation above
fun writeUInt64(fieldNumber: Int, value: Long) {
writeInt64(fieldNumber, value)
}
fun writeUInt64NoTag(value: Long) {
writeInt64NoTag(value)
}
fun writeBool(fieldNumber: Int, value: Boolean) {
writeTag(fieldNumber, WireType.VARINT)
writeBoolNoTag(value)
}
fun writeBoolNoTag(value: Boolean) {
writeInt32NoTag(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) {
writeInt32NoTag(value)
}
fun writeSInt32(fieldNumber: Int, value: Int) {
writeTag(fieldNumber, WireType.VARINT)
writeSInt32NoTag(value)
}
fun writeSInt32NoTag(value: Int) {
writeInt32NoTag((value shl 1) xor (value shr 31))
}
fun writeSInt64(fieldNumber: Int, value: Long) {
writeTag(fieldNumber, WireType.VARINT)
writeSInt64NoTag(value)
}
fun writeSInt64NoTag(value: Long) {
writeInt64NoTag((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) {
writeInt32NoTag(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 writeInt32NoTag(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 writeInt64NoTag(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)
}
}
@@ -0,0 +1,16 @@
/**
* Created by user on 8/8/16.
*/
class KotlinInputStream(val buffer: ByteArray) {
var pos = 0
fun read(): Byte {
pos += 1
return buffer[pos - 1]
}
fun isAtEnd(): Boolean {
return pos >= buffer.size
}
}
@@ -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++
}
}
}
+161
View File
@@ -0,0 +1,161 @@
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
while (curValue != 0) {
size += 1
curValue = curValue ushr VARINT_INFO_BITS_COUNT
}
return size
}
fun getVarint64Size(value: Long): Int {
var curValue = value
var size = 0
while (curValue != 0L) {
size += 1
curValue = curValue ushr VARINT_INFO_BITS_COUNT
}
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) + getVarint32Size(value)
}
fun getInt32SizeNoTag(value: Int): Int {
return getVarint32Size(value)
}
fun getUInt32Size(fieldNumber: Int, value: Int): Int {
return getInt32Size(fieldNumber, value)
}
fun getUInt32SizeNoTag(value: Int): Int {
return getVarint32Size(value)
}
fun getInt64Size(fieldNumber: Int, value: Long): Int {
return getTagSize(fieldNumber, WireType.VARINT) + getVarint64Size(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
}
}
}
}
+301
View File
@@ -0,0 +1,301 @@
class DirectionRequest private constructor (var command: DirectionRequest.Command, var sid: Int) {
//========== Properties ===========
//enum command = 1
//int32 sid = 2
var errorCode: Int = 0
//========== Nested enums declarations ===========
enum class Command(val ord: Int) {
stop (0),
forward (1),
backward (2),
left (3),
right (4),
Unexpected(5);
companion object {
fun fromIntToCommand (ord: Int): Command {
return when (ord) {
0 -> Command.stop
1 -> Command.forward
2 -> Command.backward
3 -> Command.left
4 -> Command.right
else -> Unexpected
}
}
}
}
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//enum command = 1
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
output.writeEnum (1, command.ord)
}
//int32 sid = 2
if (sid != 0) {
output.writeInt32 (2, sid)
}
}
fun mergeWith (other: DirectionRequest) {
command = other.command
sid = other.sid
}
fun mergeFromWithSize (input: CodedInputStream, expectedSize: Int) {
val builder = DirectionRequest.BuilderDirectionRequest(DirectionRequest.Command.fromIntToCommand(0), 0)
mergeWith(builder.parseFromWithSize(input, expectedSize).build())
}
fun mergeFrom (input: CodedInputStream) {
val builder = DirectionRequest.BuilderDirectionRequest(DirectionRequest.Command.fromIntToCommand(0), 0)
mergeWith(builder.parseFrom(input).build())
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
size += WireFormat.getEnumSize(1, command.ord)
}
if (sid != 0) {
size += WireFormat.getInt32Size(2, sid)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
size += WireFormat.getEnumSize(1, command.ord)
}
if (sid != 0) {
size += WireFormat.getInt32Size(2, sid)
}
return size
}
//========== Builder ===========
class BuilderDirectionRequest constructor (var command: DirectionRequest.Command, var sid: Int) {
//========== Properties ===========
//enum command = 1
fun setCommand(value: DirectionRequest.Command): DirectionRequest.BuilderDirectionRequest {
command = value
return this
}
//int32 sid = 2
fun setSid(value: Int): DirectionRequest.BuilderDirectionRequest {
sid = value
return this
}
var errorCode: Int = 0
//========== Serialization methods ===========
fun writeTo (output: CodedOutputStream) {
//enum command = 1
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
output.writeEnum (1, command.ord)
}
//int32 sid = 2
if (sid != 0) {
output.writeInt32 (2, sid)
}
}
//========== Mutating methods ===========
fun build(): DirectionRequest {
return DirectionRequest(command, sid)
}
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 }
command = DirectionRequest.Command.fromIntToCommand(input.readEnumNoTag())
}
2 -> {
if (wireType != WireType.VARINT) { errorCode = 1; return false }
sid = input.readInt32NoTag()
}
}
return true}
fun parseFromWithSize(input: CodedInputStream, expectedSize: Int): DirectionRequest.BuilderDirectionRequest {
while(getSizeNoTag() < expectedSize) {
parseFieldFrom(input)
}
if (getSizeNoTag() > expectedSize) { errorCode = 2 }
return this
}
fun parseFrom(input: CodedInputStream): DirectionRequest.BuilderDirectionRequest {
while(parseFieldFrom(input)) {}
return this
}
//========== Size-related methods ===========
fun getSize(fieldNumber: Int): Int {
var size = 0
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
size += WireFormat.getEnumSize(1, command.ord)
}
if (sid != 0) {
size += WireFormat.getInt32Size(2, sid)
}
size += WireFormat.getVarint32Size(size) + WireFormat.getTagSize(fieldNumber, WireType.LENGTH_DELIMITED)
return size
}
fun getSizeNoTag(): Int {
var size = 0
if (command != DirectionRequest.Command.fromIntToCommand(0)) {
size += WireFormat.getEnumSize(1, command.ord)
}
if (sid != 0) {
size += WireFormat.getInt32Size(2, sid)
}
return size
}
}
}
class DirectionResponse 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: DirectionResponse) {
code = other.code
}
fun mergeFromWithSize (input: CodedInputStream, expectedSize: Int) {
val builder = DirectionResponse.BuilderDirectionResponse(0)
mergeWith(builder.parseFromWithSize(input, expectedSize).build())
}
fun mergeFrom (input: CodedInputStream) {
val builder = DirectionResponse.BuilderDirectionResponse(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 BuilderDirectionResponse constructor (var code: Int) {
//========== Properties ===========
//int32 code = 1
fun setCode(value: Int): DirectionResponse.BuilderDirectionResponse {
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(): DirectionResponse {
return DirectionResponse(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): DirectionResponse.BuilderDirectionResponse {
while(getSizeNoTag() < expectedSize) {
parseFieldFrom(input)
}
if (getSizeNoTag() > expectedSize) { errorCode = 2 }
return this
}
fun parseFrom(input: CodedInputStream): DirectionResponse.BuilderDirectionResponse {
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
}
}
}
+36
View File
@@ -0,0 +1,36 @@
#include "communication.h"
#include <stddef.h>
#include <stdbool.h>
#include <usbd_cdc_vcp.h>
void send_int(int n)
{
int i = 0;
char* buffer = (char*) &n;
for (; i < sizeof(int); ++i) {
VCP_put_char(buffer[i]);
}
}
void send_buffer(int size, int pointer)
{
int i = 0;
send_int(size);
char* buffer = (char*) pointer;
for (; i < size; ++i) {
VCP_put_char(buffer[i]);
}
}
int receive_int()
{
return 0;
}
int receive_buffer()
{
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
void send_int(int i);
void send_buffer(int size, int pointer);
int receive_int();
int receive_buffer();
+1 -38
View File
@@ -5,46 +5,9 @@
#include "car_leds.h"
#include "car_rc.h"
#include "car_user_btn.h"
#include "communication.h"
#include "time.h"
#include "stm32f4xx_conf.h"
#include "stm32f4xx_it.h"
/* typedef enum { */
/* CAR_MODE_PROGRAMMED, */
/* CAR_MODE_REMOTE_CONTROL, */
/* CAR_MODE_LAST */
/* } CAR_MODE; */
/* static CAR_MODE cur_mode = CAR_MODE_PROGRAMMED; */
/* static __IO bool cur_mode_stop = false; */
/* void stop_cur_mode(void) */
/* { */
/* cur_mode_stop = true; */
/* } */
//int main(void)
//{
// /*!< At this stage the microcontroller clock setting is already configured,
// this is done through SystemInit() function which is called from startup
// file (startup_stm32f4xx.s) before to branch to application main.
// To reconfigure the default setting of SystemInit() function, refer to
// system_stm32f4xx.c file
// */
//
// /* time_init(); */
// /* leds_init(); */
// /* engine_init(); */
// /* user_btn_init(stop_cur_mode); */
// /* VCP_init(); */
//
// /* while(1) { */
// /* if (cur_mode == CAR_MODE_PROGRAMMED) */
// /* run_programmed_car(&cur_mode_stop); */
// /* else if(cur_mode == CAR_MODE_REMOTE_CONTROL) */
// /* run_rc_car(&cur_mode_stop); */
//
// /* cur_mode = (cur_mode + 1) % CAR_MODE_LAST; */
// /* cur_mode_stop = false; */
// /* } */
//}
@@ -32,7 +32,10 @@ class ObjectCodegen(state: TranslationState,
super.prepareForGenerate()
val classInstance = LLVMVariable("object.instance.$fullName", type, objectDeclaration.name, LLVMVariableScope(), pointer = 1)
codeBuilder.addGlobalInitialize(classInstance, type)
codeBuilder.addGlobalInitialize(classInstance, fields, initializedFields.map {
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, it.value)!!.type!!
Pair(it.key, state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, it.value)!!.getValue(type).toString())
}.toMap() , type)
variableManager.addGlobalVariable(fullName, classInstance)
}
@@ -35,6 +35,8 @@ abstract class StructCodegen(val state: TranslationState,
get() = "${if (type.location.size > 0) "${type.location.joinToString(".")}." else ""}$structName"
open fun prepareForGenerate() {
generateStruct()
for (declaration in classOrObject.declarations) {
when (declaration) {
is KtNamedFunction -> {
@@ -46,7 +48,6 @@ abstract class StructCodegen(val state: TranslationState,
}
open fun generate() {
generateStruct()
generateEnumFields()
generatePrimaryConstructor()
@@ -70,7 +71,7 @@ abstract class StructCodegen(val state: TranslationState,
field.offset = offset
offset++
if ((declaration.initializer != null) && this !is ObjectCodegen) {
if (declaration.initializer != null) {
initializedFields.put(field, declaration.initializer!!)
}
fields.add(field)
@@ -4,6 +4,7 @@ import org.kotlinnative.translator.llvm.types.LLVMCharType
import org.kotlinnative.translator.llvm.types.LLVMIntType
import org.kotlinnative.translator.llvm.types.LLVMStringType
import org.kotlinnative.translator.llvm.types.LLVMType
import java.util.*
class LLVMBuilder(val arm: Boolean = false) {
private val POINTER_SIZE = 4
@@ -81,8 +82,10 @@ class LLVMBuilder(val arm: Boolean = false) {
globalCode.appendln("$variable = private unnamed_addr constant ${type.fullType()} c\"$value\\00\", align 1")
}
fun addGlobalInitialize(target: LLVMVariable, classType: LLVMType) {
val code = "$target = internal global $classType zeroinitializer, align ${classType.align}"
fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) {
val code = "$target = internal global $classType { ${
fields.map { it.getType() + " " + if (initializers.containsKey(it)) initializers[it] else "0"}.joinToString()
} }, align ${classType.align}"
globalCode.appendln(code)
}
@@ -1 +1,2 @@
singleton_test_Int(5) == 40
singleton_test2() == 123456789
@@ -1,4 +1,7 @@
object Singleton {
val i: Int = 123456789
fun create(x : Int): Int {
return x * 8
}
@@ -7,3 +10,7 @@ object Singleton {
fun singleton_test(i: Int): Int {
return Singleton.create(i)
}
fun singleton_test2(): Int {
return Singleton.i
}