All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teavm.jso.impl.JSBodyAstEmitter Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2015 Alexey Andreev.
 *
 *  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.teavm.jso.impl;

import org.mozilla.javascript.Node;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.Block;
import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.rendering.AstWriter;
import org.teavm.backend.javascript.rendering.DefaultGlobalNameWriter;
import org.teavm.backend.javascript.rendering.Precedence;
import org.teavm.backend.javascript.spi.GeneratorContext;
import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference;

class JSBodyAstEmitter implements JSBodyEmitter {
    private boolean isStatic;
    private AstNode ast;
    private AstNode rootAst;
    private String[] parameterNames;
    private JsBodyImportInfo[] imports;

    JSBodyAstEmitter(boolean isStatic, AstNode ast, AstNode rootAst, String[] parameterNames,
            JsBodyImportInfo[] imports) {
        this.isStatic = isStatic;
        this.ast = ast;
        this.rootAst = rootAst;
        this.parameterNames = parameterNames;
        this.imports = imports;
    }

    @Override
    public void emit(InjectorContext context) {
        var astWriter = new AstWriter(context.getWriter(), new DefaultGlobalNameWriter());
        int paramIndex = 0;
        if (!isStatic) {
            int index = paramIndex++;
            astWriter.declareNameEmitter("this", (w, prec) -> context.writeExpr(context.getArgument(index),
                    convert(prec)));
        }
        for (int i = 0; i < parameterNames.length; ++i) {
            int index = paramIndex++;
            astWriter.declareNameEmitter(parameterNames[i],
                    (w, prec) -> context.writeExpr(context.getArgument(index), convert(prec)));
        }
        for (var importInfo : imports) {
            astWriter.declareNameEmitter(importInfo.alias,
                    (w, prec) -> context.getWriter().appendFunction(context.importModule(importInfo.fromModule)));
        }
        astWriter.hoist(rootAst);
        astWriter.print(ast, convert(context.getPrecedence()));
    }

    private static int convert(Precedence precedence) {
        switch (precedence) {
            case ADDITION:
                return AstWriter.PRECEDENCE_ADD;
            case ASSIGNMENT:
                return AstWriter.PRECEDENCE_ASSIGN;
            case BITWISE_AND:
                return AstWriter.PRECEDENCE_BITWISE_AND;
            case BITWISE_OR:
                return AstWriter.PRECEDENCE_BITWISE_OR;
            case BITWISE_XOR:
                return AstWriter.PRECEDENCE_BITWISE_XOR;
            case BITWISE_SHIFT:
                return AstWriter.PRECEDENCE_SHIFT;
            case COMMA:
                return AstWriter.PRECEDENCE_COMMA;
            case COMPARISON:
                return AstWriter.PRECEDENCE_RELATION;
            case CONDITIONAL:
                return AstWriter.PRECEDENCE_COND;
            case EQUALITY:
                return AstWriter.PRECEDENCE_EQUALITY;
            case FUNCTION_CALL:
                return AstWriter.PRECEDENCE_FUNCTION;
            case GROUPING:
                return 1;
            case LOGICAL_AND:
                return AstWriter.PRECEDENCE_AND;
            case LOGICAL_OR:
                return AstWriter.PRECEDENCE_OR;
            case MEMBER_ACCESS:
                return AstWriter.PRECEDENCE_MEMBER;
            case MULTIPLICATION:
                return AstWriter.PRECEDENCE_MUL;
            case UNARY:
                return AstWriter.PRECEDENCE_PREFIX;
            default:
                return AstWriter.PRECEDENCE_COMMA;
        }
    }

    private static Precedence convert(int precedence) {
        switch (precedence) {
            case AstWriter.PRECEDENCE_ADD:
                return Precedence.ADDITION;
            case AstWriter.PRECEDENCE_ASSIGN:
                return Precedence.ASSIGNMENT;
            case AstWriter.PRECEDENCE_BITWISE_AND:
                return Precedence.BITWISE_AND;
            case AstWriter.PRECEDENCE_BITWISE_OR:
                return Precedence.BITWISE_OR;
            case AstWriter.PRECEDENCE_BITWISE_XOR:
                return Precedence.BITWISE_XOR;
            case AstWriter.PRECEDENCE_SHIFT:
                return Precedence.BITWISE_SHIFT;
            case AstWriter.PRECEDENCE_COMMA:
                return Precedence.COMMA;
            case AstWriter.PRECEDENCE_RELATION:
                return Precedence.COMPARISON;
            case AstWriter.PRECEDENCE_COND:
                return Precedence.CONDITIONAL;
            case AstWriter.PRECEDENCE_EQUALITY:
                return Precedence.EQUALITY;
            case AstWriter.PRECEDENCE_FUNCTION:
                return Precedence.FUNCTION_CALL;
            case 1:
                return Precedence.GROUPING;
            case AstWriter.PRECEDENCE_AND:
                return Precedence.LOGICAL_AND;
            case AstWriter.PRECEDENCE_OR:
                return Precedence.LOGICAL_OR;
            case AstWriter.PRECEDENCE_MEMBER:
                return Precedence.MEMBER_ACCESS;
            case AstWriter.PRECEDENCE_MUL:
                return Precedence.MULTIPLICATION;
            case AstWriter.PRECEDENCE_PREFIX:
                return Precedence.UNARY;
            default:
                return Precedence.min();
        }
    }

    @Override
    public void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
        var astWriter = new AstWriter(writer, new DefaultGlobalNameWriter());
        int paramIndex = 1;
        if (!isStatic) {
            int index = paramIndex++;
            astWriter.declareNameEmitter("this", (w, prec) -> w.append(context.getParameterName(index)));
        }
        for (var parameterName : parameterNames) {
            int index = paramIndex++;
            astWriter.declareNameEmitter(parameterName, (w, prec) -> w.append(context.getParameterName(index)));
        }
        for (var importInfo : imports) {
            astWriter.declareNameEmitter(importInfo.alias,
                    (w, prec) -> w.appendFunction(context.importModule(importInfo.fromModule)));
        }
        astWriter.hoist(rootAst);
        if (ast instanceof Block) {
            for (Node child = ast.getFirstChild(); child != null; child = child.getNext()) {
                astWriter.print((AstNode) child);
                writer.softNewLine();
            }
        } else {
            astWriter.print(ast);
            writer.softNewLine();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy