Compare commits

...

50 Commits

Author SHA1 Message Date
Anton Bannykh
37f85d24cd ~ switch by header, not field number 2019-09-24 16:18:06 +03:00
Anton Bannykh
26828aaaea ~ mimic proto deserializer 2019-09-24 13:21:31 +03:00
Anton Bannykh
7032e1e26e ~ js ast 2019-09-23 22:06:35 +03:00
Roman Artemev
85dd9766ce Something works 2019-09-20 11:24:31 +03:00
Anton Bannykh
097ede39e5 restore @exposed fields 2019-09-20 10:40:43 +03:00
Roman Artemev
ecfb7e1a8d Implement loops and fix annotations 2019-09-20 10:08:51 +03:00
Roman Artemev
cbcf88c4cc Make it work, support special built ins 2019-09-20 01:30:10 +03:00
Roman Artemev
c7b22e05ed Support origins and nullable expression 2019-09-20 01:12:02 +03:00
Roman Artemev
3d48ac03cf Implement statement one of 2019-09-19 23:50:15 +03:00
Roman Artemev
a6b1ea357b Implement IrClass/IrFunction/IrConstructor peroperly 2019-09-19 23:32:32 +03:00
Roman Artemev
68a66d6e5b fix origin 2019-09-19 23:32:32 +03:00
Anton Bannykh
9e1a82d2f2 Fix delayed optional fields 2019-09-19 23:32:11 +03:00
Anton Bannykh
e30653bcd6 @exposed and @order 2019-09-19 23:09:50 +03:00
Roman Artemev
343fa4c9f0 Replace proto parser with new NextGen parser in IrDeserializer 2019-09-19 22:52:59 +03:00
Roman Artemev
326578e735 keep moving 2019-09-19 21:37:24 +03:00
Roman Artemev
d69bf2174e Fix parsers factories 2019-09-19 21:16:04 +03:00
Anton Bannykh
5c8215338f Parse field directives 2019-09-19 20:55:37 +03:00
Roman Artemev
be4b5fa46b proto annotations 2019-09-19 20:43:53 +03:00
Anton Bannykh
fce17a3244 More inlines in SmartParser 2019-09-19 20:21:59 +03:00
Anton Bannykh
50be3a40cc More inlines 2019-09-19 20:19:57 +03:00
Roman Artemev
66fd120ff9 Keep implementing parser 2019-09-19 19:44:36 +03:00
Roman Artemev
5ecea8eb69 Fix benchmark 2019-09-19 19:44:36 +03:00
Roman Artemev
066e2855e5 Implement parsers factories 2019-09-19 19:44:36 +03:00
Roman Artemev
938c4c443d Implement draft of ir -> proto reader 2019-09-19 19:44:35 +03:00
Roman Artemev
c3afd908bc Fix return type of ir const builders 2019-09-19 19:44:35 +03:00
Anton Bannykh
1be3f0ac9f Support @inline messages + better names 2019-09-19 18:39:29 +03:00
Anton Bannykh
03eab7c28b Not-null oneOf parameters 2019-09-19 17:38:17 +03:00
Anton Bannykh
66545c4d9a Update Smart to oneOf support 2019-09-19 17:33:36 +03:00
Anton Bannykh
8fe16db21c Support oneof 2019-09-19 17:31:27 +03:00
Anton Bannykh
669491dbbd Update SimpleIrProtoReader to share the same implementation as Smart... 2019-09-19 17:31:26 +03:00
Roman Artemev
73b786f194 Fix generator 2019-09-19 16:13:10 +03:00
Anton Bannykh
08a89be74d Ir serializer 2019-09-19 15:34:32 +03:00
Anton Bannykh
1194daa102 Support default values 2019-09-19 15:03:35 +03:00
Roman Artemev
2984109836 Add fqn to type mapping 2019-09-19 15:02:17 +03:00
Roman Artemev
6754f568fb Implement carriers 2019-09-19 14:38:52 +03:00
Roman Artemev
842bb2f12b Temporary use carrier structures 2019-09-19 14:21:29 +03:00
Roman Artemev
8ba79fb73a Add proto typemapping 2019-09-19 14:10:01 +03:00
Roman Artemev
ccb6de0abb Add nextgen parser benchmarks 2019-09-19 12:53:50 +03:00
Roman Artemev
7f0575b537 Add proto micro benchmark 2019-09-19 12:49:29 +03:00
Anton Bannykh
e64a61612f Fix message field reading; fix negative int32 parsing 2019-09-19 12:34:01 +03:00
Anton Bannykh
e5e3383d53 Fix repeated field list population 2019-09-19 11:43:52 +03:00
Anton Bannykh
020816721e Simple deserializer 2019-09-19 11:33:46 +03:00
Anton Bannykh
7eb085eeee Parse .proto file 2019-09-18 23:40:04 +03:00
Roman Artemev
87c1c65ebb Implement FqName reader
support string table
2019-09-18 18:35:49 +03:00
Anton Bannykh
7d889d842b DataIndex + skip unknown fields 2019-09-18 18:30:28 +03:00
Roman Artemev
cd38b79879 Support Coordinates 2019-09-18 18:10:46 +03:00
Roman Artemev
4ca7a7e525 Fix int32 reader 2019-09-18 18:10:34 +03:00
Anton Bannykh
75b2bd0b0f IrProtoReader reads FileEntry 2019-09-18 17:14:03 +03:00
Anton Bannykh
dd3b36030f repeated 2019-09-18 16:23:22 +03:00
Anton Bannykh
0e9ffa79b9 Basic proto parsing + tests 2019-09-18 16:10:19 +03:00
25 changed files with 13966 additions and 149 deletions

View File

@@ -57,22 +57,22 @@ class IrConstImpl<T>(
fun constFalse(startOffset: Int, endOffset: Int, type: IrType): IrConstImpl<Boolean> =
boolean(startOffset, endOffset, type, false)
fun long(startOffset: Int, endOffset: Int, type: IrType, value: Long): IrExpression =
fun long(startOffset: Int, endOffset: Int, type: IrType, value: Long): IrConst<Long> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, value)
fun float(startOffset: Int, endOffset: Int, type: IrType, value: Float): IrExpression =
fun float(startOffset: Int, endOffset: Int, type: IrType, value: Float): IrConst<Float> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Float, value)
fun double(startOffset: Int, endOffset: Int, type: IrType, value: Double): IrExpression =
fun double(startOffset: Int, endOffset: Int, type: IrType, value: Double): IrConst<Double> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Double, value)
fun char(startOffset: Int, endOffset: Int, type: IrType, value: Char): IrExpression =
fun char(startOffset: Int, endOffset: Int, type: IrType, value: Char): IrConst<Char> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Char, value)
fun byte(startOffset: Int, endOffset: Int, type: IrType, value: Byte): IrExpression =
fun byte(startOffset: Int, endOffset: Int, type: IrType, value: Byte): IrConst<Byte> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Byte, value)
fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrExpression =
fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrConst<Short> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Short, value)
}
}

View File

@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.min
class ExternalDependenciesGenerator(
@@ -73,17 +75,17 @@ class ExternalDependenciesGenerator(
deserializer?.declareForwardDeclarations()
assertEmpty(symbolTable.unboundClasses, "classes")
assertEmpty(symbolTable.unboundConstructors, "constructors")
assertEmpty(symbolTable.unboundEnumEntries, "enum entries")
assertEmpty(symbolTable.unboundFields, "fields")
assertEmpty(symbolTable.unboundSimpleFunctions, "simple functions")
assertEmpty(symbolTable.unboundProperties, "properties")
assertEmpty(symbolTable.unboundTypeParameters, "type parameters")
assertEmpty(symbolTable.unboundTypeAliases, "type aliases")
assertEmpty(symbolTable.unboundClasses.filter { !it.isBound }, "classes")
assertEmpty(symbolTable.unboundConstructors.filter { !it.isBound }, "constructors")
assertEmpty(symbolTable.unboundEnumEntries.filter { !it.isBound }, "enum entries")
assertEmpty(symbolTable.unboundFields.filter { !it.isBound }, "fields")
assertEmpty(symbolTable.unboundSimpleFunctions.filter { !it.isBound }, "simple functions")
assertEmpty(symbolTable.unboundProperties.filter { !it.isBound }, "properties")
assertEmpty(symbolTable.unboundTypeParameters.filter { !it.isBound }, "type parameters")
assertEmpty(symbolTable.unboundTypeAliases.filter { !it.isBound }, "type aliases")
}
private fun assertEmpty(s: Set<IrSymbol>, marker: String) {
private fun assertEmpty(s: Collection<IrSymbol>, marker: String) {
assert(s.isEmpty()) {
"$marker: ${s.size} unbound:\n" +
s.toList().subList(0, min(10, s.size)).joinToString(separator = "\n") { it.descriptor.toString() }

View File

@@ -8,10 +8,11 @@ dependencies {
compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:ir.tree"))
compile(project(":kotlin-util-klib"))
testCompile(commonDep("junit:junit"))
}
sourceSets {
"main" { projectDefault() }
"test" {}
"test" { projectDefault() }
}

View File

@@ -26,6 +26,7 @@ message UniqId {
}
message Coordinates {
/* @inline */
required int32 start_offset = 1;
required int32 end_offset = 2;
}
@@ -227,6 +228,7 @@ message IrBlock {
}
message MemberAccessCommon {
/* @inline */
optional IrExpression dispatch_receiver = 1;
optional IrExpression extension_receiver = 2;
repeated NullableIrExpression value_argument = 3;
@@ -322,6 +324,7 @@ message IrGetEnumValue {
}
message FieldAccessCommon {
/* @inline */
required IrDataIndex symbol = 1;
optional IrDataIndex super = 2;
optional IrExpression receiver = 3;
@@ -346,10 +349,11 @@ message IrInstanceInitializerCall {
}
message Loop {
/* @inline */
required int32 loop_id = 1;
required IrExpression condition = 2;
optional IrDataIndex label = 3;
optional IrExpression body = 4;
optional IrExpression body = 4 /* @order_1 */;
optional IrStatementOrigin origin = 5;
}
@@ -525,8 +529,8 @@ enum IrTypeOperator {
message IrExpression {
required IrOperation operation = 1;
required IrDataIndex type = 2;
required Coordinates coordinates = 3;
required IrDataIndex type = 2 /* @exposed */;
required Coordinates coordinates = 3 /* @exposed */;
}
message NullableIrExpression {
@@ -536,6 +540,7 @@ message NullableIrExpression {
/* ------ Declarations --------------------------------------------- */
message IrDeclarationBase {
/* @inline */
required IrDataIndex symbol = 1;
required IrDeclarationOrigin origin = 2;
required Coordinates coordinates = 3;
@@ -543,16 +548,17 @@ message IrDeclarationBase {
}
message IrFunctionBase {
/* @inline */
required IrDeclarationBase base = 1;
required IrDataIndex name = 2;
required Visibility visibility = 3;
required bool is_inline = 4;
required bool is_external = 5;
required IrTypeParameterContainer type_parameters = 6;
optional IrValueParameter dispatch_receiver = 7;
optional IrValueParameter extension_receiver = 8;
repeated IrValueParameter value_parameter = 9;
optional IrDataIndex body = 10;
required IrTypeParameterContainer type_parameters = 6 /* @order_1 */;
optional IrValueParameter dispatch_receiver = 7 /* @order_1 */;
optional IrValueParameter extension_receiver = 8 /* @order_1 */;
repeated IrValueParameter value_parameter = 9 /* @order_1 */;
optional IrDataIndex body = 10 /* @order_1 */;
required IrDataIndex return_type = 11;
}
@@ -669,9 +675,9 @@ message IrClass {
required bool is_data = 8;
required bool is_external = 9;
required bool is_inline = 10;
optional IrValueParameter this_receiver = 11;
required IrTypeParameterContainer type_parameters = 12;
required IrDeclarationContainer declaration_container = 13;
optional IrValueParameter this_receiver = 11 /* @order_1 */;
required IrTypeParameterContainer type_parameters = 12 /* @order_1 */;
required IrDeclarationContainer declaration_container = 13 /* @order_2 */;
repeated IrDataIndex super_type = 14;
}
@@ -743,7 +749,7 @@ message IrSyntheticBody {
// Let's try to map IrElement as well as IrStatement to IrStatement.
message IrStatement {
required Coordinates coordinates = 1;
required Coordinates coordinates = 1 /* @exposed */;
oneof statement {
IrDeclaration declaration = 2;
IrExpression expression = 3;

View File

@@ -12,14 +12,14 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConst.ValueCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration.DeclaratorCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrOperation.OperationCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement.StatementCase
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType.KindCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeArgument.KindCase.STAR
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeArgument.KindCase.TYPE
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVarargElement.VarargElementCase
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrConst.ValueCase.*
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDeclaration.DeclaratorCase.*
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrOperation.OperationCase.*
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrStatement.StatementCase
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrType.KindCase.*
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeArgument.KindCase.STAR
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeArgument.KindCase.TYPE
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrVarargElement.VarargElementCase
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -39,87 +39,87 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeParameterDescriptor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.backend.common.serialization.proto.Annotations as ProtoAnnotations
import org.jetbrains.kotlin.backend.common.serialization.proto.ClassKind as ProtoClassKind
import org.jetbrains.kotlin.backend.common.serialization.proto.DescriptorReference as ProtoDescriptorReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrAnonymousInit as ProtoAnonymousInit
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoBodyIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBranch as ProtoBranch
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBreak as ProtoBreak
import org.jetbrains.kotlin.backend.common.serialization.proto.IrCall as ProtoCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrCatch as ProtoCatch
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClassReference as ProtoClassReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrComposite as ProtoComposite
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConst as ProtoConst
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructor as ProtoConstructor
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrContinue as ProtoContinue
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationBase as ProtoDeclarationBase
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationOrigin as ProtoDeclarationOrigin
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDelegatingConstructorCall as ProtoDelegatingConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDoWhile as ProtoDoWhile
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicMemberExpression as ProtoDynamicMemberExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicOperatorExpression as ProtoDynamicOperatorExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicType as ProtoDynamicType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumEntry as ProtoEnumEntry
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorType as ProtoErrorType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrField as ProtoField
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunction as ProtoFunction
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionBase as ProtoFunctionBase
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionExpression as ProtoFunctionExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionReference as ProtoFunctionReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetClass as ProtoGetClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetEnumValue as ProtoGetEnumValue
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetField as ProtoGetField
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetObject as ProtoGetObject
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetValue as ProtoGetValue
import org.jetbrains.kotlin.backend.common.serialization.proto.IrInstanceInitializerCall as ProtoInstanceInitializerCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrLocalDelegatedProperty as ProtoLocalDelegatedProperty
import org.jetbrains.kotlin.backend.common.serialization.proto.IrLocalDelegatedPropertyReference as ProtoLocalDelegatedPropertyReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrOperation as ProtoOperation
import org.jetbrains.kotlin.backend.common.serialization.proto.IrProperty as ProtoProperty
import org.jetbrains.kotlin.backend.common.serialization.proto.IrPropertyReference as ProtoPropertyReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrReturn as ProtoReturn
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSetField as ProtoSetField
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSetVariable as ProtoSetVariable
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSimpleType as ProtoSimpleType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSpreadElement as ProtoSpreadElement
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatementOrigin as ProtoStatementOrigin
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStringConcat as ProtoStringConcat
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoSymbolIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSyntheticBody as ProtoSyntheticBody
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSyntheticBodyKind as ProtoSyntheticBodyKind
import org.jetbrains.kotlin.backend.common.serialization.proto.IrThrow as ProtoThrow
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTry as ProtoTry
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeAbbreviation as ProtoTypeAbbreviation
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeAlias as ProtoTypeAlias
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeArgument as ProtoTypeArgument
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoTypeIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeOp as ProtoTypeOp
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeOperator as ProtoTypeOperator
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeParameter as ProtoTypeParameter
import org.jetbrains.kotlin.backend.common.serialization.proto.IrTypeVariance as ProtoTypeVariance
import org.jetbrains.kotlin.backend.common.serialization.proto.IrValueParameter as ProtoValueParameter
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVararg as ProtoVararg
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVarargElement as ProtoVarargElement
import org.jetbrains.kotlin.backend.common.serialization.proto.IrVariable as ProtoVariable
import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhen as ProtoWhen
import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhile as ProtoWhile
import org.jetbrains.kotlin.backend.common.serialization.proto.Loop as ProtoLoop
import org.jetbrains.kotlin.backend.common.serialization.proto.MemberAccessCommon as ProtoMemberAccessCommon
import org.jetbrains.kotlin.backend.common.serialization.proto.ModalityKind as ProtoModalityKind
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoStringIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.TypeArguments as ProtoTypeArguments
import org.jetbrains.kotlin.backend.common.serialization.proto.Visibility as ProtoVisibility
import org.jetbrains.kotlin.backend.common.serialization.proto.FqName as ProtoFqName
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.Annotations as ProtoAnnotations
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.ClassKind as ProtoClassKind
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.DescriptorReference as ProtoDescriptorReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrAnonymousInit as ProtoAnonymousInit
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrBlock as ProtoBlock
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoBodyIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrBlockBody as ProtoBlockBody
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrBranch as ProtoBranch
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrBreak as ProtoBreak
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrCall as ProtoCall
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrCatch as ProtoCatch
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrClass as ProtoClass
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrClassReference as ProtoClassReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrComposite as ProtoComposite
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrConst as ProtoConst
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrConstructor as ProtoConstructor
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrConstructorCall as ProtoConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrContinue as ProtoContinue
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDeclarationBase as ProtoDeclarationBase
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDeclarationOrigin as ProtoDeclarationOrigin
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDelegatingConstructorCall as ProtoDelegatingConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDoWhile as ProtoDoWhile
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDynamicMemberExpression as ProtoDynamicMemberExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDynamicOperatorExpression as ProtoDynamicOperatorExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDynamicType as ProtoDynamicType
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrEnumConstructorCall as ProtoEnumConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrEnumEntry as ProtoEnumEntry
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrErrorType as ProtoErrorType
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrField as ProtoField
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrFunction as ProtoFunction
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrFunctionBase as ProtoFunctionBase
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrFunctionExpression as ProtoFunctionExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrFunctionReference as ProtoFunctionReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrGetClass as ProtoGetClass
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrGetEnumValue as ProtoGetEnumValue
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrGetField as ProtoGetField
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrGetObject as ProtoGetObject
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrGetValue as ProtoGetValue
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrInstanceInitializerCall as ProtoInstanceInitializerCall
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrLocalDelegatedProperty as ProtoLocalDelegatedProperty
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrLocalDelegatedPropertyReference as ProtoLocalDelegatedPropertyReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrOperation as ProtoOperation
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrProperty as ProtoProperty
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrPropertyReference as ProtoPropertyReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrReturn as ProtoReturn
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSetField as ProtoSetField
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSetVariable as ProtoSetVariable
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSimpleType as ProtoSimpleType
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSpreadElement as ProtoSpreadElement
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrStatement as ProtoStatement
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrStatementOrigin as ProtoStatementOrigin
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrStringConcat as ProtoStringConcat
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoSymbolIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSyntheticBody as ProtoSyntheticBody
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSyntheticBodyKind as ProtoSyntheticBodyKind
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrThrow as ProtoThrow
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTry as ProtoTry
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrType as ProtoType
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeAbbreviation as ProtoTypeAbbreviation
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeAlias as ProtoTypeAlias
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeArgument as ProtoTypeArgument
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoTypeIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeOp as ProtoTypeOp
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeOperator as ProtoTypeOperator
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeParameter as ProtoTypeParameter
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrTypeVariance as ProtoTypeVariance
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrValueParameter as ProtoValueParameter
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrVararg as ProtoVararg
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrVarargElement as ProtoVarargElement
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrVariable as ProtoVariable
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrWhen as ProtoWhen
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrWhile as ProtoWhile
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.Loop as ProtoLoop
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.MemberAccessCommon as ProtoMemberAccessCommon
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.ModalityKind as ProtoModalityKind
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoStringIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.TypeArguments as ProtoTypeArguments
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.Visibility as ProtoVisibility
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.FqName as ProtoFqName
// TODO: This code still has some uses of descriptors:
// 1. We use descriptors as keys for symbolTable -- probably symbol table related code should be refactored out from
@@ -631,7 +631,7 @@ abstract class IrFileDeserializer(
catches.add(deserializeStatement(it) as IrCatch)
}
val finallyExpression =
if (proto.hasFinally()) deserializeExpression(proto.getFinally()) else null
if (proto.hasFinally()) deserializeExpression(proto.finally) else null
return IrTryImpl(start, end, type, result, catches, finallyExpression)
}

View File

@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoBodyIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrProtoReaderMimic
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoBodyIndex
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.IrElement
@@ -31,23 +32,23 @@ import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.backend.common.serialization.proto.Annotations as ProtoAnnotations
import org.jetbrains.kotlin.backend.common.serialization.proto.DescriptorReference as ProtoDescriptorReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoSymbolIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSymbolData as ProtoSymbolData
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSymbolKind as ProtoSymbolKind
import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoTypeIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex as ProtoStringIndex
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.Annotations as ProtoAnnotations
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.DescriptorReference as ProtoDescriptorReference
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrFile as ProtoFile
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoSymbolIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSymbolData as ProtoSymbolData
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrSymbolKind as ProtoSymbolKind
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrType as ProtoType
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoTypeIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrDataIndex as ProtoStringIndex
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrStatement as ProtoStatement
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.protoMimic.UniqId as ProtoUniqId
abstract class KotlinIrLinker(
val logger: LoggingContext,
@@ -157,28 +158,28 @@ abstract class KotlinIrLinker(
}
private fun loadTopLevelDeclarationProto(uniqId: UniqId): ProtoDeclaration {
val stream = reader(moduleDescriptor, fileIndex, uniqId).codedInputStream
return ProtoDeclaration.parseFrom(stream, newInstance())
val byteArray = reader(moduleDescriptor, fileIndex, uniqId)
return IrProtoReaderMimic(byteArray).readIrDeclaration()
}
private fun loadSymbolProto(index: Int): ProtoSymbolData {
val stream = readSymbol(moduleDescriptor, fileIndex, index).codedInputStream
return ProtoSymbolData.parseFrom(stream, newInstance())
val byteArray = readSymbol(moduleDescriptor, fileIndex, index)
return IrProtoReaderMimic(byteArray).readIrSymbolData()
}
private fun loadTypeProto(index: Int): ProtoType {
val stream = readType(moduleDescriptor, fileIndex, index).codedInputStream
return ProtoType.parseFrom(stream, newInstance())
val byteArray = readType(moduleDescriptor, fileIndex, index)
return IrProtoReaderMimic(byteArray).readIrType()
}
private fun loadStatementBodyProto(index: Int): ProtoStatement {
val stream = readBody(moduleDescriptor, fileIndex, index).codedInputStream
return ProtoStatement.parseFrom(stream, newInstance())
val byteArray = readBody(moduleDescriptor, fileIndex, index)
return IrProtoReaderMimic(byteArray).readIrStatement()
}
private fun loadExpressionBodyProto(index: Int): ProtoExpression {
val stream = readBody(moduleDescriptor, fileIndex, index).codedInputStream
return ProtoExpression.parseFrom(stream, newInstance())
val byteArray = readBody(moduleDescriptor, fileIndex, index)
return IrProtoReaderMimic(byteArray).readIrExpression()
}
private fun loadStringProto(index: Int): String {
@@ -444,7 +445,7 @@ abstract class KotlinIrLinker(
val files = mutableListOf<IrFile>()
for (i in 0 until fileCount) {
files.add(deserializeIrFile(ProtoFile.parseFrom(readFile(moduleDescriptor, i), newInstance()), i))
files.add(deserializeIrFile(IrProtoReaderMimic(readFile(moduleDescriptor, i)).readIrFile(), i))
}
@@ -625,3 +626,5 @@ enum class DeserializationStrategy(val needBodies: Boolean, val explicitlyExport
EXPLICITLY_EXPORTED(true, true, false),
ONLY_DECLARATION_HEADERS(false, false, false)
}
private fun ProtoUniqId.uniqId(): UniqId = UniqId(this.index, this.isLocal)

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
class DeclarationBaseCarrier(
val symbolId: Int,
val origin: IrDeclarationOrigin,
val coordinates: CoordinatesCarrier,
val annotations: List<IrConstructorCall>
)
class FunctionBaseCarrier(
val declarationBaseCarrier: DeclarationBaseCarrier,
val nameId: Int,
val visibility: Visibility,
val isInline: Boolean,
val isExternal: Boolean,
val typeParameters: List<IrTypeParameter>,
val dispathReceiver: IrValueParameter?,
val extensionReceiver: IrValueParameter?,
val valueParameters: List<IrValueParameter>,
val bodyIndex: Int?,
val returnTypeIndex: Int
)
class MemberAccessCarrier(
val dispatchReceiver: IrExpression?,
val extensionReceiver: IrExpression?,
val valueArguments: List<IrExpression>,
val typeArguments: List<IrType>
)
class FieldAccessCarrier(val symbolId: Int, val superId: Int?, val receiver: IrExpression?)
class LoopCarrier(val loopId: Int, val condition: IrExpression, val label: Int?, val body: IrExpression?, val origin: IrStatementOrigin?)
class CoordinatesCarrier(val start: Int, val end: Int)
class NullableExpression(val expression: IrExpression?)

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.name.FqName
import java.lang.StringBuilder
abstract class IrProtoReader(source: ByteArray) : ProtoReader(source) {
protected abstract fun readStringById(id: Int): String
fun readDataIndex(): Int {
var result = 0
while (hasData) {
readField { fieldNumber, type ->
when (fieldNumber) {
1 -> result = readInt32()
else -> skip(type)
}
}
}
return result
}
fun readFqName(): FqName {
val stringBuilder = StringBuilder()
while (hasData) {
readField { fieldNumber, _ ->
assert(fieldNumber == 1)
if (stringBuilder.isNotEmpty()) stringBuilder.append('.')
val stringId = readWithLength { readDataIndex() }
stringBuilder.append(readStringById(stringId))
}
}
return if (stringBuilder.isEmpty()) FqName.ROOT else FqName(stringBuilder.toString())
}
fun readCoordinates(): Pair<Int, Int> {
var start = -1
var end = -1
while (hasData) {
readField { fieldNumber, type ->
when (fieldNumber) {
1 -> start = readInt32()
2 -> end = readInt32()
else -> skip(type)
}
}
}
return Pair(start, end)
}
fun readFileEntry(): NaiveSourceBasedFileEntryImpl {
var name: String? = null
val offsets = mutableListOf<Int>()
while (hasData) {
readField { fieldNumber, type ->
when (fieldNumber) {
1 -> name = readString()
2 -> offsets += readInt32()
else -> skip(type)
}
}
}
return NaiveSourceBasedFileEntryImpl(name!!, offsets.toIntArray())
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
open class ProtoReader(
val source: ByteArray,
var offset: Int = 0
) {
var currentEnd = source.size
val hasData: Boolean
get() = offset < currentEnd
inline fun <T> readWithLength(block: () -> T): T {
val length = readInt32()
val oldEnd = currentEnd
currentEnd = offset + length
try {
return block()
} finally {
currentEnd = oldEnd
}
}
private fun nextByte(): Byte {
if (!hasData) error("Oops")
return source[offset++]
}
private fun readVarint64(): Long {
var result = 0L
var shift = 0
while (true) {
val b = nextByte().toInt()
result = result or ((b and 0x7F).toLong() shl shift)
shift += 7
if ((b and 0x80) == 0) break
}
if (shift > 70) {
error("int64 overflow $shift")
}
return result
}
private fun readVarint32(): Int {
var result = 0
var shift = 0
while (true) {
val b = nextByte().toInt()
result = result or ((b and 0x7F) shl shift)
shift += 7
if ((b and 0x80) == 0) break
}
if (shift > 70) {
error("int32 overflow $shift")
}
return result
}
fun readInt32(): Int = readVarint32()
fun readInt64(): Long = readVarint64()
fun readBool(): Boolean = readVarint32() != 0
fun readFloat(): Float {
var bits = nextByte().toInt()
bits = (bits shl 8) or nextByte().toInt()
bits = (bits shl 8) or nextByte().toInt()
bits = (bits shl 8) or nextByte().toInt()
return Float.fromBits(bits)
}
fun readDouble(): Double {
var bits = nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
bits = (bits shl 8) or nextByte().toLong()
return Double.fromBits(bits)
}
fun readString(): String {
val length = readInt32()
val result = String(source, offset, length)
offset += length
return result
}
inline fun <T> readField(block: (fieldNumber: Int, type: Int) -> T): T {
val wire = readInt32()
val fieldNumber = wire ushr 3
val wireType = wire and 0x7
return block(fieldNumber, wireType)
}
fun skip(type: Int) {
when (type) {
0 -> readInt64()
1 -> offset += 8
2 -> {
val len = readInt32()
offset += len
}
3, 4 -> error("groups")
5 -> offset += 4
}
}
inline fun <T> delayed(o: Int, block: () -> T): T {
val oldOffset = offset
try {
offset = o
return block()
} finally {
offset = oldOffset
}
}
}

View File

@@ -0,0 +1,551 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import org.jetbrains.kotlin.backend.common.atMostOne
import java.lang.StringBuilder
fun List<Proto>.createIrDeserializer(classMap: Map<String, String>, isSimple: Boolean): String {
return IrDeserializerPrinter(this, classMap, isSimple).buildDeclaration()
}
private class IrDeserializerPrinter(
val protoList: List<Proto>,
importMap_: Map<String, String>,
val isSimple: Boolean
) {
val importMap = if (!isSimple) importMap_ else importMap_.keys.associate { it to "kotlin.Any" }
val typeMap: Map<String, Proto> = protoList.associate { it.name to it }
private fun String.typeParameters(): String {
val index = indexOf('<')
return if (index < 0) "" else substring(index)
}
private fun String.noTypeParameters(): String {
val index = indexOf('<')
return if (index < 0) this else substring(0, index)
}
private val String.isBuiltin: Boolean
get() = this.startsWith("kotlin.")
val classMap: Map<String, String> = importMap.entries.associate { (k, v) ->
k to if (v.isBuiltin) {
v.noTypeParameters().let {
it.substring(it.lastIndexOf('.') + 1)
} + v.typeParameters()
} else {
k + "MessageType" + v.typeParameters()
}
} + mapOf(
"int32" to "Int",
"int64" to "Long",
"uint64" to "Long",
"string" to "String",
"bool" to "Boolean",
"float" to "Float",
"double" to "Double"
)
fun buildDeclaration(): String {
val sb = StringBuilder()
importMap.entries.map { (k, v) ->
if (!v.isBuiltin) {
"import ${v.noTypeParameters()} as ${k}MessageType"
} else {
"import ${v.noTypeParameters()}"
}
}.toSet().forEach {
sb.appendln(it)
}
sb.appendln()
val prefix = if (isSimple) "" else "abstract "
val name = if (isSimple) "SimpleIr" else "AbstractIrSmart"
sb.appendln("${prefix}class ${name}ProtoReader(source: ByteArray) : ProtoReader(source) {")
protoList.forEach { sb.addAbstractFactory(it) }
protoList.filterIsInstance<Proto.Message>().forEach { sb.addMessage(it) }
sb.appendln("}")
return sb.toString()
}
private fun String.escape(): String {
val result = this.split('_').fold("") { acc, c ->
if (c.isEmpty()) acc else {
if (acc.isEmpty()) {
c[0].toLowerCase() + c.substring(1)
} else {
acc + c[0].toUpperCase() + c.substring(1)
}
}
}
return result + (if (result in setOf(
"super",
"this",
"null",
"break",
"continue",
"while",
"for",
"return",
"throw",
"try",
"when",
"hasData",
"fieldNumber",
"type"
)
) "_" else "")
}
private fun StringBuilder.addAbstractFactory(p: Proto) {
val maybeAbstract = if (isSimple) "" else "abstract "
when (p) {
is Proto.Enum -> {
val impl = if (isSimple) " = index" else ""
appendln(" ${maybeAbstract}fun create${p.name}(index: Int): ${p.name.ktType}${impl}")
}
is Proto.Message -> {
if (p.isInline) return
val names = mutableMapOf<MessageEntry, String>()
names += p.fields.buildNames("")
fun addMessage(index: Int, suffix: String, fields: List<MessageEntry.Field>) {
val actualSuffix = if (index != 0) "" + index + suffix else suffix
append(" ${maybeAbstract}fun create${p.name}${actualSuffix}(")
fields.forEachIndexed { i, f ->
if (i != 0) {
append(", ")
} else if (index != 0) {
append("partial: ${p.name.ktType}, ")
}
val type = when (f.kind) {
FieldKind.REPEATED -> "List<${f.type.ktType}>"
FieldKind.REQUIRED, FieldKind.ONE_OF -> f.type.ktType
else -> "${f.type.ktType}?"
}
append("${names[f]!!} : $type")
}
val impl = if (!isSimple) "" else {
val args = fields.fold("") { acc, c ->
(if (acc == "") "" else acc + ", ") + names[c]!!
}
" = arrayOf<Any?>($args)"
}
appendln("): ${p.name.ktType}$impl")
}
val fieldsByOrder = p.fields.inlined().splitByOrder()
fieldsByOrder.forEachIndexed { i, allFields ->
if (allFields.any { it is MessageEntry.OneOf }) {
val o =
allFields.filterIsInstance<MessageEntry.OneOf>().singleOrNull()
?: error("Too many oneof's in message ${p.name}")
val (fp, fs) = allFields.splitBy(o)
for (of in o.fields.inlined()) {
of as MessageEntry.Field
addMessage(i, "_${of.name.escape()}", fp + of + fs)
}
} else {
addMessage(i, "", allFields.map { it as MessageEntry.Field })
}
}
}
}
appendln()
}
val MessageEntry.order: Int
get() = (this as? MessageEntry.Field)?.directives?.atMostOne { it.startsWith("@order_") }?.substring("@order_".length)?.toInt()
?: 0
private fun List<MessageEntry>.splitByOrder(): List<List<MessageEntry>> {
return this.groupBy { it.order }.entries.sortedBy { (k, _) -> k }.map { (_, v) -> v }
}
val Proto.Message.isInline: Boolean
get() = "@inline" in this.directives
val MessageEntry.Field.isInline: Boolean
get() = type in typeMap && (typeMap[type]!! as? Proto.Message)?.isInline == true
fun List<MessageEntry>.inlined(): List<MessageEntry> {
return this.flatMap {
if (it is MessageEntry.Field && it.isInline) {
(typeMap[it.type] as Proto.Message).fields.inlined()
} else listOf(it)
}
}
private fun List<MessageEntry>.splitBy(of: MessageEntry.OneOf): Pair<List<MessageEntry.Field>, List<MessageEntry.Field>> {
val fp = mutableListOf<MessageEntry.Field>()
val fs = mutableListOf<MessageEntry.Field>()
var cf = fp
this.forEach {
if (it === of) {
cf = fs
} else {
cf.add(it as MessageEntry.Field)
}
}
return fp to fs
}
private val String.ktType: String
get() = classMap[this] ?: error("No known Kotlin type for '$this'")
private val String.zeroValue: String?
get() = when (this) {
"int32" -> "0"
"int64" -> "0L"
"uint64" -> "0L"
"string" -> "\"\""
"bool" -> "false"
"float" -> "0.0f"
"double" -> "0.0"
else -> null
}
private fun String.toReaderInvocation(): String {
return typeMap.get(this)?.let {
when (it) {
is Proto.Enum -> "create${it.name}(readInt32())"
is Proto.Message -> "readWithLength { read${it.name}() }"
}
} ?: run {
when (this) {
"int32" -> "readInt32()"
"int64", "uint64" -> "readInt64()"
"string" -> "readString()"
"bool" -> "readBool()"
"float" -> "readFloat()"
"double" -> "readDouble()"
else -> error("Unknown type: ${this}")
}
}
}
private val List<MessageEntry>.oneOfInlined: List<MessageEntry.Field>
get() = flatMap {
when (it) {
is MessageEntry.OneOf -> it.fields
is MessageEntry.Field -> listOf(it)
}
}
fun List<MessageEntry>.buildNames(prefix: String): MutableMap<MessageEntry.Field, String> {
val result = mutableMapOf<MessageEntry.Field, String>()
forEach { f ->
when (f) {
is MessageEntry.Field -> {
if (f.isInline) {
val msg = typeMap[f.type] as Proto.Message
result += msg.fields.buildNames((prefix + "_" + f.name).escape())
} else {
result[f] = (prefix + "_" + f.name).escape()
}
}
is MessageEntry.OneOf -> {
result += f.fields.buildNames(prefix + "OneOf")
}
}
}
return result
}
val MessageEntry.Field.isExposed: Boolean
get() = "@exposed" in this.directives
private fun List<MessageEntry>.buildExposedSet(exposeAll: Boolean = false): List<MessageEntry.Field> {
val result = mutableListOf<MessageEntry.Field>()
forEach { f ->
when (f) {
is MessageEntry.Field -> {
if (exposeAll || f.isExposed) {
if (f.isInline) {
result += (typeMap[f.type] as Proto.Message).fields.buildExposedSet(true)
} else {
result += f
}
}
}
is MessageEntry.OneOf -> {
result += f.fields.buildExposedSet(exposeAll)
}
}
}
return result
}
private fun StringBuilder.addMessage(m: Proto.Message) {
if (m.isInline) return
val exposedFields = m.fields.buildExposedSet()
val allFields = m.fields.inlined().oneOfInlined.inlined().oneOfInlined // TODO
val names = m.fields.buildNames("")
fun getName(field: MessageEntry.Field): String {
return names[field]!!
}
allFields.fold(mutableMapOf<String, Int>()) { acc, c ->
val name = getName(c)
acc[name] = acc.getOrDefault(name, 0) + 1
acc
}.entries.forEach { (name, cnt) ->
if (cnt > 1) {
error("Duplication name '$name' in ${m.name}")
}
}
val exposedName = mutableMapOf<MessageEntry.Field, String>()
if (exposedFields.isNotEmpty()) {
for (f in exposedFields) {
val name = "field_${m.name}_${getName(f)}".escape()
exposedName[f] = name
f.type.zeroValue?.let {
appendln(" protected var $name: ${f.type.ktType} = ${it}")
} ?: appendln(" protected var $name: ${f.type.ktType}? = null")
}
appendln()
}
appendln(" open fun read${m.name}(): ${m.name.ktType} {")
val iterations = allFields.groupBy { if (it in exposedFields) -1 else it.order }.entries.sortedBy { (k, _) -> k }.map { (_, v) -> v }.filter { !it.isEmpty() }
val fieldToIteration = mutableMapOf<MessageEntry.Field, Int>()
iterations.forEachIndexed { index, list ->
list.forEach { fieldToIteration[it] = index }
}
val nullableFields = mutableSetOf<MessageEntry.Field>()
val delayedReads = mutableSetOf<MessageEntry.Field>()
allFields.forEach { f ->
val (type, initExpression) = if (f.kind == FieldKind.REPEATED) {
"MutableList<${f.type.ktType}>" to "mutableListOf()"
} else {
val zero = f.type.zeroValue
if (f.kind == FieldKind.OPTIONAL && f.defaultValue != null) {
f.type.ktType to f.defaultValue
} else if (f.kind == FieldKind.REQUIRED && zero != null) {
f.type.ktType to zero
} else {
nullableFields.add(f)
"${f.type.ktType}?" to "null"
}
}
appendln(" var ${getName(f)}: $type = $initExpression")
if (fieldToIteration[f] != 0 && typeMap[f.type] is Proto.Message) {
delayedReads += f
if (f.kind == FieldKind.REPEATED) {
appendln(" var ${getName(f)}OffsetList: MutableList<Int> = arrayListOf()")
} else {
appendln(" var ${getName(f)}Offset: Int = -1")
}
}
}
val of = m.fields.inlined().filterIsInstance<MessageEntry.OneOf>().singleOrNull()?.let { of ->
appendln(" var oneOfIndex: Int = -1")
of
}
fun readFields(shift: String, fields: List<MessageEntry.Field>) {
appendln("${shift}while (hasData) {")
appendln("${shift} readField { fieldNumber, type -> ")
appendln("${shift} when (fieldNumber) {")
val indent = "${shift} "
fields.forEach { f ->
if (f.isInline) {
appendln("${indent}${f.index} -> readWithLength {")
readFields("${indent} ", (typeMap[f.type] as Proto.Message).fields.oneOfInlined)
appendln("${indent}}")
} else {
val readExpression = f.type.toReaderInvocation()
if (f.kind == FieldKind.REPEATED) {
if (f in delayedReads) {
appendln("${indent}${f.index} -> {")
appendln("${indent} ${getName(f)}OffsetList.add(offset)")
appendln("${indent} skip(type)")
appendln("${indent}}")
} else {
appendln("${indent}${f.index} -> ${getName(f)}.add($readExpression)")
}
} else if (f.kind == FieldKind.ONE_OF) {
appendln("${indent}${f.index} -> {")
if (f in delayedReads) {
appendln("${indent} ${getName(f)}Offset = offset")
appendln("${indent} skip(type)")
} else {
appendln("${indent} ${getName(f)} = $readExpression")
}
appendln("${indent} oneOfIndex = ${f.index}")
appendln("${indent}}")
} else {
if (f in delayedReads) {
appendln("${indent}${f.index} -> {")
appendln("${indent} ${getName(f)}Offset = offset")
appendln("${indent} skip(type)")
appendln("${indent}}")
} else {
appendln("${indent}${f.index} -> ${getName(f)} = $readExpression")
}
}
}
}
appendln("${shift} else -> skip(type)")
appendln("${shift} }")
appendln("${shift} }")
appendln("${shift}}")
}
readFields(" ", m.fields.oneOfInlined)
val lastIteration = allFields.splitByOrder().size - 1
val hasExposed = exposedFields.isNotEmpty()
fun invokeCreate(index: Int, suffix: String, fields: List<MessageEntry.Field>): String {
val prefix = if (index != lastIteration || hasExposed) {
"create${m.name}${suffix}("
} else {
"return create${m.name}${suffix}("
} + if (index == 0) "" else {
"p${index - 1}, "
}
return "${prefix}${fields.fold("") { acc, c ->
var result = if (acc.isEmpty()) "" else "$acc, "
result += getName(c)
if ((c.kind == FieldKind.REQUIRED || c.kind == FieldKind.ONE_OF) && c in nullableFields) {
result += "!!"
}
result
}})"
}
fun invokeCreateWithOneOf(index: Int, fields: List<MessageEntry.Field>) {
val hasOneOf = fields.any { it.kind == FieldKind.ONE_OF }
val suffixPrefix = if (index == 0) "" else "" + index
if (!hasOneOf) {
if (index != lastIteration || hasExposed) {
appendln(" val p${index} = ${invokeCreate(index, suffixPrefix, fields)}")
} else {
appendln(" ${invokeCreate(index, suffixPrefix, fields)}")
}
} else {
val fp = mutableListOf<MessageEntry.Field>()
val fs = mutableListOf<MessageEntry.Field>()
val mf = mutableListOf<MessageEntry.Field>()
var cf = fp
fields.forEach {
if (it.kind == FieldKind.ONE_OF) {
cf = fs
mf.add(it)
} else {
cf.add(it)
}
}
if (index != lastIteration || hasExposed) {
appendln(" val p${index} = when (oneOfIndex) {")
} else {
appendln(" when (oneOfIndex) {")
}
for (f in mf) {
appendln(" ${f.index} -> ${invokeCreate(index, "${suffixPrefix}_${f.name.escape()}", fp + f + fs)}")
}
appendln(" else -> error(\"Incorrect oneOf index: \" + oneOfIndex)")
appendln(" }")
}
}
if (!hasExposed) {
invokeCreateWithOneOf(0, iterations[0])
if (lastIteration != 0) appendln()
} else {
for (f in exposedFields) {
appendln(" val old${exposedName[f]} = ${exposedName[f]}")
appendln(" ${exposedName[f]} = ${getName(f)}")
}
}
for (i in 1 until iterations.size) {
val fields = iterations[i].filter { it in delayedReads }
for (f in fields) {
if (f.kind == FieldKind.REPEATED) {
appendln(" for (o in ${getName(f)}OffsetList) {")
appendln(" ${getName(f)}.add(delayed(o) { ${f.type.toReaderInvocation()} })")
appendln(" }")
} else {
appendln(" if (${getName(f)}Offset != -1) {")
appendln(" ${getName(f)} = delayed(${getName(f)}Offset) { ${f.type.toReaderInvocation()} }")
appendln(" }")
}
}
val params = if (i == 1 && hasExposed) allFields.splitByOrder()[0].map { it as MessageEntry.Field } else iterations[i]
val index = if (hasExposed) i - 1 else i
invokeCreateWithOneOf(index, params)
if (lastIteration != index) appendln()
}
for (f in exposedFields) {
appendln(" ${exposedName[f]} = old${exposedName[f]}")
}
if (hasExposed) {
appendln(" return p${lastIteration}")
}
appendln(" }")
appendln()
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry
import org.jetbrains.kotlin.backend.common.serialization.proto.Coordinates
import org.jetbrains.kotlin.backend.common.serialization.proto.FqName as ProtoFqName
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDataIndex
import org.jetbrains.kotlin.name.FqName
import org.junit.Assert.assertEquals
import org.junit.Test
class IrTest {
private val stringTable = listOf("A", "B", "C", "D", "E")
inner class MockIrProtoReader(bytes: ByteArray) : IrProtoReader(bytes) {
override fun readStringById(id: Int) = stringTable[id]
}
/**
* message IrDataIndex {
* required int32 index = 1;
* }
*/
@Test
fun dataIndexTest() {
val id = 8765643
val bytes = IrDataIndex.newBuilder()
.setIndex(id)
.build().toByteArray()
val reader = MockIrProtoReader(bytes)
val newId = reader.readDataIndex()
assertEquals(id, newId)
}
/**
* message FqName {
* repeated IrDataIndex segment = 1;
* }
*/
@Test
fun fqNameTest() {
val fqnName = FqName("A.B.C.D.A")
val proto = ProtoFqName.newBuilder()
fqnName.pathSegments().forEach {
val dataIndex = IrDataIndex.newBuilder().setIndex(stringTable.indexOf(it.asString()))
proto.addSegment(dataIndex)
}
val bytes = proto.build().toByteArray()
val reader = MockIrProtoReader(bytes)
val newFqName = reader.readFqName()
assertEquals(fqnName, newFqName)
}
/**
* message Coordinates {
* required int32 start_offset = 1;
* required int32 end_offset = 2;
* }
*/
@Test
fun coordinatesTest() {
val start = -1
val end = 736_818_941
val bytes = Coordinates.newBuilder()
.setStartOffset(start)
.setEndOffset(end)
.build().toByteArray()
val reader = MockIrProtoReader(bytes)
val (newStart, newEnd) = reader.readCoordinates()
// val simpleReader = SimpleIrProtoReader(bytes)
// val result = simpleReader.readCoordinates() as Array<Any>
// assertEquals(start, result[0] as Int)
// assertEquals(end, result[1] as Int)
assertEquals(start, newStart)
assertEquals(end, newEnd)
}
/**
* message FileEntry {
* required string name = 1;
* repeated int32 line_start_offsets = 2;
* }
*/
@Test
fun fileEntryTest() {
val bytes = FileEntry.newBuilder()
.addLineStartOffsets(10)
.setName("<entry name>")
.addAllLineStartOffsets(listOf(1, 2, 3))
.build().toByteArray()
val reader = MockIrProtoReader(bytes)
val fileEntry = reader.readFileEntry()
assertEquals("<entry name>", fileEntry.name)
assertEquals(listOf(10, 1, 2, 3), fileEntry.lineStartOffsets.toList())
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
sealed class Proto(val name: String, val directives: List<String>) {
class Message(name: String, val fields: List<MessageEntry>, directives: List<String> = emptyList()) : Proto(name, directives)
class Enum(name: String, val entries: List<EnumEntry>, directives: List<String> = emptyList()) : Proto(name, directives)
}
class EnumEntry(
val index: Int,
val name: String
)
enum class FieldKind {
REQUIRED,
OPTIONAL,
REPEATED,
ONE_OF
}
sealed class MessageEntry(val name: String) {
class Field(
val kind: FieldKind,
name: String,
val index: Int,
val type: String,
val directives: List<String> = emptyList(),
val defaultValue: String? = null
): MessageEntry(name)
class OneOf(
name: String,
val fields: List<Field>
): MessageEntry(name)
}
fun printProto(p: Proto) {
when (p) {
is Proto.Message -> printMessage(p)
is Proto.Enum -> printEnum(p)
}
println()
}
fun printMessage(message: Proto.Message) {
println("message ${message.name} {")
for (f in message.fields) {
when (f) {
is MessageEntry.OneOf -> {
println(" oneof ${f.name} {")
for (f2 in f.fields) {
println(" ${f2.type} ${f2.name} = ${f2.index};")
}
println(" }")
}
is MessageEntry.Field -> {
print(" ${f.kind.toString().toLowerCase()} ${f.type} ${f.name} = ${f.index}")
if (f.defaultValue != null) {
print(" [default = ${f.defaultValue}]")
}
if (f.directives.isNotEmpty()) {
print(" /*${f.directives.fold("") { acc, c -> acc + " " + c}} */")
}
println(";")
}
}
}
println("}")
}
fun printEnum(enum: Proto.Enum) {
println("enum ${enum.name} {")
for (e in enum.entries) {
println(" ${e.name} = ${e.index};")
}
println("}")
}

View File

@@ -0,0 +1,265 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import java.nio.file.Files
import java.nio.file.Paths
val predefinedProto: String? = "compiler/ir/serialization.common/src/KotlinIr.proto"
fun main(args: Array<String>) {
if (predefinedProto == null && args.size < 1) {
println("*.proto file expected")
return
}
val protoFile = predefinedProto ?: args[0]
val result = ProtoParser(Files.readAllLines(Paths.get(protoFile))).parse()
println(result.createIrDeserializer(typeMappings, false))
// result.forEach {
// printProto(it)
// println()
// }
}
val Char.validIdSymbol: Boolean
get() = 'a' <= this && this <= 'z' || 'A' <= this && this <= 'Z' || '0' <= this && this <= '9' || this in "_.@"
val Char.skip: Boolean
get() = this in " \r\n\t"
fun String.tokenize(): List<String> {
val result = mutableListOf<String>()
var idPart: String? = null
for (c in this.toCharArray()) {
if (c.validIdSymbol) {
idPart = (idPart ?: "") + c
} else {
if (idPart != null) {
result += idPart
idPart = null
}
if (!c.skip) {
result += "$c"
}
}
}
if (idPart != null) {
result += idPart
}
return result
}
fun String.removeLineComments(): String {
val i = indexOf("//")
if (i >= 0) return substring(0, i)
return this
}
class ProtoParser(val lines: List<String>) {
var lineIndex = 0
var tokenIndex = 0
var tokens: List<String> = emptyList()
var eof = false
fun fillTokens() {
while (tokenIndex >= tokens.size) {
if (lineIndex >= lines.size) {
eof = true
return
}
tokens = lines[lineIndex++].removeLineComments().tokenize()
tokenIndex = 0
}
}
fun nextToken(): String {
fillTokens()
if (eof) error("eof")
return tokens[tokenIndex++]
}
private val result = mutableListOf<Proto>()
private fun raise(token: String, expected: String? = null) {
var msg = "Unexpected token '$token' and line $lineIndex"
if (expected != null) {
msg += "; expected '$expected'"
}
error(msg)
}
private fun expect(vararg s: String) {
for (e in s) {
val token = nextToken()
if (token != e) raise(token, e)
}
}
private fun expect(s: Collection<String>) {
for (e in s) {
val token = nextToken()
if (token != e) raise(token, e)
}
}
fun parse(): List<Proto> {
while (true) {
fillTokens()
if (eof) break
when (val token = nextToken()) {
"message" -> parseMessage()
"enum" -> parseEnum()
"syntax" -> expect(" = \"proto2\";".tokenize())
"package" -> expect(" org.jetbrains.kotlin.backend.common.serialization.proto;".tokenize())
"option" -> parseOption()
"/" -> parseComment()
else -> raise(token)
}
}
return result
}
fun parseMessage(container: String? = null) {
val name = nextToken().let {
if (container != null) container + "." + it else it
}
expect("{")
val fields = mutableListOf<MessageEntry>()
val directives = mutableListOf<String>()
while (true) {
when (val token = nextToken()) {
"}" -> {
result += Proto.Message(name, fields, directives)
return
}
"message" -> parseMessage(name)
"enum" -> parseEnum(name)
"required" -> fields += parseField(FieldKind.REQUIRED)
"optional" -> fields += parseField(FieldKind.OPTIONAL)
"repeated" -> fields += parseField(FieldKind.REPEATED)
"oneof" -> fields += parseOneOf()
"/" -> directives += parseComment()
else -> raise(token)
}
}
}
fun parseOneOf(): MessageEntry.OneOf {
val name = nextToken()
expect("{")
val fields = mutableListOf<MessageEntry.Field>()
while (true) {
when (val token = nextToken()) {
"}" -> {
return MessageEntry.OneOf(name, fields)
}
"/" -> parseComment()
else -> {
fields += parseField(FieldKind.ONE_OF, token)
}
}
}
}
fun parseField(kind: FieldKind, knownType: String? = null): MessageEntry.Field {
val type = knownType ?: nextToken()
val name = nextToken()
expect("=")
val fieldNumber = nextToken().toInt()
var defaultValue: String? = null
val directives = mutableListOf<String>()
when (val token = nextToken()) {
";" -> Unit
"[" -> {
expect("default =".tokenize())
defaultValue = nextToken()
expect("];".tokenize())
}
"/" -> {
directives += parseComment()
expect(";")
}
else -> raise(token)
}
return MessageEntry.Field(kind, name, fieldNumber, type, directives, defaultValue)
}
fun parseEnum(container: String? = null) {
val name = nextToken()/*.let {
if (container != null) container + "." + it else it
}*/
expect("{")
val entries = mutableListOf<EnumEntry>()
while (true) {
when (val token = nextToken()) {
"}" -> {
result += Proto.Enum(name, entries)
return
}
"message" -> parseMessage(name)
"enum" -> parseEnum(name)
"/" -> parseComment()
else -> {
val entryName = token
expect("=")
val index = nextToken().toInt()
expect(";")
entries += EnumEntry(index, entryName)
}
}
}
}
// e.g. `option java_multiple_files = true;`
fun parseOption() {
nextToken()
expect("=")
val token = nextToken()
if (token == "\"") {
while (nextToken() != "\"") {
}
}
expect(";")
}
fun parseComment(): List<String> {
expect("*")
var token = nextToken()
var wasStar = false
val result = mutableListOf<String>()
while (true) {
if (wasStar && token == "/") return result
if (token.startsWith('@')) {
result += token
}
wasStar = token == "*"
token = nextToken()
}
return result
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
val typeMappings = mapOf(
"DescriptorReference" to "org.jetbrains.kotlin.descriptors.DeclarationDescriptor",
"UniqId" to "org.jetbrains.kotlin.backend.common.serialization.UniqId",
"Visibility" to "org.jetbrains.kotlin.descriptors.Visibility",
"IrStatementOrigin" to "org.jetbrains.kotlin.ir.expressions.IrStatementOrigin",
"KnownOrigin" to "org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin",
"IrDeclarationOrigin" to "org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin",
"IrDataIndex" to "kotlin.Int",
"FqName" to "org.jetbrains.kotlin.name.FqName",
"IrDeclarationContainer" to "kotlin.collections.List<org.jetbrains.kotlin.ir.declarations.IrDeclaration>",
"FileEntry" to "org.jetbrains.kotlin.ir.SourceManager.FileEntry",
"IrFile" to "org.jetbrains.kotlin.ir.declarations.IrFile",
"StringTable" to "kotlin.Array<String>",
"IrSymbolKind" to "kotlin.Int",
"IrSymbolData" to "org.jetbrains.kotlin.ir.symbols.IrSymbol",
"IrSymbolTable" to "kotlin.Array<org.jetbrains.kotlin.ir.symbols.IrSymbol>",
"IrTypeVariance" to "org.jetbrains.kotlin.types.Variance",
"Annotations" to "kotlin.collections.List<org.jetbrains.kotlin.ir.expressions.IrConstructorCall>",
"TypeArguments" to "kotlin.collections.List<org.jetbrains.kotlin.ir.types.IrType>",
"IrStarProjection" to "org.jetbrains.kotlin.ir.types.IrStarProjection",
"IrTypeProjection" to "org.jetbrains.kotlin.ir.types.IrTypeProjection",
"IrTypeArgument" to "org.jetbrains.kotlin.ir.types.IrTypeArgument",
"IrSimpleType" to "org.jetbrains.kotlin.ir.types.IrSimpleType",
"IrTypeAbbreviation" to "org.jetbrains.kotlin.ir.types.IrTypeAbbreviation",
"IrDynamicType" to "org.jetbrains.kotlin.ir.types.IrDynamicType",
"IrErrorType" to "org.jetbrains.kotlin.ir.types.IrErrorType",
"IrType" to "org.jetbrains.kotlin.ir.types.IrType",
"IrTypeTable" to "kotlin.Array<org.jetbrains.kotlin.ir.types.IrType>",
"IrBreak" to "org.jetbrains.kotlin.ir.expressions.IrBreak",
"IrBlock" to "org.jetbrains.kotlin.ir.expressions.IrBlock",
"MemberAccessCommon" to "org.jetbrains.kotlin.backend.common.serialization.nextgen.MemberAccessCarrier",
"IrCall" to "org.jetbrains.kotlin.ir.expressions.IrCall",
"IrConstructorCall" to "org.jetbrains.kotlin.ir.expressions.IrConstructorCall",
"IrFunctionReference" to "org.jetbrains.kotlin.ir.expressions.IrFunctionReference",
"IrLocalDelegatedPropertyReference" to "org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference",
"IrPropertyReference" to "org.jetbrains.kotlin.ir.expressions.IrPropertyReference",
"IrComposite" to "org.jetbrains.kotlin.ir.expressions.IrComposite",
"IrClassReference" to "org.jetbrains.kotlin.ir.expressions.IrClassReference",
"IrConst" to "org.jetbrains.kotlin.ir.expressions.IrConst<*>",
"IrContinue" to "org.jetbrains.kotlin.ir.expressions.IrContinue",
"IrDelegatingConstructorCall" to "org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall",
"IrDoWhile" to "org.jetbrains.kotlin.ir.expressions.IrDoWhileLoop",
"IrEnumConstructorCall" to "org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall",
"IrGetClass" to "org.jetbrains.kotlin.ir.expressions.IrGetClass",
"IrGetEnumValue" to "org.jetbrains.kotlin.ir.expressions.IrGetEnumValue",
"IrGetField" to "org.jetbrains.kotlin.ir.expressions.IrGetField",
"IrGetValue" to "org.jetbrains.kotlin.ir.expressions.IrGetValue",
"IrGetObject" to "org.jetbrains.kotlin.ir.expressions.IrGetObjectValue",
"IrInstanceInitializerCall" to "org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall",
"IrReturn" to "org.jetbrains.kotlin.ir.expressions.IrReturn",
"IrSetField" to "org.jetbrains.kotlin.ir.expressions.IrSetField",
"IrSetVariable" to "org.jetbrains.kotlin.ir.expressions.IrSetVariable",
"IrSpreadElement" to "org.jetbrains.kotlin.ir.expressions.IrSpreadElement",
"IrStringConcat" to "org.jetbrains.kotlin.ir.expressions.IrStringConcatenation",
"IrThrow" to "org.jetbrains.kotlin.ir.expressions.IrThrow",
"IrTry" to "org.jetbrains.kotlin.ir.expressions.IrTry",
"IrTypeOp" to "org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall",
"IrVararg" to "org.jetbrains.kotlin.ir.expressions.IrVararg",
"IrVarargElement" to "org.jetbrains.kotlin.ir.expressions.IrVarargElement",
"IrWhen" to "org.jetbrains.kotlin.ir.expressions.IrWhen",
"IrWhile" to "org.jetbrains.kotlin.ir.expressions.IrWhileLoop",
"IrFunctionExpression" to "org.jetbrains.kotlin.ir.expressions.IrFunctionExpression",
"IrDynamicMemberExpression" to "org.jetbrains.kotlin.ir.expressions.IrDynamicMemberExpression",
"IrDynamicOperator" to "org.jetbrains.kotlin.ir.expressions.IrDynamicOperator",
"IrDynamicOperatorExpression" to "org.jetbrains.kotlin.ir.expressions.IrDynamicOperatorExpression",
"IrOperation" to "org.jetbrains.kotlin.ir.expressions.IrExpression",
"IrTypeOperator" to "org.jetbrains.kotlin.ir.expressions.IrTypeOperator",
"IrExpression" to "org.jetbrains.kotlin.ir.expressions.IrExpression",
"NullableIrExpression" to "org.jetbrains.kotlin.backend.common.serialization.nextgen.NullableExpression",
"IrFunction" to "org.jetbrains.kotlin.ir.declarations.IrSimpleFunction",
"IrConstructor" to "org.jetbrains.kotlin.ir.declarations.IrConstructor",
"IrField" to "org.jetbrains.kotlin.ir.declarations.IrField",
"IrLocalDelegatedProperty" to "org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty",
"IrProperty" to "org.jetbrains.kotlin.ir.declarations.IrProperty",
"IrVariable" to "org.jetbrains.kotlin.ir.declarations.IrVariable",
"ClassKind" to "org.jetbrains.kotlin.descriptors.ClassKind",
"ModalityKind" to "org.jetbrains.kotlin.descriptors.Modality",
"IrValueParameter" to "org.jetbrains.kotlin.ir.declarations.IrValueParameter",
"IrTypeParameter" to "org.jetbrains.kotlin.ir.declarations.IrTypeParameter",
"IrTypeParameterContainer" to "kotlin.collections.List<org.jetbrains.kotlin.ir.declarations.IrTypeParameter>",
"IrClass" to "org.jetbrains.kotlin.ir.declarations.IrClass",
"IrTypeAlias" to "org.jetbrains.kotlin.ir.declarations.IrTypeAlias",
"IrEnumEntry" to "org.jetbrains.kotlin.ir.declarations.IrEnumEntry",
"IrAnonymousInit" to "org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer",
"IrDeclaration" to "org.jetbrains.kotlin.ir.declarations.IrDeclaration",
"IrBranch" to "org.jetbrains.kotlin.ir.expressions.IrBranch",
"IrBlockBody" to "org.jetbrains.kotlin.ir.expressions.IrBlockBody",
"IrCatch" to "org.jetbrains.kotlin.ir.expressions.IrCatch",
"IrSyntheticBodyKind" to "org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind",
"IrSyntheticBody" to "org.jetbrains.kotlin.ir.expressions.IrSyntheticBody",
"IrStatement" to "org.jetbrains.kotlin.ir.IrElement"
)

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import java.lang.StringBuilder
fun List<Proto>.createSimpleDeserializer(): String {
val sb = StringBuilder()
sb.appendln("class SimpleIrProtoReader(source: ByteArray) : ProtoReader(source) {")
val typeMap = this.associate { it.name to it }
filterIsInstance<Proto.Message>().forEach { sb.addMessage(it, typeMap) }
sb.appendln("}")
return sb.toString()
}
private fun String.toReaderInvocation(typeMap: Map<String, Proto>): String {
return typeMap.get(this)?.let {
when (it) {
is Proto.Enum -> "readInt32()"
is Proto.Message -> "readWithLength { read${it.name}() }"
}
} ?: run {
when (this) {
"int32" -> "readInt32()"
"int64", "uint64" -> "readInt64()"
"string" -> "readString()"
"bool" -> "readBool()"
"float" -> "readFloat()"
"double" -> "readDouble()"
else -> error("Unknown type: ${this}")
}
}
}
private fun StringBuilder.addMessage(m: Proto.Message, typeMap: Map<String, Proto>) {
val allFields = m.fields.flatMap {
when (it) {
is MessageEntry.OneOf -> it.fields
is MessageEntry.Field -> listOf(it)
}
}
appendln(" fun read${m.name}(): Any {")
allFields.forEach { f ->
val (type, initExpression) = if (f.kind == FieldKind.REPEATED) {
"MutableList<Any>" to "mutableListOf<Any>()"
} else {
"Any?" to "null"
}
appendln(" var ${f.name}__: $type = $initExpression")
}
appendln(" while (hasData) {")
appendln(" readField { fieldNumber, type -> ")
appendln(" when (fieldNumber) {")
val indent = " "
allFields.forEach { f ->
val readExpression = f.type.toReaderInvocation(typeMap)
if (f.kind == FieldKind.REPEATED) {
appendln("${indent}${f.index} -> ${f.name}__.add($readExpression)")
} else {
appendln("${indent}${f.index} -> ${f.name}__ = $readExpression")
}
}
appendln(" else -> skip(type)")
appendln(" }")
appendln(" }")
appendln(" }")
appendln(" return arrayOf(${allFields.fold("") { acc, c -> (if (acc.isEmpty()) "" else "$acc, ") + c.name + "__" }})")
appendln(" }")
appendln()
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.nextgen
import org.junit.*
import org.junit.Assert.*;
/**
* Based on https://developers.google.com/protocol-buffers/docs/encoding
*/
class SimpleTest {
private fun String.asBytes(): ByteArray {
return this.split(" ").map {
it.toInt(radix = 16).toByte()
}.toByteArray()
}
/**
* message Test1 {
* optional int32 a = 1;
* }
*
* a = 150
*/
@Test fun testInt32() {
val bytes = "08 96 01".asBytes()
val reader = ProtoReader(bytes)
reader.readField { number, type ->
assertEquals(1, number)
assertEquals(0, type)
assertEquals(150, reader.readInt32())
}
}
/**
* message Test2 {
* optional string b = 2;
* }
*
* b = "testing"
*/
@Test fun testString() {
val bytes = "12 07 74 65 73 74 69 6e 67".asBytes()
val reader = ProtoReader(bytes)
reader.readField { number, type ->
assertEquals(2, number)
assertEquals(2, type)
assertEquals("testing", reader.readString())
}
}
/**
* message Test3 {
* optional Test1 c = 3;
* }
*
* c = 150
*/
@Test fun testNested() {
val bytes = "1a 03 08 96 01".asBytes()
val reader = ProtoReader(bytes)
reader.readField { number, type ->
assertEquals(3, number)
assertEquals(2, type)
val test1Length = reader.readInt32()
assertEquals(3, test1Length)
reader.readField { number, type ->
assertEquals(1, number)
assertEquals(0, type)
assertEquals(150, reader.readInt32())
}
}
}
/**
* message Test3 {
* repeated Test1 c = 3;
* }
*
* c = 150
*/
@Test fun testRepeated() {
val bytes = "1a 03 08 96 01 1a 03 08 96 01 1a 03 08 96 01".asBytes()
val reader = ProtoReader(bytes)
while (reader.hasData) {
reader.readField { number, type ->
assertEquals(3, number)
assertEquals(2, type)
reader.readWithLength {
reader.readField { number, type ->
assertEquals(1, number)
assertEquals(0, type)
assertEquals(150, reader.readInt32())
}
}
}
}
}
}

View File

@@ -179,7 +179,7 @@ val packFullRuntimeKLib by tasks.registering(Jar::class) {
archiveFileName.set("full-runtime.klib")
}
val generateReducedRuntimeKLib by eagerTask<NoDebugJavaExec> {
val generateReducedRuntimeKLib by eagerTask<JavaExec> {
dependsOn(reducedRuntimeSources)
val outPath = buildDir.resolve("reducedRuntime/klib").absolutePath

View File

@@ -131,9 +131,9 @@ message DocCommentTag {
message BinaryOperation {
required Expression left = 1;
required Expression right = 2;
required Type type = 3;
required BinaryOperationType type = 3;
enum Type {
enum BinaryOperationType {
MUL = 1;
DIV = 2;
MOD = 3;
@@ -175,10 +175,10 @@ message BinaryOperation {
message UnaryOperation {
required Expression operand = 1;
required Type type = 2;
required UnaryOperationType type = 2;
required bool postfix = 3;
enum Type {
enum UnaryOperationType {
BIT_NOT = 1;
DEC = 2;
DELETE = 3;

View File

@@ -76,7 +76,7 @@ abstract class BasicIrBoxTest(
// TODO: split input files to some parts (global common, local common, test)
.filterNot { it.virtualFilePath.contains(COMMON_FILES_DIR_PATH) }
val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(defaultRuntimeKlib)
val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(fullRuntimeKlib)
val transitiveLibraries = config.configuration[JSConfigurationKeys.TRANSITIVE_LIBRARIES]!!.map { File(it).name }