comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 7855:6e4fb0ccebb1

Generated factories implement the new NodeFactory interface.
author Christian Humer <christian.humer@gmail.com>
date Mon, 25 Feb 2013 13:13:02 +0100
parents 06a7cd6aaf00
children 4958cbdbf360
comparison
equal deleted inserted replaced
7854:8e56c6951c86 7855:6e4fb0ccebb1
29 29
30 import javax.lang.model.element.*; 30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*; 31 import javax.lang.model.type.*;
32 import javax.lang.model.util.*; 32 import javax.lang.model.util.*;
33 33
34 import com.oracle.truffle.api.codegen.*;
34 import com.oracle.truffle.codegen.processor.*; 35 import com.oracle.truffle.codegen.processor.*;
35 import com.oracle.truffle.codegen.processor.ast.*; 36 import com.oracle.truffle.codegen.processor.ast.*;
36 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; 37 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
37 import com.oracle.truffle.codegen.processor.template.*; 38 import com.oracle.truffle.codegen.processor.template.*;
38 import com.oracle.truffle.codegen.processor.typesystem.*; 39 import com.oracle.truffle.codegen.processor.typesystem.*;
420 if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) { 421 if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) {
421 NodeGenFactory factory = new NodeGenFactory(context); 422 NodeGenFactory factory = new NodeGenFactory(context);
422 add(factory, node); 423 add(factory, node);
423 } 424 }
424 425
425 if (node.getSpecializations() == null) {
426 return;
427 }
428
429 if (node.needsFactory() || childTypes.size() > 0) { 426 if (node.needsFactory() || childTypes.size() > 0) {
430 add(new NodeFactoryFactory(context, childTypes), node); 427 add(new NodeFactoryFactory(context, childTypes), node);
431 } 428 }
432 } 429 }
433 430
509 } 506 }
510 507
511 for (SpecializationData specialization : node.getSpecializations()) { 508 for (SpecializationData specialization : node.getSpecializations()) {
512 add(new SpecializedNodeFactory(context), specialization); 509 add(new SpecializedNodeFactory(context), specialization);
513 } 510 }
511
512 TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType());
513 clazz.getImplements().add(nodeFactory);
514 clazz.add(createCreateNodeMethod(node, createVisibility));
515 clazz.add(createCreateNodeSpecializedMethod(node, createVisibility));
516 clazz.add(createGetNodeClassMethod(node));
517 clazz.add(createGetNodeSignaturesMethod(node));
518 clazz.add(createGetInstanceMethod(node, clazz.asType(), createVisibility));
519 clazz.add(createInstanceConstant(node, clazz.asType()));
514 } 520 }
515 521
516 for (NodeData childNode : childTypes.keySet()) { 522 for (NodeData childNode : childTypes.keySet()) {
517 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { 523 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
518 continue; 524 continue;
529 typeModifiers.add(Modifier.STATIC); 535 typeModifiers.add(Modifier.STATIC);
530 typeModifiers.add(Modifier.FINAL); 536 typeModifiers.add(Modifier.FINAL);
531 clazz.add(type); 537 clazz.add(type);
532 } 538 }
533 } 539 }
540
541 if (node.getParent() == null && node.getDeclaredChildren().size() > 0) {
542 List<NodeData> children = node.getNodeChildren();
543 List<TypeMirror> types = new ArrayList<>();
544 if (node.needsFactory()) {
545 types.add(node.getNodeType());
546 }
547 for (NodeData child : children) {
548 types.add(child.getTemplateType().asType());
549 }
550 TypeMirror commonSuperType = Utils.getCommonSuperType(getContext(), types.toArray(new TypeMirror[types.size()]));
551 clazz.add(createGetFactories(node, commonSuperType));
552 }
553
554 }
555
556 private CodeExecutableElement createGetNodeClassMethod(NodeData node) {
557 Types types = getContext().getEnvironment().getTypeUtils();
558 TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType());
559 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass");
560 CodeTreeBuilder builder = method.createBuilder();
561 builder.startReturn().typeLiteral(node.getNodeType()).end();
562 return method;
563 }
564
565 private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) {
566 Types types = getContext().getEnvironment().getTypeUtils();
567 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
568 TypeMirror classType = getContext().getType(Class.class);
569 TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType));
570 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures");
571 CodeTreeBuilder builder = method.createBuilder();
572 builder.startReturn();
573 builder.startStaticCall(getContext().getType(Arrays.class), "asList");
574 List<ExecutableElement> constructors = findUserConstructors(node);
575 for (ExecutableElement constructor : constructors) {
576 builder.startGroup();
577 builder.type(getContext().getType(Arrays.class));
578 builder.string(".<").type(getContext().getType(Class.class)).string(">");
579 builder.startCall("asList");
580 for (VariableElement param : constructor.getParameters()) {
581 builder.typeLiteral(param.asType());
582 }
583 builder.end();
584 builder.end();
585 }
586 builder.end();
587 builder.end();
588 return method;
589 }
590
591 private CodeExecutableElement createCreateNodeMethod(NodeData node, Modifier visibility) {
592 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createNode");
593 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
594 method.setVarArgs(true);
595 method.addParameter(arguments);
596
597 if (visibility != null) {
598 method.getModifiers().add(visibility);
599 }
600
601 CodeTreeBuilder builder = method.createBuilder();
602 List<ExecutableElement> signatures = findUserConstructors(node);
603 boolean ifStarted = false;
604
605 for (ExecutableElement element : signatures) {
606 ifStarted = builder.startIf(ifStarted);
607 builder.string("arguments.length == " + element.getParameters().size());
608
609 int index = 0;
610 for (VariableElement param : element.getParameters()) {
611 builder.string(" && ");
612 if (!param.asType().getKind().isPrimitive()) {
613 builder.string("(arguments[" + index + "] == null || ");
614 }
615 builder.string("arguments[" + index + "] instanceof ");
616 builder.type(Utils.boxType(getContext(), param.asType()));
617 if (!param.asType().getKind().isPrimitive()) {
618 builder.string(")");
619 }
620 index++;
621 }
622 builder.end();
623 builder.startBlock();
624
625 builder.startReturn().startCall("create");
626 index = 0;
627 for (VariableElement param : element.getParameters()) {
628 builder.startGroup();
629 builder.string("(").type(param.asType()).string(") ");
630 builder.string("arguments[").string(String.valueOf(index)).string("]");
631 builder.end();
632 index++;
633 }
634 builder.end().end();
635
636 builder.end(); // block
637 }
638
639 builder.startElseBlock();
640 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
641 builder.doubleQuote("Invalid create signature.");
642 builder.end().end();
643 builder.end(); // else block
644 return method;
645 }
646
647 private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node, Modifier visibility) {
648 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createNodeSpecialized");
649 CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode");
650 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types");
651 method.addParameter(nodeParam);
652 method.addParameter(arguments);
653 method.setVarArgs(true);
654 if (visibility != null) {
655 method.getModifiers().add(visibility);
656 }
657
658 CodeTreeBuilder builder = method.createBuilder();
659 if (!node.needsRewrites(getContext())) {
660 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
661 } else {
662 builder.startIf();
663 builder.string("types.length == 1");
664 builder.end();
665 builder.startBlock();
666
667 builder.startReturn().startCall("createSpecialized");
668 builder.string("thisNode");
669 builder.string("types[0]");
670 builder.end().end();
671
672 builder.end();
673 builder.startElseBlock();
674 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
675 builder.doubleQuote("Invalid createSpecialized signature.");
676 builder.end().end();
677 builder.end();
678 }
679
680 return method;
681 }
682
683 private ExecutableElement createGetInstanceMethod(NodeData node, TypeMirror factoryType, Modifier visibility) {
684 CodeExecutableElement method = new CodeExecutableElement(modifiers(), factoryType, "getInstance");
685 if (visibility != null) {
686 method.getModifiers().add(visibility);
687 }
688 method.getModifiers().add(Modifier.STATIC);
689
690 String varName = instanceVarName(node);
691
692 CodeTreeBuilder builder = method.createBuilder();
693 builder.startIf();
694 builder.string(varName).string(" == null");
695 builder.end().startBlock();
696
697 builder.startStatement();
698 builder.string(varName);
699 builder.string(" = ");
700 builder.startNew(factoryClassName(node)).end();
701 builder.end();
702
703 builder.end();
704 builder.startReturn().string(varName).end();
705 return method;
706 }
707
708 private String instanceVarName(NodeData node) {
709 if (node.getParent() != null) {
710 return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
711 } else {
712 return "instance";
713 }
714 }
715
716 private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
717 String varName = instanceVarName(node);
718 CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
719 var.getModifiers().add(Modifier.PRIVATE);
720 var.getModifiers().add(Modifier.STATIC);
721 return var;
722 }
723
724 private ExecutableElement createGetFactories(NodeData node, TypeMirror commonSuperType) {
725 Types types = getContext().getEnvironment().getTypeUtils();
726 TypeMirror classType = getContext().getType(NodeFactory.class);
727 TypeMirror classWithWildcards = types.getDeclaredType(Utils.fromTypeMirror(classType), types.getWildcardType(commonSuperType, null));
728 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), classWithWildcards);
729
730 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
731
732 CodeTreeBuilder builder = method.createBuilder();
733 builder.startReturn();
734 builder.startStaticCall(getContext().getType(Arrays.class), "asList");
735 List<NodeData> children = node.getNodeChildren();
736 if (node.needsFactory()) {
737 children.add(node);
738 }
739
740 for (NodeData child : children) {
741 builder.startGroup();
742 NodeData childNode = child;
743 List<NodeData> factories = new ArrayList<>();
744 while (childNode.getParent() != null) {
745 factories.add(childNode);
746 childNode = childNode.getParent();
747 }
748 Collections.reverse(factories);
749 for (NodeData nodeData : factories) {
750 builder.string(factoryClassName(nodeData)).string(".");
751 }
752 builder.string("getInstance()");
753 builder.end();
754 }
755 builder.end();
756 builder.end();
757 return method;
534 } 758 }
535 759
536 private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { 760 private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
761 List<ExecutableElement> constructors = findUserConstructors(node);
762 for (ExecutableElement constructor : constructors) {
763 clazz.add(createCreateMethod(node, createVisibility, constructor));
764 }
765 }
766
767 private List<ExecutableElement> findUserConstructors(NodeData node) {
768 List<ExecutableElement> constructors = new ArrayList<>();
537 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { 769 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) {
538 if (constructor.getModifiers().contains(PRIVATE)) { 770 if (constructor.getModifiers().contains(PRIVATE)) {
539 continue; 771 continue;
540 } 772 }
541 773
542 // skip node rewrite constructor 774 // skip node rewrite constructor
543 if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { 775 if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) {
544 continue; 776 continue;
545 } 777 }
546 778 constructors.add(constructor);
547 clazz.add(createCreateMethod(node, createVisibility, constructor)); 779 }
548 } 780 return constructors;
549 } 781 }
550 782
551 private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { 783 private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
552 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); 784 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
553 method.setSimpleName(CodeNames.of("create")); 785 method.setSimpleName(CodeNames.of("create"));