Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "hoc.h"
5
#include "y.tab.h"
6
 
7
#define	NSTACK	256
8
 
9
static Datum stack[NSTACK];	/* the stack */
10
static Datum *stackp;		/* next free spot on stack */
11
 
12
#define	NPROG	2000
13
Inst	prog[NPROG];	/* the machine */
14
Inst	*progp;		/* next free spot for code generation */
15
Inst	*pc;		/* program counter during execution */
16
Inst	*progbase = prog; /* start of current subprogram */
17
int	returning;	/* 1 if return stmt seen */
18
int	indef;	/* 1 if parsing a func or proc */
19
 
20
typedef struct Frame {	/* proc/func call stack frame */
21
	Symbol	*sp;	/* symbol table entry */
22
	Inst	*retpc;	/* where to resume after return */
23
	Datum	*argn;	/* n-th argument on stack */
24
	int	nargs;	/* number of arguments */
25
} Frame;
26
#define	NFRAME	100
27
Frame	frame[NFRAME];
28
Frame	*fp;		/* frame pointer */
29
 
30
void
31
initcode(void)
32
{
33
	progp = progbase;
34
	stackp = stack;
35
	fp = frame;
36
	returning = 0;
37
	indef = 0;
38
}
39
 
40
void
41
push(Datum d)
42
{
43
	if (stackp >= &stack[NSTACK])
44
		execerror("stack too deep", 0);
45
	*stackp++ = d;
46
}
47
 
48
Datum
49
pop(void)
50
{
51
	if (stackp == stack)
52
		execerror("stack underflow", 0);
53
	return *--stackp;
54
}
55
 
56
void
57
xpop(void)	/* for when no value is wanted */
58
{
59
	if (stackp == stack)
60
		execerror("stack underflow", (char *)0);
61
	--stackp;
62
}
63
 
64
void
65
constpush(void)
66
{
67
	Datum d;
68
	d.val = ((Symbol *)*pc++)->u.val;
69
	push(d);
70
}
71
 
72
void
73
varpush(void)
74
{
75
	Datum d;
76
	d.sym = (Symbol *)(*pc++);
77
	push(d);
78
}
79
 
80
void
81
whilecode(void)
82
{
83
	Datum d;
84
	Inst *savepc = pc;
85
 
86
	execute(savepc+2);	/* condition */
87
	d = pop();
88
	while (d.val) {
89
		execute(*((Inst **)(savepc)));	/* body */
90
		if (returning)
91
			break;
92
		execute(savepc+2);	/* condition */
93
		d = pop();
94
	}
95
	if (!returning)
96
		pc = *((Inst **)(savepc+1)); /* next stmt */
97
}
98
 
99
void
100
forcode(void)
101
{
102
	Datum d;
103
	Inst *savepc = pc;
104
 
105
	execute(savepc+4);		/* precharge */
106
	pop();
107
	execute(*((Inst **)(savepc)));	/* condition */
108
	d = pop();
109
	while (d.val) {
110
		execute(*((Inst **)(savepc+2)));	/* body */
111
		if (returning)
112
			break;
113
		execute(*((Inst **)(savepc+1)));	/* post loop */
114
		pop();
115
		execute(*((Inst **)(savepc)));	/* condition */
116
		d = pop();
117
	}
118
	if (!returning)
119
		pc = *((Inst **)(savepc+3)); /* next stmt */
120
}
121
 
122
void
123
ifcode(void) 
124
{
125
	Datum d;
126
	Inst *savepc = pc;	/* then part */
127
 
128
	execute(savepc+3);	/* condition */
129
	d = pop();
130
	if (d.val)
131
		execute(*((Inst **)(savepc)));	
132
	else if (*((Inst **)(savepc+1))) /* else part? */
133
		execute(*((Inst **)(savepc+1)));
134
	if (!returning)
135
		pc = *((Inst **)(savepc+2)); /* next stmt */
136
}
137
 
138
void
139
define(Symbol* sp, Formal *f)	/* put func/proc in symbol table */
140
{
141
	Fndefn *fd;
142
	int n;
143
 
144
	fd = emalloc(sizeof(Fndefn));
145
	fd->code = progbase;	/* start of code */
146
	progbase = progp;	/* next code starts here */
147
	fd->formals = f;
148
	for(n=0; f; f=f->next)
149
		n++;
150
	fd->nargs = n;
151
	sp->u.defn = fd;
152
}
153
 
154
void
155
call(void) 		/* call a function */
156
{
157
	Formal *f;
158
	Datum *arg;
159
	Saveval *s;
160
	int i;
161
 
162
	Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */
163
				      /* for function */
164
	if (fp >= &frame[NFRAME-1])
165
		execerror(sp->name, "call nested too deeply");
166
	fp++;
167
	fp->sp = sp;
168
	fp->nargs = (int)(uintptr)pc[1];
169
	fp->retpc = pc + 2;
170
	fp->argn = stackp - 1;	/* last argument */
171
	if(fp->nargs != sp->u.defn->nargs)
172
		execerror(sp->name, "called with wrong number of arguments");
173
	/* bind formals */
174
	f = sp->u.defn->formals;
175
	arg = stackp - fp->nargs;
176
	while(f){
177
		s = emalloc(sizeof(Saveval));
178
		s->val = f->sym->u;
179
		s->type = f->sym->type;
180
		s->next = f->save;
181
		f->save = s;
182
		f->sym->u.val = arg->val;
183
		f->sym->type = VAR;
184
		f = f->next;
185
		arg++;
186
	}
187
	for (i = 0; i < fp->nargs; i++)
188
		pop();	/* pop arguments; no longer needed */
189
	execute(sp->u.defn->code);
190
	returning = 0;
191
}
192
 
193
void
194
restore(Symbol *sp)	/* restore formals associated with symbol */
195
{
196
	Formal *f;
197
	Saveval *s;
198
 
199
	f = sp->u.defn->formals;
200
	while(f){
201
		s = f->save;
202
		if(s == 0)	/* more actuals than formals */
203
			break;
204
		f->sym->u = s->val;
205
		f->sym->type = s->type;
206
		f->save = s->next;
207
		free(s);
208
		f = f->next;
209
	}
210
}
211
 
212
void
213
restoreall(void)	/* restore all variables in case of error */
214
{
215
	while(fp>=frame && fp->sp){
216
		restore(fp->sp);
217
		--fp;
218
	}
219
	fp = frame;
220
}
221
 
222
static void
223
ret(void) 		/* common return from func or proc */
224
{
225
	/* restore formals */
226
	restore(fp->sp);
227
	pc = (Inst *)fp->retpc;
228
	--fp;
229
	returning = 1;
230
}
231
 
232
void
233
funcret(void) 	/* return from a function */
234
{
235
	Datum d;
236
	if (fp->sp->type == PROCEDURE)
237
		execerror(fp->sp->name, "(proc) returns value");
238
	d = pop();	/* preserve function return value */
239
	ret();
240
	push(d);
241
}
242
 
243
void
244
procret(void) 	/* return from a procedure */
245
{
246
	if (fp->sp->type == FUNCTION)
247
		execerror(fp->sp->name,
248
			"(func) returns no value");
249
	ret();
250
}
251
 
252
void
253
bltin(void) 
254
{
255
 
256
	Datum d;
257
	d = pop();
258
	d.val = (*(double (*)(double))*pc++)(d.val);
259
	push(d);
260
}
261
 
262
void
263
add(void)
264
{
265
	Datum d1, d2;
266
	d2 = pop();
267
	d1 = pop();
268
	d1.val += d2.val;
269
	push(d1);
270
}
271
 
272
void
273
sub(void)
274
{
275
	Datum d1, d2;
276
	d2 = pop();
277
	d1 = pop();
278
	d1.val -= d2.val;
279
	push(d1);
280
}
281
 
282
void
283
mul(void)
284
{
285
	Datum d1, d2;
286
	d2 = pop();
287
	d1 = pop();
288
	d1.val *= d2.val;
289
	push(d1);
290
}
291
 
292
void
293
div(void)
294
{
295
	Datum d1, d2;
296
	d2 = pop();
297
	if (d2.val == 0.0)
298
		execerror("division by zero", (char *)0);
299
	d1 = pop();
300
	d1.val /= d2.val;
301
	push(d1);
302
}
303
 
304
void
305
mod(void)
306
{
307
	Datum d1, d2;
308
	d2 = pop();
309
	if (d2.val == 0.0)
310
		execerror("division by zero", (char *)0);
311
	d1 = pop();
312
	/* d1.val %= d2.val; */
313
	d1.val = fmod(d1.val, d2.val);
314
	push(d1);
315
}
316
 
317
void
318
negate(void)
319
{
320
	Datum d;
321
	d = pop();
322
	d.val = -d.val;
323
	push(d);
324
}
325
 
326
void
327
verify(Symbol* s)
328
{
329
	if (s->type != VAR && s->type != UNDEF)
330
		execerror("attempt to evaluate non-variable", s->name);
331
	if (s->type == UNDEF)
332
		execerror("undefined variable", s->name);
333
}
334
 
335
void
336
eval(void)		/* evaluate variable on stack */
337
{
338
	Datum d;
339
	d = pop();
340
	verify(d.sym);
341
	d.val = d.sym->u.val;
342
	push(d);
343
}
344
 
345
void
346
preinc(void)
347
{
348
	Datum d;
349
	d.sym = (Symbol *)(*pc++);
350
	verify(d.sym);
351
	d.val = d.sym->u.val += 1.0;
352
	push(d);
353
}
354
 
355
void
356
predec(void)
357
{
358
	Datum d;
359
	d.sym = (Symbol *)(*pc++);
360
	verify(d.sym);
361
	d.val = d.sym->u.val -= 1.0;
362
	push(d);
363
}
364
 
365
void
366
postinc(void)
367
{
368
	Datum d;
369
	double v;
370
	d.sym = (Symbol *)(*pc++);
371
	verify(d.sym);
372
	v = d.sym->u.val;
373
	d.sym->u.val += 1.0;
374
	d.val = v;
375
	push(d);
376
}
377
 
378
void
379
postdec(void)
380
{
381
	Datum d;
382
	double v;
383
	d.sym = (Symbol *)(*pc++);
384
	verify(d.sym);
385
	v = d.sym->u.val;
386
	d.sym->u.val -= 1.0;
387
	d.val = v;
388
	push(d);
389
}
390
 
391
void
392
gt(void)
393
{
394
	Datum d1, d2;
395
	d2 = pop();
396
	d1 = pop();
397
	d1.val = (double)(d1.val > d2.val);
398
	push(d1);
399
}
400
 
401
void
402
lt(void)
403
{
404
	Datum d1, d2;
405
	d2 = pop();
406
	d1 = pop();
407
	d1.val = (double)(d1.val < d2.val);
408
	push(d1);
409
}
410
 
411
void
412
ge(void)
413
{
414
	Datum d1, d2;
415
	d2 = pop();
416
	d1 = pop();
417
	d1.val = (double)(d1.val >= d2.val);
418
	push(d1);
419
}
420
 
421
void
422
le(void)
423
{
424
	Datum d1, d2;
425
	d2 = pop();
426
	d1 = pop();
427
	d1.val = (double)(d1.val <= d2.val);
428
	push(d1);
429
}
430
 
431
void
432
eq(void)
433
{
434
	Datum d1, d2;
435
	d2 = pop();
436
	d1 = pop();
437
	d1.val = (double)(d1.val == d2.val);
438
	push(d1);
439
}
440
 
441
void
442
ne(void)
443
{
444
	Datum d1, d2;
445
	d2 = pop();
446
	d1 = pop();
447
	d1.val = (double)(d1.val != d2.val);
448
	push(d1);
449
}
450
 
451
void
452
and(void)
453
{
454
	Datum d1, d2;
455
	d2 = pop();
456
	d1 = pop();
457
	d1.val = (double)(d1.val != 0.0 && d2.val != 0.0);
458
	push(d1);
459
}
460
 
461
void
462
or(void)
463
{
464
	Datum d1, d2;
465
	d2 = pop();
466
	d1 = pop();
467
	d1.val = (double)(d1.val != 0.0 || d2.val != 0.0);
468
	push(d1);
469
}
470
 
471
void
472
not(void)
473
{
474
	Datum d;
475
	d = pop();
476
	d.val = (double)(d.val == 0.0);
477
	push(d);
478
}
479
 
480
void
481
power(void)
482
{
483
	Datum d1, d2;
484
	d2 = pop();
485
	d1 = pop();
486
	d1.val = Pow(d1.val, d2.val);
487
	push(d1);
488
}
489
 
490
void
491
assign(void)
492
{
493
	Datum d1, d2;
494
	d1 = pop();
495
	d2 = pop();
496
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
497
		execerror("assignment to non-variable",
498
			d1.sym->name);
499
	d1.sym->u.val = d2.val;
500
	d1.sym->type = VAR;
501
	push(d2);
502
}
503
 
504
void
505
addeq(void)
506
{
507
	Datum d1, d2;
508
	d1 = pop();
509
	d2 = pop();
510
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
511
		execerror("assignment to non-variable",
512
			d1.sym->name);
513
	d2.val = d1.sym->u.val += d2.val;
514
	d1.sym->type = VAR;
515
	push(d2);
516
}
517
 
518
void
519
subeq(void)
520
{
521
	Datum d1, d2;
522
	d1 = pop();
523
	d2 = pop();
524
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
525
		execerror("assignment to non-variable",
526
			d1.sym->name);
527
	d2.val = d1.sym->u.val -= d2.val;
528
	d1.sym->type = VAR;
529
	push(d2);
530
}
531
 
532
void
533
muleq(void)
534
{
535
	Datum d1, d2;
536
	d1 = pop();
537
	d2 = pop();
538
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
539
		execerror("assignment to non-variable",
540
			d1.sym->name);
541
	d2.val = d1.sym->u.val *= d2.val;
542
	d1.sym->type = VAR;
543
	push(d2);
544
}
545
 
546
void
547
diveq(void)
548
{
549
	Datum d1, d2;
550
	d1 = pop();
551
	d2 = pop();
552
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
553
		execerror("assignment to non-variable",
554
			d1.sym->name);
555
	d2.val = d1.sym->u.val /= d2.val;
556
	d1.sym->type = VAR;
557
	push(d2);
558
}
559
 
560
void
561
modeq(void)
562
{
563
	Datum d1, d2;
564
	long x;
565
	d1 = pop();
566
	d2 = pop();
567
	if (d1.sym->type != VAR && d1.sym->type != UNDEF)
568
		execerror("assignment to non-variable",
569
			d1.sym->name);
570
	/* d2.val = d1.sym->u.val %= d2.val; */
571
	x = d1.sym->u.val;
572
	x %= (long) d2.val;
573
	d2.val = d1.sym->u.val = x;
574
	d1.sym->type = VAR;
575
	push(d2);
576
}
577
 
578
void
579
printtop(void)	/* pop top value from stack, print it */
580
{
581
	Datum d;
582
	static Symbol *s;	/* last value computed */
583
	if (s == 0)
584
		s = install("_", VAR, 0.0);
585
	d = pop();
586
	print("%.12g\n", d.val);
587
	s->u.val = d.val;
588
}
589
 
590
void
591
prexpr(void)	/* print numeric value */
592
{
593
	Datum d;
594
	d = pop();
595
	print("%.12g ", d.val);
596
}
597
 
598
void
599
prstr(void)		/* print string value */ 
600
{
601
	print("%s", (char *) *pc++);
602
}
603
 
604
void
605
varread(void)	/* read into variable */
606
{
607
	Datum d;
608
	extern Biobuf *bin;
609
	Symbol *var = (Symbol *) *pc++;
610
	int c;
611
 
612
  Again:
613
	do
614
		c = Bgetc(bin);
615
	while(c==' ' || c=='\t' || c=='\n');
616
	if(c == Beof){
617
  Iseof:
618
		if(moreinput())
619
			goto Again;
620
		d.val = var->u.val = 0.0;
621
		goto Return;
622
	}
623
 
624
	if(strchr("+-.0123456789", c) == 0)
625
		execerror("non-number read into", var->name);
626
	Bungetc(bin);
627
	if(Bgetd(bin, &var->u.val) == Beof)
628
		goto Iseof;
629
	else
630
		d.val = 1.0;
631
  Return:
632
	var->type = VAR;
633
	push(d);
634
}
635
 
636
Inst*
637
code(Inst f)	/* install one instruction or operand */
638
{
639
	Inst *oprogp = progp;
640
	if (progp >= &prog[NPROG])
641
		execerror("program too big", (char *)0);
642
	*progp++ = f;
643
	return oprogp;
644
}
645
 
646
void
647
execute(Inst* p)
648
{
649
	for (pc = p; *pc != STOP && !returning; )
650
		(*((++pc)[-1]))();
651
}