xref: /csrg-svn/usr.bin/pascal/src/func.c (revision 1197)
1753Speter /* Copyright (c) 1979 Regents of the University of California */
2753Speter 
3*1197Speter static	char sccsid[] = "@(#)func.c 1.2 10/03/80";
4753Speter 
5753Speter #include "whoami.h"
6753Speter #ifdef OBJ
7753Speter     /*
8753Speter      *	the rest of the file
9753Speter      */
10753Speter #include "0.h"
11753Speter #include "tree.h"
12753Speter #include "opcode.h"
13753Speter 
14753Speter bool cardempty = FALSE;
15753Speter 
16753Speter /*
17753Speter  * Funccod generates code for
18753Speter  * built in function calls and calls
19753Speter  * call to generate calls to user
20753Speter  * defined functions and procedures.
21753Speter  */
22753Speter funccod(r)
23753Speter 	int *r;
24753Speter {
25753Speter 	struct nl *p;
26753Speter 	register struct nl *p1;
27753Speter 	register int *al;
28753Speter 	register op;
29753Speter 	int argc, *argv;
30753Speter 	int tr[2], tr2[4];
31753Speter 
32753Speter 	/*
33753Speter 	 * Verify that the given name
34753Speter 	 * is defined and the name of
35753Speter 	 * a function.
36753Speter 	 */
37753Speter 	p = lookup(r[2]);
38753Speter 	if (p == NIL) {
39753Speter 		rvlist(r[3]);
40753Speter 		return (NIL);
41753Speter 	}
42*1197Speter 	if (p->class != FUNC && p->class != FFUNC) {
43753Speter 		error("%s is not a function", p->symbol);
44753Speter 		rvlist(r[3]);
45753Speter 		return (NIL);
46753Speter 	}
47753Speter 	argv = r[3];
48753Speter 	/*
49753Speter 	 * Call handles user defined
50753Speter 	 * procedures and functions
51753Speter 	 */
52753Speter 	if (bn != 0)
53753Speter 		return (call(p, argv, FUNC, bn));
54753Speter 	/*
55753Speter 	 * Count the arguments
56753Speter 	 */
57753Speter 	argc = 0;
58753Speter 	for (al = argv; al != NIL; al = al[2])
59753Speter 		argc++;
60753Speter 	/*
61753Speter 	 * Built-in functions have
62753Speter 	 * their interpreter opcode
63753Speter 	 * associated with them.
64753Speter 	 */
65753Speter 	op = p->value[0] &~ NSTAND;
66753Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
67753Speter 		standard();
68753Speter 		error("%s is a nonstandard function", p->symbol);
69753Speter 	}
70753Speter 	switch (op) {
71753Speter 		/*
72753Speter 		 * Parameterless functions
73753Speter 		 */
74753Speter 		case O_CLCK:
75753Speter 		case O_SCLCK:
76753Speter 		case O_WCLCK:
77753Speter 		case O_ARGC:
78753Speter 			if (argc != 0) {
79753Speter 				error("%s takes no arguments", p->symbol);
80753Speter 				rvlist(argv);
81753Speter 				return (NIL);
82753Speter 			}
83753Speter 			put1(op);
84753Speter 			return (nl+T4INT);
85753Speter 		case O_EOF:
86753Speter 		case O_EOLN:
87753Speter 			if (argc == 0) {
88753Speter 				argv = tr;
89753Speter 				tr[1] = tr2;
90753Speter 				tr2[0] = T_VAR;
91753Speter 				tr2[2] = input->symbol;
92753Speter 				tr2[1] = tr2[3] = NIL;
93753Speter 				argc = 1;
94753Speter 			} else if (argc != 1) {
95753Speter 				error("%s takes either zero or one argument", p->symbol);
96753Speter 				rvlist(argv);
97753Speter 				return (NIL);
98753Speter 			}
99753Speter 		}
100753Speter 	/*
101753Speter 	 * All other functions take
102753Speter 	 * exactly one argument.
103753Speter 	 */
104753Speter 	if (argc != 1) {
105753Speter 		error("%s takes exactly one argument", p->symbol);
106753Speter 		rvlist(argv);
107753Speter 		return (NIL);
108753Speter 	}
109753Speter 	/*
110753Speter 	 * Evaluate the argmument
111753Speter 	 */
112753Speter 	p1 = stkrval((int *) argv[1], NLNIL , RREQ );
113753Speter 	if (p1 == NIL)
114753Speter 		return (NIL);
115753Speter 	switch (op) {
116753Speter 		case O_EXP:
117753Speter 		case O_SIN:
118753Speter 		case O_COS:
119753Speter 		case O_ATAN:
120753Speter 		case O_LN:
121753Speter 		case O_SQRT:
122753Speter 		case O_RANDOM:
123753Speter 		case O_EXPO:
124753Speter 		case O_UNDEF:
125753Speter 			if (isa(p1, "i"))
126753Speter 				convert(p1, nl+TDOUBLE);
127753Speter 			else if (isnta(p1, "d")) {
128753Speter 				error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
129753Speter 				return (NIL);
130753Speter 			}
131753Speter 			put1(op);
132753Speter 			if (op == O_UNDEF)
133753Speter 				return (nl+TBOOL);
134753Speter 			else if (op == O_EXPO)
135753Speter 				return (nl+T4INT);
136753Speter 			else
137753Speter 				return (nl+TDOUBLE);
138753Speter 		case O_SEED:
139753Speter 			if (isnta(p1, "i")) {
140753Speter 				error("seed's argument must be an integer, not %s", nameof(p1));
141753Speter 				return (NIL);
142753Speter 			}
143753Speter 			put1(op);
144753Speter 			return (nl+T4INT);
145753Speter 		case O_ROUND:
146753Speter 		case O_TRUNC:
147753Speter 			if (isnta(p1, "d"))  {
148753Speter 				error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
149753Speter 				return (NIL);
150753Speter 			}
151753Speter 			put1(op);
152753Speter 			return (nl+T4INT);
153753Speter 		case O_ABS2:
154753Speter 		case O_SQR2:
155753Speter 			if (isa(p1, "d")) {
156753Speter 				put1(op + O_ABS8-O_ABS2);
157753Speter 				return (nl+TDOUBLE);
158753Speter 			}
159753Speter 			if (isa(p1, "i")) {
160753Speter 				put1(op + (width(p1) >> 2));
161753Speter 				return (nl+T4INT);
162753Speter 			}
163753Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
164753Speter 			return (NIL);
165753Speter 		case O_ORD2:
166753Speter 			if (isa(p1, "bcis") || classify(p1) == TPTR) {
167753Speter 				return (nl+T4INT);
168753Speter 			}
169753Speter 			error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1));
170753Speter 			return (NIL);
171753Speter 		case O_SUCC2:
172753Speter 		case O_PRED2:
173753Speter 			if (isa(p1, "bcs")) {
174753Speter 				put1(op);
175753Speter 				return (p1);
176753Speter 			}
177753Speter 			if (isa(p1, "i")) {
178753Speter 				if (width(p1) <= 2)
179753Speter 					op += O_PRED24-O_PRED2;
180753Speter 				else
181753Speter 					op++;
182753Speter 				put1(op);
183753Speter 				return (nl+T4INT);
184753Speter 			}
185753Speter 			if (isa(p1, "id")) {
186753Speter 				error("%s is forbidden for reals", p->symbol);
187753Speter 				return (NIL);
188753Speter 			}
189753Speter 			error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
190753Speter 			return (NIL);
191753Speter 		case O_ODD2:
192753Speter 			if (isnta(p1, "i")) {
193753Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
194753Speter 				return (NIL);
195753Speter 			}
196753Speter 			put1(op + (width(p1) >> 2));
197753Speter 			return (nl+TBOOL);
198753Speter 		case O_CHR2:
199753Speter 			if (isnta(p1, "i")) {
200753Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
201753Speter 				return (NIL);
202753Speter 			}
203753Speter 			put1(op + (width(p1) >> 2));
204753Speter 			return (nl+TCHAR);
205753Speter 		case O_CARD:
206753Speter 			if ( p1 != nl + TSET ) {
207753Speter 			    if (isnta(p1, "t")) {
208753Speter 				error("Argument to card must be a set, not %s", nameof(p1));
209753Speter 				return (NIL);
210753Speter 			    }
211753Speter 			    put2(O_CARD, width(p1));
212753Speter 			} else {
213753Speter 			    if ( !cardempty ) {
214753Speter 				warning();
215753Speter 				error("Cardinality of the empty set is 0." );
216753Speter 				cardempty = TRUE;
217753Speter 			    }
218753Speter 			    put(1, O_CON1, 0);
219753Speter 			}
220753Speter 			return (nl+T2INT);
221753Speter 		case O_EOLN:
222753Speter 			if (!text(p1)) {
223753Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
224753Speter 				return (NIL);
225753Speter 			}
226753Speter 			put1(op);
227753Speter 			return (nl+TBOOL);
228753Speter 		case O_EOF:
229753Speter 			if (p1->class != FILET) {
230753Speter 				error("Argument to eof must be file, not %s", nameof(p1));
231753Speter 				return (NIL);
232753Speter 			}
233753Speter 			put1(op);
234753Speter 			return (nl+TBOOL);
235753Speter 		case 0:
236753Speter 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
237753Speter 		default:
238753Speter 			panic("func1");
239753Speter 	}
240753Speter }
241753Speter #endif OBJ
242