| 575 | | public static AnalyzeResult disambiguate(FortressRepository repository, |
| 576 | | GlobalEnvironment env, |
| 577 | | AnalyzeResult previousPhase, |
| 578 | | long lastModified) throws StaticError { |
| 579 | | |
| 580 | | // Build a new GlobalEnvironment consisting of all APIs in a global |
| 581 | | // repository combined with all APIs that have been processed in the previous |
| 582 | | // step. For now, we are implementing pure static linking, so there is |
| 583 | | // no global repository. |
| 584 | | GlobalEnvironment rawApiEnv = |
| 585 | | new GlobalEnvironment.FromMap(CollectUtil.union(repository.apis(), |
| 586 | | previousPhase.apis())); |
| 587 | | |
| 588 | | // Rewrite all API ASTs so they include only fully qualified names, relying |
| 589 | | // on the rawApiEnv constructed in the previous step. Note that, after this |
| 590 | | // step, the rawApiEnv is stale and needs to be rebuilt with the new API ASTs. |
| 591 | | Disambiguator.ApiResult apiDR = |
| 592 | | Disambiguator.disambiguateApis(previousPhase.apiIterator(), rawApiEnv, repository.apis()); |
| 593 | | if (!apiDR.isSuccessful()) { |
| 594 | | throw new MultipleStaticError(apiDR.errors()); |
| 595 | | } |
| 596 | | |
| 597 | | // Rebuild ApiIndices. |
| 598 | | IndexBuilder.ApiResult apiIR = |
| 599 | | IndexBuilder.buildApis(apiDR.apis(), lastModified); |
| 600 | | if (!apiIR.isSuccessful()) { |
| 601 | | throw new MultipleStaticError(apiIR.errors()); |
| 602 | | } |
| 603 | | |
| 604 | | // Rebuild GlobalEnvironment. |
| 605 | | GlobalEnvironment apiEnv = |
| 606 | | new GlobalEnvironment.FromMap(CollectUtil.union(repository.apis(), |
| 607 | | apiIR.apis())); |
| 608 | | |
| 609 | | Disambiguator.ComponentResult componentDR = |
| 610 | | Disambiguator.disambiguateComponents(previousPhase.componentIterator(), apiEnv, |
| 611 | | previousPhase.components()); |
| 612 | | if (!componentDR.isSuccessful()) { |
| 613 | | throw new MultipleStaticError(componentDR.errors()); |
| 614 | | } |
| 615 | | |
| 616 | | // Rebuild ComponentIndices. |
| 617 | | IndexBuilder.ComponentResult componentsDone = |
| 618 | | IndexBuilder.buildComponents(componentDR.components(), lastModified); |
| 619 | | if (!componentsDone.isSuccessful()) { |
| 620 | | throw new MultipleStaticError(componentsDone.errors()); |
| 621 | | } |
| 622 | | |
| 623 | | return new AnalyzeResult(previousPhase, apiIR.apis(), |
| 624 | | componentsDone.components(), IterUtil.<StaticError>empty()); |
| 625 | | } |
| 626 | | |
| 627 | | public static AnalyzeResult rewriteGrammar(FortressRepository repository, |
| 628 | | GlobalEnvironment env, |
| 629 | | AnalyzeResult previousPhase, |
| 630 | | long lastModified) throws StaticError { |
| 631 | | GlobalEnvironment apiEnv = |
| 632 | | new GlobalEnvironment.FromMap(CollectUtil.union(repository.apis(), |
| 633 | | previousPhase.apis())); |
| 634 | | |
| 635 | | GrammarRewriter.ApiResult apiID = GrammarRewriter.rewriteApis(previousPhase.apis(), apiEnv); |
| 636 | | if (!apiID.isSuccessful()) { |
| 637 | | throw new MultipleStaticError(apiID.errors()); |
| 638 | | } |
| 639 | | |
| 640 | | IndexBuilder.ApiResult apiDone = IndexBuilder.buildApis(apiID.apis(), lastModified); |
| 641 | | if (!apiDone.isSuccessful()) { |
| 642 | | throw new MultipleStaticError(apiDone.errors()); |
| 643 | | } |
| 644 | | |
| 645 | | return new AnalyzeResult(previousPhase, apiDone.apis(), |
| 646 | | previousPhase.components(), IterUtil.<StaticError>empty()); |
| 647 | | } |
| 648 | | |
| 649 | | public static AnalyzeResult typecheck(FortressRepository _repository, |
| 650 | | GlobalEnvironment env, |
| 651 | | AnalyzeResult previousPhase, |
| 652 | | long lastModified) throws StaticError { |
| 653 | | IndexBuilder.ApiResult apiIndex = IndexBuilder.buildApis(previousPhase.apiIterator(), lastModified); |
| 654 | | IndexBuilder.ComponentResult componentIndex = IndexBuilder.buildComponents(previousPhase.componentIterator(), lastModified); |
| 655 | | GlobalEnvironment apiEnv = new GlobalEnvironment.FromMap(CollectUtil.union(_repository.apis(), |
| 656 | | apiIndex.apis())); |
| 657 | | |
| 658 | | StaticChecker.ApiResult apiSR = StaticChecker.checkApis( apiIndex.apis(), apiEnv ); |
| 659 | | |
| 660 | | if ( !apiSR.isSuccessful() ){ |
| 661 | | throw new MultipleStaticError(apiSR.errors()); |
| 662 | | } |
| 663 | | |
| 664 | | StaticChecker.ComponentResult componentSR = |
| 665 | | StaticChecker.checkComponents( componentIndex.components(), env); |
| 666 | | |
| 667 | | if ( !componentSR.isSuccessful() ){ |
| 668 | | throw new MultipleStaticError(componentSR.errors()); |
| 669 | | } |
| 670 | | |
| 671 | | return new AnalyzeResult(apiSR.apis(), componentSR.components(), |
| 672 | | IterUtil.<StaticError>empty(), componentSR.typeEnvAtNode()); |
| 673 | | } |
| 674 | | |
| 675 | | public static AnalyzeResult desugar(FortressRepository _repository, |
| 676 | | GlobalEnvironment env, |
| 677 | | AnalyzeResult previousPhase, |
| 678 | | long lastModified) throws StaticError { |
| 679 | | GlobalEnvironment apiEnv = new GlobalEnvironment.FromMap(CollectUtil.union(_repository.apis(), |
| 680 | | previousPhase.apis())); |
| 681 | | |
| 682 | | Desugarer.ApiResult apiDSR = Desugarer.desugarApis(previousPhase.apis(), apiEnv); |
| 683 | | |
| 684 | | if ( ! apiDSR.isSuccessful() ){ |
| 685 | | throw new MultipleStaticError(apiDSR.errors()); |
| 686 | | } |
| 687 | | |
| 688 | | Desugarer.ComponentResult componentDSR = Desugarer.desugarComponents(previousPhase.components(), apiEnv); |
| 689 | | |
| 690 | | if ( ! componentDSR.isSuccessful() ){ |
| 691 | | throw new MultipleStaticError(componentDSR.errors()); |
| 692 | | } |
| 693 | | |
| 694 | | return new AnalyzeResult(previousPhase, apiDSR.apis(), |
| 695 | | componentDSR.components(), IterUtil.<StaticError>empty()); |
| 696 | | } |
| 697 | | |
| 698 | | public static AnalyzeResult codeGeneration(FortressRepository _repository, |
| 699 | | GlobalEnvironment env, |
| 700 | | AnalyzeResult previousPhase, |
| 701 | | long lastModified) throws StaticError { |
| 702 | | TopLevelEnvGen.CompilationUnitResult apiGR = |
| 703 | | TopLevelEnvGen.generateApiEnvs(previousPhase.apis()); |
| 704 | | |
| 705 | | if ( !apiGR.isSuccessful() ){ |
| 706 | | throw new MultipleStaticError(apiGR.errors()); |
| 707 | | } |
| 708 | | |
| 709 | | // Generate top-level byte code environments for components |
| 710 | | TopLevelEnvGen.CompilationUnitResult componentGR = |
| 711 | | TopLevelEnvGen.generateComponentEnvs(previousPhase.components()); |
| 712 | | |
| 713 | | if ( !componentGR.isSuccessful() ){ |
| 714 | | throw new MultipleStaticError(componentGR.errors()); |
| 715 | | } |
| 716 | | |
| 717 | | return new AnalyzeResult(previousPhase, previousPhase.apis(), |
| 718 | | previousPhase.components(), IterUtil.<StaticError>empty()); |
| 719 | | } |
| 720 | | |
| 721 | | private static abstract class Phase{ |
| 722 | | Phase parent; |
| 723 | | public Phase( Phase parent ){ |
| 724 | | this.parent = parent; |
| 725 | | } |
| 726 | | |
| 727 | | public abstract AnalyzeResult execute( AnalyzeResult previousPhase) throws StaticError ; |
| 728 | | |
| 729 | | public AnalyzeResult run() throws StaticError { |
| 730 | | AnalyzeResult result = parent.run(); |
| 731 | | return execute( result ); |
| 732 | | } |
| 733 | | } |
| 734 | | |
| 735 | | private static Phase getPhase(final FortressRepository repository, |
| 736 | | final GlobalEnvironment env, |
| 737 | | final Iterable<Api> apis, |
| 738 | | final Iterable<Component> components, |
| 739 | | final long lastModified, |
| 740 | | final int phase){ |
| 741 | | class EmptyPhase extends Phase{ |
| 742 | | public EmptyPhase(){ |
| 743 | | super(null); |
| 744 | | } |
| 745 | | |
| 746 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 747 | | return null; |
| 748 | | } |
| 749 | | |
| 750 | | public AnalyzeResult run() throws StaticError { |
| 751 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase Empty" ); |
| 752 | | IndexBuilder.ApiResult apiIndex = IndexBuilder.buildApis(apis, lastModified); |
| 753 | | IndexBuilder.ComponentResult componentIndex = IndexBuilder.buildComponents(components, lastModified); |
| 754 | | return new AnalyzeResult(apiIndex.apis(), componentIndex.components(), IterUtil.<StaticError>empty()); |
| 755 | | } |
| 756 | | } |
| 757 | | |
| 758 | | class DisambiguatePhase extends Phase { |
| 759 | | public DisambiguatePhase( Phase parent ){ |
| 760 | | super(parent); |
| 761 | | } |
| 762 | | |
| 763 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 764 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase Disambiguate" ); |
| 765 | | return disambiguate(repository, env, previousPhase, lastModified); |
| 766 | | } |
| 767 | | } |
| 768 | | |
| 769 | | class TypecheckPhase extends Phase { |
| 770 | | public TypecheckPhase( Phase parent ){ |
| 771 | | super(parent); |
| 772 | | } |
| 773 | | |
| 774 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 775 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase TypeCheck" ); |
| 776 | | return typecheck(repository, env, previousPhase, lastModified); |
| 777 | | } |
| 778 | | } |
| 779 | | |
| 780 | | class DesugarPhase extends Phase { |
| 781 | | public DesugarPhase( Phase parent ){ |
| 782 | | super(parent); |
| 783 | | } |
| 784 | | |
| 785 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 786 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase Desugar" ); |
| 787 | | return desugar(repository, env, previousPhase, lastModified); |
| 788 | | } |
| 789 | | } |
| 790 | | |
| 791 | | class CodeGenerationPhase extends Phase { |
| 792 | | public CodeGenerationPhase( Phase parent ){ |
| 793 | | super(parent); |
| 794 | | } |
| 795 | | |
| 796 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 797 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase TopLevelEnvironment" ); |
| 798 | | return codeGeneration(repository, env, previousPhase, lastModified); |
| 799 | | } |
| 800 | | } |
| 801 | | |
| 802 | | class GrammarPhase extends Phase { |
| 803 | | public GrammarPhase( Phase parent ){ |
| 804 | | super(parent); |
| 805 | | } |
| 806 | | |
| 807 | | public AnalyzeResult execute( AnalyzeResult previousPhase ) throws StaticError { |
| 808 | | Debug.debug( Debug.Type.FORTRESS, 1, "Start phase GrammarPhase" ); |
| 809 | | return rewriteGrammar(repository, env, previousPhase, lastModified); |
| 810 | | } |
| 811 | | } |
| 812 | | |
| 813 | | Lambda<Integer,Phase> nextPhase = new Lambda<Integer,Phase>(){ |
| 814 | | public Phase value(Integer phase){ |
| 815 | | return getPhase(repository, env, apis, components, lastModified, phase ); |
| 816 | | } |
| 817 | | }; |
| 818 | | |
| 819 | | /* Phases are listed in the order they occur, top to bottom. If new phases are added please |
| 820 | | * respect this ordering. This is simply to make it easy to look at. |
| 821 | | */ |
| 822 | | switch (phase){ |
| 823 | | case PHASE_EMPTY : return new EmptyPhase(); |
| 824 | | case PHASE_DISAMBIGUATE : return new DisambiguatePhase(nextPhase.value(PHASE_EMPTY)); |
| 825 | | case PHASE_GRAMMAR : return new GrammarPhase(nextPhase.value(PHASE_DISAMBIGUATE)); |
| 826 | | case PHASE_TYPECHECK : return new TypecheckPhase(nextPhase.value(PHASE_GRAMMAR)); |
| 827 | | case PHASE_DESUGAR : return new DesugarPhase(nextPhase.value(PHASE_TYPECHECK)); |
| 828 | | case PHASE_CODEGEN : return new CodeGenerationPhase(nextPhase.value(PHASE_DESUGAR)); |
| 829 | | default : throw new RuntimeException( "Invalid phase number: " + phase ); |
| 830 | | } |
| 831 | | } |
| 832 | | |