⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#include <mach.h>#define Extern extern#include "acid.h"static int fsize[] ={	['A'] 4,	['B'] 4,	['C'] 1,	['D'] 4,	['F'] 8,	['G'] 8,	['O'] 4,	['Q'] 4,	['R'] 4,	['S'] 4,	['U'] 4,	['V'] 8,	['W'] 8,	['X'] 4,	['Y'] 8,	['Z'] 8,	['a'] 4,	['b'] 1,	['c'] 1,	['d'] 2,	['f'] 4,	['g'] 4,	['o'] 2,	['q'] 2,	['r'] 2,	['s'] 4,	['u'] 2,	['x'] 2,};intfmtsize(Value *v){	int ret;	switch(v->fmt) {	default:		return  fsize[v->fmt];	case 'i':	case 'I':		if(v->type != TINT || machdata == 0)			error("no size for i fmt pointer ++/--");		ret = (*machdata->instsize)(cormap, v->ival);		if(ret < 0) {			ret = (*machdata->instsize)(symmap, v->ival);			if(ret < 0)				error("%r");		}		return ret;	}}voidchklval(Node *lp){	if(lp->op != ONAME)		error("need l-value");}voidolist(Node *n, Node *res){	expr(n->left, res);	expr(n->right, res);}voidoeval(Node *n, Node *res){	expr(n->left, res);	if(res->type != TCODE)		error("bad type for eval");	expr(res->cc, res);}voidocast(Node *n, Node *res){	if(n->sym->lt == 0)		error("%s is not a complex type", n->sym->name);	expr(n->left, res);	res->comt = n->sym->lt;	res->fmt = 'a';}voidoindm(Node *n, Node *res){	Map *m;	Node l;	m = cormap;	if(m == 0)		m = symmap;	expr(n->left, &l);	if(l.type != TINT)		error("bad type for *");	if(m == 0)		error("no map for *");	indir(m, l.ival, l.fmt, res);	res->comt = l.comt;}voidoindc(Node *n, Node *res){	Map *m;	Node l;	m = symmap;	if(m == 0)		m = cormap;	expr(n->left, &l);	if(l.type != TINT)		error("bad type for @");	if(m == 0)		error("no map for @");	indir(m, l.ival, l.fmt, res);	res->comt = l.comt;}voidoframe(Node *n, Node *res){	char *p;	Node *lp;	uvlong ival;	Frtype *f;	p = n->sym->name;	while(*p && *p == '$')		p++;	lp = n->left;	if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)		error("colon: %r");	res->ival = ival;	res->op = OCONST;	res->fmt = 'X';	res->type = TINT;	/* Try and set comt */	for(f = n->sym->local; f; f = f->next) {		if(f->var == lp->sym) {			res->comt = f->type;			res->fmt = 'a';			break;		}	}}voidoindex(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	if(r.type != TINT)		error("bad type for []");	switch(l.type) {	default:		error("lhs[] has bad type");	case TINT:		indir(cormap, l.ival+(r.ival*fsize[l.fmt]), l.fmt, res);		res->comt = l.comt;		res->fmt = l.fmt;		break;	case TLIST:		nthelem(l.l, r.ival, res);		break;	case TSTRING:		res->ival = 0;		if(r.ival >= 0 && r.ival < l.string->len) {			int xx8;	/* to get around bug in vc */			xx8 = r.ival;			res->ival = l.string->string[xx8];		}		res->op = OCONST;		res->type = TINT;		res->fmt = 'c';		break;	}}voidoappend(Node *n, Node *res){	Node r, l;	expr(n->left, &l);	expr(n->right, &r);	if(l.type != TLIST)		error("must append to list");	append(res, &l, &r);}voidodelete(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	if(l.type != TLIST)		error("must delete from list");	if(r.type != TINT)		error("delete index must be integer");	delete(l.l, r.ival, res);}voidohead(Node *n, Node *res){	Node l;	expr(n->left, &l);	if(l.type != TLIST)		error("head needs list");	res->op = OCONST;	if(l.l) {		res->type = l.l->type;		res->Store = l.l->Store;	}	else {		res->type = TLIST;		res->l = 0;	}}voidotail(Node *n, Node *res){	Node l;	expr(n->left, &l);	if(l.type != TLIST)		error("tail needs list");	res->op = OCONST;	res->type = TLIST;	if(l.l)		res->l = l.l->next;	else		res->l = 0;}voidoconst(Node *n, Node *res){	res->op = OCONST;	res->type = n->type;	res->Store = n->Store;	res->comt = n->comt;}voidoname(Node *n, Node *res){	Value *v;	v = n->sym->v;	if(v->set == 0)		error("%s used but not set", n->sym->name);	res->op = OCONST;	res->type = v->type;	res->Store = v->Store;	res->comt = v->comt;}voidoctruct(Node *n, Node *res){	res->op = OCONST;	res->type = TLIST;	res->l = construct(n->left);}voidoasgn(Node *n, Node *res){	Node *lp, r;	Value *v;	lp = n->left;	switch(lp->op) {	case OINDM:		windir(cormap, lp->left, n->right, res);		break;	case OINDC:		windir(symmap, lp->left, n->right, res);		break;	default:		chklval(lp);		v = lp->sym->v;		expr(n->right, &r);		v->set = 1;		v->type = r.type;		v->Store = r.Store;		res->op = OCONST;		res->type = v->type;		res->Store = v->Store;		res->comt = v->comt;	}}voidoadd(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TFLOAT;	switch(l.type) {	default:		error("bad lhs type +");	case TINT:		switch(r.type) {		case TINT:			res->type = TINT;			res->ival = l.ival+r.ival;			break;		case TFLOAT:			res->fval = l.ival+r.fval;			break;		default:			error("bad rhs type +");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->fval = l.fval+r.ival;			break;		case TFLOAT:			res->fval = l.fval+r.fval;			break;		default:			error("bad rhs type +");		}		break;	case TSTRING:		if(r.type == TSTRING) {			res->type = TSTRING;			res->fmt = 's';			res->string = stradd(l.string, r.string); 			break;		}		if(r.type == TINT) {			res->type = TSTRING;			res->fmt = 's';			res->string = straddrune(l.string, r.ival);			break;		}		error("bad rhs for +");	case TLIST:		res->type = TLIST;		switch(r.type) {		case TLIST:			res->l = addlist(l.l, r.l);			break;		default:			r.left = 0;			r.right = 0;			res->l = addlist(l.l, construct(&r));			break;		}	}}voidosub(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TFLOAT;	switch(l.type) {	default:		error("bad lhs type -");	case TINT:		switch(r.type) {		case TINT:			res->type = TINT;			res->ival = l.ival-r.ival;			break;		case TFLOAT:			res->fval = l.ival-r.fval;			break;		default:			error("bad rhs type -");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->fval = l.fval-r.ival;			break;		case TFLOAT:			res->fval = l.fval-r.fval;			break;		default:			error("bad rhs type -");		}		break;	}}voidomul(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TFLOAT;	switch(l.type) {	default:		error("bad lhs type *");	case TINT:		switch(r.type) {		case TINT:			res->type = TINT;			res->ival = l.ival*r.ival;			break;		case TFLOAT:			res->fval = l.ival*r.fval;			break;		default:			error("bad rhs type *");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->fval = l.fval*r.ival;			break;		case TFLOAT:			res->fval = l.fval*r.fval;			break;		default:			error("bad rhs type *");		}		break;	}}voidodiv(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TFLOAT;	switch(l.type) {	default:		error("bad lhs type /");	case TINT:		switch(r.type) {		case TINT:			res->type = TINT;			if(r.ival == 0)				error("zero divide");			res->ival = l.ival/r.ival;			break;		case TFLOAT:			if(r.fval == 0)				error("zero divide");			res->fval = l.ival/r.fval;			break;		default:			error("bad rhs type /");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->fval = l.fval/r.ival;			break;		case TFLOAT:			res->fval = l.fval/r.fval;			break;		default:			error("bad rhs type /");		}		break;	}}voidomod(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type %");	res->ival = l.ival%r.ival;}voidolsh(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type <<");	res->ival = l.ival<<r.ival;}voidorsh(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type >>");	res->ival = (uvlong)l.ival>>r.ival;}voidolt(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	switch(l.type) {	default:		error("bad lhs type <");	case TINT:		switch(r.type) {		case TINT:			res->ival = l.ival < r.ival;			break;		case TFLOAT:			res->ival = l.ival < r.fval;			break;		default:			error("bad rhs type <");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->ival = l.fval < r.ival;			break;		case TFLOAT:			res->ival = l.fval < r.fval;			break;		default:			error("bad rhs type <");		}		break;	}}voidogt(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = 'D';	res->op = OCONST;	res->type = TINT;	switch(l.type) {	default:		error("bad lhs type >");	case TINT:		switch(r.type) {		case TINT:			res->ival = l.ival > r.ival;			break;		case TFLOAT:			res->ival = l.ival > r.fval;			break;		default:			error("bad rhs type >");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->ival = l.fval > r.ival;			break;		case TFLOAT:			res->ival = l.fval > r.fval;			break;		default:			error("bad rhs type >");		}		break;	}}voidoleq(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = 'D';	res->op = OCONST;	res->type = TINT;	switch(l.type) {	default:		error("bad expr type <=");	case TINT:		switch(r.type) {		case TINT:			res->ival = l.ival <= r.ival;			break;		case TFLOAT:			res->ival = l.ival <= r.fval;			break;		default:			error("bad expr type <=");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->ival = l.fval <= r.ival;			break;		case TFLOAT:			res->ival = l.fval <= r.fval;			break;		default:			error("bad expr type <=");		}		break;	}}voidogeq(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = 'D';	res->op = OCONST;	res->type = TINT;	switch(l.type) {	default:		error("bad lhs type >=");	case TINT:		switch(r.type) {		case TINT:			res->ival = l.ival >= r.ival;			break;		case TFLOAT:			res->ival = l.ival >= r.fval;			break;		default:			error("bad rhs type >=");		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->ival = l.fval >= r.ival;			break;		case TFLOAT:			res->ival = l.fval >= r.fval;			break;		default:			error("bad rhs type >=");		}		break;	}}voidoeq(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = 'D';	res->op = OCONST;	res->type = TINT;	res->ival = 0;	switch(l.type) {	default:		break;	case TINT:		switch(r.type) {		case TINT:			res->ival = l.ival == r.ival;			break;		case TFLOAT:			res->ival = l.ival == r.fval;			break;		default:			break;		}		break;	case TFLOAT:		switch(r.type) {		case TINT:			res->ival = l.fval == r.ival;			break;		case TFLOAT:			res->ival = l.fval == r.fval;			break;		default:			break;		}		break;	case TSTRING:		if(r.type == TSTRING) {			res->ival = scmp(r.string, l.string);			break;		}		break;	case TLIST:		if(r.type == TLIST) {			res->ival = listcmp(l.l, r.l);			break;		}		break;	}	if(n->op == ONEQ)		res->ival = !res->ival;}voidoland(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type &");	res->ival = l.ival&r.ival;}voidoxor(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type ^");	res->ival = l.ival^r.ival;}voidolor(Node *n, Node *res){	Node l, r;	expr(n->left, &l);	expr(n->right, &r);	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	if(l.type != TINT || r.type != TINT)		error("bad expr type |");	res->ival = l.ival|r.ival;}voidocand(Node *n, Node *res){	Node l, r;	res->fmt = l.fmt;	res->op = OCONST;	res->type = TINT;	res->ival = 0;	expr(n->left, &l);	if(bool(&l) == 0)		return;	expr(n->right, &r);	if(bool(&r) == 0)		return;	res->ival = 1;}voidonot(Node *n, Node *res){	Node l;	res->op = OCONST;	res->type = TINT;	res->ival = 0;	expr(n->left, &l);	if(bool(&l) == 0)		res->ival = 1;}voidocor(Node *n, Node *res){	Node l, r;	res->op = OCONST;	res->type = TINT;	res->ival = 0;	expr(n->left, &l);	if(bool(&l)) {		res->ival = 1;		return;	}	expr(n->right, &r);	if(bool(&r)) {		res->ival = 1;		return;	}}voidoeinc(Node *n, Node *res){	Value *v;	chklval(n->left);	v = n->left->sym->v;	res->op = OCONST;	res->type = v->type;	switch(v->type) {	case TINT:		if(n->op == OEDEC)			v->ival -= fmtsize(v);		else			v->ival += fmtsize(v);		break;				case TFLOAT:		if(n->op == OEDEC)			v->fval--;		else			v->fval++;		break;	default:		error("bad type for pre --/++");	}	res->Store = v->Store;}voidopinc(Node *n, Node *res){	Value *v;	chklval(n->left);	v = n->left->sym->v;	res->op = OCONST;	res->type = v->type;	res->Store = v->Store;	switch(v->type) {	case TINT:		if(n->op == OPDEC)			v->ival -= fmtsize(v);		else			v->ival += fmtsize(v);		break;				case TFLOAT:		if(n->op == OPDEC)			v->fval--;		else			v->fval++;		break;	default:		error("bad type for post --/++");	}}voidocall(Node *n, Node *res){	Lsym *s;	Rplace *rsav;	res->op = OCONST;		/* Default return value */	res->type = TLIST;	res->l = 0;	chklval(n->left);	s = n->left->sym;	if(n->builtin && !s->builtin){		error("no builtin %s", s->name);		return;	}	if(s->builtin && (n->builtin || s->proc == 0)) {		(*s->builtin)(res, n->right);		return;	}	if(s->proc == 0)		error("no function %s", s->name);	rsav = ret;	call(s->name, n->right, s->proc->left, s->proc->right, res);	ret = rsav;}voidofmt(Node *n, Node *res){	expr(n->left, res);	res->fmt = n->right->ival;}voidowhat(Node *n, Node *res){	res->op = OCONST;		/* Default return value */	res->type = TLIST;	res->l = 0;	whatis(n->sym);}void (*expop[])(Node*, Node*) ={	[ONAME]		oname,	[OCONST]	oconst,	[OMUL]		omul,	[ODIV]		odiv,	[OMOD]		omod,	[OADD]		oadd,	[OSUB]		osub,	[ORSH]		orsh,	[OLSH]		olsh,	[OLT]		olt,	[OGT]		ogt,	[OLEQ]		oleq,	[OGEQ]		ogeq,	[OEQ]		oeq,	[ONEQ]		oeq,	[OLAND]		oland,	[OXOR]		oxor,	[OLOR]		olor,	[OCAND]		ocand,	[OCOR]		ocor,	[OASGN]		oasgn,	[OINDM]		oindm,	[OEDEC]		oeinc,	[OEINC]		oeinc,	[OPINC]		opinc,	[OPDEC]		opinc,	[ONOT]		onot,	[OIF]		0,	[ODO]		0,	[OLIST]		olist,	[OCALL]		ocall,	[OCTRUCT]	octruct,	[OWHILE]	0,	[OELSE]		0,	[OHEAD]		ohead,	[OTAIL]		otail,	[OAPPEND]	oappend,	[ORET]		0,	[OINDEX]	oindex,	[OINDC]		oindc,	[ODOT]		odot,	[OLOCAL]	0,	[OFRAME]	oframe,	[OCOMPLEX]	0,	[ODELETE]	odelete,	[OCAST]		ocast,	[OFMT]		ofmt,	[OEVAL]		oeval,	[OWHAT]		owhat,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -