JS: add AST deserializer
This commit is contained in:
@@ -17,6 +17,11 @@ public class JsCatch extends SourceInfoAwareJsNode implements HasCondition {
|
|||||||
private JsExpression condition;
|
private JsExpression condition;
|
||||||
private JsParameter param;
|
private JsParameter param;
|
||||||
|
|
||||||
|
public JsCatch(@NotNull JsName name) {
|
||||||
|
param = new JsParameter(name);
|
||||||
|
scope = null;
|
||||||
|
}
|
||||||
|
|
||||||
public JsCatch(JsScope parent, @NotNull String ident) {
|
public JsCatch(JsScope parent, @NotNull String ident) {
|
||||||
super();
|
super();
|
||||||
assert (parent != null);
|
assert (parent != null);
|
||||||
|
|||||||
@@ -0,0 +1,429 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.serialization.js.ast
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.*
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Expression.ExpressionCase
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Statement.StatementCase
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class JsAstDeserializer(private val program: JsProgram) {
|
||||||
|
private val scope = JsRootScope(program)
|
||||||
|
private val stringTable = mutableListOf<String>()
|
||||||
|
private val nameTable = mutableListOf<Name>()
|
||||||
|
private val nameCache = mutableListOf<JsName?>()
|
||||||
|
|
||||||
|
fun deserialize(input: InputStream): JsProgramFragment {
|
||||||
|
return deserialize(Chunk.parseFrom(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserialize(proto: Chunk): JsProgramFragment {
|
||||||
|
stringTable += proto.stringTable.entryList
|
||||||
|
nameTable += proto.nameTable.entryList
|
||||||
|
nameCache += nameTable.map { null }
|
||||||
|
try {
|
||||||
|
return deserialize(proto.fragment)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
stringTable.clear()
|
||||||
|
nameTable.clear()
|
||||||
|
nameCache.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserialize(proto: Fragment): JsProgramFragment {
|
||||||
|
val fragment = JsProgramFragment(scope)
|
||||||
|
|
||||||
|
fragment.importedModules += proto.importedModuleList.map { importedModuleProto ->
|
||||||
|
JsImportedModule(
|
||||||
|
deserializeString(importedModuleProto.externalNameId),
|
||||||
|
deserializeName(importedModuleProto.internalNameId),
|
||||||
|
if (importedModuleProto.hasPlainReference()) deserialize(importedModuleProto.plainReference) else null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment.imports += proto.importEntryList.associate { importProto ->
|
||||||
|
deserializeString(importProto.signatureId) to deserialize(importProto.expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proto.hasDeclarationBlock()) {
|
||||||
|
fragment.declarationBlock.statements += deserializeGlobalBlock(proto.declarationBlock).statements
|
||||||
|
}
|
||||||
|
if (proto.hasInitializerBlock()) {
|
||||||
|
fragment.initializerBlock.statements += deserializeGlobalBlock(proto.initializerBlock).statements
|
||||||
|
}
|
||||||
|
if (proto.hasExportBlock()) {
|
||||||
|
fragment.exportBlock.statements += deserializeGlobalBlock(proto.exportBlock).statements
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment.nameBindings += proto.nameBindingList.map { nameBindingProto ->
|
||||||
|
JsNameBinding(deserializeString(nameBindingProto.signatureId), deserializeName(nameBindingProto.nameId))
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment.classes += proto.classModelList.associate { clsProto -> deserialize(clsProto).let { it.name to it } }
|
||||||
|
|
||||||
|
val moduleExpressions = proto.moduleExpressionList.map { deserialize(it) }
|
||||||
|
fragment.inlineModuleMap += proto.inlineModuleList.associate { inlineModuleProto ->
|
||||||
|
deserializeString(inlineModuleProto.signatureId) to moduleExpressions[inlineModuleProto.expressionId]
|
||||||
|
}
|
||||||
|
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserialize(proto: ClassModel): JsClassModel {
|
||||||
|
val superName = if (proto.hasSuperNameId()) deserializeName(proto.superNameId) else null
|
||||||
|
return JsClassModel(deserializeName(proto.nameId), superName).apply {
|
||||||
|
if (proto.hasPostDeclarationBlock()) {
|
||||||
|
postDeclarationBlock.statements += deserializeGlobalBlock(proto.postDeclarationBlock).statements
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserialize(proto: Statement): JsStatement = when (proto.statementCase) {
|
||||||
|
StatementCase.RETURN_STATEMENT -> {
|
||||||
|
val returnProto = proto.returnStatement
|
||||||
|
JsReturn(if (returnProto.hasValue()) deserialize(returnProto.value) else null)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.THROW_STATEMENT -> {
|
||||||
|
val throwProto = proto.throwStatement
|
||||||
|
JsThrow(deserialize(throwProto.exception))
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.BREAK_STATEMENT -> {
|
||||||
|
val breakProto = proto.breakStatement
|
||||||
|
JsBreak(if (breakProto.hasLabelId()) JsNameRef(deserializeName(breakProto.labelId)) else null)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.CONTINUE_STATEMENT -> {
|
||||||
|
val continueProto = proto.continueStatement
|
||||||
|
JsContinue(if (continueProto.hasLabelId()) JsNameRef(deserializeName(continueProto.labelId)) else null)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.DEBUGGER -> {
|
||||||
|
JsDebugger()
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.EXPRESSION -> {
|
||||||
|
val expressionProto = proto.expression
|
||||||
|
JsExpressionStatement(deserialize(expressionProto.expression))
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.VARS -> {
|
||||||
|
deserializeVars(proto.vars)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.BLOCK -> {
|
||||||
|
val blockProto = proto.block
|
||||||
|
val block = JsBlock()
|
||||||
|
block.statements += blockProto.statementList.map { deserialize(it) }
|
||||||
|
block
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.GLOBAL_BLOCK -> {
|
||||||
|
deserializeGlobalBlock(proto.globalBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.LABEL -> {
|
||||||
|
val labelProto = proto.label
|
||||||
|
JsLabel(deserializeName(labelProto.nameId), deserialize(labelProto.innerStatement))
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.IF_STATEMENT -> {
|
||||||
|
val ifProto = proto.ifStatement
|
||||||
|
JsIf(
|
||||||
|
deserialize(ifProto.condition),
|
||||||
|
deserialize(ifProto.thenStatement),
|
||||||
|
if (ifProto.hasElseStatement()) deserialize(ifProto.elseStatement) else null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.SWITCH_STATEMENT -> {
|
||||||
|
val switchProto = proto.switchStatement
|
||||||
|
JsSwitch(
|
||||||
|
deserialize(switchProto.expression),
|
||||||
|
switchProto.entryList.map { entryProto ->
|
||||||
|
val member = if (entryProto.hasLabel()) {
|
||||||
|
JsCase().apply { caseExpression = deserialize(entryProto.label) }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JsDefault()
|
||||||
|
}
|
||||||
|
member.statements += entryProto.statementList.map { deserialize(it) }
|
||||||
|
member
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.WHILE_STATEMENT -> {
|
||||||
|
val whileProto = proto.whileStatement
|
||||||
|
JsWhile(deserialize(whileProto.condition), deserialize(whileProto.body))
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.DO_WHILE_STATEMENT -> {
|
||||||
|
val doWhileProto = proto.doWhileStatement
|
||||||
|
JsDoWhile(deserialize(doWhileProto.condition), deserialize(doWhileProto.body))
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.FOR_STATEMENT -> {
|
||||||
|
val forProto = proto.forStatement
|
||||||
|
val initVars = if (forProto.hasVariables()) deserializeVars(forProto.variables) else null
|
||||||
|
val initExpr = if (forProto.hasExpression()) deserialize(forProto.expression) else null
|
||||||
|
val condition = if (forProto.hasCondition()) deserialize(forProto.condition) else null
|
||||||
|
val increment = if (forProto.hasIncrement()) deserialize(forProto.increment) else null
|
||||||
|
val body = deserialize(forProto.body)
|
||||||
|
if (initVars != null) {
|
||||||
|
JsFor(initVars, condition, increment, body)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JsFor(initExpr!!, condition, increment, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.FOR_IN_STATEMENT -> {
|
||||||
|
val forInProto = proto.forInStatement
|
||||||
|
val iterName = if (forInProto.hasNameId()) deserializeName(forInProto.nameId) else null
|
||||||
|
val iterExpr = if (forInProto.hasExpression()) deserialize(forInProto.expression) else null
|
||||||
|
val iterable = deserialize(forInProto.iterable)
|
||||||
|
val body = deserialize(forInProto.body)
|
||||||
|
JsForIn(iterName, iterExpr, iterable, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.TRY_STATEMENT -> {
|
||||||
|
val tryProto = proto.tryStatement
|
||||||
|
val tryBlock = deserialize(tryProto.tryBlock) as JsBlock
|
||||||
|
val catchBlock = if (tryProto.hasCatchBlock()) {
|
||||||
|
val catchProto = tryProto.catchBlock
|
||||||
|
JsCatch(deserializeName(catchProto.parameter.nameId)).apply {
|
||||||
|
body = deserialize(catchProto.body) as JsBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
val finallyBlock = if (tryProto.hasFinallyBlock()) deserialize(tryProto.finallyBlock) as JsBlock else null
|
||||||
|
JsTry(tryBlock, catchBlock, finallyBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementCase.EMPTY -> JsEmpty
|
||||||
|
|
||||||
|
StatementCase.STATEMENT_NOT_SET,
|
||||||
|
null -> error("Statement not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserialize(proto: Expression): JsExpression = when(proto.expressionCase) {
|
||||||
|
ExpressionCase.THIS_LITERAL -> JsLiteral.THIS
|
||||||
|
ExpressionCase.NULL_LITERAL -> JsLiteral.NULL
|
||||||
|
ExpressionCase.TRUE_LITERAL -> JsLiteral.TRUE
|
||||||
|
ExpressionCase.FALSE_LITERAL -> JsLiteral.FALSE
|
||||||
|
ExpressionCase.STRING_LITERAL -> program.getStringLiteral(deserializeString(proto.stringLiteral.stringId))
|
||||||
|
ExpressionCase.INT_LITERAL -> program.getNumberLiteral(proto.intLiteral.value)
|
||||||
|
ExpressionCase.DOUBLE_LITERAL -> program.getNumberLiteral(proto.doubleLiteral.value)
|
||||||
|
ExpressionCase.SIMPLE_NAME_REFERENCE -> JsNameRef(deserializeName(proto.simpleNameReference))
|
||||||
|
|
||||||
|
ExpressionCase.REG_EXP_LITERAL -> {
|
||||||
|
val regExpProto = proto.regExpLiteral
|
||||||
|
JsRegExp().apply {
|
||||||
|
pattern = deserializeString(regExpProto.patternStringId)
|
||||||
|
if (regExpProto.hasFlagsStringId()) {
|
||||||
|
flags = deserializeString(regExpProto.flagsStringId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.ARRAY_LITERAL -> {
|
||||||
|
val arrayProto = proto.arrayLiteral
|
||||||
|
JsArrayLiteral(arrayProto.elementList.map { deserialize(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.OBJECT_LITERAL -> {
|
||||||
|
val objectProto = proto.objectLiteral
|
||||||
|
JsObjectLiteral(
|
||||||
|
objectProto.entryList.map { entryProto ->
|
||||||
|
JsPropertyInitializer(deserialize(entryProto.key), deserialize(entryProto.value))
|
||||||
|
},
|
||||||
|
objectProto.multiline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.FUNCTION -> {
|
||||||
|
val functionProto = proto.function
|
||||||
|
JsFunction(scope, deserialize(functionProto.body) as JsBlock, "").apply {
|
||||||
|
parameters += functionProto.parameterList.map { deserializeParameter(it) }
|
||||||
|
if (functionProto.hasNameId()) {
|
||||||
|
name = deserializeName(functionProto.nameId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.DOC_COMMENT -> {
|
||||||
|
val docCommentProto = proto.docComment
|
||||||
|
JsDocComment(docCommentProto.tagList.associate { tagProto ->
|
||||||
|
val name = deserializeString(tagProto.nameId)
|
||||||
|
val value: Any = if (tagProto.hasExpression()) {
|
||||||
|
deserialize(tagProto.expression)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deserializeString(tagProto.valueStringId)
|
||||||
|
}
|
||||||
|
name to value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.BINARY -> {
|
||||||
|
val binaryProto = proto.binary
|
||||||
|
JsBinaryOperation(map(binaryProto.type), deserialize(binaryProto.left), deserialize(binaryProto.right))
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.UNARY -> {
|
||||||
|
val unaryProto = proto.unary
|
||||||
|
val type = map(unaryProto.type)
|
||||||
|
val operand = deserialize(unaryProto.operand)
|
||||||
|
if (unaryProto.postfix) JsPostfixOperation(type, operand) else JsPrefixOperation(type, operand)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.CONDITIONAL -> {
|
||||||
|
val conditionalProto = proto.conditional
|
||||||
|
JsConditional(
|
||||||
|
deserialize(conditionalProto.testExpression),
|
||||||
|
deserialize(conditionalProto.thenExpression),
|
||||||
|
deserialize(conditionalProto.elseExpression)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.ARRAY_ACCESS -> {
|
||||||
|
val arrayAccessProto = proto.arrayAccess
|
||||||
|
JsArrayAccess(deserialize(arrayAccessProto.array), deserialize(arrayAccessProto.index))
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.NAME_REFERENCE -> {
|
||||||
|
val nameRefProto = proto.nameReference
|
||||||
|
JsNameRef(deserializeName(nameRefProto.nameId), if (nameRefProto.hasQualifier()) deserialize(nameRefProto.qualifier) else null)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.PROPERTY_REFERENCE -> {
|
||||||
|
val propertyRefProto = proto.propertyReference
|
||||||
|
val qualifier = if (propertyRefProto.hasQualifier()) deserialize(propertyRefProto.qualifier) else null
|
||||||
|
JsNameRef(deserializeString(propertyRefProto.stringId), qualifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.INVOCATION -> {
|
||||||
|
val invocationProto = proto.invocation
|
||||||
|
JsInvocation(
|
||||||
|
deserialize(invocationProto.qualifier),
|
||||||
|
invocationProto.argumentList.map { deserialize(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionCase.INSTANTIATION -> {
|
||||||
|
val instantiationProto = proto.instantiation
|
||||||
|
JsNew(
|
||||||
|
deserialize(instantiationProto.qualifier),
|
||||||
|
instantiationProto.argumentList.map { deserialize(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
null,
|
||||||
|
ExpressionCase.EXPRESSION_NOT_SET -> error("Unknown expression")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeVars(proto: Vars): JsVars {
|
||||||
|
val vars = JsVars(proto.multiline)
|
||||||
|
for (declProto in proto.declarationList) {
|
||||||
|
val initialValue = if (declProto.hasInitialValue()) deserialize(declProto.initialValue) else null
|
||||||
|
vars.vars += JsVars.JsVar(deserializeName(declProto.nameId), initialValue)
|
||||||
|
}
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeGlobalBlock(proto: GlobalBlock): JsGlobalBlock {
|
||||||
|
return JsGlobalBlock().apply { statements += proto.statementList.map { deserialize(it) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeParameter(proto: Parameter): JsParameter {
|
||||||
|
return JsParameter(deserializeName(proto.nameId))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeName(id: Int): JsName {
|
||||||
|
return nameCache[id] ?: let {
|
||||||
|
val nameProto = nameTable[id]
|
||||||
|
val identifier = deserializeString(nameProto.identifier)
|
||||||
|
val name = if (nameProto.temporary) {
|
||||||
|
JsScope.declareTemporaryName(identifier)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JsDynamicScope.declareName(identifier)
|
||||||
|
}
|
||||||
|
nameCache[id] = name
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeString(id: Int): String = stringTable[id]
|
||||||
|
|
||||||
|
private fun map(op: BinaryOperation.Type) = when (op) {
|
||||||
|
BinaryOperation.Type.MUL -> JsBinaryOperator.MUL
|
||||||
|
BinaryOperation.Type.DIV -> JsBinaryOperator.DIV
|
||||||
|
BinaryOperation.Type.MOD -> JsBinaryOperator.MOD
|
||||||
|
BinaryOperation.Type.ADD -> JsBinaryOperator.ADD
|
||||||
|
BinaryOperation.Type.SUB -> JsBinaryOperator.SUB
|
||||||
|
BinaryOperation.Type.SHL -> JsBinaryOperator.SHL
|
||||||
|
BinaryOperation.Type.SHR -> JsBinaryOperator.SHR
|
||||||
|
BinaryOperation.Type.SHRU -> JsBinaryOperator.SHRU
|
||||||
|
BinaryOperation.Type.LT -> JsBinaryOperator.LT
|
||||||
|
BinaryOperation.Type.LTE -> JsBinaryOperator.LTE
|
||||||
|
BinaryOperation.Type.GT -> JsBinaryOperator.GT
|
||||||
|
BinaryOperation.Type.GTE -> JsBinaryOperator.GTE
|
||||||
|
BinaryOperation.Type.INSTANCEOF -> JsBinaryOperator.INSTANCEOF
|
||||||
|
BinaryOperation.Type.IN -> JsBinaryOperator.INOP
|
||||||
|
BinaryOperation.Type.EQ -> JsBinaryOperator.EQ
|
||||||
|
BinaryOperation.Type.NEQ -> JsBinaryOperator.NEQ
|
||||||
|
BinaryOperation.Type.REF_EQ -> JsBinaryOperator.REF_EQ
|
||||||
|
BinaryOperation.Type.REF_NEQ -> JsBinaryOperator.REF_NEQ
|
||||||
|
BinaryOperation.Type.BIT_AND -> JsBinaryOperator.BIT_AND
|
||||||
|
BinaryOperation.Type.BIT_XOR -> JsBinaryOperator.BIT_XOR
|
||||||
|
BinaryOperation.Type.BIT_OR -> JsBinaryOperator.BIT_OR
|
||||||
|
BinaryOperation.Type.AND -> JsBinaryOperator.AND
|
||||||
|
BinaryOperation.Type.OR -> JsBinaryOperator.OR
|
||||||
|
BinaryOperation.Type.ASG -> JsBinaryOperator.ASG
|
||||||
|
BinaryOperation.Type.ASG_ADD -> JsBinaryOperator.ASG_ADD
|
||||||
|
BinaryOperation.Type.ASG_SUB -> JsBinaryOperator.ASG_SUB
|
||||||
|
BinaryOperation.Type.ASG_MUL -> JsBinaryOperator.ASG_MUL
|
||||||
|
BinaryOperation.Type.ASG_DIV -> JsBinaryOperator.ASG_DIV
|
||||||
|
BinaryOperation.Type.ASG_MOD -> JsBinaryOperator.ASG_MOD
|
||||||
|
BinaryOperation.Type.ASG_SHL -> JsBinaryOperator.ASG_SHL
|
||||||
|
BinaryOperation.Type.ASG_SHR -> JsBinaryOperator.ASG_SHR
|
||||||
|
BinaryOperation.Type.ASG_SHRU -> JsBinaryOperator.ASG_SHRU
|
||||||
|
BinaryOperation.Type.ASG_BIT_AND -> JsBinaryOperator.ASG_BIT_AND
|
||||||
|
BinaryOperation.Type.ASG_BIT_OR -> JsBinaryOperator.ASG_BIT_OR
|
||||||
|
BinaryOperation.Type.ASG_BIT_XOR -> JsBinaryOperator.ASG_BIT_XOR
|
||||||
|
BinaryOperation.Type.COMMA -> JsBinaryOperator.COMMA
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun map(op: UnaryOperation.Type) = when (op) {
|
||||||
|
UnaryOperation.Type.BIT_NOT -> JsUnaryOperator.BIT_NOT
|
||||||
|
UnaryOperation.Type.DEC -> JsUnaryOperator.DEC
|
||||||
|
UnaryOperation.Type.DELETE -> JsUnaryOperator.DELETE
|
||||||
|
UnaryOperation.Type.INC -> JsUnaryOperator.INC
|
||||||
|
UnaryOperation.Type.NEG -> JsUnaryOperator.NEG
|
||||||
|
UnaryOperation.Type.POS -> JsUnaryOperator.POS
|
||||||
|
UnaryOperation.Type.NOT -> JsUnaryOperator.NOT
|
||||||
|
UnaryOperation.Type.TYPEOF -> JsUnaryOperator.TYPEOF
|
||||||
|
UnaryOperation.Type.VOID -> JsUnaryOperator.VOID
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.facade;
|
package org.jetbrains.kotlin.js.facade;
|
||||||
|
|
||||||
import com.intellij.util.Base64;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
@@ -38,8 +37,10 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
|
|||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstDeserializer;
|
||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstSerializer;
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstSerializer;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -91,14 +92,20 @@ public final class K2JSTranslator {
|
|||||||
|
|
||||||
// TODO: temporary code for testing purposes, remove later
|
// TODO: temporary code for testing purposes, remove later
|
||||||
JsAstSerializer serializer = new JsAstSerializer();
|
JsAstSerializer serializer = new JsAstSerializer();
|
||||||
|
JsAstDeserializer deserializer = new JsAstDeserializer(new JsProgram());
|
||||||
JsProgram program = translationResult.getProgram();
|
JsProgram program = translationResult.getProgram();
|
||||||
int bytesTotal = 0;
|
int bytesTotal = 0;
|
||||||
for (JsProgramFragment fragment : translationResult.getFragments()) {
|
for (JsProgramFragment fragment : translationResult.getFragments()) {
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
serializer.serialize(fragment, output);
|
serializer.serialize(fragment, output);
|
||||||
bytesTotal += output.size();
|
bytesTotal += output.size();
|
||||||
String base64 = Base64.encode(output.toByteArray());
|
|
||||||
program.getGlobalBlock().getStatements().add(program.getStringLiteral(base64).makeStmt());
|
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
|
||||||
|
JsProgramFragment deserializedFragment = deserializer.deserialize(input);
|
||||||
|
|
||||||
|
String expected = fragmentToString(fragment);
|
||||||
|
String actual = fragmentToString(deserializedFragment);
|
||||||
|
assert expected.equals(actual) : "Deserialization: " + expected + "\n\nvs.\n\n" + actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
program.getGlobalBlock().getStatements().add(program.getNumberLiteral(bytesTotal).makeStmt());
|
program.getGlobalBlock().getStatements().add(program.getNumberLiteral(bytesTotal).makeStmt());
|
||||||
@@ -123,4 +130,9 @@ public final class K2JSTranslator {
|
|||||||
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
||||||
moduleDescriptor, bindingTrace.getBindingContext());
|
moduleDescriptor, bindingTrace.getBindingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String fragmentToString(JsProgramFragment fragment) {
|
||||||
|
return fragment.getDeclarationBlock().toString() + fragment.getInitializerBlock().toString() +
|
||||||
|
fragment.getExportBlock().toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user