コード例 #1
0
ファイル: racewalk.c プロジェクト: 8l/go
static Node*
detachexpr(Node *n, NodeList **init)
{
	Node *addr, *as, *ind, *l;

	addr = nod(OADDR, n, N);
	l = temp(ptrto(n->type));
	as = nod(OAS, l, addr);
	typecheck(&as, Etop);
	walkexpr(&as, init);
	*init = list(*init, as);
	ind = nod(OIND, l, N);
	typecheck(&ind, Erv);
	walkexpr(&ind, init);
	return ind;
}
コード例 #2
0
ファイル: sinit.c プロジェクト: WXB506/golang
static void
arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Node *index, *value;

	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("arraylit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0) {
				if(pass == 1 && ctxt != 0) {
					a = nod(OINDEX, var, index);
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 2 && ctxt == 0) {
					a = nod(OINDEX, var, index);
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 3)
					break;
				continue;
			}
			a = nod(OINDEX, var, index);
			arraylit(ctxt, pass, value, a, init);
			continue;

		case OSTRUCTLIT:
			a = nod(OINDEX, var, index);
			structlit(ctxt, pass, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value)) {
			if(pass == 2)
				continue;
		} else
			if(pass == 1)
				continue;

		// build list of var[index] = value
		a = nod(OINDEX, var, index);
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);	// add any assignments in r to top
		if(pass == 1) {
			if(a->op != OAS)
				fatal("structlit: not as");
			a->dodata = 2;
		}
		*init = list(*init, a);
	}
}
コード例 #3
0
ファイル: sinit.c プロジェクト: WXB506/golang
static void
structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *nl;
	Node *index, *value;

	for(nl=n->list; nl; nl=nl->next) {
		r = nl->n;
		if(r->op != OKEY)
			fatal("structlit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0) {
				if(pass == 1 && ctxt != 0) {
					a = nod(ODOT, var, newname(index->sym));
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 2 && ctxt == 0) {
					a = nod(ODOT, var, newname(index->sym));
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 3)
					break;
				continue;
			}
			a = nod(ODOT, var, newname(index->sym));
			arraylit(ctxt, pass, value, a, init);
			continue;

		case OSTRUCTLIT:
			a = nod(ODOT, var, newname(index->sym));
			structlit(ctxt, pass, value, a, init);
			continue;
		}

		if(isliteral(value)) {
			if(pass == 2)
				continue;
		} else
			if(pass == 1)
				continue;

		// build list of var.field = expr
		a = nod(ODOT, var, newname(index->sym));
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		if(pass == 1) {
			if(a->op != OAS)
				fatal("structlit: not as");
			a->dodata = 2;
		}
		*init = list(*init, a);
	}
}
コード例 #4
0
ファイル: sinit.c プロジェクト: WXB506/golang
static void
litas(Node *l, Node *r, NodeList **init)
{
	Node *a;

	a = nod(OAS, l, r);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);
}
コード例 #5
0
ファイル: swt.c プロジェクト: 8l/go
/*
 * convert switch of the form
 *	switch v := i.(type) { case t1: ..; case t2: ..; }
 * into if statements
 */
static void
typeswitch(Node *sw)
{
	Node *def;
	NodeList *cas, *hash;
	Node *a, *n;
	Case *c, *c0, *c1;
	int ncase;
	Type *t;
	Val v;

	if(sw->ntest == nil)
		return;
	if(sw->ntest->right == nil) {
		setlineno(sw);
		yyerror("type switch must have an assignment");
		return;
	}
	walkexpr(&sw->ntest->right, &sw->ninit);
	if(!istype(sw->ntest->right->type, TINTER)) {
		yyerror("type switch must be on an interface");
		return;
	}
	cas = nil;

	/*
	 * predeclare temporary variables
	 * and the boolean var
	 */
	facename = temp(sw->ntest->right->type);
	a = nod(OAS, facename, sw->ntest->right);
	typecheck(&a, Etop);
	cas = list(cas, a);

	casebody(sw, facename);

	boolname = temp(types[TBOOL]);
	typecheck(&boolname, Erv);

	hashname = temp(types[TUINT32]);
	typecheck(&hashname, Erv);

	t = sw->ntest->right->type;
	if(isnilinter(t))
		a = syslook("efacethash", 1);
	else
		a = syslook("ifacethash", 1);
	argtype(a, t);
	a = nod(OCALL, a, N);
	a->list = list1(facename);
	a = nod(OAS, hashname, a);
	typecheck(&a, Etop);
	cas = list(cas, a);

	c0 = mkcaselist(sw, Stype);
	if(c0 != C && c0->type == Tdefault) {
		def = c0->node->right;
		c0 = c0->link;
	} else {
		def = nod(OBREAK, N, N);
	}
	
	/*
	 * insert if statement into each case block
	 */
	for(c=c0; c!=C; c=c->link) {
		n = c->node;
		switch(c->type) {

		case Ttypenil:
			v.ctype = CTNIL;
			a = nod(OIF, N, N);
			a->ntest = nod(OEQ, facename, nodlit(v));
			typecheck(&a->ntest, Erv);
			a->nbody = list1(n->right);		// if i==nil { goto l }
			n->right = a;
			break;
		
		case Ttypevar:
		case Ttypeconst:
			n->right = typeone(n);
			break;
		}
	}

	/*
	 * generate list of if statements, binary search for constant sequences
	 */
	while(c0 != C) {
		if(c0->type != Ttypeconst) {
			n = c0->node;
			cas = list(cas, n->right);
			c0=c0->link;
			continue;
		}
		
		// identify run of constants
		c1 = c = c0;
		while(c->link!=C && c->link->type==Ttypeconst)
			c = c->link;
		c0 = c->link;
		c->link = nil;

		// sort by hash
		c1 = csort(c1, typecmp);
		
		// for debugging: linear search
		if(0) {
			for(c=c1; c!=C; c=c->link) {
				n = c->node;
				cas = list(cas, n->right);
			}
			continue;
		}

		// combine adjacent cases with the same hash
		ncase = 0;
		for(c=c1; c!=C; c=c->link) {
			ncase++;
			hash = list1(c->node->right);
			while(c->link != C && c->link->hash == c->hash) {
				hash = list(hash, c->link->node->right);
				c->link = c->link->link;
			}
			c->node->right = liststmt(hash);
		}
		
		// binary search among cases to narrow by hash
		cas = list(cas, typebsw(c1, ncase));
	}
	if(nerrors == 0) {
		cas = list(cas, def);
		sw->nbody = concat(cas, sw->nbody);
		sw->list = nil;
		walkstmtlist(sw->nbody);
	}
}
コード例 #6
0
ファイル: swt.c プロジェクト: 8l/go
/*
 * normal (expression) switch.
 * rebulid case statements into if .. goto
 */
static void
exprswitch(Node *sw)
{
	Node *def;
	NodeList *cas;
	Node *a;
	Case *c0, *c, *c1;
	Type *t;
	int arg, ncase;

	casebody(sw, N);

	arg = Snorm;
	if(isconst(sw->ntest, CTBOOL)) {
		arg = Strue;
		if(sw->ntest->val.u.bval == 0)
			arg = Sfalse;
	}
	walkexpr(&sw->ntest, &sw->ninit);
	t = sw->type;
	if(t == T)
		return;

	/*
	 * convert the switch into OIF statements
	 */
	exprname = N;
	cas = nil;
	if(arg != Strue && arg != Sfalse) {
		exprname = temp(sw->ntest->type);
		cas = list1(nod(OAS, exprname, sw->ntest));
		typechecklist(cas, Etop);
	} else {
		exprname = nodbool(arg == Strue);
	}

	c0 = mkcaselist(sw, arg);
	if(c0 != C && c0->type == Tdefault) {
		def = c0->node->right;
		c0 = c0->link;
	} else {
		def = nod(OBREAK, N, N);
	}

loop:
	if(c0 == C) {
		cas = list(cas, def);
		sw->nbody = concat(cas, sw->nbody);
		sw->list = nil;
		walkstmtlist(sw->nbody);
		return;
	}

	// deal with the variables one-at-a-time
	if(!okforcmp[t->etype] || c0->type != Texprconst) {
		a = exprbsw(c0, 1, arg);
		cas = list(cas, a);
		c0 = c0->link;
		goto loop;
	}

	// do binary search on run of constants
	ncase = 1;
	for(c=c0; c->link!=C; c=c->link) {
		if(c->link->type != Texprconst)
			break;
		ncase++;
	}

	// break the chain at the count
	c1 = c->link;
	c->link = C;

	// sort and compile constants
	c0 = csort(c0, exprcmp);
	a = exprbsw(c0, ncase, arg);
	cas = list(cas, a);

	c0 = c1;
	goto loop;

}
コード例 #7
0
ファイル: swt.c プロジェクト: edisonwsk/golang-on-cygwin
/*
 * convert switch of the form
 *	switch v := i.(type) { case t1: ..; case t2: ..; }
 * into if statements
 */
void
typeswitch(Node *sw)
{
	Node *def;
	NodeList *cas;
	Node *a;
	Case *c, *c0, *c1;
	int ncase;
	Type *t;

	if(sw->ntest == nil)
		return;
	if(sw->ntest->right == nil) {
		setlineno(sw);
		yyerror("type switch must have an assignment");
		return;
	}
	walkexpr(&sw->ntest->right, &sw->ninit);
	if(!istype(sw->ntest->right->type, TINTER)) {
		yyerror("type switch must be on an interface");
		return;
	}
	cas = nil;

	/*
	 * predeclare temporary variables
	 * and the boolean var
	 */
	facename = nod(OXXX, N, N);
	tempname(facename, sw->ntest->right->type);
	a = nod(OAS, facename, sw->ntest->right);
	typecheck(&a, Etop);
	cas = list(cas, a);

	casebody(sw, facename);

	boolname = nod(OXXX, N, N);
	tempname(boolname, types[TBOOL]);
	typecheck(&boolname, Erv);

	hashname = nod(OXXX, N, N);
	tempname(hashname, types[TUINT32]);
	typecheck(&hashname, Erv);

	t = sw->ntest->right->type;
	if(isnilinter(t))
		a = syslook("efacethash", 1);
	else
		a = syslook("ifacethash", 1);
	argtype(a, t);
	a = nod(OCALL, a, N);
	a->list = list1(facename);
	a = nod(OAS, hashname, a);
	typecheck(&a, Etop);
	cas = list(cas, a);

	c0 = mkcaselist(sw, Stype);
	if(c0 != C && c0->type == Tdefault) {
		def = c0->node->right;
		c0 = c0->link;
	} else {
		def = nod(OBREAK, N, N);
	}

loop:
	if(c0 == C) {
		cas = list(cas, def);
		sw->nbody = concat(cas, sw->nbody);
		sw->list = nil;
		walkstmtlist(sw->nbody);
		return;
	}

	// deal with the variables one-at-a-time
	if(c0->type != Ttypeconst) {
		a = typebsw(c0, 1);
		cas = list(cas, a);
		c0 = c0->link;
		goto loop;
	}

	// do binary search on run of constants
	ncase = 1;
	for(c=c0; c->link!=C; c=c->link) {
		if(c->link->type != Ttypeconst)
			break;
		ncase++;
	}

	// break the chain at the count
	c1 = c->link;
	c->link = C;

	// sort and compile constants
	c0 = csort(c0, typecmp);
	a = typebsw(c0, ncase);
	cas = list(cas, a);

	c0 = c1;
	goto loop;
}
コード例 #8
0
ファイル: sinit.c プロジェクト: WXB506/golang
void
anylit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Type *t;
	Node *a, *vstat;

	t = n->type;
	switch(n->op) {
	default:
		fatal("anylit: not lit");

	case OSTRUCTLIT:
		if(t->etype != TSTRUCT)
			fatal("anylit: not struct");

		if(simplename(var)) {

			if(ctxt == 0) {
				// lay out static data
				vstat = staticname(t, ctxt);
				structlit(ctxt, 1, n, vstat, init);

				// copy static to var
				a = nod(OAS, var, vstat);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				*init = list(*init, a);

				// add expressions to automatic
				structlit(ctxt, 2, n, var, init);
				break;
			}
			structlit(ctxt, 1, n, var, init);
			structlit(ctxt, 2, n, var, init);
			break;
		}

		// initialize of not completely specified
		if(count(n->list) < structcount(t)) {
			a = nod(OAS, var, N);
			typecheck(&a, Etop);
			walkexpr(&a, init);
			*init = list(*init, a);
		}
		structlit(ctxt, 3, n, var, init);
		break;

	case OARRAYLIT:
		if(t->etype != TARRAY)
			fatal("anylit: not array");
		if(t->bound < 0) {
			slicelit(ctxt, n, var, init);
			break;
		}

		if(simplename(var)) {

			if(ctxt == 0) {
				// lay out static data
				vstat = staticname(t, ctxt);
				arraylit(1, 1, n, vstat, init);

				// copy static to automatic
				a = nod(OAS, var, vstat);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				*init = list(*init, a);

				// add expressions to automatic
				arraylit(ctxt, 2, n, var, init);
				break;
			}
			arraylit(ctxt, 1, n, var, init);
			arraylit(ctxt, 2, n, var, init);
			break;
		}

		// initialize of not completely specified
		if(count(n->list) < t->bound) {
			a = nod(OAS, var, N);
			typecheck(&a, Etop);
			walkexpr(&a, init);
			*init = list(*init, a);
		}
		arraylit(ctxt, 3, n, var, init);
		break;

	case OMAPLIT:
		if(t->etype != TMAP)
			fatal("anylit: not map");
		maplit(ctxt, n, var, init);
		break;
	}
}
コード例 #9
0
ファイル: sinit.c プロジェクト: WXB506/golang
static void
maplit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	int nerr, b;
	Type *t, *tk, *tv, *t1;
	Node *vstat, *index, *value;
	Sym *syma, *symb;

ctxt = 0;

	// make the map var
	nerr = nerrors;

	a = nod(OMAKE, N, N);
	a->list = list1(typenod(n->type));
	litas(var, a, init);

	// count the initializers
	b = 0;
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			b++;
	}

	t = T;
	if(b != 0) {
		// build type [count]struct { a Tindex, b Tvalue }
		t = n->type;
		tk = t->down;
		tv = t->type;

		symb = lookup("b");
		t = typ(TFIELD);
		t->type = tv;
		t->sym = symb;

		syma = lookup("a");
		t1 = t;
		t = typ(TFIELD);
		t->type = tk;
		t->sym = syma;
		t->down = t1;

		t1 = t;
		t = typ(TSTRUCT);
		t->type = t1;

		t1 = t;
		t = typ(TARRAY);
		t->bound = b;
		t->type = t1;

		dowidth(t);

		// make and initialize static array
		vstat = staticname(t, ctxt);
		b = 0;
		for(l=n->list; l; l=l->next) {
			r = l->n;

			if(r->op != OKEY)
				fatal("slicelit: rhs not OKEY: %N", r);
			index = r->left;
			value = r->right;

			if(isliteral(index) && isliteral(value)) {
				// build vstat[b].a = key;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(syma));
				a = nod(OAS, a, index);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				// build vstat[b].b = value;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(symb));
				a = nod(OAS, a, value);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				b++;
			}
		}

		// loop adding structure elements to map
		// for i = 0; i < len(vstat); i++ {
		//	map[vstat[i].a] = vstat[i].b
		// }
		index = nod(OXXX, N, N);
		tempname(index, types[TINT]);

		a = nod(OINDEX, vstat, index);
		a->etype = 1;	// no bounds checking
		a = nod(ODOT, a, newname(symb));

		r = nod(OINDEX, vstat, index);
		r->etype = 1;	// no bounds checking
		r = nod(ODOT, r, newname(syma));
		r = nod(OINDEX, var, r);

		r = nod(OAS, r, a);

		a = nod(OFOR, N, N);
		a->nbody = list1(r);

		a->ninit = list1(nod(OAS, index, nodintconst(0)));
		a->ntest = nod(OLT, index, nodintconst(t->bound));
		a->nincr = nod(OASOP, index, nodintconst(1));
		a->nincr->etype = OADD;

		typecheck(&a, Etop);
		walkstmt(&a);
		*init = list(*init, a);
	}

	// put in dynamic entries one-at-a-time
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OINDEX, var, r->left);
		a = nod(OAS, a, r->right);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		if(nerr != nerrors)
			break;

		*init = list(*init, a);
	}
}
コード例 #10
0
ファイル: sinit.c プロジェクト: WXB506/golang
static void
slicelit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Type *t;
	Node *vstat, *vauto;
	Node *index, *value;
	int mode;

	// make an array type
	t = shallow(n->type);
	t->bound = mpgetfix(n->right->val.u.xval);
	t->width = 0;
	t->sym = nil;
	dowidth(t);

	if(ctxt != 0) {

		// put everything into static array
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
		arraylit(ctxt, 2, n, vstat, init);

		// copy static to slice
		a = nod(OSLICE, vstat, nod(OKEY, N, N));
		a = nod(OAS, var, a);
		typecheck(&a, Etop);
		a->dodata = 2;
		*init = list(*init, a);
		return;
	}

	// recipe for var = []t{...}
	// 1. make a static array
	//	var vstat [...]t
	// 2. assign (data statements) the constant part
	//	vstat = constpart{}
	// 3. make an auto pointer to array and allocate heap to it
	//	var vauto *[...]t = new([...]t)
	// 4. copy the static array to the auto array
	//	*vauto = vstat
	// 5. assign slice of allocated heap to var
	//	var = [0:]*auto
	// 6. for each dynamic part assign to the slice
	//	var[i] = dynamic part
	//
	// an optimization is done if there is no constant part
	//	3. var vauto *[...]t = new([...]t)
	//	5. var = [0:]*auto
	//	6. var[i] = dynamic part

	// if the literal contains constants,
	// make static initialized array (1),(2)
	vstat = N;
	mode = getdyn(n, 1);
	if(mode & MODECONST) {
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
	}

	// make new auto *array (3 declare)
	vauto = nod(OXXX, N, N);
	tempname(vauto, ptrto(t));

	// set auto to point at new heap (3 assign)
	a = nod(ONEW, N, N);
	a->list = list1(typenod(t));
	a = nod(OAS, vauto, a);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	if(vstat != N) {
		// copy static to heap (4)
		a = nod(OIND, vauto, N);
		a = nod(OAS, a, vstat);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}

	// make slice out of heap (5)
	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	// put dynamics into slice (6)
	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;
		a = nod(OINDEX, var, index);
		a->etype = 1;	// no bounds checking
		// TODO need to check bounds?

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0)
				break;
			arraylit(ctxt, 2, value, a, init);
			continue;

		case OSTRUCTLIT:
			structlit(ctxt, 2, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}
}