view dmd/Argument.d @ 56:51605de93870

TupleExp.optimize UnrolledLoopStatement.ctor UnrolledLoopStatement.semantic UnrolledLoopStatement.blockExit OrOrExp.checkSideEffect FuncExp.syntaxCopy FuncLiteralDeclaration.syntaxCopy WhileStatement.hasBreak StructInitializer.toExpression StructLiteralExp.ctor StructLiteralExp.optimize BinExp.commonSemanticAssign ModAssignExp.opId Argument.isLazyArray CommaExp.implicitConvTo CommaExp.castTo TypeClass.isBaseOf createTypeInfoArray TypeTuple.getTypeInfoDeclaration TypeInfoTupleDeclaration.ctor TypeNext.constConv XorExp.implicitConvTo TemplateParameter.isTemplateValueParameter
author korDen
date Sat, 21 Aug 2010 14:16:53 +0400
parents 5c9b78899f5d
children e28b18c23469
line wrap: on
line source

module dmd.Argument;

import dmd.Type;
import dmd.Identifier;
import dmd.TypeArray;
import dmd.TypeFunction;
import dmd.TypeDelegate;
import dmd.TypeTuple;
import dmd.TY;
import dmd.Expression;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.ArrayTypes;
import dmd.StorageClassDeclaration;
import dmd.Global;
import dmd.MOD;
import dmd.CppMangleState;
import dmd.STC;

class Argument
{
    //enum InOut inout;
    STC storageClass;
    Type type;
    Identifier ident;
    Expression defaultArg;

    this(STC storageClass, Type type, Identifier ident, Expression defaultArg)
	{
		this.type = type;
		this.ident = ident;
		this.storageClass = storageClass;
		this.defaultArg = defaultArg;
	}
	
	Argument clone()
	{
		return new Argument(storageClass, type, ident, defaultArg);
	}
	
    Argument syntaxCopy()
	{
		return new Argument(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null);
	}
	
	/****************************************************
	 * Determine if parameter is a lazy array of delegates.
	 * If so, return the return type of those delegates.
	 * If not, return null.
	 */
    Type isLazyArray()
	{
	//    if (inout == Lazy)
		{
			Type tb = type.toBasetype();
			if (tb.ty == Tsarray || tb.ty == Tarray)
			{
				Type tel = (cast(TypeArray)tb).next.toBasetype();
				if (tel.ty == Tdelegate)
				{
					TypeDelegate td = cast(TypeDelegate)tel;
					TypeFunction tf = cast(TypeFunction)td.next;

					if (!tf.varargs && Argument.dim(tf.parameters) == 0)
					{
						return tf.next;	// return type of delegate
					}
				}
			}
		}
		return null;
	}
	
    void toDecoBuffer(OutBuffer buf)
	{
		if (storageClass & STC.STCscope)
			buf.writeByte('M');
		switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy))
		{   
			case STC.STCundefined:
			case STC.STCin:
				break;
			case STC.STCout:
				buf.writeByte('J');
				break;
			case STC.STCref:
				buf.writeByte('K');
				break;
			case STC.STClazy:
				buf.writeByte('L');
				break;
		}
static if (false) {
		int mod = 0x100;
		if (type.toBasetype().ty == TY.Tclass)
			mod = 0;
		type.toDecoBuffer(buf, mod);
} else {
		//type.toHeadMutable().toDecoBuffer(buf, 0);
		type.toDecoBuffer(buf, 0);
}
	}
	
    static Arguments arraySyntaxCopy(Arguments args)
	{
		Arguments a = null;

		if (args)
		{
			a = new Arguments();
			a.setDim(args.dim);

			for (size_t i = 0; i < a.dim; i++)
			{   
				Argument arg = cast(Argument)args.data[i];

				arg = arg.syntaxCopy();
				a.data[i] = cast(void*)arg;
			}
		}
	
		return a;
	}
	
    static string argsTypesToChars(Arguments args, int varargs)
	{
		scope OutBuffer buf = new OutBuffer();

	static if (true) {
		HdrGenState hgs;
		argsToCBuffer(buf, &hgs, args, varargs);
	} else {
		buf.writeByte('(');
		if (args)
		{	
			OutBuffer argbuf = new OutBuffer();
			HdrGenState hgs;

			for (int i = 0; i < args.dim; i++)
			{   
				if (i)
					buf.writeByte(',');
				Argument arg = cast(Argument)args.data[i];
				argbuf.reset();
				arg.type.toCBuffer2(&argbuf, &hgs, 0);
				buf.write(&argbuf);
			}
			if (varargs)
			{
				if (i && varargs == 1)
					buf.writeByte(',');
				buf.writestring("...");
			}
		}
		buf.writeByte(')');
	}
		return buf.toChars();
	}
	
    static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Arguments arguments, int varargs)
	{
		assert(false);
	}
	
    static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Arguments arguments, int varargs)
	{
		buf.writeByte('(');
		if (arguments)
		{	
			int i;
			scope OutBuffer argbuf = new OutBuffer();

			for (i = 0; i < arguments.dim; i++)
			{
				if (i)
					buf.writestring(", ");
				Argument arg = cast(Argument)arguments.data[i];

				if (arg.storageClass & STCout)
					buf.writestring("out ");
				else if (arg.storageClass & STCref)
					buf.writestring((global.params.Dversion == 1) ? "inout " : "ref ");
				else if (arg.storageClass & STCin)
					buf.writestring("in ");
				else if (arg.storageClass & STClazy)
					buf.writestring("lazy ");
				else if (arg.storageClass & STCalias)
					buf.writestring("alias ");
				else if (arg.storageClass & STCauto)
					buf.writestring("auto ");

				uint stc = arg.storageClass;
				if (arg.type && arg.type.mod & MODshared)
					stc &= ~STCshared;

				StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope));

				argbuf.reset();
				if (arg.storageClass & STCalias)
				{	
					if (arg.ident)
						argbuf.writestring(arg.ident.toChars());
				}
				else
					arg.type.toCBuffer(argbuf, arg.ident, hgs);
				if (arg.defaultArg)
				{
					argbuf.writestring(" = ");
					arg.defaultArg.toCBuffer(argbuf, hgs);
				}
				buf.write(argbuf);
			}
			if (varargs)
			{
				if (i && varargs == 1)
					buf.writeByte(',');
				buf.writestring("...");
			}
		}
		buf.writeByte(')');
	}
	
    static void argsToDecoBuffer(OutBuffer buf, Arguments arguments)
	{
		//printf("Argument::argsToDecoBuffer()\n");

		// Write argument types
		if (arguments)
		{
			size_t dim = Argument.dim(arguments);
			for (size_t i = 0; i < dim; i++)
			{
				Argument arg = Argument.getNth(arguments, i);
				arg.toDecoBuffer(buf);
			}
		}
	}
	
    static int isTPL(Arguments arguments)
	{
		assert(false);
	}

	/***************************************
	 * Determine number of arguments, folding in tuples.
	 */	
    static size_t dim(Arguments args)
	{
		size_t n = 0;
		if (args)
		{
			for (size_t i = 0; i < args.dim; i++)
			{   
				Argument arg = cast(Argument)args.data[i];
				Type t = arg.type.toBasetype();

				if (t.ty == TY.Ttuple)
				{   
					TypeTuple tu = cast(TypeTuple)t;
					n += dim(tu.arguments);
				}
				else
					n++;
			}
		}
		return n;
	}
	
	/***************************************
	 * Get nth Argument, folding in tuples.
	 * Returns:
	 *	Argument	nth Argument
	 *	null		not found, *pn gets incremented by the number
	 *			of Arguments
	 */
    static Argument getNth(Arguments args, size_t nth, size_t* pn = null)
	{
		if (!args)
			return null;

		size_t n = 0;
		for (size_t i = 0; i < args.dim; i++)
		{   
			Argument arg = cast(Argument)args.data[i];
			Type t = arg.type.toBasetype();

			if (t.ty == TY.Ttuple)
			{   TypeTuple tu = cast(TypeTuple)t;
				arg = getNth(tu.arguments, nth - n, &n);
				if (arg)
					return arg;
			}
			else if (n == nth)
				return arg;
			else
				n++;
		}

		if (pn)
			*pn += n;

		return null;
	}
}