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