|
|
@@ -790,3322 +790,3324 @@ Listing:
|
|
|
771 astSeq, astTail, astProc: AST.Node; .)
|
|
|
772 = (. refN := 0; refSeen := FALSE; .)
|
|
|
773 "DEFINITION" "MODULE"
|
|
|
- 774 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
- 775 IF instActive THEN
|
|
|
- 776 IF NOT SymTab.Reenter(m1,
|
|
|
- 777 SymTab.UnitDef) THEN
|
|
|
- 778 SemError(200) END
|
|
|
- 779 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
- 780 SemError(200) END;
|
|
|
- 781 QbeGen.SetModule(m1);
|
|
|
- 782 CopyNm(m1, unitName);
|
|
|
- 783 unitWasGen := isGen
|
|
|
- 784 AND NOT instActive;
|
|
|
- 785 unitWasDef := TRUE; .)
|
|
|
- 786 [ GenericFormals ]
|
|
|
- 787 ( ";"
|
|
|
- 788 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 789 astImp, astImpTail, astDecl); .) }
|
|
|
- 790 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
- 791 list: parsed, and the
|
|
|
- 792 names are already exported
|
|
|
- 793 by the module scope *) .)
|
|
|
- 794 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
- 795 (. astSeq := AST.NoNode;
|
|
|
- 796 astTail := AST.NoNode; .)
|
|
|
- 797 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
- 798 astSeq, astTail, astDecl); .)
|
|
|
- 799 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
- 800 astSeq, astTail, astDecl); .)
|
|
|
- 801 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
- 802 astSeq, astTail, astDecl); .)
|
|
|
- 803 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 804 (. (* a heading only: record it so
|
|
|
- 805 Lower can replay it *)
|
|
|
- 806 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 807 AST.SetOp(astProc, 0);
|
|
|
- 808 AST.SetChild(astProc, 0,
|
|
|
- 809 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 810 AstAppend(AST.NkDeclSeq,
|
|
|
- 811 astSeq, astTail, astProc);
|
|
|
- 812 Lower.NoteProcNode(astProc);
|
|
|
- 813 Lower.ScopeLeave;
|
|
|
- 814 SymTab.CloseProc;
|
|
|
- 815 QbeGen.AbortFunc; .) }
|
|
|
- 816 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
- 817 AST.SetChild(astUnit, 0,
|
|
|
- 818 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 819 AST.SetChild(astUnit, 1, astSeq);
|
|
|
- 820 AST.SetChild(astUnit, 3, astImp);
|
|
|
- 821 astDecl := AST.NoNode;
|
|
|
- 822 astStmt := AST.NoNode; .)
|
|
|
- 823 "END"
|
|
|
- 824 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
- 825 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 826 SemError(202) END;
|
|
|
- 827 SymTab.EndUnit; .)
|
|
|
- 828 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
- 829 (. CopyNm(m1, refInst);
|
|
|
- 830 CopyNm(g, refGen);
|
|
|
- 831 refSeen := TRUE; refIsDef := TRUE;
|
|
|
- 832 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
- 833 AST.SetChild(astUnit, 0,
|
|
|
- 834 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 835 astDecl := AST.NoNode;
|
|
|
- 836 astStmt := AST.NoNode; .)
|
|
|
- 837 "END"
|
|
|
- 838 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 839 SemError(202) END;
|
|
|
- 840 SymTab.EndUnit; .) ) .
|
|
|
- 841 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
- 842 g: SymTab.Name;
|
|
|
- 843 k: CARDINAL;
|
|
|
- 844 rp: CARDINAL;
|
|
|
- 845 rpOk: BOOLEAN;
|
|
|
- 846 rErrs: INTEGER;
|
|
|
- 847 rDecl, rStmt: AST.Node;
|
|
|
- 848 rnm: SymTab.Name;
|
|
|
- 849 rSym, rErr: CARDINAL;
|
|
|
- 850 fname: SymTab.Name;
|
|
|
- 851 unres: BOOLEAN;
|
|
|
- 852 astNode: AST.Node; .)
|
|
|
- 853 = (. refN := 0; refSeen := FALSE; .)
|
|
|
- 854 "IMPLEMENTATION" "MODULE"
|
|
|
- 855 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
- 856 IF instActive THEN
|
|
|
- 857 IF NOT SymTab.Reenter(m1,
|
|
|
- 858 SymTab.UnitImpl) THEN
|
|
|
- 859 SemError(201) END
|
|
|
- 860 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
- 861 SemError(201) END;
|
|
|
- 862 astStmt := AST.NoNode;
|
|
|
- 863 astDecl := AST.NoNode;
|
|
|
- 864 astImp := AST.NoNode;
|
|
|
- 865 astImpTail := AST.NoNode;
|
|
|
- 866 nPendVar := 0;
|
|
|
- 867 CopyNm(m1, unitName);
|
|
|
- 868 unitWasGen := isGen AND NOT instActive;
|
|
|
- 869 unitWasDef := FALSE;
|
|
|
- 870 QbeGen.SetModule(m1); .)
|
|
|
- 871 [ GenericFormals ]
|
|
|
- 872 ( ";"
|
|
|
- 873 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 874 astImp, astImpTail, astDecl); .) }
|
|
|
- 875 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 876 [ "BEGIN" (. FlushPend;
|
|
|
- 877 k := 0;
|
|
|
- 878 WHILE k < SymTab.FwdPending() DO
|
|
|
- 879 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 880 IF unres THEN SemError(201) END;
|
|
|
- 881 INC(k)
|
|
|
- 882 END;
|
|
|
- 883 SymTab.FwdClear;
|
|
|
- 884
|
|
|
- 885 nLab := 0; nGot := 0; .)
|
|
|
- 886 [ StatSeq ] ]
|
|
|
- 887 (. IF twoPhaseParse THEN
|
|
|
- 888 rSym := sym; rErr := errDist;
|
|
|
- 889 rDecl := astDecl; rStmt := astStmt;
|
|
|
- 890 M2S.PushPos;
|
|
|
- 891 repassing := TRUE;
|
|
|
- 892 rp := 0;
|
|
|
- 893 WHILE rp < nSpans DO
|
|
|
- 894 k := 0;
|
|
|
- 895 WHILE (k <= HIGH(rnm))
|
|
|
- 896 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
- 897 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
- 898 END;
|
|
|
- 899 rnm[k] := CHR(0);
|
|
|
- 900 M2S.SeekTo(spanStart[rp]);
|
|
|
- 901 Adv;
|
|
|
- 902 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
- 903 IF NOT rpOk THEN
|
|
|
- 904 FileIO.WriteString(FileIO.StdOut,
|
|
|
- 905 "twophase reenter failed");
|
|
|
- 906 FileIO.WriteLn(FileIO.StdOut)
|
|
|
- 907 END;
|
|
|
- 908 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
- 909 QbeGen.BeginFunc("");
|
|
|
- 910 Block(rnm);
|
|
|
- 911 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
- 912 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
- 913 Lower.ScopeLeave;
|
|
|
- 914 SymTab.CloseProc;
|
|
|
- 915 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
- 916 INC(rp)
|
|
|
- 917 END;
|
|
|
- 918 rErrs := M2S.errors;
|
|
|
- 919 repassing := FALSE;
|
|
|
- 920 M2S.PopPos;
|
|
|
- 921 sym := rSym; errDist := rErr;
|
|
|
- 922 M2S.errors := rErrs;
|
|
|
- 923
|
|
|
- 924 astDecl := rDecl; astStmt := rStmt
|
|
|
- 925 END; .)
|
|
|
- 926 "END"
|
|
|
- 927 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
- 928 FlushPend;
|
|
|
- 929 k := 0;
|
|
|
- 930 WHILE k < SymTab.FwdPending() DO
|
|
|
- 931 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 932 IF unres THEN SemError(201) END;
|
|
|
- 933 INC(k)
|
|
|
- 934 END;
|
|
|
- 935 SymTab.FwdClear;
|
|
|
- 936
|
|
|
- 937 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 938 AST.SetChild(astNode, 0,
|
|
|
- 939 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 940 AST.SetChild(astNode, 1, astDecl);
|
|
|
- 941 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 942 AST.SetChild(astNode, 3, astImp);
|
|
|
- 943 astUnit := astNode;
|
|
|
- 944 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 945 SemError(202) END;
|
|
|
- 946 CheckGotos;
|
|
|
- 947 SymTab.EndUnit; .)
|
|
|
- 948 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
- 949 (. CopyNm(m1, refInst);
|
|
|
- 950 CopyNm(g, refGen);
|
|
|
- 951 refSeen := TRUE; refIsDef := FALSE;
|
|
|
- 952 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 953 AST.SetChild(astNode, 0,
|
|
|
- 954 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 955 astDecl := AST.NoNode;
|
|
|
- 956 astStmt := AST.NoNode; .)
|
|
|
- 957 { Import (. (* refinement unit import *) .) }
|
|
|
- 958 "END"
|
|
|
- 959 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 960 SemError(202) END;
|
|
|
- 961 SymTab.EndUnit; .) ) .
|
|
|
- 962 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
- 963 k: CARDINAL;
|
|
|
- 964 rp: CARDINAL;
|
|
|
- 965 rpOk: BOOLEAN;
|
|
|
- 966 rErrs: INTEGER;
|
|
|
- 967 rDecl, rStmt: AST.Node;
|
|
|
- 968 rnm: SymTab.Name;
|
|
|
- 969 rSym, rErr: CARDINAL;
|
|
|
- 970 fname: SymTab.Name;
|
|
|
- 971 unres: BOOLEAN;
|
|
|
- 972 astNode: AST.Node; .)
|
|
|
- 973 = "MODULE"
|
|
|
- 974 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
- 975 SemError(200) END;
|
|
|
- 976 astStmt := AST.NoNode;
|
|
|
- 977 astDecl := AST.NoNode;
|
|
|
- 978 astImp := AST.NoNode;
|
|
|
- 979 astImpTail := AST.NoNode;
|
|
|
- 980 nPendVar := 0;
|
|
|
- 981 QbeGen.SetModule(m1); .)
|
|
|
- 982 [ Priority ]
|
|
|
- 983 ";"
|
|
|
- 984 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 985 astImp, astImpTail, astDecl); .) }
|
|
|
- 986 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 987 [ "BEGIN" (. FlushPend;
|
|
|
- 988 k := 0;
|
|
|
- 989 WHILE k < SymTab.FwdPending() DO
|
|
|
- 990 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 991 IF unres THEN SemError(201) END;
|
|
|
- 992 INC(k)
|
|
|
- 993 END;
|
|
|
- 994 SymTab.FwdClear;
|
|
|
- 995
|
|
|
- 996 nLab := 0; nGot := 0; .)
|
|
|
- 997 [ StatSeq ] ]
|
|
|
- 998 (. IF twoPhaseParse THEN
|
|
|
- 999 rSym := sym; rErr := errDist;
|
|
|
- 1000 rDecl := astDecl; rStmt := astStmt;
|
|
|
- 1001 M2S.PushPos;
|
|
|
- 1002 repassing := TRUE;
|
|
|
- 1003 rp := 0;
|
|
|
- 1004 WHILE rp < nSpans DO
|
|
|
- 1005 k := 0;
|
|
|
- 1006 WHILE (k <= HIGH(rnm))
|
|
|
- 1007 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
- 1008 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
- 1009 END;
|
|
|
- 1010 rnm[k] := CHR(0);
|
|
|
- 1011 M2S.SeekTo(spanStart[rp]);
|
|
|
- 1012 Adv;
|
|
|
- 1013 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
- 1014 IF NOT rpOk THEN
|
|
|
- 1015 FileIO.WriteString(FileIO.StdOut,
|
|
|
- 1016 "twophase reenter failed");
|
|
|
- 1017 FileIO.WriteLn(FileIO.StdOut)
|
|
|
- 1018 END;
|
|
|
- 1019 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
- 1020 QbeGen.BeginFunc("");
|
|
|
- 1021 Block(rnm);
|
|
|
- 1022 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
- 1023 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
- 1024 Lower.ScopeLeave;
|
|
|
- 1025 SymTab.CloseProc;
|
|
|
- 1026 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
- 1027 INC(rp)
|
|
|
- 1028 END;
|
|
|
- 1029 rErrs := M2S.errors;
|
|
|
- 1030 repassing := FALSE;
|
|
|
- 1031 M2S.PopPos;
|
|
|
- 1032 sym := rSym; errDist := rErr;
|
|
|
- 1033 M2S.errors := rErrs;
|
|
|
- 1034
|
|
|
- 1035 astDecl := rDecl; astStmt := rStmt
|
|
|
- 1036 END; .)
|
|
|
- 1037 "END"
|
|
|
- 1038 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
- 1039 FlushPend;
|
|
|
- 1040 k := 0;
|
|
|
- 1041 WHILE k < SymTab.FwdPending() DO
|
|
|
- 1042 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 1043 IF unres THEN SemError(201) END;
|
|
|
- 1044 INC(k)
|
|
|
- 1045 END;
|
|
|
- 1046 SymTab.FwdClear;
|
|
|
- 1047
|
|
|
- 1048 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 1049 SemError(202) END;
|
|
|
- 1050 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 1051 AST.SetChild(astNode, 0,
|
|
|
- 1052 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 1053 AST.SetChild(astNode, 1, astDecl);
|
|
|
- 1054 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 1055 AST.SetChild(astNode, 3, astImp);
|
|
|
- 1056 astUnit := astNode;
|
|
|
- 1057 CheckGotos;
|
|
|
- 1058 SymTab.EndUnit; .) .
|
|
|
- 1059 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1060 = (. astSeq := AST.NoNode;
|
|
|
- 1061 astTail := AST.NoNode; .)
|
|
|
- 1062 { (. astDecl := AST.NoNode; .)
|
|
|
- 1063 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
- 1064 | NestedModule ";" | ClassItem ";" )
|
|
|
- 1065 (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1066 astSeq, astTail, astDecl); .) }
|
|
|
- 1067 (. astDecl := astSeq; .) .
|
|
|
- 1068 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
- 1069 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
- 1070 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
- 1071 scope at END. *)
|
|
|
- 1072 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
- 1073 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
- 1074 expCount, k: CARDINAL;
|
|
|
- 1075 astNode, nImp, nImpTail:
|
|
|
- 1076 AST.Node; .)
|
|
|
- 1077 = "MODULE"
|
|
|
- 1078 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
- 1079 SymTab.KindModule) THEN
|
|
|
- 1080 SemError(200) END;
|
|
|
- 1081 SymTab.PushScope;
|
|
|
- 1082 expCount := 0;
|
|
|
- 1083 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 1084 AST.SetChild(astNode, 0,
|
|
|
- 1085 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 1086 astStmt := AST.NoNode;
|
|
|
- 1087 astDecl := AST.NoNode;
|
|
|
- 1088 nImp := AST.NoNode;
|
|
|
- 1089 nImpTail := AST.NoNode; .)
|
|
|
- 1090 [ Priority ]
|
|
|
- 1091 ";"
|
|
|
- 1092 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1093 nImp, nImpTail, astDecl); .) }
|
|
|
- 1094 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
- 1095 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
- 1096 { "," GetIdent<expNames[expCount]>
|
|
|
- 1097 (. INC(expCount); .) }
|
|
|
- 1098 ";" ]
|
|
|
- 1099 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 1100 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
- 1101 .)
|
|
|
- 1102 [ StatSeq ] ]
|
|
|
- 1103 "END"
|
|
|
- 1104 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
- 1105 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 1106 AST.SetChild(astNode, 3, nImp);
|
|
|
- 1107 astDecl := astNode;
|
|
|
- 1108 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 1109 SemError(202) END;
|
|
|
- 1110 k := 0;
|
|
|
- 1111 WHILE k < expCount DO
|
|
|
- 1112 SymTab.ExportUp(expNames[k]);
|
|
|
- 1113 INC(k)
|
|
|
- 1114 END;
|
|
|
- 1115 SymTab.PopScope; .) .
|
|
|
- 1116 Priority
|
|
|
- 1117 = "[" integer "]" (. SemError(230); .) .
|
|
|
- 1118 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
- 1119 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
- 1120 materializes on first use (Design). *)
|
|
|
- 1121 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
- 1122 import lines don't fail); a known module's missing export is
|
|
|
- 1123 201. *)
|
|
|
- 1124 Import (. VAR n: SymTab.Name;
|
|
|
- 1125 astImport: AST.Node; .)
|
|
|
- 1126 = "FROM"
|
|
|
- 1127 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
- 1128 AST.SetChild(astImport, 0,
|
|
|
- 1129 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 1130 "IMPORT"
|
|
|
- 1131 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
- 1132 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
- 1133 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
- 1134 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
- 1135 (. VAR n: SymTab.Name; .)
|
|
|
- 1136 = ImpName<mod, node>
|
|
|
- 1137 { "," ImpName<mod, node> } .
|
|
|
- 1138 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
- 1139 accepted and ignored: the built-in applies regardless. *)
|
|
|
- 1140 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
- 1141 (. VAR n: SymTab.Name; .)
|
|
|
- 1142 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 1143 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1144 IF SymTab.Equal(mod, "libc") THEN
|
|
|
- 1145 (* intrinsic C library:
|
|
|
- 1146 permissive external *)
|
|
|
- 1147 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
- 1148 SemError(201) END;
|
|
|
- 1149 Lower.NoteCProc(n)
|
|
|
- 1150 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
- 1151 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
- 1152 SemError(201)
|
|
|
- 1153 ELSE Lower.NoteImportedProc(n)
|
|
|
- 1154 END
|
|
|
- 1155 END; .)
|
|
|
- 1156 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
- 1157 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
- 1158 | "ODD" | "TRUNC" | "FLOAT"
|
|
|
- 1159 | "UCHR" | "CHR8" | "UORD"
|
|
|
- 1160 | "INC" | "DEC"
|
|
|
- 1161 | "SHIFT" | "ROTATE" | "CAST" | "MIN" | "MAX"
|
|
|
- 1162 | "INCL" | "EXCL" | "NEW" | "DISPOSE" | "LOC" ) .
|
|
|
- 1163 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
- 1164 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 1165 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 1166 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 1167 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
- 1168 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
- 1169 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
- 1170 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
- 1171 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
- 1172 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
- 1173 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1174 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
- 1175 astSeq := AST.NoNode;
|
|
|
- 1176 astTail := AST.NoNode; .)
|
|
|
- 1177 { (. astDecl := AST.NoNode; .)
|
|
|
- 1178 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
- 1179 (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1180 astSeq, astTail, astDecl); .) }
|
|
|
- 1181 (. SymTab.EndTypeBlock;
|
|
|
- 1182 astDecl := astSeq; .) .
|
|
|
- 1183 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
- 1184 t, op: SymTab.TypeIndex;
|
|
|
- 1185 astNode: AST.Node; .)
|
|
|
- 1186 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
- 1187 IF op = SymTab.InvalidType THEN
|
|
|
- 1188 IF NOT SymTab.Enter(n,
|
|
|
- 1189 SymTab.KindType) THEN
|
|
|
- 1190 SemError(200) END
|
|
|
- 1191 END; .)
|
|
|
- 1192 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
- 1193 AST.SetChild(astNode, 0,
|
|
|
- 1194 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1195 AST.SetTy(astNode, t);
|
|
|
- 1196 astDecl := astNode;
|
|
|
- 1197 IF op # SymTab.InvalidType THEN
|
|
|
- 1198 SymTab.SetTarget(op, t)
|
|
|
- 1199 ELSE SymTab.SetSymType(n, t)
|
|
|
- 1200 END; .)
|
|
|
- 1201 | (. IF op # SymTab.InvalidType THEN
|
|
|
- 1202 (* stays opaque *)
|
|
|
- 1203 ELSIF NOT isDef THEN
|
|
|
- 1204 SemError(231)
|
|
|
- 1205 ELSE SymTab.SetSymType(n,
|
|
|
- 1206 SymTab.NewAlias()) END; .) ) .
|
|
|
- 1207 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 1208 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
- 1209 | Subrange<t>
|
|
|
- 1210 | Enum<t>
|
|
|
- 1211 | ArrayType<t, allowOpen>
|
|
|
- 1212 | SetType<t>
|
|
|
- 1213 | RecordType<t>
|
|
|
- 1214 | PointerType<t>
|
|
|
- 1215 | ProcType<t> .
|
|
|
- 1216 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
- 1217 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
- 1218 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
- 1219 are code pointers; params are collected into the descriptor. *)
|
|
|
- 1220 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
- 1221 isV: BOOLEAN; .)
|
|
|
- 1222 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
- 1223 t := SymTab.NewProcType(res); .)
|
|
|
- 1224 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
- 1225 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
- 1226 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
- 1227 isV: BOOLEAN;
|
|
|
- 1228 cnt, k: CARDINAL;
|
|
|
- 1229 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
- 1230 = (. isV := FALSE; cnt := 0; .)
|
|
|
- 1231 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1232 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
- 1233 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
- 1234 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
- 1235 WHILE k < cnt DO
|
|
|
- 1236 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 1237 INC(k)
|
|
|
- 1238 END; .)
|
|
|
- 1239 | (. (* type-only parameter list:
|
|
|
- 1240 each name is a type (GNU
|
|
|
- 1241 shorthand used by the
|
|
|
- 1242 Coco/R scanner frame) *)
|
|
|
- 1243 k := 0;
|
|
|
- 1244 WHILE k < cnt DO
|
|
|
- 1245 IF SymTab.Lookup(names[k])
|
|
|
- 1246 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
- 1247 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
- 1248 pt := SymTab.SymType(names[k])
|
|
|
- 1249 ELSE SemError(201);
|
|
|
- 1250 pt := SymTab.InvalidType
|
|
|
- 1251 END;
|
|
|
- 1252 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 1253 INC(k)
|
|
|
- 1254 END; .) )
|
|
|
- 1255 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
- 1256 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
- 1257 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
- 1258 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
- 1259 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
- 1260 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
- 1261 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
- 1262 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 1263 (. VAR elem: SymTab.TypeIndex;
|
|
|
- 1264 ok: BOOLEAN;
|
|
|
- 1265 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
- 1266 nb, k: CARDINAL;
|
|
|
- 1267 idx: SymTab.TypeIndex;
|
|
|
- 1268 ilo, ihi: INTEGER; .)
|
|
|
- 1269 = "ARRAY"
|
|
|
- 1270 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
- 1271 SemError(230) END;
|
|
|
- 1272 t := SymTab.NewOpenArray(elem); .)
|
|
|
- 1273 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
- 1274 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
- 1275 type's ordinal bounds give the
|
|
|
- 1276 [lo..hi] pair *)
|
|
|
- 1277 IF SymTab.TypeBounds(idx, ilo,
|
|
|
- 1278 ihi)
|
|
|
- 1279 THEN t := SymTab.NewArrayB(elem,
|
|
|
- 1280 ilo, ihi)
|
|
|
- 1281 ELSIF SymTab.IsForwardType(idx)
|
|
|
- 1282 THEN
|
|
|
- 1283 (* forward index type: build
|
|
|
- 1284 with placeholder bounds,
|
|
|
- 1285 patched at EndTypeBlock *)
|
|
|
- 1286 t := SymTab.NewArrayB(elem,
|
|
|
- 1287 0, 0);
|
|
|
- 1288 SymTab.DeferArrayIdx(t, idx)
|
|
|
- 1289 ELSE SemError(230);
|
|
|
- 1290 t := SymTab.InvalidType
|
|
|
- 1291 END; .)
|
|
|
- 1292 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
- 1293 BoundPair<ok>
|
|
|
- 1294 { "," BoundPair<ok> }
|
|
|
- 1295 "]" (. (* snapshot before the element
|
|
|
- 1296 type, which reuses the bound
|
|
|
- 1297 buffer for a nested ARRAY *)
|
|
|
- 1298 nb := SymTab.BoundCount();
|
|
|
- 1299 k := 0;
|
|
|
- 1300 WHILE k < nb DO
|
|
|
- 1301 bnds[k] := SymTab.BoundLo(k);
|
|
|
- 1302 bndh[k] := SymTab.BoundHi(k);
|
|
|
- 1303 INC(k)
|
|
|
- 1304 END; .)
|
|
|
- 1305 "OF" Type<elem, FALSE>
|
|
|
- 1306 (. IF ok THEN
|
|
|
- 1307 k := nb;
|
|
|
- 1308 WHILE k > 0 DO
|
|
|
- 1309 DEC(k);
|
|
|
- 1310 elem := SymTab.NewArrayB(
|
|
|
- 1311 elem, bnds[k], bndh[k])
|
|
|
- 1312 END;
|
|
|
- 1313 t := elem
|
|
|
- 1314 ELSE t := SymTab.InvalidType
|
|
|
- 1315 END; .) ) .
|
|
|
- 1316 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 1317 qlo, qhi: QbeGen.QVal;
|
|
|
- 1318 lo, hi: INTEGER;
|
|
|
- 1319 cl, cl2: INTEGER; .)
|
|
|
- 1320 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 1321 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 1322 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 1323 ok := FALSE
|
|
|
- 1324 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
- 1325 cl2 := SymTab.ClassOf(thi);
|
|
|
- 1326 IF ((cl # SymTab.ClInt)
|
|
|
- 1327 AND (cl # SymTab.ClChar)
|
|
|
- 1328 AND (cl # SymTab.ClBool)
|
|
|
- 1329 AND (cl # SymTab.ClEnum))
|
|
|
- 1330 OR ((cl2 # SymTab.ClInt)
|
|
|
- 1331 AND (cl2 # SymTab.ClChar)
|
|
|
- 1332 AND (cl2 # SymTab.ClBool)
|
|
|
- 1333 AND (cl2 # SymTab.ClEnum)) THEN
|
|
|
- 1334 SemError(230); ok := FALSE
|
|
|
- 1335 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 1336 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 1337 OR (lo > hi) THEN
|
|
|
- 1338 SemError(230); ok := FALSE
|
|
|
- 1339 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
- 1340 SemError(230); ok := FALSE
|
|
|
- 1341 END;
|
|
|
- 1342 END; .) .
|
|
|
- 1343 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
- 1344 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
- 1345 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
- 1346 comparison across suitable bases are lenient (masks over min
|
|
|
- 1347 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
- 1348 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
- 1349 blo, bhi, bspan: INTEGER;
|
|
|
- 1350 bcls: INTEGER; .)
|
|
|
- 1351 = "SET" "OF" Type<base, FALSE>
|
|
|
- 1352 (. IF base = SymTab.InvalidType THEN
|
|
|
- 1353 t := SymTab.InvalidType
|
|
|
- 1354 ELSIF SymTab.Unresolved(base) THEN
|
|
|
- 1355 (* a forward type: defer the
|
|
|
- 1356 span check; the base
|
|
|
- 1357 resolves once the TYPE
|
|
|
- 1358 block completes *)
|
|
|
- 1359 t := SymTab.NewSet(base)
|
|
|
- 1360 ELSE bcls :=
|
|
|
- 1361 SymTab.ClassOf(base);
|
|
|
- 1362 IF bcls = SymTab.ClBool THEN
|
|
|
- 1363 blo := 0; bspan := 2
|
|
|
- 1364 ELSIF bcls = SymTab.ClChar THEN
|
|
|
- 1365 blo := 0; bspan := 256
|
|
|
- 1366 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
- 1367 blo := 0;
|
|
|
- 1368 bspan := VAL(INTEGER,
|
|
|
- 1369 SymTab.EnumCount(base))
|
|
|
- 1370 ELSIF SymTab.SubBounds(base,
|
|
|
- 1371 blo, bhi) THEN
|
|
|
- 1372 bspan := bhi - blo + 1
|
|
|
- 1373 ELSE bspan := 0 END;
|
|
|
- 1374 IF (bspan <= 0)
|
|
|
- 1375 OR (bspan > 65536) THEN
|
|
|
- 1376 SemError(230);
|
|
|
- 1377 t := SymTab.InvalidType
|
|
|
- 1378 ELSE t := SymTab.NewSet(base)
|
|
|
- 1379 END
|
|
|
- 1380 END; .) .
|
|
|
- 1381 (* Records: flat blobs; array fields are pointers to static
|
|
|
- 1382 descriptors (locked amendment), nested records inline. Field
|
|
|
- 1383 offsets static and declaration-ordered. *)
|
|
|
- 1384 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
- 1385 variant part is a `CASE ... END` item; because it starts with the
|
|
|
- 1386 CASE keyword it is unambiguously distinguishable from a field
|
|
|
- 1387 (which starts with an identifier). *)
|
|
|
- 1388 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
- 1389 tagOk: BOOLEAN; .)
|
|
|
- 1390 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
- 1391 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
- 1392 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
- 1393 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
- 1394 = RecField<rec>
|
|
|
- 1395 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
- 1396 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
- 1397 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
- 1398 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
- 1399 tagN: SymTab.Name; .)
|
|
|
- 1400 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
- 1401 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1402 tagN) THEN
|
|
|
- 1403 SemError(200) END; .)
|
|
|
- 1404 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
- 1405 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
- 1406 SemError(224)
|
|
|
- 1407 END;
|
|
|
- 1408 SymTab.FixPendingF(rec, tagT);
|
|
|
- 1409 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
- 1410 "OF"
|
|
|
- 1411 RecFieldList<rec>
|
|
|
- 1412 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
- 1413 RecFieldList<rec> }
|
|
|
- 1414 "END" .
|
|
|
- 1415 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
- 1416 lv1, lv2: QbeGen.QVal; .)
|
|
|
- 1417 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
- 1418 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
- 1419 (* Variant case label: a constant (or a constant range). Values are
|
|
|
- 1420 not interpreted (the layout overlays regardless). *)
|
|
|
- 1421 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1422 (. VAR lname: SymTab.Name; .)
|
|
|
- 1423 = ( ident (. LexName(lname);
|
|
|
- 1424 QbeGen.CopyOp("0", q);
|
|
|
- 1425 t := SymTab.IntType(); .)
|
|
|
- 1426 | integer (. LexString(lname);
|
|
|
- 1427 QbeGen.CopyOp("0", q);
|
|
|
- 1428 t := SymTab.IntType(); .)
|
|
|
- 1429 | charConst (. LexString(lname);
|
|
|
- 1430 QbeGen.CopyOp("0", q);
|
|
|
- 1431 t := SymTab.CharType(); .) ) .
|
|
|
- 1432 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1433 t2: SymTab.TypeIndex; .)
|
|
|
- 1434 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
- 1435 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 1436 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1437 n) THEN
|
|
|
- 1438 SemError(200) END; .)
|
|
|
- 1439 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1440 n) THEN
|
|
|
- 1441 SemError(200) END; .) } .
|
|
|
- 1442 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
- 1443 k: INTEGER;
|
|
|
- 1444 dotted: BOOLEAN; .)
|
|
|
- 1445 = GetIdent<n> (. dotted := FALSE;
|
|
|
- 1446 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 1447 k := -1;
|
|
|
- 1448 t := SymTab.ForwardType(n);
|
|
|
- 1449 IF t = SymTab.InvalidType THEN
|
|
|
- 1450 SemError(201)
|
|
|
- 1451 END
|
|
|
- 1452 ELSE k := SymTab.SymKind(n);
|
|
|
- 1453 IF (k = SymTab.KindType)
|
|
|
- 1454 OR (k = SymTab.KindPredef) THEN
|
|
|
- 1455 t := SymTab.SymType(n)
|
|
|
- 1456 ELSE t := SymTab.InvalidType
|
|
|
- 1457 END
|
|
|
- 1458 END; .)
|
|
|
- 1459 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
- 1460 IF k = SymTab.KindModule THEN
|
|
|
- 1461 t := SymTab.QualType(n, qid);
|
|
|
- 1462 IF t = SymTab.InvalidType THEN
|
|
|
- 1463 SemError(201)
|
|
|
- 1464 END
|
|
|
- 1465 ELSE SemError(221);
|
|
|
- 1466 t := SymTab.InvalidType
|
|
|
- 1467 END; .) ]
|
|
|
- 1468 (. IF NOT dotted THEN
|
|
|
- 1469 IF (k = SymTab.KindModule)
|
|
|
- 1470 OR ((k # SymTab.KindType)
|
|
|
- 1471 AND (k # SymTab.KindPredef)
|
|
|
- 1472 AND (k # SymTab.KindImport)
|
|
|
- 1473 AND (k # -1)) THEN
|
|
|
- 1474 SemError(221)
|
|
|
- 1475 END
|
|
|
- 1476 END; .) .
|
|
|
- 1477 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 1478 qlo, qhi: QbeGen.QVal;
|
|
|
- 1479 lo, hi: INTEGER; .)
|
|
|
- 1480 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 1481 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 1482 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 1483 t := SymTab.InvalidType
|
|
|
- 1484 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
- 1485 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
- 1486 SemError(230);
|
|
|
- 1487 t := SymTab.InvalidType
|
|
|
- 1488 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 1489 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 1490 OR (lo > hi) THEN
|
|
|
- 1491 SemError(230);
|
|
|
- 1492 t := SymTab.InvalidType
|
|
|
- 1493 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
- 1494 END; .)
|
|
|
- 1495 "]" .
|
|
|
- 1496 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1497 ord: INTEGER;
|
|
|
- 1498 qv: QbeGen.QVal; .)
|
|
|
- 1499 = "(" (. t := SymTab.NewEnum();
|
|
|
- 1500 ord := 0; .)
|
|
|
- 1501 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1502 SymTab.KindConst) THEN
|
|
|
- 1503 SemError(200) END;
|
|
|
- 1504 SymTab.SetSymType(n, t);
|
|
|
- 1505 QbeGen.IntStr(ord, qv);
|
|
|
- 1506 SymTab.SetSymVal(n, qv);
|
|
|
- 1507 Lower.NoteVar(n,
|
|
|
- 1508 SymTab.KindConst, t);
|
|
|
- 1509 Lower.NoteConstVal(qv);
|
|
|
- 1510 INC(ord); .)
|
|
|
- 1511 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1512 SymTab.KindConst) THEN
|
|
|
- 1513 SemError(200) END;
|
|
|
- 1514 SymTab.SetSymType(n, t);
|
|
|
- 1515 QbeGen.IntStr(ord, qv);
|
|
|
- 1516 SymTab.SetSymVal(n, qv);
|
|
|
- 1517 Lower.NoteVar(n,
|
|
|
- 1518 SymTab.KindConst, t);
|
|
|
- 1519 Lower.NoteConstVal(qv);
|
|
|
- 1520 INC(ord); .) }
|
|
|
- 1521 ")" (. SymTab.SetEnumCount(t,
|
|
|
- 1522 VAL(CARDINAL, ord)); .) .
|
|
|
- 1523 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
- 1524 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
- 1525 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
- 1526 class/impl block. Methods end with ";" per the Table example
|
|
|
- 1527 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
- 1528 (* Single CLASS item in both loops: separating declaration from
|
|
|
- 1529 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
- 1530 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
- 1531 The second token decides after CLASS is consumed. A misplaced
|
|
|
- 1532 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
- 1533 whole unit ends 230 until lowering). *)
|
|
|
- 1534 ClassItem
|
|
|
- 1535 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
- 1536 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
- 1537 ct: SymTab.TypeIndex; .)
|
|
|
- 1538 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
- 1539 SymTab.KindType) THEN
|
|
|
- 1540 SemError(200) END;
|
|
|
- 1541 ct := SymTab.NewClass();
|
|
|
- 1542 SymTab.SetSymType(cn, ct);
|
|
|
- 1543 SymTab.PushClassScope(ct);
|
|
|
- 1544 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1545 AST.SetChild(astCls, 0,
|
|
|
- 1546 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1547 astClsP := AST.NoNode;
|
|
|
- 1548 astClsPTail := AST.NoNode;
|
|
|
- 1549 astClsF := AST.NoNode;
|
|
|
- 1550 astClsFTail := AST.NoNode;
|
|
|
- 1551 astClsM := AST.NoNode;
|
|
|
- 1552 astClsMTail := AST.NoNode; .)
|
|
|
- 1553 [ Parents<ct> ]
|
|
|
- 1554 ";"
|
|
|
- 1555 { ClassField<ct> ";" }
|
|
|
- 1556 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1557 (. Lower.ScopeLeave;
|
|
|
- 1558 SymTab.CloseProc;
|
|
|
- 1559 QbeGen.AbortFunc; .) }
|
|
|
- 1560 "END"
|
|
|
- 1561 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1562 SemError(202) END;
|
|
|
- 1563 SymTab.LayoutClass(ct);
|
|
|
- 1564 SymTab.PopScope;
|
|
|
- 1565 AST.SetChild(astCls, 1, astClsP);
|
|
|
- 1566 AST.SetChild(astCls, 2, astClsF);
|
|
|
- 1567 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1568 astDecl := astCls; .) .
|
|
|
- 1569 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
- 1570 = "(" Parent1<ct>
|
|
|
- 1571 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
- 1572 ")" .
|
|
|
- 1573 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
- 1574 pt: SymTab.TypeIndex; .)
|
|
|
- 1575 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
- 1576 SemError(201)
|
|
|
- 1577 ELSE pt := SymTab.SymType(p);
|
|
|
- 1578 IF SymTab.ClassOf(pt) #
|
|
|
- 1579 SymTab.ClClass THEN
|
|
|
- 1580 SemError(230)
|
|
|
- 1581 ELSE SymTab.SetParent(ct, pt)
|
|
|
- 1582 END
|
|
|
- 1583 END;
|
|
|
- 1584 AstAppend(AST.NkFieldDecl,
|
|
|
- 1585 astClsP, astClsPTail,
|
|
|
- 1586 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
- 1587 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- 1588 t: SymTab.TypeIndex;
|
|
|
- 1589 astNode: AST.Node; .)
|
|
|
- 1590 = GetIdent<n>
|
|
|
- 1591 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
- 1592 SymTab.KindConst) THEN
|
|
|
- 1593 SemError(200) END;
|
|
|
- 1594 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1595 AST.SetChild(astNode, 0,
|
|
|
- 1596 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1597 AST.SetChild(astNode, 1,
|
|
|
- 1598 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
- 1599 AstAppend(AST.NkFieldDecl,
|
|
|
- 1600 astClsF, astClsFTail, astNode);
|
|
|
- 1601 IF SymTab.Lookup(rhs) THEN
|
|
|
- 1602 SymTab.SetSymType(n,
|
|
|
- 1603 SymTab.SymType(rhs))
|
|
|
- 1604 END; .)
|
|
|
- 1605 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1606 n) THEN
|
|
|
- 1607 SemError(200) END;
|
|
|
- 1608 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1609 AST.SetChild(astNode, 0,
|
|
|
- 1610 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 1611 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1612 n) THEN
|
|
|
- 1613 SemError(200) END;
|
|
|
- 1614 AST.SetChild(astNode,
|
|
|
- 1615 AST.NChild(astNode),
|
|
|
- 1616 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
- 1617 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
- 1618 AST.SetTy(astNode, t);
|
|
|
- 1619 AstAppend(AST.NkFieldDecl,
|
|
|
- 1620 astClsF, astClsFTail, astNode); .) ) .
|
|
|
- 1621 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
- 1622 (. VAR wantVirt: BOOLEAN; .)
|
|
|
- 1623 = (. wantVirt := FALSE; .)
|
|
|
- 1624 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
- 1625 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
- 1626 SymTab.MarkVirtual END;
|
|
|
- 1627 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1628 AST.SetChild(astMethod, 0,
|
|
|
- 1629 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1630 IF wantVirt THEN
|
|
|
- 1631 AST.SetOp(astMethod, 3)
|
|
|
- 1632 ELSE AST.SetOp(astMethod, 0)
|
|
|
- 1633 END;
|
|
|
- 1634 AstAppend(AST.NkFieldDecl,
|
|
|
- 1635 astClsM, astClsMTail, astMethod); .) .
|
|
|
- 1636 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
- 1637 ct: SymTab.TypeIndex; .)
|
|
|
- 1638 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
- 1639 SemError(201);
|
|
|
- 1640 ct := SymTab.InvalidType
|
|
|
- 1641 ELSE ct := SymTab.SymType(cn);
|
|
|
- 1642 IF SymTab.ClassOf(ct) #
|
|
|
- 1643 SymTab.ClClass THEN
|
|
|
- 1644 SemError(230);
|
|
|
- 1645 ct := SymTab.InvalidType
|
|
|
- 1646 END
|
|
|
- 1647 END;
|
|
|
- 1648 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1649 AST.SetOp(astCls, 1);
|
|
|
- 1650 AST.SetChild(astCls, 0,
|
|
|
- 1651 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1652 astClsM := AST.NoNode;
|
|
|
- 1653 astClsMTail := AST.NoNode;
|
|
|
- 1654 astStmt := AST.NoNode;
|
|
|
- 1655 IF ct #
|
|
|
- 1656 SymTab.InvalidType THEN
|
|
|
- 1657 IF NOT SymTab.PushClassMembers(
|
|
|
- 1658 ct) THEN
|
|
|
- 1659 SemError(230) END;
|
|
|
- 1660 SymTab.PushImplClass(ct)
|
|
|
- 1661 END; .)
|
|
|
- 1662 ";" { MethodImpl<ct> ";" }
|
|
|
- 1663 (. astStmt := AST.NoNode; .)
|
|
|
- 1664 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
- 1665 .)
|
|
|
- 1666 [ StatSeq ] ]
|
|
|
- 1667 "END"
|
|
|
- 1668 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1669 SemError(202) END;
|
|
|
- 1670 SymTab.PopImplClass;
|
|
|
- 1671 SymTab.PopScope;
|
|
|
- 1672 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
- 1673 AST.SetChild(astCls, 2, astStmt);
|
|
|
- 1674 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1675 astDecl := astCls; .) .
|
|
|
- 1676 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
- 1677 thisQ: QbeGen.QVal;
|
|
|
- 1678 methRes: SymTab.TypeIndex; .)
|
|
|
- 1679 = MethodHeading<pn, ct> ";"
|
|
|
- 1680 (. IF (ct #
|
|
|
- 1681 SymTab.InvalidType)
|
|
|
- 1682 AND NOT SymTab.MethodExists(ct,
|
|
|
- 1683 pn) THEN
|
|
|
- 1684 SemError(201) END; .)
|
|
|
- 1685 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
- 1686 SymTab.MarkFwd;
|
|
|
- 1687 QbeGen.AbortFunc;
|
|
|
- 1688 Lower.ScopeLeave;
|
|
|
- 1689 SymTab.CloseProc; .)
|
|
|
- 1690 | (.
|
|
|
- 1691 (* bind the receiver: bare
|
|
|
- 1692 field names resolve
|
|
|
- 1693 against THIS *)
|
|
|
- 1694 QbeGen.CopyOp("@", thisQ);
|
|
|
- 1695 QbeGen.PushWith(thisQ); .)
|
|
|
- 1696 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
- 1697 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
- 1698 QbeGen.PopWith;
|
|
|
- 1699 methRes := SymTab.CurRes();
|
|
|
- 1700 Lower.ScopeLeave;
|
|
|
- 1701 SymTab.CloseProc;
|
|
|
- 1702 QbeGen.EndFunc(methRes); .) ) .
|
|
|
- 1703 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1704 = "CONST" (. astSeq := AST.NoNode;
|
|
|
- 1705 astTail := AST.NoNode; .)
|
|
|
- 1706 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1707 astSeq, astTail, astDecl); .) }
|
|
|
- 1708 (. astDecl := astSeq; .) .
|
|
|
- 1709 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 1710 t: SymTab.TypeIndex;
|
|
|
- 1711 qv: QbeGen.QVal;
|
|
|
- 1712 cls: INTEGER;
|
|
|
- 1713 mk: ARRAY [0 .. 15] OF CARDINAL;
|
|
|
- 1714 mw: CARDINAL;
|
|
|
- 1715 mlo: INTEGER;
|
|
|
- 1716 astNode: AST.Node; .)
|
|
|
- 1717 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1718 SymTab.KindConst) THEN
|
|
|
- 1719 SemError(200) END; .)
|
|
|
- 1720 "="
|
|
|
- 1721 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1722 AST.SetChild(astNode, 0,
|
|
|
- 1723 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1724 AST.SetChild(astNode, 1, astCur);
|
|
|
- 1725 AST.SetTy(astNode, t);
|
|
|
- 1726 astDecl := astNode;
|
|
|
- 1727 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
- 1728 Lower.NoteConstVal(qv);
|
|
|
- 1729 SymTab.SetSymType(n, t);
|
|
|
- 1730 cls := SymTab.ClassOf(t);
|
|
|
- 1731 IF cls = SymTab.ClSet THEN
|
|
|
- 1732 (* a SET CONST needs static
|
|
|
- 1733 data: fold its mask now
|
|
|
- 1734 (the grammar sees the
|
|
|
- 1735 element values) and let
|
|
|
- 1736 Lower re-emit it *)
|
|
|
- 1737 IF Lower.SetConstMaskOf(
|
|
|
- 1738 AST.Child(astNode, 1),
|
|
|
- 1739 mk, mw, mlo) THEN
|
|
|
- 1740 Lower.NoteSetMask(n, mk, mw,
|
|
|
- 1741 mlo);
|
|
|
- 1742 SymTab.SetSymVal(n, qv)
|
|
|
- 1743 ELSE
|
|
|
- 1744 SemError(230)
|
|
|
- 1745 END
|
|
|
- 1746 ELSIF (cls = SymTab.ClArray)
|
|
|
- 1747 OR (cls = SymTab.ClRecord)
|
|
|
- 1748 OR (cls = SymTab.ClClass)
|
|
|
- 1749 OR (cls = SymTab.ClStr)
|
|
|
- 1750 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 1751 (* an aggregate/string
|
|
|
- 1752 constant: qv is its
|
|
|
- 1753 descriptor address; no
|
|
|
- 1754 scalar data *)
|
|
|
- 1755 SymTab.SetSymVal(n, qv)
|
|
|
- 1756 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- 1757 SemError(230)
|
|
|
- 1758 ELSE
|
|
|
- 1759 SymTab.SetSymVal(n, qv);
|
|
|
- 1760 END; .) .
|
|
|
- 1761 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1762 = "VAR" (. astSeq := AST.NoNode;
|
|
|
- 1763 astTail := AST.NoNode; .)
|
|
|
- 1764 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1765 astSeq, astTail, astDecl); .) }
|
|
|
- 1766 (. astDecl := astSeq; .) .
|
|
|
- 1767 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 1768 t: SymTab.TypeIndex;
|
|
|
- 1769 i: CARDINAL;
|
|
|
- 1770 cls: INTEGER;
|
|
|
- 1771 astNode, astTail: AST.Node; .)
|
|
|
- 1772 = VarIdents ":"
|
|
|
- 1773 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1774 astTail := astNode;
|
|
|
- 1775 i := 0;
|
|
|
- 1776 WHILE i < SymTab.PendCount() DO
|
|
|
- 1777 SymTab.PendName(i, nm);
|
|
|
- 1778 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
- 1779 (* chunked: a VAR list can
|
|
|
- 1780 exceed AST.MaxChild *)
|
|
|
- 1781 AstAppend(AST.NkBlock,
|
|
|
- 1782 astNode, astTail,
|
|
|
- 1783 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
- 1784 INC(i)
|
|
|
- 1785 END;
|
|
|
- 1786 AST.SetTy(astNode, t);
|
|
|
- 1787 astDecl := astNode;
|
|
|
- 1788 cls := SymTab.ClassOf(t);
|
|
|
- 1789 IF (t # SymTab.InvalidType)
|
|
|
- 1790 AND NOT SymTab.IsUnresolved(t)
|
|
|
- 1791 AND (cls # SymTab.ClInt)
|
|
|
- 1792 AND (cls # SymTab.ClBool)
|
|
|
- 1793 AND (cls # SymTab.ClChar)
|
|
|
- 1794 AND (cls # SymTab.ClReal)
|
|
|
- 1795 AND (cls # SymTab.ClArray)
|
|
|
- 1796 AND (cls # SymTab.ClSet)
|
|
|
- 1797 AND (cls # SymTab.ClRecord)
|
|
|
- 1798 AND (cls # SymTab.ClPtr)
|
|
|
- 1799 AND (cls # SymTab.ClLong)
|
|
|
- 1800 AND (cls # SymTab.ClProc)
|
|
|
- 1801 AND (cls # SymTab.ClUChar)
|
|
|
- 1802 AND (cls # SymTab.ClUStr)
|
|
|
- 1803 AND (cls # SymTab.ClEnum)
|
|
|
- 1804 AND (cls # SymTab.ClClass) THEN
|
|
|
- 1805 SemError(230) END;
|
|
|
- 1806 IF QbeGen.LocFull() THEN
|
|
|
- 1807 SemError(233) END;
|
|
|
- 1808 i := 0;
|
|
|
- 1809 IF SymTab.IsUnresolved(t)
|
|
|
- 1810 AND NOT SymTab.InProc() THEN
|
|
|
- 1811 (* a forward-typed global:
|
|
|
- 1812 defer emission until the
|
|
|
- 1813 TYPE block completes *)
|
|
|
- 1814 AST.SetOp(astNode, 1);
|
|
|
- 1815 WHILE i < SymTab.PendCount() DO
|
|
|
- 1816 SymTab.PendName(i, nm);
|
|
|
- 1817 IF nPendVar <=
|
|
|
- 1818 HIGH(pendVarName) THEN
|
|
|
- 1819 pendVarName[nPendVar] := nm;
|
|
|
- 1820 pendVarT[nPendVar] := t;
|
|
|
- 1821 INC(nPendVar)
|
|
|
- 1822 END;
|
|
|
- 1823 INC(i)
|
|
|
- 1824 END
|
|
|
- 1825 ELSE
|
|
|
- 1826 WHILE i < SymTab.PendCount() DO
|
|
|
- 1827 SymTab.PendName(i, nm);
|
|
|
- 1828 INC(i)
|
|
|
- 1829 END
|
|
|
- 1830 END;
|
|
|
- 1831 (* a plain VAR list, not a
|
|
|
- 1832 heading: the signature
|
|
|
- 1833 result is discarded *)
|
|
|
- 1834 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1835 END; .) .
|
|
|
- 1836 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 1837 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1838 SymTab.KindVar) THEN
|
|
|
- 1839 SemError(200) END; .)
|
|
|
- 1840 { ","
|
|
|
- 1841 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1842 SymTab.KindVar) THEN
|
|
|
- 1843 SemError(200) END; .) } .
|
|
|
- 1844 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 1845 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1846 SemError(200) END; .)
|
|
|
- 1847 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1848 SemError(200) END; .) } .
|
|
|
- 1849 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 1850 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 1851 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 1852 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 1853 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
- 1854 (. VAR t: SymTab.TypeIndex;
|
|
|
- 1855 mg: QbeGen.QVal; .)
|
|
|
- 1856 = "PROCEDURE"
|
|
|
- 1857 GetIdent<pn> (. IF methCls #
|
|
|
- 1858 SymTab.InvalidType THEN
|
|
|
- 1859 (* a method: resume the
|
|
|
- 1860 declared symbol (reuse
|
|
|
- 1861 its uid) *)
|
|
|
- 1862 IF NOT SymTab.ResumeMethod(
|
|
|
- 1863 methCls, pn) THEN
|
|
|
- 1864 SemError(200) END
|
|
|
- 1865 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 1866 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 1867 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 1868 SemError(200) END
|
|
|
- 1869 END
|
|
|
- 1870 END;
|
|
|
- 1871 Lower.ScopeEnter;
|
|
|
- 1872 Lower.NoteProc(pn,
|
|
|
- 1873 SymTab.ProcUid(pn),
|
|
|
- 1874 SymTab.InvalidType,
|
|
|
- 1875 SymTab.ProcDepthOf(pn),
|
|
|
- 1876 FALSE);
|
|
|
- 1877 QbeGen.BeginFunc("");
|
|
|
- 1878 IF methCls #
|
|
|
- 1879 SymTab.InvalidType THEN
|
|
|
- 1880 (* hidden THIS receiver:
|
|
|
- 1881 a VAR param of the
|
|
|
- 1882 class type, pushed as
|
|
|
- 1883 the WITH base *)
|
|
|
- 1884 IF NOT SymTab.EnterThisParam(
|
|
|
- 1885 methCls) THEN
|
|
|
- 1886 SemError(200) END;
|
|
|
- 1887 IF NOT QbeGen.FuncParam(
|
|
|
- 1888 "THIS", TRUE,
|
|
|
- 1889 methCls) THEN
|
|
|
- 1890 SemError(233) END
|
|
|
- 1891 END; .)
|
|
|
- 1892 [ FormalParams ]
|
|
|
- 1893 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
- 1894 SemError(235) END;
|
|
|
- 1895 Lower.SetProcRes(t); .) ] .
|
|
|
- 1896 FormalParams
|
|
|
- 1897 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 1898 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 1899 nm: SymTab.Name;
|
|
|
- 1900 i: CARDINAL;
|
|
|
- 1901 isV: BOOLEAN; .)
|
|
|
- 1902 = (. isV := FALSE; .)
|
|
|
- 1903 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1904 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 1905 WHILE i < SymTab.PendCount() DO
|
|
|
- 1906 SymTab.PendName(i, nm);
|
|
|
- 1907 Lower.NoteParam(nm, t, isV);
|
|
|
- 1908 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
- 1909 (* value open arrays are
|
|
|
- 1910 passed as descriptor
|
|
|
- 1911 addresses (no copy):
|
|
|
- 1912 same representation as
|
|
|
- 1913 VAR formals *)
|
|
|
- 1914 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 1915 isV
|
|
|
- 1916 OR SymTab.IsOpenArray(t),
|
|
|
- 1917 t) THEN
|
|
|
- 1918 SemError(233) END;
|
|
|
- 1919 INC(i)
|
|
|
- 1920 END;
|
|
|
- 1921 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1922 SemError(235) END; .) .
|
|
|
- 1923 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 1924 static link gives them their parent's frame. Methods keep
|
|
|
- 1925 parse-now/230-later. *)
|
|
|
- 1926 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
- 1927 astNode: AST.Node; .)
|
|
|
- 1928 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1929 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1930 AST.SetOp(astNode, 0);
|
|
|
- 1931 AST.SetChild(astNode, 0,
|
|
|
- 1932 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1933 Lower.NoteProcNode(astNode); .)
|
|
|
- 1934 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
- 1935 astDecl := astNode;
|
|
|
- 1936 Lower.ScopeLeave;
|
|
|
- 1937 SymTab.MarkFwd;
|
|
|
- 1938 SymTab.CloseProc;
|
|
|
- 1939 QbeGen.AbortFunc; .)
|
|
|
- 1940 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
- 1941 astDecl := astNode;
|
|
|
- 1942 Lower.MarkProcExternal;
|
|
|
- 1943 Lower.ScopeLeave;
|
|
|
- 1944 SymTab.MarkExternal("");
|
|
|
- 1945 SymTab.CloseProc;
|
|
|
- 1946 QbeGen.AbortFunc; .)
|
|
|
- 1947 |
|
|
|
- 1948 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
- 1949 curProcNode := astNode; .)
|
|
|
- 1950 Block<pn> (. IF deferredBody THEN
|
|
|
- 1951 (* body skipped: close like
|
|
|
- 1952 FORWARD (no body node) *)
|
|
|
- 1953 astDecl := astNode;
|
|
|
- 1954 Lower.ScopeLeave;
|
|
|
- 1955 SymTab.CloseProc;
|
|
|
- 1956 QbeGen.AbortFunc
|
|
|
- 1957 ELSE
|
|
|
- 1958 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1959 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
- 1960 astDecl := astNode;
|
|
|
- 1961 Lower.ScopeLeave;
|
|
|
- 1962 SymTab.CloseProc;
|
|
|
- 1963 QbeGen.EndFunc(
|
|
|
- 1964 SymTab.ProcRes(pn))
|
|
|
- 1965 END; .) ) .
|
|
|
- 1966 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
- 1967 = (. dfr := FALSE;
|
|
|
- 1968 IF allowDefer AND twoPhaseParse
|
|
|
- 1969 AND NOT repassing THEN
|
|
|
- 1970 dfr := DeferSkip(pn)
|
|
|
- 1971 END;
|
|
|
- 1972 allowDefer := FALSE;
|
|
|
- 1973 .)
|
|
|
- 1974 DeclSeq (. astBlkDecls := astDecl;
|
|
|
- 1975 astStmt := AST.NoNode;
|
|
|
- 1976 nLab := 0; nGot := 0; .)
|
|
|
- 1977 [ "BEGIN" (. (* an empty body is still a
|
|
|
- 1978 body: mark it so Lower
|
|
|
- 1979 does not read it as a
|
|
|
- 1980 definition heading *)
|
|
|
- 1981 IF NOT dfr THEN
|
|
|
- 1982 IF astStmt = AST.NoNode THEN
|
|
|
- 1983 astStmt :=
|
|
|
- 1984 AST.MakeNode(AST.NkBlock)
|
|
|
- 1985 END
|
|
|
- 1986 END; .)
|
|
|
- 1987 [ StatSeq ] ]
|
|
|
- 1988 "END"
|
|
|
- 1989 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 1990 SemError(202) END;
|
|
|
- 1991 CheckGotos; .) .
|
|
|
- 1992 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
- 1993 level body once the unit's declarations are complete. Inlined at
|
|
|
- 1994 both call sites because a stand-alone epsilon production is
|
|
|
- 1995 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
- 1996 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1997 = (. astSeq := AST.NoNode;
|
|
|
- 1998 astTail := AST.NoNode; .)
|
|
|
- 1999 Statement (. AstAppend(AST.NkBlock,
|
|
|
- 2000 astSeq, astTail, astStmt); .)
|
|
|
- 2001 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
- 2002 astSeq, astTail, astStmt); .) ] }
|
|
|
- 2003 (. astStmt := astSeq; .) .
|
|
|
- 2004 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 2005 are accepted: the statement after ';' is optional. *)
|
|
|
- 2006 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
- 2007 = (. astStmt := AST.NoNode; .)
|
|
|
- 2008 ( AssOrCall
|
|
|
- 2009 | IfStat
|
|
|
- 2010 | WhileStat
|
|
|
- 2011 | RepeatStat
|
|
|
- 2012 | LoopStat
|
|
|
- 2013 | ForStat
|
|
|
- 2014 | CaseStat
|
|
|
- 2015 | WithStat
|
|
|
- 2016 | ReturnStat
|
|
|
- 2017 | HaltStat
|
|
|
- 2018 | NewStat
|
|
|
- 2019 | DisposeStat
|
|
|
- 2020 | IncDecStat
|
|
|
- 2021 | InclExclStat
|
|
|
- 2022 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
- 2023 SemError(230) END;
|
|
|
- 2024 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
- 2025 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
- 2026 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
- 2027 AST.SetChild(astStmt, 0,
|
|
|
- 2028 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
- 2029 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
- 2030 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
- 2031 dk: INTEGER;
|
|
|
- 2032 qd, qe: QbeGen.QVal;
|
|
|
- 2033 qn: SymTab.Name;
|
|
|
- 2034 sfx, isInc: BOOLEAN;
|
|
|
- 2035 astNode, astD: AST.Node; .)
|
|
|
- 2036 = ( "INCL" (. isInc := TRUE; .)
|
|
|
- 2037 | "EXCL" (. isInc := FALSE; .) )
|
|
|
- 2038 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
- 2039 Expr<et2, qe> ")"
|
|
|
- 2040 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2041 IF isInc THEN
|
|
|
- 2042 AST.SetChild(astNode, 0,
|
|
|
- 2043 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
- 2044 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2045 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
- 2046 END;
|
|
|
- 2047 IF astD # AST.NoNode THEN
|
|
|
- 2048 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2049 IF astCur # AST.NoNode THEN
|
|
|
- 2050 AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 2051 astStmt := astNode; .)
|
|
|
- 2052 (. IF (at # SymTab.InvalidType)
|
|
|
- 2053 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
- 2054 SemError(222)
|
|
|
- 2055 END; .) .
|
|
|
- 2056 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 2057 integer designator. *)
|
|
|
- 2058 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 2059 dk: INTEGER;
|
|
|
- 2060 qd, qv, qn2, qstep:
|
|
|
- 2061 QbeGen.QVal;
|
|
|
- 2062 qn: SymTab.Name;
|
|
|
- 2063 sfx, isInc: BOOLEAN;
|
|
|
- 2064 astNode, astD, astStep:
|
|
|
- 2065 AST.Node; .)
|
|
|
- 2066 = (. isInc := TRUE; .)
|
|
|
- 2067 ( "INC" (. isInc := TRUE; .)
|
|
|
- 2068 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 2069 "(" (. astStep := AST.NoNode; .)
|
|
|
- 2070 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
- 2071 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
- 2072 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2073 IF isInc THEN
|
|
|
- 2074 AST.SetChild(astNode, 0,
|
|
|
- 2075 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
- 2076 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2077 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
- 2078 END;
|
|
|
- 2079 IF astD # AST.NoNode THEN
|
|
|
- 2080 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2081 IF astStep # AST.NoNode THEN
|
|
|
- 2082 AST.SetChild(astNode, 2, astStep) END;
|
|
|
- 2083 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2084 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2085 AND (dk # SymTab.KindParam)
|
|
|
- 2086 AND (dk # SymTab.KindField) THEN
|
|
|
- 2087 SemError(210)
|
|
|
- 2088 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 2089 SemError(211)
|
|
|
- 2090 END; .) .
|
|
|
- 2091 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 2092 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 2093 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 2094 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2095 dk: INTEGER;
|
|
|
- 2096 qd, qm: QbeGen.QVal;
|
|
|
- 2097 qn: SymTab.Name;
|
|
|
- 2098 sfx: BOOLEAN;
|
|
|
- 2099 bt: SymTab.TypeIndex;
|
|
|
- 2100 astNode, astD: AST.Node; .)
|
|
|
- 2101 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 2102 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2103 AST.SetChild(astNode, 0,
|
|
|
- 2104 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
- 2105 IF astD # AST.NoNode THEN
|
|
|
- 2106 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2107 astStmt := astNode; .)
|
|
|
- 2108 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2109 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2110 AND (dk # SymTab.KindParam)
|
|
|
- 2111 AND (dk # SymTab.KindField) THEN
|
|
|
- 2112 SemError(210)
|
|
|
- 2113 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 2114 SymTab.ClPtr THEN
|
|
|
- 2115 SemError(219)
|
|
|
- 2116 END; .) .
|
|
|
- 2117 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2118 dk: INTEGER;
|
|
|
- 2119 qd, qv: QbeGen.QVal;
|
|
|
- 2120 qn: SymTab.Name;
|
|
|
- 2121 sfx: BOOLEAN;
|
|
|
- 2122 astNode, astD: AST.Node; .)
|
|
|
- 2123 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 2124 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2125 AST.SetChild(astNode, 0,
|
|
|
- 2126 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
- 2127 IF astD # AST.NoNode THEN
|
|
|
- 2128 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2129 astStmt := astNode; .)
|
|
|
- 2130 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2131 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2132 AND (dk # SymTab.KindParam)
|
|
|
- 2133 AND (dk # SymTab.KindField) THEN
|
|
|
- 2134 SemError(210)
|
|
|
- 2135 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 2136 SymTab.ClPtr THEN
|
|
|
- 2137 SemError(219)
|
|
|
- 2138 END; .) .
|
|
|
- 2139 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 2140 address; field designators resolve through both stacks. *)
|
|
|
- 2141 WithStat (. VAR nW: CARDINAL;
|
|
|
- 2142 astNode: AST.Node; .)
|
|
|
- 2143 = "WITH" (. nW := 0;
|
|
|
- 2144 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
- 2145 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
- 2146 "DO" (. astStmt := AST.NoNode; .)
|
|
|
- 2147 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
- 2148 AST.NChild(astNode), astStmt);
|
|
|
- 2149 astStmt := astNode;
|
|
|
- 2150 WHILE nW > 0 DO
|
|
|
- 2151 SymTab.PopScope;
|
|
|
- 2152 QbeGen.PopWith;
|
|
|
- 2153 DEC(nW)
|
|
|
- 2154 END; .) .
|
|
|
- 2155 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
- 2156 (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2157 dk: INTEGER;
|
|
|
- 2158 qd, qe: QbeGen.QVal;
|
|
|
- 2159 qn: SymTab.Name;
|
|
|
- 2160 sfx: BOOLEAN; .)
|
|
|
- 2161 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 2162 (. IF astCur # AST.NoNode THEN
|
|
|
- 2163 AST.SetChild(wnode,
|
|
|
- 2164 AST.NChild(wnode), astCur) END;
|
|
|
- 2165 IF dt = SymTab.InvalidType THEN
|
|
|
- 2166 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 2167 SymTab.ClRecord)
|
|
|
- 2168 AND (SymTab.ClassOf(dt) #
|
|
|
- 2169 SymTab.ClClass) THEN
|
|
|
- 2170 SemError(215)
|
|
|
- 2171 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 2172 QbeGen.PushWith(qd);
|
|
|
- 2173 INC(nW)
|
|
|
- 2174 END; .) .
|
|
|
- 2175 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 2176 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 2177 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 2178 dk: INTEGER;
|
|
|
- 2179 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 2180 qn: SymTab.Name;
|
|
|
- 2181 ct2, res0: SymTab.TypeIndex;
|
|
|
- 2182 q2, mg0: QbeGen.QVal;
|
|
|
- 2183 isR, conv, wconv: BOOLEAN;
|
|
|
- 2184 called, sfx: BOOLEAN;
|
|
|
- 2185 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 2186 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
- 2187 = GetIdent<n>
|
|
|
- 2188 ( ":" (. NoteLabel(n);
|
|
|
- 2189 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
- 2190 AST.SetChild(astNode, 0,
|
|
|
- 2191 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 2192 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
- 2193 AST.SetChild(astLab, 0, astNode); .)
|
|
|
- 2194 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
- 2195 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
- 2196 astStmt := astLab; .)
|
|
|
- 2197 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
- 2198 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
- 2199 ( ":="
|
|
|
- 2200 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 2201 AST.NkAssign, 0, astLhs, astCur);
|
|
|
- 2202 IF (dt # SymTab.InvalidType)
|
|
|
- 2203 AND (dk # SymTab.KindVar)
|
|
|
- 2204 AND (dk # SymTab.KindParam)
|
|
|
- 2205 AND (dk # SymTab.KindField) THEN
|
|
|
- 2206 SemError(210)
|
|
|
- 2207 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 2208 dt) THEN
|
|
|
- 2209 SemError(210)
|
|
|
- 2210 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 2211 AND (SymTab.ClassOf(dt) =
|
|
|
- 2212 SymTab.ClClass) THEN
|
|
|
- 2213 SemError(230) END;
|
|
|
- 2214 isR := (dt #
|
|
|
- 2215 SymTab.InvalidType)
|
|
|
- 2216 AND (SymTab.ClassOf(dt)
|
|
|
- 2217 = SymTab.ClReal);
|
|
|
- 2218 conv := isR
|
|
|
- 2219 AND SymTab.IsIntFamily(et);
|
|
|
- 2220 wconv := (dt #
|
|
|
- 2221 SymTab.InvalidType)
|
|
|
- 2222 AND SymTab.IsLongFamily(dt)
|
|
|
- 2223 AND SymTab.IsIntFamily(et);
|
|
|
- 2224 IF ((dk = SymTab.KindVar)
|
|
|
- 2225 OR (dk = SymTab.KindParam)
|
|
|
- 2226 OR (dk = SymTab.KindField))
|
|
|
- 2227 AND (dt # SymTab.InvalidType)
|
|
|
- 2228 AND (et # SymTab.InvalidType)
|
|
|
- 2229 AND (SymTab.ClassOf(dt) #
|
|
|
- 2230 SymTab.ClClass) THEN
|
|
|
- 2231 END; .)
|
|
|
- 2232 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
- 2233 (. astRes := AstCallNode(astLhs);
|
|
|
- 2234 sfx := FALSE; .)
|
|
|
- 2235 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
- 2236 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 2237 AST.NkAssign, 0, astRes, astCur);
|
|
|
- 2238 IF NOT sfx THEN
|
|
|
- 2239 SemError(233)
|
|
|
- 2240 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
- 2241 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
- 2242 SemError(210)
|
|
|
- 2243 END; .)
|
|
|
- 2244 | (. IF ct2 #
|
|
|
- 2245 SymTab.InvalidType THEN
|
|
|
- 2246 SemError(233) END;
|
|
|
- 2247 astStmt := astRes; .) )
|
|
|
- 2248 | (* bare `P;`: proper parameterless
|
|
|
- 2249 procedure call; anything else
|
|
|
- 2250 here is 233 (was a bare syntax
|
|
|
- 2251 error before 4.2) *)
|
|
|
- 2252 (. astStmt := AstCallNode(astLhs);
|
|
|
- 2253 IF (dk = SymTab.KindProc)
|
|
|
- 2254 AND NOT sfx THEN
|
|
|
- 2255 res0 := SymTab.ProcRes(qn);
|
|
|
- 2256 IF res0 #
|
|
|
- 2257 SymTab.InvalidType THEN
|
|
|
- 2258 SemError(233)
|
|
|
- 2259 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 2260 0 THEN
|
|
|
- 2261 SemError(233)
|
|
|
- 2262 END
|
|
|
- 2263 ELSE SemError(233)
|
|
|
- 2264 END; .) ) ) .
|
|
|
- 2265 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 2266 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 2267 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 2268 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 2269 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 2270 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 2271 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2272 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 2273 vs: INTEGER;
|
|
|
- 2274 res: SymTab.TypeIndex;
|
|
|
- 2275 mg: QbeGen.QVal;
|
|
|
- 2276 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
- 2277 = "(" (. called := TRUE;
|
|
|
- 2278 ok := TRUE;
|
|
|
- 2279 ind := FALSE;
|
|
|
- 2280 isConv := FALSE;
|
|
|
- 2281 isMeth := methCls #
|
|
|
- 2282 SymTab.InvalidType;
|
|
|
- 2283 IF isMeth THEN
|
|
|
- 2284 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
- 2285 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
- 2286 res := SymTab.ProcRes(pn)
|
|
|
- 2287 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
- 2288 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
- 2289 (* ISO type conversion T(x):
|
|
|
- 2290 one value, result is T *)
|
|
|
- 2291 isConv := TRUE;
|
|
|
- 2292 res := SymTab.SymType(pn)
|
|
|
- 2293 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 2294 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 2295 ind := TRUE;
|
|
|
- 2296 res := SymTab.ProcTypeRes(pt)
|
|
|
- 2297 ELSE SemError(233);
|
|
|
- 2298 ok := FALSE;
|
|
|
- 2299 res := SymTab.InvalidType
|
|
|
- 2300 END;
|
|
|
- 2301 i := 0; .)
|
|
|
- 2302 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 2303 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 2304 ")" (. IF ok THEN
|
|
|
- 2305 IF isConv THEN
|
|
|
- 2306 (* a conversion takes
|
|
|
- 2307 exactly one value *)
|
|
|
- 2308 IF i # 1 THEN
|
|
|
- 2309 SemError(233); ok := FALSE
|
|
|
- 2310 END
|
|
|
- 2311 ELSE
|
|
|
- 2312 IF isMeth THEN
|
|
|
- 2313 np := SymTab.ClassMethodNPar(
|
|
|
- 2314 methCls, pn)
|
|
|
- 2315 ELSIF ind THEN
|
|
|
- 2316 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 2317 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 2318 END;
|
|
|
- 2319 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 2320 AND (SymTab.SymKind(pn) =
|
|
|
- 2321 SymTab.KindProc)
|
|
|
- 2322 AND SymTab.Varargs(pn);
|
|
|
- 2323 IF (i # np) AND NOT va THEN
|
|
|
- 2324 SemError(233); ok := FALSE
|
|
|
- 2325 END
|
|
|
- 2326 END
|
|
|
- 2327 END;
|
|
|
- 2328 IF NOT ok THEN
|
|
|
- 2329 t := SymTab.InvalidType;
|
|
|
- 2330 QbeGen.CopyOp("0", q)
|
|
|
- 2331 ELSIF want THEN
|
|
|
- 2332 IF res =
|
|
|
- 2333 SymTab.InvalidType THEN
|
|
|
- 2334 IF NOT soft THEN SemError(233) END;
|
|
|
- 2335 t := SymTab.InvalidType;
|
|
|
- 2336 QbeGen.CopyOp("0", q)
|
|
|
- 2337 ELSE t := res;
|
|
|
- 2338 QbeGen.CopyOp("@", q)
|
|
|
- 2339 END
|
|
|
- 2340 ELSE
|
|
|
- 2341 IF res #
|
|
|
- 2342 SymTab.InvalidType THEN
|
|
|
- 2343 SemError(233)
|
|
|
- 2344 END;
|
|
|
- 2345 t := SymTab.InvalidType;
|
|
|
- 2346 QbeGen.CopyOp("0", q);
|
|
|
- 2347 END; .) .
|
|
|
- 2348 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 2349 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 2350 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 2351 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 2352 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 2353 qe, qa, qt: QbeGen.QVal;
|
|
|
- 2354 isV, conv, va: BOOLEAN;
|
|
|
- 2355 cl: CHAR;
|
|
|
- 2356 savedN, aj: CARDINAL;
|
|
|
- 2357 savedArgs: ARRAY [0 .. 31]
|
|
|
- 2358 OF AST.Node;
|
|
|
- 2359 astActual: AST.Node; .)
|
|
|
- 2360 = (. (* Parsing the actual can clobber
|
|
|
- 2361 the enclosing call's argument
|
|
|
- 2362 list (Factor resets astNArgs),
|
|
|
- 2363 so save/restore it. *)
|
|
|
- 2364 savedN := astNArgs; aj := 0;
|
|
|
- 2365 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2366 savedArgs[aj] := astArgs[aj];
|
|
|
- 2367 INC(aj)
|
|
|
- 2368 END; .)
|
|
|
- 2369 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
- 2370 astActual := astCur;
|
|
|
- 2371 astNArgs := savedN; aj := 0;
|
|
|
- 2372 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2373 astArgs[aj] := savedArgs[aj];
|
|
|
- 2374 INC(aj)
|
|
|
- 2375 END;
|
|
|
- 2376 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 2377 astArgs[astNArgs] := astCur;
|
|
|
- 2378 INC(astNArgs)
|
|
|
- 2379 END;
|
|
|
- 2380 va := (NOT ind)
|
|
|
- 2381 AND (methCls =
|
|
|
- 2382 SymTab.InvalidType)
|
|
|
- 2383 AND (SymTab.SymKind(pn) =
|
|
|
- 2384 SymTab.KindProc)
|
|
|
- 2385 AND SymTab.Varargs(pn);
|
|
|
- 2386 IF ind THEN
|
|
|
- 2387 ft :=
|
|
|
- 2388 SymTab.ProcTypeParamType(pt,
|
|
|
- 2389 i);
|
|
|
- 2390 isV :=
|
|
|
- 2391 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 2392 i)
|
|
|
- 2393 ELSIF methCls #
|
|
|
- 2394 SymTab.InvalidType THEN
|
|
|
- 2395 ft :=
|
|
|
- 2396 SymTab.ClassMethodParamType(
|
|
|
- 2397 methCls, pn, i);
|
|
|
- 2398 isV :=
|
|
|
- 2399 SymTab.ClassMethodParamIsVar(
|
|
|
- 2400 methCls, pn, i)
|
|
|
- 2401 ELSE
|
|
|
- 2402 ft := SymTab.ParamType(pn, i);
|
|
|
- 2403 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 2404 END;
|
|
|
- 2405 IF (at = SymTab.InvalidType) THEN
|
|
|
- 2406 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 2407 ELSIF isV THEN
|
|
|
- 2408 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 2409 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 2410 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 2411 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2412 ELSIF (AST.Kind(astActual) #
|
|
|
- 2413 AST.NkDesignator)
|
|
|
- 2414 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
- 2415 SemError(233)
|
|
|
- 2416 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
+ 774 [ "FOR" string ] (* ISO foreign module: FOR "C" *)
|
|
|
+ 775 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
+ 776 IF instActive THEN
|
|
|
+ 777 IF NOT SymTab.Reenter(m1,
|
|
|
+ 778 SymTab.UnitDef) THEN
|
|
|
+ 779 SemError(200) END
|
|
|
+ 780 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
+ 781 SemError(200) END;
|
|
|
+ 782 QbeGen.SetModule(m1);
|
|
|
+ 783 CopyNm(m1, unitName);
|
|
|
+ 784 unitWasGen := isGen
|
|
|
+ 785 AND NOT instActive;
|
|
|
+ 786 unitWasDef := TRUE; .)
|
|
|
+ 787 [ GenericFormals ]
|
|
|
+ 788 ( ";"
|
|
|
+ 789 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 790 astImp, astImpTail, astDecl); .) }
|
|
|
+ 791 [ "EXPORT" [ "QUALIFIED" | "UNQUALIFIED" ] (. (* definition-module export
|
|
|
+ 792 list: parsed, and the
|
|
|
+ 793 names are already exported
|
|
|
+ 794 by the module scope *) .)
|
|
|
+ 795 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
+ 796 (. astSeq := AST.NoNode;
|
|
|
+ 797 astTail := AST.NoNode; .)
|
|
|
+ 798 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 799 astSeq, astTail, astDecl); .)
|
|
|
+ 800 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 801 astSeq, astTail, astDecl); .)
|
|
|
+ 802 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 803 astSeq, astTail, astDecl); .)
|
|
|
+ 804 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 805 (. (* a heading only: record it so
|
|
|
+ 806 Lower can replay it *)
|
|
|
+ 807 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 808 AST.SetOp(astProc, 0);
|
|
|
+ 809 AST.SetChild(astProc, 0,
|
|
|
+ 810 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 811 AstAppend(AST.NkDeclSeq,
|
|
|
+ 812 astSeq, astTail, astProc);
|
|
|
+ 813 Lower.NoteProcNode(astProc);
|
|
|
+ 814 Lower.ScopeLeave;
|
|
|
+ 815 SymTab.CloseProc;
|
|
|
+ 816 QbeGen.AbortFunc; .) }
|
|
|
+ 817 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
+ 818 AST.SetChild(astUnit, 0,
|
|
|
+ 819 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 820 AST.SetChild(astUnit, 1, astSeq);
|
|
|
+ 821 AST.SetChild(astUnit, 3, astImp);
|
|
|
+ 822 astDecl := AST.NoNode;
|
|
|
+ 823 astStmt := AST.NoNode; .)
|
|
|
+ 824 "END"
|
|
|
+ 825 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 826 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 827 SemError(202) END;
|
|
|
+ 828 SymTab.EndUnit; .)
|
|
|
+ 829 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
+ 830 (. CopyNm(m1, refInst);
|
|
|
+ 831 CopyNm(g, refGen);
|
|
|
+ 832 refSeen := TRUE; refIsDef := TRUE;
|
|
|
+ 833 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
+ 834 AST.SetChild(astUnit, 0,
|
|
|
+ 835 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 836 astDecl := AST.NoNode;
|
|
|
+ 837 astStmt := AST.NoNode; .)
|
|
|
+ 838 "END"
|
|
|
+ 839 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 840 SemError(202) END;
|
|
|
+ 841 SymTab.EndUnit; .) ) .
|
|
|
+ 842 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
+ 843 g: SymTab.Name;
|
|
|
+ 844 k: CARDINAL;
|
|
|
+ 845 rp: CARDINAL;
|
|
|
+ 846 rpOk: BOOLEAN;
|
|
|
+ 847 rErrs: INTEGER;
|
|
|
+ 848 rDecl, rStmt: AST.Node;
|
|
|
+ 849 rnm: SymTab.Name;
|
|
|
+ 850 rSym, rErr: CARDINAL;
|
|
|
+ 851 fname: SymTab.Name;
|
|
|
+ 852 unres: BOOLEAN;
|
|
|
+ 853 astNode: AST.Node; .)
|
|
|
+ 854 = (. refN := 0; refSeen := FALSE; .)
|
|
|
+ 855 "IMPLEMENTATION" "MODULE"
|
|
|
+ 856 [ "FOR" string ] (* ISO foreign module: FOR "C" *)
|
|
|
+ 857 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
+ 858 IF instActive THEN
|
|
|
+ 859 IF NOT SymTab.Reenter(m1,
|
|
|
+ 860 SymTab.UnitImpl) THEN
|
|
|
+ 861 SemError(201) END
|
|
|
+ 862 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
+ 863 SemError(201) END;
|
|
|
+ 864 astStmt := AST.NoNode;
|
|
|
+ 865 astDecl := AST.NoNode;
|
|
|
+ 866 astImp := AST.NoNode;
|
|
|
+ 867 astImpTail := AST.NoNode;
|
|
|
+ 868 nPendVar := 0;
|
|
|
+ 869 CopyNm(m1, unitName);
|
|
|
+ 870 unitWasGen := isGen AND NOT instActive;
|
|
|
+ 871 unitWasDef := FALSE;
|
|
|
+ 872 QbeGen.SetModule(m1); .)
|
|
|
+ 873 [ GenericFormals ]
|
|
|
+ 874 ( ";"
|
|
|
+ 875 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 876 astImp, astImpTail, astDecl); .) }
|
|
|
+ 877 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 878 [ "BEGIN" (. FlushPend;
|
|
|
+ 879 k := 0;
|
|
|
+ 880 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 881 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 882 IF unres THEN SemError(201) END;
|
|
|
+ 883 INC(k)
|
|
|
+ 884 END;
|
|
|
+ 885 SymTab.FwdClear;
|
|
|
+ 886
|
|
|
+ 887 nLab := 0; nGot := 0; .)
|
|
|
+ 888 [ StatSeq ] ]
|
|
|
+ 889 (. IF twoPhaseParse THEN
|
|
|
+ 890 rSym := sym; rErr := errDist;
|
|
|
+ 891 rDecl := astDecl; rStmt := astStmt;
|
|
|
+ 892 M2S.PushPos;
|
|
|
+ 893 repassing := TRUE;
|
|
|
+ 894 rp := 0;
|
|
|
+ 895 WHILE rp < nSpans DO
|
|
|
+ 896 k := 0;
|
|
|
+ 897 WHILE (k <= HIGH(rnm))
|
|
|
+ 898 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
+ 899 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
+ 900 END;
|
|
|
+ 901 rnm[k] := CHR(0);
|
|
|
+ 902 M2S.SeekTo(spanStart[rp]);
|
|
|
+ 903 Adv;
|
|
|
+ 904 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
+ 905 IF NOT rpOk THEN
|
|
|
+ 906 FileIO.WriteString(FileIO.StdOut,
|
|
|
+ 907 "twophase reenter failed");
|
|
|
+ 908 FileIO.WriteLn(FileIO.StdOut)
|
|
|
+ 909 END;
|
|
|
+ 910 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
+ 911 QbeGen.BeginFunc("");
|
|
|
+ 912 Block(rnm);
|
|
|
+ 913 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
+ 914 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
+ 915 Lower.ScopeLeave;
|
|
|
+ 916 SymTab.CloseProc;
|
|
|
+ 917 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
+ 918 INC(rp)
|
|
|
+ 919 END;
|
|
|
+ 920 rErrs := M2S.errors;
|
|
|
+ 921 repassing := FALSE;
|
|
|
+ 922 M2S.PopPos;
|
|
|
+ 923 sym := rSym; errDist := rErr;
|
|
|
+ 924 M2S.errors := rErrs;
|
|
|
+ 925
|
|
|
+ 926 astDecl := rDecl; astStmt := rStmt
|
|
|
+ 927 END; .)
|
|
|
+ 928 "END"
|
|
|
+ 929 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 930 FlushPend;
|
|
|
+ 931 k := 0;
|
|
|
+ 932 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 933 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 934 IF unres THEN SemError(201) END;
|
|
|
+ 935 INC(k)
|
|
|
+ 936 END;
|
|
|
+ 937 SymTab.FwdClear;
|
|
|
+ 938
|
|
|
+ 939 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 940 AST.SetChild(astNode, 0,
|
|
|
+ 941 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 942 AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 943 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 944 AST.SetChild(astNode, 3, astImp);
|
|
|
+ 945 astUnit := astNode;
|
|
|
+ 946 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 947 SemError(202) END;
|
|
|
+ 948 CheckGotos;
|
|
|
+ 949 SymTab.EndUnit; .)
|
|
|
+ 950 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
+ 951 (. CopyNm(m1, refInst);
|
|
|
+ 952 CopyNm(g, refGen);
|
|
|
+ 953 refSeen := TRUE; refIsDef := FALSE;
|
|
|
+ 954 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 955 AST.SetChild(astNode, 0,
|
|
|
+ 956 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 957 astDecl := AST.NoNode;
|
|
|
+ 958 astStmt := AST.NoNode; .)
|
|
|
+ 959 { Import (. (* refinement unit import *) .) }
|
|
|
+ 960 "END"
|
|
|
+ 961 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 962 SemError(202) END;
|
|
|
+ 963 SymTab.EndUnit; .) ) .
|
|
|
+ 964 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
+ 965 k: CARDINAL;
|
|
|
+ 966 rp: CARDINAL;
|
|
|
+ 967 rpOk: BOOLEAN;
|
|
|
+ 968 rErrs: INTEGER;
|
|
|
+ 969 rDecl, rStmt: AST.Node;
|
|
|
+ 970 rnm: SymTab.Name;
|
|
|
+ 971 rSym, rErr: CARDINAL;
|
|
|
+ 972 fname: SymTab.Name;
|
|
|
+ 973 unres: BOOLEAN;
|
|
|
+ 974 astNode: AST.Node; .)
|
|
|
+ 975 = "MODULE"
|
|
|
+ 976 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
+ 977 SemError(200) END;
|
|
|
+ 978 astStmt := AST.NoNode;
|
|
|
+ 979 astDecl := AST.NoNode;
|
|
|
+ 980 astImp := AST.NoNode;
|
|
|
+ 981 astImpTail := AST.NoNode;
|
|
|
+ 982 nPendVar := 0;
|
|
|
+ 983 QbeGen.SetModule(m1); .)
|
|
|
+ 984 [ Priority ]
|
|
|
+ 985 ";"
|
|
|
+ 986 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 987 astImp, astImpTail, astDecl); .) }
|
|
|
+ 988 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 989 [ "BEGIN" (. FlushPend;
|
|
|
+ 990 k := 0;
|
|
|
+ 991 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 992 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 993 IF unres THEN SemError(201) END;
|
|
|
+ 994 INC(k)
|
|
|
+ 995 END;
|
|
|
+ 996 SymTab.FwdClear;
|
|
|
+ 997
|
|
|
+ 998 nLab := 0; nGot := 0; .)
|
|
|
+ 999 [ StatSeq ] ]
|
|
|
+ 1000 (. IF twoPhaseParse THEN
|
|
|
+ 1001 rSym := sym; rErr := errDist;
|
|
|
+ 1002 rDecl := astDecl; rStmt := astStmt;
|
|
|
+ 1003 M2S.PushPos;
|
|
|
+ 1004 repassing := TRUE;
|
|
|
+ 1005 rp := 0;
|
|
|
+ 1006 WHILE rp < nSpans DO
|
|
|
+ 1007 k := 0;
|
|
|
+ 1008 WHILE (k <= HIGH(rnm))
|
|
|
+ 1009 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
+ 1010 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
+ 1011 END;
|
|
|
+ 1012 rnm[k] := CHR(0);
|
|
|
+ 1013 M2S.SeekTo(spanStart[rp]);
|
|
|
+ 1014 Adv;
|
|
|
+ 1015 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
+ 1016 IF NOT rpOk THEN
|
|
|
+ 1017 FileIO.WriteString(FileIO.StdOut,
|
|
|
+ 1018 "twophase reenter failed");
|
|
|
+ 1019 FileIO.WriteLn(FileIO.StdOut)
|
|
|
+ 1020 END;
|
|
|
+ 1021 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
+ 1022 QbeGen.BeginFunc("");
|
|
|
+ 1023 Block(rnm);
|
|
|
+ 1024 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
+ 1025 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
+ 1026 Lower.ScopeLeave;
|
|
|
+ 1027 SymTab.CloseProc;
|
|
|
+ 1028 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
+ 1029 INC(rp)
|
|
|
+ 1030 END;
|
|
|
+ 1031 rErrs := M2S.errors;
|
|
|
+ 1032 repassing := FALSE;
|
|
|
+ 1033 M2S.PopPos;
|
|
|
+ 1034 sym := rSym; errDist := rErr;
|
|
|
+ 1035 M2S.errors := rErrs;
|
|
|
+ 1036
|
|
|
+ 1037 astDecl := rDecl; astStmt := rStmt
|
|
|
+ 1038 END; .)
|
|
|
+ 1039 "END"
|
|
|
+ 1040 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 1041 FlushPend;
|
|
|
+ 1042 k := 0;
|
|
|
+ 1043 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 1044 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 1045 IF unres THEN SemError(201) END;
|
|
|
+ 1046 INC(k)
|
|
|
+ 1047 END;
|
|
|
+ 1048 SymTab.FwdClear;
|
|
|
+ 1049
|
|
|
+ 1050 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 1051 SemError(202) END;
|
|
|
+ 1052 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 1053 AST.SetChild(astNode, 0,
|
|
|
+ 1054 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 1055 AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 1056 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 1057 AST.SetChild(astNode, 3, astImp);
|
|
|
+ 1058 astUnit := astNode;
|
|
|
+ 1059 CheckGotos;
|
|
|
+ 1060 SymTab.EndUnit; .) .
|
|
|
+ 1061 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1062 = (. astSeq := AST.NoNode;
|
|
|
+ 1063 astTail := AST.NoNode; .)
|
|
|
+ 1064 { (. astDecl := AST.NoNode; .)
|
|
|
+ 1065 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
+ 1066 | NestedModule ";" | ClassItem ";" )
|
|
|
+ 1067 (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1068 astSeq, astTail, astDecl); .) }
|
|
|
+ 1069 (. astDecl := astSeq; .) .
|
|
|
+ 1070 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
+ 1071 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
+ 1072 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
+ 1073 scope at END. *)
|
|
|
+ 1074 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
+ 1075 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
+ 1076 expCount, k: CARDINAL;
|
|
|
+ 1077 astNode, nImp, nImpTail:
|
|
|
+ 1078 AST.Node; .)
|
|
|
+ 1079 = "MODULE"
|
|
|
+ 1080 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
+ 1081 SymTab.KindModule) THEN
|
|
|
+ 1082 SemError(200) END;
|
|
|
+ 1083 SymTab.PushScope;
|
|
|
+ 1084 expCount := 0;
|
|
|
+ 1085 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 1086 AST.SetChild(astNode, 0,
|
|
|
+ 1087 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 1088 astStmt := AST.NoNode;
|
|
|
+ 1089 astDecl := AST.NoNode;
|
|
|
+ 1090 nImp := AST.NoNode;
|
|
|
+ 1091 nImpTail := AST.NoNode; .)
|
|
|
+ 1092 [ Priority ]
|
|
|
+ 1093 ";"
|
|
|
+ 1094 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1095 nImp, nImpTail, astDecl); .) }
|
|
|
+ 1096 [ "EXPORT" [ "QUALIFIED" | "UNQUALIFIED" ]
|
|
|
+ 1097 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
+ 1098 { "," GetIdent<expNames[expCount]>
|
|
|
+ 1099 (. INC(expCount); .) }
|
|
|
+ 1100 ";" ]
|
|
|
+ 1101 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 1102 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
+ 1103 .)
|
|
|
+ 1104 [ StatSeq ] ]
|
|
|
+ 1105 "END"
|
|
|
+ 1106 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 1107 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 1108 AST.SetChild(astNode, 3, nImp);
|
|
|
+ 1109 astDecl := astNode;
|
|
|
+ 1110 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 1111 SemError(202) END;
|
|
|
+ 1112 k := 0;
|
|
|
+ 1113 WHILE k < expCount DO
|
|
|
+ 1114 SymTab.ExportUp(expNames[k]);
|
|
|
+ 1115 INC(k)
|
|
|
+ 1116 END;
|
|
|
+ 1117 SymTab.PopScope; .) .
|
|
|
+ 1118 Priority
|
|
|
+ 1119 = "[" integer "]" (. SemError(230); .) .
|
|
|
+ 1120 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
+ 1121 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
+ 1122 materializes on first use (Design). *)
|
|
|
+ 1123 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
+ 1124 import lines don't fail); a known module's missing export is
|
|
|
+ 1125 201. *)
|
|
|
+ 1126 Import (. VAR n: SymTab.Name;
|
|
|
+ 1127 astImport: AST.Node; .)
|
|
|
+ 1128 = "FROM"
|
|
|
+ 1129 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
+ 1130 AST.SetChild(astImport, 0,
|
|
|
+ 1131 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 1132 "IMPORT"
|
|
|
+ 1133 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
+ 1134 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
+ 1135 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
+ 1136 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
+ 1137 (. VAR n: SymTab.Name; .)
|
|
|
+ 1138 = ImpName<mod, node>
|
|
|
+ 1139 { "," ImpName<mod, node> } .
|
|
|
+ 1140 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
+ 1141 accepted and ignored: the built-in applies regardless. *)
|
|
|
+ 1142 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
+ 1143 (. VAR n: SymTab.Name; .)
|
|
|
+ 1144 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 1145 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1146 IF SymTab.Equal(mod, "libc") THEN
|
|
|
+ 1147 (* intrinsic C library:
|
|
|
+ 1148 permissive external *)
|
|
|
+ 1149 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
+ 1150 SemError(201) END;
|
|
|
+ 1151 Lower.NoteCProc(n)
|
|
|
+ 1152 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
+ 1153 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
+ 1154 SemError(201)
|
|
|
+ 1155 ELSE Lower.NoteImportedProc(n)
|
|
|
+ 1156 END
|
|
|
+ 1157 END; .)
|
|
|
+ 1158 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
+ 1159 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
+ 1160 | "ODD" | "TRUNC" | "FLOAT"
|
|
|
+ 1161 | "UCHR" | "CHR8" | "UORD"
|
|
|
+ 1162 | "INC" | "DEC"
|
|
|
+ 1163 | "SHIFT" | "ROTATE" | "CAST" | "MIN" | "MAX"
|
|
|
+ 1164 | "INCL" | "EXCL" | "NEW" | "DISPOSE" | "LOC" ) .
|
|
|
+ 1165 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
+ 1166 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 1167 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 1168 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 1169 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
+ 1170 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
+ 1171 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
+ 1172 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
+ 1173 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
+ 1174 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
+ 1175 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1176 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
+ 1177 astSeq := AST.NoNode;
|
|
|
+ 1178 astTail := AST.NoNode; .)
|
|
|
+ 1179 { (. astDecl := AST.NoNode; .)
|
|
|
+ 1180 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
+ 1181 (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1182 astSeq, astTail, astDecl); .) }
|
|
|
+ 1183 (. SymTab.EndTypeBlock;
|
|
|
+ 1184 astDecl := astSeq; .) .
|
|
|
+ 1185 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
+ 1186 t, op: SymTab.TypeIndex;
|
|
|
+ 1187 astNode: AST.Node; .)
|
|
|
+ 1188 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
+ 1189 IF op = SymTab.InvalidType THEN
|
|
|
+ 1190 IF NOT SymTab.Enter(n,
|
|
|
+ 1191 SymTab.KindType) THEN
|
|
|
+ 1192 SemError(200) END
|
|
|
+ 1193 END; .)
|
|
|
+ 1194 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
+ 1195 AST.SetChild(astNode, 0,
|
|
|
+ 1196 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1197 AST.SetTy(astNode, t);
|
|
|
+ 1198 astDecl := astNode;
|
|
|
+ 1199 IF op # SymTab.InvalidType THEN
|
|
|
+ 1200 SymTab.SetTarget(op, t)
|
|
|
+ 1201 ELSE SymTab.SetSymType(n, t)
|
|
|
+ 1202 END; .)
|
|
|
+ 1203 | (. IF op # SymTab.InvalidType THEN
|
|
|
+ 1204 (* stays opaque *)
|
|
|
+ 1205 ELSIF NOT isDef THEN
|
|
|
+ 1206 SemError(231)
|
|
|
+ 1207 ELSE SymTab.SetSymType(n,
|
|
|
+ 1208 SymTab.NewAlias()) END; .) ) .
|
|
|
+ 1209 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 1210 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
+ 1211 | Subrange<t>
|
|
|
+ 1212 | Enum<t>
|
|
|
+ 1213 | ArrayType<t, allowOpen>
|
|
|
+ 1214 | SetType<t>
|
|
|
+ 1215 | RecordType<t>
|
|
|
+ 1216 | PointerType<t>
|
|
|
+ 1217 | ProcType<t> .
|
|
|
+ 1218 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
+ 1219 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
+ 1220 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
+ 1221 are code pointers; params are collected into the descriptor. *)
|
|
|
+ 1222 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
+ 1223 isV: BOOLEAN; .)
|
|
|
+ 1224 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
+ 1225 t := SymTab.NewProcType(res); .)
|
|
|
+ 1226 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
+ 1227 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
+ 1228 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
+ 1229 isV: BOOLEAN;
|
|
|
+ 1230 cnt, k: CARDINAL;
|
|
|
+ 1231 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
+ 1232 = (. isV := FALSE; cnt := 0; .)
|
|
|
+ 1233 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1234 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
+ 1235 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
+ 1236 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
+ 1237 WHILE k < cnt DO
|
|
|
+ 1238 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 1239 INC(k)
|
|
|
+ 1240 END; .)
|
|
|
+ 1241 | (. (* type-only parameter list:
|
|
|
+ 1242 each name is a type (GNU
|
|
|
+ 1243 shorthand used by the
|
|
|
+ 1244 Coco/R scanner frame) *)
|
|
|
+ 1245 k := 0;
|
|
|
+ 1246 WHILE k < cnt DO
|
|
|
+ 1247 IF SymTab.Lookup(names[k])
|
|
|
+ 1248 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
+ 1249 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
+ 1250 pt := SymTab.SymType(names[k])
|
|
|
+ 1251 ELSE SemError(201);
|
|
|
+ 1252 pt := SymTab.InvalidType
|
|
|
+ 1253 END;
|
|
|
+ 1254 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 1255 INC(k)
|
|
|
+ 1256 END; .) )
|
|
|
+ 1257 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
+ 1258 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
+ 1259 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
+ 1260 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
+ 1261 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
+ 1262 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
+ 1263 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
+ 1264 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 1265 (. VAR elem: SymTab.TypeIndex;
|
|
|
+ 1266 ok: BOOLEAN;
|
|
|
+ 1267 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
+ 1268 nb, k: CARDINAL;
|
|
|
+ 1269 idx: SymTab.TypeIndex;
|
|
|
+ 1270 ilo, ihi: INTEGER; .)
|
|
|
+ 1271 = "ARRAY"
|
|
|
+ 1272 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
+ 1273 SemError(230) END;
|
|
|
+ 1274 t := SymTab.NewOpenArray(elem); .)
|
|
|
+ 1275 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
+ 1276 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
+ 1277 type's ordinal bounds give the
|
|
|
+ 1278 [lo..hi] pair *)
|
|
|
+ 1279 IF SymTab.TypeBounds(idx, ilo,
|
|
|
+ 1280 ihi)
|
|
|
+ 1281 THEN t := SymTab.NewArrayB(elem,
|
|
|
+ 1282 ilo, ihi)
|
|
|
+ 1283 ELSIF SymTab.IsForwardType(idx)
|
|
|
+ 1284 THEN
|
|
|
+ 1285 (* forward index type: build
|
|
|
+ 1286 with placeholder bounds,
|
|
|
+ 1287 patched at EndTypeBlock *)
|
|
|
+ 1288 t := SymTab.NewArrayB(elem,
|
|
|
+ 1289 0, 0);
|
|
|
+ 1290 SymTab.DeferArrayIdx(t, idx)
|
|
|
+ 1291 ELSE SemError(230);
|
|
|
+ 1292 t := SymTab.InvalidType
|
|
|
+ 1293 END; .)
|
|
|
+ 1294 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
+ 1295 BoundPair<ok>
|
|
|
+ 1296 { "," BoundPair<ok> }
|
|
|
+ 1297 "]" (. (* snapshot before the element
|
|
|
+ 1298 type, which reuses the bound
|
|
|
+ 1299 buffer for a nested ARRAY *)
|
|
|
+ 1300 nb := SymTab.BoundCount();
|
|
|
+ 1301 k := 0;
|
|
|
+ 1302 WHILE k < nb DO
|
|
|
+ 1303 bnds[k] := SymTab.BoundLo(k);
|
|
|
+ 1304 bndh[k] := SymTab.BoundHi(k);
|
|
|
+ 1305 INC(k)
|
|
|
+ 1306 END; .)
|
|
|
+ 1307 "OF" Type<elem, FALSE>
|
|
|
+ 1308 (. IF ok THEN
|
|
|
+ 1309 k := nb;
|
|
|
+ 1310 WHILE k > 0 DO
|
|
|
+ 1311 DEC(k);
|
|
|
+ 1312 elem := SymTab.NewArrayB(
|
|
|
+ 1313 elem, bnds[k], bndh[k])
|
|
|
+ 1314 END;
|
|
|
+ 1315 t := elem
|
|
|
+ 1316 ELSE t := SymTab.InvalidType
|
|
|
+ 1317 END; .) ) .
|
|
|
+ 1318 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 1319 qlo, qhi: QbeGen.QVal;
|
|
|
+ 1320 lo, hi: INTEGER;
|
|
|
+ 1321 cl, cl2: INTEGER; .)
|
|
|
+ 1322 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 1323 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 1324 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 1325 ok := FALSE
|
|
|
+ 1326 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
+ 1327 cl2 := SymTab.ClassOf(thi);
|
|
|
+ 1328 IF ((cl # SymTab.ClInt)
|
|
|
+ 1329 AND (cl # SymTab.ClChar)
|
|
|
+ 1330 AND (cl # SymTab.ClBool)
|
|
|
+ 1331 AND (cl # SymTab.ClEnum))
|
|
|
+ 1332 OR ((cl2 # SymTab.ClInt)
|
|
|
+ 1333 AND (cl2 # SymTab.ClChar)
|
|
|
+ 1334 AND (cl2 # SymTab.ClBool)
|
|
|
+ 1335 AND (cl2 # SymTab.ClEnum)) THEN
|
|
|
+ 1336 SemError(230); ok := FALSE
|
|
|
+ 1337 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 1338 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 1339 OR (lo > hi) THEN
|
|
|
+ 1340 SemError(230); ok := FALSE
|
|
|
+ 1341 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
+ 1342 SemError(230); ok := FALSE
|
|
|
+ 1343 END;
|
|
|
+ 1344 END; .) .
|
|
|
+ 1345 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
+ 1346 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
+ 1347 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
+ 1348 comparison across suitable bases are lenient (masks over min
|
|
|
+ 1349 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
+ 1350 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
+ 1351 blo, bhi, bspan: INTEGER;
|
|
|
+ 1352 bcls: INTEGER; .)
|
|
|
+ 1353 = "SET" "OF" Type<base, FALSE>
|
|
|
+ 1354 (. IF base = SymTab.InvalidType THEN
|
|
|
+ 1355 t := SymTab.InvalidType
|
|
|
+ 1356 ELSIF SymTab.Unresolved(base) THEN
|
|
|
+ 1357 (* a forward type: defer the
|
|
|
+ 1358 span check; the base
|
|
|
+ 1359 resolves once the TYPE
|
|
|
+ 1360 block completes *)
|
|
|
+ 1361 t := SymTab.NewSet(base)
|
|
|
+ 1362 ELSE bcls :=
|
|
|
+ 1363 SymTab.ClassOf(base);
|
|
|
+ 1364 IF bcls = SymTab.ClBool THEN
|
|
|
+ 1365 blo := 0; bspan := 2
|
|
|
+ 1366 ELSIF bcls = SymTab.ClChar THEN
|
|
|
+ 1367 blo := 0; bspan := 256
|
|
|
+ 1368 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
+ 1369 blo := 0;
|
|
|
+ 1370 bspan := VAL(INTEGER,
|
|
|
+ 1371 SymTab.EnumCount(base))
|
|
|
+ 1372 ELSIF SymTab.SubBounds(base,
|
|
|
+ 1373 blo, bhi) THEN
|
|
|
+ 1374 bspan := bhi - blo + 1
|
|
|
+ 1375 ELSE bspan := 0 END;
|
|
|
+ 1376 IF (bspan <= 0)
|
|
|
+ 1377 OR (bspan > 65536) THEN
|
|
|
+ 1378 SemError(230);
|
|
|
+ 1379 t := SymTab.InvalidType
|
|
|
+ 1380 ELSE t := SymTab.NewSet(base)
|
|
|
+ 1381 END
|
|
|
+ 1382 END; .) .
|
|
|
+ 1383 (* Records: flat blobs; array fields are pointers to static
|
|
|
+ 1384 descriptors (locked amendment), nested records inline. Field
|
|
|
+ 1385 offsets static and declaration-ordered. *)
|
|
|
+ 1386 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
+ 1387 variant part is a `CASE ... END` item; because it starts with the
|
|
|
+ 1388 CASE keyword it is unambiguously distinguishable from a field
|
|
|
+ 1389 (which starts with an identifier). *)
|
|
|
+ 1390 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 1391 tagOk: BOOLEAN; .)
|
|
|
+ 1392 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
+ 1393 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
+ 1394 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
+ 1395 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
+ 1396 = RecField<rec>
|
|
|
+ 1397 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
+ 1398 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
+ 1399 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
+ 1400 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
+ 1401 tagN: SymTab.Name; .)
|
|
|
+ 1402 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
+ 1403 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1404 tagN) THEN
|
|
|
+ 1405 SemError(200) END; .)
|
|
|
+ 1406 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
+ 1407 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
+ 1408 SemError(224)
|
|
|
+ 1409 END;
|
|
|
+ 1410 SymTab.FixPendingF(rec, tagT);
|
|
|
+ 1411 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
+ 1412 "OF"
|
|
|
+ 1413 RecFieldList<rec>
|
|
|
+ 1414 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
+ 1415 RecFieldList<rec> }
|
|
|
+ 1416 "END" .
|
|
|
+ 1417 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
+ 1418 lv1, lv2: QbeGen.QVal; .)
|
|
|
+ 1419 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
+ 1420 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
+ 1421 (* Variant case label: a constant (or a constant range). Values are
|
|
|
+ 1422 not interpreted (the layout overlays regardless). *)
|
|
|
+ 1423 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1424 (. VAR lname: SymTab.Name; .)
|
|
|
+ 1425 = ( ident (. LexName(lname);
|
|
|
+ 1426 QbeGen.CopyOp("0", q);
|
|
|
+ 1427 t := SymTab.IntType(); .)
|
|
|
+ 1428 | integer (. LexString(lname);
|
|
|
+ 1429 QbeGen.CopyOp("0", q);
|
|
|
+ 1430 t := SymTab.IntType(); .)
|
|
|
+ 1431 | charConst (. LexString(lname);
|
|
|
+ 1432 QbeGen.CopyOp("0", q);
|
|
|
+ 1433 t := SymTab.CharType(); .) ) .
|
|
|
+ 1434 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1435 t2: SymTab.TypeIndex; .)
|
|
|
+ 1436 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
+ 1437 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 1438 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1439 n) THEN
|
|
|
+ 1440 SemError(200) END; .)
|
|
|
+ 1441 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1442 n) THEN
|
|
|
+ 1443 SemError(200) END; .) } .
|
|
|
+ 1444 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
+ 1445 k: INTEGER;
|
|
|
+ 1446 dotted: BOOLEAN; .)
|
|
|
+ 1447 = GetIdent<n> (. dotted := FALSE;
|
|
|
+ 1448 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 1449 k := -1;
|
|
|
+ 1450 t := SymTab.ForwardType(n);
|
|
|
+ 1451 IF t = SymTab.InvalidType THEN
|
|
|
+ 1452 SemError(201)
|
|
|
+ 1453 END
|
|
|
+ 1454 ELSE k := SymTab.SymKind(n);
|
|
|
+ 1455 IF (k = SymTab.KindType)
|
|
|
+ 1456 OR (k = SymTab.KindPredef) THEN
|
|
|
+ 1457 t := SymTab.SymType(n)
|
|
|
+ 1458 ELSE t := SymTab.InvalidType
|
|
|
+ 1459 END
|
|
|
+ 1460 END; .)
|
|
|
+ 1461 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
+ 1462 IF k = SymTab.KindModule THEN
|
|
|
+ 1463 t := SymTab.QualType(n, qid);
|
|
|
+ 1464 IF t = SymTab.InvalidType THEN
|
|
|
+ 1465 SemError(201)
|
|
|
+ 1466 END
|
|
|
+ 1467 ELSE SemError(221);
|
|
|
+ 1468 t := SymTab.InvalidType
|
|
|
+ 1469 END; .) ]
|
|
|
+ 1470 (. IF NOT dotted THEN
|
|
|
+ 1471 IF (k = SymTab.KindModule)
|
|
|
+ 1472 OR ((k # SymTab.KindType)
|
|
|
+ 1473 AND (k # SymTab.KindPredef)
|
|
|
+ 1474 AND (k # SymTab.KindImport)
|
|
|
+ 1475 AND (k # -1)) THEN
|
|
|
+ 1476 SemError(221)
|
|
|
+ 1477 END
|
|
|
+ 1478 END; .) .
|
|
|
+ 1479 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 1480 qlo, qhi: QbeGen.QVal;
|
|
|
+ 1481 lo, hi: INTEGER; .)
|
|
|
+ 1482 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 1483 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 1484 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 1485 t := SymTab.InvalidType
|
|
|
+ 1486 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
+ 1487 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
+ 1488 SemError(230);
|
|
|
+ 1489 t := SymTab.InvalidType
|
|
|
+ 1490 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 1491 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 1492 OR (lo > hi) THEN
|
|
|
+ 1493 SemError(230);
|
|
|
+ 1494 t := SymTab.InvalidType
|
|
|
+ 1495 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ 1496 END; .)
|
|
|
+ 1497 "]" .
|
|
|
+ 1498 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1499 ord: INTEGER;
|
|
|
+ 1500 qv: QbeGen.QVal; .)
|
|
|
+ 1501 = "(" (. t := SymTab.NewEnum();
|
|
|
+ 1502 ord := 0; .)
|
|
|
+ 1503 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1504 SymTab.KindConst) THEN
|
|
|
+ 1505 SemError(200) END;
|
|
|
+ 1506 SymTab.SetSymType(n, t);
|
|
|
+ 1507 QbeGen.IntStr(ord, qv);
|
|
|
+ 1508 SymTab.SetSymVal(n, qv);
|
|
|
+ 1509 Lower.NoteVar(n,
|
|
|
+ 1510 SymTab.KindConst, t);
|
|
|
+ 1511 Lower.NoteConstVal(qv);
|
|
|
+ 1512 INC(ord); .)
|
|
|
+ 1513 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1514 SymTab.KindConst) THEN
|
|
|
+ 1515 SemError(200) END;
|
|
|
+ 1516 SymTab.SetSymType(n, t);
|
|
|
+ 1517 QbeGen.IntStr(ord, qv);
|
|
|
+ 1518 SymTab.SetSymVal(n, qv);
|
|
|
+ 1519 Lower.NoteVar(n,
|
|
|
+ 1520 SymTab.KindConst, t);
|
|
|
+ 1521 Lower.NoteConstVal(qv);
|
|
|
+ 1522 INC(ord); .) }
|
|
|
+ 1523 ")" (. SymTab.SetEnumCount(t,
|
|
|
+ 1524 VAL(CARDINAL, ord)); .) .
|
|
|
+ 1525 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
+ 1526 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
+ 1527 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
+ 1528 class/impl block. Methods end with ";" per the Table example
|
|
|
+ 1529 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
+ 1530 (* Single CLASS item in both loops: separating declaration from
|
|
|
+ 1531 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
+ 1532 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
+ 1533 The second token decides after CLASS is consumed. A misplaced
|
|
|
+ 1534 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
+ 1535 whole unit ends 230 until lowering). *)
|
|
|
+ 1536 ClassItem
|
|
|
+ 1537 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
+ 1538 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
+ 1539 ct: SymTab.TypeIndex; .)
|
|
|
+ 1540 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
+ 1541 SymTab.KindType) THEN
|
|
|
+ 1542 SemError(200) END;
|
|
|
+ 1543 ct := SymTab.NewClass();
|
|
|
+ 1544 SymTab.SetSymType(cn, ct);
|
|
|
+ 1545 SymTab.PushClassScope(ct);
|
|
|
+ 1546 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1547 AST.SetChild(astCls, 0,
|
|
|
+ 1548 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1549 astClsP := AST.NoNode;
|
|
|
+ 1550 astClsPTail := AST.NoNode;
|
|
|
+ 1551 astClsF := AST.NoNode;
|
|
|
+ 1552 astClsFTail := AST.NoNode;
|
|
|
+ 1553 astClsM := AST.NoNode;
|
|
|
+ 1554 astClsMTail := AST.NoNode; .)
|
|
|
+ 1555 [ Parents<ct> ]
|
|
|
+ 1556 ";"
|
|
|
+ 1557 { ClassField<ct> ";" }
|
|
|
+ 1558 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1559 (. Lower.ScopeLeave;
|
|
|
+ 1560 SymTab.CloseProc;
|
|
|
+ 1561 QbeGen.AbortFunc; .) }
|
|
|
+ 1562 "END"
|
|
|
+ 1563 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1564 SemError(202) END;
|
|
|
+ 1565 SymTab.LayoutClass(ct);
|
|
|
+ 1566 SymTab.PopScope;
|
|
|
+ 1567 AST.SetChild(astCls, 1, astClsP);
|
|
|
+ 1568 AST.SetChild(astCls, 2, astClsF);
|
|
|
+ 1569 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1570 astDecl := astCls; .) .
|
|
|
+ 1571 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
+ 1572 = "(" Parent1<ct>
|
|
|
+ 1573 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
+ 1574 ")" .
|
|
|
+ 1575 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
+ 1576 pt: SymTab.TypeIndex; .)
|
|
|
+ 1577 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
+ 1578 SemError(201)
|
|
|
+ 1579 ELSE pt := SymTab.SymType(p);
|
|
|
+ 1580 IF SymTab.ClassOf(pt) #
|
|
|
+ 1581 SymTab.ClClass THEN
|
|
|
+ 1582 SemError(230)
|
|
|
+ 1583 ELSE SymTab.SetParent(ct, pt)
|
|
|
+ 1584 END
|
|
|
+ 1585 END;
|
|
|
+ 1586 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1587 astClsP, astClsPTail,
|
|
|
+ 1588 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
+ 1589 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
+ 1590 t: SymTab.TypeIndex;
|
|
|
+ 1591 astNode: AST.Node; .)
|
|
|
+ 1592 = GetIdent<n>
|
|
|
+ 1593 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1594 SymTab.KindConst) THEN
|
|
|
+ 1595 SemError(200) END;
|
|
|
+ 1596 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1597 AST.SetChild(astNode, 0,
|
|
|
+ 1598 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1599 AST.SetChild(astNode, 1,
|
|
|
+ 1600 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
+ 1601 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1602 astClsF, astClsFTail, astNode);
|
|
|
+ 1603 IF SymTab.Lookup(rhs) THEN
|
|
|
+ 1604 SymTab.SetSymType(n,
|
|
|
+ 1605 SymTab.SymType(rhs))
|
|
|
+ 1606 END; .)
|
|
|
+ 1607 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1608 n) THEN
|
|
|
+ 1609 SemError(200) END;
|
|
|
+ 1610 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1611 AST.SetChild(astNode, 0,
|
|
|
+ 1612 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 1613 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1614 n) THEN
|
|
|
+ 1615 SemError(200) END;
|
|
|
+ 1616 AST.SetChild(astNode,
|
|
|
+ 1617 AST.NChild(astNode),
|
|
|
+ 1618 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
+ 1619 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
+ 1620 AST.SetTy(astNode, t);
|
|
|
+ 1621 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1622 astClsF, astClsFTail, astNode); .) ) .
|
|
|
+ 1623 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
+ 1624 (. VAR wantVirt: BOOLEAN; .)
|
|
|
+ 1625 = (. wantVirt := FALSE; .)
|
|
|
+ 1626 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
+ 1627 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
+ 1628 SymTab.MarkVirtual END;
|
|
|
+ 1629 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1630 AST.SetChild(astMethod, 0,
|
|
|
+ 1631 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1632 IF wantVirt THEN
|
|
|
+ 1633 AST.SetOp(astMethod, 3)
|
|
|
+ 1634 ELSE AST.SetOp(astMethod, 0)
|
|
|
+ 1635 END;
|
|
|
+ 1636 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1637 astClsM, astClsMTail, astMethod); .) .
|
|
|
+ 1638 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
+ 1639 ct: SymTab.TypeIndex; .)
|
|
|
+ 1640 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
+ 1641 SemError(201);
|
|
|
+ 1642 ct := SymTab.InvalidType
|
|
|
+ 1643 ELSE ct := SymTab.SymType(cn);
|
|
|
+ 1644 IF SymTab.ClassOf(ct) #
|
|
|
+ 1645 SymTab.ClClass THEN
|
|
|
+ 1646 SemError(230);
|
|
|
+ 1647 ct := SymTab.InvalidType
|
|
|
+ 1648 END
|
|
|
+ 1649 END;
|
|
|
+ 1650 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1651 AST.SetOp(astCls, 1);
|
|
|
+ 1652 AST.SetChild(astCls, 0,
|
|
|
+ 1653 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1654 astClsM := AST.NoNode;
|
|
|
+ 1655 astClsMTail := AST.NoNode;
|
|
|
+ 1656 astStmt := AST.NoNode;
|
|
|
+ 1657 IF ct #
|
|
|
+ 1658 SymTab.InvalidType THEN
|
|
|
+ 1659 IF NOT SymTab.PushClassMembers(
|
|
|
+ 1660 ct) THEN
|
|
|
+ 1661 SemError(230) END;
|
|
|
+ 1662 SymTab.PushImplClass(ct)
|
|
|
+ 1663 END; .)
|
|
|
+ 1664 ";" { MethodImpl<ct> ";" }
|
|
|
+ 1665 (. astStmt := AST.NoNode; .)
|
|
|
+ 1666 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
+ 1667 .)
|
|
|
+ 1668 [ StatSeq ] ]
|
|
|
+ 1669 "END"
|
|
|
+ 1670 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1671 SemError(202) END;
|
|
|
+ 1672 SymTab.PopImplClass;
|
|
|
+ 1673 SymTab.PopScope;
|
|
|
+ 1674 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
+ 1675 AST.SetChild(astCls, 2, astStmt);
|
|
|
+ 1676 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1677 astDecl := astCls; .) .
|
|
|
+ 1678 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
+ 1679 thisQ: QbeGen.QVal;
|
|
|
+ 1680 methRes: SymTab.TypeIndex; .)
|
|
|
+ 1681 = MethodHeading<pn, ct> ";"
|
|
|
+ 1682 (. IF (ct #
|
|
|
+ 1683 SymTab.InvalidType)
|
|
|
+ 1684 AND NOT SymTab.MethodExists(ct,
|
|
|
+ 1685 pn) THEN
|
|
|
+ 1686 SemError(201) END; .)
|
|
|
+ 1687 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
+ 1688 SymTab.MarkFwd;
|
|
|
+ 1689 QbeGen.AbortFunc;
|
|
|
+ 1690 Lower.ScopeLeave;
|
|
|
+ 1691 SymTab.CloseProc; .)
|
|
|
+ 1692 | (.
|
|
|
+ 1693 (* bind the receiver: bare
|
|
|
+ 1694 field names resolve
|
|
|
+ 1695 against THIS *)
|
|
|
+ 1696 QbeGen.CopyOp("@", thisQ);
|
|
|
+ 1697 QbeGen.PushWith(thisQ); .)
|
|
|
+ 1698 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
+ 1699 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
+ 1700 QbeGen.PopWith;
|
|
|
+ 1701 methRes := SymTab.CurRes();
|
|
|
+ 1702 Lower.ScopeLeave;
|
|
|
+ 1703 SymTab.CloseProc;
|
|
|
+ 1704 QbeGen.EndFunc(methRes); .) ) .
|
|
|
+ 1705 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1706 = "CONST" (. astSeq := AST.NoNode;
|
|
|
+ 1707 astTail := AST.NoNode; .)
|
|
|
+ 1708 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1709 astSeq, astTail, astDecl); .) }
|
|
|
+ 1710 (. astDecl := astSeq; .) .
|
|
|
+ 1711 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 1712 t: SymTab.TypeIndex;
|
|
|
+ 1713 qv: QbeGen.QVal;
|
|
|
+ 1714 cls: INTEGER;
|
|
|
+ 1715 mk: ARRAY [0 .. 15] OF CARDINAL;
|
|
|
+ 1716 mw: CARDINAL;
|
|
|
+ 1717 mlo: INTEGER;
|
|
|
+ 1718 astNode: AST.Node; .)
|
|
|
+ 1719 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1720 SymTab.KindConst) THEN
|
|
|
+ 1721 SemError(200) END; .)
|
|
|
+ 1722 "="
|
|
|
+ 1723 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1724 AST.SetChild(astNode, 0,
|
|
|
+ 1725 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1726 AST.SetChild(astNode, 1, astCur);
|
|
|
+ 1727 AST.SetTy(astNode, t);
|
|
|
+ 1728 astDecl := astNode;
|
|
|
+ 1729 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
+ 1730 Lower.NoteConstVal(qv);
|
|
|
+ 1731 SymTab.SetSymType(n, t);
|
|
|
+ 1732 cls := SymTab.ClassOf(t);
|
|
|
+ 1733 IF cls = SymTab.ClSet THEN
|
|
|
+ 1734 (* a SET CONST needs static
|
|
|
+ 1735 data: fold its mask now
|
|
|
+ 1736 (the grammar sees the
|
|
|
+ 1737 element values) and let
|
|
|
+ 1738 Lower re-emit it *)
|
|
|
+ 1739 IF Lower.SetConstMaskOf(
|
|
|
+ 1740 AST.Child(astNode, 1),
|
|
|
+ 1741 mk, mw, mlo) THEN
|
|
|
+ 1742 Lower.NoteSetMask(n, mk, mw,
|
|
|
+ 1743 mlo);
|
|
|
+ 1744 SymTab.SetSymVal(n, qv)
|
|
|
+ 1745 ELSE
|
|
|
+ 1746 SemError(230)
|
|
|
+ 1747 END
|
|
|
+ 1748 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 1749 OR (cls = SymTab.ClRecord)
|
|
|
+ 1750 OR (cls = SymTab.ClClass)
|
|
|
+ 1751 OR (cls = SymTab.ClStr)
|
|
|
+ 1752 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 1753 (* an aggregate/string
|
|
|
+ 1754 constant: qv is its
|
|
|
+ 1755 descriptor address; no
|
|
|
+ 1756 scalar data *)
|
|
|
+ 1757 SymTab.SetSymVal(n, qv)
|
|
|
+ 1758 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
+ 1759 SemError(230)
|
|
|
+ 1760 ELSE
|
|
|
+ 1761 SymTab.SetSymVal(n, qv);
|
|
|
+ 1762 END; .) .
|
|
|
+ 1763 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1764 = "VAR" (. astSeq := AST.NoNode;
|
|
|
+ 1765 astTail := AST.NoNode; .)
|
|
|
+ 1766 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1767 astSeq, astTail, astDecl); .) }
|
|
|
+ 1768 (. astDecl := astSeq; .) .
|
|
|
+ 1769 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 1770 t: SymTab.TypeIndex;
|
|
|
+ 1771 i: CARDINAL;
|
|
|
+ 1772 cls: INTEGER;
|
|
|
+ 1773 astNode, astTail: AST.Node; .)
|
|
|
+ 1774 = VarIdents ":"
|
|
|
+ 1775 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1776 astTail := astNode;
|
|
|
+ 1777 i := 0;
|
|
|
+ 1778 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1779 SymTab.PendName(i, nm);
|
|
|
+ 1780 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
+ 1781 (* chunked: a VAR list can
|
|
|
+ 1782 exceed AST.MaxChild *)
|
|
|
+ 1783 AstAppend(AST.NkBlock,
|
|
|
+ 1784 astNode, astTail,
|
|
|
+ 1785 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
+ 1786 INC(i)
|
|
|
+ 1787 END;
|
|
|
+ 1788 AST.SetTy(astNode, t);
|
|
|
+ 1789 astDecl := astNode;
|
|
|
+ 1790 cls := SymTab.ClassOf(t);
|
|
|
+ 1791 IF (t # SymTab.InvalidType)
|
|
|
+ 1792 AND NOT SymTab.IsUnresolved(t)
|
|
|
+ 1793 AND (cls # SymTab.ClInt)
|
|
|
+ 1794 AND (cls # SymTab.ClBool)
|
|
|
+ 1795 AND (cls # SymTab.ClChar)
|
|
|
+ 1796 AND (cls # SymTab.ClReal)
|
|
|
+ 1797 AND (cls # SymTab.ClArray)
|
|
|
+ 1798 AND (cls # SymTab.ClSet)
|
|
|
+ 1799 AND (cls # SymTab.ClRecord)
|
|
|
+ 1800 AND (cls # SymTab.ClPtr)
|
|
|
+ 1801 AND (cls # SymTab.ClLong)
|
|
|
+ 1802 AND (cls # SymTab.ClProc)
|
|
|
+ 1803 AND (cls # SymTab.ClUChar)
|
|
|
+ 1804 AND (cls # SymTab.ClUStr)
|
|
|
+ 1805 AND (cls # SymTab.ClEnum)
|
|
|
+ 1806 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 1807 SemError(230) END;
|
|
|
+ 1808 IF QbeGen.LocFull() THEN
|
|
|
+ 1809 SemError(233) END;
|
|
|
+ 1810 i := 0;
|
|
|
+ 1811 IF SymTab.IsUnresolved(t)
|
|
|
+ 1812 AND NOT SymTab.InProc() THEN
|
|
|
+ 1813 (* a forward-typed global:
|
|
|
+ 1814 defer emission until the
|
|
|
+ 1815 TYPE block completes *)
|
|
|
+ 1816 AST.SetOp(astNode, 1);
|
|
|
+ 1817 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1818 SymTab.PendName(i, nm);
|
|
|
+ 1819 IF nPendVar <=
|
|
|
+ 1820 HIGH(pendVarName) THEN
|
|
|
+ 1821 pendVarName[nPendVar] := nm;
|
|
|
+ 1822 pendVarT[nPendVar] := t;
|
|
|
+ 1823 INC(nPendVar)
|
|
|
+ 1824 END;
|
|
|
+ 1825 INC(i)
|
|
|
+ 1826 END
|
|
|
+ 1827 ELSE
|
|
|
+ 1828 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1829 SymTab.PendName(i, nm);
|
|
|
+ 1830 INC(i)
|
|
|
+ 1831 END
|
|
|
+ 1832 END;
|
|
|
+ 1833 (* a plain VAR list, not a
|
|
|
+ 1834 heading: the signature
|
|
|
+ 1835 result is discarded *)
|
|
|
+ 1836 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1837 END; .) .
|
|
|
+ 1838 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 1839 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1840 SymTab.KindVar) THEN
|
|
|
+ 1841 SemError(200) END; .)
|
|
|
+ 1842 { ","
|
|
|
+ 1843 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1844 SymTab.KindVar) THEN
|
|
|
+ 1845 SemError(200) END; .) } .
|
|
|
+ 1846 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 1847 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1848 SemError(200) END; .)
|
|
|
+ 1849 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1850 SemError(200) END; .) } .
|
|
|
+ 1851 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 1852 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 1853 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 1854 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 1855 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
+ 1856 (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1857 mg: QbeGen.QVal; .)
|
|
|
+ 1858 = "PROCEDURE"
|
|
|
+ 1859 GetIdent<pn> (. IF methCls #
|
|
|
+ 1860 SymTab.InvalidType THEN
|
|
|
+ 1861 (* a method: resume the
|
|
|
+ 1862 declared symbol (reuse
|
|
|
+ 1863 its uid) *)
|
|
|
+ 1864 IF NOT SymTab.ResumeMethod(
|
|
|
+ 1865 methCls, pn) THEN
|
|
|
+ 1866 SemError(200) END
|
|
|
+ 1867 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 1868 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 1869 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 1870 SemError(200) END
|
|
|
+ 1871 END
|
|
|
+ 1872 END;
|
|
|
+ 1873 Lower.ScopeEnter;
|
|
|
+ 1874 Lower.NoteProc(pn,
|
|
|
+ 1875 SymTab.ProcUid(pn),
|
|
|
+ 1876 SymTab.InvalidType,
|
|
|
+ 1877 SymTab.ProcDepthOf(pn),
|
|
|
+ 1878 FALSE);
|
|
|
+ 1879 QbeGen.BeginFunc("");
|
|
|
+ 1880 IF methCls #
|
|
|
+ 1881 SymTab.InvalidType THEN
|
|
|
+ 1882 (* hidden THIS receiver:
|
|
|
+ 1883 a VAR param of the
|
|
|
+ 1884 class type, pushed as
|
|
|
+ 1885 the WITH base *)
|
|
|
+ 1886 IF NOT SymTab.EnterThisParam(
|
|
|
+ 1887 methCls) THEN
|
|
|
+ 1888 SemError(200) END;
|
|
|
+ 1889 IF NOT QbeGen.FuncParam(
|
|
|
+ 1890 "THIS", TRUE,
|
|
|
+ 1891 methCls) THEN
|
|
|
+ 1892 SemError(233) END
|
|
|
+ 1893 END; .)
|
|
|
+ 1894 [ FormalParams ]
|
|
|
+ 1895 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
+ 1896 SemError(235) END;
|
|
|
+ 1897 Lower.SetProcRes(t); .) ] .
|
|
|
+ 1898 FormalParams
|
|
|
+ 1899 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 1900 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1901 nm: SymTab.Name;
|
|
|
+ 1902 i: CARDINAL;
|
|
|
+ 1903 isV: BOOLEAN; .)
|
|
|
+ 1904 = (. isV := FALSE; .)
|
|
|
+ 1905 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1906 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 1907 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1908 SymTab.PendName(i, nm);
|
|
|
+ 1909 Lower.NoteParam(nm, t, isV);
|
|
|
+ 1910 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
+ 1911 (* value open arrays are
|
|
|
+ 1912 passed as descriptor
|
|
|
+ 1913 addresses (no copy):
|
|
|
+ 1914 same representation as
|
|
|
+ 1915 VAR formals *)
|
|
|
+ 1916 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 1917 isV
|
|
|
+ 1918 OR SymTab.IsOpenArray(t),
|
|
|
+ 1919 t) THEN
|
|
|
+ 1920 SemError(233) END;
|
|
|
+ 1921 INC(i)
|
|
|
+ 1922 END;
|
|
|
+ 1923 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1924 SemError(235) END; .) .
|
|
|
+ 1925 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 1926 static link gives them their parent's frame. Methods keep
|
|
|
+ 1927 parse-now/230-later. *)
|
|
|
+ 1928 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
+ 1929 astNode: AST.Node; .)
|
|
|
+ 1930 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1931 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1932 AST.SetOp(astNode, 0);
|
|
|
+ 1933 AST.SetChild(astNode, 0,
|
|
|
+ 1934 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1935 Lower.NoteProcNode(astNode); .)
|
|
|
+ 1936 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
+ 1937 astDecl := astNode;
|
|
|
+ 1938 Lower.ScopeLeave;
|
|
|
+ 1939 SymTab.MarkFwd;
|
|
|
+ 1940 SymTab.CloseProc;
|
|
|
+ 1941 QbeGen.AbortFunc; .)
|
|
|
+ 1942 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
+ 1943 astDecl := astNode;
|
|
|
+ 1944 Lower.MarkProcExternal;
|
|
|
+ 1945 Lower.ScopeLeave;
|
|
|
+ 1946 SymTab.MarkExternal("");
|
|
|
+ 1947 SymTab.CloseProc;
|
|
|
+ 1948 QbeGen.AbortFunc; .)
|
|
|
+ 1949 |
|
|
|
+ 1950 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
+ 1951 curProcNode := astNode; .)
|
|
|
+ 1952 Block<pn> (. IF deferredBody THEN
|
|
|
+ 1953 (* body skipped: close like
|
|
|
+ 1954 FORWARD (no body node) *)
|
|
|
+ 1955 astDecl := astNode;
|
|
|
+ 1956 Lower.ScopeLeave;
|
|
|
+ 1957 SymTab.CloseProc;
|
|
|
+ 1958 QbeGen.AbortFunc
|
|
|
+ 1959 ELSE
|
|
|
+ 1960 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1961 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
+ 1962 astDecl := astNode;
|
|
|
+ 1963 Lower.ScopeLeave;
|
|
|
+ 1964 SymTab.CloseProc;
|
|
|
+ 1965 QbeGen.EndFunc(
|
|
|
+ 1966 SymTab.ProcRes(pn))
|
|
|
+ 1967 END; .) ) .
|
|
|
+ 1968 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
+ 1969 = (. dfr := FALSE;
|
|
|
+ 1970 IF allowDefer AND twoPhaseParse
|
|
|
+ 1971 AND NOT repassing THEN
|
|
|
+ 1972 dfr := DeferSkip(pn)
|
|
|
+ 1973 END;
|
|
|
+ 1974 allowDefer := FALSE;
|
|
|
+ 1975 .)
|
|
|
+ 1976 DeclSeq (. astBlkDecls := astDecl;
|
|
|
+ 1977 astStmt := AST.NoNode;
|
|
|
+ 1978 nLab := 0; nGot := 0; .)
|
|
|
+ 1979 [ "BEGIN" (. (* an empty body is still a
|
|
|
+ 1980 body: mark it so Lower
|
|
|
+ 1981 does not read it as a
|
|
|
+ 1982 definition heading *)
|
|
|
+ 1983 IF NOT dfr THEN
|
|
|
+ 1984 IF astStmt = AST.NoNode THEN
|
|
|
+ 1985 astStmt :=
|
|
|
+ 1986 AST.MakeNode(AST.NkBlock)
|
|
|
+ 1987 END
|
|
|
+ 1988 END; .)
|
|
|
+ 1989 [ StatSeq ] ]
|
|
|
+ 1990 "END"
|
|
|
+ 1991 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 1992 SemError(202) END;
|
|
|
+ 1993 CheckGotos; .) .
|
|
|
+ 1994 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
+ 1995 level body once the unit's declarations are complete. Inlined at
|
|
|
+ 1996 both call sites because a stand-alone epsilon production is
|
|
|
+ 1997 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
+ 1998 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1999 = (. astSeq := AST.NoNode;
|
|
|
+ 2000 astTail := AST.NoNode; .)
|
|
|
+ 2001 Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 2002 astSeq, astTail, astStmt); .)
|
|
|
+ 2003 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 2004 astSeq, astTail, astStmt); .) ] }
|
|
|
+ 2005 (. astStmt := astSeq; .) .
|
|
|
+ 2006 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 2007 are accepted: the statement after ';' is optional. *)
|
|
|
+ 2008 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
+ 2009 = (. astStmt := AST.NoNode; .)
|
|
|
+ 2010 ( AssOrCall
|
|
|
+ 2011 | IfStat
|
|
|
+ 2012 | WhileStat
|
|
|
+ 2013 | RepeatStat
|
|
|
+ 2014 | LoopStat
|
|
|
+ 2015 | ForStat
|
|
|
+ 2016 | CaseStat
|
|
|
+ 2017 | WithStat
|
|
|
+ 2018 | ReturnStat
|
|
|
+ 2019 | HaltStat
|
|
|
+ 2020 | NewStat
|
|
|
+ 2021 | DisposeStat
|
|
|
+ 2022 | IncDecStat
|
|
|
+ 2023 | InclExclStat
|
|
|
+ 2024 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
+ 2025 SemError(230) END;
|
|
|
+ 2026 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
+ 2027 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
+ 2028 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
+ 2029 AST.SetChild(astStmt, 0,
|
|
|
+ 2030 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
+ 2031 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
+ 2032 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
+ 2033 dk: INTEGER;
|
|
|
+ 2034 qd, qe: QbeGen.QVal;
|
|
|
+ 2035 qn: SymTab.Name;
|
|
|
+ 2036 sfx, isInc: BOOLEAN;
|
|
|
+ 2037 astNode, astD: AST.Node; .)
|
|
|
+ 2038 = ( "INCL" (. isInc := TRUE; .)
|
|
|
+ 2039 | "EXCL" (. isInc := FALSE; .) )
|
|
|
+ 2040 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
+ 2041 Expr<et2, qe> ")"
|
|
|
+ 2042 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2043 IF isInc THEN
|
|
|
+ 2044 AST.SetChild(astNode, 0,
|
|
|
+ 2045 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
+ 2046 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2047 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
+ 2048 END;
|
|
|
+ 2049 IF astD # AST.NoNode THEN
|
|
|
+ 2050 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2051 IF astCur # AST.NoNode THEN
|
|
|
+ 2052 AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 2053 astStmt := astNode; .)
|
|
|
+ 2054 (. IF (at # SymTab.InvalidType)
|
|
|
+ 2055 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
+ 2056 SemError(222)
|
|
|
+ 2057 END; .) .
|
|
|
+ 2058 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 2059 integer designator. *)
|
|
|
+ 2060 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 2061 dk: INTEGER;
|
|
|
+ 2062 qd, qv, qn2, qstep:
|
|
|
+ 2063 QbeGen.QVal;
|
|
|
+ 2064 qn: SymTab.Name;
|
|
|
+ 2065 sfx, isInc: BOOLEAN;
|
|
|
+ 2066 astNode, astD, astStep:
|
|
|
+ 2067 AST.Node; .)
|
|
|
+ 2068 = (. isInc := TRUE; .)
|
|
|
+ 2069 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 2070 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 2071 "(" (. astStep := AST.NoNode; .)
|
|
|
+ 2072 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
+ 2073 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
+ 2074 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2075 IF isInc THEN
|
|
|
+ 2076 AST.SetChild(astNode, 0,
|
|
|
+ 2077 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
+ 2078 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2079 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
+ 2080 END;
|
|
|
+ 2081 IF astD # AST.NoNode THEN
|
|
|
+ 2082 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2083 IF astStep # AST.NoNode THEN
|
|
|
+ 2084 AST.SetChild(astNode, 2, astStep) END;
|
|
|
+ 2085 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2086 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2087 AND (dk # SymTab.KindParam)
|
|
|
+ 2088 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2089 SemError(210)
|
|
|
+ 2090 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 2091 SemError(211)
|
|
|
+ 2092 END; .) .
|
|
|
+ 2093 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 2094 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 2095 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 2096 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2097 dk: INTEGER;
|
|
|
+ 2098 qd, qm: QbeGen.QVal;
|
|
|
+ 2099 qn: SymTab.Name;
|
|
|
+ 2100 sfx: BOOLEAN;
|
|
|
+ 2101 bt: SymTab.TypeIndex;
|
|
|
+ 2102 astNode, astD: AST.Node; .)
|
|
|
+ 2103 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 2104 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2105 AST.SetChild(astNode, 0,
|
|
|
+ 2106 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
+ 2107 IF astD # AST.NoNode THEN
|
|
|
+ 2108 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2109 astStmt := astNode; .)
|
|
|
+ 2110 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2111 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2112 AND (dk # SymTab.KindParam)
|
|
|
+ 2113 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2114 SemError(210)
|
|
|
+ 2115 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 2116 SymTab.ClPtr THEN
|
|
|
+ 2117 SemError(219)
|
|
|
+ 2118 END; .) .
|
|
|
+ 2119 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2120 dk: INTEGER;
|
|
|
+ 2121 qd, qv: QbeGen.QVal;
|
|
|
+ 2122 qn: SymTab.Name;
|
|
|
+ 2123 sfx: BOOLEAN;
|
|
|
+ 2124 astNode, astD: AST.Node; .)
|
|
|
+ 2125 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 2126 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2127 AST.SetChild(astNode, 0,
|
|
|
+ 2128 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
+ 2129 IF astD # AST.NoNode THEN
|
|
|
+ 2130 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2131 astStmt := astNode; .)
|
|
|
+ 2132 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2133 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2134 AND (dk # SymTab.KindParam)
|
|
|
+ 2135 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2136 SemError(210)
|
|
|
+ 2137 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 2138 SymTab.ClPtr THEN
|
|
|
+ 2139 SemError(219)
|
|
|
+ 2140 END; .) .
|
|
|
+ 2141 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 2142 address; field designators resolve through both stacks. *)
|
|
|
+ 2143 WithStat (. VAR nW: CARDINAL;
|
|
|
+ 2144 astNode: AST.Node; .)
|
|
|
+ 2145 = "WITH" (. nW := 0;
|
|
|
+ 2146 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ 2147 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ 2148 "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ 2149 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ 2150 AST.NChild(astNode), astStmt);
|
|
|
+ 2151 astStmt := astNode;
|
|
|
+ 2152 WHILE nW > 0 DO
|
|
|
+ 2153 SymTab.PopScope;
|
|
|
+ 2154 QbeGen.PopWith;
|
|
|
+ 2155 DEC(nW)
|
|
|
+ 2156 END; .) .
|
|
|
+ 2157 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ 2158 (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2159 dk: INTEGER;
|
|
|
+ 2160 qd, qe: QbeGen.QVal;
|
|
|
+ 2161 qn: SymTab.Name;
|
|
|
+ 2162 sfx: BOOLEAN; .)
|
|
|
+ 2163 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 2164 (. IF astCur # AST.NoNode THEN
|
|
|
+ 2165 AST.SetChild(wnode,
|
|
|
+ 2166 AST.NChild(wnode), astCur) END;
|
|
|
+ 2167 IF dt = SymTab.InvalidType THEN
|
|
|
+ 2168 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 2169 SymTab.ClRecord)
|
|
|
+ 2170 AND (SymTab.ClassOf(dt) #
|
|
|
+ 2171 SymTab.ClClass) THEN
|
|
|
+ 2172 SemError(215)
|
|
|
+ 2173 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 2174 QbeGen.PushWith(qd);
|
|
|
+ 2175 INC(nW)
|
|
|
+ 2176 END; .) .
|
|
|
+ 2177 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 2178 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 2179 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 2180 dk: INTEGER;
|
|
|
+ 2181 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 2182 qn: SymTab.Name;
|
|
|
+ 2183 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 2184 q2, mg0: QbeGen.QVal;
|
|
|
+ 2185 isR, conv, wconv: BOOLEAN;
|
|
|
+ 2186 called, sfx: BOOLEAN;
|
|
|
+ 2187 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 2188 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
+ 2189 = GetIdent<n>
|
|
|
+ 2190 ( ":" (. NoteLabel(n);
|
|
|
+ 2191 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
+ 2192 AST.SetChild(astNode, 0,
|
|
|
+ 2193 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 2194 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
+ 2195 AST.SetChild(astLab, 0, astNode); .)
|
|
|
+ 2196 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
+ 2197 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
+ 2198 astStmt := astLab; .)
|
|
|
+ 2199 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
+ 2200 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
+ 2201 ( ":="
|
|
|
+ 2202 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 2203 AST.NkAssign, 0, astLhs, astCur);
|
|
|
+ 2204 IF (dt # SymTab.InvalidType)
|
|
|
+ 2205 AND (dk # SymTab.KindVar)
|
|
|
+ 2206 AND (dk # SymTab.KindParam)
|
|
|
+ 2207 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2208 SemError(210)
|
|
|
+ 2209 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 2210 dt) THEN
|
|
|
+ 2211 SemError(210)
|
|
|
+ 2212 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 2213 AND (SymTab.ClassOf(dt) =
|
|
|
+ 2214 SymTab.ClClass) THEN
|
|
|
+ 2215 SemError(230) END;
|
|
|
+ 2216 isR := (dt #
|
|
|
+ 2217 SymTab.InvalidType)
|
|
|
+ 2218 AND (SymTab.ClassOf(dt)
|
|
|
+ 2219 = SymTab.ClReal);
|
|
|
+ 2220 conv := isR
|
|
|
+ 2221 AND SymTab.IsIntFamily(et);
|
|
|
+ 2222 wconv := (dt #
|
|
|
+ 2223 SymTab.InvalidType)
|
|
|
+ 2224 AND SymTab.IsLongFamily(dt)
|
|
|
+ 2225 AND SymTab.IsIntFamily(et);
|
|
|
+ 2226 IF ((dk = SymTab.KindVar)
|
|
|
+ 2227 OR (dk = SymTab.KindParam)
|
|
|
+ 2228 OR (dk = SymTab.KindField))
|
|
|
+ 2229 AND (dt # SymTab.InvalidType)
|
|
|
+ 2230 AND (et # SymTab.InvalidType)
|
|
|
+ 2231 AND (SymTab.ClassOf(dt) #
|
|
|
+ 2232 SymTab.ClClass) THEN
|
|
|
+ 2233 END; .)
|
|
|
+ 2234 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
+ 2235 (. astRes := AstCallNode(astLhs);
|
|
|
+ 2236 sfx := FALSE; .)
|
|
|
+ 2237 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
+ 2238 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 2239 AST.NkAssign, 0, astRes, astCur);
|
|
|
+ 2240 IF NOT sfx THEN
|
|
|
+ 2241 SemError(233)
|
|
|
+ 2242 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
+ 2243 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
+ 2244 SemError(210)
|
|
|
+ 2245 END; .)
|
|
|
+ 2246 | (. IF ct2 #
|
|
|
+ 2247 SymTab.InvalidType THEN
|
|
|
+ 2248 SemError(233) END;
|
|
|
+ 2249 astStmt := astRes; .) )
|
|
|
+ 2250 | (* bare `P;`: proper parameterless
|
|
|
+ 2251 procedure call; anything else
|
|
|
+ 2252 here is 233 (was a bare syntax
|
|
|
+ 2253 error before 4.2) *)
|
|
|
+ 2254 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 2255 IF (dk = SymTab.KindProc)
|
|
|
+ 2256 AND NOT sfx THEN
|
|
|
+ 2257 res0 := SymTab.ProcRes(qn);
|
|
|
+ 2258 IF res0 #
|
|
|
+ 2259 SymTab.InvalidType THEN
|
|
|
+ 2260 SemError(233)
|
|
|
+ 2261 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 2262 0 THEN
|
|
|
+ 2263 SemError(233)
|
|
|
+ 2264 END
|
|
|
+ 2265 ELSE SemError(233)
|
|
|
+ 2266 END; .) ) ) .
|
|
|
+ 2267 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 2268 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 2269 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 2270 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 2271 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 2272 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 2273 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2274 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 2275 vs: INTEGER;
|
|
|
+ 2276 res: SymTab.TypeIndex;
|
|
|
+ 2277 mg: QbeGen.QVal;
|
|
|
+ 2278 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
+ 2279 = "(" (. called := TRUE;
|
|
|
+ 2280 ok := TRUE;
|
|
|
+ 2281 ind := FALSE;
|
|
|
+ 2282 isConv := FALSE;
|
|
|
+ 2283 isMeth := methCls #
|
|
|
+ 2284 SymTab.InvalidType;
|
|
|
+ 2285 IF isMeth THEN
|
|
|
+ 2286 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
+ 2287 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
+ 2288 res := SymTab.ProcRes(pn)
|
|
|
+ 2289 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
+ 2290 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
+ 2291 (* ISO type conversion T(x):
|
|
|
+ 2292 one value, result is T *)
|
|
|
+ 2293 isConv := TRUE;
|
|
|
+ 2294 res := SymTab.SymType(pn)
|
|
|
+ 2295 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 2296 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 2297 ind := TRUE;
|
|
|
+ 2298 res := SymTab.ProcTypeRes(pt)
|
|
|
+ 2299 ELSE SemError(233);
|
|
|
+ 2300 ok := FALSE;
|
|
|
+ 2301 res := SymTab.InvalidType
|
|
|
+ 2302 END;
|
|
|
+ 2303 i := 0; .)
|
|
|
+ 2304 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 2305 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 2306 ")" (. IF ok THEN
|
|
|
+ 2307 IF isConv THEN
|
|
|
+ 2308 (* a conversion takes
|
|
|
+ 2309 exactly one value *)
|
|
|
+ 2310 IF i # 1 THEN
|
|
|
+ 2311 SemError(233); ok := FALSE
|
|
|
+ 2312 END
|
|
|
+ 2313 ELSE
|
|
|
+ 2314 IF isMeth THEN
|
|
|
+ 2315 np := SymTab.ClassMethodNPar(
|
|
|
+ 2316 methCls, pn)
|
|
|
+ 2317 ELSIF ind THEN
|
|
|
+ 2318 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 2319 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 2320 END;
|
|
|
+ 2321 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 2322 AND (SymTab.SymKind(pn) =
|
|
|
+ 2323 SymTab.KindProc)
|
|
|
+ 2324 AND SymTab.Varargs(pn);
|
|
|
+ 2325 IF (i # np) AND NOT va THEN
|
|
|
+ 2326 SemError(233); ok := FALSE
|
|
|
+ 2327 END
|
|
|
+ 2328 END
|
|
|
+ 2329 END;
|
|
|
+ 2330 IF NOT ok THEN
|
|
|
+ 2331 t := SymTab.InvalidType;
|
|
|
+ 2332 QbeGen.CopyOp("0", q)
|
|
|
+ 2333 ELSIF want THEN
|
|
|
+ 2334 IF res =
|
|
|
+ 2335 SymTab.InvalidType THEN
|
|
|
+ 2336 IF NOT soft THEN SemError(233) END;
|
|
|
+ 2337 t := SymTab.InvalidType;
|
|
|
+ 2338 QbeGen.CopyOp("0", q)
|
|
|
+ 2339 ELSE t := res;
|
|
|
+ 2340 QbeGen.CopyOp("@", q)
|
|
|
+ 2341 END
|
|
|
+ 2342 ELSE
|
|
|
+ 2343 IF res #
|
|
|
+ 2344 SymTab.InvalidType THEN
|
|
|
+ 2345 SemError(233)
|
|
|
+ 2346 END;
|
|
|
+ 2347 t := SymTab.InvalidType;
|
|
|
+ 2348 QbeGen.CopyOp("0", q);
|
|
|
+ 2349 END; .) .
|
|
|
+ 2350 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 2351 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 2352 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 2353 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 2354 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 2355 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 2356 isV, conv, va: BOOLEAN;
|
|
|
+ 2357 cl: CHAR;
|
|
|
+ 2358 savedN, aj: CARDINAL;
|
|
|
+ 2359 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 2360 OF AST.Node;
|
|
|
+ 2361 astActual: AST.Node; .)
|
|
|
+ 2362 = (. (* Parsing the actual can clobber
|
|
|
+ 2363 the enclosing call's argument
|
|
|
+ 2364 list (Factor resets astNArgs),
|
|
|
+ 2365 so save/restore it. *)
|
|
|
+ 2366 savedN := astNArgs; aj := 0;
|
|
|
+ 2367 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2368 savedArgs[aj] := astArgs[aj];
|
|
|
+ 2369 INC(aj)
|
|
|
+ 2370 END; .)
|
|
|
+ 2371 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
+ 2372 astActual := astCur;
|
|
|
+ 2373 astNArgs := savedN; aj := 0;
|
|
|
+ 2374 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2375 astArgs[aj] := savedArgs[aj];
|
|
|
+ 2376 INC(aj)
|
|
|
+ 2377 END;
|
|
|
+ 2378 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 2379 astArgs[astNArgs] := astCur;
|
|
|
+ 2380 INC(astNArgs)
|
|
|
+ 2381 END;
|
|
|
+ 2382 va := (NOT ind)
|
|
|
+ 2383 AND (methCls =
|
|
|
+ 2384 SymTab.InvalidType)
|
|
|
+ 2385 AND (SymTab.SymKind(pn) =
|
|
|
+ 2386 SymTab.KindProc)
|
|
|
+ 2387 AND SymTab.Varargs(pn);
|
|
|
+ 2388 IF ind THEN
|
|
|
+ 2389 ft :=
|
|
|
+ 2390 SymTab.ProcTypeParamType(pt,
|
|
|
+ 2391 i);
|
|
|
+ 2392 isV :=
|
|
|
+ 2393 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 2394 i)
|
|
|
+ 2395 ELSIF methCls #
|
|
|
+ 2396 SymTab.InvalidType THEN
|
|
|
+ 2397 ft :=
|
|
|
+ 2398 SymTab.ClassMethodParamType(
|
|
|
+ 2399 methCls, pn, i);
|
|
|
+ 2400 isV :=
|
|
|
+ 2401 SymTab.ClassMethodParamIsVar(
|
|
|
+ 2402 methCls, pn, i)
|
|
|
+ 2403 ELSE
|
|
|
+ 2404 ft := SymTab.ParamType(pn, i);
|
|
|
+ 2405 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 2406 END;
|
|
|
+ 2407 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 2408 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 2409 ELSIF isV THEN
|
|
|
+ 2410 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 2411 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 2412 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 2413 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 2414 ELSIF (AST.Kind(astActual) #
|
|
|
+ 2415 AST.NkDesignator)
|
|
|
+ 2416 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
2417 SemError(233)
|
|
|
- 2418 END
|
|
|
- 2419 ELSE
|
|
|
- 2420 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 2421 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 2422 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 2423 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2424 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
- 2425 SemError(233)
|
|
|
- 2426 END
|
|
|
- 2427 END; .) .
|
|
|
- 2428 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2429 q: QbeGen.QVal;
|
|
|
- 2430 hasElse: BOOLEAN;
|
|
|
- 2431 astCond, astIf, astLast,
|
|
|
- 2432 astNode: AST.Node; .)
|
|
|
- 2433 = "IF" (. hasElse := FALSE; .)
|
|
|
- 2434 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2435 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2436 SemError(214) END; .)
|
|
|
- 2437 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2438 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2439 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2440 astIf := astNode;
|
|
|
- 2441 astLast := astNode; .)
|
|
|
- 2442 { "ELSIF"
|
|
|
- 2443 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2444 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2445 SemError(214) END; .)
|
|
|
- 2446 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2447 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2448 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2449 AST.SetChild(astLast, 2, astNode);
|
|
|
- 2450 astLast := astNode; .) }
|
|
|
- 2451 [ "ELSE" (. hasElse := TRUE;
|
|
|
- 2452 astStmt := AST.NoNode; .)
|
|
|
- 2453 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 2454 "END" (. astStmt := astIf; .) .
|
|
|
- 2455 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2456 q: QbeGen.QVal;
|
|
|
- 2457 astCond, astNode: AST.Node; .)
|
|
|
- 2458 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
- 2459 Expr<t, q> (. astCond := astCur;
|
|
|
- 2460 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2461 SemError(214) END; .)
|
|
|
- 2462 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 2463 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2464 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2465 astStmt := astNode; .)
|
|
|
- 2466 "END" .
|
|
|
- 2467 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2468 q: QbeGen.QVal;
|
|
|
- 2469 astCond, astBody, astNode:
|
|
|
- 2470 AST.Node; .)
|
|
|
- 2471 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
- 2472 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 2473 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 2474 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 2475 AST.SetChild(astNode, 0, astBody);
|
|
|
- 2476 AST.SetChild(astNode, 1, astCond);
|
|
|
- 2477 astStmt := astNode;
|
|
|
- 2478 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2479 SemError(214) END; .) .
|
|
|
- 2480 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 2481 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
- 2482 QbeGen.NewLabel(lEnd);
|
|
|
- 2483 QbeGen.PushLoop(lEnd); .)
|
|
|
- 2484 [ StatSeq ]
|
|
|
- 2485 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 2486 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 2487 astStmt := astNode;
|
|
|
- 2488 QbeGen.PopLoop; .) .
|
|
|
- 2489 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 2490 Runtime direction would need a compare-select; the literal
|
|
|
- 2491 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 2492 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 2493 tlo, thi, tby:
|
|
|
- 2494 SymTab.TypeIndex;
|
|
|
- 2495 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 2496 QbeGen.QVal;
|
|
|
- 2497 lTop, lBody, lEnd:
|
|
|
+ 2418 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
+ 2419 SemError(233)
|
|
|
+ 2420 END
|
|
|
+ 2421 ELSE
|
|
|
+ 2422 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 2423 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 2424 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 2425 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 2426 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
+ 2427 SemError(233)
|
|
|
+ 2428 END
|
|
|
+ 2429 END; .) .
|
|
|
+ 2430 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2431 q: QbeGen.QVal;
|
|
|
+ 2432 hasElse: BOOLEAN;
|
|
|
+ 2433 astCond, astIf, astLast,
|
|
|
+ 2434 astNode: AST.Node; .)
|
|
|
+ 2435 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 2436 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2437 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2438 SemError(214) END; .)
|
|
|
+ 2439 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2440 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2441 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2442 astIf := astNode;
|
|
|
+ 2443 astLast := astNode; .)
|
|
|
+ 2444 { "ELSIF"
|
|
|
+ 2445 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2446 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2447 SemError(214) END; .)
|
|
|
+ 2448 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2449 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2450 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2451 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 2452 astLast := astNode; .) }
|
|
|
+ 2453 [ "ELSE" (. hasElse := TRUE;
|
|
|
+ 2454 astStmt := AST.NoNode; .)
|
|
|
+ 2455 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 2456 "END" (. astStmt := astIf; .) .
|
|
|
+ 2457 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2458 q: QbeGen.QVal;
|
|
|
+ 2459 astCond, astNode: AST.Node; .)
|
|
|
+ 2460 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2461 Expr<t, q> (. astCond := astCur;
|
|
|
+ 2462 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2463 SemError(214) END; .)
|
|
|
+ 2464 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 2465 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2466 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2467 astStmt := astNode; .)
|
|
|
+ 2468 "END" .
|
|
|
+ 2469 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2470 q: QbeGen.QVal;
|
|
|
+ 2471 astCond, astBody, astNode:
|
|
|
+ 2472 AST.Node; .)
|
|
|
+ 2473 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
+ 2474 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 2475 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 2476 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 2477 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 2478 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 2479 astStmt := astNode;
|
|
|
+ 2480 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2481 SemError(214) END; .) .
|
|
|
+ 2482 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 2483 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
+ 2484 QbeGen.NewLabel(lEnd);
|
|
|
+ 2485 QbeGen.PushLoop(lEnd); .)
|
|
|
+ 2486 [ StatSeq ]
|
|
|
+ 2487 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 2488 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 2489 astStmt := astNode;
|
|
|
+ 2490 QbeGen.PopLoop; .) .
|
|
|
+ 2491 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 2492 Runtime direction would need a compare-select; the literal
|
|
|
+ 2493 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 2494 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 2495 tlo, thi, tby:
|
|
|
+ 2496 SymTab.TypeIndex;
|
|
|
+ 2497 qlo, qhi, qby, qt, qk, qb:
|
|
|
2498 QbeGen.QVal;
|
|
|
- 2499 by: INTEGER;
|
|
|
- 2500 ok: BOOLEAN;
|
|
|
- 2501 astVar, astLo, astHi, astBy,
|
|
|
- 2502 astNode: AST.Node; .)
|
|
|
- 2503 = "FOR" (. by := 1; .)
|
|
|
- 2504 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 2505 astStmt := AST.NoNode;
|
|
|
- 2506 astBy := AST.NoNode;
|
|
|
- 2507 ok := SymTab.Lookup(lv);
|
|
|
- 2508 IF NOT ok THEN
|
|
|
- 2509 SemError(201)
|
|
|
- 2510 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 2511 SymTab.KindVar)
|
|
|
- 2512 AND (SymTab.SymKind(lv) #
|
|
|
- 2513 SymTab.KindParam) THEN
|
|
|
- 2514 SemError(220); ok := FALSE
|
|
|
- 2515 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 2516 SymTab.SymType(lv)) THEN
|
|
|
- 2517 SemError(220); ok := FALSE
|
|
|
- 2518 END; .)
|
|
|
- 2519 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 2520 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 2521 SemError(220); ok := FALSE
|
|
|
- 2522 END; .)
|
|
|
- 2523 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 2524 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 2525 SemError(220); ok := FALSE
|
|
|
- 2526 END; .)
|
|
|
- 2527 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 2528 IF (tby #
|
|
|
- 2529 SymTab.InvalidType)
|
|
|
- 2530 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 2531 SemError(220); ok := FALSE
|
|
|
- 2532 END;
|
|
|
- 2533 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 2534 SemError(230); by := 1
|
|
|
- 2535 ELSIF by = 0 THEN
|
|
|
- 2536 SemError(220); by := 1
|
|
|
- 2537 END; .) ]
|
|
|
- 2538 "DO"
|
|
|
- 2539 [ StatSeq ]
|
|
|
- 2540 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 2541 AST.SetChild(astNode, 0, astVar);
|
|
|
- 2542 AST.SetChild(astNode, 1, astLo);
|
|
|
- 2543 AST.SetChild(astNode, 2, astHi);
|
|
|
- 2544 AST.SetChild(astNode, 3, astBy);
|
|
|
- 2545 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 2546 astStmt := astNode;
|
|
|
- 2547 .) .
|
|
|
- 2548 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 2549 qsel, lEnd: QbeGen.QVal;
|
|
|
- 2550 arm, astNode, astArms,
|
|
|
- 2551 astArmsTail: AST.Node; .)
|
|
|
- 2552 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 2553 AST.SetChild(astNode, 0, astCur);
|
|
|
- 2554 astArms := AST.NoNode;
|
|
|
- 2555 astArmsTail := AST.NoNode;
|
|
|
- 2556 .)
|
|
|
- 2557 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 2558 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 2559 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 2560 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2561 AST.SetOp(arm, 1);
|
|
|
- 2562 AST.SetChild(arm, 0, astStmt);
|
|
|
- 2563 AstAppend(AST.NkBlock,
|
|
|
- 2564 astArms, astArmsTail, arm); .) ]
|
|
|
- 2565 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 2566 astStmt := astNode;
|
|
|
- 2567 .) .
|
|
|
- 2568 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 2569 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 2570 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 2571 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 2572 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2573 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 2574 (. VAR arm: AST.Node; .)
|
|
|
- 2575 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
- 2576 CaseLabel<tsel, qsel, arm>
|
|
|
- 2577 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
- 2578 ":" (. astStmt := AST.NoNode; .)
|
|
|
- 2579 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 2580 astStmt);
|
|
|
- 2581 AstAppend(AST.NkBlock,
|
|
|
- 2582 arms, armsTail, arm);
|
|
|
- 2583 .) .
|
|
|
- 2584 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2585 arm: AST.Node>
|
|
|
- 2586 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 2587 q2, q3, qc, qd, qe:
|
|
|
- 2588 QbeGen.QVal;
|
|
|
- 2589 astLab: AST.Node;
|
|
|
- 2590 lNext: QbeGen.QVal; .)
|
|
|
- 2591 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 2592 IF (t2 #
|
|
|
- 2593 SymTab.InvalidType)
|
|
|
- 2594 AND (tsel #
|
|
|
- 2595 SymTab.InvalidType)
|
|
|
- 2596 AND ((SymTab.ClassOf(t2) =
|
|
|
- 2597 SymTab.ClSet)
|
|
|
- 2598 OR (SymTab.ClassOf(tsel) =
|
|
|
- 2599 SymTab.ClSet)) THEN
|
|
|
- 2600 SemError(230)
|
|
|
- 2601 ELSIF (t2 #
|
|
|
- 2602 SymTab.InvalidType)
|
|
|
- 2603 AND (tsel #
|
|
|
- 2604 SymTab.InvalidType)
|
|
|
- 2605 AND NOT SymTab.EqCheck(t2,
|
|
|
- 2606 tsel) THEN
|
|
|
- 2607 SemError(213) END;
|
|
|
- 2608 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 2609 SemError(230)
|
|
|
- 2610 END; .)
|
|
|
- 2611 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 2612 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 2613 IF (t3 #
|
|
|
- 2614 SymTab.InvalidType)
|
|
|
- 2615 AND (tsel #
|
|
|
- 2616 SymTab.InvalidType)
|
|
|
- 2617 AND NOT SymTab.EqCheck(t3,
|
|
|
- 2618 tsel) THEN
|
|
|
- 2619 SemError(213) END;
|
|
|
- 2620 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 2621 SemError(230)
|
|
|
- 2622 END; .) ]
|
|
|
- 2623 (. AST.SetChild(arm,
|
|
|
- 2624 AST.NChild(arm), astLab); .) .
|
|
|
- 2625 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2626 q, qt: QbeGen.QVal;
|
|
|
- 2627 res: SymTab.TypeIndex;
|
|
|
- 2628 hadE, conv: BOOLEAN;
|
|
|
- 2629 astVal, astNode: AST.Node; .)
|
|
|
- 2630 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 2631 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 2632 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 2633 IF hadE THEN
|
|
|
- 2634 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2635 END;
|
|
|
- 2636 astStmt := astNode;
|
|
|
- 2637 conv := FALSE;
|
|
|
- 2638 IF NOT SymTab.InProc() THEN
|
|
|
- 2639 SemError(232)
|
|
|
- 2640 ELSE res := SymTab.CurRes();
|
|
|
- 2641 IF NOT hadE THEN
|
|
|
- 2642 IF res #
|
|
|
- 2643 SymTab.InvalidType THEN
|
|
|
- 2644 SemError(232)
|
|
|
- 2645 END
|
|
|
- 2646 ELSIF (res =
|
|
|
- 2647 SymTab.InvalidType)
|
|
|
- 2648 OR (t #
|
|
|
+ 2499 lTop, lBody, lEnd:
|
|
|
+ 2500 QbeGen.QVal;
|
|
|
+ 2501 by: INTEGER;
|
|
|
+ 2502 ok: BOOLEAN;
|
|
|
+ 2503 astVar, astLo, astHi, astBy,
|
|
|
+ 2504 astNode: AST.Node; .)
|
|
|
+ 2505 = "FOR" (. by := 1; .)
|
|
|
+ 2506 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 2507 astStmt := AST.NoNode;
|
|
|
+ 2508 astBy := AST.NoNode;
|
|
|
+ 2509 ok := SymTab.Lookup(lv);
|
|
|
+ 2510 IF NOT ok THEN
|
|
|
+ 2511 SemError(201)
|
|
|
+ 2512 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 2513 SymTab.KindVar)
|
|
|
+ 2514 AND (SymTab.SymKind(lv) #
|
|
|
+ 2515 SymTab.KindParam) THEN
|
|
|
+ 2516 SemError(220); ok := FALSE
|
|
|
+ 2517 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 2518 SymTab.SymType(lv)) THEN
|
|
|
+ 2519 SemError(220); ok := FALSE
|
|
|
+ 2520 END; .)
|
|
|
+ 2521 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 2522 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 2523 SemError(220); ok := FALSE
|
|
|
+ 2524 END; .)
|
|
|
+ 2525 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 2526 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 2527 SemError(220); ok := FALSE
|
|
|
+ 2528 END; .)
|
|
|
+ 2529 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 2530 IF (tby #
|
|
|
+ 2531 SymTab.InvalidType)
|
|
|
+ 2532 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 2533 SemError(220); ok := FALSE
|
|
|
+ 2534 END;
|
|
|
+ 2535 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 2536 SemError(230); by := 1
|
|
|
+ 2537 ELSIF by = 0 THEN
|
|
|
+ 2538 SemError(220); by := 1
|
|
|
+ 2539 END; .) ]
|
|
|
+ 2540 "DO"
|
|
|
+ 2541 [ StatSeq ]
|
|
|
+ 2542 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 2543 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 2544 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 2545 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 2546 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 2547 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 2548 astStmt := astNode;
|
|
|
+ 2549 .) .
|
|
|
+ 2550 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 2551 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 2552 arm, astNode, astArms,
|
|
|
+ 2553 astArmsTail: AST.Node; .)
|
|
|
+ 2554 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 2555 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 2556 astArms := AST.NoNode;
|
|
|
+ 2557 astArmsTail := AST.NoNode;
|
|
|
+ 2558 .)
|
|
|
+ 2559 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 2560 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 2561 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2562 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2563 AST.SetOp(arm, 1);
|
|
|
+ 2564 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 2565 AstAppend(AST.NkBlock,
|
|
|
+ 2566 astArms, astArmsTail, arm); .) ]
|
|
|
+ 2567 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 2568 astStmt := astNode;
|
|
|
+ 2569 .) .
|
|
|
+ 2570 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 2571 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 2572 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 2573 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 2574 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2575 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 2576 (. VAR arm: AST.Node; .)
|
|
|
+ 2577 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ 2578 CaseLabel<tsel, qsel, arm>
|
|
|
+ 2579 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ 2580 ":" (. astStmt := AST.NoNode; .)
|
|
|
+ 2581 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 2582 astStmt);
|
|
|
+ 2583 AstAppend(AST.NkBlock,
|
|
|
+ 2584 arms, armsTail, arm);
|
|
|
+ 2585 .) .
|
|
|
+ 2586 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2587 arm: AST.Node>
|
|
|
+ 2588 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 2589 q2, q3, qc, qd, qe:
|
|
|
+ 2590 QbeGen.QVal;
|
|
|
+ 2591 astLab: AST.Node;
|
|
|
+ 2592 lNext: QbeGen.QVal; .)
|
|
|
+ 2593 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 2594 IF (t2 #
|
|
|
+ 2595 SymTab.InvalidType)
|
|
|
+ 2596 AND (tsel #
|
|
|
+ 2597 SymTab.InvalidType)
|
|
|
+ 2598 AND ((SymTab.ClassOf(t2) =
|
|
|
+ 2599 SymTab.ClSet)
|
|
|
+ 2600 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 2601 SymTab.ClSet)) THEN
|
|
|
+ 2602 SemError(230)
|
|
|
+ 2603 ELSIF (t2 #
|
|
|
+ 2604 SymTab.InvalidType)
|
|
|
+ 2605 AND (tsel #
|
|
|
+ 2606 SymTab.InvalidType)
|
|
|
+ 2607 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 2608 tsel) THEN
|
|
|
+ 2609 SemError(213) END;
|
|
|
+ 2610 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 2611 SemError(230)
|
|
|
+ 2612 END; .)
|
|
|
+ 2613 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 2614 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 2615 IF (t3 #
|
|
|
+ 2616 SymTab.InvalidType)
|
|
|
+ 2617 AND (tsel #
|
|
|
+ 2618 SymTab.InvalidType)
|
|
|
+ 2619 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 2620 tsel) THEN
|
|
|
+ 2621 SemError(213) END;
|
|
|
+ 2622 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 2623 SemError(230)
|
|
|
+ 2624 END; .) ]
|
|
|
+ 2625 (. AST.SetChild(arm,
|
|
|
+ 2626 AST.NChild(arm), astLab); .) .
|
|
|
+ 2627 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2628 q, qt: QbeGen.QVal;
|
|
|
+ 2629 res: SymTab.TypeIndex;
|
|
|
+ 2630 hadE, conv: BOOLEAN;
|
|
|
+ 2631 astVal, astNode: AST.Node; .)
|
|
|
+ 2632 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 2633 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 2634 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 2635 IF hadE THEN
|
|
|
+ 2636 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2637 END;
|
|
|
+ 2638 astStmt := astNode;
|
|
|
+ 2639 conv := FALSE;
|
|
|
+ 2640 IF NOT SymTab.InProc() THEN
|
|
|
+ 2641 SemError(232)
|
|
|
+ 2642 ELSE res := SymTab.CurRes();
|
|
|
+ 2643 IF NOT hadE THEN
|
|
|
+ 2644 IF res #
|
|
|
+ 2645 SymTab.InvalidType THEN
|
|
|
+ 2646 SemError(232)
|
|
|
+ 2647 END
|
|
|
+ 2648 ELSIF (res =
|
|
|
2649 SymTab.InvalidType)
|
|
|
- 2650 AND NOT SymTab.Assignable(t,
|
|
|
- 2651 res) THEN
|
|
|
- 2652 SemError(232)
|
|
|
- 2653 END
|
|
|
- 2654 END; .) .
|
|
|
- 2655 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2656 q: QbeGen.QVal;
|
|
|
- 2657 astVal, astNode: AST.Node; .)
|
|
|
- 2658 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 2659 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 2660 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 2661 IF astVal # AST.NoNode THEN
|
|
|
- 2662 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2663 END;
|
|
|
- 2664 astStmt := astNode;
|
|
|
- 2665 .) .
|
|
|
- 2666 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 2667 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 2668 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 2669 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 2670 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 2671 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2672 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2673 (. VAR n: SymTab.Name; .)
|
|
|
- 2674 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
- 2675 (* The part of Design after the identifier: resolve it and walk the
|
|
|
- 2676 selectors. Split out so a statement can decide between a label
|
|
|
- 2677 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
- 2678 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2679 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2680 (. VAR fn, mal: SymTab.Name;
|
|
|
- 2681 cls: INTEGER;
|
|
|
- 2682 ic: SymTab.TypeIndex;
|
|
|
- 2683 curT, it, eT, bt:
|
|
|
- 2684 SymTab.TypeIndex;
|
|
|
- 2685 iq, ql, qlo, qhi, qe:
|
|
|
- 2686 QbeGen.QVal;
|
|
|
- 2687 lo, hi: INTEGER;
|
|
|
- 2688 fo: INTEGER;
|
|
|
- 2689 isOpen: BOOLEAN;
|
|
|
- 2690 qb, cv: QbeGen.QVal;
|
|
|
- 2691 r: BOOLEAN;
|
|
|
- 2692 astDes, astSel: AST.Node; .)
|
|
|
- 2693 = (. methCls := SymTab.InvalidType;
|
|
|
- 2694 QbeGen.CopyOp(n, qn);
|
|
|
- 2695 sfx := FALSE;
|
|
|
- 2696 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 2697 (* a bare method name inside
|
|
|
- 2698 a CLASS IMPLEMENTATION
|
|
|
- 2699 is a sibling call on
|
|
|
- 2700 THIS *)
|
|
|
- 2701 ic := SymTab.CurImplClass();
|
|
|
- 2702 IF (ic #
|
|
|
- 2703 SymTab.InvalidType)
|
|
|
- 2704 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 2705 sfx := FALSE;
|
|
|
- 2706 QbeGen.CopyOp("@", q);
|
|
|
- 2707 methCls := ic;
|
|
|
- 2708 k := SymTab.KindProc;
|
|
|
- 2709 t := SymTab.InvalidType
|
|
|
- 2710 ELSIF SymTab.InProc() THEN
|
|
|
- 2711 (* not declared anywhere
|
|
|
- 2712 in scope: with bodies
|
|
|
- 2713 parsed at unit end this
|
|
|
- 2714 is a genuine 201 (a
|
|
|
- 2715 nested-local forward is
|
|
|
- 2716 no longer tolerated). *)
|
|
|
- 2717 SemError(201);
|
|
|
- 2718 t := SymTab.InvalidType;
|
|
|
- 2719 k := -1;
|
|
|
- 2720 QbeGen.CopyOp("0", q)
|
|
|
- 2721 ELSE
|
|
|
- 2722 SemError(201);
|
|
|
- 2723 t :=
|
|
|
- 2724 SymTab.InvalidType;
|
|
|
- 2725 k := -1;
|
|
|
- 2726 QbeGen.CopyOp("0", q)
|
|
|
- 2727 END
|
|
|
- 2728 ELSE
|
|
|
- 2729 t := SymTab.SymType(n);
|
|
|
- 2730 k := SymTab.SymKind(n);
|
|
|
- 2731 IF k = SymTab.KindConst THEN
|
|
|
- 2732 IF SymTab.Equal(n,
|
|
|
- 2733 "TRUE") THEN
|
|
|
- 2734 t := SymTab.BoolType();
|
|
|
- 2735 QbeGen.CopyOp("1", q)
|
|
|
- 2736 ELSIF SymTab.Equal(n,
|
|
|
- 2737 "FALSE") THEN
|
|
|
- 2738 t := SymTab.BoolType();
|
|
|
- 2739 QbeGen.CopyOp("0", q)
|
|
|
- 2740 ELSIF SymTab.Equal(n,
|
|
|
- 2741 "NIL") THEN
|
|
|
- 2742 QbeGen.CopyOp("0", q)
|
|
|
- 2743 ELSE
|
|
|
- 2744 cls :=
|
|
|
- 2745 SymTab.ClassOf(t);
|
|
|
- 2746 IF (t #
|
|
|
- 2747 SymTab.InvalidType)
|
|
|
- 2748 AND ((cls = SymTab.ClInt)
|
|
|
- 2749 OR (cls
|
|
|
- 2750 = SymTab.ClChar)
|
|
|
+ 2650 OR (t #
|
|
|
+ 2651 SymTab.InvalidType)
|
|
|
+ 2652 AND NOT SymTab.Assignable(t,
|
|
|
+ 2653 res) THEN
|
|
|
+ 2654 SemError(232)
|
|
|
+ 2655 END
|
|
|
+ 2656 END; .) .
|
|
|
+ 2657 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2658 q: QbeGen.QVal;
|
|
|
+ 2659 astVal, astNode: AST.Node; .)
|
|
|
+ 2660 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 2661 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 2662 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 2663 IF astVal # AST.NoNode THEN
|
|
|
+ 2664 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2665 END;
|
|
|
+ 2666 astStmt := astNode;
|
|
|
+ 2667 .) .
|
|
|
+ 2668 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 2669 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 2670 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 2671 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 2672 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 2673 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2674 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2675 (. VAR n: SymTab.Name; .)
|
|
|
+ 2676 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
+ 2677 (* The part of Design after the identifier: resolve it and walk the
|
|
|
+ 2678 selectors. Split out so a statement can decide between a label
|
|
|
+ 2679 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
+ 2680 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2681 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2682 (. VAR fn, mal: SymTab.Name;
|
|
|
+ 2683 cls: INTEGER;
|
|
|
+ 2684 ic: SymTab.TypeIndex;
|
|
|
+ 2685 curT, it, eT, bt:
|
|
|
+ 2686 SymTab.TypeIndex;
|
|
|
+ 2687 iq, ql, qlo, qhi, qe:
|
|
|
+ 2688 QbeGen.QVal;
|
|
|
+ 2689 lo, hi: INTEGER;
|
|
|
+ 2690 fo: INTEGER;
|
|
|
+ 2691 isOpen: BOOLEAN;
|
|
|
+ 2692 qb, cv: QbeGen.QVal;
|
|
|
+ 2693 r: BOOLEAN;
|
|
|
+ 2694 astDes, astSel: AST.Node; .)
|
|
|
+ 2695 = (. methCls := SymTab.InvalidType;
|
|
|
+ 2696 QbeGen.CopyOp(n, qn);
|
|
|
+ 2697 sfx := FALSE;
|
|
|
+ 2698 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 2699 (* a bare method name inside
|
|
|
+ 2700 a CLASS IMPLEMENTATION
|
|
|
+ 2701 is a sibling call on
|
|
|
+ 2702 THIS *)
|
|
|
+ 2703 ic := SymTab.CurImplClass();
|
|
|
+ 2704 IF (ic #
|
|
|
+ 2705 SymTab.InvalidType)
|
|
|
+ 2706 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 2707 sfx := FALSE;
|
|
|
+ 2708 QbeGen.CopyOp("@", q);
|
|
|
+ 2709 methCls := ic;
|
|
|
+ 2710 k := SymTab.KindProc;
|
|
|
+ 2711 t := SymTab.InvalidType
|
|
|
+ 2712 ELSIF SymTab.InProc() THEN
|
|
|
+ 2713 (* not declared anywhere
|
|
|
+ 2714 in scope: with bodies
|
|
|
+ 2715 parsed at unit end this
|
|
|
+ 2716 is a genuine 201 (a
|
|
|
+ 2717 nested-local forward is
|
|
|
+ 2718 no longer tolerated). *)
|
|
|
+ 2719 SemError(201);
|
|
|
+ 2720 t := SymTab.InvalidType;
|
|
|
+ 2721 k := -1;
|
|
|
+ 2722 QbeGen.CopyOp("0", q)
|
|
|
+ 2723 ELSE
|
|
|
+ 2724 SemError(201);
|
|
|
+ 2725 t :=
|
|
|
+ 2726 SymTab.InvalidType;
|
|
|
+ 2727 k := -1;
|
|
|
+ 2728 QbeGen.CopyOp("0", q)
|
|
|
+ 2729 END
|
|
|
+ 2730 ELSE
|
|
|
+ 2731 t := SymTab.SymType(n);
|
|
|
+ 2732 k := SymTab.SymKind(n);
|
|
|
+ 2733 IF k = SymTab.KindConst THEN
|
|
|
+ 2734 IF SymTab.Equal(n,
|
|
|
+ 2735 "TRUE") THEN
|
|
|
+ 2736 t := SymTab.BoolType();
|
|
|
+ 2737 QbeGen.CopyOp("1", q)
|
|
|
+ 2738 ELSIF SymTab.Equal(n,
|
|
|
+ 2739 "FALSE") THEN
|
|
|
+ 2740 t := SymTab.BoolType();
|
|
|
+ 2741 QbeGen.CopyOp("0", q)
|
|
|
+ 2742 ELSIF SymTab.Equal(n,
|
|
|
+ 2743 "NIL") THEN
|
|
|
+ 2744 QbeGen.CopyOp("0", q)
|
|
|
+ 2745 ELSE
|
|
|
+ 2746 cls :=
|
|
|
+ 2747 SymTab.ClassOf(t);
|
|
|
+ 2748 IF (t #
|
|
|
+ 2749 SymTab.InvalidType)
|
|
|
+ 2750 AND ((cls = SymTab.ClInt)
|
|
|
2751 OR (cls
|
|
|
- 2752 = SymTab.ClEnum)
|
|
|
+ 2752 = SymTab.ClChar)
|
|
|
2753 OR (cls
|
|
|
- 2754 = SymTab.ClReal)
|
|
|
+ 2754 = SymTab.ClEnum)
|
|
|
2755 OR (cls
|
|
|
- 2756 = SymTab.ClLong)
|
|
|
+ 2756 = SymTab.ClReal)
|
|
|
2757 OR (cls
|
|
|
- 2758 = SymTab.ClNil)
|
|
|
- 2759 OR (cls = SymTab.ClBool)) THEN
|
|
|
- 2760 IF cls = SymTab.ClNil THEN
|
|
|
- 2761 QbeGen.CopyOp("0", q)
|
|
|
- 2762 ELSIF ((cls
|
|
|
- 2763 = SymTab.ClInt)
|
|
|
- 2764 OR (cls
|
|
|
- 2765 = SymTab.ClChar)
|
|
|
+ 2758 = SymTab.ClLong)
|
|
|
+ 2759 OR (cls
|
|
|
+ 2760 = SymTab.ClNil)
|
|
|
+ 2761 OR (cls = SymTab.ClBool)) THEN
|
|
|
+ 2762 IF cls = SymTab.ClNil THEN
|
|
|
+ 2763 QbeGen.CopyOp("0", q)
|
|
|
+ 2764 ELSIF ((cls
|
|
|
+ 2765 = SymTab.ClInt)
|
|
|
2766 OR (cls
|
|
|
- 2767 = SymTab.ClEnum)
|
|
|
+ 2767 = SymTab.ClChar)
|
|
|
2768 OR (cls
|
|
|
- 2769 = SymTab.ClLong)
|
|
|
- 2770 OR (cls = SymTab.ClBool))
|
|
|
- 2771 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2772 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2773 QbeGen.CopyOp(cv, q)
|
|
|
- 2774 ELSE
|
|
|
- 2775 QbeGen.LoadVar(n,
|
|
|
- 2776 cls = SymTab.ClReal,
|
|
|
- 2777 q)
|
|
|
- 2778 END
|
|
|
- 2779 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2780 OR (cls = SymTab.ClRecord)
|
|
|
- 2781 OR (cls = SymTab.ClClass)
|
|
|
- 2782 OR (cls = SymTab.ClStr)
|
|
|
- 2783 OR (cls = SymTab.ClUStr)
|
|
|
- 2784 OR (cls = SymTab.ClSet) THEN
|
|
|
- 2785 (* aggregate constant:
|
|
|
- 2786 its value IS the
|
|
|
- 2787 descriptor address *)
|
|
|
- 2788 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2789 QbeGen.CopyOp(cv, q)
|
|
|
- 2790 ELSE
|
|
|
- 2791 QbeGen.CopyOp("0", q)
|
|
|
- 2792 END
|
|
|
- 2793 ELSE
|
|
|
- 2794 IF t #
|
|
|
- 2795 SymTab.InvalidType THEN
|
|
|
- 2796 SemError(230)
|
|
|
- 2797 END;
|
|
|
- 2798 QbeGen.CopyOp("0", q)
|
|
|
- 2799 END
|
|
|
- 2800 END
|
|
|
- 2801 ELSIF (k = SymTab.KindVar)
|
|
|
- 2802 OR (k = SymTab.KindParam) THEN
|
|
|
- 2803 cls := SymTab.ClassOf(t);
|
|
|
- 2804 IF (cls # SymTab.ClInt)
|
|
|
- 2805 AND (cls # SymTab.ClBool)
|
|
|
- 2806 AND (cls # SymTab.ClChar)
|
|
|
- 2807 AND (cls # SymTab.ClUChar)
|
|
|
- 2808 AND (cls # SymTab.ClEnum)
|
|
|
- 2809 AND (cls # SymTab.ClReal)
|
|
|
- 2810 AND (cls # SymTab.ClPtr)
|
|
|
- 2811 AND (cls # SymTab.ClProc)
|
|
|
- 2812 AND (cls # SymTab.ClLong)
|
|
|
- 2813 AND (cls # SymTab.ClArray)
|
|
|
- 2814 AND (cls # SymTab.ClSet)
|
|
|
- 2815 AND (cls # SymTab.ClRecord)
|
|
|
- 2816 AND (cls # SymTab.ClUStr)
|
|
|
- 2817 AND (cls # SymTab.ClClass) THEN
|
|
|
- 2818 SemError(230);
|
|
|
- 2819 QbeGen.CopyOp("0", q)
|
|
|
- 2820 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2821 END
|
|
|
- 2822 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2823 IF k = SymTab.KindImport THEN
|
|
|
- 2824 SemError(230)
|
|
|
- 2825 ELSIF k =
|
|
|
- 2826 SymTab.KindProc THEN
|
|
|
- 2827 (* bare procedure name:
|
|
|
- 2828 a following ArgList
|
|
|
- 2829 makes it a call;
|
|
|
- 2830 otherwise Fact
|
|
|
- 2831 reports 230 *)
|
|
|
- 2832 ELSE
|
|
|
- 2833 IF k = SymTab.KindField THEN
|
|
|
- 2834 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2835 sfx := TRUE
|
|
|
- 2836 ELSE SemError(230);
|
|
|
- 2837 QbeGen.CopyOp("0", q)
|
|
|
- 2838 END
|
|
|
- 2839 END
|
|
|
- 2840 END
|
|
|
- 2841 END
|
|
|
- 2842 END; .)
|
|
|
- 2843 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2844 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 2845 { "[" Expr<it, iq>
|
|
|
- 2846 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2847 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2848 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2849 SymTab.ClArray THEN
|
|
|
- 2850 SemError(217);
|
|
|
- 2851 t := SymTab.InvalidType
|
|
|
- 2852 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2853 AND (SymTab.ClassOf(it) #
|
|
|
- 2854 SymTab.ClChar)
|
|
|
+ 2769 = SymTab.ClEnum)
|
|
|
+ 2770 OR (cls
|
|
|
+ 2771 = SymTab.ClLong)
|
|
|
+ 2772 OR (cls = SymTab.ClBool))
|
|
|
+ 2773 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2774 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2775 QbeGen.CopyOp(cv, q)
|
|
|
+ 2776 ELSE
|
|
|
+ 2777 QbeGen.LoadVar(n,
|
|
|
+ 2778 cls = SymTab.ClReal,
|
|
|
+ 2779 q)
|
|
|
+ 2780 END
|
|
|
+ 2781 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2782 OR (cls = SymTab.ClRecord)
|
|
|
+ 2783 OR (cls = SymTab.ClClass)
|
|
|
+ 2784 OR (cls = SymTab.ClStr)
|
|
|
+ 2785 OR (cls = SymTab.ClUStr)
|
|
|
+ 2786 OR (cls = SymTab.ClSet) THEN
|
|
|
+ 2787 (* aggregate constant:
|
|
|
+ 2788 its value IS the
|
|
|
+ 2789 descriptor address *)
|
|
|
+ 2790 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2791 QbeGen.CopyOp(cv, q)
|
|
|
+ 2792 ELSE
|
|
|
+ 2793 QbeGen.CopyOp("0", q)
|
|
|
+ 2794 END
|
|
|
+ 2795 ELSE
|
|
|
+ 2796 IF t #
|
|
|
+ 2797 SymTab.InvalidType THEN
|
|
|
+ 2798 SemError(230)
|
|
|
+ 2799 END;
|
|
|
+ 2800 QbeGen.CopyOp("0", q)
|
|
|
+ 2801 END
|
|
|
+ 2802 END
|
|
|
+ 2803 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2804 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2805 cls := SymTab.ClassOf(t);
|
|
|
+ 2806 IF (cls # SymTab.ClInt)
|
|
|
+ 2807 AND (cls # SymTab.ClBool)
|
|
|
+ 2808 AND (cls # SymTab.ClChar)
|
|
|
+ 2809 AND (cls # SymTab.ClUChar)
|
|
|
+ 2810 AND (cls # SymTab.ClEnum)
|
|
|
+ 2811 AND (cls # SymTab.ClReal)
|
|
|
+ 2812 AND (cls # SymTab.ClPtr)
|
|
|
+ 2813 AND (cls # SymTab.ClProc)
|
|
|
+ 2814 AND (cls # SymTab.ClLong)
|
|
|
+ 2815 AND (cls # SymTab.ClArray)
|
|
|
+ 2816 AND (cls # SymTab.ClSet)
|
|
|
+ 2817 AND (cls # SymTab.ClRecord)
|
|
|
+ 2818 AND (cls # SymTab.ClUStr)
|
|
|
+ 2819 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 2820 SemError(230);
|
|
|
+ 2821 QbeGen.CopyOp("0", q)
|
|
|
+ 2822 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2823 END
|
|
|
+ 2824 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2825 IF k = SymTab.KindImport THEN
|
|
|
+ 2826 SemError(230)
|
|
|
+ 2827 ELSIF k =
|
|
|
+ 2828 SymTab.KindProc THEN
|
|
|
+ 2829 (* bare procedure name:
|
|
|
+ 2830 a following ArgList
|
|
|
+ 2831 makes it a call;
|
|
|
+ 2832 otherwise Fact
|
|
|
+ 2833 reports 230 *)
|
|
|
+ 2834 ELSE
|
|
|
+ 2835 IF k = SymTab.KindField THEN
|
|
|
+ 2836 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2837 sfx := TRUE
|
|
|
+ 2838 ELSE SemError(230);
|
|
|
+ 2839 QbeGen.CopyOp("0", q)
|
|
|
+ 2840 END
|
|
|
+ 2841 END
|
|
|
+ 2842 END
|
|
|
+ 2843 END
|
|
|
+ 2844 END; .)
|
|
|
+ 2845 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2846 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 2847 { "[" Expr<it, iq>
|
|
|
+ 2848 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2849 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2850 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2851 SymTab.ClArray THEN
|
|
|
+ 2852 SemError(217);
|
|
|
+ 2853 t := SymTab.InvalidType
|
|
|
+ 2854 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
2855 AND (SymTab.ClassOf(it) #
|
|
|
- 2856 SymTab.ClEnum)
|
|
|
+ 2856 SymTab.ClChar)
|
|
|
2857 AND (SymTab.ClassOf(it) #
|
|
|
- 2858 SymTab.ClBool) THEN
|
|
|
- 2859 SemError(218);
|
|
|
- 2860 t := SymTab.InvalidType
|
|
|
- 2861 ELSE
|
|
|
- 2862 eT := SymTab.ArrayElem(t);
|
|
|
- 2863 t := eT; sfx := TRUE
|
|
|
- 2864 END; .)
|
|
|
- 2865 { "," Expr<it, iq>
|
|
|
- 2866 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2867 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2868 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2869 SymTab.ClArray THEN
|
|
|
- 2870 SemError(217);
|
|
|
- 2871 t := SymTab.InvalidType
|
|
|
- 2872 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2873 AND (SymTab.ClassOf(it) #
|
|
|
- 2874 SymTab.ClChar)
|
|
|
+ 2858 SymTab.ClEnum)
|
|
|
+ 2859 AND (SymTab.ClassOf(it) #
|
|
|
+ 2860 SymTab.ClBool) THEN
|
|
|
+ 2861 SemError(218);
|
|
|
+ 2862 t := SymTab.InvalidType
|
|
|
+ 2863 ELSE
|
|
|
+ 2864 eT := SymTab.ArrayElem(t);
|
|
|
+ 2865 t := eT; sfx := TRUE
|
|
|
+ 2866 END; .)
|
|
|
+ 2867 { "," Expr<it, iq>
|
|
|
+ 2868 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2869 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2870 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2871 SymTab.ClArray THEN
|
|
|
+ 2872 SemError(217);
|
|
|
+ 2873 t := SymTab.InvalidType
|
|
|
+ 2874 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
2875 AND (SymTab.ClassOf(it) #
|
|
|
- 2876 SymTab.ClEnum)
|
|
|
+ 2876 SymTab.ClChar)
|
|
|
2877 AND (SymTab.ClassOf(it) #
|
|
|
- 2878 SymTab.ClBool) THEN
|
|
|
- 2879 SemError(218);
|
|
|
- 2880 t := SymTab.InvalidType
|
|
|
- 2881 ELSE
|
|
|
- 2882 eT := SymTab.ArrayElem(t);
|
|
|
- 2883 t := eT; sfx := TRUE
|
|
|
- 2884 END; .) }
|
|
|
- 2885 "]"
|
|
|
- 2886 | "." GetIdent<fn>
|
|
|
- 2887 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2888 AST.SetOp(astSel, AST.SelField);
|
|
|
- 2889 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 2890 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 2891 (* qualified L.x: materialize
|
|
|
- 2892 the export, then load it *)
|
|
|
- 2893 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 2894 fn, mal) THEN
|
|
|
- 2895 SemError(201);
|
|
|
- 2896 t := SymTab.InvalidType;
|
|
|
- 2897 QbeGen.CopyOp("0", q)
|
|
|
- 2898 ELSE
|
|
|
- 2899 QbeGen.CopyOp(mal, qn);
|
|
|
- 2900 t := SymTab.SymType(mal);
|
|
|
- 2901 k := SymTab.SymKind(mal);
|
|
|
- 2902 sfx := FALSE;
|
|
|
- 2903 IF k = SymTab.KindProc THEN
|
|
|
- 2904 (* call: ArgList supplies
|
|
|
- 2905 the value *)
|
|
|
- 2906 QbeGen.CopyOp("0", q)
|
|
|
- 2907 END
|
|
|
- 2908 END
|
|
|
- 2909 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 2910 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2911 SymTab.ClRecord)
|
|
|
- 2912 AND (SymTab.ClassOf(t) #
|
|
|
- 2913 SymTab.ClClass) THEN
|
|
|
- 2914 SemError(215);
|
|
|
- 2915 t := SymTab.InvalidType
|
|
|
- 2916 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2917 SymTab.ClClass)
|
|
|
- 2918 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 2919 (* obj.Method: bind the
|
|
|
- 2920 method and pass obj as
|
|
|
- 2921 the hidden receiver; q
|
|
|
- 2922 already holds the
|
|
|
- 2923 object's address *)
|
|
|
- 2924 QbeGen.CopyOp(fn, n);
|
|
|
- 2925 QbeGen.CopyOp(fn, qn);
|
|
|
- 2926 methCls := t;
|
|
|
- 2927 k := SymTab.KindProc;
|
|
|
- 2928 t := SymTab.InvalidType
|
|
|
- 2929 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2930 fn) THEN
|
|
|
- 2931 SemError(216);
|
|
|
- 2932 t := SymTab.InvalidType
|
|
|
- 2933 ELSE
|
|
|
- 2934 t := SymTab.FieldType(t, fn);
|
|
|
- 2935 sfx := TRUE
|
|
|
- 2936 END; .)
|
|
|
- 2937 | "^"
|
|
|
- 2938 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2939 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2940 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2941 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2942 SymTab.ClPtr THEN
|
|
|
- 2943 SemError(219);
|
|
|
- 2944 t := SymTab.InvalidType
|
|
|
- 2945 ELSE
|
|
|
- 2946 bt := SymTab.PtrBase(t);
|
|
|
- 2947 IF bt = SymTab.InvalidType THEN
|
|
|
- 2948 ELSE
|
|
|
- 2949 t := bt;
|
|
|
- 2950 sfx := TRUE
|
|
|
- 2951 END
|
|
|
- 2952 END; .) } (. astCur := astDes; .) .
|
|
|
- 2953 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 2954 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 2955 (a value, or a descriptor address for aggregates); each component
|
|
|
- 2956 descends one level exactly like the Design components. *)
|
|
|
- 2957 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2958 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
- 2959 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
- 2960 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 2961 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 2962 QbeGen.QVal;
|
|
|
- 2963 lo, hi, fo: INTEGER;
|
|
|
- 2964 isOpen: BOOLEAN;
|
|
|
- 2965 fname: SymTab.Name;
|
|
|
- 2966 astWrap, astSel: AST.Node; .)
|
|
|
- 2967 = "[" Expr<it, iq>
|
|
|
- 2968 (. isM := FALSE;
|
|
|
- 2969 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2970 astWrap := AST.MakeNode(
|
|
|
- 2971 AST.NkDesignator);
|
|
|
- 2972 AST.SetChild(astWrap, 0, node);
|
|
|
- 2973 node := astWrap
|
|
|
- 2974 END;
|
|
|
- 2975 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2976 AST.MakeUn(AST.NkSelector,
|
|
|
- 2977 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2978 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2979 SymTab.ClArray THEN
|
|
|
- 2980 SemError(217);
|
|
|
- 2981 t := SymTab.InvalidType
|
|
|
- 2982 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2983 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
- 2984 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
- 2985 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
- 2986 SemError(218);
|
|
|
- 2987 t := SymTab.InvalidType
|
|
|
- 2988 ELSE
|
|
|
- 2989 eT := SymTab.ArrayElem(t);
|
|
|
- 2990 t := eT; sfx := TRUE
|
|
|
- 2991 END; .)
|
|
|
- 2992 "]"
|
|
|
- 2993 | "." GetIdent<fname>
|
|
|
- 2994 (. isM := FALSE;
|
|
|
- 2995 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2996 astWrap := AST.MakeNode(
|
|
|
- 2997 AST.NkDesignator);
|
|
|
- 2998 AST.SetChild(astWrap, 0, node);
|
|
|
- 2999 node := astWrap
|
|
|
- 3000 END;
|
|
|
- 3001 AST.SetChild(node, AST.NChild(node),
|
|
|
- 3002 AST.MakeUn(AST.NkSelector,
|
|
|
- 3003 AST.SelField,
|
|
|
- 3004 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 3005 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 3006 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3007 SymTab.ClRecord)
|
|
|
- 3008 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3009 SemError(215);
|
|
|
- 3010 t := SymTab.InvalidType
|
|
|
- 3011 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 3012 SymTab.ClClass)
|
|
|
- 3013 AND SymTab.MethodExists(t, fname) THEN
|
|
|
- 3014 (* a method on the call result:
|
|
|
- 3015 a following ArgList makes
|
|
|
- 3016 the call *)
|
|
|
- 3017 mname := fname;
|
|
|
- 3018 methCls := t; isM := TRUE;
|
|
|
- 3019 t := SymTab.InvalidType
|
|
|
- 3020 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 3021 fname) THEN
|
|
|
- 3022 SemError(216);
|
|
|
- 3023 t := SymTab.InvalidType
|
|
|
- 3024 ELSE
|
|
|
- 3025 t := SymTab.FieldType(t, fname);
|
|
|
- 3026 sfx := TRUE
|
|
|
- 3027 END; .)
|
|
|
- 3028 | "^" (. isM := FALSE;
|
|
|
- 3029 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3030 astWrap := AST.MakeNode(
|
|
|
- 3031 AST.NkDesignator);
|
|
|
- 3032 AST.SetChild(astWrap, 0, node);
|
|
|
- 3033 node := astWrap
|
|
|
- 3034 END;
|
|
|
- 3035 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 3036 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 3037 AST.SetChild(node,
|
|
|
- 3038 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 3039 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3040 SymTab.ClPtr THEN
|
|
|
- 3041 SemError(219);
|
|
|
- 3042 t := SymTab.InvalidType
|
|
|
- 3043 ELSE
|
|
|
- 3044 bt := SymTab.PtrBase(t);
|
|
|
- 3045 IF bt # SymTab.InvalidType THEN
|
|
|
- 3046 t := bt; sfx := TRUE
|
|
|
- 3047 END
|
|
|
- 3048 END; .) .
|
|
|
- 3049 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3050 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 3051 op: INTEGER;
|
|
|
- 3052 q2, qt, wl: QbeGen.QVal;
|
|
|
- 3053 astA, astB: AST.Node;
|
|
|
- 3054 astOp: INTEGER;
|
|
|
- 3055 astMade: BOOLEAN;
|
|
|
- 3056 isR: BOOLEAN; .)
|
|
|
- 3057 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 3058 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 3059 (. astB := astCur; astMade := TRUE;
|
|
|
- 3060 astOp := AST.OpEq;
|
|
|
- 3061 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 3062 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 3063 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 3064 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 3065 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 3066 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 3067 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 3068 END;
|
|
|
- 3069 IF op = SymTab.OpIn THEN
|
|
|
- 3070 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 3071 IF (t = SymTab.InvalidType)
|
|
|
- 3072 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3073 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3074 ELSE
|
|
|
- 3075 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3076 END
|
|
|
- 3077 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 3078 QbeGen.CopyOp("0", q)
|
|
|
- 3079 END
|
|
|
- 3080 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 3081 IF (t = SymTab.InvalidType)
|
|
|
- 3082 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3083 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3084 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 3085 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 3086 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 3087 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 3088 SemError(213); t := SymTab.InvalidType;
|
|
|
- 3089 QbeGen.CopyOp("0", q)
|
|
|
- 3090 ELSE
|
|
|
- 3091 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3092 END
|
|
|
- 3093 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3094 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3095 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3096 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 3097 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 3098 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 3099 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 3100 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 3101 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3102 ELSE
|
|
|
- 3103 t := SymTab.BoolType();
|
|
|
- 3104 QbeGen.CopyOp("@", q)
|
|
|
- 3105 END
|
|
|
- 3106 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 3107 QbeGen.CopyOp("0", q)
|
|
|
- 3108 END;
|
|
|
- 3109 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 3110 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
- 3111 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3112 Rel<VAR op: INTEGER>
|
|
|
- 3113 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 3114 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 3115 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 3116 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 3117 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 3118 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 3119 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 3120 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3121 (. VAR t2, res2, lt, rt:
|
|
|
- 3122 SymTab.TypeIndex;
|
|
|
- 3123 op: INTEGER;
|
|
|
- 3124 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 3125 QbeGen.QVal;
|
|
|
- 3126 neg, isR, isL, folded:
|
|
|
- 3127 BOOLEAN;
|
|
|
- 3128 fok: BOOLEAN;
|
|
|
- 3129 lw, rw, mw: CARDINAL;
|
|
|
- 3130 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3131 astA, astB: AST.Node;
|
|
|
- 3132 astSign, astOp: INTEGER; .)
|
|
|
- 3133 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 3134 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 3135 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 3136 Term<t, q> (. astA := astCur;
|
|
|
- 3137 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
- 3138 QbeGen.NegFold(q, q)
|
|
|
- 3139 END;
|
|
|
- 3140 IF astSign < 0 THEN
|
|
|
- 3141 astCur := AST.MakeUn(
|
|
|
- 3142 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 3143 astA := astCur
|
|
|
- 3144 END; .)
|
|
|
- 3145 { AddOp<op>
|
|
|
- 3146 Term<t2, q2> (. astB := astCur; .)
|
|
|
- 3147 (. astOp := AST.OpAdd;
|
|
|
- 3148 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 3149 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 3150 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3151 astCur := astA;
|
|
|
- 3152 IF op = SymTab.OpOr THEN
|
|
|
- 3153 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 3154 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3155 t := SymTab.BoolType()
|
|
|
- 3156 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3157 IF t # SymTab.InvalidType THEN
|
|
|
- 3158 QbeGen.CopyOp("@", q)
|
|
|
- 3159 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3160 END
|
|
|
- 3161 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3162 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 3163 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3164 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 3165 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 3166 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 3167 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3168 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 3169 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 3170 1-codepoint UString; the result is a descriptor in the
|
|
|
- 3171 shim's concat buffer. Work on copies so neither
|
|
|
- 3172 operand is clobbered. *)
|
|
|
- 3173 t := SymTab.NewUStr();
|
|
|
- 3174 QbeGen.CopyOp("@", q)
|
|
|
- 3175 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3176 AND (SymTab.StrCompat(t, t2)
|
|
|
- 3177 OR (SymTab.IsStrType(t)
|
|
|
- 3178 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 3179 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 3180 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 3181 (* string concatenation; a CHAR operand becomes a
|
|
|
- 3182 1-character string literal. When both operands are
|
|
|
- 3183 constants, fold to a single string literal so a
|
|
|
- 3184 constructor element stays compile-time. *)
|
|
|
- 3185 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 3186 qt, fok);
|
|
|
- 3187 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
- 3188 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3189 END;
|
|
|
- 3190 t := SymTab.NewStr()
|
|
|
- 3191 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3192 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3193 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3194 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3195 mw := lw;
|
|
|
- 3196 IF rw > mw THEN mw := rw END;
|
|
|
- 3197 t := SymTab.NewSet(
|
|
|
- 3198 SymTab.NewSubR(0,
|
|
|
- 3199 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3200 QbeGen.CopyOp("@", q)
|
|
|
- 3201 ELSE
|
|
|
- 3202 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 3203 lt := t; rt := t2; t := res2
|
|
|
- 3204 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3205 IF t # SymTab.InvalidType THEN
|
|
|
- 3206 isL := SymTab.IsLongFamily(t);
|
|
|
- 3207 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3208 folded := FALSE;
|
|
|
- 3209 IF (NOT isL) AND (NOT isR)
|
|
|
- 3210 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3211 IF op = SymTab.OpAdd THEN
|
|
|
- 3212 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 3213 ELSE
|
|
|
- 3214 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 3215 END
|
|
|
- 3216 END;
|
|
|
- 3217 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3218 ELSE
|
|
|
- 3219 QbeGen.CopyOp("@", q)
|
|
|
- 3220 END
|
|
|
- 3221 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3222 END
|
|
|
- 3223 END; .) }
|
|
|
- 3224 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3225 AddOp<VAR op: INTEGER>
|
|
|
- 3226 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 3227 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 3228 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 3229 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3230 (. VAR t2, res2, lt, rt:
|
|
|
- 3231 SymTab.TypeIndex;
|
|
|
- 3232 op: INTEGER;
|
|
|
- 3233 q2, qt, wq, qf:
|
|
|
- 3234 QbeGen.QVal;
|
|
|
- 3235 isR, isL, folded: BOOLEAN;
|
|
|
- 3236 lw, rw, mw: CARDINAL;
|
|
|
- 3237 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3238 astA, astB: AST.Node;
|
|
|
- 3239 astOp: INTEGER; .)
|
|
|
- 3240 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
- 3241 Fact<t2, q2> (. astB := astCur; .)
|
|
|
- 3242 (. astOp := AST.OpMul;
|
|
|
- 3243 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 3244 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 3245 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 3246 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 3247 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3248 astCur := astA;
|
|
|
- 3249 IF op = SymTab.OpAnd THEN
|
|
|
- 3250 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 3251 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3252 t := SymTab.BoolType()
|
|
|
- 3253 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3254 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
- 3255 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3256 END
|
|
|
- 3257 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3258 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3259 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3260 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3261 mw := lw;
|
|
|
- 3262 IF rw > mw THEN mw := rw END;
|
|
|
- 3263 t := SymTab.NewSet(
|
|
|
- 3264 SymTab.NewSubR(0,
|
|
|
- 3265 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3266 QbeGen.CopyOp("@", q)
|
|
|
- 3267 ELSE
|
|
|
- 3268 IF SymTab.ArithCheck(t, t2,
|
|
|
- 3269 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 3270 res2) THEN
|
|
|
- 3271 lt := t; rt := t2; t := res2
|
|
|
- 3272 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3273 IF t # SymTab.InvalidType THEN
|
|
|
- 3274 isL := SymTab.IsLongFamily(t);
|
|
|
- 3275 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3276 folded := FALSE;
|
|
|
- 3277 IF (NOT isL) AND (NOT isR)
|
|
|
- 3278 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3279 IF op = SymTab.OpTimes THEN
|
|
|
- 3280 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 3281 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 3282 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 3283 ELSIF op = SymTab.OpMod THEN
|
|
|
- 3284 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 3285 END
|
|
|
- 3286 END;
|
|
|
- 3287 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3288 ELSE
|
|
|
- 3289 QbeGen.CopyOp("@", q)
|
|
|
- 3290 END
|
|
|
- 3291 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3292 END
|
|
|
- 3293 END; .) }
|
|
|
- 3294 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3295 MulOp<VAR op: INTEGER>
|
|
|
- 3296 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 3297 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 3298 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 3299 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 3300 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 3301 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3302 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 3303 et, dt, t2, st, ct2, et2:
|
|
|
- 3304 SymTab.TypeIndex;
|
|
|
- 3305 dk: INTEGER;
|
|
|
- 3306 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 3307 QbeGen.QVal;
|
|
|
- 3308 qn, vn: SymTab.Name;
|
|
|
- 3309 vt: SymTab.TypeIndex;
|
|
|
- 3310 c1, c2: INTEGER;
|
|
|
- 3311 lo, hi: INTEGER;
|
|
|
- 3312 isMax: BOOLEAN;
|
|
|
- 3313 called, isHigh, sfx, isCh,
|
|
|
- 3314 isU, uok, isStr: BOOLEAN;
|
|
|
- 3315 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 3316 astD: AST.Node;
|
|
|
- 3317 astCall: BOOLEAN;
|
|
|
- 3318 astNode, astNot: AST.Node;
|
|
|
- 3319 j: CARDINAL;
|
|
|
- 3320 astArg2: AST.Node;
|
|
|
- 3321 astBrace: AST.Node;
|
|
|
- 3322 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 3323 isConvF: BOOLEAN; .)
|
|
|
- 3324 = (. astIsLit := FALSE; .)
|
|
|
- 3325 ( integer (. LexString(s);
|
|
|
- 3326 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
- 3327 t := SymTab.IntType(); .)
|
|
|
- 3328 | charConst (. LexString(s);
|
|
|
- 3329 QbeGen.NormLit(s, q, isCh);
|
|
|
- 3330 astIsLit := TRUE;
|
|
|
- 3331 astCur := AST.MakeLeaf(
|
|
|
- 3332 AST.NkCharLit, s);
|
|
|
- 3333 t := SymTab.CharType(); .)
|
|
|
- 3334 | real (. LexString(s);
|
|
|
- 3335 QbeGen.NormReal(s, q);
|
|
|
- 3336 astIsLit := TRUE;
|
|
|
- 3337 astCur := AST.MakeLeaf(
|
|
|
- 3338 AST.NkRealLit, s);
|
|
|
- 3339 t := SymTab.RealType(); .)
|
|
|
- 3340 | string (. LexString(s);
|
|
|
- 3341 astIsLit := TRUE;
|
|
|
- 3342 astCur := AST.MakeLeaf(
|
|
|
- 3343 AST.NkStrLit, s);
|
|
|
- 3344 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3345 t := SymTab.CharType();
|
|
|
- 3346 QbeGen.IntStr(
|
|
|
- 3347 QbeGen.CharVal(s), q)
|
|
|
- 3348 ELSE t := SymTab.NewStr();
|
|
|
- 3349 QbeGen.DeclStr(s, q);
|
|
|
- 3350 (* a literal's value IS its
|
|
|
- 3351 static descriptor address *)
|
|
|
- 3352 END; .)
|
|
|
- 3353 | ustring (. LexString(s);
|
|
|
- 3354 astIsLit := TRUE;
|
|
|
- 3355 astCur := AST.MakeLeaf(
|
|
|
- 3356 AST.NkStrLit, s);
|
|
|
- 3357 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 3358 uok);
|
|
|
- 3359 IF NOT uok THEN
|
|
|
- 3360 SemError(234);
|
|
|
- 3361 t := SymTab.InvalidType
|
|
|
- 3362 ELSIF isU THEN
|
|
|
- 3363 t := SymTab.UCharType();
|
|
|
- 3364 QbeGen.IntStr(ucp, q)
|
|
|
- 3365 ELSE
|
|
|
- 3366 t := SymTab.NewUStr();
|
|
|
- 3367 END; .)
|
|
|
- 3368 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 3369 astNArgs := 0; called := FALSE;
|
|
|
- 3370 t := dt;
|
|
|
- 3371 IF dk = SymTab.KindConst THEN
|
|
|
- 3372 QbeGen.CopyOp(qd, q)
|
|
|
- 3373 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3374 END; .)
|
|
|
- 3375 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 3376 astBrace := astCur; .) ]
|
|
|
- 3377 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3378 (. astCall := TRUE;
|
|
|
- 3379 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
- 3380 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
- 3381 (* T(x): emit as the VAL builtin so Lower's
|
|
|
- 3382 conversion rules apply unchanged *)
|
|
|
- 3383 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3384 AST.SetChild(astNode, 0,
|
|
|
- 3385 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3386 AST.SetChild(astNode, 1,
|
|
|
- 3387 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
- 3388 IF astNArgs = 1 THEN
|
|
|
- 3389 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
- 3390 END;
|
|
|
- 3391 isConvF := TRUE
|
|
|
- 3392 ELSE astNode := AstCallNode(astD)
|
|
|
- 3393 END;
|
|
|
- 3394 astRes := astNode;
|
|
|
- 3395 t := ct2;
|
|
|
- 3396 QbeGen.CopyOp(q2, q);
|
|
|
- 3397 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
- 3398 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
- 3399 QbeGen.CopyOp(convQ, q)
|
|
|
- 3400 END;
|
|
|
- 3401 sfx := FALSE; .)
|
|
|
- 3402 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
- 3403 [ (. astNArgs := 0; .)
|
|
|
- 3404 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3405 (. astNode := AstCallNode(astRes);
|
|
|
- 3406 astRes := astNode;
|
|
|
- 3407 t := ct2;
|
|
|
- 3408 QbeGen.CopyOp(q2, q);
|
|
|
- 3409 sfx := FALSE; .) ] }
|
|
|
- 3410 (. IF sfx THEN
|
|
|
- 3411 IF t = SymTab.InvalidType THEN
|
|
|
- 3412 QbeGen.CopyOp("0", q)
|
|
|
- 3413 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3414 SymTab.ClRecord)
|
|
|
- 3415 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 3416 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 3417 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3418 QbeGen.CopyOp("@", q)
|
|
|
- 3419 END
|
|
|
- 3420 END; .) ]
|
|
|
- 3421 (. IF called THEN
|
|
|
- 3422 astCur := astRes
|
|
|
- 3423 ELSIF astCall THEN
|
|
|
- 3424 astCur := astBrace
|
|
|
- 3425 ELSE astCur := astD
|
|
|
- 3426 END;
|
|
|
- 3427 astIsLit := TRUE;
|
|
|
- 3428 IF NOT called
|
|
|
- 3429 AND (dk = SymTab.KindProc) THEN
|
|
|
- 3430 (* bare zero-arg function
|
|
|
- 3431 call (parentheses may be
|
|
|
- 3432 omitted); a proper or
|
|
|
- 3433 parameterised proc here
|
|
|
- 3434 is 230 *)
|
|
|
- 3435 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 3436 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
- 3437 t := SymTab.ProcRes(qn);
|
|
|
- 3438 QbeGen.CopyOp("@", q);
|
|
|
- 3439 astCur := AST.MakeNode(AST.NkCall);
|
|
|
- 3440 AST.SetChild(astCur, 0, astD)
|
|
|
- 3441 ELSE
|
|
|
- 3442 t := SymTab.ProcTypeOf(qn);
|
|
|
- 3443 QbeGen.CopyOp("@", q)
|
|
|
- 3444 END
|
|
|
- 3445 END; .)
|
|
|
- 3446 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 3447 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 3448 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 3449 isU := FALSE; .)
|
|
|
- 3450 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3451 isStr := TRUE;
|
|
|
- 3452 isU := FALSE;
|
|
|
- 3453 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3454 dt := SymTab.CharType();
|
|
|
- 3455 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 3456 qd)
|
|
|
- 3457 ELSE
|
|
|
- 3458 dt := SymTab.NewStr();
|
|
|
- 3459 QbeGen.DeclStr(s, qd);
|
|
|
- 3460 END;
|
|
|
- 3461 dk := -1;
|
|
|
- 3462 qn[0] := CHR(0); .)
|
|
|
- 3463 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3464 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 3465 uok);
|
|
|
- 3466 isStr := FALSE;
|
|
|
- 3467 IF NOT uok THEN
|
|
|
- 3468 SemError(234);
|
|
|
- 3469 dt := SymTab.InvalidType
|
|
|
- 3470 ELSIF isU THEN
|
|
|
- 3471 (* one codepoint: a UCHAR;
|
|
|
- 3472 LEN is 1, HIGH is 0 *)
|
|
|
- 3473 dt := SymTab.UCharType();
|
|
|
- 3474 QbeGen.IntStr(ucp, qd)
|
|
|
- 3475 ELSE
|
|
|
- 3476 dt := SymTab.NewUStr();
|
|
|
- 3477 END;
|
|
|
- 3478 dk := -1;
|
|
|
- 3479 qn[0] := CHR(0); .) )
|
|
|
- 3480 ")"
|
|
|
- 3481 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3482 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 3483 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 3484 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3485 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 3486 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3487 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3488 IF (dt # SymTab.InvalidType)
|
|
|
- 3489 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 3490 (* UString: the count is
|
|
|
- 3491 the descriptor header *)
|
|
|
- 3492 t := SymTab.IntType();
|
|
|
- 3493 QbeGen.CopyOp("@", q)
|
|
|
- 3494 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 3495 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 3496 (* single UCHAR codepoint *)
|
|
|
- 3497 IF isHigh THEN
|
|
|
- 3498 QbeGen.CopyOp("0", qr)
|
|
|
- 3499 ELSE
|
|
|
- 3500 QbeGen.CopyOp("1", qr)
|
|
|
- 3501 END;
|
|
|
- 3502 t := SymTab.IntType();
|
|
|
- 3503 QbeGen.CopyOp(qr, q)
|
|
|
- 3504 ELSIF isStr THEN
|
|
|
- 3505 (* fold: content length at
|
|
|
- 3506 compile time *)
|
|
|
- 3507 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3508 c1 := 1
|
|
|
- 3509 ELSE
|
|
|
- 3510 c1 :=
|
|
|
- 3511 SymTab.StrLen(s) - 2
|
|
|
- 3512 END;
|
|
|
- 3513 IF isHigh THEN
|
|
|
- 3514 DEC(c1)
|
|
|
- 3515 END;
|
|
|
- 3516 QbeGen.IntStr(c1, qr);
|
|
|
- 3517 t := SymTab.IntType();
|
|
|
- 3518 QbeGen.CopyOp(qr, q)
|
|
|
- 3519 ELSIF dt = SymTab.InvalidType THEN
|
|
|
- 3520 t := SymTab.InvalidType;
|
|
|
- 3521 QbeGen.CopyOp("0", q)
|
|
|
- 3522 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 3523 SymTab.ClArray THEN
|
|
|
- 3524 SemError(217);
|
|
|
- 3525 t := SymTab.InvalidType;
|
|
|
- 3526 QbeGen.CopyOp("0", q)
|
|
|
- 3527 ELSE
|
|
|
- 3528 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3529 t := SymTab.IntType();
|
|
|
- 3530 QbeGen.CopyOp("@", q)
|
|
|
- 3531 ELSE
|
|
|
- 3532 IF isHigh THEN
|
|
|
- 3533 QbeGen.IntStr(
|
|
|
- 3534 SymTab.ArrayHi(dt), qr)
|
|
|
- 3535 ELSE
|
|
|
- 3536 QbeGen.IntStr(VAL(
|
|
|
- 3537 INTEGER,
|
|
|
- 3538 SymTab.ArrayLen(dt)),
|
|
|
- 3539 qr)
|
|
|
- 3540 END;
|
|
|
- 3541 t := SymTab.IntType();
|
|
|
- 3542 QbeGen.CopyOp(qr, q)
|
|
|
- 3543 END
|
|
|
- 3544 END; .)
|
|
|
- 3545 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3546 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3547 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 3548 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3549 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3550 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3551 t := SymTab.InvalidType;
|
|
|
- 3552 QbeGen.CopyOp("0", q)
|
|
|
- 3553 ELSE
|
|
|
- 3554 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 3555 SymTab.ObjectSize(dt)), q);
|
|
|
- 3556 t := SymTab.IntType()
|
|
|
- 3557 END; .)
|
|
|
- 3558 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 3559 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 3560 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 3561 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3562 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3563 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 3564 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3565 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 3566 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3567 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3568 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3569 (* set shift/rotate: isMax
|
|
|
- 3570 doubles as "rotate" *)
|
|
|
- 3571 IF (et # SymTab.InvalidType)
|
|
|
- 3572 AND (SymTab.ClassOf(et) =
|
|
|
- 3573 SymTab.ClSet) THEN
|
|
|
- 3574 t := et;
|
|
|
- 3575 QbeGen.CopyOp("@", q)
|
|
|
- 3576 ELSE SemError(230);
|
|
|
- 3577 t := SymTab.InvalidType;
|
|
|
- 3578 QbeGen.CopyOp("0", q)
|
|
|
- 3579 END; .)
|
|
|
- 3580 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 3581 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 3582 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3583 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3584 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3585 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 3586 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3587 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 3588 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3589 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3590 IF (dt # SymTab.InvalidType)
|
|
|
- 3591 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 3592 (* REAL/LONGREAL: the
|
|
|
- 3593 implementation bounds *)
|
|
|
- 3594 IF isMax THEN
|
|
|
- 3595 QbeGen.NormReal(
|
|
|
- 3596 "3.402823e38", q)
|
|
|
- 3597 ELSE QbeGen.NormReal(
|
|
|
- 3598 "-3.402823e38", q)
|
|
|
- 3599 END;
|
|
|
- 3600 t := SymTab.RealType()
|
|
|
- 3601 ELSIF (dt #
|
|
|
- 3602 SymTab.InvalidType)
|
|
|
- 3603 AND (SymTab.ClassOf(dt) =
|
|
|
- 3604 SymTab.ClLong) THEN
|
|
|
- 3605 IF isMax THEN
|
|
|
- 3606 QbeGen.CopyOp(
|
|
|
- 3607 "9223372036854775807", q)
|
|
|
- 3608 ELSE QbeGen.CopyOp(
|
|
|
- 3609 "-9223372036854775808", q)
|
|
|
- 3610 END;
|
|
|
- 3611 t := SymTab.LongType()
|
|
|
- 3612 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 3613 hi) THEN
|
|
|
- 3614 IF isMax THEN
|
|
|
- 3615 QbeGen.IntStr(hi, q)
|
|
|
- 3616 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 3617 END;
|
|
|
- 3618 t := SymTab.IntType()
|
|
|
- 3619 ELSE SemError(230);
|
|
|
- 3620 t := SymTab.InvalidType;
|
|
|
- 3621 QbeGen.CopyOp("0", q)
|
|
|
- 3622 END; .)
|
|
|
- 3623 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3624 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3625 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 3626 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3627 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3628 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3629 t := SymTab.InvalidType;
|
|
|
- 3630 QbeGen.CopyOp("0", q)
|
|
|
- 3631 ELSE
|
|
|
- 3632 IF sfx
|
|
|
- 3633 OR (dk = SymTab.KindVar)
|
|
|
- 3634 OR (dk = SymTab.KindParam) THEN
|
|
|
- 3635 QbeGen.CopyOp("@", q)
|
|
|
- 3636 ELSE SemError(230);
|
|
|
- 3637 QbeGen.CopyOp("0", q)
|
|
|
- 3638 END;
|
|
|
- 3639 t := SymTab.AddrType()
|
|
|
- 3640 END; .)
|
|
|
- 3641 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 3642 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3643 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 3644 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3645 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3646 (. IF (et # SymTab.InvalidType)
|
|
|
- 3647 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3648 SemError(211) END;
|
|
|
- 3649 t := SymTab.CharType(); .)
|
|
|
- 3650 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
- 3651 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3652 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 3653 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3654 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3655 (. IF et # SymTab.InvalidType THEN
|
|
|
- 3656 IF (SymTab.ClassOf(et) #
|
|
|
- 3657 SymTab.ClChar)
|
|
|
- 3658 AND (SymTab.ClassOf(et) #
|
|
|
- 3659 SymTab.ClBool)
|
|
|
+ 2878 SymTab.ClEnum)
|
|
|
+ 2879 AND (SymTab.ClassOf(it) #
|
|
|
+ 2880 SymTab.ClBool) THEN
|
|
|
+ 2881 SemError(218);
|
|
|
+ 2882 t := SymTab.InvalidType
|
|
|
+ 2883 ELSE
|
|
|
+ 2884 eT := SymTab.ArrayElem(t);
|
|
|
+ 2885 t := eT; sfx := TRUE
|
|
|
+ 2886 END; .) }
|
|
|
+ 2887 "]"
|
|
|
+ 2888 | "." GetIdent<fn>
|
|
|
+ 2889 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2890 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 2891 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 2892 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 2893 (* qualified L.x: materialize
|
|
|
+ 2894 the export, then load it *)
|
|
|
+ 2895 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 2896 fn, mal) THEN
|
|
|
+ 2897 SemError(201);
|
|
|
+ 2898 t := SymTab.InvalidType;
|
|
|
+ 2899 QbeGen.CopyOp("0", q)
|
|
|
+ 2900 ELSE
|
|
|
+ 2901 QbeGen.CopyOp(mal, qn);
|
|
|
+ 2902 t := SymTab.SymType(mal);
|
|
|
+ 2903 k := SymTab.SymKind(mal);
|
|
|
+ 2904 sfx := FALSE;
|
|
|
+ 2905 IF k = SymTab.KindProc THEN
|
|
|
+ 2906 (* call: ArgList supplies
|
|
|
+ 2907 the value *)
|
|
|
+ 2908 QbeGen.CopyOp("0", q)
|
|
|
+ 2909 END
|
|
|
+ 2910 END
|
|
|
+ 2911 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 2912 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2913 SymTab.ClRecord)
|
|
|
+ 2914 AND (SymTab.ClassOf(t) #
|
|
|
+ 2915 SymTab.ClClass) THEN
|
|
|
+ 2916 SemError(215);
|
|
|
+ 2917 t := SymTab.InvalidType
|
|
|
+ 2918 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2919 SymTab.ClClass)
|
|
|
+ 2920 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 2921 (* obj.Method: bind the
|
|
|
+ 2922 method and pass obj as
|
|
|
+ 2923 the hidden receiver; q
|
|
|
+ 2924 already holds the
|
|
|
+ 2925 object's address *)
|
|
|
+ 2926 QbeGen.CopyOp(fn, n);
|
|
|
+ 2927 QbeGen.CopyOp(fn, qn);
|
|
|
+ 2928 methCls := t;
|
|
|
+ 2929 k := SymTab.KindProc;
|
|
|
+ 2930 t := SymTab.InvalidType
|
|
|
+ 2931 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2932 fn) THEN
|
|
|
+ 2933 SemError(216);
|
|
|
+ 2934 t := SymTab.InvalidType
|
|
|
+ 2935 ELSE
|
|
|
+ 2936 t := SymTab.FieldType(t, fn);
|
|
|
+ 2937 sfx := TRUE
|
|
|
+ 2938 END; .)
|
|
|
+ 2939 | "^"
|
|
|
+ 2940 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2941 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2942 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2943 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2944 SymTab.ClPtr THEN
|
|
|
+ 2945 SemError(219);
|
|
|
+ 2946 t := SymTab.InvalidType
|
|
|
+ 2947 ELSE
|
|
|
+ 2948 bt := SymTab.PtrBase(t);
|
|
|
+ 2949 IF bt = SymTab.InvalidType THEN
|
|
|
+ 2950 ELSE
|
|
|
+ 2951 t := bt;
|
|
|
+ 2952 sfx := TRUE
|
|
|
+ 2953 END
|
|
|
+ 2954 END; .) } (. astCur := astDes; .) .
|
|
|
+ 2955 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 2956 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 2957 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 2958 descends one level exactly like the Design components. *)
|
|
|
+ 2959 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2960 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
+ 2961 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
+ 2962 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 2963 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 2964 QbeGen.QVal;
|
|
|
+ 2965 lo, hi, fo: INTEGER;
|
|
|
+ 2966 isOpen: BOOLEAN;
|
|
|
+ 2967 fname: SymTab.Name;
|
|
|
+ 2968 astWrap, astSel: AST.Node; .)
|
|
|
+ 2969 = "[" Expr<it, iq>
|
|
|
+ 2970 (. isM := FALSE;
|
|
|
+ 2971 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2972 astWrap := AST.MakeNode(
|
|
|
+ 2973 AST.NkDesignator);
|
|
|
+ 2974 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2975 node := astWrap
|
|
|
+ 2976 END;
|
|
|
+ 2977 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2978 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2979 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2980 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2981 SymTab.ClArray THEN
|
|
|
+ 2982 SemError(217);
|
|
|
+ 2983 t := SymTab.InvalidType
|
|
|
+ 2984 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2985 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 2986 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
+ 2987 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
+ 2988 SemError(218);
|
|
|
+ 2989 t := SymTab.InvalidType
|
|
|
+ 2990 ELSE
|
|
|
+ 2991 eT := SymTab.ArrayElem(t);
|
|
|
+ 2992 t := eT; sfx := TRUE
|
|
|
+ 2993 END; .)
|
|
|
+ 2994 "]"
|
|
|
+ 2995 | "." GetIdent<fname>
|
|
|
+ 2996 (. isM := FALSE;
|
|
|
+ 2997 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2998 astWrap := AST.MakeNode(
|
|
|
+ 2999 AST.NkDesignator);
|
|
|
+ 3000 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3001 node := astWrap
|
|
|
+ 3002 END;
|
|
|
+ 3003 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 3004 AST.MakeUn(AST.NkSelector,
|
|
|
+ 3005 AST.SelField,
|
|
|
+ 3006 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 3007 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 3008 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3009 SymTab.ClRecord)
|
|
|
+ 3010 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3011 SemError(215);
|
|
|
+ 3012 t := SymTab.InvalidType
|
|
|
+ 3013 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 3014 SymTab.ClClass)
|
|
|
+ 3015 AND SymTab.MethodExists(t, fname) THEN
|
|
|
+ 3016 (* a method on the call result:
|
|
|
+ 3017 a following ArgList makes
|
|
|
+ 3018 the call *)
|
|
|
+ 3019 mname := fname;
|
|
|
+ 3020 methCls := t; isM := TRUE;
|
|
|
+ 3021 t := SymTab.InvalidType
|
|
|
+ 3022 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 3023 fname) THEN
|
|
|
+ 3024 SemError(216);
|
|
|
+ 3025 t := SymTab.InvalidType
|
|
|
+ 3026 ELSE
|
|
|
+ 3027 t := SymTab.FieldType(t, fname);
|
|
|
+ 3028 sfx := TRUE
|
|
|
+ 3029 END; .)
|
|
|
+ 3030 | "^" (. isM := FALSE;
|
|
|
+ 3031 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3032 astWrap := AST.MakeNode(
|
|
|
+ 3033 AST.NkDesignator);
|
|
|
+ 3034 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3035 node := astWrap
|
|
|
+ 3036 END;
|
|
|
+ 3037 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 3038 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 3039 AST.SetChild(node,
|
|
|
+ 3040 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 3041 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3042 SymTab.ClPtr THEN
|
|
|
+ 3043 SemError(219);
|
|
|
+ 3044 t := SymTab.InvalidType
|
|
|
+ 3045 ELSE
|
|
|
+ 3046 bt := SymTab.PtrBase(t);
|
|
|
+ 3047 IF bt # SymTab.InvalidType THEN
|
|
|
+ 3048 t := bt; sfx := TRUE
|
|
|
+ 3049 END
|
|
|
+ 3050 END; .) .
|
|
|
+ 3051 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3052 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 3053 op: INTEGER;
|
|
|
+ 3054 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 3055 astA, astB: AST.Node;
|
|
|
+ 3056 astOp: INTEGER;
|
|
|
+ 3057 astMade: BOOLEAN;
|
|
|
+ 3058 isR: BOOLEAN; .)
|
|
|
+ 3059 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 3060 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 3061 (. astB := astCur; astMade := TRUE;
|
|
|
+ 3062 astOp := AST.OpEq;
|
|
|
+ 3063 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 3064 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 3065 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 3066 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 3067 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 3068 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 3069 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 3070 END;
|
|
|
+ 3071 IF op = SymTab.OpIn THEN
|
|
|
+ 3072 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 3073 IF (t = SymTab.InvalidType)
|
|
|
+ 3074 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3075 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3076 ELSE
|
|
|
+ 3077 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3078 END
|
|
|
+ 3079 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 3080 QbeGen.CopyOp("0", q)
|
|
|
+ 3081 END
|
|
|
+ 3082 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 3083 IF (t = SymTab.InvalidType)
|
|
|
+ 3084 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3085 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3086 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 3087 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 3088 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 3089 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 3090 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3091 QbeGen.CopyOp("0", q)
|
|
|
+ 3092 ELSE
|
|
|
+ 3093 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3094 END
|
|
|
+ 3095 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3096 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3097 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3098 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 3099 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 3100 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 3101 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 3102 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 3103 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3104 ELSE
|
|
|
+ 3105 t := SymTab.BoolType();
|
|
|
+ 3106 QbeGen.CopyOp("@", q)
|
|
|
+ 3107 END
|
|
|
+ 3108 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3109 QbeGen.CopyOp("0", q)
|
|
|
+ 3110 END;
|
|
|
+ 3111 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 3112 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
+ 3113 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3114 Rel<VAR op: INTEGER>
|
|
|
+ 3115 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 3116 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 3117 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 3118 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 3119 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 3120 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 3121 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 3122 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3123 (. VAR t2, res2, lt, rt:
|
|
|
+ 3124 SymTab.TypeIndex;
|
|
|
+ 3125 op: INTEGER;
|
|
|
+ 3126 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 3127 QbeGen.QVal;
|
|
|
+ 3128 neg, isR, isL, folded:
|
|
|
+ 3129 BOOLEAN;
|
|
|
+ 3130 fok: BOOLEAN;
|
|
|
+ 3131 lw, rw, mw: CARDINAL;
|
|
|
+ 3132 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3133 astA, astB: AST.Node;
|
|
|
+ 3134 astSign, astOp: INTEGER; .)
|
|
|
+ 3135 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 3136 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 3137 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 3138 Term<t, q> (. astA := astCur;
|
|
|
+ 3139 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
+ 3140 QbeGen.NegFold(q, q)
|
|
|
+ 3141 END;
|
|
|
+ 3142 IF astSign < 0 THEN
|
|
|
+ 3143 astCur := AST.MakeUn(
|
|
|
+ 3144 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 3145 astA := astCur
|
|
|
+ 3146 END; .)
|
|
|
+ 3147 { AddOp<op>
|
|
|
+ 3148 Term<t2, q2> (. astB := astCur; .)
|
|
|
+ 3149 (. astOp := AST.OpAdd;
|
|
|
+ 3150 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 3151 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 3152 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3153 astCur := astA;
|
|
|
+ 3154 IF op = SymTab.OpOr THEN
|
|
|
+ 3155 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 3156 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3157 t := SymTab.BoolType()
|
|
|
+ 3158 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3159 IF t # SymTab.InvalidType THEN
|
|
|
+ 3160 QbeGen.CopyOp("@", q)
|
|
|
+ 3161 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3162 END
|
|
|
+ 3163 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3164 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 3165 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3166 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 3167 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 3168 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 3169 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3170 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 3171 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 3172 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 3173 shim's concat buffer. Work on copies so neither
|
|
|
+ 3174 operand is clobbered. *)
|
|
|
+ 3175 t := SymTab.NewUStr();
|
|
|
+ 3176 QbeGen.CopyOp("@", q)
|
|
|
+ 3177 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3178 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 3179 OR (SymTab.IsStrType(t)
|
|
|
+ 3180 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 3181 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 3182 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 3183 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 3184 1-character string literal. When both operands are
|
|
|
+ 3185 constants, fold to a single string literal so a
|
|
|
+ 3186 constructor element stays compile-time. *)
|
|
|
+ 3187 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 3188 qt, fok);
|
|
|
+ 3189 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
+ 3190 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3191 END;
|
|
|
+ 3192 t := SymTab.NewStr()
|
|
|
+ 3193 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3194 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3195 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3196 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3197 mw := lw;
|
|
|
+ 3198 IF rw > mw THEN mw := rw END;
|
|
|
+ 3199 t := SymTab.NewSet(
|
|
|
+ 3200 SymTab.NewSubR(0,
|
|
|
+ 3201 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3202 QbeGen.CopyOp("@", q)
|
|
|
+ 3203 ELSE
|
|
|
+ 3204 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 3205 lt := t; rt := t2; t := res2
|
|
|
+ 3206 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3207 IF t # SymTab.InvalidType THEN
|
|
|
+ 3208 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3209 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3210 folded := FALSE;
|
|
|
+ 3211 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3212 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3213 IF op = SymTab.OpAdd THEN
|
|
|
+ 3214 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 3215 ELSE
|
|
|
+ 3216 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 3217 END
|
|
|
+ 3218 END;
|
|
|
+ 3219 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3220 ELSE
|
|
|
+ 3221 QbeGen.CopyOp("@", q)
|
|
|
+ 3222 END
|
|
|
+ 3223 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3224 END
|
|
|
+ 3225 END; .) }
|
|
|
+ 3226 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3227 AddOp<VAR op: INTEGER>
|
|
|
+ 3228 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 3229 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 3230 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 3231 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3232 (. VAR t2, res2, lt, rt:
|
|
|
+ 3233 SymTab.TypeIndex;
|
|
|
+ 3234 op: INTEGER;
|
|
|
+ 3235 q2, qt, wq, qf:
|
|
|
+ 3236 QbeGen.QVal;
|
|
|
+ 3237 isR, isL, folded: BOOLEAN;
|
|
|
+ 3238 lw, rw, mw: CARDINAL;
|
|
|
+ 3239 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3240 astA, astB: AST.Node;
|
|
|
+ 3241 astOp: INTEGER; .)
|
|
|
+ 3242 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
+ 3243 Fact<t2, q2> (. astB := astCur; .)
|
|
|
+ 3244 (. astOp := AST.OpMul;
|
|
|
+ 3245 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 3246 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 3247 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 3248 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 3249 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3250 astCur := astA;
|
|
|
+ 3251 IF op = SymTab.OpAnd THEN
|
|
|
+ 3252 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 3253 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3254 t := SymTab.BoolType()
|
|
|
+ 3255 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3256 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
+ 3257 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3258 END
|
|
|
+ 3259 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3260 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3261 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3262 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3263 mw := lw;
|
|
|
+ 3264 IF rw > mw THEN mw := rw END;
|
|
|
+ 3265 t := SymTab.NewSet(
|
|
|
+ 3266 SymTab.NewSubR(0,
|
|
|
+ 3267 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3268 QbeGen.CopyOp("@", q)
|
|
|
+ 3269 ELSE
|
|
|
+ 3270 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 3271 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 3272 res2) THEN
|
|
|
+ 3273 lt := t; rt := t2; t := res2
|
|
|
+ 3274 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3275 IF t # SymTab.InvalidType THEN
|
|
|
+ 3276 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3277 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3278 folded := FALSE;
|
|
|
+ 3279 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3280 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3281 IF op = SymTab.OpTimes THEN
|
|
|
+ 3282 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 3283 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 3284 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 3285 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 3286 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 3287 END
|
|
|
+ 3288 END;
|
|
|
+ 3289 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3290 ELSE
|
|
|
+ 3291 QbeGen.CopyOp("@", q)
|
|
|
+ 3292 END
|
|
|
+ 3293 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3294 END
|
|
|
+ 3295 END; .) }
|
|
|
+ 3296 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3297 MulOp<VAR op: INTEGER>
|
|
|
+ 3298 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 3299 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 3300 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 3301 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 3302 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 3303 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3304 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 3305 et, dt, t2, st, ct2, et2:
|
|
|
+ 3306 SymTab.TypeIndex;
|
|
|
+ 3307 dk: INTEGER;
|
|
|
+ 3308 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 3309 QbeGen.QVal;
|
|
|
+ 3310 qn, vn: SymTab.Name;
|
|
|
+ 3311 vt: SymTab.TypeIndex;
|
|
|
+ 3312 c1, c2: INTEGER;
|
|
|
+ 3313 lo, hi: INTEGER;
|
|
|
+ 3314 isMax: BOOLEAN;
|
|
|
+ 3315 called, isHigh, sfx, isCh,
|
|
|
+ 3316 isU, uok, isStr: BOOLEAN;
|
|
|
+ 3317 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 3318 astD: AST.Node;
|
|
|
+ 3319 astCall: BOOLEAN;
|
|
|
+ 3320 astNode, astNot: AST.Node;
|
|
|
+ 3321 j: CARDINAL;
|
|
|
+ 3322 astArg2: AST.Node;
|
|
|
+ 3323 astBrace: AST.Node;
|
|
|
+ 3324 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 3325 isConvF: BOOLEAN; .)
|
|
|
+ 3326 = (. astIsLit := FALSE; .)
|
|
|
+ 3327 ( integer (. LexString(s);
|
|
|
+ 3328 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
+ 3329 t := SymTab.IntType(); .)
|
|
|
+ 3330 | charConst (. LexString(s);
|
|
|
+ 3331 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 3332 astIsLit := TRUE;
|
|
|
+ 3333 astCur := AST.MakeLeaf(
|
|
|
+ 3334 AST.NkCharLit, s);
|
|
|
+ 3335 t := SymTab.CharType(); .)
|
|
|
+ 3336 | real (. LexString(s);
|
|
|
+ 3337 QbeGen.NormReal(s, q);
|
|
|
+ 3338 astIsLit := TRUE;
|
|
|
+ 3339 astCur := AST.MakeLeaf(
|
|
|
+ 3340 AST.NkRealLit, s);
|
|
|
+ 3341 t := SymTab.RealType(); .)
|
|
|
+ 3342 | string (. LexString(s);
|
|
|
+ 3343 astIsLit := TRUE;
|
|
|
+ 3344 astCur := AST.MakeLeaf(
|
|
|
+ 3345 AST.NkStrLit, s);
|
|
|
+ 3346 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3347 t := SymTab.CharType();
|
|
|
+ 3348 QbeGen.IntStr(
|
|
|
+ 3349 QbeGen.CharVal(s), q)
|
|
|
+ 3350 ELSE t := SymTab.NewStr();
|
|
|
+ 3351 QbeGen.DeclStr(s, q);
|
|
|
+ 3352 (* a literal's value IS its
|
|
|
+ 3353 static descriptor address *)
|
|
|
+ 3354 END; .)
|
|
|
+ 3355 | ustring (. LexString(s);
|
|
|
+ 3356 astIsLit := TRUE;
|
|
|
+ 3357 astCur := AST.MakeLeaf(
|
|
|
+ 3358 AST.NkStrLit, s);
|
|
|
+ 3359 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 3360 uok);
|
|
|
+ 3361 IF NOT uok THEN
|
|
|
+ 3362 SemError(234);
|
|
|
+ 3363 t := SymTab.InvalidType
|
|
|
+ 3364 ELSIF isU THEN
|
|
|
+ 3365 t := SymTab.UCharType();
|
|
|
+ 3366 QbeGen.IntStr(ucp, q)
|
|
|
+ 3367 ELSE
|
|
|
+ 3368 t := SymTab.NewUStr();
|
|
|
+ 3369 END; .)
|
|
|
+ 3370 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 3371 astNArgs := 0; called := FALSE;
|
|
|
+ 3372 t := dt;
|
|
|
+ 3373 IF dk = SymTab.KindConst THEN
|
|
|
+ 3374 QbeGen.CopyOp(qd, q)
|
|
|
+ 3375 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3376 END; .)
|
|
|
+ 3377 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 3378 astBrace := astCur; .) ]
|
|
|
+ 3379 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3380 (. astCall := TRUE;
|
|
|
+ 3381 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
+ 3382 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
+ 3383 (* T(x): emit as the VAL builtin so Lower's
|
|
|
+ 3384 conversion rules apply unchanged *)
|
|
|
+ 3385 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3386 AST.SetChild(astNode, 0,
|
|
|
+ 3387 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3388 AST.SetChild(astNode, 1,
|
|
|
+ 3389 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
+ 3390 IF astNArgs = 1 THEN
|
|
|
+ 3391 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
+ 3392 END;
|
|
|
+ 3393 isConvF := TRUE
|
|
|
+ 3394 ELSE astNode := AstCallNode(astD)
|
|
|
+ 3395 END;
|
|
|
+ 3396 astRes := astNode;
|
|
|
+ 3397 t := ct2;
|
|
|
+ 3398 QbeGen.CopyOp(q2, q);
|
|
|
+ 3399 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
+ 3400 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
+ 3401 QbeGen.CopyOp(convQ, q)
|
|
|
+ 3402 END;
|
|
|
+ 3403 sfx := FALSE; .)
|
|
|
+ 3404 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
+ 3405 [ (. astNArgs := 0; .)
|
|
|
+ 3406 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3407 (. astNode := AstCallNode(astRes);
|
|
|
+ 3408 astRes := astNode;
|
|
|
+ 3409 t := ct2;
|
|
|
+ 3410 QbeGen.CopyOp(q2, q);
|
|
|
+ 3411 sfx := FALSE; .) ] }
|
|
|
+ 3412 (. IF sfx THEN
|
|
|
+ 3413 IF t = SymTab.InvalidType THEN
|
|
|
+ 3414 QbeGen.CopyOp("0", q)
|
|
|
+ 3415 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3416 SymTab.ClRecord)
|
|
|
+ 3417 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 3418 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 3419 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3420 QbeGen.CopyOp("@", q)
|
|
|
+ 3421 END
|
|
|
+ 3422 END; .) ]
|
|
|
+ 3423 (. IF called THEN
|
|
|
+ 3424 astCur := astRes
|
|
|
+ 3425 ELSIF astCall THEN
|
|
|
+ 3426 astCur := astBrace
|
|
|
+ 3427 ELSE astCur := astD
|
|
|
+ 3428 END;
|
|
|
+ 3429 astIsLit := TRUE;
|
|
|
+ 3430 IF NOT called
|
|
|
+ 3431 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 3432 (* bare zero-arg function
|
|
|
+ 3433 call (parentheses may be
|
|
|
+ 3434 omitted); a proper or
|
|
|
+ 3435 parameterised proc here
|
|
|
+ 3436 is 230 *)
|
|
|
+ 3437 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 3438 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
+ 3439 t := SymTab.ProcRes(qn);
|
|
|
+ 3440 QbeGen.CopyOp("@", q);
|
|
|
+ 3441 astCur := AST.MakeNode(AST.NkCall);
|
|
|
+ 3442 AST.SetChild(astCur, 0, astD)
|
|
|
+ 3443 ELSE
|
|
|
+ 3444 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 3445 QbeGen.CopyOp("@", q)
|
|
|
+ 3446 END
|
|
|
+ 3447 END; .)
|
|
|
+ 3448 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 3449 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 3450 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 3451 isU := FALSE; .)
|
|
|
+ 3452 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3453 isStr := TRUE;
|
|
|
+ 3454 isU := FALSE;
|
|
|
+ 3455 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3456 dt := SymTab.CharType();
|
|
|
+ 3457 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 3458 qd)
|
|
|
+ 3459 ELSE
|
|
|
+ 3460 dt := SymTab.NewStr();
|
|
|
+ 3461 QbeGen.DeclStr(s, qd);
|
|
|
+ 3462 END;
|
|
|
+ 3463 dk := -1;
|
|
|
+ 3464 qn[0] := CHR(0); .)
|
|
|
+ 3465 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3466 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 3467 uok);
|
|
|
+ 3468 isStr := FALSE;
|
|
|
+ 3469 IF NOT uok THEN
|
|
|
+ 3470 SemError(234);
|
|
|
+ 3471 dt := SymTab.InvalidType
|
|
|
+ 3472 ELSIF isU THEN
|
|
|
+ 3473 (* one codepoint: a UCHAR;
|
|
|
+ 3474 LEN is 1, HIGH is 0 *)
|
|
|
+ 3475 dt := SymTab.UCharType();
|
|
|
+ 3476 QbeGen.IntStr(ucp, qd)
|
|
|
+ 3477 ELSE
|
|
|
+ 3478 dt := SymTab.NewUStr();
|
|
|
+ 3479 END;
|
|
|
+ 3480 dk := -1;
|
|
|
+ 3481 qn[0] := CHR(0); .) )
|
|
|
+ 3482 ")"
|
|
|
+ 3483 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3484 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 3485 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 3486 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3487 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 3488 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3489 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3490 IF (dt # SymTab.InvalidType)
|
|
|
+ 3491 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 3492 (* UString: the count is
|
|
|
+ 3493 the descriptor header *)
|
|
|
+ 3494 t := SymTab.IntType();
|
|
|
+ 3495 QbeGen.CopyOp("@", q)
|
|
|
+ 3496 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 3497 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 3498 (* single UCHAR codepoint *)
|
|
|
+ 3499 IF isHigh THEN
|
|
|
+ 3500 QbeGen.CopyOp("0", qr)
|
|
|
+ 3501 ELSE
|
|
|
+ 3502 QbeGen.CopyOp("1", qr)
|
|
|
+ 3503 END;
|
|
|
+ 3504 t := SymTab.IntType();
|
|
|
+ 3505 QbeGen.CopyOp(qr, q)
|
|
|
+ 3506 ELSIF isStr THEN
|
|
|
+ 3507 (* fold: content length at
|
|
|
+ 3508 compile time *)
|
|
|
+ 3509 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3510 c1 := 1
|
|
|
+ 3511 ELSE
|
|
|
+ 3512 c1 :=
|
|
|
+ 3513 SymTab.StrLen(s) - 2
|
|
|
+ 3514 END;
|
|
|
+ 3515 IF isHigh THEN
|
|
|
+ 3516 DEC(c1)
|
|
|
+ 3517 END;
|
|
|
+ 3518 QbeGen.IntStr(c1, qr);
|
|
|
+ 3519 t := SymTab.IntType();
|
|
|
+ 3520 QbeGen.CopyOp(qr, q)
|
|
|
+ 3521 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 3522 t := SymTab.InvalidType;
|
|
|
+ 3523 QbeGen.CopyOp("0", q)
|
|
|
+ 3524 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 3525 SymTab.ClArray THEN
|
|
|
+ 3526 SemError(217);
|
|
|
+ 3527 t := SymTab.InvalidType;
|
|
|
+ 3528 QbeGen.CopyOp("0", q)
|
|
|
+ 3529 ELSE
|
|
|
+ 3530 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3531 t := SymTab.IntType();
|
|
|
+ 3532 QbeGen.CopyOp("@", q)
|
|
|
+ 3533 ELSE
|
|
|
+ 3534 IF isHigh THEN
|
|
|
+ 3535 QbeGen.IntStr(
|
|
|
+ 3536 SymTab.ArrayHi(dt), qr)
|
|
|
+ 3537 ELSE
|
|
|
+ 3538 QbeGen.IntStr(VAL(
|
|
|
+ 3539 INTEGER,
|
|
|
+ 3540 SymTab.ArrayLen(dt)),
|
|
|
+ 3541 qr)
|
|
|
+ 3542 END;
|
|
|
+ 3543 t := SymTab.IntType();
|
|
|
+ 3544 QbeGen.CopyOp(qr, q)
|
|
|
+ 3545 END
|
|
|
+ 3546 END; .)
|
|
|
+ 3547 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3548 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3549 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 3550 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3551 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3552 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3553 t := SymTab.InvalidType;
|
|
|
+ 3554 QbeGen.CopyOp("0", q)
|
|
|
+ 3555 ELSE
|
|
|
+ 3556 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 3557 SymTab.ObjectSize(dt)), q);
|
|
|
+ 3558 t := SymTab.IntType()
|
|
|
+ 3559 END; .)
|
|
|
+ 3560 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 3561 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 3562 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 3563 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3564 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3565 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 3566 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3567 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 3568 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3569 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3570 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3571 (* set shift/rotate: isMax
|
|
|
+ 3572 doubles as "rotate" *)
|
|
|
+ 3573 IF (et # SymTab.InvalidType)
|
|
|
+ 3574 AND (SymTab.ClassOf(et) =
|
|
|
+ 3575 SymTab.ClSet) THEN
|
|
|
+ 3576 t := et;
|
|
|
+ 3577 QbeGen.CopyOp("@", q)
|
|
|
+ 3578 ELSE SemError(230);
|
|
|
+ 3579 t := SymTab.InvalidType;
|
|
|
+ 3580 QbeGen.CopyOp("0", q)
|
|
|
+ 3581 END; .)
|
|
|
+ 3582 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 3583 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 3584 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3585 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3586 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3587 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 3588 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3589 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 3590 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3591 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3592 IF (dt # SymTab.InvalidType)
|
|
|
+ 3593 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 3594 (* REAL/LONGREAL: the
|
|
|
+ 3595 implementation bounds *)
|
|
|
+ 3596 IF isMax THEN
|
|
|
+ 3597 QbeGen.NormReal(
|
|
|
+ 3598 "3.402823e38", q)
|
|
|
+ 3599 ELSE QbeGen.NormReal(
|
|
|
+ 3600 "-3.402823e38", q)
|
|
|
+ 3601 END;
|
|
|
+ 3602 t := SymTab.RealType()
|
|
|
+ 3603 ELSIF (dt #
|
|
|
+ 3604 SymTab.InvalidType)
|
|
|
+ 3605 AND (SymTab.ClassOf(dt) =
|
|
|
+ 3606 SymTab.ClLong) THEN
|
|
|
+ 3607 IF isMax THEN
|
|
|
+ 3608 QbeGen.CopyOp(
|
|
|
+ 3609 "9223372036854775807", q)
|
|
|
+ 3610 ELSE QbeGen.CopyOp(
|
|
|
+ 3611 "-9223372036854775808", q)
|
|
|
+ 3612 END;
|
|
|
+ 3613 t := SymTab.LongType()
|
|
|
+ 3614 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 3615 hi) THEN
|
|
|
+ 3616 IF isMax THEN
|
|
|
+ 3617 QbeGen.IntStr(hi, q)
|
|
|
+ 3618 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 3619 END;
|
|
|
+ 3620 t := SymTab.IntType()
|
|
|
+ 3621 ELSE SemError(230);
|
|
|
+ 3622 t := SymTab.InvalidType;
|
|
|
+ 3623 QbeGen.CopyOp("0", q)
|
|
|
+ 3624 END; .)
|
|
|
+ 3625 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3626 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3627 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 3628 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3629 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3630 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3631 t := SymTab.InvalidType;
|
|
|
+ 3632 QbeGen.CopyOp("0", q)
|
|
|
+ 3633 ELSE
|
|
|
+ 3634 IF sfx
|
|
|
+ 3635 OR (dk = SymTab.KindVar)
|
|
|
+ 3636 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 3637 QbeGen.CopyOp("@", q)
|
|
|
+ 3638 ELSE SemError(230);
|
|
|
+ 3639 QbeGen.CopyOp("0", q)
|
|
|
+ 3640 END;
|
|
|
+ 3641 t := SymTab.AddrType()
|
|
|
+ 3642 END; .)
|
|
|
+ 3643 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 3644 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3645 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 3646 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3647 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3648 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3649 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3650 SemError(211) END;
|
|
|
+ 3651 t := SymTab.CharType(); .)
|
|
|
+ 3652 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
+ 3653 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3654 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 3655 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3656 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3657 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 3658 IF (SymTab.ClassOf(et) #
|
|
|
+ 3659 SymTab.ClChar)
|
|
|
3660 AND (SymTab.ClassOf(et) #
|
|
|
- 3661 SymTab.ClEnum)
|
|
|
- 3662 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3663 SemError(211) END
|
|
|
- 3664 END;
|
|
|
- 3665 t := SymTab.IntType(); .)
|
|
|
- 3666 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 3667 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3668 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 3669 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3670 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3671 (. IF QbeGen.IsImm(q)
|
|
|
- 3672 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3673 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
- 3674 QbeGen.IntStr(lo, q)
|
|
|
- 3675 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3676 END;
|
|
|
- 3677 t := SymTab.CharType(); .)
|
|
|
- 3678 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 3679 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3680 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 3681 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3682 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3683 (. (* UCHR: the UCHAR constructor.
|
|
|
- 3684 CHAR -> UCHAR (identity);
|
|
|
- 3685 INTEGER familly -> UCHAR
|
|
|
- 3686 (codepoint value). *)
|
|
|
- 3687 IF (et # SymTab.InvalidType)
|
|
|
- 3688 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 3689 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3690 SemError(211) END;
|
|
|
- 3691 t := SymTab.UCharType(); .)
|
|
|
- 3692 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 3693 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3694 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 3695 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3696 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3697 (. IF (et # SymTab.InvalidType)
|
|
|
- 3698 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3699 SemError(211) END;
|
|
|
- 3700 t := SymTab.CharType(); .)
|
|
|
- 3701 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 3702 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3703 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 3704 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3705 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3706 (. (* UORD(u): the codepoint as a
|
|
|
- 3707 32-bit ordinal (INTEGER),
|
|
|
- 3708 cf. ORD for CHAR. *)
|
|
|
- 3709 IF (et # SymTab.InvalidType)
|
|
|
- 3710 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3711 SemError(211) END;
|
|
|
- 3712 t := SymTab.IntType(); .)
|
|
|
- 3713 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 3714 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3715 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 3716 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3717 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3718 (. IF (et # SymTab.InvalidType)
|
|
|
- 3719 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 3720 AND (SymTab.ClassOf(et) #
|
|
|
- 3721 SymTab.ClReal) THEN
|
|
|
- 3722 SemError(211)
|
|
|
- 3723 ELSIF QbeGen.IsImm(q)
|
|
|
- 3724 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3725 IF lo < 0 THEN lo := -lo END;
|
|
|
- 3726 QbeGen.IntStr(lo, q)
|
|
|
- 3727 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3728 END;
|
|
|
- 3729 t := et; .)
|
|
|
- 3730 | "ODD" "(" Expr<et, q> ")"
|
|
|
- 3731 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3732 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
- 3733 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3734 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3735 (. IF (et # SymTab.InvalidType)
|
|
|
- 3736 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3737 SemError(211) END;
|
|
|
- 3738 t := SymTab.BoolType();
|
|
|
- 3739 IF QbeGen.IsImm(q)
|
|
|
- 3740 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3741 IF (lo MOD 2) # 0 THEN
|
|
|
- 3742 QbeGen.CopyOp("1", q)
|
|
|
- 3743 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3744 END
|
|
|
- 3745 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3746 END; .)
|
|
|
- 3747 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
- 3748 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
- 3749 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3750 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3751 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
- 3752 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3753 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3754 (. t := SymTab.IntType();
|
|
|
- 3755 QbeGen.CopyOp("@", q); .)
|
|
|
- 3756 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
- 3757 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
- 3758 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3759 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3760 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
- 3761 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3762 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3763 (. t := SymTab.RealType();
|
|
|
- 3764 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
- 3765 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
- 3766 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 3767 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3768 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3769 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3770 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3771 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3772 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 3773 SemError(201);
|
|
|
- 3774 t := SymTab.InvalidType
|
|
|
- 3775 ELSE vt := SymTab.SymType(vn);
|
|
|
- 3776 IF vt = SymTab.InvalidType THEN
|
|
|
- 3777 t := SymTab.InvalidType
|
|
|
- 3778 ELSIF et =
|
|
|
- 3779 SymTab.InvalidType THEN
|
|
|
- 3780 t := vt
|
|
|
- 3781 ELSE
|
|
|
- 3782 c1 := SymTab.ClassOf(et);
|
|
|
- 3783 c2 := SymTab.ClassOf(vt);
|
|
|
- 3784 IF (c1 = SymTab.ClInt)
|
|
|
- 3785 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3786 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3787 t := vt
|
|
|
- 3788 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3789 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3790 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3791 t := vt
|
|
|
- 3792 ELSIF (c1 = SymTab.ClInt)
|
|
|
- 3793 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3794 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
- 3795 QbeGen.CopyOp(qa, q);
|
|
|
- 3796 t := vt
|
|
|
- 3797 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3798 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3799 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
- 3800 QbeGen.CopyOp(qa, q);
|
|
|
- 3801 t := vt
|
|
|
- 3802 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3803 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3804 QbeGen.ConvRI(q, qa);
|
|
|
- 3805 QbeGen.CopyOp(qa, q);
|
|
|
- 3806 t := vt
|
|
|
- 3807 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3808 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3809 QbeGen.ConvRL(q, qa);
|
|
|
- 3810 QbeGen.CopyOp(qa, q);
|
|
|
- 3811 t := vt
|
|
|
- 3812 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3813 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3814 t := vt
|
|
|
- 3815 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 3816 OR (c1 =
|
|
|
- 3817 SymTab.ClChar)
|
|
|
+ 3661 SymTab.ClBool)
|
|
|
+ 3662 AND (SymTab.ClassOf(et) #
|
|
|
+ 3663 SymTab.ClEnum)
|
|
|
+ 3664 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3665 SemError(211) END
|
|
|
+ 3666 END;
|
|
|
+ 3667 t := SymTab.IntType(); .)
|
|
|
+ 3668 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 3669 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3670 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 3671 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3672 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3673 (. IF QbeGen.IsImm(q)
|
|
|
+ 3674 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3675 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
+ 3676 QbeGen.IntStr(lo, q)
|
|
|
+ 3677 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3678 END;
|
|
|
+ 3679 t := SymTab.CharType(); .)
|
|
|
+ 3680 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 3681 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3682 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 3683 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3684 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3685 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 3686 CHAR -> UCHAR (identity);
|
|
|
+ 3687 INTEGER familly -> UCHAR
|
|
|
+ 3688 (codepoint value). *)
|
|
|
+ 3689 IF (et # SymTab.InvalidType)
|
|
|
+ 3690 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 3691 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3692 SemError(211) END;
|
|
|
+ 3693 t := SymTab.UCharType(); .)
|
|
|
+ 3694 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 3695 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3696 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 3697 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3698 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3699 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3700 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3701 SemError(211) END;
|
|
|
+ 3702 t := SymTab.CharType(); .)
|
|
|
+ 3703 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 3704 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3705 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 3706 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3707 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3708 (. (* UORD(u): the codepoint as a
|
|
|
+ 3709 32-bit ordinal (INTEGER),
|
|
|
+ 3710 cf. ORD for CHAR. *)
|
|
|
+ 3711 IF (et # SymTab.InvalidType)
|
|
|
+ 3712 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3713 SemError(211) END;
|
|
|
+ 3714 t := SymTab.IntType(); .)
|
|
|
+ 3715 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 3716 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3717 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 3718 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3719 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3720 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3721 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 3722 AND (SymTab.ClassOf(et) #
|
|
|
+ 3723 SymTab.ClReal) THEN
|
|
|
+ 3724 SemError(211)
|
|
|
+ 3725 ELSIF QbeGen.IsImm(q)
|
|
|
+ 3726 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3727 IF lo < 0 THEN lo := -lo END;
|
|
|
+ 3728 QbeGen.IntStr(lo, q)
|
|
|
+ 3729 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3730 END;
|
|
|
+ 3731 t := et; .)
|
|
|
+ 3732 | "ODD" "(" Expr<et, q> ")"
|
|
|
+ 3733 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3734 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
+ 3735 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3736 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3737 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3738 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3739 SemError(211) END;
|
|
|
+ 3740 t := SymTab.BoolType();
|
|
|
+ 3741 IF QbeGen.IsImm(q)
|
|
|
+ 3742 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3743 IF (lo MOD 2) # 0 THEN
|
|
|
+ 3744 QbeGen.CopyOp("1", q)
|
|
|
+ 3745 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3746 END
|
|
|
+ 3747 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3748 END; .)
|
|
|
+ 3749 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
+ 3750 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
+ 3751 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3752 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3753 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
+ 3754 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3755 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3756 (. t := SymTab.IntType();
|
|
|
+ 3757 QbeGen.CopyOp("@", q); .)
|
|
|
+ 3758 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
+ 3759 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
+ 3760 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3761 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3762 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
+ 3763 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3764 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3765 (. t := SymTab.RealType();
|
|
|
+ 3766 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
+ 3767 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
+ 3768 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 3769 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3770 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3771 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3772 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3773 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3774 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 3775 SemError(201);
|
|
|
+ 3776 t := SymTab.InvalidType
|
|
|
+ 3777 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 3778 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3779 t := SymTab.InvalidType
|
|
|
+ 3780 ELSIF et =
|
|
|
+ 3781 SymTab.InvalidType THEN
|
|
|
+ 3782 t := vt
|
|
|
+ 3783 ELSE
|
|
|
+ 3784 c1 := SymTab.ClassOf(et);
|
|
|
+ 3785 c2 := SymTab.ClassOf(vt);
|
|
|
+ 3786 IF (c1 = SymTab.ClInt)
|
|
|
+ 3787 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3788 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
+ 3789 t := vt
|
|
|
+ 3790 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3791 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3792 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
+ 3793 t := vt
|
|
|
+ 3794 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 3795 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3796 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
+ 3797 QbeGen.CopyOp(qa, q);
|
|
|
+ 3798 t := vt
|
|
|
+ 3799 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3800 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3801 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
+ 3802 QbeGen.CopyOp(qa, q);
|
|
|
+ 3803 t := vt
|
|
|
+ 3804 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3805 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3806 QbeGen.ConvRI(q, qa);
|
|
|
+ 3807 QbeGen.CopyOp(qa, q);
|
|
|
+ 3808 t := vt
|
|
|
+ 3809 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3810 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3811 QbeGen.ConvRL(q, qa);
|
|
|
+ 3812 QbeGen.CopyOp(qa, q);
|
|
|
+ 3813 t := vt
|
|
|
+ 3814 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3815 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3816 t := vt
|
|
|
+ 3817 ELSIF ((c1 = SymTab.ClInt)
|
|
|
3818 OR (c1 =
|
|
|
- 3819 SymTab.ClBool)
|
|
|
+ 3819 SymTab.ClChar)
|
|
|
3820 OR (c1 =
|
|
|
- 3821 SymTab.ClEnum))
|
|
|
- 3822 AND ((c2 = SymTab.ClInt)
|
|
|
- 3823 OR (c2 =
|
|
|
- 3824 SymTab.ClChar)
|
|
|
+ 3821 SymTab.ClBool)
|
|
|
+ 3822 OR (c1 =
|
|
|
+ 3823 SymTab.ClEnum))
|
|
|
+ 3824 AND ((c2 = SymTab.ClInt)
|
|
|
3825 OR (c2 =
|
|
|
- 3826 SymTab.ClBool)
|
|
|
+ 3826 SymTab.ClChar)
|
|
|
3827 OR (c2 =
|
|
|
- 3828 SymTab.ClEnum)) THEN
|
|
|
- 3829 t := vt
|
|
|
- 3830 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 3831 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 3832 t := vt
|
|
|
- 3833 ELSIF ((c1 = SymTab.ClProc)
|
|
|
- 3834 AND (c2 = SymTab.ClProc))
|
|
|
- 3835 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
- 3836 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
- 3837 t := vt
|
|
|
- 3838 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3839 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3840 t := vt
|
|
|
- 3841 ELSE SemError(230);
|
|
|
- 3842 t := SymTab.InvalidType
|
|
|
- 3843 END
|
|
|
- 3844 END
|
|
|
- 3845 END; .)
|
|
|
- 3846 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 3847 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 3848 QbeGen.CopyOp(sq, q); .)
|
|
|
- 3849 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 3850 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 3851 t := SymTab.BoolType()
|
|
|
- 3852 ELSE SemError(212);
|
|
|
- 3853 t := SymTab.InvalidType END;
|
|
|
- 3854 IF t # SymTab.InvalidType THEN
|
|
|
- 3855 QbeGen.CopyOp("@", q)
|
|
|
- 3856 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3857 END;
|
|
|
- 3858 astIsLit := TRUE;
|
|
|
- 3859 astCur := AST.MakeUn(
|
|
|
- 3860 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 3861 )
|
|
|
- 3862 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
- 3863 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3864 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 3865 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 3866 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 3867 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3868 (. VAR astNode: AST.Node; .)
|
|
|
- 3869 = "{" (. t := SymTab.NewSet(
|
|
|
- 3870 SymTab.NewSubR(0, 255));
|
|
|
- 3871 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 3872 QbeGen.NewSetTemp(8, q);
|
|
|
- 3873 QbeGen.SetZero(q, 8); .)
|
|
|
- 3874 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 3875 "}" (. astCur := astNode; .) .
|
|
|
- 3876 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 3877 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 3878 declared type sets the width (set) or element type (array). *)
|
|
|
- 3879 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3880 (. VAR nw: CARDINAL;
|
|
|
- 3881 astNode, astTail: AST.Node;
|
|
|
- 3882 savedCls: INTEGER; .)
|
|
|
- 3883 = "{" (. savedCls := braceCls;
|
|
|
- 3884 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 3885 AST.SetTy(astNode, vt);
|
|
|
- 3886 astTail := astNode;
|
|
|
- 3887 IF vt = SymTab.InvalidType THEN
|
|
|
- 3888 braceCls := -1
|
|
|
- 3889 ELSE braceCls :=
|
|
|
- 3890 SymTab.ClassOf(vt)
|
|
|
- 3891 END;
|
|
|
- 3892 IF braceCls = SymTab.ClSet THEN
|
|
|
- 3893 IF vt = SymTab.InvalidType THEN
|
|
|
- 3894 nw := 8
|
|
|
- 3895 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 3896 IF nw = 0 THEN nw := 8 END
|
|
|
- 3897 END;
|
|
|
- 3898 QbeGen.NewSetTemp(nw, q);
|
|
|
- 3899 QbeGen.SetZero(q, nw)
|
|
|
- 3900 ELSIF (braceCls =
|
|
|
- 3901 SymTab.ClArray)
|
|
|
- 3902 OR (braceCls =
|
|
|
- 3903 SymTab.ClRecord)
|
|
|
+ 3828 SymTab.ClBool)
|
|
|
+ 3829 OR (c2 =
|
|
|
+ 3830 SymTab.ClEnum)) THEN
|
|
|
+ 3831 t := vt
|
|
|
+ 3832 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 3833 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 3834 t := vt
|
|
|
+ 3835 ELSIF ((c1 = SymTab.ClProc)
|
|
|
+ 3836 AND (c2 = SymTab.ClProc))
|
|
|
+ 3837 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
+ 3838 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
+ 3839 t := vt
|
|
|
+ 3840 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3841 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3842 t := vt
|
|
|
+ 3843 ELSE SemError(230);
|
|
|
+ 3844 t := SymTab.InvalidType
|
|
|
+ 3845 END
|
|
|
+ 3846 END
|
|
|
+ 3847 END; .)
|
|
|
+ 3848 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 3849 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 3850 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 3851 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 3852 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 3853 t := SymTab.BoolType()
|
|
|
+ 3854 ELSE SemError(212);
|
|
|
+ 3855 t := SymTab.InvalidType END;
|
|
|
+ 3856 IF t # SymTab.InvalidType THEN
|
|
|
+ 3857 QbeGen.CopyOp("@", q)
|
|
|
+ 3858 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3859 END;
|
|
|
+ 3860 astIsLit := TRUE;
|
|
|
+ 3861 astCur := AST.MakeUn(
|
|
|
+ 3862 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 3863 )
|
|
|
+ 3864 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
+ 3865 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3866 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 3867 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 3868 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 3869 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3870 (. VAR astNode: AST.Node; .)
|
|
|
+ 3871 = "{" (. t := SymTab.NewSet(
|
|
|
+ 3872 SymTab.NewSubR(0, 255));
|
|
|
+ 3873 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 3874 QbeGen.NewSetTemp(8, q);
|
|
|
+ 3875 QbeGen.SetZero(q, 8); .)
|
|
|
+ 3876 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 3877 "}" (. astCur := astNode; .) .
|
|
|
+ 3878 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 3879 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 3880 declared type sets the width (set) or element type (array). *)
|
|
|
+ 3881 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3882 (. VAR nw: CARDINAL;
|
|
|
+ 3883 astNode, astTail: AST.Node;
|
|
|
+ 3884 savedCls: INTEGER; .)
|
|
|
+ 3885 = "{" (. savedCls := braceCls;
|
|
|
+ 3886 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 3887 AST.SetTy(astNode, vt);
|
|
|
+ 3888 astTail := astNode;
|
|
|
+ 3889 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3890 braceCls := -1
|
|
|
+ 3891 ELSE braceCls :=
|
|
|
+ 3892 SymTab.ClassOf(vt)
|
|
|
+ 3893 END;
|
|
|
+ 3894 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3895 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3896 nw := 8
|
|
|
+ 3897 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 3898 IF nw = 0 THEN nw := 8 END
|
|
|
+ 3899 END;
|
|
|
+ 3900 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 3901 QbeGen.SetZero(q, nw)
|
|
|
+ 3902 ELSIF (braceCls =
|
|
|
+ 3903 SymTab.ClArray)
|
|
|
3904 OR (braceCls =
|
|
|
- 3905 SymTab.ClClass) THEN
|
|
|
- 3906 QbeGen.CtorBegin(vt)
|
|
|
- 3907 ELSE
|
|
|
- 3908 IF vt # SymTab.InvalidType THEN
|
|
|
- 3909 SemError(230) END;
|
|
|
- 3910 braceCls := -1
|
|
|
- 3911 END; .)
|
|
|
- 3912 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 3913 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 3914 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
- 3915 OR (braceCls =
|
|
|
- 3916 SymTab.ClRecord)
|
|
|
+ 3905 SymTab.ClRecord)
|
|
|
+ 3906 OR (braceCls =
|
|
|
+ 3907 SymTab.ClClass) THEN
|
|
|
+ 3908 QbeGen.CtorBegin(vt)
|
|
|
+ 3909 ELSE
|
|
|
+ 3910 IF vt # SymTab.InvalidType THEN
|
|
|
+ 3911 SemError(230) END;
|
|
|
+ 3912 braceCls := -1
|
|
|
+ 3913 END; .)
|
|
|
+ 3914 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 3915 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 3916 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
3917 OR (braceCls =
|
|
|
- 3918 SymTab.ClClass) THEN
|
|
|
- 3919 QbeGen.CtorEnd(q)
|
|
|
- 3920 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 3921 QbeGen.CopyOp("0", q)
|
|
|
- 3922 END;
|
|
|
- 3923 braceCls := savedCls; .)
|
|
|
- 3924 (. astCur := astNode; .) .
|
|
|
- 3925 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 3926 VAR node, tail: AST.Node>
|
|
|
- 3927 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3928 qe, q2: QbeGen.QVal;
|
|
|
- 3929 v, v2, reps, k: INTEGER;
|
|
|
- 3930 elem: SymTab.TypeIndex;
|
|
|
- 3931 lo: INTEGER;
|
|
|
- 3932 span: CARDINAL;
|
|
|
- 3933 cl, cl2: INTEGER;
|
|
|
- 3934 hasR, hasB: BOOLEAN;
|
|
|
- 3935 astEl: AST.Node; .)
|
|
|
- 3936 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 3937 reps := 1; .)
|
|
|
- 3938 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3939 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3940 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3941 hasR := TRUE; .) ]
|
|
|
- 3942 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 3943 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 3944 IF hasB THEN SemError(230) END;
|
|
|
- 3945 lo := SymTab.SetBaseLo(vt);
|
|
|
- 3946 span := SymTab.SetCount(vt);
|
|
|
- 3947 IF (et = SymTab.InvalidType)
|
|
|
- 3948 OR (hasR AND (et2 =
|
|
|
- 3949 SymTab.InvalidType)) THEN
|
|
|
- 3950 ELSE cl :=
|
|
|
- 3951 SymTab.ClassOf(et);
|
|
|
- 3952 IF hasR THEN
|
|
|
- 3953 cl2 :=
|
|
|
- 3954 SymTab.ClassOf(et2)
|
|
|
- 3955 ELSE cl2 := SymTab.ClInt
|
|
|
- 3956 END;
|
|
|
- 3957 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3958 OR (hasR AND NOT
|
|
|
- 3959 SymTab.SetElemClassOk(cl2))
|
|
|
- 3960 THEN
|
|
|
- 3961 SemError(222)
|
|
|
- 3962 ELSIF hasR
|
|
|
- 3963 AND SymTab.ConstInt(qe, v)
|
|
|
- 3964 AND SymTab.ConstInt(q2,
|
|
|
- 3965 v2)
|
|
|
- 3966 AND ((v < lo)
|
|
|
- 3967 OR (v2 < lo)
|
|
|
- 3968 OR (v >= lo +
|
|
|
- 3969 VAL(INTEGER, span))
|
|
|
- 3970 OR (v2 >= lo +
|
|
|
+ 3918 SymTab.ClRecord)
|
|
|
+ 3919 OR (braceCls =
|
|
|
+ 3920 SymTab.ClClass) THEN
|
|
|
+ 3921 QbeGen.CtorEnd(q)
|
|
|
+ 3922 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 3923 QbeGen.CopyOp("0", q)
|
|
|
+ 3924 END;
|
|
|
+ 3925 braceCls := savedCls; .)
|
|
|
+ 3926 (. astCur := astNode; .) .
|
|
|
+ 3927 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 3928 VAR node, tail: AST.Node>
|
|
|
+ 3929 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3930 qe, q2: QbeGen.QVal;
|
|
|
+ 3931 v, v2, reps, k: INTEGER;
|
|
|
+ 3932 elem: SymTab.TypeIndex;
|
|
|
+ 3933 lo: INTEGER;
|
|
|
+ 3934 span: CARDINAL;
|
|
|
+ 3935 cl, cl2: INTEGER;
|
|
|
+ 3936 hasR, hasB: BOOLEAN;
|
|
|
+ 3937 astEl: AST.Node; .)
|
|
|
+ 3938 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 3939 reps := 1; .)
|
|
|
+ 3940 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3941 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3942 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3943 hasR := TRUE; .) ]
|
|
|
+ 3944 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 3945 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3946 IF hasB THEN SemError(230) END;
|
|
|
+ 3947 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 3948 span := SymTab.SetCount(vt);
|
|
|
+ 3949 IF (et = SymTab.InvalidType)
|
|
|
+ 3950 OR (hasR AND (et2 =
|
|
|
+ 3951 SymTab.InvalidType)) THEN
|
|
|
+ 3952 ELSE cl :=
|
|
|
+ 3953 SymTab.ClassOf(et);
|
|
|
+ 3954 IF hasR THEN
|
|
|
+ 3955 cl2 :=
|
|
|
+ 3956 SymTab.ClassOf(et2)
|
|
|
+ 3957 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3958 END;
|
|
|
+ 3959 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3960 OR (hasR AND NOT
|
|
|
+ 3961 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3962 THEN
|
|
|
+ 3963 SemError(222)
|
|
|
+ 3964 ELSIF hasR
|
|
|
+ 3965 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3966 AND SymTab.ConstInt(q2,
|
|
|
+ 3967 v2)
|
|
|
+ 3968 AND ((v < lo)
|
|
|
+ 3969 OR (v2 < lo)
|
|
|
+ 3970 OR (v >= lo +
|
|
|
3971 VAL(INTEGER, span))
|
|
|
- 3972 OR (v > v2)) THEN
|
|
|
- 3973 SemError(222)
|
|
|
- 3974 ELSIF hasR THEN
|
|
|
- 3975 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3976 lo, span)
|
|
|
- 3977 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3978 v)
|
|
|
- 3979 AND ((v < lo)
|
|
|
- 3980 OR (v >= lo +
|
|
|
- 3981 VAL(INTEGER,
|
|
|
- 3982 span))) THEN
|
|
|
- 3983 SemError(222)
|
|
|
- 3984 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3985 lo, span)
|
|
|
- 3986 END
|
|
|
- 3987 END
|
|
|
- 3988 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 3989 OR (braceCls =
|
|
|
- 3990 SymTab.ClRecord)
|
|
|
+ 3972 OR (v2 >= lo +
|
|
|
+ 3973 VAL(INTEGER, span))
|
|
|
+ 3974 OR (v > v2)) THEN
|
|
|
+ 3975 SemError(222)
|
|
|
+ 3976 ELSIF hasR THEN
|
|
|
+ 3977 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3978 lo, span)
|
|
|
+ 3979 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3980 v)
|
|
|
+ 3981 AND ((v < lo)
|
|
|
+ 3982 OR (v >= lo +
|
|
|
+ 3983 VAL(INTEGER,
|
|
|
+ 3984 span))) THEN
|
|
|
+ 3985 SemError(222)
|
|
|
+ 3986 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3987 lo, span)
|
|
|
+ 3988 END
|
|
|
+ 3989 END
|
|
|
+ 3990 ELSIF (braceCls = SymTab.ClArray)
|
|
|
3991 OR (braceCls =
|
|
|
- 3992 SymTab.ClClass) THEN
|
|
|
- 3993 IF hasR THEN SemError(230) END;
|
|
|
- 3994 reps := 1;
|
|
|
- 3995 IF hasB THEN
|
|
|
- 3996 IF SymTab.ConstInt(q2, v2)
|
|
|
- 3997 AND (v2 >= 1) THEN
|
|
|
- 3998 reps := v2
|
|
|
- 3999 ELSE SemError(230)
|
|
|
- 4000 END
|
|
|
- 4001 END;
|
|
|
- 4002 k := 0;
|
|
|
- 4003 WHILE k < reps DO
|
|
|
- 4004 QbeGen.CtorElem(qe);
|
|
|
- 4005 INC(k)
|
|
|
- 4006 END
|
|
|
- 4007 END; .)
|
|
|
- 4008 (. (* the BY form repeats the
|
|
|
- 4009 element; keep the AST in
|
|
|
- 4010 step with CtorElem *)
|
|
|
- 4011 k := 0;
|
|
|
- 4012 WHILE k < reps DO
|
|
|
- 4013 AstAppend(AST.NkBlock,
|
|
|
- 4014 node, tail, astEl);
|
|
|
- 4015 INC(k)
|
|
|
- 4016 END; .) .
|
|
|
- 4017 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 4018 qe, q2: QbeGen.QVal;
|
|
|
- 4019 v, v2: INTEGER;
|
|
|
- 4020 lo: INTEGER;
|
|
|
- 4021 span: CARDINAL;
|
|
|
- 4022 cl, cl2: INTEGER;
|
|
|
- 4023 hasR: BOOLEAN;
|
|
|
- 4024 astEl: AST.Node; .)
|
|
|
- 4025 = (. hasR := FALSE; .)
|
|
|
- 4026 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 4027 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 4028 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 4029 hasR := TRUE; .) ]
|
|
|
- 4030 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 4031 span := SymTab.SetCount(st);
|
|
|
- 4032 IF (et = SymTab.InvalidType)
|
|
|
- 4033 OR (hasR AND (et2 =
|
|
|
- 4034 SymTab.InvalidType)) THEN
|
|
|
- 4035 ELSE cl :=
|
|
|
- 4036 SymTab.ClassOf(et);
|
|
|
- 4037 IF hasR THEN
|
|
|
- 4038 cl2 :=
|
|
|
- 4039 SymTab.ClassOf(et2)
|
|
|
- 4040 ELSE cl2 := SymTab.ClInt
|
|
|
- 4041 END;
|
|
|
- 4042 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 4043 OR (hasR AND NOT
|
|
|
- 4044 SymTab.SetElemClassOk(cl2))
|
|
|
- 4045 THEN
|
|
|
- 4046 SemError(222)
|
|
|
- 4047 ELSIF hasR
|
|
|
- 4048 AND SymTab.ConstInt(qe, v)
|
|
|
- 4049 AND SymTab.ConstInt(q2,
|
|
|
- 4050 v2)
|
|
|
- 4051 AND ((v < lo)
|
|
|
- 4052 OR (v2 < lo)
|
|
|
- 4053 OR (v >= lo +
|
|
|
- 4054 VAL(INTEGER, span))
|
|
|
- 4055 OR (v2 >= lo +
|
|
|
+ 3992 SymTab.ClRecord)
|
|
|
+ 3993 OR (braceCls =
|
|
|
+ 3994 SymTab.ClClass) THEN
|
|
|
+ 3995 IF hasR THEN SemError(230) END;
|
|
|
+ 3996 reps := 1;
|
|
|
+ 3997 IF hasB THEN
|
|
|
+ 3998 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 3999 AND (v2 >= 1) THEN
|
|
|
+ 4000 reps := v2
|
|
|
+ 4001 ELSE SemError(230)
|
|
|
+ 4002 END
|
|
|
+ 4003 END;
|
|
|
+ 4004 k := 0;
|
|
|
+ 4005 WHILE k < reps DO
|
|
|
+ 4006 QbeGen.CtorElem(qe);
|
|
|
+ 4007 INC(k)
|
|
|
+ 4008 END
|
|
|
+ 4009 END; .)
|
|
|
+ 4010 (. (* the BY form repeats the
|
|
|
+ 4011 element; keep the AST in
|
|
|
+ 4012 step with CtorElem *)
|
|
|
+ 4013 k := 0;
|
|
|
+ 4014 WHILE k < reps DO
|
|
|
+ 4015 AstAppend(AST.NkBlock,
|
|
|
+ 4016 node, tail, astEl);
|
|
|
+ 4017 INC(k)
|
|
|
+ 4018 END; .) .
|
|
|
+ 4019 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 4020 qe, q2: QbeGen.QVal;
|
|
|
+ 4021 v, v2: INTEGER;
|
|
|
+ 4022 lo: INTEGER;
|
|
|
+ 4023 span: CARDINAL;
|
|
|
+ 4024 cl, cl2: INTEGER;
|
|
|
+ 4025 hasR: BOOLEAN;
|
|
|
+ 4026 astEl: AST.Node; .)
|
|
|
+ 4027 = (. hasR := FALSE; .)
|
|
|
+ 4028 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 4029 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 4030 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 4031 hasR := TRUE; .) ]
|
|
|
+ 4032 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 4033 span := SymTab.SetCount(st);
|
|
|
+ 4034 IF (et = SymTab.InvalidType)
|
|
|
+ 4035 OR (hasR AND (et2 =
|
|
|
+ 4036 SymTab.InvalidType)) THEN
|
|
|
+ 4037 ELSE cl :=
|
|
|
+ 4038 SymTab.ClassOf(et);
|
|
|
+ 4039 IF hasR THEN
|
|
|
+ 4040 cl2 :=
|
|
|
+ 4041 SymTab.ClassOf(et2)
|
|
|
+ 4042 ELSE cl2 := SymTab.ClInt
|
|
|
+ 4043 END;
|
|
|
+ 4044 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 4045 OR (hasR AND NOT
|
|
|
+ 4046 SymTab.SetElemClassOk(cl2))
|
|
|
+ 4047 THEN
|
|
|
+ 4048 SemError(222)
|
|
|
+ 4049 ELSIF hasR
|
|
|
+ 4050 AND SymTab.ConstInt(qe, v)
|
|
|
+ 4051 AND SymTab.ConstInt(q2,
|
|
|
+ 4052 v2)
|
|
|
+ 4053 AND ((v < lo)
|
|
|
+ 4054 OR (v2 < lo)
|
|
|
+ 4055 OR (v >= lo +
|
|
|
4056 VAL(INTEGER, span))
|
|
|
- 4057 OR (v > v2)) THEN
|
|
|
- 4058 SemError(222)
|
|
|
- 4059 ELSIF hasR THEN
|
|
|
- 4060 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 4061 lo, span)
|
|
|
- 4062 ELSIF SymTab.ConstInt(qe,
|
|
|
- 4063 v)
|
|
|
- 4064 AND ((v < lo)
|
|
|
- 4065 OR (v >= lo +
|
|
|
- 4066 VAL(INTEGER,
|
|
|
- 4067 span))) THEN
|
|
|
- 4068 SemError(222)
|
|
|
- 4069 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 4070 lo, span)
|
|
|
- 4071 END
|
|
|
- 4072 END; .)
|
|
|
- 4073 (. AST.SetChild(node,
|
|
|
- 4074 AST.NChild(node), astEl); .) .
|
|
|
- 4075 GetIdent<VAR n: SymTab.Name>
|
|
|
- 4076 = ident (. LexName(n); .) .
|
|
|
- 4077
|
|
|
- 4078 END M2.
|
|
|
+ 4057 OR (v2 >= lo +
|
|
|
+ 4058 VAL(INTEGER, span))
|
|
|
+ 4059 OR (v > v2)) THEN
|
|
|
+ 4060 SemError(222)
|
|
|
+ 4061 ELSIF hasR THEN
|
|
|
+ 4062 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 4063 lo, span)
|
|
|
+ 4064 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 4065 v)
|
|
|
+ 4066 AND ((v < lo)
|
|
|
+ 4067 OR (v >= lo +
|
|
|
+ 4068 VAL(INTEGER,
|
|
|
+ 4069 span))) THEN
|
|
|
+ 4070 SemError(222)
|
|
|
+ 4071 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 4072 lo, span)
|
|
|
+ 4073 END
|
|
|
+ 4074 END; .)
|
|
|
+ 4075 (. AST.SetChild(node,
|
|
|
+ 4076 AST.NChild(node), astEl); .) .
|
|
|
+ 4077 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 4078 = ident (. LexName(n); .) .
|
|
|
+ 4079
|
|
|
+ 4080 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|
|
|
|
|
|
Statistics:
|
|
|
|
|
|
- nr of terminals: 111 (limit 400)
|
|
|
+ nr of terminals: 112 (limit 400)
|
|
|
nr of non-terminals: 90 (limit 210)
|
|
|
- nr of pragmas: 0 (limit 389)
|
|
|
- nr of symbolnodes: 201 (limit 500)
|
|
|
- nr of graphnodes: 1272 (limit 1500)
|
|
|
+ nr of pragmas: 0 (limit 388)
|
|
|
+ nr of symbolnodes: 202 (limit 500)
|
|
|
+ nr of graphnodes: 1284 (limit 1500)
|
|
|
nr of conditionsets: 12 (limit 100)
|
|
|
nr of charactersets: 16 (limit 250)
|
|
|
|