Merged DMD 1.034, array operations are not yet implemented ;)

This commit is contained in:
Tomas Lindquist Olsen
2008-08-14 06:55:41 +02:00
parent c092165b3a
commit 5aae7a6bee
13 changed files with 1149 additions and 173 deletions

505
dmd/arrayop.c Normal file
View File

@@ -0,0 +1,505 @@
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#if _WIN32 || IN_GCC || IN_LLVM
#include "mem.h"
#else
#include "../root/mem.h"
#endif
#include "stringtable.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "declaration.h"
#include "scope.h"
#include "id.h"
#include "module.h"
#include "init.h"
// FIXME
int binary(const char *p , const char **tab, int high)
{
assert(0);
}
/**************************************
* Hash table of array op functions already generated or known about.
*/
StringTable arrayfuncs;
/***********************************
* Construct the array operation expression.
*/
Expression *BinExp::arrayOp(Scope *sc)
{
// FIXME
error("array operations not yet implemented");
fatal();
Expressions *arguments = new Expressions();
/* The expression to generate an array operation for is mangled
* into a name to use as the array operation function name.
* Mangle in the operands and operators in RPN order, and type.
*/
OutBuffer buf;
buf.writestring("_array");
buildArrayIdent(&buf, arguments);
buf.writeByte('_');
/* Append deco of array element type
*/
#if DMDV2
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
#else
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
#endif
size_t namelen = buf.offset;
buf.writeByte(0);
char *name = (char *)buf.extractData();
/* Look up name in hash table
*/
StringValue *sv = arrayfuncs.update(name, namelen);
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
if (!fd)
{
/* Some of the array op functions are written as library functions,
* presumably to optimize them with special CPU vector instructions.
* List those library functions here, in alpha order.
*/
static const char *libArrayopFuncs[] =
{
"_arrayExpSliceAddass_a",
"_arrayExpSliceAddass_d", // T[]+=T
"_arrayExpSliceAddass_f", // T[]+=T
"_arrayExpSliceAddass_g",
"_arrayExpSliceAddass_h",
"_arrayExpSliceAddass_i",
"_arrayExpSliceAddass_k",
"_arrayExpSliceAddass_s",
"_arrayExpSliceAddass_t",
"_arrayExpSliceAddass_u",
"_arrayExpSliceAddass_w",
"_arrayExpSliceDivass_d", // T[]/=T
"_arrayExpSliceDivass_f", // T[]/=T
"_arrayExpSliceMinSliceAssign_a",
"_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_g",
"_arrayExpSliceMinSliceAssign_h",
"_arrayExpSliceMinSliceAssign_i",
"_arrayExpSliceMinSliceAssign_k",
"_arrayExpSliceMinSliceAssign_s",
"_arrayExpSliceMinSliceAssign_t",
"_arrayExpSliceMinSliceAssign_u",
"_arrayExpSliceMinSliceAssign_w",
"_arrayExpSliceMinass_a",
"_arrayExpSliceMinass_d", // T[]-=T
"_arrayExpSliceMinass_f", // T[]-=T
"_arrayExpSliceMinass_g",
"_arrayExpSliceMinass_h",
"_arrayExpSliceMinass_i",
"_arrayExpSliceMinass_k",
"_arrayExpSliceMinass_s",
"_arrayExpSliceMinass_t",
"_arrayExpSliceMinass_u",
"_arrayExpSliceMinass_w",
"_arrayExpSliceMulass_d", // T[]*=T
"_arrayExpSliceMulass_f", // T[]*=T
"_arrayExpSliceMulass_i",
"_arrayExpSliceMulass_k",
"_arrayExpSliceMulass_s",
"_arrayExpSliceMulass_t",
"_arrayExpSliceMulass_u",
"_arrayExpSliceMulass_w",
"_arraySliceExpAddSliceAssign_a",
"_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_g",
"_arraySliceExpAddSliceAssign_h",
"_arraySliceExpAddSliceAssign_i",
"_arraySliceExpAddSliceAssign_k",
"_arraySliceExpAddSliceAssign_s",
"_arraySliceExpAddSliceAssign_t",
"_arraySliceExpAddSliceAssign_u",
"_arraySliceExpAddSliceAssign_w",
"_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
"_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
"_arraySliceExpMinSliceAssign_a",
"_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_g",
"_arraySliceExpMinSliceAssign_h",
"_arraySliceExpMinSliceAssign_i",
"_arraySliceExpMinSliceAssign_k",
"_arraySliceExpMinSliceAssign_s",
"_arraySliceExpMinSliceAssign_t",
"_arraySliceExpMinSliceAssign_u",
"_arraySliceExpMinSliceAssign_w",
"_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
"_arraySliceExpMulSliceAddass_f",
"_arraySliceExpMulSliceAddass_r",
"_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_i",
"_arraySliceExpMulSliceAssign_k",
"_arraySliceExpMulSliceAssign_s",
"_arraySliceExpMulSliceAssign_t",
"_arraySliceExpMulSliceAssign_u",
"_arraySliceExpMulSliceAssign_w",
"_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
"_arraySliceExpMulSliceMinass_f",
"_arraySliceExpMulSliceMinass_r",
"_arraySliceSliceAddSliceAssign_a",
"_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_g",
"_arraySliceSliceAddSliceAssign_h",
"_arraySliceSliceAddSliceAssign_i",
"_arraySliceSliceAddSliceAssign_k",
"_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_s",
"_arraySliceSliceAddSliceAssign_t",
"_arraySliceSliceAddSliceAssign_u",
"_arraySliceSliceAddSliceAssign_w",
"_arraySliceSliceAddass_a",
"_arraySliceSliceAddass_d", // T[]+=T[]
"_arraySliceSliceAddass_f", // T[]+=T[]
"_arraySliceSliceAddass_g",
"_arraySliceSliceAddass_h",
"_arraySliceSliceAddass_i",
"_arraySliceSliceAddass_k",
"_arraySliceSliceAddass_s",
"_arraySliceSliceAddass_t",
"_arraySliceSliceAddass_u",
"_arraySliceSliceAddass_w",
"_arraySliceSliceMinSliceAssign_a",
"_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_g",
"_arraySliceSliceMinSliceAssign_h",
"_arraySliceSliceMinSliceAssign_i",
"_arraySliceSliceMinSliceAssign_k",
"_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_s",
"_arraySliceSliceMinSliceAssign_t",
"_arraySliceSliceMinSliceAssign_u",
"_arraySliceSliceMinSliceAssign_w",
"_arraySliceSliceMinass_a",
"_arraySliceSliceMinass_d", // T[]-=T[]
"_arraySliceSliceMinass_f", // T[]-=T[]
"_arraySliceSliceMinass_g",
"_arraySliceSliceMinass_h",
"_arraySliceSliceMinass_i",
"_arraySliceSliceMinass_k",
"_arraySliceSliceMinass_s",
"_arraySliceSliceMinass_t",
"_arraySliceSliceMinass_u",
"_arraySliceSliceMinass_w",
"_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_i",
"_arraySliceSliceMulSliceAssign_k",
"_arraySliceSliceMulSliceAssign_s",
"_arraySliceSliceMulSliceAssign_t",
"_arraySliceSliceMulSliceAssign_u",
"_arraySliceSliceMulSliceAssign_w",
"_arraySliceSliceMulass_d", // T[]*=T[]
"_arraySliceSliceMulass_f", // T[]*=T[]
"_arraySliceSliceMulass_i",
"_arraySliceSliceMulass_k",
"_arraySliceSliceMulass_s",
"_arraySliceSliceMulass_t",
"_arraySliceSliceMulass_u",
"_arraySliceSliceMulass_w",
};
int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
if (i == -1)
{
#ifdef DEBUG // Make sure our array is alphabetized
for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
{
if (strcmp(name, libArrayopFuncs[i]) == 0)
assert(0);
}
#endif
/* Not in library, so generate it.
* Construct the function body:
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
* loopbody;
* return p;
*/
Arguments *fparams = new Arguments();
Expression *loopbody = buildArrayLoop(fparams);
Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new DeclarationStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
new Argument(0, NULL, Id::p, NULL),
new IntegerExp(0, 0, Type::tint32),
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
new ExpStatement(0, loopbody));
#endif
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(0, s1, s2);
/* Construct the function
*/
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKc;
sc->module->importedFrom->members->push(fd);
sc = sc->push();
sc->parent = sc->module->importedFrom;
sc->stc = 0;
sc->linkage = LINKc;
fd->semantic(sc);
sc->pop();
}
else
{ /* In library, refer to it.
*/
// LLVMDC FIXME
fd = FuncDeclaration::genCfunc(NULL, type, name);
}
sv->ptrvalue = fd; // cache symbol in hash table
}
/* Call the function fd(arguments)
*/
Expression *ec = new VarExp(0, fd);
Expression *e = new CallExp(loc, ec, arguments);
e->type = type;
return e;
}
/******************************************
* Construct the identifier for the array operation function,
* and build the argument list to pass to it.
*/
void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Exp");
arguments->shift(this);
}
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
arguments->shift(this);
}
void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
/* Evaluate assign expressions right to left
*/
e2->buildArrayIdent(buf, arguments);
e1->buildArrayIdent(buf, arguments);
buf->writestring("Assign");
}
#define X(Str) \
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions right to left \
*/ \
e2->buildArrayIdent(buf, arguments); \
e1->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
buf->writestring("ass"); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Neg");
}
void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Com");
}
#define X(Str) \
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions left to right \
*/ \
e1->buildArrayIdent(buf, arguments); \
e2->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
/******************************************
* Construct the inner loop for the array operation function,
* and build the parameter list.
*/
Expression *Expression::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("c", fparams->dim);
Argument *param = new Argument(0, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
return e;
}
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Argument *param = new Argument(STCconst, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
Expressions *arguments = new Expressions();
Expression *index = new IdentifierExp(0, Id::p);
arguments->push(index);
e = new ArrayExp(0, e, arguments);
return e;
}
Expression *AssignExp::buildArrayLoop(Arguments *fparams)
{
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
Expression *ex1 = e1->buildArrayLoop(fparams);
Argument *param = (Argument *)fparams->data[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
return e;
}
#define X(Str) \
Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions right to left \
*/ \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Argument *param = (Argument *)fparams->data[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
Expression *NegExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new NegExp(0, ex1);
return e;
}
Expression *ComExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new ComExp(0, ex1);
return e;
}
#define X(Str) \
Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions left to right \
*/ \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *e = new Str##Exp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X

View File

@@ -46,6 +46,14 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
loc.toChars(), toChars(), type->toChars(), t->toChars());
}
#if DMDV2
if (match == MATCHconst && t == type->constOf())
{
Expression *e = copy();
e->type = t;
return e;
}
#endif
return castTo(sc, t);
}
@@ -54,12 +62,13 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
return e->implicitCastTo(sc, t);
#if 0
printf("ty = %d\n", type->ty);
print();
type->print();
printf("to:\n");
t->print();
printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
//printf("%p %p %p\n", type->next->arrayOf(), type, t);
//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
fflush(stdout);
#endif
if (!t->deco)
@@ -92,6 +101,7 @@ MATCH Expression::implicitConvTo(Type *t)
printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
//static int nest; if (++nest == 10) halt();
if (!type)
{ error("%s is not an expression", toChars());
type = Type::terror;
@@ -110,16 +120,16 @@ MATCH Expression::implicitConvTo(Type *t)
Type *tb = t->toBasetype();
if (tb->ty == Tdelegate)
{ TypeDelegate *td = (TypeDelegate *)tb;
TypeFunction *tf = (TypeFunction *)td->next;
TypeFunction *tf = (TypeFunction *)td->nextOf();
if (!tf->varargs &&
!(tf->arguments && tf->arguments->dim)
)
{
match = type->implicitConvTo(tf->next);
match = type->implicitConvTo(tf->nextOf());
if (match)
return match;
if (tf->next->toBasetype()->ty == Tvoid)
if (tf->nextOf()->toBasetype()->ty == Tvoid)
return MATCHconvert;
}
}
@@ -332,6 +342,39 @@ MATCH NullExp::implicitConvTo(Type *t)
return Expression::implicitConvTo(t);
}
#if DMDV2
MATCH StructLiteralExp::implicitConvTo(Type *t)
{
#if 0
printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
MATCH m = Expression::implicitConvTo(t);
if (m != MATCHnomatch)
return m;
if (type->ty == t->ty && type->ty == Tstruct &&
((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym)
{
m = MATCHconst;
for (int i = 0; i < elements->dim; i++)
{ Expression *e = (Expression *)elements->data[i];
Type *te = e->type;
if (t->mod == 0)
te = te->mutableOf();
else
{ assert(t->mod == MODinvariant);
te = te->invariantOf();
}
MATCH m2 = e->implicitConvTo(te);
//printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
if (m2 < m)
m = m2;
}
}
return m;
}
#endif
MATCH StringExp::implicitConvTo(Type *t)
{ MATCH m;
@@ -387,6 +430,10 @@ MATCH StringExp::implicitConvTo(Type *t)
MATCH ArrayLiteralExp::implicitConvTo(Type *t)
{ MATCH result = MATCHexact;
#if 0
printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
Type *typeb = type->toBasetype();
Type *tb = t->toBasetype();
if ((tb->ty == Tarray || tb->ty == Tsarray) &&
@@ -400,7 +447,7 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
for (int i = 0; i < elements->dim; i++)
{ Expression *e = (Expression *)elements->data[i];
MATCH m = (MATCH)e->implicitConvTo(tb->next);
MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
if (m < result)
result = m; // remember worst match
if (result == MATCHnomatch)
@@ -427,7 +474,7 @@ MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
if (result == MATCHnomatch)
break; // no need to check for worse
e = (Expression *)values->data[i];
m = (MATCH)e->implicitConvTo(tb->next);
m = (MATCH)e->implicitConvTo(tb->nextOf());
if (m < result)
result = m; // remember worst match
if (result == MATCHnomatch)
@@ -516,10 +563,10 @@ MATCH DelegateExp::implicitConvTo(Type *t)
FuncDeclaration *f;
t = t->toBasetype();
if (type->ty == Tdelegate && type->next->ty == Tfunction &&
t->ty == Tdelegate && t->next->ty == Tfunction)
if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
t->ty == Tdelegate && t->nextOf()->ty == Tfunction)
{
if (func && func->overloadExactMatch(t->next))
if (func && func->overloadExactMatch(t->nextOf()))
result = MATCHexact;
}
}
@@ -948,7 +995,7 @@ Expression *TupleExp::castTo(Scope *sc, Type *t)
Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
{
#if 0
printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n",
printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
toChars(), type->toChars(), t->toChars());
#endif
if (type == t)
@@ -1016,7 +1063,6 @@ L1:
return e->Expression::castTo(sc, t);
}
Expression *SymOffExp::castTo(Scope *sc, Type *t)
{
Type *tb;
@@ -1134,7 +1180,7 @@ Expression *BinExp::scaleFactor(Scope *sc)
// Replace (ptr + int) with (ptr + (int * stride))
Type *t = Type::tptrdiff_t;
stride = t1b->next->size();
stride = t1b->nextOf()->size(loc);
if (!t->equals(t2b))
e2 = e2->castTo(sc, t);
// LLVMDC: llvm uses typesafe pointer arithmetic
@@ -1156,7 +1202,7 @@ Expression *BinExp::scaleFactor(Scope *sc)
Type *t = Type::tptrdiff_t;
Expression *e;
stride = t2b->next->size();
stride = t2b->nextOf()->size(loc);
if (!t->equals(t1b))
e = e1->castTo(sc, t);
else
@@ -1327,13 +1373,17 @@ Expression *BinExp::typeCombine(Scope *sc)
goto Lincompatible;
}
else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
e2->op == TOKnull && t2->ty == Tpointer && t2->next->ty == Tvoid)
{
e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid)
{ /* (T[n] op void*)
* (T[] op void*)
*/
goto Lx1;
}
else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid)
{
e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid)
{ /* (void* op T[n])
* (void* op T[])
*/
goto Lx2;
}
else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
@@ -1375,7 +1425,7 @@ Expression *BinExp::typeCombine(Scope *sc)
/* Pick 'tightest' type
*/
ClassDeclaration *cd1 = tc1->sym->baseClass;
ClassDeclaration *cd2 = tc1->sym->baseClass;
ClassDeclaration *cd2 = tc2->sym->baseClass;
if (cd1 && cd2)
{ t1 = cd1->type;
@@ -1402,21 +1452,48 @@ Expression *BinExp::typeCombine(Scope *sc)
goto Lt1;
}
else if (t1->ty == Tsarray && t2->ty == Tsarray &&
e2->implicitConvTo(t1->next->arrayOf()))
e2->implicitConvTo(t1->nextOf()->arrayOf()))
{
Lx1:
t = t1->next->arrayOf();
t = t1->nextOf()->arrayOf();
e1 = e1->castTo(sc, t);
e2 = e2->castTo(sc, t);
}
else if (t1->ty == Tsarray && t2->ty == Tsarray &&
e1->implicitConvTo(t2->next->arrayOf()))
e1->implicitConvTo(t2->nextOf()->arrayOf()))
{
Lx2:
t = t2->next->arrayOf();
t = t2->nextOf()->arrayOf();
e1 = e1->castTo(sc, t);
e2 = e2->castTo(sc, t);
}
else if (t1->isintegral() && t2->isintegral())
{
assert(0);
}
else if (e1->op == TOKslice && t1->ty == Tarray &&
e2->implicitConvTo(t1->nextOf()))
{ // T[] op T
e2 = e2->castTo(sc, t1->nextOf());
t = t1->nextOf()->arrayOf();
}
else if (e2->op == TOKslice && t2->ty == Tarray &&
e1->implicitConvTo(t2->nextOf()))
{ // T op T[]
e1 = e1->castTo(sc, t2->nextOf());
t = t2->nextOf()->arrayOf();
//printf("test %s\n", e->toChars());
e1 = e1->optimize(WANTvalue);
if (isCommutative() && e1->isConst())
{ /* Swap operands to minimize number of functions generated
*/
//printf("swap %s\n", e->toChars());
Expression *tmp = e1;
e1 = e2;
e2 = tmp;
}
}
else
{
Lincompatible:
@@ -1446,9 +1523,10 @@ Lt2:
*/
Expression *Expression::integralPromotions(Scope *sc)
{ Expression *e;
{
Expression *e = this;
e = this;
//printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
switch (type->toBasetype()->ty)
{
case Tvoid:

View File

@@ -775,7 +775,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
{
TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
if (i)
buf->writeByte(',');
buf->writestring(", ");
tp->toCBuffer(buf, &hgs);
}
buf->writeByte(')');

View File

@@ -368,6 +368,7 @@ Expression *resolveProperties(Scope *sc, Expression *e)
{
e->error("expression has no value");
}
}
return e;
}
@@ -389,6 +390,26 @@ void arrayExpressionSemantic(Expressions *exps, Scope *sc)
}
}
/******************************
* Perform canThrow() on an array of Expressions.
*/
#if DMDV2
int arrayExpressionCanThrow(Expressions *exps)
{
if (exps)
{
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i];
if (e && e->canThrow())
return 1;
}
}
return 0;
}
#endif
/****************************************
* Expand tuples.
*/
@@ -503,10 +524,10 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
/****************************************
* Now that we know the exact type of the function we're calling,
* the arguments[] need to be adjusted:
* 1) implicitly convert argument to the corresponding parameter type
* 2) add default arguments for any missing arguments
* 3) do default promotions on arguments corresponding to ...
* 4) add hidden _arguments[] argument
* 1. implicitly convert argument to the corresponding parameter type
* 2. add default arguments for any missing arguments
* 3. do default promotions on arguments corresponding to ...
* 4. add hidden _arguments[] argument
*/
void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
@@ -802,6 +823,7 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h
Expression::Expression(Loc loc, enum TOK op, int size)
: loc(loc)
{
//printf("Expression::Expression(op = %d) this = %p\n", op, this);
this->loc = loc;
this->op = op;
this->size = size;
@@ -832,6 +854,7 @@ Expression *Expression::copy()
assert(0);
}
e = (Expression *)mem.malloc(size);
//printf("Expression::copy(op = %d) e = %p\n", op, e);
return (Expression *)memcpy(e, this, size);
}
@@ -965,6 +988,8 @@ Expression *Expression::toLvalue(Scope *sc, Expression *e)
Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
// See if this expression is a modifiable lvalue (i.e. not const)
return toLvalue(sc, e);
}
@@ -1300,7 +1325,8 @@ Expression *IntegerExp::semantic(Scope *sc)
type = Type::tint32;
}
else
{ type = type->semantic(loc, sc);
{ if (!type->deco)
type = type->semantic(loc, sc);
}
return this;
}
@@ -1785,7 +1811,8 @@ Expression *IdentifierExp::semantic(Scope *sc)
{ Expression *e;
WithScopeSymbol *withsym;
// See if it was a with class
/* See if the symbol was a member of an enclosing 'with'
*/
withsym = scopesym->isWithScopeSymbol();
if (withsym)
{
@@ -1800,7 +1827,7 @@ Expression *IdentifierExp::semantic(Scope *sc)
else
{ Type *t = withsym->withstate->wthis->type;
if (t->ty == Tpointer)
t = t->next;
t = ((TypePointer *)t)->next;
e = new TypeDotIdExp(loc, t, ident);
}
}
@@ -2161,8 +2188,8 @@ Expression *ThisExp::semantic(Scope *sc)
return this;
Lerr:
error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars());
type = Type::tint32;
error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
type = Type::terror;
return this;
}
@@ -2695,7 +2722,7 @@ Expression *ArrayLiteralExp::semantic(Scope *sc)
// Convert any static arrays to dynamic arrays
if (t0->ty == Tsarray)
{
t0 = t0->next->arrayOf();
t0 = ((TypeSArray *)t0)->next->arrayOf();
e = e->implicitCastTo(sc, t0);
}
}
@@ -2906,6 +2933,8 @@ Expression *StructLiteralExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("StructLiteralExp::semantic('%s')\n", toChars());
#endif
if (type)
return this;
// Run semantic() on each element
for (size_t i = 0; i < elements->dim; i++)
@@ -2986,11 +3015,17 @@ Expression *StructLiteralExp::semantic(Scope *sc)
*/
Expression *StructLiteralExp::getField(Type *type, unsigned offset)
{ Expression *e = NULL;
{
//printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
// /*toChars()*/"", type->toChars(), offset);
Expression *e = NULL;
int i = getFieldIndex(type, offset);
if (i != -1)
{ e = (Expression *)elements->data[i];
{
//printf("\ti = %d\n", i);
assert(i < elements->dim);
e = (Expression *)elements->data[i];
if (e)
{
e = e->copy();
@@ -3330,7 +3365,7 @@ Lagain:
Dsymbol *s = cd->toParent2();
ClassDeclaration *cdn = s->isClassDeclaration();
//printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
//printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
if (cdn)
{
if (!cdthis)
@@ -3485,7 +3520,7 @@ Lagain:
if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
error("negative array index %s", arg->toChars());
arguments->data[i] = (void *) arg;
tb = tb->next->toBasetype();
tb = ((TypeDArray *)tb)->next->toBasetype();
}
}
else if (tb->isscalar())
@@ -3822,6 +3857,29 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
}
/******************************** OverExp **************************/
#if DMDV2
OverExp::OverExp(OverloadSet *s)
: Expression(loc, TOKoverloadset, sizeof(OverExp))
{
//printf("OverExp(this = %p, '%s')\n", this, var->toChars());
vars = s;
type = Type::tvoid;
}
int OverExp::isLvalue()
{
return 1;
}
Expression *OverExp::toLvalue(Scope *sc, Expression *e)
{
return this;
}
#endif
/******************************** TupleExp **************************/
TupleExp::TupleExp(Loc loc, Expressions *exps)
@@ -4158,6 +4216,43 @@ void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writeByte(')');
}
/************************ TraitsExp ************************************/
#if DMDV2
/*
* __traits(identifier, args...)
*/
TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
: Expression(loc, TOKtraits, sizeof(TraitsExp))
{
this->ident = ident;
this->args = args;
}
Expression *TraitsExp::syntaxCopy()
{
return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
}
void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("__traits(");
buf->writestring(ident->toChars());
if (args)
{
for (int i = 0; i < args->dim; i++)
{
buf->writeByte(',');
Object *oarg = (Object *)args->data[i];
ObjectToCBuffer(buf, hgs, oarg);
}
}
buf->writeByte(')');
}
#endif
/************************************************************/
HaltExp::HaltExp(Loc loc)
@@ -4210,7 +4305,11 @@ Expression *IsExp::syntaxCopy()
Expression *IsExp::semantic(Scope *sc)
{ Type *tded;
//printf("IsExp::semantic()\n");
/* is(targ id tok tspec)
* is(targ id == tok2)
*/
//printf("IsExp::semantic(%s)\n", toChars());
if (id && !(sc->flags & SCOPEstaticif))
error("can only declare type aliases within static if conditionals");
@@ -4267,6 +4366,19 @@ Expression *IsExp::semantic(Scope *sc)
goto Lno;
tded = targ;
break;
#if DMDV2
case TOKconst:
if (!targ->isConst())
goto Lno;
tded = targ;
break;
case TOKinvariant:
if (!targ->isInvariant())
goto Lno;
tded = targ;
break;
#endif
case TOKsuper:
// If class or interface, get the base class and interfaces
@@ -4293,11 +4405,12 @@ Expression *IsExp::semantic(Scope *sc)
case TOKdelegate:
if (targ->ty != Tdelegate)
goto Lno;
tded = targ->next; // the underlying function type
tded = ((TypeDelegate *)targ)->next; // the underlying function type
break;
case TOKfunction:
{ if (targ->ty != Tfunction)
{
if (targ->ty != Tfunction)
goto Lno;
tded = targ;
@@ -4321,7 +4434,7 @@ Expression *IsExp::semantic(Scope *sc)
* delegate, or pointer to function.
*/
if (targ->ty == Tfunction)
tded = targ->next;
tded = ((TypeFunction *)targ)->next;
else if (targ->ty == Tdelegate)
tded = targ->next->next;
else if (targ->ty == Tpointer && targ->next->ty == Tfunction)
@@ -4537,6 +4650,13 @@ Expression *BinExp::commonSemanticAssign(Scope *sc)
if (e)
return e;
if (e1->op == TOKslice)
{ // T[] op= ...
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
type = e1->type;
@@ -4568,6 +4688,13 @@ Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
if (e)
return e;
if (e1->op == TOKslice)
{ // T[] op= ...
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
type = e1->type;
@@ -4888,6 +5015,24 @@ Expression *DotIdExp::semantic(Scope *sc)
eleft = NULL;
eright = e1;
}
#if DMDV2
if (e1->op == TOKtuple && ident == Id::offsetof)
{ /* 'distribute' the .offsetof to each of the tuple elements.
*/
TupleExp *te = (TupleExp *)e1;
Expressions *exps = new Expressions();
exps->setDim(te->exps->dim);
for (int i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)te->exps->data[i];
e = e->semantic(sc);
e = new DotIdExp(e->loc, e, Id::offsetof);
exps->data[i] = (void *)e;
}
e = new TupleExp(loc, exps);
e = e->semantic(sc);
return e;
}
#endif
if (e1->op == TOKtuple && ident == Id::length)
{
@@ -5048,7 +5193,7 @@ Expression *DotIdExp::semantic(Scope *sc)
ident != Id::mangleof && ident != Id::stringof)
{
e = new PtrExp(loc, e1);
e->type = e1->type->next;
e->type = ((TypePointer *)e1->type)->next;
return e->type->dotExp(sc, e, ident);
}
else
@@ -5176,7 +5321,11 @@ Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
{
//printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
#if 0
printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
printf("e1->type = %s\n", e1->type->toChars());
printf("var->type = %s\n", var->type->toChars());
#endif
if (var->isCtorinit())
{ // It's only modifiable if inside the right constructor
@@ -5265,6 +5414,12 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc)
if (t1)
t1 = t1->toBasetype();
//t1->print();
/* Extract the following from e1:
* s: the symbol which ti should be a member of
* eleft: if not NULL, it is the 'this' pointer for ti
*/
if (e1->op == TOKdotexp)
{ DotExp *de = (DotExp *)e1;
eleft = de->e1;
@@ -5295,7 +5450,7 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc)
}
else if (t1 && t1->ty == Tpointer)
{
t1 = t1->next->toBasetype();
t1 = ((TypePointer *)t1)->next->toBasetype();
if (t1->ty != Tstruct)
goto L1;
s = t1->toDsymbol(sc);
@@ -5471,6 +5626,7 @@ Expression *CallExp::semantic(Scope *sc)
int i;
Type *t1;
int istemp;
Objects *targsi = NULL; // initial list of template arguments
#if LOGSEMANTIC
printf("CallExp::semantic() %s\n", toChars());
@@ -5534,8 +5690,66 @@ Expression *CallExp::semantic(Scope *sc)
}
}
#if DMDV2
/* This recognizes:
* foo!(tiargs)(funcargs)
*/
if (e1->op == TOKimport && !e1->type)
{ ScopeExp *se = (ScopeExp *)e1;
TemplateInstance *ti = se->sds->isTemplateInstance();
if (ti && !ti->semanticdone)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
*/
ti->semanticTiargs(sc);
unsigned errors = global.errors;
global.gag++;
ti->semantic(sc);
global.gag--;
if (errors != global.errors)
{
/* Didn't work, go with partial explicit specialization
*/
global.errors = errors;
targsi = ti->tiargs;
e1 = new IdentifierExp(loc, ti->name);
}
}
}
/* This recognizes:
* expr.foo!(tiargs)(funcargs)
*/
if (e1->op == TOKdotti && !e1->type)
{ DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
TemplateInstance *ti = se->ti;
if (!ti->semanticdone)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
*/
ti->semanticTiargs(sc);
Expression *etmp;
unsigned errors = global.errors;
global.gag++;
etmp = e1->semantic(sc);
global.gag--;
if (errors != global.errors)
{
global.errors = errors;
targsi = ti->tiargs;
e1 = new DotIdExp(loc, se->e1, ti->name);
}
else
e1 = etmp;
}
}
#endif
istemp = 0;
Lagain:
//printf("Lagain: %s\n", toChars());
f = NULL;
if (e1->op == TOKthis || e1->op == TOKsuper)
{
@@ -5804,16 +6018,16 @@ Lagain:
else if (t1->ty != Tfunction)
{
if (t1->ty == Tdelegate)
{
assert(t1->next->ty == Tfunction);
tf = (TypeFunction *)(t1->next);
{ TypeDelegate *td = (TypeDelegate *)t1;
assert(td->next->ty == Tfunction);
tf = (TypeFunction *)(td->next);
goto Lcheckargs;
}
else if (t1->ty == Tpointer && t1->next->ty == Tfunction)
else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
{ Expression *e;
e = new PtrExp(loc, e1);
t1 = t1->next;
t1 = ((TypePointer *)t1)->next;
e->type = t1;
e1 = e;
}
@@ -5909,10 +6123,11 @@ Lcheckargs:
{
Type *t = type;
int offset = 0;
TypeFunction *tf = (TypeFunction *)f->tintro;
if (f->tintro->next->isBaseOf(t, &offset) && offset)
if (tf->next->isBaseOf(t, &offset) && offset)
{
type = f->tintro->next;
type = tf->next;
return castTo(sc, t);
}
}
@@ -5974,9 +6189,7 @@ Expression *AddrExp::semantic(Scope *sc)
FuncDeclaration *f = dve->var->isFuncDeclaration();
if (f)
{ Expression *e;
e = new DelegateExp(loc, dve->e1, f);
{ Expression *e = new DelegateExp(loc, dve->e1, f);
e = e->semantic(sc);
return e;
}
@@ -6018,7 +6231,7 @@ PtrExp::PtrExp(Loc loc, Expression *e)
: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
{
if (e->type)
type = e->type->next;
type = ((TypePointer *)e->type)->next;
}
PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
@@ -6108,7 +6321,8 @@ Expression *NegExp::semantic(Scope *sc)
return e;
e1->checkNoBool();
e1->checkArithmetic();
if (e1->op != TOKslice)
e1->checkArithmetic();
type = e1->type;
}
return this;
@@ -6157,7 +6371,8 @@ Expression *ComExp::semantic(Scope *sc)
return e;
e1->checkNoBool();
e1 = e1->checkIntegral();
if (e1->op != TOKslice)
e1 = e1->checkIntegral();
type = e1->type;
}
return this;
@@ -6238,7 +6453,7 @@ Expression *DeleteExp::semantic(Scope *sc)
break;
}
case Tpointer:
tb = tb->next->toBasetype();
tb = ((TypePointer *)tb)->next->toBasetype();
if (tb->ty == Tstruct)
{
TypeStruct *ts = (TypeStruct *)tb;
@@ -6569,7 +6784,7 @@ Expression *SliceExp::semantic(Scope *sc)
return e;
}
type = t->next->arrayOf();
type = t->nextOf()->arrayOf();
return e;
Lerror:
@@ -6878,7 +7093,7 @@ Expression *IndexExp::semantic(Scope *sc)
index, length);
}
#endif
e->type = t1->next;
e->type = t1->nextOf();
break;
}
@@ -7199,6 +7414,20 @@ Expression *AssignExp::semantic(Scope *sc)
{
e2 = e2->implicitCastTo(sc, e1->type);
}
/* Look for array operations
*/
if (e1->op == TOKslice && !ismemset &&
(e2->op == TOKadd || e2->op == TOKmin ||
e2->op == TOKmul || e2->op == TOKdiv ||
e2->op == TOKmod || e2->op == TOKxor ||
e2->op == TOKand || e2->op == TOKor ||
e2->op == TOKtilde || e2->op == TOKneg))
{
type = e1->type;
return arrayOp(sc);
}
type = e1->type;
assert(type);
return this;
@@ -7234,14 +7463,23 @@ Expression *AddAssignExp::semantic(Scope *sc)
if (e)
return e;
e1 = e1->modifiableLvalue(sc, e1);
Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();
if (e1->op == TOKslice)
{
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
else
{
e1 = e1->modifiableLvalue(sc, e1);
}
if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
(tb2->ty == Tarray || tb2->ty == Tsarray) &&
tb1->next->equals(tb2->next)
tb1->nextOf()->equals(tb2->nextOf())
)
{
type = e1->type;
@@ -7263,11 +7501,7 @@ Expression *AddAssignExp::semantic(Scope *sc)
Expression *ea;
Expression *ex;
char name[6+6+1];
Identifier *id;
static int idn;
sprintf(name, "__name%d", ++idn);
id = Lexer::idPool(name);
Identifier *id = Lexer::uniqueId("__name");
v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
v->semantic(sc);
@@ -7334,6 +7568,13 @@ Expression *MinAssignExp::semantic(Scope *sc)
if (e)
return e;
if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
@@ -7397,10 +7638,10 @@ Expression *CatAssignExp::semantic(Scope *sc)
e = this;
}
else if ((tb1->ty == Tarray) &&
e2->implicitConvTo(tb1->next)
e2->implicitConvTo(tb1->nextOf())
)
{ // Append element
e2 = e2->castTo(sc, tb1->next);
e2 = e2->castTo(sc, tb1->nextOf());
type = e1->type;
e = this;
}
@@ -7430,6 +7671,13 @@ Expression *MulAssignExp::semantic(Scope *sc)
if (e)
return e;
if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
@@ -7486,6 +7734,13 @@ Expression *DivAssignExp::semantic(Scope *sc)
if (e)
return e;
if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
type = e1->type;
return arrayOp(sc);
}
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
@@ -7690,7 +7945,7 @@ Expression *AddExp::semantic(Scope *sc)
if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
(tb2->ty == Tarray || tb2->ty == Tsarray) &&
tb1->next->equals(tb2->next)
tb1->nextOf()->equals(tb2->nextOf())
)
{
type = e1->type;
@@ -7776,17 +8031,22 @@ Expression *MinExp::semantic(Scope *sc)
typeCombine(sc); // make sure pointer types are compatible
type = Type::tptrdiff_t;
stride = t2->next->size();
if (!stride)
return new IntegerExp(0, 0, Type::tptrdiff_t);
e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
e->type = Type::tptrdiff_t;
stride = t2->nextOf()->size();
if (stride == 0)
{
e = new IntegerExp(loc, 0, Type::tptrdiff_t);
}
else
{
e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
e->type = Type::tptrdiff_t;
}
return e;
}
else if (t2->isintegral())
e = scaleFactor(sc);
else
{ error("incompatible types for -");
{ error("incompatible types for minus");
return new IntegerExp(0);
}
}
@@ -7864,7 +8124,7 @@ Expression *CatExp::semantic(Scope *sc)
if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
e2->type->equals(tb1->next))
{
type = tb1->next->arrayOf();
type = tb1->nextOf()->arrayOf();
if (tb2->ty == Tarray)
{ // Make e2 into [e2]
e2 = new ArrayLiteralExp(e2->loc, e2);
@@ -7875,7 +8135,7 @@ Expression *CatExp::semantic(Scope *sc)
else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
e1->type->equals(tb2->next))
{
type = tb2->next->arrayOf();
type = tb2->nextOf()->arrayOf();
if (tb1->ty == Tarray)
{ // Make e1 into [e1]
e1 = new ArrayLiteralExp(e1->loc, e1);
@@ -7904,6 +8164,7 @@ Expression *CatExp::semantic(Scope *sc)
}
else
{
//printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
error("Can only concatenate arrays, not (%s ~ %s)",
e1->type->toChars(), e2->type->toChars());
type = Type::tint32;
@@ -7939,8 +8200,10 @@ Expression *MulExp::semantic(Scope *sc)
return e;
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
e2->checkArithmetic();
}
if (type->isfloating())
{ Type *t1 = e1->type;
Type *t2 = e2->type;
@@ -8003,8 +8266,10 @@ Expression *DivExp::semantic(Scope *sc)
return e;
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
e2->checkArithmetic();
}
if (type->isfloating())
{ Type *t1 = e1->type;
Type *t2 = e2->type;
@@ -8068,8 +8333,10 @@ Expression *ModExp::semantic(Scope *sc)
return e;
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
e2->checkArithmetic();
}
if (type->isfloating())
{ type = e1->type;
if (e2->type->iscomplex())
@@ -8180,8 +8447,10 @@ Expression *AndExp::semantic(Scope *sc)
else
{
typeCombine(sc);
e1->checkIntegral();
e2->checkIntegral();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
e2->checkIntegral();
}
}
}
return this;
@@ -8211,8 +8480,10 @@ Expression *OrExp::semantic(Scope *sc)
else
{
typeCombine(sc);
e1->checkIntegral();
e2->checkIntegral();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
e2->checkIntegral();
}
}
}
return this;
@@ -8242,8 +8513,10 @@ Expression *XorExp::semantic(Scope *sc)
else
{
typeCombine(sc);
e1->checkIntegral();
e2->checkIntegral();
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
e2->checkIntegral();
}
}
}
return this;
@@ -8414,7 +8687,7 @@ Expression *InExp::semantic(Scope *sc)
e1 = e1->implicitCastTo(sc, ta->index);
// Return type is pointer to value
type = ta->next->pointerTo();
type = ta->nextOf()->pointerTo();
}
return this;
}
@@ -8501,6 +8774,7 @@ Expression *CmpExp::semantic(Scope *sc)
#endif
else
e = this;
//printf("CmpExp: %s\n", e->toChars());
return e;
}

View File

@@ -43,7 +43,7 @@ struct HdrGenState;
struct BinExp;
struct InterState;
struct Symbol; // back end symbol
struct OverloadSet;
namespace llvm
{
class Constant;
@@ -151,6 +151,10 @@ struct Expression : Object
virtual Identifier *opId();
virtual Identifier *opId_r();
// For array ops
virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
virtual Expression *buildArrayLoop(Arguments *fparams);
// Back end
virtual elem *toElem(IRState *irs);
virtual dt_t **toDt(dt_t **pdt);
@@ -594,6 +598,19 @@ struct VarExp : Expression
virtual llvm::Constant *toConstElem(IRState *irs);
};
#if DMDV2
// Overload Set
struct OverExp : Expression
{
OverloadSet *vars;
OverExp(OverloadSet *s);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
#endif
// Function/Delegate literal
struct FuncExp : Expression
@@ -643,6 +660,19 @@ struct TypeidExp : Expression
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#if DMDV2
struct TraitsExp : Expression
{
Identifier *ident;
Objects *args;
TraitsExp(Loc loc, Identifier *ident, Objects *args);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
struct HaltExp : Expression
{
HaltExp(Loc loc);
@@ -715,6 +745,7 @@ struct BinExp : Expression
Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
Expression *arrayOp(Scope *sc);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -887,6 +918,8 @@ struct NegExp : UnaExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
Identifier *opId();
@@ -909,6 +942,8 @@ struct ComExp : UnaExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
Identifier *opId();
@@ -984,6 +1019,8 @@ struct SliceExp : UnaExp
void dump(int indent);
elem *toElem(IRState *irs);
void scanForNestedRef(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -1081,6 +1118,8 @@ struct AssignExp : BinExp
Expression *checkToBoolean();
Expression *interpret(InterState *istate);
Identifier *opId(); // For operator overloading
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
elem *toElem(IRState *irs);
};
@@ -1090,25 +1129,33 @@ struct op##AssignExp : BinExp \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
Expression *semantic(Scope *sc); \
Expression *interpret(InterState *istate); \
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
X(Expression *buildArrayLoop(Arguments *fparams);) \
\
Identifier *opId(); /* For operator overloading */ \
\
elem *toElem(IRState *irs); \
};
#define X(a) a
ASSIGNEXP(Add)
ASSIGNEXP(Min)
ASSIGNEXP(Cat)
ASSIGNEXP(Mul)
ASSIGNEXP(Div)
ASSIGNEXP(Mod)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#undef X
#define X(a)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
ASSIGNEXP(Cat)
#undef X
#undef ASSIGNEXP
struct AddExp : BinExp
@@ -1117,6 +1164,8 @@ struct AddExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
int isCommutative();
@@ -1135,6 +1184,8 @@ struct MinExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
Identifier *opId();
@@ -1163,6 +1214,8 @@ struct MulExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
int isCommutative();
@@ -1178,6 +1231,8 @@ struct DivExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
Identifier *opId();
@@ -1192,6 +1247,8 @@ struct ModExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
Identifier *opId();
@@ -1248,6 +1305,8 @@ struct AndExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
int isCommutative();
@@ -1263,6 +1322,8 @@ struct OrExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
int isCommutative();
@@ -1278,6 +1339,8 @@ struct XorExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
// For operator overloading
int isCommutative();
@@ -1402,6 +1465,32 @@ struct CondExp : BinExp
elem *toElem(IRState *irs);
};
#if DMDV2
/****************************************************************/
struct DefaultInitExp : Expression
{
enum TOK subop; // which of the derived classes this is
DefaultInitExp(Loc loc, enum TOK subop, int size);
virtual Expression *resolve(Loc loc, Scope *sc) = 0;
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct FileInitExp : DefaultInitExp
{
FileInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolve(Loc loc, Scope *sc);
};
struct LineInitExp : DefaultInitExp
{
LineInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolve(Loc loc, Scope *sc);
};
#endif
/****************************************************************/

View File

@@ -68,6 +68,9 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s
fes = NULL;
introducing = 0;
tintro = NULL;
/* The type given for "infer the return type" is a TypeFunction with
* NULL for the return type.
*/
inferRetType = (type && type->nextOf() == NULL);
scope = NULL;
hasReturnExp = 0;
@@ -112,7 +115,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (isFuncLiteralDeclaration())
printf("\tFuncLiteralDeclaration()\n");
printf("sc->parent = %s\n", sc->parent->toChars());
printf("type: %s\n", type->toChars());
printf("type: %p, %s\n", type, type->toChars());
#endif
if (type->nextOf())
@@ -281,8 +284,11 @@ void FuncDeclaration::semantic(Scope *sc)
vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
switch (vi)
{
case -1: // didn't find one
// This is an 'introducing' function.
case -1:
/* Didn't find one, so
* This is an 'introducing' function which gets a new
* slot in the vtbl[].
*/
// Verify this doesn't override previous final function
if (cd->baseClass)
@@ -632,9 +638,8 @@ void FuncDeclaration::semantic3(Scope *sc)
// Check the 'throws' clause
if (fthrows)
{ int i;
for (i = 0; i < fthrows->dim; i++)
{
for (int i = 0; i < fthrows->dim; i++)
{
Type *t = (Type *)fthrows->data[i];
@@ -696,9 +701,11 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else if (isNested())
{
VarDeclaration *v;
v = new ThisDeclaration(Type::tvoid->pointerTo());
/* The 'this' for a nested function is the link to the
* enclosing function's stack frame.
* Note that nested functions and member functions are disjoint.
*/
VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo());
v->storage_class |= STCparameter | STCin;
v->semantic(sc2);
if (!sc2->insert(v))
@@ -781,11 +788,7 @@ void FuncDeclaration::semantic3(Scope *sc)
/* Generate identifier for un-named parameter,
* because we need it later on.
*/
OutBuffer buf;
buf.printf("_param_%"PRIuSIZE, i);
char *name = (char *)buf.extractData();
id = new Identifier(name, TOKidentifier);
arg->ident = id;
arg->ident = id = Identifier::generateId("_param_", i);
}
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
@@ -824,11 +827,11 @@ void FuncDeclaration::semantic3(Scope *sc)
assert(narg->ident);
VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
assert(v);
Expression *e = new VarExp(0, v);
Expression *e = new VarExp(v->loc, v);
exps->data[j] = (void *)e;
}
assert(arg->ident);
TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps);
TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
//printf("declaring tuple %s\n", v->toChars());
v->isexp = 1;
if (!sc2->insert(v))
@@ -1569,10 +1572,8 @@ int fp2(void *param, FuncDeclaration *f)
if (f != m->lastf) // skip duplicates
{
TypeFunction *tf;
m->anyf = f;
tf = (TypeFunction *)f->type;
TypeFunction *tf = (TypeFunction *)f->type;
match = (MATCH) tf->callMatch(arguments);
//printf("match = %d\n", match);
if (match != MATCHnomatch)
@@ -1910,8 +1911,16 @@ int FuncDeclaration::isMain()
int FuncDeclaration::isWinMain()
{
//printf("FuncDeclaration::isWinMain() %s\n", toChars());
#if 0
int x = ident == Id::WinMain &&
linkage != LINKc && !isMember();
printf("%s\n", x ? "yes" : "no");
return x;
#else
return ident == Id::WinMain &&
linkage != LINKc && !isMember();
#endif
}
int FuncDeclaration::isDllMain()
@@ -2090,7 +2099,7 @@ int FuncDeclaration::needsClosure()
goto Lyes; // assume f escapes this function's scope
// Look to see if any parents of f that are below this escape
for (Dsymbol *s = f->parent; s != this; s = s->parent)
for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
{
f = s->isFuncDeclaration();
if (f && (f->isThis() || f->tookAddressOf))
@@ -2196,7 +2205,7 @@ CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int
{
this->arguments = arguments;
this->varargs = varargs;
//printf("CtorDeclaration() %s\n", toChars());
//printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
}
Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)

View File

@@ -81,15 +81,21 @@ int Identifier::dyncast()
return DYNCAST_IDENTIFIER;
}
Identifier *Identifier::generateId(char *prefix)
Identifier *Identifier::generateId(const char *prefix)
{
static size_t i;
return generateId(prefix, ++i);
}
Identifier *Identifier::generateId(const char *prefix, size_t i)
{ OutBuffer buf;
char *id;
static unsigned i;
buf.writestring(prefix);
buf.printf("%u", ++i);
buf.printf("%zu", i);
id = buf.toChars();
char *id = buf.toChars();
buf.data = NULL;
return new Identifier(id, TOKidentifier);
return Lexer::idPool(id);
}

View File

@@ -1,46 +1,47 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IDENTIFIER_H
#define DMD_IDENTIFIER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
namespace llvm
{
class Value;
}
struct Identifier : Object
{
int value;
const char *string;
unsigned len;
Identifier(const char *string, int value);
int equals(Object *o);
hash_t hashCode();
int compare(Object *o);
void print();
char *toChars();
#ifdef _DH
char *toHChars();
#endif
char *toHChars2();
int dyncast();
static Identifier *generateId(char *prefix);
};
#endif /* DMD_IDENTIFIER_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IDENTIFIER_H
#define DMD_IDENTIFIER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
namespace llvm
{
class Value;
}
struct Identifier : Object
{
int value;
const char *string;
unsigned len;
Identifier(const char *string, int value);
int equals(Object *o);
hash_t hashCode();
int compare(Object *o);
void print();
char *toChars();
#ifdef _DH
char *toHChars();
#endif
char *toHChars2();
int dyncast();
static Identifier *generateId(const char *prefix);
static Identifier *generateId(const char *prefix, size_t i);
};
#endif /* DMD_IDENTIFIER_H */

View File

@@ -865,6 +865,7 @@ int main(int argc, char *argv[])
#endif
if (stricmp(ext, global.mars_ext) == 0 ||
stricmp(ext, global.hdr_ext) == 0 ||
stricmp(ext, "htm") == 0 ||
stricmp(ext, "html") == 0 ||
stricmp(ext, "xhtml") == 0)

View File

@@ -112,6 +112,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
srcfilename = FileName::defaultExt(filename, global.mars_ext);
if (!srcfilename->equalsExt(global.mars_ext) &&
!srcfilename->equalsExt(global.hdr_ext) &&
!srcfilename->equalsExt("dd"))
{
if (srcfilename->equalsExt("html") ||

View File

@@ -1968,8 +1968,10 @@ void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (arg->type)
arg->type->toCBuffer(buf, arg->ident, hgs);
else
{ buf->writestring("auto ");
buf->writestring(arg->ident->toChars());
buf->writebyte(';');
}
buf->writestring(" = ");
}
condition->toCBuffer(buf, hgs);
buf->writebyte(')');
@@ -2041,6 +2043,14 @@ int ConditionalStatement::usesEH()
return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
}
int ConditionalStatement::blockExit()
{
int result = ifbody->blockExit();
if (elsebody)
result |= elsebody->blockExit();
return result;
}
void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
condition->toCBuffer(buf, hgs);

View File

@@ -461,6 +461,7 @@ struct ConditionalStatement : Statement
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int usesEH();
int blockExit();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};

View File

@@ -3,6 +3,7 @@ dmd
dmd/access.c
dmd/aggregate.h
dmd/array.c
dmd/arrayop.c
dmd/arraytypes.h
dmd/attrib.c
dmd/attrib.h