mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-23 08:13:13 +01:00
Merged DMD 1.034, array operations are not yet implemented ;)
This commit is contained in:
505
dmd/arrayop.c
Normal file
505
dmd/arrayop.c
Normal 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
|
||||
|
||||
|
||||
126
dmd/cast.c
126
dmd/cast.c
@@ -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:
|
||||
|
||||
@@ -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(')');
|
||||
|
||||
412
dmd/expression.c
412
dmd/expression.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
51
dmd/func.c
51
dmd/func.c
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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") ||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user