Package org.teavm.classlib.java.lang

Source Code of org.teavm.classlib.java.lang.ClassNativeGenerator

/*
*  Copyright 2013 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.classlib.java.lang;

import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.javascript.ni.Injector;
import org.teavm.javascript.ni.InjectorContext;
import org.teavm.model.*;

/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ClassNativeGenerator implements Generator, Injector, DependencyPlugin {
    @Override
    public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
            throws IOException {
        switch (methodRef.getName()) {
            case "getComponentType0":
                generateGetComponentType(context, writer);
                break;
            case "getSuperclass":
                generateGetSuperclass(context, writer);
                break;
            case "forNameImpl":
                generateForName(context, writer);
                break;
            case "newInstance":
                generateNewInstance(context, writer);
                break;
            case "getDeclaringClass":
                generateGetDeclaringClass(context, writer);
                break;
        }
    }

    private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException {
        String thisArg = context.getParameterName(0);
        writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
        writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
    }

    private void generateGetSuperclass(GeneratorContext context, SourceWriter writer) throws IOException {
        String thisArg = context.getParameterName(0);
        writer.append("var superclass = " + thisArg + ".$data.$meta.superclass;").softNewLine();
        writer.append("return superclass ? $rt_cls(superclass) : null;").softNewLine();
    }

    @Override
    public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
        switch (methodRef.getName()) {
            case "isInstance":
                generateIsInstance(context);
                break;
            case "isAssignableFrom":
                generateIsAssignableFrom(context);
                break;
            case "voidClass":
                context.getWriter().append("$rt_cls($rt_voidcls())");
                break;
            case "booleanClass":
                context.getWriter().append("$rt_cls($rt_booleancls())");
                break;
            case "charClass":
                context.getWriter().append("$rt_cls($rt_charcls())");
                break;
            case "byteClass":
                context.getWriter().append("$rt_cls($rt_bytecls())");
                break;
            case "shortClass":
                context.getWriter().append("$rt_cls($rt_shortcls())");
                break;
            case "intClass":
                context.getWriter().append("$rt_cls($rt_intcls())");
                break;
            case "longClass":
                context.getWriter().append("$rt_cls($rt_longcls())");
                break;
            case "floatClass":
                context.getWriter().append("$rt_cls($rt_floatcls())");
                break;
            case "doubleClass":
                context.getWriter().append("$rt_cls($rt_doublecls())");
                break;
            case "wrapClass":
                context.writeExpr(context.getArgument(0));
                break;
            case "getEnumConstantsImpl":
                context.writeExpr(context.getArgument(0));
                context.getWriter().append(".$data.values()");
                break;
        }
    }

    private void generateIsAssignableFrom(InjectorContext context) throws IOException {
        SourceWriter writer = context.getWriter();
        writer.append("$rt_isAssignable(");
        context.writeExpr(context.getArgument(1));
        writer.append(".$data,").ws();
        context.writeExpr(context.getArgument(0));
        writer.append(".$data)");
    }

    private void generateIsInstance(InjectorContext context) throws IOException {
        SourceWriter writer = context.getWriter();
        writer.append("$rt_isInstance(");
        context.writeExpr(context.getArgument(1));
        writer.append(",").ws();
        context.writeExpr(context.getArgument(0));
        writer.append(".$data)");
    }

    private void generateForName(GeneratorContext context, SourceWriter writer) throws IOException {
        String param = context.getParameterName(1);
        writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent();
        for (String name : context.getClassSource().getClassNames()) {
            writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ")
                    .append("return $rt_cls(").appendClass(name).append(");").softNewLine();
        }
        writer.append("default: return null;").softNewLine();
        writer.outdent().append("}").softNewLine();
    }

    private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
        String self = context.getParameterName(0);
        writer.append("if (!").appendClass("java.lang.Class").append(".$$constructors$$) {").indent().softNewLine();
        writer.appendClass("java.lang.Class").append(".$$constructors$$ = true;").softNewLine();
        for (String clsName : context.getClassSource().getClassNames()) {
            ClassReader cls = context.getClassSource().get(clsName);
            MethodReader method = cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID));
            if (method != null) {
                writer.appendClass(clsName).append(".$$constructor$$ = ").appendMethodBody(method.getReference())
                        .append(";").softNewLine();
            }
        }
        writer.outdent().append("}").softNewLine();
        writer.append("var cls = " + self + ".$data;").softNewLine();
        writer.append("var ctor = cls.$$constructor$$;").softNewLine();
        writer.append("if (!ctor) {").indent().softNewLine();
        writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();").softNewLine();
        writer.appendMethodBody(new MethodReference(InstantiationException.class.getName(), new MethodDescriptor(
                "<init>", ValueType.VOID))).append("(ex);").softNewLine();
        writer.append("$rt_throw(ex);").softNewLine();
        writer.outdent().append("}").softNewLine();
        writer.append("var instance = new cls();").softNewLine();
        writer.append("ctor(instance);").softNewLine();
        writer.append("return instance;").softNewLine();
    }

    private void generateGetDeclaringClass(GeneratorContext context, SourceWriter writer) throws IOException {
        String self = context.getParameterName(0);
        writer.append("if (!").appendClass("java.lang.Class").append(".$$owners$$) {").indent().softNewLine();
        writer.appendClass("java.lang.Class").append(".$$owners$$ = true;").softNewLine();
        for (String clsName : context.getClassSource().getClassNames()) {
            ClassReader cls = context.getClassSource().get(clsName);
            writer.appendClass(clsName).append(".$$owner$$ = ");
            if (cls.getOwnerName() != null) {
                writer.appendClass(cls.getOwnerName());
            } else {
                writer.append("null");
            }
            writer.append(";").softNewLine();
        }
        writer.outdent().append("}").softNewLine();
        writer.append("var cls = " + self + ".$data;").softNewLine();
        writer.append("return cls.$$owner$$ != null ? $rt_cls(cls.$$owner$$) : null;").softNewLine();
    }

    @Override
    public void methodAchieved(DependencyAgent agent, MethodDependency graph) {
        switch (graph.getReference().getName()) {
            case "voidClass":
            case "booleanClass":
            case "byteClass":
            case "shortClass":
            case "charClass":
            case "intClass":
            case "longClass":
            case "floatClass":
            case "doubleClass":
            case "wrapClass":
            case "getSuperclass":
            case "getComponentType0":
            case "forNameImpl":
            case "getDeclaringClass":
                graph.getResult().propagate(agent.getType("java.lang.Class"));
                break;
            case "newInstance":
                agent.linkMethod(new MethodReference(InstantiationException.class.getName(), "<init>",
                        ValueType.VOID), graph.getStack()).use();
                break;
        }
    }
}
TOP

Related Classes of org.teavm.classlib.java.lang.ClassNativeGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.