Initial revision
This commit is contained in:
		
							parent
							
								
									a731f979b0
								
							
						
					
					
						commit
						bc94559e4d
					
				
					 16 changed files with 3123 additions and 0 deletions
				
			
		
							
								
								
									
										27
									
								
								lang/occam/comp/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lang/occam/comp/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | GFILES=		occam.g | ||||||
|  | PRIMARY=	occam.o Lpars.o keytab.o lex.yy.o code.o em.o | ||||||
|  | SECUNDARY=	symtab.o expr.o builtin.o | ||||||
|  | TERTIARY=	report.o | ||||||
|  | LLOPT= | ||||||
|  | LIBRARY=	-lln libemk.a libsystem.a | ||||||
|  | 
 | ||||||
|  | all: | ||||||
|  | 		make dummy | ||||||
|  | 		make oc | ||||||
|  | 
 | ||||||
|  | dummy:		$(GFILES) | ||||||
|  | 		LLgen $(LLOPT) $(GFILES) | ||||||
|  | 		touch dummy | ||||||
|  | 
 | ||||||
|  | oc:		$(PRIMARY) $(SECUNDARY) $(TERTIARY) | ||||||
|  | 		$(CC) -o oc $(PRIMARY) $(SECUNDARY) $(TERTIARY) $(LIBRARY) | ||||||
|  | 
 | ||||||
|  | lex.yy.c:	lex.l | ||||||
|  | 		lex lex.l | ||||||
|  | 
 | ||||||
|  | $(PRIMARY):			Lpars.h | ||||||
|  | occam.o keytab.o:		token.h | ||||||
|  | occam.o $(SECUNDARY):		symtab.h expr.h | ||||||
|  | $(PRIMARY) $(SECUNDARY):	sizes.h | ||||||
|  | occam.o code.o:			code.h | ||||||
|  | code.o em.o:			em.h | ||||||
							
								
								
									
										74
									
								
								lang/occam/comp/builtin.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								lang/occam/comp/builtin.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "symtab.h" | ||||||
|  | #include "expr.h" | ||||||
|  | #include "sizes.h" | ||||||
|  | 
 | ||||||
|  | void init_builtins() | ||||||
|  | /* Insert all builtin names into the outermost symbol table (first statement
 | ||||||
|  |  * is sym_down() ).  Note that this table is never destroy()ed, so static | ||||||
|  |  * initializers may be used. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	union type_info info; | ||||||
|  | 
 | ||||||
|  | 	static char file[]="file"; | ||||||
|  | 
 | ||||||
|  | 	static struct par_list | ||||||
|  | 	open_list[] = { | ||||||
|  | 		{ &open_list[1], nil, T_VAR },		/* File descriptor */ | ||||||
|  | 		{ &open_list[2], nil, T_VALUE|T_ARR },	/* File name */ | ||||||
|  | 		{ nil,		 nil, T_VALUE|T_ARR }	/* "r", "w", "a" */ | ||||||
|  | 	}, | ||||||
|  | 	close_list[]= { | ||||||
|  | 		{ nil,		 nil, T_VALUE }		/* File descriptor */ | ||||||
|  | 	}, | ||||||
|  | 	exit_list[]= { | ||||||
|  | 		{ nil,		 nil, T_VALUE }		/* Exit code */ | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	sym_down();	/* Add level of symbols above all others */ | ||||||
|  | 
 | ||||||
|  | 	/* CHAN file[20], input=file[0], output=file[1], error=file[2]: */ | ||||||
|  | 
 | ||||||
|  | 	info.vc.st.builtin=file; | ||||||
|  | 	info.vc.offset=0; | ||||||
|  | 	insert(file, T_CHAN|T_ARR|T_BUILTIN, _NFILE, info); | ||||||
|  | 
 | ||||||
|  | 	info.vc.st.builtin=file; | ||||||
|  | 	info.vc.offset=0; | ||||||
|  | 	insert("input", T_CHAN|T_BUILTIN, 1, info); | ||||||
|  | 
 | ||||||
|  | 	info.vc.st.builtin=file; | ||||||
|  | 	info.vc.offset=wz+pz; | ||||||
|  | 	insert("output", T_CHAN|T_BUILTIN, 1, info); | ||||||
|  | 
 | ||||||
|  | 	info.vc.st.builtin=file; | ||||||
|  | 	info.vc.offset=2*(wz+pz); | ||||||
|  | 	insert("error", T_CHAN|T_BUILTIN, 1, info); | ||||||
|  | 
 | ||||||
|  | 	/* DEF EOF= -1, TEXT= -2, RAW= -3: */ | ||||||
|  | 
 | ||||||
|  | 	info.const=new_const(-1L); | ||||||
|  | 	insert("EOF", T_CONST|T_BUILTIN, 0, info); | ||||||
|  | 
 | ||||||
|  | 	info.const=new_const(-2L); | ||||||
|  | 	insert("TEXT", T_CONST|T_BUILTIN, 0, info); | ||||||
|  | 
 | ||||||
|  | 	info.const=new_const(-3L); | ||||||
|  | 	insert("RAW", T_CONST|T_BUILTIN, 0, info); | ||||||
|  | 
 | ||||||
|  | 	/* PROC open(VAR fd, VALUE name[], mode[])= .... : */ | ||||||
|  | 	info.proc.st.builtin="b_open"; | ||||||
|  | 	info.proc.pars=open_list; | ||||||
|  | 	insert("open", T_PROC|T_BUILTIN, 0, info); | ||||||
|  | 
 | ||||||
|  | 	/* PROC close(VALUE fd)= .... : */ | ||||||
|  | 	info.proc.st.builtin="b_close"; | ||||||
|  | 	info.proc.pars=close_list; | ||||||
|  | 	insert("close", T_PROC|T_BUILTIN, 0, info); | ||||||
|  | 
 | ||||||
|  | 	/* PROC exit(VALUE code)= .... : */ | ||||||
|  | 	info.proc.st.builtin="b_exit"; | ||||||
|  | 	info.proc.pars=exit_list; | ||||||
|  | 	insert("exit", T_PROC|T_BUILTIN, 0, info); | ||||||
|  | } | ||||||
							
								
								
									
										607
									
								
								lang/occam/comp/code.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								lang/occam/comp/code.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,607 @@ | ||||||
|  | #include "em.h" | ||||||
|  | #include "expr.h" | ||||||
|  | #include "symtab.h" | ||||||
|  | #include "sizes.h" | ||||||
|  | #include "Lpars.h" | ||||||
|  | #include "code.h" | ||||||
|  | 
 | ||||||
|  | extern err; | ||||||
|  | 
 | ||||||
|  | static void subscript(); | ||||||
|  | enum addr_val { address, value }; | ||||||
|  | 
 | ||||||
|  | void code_val(e) register struct expr *e; | ||||||
|  | /* Compile e for its value, which is put on the stack. */ | ||||||
|  | { | ||||||
|  | 	register struct expr *left, *right; | ||||||
|  | 
 | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	switch(e->kind) { | ||||||
|  | 	case E_NODE: | ||||||
|  | 		left=e->u.node.left; | ||||||
|  | 		right=e->u.node.right; | ||||||
|  | 
 | ||||||
|  | 		switch (e->u.node.op) { | ||||||
|  | 		case '+': | ||||||
|  | 		case '-': | ||||||
|  | 		case '*': | ||||||
|  | 		case '/': | ||||||
|  | 		case BS: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			xxi(e->u.node.op); | ||||||
|  | 			break; | ||||||
|  | 		case '<': | ||||||
|  | 		case '>': | ||||||
|  | 		case LE: | ||||||
|  | 		case GE: | ||||||
|  | 		case NE: | ||||||
|  | 		case '=': | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			cmi(); | ||||||
|  | 			Txx(e->u.node.op); | ||||||
|  | 			break; | ||||||
|  | 		case AFTER: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			xxi('-'); | ||||||
|  | 			cvw(); | ||||||
|  | 			tst(); | ||||||
|  | 			Txx('>'); | ||||||
|  | 			break; | ||||||
|  | 		case BA: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			and(); | ||||||
|  | 			break; | ||||||
|  | 		case BO: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			ior(); | ||||||
|  | 			break; | ||||||
|  | 		case BX: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			xor(); | ||||||
|  | 			break; | ||||||
|  | 		case AND: | ||||||
|  | 		case OR: { | ||||||
|  | 			int T=0, F=0, L=0; | ||||||
|  | 
 | ||||||
|  | 			code_bool(e, positive, &T, &F); | ||||||
|  | 			Label(T); | ||||||
|  | 			Loc(-1L); | ||||||
|  | 			branch(&L); | ||||||
|  | 			Label(F); | ||||||
|  | 			Loc(0L); | ||||||
|  | 			Label(L); | ||||||
|  | 			}break; | ||||||
|  | 		case LS: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			cvw(); | ||||||
|  | 			sli(); | ||||||
|  | 			break; | ||||||
|  | 		case RS: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			cvw(); | ||||||
|  | 			sri(); | ||||||
|  | 			break; | ||||||
|  | 		case '~': | ||||||
|  | 			code_val(left); | ||||||
|  | 			ngi(); | ||||||
|  | 			break; | ||||||
|  | 		case NOT: | ||||||
|  | 			code_val(left); | ||||||
|  | 			com(); | ||||||
|  | 			break; | ||||||
|  | 		case '[': | ||||||
|  | 			subscript(e, value); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case E_VAR: { | ||||||
|  | 		register struct symbol *var=e->u.var; | ||||||
|  | 
 | ||||||
|  | 		if (var->type&T_BUILTIN) | ||||||
|  | 			Loe(var->info.vc.st.builtin, var->info.vc.offset); | ||||||
|  | 		else | ||||||
|  | 		if (var->info.vc.st.level==curr_level) | ||||||
|  | 			if (var->type&T_PARAM && (var->type&T_TYPE)!=T_VALUE) | ||||||
|  | 				Lil(var->info.vc.offset); | ||||||
|  | 			else | ||||||
|  | 				Lol(var->info.vc.offset); | ||||||
|  | 		else { | ||||||
|  | 			if (var->info.vc.offset<0) | ||||||
|  | 				lxl(curr_level-var->info.vc.st.level); | ||||||
|  | 			else | ||||||
|  | 				lxa(curr_level-var->info.vc.st.level); | ||||||
|  | 			if (var->type&T_PARAM && (var->type&T_TYPE)!=T_VALUE) | ||||||
|  | 				Lif(var->info.vc.offset); | ||||||
|  | 			else | ||||||
|  | 				Lof(var->info.vc.offset); | ||||||
|  | 		} | ||||||
|  | 		}break; | ||||||
|  | 	case E_CONST: | ||||||
|  | 		Loc(e->u.const); | ||||||
|  | 		break; | ||||||
|  | 	case E_NOW: | ||||||
|  | 		cal("now"); | ||||||
|  | 		lfr(vz); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subscript(e, av) register struct expr *e; enum addr_val av; | ||||||
|  | /* Produce code to compute the address or value of e->left[e->right] or
 | ||||||
|  |  * the address of e->left[e->right->left FOR e->right->right]. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register char *des; | ||||||
|  | 	register struct expr *left; | ||||||
|  | 	register struct expr *index; | ||||||
|  | 
 | ||||||
|  | 	code_addr(left=e->u.node.left); | ||||||
|  | 
 | ||||||
|  | 	if ((index=e->u.node.right)->kind==E_NODE && index->u.node.op==FOR) | ||||||
|  | 		index=index->u.node.left; | ||||||
|  | 
 | ||||||
|  | 	if (left->arr_siz==0) { | ||||||
|  | 		if ((left->type&T_TYPE)==T_CHAN) | ||||||
|  | 			des="maxcdes"; | ||||||
|  | 		else | ||||||
|  | 			des= e->type&T_BYTE ? "maxbdes" : "maxwdes"; | ||||||
|  | 	} else { | ||||||
|  | 		register lsiz=left->arr_siz; | ||||||
|  | 
 | ||||||
|  | 		if (left->type&T_BYTE && !(e->type&T_BYTE)) | ||||||
|  | 			lsiz/=vz; | ||||||
|  | 		else | ||||||
|  | 		if (!(left->type&T_BYTE) && e->type&T_BYTE) | ||||||
|  | 			lsiz*=vz; | ||||||
|  | 
 | ||||||
|  | 		if (e->type&T_ARR) | ||||||
|  | 			lsiz-=(e->arr_siz -1); | ||||||
|  | 
 | ||||||
|  | 		if (constant(index)) { | ||||||
|  | 			if (index->u.const<0 || index->u.const>=lsiz) { | ||||||
|  | 				warning("constant index outside vector"); | ||||||
|  | 				lin(); | ||||||
|  | 				loc(0); | ||||||
|  | 				trp(); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			loc(lsiz); | ||||||
|  | 
 | ||||||
|  | 			if ((left->type&T_TYPE)==T_CHAN) | ||||||
|  | 				des="chandes"; | ||||||
|  | 			else | ||||||
|  | 				des= e->type&T_BYTE ? "bytedes" : "worddes"; | ||||||
|  | 			ste(des, wz); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (constant(index)) { | ||||||
|  | 		register offset=index->u.const; | ||||||
|  | 
 | ||||||
|  | 		if ((left->type&T_TYPE)==T_CHAN) | ||||||
|  | 			offset*=(wz+vz); | ||||||
|  | 		else | ||||||
|  | 		if ( !(e->type&T_BYTE) ) | ||||||
|  | 			offset*=vz; | ||||||
|  | 
 | ||||||
|  | 		if (av==address) | ||||||
|  | 			adp(offset); | ||||||
|  | 		else { | ||||||
|  | 			if (e->type&T_BYTE) { | ||||||
|  | 				adp(offset); | ||||||
|  | 				loi(1); | ||||||
|  | 				cwv(); | ||||||
|  | 			} else | ||||||
|  | 				Lof(offset); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		code_val(index); | ||||||
|  | 		cvw(); | ||||||
|  | 		lin(); | ||||||
|  | 		lae(des, 0); | ||||||
|  | 		if (av==address) { | ||||||
|  | 			aar(); | ||||||
|  | 		} else { | ||||||
|  | 			lar(); | ||||||
|  | 			if (e->type&T_BYTE) cwv(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_addr(e) register struct expr *e; | ||||||
|  | /* The address of e is wat we want. */ | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	switch(e->kind) { | ||||||
|  | 	case E_NODE: | ||||||
|  | 		subscript(e, address); | ||||||
|  | 		break; | ||||||
|  | 	case E_VAR: {	/* variable or channel */ | ||||||
|  | 		register struct symbol *var=e->u.var; | ||||||
|  | 
 | ||||||
|  | 		if (var->type&T_BUILTIN) | ||||||
|  | 			lae(var->info.vc.st.builtin, var->info.vc.offset); | ||||||
|  | 		else | ||||||
|  | 		if (var->info.vc.st.level==curr_level) | ||||||
|  | 			if (var->type&T_PARAM | ||||||
|  | 			    && (var->type&(T_TYPE|T_ARR))!=T_VALUE) | ||||||
|  | 				Lolp(var->info.vc.offset); | ||||||
|  | 			else | ||||||
|  | 				lal(var->info.vc.offset); | ||||||
|  | 		else { | ||||||
|  | 			if (var->info.vc.offset<0) | ||||||
|  | 				lxl(curr_level-var->info.vc.st.level); | ||||||
|  | 			else | ||||||
|  | 				lxa(curr_level-var->info.vc.st.level); | ||||||
|  | 			if (var->type&T_PARAM | ||||||
|  | 			    && (var->type&(T_TYPE|T_ARR))!=T_VALUE) | ||||||
|  | 				Lofp(var->info.vc.offset); | ||||||
|  | 			else | ||||||
|  | 				adp(var->info.vc.offset); | ||||||
|  | 		} | ||||||
|  | 		} break; | ||||||
|  | 	case E_TABLE: | ||||||
|  | 	case E_BTAB: | ||||||
|  | 		laedot(e->u.tab); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_bool(e, pos, T, F) | ||||||
|  | 	register struct expr *e; | ||||||
|  | 	register pos; | ||||||
|  | 	register int *T, *F; | ||||||
|  | /* if e = pos then
 | ||||||
|  | 	fall through or jump to T; | ||||||
|  |    else | ||||||
|  | 	jump to F; | ||||||
|  |    fi | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register Default=0; | ||||||
|  | 
 | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	if (e->kind==E_NODE) { | ||||||
|  | 		register struct expr *left=e->u.node.left; | ||||||
|  | 		register struct expr *right=e->u.node.right; | ||||||
|  | 
 | ||||||
|  | 		switch(e->u.node.op) { | ||||||
|  | 		case '<': | ||||||
|  | 		case '>': | ||||||
|  | 		case LE: | ||||||
|  | 		case GE: | ||||||
|  | 		case NE: | ||||||
|  | 		case '=': | ||||||
|  | 		case AFTER: | ||||||
|  | 			code_val(left); | ||||||
|  | 			code_val(right); | ||||||
|  | 			bxx(pos, e->u.node.op, new_label(F)); | ||||||
|  | 			break; | ||||||
|  | 		case AND: | ||||||
|  | 		case OR: | ||||||
|  | 			if ((e->u.node.op==AND && pos) | ||||||
|  | 			 || (e->u.node.op==OR && !pos) | ||||||
|  | 			) { | ||||||
|  | 				int L=0; | ||||||
|  | 				code_bool(left, pos, &L, F); | ||||||
|  | 				Label(L); | ||||||
|  | 				code_bool(right, pos, T, F); | ||||||
|  | 			} else { | ||||||
|  | 				int L=0; | ||||||
|  | 				code_bool(left, !pos, &L, T); | ||||||
|  | 				Label(L); | ||||||
|  | 				code_bool(right, pos, T, F); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case NOT: | ||||||
|  | 			code_bool(left, !pos, T, F); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			Default=1; | ||||||
|  | 		} | ||||||
|  | 	} else | ||||||
|  | 		Default=1; | ||||||
|  | 
 | ||||||
|  | 	if (Default) { | ||||||
|  | 		code_val(e); | ||||||
|  | 		if (vz>wz) { | ||||||
|  | 			ldc0(); | ||||||
|  | 			cmi(); | ||||||
|  | 		} else | ||||||
|  | 			tst(); | ||||||
|  | 		if (pos) zeq(new_label(F)); else zne(new_label(F)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_assignment(e) register struct expr *e; | ||||||
|  | /* e->left := e->right */ | ||||||
|  | { | ||||||
|  | 	register struct expr *left=e->u.node.left; | ||||||
|  | 	register struct expr *right=e->u.node.right; | ||||||
|  | 
 | ||||||
|  | 	if (left->type&T_ARR) { | ||||||
|  | 		register siz=left->arr_siz; | ||||||
|  | 
 | ||||||
|  | 		code_addr(right); | ||||||
|  | 		code_addr(left); | ||||||
|  | 		blm(left->type&T_BYTE ? siz : siz*vz); | ||||||
|  | 	} else { | ||||||
|  | 		code_val(right); | ||||||
|  | 		code_addr(left); | ||||||
|  | 		sti(left->type&T_BYTE ? 1 : vz); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_input(e) register struct expr *e; | ||||||
|  | /* Input one v from c ? v0; v1; ... */ | ||||||
|  | { | ||||||
|  | 	if (e==nil) { | ||||||
|  | 		lae("any", 0); | ||||||
|  | 		cal("chan_in"); | ||||||
|  | 		asp(pz); | ||||||
|  | 	} else | ||||||
|  | 	if (e->type&T_ARR) { | ||||||
|  | 		loc(e->arr_siz); | ||||||
|  | 		code_addr(e); | ||||||
|  | 		cal(e->type&T_BYTE ? "c_ba_in" : "c_wa_in"); | ||||||
|  | 		asp(pz+wz); | ||||||
|  | 	} else { | ||||||
|  | 		code_addr(e); | ||||||
|  | 		cal(e->type&T_BYTE ? "cbyte_in" : "chan_in"); | ||||||
|  | 		asp(pz); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_output(e) register struct expr *e; | ||||||
|  | /* Output one e from c ? e0; e1; ... */ | ||||||
|  | { | ||||||
|  | 	if (e==nil) { | ||||||
|  | 		Loc(0L); | ||||||
|  | 		cal("chan_out"); | ||||||
|  | 		asp(vz); | ||||||
|  | 	} else | ||||||
|  | 	if (e->type&T_ARR) { | ||||||
|  | 		loc(e->arr_siz); | ||||||
|  | 		code_addr(e); | ||||||
|  | 		cal(e->type&T_BYTE ? "c_ba_out" : "c_wa_out"); | ||||||
|  | 		asp(pz+wz); | ||||||
|  | 	} else { | ||||||
|  | 		code_val(e); | ||||||
|  | 		cal("chan_out"); | ||||||
|  | 		asp(vz); | ||||||
|  | 	}  | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_any(e, NO) register struct expr *e; int *NO; | ||||||
|  | /* Test if the channel (push address on stack) has input. If not so remove the
 | ||||||
|  |  * channel pointer and jump to NO.  Otherwise input values. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	int YES=0; | ||||||
|  | 	register struct expr_list *elp; | ||||||
|  | 
 | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	code_addr(e->u.io.chan); | ||||||
|  | 	cal("chan_any"); | ||||||
|  | 	lfr(wz); | ||||||
|  | 	tst(); | ||||||
|  | 	zne(new_label(&YES)); | ||||||
|  | 	asp(pz); | ||||||
|  | 	branch(NO); | ||||||
|  | 	Label(YES); | ||||||
|  | 	elp=e->u.io.args; | ||||||
|  | 	while (elp!=nil) { | ||||||
|  | 		code_input(elp->arg); | ||||||
|  | 		elp=elp->next; | ||||||
|  | 	} | ||||||
|  | 	asp(pz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void code_void(e) register struct expr *e; | ||||||
|  | /* Assignment, I/O, or procedure call. */ | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	switch (e->kind) { | ||||||
|  | 	case E_NODE:	/* Must be assignment */ | ||||||
|  | 		code_assignment(e); | ||||||
|  | 		break; | ||||||
|  | 	case E_IO: { | ||||||
|  | 		register struct expr_list *elp; | ||||||
|  | 
 | ||||||
|  | 		code_addr(e->u.io.chan); | ||||||
|  | 
 | ||||||
|  | 		elp=e->u.io.args; | ||||||
|  | 		while (elp!=nil) { | ||||||
|  | 			if (e->u.io.out) | ||||||
|  | 				code_output(elp->arg); | ||||||
|  | 			else | ||||||
|  | 				code_input(elp->arg); | ||||||
|  | 			elp=elp->next; | ||||||
|  | 		} | ||||||
|  | 		asp(pz); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case E_CALL: { | ||||||
|  | 		register size=0; | ||||||
|  | 		register struct expr_list *elp=e->u.call.args; | ||||||
|  | 		register struct symbol *proc=e->u.call.proc->u.var; | ||||||
|  | 		register struct par_list *pars=proc->info.proc.pars; | ||||||
|  | 
 | ||||||
|  | 		while (elp!=nil) { | ||||||
|  | 			if (pars->type==T_VALUE) { | ||||||
|  | 				code_val(elp->arg); | ||||||
|  | 				size+=vz; | ||||||
|  | 			} else { | ||||||
|  | 				code_addr(elp->arg); | ||||||
|  | 				size+=pz; | ||||||
|  | 			} | ||||||
|  | 			elp=elp->next; | ||||||
|  | 			pars=pars->next; | ||||||
|  | 		} | ||||||
|  | 		if (proc->type&T_BUILTIN) { | ||||||
|  | 			cal(proc->info.proc.st.builtin); | ||||||
|  | 			asp(size); | ||||||
|  | 		} else { | ||||||
|  | 			if (proc->info.proc.st.level>curr_level) { | ||||||
|  | 				/* Call down */ | ||||||
|  | 				lor0(); | ||||||
|  | 			} else | ||||||
|  | 			if (proc->info.proc.st.level==curr_level) { | ||||||
|  | 				/* Call at same level */ | ||||||
|  | 				Lolp(0); | ||||||
|  | 			} else { | ||||||
|  | 				/* Call up */ | ||||||
|  | 				lxa(curr_level-proc->info.proc.st.level); | ||||||
|  | 				loi(pz); | ||||||
|  | 			} | ||||||
|  | 			cal(proc_label(proc->info.proc.label, proc->name)); | ||||||
|  | 			asp(size+pz); | ||||||
|  | 			if (proc->info.proc.file!=curr_file) fil(); | ||||||
|  | 		} | ||||||
|  | 		} break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void prologue(proc) register struct symbol *proc; | ||||||
|  | /* Open up the scope for a new proc definition. */ | ||||||
|  | { | ||||||
|  | 	static P=0; | ||||||
|  | 
 | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	proc->info.proc.st.level= ++curr_level; | ||||||
|  | 	proc->info.proc.file= curr_file; | ||||||
|  | 	proc->info.proc.label= ++P; | ||||||
|  | 	curr_offset=min_offset=0; | ||||||
|  | 	pro(proc_label(proc->info.proc.label, proc->name)); | ||||||
|  | 	if (curr_level==1) fil(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void epilogue(proc) register struct symbol *proc; | ||||||
|  | /* Close the scope of a proc def. */ | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	curr_level--; | ||||||
|  | 	ret(0); | ||||||
|  | 	_end(-min_offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void rep_init(v, e1, e2, r_info) | ||||||
|  | 	struct symbol *v; | ||||||
|  | 	register struct expr *e1, *e2; | ||||||
|  | 	register struct replicator *r_info; | ||||||
|  | /* Compile v=[e1 FOR e2].  Info tells rep_test what decisions rep_init makes. */ | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	r_info->BEGIN=r_info->END=0; | ||||||
|  | 
 | ||||||
|  | 	code_val(e1); | ||||||
|  | 	Stl(v->info.vc.offset); | ||||||
|  | 
 | ||||||
|  | 	if (!constant(e1) || !constant(e2)) { | ||||||
|  | 		if (constant(e2) && word_constant(e2->u.const)) { | ||||||
|  | 			r_info->counter=memory(wz); | ||||||
|  | 			loc((int) e2->u.const); | ||||||
|  | 			stl(r_info->counter); | ||||||
|  | 		} else { | ||||||
|  | 			r_info->counter=memory(vz); | ||||||
|  | 			code_val(e2); | ||||||
|  | 			Stl(r_info->counter); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!constant(e2) || e2->u.const<=0L) | ||||||
|  | 		branch(&r_info->END); | ||||||
|  | 	Label(new_label(&r_info->BEGIN)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void rep_test(v, e1, e2, r_info) | ||||||
|  | 	register struct symbol *v; | ||||||
|  | 	register struct expr *e1, *e2; | ||||||
|  | 	register struct replicator *r_info; | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	Inl(v->info.vc.offset); | ||||||
|  | 
 | ||||||
|  | 	if (constant(e1) && constant(e2)) { | ||||||
|  | 		Lol(v->info.vc.offset); | ||||||
|  | 		Loc(e1->u.const+e2->u.const); | ||||||
|  | 		if (vz>wz) { | ||||||
|  | 			cmi(); | ||||||
|  | 			zlt(r_info->BEGIN); | ||||||
|  | 		} else | ||||||
|  | 			blt(r_info->BEGIN); | ||||||
|  | 		Label(r_info->END); | ||||||
|  | 	} else { | ||||||
|  | 		if (constant(e2) && word_constant(e2->u.const)) { | ||||||
|  | 			del(r_info->counter); | ||||||
|  | 			Label(r_info->END); | ||||||
|  | 			lol(r_info->counter); | ||||||
|  | 			tst(); | ||||||
|  | 		} else { | ||||||
|  | 			Del(r_info->counter); | ||||||
|  | 			Label(r_info->END); | ||||||
|  | 			Lol(r_info->counter); | ||||||
|  | 			if (vz>wz) { | ||||||
|  | 				ldc0(); | ||||||
|  | 				cmi(); | ||||||
|  | 			} else | ||||||
|  | 				tst(); | ||||||
|  | 		} | ||||||
|  | 		zgt(r_info->BEGIN); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void chan_init(info, arr_siz) union type_info *info; int arr_siz; | ||||||
|  | /* Garbage disposal unit for fresh channels. */ | ||||||
|  | { | ||||||
|  | 	if (err) return; | ||||||
|  | 
 | ||||||
|  | 	loc(arr_siz); | ||||||
|  | 	lal(info->vc.offset); | ||||||
|  | 	cal("c_init"); | ||||||
|  | 	asp(wz+pz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void leader() | ||||||
|  | { | ||||||
|  | 	init(); | ||||||
|  | 	openfile((char *) nil); | ||||||
|  | 	magic(); | ||||||
|  | 	meswp(); | ||||||
|  | 	maxdes(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void header() | ||||||
|  | { | ||||||
|  | 	exp("main"); | ||||||
|  | 	pro("main"); | ||||||
|  | 	init_rt(); | ||||||
|  | 	main_fil(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void trailer() | ||||||
|  | { | ||||||
|  | 	if (err) | ||||||
|  | 		meserr(); | ||||||
|  | 	else { | ||||||
|  | 		loc(0); | ||||||
|  | 		ret(wz); | ||||||
|  | 		_end(-min_offset); | ||||||
|  | 	} | ||||||
|  | 	closefile(); | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								lang/occam/comp/code.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lang/occam/comp/code.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | struct replicator {	/* Info transferred from rep_init to rep_test */ | ||||||
|  | 	int counter; | ||||||
|  | 	int BEGIN; | ||||||
|  | 	int END; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void rep_init(), rep_test(); | ||||||
|  | 
 | ||||||
|  | void code_val(), code_addr(), code_void(); | ||||||
|  | void code_assignment(), code_input(), code_any(), code_output(); | ||||||
|  | 
 | ||||||
|  | void code_bool(); | ||||||
|  | #define positive 1	/* Use positive logic for boolean expression */ | ||||||
|  | #define negative 0	/* Use negative logic, i.e. 0 = true */ | ||||||
|  | 
 | ||||||
|  | void epilogue(), prologue(); | ||||||
|  | void leader(), header(), trailer(); | ||||||
|  | 
 | ||||||
|  | void chan_init(); | ||||||
							
								
								
									
										405
									
								
								lang/occam/comp/em.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								lang/occam/comp/em.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,405 @@ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "sizes.h" | ||||||
|  | #include "Lpars.h" | ||||||
|  | #include "em_arith.h" | ||||||
|  | #include "em_label.h" | ||||||
|  | #include "em.h" | ||||||
|  | 
 | ||||||
|  | /* This file is used to shield code.c as much as possible from em dependant
 | ||||||
|  |  * details.  It introduces some call overhead but not enough for a coffee | ||||||
|  |  * break. (Sorry) | ||||||
|  |  * Note that functions with a leading upper case letter normally decide between | ||||||
|  |  * word or double word arith. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | int wz, pz; | ||||||
|  | static Lab=0; | ||||||
|  | char *malloc(); | ||||||
|  | 
 | ||||||
|  | void init() | ||||||
|  | { | ||||||
|  | 	C_init((arith) wz, (arith) pz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void openfile(file) char *file; | ||||||
|  | { | ||||||
|  | 	C_open(file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void meswp() | ||||||
|  | { | ||||||
|  | 	C_mes_begin(2); | ||||||
|  | 	C_cst((arith) wz); | ||||||
|  | 	C_cst((arith) pz); | ||||||
|  | 	C_mes_end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void maxdes() | ||||||
|  | { | ||||||
|  | 	C_df_dnam("maxcdes"); | ||||||
|  | 	rom(wz, 0L); rom(wz, -1L); rom(wz, (long) (wz+pz)); | ||||||
|  | 	C_df_dnam("maxwdes"); | ||||||
|  | 	rom(wz, 0L); rom(wz, -1L); rom(wz, (long) vz); | ||||||
|  | 	C_df_dnam("maxbdes"); | ||||||
|  | 	rom(wz, 0L); rom(wz, -1L); rom(wz, 1L); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int new_label(L) register *L; | ||||||
|  | { | ||||||
|  | 	if (*L==0) *L= ++Lab; | ||||||
|  | 	return *L; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Label(L) register L; | ||||||
|  | { | ||||||
|  | 	if (L!=0) C_df_ilb((label) L); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static Dot_label=0; | ||||||
|  | 
 | ||||||
|  | int new_dot_label(L) int *L; | ||||||
|  | { | ||||||
|  | 	return *L= ++Dot_label; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dot_label(L) int L; | ||||||
|  | { | ||||||
|  | 	C_df_dlb((label) L); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void branch(L) int *L; | ||||||
|  | { | ||||||
|  | 	C_bra((label) new_label(L)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *proc_label(L, name) register L; register char *name; | ||||||
|  | { | ||||||
|  | 	static char *lab=nil; | ||||||
|  | 	register char *n; | ||||||
|  | 
 | ||||||
|  | 	if (lab!=nil) free(lab); | ||||||
|  | 
 | ||||||
|  | 	lab=malloc(strlen(name)+(1+sizeof(int)*3+1)); | ||||||
|  | 		/* That is: P<L><name>\0 */ | ||||||
|  | 
 | ||||||
|  | 	sprintf(lab, "P%d", L); | ||||||
|  | 
 | ||||||
|  | 	n=lab+strlen(lab); | ||||||
|  | 
 | ||||||
|  | 	while (*name!=0) { | ||||||
|  | 		*n++ = *name=='.' ? '_' : *name; | ||||||
|  | 		name++; | ||||||
|  | 	} | ||||||
|  | 	*n=0; | ||||||
|  | 	return lab; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void magic()	/* magic? should be called invisible */ | ||||||
|  | { | ||||||
|  | 	C_magic(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void cwv() | ||||||
|  | { | ||||||
|  | 	if (vz>wz) { | ||||||
|  | 		C_loc((arith) wz); | ||||||
|  | 		C_loc((arith) vz); | ||||||
|  | 		C_cii(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void cvw() | ||||||
|  | { | ||||||
|  | 	if (vz>wz) { | ||||||
|  | 		C_loc((arith) vz); | ||||||
|  | 		C_loc((arith) wz); | ||||||
|  | 		C_cii(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Loc(const) long const; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) C_ldc((arith) const); else C_loc((arith) const); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lol(offset) int offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) C_ldl((arith) offset); else C_lol((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lolp(offset) int offset; | ||||||
|  | { | ||||||
|  | 	if (pz>wz) C_ldl((arith) offset); else C_lol((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lil(offset) register offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) { | ||||||
|  | 		Lolp(offset); | ||||||
|  | 		C_loi((arith) vz); | ||||||
|  | 	} else | ||||||
|  | 		C_lil((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lof(offset) int offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) C_ldf((arith) offset); else C_lof((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lofp(offset) int offset; | ||||||
|  | { | ||||||
|  | 	if (pz>wz) C_ldf((arith) offset); else C_lof((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Lif(offset) register offset; | ||||||
|  | { | ||||||
|  | 	Lofp(offset); | ||||||
|  | 	C_loi((arith) vz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Stl(offset) int offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) C_sdl((arith) offset); else C_stl((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Inl(offset) register offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) { | ||||||
|  | 		C_ldl((arith) offset); | ||||||
|  | 		C_ldc((arith) 1); | ||||||
|  | 		C_adi((arith) vz); | ||||||
|  | 		C_sdl((arith) offset); | ||||||
|  | 	} else | ||||||
|  | 		C_inl((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Del(offset) register offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) { | ||||||
|  | 		C_ldl((arith) offset); | ||||||
|  | 		C_ldc((arith) 1); | ||||||
|  | 		C_sbi((arith) vz); | ||||||
|  | 		C_sdl((arith) offset); | ||||||
|  | 	} else | ||||||
|  | 		C_del((arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Loe(name, offset) char *name; int offset; | ||||||
|  | { | ||||||
|  | 	if (vz>wz) | ||||||
|  | 		C_lde_dnam(name, (arith) offset); | ||||||
|  | 	else | ||||||
|  | 		C_loe_dnam(name, (arith) offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef int (*pfi)(); | ||||||
|  | 
 | ||||||
|  | static int operators[]=	{ '<', '>', '=',  GE,  LE,  NE }; | ||||||
|  | 
 | ||||||
|  | extern C_blt(), C_bgt(), C_beq(), C_bge(), C_ble(), C_bne(); | ||||||
|  | extern C_tlt(), C_tgt(), C_teq(), C_tge(), C_tle(), C_tne(); | ||||||
|  | extern C_zlt(), C_zgt(), C_zeq(), C_zge(), C_zle(), C_zne(); | ||||||
|  | 
 | ||||||
|  | static pfi C_bxx[]= { C_blt, C_bgt, C_beq, C_bge, C_ble, C_bne }; | ||||||
|  | static pfi C_txx[]= { C_tlt, C_tgt, C_teq, C_tge, C_tle, C_tne }; | ||||||
|  | static pfi C_zxx[]= { C_zlt, C_zgt, C_zeq, C_zge, C_zle, C_zne }; | ||||||
|  | 
 | ||||||
|  | void bxx(pos, op, L) register pos, op, L; | ||||||
|  | { | ||||||
|  | 	register i; | ||||||
|  | 
 | ||||||
|  | 	if (op==AFTER) { | ||||||
|  | 		C_sbi((arith) vz); | ||||||
|  | 		if (vz>wz) { | ||||||
|  | 			C_ldc((arith) 0); | ||||||
|  | 			C_cmi((arith) vz); | ||||||
|  | 		} | ||||||
|  | 		if (pos) C_zle((label) L); else C_zgt((label) L); | ||||||
|  | 	} else { | ||||||
|  | 		for (i=0; operators[i]!=op; i++) ; | ||||||
|  | 		if (pos && (i+=3)>=6) i-=6; | ||||||
|  | 		if (vz>wz) { | ||||||
|  | 			C_cmi((arith) vz); | ||||||
|  | 			(C_zxx[i])((label) L); | ||||||
|  | 		} else { | ||||||
|  | 			(C_bxx[i])((label) L); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Txx(op) register int op; | ||||||
|  | { | ||||||
|  | 	register i; | ||||||
|  | 
 | ||||||
|  | 	for (i=0; operators[i]!=op; i++) ; | ||||||
|  | 
 | ||||||
|  | 	(C_txx[i])(); | ||||||
|  | 	cwv(); | ||||||
|  | 	C_ngi((arith) vz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extern C_adi(), C_sbi(), C_mli(), C_dvi(), C_rmi(); | ||||||
|  | 
 | ||||||
|  | void xxi(op) register op; | ||||||
|  | { | ||||||
|  | 	static int operators[]=	{ '+',   '-',   '*',   '/',   BS }; | ||||||
|  | 	static pfi C_xxi[]=	{ C_adi, C_sbi, C_mli, C_dvi, C_rmi }; | ||||||
|  | 	register i; | ||||||
|  | 
 | ||||||
|  | 	for (i=0; operators[i]!=op; i++) ; | ||||||
|  | 
 | ||||||
|  | 	(C_xxi[i])((arith) vz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void aar()			{	C_aar((arith) wz); } | ||||||
|  | void adp(offset) int offset;	{	C_adp((arith) offset); } | ||||||
|  | void and()			{	C_and((arith) vz); } | ||||||
|  | void asp(size) int size;	{	C_asp((arith) size); } | ||||||
|  | void blm(size) int size;	{	C_blm((arith) size); } | ||||||
|  | void blt(lab) int lab;		{	C_blt((label) lab); } | ||||||
|  | void cal(lab) char *lab;	{	C_cal(lab); } | ||||||
|  | void cmi()			{	C_cmi((arith) vz); } | ||||||
|  | void com()			{	C_com((arith) vz); } | ||||||
|  | void del(offset) int offset;	{	C_del((arith) offset); } | ||||||
|  | void _end(size) int size;	{	C_end((arith) size); } | ||||||
|  | void exp(lab) char *lab;	{	C_exp(lab); } | ||||||
|  | void ior()			{	C_ior((arith) vz); } | ||||||
|  | void lae(lab, offset) char *lab; int offset; | ||||||
|  | 				{	C_lae_dnam(lab, (arith) offset); } | ||||||
|  | void laedot(lab) int lab;	{	C_lae_dlb((label) lab, (arith) 0); } | ||||||
|  | void lal(offset) int offset;	{	C_lal((arith) offset); } | ||||||
|  | void lar()			{	C_lar((arith) wz); } | ||||||
|  | void ldc0()			{	C_ldc((arith) 0); } | ||||||
|  | void ldl(offset) int offset;	{	C_ldl((arith) offset); } | ||||||
|  | void lfr(size) int size;	{	C_lfr((arith) size); } | ||||||
|  | void loc(cst) int cst;		{	C_loc((arith) cst); } | ||||||
|  | void loi(size) int size;	{	C_loi((arith) size); } | ||||||
|  | void lol(offset) int offset;	{	C_lol((arith) offset); } | ||||||
|  | void lor0()			{	C_lor((arith) 0); } | ||||||
|  | void lxa(offset) int offset;	{	C_lxa((arith) offset); } | ||||||
|  | void lxl(offset) int offset;	{	C_lxl((arith) offset); } | ||||||
|  | void meserr()			{	C_mes_begin(0); C_mes_end(); } | ||||||
|  | void ngi()			{	C_ngi((arith) vz); } | ||||||
|  | void pro(lab) char *lab;	{	C_pro_narg(lab); } | ||||||
|  | void ret(size) int size;	{	C_ret((arith) size); } | ||||||
|  | void init_rt()			{	C_cal("init");	} | ||||||
|  | void sli()			{	C_sli((arith) vz); } | ||||||
|  | void sri()			{	C_sri((arith) vz); } | ||||||
|  | void ste(lab, offset) char *lab; int offset; | ||||||
|  | 				{	C_ste_dnam(lab, (arith) offset); } | ||||||
|  | void sti(size) int size;	{	C_sti((arith) size); } | ||||||
|  | void stl(offset) int offset;	{	C_stl((arith) offset); } | ||||||
|  | void trp()			{	C_trp(); } | ||||||
|  | void tst()			{	/* No flags in EM */ } | ||||||
|  | void xor()			{	C_xor((arith) vz); } | ||||||
|  | void zeq(lab) int lab;		{	C_zeq((label) lab); } | ||||||
|  | void zgt(lab) int lab;		{	C_zgt((label) lab); } | ||||||
|  | void zlt(lab) int lab;		{	C_zlt((label) lab); } | ||||||
|  | void zne(lab) int lab;		{	C_zne((label) lab); } | ||||||
|  | 
 | ||||||
|  | char *itoa(i) long i; | ||||||
|  | { | ||||||
|  | 	static char a[sizeof(long)*3]; | ||||||
|  | 	sprintf(a, "%D", i); | ||||||
|  | 	return a; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void rom(size, c) int size; long c; | ||||||
|  | { | ||||||
|  | 	C_rom_icon(itoa(c), (arith) size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void lin() | ||||||
|  | { | ||||||
|  | 	static oldline=0; | ||||||
|  | 	extern yylineno; | ||||||
|  | 
 | ||||||
|  | 	if (yylineno!=oldline) | ||||||
|  | 		C_lin((arith) (oldline=yylineno)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct ftree { | ||||||
|  | 	char *file; | ||||||
|  | 	int lab; | ||||||
|  | 	struct ftree *left, *right; | ||||||
|  | } std_f = { "stdin", 0, nil, nil }, *curr_f= &std_f, *main_f=nil; | ||||||
|  | 
 | ||||||
|  | char *curr_file="stdin"; | ||||||
|  | 
 | ||||||
|  | static void do_fil(f) struct ftree *f; | ||||||
|  | { | ||||||
|  | 	if (f->lab==0) { | ||||||
|  | 		dot_label(new_dot_label(&f->lab)); | ||||||
|  | 		C_rom_scon(f->file, (arith) strlen(f->file)); | ||||||
|  | 	} | ||||||
|  | 	C_fil_dlb((label) f->lab); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void fil() | ||||||
|  | { | ||||||
|  | 	do_fil(curr_f); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void main_fil() | ||||||
|  | { | ||||||
|  | 	do_fil(main_f==nil ? &std_f : main_f); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int set_file(f) char *f; | ||||||
|  | { | ||||||
|  | 	char *strcpy(); | ||||||
|  | 	static struct ftree *ftop=nil; | ||||||
|  | 	register struct ftree *pf, **apf= &ftop; | ||||||
|  | 	register cmp; | ||||||
|  | 
 | ||||||
|  | 	while ((pf= *apf)!=nil && (cmp=strcmp(f, pf->file))!=0) | ||||||
|  | 		apf= cmp<0 ? &pf->left : &pf->right; | ||||||
|  | 
 | ||||||
|  | 	if (pf==nil) { | ||||||
|  | 		*apf= pf= (struct ftree *) malloc(sizeof *pf); | ||||||
|  | 		pf->file=strcpy(malloc(strlen(f)+1), f); | ||||||
|  | 		pf->lab=0; | ||||||
|  | 		pf->left=pf->right=nil; | ||||||
|  | 	} | ||||||
|  | 	curr_f=pf; | ||||||
|  | 	curr_file=pf->file; | ||||||
|  | 	if (main_f==nil) { | ||||||
|  | 		main_f=curr_f; | ||||||
|  | 		return 0; | ||||||
|  | 	} else | ||||||
|  | 		return curr_f!=main_f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void par_begin() | ||||||
|  | { | ||||||
|  | 	C_lal((arith) curr_offset); | ||||||
|  | 	C_cal("pc_begin"); | ||||||
|  | 	C_asp((arith) pz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void par_fork(NONZERO) int *NONZERO; | ||||||
|  | { | ||||||
|  | 	C_cal("pc_fork"); | ||||||
|  | 	C_lfr((arith) wz); | ||||||
|  | 	C_zne((label) new_label(NONZERO)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void resumenext() | ||||||
|  | { | ||||||
|  | 	C_cal("resumene"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void no_deadlock() | ||||||
|  | { | ||||||
|  | 	C_zre_dnam("deadlock", (arith) 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void par_end() | ||||||
|  | { | ||||||
|  | 	C_cal("parend"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void closefile() | ||||||
|  | { | ||||||
|  | 	C_close(); | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								lang/occam/comp/em.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lang/occam/comp/em.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | #ifndef nil | ||||||
|  | #define nil 0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define word_constant(c)	(-32768L<=(c) && (c)<=32767L) | ||||||
|  | void Label(), dot_label(), branch(); | ||||||
|  | int new_label(), new_dot_label(); | ||||||
|  | char *proc_label(); | ||||||
|  | extern char *curr_file; | ||||||
|  | 
 | ||||||
|  | void cwv(), cvw(); | ||||||
|  | void bxx(), Loc(), Lol(), Lolp(), Lil(), Lof(), Lofp(), Lif(); | ||||||
|  | void Txx(), xxi(), Stl(), Inl(), Del(), Loe(); | ||||||
|  | void cmi(), ngi(), and(), ior(), xor(), sli(), sri(), com(), lar(), lxl(); | ||||||
|  | void lxa(), lfr(), ste(), lae(), aar(), lal(), adp(), ldc0(), zeq(), zne(); | ||||||
|  | void zlt(), zgt(), blm(), sti(), cal(), asp(), loc(), lor0(), loi(), pro(); | ||||||
|  | void ret(), _end(), stl(), laedot(), del(), lol(), ldl(), meswp(), meserr(); | ||||||
|  | void init_rt(), exp(), rom(), blt(), magic(), lin(), tst(), fil(), trp(); | ||||||
|  | void main_fil(), init(), openfile(), closefile(), maxdes(); | ||||||
|  | 
 | ||||||
|  | void par_begin(), par_fork(), par_end(), resumenext(), no_deadlock(); | ||||||
							
								
								
									
										471
									
								
								lang/occam/comp/expr.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										471
									
								
								lang/occam/comp/expr.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,471 @@ | ||||||
|  | #include "symtab.h" | ||||||
|  | #include "sizes.h" | ||||||
|  | #include "expr.h" | ||||||
|  | #include "Lpars.h" | ||||||
|  | 
 | ||||||
|  | static void rvalue(), assignable(), inputable(), outputable(), subscriptable(); | ||||||
|  | static void assigned(); | ||||||
|  | 
 | ||||||
|  | /* The new_* functions make use of the used() and assinged() functions to
 | ||||||
|  |  * make known what is done to a variable. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct expr *new_node(op, left, right, byte) | ||||||
|  | 	int op; | ||||||
|  | 	register struct expr *left, *right; | ||||||
|  | 	int byte; | ||||||
|  | /* Makes a new node with given operator, left and right operand.
 | ||||||
|  |  * Constant folding is done if possible. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	if (op!=FOR && constant(left) && (right==nil || constant(right))) { | ||||||
|  | 		register long lc, rc; | ||||||
|  | 
 | ||||||
|  | 		lc=left->u.const; | ||||||
|  | 		rc=right->u.const; | ||||||
|  | 
 | ||||||
|  | 		switch (op) { | ||||||
|  | 		case '+':	lc+=rc; break; | ||||||
|  | 		case '-':	lc-=rc; break; | ||||||
|  | 		case '*':	lc*=rc; break; | ||||||
|  | 		case '/':	if (rc==0L) | ||||||
|  | 					report("division by zero"); | ||||||
|  | 				else | ||||||
|  | 					lc/=rc; | ||||||
|  | 				break; | ||||||
|  | 		case BS:	lc%=rc; break; | ||||||
|  | 		case '<':	lc= lc<rc ? -1L : 0L; break; | ||||||
|  | 		case '>':	lc= lc>rc ? -1L : 0L; break; | ||||||
|  | 		case LE:	lc= lc<=rc ? -1L : 0L; break; | ||||||
|  | 		case GE:	lc= lc>=rc ? -1L : 0L; break; | ||||||
|  | 		case NE:	lc= lc!=rc ? -1L : 0L; break; | ||||||
|  | 		case '=':	lc= lc==rc ? -1L : 0L; break; | ||||||
|  | 		case AFTER:	lc= (lc-rc)>0 ? -1L : 0L; break; | ||||||
|  | 		case BA:	lc&=rc; break; | ||||||
|  | 		case BO:	lc|=rc; break; | ||||||
|  | 		case BX:	lc^=rc; break; | ||||||
|  | 		case AND:	lc= lc&&rc ? -1L : 0L; break; | ||||||
|  | 		case OR:	lc= lc||rc ? -1L : 0L; break; | ||||||
|  | 		case LS:	lc<<=rc; break; | ||||||
|  | 		case RS:	lc>>=rc; break; | ||||||
|  | 		case '~':	lc= -lc; break; | ||||||
|  | 		case NOT:	lc= ~lc; break; | ||||||
|  | 		default: | ||||||
|  | 			report("illegal operator on constants"); | ||||||
|  | 		} | ||||||
|  | 		destroy(right); | ||||||
|  | 
 | ||||||
|  | 		left->u.const=lc; | ||||||
|  | 		return left; | ||||||
|  | 	} else { | ||||||
|  | 		register struct expr *pe; | ||||||
|  | 		int type=0, arr_siz=1; | ||||||
|  | 
 | ||||||
|  | 		switch (op) { | ||||||
|  | 		case '+':	case '-':	case '*':	case '/': | ||||||
|  | 		case BS:	case '<':	case '>':	case LE: | ||||||
|  | 		case GE:	case NE:	case '=':	case AFTER: | ||||||
|  | 		case BA:	case BO:	case BX:	case AND: | ||||||
|  | 		case OR:	case LS:	case RS: | ||||||
|  | 			rvalue(left); | ||||||
|  | 			rvalue(right); | ||||||
|  | 			type=T_VALUE; | ||||||
|  | 			break; | ||||||
|  | 		case '~': | ||||||
|  | 		case NOT: | ||||||
|  | 			rvalue(left); | ||||||
|  | 			type=T_VALUE; | ||||||
|  | 			break; | ||||||
|  | 		case AS: | ||||||
|  | 			assignable(left, right); | ||||||
|  | 			type=T_VOID; | ||||||
|  | 			break; | ||||||
|  | 		case '[': | ||||||
|  | 			subscriptable(left, right, byte, &type, &arr_siz); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 		pe->kind=E_NODE; | ||||||
|  | 		pe->type=type; | ||||||
|  | 		pe->arr_siz=arr_siz; | ||||||
|  | 		pe->u.node.op=op; | ||||||
|  | 		pe->u.node.left=left; | ||||||
|  | 		pe->u.node.right=right; | ||||||
|  | 
 | ||||||
|  | 		return pe; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_var(var) | ||||||
|  | 	register struct symbol *var; | ||||||
|  | /* Given a variable an expression node is constructed.  Note the changes in
 | ||||||
|  |  * type!  T_VAR becomes T_VALUE with flag T_LVALUE. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=E_VAR; | ||||||
|  | 
 | ||||||
|  | 	if ((var->type&T_TYPE)==T_VAR || var->type&T_NOTDECL) { | ||||||
|  | 		pe->type=(var->type&(~T_TYPE)); | ||||||
|  | 		pe->type|=T_VALUE|T_LVALUE; | ||||||
|  | 	} else | ||||||
|  | 		pe->type=var->type; | ||||||
|  | 
 | ||||||
|  | 	pe->arr_siz=var->arr_siz; | ||||||
|  | 
 | ||||||
|  | 	pe->u.var=var; | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_const(const) | ||||||
|  | 	long const; | ||||||
|  | /* Make a constant, which is a VALUE, of course. */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=E_CONST; | ||||||
|  | 	pe->type=T_VALUE; | ||||||
|  | 	pe->u.const=const; | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_table(kind, tab) | ||||||
|  | 	register kind; | ||||||
|  | 	register struct table *tab; | ||||||
|  | /* One table is being made, it is no doubt a VALUEd ARRay, but maybe even a
 | ||||||
|  |  * BYTE array.  A label is reserved for it and the individual elements are | ||||||
|  |  * rommified. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=kind; | ||||||
|  | 	pe->type=T_VALUE|T_ARR; | ||||||
|  | 	if (kind==E_BTAB) pe->type|=T_BYTE; | ||||||
|  | 	dot_label(new_dot_label(&pe->u.tab)); | ||||||
|  | 
 | ||||||
|  | 	pe->arr_siz=0; | ||||||
|  | 	while (tab!=nil) { | ||||||
|  | 		register struct table *junk=tab; | ||||||
|  | 		 | ||||||
|  | 		rom(kind==E_BTAB ? 1 : vz, tab->val); | ||||||
|  | 
 | ||||||
|  | 		tab=tab->next; | ||||||
|  | 		pe->arr_siz++; | ||||||
|  | 		free(junk); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *copy_const(e) struct expr *e; | ||||||
|  | /* If you double it up, you've got one you can throw away.  (Or do something
 | ||||||
|  |  * useful with). | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct expr *c; | ||||||
|  | 
 | ||||||
|  | 	c= (struct expr *) malloc(sizeof *c); | ||||||
|  | 
 | ||||||
|  | 	*c= *e; | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_now() | ||||||
|  | /* Now is the time to make a VALUE cell for the clock. */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=E_NOW; | ||||||
|  | 	pe->type=T_VALUE; | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_io(out, chan, args) | ||||||
|  | 	int out; | ||||||
|  | 	register struct expr *chan; | ||||||
|  | 	struct expr_list *args; | ||||||
|  | /* Either c ? v0; v1; v2; ... (out=0) or c ! e0; e1; e2; ... (out=1). */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	if ( ( (chan->type&T_TYPE) != T_CHAN || (chan->type&T_ARR) ) | ||||||
|  | 		&& ! (chan->type&T_NOTDECL) | ||||||
|  | 	) | ||||||
|  | 		report("channel variable expected"); | ||||||
|  | 	used(chan); | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=E_IO; | ||||||
|  | 	pe->type=T_VOID; | ||||||
|  | 	pe->u.io.out=out; | ||||||
|  | 	pe->u.io.chan=chan; | ||||||
|  | 	pe->u.io.args=args; | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct expr *new_call(proc, args) | ||||||
|  | 	struct expr *proc; | ||||||
|  | 	struct expr_list *args; | ||||||
|  | /* Dial proc(arg1, arg2, ...) and you'll hear the tone of this function.
 | ||||||
|  |  * Dialing yourself is not allowed, but it will work if you ignore the | ||||||
|  |  * compiler generated noise. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct expr *pe; | ||||||
|  | 
 | ||||||
|  | 	pe= (struct expr *) malloc(sizeof *pe); | ||||||
|  | 
 | ||||||
|  | 	used(proc); | ||||||
|  | 
 | ||||||
|  | 	check_recursion(proc); | ||||||
|  | 
 | ||||||
|  | 	pe->kind=E_CALL; | ||||||
|  | 	pe->type=T_VOID; | ||||||
|  | 	pe->u.call.proc=proc; | ||||||
|  | 	pe->u.call.args=args; | ||||||
|  | 
 | ||||||
|  | 	return pe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void table_add(aapt, val) register struct table ***aapt; long val; | ||||||
|  | /* Adds a value to a table using a hook to a hook. */ | ||||||
|  | { | ||||||
|  | 	register struct table *pt; | ||||||
|  | 
 | ||||||
|  | 	pt= (struct table *) malloc(sizeof *pt); | ||||||
|  | 
 | ||||||
|  | 	pt->val=val; | ||||||
|  | 	pt->next= **aapt; | ||||||
|  | 
 | ||||||
|  | 	**aapt=pt; | ||||||
|  | 	*aapt= &pt->next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void expr_list_add(aaelp, arg) | ||||||
|  | 	register struct expr_list ***aaelp; | ||||||
|  | 	struct expr *arg; | ||||||
|  | /* Another add, this time for actual arguments and the like. */ | ||||||
|  | { | ||||||
|  | 	register struct expr_list *elp; | ||||||
|  | 
 | ||||||
|  | 	elp= (struct expr_list *) malloc(sizeof *elp); | ||||||
|  | 
 | ||||||
|  | 	elp->arg=arg; | ||||||
|  | 	elp->next= **aaelp; | ||||||
|  | 	**aaelp=elp; | ||||||
|  | 	*aaelp= &elp->next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_io(out, arg) int out; struct expr *arg; | ||||||
|  | { | ||||||
|  | 	if (out) | ||||||
|  | 		outputable(arg); | ||||||
|  | 	else | ||||||
|  | 		inputable(arg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_wait(e) struct expr *e; | ||||||
|  | { | ||||||
|  | 	if ((e->type&T_TYPE)!=T_VALUE) | ||||||
|  | 		report("WAIT process needs valued operand"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void assigned(e) register struct expr *e; | ||||||
|  | /* Tries to tell e that it is assigned to. */ | ||||||
|  | { | ||||||
|  | 	if (e->kind==E_VAR || (e->kind==E_NODE && e->u.node.op=='[' | ||||||
|  | 		&& (e=e->u.node.left)->kind==E_VAR) | ||||||
|  | 	) { | ||||||
|  | 		register struct symbol *var; | ||||||
|  | 
 | ||||||
|  | 		if ((var=e->u.var)->type&T_REP) { | ||||||
|  | 			warning("replicator index %s may not be assigned", | ||||||
|  | 				var->name); | ||||||
|  | 			var->type&= ~T_REP; | ||||||
|  | 		} | ||||||
|  | 		var->type|=T_ASSIGNED; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void used(e) register struct expr *e; | ||||||
|  | { | ||||||
|  | 	if (e->kind==E_VAR || (e->kind==E_NODE && e->u.node.op=='[' | ||||||
|  | 		&& (e=e->u.node.left)->kind==E_VAR) | ||||||
|  | 	) { | ||||||
|  | 		register struct symbol *var; | ||||||
|  | 
 | ||||||
|  | 		if ( ! ( (var=e->u.var)->type&(T_ASSIGNED|T_BUILTIN)) | ||||||
|  | 		    && (var->type&T_TYPE)==T_VAR | ||||||
|  | 		    && var->info.vc.st.level==curr_level) | ||||||
|  | 			warning("%s used before assigned", var->name); | ||||||
|  | 		var->type|=(T_USED|T_ASSIGNED); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void rvalue(e) register struct expr *e; | ||||||
|  | { | ||||||
|  | 	if ((e->type&T_TYPE)!=T_VALUE || e->type&T_ARR) | ||||||
|  | 		report("illegal operand of arithmetic operator"); | ||||||
|  | 	used(e); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void assignable(l, r) register struct expr *l, *r; | ||||||
|  | /* See if l can be assigned r. */ | ||||||
|  | { | ||||||
|  | 	if ( ! ( (l->type&T_LVALUE && (r->type&T_TYPE)==T_VALUE | ||||||
|  | 		  && (l->type&T_ARR)==(r->type&T_ARR)) | ||||||
|  | 		|| (l->type|r->type)&T_NOTDECL | ||||||
|  | 	)) | ||||||
|  | 		report("operands of assignment are not conformable"); | ||||||
|  | 	else | ||||||
|  | 	if (l->type&T_ARR && ! ( (l->type|r->type)&T_NOTDECL ) ) { | ||||||
|  | 		register lsiz=l->arr_siz, rsiz=r->arr_siz; | ||||||
|  | 
 | ||||||
|  | 		if (lsiz!=0 && rsiz!=0 && lsiz!=rsiz) | ||||||
|  | 			report("arrays have incompatible sizes"); | ||||||
|  | 	} | ||||||
|  | 	used(r); | ||||||
|  | 	assigned(l); | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void inputable(e) struct expr *e; | ||||||
|  | { | ||||||
|  | 	if ( ! (e->type&T_LVALUE) ) | ||||||
|  | 		report("operand of input process can't be assigned"); | ||||||
|  | 
 | ||||||
|  | 	assigned(e); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void outputable(e) struct expr *e; | ||||||
|  | { | ||||||
|  | 	if ( ! ( (e->type&T_TYPE)==T_VALUE ) ) | ||||||
|  | 		report("operand of output process has no value"); | ||||||
|  | 	used(e); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subscriptable(l, r, byte, atype, arr_siz) | ||||||
|  | 	register struct expr *l, *r; | ||||||
|  | 	register byte; | ||||||
|  | 	int *atype, *arr_siz; | ||||||
|  | /* Tries to subscript l by r, returning type and array size for slices. */ | ||||||
|  | { | ||||||
|  | 	register type= (l->type&T_TYPE)|byte; | ||||||
|  | 
 | ||||||
|  | 	if ( !(l->type&(T_ARR|T_NOTDECL) ) ) | ||||||
|  | 		report("indexing on a non-array"); | ||||||
|  | 	else | ||||||
|  | 	if ( ! ( (r->type&T_TYPE)==T_VALUE | ||||||
|  | 		|| (r->kind==E_NODE && r->u.node.op==FOR) | ||||||
|  | 	) ) | ||||||
|  | 		report("index is not computable"); | ||||||
|  | 
 | ||||||
|  | 	type|=(l->type&T_LVALUE); | ||||||
|  | 
 | ||||||
|  | 	if (r->kind==E_NODE && r->u.node.op==FOR) { | ||||||
|  | 		type|=T_ARR; | ||||||
|  | 		if (r->u.node.right->kind!=E_CONST) | ||||||
|  | 			report("slice must be of constant size"); | ||||||
|  | 		else | ||||||
|  | 			*arr_siz=r->u.node.right->u.const; | ||||||
|  | 		used(r->u.node.left); | ||||||
|  | 	} else | ||||||
|  | 		used(r); | ||||||
|  | 	*atype=type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_param(aform, act, err) | ||||||
|  | 	struct par_list **aform; | ||||||
|  | 	register struct expr *act; | ||||||
|  | 	int *err; | ||||||
|  | /* Test if formal parameter *aform corresponds with actual act.  Err returns
 | ||||||
|  |  * error status.  The aform hook is set to the next formal after the check. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct par_list *form= *aform; | ||||||
|  | 	register struct expr *left; | ||||||
|  | 	register struct symbol *var; | ||||||
|  | 	static char NONCORR[]="actual and formal parameter don't correspond"; | ||||||
|  | 
 | ||||||
|  | 	if (form==nil) { | ||||||
|  | 		if (! *err) { | ||||||
|  | 			report("too many actual parameters"); | ||||||
|  | 			*err=1; | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((form->type&T_ARR)!=(act->type&T_ARR) && !(act->type&T_NOTDECL) ) { | ||||||
|  | 			report(NONCORR); | ||||||
|  | 	} else { | ||||||
|  | 		switch (form->type&T_TYPE) { | ||||||
|  | 		case T_VAR: | ||||||
|  | 			if ( ! ( | ||||||
|  | 				(act->type&T_TYPE)==T_VALUE | ||||||
|  | 				&& act->type&T_LVALUE | ||||||
|  | 				&& !(act->type&T_BYTE) | ||||||
|  | 			)) | ||||||
|  | 				report(NONCORR); | ||||||
|  | 			assigned(act); | ||||||
|  | 			used(act); | ||||||
|  | 			break; | ||||||
|  | 		case T_CHAN: | ||||||
|  | 			if((act->type&T_TYPE)!=T_CHAN && !(act->type&T_NOTDECL)) | ||||||
|  | 				report(NONCORR); | ||||||
|  | 			used(act); | ||||||
|  | 			break; | ||||||
|  | 		case T_VALUE: | ||||||
|  | 			if ((act->type&T_TYPE)!=T_VALUE) | ||||||
|  | 				report(NONCORR); | ||||||
|  | 			used(act); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	*aform= form->next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void destroy(e) register struct expr *e; | ||||||
|  | /* Opposite of making. */ | ||||||
|  | { | ||||||
|  | 	if (e!=nil) { | ||||||
|  | 		switch (e->kind) { | ||||||
|  | 		case E_NODE: | ||||||
|  | 			destroy(e->u.node.left); | ||||||
|  | 			destroy(e->u.node.right); | ||||||
|  | 			break; | ||||||
|  | 		case E_IO: | ||||||
|  | 		case E_CALL: | ||||||
|  | 			destroy(e->kind==E_IO ? e->u.io.chan : e->u.call.proc); | ||||||
|  | 			{ | ||||||
|  | 				register struct expr_list *elp, *junk; | ||||||
|  | 
 | ||||||
|  | 				elp= e->kind==E_IO ? e->u.io.args : e->u.call.args; | ||||||
|  | 
 | ||||||
|  | 				while (elp!=nil) { | ||||||
|  | 					destroy(elp->arg); | ||||||
|  | 					junk=elp; | ||||||
|  | 					elp=elp->next; | ||||||
|  | 					free(junk); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		free(e); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								lang/occam/comp/expr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lang/occam/comp/expr.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | #define E_NODE	0 | ||||||
|  | #define E_VAR	1	/* Variable *or* channel */ | ||||||
|  | #define E_CONST	2 | ||||||
|  | #define E_TABLE	3 | ||||||
|  | #define E_BTAB	4 | ||||||
|  | #define E_NOW	5 | ||||||
|  | #define E_IO	6 | ||||||
|  | #define E_CALL	7 | ||||||
|  | 
 | ||||||
|  | struct table { | ||||||
|  | 	long	val; | ||||||
|  | 	struct table	*next; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct expr; | ||||||
|  | 
 | ||||||
|  | struct expr_list { | ||||||
|  | 	struct expr *arg; | ||||||
|  | 	struct expr_list	*next; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct expr { | ||||||
|  | 	short kind; | ||||||
|  | 	short type; | ||||||
|  | 	int arr_siz; | ||||||
|  | 	union { | ||||||
|  | 		struct { | ||||||
|  | 			int op; | ||||||
|  | 			struct expr *left, *right; | ||||||
|  | 		} node; | ||||||
|  | 
 | ||||||
|  | 		struct symbol *var; | ||||||
|  | 
 | ||||||
|  | 		long const; | ||||||
|  | 
 | ||||||
|  | 		int tab; | ||||||
|  | 
 | ||||||
|  | 		struct { | ||||||
|  | 			int out; | ||||||
|  | 			struct expr *chan; | ||||||
|  | 			struct expr_list *args; | ||||||
|  | 		} io; | ||||||
|  | 
 | ||||||
|  | 		struct { | ||||||
|  | 			struct expr *proc; | ||||||
|  | 			struct expr_list *args; | ||||||
|  | 		} call; | ||||||
|  | 	} u; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct expr *new_node(), *new_var(), *new_const(), *new_table(), *new_now(); | ||||||
|  | struct expr *new_io(), *new_call(), *copy_const(); | ||||||
|  | void table_add(), expr_list_add(); | ||||||
|  | void check_param(), check_io(), check_wait(); | ||||||
|  | void destroy(), used(); | ||||||
|  | 
 | ||||||
|  | #define valueless(e)		(((e)->type&T_TYPE)==T_VOID) | ||||||
|  | #define valued(e)		(((e)->type&T_TYPE)==T_VALUE) | ||||||
|  | #define input_process(e)	((e)->kind==E_IO && !(e)->u.io.out) | ||||||
|  | #define constant(e)		((e)->kind==E_CONST) | ||||||
|  | #define arr_constant(e)		((e)->kind==E_TABLE || (e)->kind==E_BTAB) | ||||||
							
								
								
									
										82
									
								
								lang/occam/comp/keytab.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								lang/occam/comp/keytab.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | ||||||
|  | /*		keytab.c		*/ | ||||||
|  | # include "Lpars.h" | ||||||
|  | # include <ctype.h> | ||||||
|  | 
 | ||||||
|  | # define NKEYWORDS	((sizeof keytab) / (sizeof *keytab)) | ||||||
|  | # define MAXKEYLEN	8 | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	int k_token; | ||||||
|  | 	char *k_str; | ||||||
|  | } KTAB; | ||||||
|  | 
 | ||||||
|  | KTAB keytab[] = { | ||||||
|  | 	{ AFTER,	"AFTER"	   }, { ALLOCATE,	"ALLOCATE" }, | ||||||
|  | 	{ ALT,		"ALT" 	   }, { AND,		"AND" 	   }, | ||||||
|  | 	{ ANY,		"ANY" 	   }, { BYTE,		"BYTE" 	   }, | ||||||
|  | 	{ CHAN,		"CHAN"	   }, { DEF,		"DEF"	   }, | ||||||
|  | 	{ FALSE,	"FALSE"	   }, { FOR,		"FOR"	   }, | ||||||
|  | 	{ IF,		"IF"	   }, { LOAD,		"LOAD"	   }, | ||||||
|  | 	{ NOT,		"NOT"	   }, { NOW,		"NOW"	   }, | ||||||
|  | 	{ OR,		"OR"	   }, { PAR,		"PAR"	   }, | ||||||
|  | 	{ PLACED,	"PLACED"   }, { PORT,		"PORT"	   }, | ||||||
|  | 	{ PRI,		"PRI"	   }, { PROC,		"PROC"	   }, | ||||||
|  | 	{ SEQ,		"SEQ"	   }, { SKIP,		"SKIP"	   }, | ||||||
|  | 	{ TABLE,	"TABLE"	   }, { TRUE,		"TRUE"	   }, | ||||||
|  | 	{ VALUE,	"VALUE"	   }, { VAR,		"VAR"	   }, | ||||||
|  | 	{ WAIT,		"WAIT"	   }, { WHILE,		"WHILE"	   }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	The table of keywords is searched for the occurence of `str', | ||||||
|  |  *	if found the corresponding token number is returned, | ||||||
|  |  *	otherwise IDENTIFIER is the returned token number. | ||||||
|  |  */ | ||||||
|  | keyword(str) char *str; | ||||||
|  | { | ||||||
|  | 	register int high= NKEYWORDS-1; | ||||||
|  | 	register int low= 0; | ||||||
|  | 	register int i, cmp; | ||||||
|  | 	char *lowerupper(); | ||||||
|  | 	register char *key; | ||||||
|  | 
 | ||||||
|  | 	if ((key=lowerupper(str))==0) return IDENTIFIER; | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		i= (high+low) / 2; | ||||||
|  | 		if ((cmp= strcmp(key, keytab[i].k_str)) == 0) break; | ||||||
|  | 		else if (cmp > 0) low= i+1; | ||||||
|  | 		else high= i-1; | ||||||
|  | 	} while (low <= high); | ||||||
|  | 	 | ||||||
|  | 	return low<=high ? keytab[i].k_token : IDENTIFIER; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *lowerupper(str) register char *str; | ||||||
|  | { | ||||||
|  | 	static char keyword[MAXKEYLEN+1]; | ||||||
|  | 	register char *key=keyword; | ||||||
|  | 
 | ||||||
|  | 	if (islower(*str)) { | ||||||
|  | 		do | ||||||
|  | 			*key++ = toupper(*str++); | ||||||
|  | 		while (key<keyword+MAXKEYLEN && islower(*str)); | ||||||
|  | 	} else { | ||||||
|  | 		do | ||||||
|  | 			*key++ = *str++; | ||||||
|  | 		while (key<keyword+MAXKEYLEN && isupper(*str)); | ||||||
|  | 	} | ||||||
|  | 	*key=0; | ||||||
|  | 
 | ||||||
|  | 	return *str==0 ? keyword : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *keyname(key) register int key; | ||||||
|  | { | ||||||
|  | 	register KTAB *kp; | ||||||
|  | 
 | ||||||
|  | 	for (kp= keytab; kp< keytab+NKEYWORDS; kp++) | ||||||
|  | 		if (kp->k_token == key) return kp->k_str; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										344
									
								
								lang/occam/comp/lex.l
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								lang/occam/comp/lex.l
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,344 @@ | ||||||
|  | %{ | ||||||
|  | /*	lex.l		*/ | ||||||
|  | # include <ctype.h> | ||||||
|  | # include "token.h" | ||||||
|  | # include "Lpars.h" | ||||||
|  | 
 | ||||||
|  | # define TAB	8	/* Size of a acsii tab (\t) in spaces */ | ||||||
|  | # if (TAB&(TAB-1))!=0 | ||||||
|  | # define TABSTOP(ind)	((ind)+TAB-(ind)%TAB) | ||||||
|  | # else | ||||||
|  | # define TABSTOP(ind)	(((ind)+TAB)&(~(TAB-1))) | ||||||
|  | # endif | ||||||
|  | 
 | ||||||
|  | char *malloc(), *strcpy(); | ||||||
|  | 
 | ||||||
|  | struct token token; | ||||||
|  | int ind=0;		/* Indentation level of current line */ | ||||||
|  | static int tab=0;	/* First indentation found */ | ||||||
|  | 
 | ||||||
|  | int included=0;		/* Is current file included? */ | ||||||
|  | %} | ||||||
|  | 
 | ||||||
|  | %% | ||||||
|  | '((\*[^\n])|([^'\n*]))*'	{ | ||||||
|  | 	if ((token.t_lval=char_constant(yytext+1))== -1L)  | ||||||
|  | 		report("%s not a character constant", yytext); | ||||||
|  | 
 | ||||||
|  | 	return CHAR_CONST; | ||||||
|  | } | ||||||
|  | '[^'\n]*'?			{ | ||||||
|  | 	report("missing '."); | ||||||
|  | 	token.t_lval= -1L; | ||||||
|  | 
 | ||||||
|  | 	return CHAR_CONST; | ||||||
|  | } | ||||||
|  | \"((\*[^\n])|([^"\n*]))*\"	{ | ||||||
|  | 	char *string(); | ||||||
|  | 
 | ||||||
|  | 	token.t_sval=string(yytext); | ||||||
|  | 
 | ||||||
|  | 	return STRING; | ||||||
|  | } | ||||||
|  | \"[^"\n]*\"?			{ | ||||||
|  | 	report("missing \"."); | ||||||
|  | 	token.t_sval=""; | ||||||
|  | 
 | ||||||
|  | 	return STRING; | ||||||
|  | } | ||||||
|  | #[ \t]*"line"?[ \t]*[0-9]+[ \t]*\"[^"\n]*\"	{ | ||||||
|  | 	set_line_file(yytext); | ||||||
|  | 	tab=0; | ||||||
|  | } | ||||||
|  | #[A-Fa-f0-9]+			{ | ||||||
|  | 	long hex_number(); | ||||||
|  | 
 | ||||||
|  | 	token.t_lval=hex_number(yytext+1); | ||||||
|  | 
 | ||||||
|  | 	return NUMBER; | ||||||
|  | } | ||||||
|  | [0-9]+				{ | ||||||
|  | 	long number(); | ||||||
|  | 
 | ||||||
|  | 	token.t_lval=number(yytext); | ||||||
|  | 
 | ||||||
|  | 	return NUMBER; | ||||||
|  | } | ||||||
|  | [A-Za-z][A-Za-z0-9.]*		{ | ||||||
|  | 	register key; | ||||||
|  | 
 | ||||||
|  | 	if ((key=keyword(yytext))==IDENTIFIER) | ||||||
|  | 		token.t_sval=strcpy(malloc(yyleng+1), yytext); | ||||||
|  | 	 | ||||||
|  | 	return key; | ||||||
|  | } | ||||||
|  | \n[ \f\t]*/"--"			{/* Line with only a comment, don't set tab */} | ||||||
|  | 
 | ||||||
|  | \n[ \f\t]*			{ | ||||||
|  | 
 | ||||||
|  | 	ind=indentation(yytext+1); | ||||||
|  | 	if (tab==0) | ||||||
|  | 		tab=ind; | ||||||
|  | 	else | ||||||
|  | 	if (ind%tab!=0) | ||||||
|  | 		warning("indentation not on a %d space boundary", tab); | ||||||
|  | } | ||||||
|  | [ \f\t]				{ /* Nothing */ } | ||||||
|  | [-=<>:,;+*/\[\]()?!&]		return yytext[0]; | ||||||
|  | 
 | ||||||
|  | "\\"				return BS; | ||||||
|  | ":="				return AS; | ||||||
|  | "<="				return LE; | ||||||
|  | ">="				return GE; | ||||||
|  | "<>"				return NE; | ||||||
|  | "<<"				return LS; | ||||||
|  | ">>"				return RS; | ||||||
|  | "/\\"				return BA; | ||||||
|  | "\\/"				return BO; | ||||||
|  | "><"				return BX; | ||||||
|  | 
 | ||||||
|  | "--"[^\n]*			{ /* Comment is skipped */ } | ||||||
|  | .				{ | ||||||
|  | 	warning((' '<=yytext[0] && yytext[0]<0177) ? "%s'%c')" : "%soctal: %o)", | ||||||
|  | 		"bad character seen (", yytext[0]&0377); | ||||||
|  | } | ||||||
|  | %% | ||||||
|  | char *string(s) char *s; | ||||||
|  | { | ||||||
|  | 	register c; | ||||||
|  | 	register char *p= s; | ||||||
|  | 	char *str= s; | ||||||
|  | 	 | ||||||
|  | 	str++; p++; | ||||||
|  | 	while (*str != '"') { | ||||||
|  | 		if ((c=character(&str)) != -1) | ||||||
|  | 			*p++= c; | ||||||
|  | 		else | ||||||
|  | 			return ""; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*p=0; | ||||||
|  | 	*s=p-(s+1); | ||||||
|  | 	return s; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | long number(s) register char *s; | ||||||
|  | { | ||||||
|  | 	static char max_str[]="2147483647"; | ||||||
|  | 	int  maxlen=sizeof max_str-1; | ||||||
|  | 	long atol(); | ||||||
|  | 	long num; | ||||||
|  | 
 | ||||||
|  | 	while (*s=='0') { /* skip leading nulls */ | ||||||
|  | 		*s++; | ||||||
|  | 		yyleng--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (*s==0) | ||||||
|  | 		num=0L; | ||||||
|  | 	else { | ||||||
|  | 		if ((yyleng>maxlen) || (yyleng==maxlen && strcmp(s, max_str)>0)) | ||||||
|  | 			warning("integer constant overflow."); | ||||||
|  | 
 | ||||||
|  | 		num=atol(s); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return num; | ||||||
|  | } | ||||||
|  | 		 | ||||||
|  | long hex_number(s) register char *s; | ||||||
|  | { | ||||||
|  | 	long number=0L; | ||||||
|  | 
 | ||||||
|  | 	while (*s) | ||||||
|  | 		number=(number<<4)+hextoint(*s++); | ||||||
|  | 
 | ||||||
|  | 	return number; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int hextoint(c) register c; | ||||||
|  | { | ||||||
|  | 	register val; | ||||||
|  | 	 | ||||||
|  | 	if (islower(c)) | ||||||
|  | 		val=(c-'a')+10; | ||||||
|  | 	else | ||||||
|  | 	if (isupper(c)) | ||||||
|  | 		val=(c-'A')+10; | ||||||
|  | 	else | ||||||
|  | 		val=c-'0'; | ||||||
|  | 	 | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int character(S) register char **S; | ||||||
|  | { | ||||||
|  | 	register char *s= *S; | ||||||
|  | 	register c, cc; | ||||||
|  | 
 | ||||||
|  | 	if ((c= *s++)=='*') { | ||||||
|  | 		switch (c= *s++) { | ||||||
|  | 		case 'c': | ||||||
|  | 			cc='\r'; | ||||||
|  | 			break; | ||||||
|  | 		case 'n': | ||||||
|  | 			cc='\n'; | ||||||
|  | 			break; | ||||||
|  | 		case 't': | ||||||
|  | 			cc='\t'; | ||||||
|  | 			break; | ||||||
|  | 		case 's': | ||||||
|  | 			cc=' '; | ||||||
|  | 			break; | ||||||
|  | 		case '#': | ||||||
|  | 			if (isxdigit(c= *s++) && isxdigit(*s)) { | ||||||
|  | 				cc= (hextoint(c)<<4)+hextoint(*s++); | ||||||
|  | 				break; | ||||||
|  | 			} else { | ||||||
|  | 				report("two digit hexadecimal const expected."); | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  | 		default: | ||||||
|  | 			cc=c; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} else | ||||||
|  | 		cc=c; | ||||||
|  | 	 | ||||||
|  | 	*S=s; | ||||||
|  | 	return cc; | ||||||
|  | } | ||||||
|  | 	 | ||||||
|  | int char_constant(s) char *s; | ||||||
|  | { | ||||||
|  | 	register cc; | ||||||
|  | 
 | ||||||
|  | 	cc=character(&s); | ||||||
|  | 
 | ||||||
|  | 	return (*s=='\'' && cc!= -1) ? cc : -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int indentation(s) register char *s; | ||||||
|  | { | ||||||
|  | 	register in=0, c; | ||||||
|  | 
 | ||||||
|  | 	while (c= *s++) { | ||||||
|  | 		if (c=='\t') | ||||||
|  | 			in=TABSTOP(in); | ||||||
|  | 		else | ||||||
|  | 		if (c=='\f') | ||||||
|  | 			in=0; | ||||||
|  | 		else | ||||||
|  | 			in++; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return in; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int tabulated(oind, ind) register oind, ind; | ||||||
|  | { | ||||||
|  | 	if (tab>0 && ind>oind+tab) | ||||||
|  | 		warning("process' indentation too large (changed to %d tab%s)", | ||||||
|  | 			oind/tab+1, oind>=tab ? "s" : ""); | ||||||
|  | 	return ind>oind; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int rep_tk=0; | ||||||
|  | struct token rep_token; | ||||||
|  | 
 | ||||||
|  | void repeat_token(tk) | ||||||
|  | { | ||||||
|  | 	rep_tk=tk; | ||||||
|  | 	rep_token=token; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | scanner() | ||||||
|  | { | ||||||
|  | 	register tk; | ||||||
|  | 
 | ||||||
|  | 	if (rep_tk>0) { | ||||||
|  | 		tk=rep_tk;; | ||||||
|  | 		rep_tk=0; | ||||||
|  | 		token=rep_token; | ||||||
|  | 		return tk; | ||||||
|  | 	} else | ||||||
|  | 		return yylex(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *tokenname(tk, inst) register tk, inst; | ||||||
|  | { | ||||||
|  | 	if (tk<0400) { | ||||||
|  | 		static char c[7]; | ||||||
|  | 
 | ||||||
|  | 		if (' '<tk && tk<='~') | ||||||
|  | 			sprintf(c, "'%c'", tk); | ||||||
|  | 		else | ||||||
|  | 			sprintf(c, "'*#%02x'", tk); | ||||||
|  | 		return c; | ||||||
|  | 	} else { | ||||||
|  | 		switch (tk) { | ||||||
|  | 			char *keyname(); | ||||||
|  | 			char fake_id[1+sizeof(int)*3+1]; | ||||||
|  | 			static fake_cnt=0; | ||||||
|  | 		default: | ||||||
|  | 			return keyname(tk); | ||||||
|  | 		case IDENTIFIER: | ||||||
|  | 			if (inst) { | ||||||
|  | 				sprintf(fake_id, "_%d", ++fake_cnt); | ||||||
|  | 				token.t_sval=strcpy(malloc(strlen(fake_id)+1), | ||||||
|  | 					fake_id); | ||||||
|  | 				return "IDENTIFIER"; | ||||||
|  | 			} else | ||||||
|  | 				return token.t_sval; | ||||||
|  | 		case NUMBER: | ||||||
|  | 		case CHAR_CONST: | ||||||
|  | 			token.t_lval=0L; | ||||||
|  | 			return "NUMBER"; | ||||||
|  | 		case STRING: | ||||||
|  | 			if (inst) { | ||||||
|  | 				token.t_sval=malloc(1); | ||||||
|  | 				token.t_sval[0]=0; | ||||||
|  | 			} else | ||||||
|  | 				free(token.t_sval); | ||||||
|  | 			return "STRING"; | ||||||
|  | 		case AS:	case LE:	case GE:	case NE: | ||||||
|  | 		case LS:	case RS:	case BA:	case BO: | ||||||
|  | 		case BX:	case BS:	{ | ||||||
|  | 			static int op[]= { | ||||||
|  | 				AS, LE, GE, NE, LS, RS, BA, BO, BX, BS | ||||||
|  | 			}; | ||||||
|  | 			static char *opc[]= { | ||||||
|  | 				":=", "<=", ">=", "<>", "<<", ">>", "/\\", | ||||||
|  | 				"\\/", "><", "\\" | ||||||
|  | 			}; | ||||||
|  | 			register i; | ||||||
|  | 			static char qopc[5]; | ||||||
|  | 
 | ||||||
|  | 			for (i=0; op[i]!=tk; i++) ; | ||||||
|  | 			sprintf(qopc, "'%s'", opc[i]); | ||||||
|  | 			return qopc; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | set_line_file(l) register char *l; | ||||||
|  | { | ||||||
|  | 	register char *file; | ||||||
|  | 
 | ||||||
|  | 	while (*l<'0' || *l>'9') l++; | ||||||
|  | 
 | ||||||
|  | 	yylineno=0; | ||||||
|  | 	while ('0'<=*l && *l<='9') | ||||||
|  | 		yylineno=yylineno*10+(*l++ - '0'); | ||||||
|  | 
 | ||||||
|  | 	yylineno--; | ||||||
|  | 
 | ||||||
|  | 	while (*l++!='"'); | ||||||
|  | 
 | ||||||
|  | 	file=l; | ||||||
|  | 	while (*l++!='"'); | ||||||
|  | 	*--l=0; | ||||||
|  | 
 | ||||||
|  | 	included=set_file(file); | ||||||
|  | } | ||||||
							
								
								
									
										684
									
								
								lang/occam/comp/occam.g
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										684
									
								
								lang/occam/comp/occam.g
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,684 @@ | ||||||
|  | /*	OCCAM		*/ | ||||||
|  | { | ||||||
|  | #include "token.h" | ||||||
|  | #include "symtab.h" | ||||||
|  | #include "expr.h" | ||||||
|  | #include "code.h" | ||||||
|  | #include "sizes.h" | ||||||
|  | 
 | ||||||
|  | #define MAXERRORS	10	/* Maximum number of insert/delete errors */ | ||||||
|  | 
 | ||||||
|  | static void nonconst(), nonpositive(), rep_cleanup(), check_assoc(); | ||||||
|  | void init_builtins(); | ||||||
|  | 
 | ||||||
|  | extern int yylineno, LLsymb; | ||||||
|  | union type_info info, none; | ||||||
|  | } | ||||||
|  | %token	AFTER, ALLOCATE, ALT, AND, ANY, BYTE, CHAN, DEF, FALSE, FOR, IF, LOAD; | ||||||
|  | %token	NOT, NOW, OR, PAR, PLACED, PORT, PRI, PROC, SEQ, SKIP, TABLE, TRUE; | ||||||
|  | %token	VALUE, VAR, WAIT, WHILE; | ||||||
|  | %token	IDENTIFIER, NUMBER, CHAR_CONST, STRING; | ||||||
|  | %token	AS, LE, GE, NE, LS, RS, BA, BO, BX, BS; | ||||||
|  | 
 | ||||||
|  | %start	occam, program; | ||||||
|  | 
 | ||||||
|  | program	: 			{	init_builtins(); | ||||||
|  | 					header(); | ||||||
|  | 				} | ||||||
|  | 	  process | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | process	: primitive | ||||||
|  | 	| construct | ||||||
|  | 	|			{	sym_down(); } | ||||||
|  | 	  declaration ':' process | ||||||
|  | 				{	sym_up(); } | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | primitive { struct expr *e; } : | ||||||
|  | 	  statement(&e)		{	if (!valueless(e)) | ||||||
|  | 						report("primitive may not have a value"); | ||||||
|  | 					code_void(e); | ||||||
|  | 					destroy(e); | ||||||
|  | 				} | ||||||
|  | 	| WAIT val_expr(&e)	{	int BEGIN=0, END=0, TEST=0; | ||||||
|  | 					check_wait(e); | ||||||
|  | 					no_deadlock(); | ||||||
|  | 					branch(&TEST); | ||||||
|  | 					Label(new_label(&BEGIN)); | ||||||
|  | 					resumenext(); | ||||||
|  | 					Label(TEST); | ||||||
|  | 					code_bool(e, positive, &END, &BEGIN); | ||||||
|  | 					Label(END); | ||||||
|  | 					destroy(e); | ||||||
|  | 				} | ||||||
|  | 	| SKIP | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | guard(register *F;)		{	struct expr *e1, *e2; | ||||||
|  | 					register full_guard=0; | ||||||
|  | 					int T=0; | ||||||
|  | 		static char EXPECT_INP[]="input process expected as guard"; | ||||||
|  | 				} : | ||||||
|  | 	  expression(&e1) | ||||||
|  | 	  [	  '&'		{	full_guard=1; | ||||||
|  | 					if (!valued(e1)) | ||||||
|  | 						report("boolean part of guard has no value"); | ||||||
|  | 					code_bool(e1, positive, &T, F); | ||||||
|  | 					Label(T); | ||||||
|  | 				} | ||||||
|  | 		  [	  statement(&e2) | ||||||
|  | 				{	if (!input_process(e2)) | ||||||
|  | 						report(EXPECT_INP); | ||||||
|  | 					code_any(e2, F); | ||||||
|  | 					destroy(e2); | ||||||
|  | 				} | ||||||
|  | 			  | WAIT val_expr(&e2) | ||||||
|  | 				{	check_wait(e2); | ||||||
|  | 					code_bool(e2, positive, &T, F); | ||||||
|  | 					Label(T); | ||||||
|  | 					destroy(e2); | ||||||
|  | 				} | ||||||
|  | 			  | SKIP | ||||||
|  | 		  ] | ||||||
|  | 	  ]? | ||||||
|  | 				{	if (!full_guard) { | ||||||
|  | 						if (!input_process(e1)) | ||||||
|  | 							report(EXPECT_INP); | ||||||
|  | 						code_any(e1, F); | ||||||
|  | 					} | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	| WAIT val_expr(&e1) | ||||||
|  | 				{	check_wait(e1); | ||||||
|  | 					code_bool(e1, positive, &T, F); | ||||||
|  | 					Label(T); | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	| SKIP | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | guarded_process(register *END;)	{	struct symbol *v; | ||||||
|  | 					struct expr *e1, *e2; | ||||||
|  | 					struct replicator to_test; | ||||||
|  | 					register line, oind; | ||||||
|  | 					int F=0; | ||||||
|  | 				} : | ||||||
|  | 	  guard(&F) process	{	branch(END); | ||||||
|  | 					Label(F); | ||||||
|  | 				} | ||||||
|  | 	| ALT			{	line=yylineno; oind=ind; } | ||||||
|  | 	  [	  %if (line==yylineno) | ||||||
|  | 		  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); } | ||||||
|  | 		  guarded_process(END) | ||||||
|  | 				{	rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 		| | ||||||
|  | 		  [ %while (tabulated(oind, ind)) guarded_process(END) ]* | ||||||
|  | 	  ] | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | conditional(register *END; )	{	struct symbol *v; | ||||||
|  | 					struct expr *e1, *e2; | ||||||
|  | 					struct replicator to_test; | ||||||
|  | 					register line, oind; | ||||||
|  | 					int T=0, F=0; | ||||||
|  | 				} : | ||||||
|  | 	  val_expr(&e1)		{	if (!valued(e1)) | ||||||
|  | 						report("conditional needs valued expression"); | ||||||
|  | 					code_bool(e1, positive, &T, &F); | ||||||
|  | 					Label(T); | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	  process | ||||||
|  | 				{	branch(END); | ||||||
|  | 					Label(F); | ||||||
|  | 				} | ||||||
|  | 	| IF			{	line=yylineno; oind=ind; } | ||||||
|  | 	  [	  %if (line==yylineno) | ||||||
|  | 		  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); } | ||||||
|  | 		  conditional(END) | ||||||
|  | 				{	rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 		| | ||||||
|  | 		  [ %while (tabulated(oind, ind)) conditional(END) ]* | ||||||
|  | 	  ] | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | replicator(register struct symbol **s; register struct expr **e1, **e2; ) | ||||||
|  | 				{	register char *index; }: | ||||||
|  | 	  IDENTIFIER		{	index=token.t_sval; } | ||||||
|  | 	  '=' '[' val_expr(e1) FOR val_expr(e2) ']' | ||||||
|  | 				{	if (!valued(*e1) || !valued(*e2)) | ||||||
|  | 						report("replicator needs valued expressions"); | ||||||
|  | 					sym_down(); | ||||||
|  | 					var_memory(&info, T_VAR, 1); | ||||||
|  | 					*s=insert(index, | ||||||
|  | 					T_VAR|T_REP|T_USED|T_ASSIGNED, 1, info); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | construct			{	struct symbol *v; | ||||||
|  | 					struct expr *e1, *e2; | ||||||
|  | 					struct replicator to_test; | ||||||
|  | 					register line, oind; | ||||||
|  | 					int BEGIN=0, END=0, NONZERO; | ||||||
|  | 				}: | ||||||
|  | 	  SEQ			{	line=yylineno; oind=ind; } | ||||||
|  | 	  [	  %if (line==yylineno) | ||||||
|  | 		  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); } | ||||||
|  | 		  process | ||||||
|  | 				{	rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 		| | ||||||
|  | 		  [ %while (tabulated(oind, ind)) process ]* | ||||||
|  | 	  ] | ||||||
|  | 	| PRI ? | ||||||
|  | 	  [	  PAR		{	line=yylineno; oind=ind; | ||||||
|  | 					par_begin(); | ||||||
|  | 				} | ||||||
|  | 		  [	  %if (line==yylineno) | ||||||
|  | 			  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); | ||||||
|  | 					NONZERO=0; | ||||||
|  | 					par_fork(&NONZERO); | ||||||
|  | 				} | ||||||
|  | 			  process | ||||||
|  | 				{	branch(&END); | ||||||
|  | 					Label(NONZERO); | ||||||
|  | 					rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 			| | ||||||
|  | 			  [ %while (tabulated(oind, ind)) | ||||||
|  | 				{	NONZERO=0; | ||||||
|  | 					par_fork(&NONZERO); | ||||||
|  | 				} | ||||||
|  | 				  process | ||||||
|  | 				{	branch(&END); | ||||||
|  | 					Label(NONZERO); | ||||||
|  | 				} | ||||||
|  | 			  ]* | ||||||
|  | 		  ] | ||||||
|  | 				{	Label(END); | ||||||
|  | 					par_end(); | ||||||
|  | 				} | ||||||
|  | 		| ALT		{	line=yylineno; oind=ind; | ||||||
|  | 					no_deadlock(); | ||||||
|  | 					Label(new_label(&BEGIN)); | ||||||
|  | 				} | ||||||
|  | 		  [	  %if (line==yylineno) | ||||||
|  | 			  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); } | ||||||
|  | 			  guarded_process(&END) | ||||||
|  | 				{	rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 			| | ||||||
|  | 			  [ %while (tabulated(oind, ind)) guarded_process(&END) | ||||||
|  | 			  ]* | ||||||
|  | 		  ] | ||||||
|  | 				{	resumenext(); | ||||||
|  | 					branch(&BEGIN); | ||||||
|  | 					Label(END); | ||||||
|  | 				} | ||||||
|  | 	  ] | ||||||
|  | 	| IF			{	line=yylineno; oind=ind; } | ||||||
|  | 	  [	  %if (line==yylineno) | ||||||
|  | 		  replicator(&v, &e1, &e2) | ||||||
|  | 				{	rep_init(v, e1, e2, &to_test); } | ||||||
|  | 		  conditional(&END) | ||||||
|  | 				{	rep_test(v, e1, e2, &to_test); | ||||||
|  | 					rep_cleanup(e1, e2); | ||||||
|  | 				} | ||||||
|  | 		| | ||||||
|  | 		  [ %while (tabulated(oind, ind)) conditional(&END) ]* | ||||||
|  | 	  ] | ||||||
|  | 				{	Label(END); } | ||||||
|  | 	| WHILE val_expr(&e1)	{	if (!valued(e1)) | ||||||
|  | 						report("WHILE needs valued expression"); | ||||||
|  | 					branch(&END); | ||||||
|  | 					Label(new_label(&BEGIN)); | ||||||
|  | 				} | ||||||
|  | 	  process | ||||||
|  | 				{	int DONE=0; | ||||||
|  | 					Label(END); | ||||||
|  | 					code_bool(e1, negative, &DONE, &BEGIN); | ||||||
|  | 					Label(DONE); | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | subscript(register *byte; register struct expr **e; ) | ||||||
|  | 				{	struct expr *e1; | ||||||
|  | 					register slice=0, err=0; | ||||||
|  | 				} : | ||||||
|  | 	  '['			{	*byte=0; } | ||||||
|  | 	  [	  BYTE		{	*byte=T_BYTE; } | ||||||
|  | 	  ]? | ||||||
|  | 	  val_expr(e)		{	if (!valued(*e)) | ||||||
|  | 						err++; | ||||||
|  | 				} | ||||||
|  | 	  [	  FOR expression(&e1) | ||||||
|  | 	  			{	static char siz[]="slize size"; | ||||||
|  | 					if (!constant(e1)) { | ||||||
|  | 						if (!err) | ||||||
|  | 							nonconst(siz); | ||||||
|  | 						destroy(e1); | ||||||
|  | 						e1=new_const(0L); | ||||||
|  | 					} else | ||||||
|  | 					if (e1->u.const<=0) | ||||||
|  | 						nonpositive(siz); | ||||||
|  | 					*e=new_node(FOR, *e, e1); | ||||||
|  | 					slice=1; | ||||||
|  | 				} | ||||||
|  | 	  ]? | ||||||
|  | 	  ']' | ||||||
|  | 				{	if (err) | ||||||
|  | 						report(slice ? | ||||||
|  | 				"slice must be '[' value FOR constant ']'" : | ||||||
|  | 				"subscript needs valued expression"); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | chan	{ register type, arr_siz=1; register char *name; struct expr *e; }: | ||||||
|  | 	  IDENTIFIER		{	type=T_CHAN; | ||||||
|  | 					name=token.t_sval; | ||||||
|  | 				} | ||||||
|  | 	  [	  '[' expression(&e) ']' | ||||||
|  | 				{	static char siz[]="channel array size"; | ||||||
|  | 					if (!constant(e)) | ||||||
|  | 						nonconst(siz); | ||||||
|  | 					else | ||||||
|  | 					if (e->u.const<0) | ||||||
|  | 						nonpositive(siz); | ||||||
|  | 					else | ||||||
|  | 						arr_siz=e->u.const; | ||||||
|  | 					destroy(e); | ||||||
|  | 					type|=T_ARR; | ||||||
|  | 				} | ||||||
|  | 	  ]? | ||||||
|  | 				{	chan_memory(&info, arr_siz); | ||||||
|  | 					chan_init(&info, arr_siz); | ||||||
|  | 					insert(name, type, arr_siz, info); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | var				{	register type, byte=0, arr_siz=1; | ||||||
|  | 					register char *name; | ||||||
|  | 					struct expr *e; | ||||||
|  | 				}: | ||||||
|  | 	  IDENTIFIER		{	type=T_VAR; name=token.t_sval; } | ||||||
|  | 	  [	  '[' | ||||||
|  | 		  [	  BYTE	{	byte=T_BYTE; } | ||||||
|  | 		  ]? | ||||||
|  | 		  expression(&e) ']' | ||||||
|  | 				{	static char siz[]="variable array size"; | ||||||
|  | 					if (!constant(e)) | ||||||
|  | 						nonconst(siz); | ||||||
|  | 					else | ||||||
|  | 					if (e->u.const<=0) | ||||||
|  | 						nonpositive(siz); | ||||||
|  | 					else | ||||||
|  | 						arr_siz=e->u.const; | ||||||
|  | 					destroy(e); | ||||||
|  | 					type|=T_ARR|byte; | ||||||
|  | 				} | ||||||
|  | 	  ]? | ||||||
|  | 				{	var_memory(&info, type, arr_siz); | ||||||
|  | 					insert(name, type, arr_siz, info); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | const_def { register char *name; struct expr *e; }: | ||||||
|  | 	  IDENTIFIER		{	name=token.t_sval; } | ||||||
|  | 	  '=' expression(&e) | ||||||
|  | 				{	if (!constant(e) && !arr_constant(e)) | ||||||
|  | 						nonconst("expression in constant definition"); | ||||||
|  | 					info.const=e; | ||||||
|  | 					insert(name, T_CONST|T_USED, 0, info); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | form_parm(register struct par_list ***aapars; register *g_type;) | ||||||
|  | 				{	register char *name; | ||||||
|  | 					register type= *g_type; | ||||||
|  | 				}: | ||||||
|  | 	  [	  VAR		{	type=T_VAR|T_ASSIGNED|T_USED; } | ||||||
|  | 		| CHAN		{	type=T_CHAN; } | ||||||
|  | 		| VALUE		{	type=T_VALUE|T_ASSIGNED; } | ||||||
|  | 	  ]? | ||||||
|  | 	  IDENTIFIER		{ | ||||||
|  | 					if (type<0) { | ||||||
|  | 						report("VAR, CHAN or VALUE expected"); | ||||||
|  | 						type=T_VAR; | ||||||
|  | 					} | ||||||
|  | 					name=token.t_sval; | ||||||
|  | 					*g_type=type; | ||||||
|  | 				} | ||||||
|  | 	  [	  '[' ']' | ||||||
|  | 				{	type|=T_ARR; } | ||||||
|  | 	  ]? | ||||||
|  | 				{	pars_add(aapars, type&(T_TYPE|T_ARR), | ||||||
|  | 					  insert(name, type|T_PARAM, 0, none)); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | form_parms(struct par_list **apars;) { int type= -1; }: | ||||||
|  | 	  '(' form_parm(&apars, &type) | ||||||
|  | 	  [	  ',' form_parm(&apars, &type) | ||||||
|  | 	  ]* | ||||||
|  | 	  ')' | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | declaration: | ||||||
|  | 	  VAR | ||||||
|  | 	  var [ ',' var ]* | ||||||
|  | 	| CHAN | ||||||
|  | 	  chan [ ',' chan ]* | ||||||
|  | 	| DEF | ||||||
|  | 	  const_def [ ',' const_def ]* | ||||||
|  | 	| proc_declaration | ||||||
|  | 	; | ||||||
|  | 	 | ||||||
|  | proc_declaration		{	struct par_list *pars=nil; | ||||||
|  | 					register struct symbol *proc; | ||||||
|  | 					int OVER=0; | ||||||
|  | 					register old_min_offset; | ||||||
|  | 				}: | ||||||
|  | 	  PROC IDENTIFIER	{	branch(&OVER); | ||||||
|  | 					proc=insert(token.t_sval, | ||||||
|  | 						T_PROC|T_RECURS, 0, none); | ||||||
|  | 					old_min_offset=min_offset; | ||||||
|  | 					sym_down(); | ||||||
|  | 					prologue(proc); | ||||||
|  | 				} | ||||||
|  | 	  form_parms(&pars) ?	{	form_offsets(pars); | ||||||
|  | 					proc->info.proc.pars=pars; | ||||||
|  | 				} | ||||||
|  | 	  '=' process		{	epilogue(proc); | ||||||
|  | 					sym_up(); | ||||||
|  | 					proc->type&= ~T_RECURS; | ||||||
|  | 					min_offset=old_min_offset; | ||||||
|  | 					Label(OVER); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | vector_constant(register struct expr **e;) | ||||||
|  | 				{	struct table *pt=nil, **apt= &pt; | ||||||
|  | 					register Tlen=0; | ||||||
|  | 				}: | ||||||
|  | 	  table(e) | ||||||
|  | 	| STRING		{	register char *ps= token.t_sval; | ||||||
|  | 					register len; | ||||||
|  | 
 | ||||||
|  | 					Tlen+= len= (*ps++ & 0377); | ||||||
|  | 					while (--len>=0) | ||||||
|  | 						table_add(&apt, (long) *ps++); | ||||||
|  | 				} | ||||||
|  | 	  [ %while (1)	  STRING | ||||||
|  | 				{	register char *ps= token.t_sval; | ||||||
|  | 					register len; | ||||||
|  | 
 | ||||||
|  | 					Tlen+= len= (*ps++ & 0377); | ||||||
|  | 					while (--len>=0) | ||||||
|  | 						table_add(&apt, (long) *ps++); | ||||||
|  | 				} | ||||||
|  | 	  ]* | ||||||
|  | 				{	apt= &pt; | ||||||
|  | 					table_add(&apt, (long) Tlen); | ||||||
|  | 					*e=new_table(E_BTAB, pt); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | item(register struct expr **e;) | ||||||
|  | 				{	struct expr *e1; | ||||||
|  | 					register struct symbol *var; | ||||||
|  | 					struct par_list *pars=nil; | ||||||
|  | 					register line, oind; | ||||||
|  | 					int byte, err=0, subs_call=0; | ||||||
|  | 					struct expr_list *elp=nil, **aelp= &elp; | ||||||
|  | 				}: | ||||||
|  | 	  IDENTIFIER		{	line=yylineno; | ||||||
|  | 					oind=ind; | ||||||
|  | 					var=searchall(token.t_sval); | ||||||
|  | 
 | ||||||
|  | 					if (var_constant(var)) | ||||||
|  | 						*e=copy_const(var->info.const); | ||||||
|  | 					else { | ||||||
|  | 						if (var_proc(var)) | ||||||
|  | 							pars=var->info.proc.pars; | ||||||
|  | 						*e=new_var(var); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 	  [ %while (line==yylineno || tabulated(oind, ind)) | ||||||
|  | 		  [	  subscript(&byte, &e1) | ||||||
|  | 				{	*e=new_node('[', *e, e1, byte); } | ||||||
|  | 			| '('	{	if (!var_declared(var)) { | ||||||
|  | 						var->type=T_PROC|T_USED|T_NOTDECL; | ||||||
|  | 						var->info.proc.pars=nil; | ||||||
|  | 						err=1; | ||||||
|  | 					} | ||||||
|  | 					if (!var_proc(var)) { | ||||||
|  | 						report("%s is not a named process", | ||||||
|  | 							var->name); | ||||||
|  | 						err=1; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			  expression(&e1) | ||||||
|  | 				{ 	check_param(&pars, e1, &err); | ||||||
|  | 					expr_list_add(&aelp, e1); | ||||||
|  | 				} | ||||||
|  | 			  [	  ',' expression(&e1) | ||||||
|  | 				{ 	check_param(&pars, e1, &err); | ||||||
|  | 					expr_list_add(&aelp, e1); | ||||||
|  | 				} | ||||||
|  | 			  ]* | ||||||
|  | 				{ | ||||||
|  | 					if (pars!=nil) | ||||||
|  | 						report("too few actual parameters"); | ||||||
|  | 				} | ||||||
|  | 			  ')' | ||||||
|  | 				{	*e=new_call(*e, elp); } | ||||||
|  | 		  ] | ||||||
|  | 				{	subs_call=1; } | ||||||
|  | 	  ]? | ||||||
|  | 				{	if (!subs_call && var_proc(var)) { | ||||||
|  | 						if (pars!=nil) | ||||||
|  | 							report("no actual parameters"); | ||||||
|  | 						*e=new_call(*e, nil); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 	| vector_constant(e) | ||||||
|  | 	  [	  subscript(&byte, &e1) | ||||||
|  | 				{	*e=new_node('[', *e, e1, byte); } | ||||||
|  | 	  ]? | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | statement(register struct expr **e;) | ||||||
|  | 				{	struct expr *e1; | ||||||
|  | 					struct expr_list *elp=nil, **aelp= &elp; | ||||||
|  | 					register out; | ||||||
|  | 				}: | ||||||
|  | 	  item(e) | ||||||
|  | 	  [	  AS expression(&e1) | ||||||
|  | 				{	*e=new_node(AS, *e, e1); } | ||||||
|  | 		| [ | ||||||
|  | 			  '?'	{	out=0; } | ||||||
|  | 			| '!'	{	out=1; } | ||||||
|  | 		  ] | ||||||
|  | 		  io_arg(&e1) | ||||||
|  | 				{	if (e1!=nil) check_io(out, e1); | ||||||
|  | 					expr_list_add(&aelp, e1); | ||||||
|  | 				} | ||||||
|  | 		  [ %while (1) ';' io_arg(&e1) | ||||||
|  | 				{	if (e1!=nil) check_io(out, e1); | ||||||
|  | 					expr_list_add(&aelp, e1); | ||||||
|  | 				} | ||||||
|  | 		  ]* | ||||||
|  | 				{	*e=new_io(out, *e, elp); } | ||||||
|  | 	  ]? | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | io_arg(struct expr **e; ) : | ||||||
|  | 	  expression(e) | ||||||
|  | 	| ANY			{	*e=nil;	} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | table(register struct expr **e;)	 | ||||||
|  | 				{	struct table *pt=nil, **apt= &pt; | ||||||
|  | 					struct expr *e1; | ||||||
|  | 					register type; | ||||||
|  | 				}: | ||||||
|  | 	  TABLE '['		{	type=E_TABLE; } | ||||||
|  | 	  [	  BYTE		{	type=E_BTAB; } | ||||||
|  | 	  ]? | ||||||
|  | 	  expression(&e1)	{	if (!constant(e1)) | ||||||
|  | 						nonconst("table element"); | ||||||
|  | 					else | ||||||
|  | 						table_add(&apt, e1->u.const); | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	  [	  ',' expression(&e1) | ||||||
|  | 				{	if (!constant(e1)) | ||||||
|  | 						nonconst("table element"); | ||||||
|  | 					else | ||||||
|  | 						table_add(&apt, e1->u.const); | ||||||
|  | 					destroy(e1); | ||||||
|  | 				} | ||||||
|  | 	  ]* | ||||||
|  | 				{	*e=new_table(type, pt); } | ||||||
|  | 	  ']' | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | arithmetic_op:	'+' | '-' | '*' | '/' | BS | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | comparison_op:	'<' | '>' | LE | GE | NE | '=' | AFTER | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | logical_op:	BA | BO | BX | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | boolean_op:	AND | OR | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | shift_op:	LS | RS | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | monadic_op(register *op;): | ||||||
|  | 	  '-'			{	*op='~'; } | ||||||
|  | 	| NOT			{	*op=NOT; } | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | operator: arithmetic_op | comparison_op | logical_op | boolean_op | shift_op | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | element(register struct expr **e;) : | ||||||
|  | 	  %default NUMBER	{	*e=new_const(token.t_lval); } | ||||||
|  | 	| statement(e) | ||||||
|  | 	| TRUE			{	*e=new_const(-1L); } | ||||||
|  | 	| FALSE			{	*e=new_const(0L); } | ||||||
|  | 	| NOW			{	*e=new_now(); } | ||||||
|  | 	| CHAR_CONST		{	*e=new_const(token.t_lval); } | ||||||
|  | 	| '(' expression(e) ')' {	if (valueless(*e)) | ||||||
|  | 						warning("primitive should not be parenthesized"); | ||||||
|  | 				} | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | expression(register struct expr **e;) | ||||||
|  | 				{	int op=0; | ||||||
|  | 					struct expr *e1; | ||||||
|  | 				}: | ||||||
|  | 	  element(e) | ||||||
|  | 	  [ %while (1)		{	if (op!=0) check_assoc(op, LLsymb); | ||||||
|  | 					op=LLsymb; | ||||||
|  | 				} | ||||||
|  | 		  operator element(&e1) | ||||||
|  | 				{	*e=new_node(op, *e, e1); } | ||||||
|  | 	  ]* | ||||||
|  | 	| monadic_op(&op) element(&e1) | ||||||
|  | 				{	*e=new_node(op, e1, nil); } | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | val_expr(register struct expr **e;) : | ||||||
|  | 	  expression(e)		{	used(*e); } | ||||||
|  | 	; | ||||||
|  | 
 | ||||||
|  | %lexical scanner; | ||||||
|  | { | ||||||
|  | int err=0; | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | main(argc, argv) register argc; register char **argv; | ||||||
|  | { | ||||||
|  | 	wz= (argc>1 && strcmp(argv[1], "4")==0) ? 4 : 2; | ||||||
|  | 	pz= (argc>2 && strcmp(argv[2], "4")==0) ? 4 : wz; | ||||||
|  | 
 | ||||||
|  | 	leader(); | ||||||
|  | 	occam(); | ||||||
|  | 	trailer(); | ||||||
|  | 
 | ||||||
|  | 	exit(err); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LLmessage(tk) register tk; | ||||||
|  | { | ||||||
|  | 	static errors=0; | ||||||
|  | 
 | ||||||
|  | 	if (tk>0) { | ||||||
|  | 		repeat_token(LLsymb); | ||||||
|  | 		warning("syntax error: %s expected (inserted)", tokenname(tk, 1)); | ||||||
|  | 	} else | ||||||
|  | 	if (tk==0) | ||||||
|  | 		warning("syntax error: bad token %s (deleted)", tokenname(LLsymb, 0)); | ||||||
|  | 	else { /* tk<0 */ | ||||||
|  | 		fprintf(stderr, "Compiler stack overflow. Compiler ends."); | ||||||
|  | 		err=1; trailer(); exit(1); | ||||||
|  | 	} | ||||||
|  | 	if (++errors==MAXERRORS) { | ||||||
|  | 		fprintf(stderr, "Too many insert/delete errors. Compiler ends.\n"); | ||||||
|  | 		err=1; trailer(); exit(1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void nonconst(siz) char *siz; | ||||||
|  | { | ||||||
|  | 	report("%s should be a constant", siz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void nonpositive(siz) char *siz; | ||||||
|  | { | ||||||
|  | 	report("%s must be positive", siz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void rep_cleanup(e1, e2) struct expr *e1, *e2; | ||||||
|  | { | ||||||
|  | 	destroy(e1); | ||||||
|  | 	destroy(e2); | ||||||
|  | 	sym_up(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void check_assoc(prev_op, op) register prev_op, op; | ||||||
|  | { | ||||||
|  | 	switch (op) { | ||||||
|  | 		char prev[5]; | ||||||
|  | 	case '+':	case '*': | ||||||
|  | 	case AND:	case OR: | ||||||
|  | 	case BA:	case BO:	case BX: | ||||||
|  | 		if (prev_op==op) break; | ||||||
|  | 	default: | ||||||
|  | 		strcpy(prev, tokenname(prev_op, 0)); | ||||||
|  | 
 | ||||||
|  | 		warning("Operators %s and %s don't associate", | ||||||
|  | 			prev, tokenname(op, 0) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								lang/occam/comp/report.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lang/occam/comp/report.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | extern int err, yylineno; | ||||||
|  | extern char *curr_file; | ||||||
|  | 
 | ||||||
|  | report(fmt, arg1, arg2, arg3) char *fmt; | ||||||
|  | { | ||||||
|  | 	fprintf(stderr, "%s (%d) F: ", curr_file, yylineno); | ||||||
|  | 	fprintf(stderr, fmt, arg1, arg2, arg3); | ||||||
|  | 	putc('\n', stderr); | ||||||
|  | 	err=1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | warning(fmt, arg1, arg2, arg3) char *fmt, *arg1; | ||||||
|  | { | ||||||
|  | 	fprintf(stderr, "%s (%d) E: ", curr_file, yylineno); | ||||||
|  | 	fprintf(stderr, fmt, arg1, arg2, arg3); | ||||||
|  | 	putc('\n', stderr); | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								lang/occam/comp/sizes.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lang/occam/comp/sizes.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | /* Variable size, wordsize, pointer size.  Offsets for local variables. */ | ||||||
|  | 
 | ||||||
|  | #define vz	4 | ||||||
|  | extern int wz, pz; | ||||||
|  | extern int curr_level, curr_offset, min_offset; | ||||||
							
								
								
									
										202
									
								
								lang/occam/comp/symtab.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								lang/occam/comp/symtab.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,202 @@ | ||||||
|  | #include "symtab.h" | ||||||
|  | #include "expr.h" | ||||||
|  | #include "sizes.h" | ||||||
|  | 
 | ||||||
|  | int curr_level=0;	/* Current local level */ | ||||||
|  | int curr_offset=0;	/* Current offset within this level */ | ||||||
|  | int min_offset=0;	/* Minimum of all offsets within current level */ | ||||||
|  | 
 | ||||||
|  | static struct symtab *sym_table=nil; | ||||||
|  | 
 | ||||||
|  | char *malloc(); | ||||||
|  | 
 | ||||||
|  | static struct symbol **search_sym(tree, name) | ||||||
|  | 	struct symbol **tree; | ||||||
|  | 	char *name; | ||||||
|  | /* Returns a hook in the tree to the where the given name is or should be. */ | ||||||
|  | { | ||||||
|  | 	register struct symbol **aps=tree, *ps; | ||||||
|  | 	register cmp; | ||||||
|  | 
 | ||||||
|  | 	while ((ps= *aps)!=nil && (cmp=strcmp(name, ps->name))!=0) | ||||||
|  | 		aps= cmp<0 ? &ps->left : &ps->right; | ||||||
|  | 
 | ||||||
|  | 	return aps; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct symbol *insert(name, type, arr_siz, info) | ||||||
|  | 	char *name; | ||||||
|  | 	int type, arr_siz; | ||||||
|  | 	union type_info info; | ||||||
|  | /* Inserts an object with given name and other info into the current symbol
 | ||||||
|  |  * tree.  A pointer is returned to the inserted symbol so that more info may | ||||||
|  |  * or changed.  Nil is returned on redeclaration. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct symbol **aps, *ps; | ||||||
|  | 	extern included; | ||||||
|  | 
 | ||||||
|  | 	if (*(aps=search_sym(&sym_table->local, name))!=nil) { | ||||||
|  | 		report("%s redeclared", name); | ||||||
|  | 		return nil; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ps= (struct symbol *) malloc(sizeof *ps); | ||||||
|  | 
 | ||||||
|  | 	ps->name=name; | ||||||
|  | 
 | ||||||
|  | 	if (included && curr_level==0)	/* Top_level symbol in include file */ | ||||||
|  | 		type|=T_USED;		/* are always used */ | ||||||
|  | 	ps->type=type; | ||||||
|  | 	ps->arr_siz=arr_siz; | ||||||
|  | 	ps->info=info; | ||||||
|  | 	ps->left=ps->right=nil; | ||||||
|  | 	*aps=ps; | ||||||
|  | 
 | ||||||
|  | 	return ps; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct symbol *searchall(name) char *name; | ||||||
|  | /* Searches for name in all symbol trees from the inner to the outermost.
 | ||||||
|  |  * If it can't be found then it is inserted as undefined. | ||||||
|  |  */ | ||||||
|  | { | ||||||
|  | 	register struct symtab *tab=sym_table; | ||||||
|  | 	register struct symbol *ps; | ||||||
|  | 
 | ||||||
|  | 	while (tab!=nil) { | ||||||
|  | 		if ((ps= *search_sym(&tab->local, name))!=nil) return ps; | ||||||
|  | 
 | ||||||
|  | 		tab=tab->global; | ||||||
|  | 	} | ||||||
|  | 	report("%s not declared", name); | ||||||
|  | 	return insert(name, T_NOTDECL, 0, none); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_recursion(proc) | ||||||
|  | 	register struct expr *proc; | ||||||
|  | { | ||||||
|  | 	if (proc->kind==E_VAR && proc->u.var->type&T_RECURS) | ||||||
|  | 		warning("recursion not allowed"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void sym_down() | ||||||
|  | { | ||||||
|  | 	register struct symtab *ps; | ||||||
|  | 
 | ||||||
|  | 	ps= (struct symtab *) malloc(sizeof *ps); | ||||||
|  | 
 | ||||||
|  | 	ps->local=nil; | ||||||
|  | 	ps->global=sym_table; | ||||||
|  | 	ps->old_offset=curr_offset; | ||||||
|  | 
 | ||||||
|  | 	sym_table=ps; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sym_destroy(ps) register struct symbol *ps; | ||||||
|  | { | ||||||
|  | 	if (ps!=nil) { | ||||||
|  | 		sym_destroy(ps->left); | ||||||
|  | 		sym_destroy(ps->right); | ||||||
|  | 		if ( !(ps->type&T_NOTDECL) ) { | ||||||
|  | 			if ( !(ps->type&T_USED) ) | ||||||
|  | 				warning("%s: never used", ps->name); | ||||||
|  | 			else | ||||||
|  | 			if ( !(ps->type&T_ASSIGNED) && (ps->type&T_TYPE)==T_VAR) | ||||||
|  | 				warning("%s: never assigned", ps->name); | ||||||
|  | 		} | ||||||
|  | 		if ((ps->type&T_TYPE)==T_PROC) { | ||||||
|  | 			register struct par_list *par, *junk; | ||||||
|  | 
 | ||||||
|  | 			par=ps->info.proc.pars; | ||||||
|  | 			while (par!=nil) { | ||||||
|  | 				junk=par; | ||||||
|  | 				par=par->next; | ||||||
|  | 				free(junk); | ||||||
|  | 			} | ||||||
|  | 		} else | ||||||
|  | 		if ((ps->type&T_TYPE)==T_CONST) | ||||||
|  | 			destroy(ps->info.const); | ||||||
|  | 		free(ps->name); | ||||||
|  | 		free(ps); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void sym_up() | ||||||
|  | { | ||||||
|  | 	register struct symtab *ps; | ||||||
|  | 
 | ||||||
|  | 	ps=sym_table->global; | ||||||
|  | 	curr_offset=sym_table->old_offset; | ||||||
|  | 
 | ||||||
|  | 	sym_destroy(sym_table->local); | ||||||
|  | 	free(sym_table); | ||||||
|  | 
 | ||||||
|  | 	sym_table=ps; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void var_memory(info, type, n) register union type_info *info; int type, n; | ||||||
|  | /* Reserves local memory for an object, and stores it in its info field. */ | ||||||
|  | { | ||||||
|  | 	info->vc.st.level=curr_level; | ||||||
|  | 	curr_offset-= (type&T_BYTE) ? (n+wz-1) & (~(wz-1)) : n*vz; | ||||||
|  | 	info->vc.offset=curr_offset; | ||||||
|  | 	if (curr_offset<min_offset) min_offset=curr_offset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void chan_memory(info, n) register union type_info *info; int n; | ||||||
|  | { | ||||||
|  | 	info->vc.st.level=curr_level; | ||||||
|  | 	info->vc.offset= curr_offset-=n*(vz+wz); | ||||||
|  | 	if (curr_offset<min_offset) min_offset=curr_offset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int memory(z) int z; | ||||||
|  | /* Reserves z memory bytes */ | ||||||
|  | { | ||||||
|  | 	curr_offset-=z; | ||||||
|  | 	if (curr_offset<min_offset) min_offset=curr_offset; | ||||||
|  | 	return curr_offset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void pars_add(aapars, type, var) | ||||||
|  | 	register struct par_list ***aapars; | ||||||
|  | 	int type; | ||||||
|  | 	struct symbol *var; | ||||||
|  | /* Add a formal variable to a parameter list using a hook to a hook. */ | ||||||
|  | { | ||||||
|  | 	register struct par_list *pl; | ||||||
|  | 
 | ||||||
|  | 	pl= (struct par_list *) malloc(sizeof *pl); | ||||||
|  | 
 | ||||||
|  | 	pl->type=type; | ||||||
|  | 	pl->var=var; | ||||||
|  | 	pl->next= **aapars; | ||||||
|  | 
 | ||||||
|  | 	**aapars=pl; | ||||||
|  | 	*aapars= &pl->next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int form_offsets(pars) register struct par_list *pars; | ||||||
|  | /* Recursively assign offsets to formal variables. */ | ||||||
|  | { | ||||||
|  | 	register struct symbol *var; | ||||||
|  | 
 | ||||||
|  | 	if (pars==nil) return pz; | ||||||
|  | 
 | ||||||
|  | 	if ((var=pars->var)!=nil) { | ||||||
|  | 		register offset=form_offsets(pars->next); | ||||||
|  | 
 | ||||||
|  | 		switch (var->type&T_TYPE) { | ||||||
|  | 		case T_VAR: | ||||||
|  | 		case T_CHAN: | ||||||
|  | 			var->info.vc.st.level=curr_level; | ||||||
|  | 			var->info.vc.offset=offset; | ||||||
|  | 			return offset+pz; | ||||||
|  | 		case T_VALUE: | ||||||
|  | 			var->info.vc.st.level=curr_level; | ||||||
|  | 			var->info.vc.offset=offset; | ||||||
|  | 			return offset+ ((var->type&T_ARR) ? pz : vz); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								lang/occam/comp/symtab.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								lang/occam/comp/symtab.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | ||||||
|  | #ifndef nil | ||||||
|  | #define nil 0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	/* Symbol/Expression type: */ | ||||||
|  | #define	T_VAR		0x0000 | ||||||
|  | #define	T_CHAN		0x0001 | ||||||
|  | #define	T_CONST		0x0002 | ||||||
|  | #define	T_VALUE		0x0003 | ||||||
|  | #define	T_PROC		0x0004 | ||||||
|  | #define T_NOW		0x0005 | ||||||
|  | #define T_VOID		0x0006 | ||||||
|  | 
 | ||||||
|  | #define	T_TYPE		0x0007	/* Mask for type bits */ | ||||||
|  | 
 | ||||||
|  | 	/* Flags: */ | ||||||
|  | #define	T_ARR		0x0008	/* Object is an array */ | ||||||
|  | #define	T_BYTE		0x0010	/* Object is a byte array if T_ARR */ | ||||||
|  | #define	T_PARAM		0x0020	/* Formal parameter */ | ||||||
|  | #define	T_LVALUE	0x0040	/* This object may be assigned */ | ||||||
|  | #define T_NOTDECL	0x0080	/* If you didn't declare it */ | ||||||
|  | #define T_USED		0x0100	/* If you've used it */ | ||||||
|  | #define T_ASSIGNED	0x0200	/* Or assigned it */ | ||||||
|  | #define T_REP		0x0400	/* Replicator index */ | ||||||
|  | #define T_BUILTIN	0x0800	/* Builtin name */ | ||||||
|  | #define T_RECURS	0x1000	/* This proc is now compiled */ | ||||||
|  | /* Note that some types and flags are only used for symbols, and others only
 | ||||||
|  |  * for expressions. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct symbol; | ||||||
|  | 
 | ||||||
|  | struct par_list {	/* List of parameter types for a proc object */ | ||||||
|  | 	struct par_list *next; | ||||||
|  | 	struct symbol *var;	/* The formal parameter while visible */ | ||||||
|  | 	int type;		/* Its type */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct expr; | ||||||
|  | 
 | ||||||
|  | union storage {		/* An object is found */ | ||||||
|  | 	int level;	/* either at a certain local level */ | ||||||
|  | 	char *builtin;	/* or using a global builtin name */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union type_info { | ||||||
|  | 	struct { | ||||||
|  | 		union storage st; | ||||||
|  | 		int offset;	/* from its local level or builtin name */ | ||||||
|  | 	} vc;			/* Variable or channel */ | ||||||
|  | 
 | ||||||
|  | 	struct expr *const; | ||||||
|  | 
 | ||||||
|  | 	struct { | ||||||
|  | 		union storage st; | ||||||
|  | 		char *file;	/* file it is in */ | ||||||
|  | 		int label;	/* A unique id*/ | ||||||
|  | 		struct par_list *pars; | ||||||
|  | 	} proc; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct symbol { | ||||||
|  | 	char	*name; | ||||||
|  | 	short	type; | ||||||
|  | 	int	arr_siz; | ||||||
|  | 	union type_info	info; | ||||||
|  | 	struct symbol	*left, *right; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct symtab { | ||||||
|  | 	struct symbol *local; | ||||||
|  | 	struct symtab *global; | ||||||
|  | 	int old_offset; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct symbol *insert(); | ||||||
|  | struct symbol *searchall(); | ||||||
|  | 
 | ||||||
|  | void sym_down(); | ||||||
|  | void sym_up(); | ||||||
|  | void var_memory(), chan_memory(); | ||||||
|  | 
 | ||||||
|  | void pars_add(); | ||||||
|  | int form_offsets(); | ||||||
|  | void check_recursion(); | ||||||
|  | 
 | ||||||
|  | #define var_constant(v)	(((v)->type&T_TYPE)==T_CONST) | ||||||
|  | #define var_proc(v)	(((v)->type&T_TYPE)==T_PROC) | ||||||
|  | #define var_declared(v)	(! ((v)->type&T_NOTDECL)) | ||||||
|  | 
 | ||||||
|  | extern union type_info none; | ||||||
							
								
								
									
										11
									
								
								lang/occam/comp/token.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								lang/occam/comp/token.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | /*	token.h		*/ | ||||||
|  | 
 | ||||||
|  | extern struct token { | ||||||
|  | 	long	t_lval; | ||||||
|  | 	char	*t_sval; | ||||||
|  | } token; | ||||||
|  | 
 | ||||||
|  | extern ind; | ||||||
|  | void repeat_token(); | ||||||
|  | char *tokenname(); | ||||||
|  | int tabulated(); | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue