mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Added initial D2 support, D2 frontend and changes to codegen to make things compile.
This commit is contained in:
@@ -39,19 +39,32 @@ execute_process(
|
||||
# get llvm's install dir. a little hackish, we could do something like llvm-config --prefix, but this does as well
|
||||
string(REPLACE "/bin/llvm-config" "" LLVM_INSTDIR ${LLVM_CONFIG})
|
||||
|
||||
set(D_VERSION 1 CACHE STRING "D language version")
|
||||
if(D_VERSION EQUAL 1)
|
||||
set(DMDFE_PATH dmd)
|
||||
set(LDC_EXE ldc)
|
||||
add_definitions(-DDMDV1)
|
||||
elseif(D_VERSION EQUAL 2)
|
||||
set(DMDFE_PATH dmd2)
|
||||
set(LDC_EXE ldc2)
|
||||
add_definitions(-DDMDV2)
|
||||
else(D_VERSION EQUAL 1)
|
||||
message(FATAL_ERROR "unsupported D version")
|
||||
endif(D_VERSION EQUAL 1)
|
||||
|
||||
file(MAKE_DIRECTORY
|
||||
${PROJECT_BINARY_DIR}/bin
|
||||
${PROJECT_BINARY_DIR}/dmd
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}
|
||||
)
|
||||
|
||||
# idgen and impcnvgen
|
||||
set_source_files_properties(
|
||||
dmd/idgen.c
|
||||
dmd/impcnvgen.c
|
||||
${DMDFE_PATH}/idgen.c
|
||||
${DMDFE_PATH}/impcnvgen.c
|
||||
PROPERTIES LANGUAGE CXX
|
||||
)
|
||||
add_executable(idgen dmd/idgen.c)
|
||||
add_executable(impcnvgen dmd/impcnvgen.c)
|
||||
add_executable(idgen ${DMDFE_PATH}/idgen.c)
|
||||
add_executable(impcnvgen ${DMDFE_PATH}/impcnvgen.c)
|
||||
# cmake 2.4
|
||||
set_target_properties(
|
||||
idgen impcnvgen PROPERTIES
|
||||
@@ -62,42 +75,42 @@ get_target_property(IMPCNVGEN_LOC impcnvgen LOCATION)
|
||||
#
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${PROJECT_BINARY_DIR}/dmd/id.c
|
||||
${PROJECT_BINARY_DIR}/dmd/id.h
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}/id.c
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}/id.h
|
||||
# 2.4
|
||||
COMMAND ${IDGEN_LOC}
|
||||
#COMMAND idgen
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/dmd
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${DMDFE_PATH}
|
||||
DEPENDS idgen
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_BINARY_DIR}/dmd/impcnvtab.c
|
||||
OUTPUT ${PROJECT_BINARY_DIR}/${DMDFE_PATH}/impcnvtab.c
|
||||
# 2.4
|
||||
COMMAND ${IMPCNVGEN_LOC}
|
||||
#COMMAND impcnvgen
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/dmd
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${DMDFE_PATH}
|
||||
DEPENDS impcnvgen
|
||||
)
|
||||
set(LDC_GENERATED
|
||||
${PROJECT_BINARY_DIR}/dmd/id.c
|
||||
${PROJECT_BINARY_DIR}/dmd/id.h
|
||||
${PROJECT_BINARY_DIR}/dmd/impcnvtab.c
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}/id.c
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}/id.h
|
||||
${PROJECT_BINARY_DIR}/${DMDFE_PATH}/impcnvtab.c
|
||||
)
|
||||
# idgen and impcnvgen done
|
||||
|
||||
set(DEFAULT_TARGET ${HOST_TARGET} CACHE STRING "default target")
|
||||
|
||||
include_directories(. dmd ${PROJECT_BINARY_DIR}/dmd ${LLVM_INSTDIR}/include)
|
||||
include_directories(. ${DMDFE_PATH} ${PROJECT_BINARY_DIR}/${DMDFE_PATH} ${LLVM_INSTDIR}/include)
|
||||
|
||||
file(GLOB FE_SRC dmd/*.c)
|
||||
file(GLOB FE_SRC ${DMDFE_PATH}/*.c)
|
||||
file(GLOB GEN_SRC gen/*.cpp)
|
||||
file(GLOB IR_SRC ir/*.cpp)
|
||||
# exclude idgen and impcnvgen and generated sources, just in case
|
||||
list(REMOVE_ITEM FE_SRC
|
||||
${PROJECT_SOURCE_DIR}/dmd/idgen.c
|
||||
${PROJECT_SOURCE_DIR}/dmd/impcnvgen.c
|
||||
${PROJECT_SOURCE_DIR}/dmd/id.c
|
||||
${PROJECT_SOURCE_DIR}/dmd/impcnvtab.c
|
||||
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/idgen.c
|
||||
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/impcnvgen.c
|
||||
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/id.c
|
||||
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/impcnvtab.c
|
||||
)
|
||||
set(LDC_SOURCE_FILES
|
||||
${LDC_GENERATED}
|
||||
@@ -115,7 +128,6 @@ add_definitions(
|
||||
-D_DH
|
||||
-DOPAQUE_VTBLS
|
||||
-DUSE_BOEHM_GC=0
|
||||
-DDMDV1
|
||||
-DX86_REVERSE_PARAMS
|
||||
-DX86_PASS_IN_EAX
|
||||
)
|
||||
@@ -131,26 +143,26 @@ else(CMAKE_MINOR_VERSION LESS 6)
|
||||
add_definitions(-DDEFAULT_TARGET_TRIPLE="${DEFAULT_TARGET}")
|
||||
endif(CMAKE_MINOR_VERSION LESS 6)
|
||||
|
||||
add_executable(ldc ${LDC_SOURCE_FILES})
|
||||
add_executable(${LDC_EXE} ${LDC_SOURCE_FILES})
|
||||
|
||||
set_target_properties(
|
||||
ldc PROPERTIES
|
||||
${LDC_EXE} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin
|
||||
COMPILE_FLAGS "${LLVM_CXXFLAGS} -Wno-deprecated"
|
||||
COMPILE_FLAGS "${LLVM_CXXFLAGS} -Wno-deprecated -Wno-write-strings"
|
||||
)
|
||||
|
||||
# LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems
|
||||
target_link_libraries(ldc "${LLVM_LDFLAGS} ${LLVM_LIBS}")
|
||||
target_link_libraries(${LDC_EXE} "${LLVM_LDFLAGS} ${LLVM_LIBS}")
|
||||
if(WIN32)
|
||||
target_link_libraries(ldc psapi)
|
||||
target_link_libraries(${LDC_EXE} psapi)
|
||||
#set(CONF_SUFFIX ini)
|
||||
endif(WIN32)
|
||||
|
||||
# cmake pre 2.6 doesn't support the RUNTIME_OUTPUT_DIRECTORY target property
|
||||
if(CMAKE_MINOR_VERSION LESS 6)
|
||||
get_target_property(LDC_LOC ldc LOCATION)
|
||||
get_target_property(LDC_LOC ${LDC_EXE} LOCATION)
|
||||
add_custom_command(
|
||||
TARGET ldc
|
||||
TARGET ${LDC_EXE}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LDC_LOC} ${PROJECT_BINARY_DIR}/bin/
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${LDC_LOC}
|
||||
|
||||
@@ -368,7 +368,7 @@ struct TypeAArray : TypeArray
|
||||
int hasPointers();
|
||||
|
||||
// Back end
|
||||
Symbol *aaGetSymbol(char *func, int flags);
|
||||
Symbol *aaGetSymbol(const char *func, int flags);
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
424
dmd2/access.c
Normal file
424
dmd2/access.c
Normal file
@@ -0,0 +1,424 @@
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "enum.h"
|
||||
#include "aggregate.h"
|
||||
#include "init.h"
|
||||
#include "attrib.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "expression.h"
|
||||
#include "module.h"
|
||||
|
||||
#define LOG 0
|
||||
|
||||
/* Code to do access checks
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s);
|
||||
|
||||
/****************************************
|
||||
* Return PROT access for Dsymbol smember in this declaration.
|
||||
*/
|
||||
|
||||
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
return PROTpublic;
|
||||
}
|
||||
|
||||
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else
|
||||
{
|
||||
enum PROT access;
|
||||
int i;
|
||||
|
||||
if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
|
||||
for (i = 0; i < baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
switch (access)
|
||||
{
|
||||
case PROTnone:
|
||||
break;
|
||||
|
||||
case PROTprivate:
|
||||
access = PROTnone; // private members of base class not accessible
|
||||
break;
|
||||
|
||||
case PROTpackage:
|
||||
case PROTprotected:
|
||||
case PROTpublic:
|
||||
case PROTexport:
|
||||
// If access is to be tightened
|
||||
if (b->protection < access)
|
||||
access = b->protection;
|
||||
|
||||
// Pick path with loosest access
|
||||
if (access > access_ret)
|
||||
access_ret = access;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
|
||||
toChars(), smember->toChars(), access_ret);
|
||||
#endif
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Helper function for ClassDeclaration::accessCheck()
|
||||
* Returns:
|
||||
* 0 no access
|
||||
* 1 access
|
||||
*/
|
||||
|
||||
static int accessCheckX(
|
||||
Dsymbol *smember,
|
||||
Dsymbol *sfunc,
|
||||
AggregateDeclaration *dthis,
|
||||
AggregateDeclaration *cdscope)
|
||||
{
|
||||
assert(dthis);
|
||||
|
||||
#if 0
|
||||
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
|
||||
dthis->toChars(), smember->toChars(),
|
||||
sfunc ? sfunc->toChars() : "NULL",
|
||||
cdscope ? cdscope->toChars() : "NULL");
|
||||
#endif
|
||||
if (dthis->hasPrivateAccess(sfunc) ||
|
||||
dthis->isFriendOf(cdscope))
|
||||
{
|
||||
if (smember->toParent() == dthis)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
enum PROT access;
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
if (access >= PROTprotected ||
|
||||
accessCheckX(smember, sfunc, b->base, cdscope)
|
||||
)
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (smember->toParent() != dthis)
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
|
||||
if (accessCheckX(smember, sfunc, b->base, cdscope))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Do access check for member of this class, this class being the
|
||||
* type of the 'this' pointer used to access smember.
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
{
|
||||
int result;
|
||||
|
||||
FuncDeclaration *f = sc->func;
|
||||
AggregateDeclaration *cdscope = sc->getStructClassScope();
|
||||
enum PROT access;
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
|
||||
toChars(), smember->toChars(),
|
||||
f ? f->toChars() : NULL,
|
||||
cdscope ? cdscope->toChars() : NULL);
|
||||
#endif
|
||||
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (!smemberparent || !smemberparent->isAggregateDeclaration())
|
||||
{
|
||||
#if LOG
|
||||
printf("not an aggregate member\n");
|
||||
#endif
|
||||
return; // then it is accessible
|
||||
}
|
||||
|
||||
// BUG: should enable this check
|
||||
//assert(smember->parent->isBaseOf(this, NULL));
|
||||
|
||||
if (smemberparent == this)
|
||||
{ enum PROT access = smember->prot();
|
||||
|
||||
result = access >= PROTpublic ||
|
||||
hasPrivateAccess(f) ||
|
||||
isFriendOf(cdscope) ||
|
||||
(access == PROTpackage && hasPackageAccess(sc, this));
|
||||
#if LOG
|
||||
printf("result1 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if ((access = this->getAccess(smember)) >= PROTpublic)
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result2 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if (access == PROTpackage && hasPackageAccess(sc, this))
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result3 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
result = accessCheckX(smember, f, this, cdscope);
|
||||
#if LOG
|
||||
printf("result4 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
error(loc, "member %s is not accessible", smember->toChars());
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if this is the same or friend of cd.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
|
||||
{
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
|
||||
#endif
|
||||
if (this == cd)
|
||||
return 1;
|
||||
|
||||
// Friends if both are in the same module
|
||||
//if (toParent() == cd->toParent())
|
||||
if (cd && getModule() == cd->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tin same module\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LOG
|
||||
printf("\tnot friend\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if scope sc has package level access to s.
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s)
|
||||
{
|
||||
#if LOG
|
||||
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
|
||||
#endif
|
||||
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (s->isPackage() && !s->isModule())
|
||||
break;
|
||||
}
|
||||
#if LOG
|
||||
if (s)
|
||||
printf("\tthis is in package '%s'\n", s->toChars());
|
||||
#endif
|
||||
|
||||
if (s && s == sc->module->parent)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in same package as sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if LOG
|
||||
printf("\tno package access\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if smember has access to private members of this declaration.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
|
||||
{
|
||||
if (smember)
|
||||
{ AggregateDeclaration *cd = NULL;
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (smemberparent)
|
||||
cd = smemberparent->isAggregateDeclaration();
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
|
||||
if (this == cd) // smember is a member of this class
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 1\n");
|
||||
#endif
|
||||
return 1; // so we get private access
|
||||
}
|
||||
|
||||
// If both are members of the same module, grant access
|
||||
while (1)
|
||||
{ Dsymbol *sp = smember->toParent();
|
||||
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
|
||||
smember = sp;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!cd && toParent() == smember->toParent())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 2\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if (!cd && getModule() == smember->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 3\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("\tno\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Check access to d for expression e.d
|
||||
*/
|
||||
|
||||
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
{
|
||||
#if LOG
|
||||
if (e)
|
||||
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
|
||||
printf("\te->type = %s\n", e->type->toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("accessCheck(%s)\n", d->toChars());
|
||||
}
|
||||
#endif
|
||||
if (!e)
|
||||
{
|
||||
if (d->prot() == PROTprivate && d->getModule() != sc->module ||
|
||||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
|
||||
|
||||
error(loc, "%s %s.%s is not accessible from %s",
|
||||
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
|
||||
}
|
||||
else if (e->type->ty == Tclass)
|
||||
{ // Do access check
|
||||
ClassDeclaration *cd;
|
||||
|
||||
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
|
||||
#if 1
|
||||
if (e->op == TOKsuper)
|
||||
{ ClassDeclaration *cd2;
|
||||
|
||||
cd2 = sc->func->toParent()->isClassDeclaration();
|
||||
if (cd2)
|
||||
cd = cd2;
|
||||
}
|
||||
#endif
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
else if (e->type->ty == Tstruct)
|
||||
{ // Do access check
|
||||
StructDeclaration *cd;
|
||||
|
||||
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
}
|
||||
296
dmd2/aggregate.h
Normal file
296
dmd2/aggregate.h
Normal file
@@ -0,0 +1,296 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_AGGREGATE_H
|
||||
#define DMD_AGGREGATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct TypeFunction;
|
||||
struct Expression;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct dt_t;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class Type;
|
||||
class Value;
|
||||
class Constant;
|
||||
class ConstantStruct;
|
||||
class GlobalVariable;
|
||||
}
|
||||
struct DUnion;
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
{
|
||||
Type *type;
|
||||
unsigned storage_class;
|
||||
enum PROT protection;
|
||||
Type *handle; // 'this' type
|
||||
unsigned structsize; // size of struct
|
||||
unsigned alignsize; // size of struct for alignment purposes
|
||||
unsigned structalign; // struct member alignment in effect
|
||||
int hasUnions; // set if aggregate has overlapping fields
|
||||
Array fields; // VarDeclaration fields
|
||||
unsigned sizeok; // set when structsize contains valid data
|
||||
// 0: no size
|
||||
// 1: size is correct
|
||||
// 2: cannot determine size; fwd referenced
|
||||
int isdeprecated; // !=0 if deprecated
|
||||
Scope *scope; // !=NULL means context to use
|
||||
|
||||
// Special member functions
|
||||
InvariantDeclaration *inv; // invariant
|
||||
NewDeclaration *aggNew; // allocator
|
||||
DeleteDeclaration *aggDelete; // deallocator
|
||||
|
||||
#if DMDV2
|
||||
CtorDeclaration *ctor;
|
||||
CtorDeclaration *defaultCtor; // default constructor
|
||||
#endif
|
||||
|
||||
FuncDeclarations dtors; // Array of destructors
|
||||
FuncDeclaration *dtor; // aggregate destructor
|
||||
|
||||
#ifdef IN_GCC
|
||||
Array methods; // flat list of all methods for debug information
|
||||
#endif
|
||||
|
||||
AggregateDeclaration(Loc loc, Identifier *id);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
unsigned size(Loc loc);
|
||||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||
Type *getType();
|
||||
void addField(Scope *sc, VarDeclaration *v);
|
||||
int isDeprecated(); // is aggregate deprecated?
|
||||
FuncDeclaration *buildDtor(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
// For access checking
|
||||
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
int isFriendOf(AggregateDeclaration *cd);
|
||||
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
|
||||
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
|
||||
|
||||
enum PROT prot();
|
||||
|
||||
// Back end
|
||||
Symbol *stag; // tag symbol for debug data
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct AnonymousAggregateDeclaration : AggregateDeclaration
|
||||
{
|
||||
AnonymousAggregateDeclaration()
|
||||
: AggregateDeclaration(0, NULL)
|
||||
{
|
||||
}
|
||||
|
||||
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StructDeclaration : AggregateDeclaration
|
||||
{
|
||||
int zeroInit; // !=0 if initialize with 0 fill
|
||||
#if DMDV2
|
||||
int hasIdentityAssign; // !=0 if has identity opAssign
|
||||
FuncDeclaration *cpctor; // generated copy-constructor, if any
|
||||
|
||||
FuncDeclarations postblits; // Array of postblit functions
|
||||
FuncDeclaration *postblit; // aggregate postblit
|
||||
#endif
|
||||
|
||||
StructDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
int needOpAssign();
|
||||
FuncDeclaration *buildOpAssign(Scope *sc);
|
||||
FuncDeclaration *buildPostBlit(Scope *sc);
|
||||
FuncDeclaration *buildCpCtor(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDt(dt_t **pdt);
|
||||
void toDebug(); // to symbolic debug info
|
||||
|
||||
StructDeclaration *isStructDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct UnionDeclaration : StructDeclaration
|
||||
{
|
||||
UnionDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
const char *kind();
|
||||
|
||||
UnionDeclaration *isUnionDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct BaseClass
|
||||
{
|
||||
Type *type; // (before semantic processing)
|
||||
enum PROT protection; // protection for the base interface
|
||||
|
||||
ClassDeclaration *base;
|
||||
int offset; // 'this' pointer offset
|
||||
Array vtbl; // for interfaces: Array of FuncDeclaration's
|
||||
// making up the vtbl[]
|
||||
|
||||
int baseInterfaces_dim;
|
||||
BaseClass *baseInterfaces; // if BaseClass is an interface, these
|
||||
// are a copy of the InterfaceDeclaration::interfaces
|
||||
|
||||
BaseClass();
|
||||
BaseClass(Type *type, enum PROT protection);
|
||||
|
||||
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
|
||||
void copyBaseInterfaces(BaseClasses *);
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
#define CLASSINFO_SIZE (0x3C+16) // value of ClassInfo.size
|
||||
#else
|
||||
#define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size
|
||||
#endif
|
||||
|
||||
struct ClassDeclaration : AggregateDeclaration
|
||||
{
|
||||
static ClassDeclaration *object;
|
||||
static ClassDeclaration *classinfo;
|
||||
|
||||
ClassDeclaration *baseClass; // NULL only if this is Object
|
||||
FuncDeclaration *staticCtor;
|
||||
FuncDeclaration *staticDtor;
|
||||
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
|
||||
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
|
||||
|
||||
BaseClasses baseclasses; // Array of BaseClass's; first is super,
|
||||
// rest are Interface's
|
||||
|
||||
int interfaces_dim;
|
||||
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
|
||||
// (does not include baseClass)
|
||||
|
||||
BaseClasses *vtblInterfaces; // array of base interfaces that have
|
||||
// their own vtbl[]
|
||||
|
||||
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
||||
int com; // !=0 if this is a COM class (meaning
|
||||
// it derives from IUnknown)
|
||||
int isauto; // !=0 if this is an auto class
|
||||
int isabstract; // !=0 if abstract class
|
||||
|
||||
int isnested; // !=0 if is nested
|
||||
VarDeclaration *vthis; // 'this' parameter if this class is nested
|
||||
|
||||
int inuse; // to prevent recursive attempts
|
||||
|
||||
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isBaseOf2(ClassDeclaration *cd);
|
||||
|
||||
#define OFFSET_RUNTIME 0x76543210
|
||||
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#if DMDV2
|
||||
int isFuncHidden(FuncDeclaration *fd);
|
||||
#endif
|
||||
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
|
||||
void interfaceSemantic(Scope *sc);
|
||||
int isNested();
|
||||
int isCOMclass();
|
||||
virtual int isCOMinterface();
|
||||
#if DMDV2
|
||||
virtual int isCPPinterface();
|
||||
#endif
|
||||
int isAbstract();
|
||||
virtual int vtblOffset();
|
||||
const char *kind();
|
||||
char *mangle();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
void addLocalClass(ClassDeclarations *);
|
||||
|
||||
// Back end
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
unsigned baseVtblOffset(BaseClass *bc);
|
||||
Symbol *toSymbol();
|
||||
Symbol *toVtblSymbol();
|
||||
void toDt(dt_t **pdt);
|
||||
void toDt2(dt_t **pdt, ClassDeclaration *cd);
|
||||
|
||||
Symbol *vtblsym;
|
||||
|
||||
// llvm
|
||||
void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
|
||||
|
||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||
};
|
||||
|
||||
struct InterfaceDeclaration : ClassDeclaration
|
||||
{
|
||||
#if DMDV2
|
||||
int cpp; // !=0 if this is a C++ interface
|
||||
#endif
|
||||
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
int isBaseOf(BaseClass *bc, int *poffset);
|
||||
const char *kind();
|
||||
int vtblOffset();
|
||||
#if DMDV2
|
||||
int isCPPinterface();
|
||||
#endif
|
||||
virtual int isCOMinterface();
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
Symbol *toSymbol();
|
||||
|
||||
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_AGGREGATE_H */
|
||||
220
dmd2/array.c
Normal file
220
dmd2/array.c
Normal file
@@ -0,0 +1,220 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _MSC_VER || __MINGW32__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#include "gdc_alloca.h"
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
/********************************* Array ****************************/
|
||||
|
||||
Array::Array()
|
||||
{
|
||||
data = NULL;
|
||||
dim = 0;
|
||||
allocdim = 0;
|
||||
}
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void Array::mark()
|
||||
{ unsigned u;
|
||||
|
||||
mem.mark(data);
|
||||
for (u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
void Array::reserve(unsigned nentries)
|
||||
{
|
||||
//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
|
||||
void Array::setDim(unsigned newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void Array::fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{ data = (void **)mem.realloc(data, dim * sizeof(*data));
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
void Array::push(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
data[dim++] = ptr;
|
||||
}
|
||||
|
||||
void *Array::pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void Array::shift(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void Array::insert(unsigned index, void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
|
||||
void Array::insert(unsigned index, Array *a)
|
||||
{
|
||||
if (a)
|
||||
{ unsigned d;
|
||||
|
||||
d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Append array a to this array.
|
||||
*/
|
||||
|
||||
void Array::append(Array *a)
|
||||
{
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void Array::remove(unsigned i)
|
||||
{
|
||||
memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
char *Array::toChars()
|
||||
{
|
||||
unsigned len;
|
||||
unsigned u;
|
||||
char **buf;
|
||||
char *str;
|
||||
char *p;
|
||||
|
||||
buf = (char **)alloca(dim * sizeof(char *));
|
||||
len = 2;
|
||||
for (u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((Object *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
p = str + 1;
|
||||
for (u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
void Array::zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
void *Array::tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
Object *ox = *(Object **)x;
|
||||
Object *oy = *(Object **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
|
||||
void Array::sort()
|
||||
{
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
Array *Array::copy()
|
||||
{
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(void *));
|
||||
return a;
|
||||
}
|
||||
|
||||
494
dmd2/arrayop.c
Normal file
494
dmd2/arrayop.c
Normal file
@@ -0,0 +1,494 @@
|
||||
|
||||
// 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"
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct the array operation expression.
|
||||
*/
|
||||
|
||||
Expression *BinExp::arrayOp(Scope *sc)
|
||||
{
|
||||
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 = sc->module->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 = PROTprotected;
|
||||
fd->linkage = LINKd;
|
||||
|
||||
// special attention for array ops
|
||||
fd->isArrayOp = true;
|
||||
|
||||
sc->module->members->push(fd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->parent = sc->module;
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
fd->semantic(sc);
|
||||
sc->pop();
|
||||
// }
|
||||
// else
|
||||
// { /* In library, refer to it.
|
||||
// */
|
||||
// // 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
|
||||
|
||||
|
||||
51
dmd2/arraytypes.h
Normal file
51
dmd2/arraytypes.h
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2006-2007 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_ARRAYTYPES_H
|
||||
#define DMD_ARRAYTYPES_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
|
||||
#include "root.h"
|
||||
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct BaseClass;
|
||||
struct TemplateParameter;
|
||||
struct FuncDeclaration;
|
||||
struct Identifier;
|
||||
struct Initializer;
|
||||
|
||||
struct TemplateParameters : Array { };
|
||||
|
||||
struct Expressions : Array { };
|
||||
|
||||
struct Statements : Array { };
|
||||
|
||||
struct BaseClasses : Array { };
|
||||
|
||||
struct ClassDeclarations : Array { };
|
||||
|
||||
struct Dsymbols : Array { };
|
||||
|
||||
struct Objects : Array { };
|
||||
|
||||
struct FuncDeclarations : Array { };
|
||||
|
||||
struct Arguments : Array { };
|
||||
|
||||
struct Identifiers : Array { };
|
||||
|
||||
struct Initializers : Array { };
|
||||
|
||||
#endif
|
||||
117
dmd2/artistic.txt
Normal file
117
dmd2/artistic.txt
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
|
||||
|
||||
|
||||
The "Artistic License"
|
||||
|
||||
Preamble
|
||||
|
||||
The intent of this document is to state the conditions under which a
|
||||
Package may be copied, such that the Copyright Holder maintains some
|
||||
semblance of artistic control over the development of the package,
|
||||
while giving the users of the package the right to use and distribute
|
||||
the Package in a more-or-less customary fashion, plus the right to make
|
||||
reasonable modifications.
|
||||
|
||||
Definitions:
|
||||
|
||||
"Package" refers to the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection of files
|
||||
created through textual modification.
|
||||
|
||||
"Standard Version" refers to such a Package if it has not been
|
||||
modified, or has been modified in accordance with the wishes
|
||||
of the Copyright Holder as specified below.
|
||||
|
||||
"Copyright Holder" is whoever is named in the copyright or
|
||||
copyrights for the package.
|
||||
|
||||
"You" is you, if you're thinking about copying or distributing
|
||||
this Package.
|
||||
|
||||
"Reasonable copying fee" is whatever you can justify on the
|
||||
basis of media cost, duplication charges, time of people involved,
|
||||
and so on. (You will not be required to justify it to the
|
||||
Copyright Holder, but only to the computing community at large
|
||||
as a market that must bear the fee.)
|
||||
|
||||
"Freely Available" means that no fee is charged for the item
|
||||
itself, though there may be fees involved in handling the item.
|
||||
It also means that recipients of the item may redistribute it
|
||||
under the same conditions they received it.
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of the
|
||||
Standard Version of this Package without restriction, provided that you
|
||||
duplicate all of the original copyright notices and associated disclaimers.
|
||||
|
||||
2. You may apply bug fixes, portability fixes and other modifications
|
||||
derived from the Public Domain or from the Copyright Holder. A Package
|
||||
modified in such a way shall still be considered the Standard Version.
|
||||
|
||||
3. You may otherwise modify your copy of this Package in any way, provided
|
||||
that you insert a prominent notice in each changed file stating how and
|
||||
when you changed that file, and provided that you do at least ONE of the
|
||||
following:
|
||||
|
||||
a) place your modifications in the Public Domain or otherwise make them
|
||||
Freely Available, such as by posting said modifications to Usenet or
|
||||
an equivalent medium, or placing the modifications on a major archive
|
||||
site such as uunet.uu.net, or by allowing the Copyright Holder to include
|
||||
your modifications in the Standard Version of the Package.
|
||||
|
||||
b) use the modified Package only within your corporation or organization.
|
||||
|
||||
c) rename any non-standard executables so the names do not conflict
|
||||
with standard executables, which must also be provided, and provide
|
||||
a separate manual page for each non-standard executable that clearly
|
||||
documents how it differs from the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
4. You may distribute the programs of this Package in object code or
|
||||
executable form, provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute a Standard Version of the executables and library files,
|
||||
together with instructions (in the manual page or equivalent) on where
|
||||
to get the Standard Version.
|
||||
|
||||
b) accompany the distribution with the machine-readable source of
|
||||
the Package with your modifications.
|
||||
|
||||
c) give non-standard executables non-standard names, and clearly
|
||||
document the differences in manual pages (or equivalent), together
|
||||
with instructions on where to get the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
5. You may charge a reasonable copying fee for any distribution of this
|
||||
Package. You may charge any fee you choose for support of this
|
||||
Package. You may not charge a fee for this Package itself. However,
|
||||
you may distribute this Package in aggregate with other (possibly
|
||||
commercial) programs as part of a larger (possibly commercial) software
|
||||
distribution provided that you do not advertise this Package as a
|
||||
product of your own. You may embed this Package's interpreter within
|
||||
an executable of yours (by linking); this shall be construed as a mere
|
||||
form of aggregation, provided that the complete Standard Version of the
|
||||
interpreter is so embedded.
|
||||
|
||||
6. The source code and object code supplied as input to or produced as
|
||||
output from the programs of this Package do not automatically fall
|
||||
under the copyright of this Package, but belong to whoever generated
|
||||
them, and may be sold commercially, and may be aggregated with this
|
||||
Package.
|
||||
|
||||
7. Aggregation of this Package with a commercial distribution is always
|
||||
permitted provided that the use of this Package is embedded; that is,
|
||||
when no overt attempt is made to make this Package's interfaces visible
|
||||
to the end user of the commercial distribution. Such use shall not be
|
||||
construed as a distribution of this Package.
|
||||
|
||||
8. The name of the Copyright Holder may not be used to endorse or promote
|
||||
products derived from this software without specific prior written permission.
|
||||
|
||||
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
The End
|
||||
1473
dmd2/attrib.c
Normal file
1473
dmd2/attrib.c
Normal file
File diff suppressed because it is too large
Load Diff
168
dmd2/attrib.h
Normal file
168
dmd2/attrib.h
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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_ATTRIB_H
|
||||
#define DMD_ATTRIB_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct LabelDsymbol;
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
struct Condition;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct AttribDeclaration : Dsymbol
|
||||
{
|
||||
Array *decl; // array of Dsymbol's
|
||||
|
||||
AttribDeclaration(Array *decl);
|
||||
virtual Array *include(Scope *sc, ScopeDsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void addComment(unsigned char *comment);
|
||||
void emitComment(Scope *sc);
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
int hasPointers();
|
||||
void checkCtorConstInit();
|
||||
void addLocalClass(ClassDeclarations *);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
AttribDeclaration *isAttribDeclaration() { return this; }
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
};
|
||||
|
||||
struct StorageClassDeclaration: AttribDeclaration
|
||||
{
|
||||
unsigned stc;
|
||||
|
||||
StorageClassDeclaration(unsigned stc, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct LinkDeclaration : AttribDeclaration
|
||||
{
|
||||
enum LINK linkage;
|
||||
|
||||
LinkDeclaration(enum LINK p, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
struct ProtDeclaration : AttribDeclaration
|
||||
{
|
||||
enum PROT protection;
|
||||
|
||||
ProtDeclaration(enum PROT p, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct AlignDeclaration : AttribDeclaration
|
||||
{
|
||||
unsigned salign;
|
||||
|
||||
AlignDeclaration(Loc loc, unsigned sa, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct AnonDeclaration : AttribDeclaration
|
||||
{
|
||||
int isunion;
|
||||
Scope *scope; // !=NULL means context to use
|
||||
int sem; // 1 if successful semantic()
|
||||
|
||||
AnonDeclaration(Loc loc, int isunion, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
struct PragmaDeclaration : AttribDeclaration
|
||||
{
|
||||
Expressions *args; // array of Expression's
|
||||
|
||||
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
};
|
||||
|
||||
struct ConditionalDeclaration : AttribDeclaration
|
||||
{
|
||||
Condition *condition;
|
||||
Array *elsedecl; // array of Dsymbol's for else block
|
||||
|
||||
ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void emitComment(Scope *sc);
|
||||
Array *include(Scope *sc, ScopeDsymbol *s);
|
||||
void addComment(unsigned char *comment);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct StaticIfDeclaration : ConditionalDeclaration
|
||||
{
|
||||
ScopeDsymbol *sd;
|
||||
int addisdone;
|
||||
|
||||
StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
// Mixin declarations
|
||||
|
||||
struct CompileDeclaration : AttribDeclaration
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
ScopeDsymbol *sd;
|
||||
int compiled;
|
||||
|
||||
CompileDeclaration(Loc loc, Expression *exp);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
|
||||
void compileIt(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
#endif /* DMD_ATTRIB_H */
|
||||
102
dmd2/builtin.c
Normal file
102
dmd2/builtin.c
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "declaration.h"
|
||||
#include "attrib.h"
|
||||
#include "expression.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "aggregate.h"
|
||||
#include "identifier.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
|
||||
/**********************************
|
||||
* Determine if function is a builtin one.
|
||||
*/
|
||||
enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
{
|
||||
static const char FeZe[] = "FeZe"; // real function(real)
|
||||
|
||||
//printf("FuncDeclaration::isBuiltin() %s\n", toChars());
|
||||
if (builtin == BUILTINunknown)
|
||||
{
|
||||
builtin = BUILTINnot;
|
||||
if (parent && parent->isModule())
|
||||
{
|
||||
if (parent->ident == Id::math &&
|
||||
parent->parent && parent->parent->ident == Id::std &&
|
||||
!parent->parent->parent)
|
||||
{
|
||||
if (strcmp(type->deco, FeZe) == 0)
|
||||
{
|
||||
if (ident == Id::sin)
|
||||
builtin = BUILTINsin;
|
||||
else if (ident == Id::cos)
|
||||
builtin = BUILTINcos;
|
||||
else if (ident == Id::tan)
|
||||
builtin = BUILTINtan;
|
||||
else if (ident == Id::_sqrt)
|
||||
builtin = BUILTINsqrt;
|
||||
else if (ident == Id::fabs)
|
||||
builtin = BUILTINfabs;
|
||||
//printf("builtin = %d\n", builtin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return builtin;
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Evaluate builtin function.
|
||||
* Return result; NULL if cannot evaluate it.
|
||||
*/
|
||||
|
||||
Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments)
|
||||
{
|
||||
assert(arguments && arguments->dim);
|
||||
Expression *arg0 = (Expression *)arguments->data[0];
|
||||
Expression *e = NULL;
|
||||
switch (builtin)
|
||||
{
|
||||
case BUILTINsin:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, sinl(arg0->toReal()), Type::tfloat80);
|
||||
break;
|
||||
|
||||
case BUILTINcos:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, cosl(arg0->toReal()), Type::tfloat80);
|
||||
break;
|
||||
|
||||
case BUILTINtan:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, tanl(arg0->toReal()), Type::tfloat80);
|
||||
break;
|
||||
|
||||
case BUILTINsqrt:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, sqrtl(arg0->toReal()), Type::tfloat80);
|
||||
break;
|
||||
|
||||
case BUILTINfabs:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, fabsl(arg0->toReal()), Type::tfloat80);
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
1688
dmd2/cast.c
Normal file
1688
dmd2/cast.c
Normal file
File diff suppressed because it is too large
Load Diff
1420
dmd2/class.c
Normal file
1420
dmd2/class.c
Normal file
File diff suppressed because it is too large
Load Diff
423
dmd2/clone.c
Normal file
423
dmd2/clone.c
Normal file
@@ -0,0 +1,423 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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 <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "init.h"
|
||||
|
||||
|
||||
/*******************************************
|
||||
* We need an opAssign for the struct if
|
||||
* it has a destructor or a postblit.
|
||||
* We need to generate one if a user-specified one does not exist.
|
||||
*/
|
||||
|
||||
int StructDeclaration::needOpAssign()
|
||||
{
|
||||
#define X 0
|
||||
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
|
||||
if (hasIdentityAssign)
|
||||
goto Ldontneed;
|
||||
|
||||
if (dtor || postblit)
|
||||
goto Lneed;
|
||||
|
||||
/* If any of the fields need an opAssign, then we
|
||||
* need it too.
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->needOpAssign())
|
||||
goto Lneed;
|
||||
}
|
||||
}
|
||||
Ldontneed:
|
||||
if (X) printf("\tdontneed\n");
|
||||
return 0;
|
||||
|
||||
Lneed:
|
||||
if (X) printf("\tneed\n");
|
||||
return 1;
|
||||
#undef X
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Build opAssign for struct.
|
||||
* S* opAssign(S s) { ... }
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
{
|
||||
if (!needOpAssign())
|
||||
return NULL;
|
||||
|
||||
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
FuncDeclaration *fop = NULL;
|
||||
|
||||
Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
|
||||
|
||||
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
|
||||
|
||||
Expression *e = NULL;
|
||||
if (postblit)
|
||||
{ /* Swap:
|
||||
* tmp = *this; *this = s; tmp.dtor();
|
||||
*/
|
||||
//printf("\tswap copy\n");
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
VarDeclaration *tmp;
|
||||
AssignExp *ec = NULL;
|
||||
if (dtor)
|
||||
{
|
||||
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
|
||||
tmp->noauto = 1;
|
||||
e = new DeclarationExp(0, tmp);
|
||||
ec = new AssignExp(0,
|
||||
new VarExp(0, tmp),
|
||||
new PtrExp(0, new ThisExp(0)));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
ec = new AssignExp(0,
|
||||
new PtrExp(0, new ThisExp(0)),
|
||||
new IdentifierExp(0, Id::p));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
if (dtor)
|
||||
{
|
||||
/* Instead of running the destructor on s, run it
|
||||
* on tmp. This avoids needing to copy tmp back in to s.
|
||||
*/
|
||||
Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
|
||||
ec = new CallExp(0, ec);
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Do memberwise copy
|
||||
*/
|
||||
//printf("\tmemberwise copy\n");
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
// this.v = s.v;
|
||||
AssignExp *ec = new AssignExp(0,
|
||||
new DotVarExp(0, new ThisExp(0), v, 0),
|
||||
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
Statement *s1 = new ExpStatement(0, e);
|
||||
|
||||
/* Add:
|
||||
* return this;
|
||||
*/
|
||||
e = new ThisExp(0);
|
||||
Statement *s2 = new ReturnStatement(0, e);
|
||||
|
||||
fop->fbody = new CompoundStatement(0, s1, s2);
|
||||
|
||||
members->push(fop);
|
||||
fop->addMember(sc, this, 1);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fop->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
|
||||
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
return fop;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Build copy constructor for struct.
|
||||
* Copy constructors are compiler generated only, and are only
|
||||
* callable from the compiler. They are not user accessible.
|
||||
* A copy constructor is:
|
||||
* void cpctpr(ref S s)
|
||||
* {
|
||||
* *this = s;
|
||||
* this.postBlit();
|
||||
* }
|
||||
* This is done so:
|
||||
* - postBlit() never sees uninitialized data
|
||||
* - memcpy can be much more efficient than memberwise copy
|
||||
* - no fields are overlooked
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
|
||||
FuncDeclaration *fcp = NULL;
|
||||
|
||||
/* Copy constructor is only necessary if there is a postblit function,
|
||||
* otherwise the code generator will just do a bit copy.
|
||||
*/
|
||||
if (postblit)
|
||||
{
|
||||
//printf("generating cpctor\n");
|
||||
|
||||
Argument *param = new Argument(STCref, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
|
||||
|
||||
// Build *this = p;
|
||||
Expression *e = new ThisExp(0);
|
||||
e = new PtrExp(0, e);
|
||||
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
|
||||
ea->op = TOKblit;
|
||||
Statement *s = new ExpStatement(0, ea);
|
||||
|
||||
// Build postBlit();
|
||||
e = new VarExp(0, postblit, 0);
|
||||
e = new CallExp(0, e);
|
||||
|
||||
s = new CompoundStatement(0, s, new ExpStatement(0, e));
|
||||
fcp->fbody = s;
|
||||
|
||||
members->push(fcp);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fcp->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
return fcp;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive postblit for struct by aggregating
|
||||
* all the postblits in postblits[] with the postblits for
|
||||
* all the members.
|
||||
* Note the close similarity with AggregateDeclaration::buildDtor(),
|
||||
* and the ordering changes (runs forward instead of backwards).
|
||||
*/
|
||||
|
||||
#if DMDV2
|
||||
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->postblit)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->postblit, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.postblit(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::postblit);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(e, ex); // combine in forward order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "postblit" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldPostBlit()\n");
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.push(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
|
||||
switch (postblits.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)postblits.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < postblits.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(e, ex);
|
||||
}
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive destructor for struct/class by aggregating
|
||||
* all the destructors in dtors[] with the destructors for
|
||||
* all the members.
|
||||
* Note the close similarity with StructDeclaration::buildPostBlit(),
|
||||
* and the ordering changes (runs backward instead of forwards).
|
||||
*/
|
||||
|
||||
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
{
|
||||
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
#if DMDV2
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->dtor, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.destroy(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::destroy);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(ex, e); // combine in reverse order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "destructor" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldDtor()\n");
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.shift(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (dtors.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)dtors.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < dtors.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(ex, e);
|
||||
}
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
74
dmd2/complex_t.h
Normal file
74
dmd2/complex_t.h
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright and Burton Radons
|
||||
// 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_COMPLEX_T_H
|
||||
#define DMD_COMPLEX_T_H
|
||||
|
||||
/* Roll our own complex type for compilers that don't support complex
|
||||
*/
|
||||
|
||||
struct complex_t
|
||||
{
|
||||
long double re;
|
||||
long double im;
|
||||
|
||||
complex_t() { this->re = 0; this->im = 0; }
|
||||
complex_t(long double re) { this->re = re; this->im = 0; }
|
||||
complex_t(long double re, long double im) { this->re = re; this->im = im; }
|
||||
|
||||
complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; }
|
||||
complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; }
|
||||
complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; }
|
||||
complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); }
|
||||
|
||||
complex_t operator / (complex_t y)
|
||||
{
|
||||
long double abs_y_re = y.re < 0 ? -y.re : y.re;
|
||||
long double abs_y_im = y.im < 0 ? -y.im : y.im;
|
||||
long double r, den;
|
||||
|
||||
if (abs_y_re < abs_y_im)
|
||||
{
|
||||
r = y.re / y.im;
|
||||
den = y.im + r * y.re;
|
||||
return complex_t((re * r + im) / den,
|
||||
(im * r - re) / den);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = y.im / y.re;
|
||||
den = y.re + r * y.im;
|
||||
return complex_t((re + r * im) / den,
|
||||
(im - r * re) / den);
|
||||
}
|
||||
}
|
||||
|
||||
operator bool () { return re || im; }
|
||||
|
||||
int operator == (complex_t y) { return re == y.re && im == y.im; }
|
||||
int operator != (complex_t y) { return re != y.re || im != y.im; }
|
||||
};
|
||||
|
||||
inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; }
|
||||
inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); }
|
||||
inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); }
|
||||
|
||||
|
||||
inline long double creall(complex_t x)
|
||||
{
|
||||
return x.re;
|
||||
}
|
||||
|
||||
inline long double cimagl(complex_t x)
|
||||
{
|
||||
return x.im;
|
||||
}
|
||||
|
||||
#endif
|
||||
391
dmd2/cond.c
Normal file
391
dmd2/cond.c
Normal file
@@ -0,0 +1,391 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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 <assert.h>
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "identifier.h"
|
||||
#include "expression.h"
|
||||
#include "cond.h"
|
||||
#include "module.h"
|
||||
#include "template.h"
|
||||
#include "lexer.h"
|
||||
#ifdef _DH
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident)
|
||||
{
|
||||
if (ids)
|
||||
{
|
||||
for (int i = 0; i < ids->dim; i++)
|
||||
{
|
||||
const char *id = (const char *)ids->data[i];
|
||||
|
||||
if (strcmp(id, ident->toChars()) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
Condition::Condition(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: Condition(0)
|
||||
{
|
||||
this->mod = mod;
|
||||
this->level = level;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Condition *DVCondition::syntaxCopy()
|
||||
{
|
||||
return this; // don't need to copy
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void DebugCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.debuglevel = level;
|
||||
}
|
||||
|
||||
void DebugCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.debugids)
|
||||
global.params.debugids = new Array();
|
||||
global.params.debugids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{ if (!mod->debugidsNot)
|
||||
mod->debugidsNot = new Array();
|
||||
mod->debugidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("debug (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("debug (%u)", level);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void VersionCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
{
|
||||
static const char* reserved[] =
|
||||
{
|
||||
"DigitalMars", "LLVM", "LDC", "LLVM64",
|
||||
"X86", "X86_64", "PPC", "PPC64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux", "darwin", "Posix",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
checkPredefined(0, ident);
|
||||
addPredefinedGlobalIdent(ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addPredefinedGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.versionids)
|
||||
global.params.versionids = new Array();
|
||||
global.params.versionids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
|
||||
//if (ident) printf("\tident = '%s'\n", ident->toChars());
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{
|
||||
if (!mod->versionidsNot)
|
||||
mod->versionidsNot = new Array();
|
||||
mod->versionidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("version (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("version (%u)", level);
|
||||
}
|
||||
|
||||
|
||||
/**************************** StaticIfCondition *******************************/
|
||||
|
||||
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
{
|
||||
return new StaticIfCondition(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
}
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("static if(");
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
/**************************** IftypeCondition *******************************/
|
||||
|
||||
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->targ = targ;
|
||||
this->id = id;
|
||||
this->tok = tok;
|
||||
this->tspec = tspec;
|
||||
}
|
||||
|
||||
Condition *IftypeCondition::syntaxCopy()
|
||||
{
|
||||
return new IftypeCondition(loc,
|
||||
targ->syntaxCopy(),
|
||||
id,
|
||||
tok,
|
||||
tspec ? tspec->syntaxCopy() : NULL);
|
||||
}
|
||||
|
||||
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("IftypeCondition::include()\n");
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "iftype conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
unsigned errors = global.errors;
|
||||
global.gag++; // suppress printing of error messages
|
||||
targ = targ->semantic(loc, sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors) // if any errors happened
|
||||
{ inc = 2; // then condition is false
|
||||
global.errors = errors;
|
||||
}
|
||||
else if (id && tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec.
|
||||
* If TRUE, declare id as an alias for the specialized type.
|
||||
*/
|
||||
|
||||
MATCH m;
|
||||
TemplateTypeParameter tp(loc, id, NULL, NULL);
|
||||
|
||||
TemplateParameters parameters;
|
||||
parameters.setDim(1);
|
||||
parameters.data[0] = (void *)&tp;
|
||||
|
||||
Objects dedtypes;
|
||||
dedtypes.setDim(1);
|
||||
|
||||
m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes);
|
||||
if (m == MATCHnomatch ||
|
||||
(m != MATCHexact && tok == TOKequal))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
inc = 1;
|
||||
Type *tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
}
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
/* Declare id as an alias for type targ. Evaluate to TRUE
|
||||
*/
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, targ);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
inc = 1;
|
||||
}
|
||||
else if (tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec
|
||||
*/
|
||||
tspec = tspec->semantic(loc, sc);
|
||||
//printf("targ = %s\n", targ->toChars());
|
||||
//printf("tspec = %s\n", tspec->toChars());
|
||||
if (tok == TOKcolon)
|
||||
{ if (targ->implicitConvTo(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
else /* == */
|
||||
{ if (targ->equals(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
inc = 1;
|
||||
//printf("inc = %d\n", inc);
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("iftype(");
|
||||
targ->toCBuffer(buf, id, hgs);
|
||||
if (tspec)
|
||||
{
|
||||
if (tok == TOKcolon)
|
||||
buf->writestring(" : ");
|
||||
else
|
||||
buf->writestring(" == ");
|
||||
tspec->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
106
dmd2/cond.h
Normal file
106
dmd2/cond.h
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_DEBCOND_H
|
||||
#define DMD_DEBCOND_H
|
||||
|
||||
struct Expression;
|
||||
struct Identifier;
|
||||
struct OutBuffer;
|
||||
struct Module;
|
||||
struct Scope;
|
||||
struct ScopeDsymbol;
|
||||
#ifdef _DH
|
||||
#include "lexer.h" // dmdhg
|
||||
#endif
|
||||
enum TOK;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident);
|
||||
|
||||
struct Condition
|
||||
{
|
||||
Loc loc;
|
||||
int inc; // 0: not computed yet
|
||||
// 1: include
|
||||
// 2: do not include
|
||||
|
||||
Condition(Loc loc);
|
||||
|
||||
virtual Condition *syntaxCopy() = 0;
|
||||
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
};
|
||||
|
||||
struct DVCondition : Condition
|
||||
{
|
||||
unsigned level;
|
||||
Identifier *ident;
|
||||
Module *mod;
|
||||
|
||||
DVCondition(Module *mod, unsigned level, Identifier *ident);
|
||||
|
||||
Condition *syntaxCopy();
|
||||
};
|
||||
|
||||
struct DebugCondition : DVCondition
|
||||
{
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void addGlobalIdent(const char *ident);
|
||||
static void addPredefinedGlobalIdent(const char *ident);
|
||||
|
||||
DebugCondition(Module *mod, unsigned level, Identifier *ident);
|
||||
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct VersionCondition : DVCondition
|
||||
{
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void checkPredefined(Loc loc, const char *ident);
|
||||
static void addGlobalIdent(const char *ident);
|
||||
static void addPredefinedGlobalIdent(const char *ident);
|
||||
|
||||
VersionCondition(Module *mod, unsigned level, Identifier *ident);
|
||||
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct StaticIfCondition : Condition
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
StaticIfCondition(Loc loc, Expression *exp);
|
||||
Condition *syntaxCopy();
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct IftypeCondition : Condition
|
||||
{
|
||||
/* iftype (targ id tok tspec)
|
||||
*/
|
||||
Type *targ;
|
||||
Identifier *id; // can be NULL
|
||||
enum TOK tok; // ':' or '=='
|
||||
Type *tspec; // can be NULL
|
||||
|
||||
IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec);
|
||||
Condition *syntaxCopy();
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1606
dmd2/constfold.c
Normal file
1606
dmd2/constfold.c
Normal file
File diff suppressed because it is too large
Load Diff
482
dmd2/dchar.c
Normal file
482
dmd2/dchar.c
Normal file
@@ -0,0 +1,482 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dchar.h"
|
||||
#include "mem.h"
|
||||
|
||||
#if M_UNICODE
|
||||
|
||||
// Converts a char string to Unicode
|
||||
|
||||
dchar *Dchar::dup(char *p)
|
||||
{
|
||||
dchar *s;
|
||||
size_t len;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
len = strlen(p);
|
||||
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
s[i] = (dchar)(p[i] & 0xFF);
|
||||
}
|
||||
s[len] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
dchar *Dchar::memchr(dchar *p, int c, int count)
|
||||
{
|
||||
int u;
|
||||
|
||||
for (u = 0; u < count; u++)
|
||||
{
|
||||
if (p[u] == c)
|
||||
return p + u;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if _WIN32 && __DMC__
|
||||
__declspec(naked)
|
||||
unsigned Dchar::calcHash(const dchar *str, unsigned len)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ECX,4[ESP]
|
||||
mov EDX,8[ESP]
|
||||
xor EAX,EAX
|
||||
test EDX,EDX
|
||||
je L92
|
||||
|
||||
LC8: cmp EDX,1
|
||||
je L98
|
||||
cmp EDX,2
|
||||
je LAE
|
||||
|
||||
add EAX,[ECX]
|
||||
// imul EAX,EAX,025h
|
||||
lea EAX,[EAX][EAX*8]
|
||||
add ECX,4
|
||||
sub EDX,2
|
||||
jmp LC8
|
||||
|
||||
L98: mov DX,[ECX]
|
||||
and EDX,0FFFFh
|
||||
add EAX,EDX
|
||||
ret
|
||||
|
||||
LAE: add EAX,[ECX]
|
||||
L92: ret
|
||||
}
|
||||
}
|
||||
#else
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash += *(const uint16_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash += *(const uint32_t *)str;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash += *(const uint32_t *)str;
|
||||
hash *= 37;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash += *(const uint16_t *)str | 0x20;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash += *(const uint32_t *)str | 0x200020;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash += *(const uint32_t *)str | 0x200020;
|
||||
hash *= 37;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif MCBS
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(const uint16_t *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(const uint32_t *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif UTF8
|
||||
|
||||
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
|
||||
|
||||
char Dchar::mblen[256] =
|
||||
{
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
|
||||
};
|
||||
|
||||
dchar *Dchar::dec(dchar *pstart, dchar *p)
|
||||
{
|
||||
while ((p[-1] & 0xC0) == 0x80)
|
||||
p--;
|
||||
return p;
|
||||
}
|
||||
|
||||
int Dchar::get(dchar *p)
|
||||
{
|
||||
unsigned c;
|
||||
unsigned char *q = (unsigned char *)p;
|
||||
|
||||
c = q[0];
|
||||
switch (mblen[c])
|
||||
{
|
||||
case 2:
|
||||
c = ((c - 0xC0) << 6) |
|
||||
(q[1] - 0x80);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
c = ((c - 0xE0) << 12) |
|
||||
((q[1] - 0x80) << 6) |
|
||||
(q[2] - 0x80);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
c = ((c - 0xF0) << 18) |
|
||||
((q[1] - 0x80) << 12) |
|
||||
((q[2] - 0x80) << 6) |
|
||||
(q[3] - 0x80);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
c = ((c - 0xF8) << 24) |
|
||||
((q[1] - 0x80) << 18) |
|
||||
((q[2] - 0x80) << 12) |
|
||||
((q[3] - 0x80) << 6) |
|
||||
(q[4] - 0x80);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
c = ((c - 0xFC) << 30) |
|
||||
((q[1] - 0x80) << 24) |
|
||||
((q[2] - 0x80) << 18) |
|
||||
((q[3] - 0x80) << 12) |
|
||||
((q[4] - 0x80) << 6) |
|
||||
(q[5] - 0x80);
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
dchar *Dchar::put(dchar *p, unsigned c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
*p++ = c;
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
p[0] = 0xC0 + (c >> 6);
|
||||
p[1] = 0x80 + (c & 0x3F);
|
||||
p += 2;
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
p[0] = 0xE0 + (c >> 12);
|
||||
p[1] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[2] = 0x80 + (c & 0x3F);
|
||||
p += 3;
|
||||
}
|
||||
else if (c <= 0x1FFFFF)
|
||||
{
|
||||
p[0] = 0xF0 + (c >> 18);
|
||||
p[1] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[3] = 0x80 + (c & 0x3F);
|
||||
p += 4;
|
||||
}
|
||||
else if (c <= 0x3FFFFFF)
|
||||
{
|
||||
p[0] = 0xF8 + (c >> 24);
|
||||
p[1] = 0x80 + ((c >> 18) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[3] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[4] = 0x80 + (c & 0x3F);
|
||||
p += 5;
|
||||
}
|
||||
else if (c <= 0x7FFFFFFF)
|
||||
{
|
||||
p[0] = 0xFC + (c >> 30);
|
||||
p[1] = 0x80 + ((c >> 24) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 18) & 0x3F);
|
||||
p[3] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[4] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[5] = 0x80 + (c & 0x3F);
|
||||
p += 6;
|
||||
}
|
||||
else
|
||||
assert(0); // not a UCS-4 character
|
||||
return p;
|
||||
}
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint16_t *)str;
|
||||
#else
|
||||
hash += str[0] * 256 + str[1];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
#else
|
||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint32_t *)str;
|
||||
#else
|
||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||
#endif
|
||||
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // ascii
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint16_t *)str;
|
||||
#else
|
||||
hash += str[0] * 256 + str[1];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
#else
|
||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint32_t *)str;
|
||||
#else
|
||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||
#endif
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str | 0x20;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(const uint16_t *)str | 0x2020;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += ((*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2]) | 0x202020;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(const uint32_t *)str | 0x20202020;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
// Print out values to hardcode into Dchar::mblen[]
|
||||
int c;
|
||||
int s;
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
s = 1;
|
||||
if (c >= 0xC0 && c <= 0xDF)
|
||||
s = 2;
|
||||
if (c >= 0xE0 && c <= 0xEF)
|
||||
s = 3;
|
||||
if (c >= 0xF0 && c <= 0xF7)
|
||||
s = 4;
|
||||
if (c >= 0xF8 && c <= 0xFB)
|
||||
s = 5;
|
||||
if (c >= 0xFC && c <= 0xFD)
|
||||
s = 6;
|
||||
|
||||
printf("%d", s);
|
||||
if ((c & 15) == 15)
|
||||
printf(",\n");
|
||||
else
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
194
dmd2/dchar.h
Normal file
194
dmd2/dchar.h
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 DCHAR_H
|
||||
#define DCHAR_H
|
||||
|
||||
#if __GNUC__ && !_WIN32
|
||||
#include "gnuc.h"
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
// Disable useless warnings about unreferenced functions
|
||||
#pragma warning (disable : 4514)
|
||||
#endif
|
||||
|
||||
//#include "root.h"
|
||||
typedef size_t hash_t;
|
||||
|
||||
#undef TEXT
|
||||
|
||||
// NOTE: All functions accepting pointer arguments must not be NULL
|
||||
|
||||
#if M_UNICODE
|
||||
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef wchar_t dchar;
|
||||
#define TEXT(x) L##x
|
||||
|
||||
#define Dchar_mbmax 1
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static dchar *inc(dchar *p) { return p + 1; }
|
||||
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
|
||||
static int len(const dchar *p) { return wcslen(p); }
|
||||
static dchar get(dchar *p) { return *p; }
|
||||
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
|
||||
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
|
||||
static int cmp(dchar *s1, dchar *s2)
|
||||
{
|
||||
#if __DMC__
|
||||
if (!*s1 && !*s2) // wcscmp is broken
|
||||
return 0;
|
||||
#endif
|
||||
return wcscmp(s1, s2);
|
||||
#if 0
|
||||
return (*s1 == *s2)
|
||||
? wcscmp(s1, s2)
|
||||
: ((int)*s1 - (int)*s2);
|
||||
#endif
|
||||
}
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
static int isAlpha(dchar c) { return iswalpha(c); }
|
||||
static int isUpper(dchar c) { return iswupper(c); }
|
||||
static int isLower(dchar c) { return iswlower(c); }
|
||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
|
||||
static dchar *dup(char *p);
|
||||
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
|
||||
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
|
||||
static dchar *memchr(dchar *p, int c, int count);
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
|
||||
static hash_t icalcHash(const dchar *str, size_t len);
|
||||
};
|
||||
|
||||
#elif MCBS
|
||||
|
||||
#include <limits.h>
|
||||
#include <mbstring.h>
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax MB_LEN_MAX
|
||||
|
||||
#elif UTF8
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax 6
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static char mblen[256];
|
||||
|
||||
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
|
||||
static dchar *dec(dchar *pstart, dchar *p);
|
||||
static int len(const dchar *p) { return strlen(p); }
|
||||
static int get(dchar *p);
|
||||
static int getprev(dchar *pstart, dchar *p)
|
||||
{ return *dec(pstart, p) & 0xFF; }
|
||||
static dchar *put(dchar *p, unsigned c);
|
||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
|
||||
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
|
||||
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
|
||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||
static dchar *memchr(dchar *p, int c, int count)
|
||||
{ return (dchar *)::memchr(p, c, count); }
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax 1
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static dchar *inc(dchar *p) { return p + 1; }
|
||||
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
|
||||
static int len(const dchar *p) { return strlen(p); }
|
||||
static int get(dchar *p) { return *p & 0xFF; }
|
||||
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
|
||||
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
|
||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
#ifndef GCC_SAFE_DMD
|
||||
static int isAlpha(dchar c) { return isalpha(c); }
|
||||
static int isUpper(dchar c) { return isupper(c); }
|
||||
static int isLower(dchar c) { return islower(c); }
|
||||
static int isLocaleUpper(dchar c) { return isupper(c); }
|
||||
static int isLocaleLower(dchar c) { return islower(c); }
|
||||
static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||
#endif
|
||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||
static dchar *memchr(dchar *p, int c, int count)
|
||||
{ return (dchar *)::memchr(p, c, count); }
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
#ifdef __GNUC__
|
||||
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
|
||||
#else
|
||||
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
|
||||
#endif
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
|
||||
static hash_t icalcHash(const dchar *str, size_t len);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
1649
dmd2/declaration.c
Normal file
1649
dmd2/declaration.c
Normal file
File diff suppressed because it is too large
Load Diff
853
dmd2/declaration.h
Normal file
853
dmd2/declaration.h
Normal file
@@ -0,0 +1,853 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_DECLARATION_H
|
||||
#define DMD_DECLARATION_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "dsymbol.h"
|
||||
#include "lexer.h"
|
||||
#include "mtype.h"
|
||||
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct LabelDsymbol;
|
||||
struct LabelStatement;
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
struct InlineScanState;
|
||||
struct ForeachStatement;
|
||||
struct FuncDeclaration;
|
||||
struct ExpInitializer;
|
||||
struct StructDeclaration;
|
||||
struct TupleType;
|
||||
struct InterState;
|
||||
struct IRState;
|
||||
struct AnonDeclaration;
|
||||
|
||||
enum PROT;
|
||||
enum LINK;
|
||||
enum TOK;
|
||||
enum MATCH;
|
||||
|
||||
enum STC
|
||||
{
|
||||
STCundefined = 0,
|
||||
STCstatic = 1,
|
||||
STCextern = 2,
|
||||
STCconst = 4,
|
||||
STCfinal = 8,
|
||||
STCabstract = 0x10,
|
||||
STCparameter = 0x20,
|
||||
STCfield = 0x40,
|
||||
STCoverride = 0x80,
|
||||
STCauto = 0x100,
|
||||
STCsynchronized = 0x200,
|
||||
STCdeprecated = 0x400,
|
||||
STCin = 0x800, // in parameter
|
||||
STCout = 0x1000, // out parameter
|
||||
STClazy = 0x2000, // lazy parameter
|
||||
STCforeach = 0x4000, // variable for foreach loop
|
||||
STCcomdat = 0x8000, // should go into COMDAT record
|
||||
STCvariadic = 0x10000, // variadic function argument
|
||||
STCctorinit = 0x20000, // can only be set inside constructor
|
||||
STCtemplateparameter = 0x40000, // template parameter
|
||||
STCscope = 0x80000, // template parameter
|
||||
STCinvariant = 0x100000,
|
||||
STCref = 0x200000,
|
||||
STCinit = 0x400000, // has explicit initializer
|
||||
STCmanifest = 0x800000, // manifest constant
|
||||
STCnodtor = 0x1000000, // don't run destructor
|
||||
STCnothrow = 0x2000000, // never throws exceptions
|
||||
STCpure = 0x4000000, // pure function
|
||||
STCtls = 0x8000000, // thread local
|
||||
STCalias = 0x10000000, // alias parameter
|
||||
STCshared = 0x20000000, // accessible from multiple threads
|
||||
};
|
||||
|
||||
struct Match
|
||||
{
|
||||
int count; // number of matches found
|
||||
MATCH last; // match level of lastf
|
||||
FuncDeclaration *lastf; // last matching function we found
|
||||
FuncDeclaration *nextf; // current matching function
|
||||
FuncDeclaration *anyf; // pick a func, any func, to use for error recovery
|
||||
};
|
||||
|
||||
void overloadResolveX(Match *m, FuncDeclaration *f,
|
||||
Expression *ethis, Expressions *arguments);
|
||||
int overloadApply(FuncDeclaration *fstart,
|
||||
int (*fp)(void *, FuncDeclaration *),
|
||||
void *param);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct Declaration : Dsymbol
|
||||
{
|
||||
Type *type;
|
||||
Type *originalType; // before semantic analysis
|
||||
unsigned storage_class;
|
||||
enum PROT protection;
|
||||
enum LINK linkage;
|
||||
|
||||
Declaration(Identifier *id);
|
||||
void semantic(Scope *sc);
|
||||
const char *kind();
|
||||
unsigned size(Loc loc);
|
||||
void checkModify(Loc loc, Scope *sc, Type *t);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
char *mangle();
|
||||
int isStatic() { return storage_class & STCstatic; }
|
||||
virtual int isStaticConstructor();
|
||||
virtual int isStaticDestructor();
|
||||
virtual int isDelete();
|
||||
virtual int isDataseg();
|
||||
virtual int isCodeseg();
|
||||
int isCtorinit() { return storage_class & STCctorinit; }
|
||||
int isFinal() { return storage_class & STCfinal; }
|
||||
int isAbstract() { return storage_class & STCabstract; }
|
||||
int isConst() { return storage_class & STCconst; }
|
||||
int isInvariant() { return storage_class & STCinvariant; }
|
||||
int isAuto() { return storage_class & STCauto; }
|
||||
int isScope() { return storage_class & (STCscope | STCauto); }
|
||||
int isSynchronized() { return storage_class & STCsynchronized; }
|
||||
int isParameter() { return storage_class & STCparameter; }
|
||||
int isDeprecated() { return storage_class & STCdeprecated; }
|
||||
int isOverride() { return storage_class & STCoverride; }
|
||||
|
||||
int isIn() { return storage_class & STCin; }
|
||||
int isOut() { return storage_class & STCout; }
|
||||
int isRef() { return storage_class & STCref; }
|
||||
|
||||
enum PROT prot();
|
||||
|
||||
Declaration *isDeclaration() { return this; }
|
||||
|
||||
// llvm
|
||||
virtual void toObjFile(int unused = 0); // compile to .obj file
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct TupleDeclaration : Declaration
|
||||
{
|
||||
Objects *objects;
|
||||
int isexp; // 1: expression tuple
|
||||
|
||||
TypeTuple *tupletype; // !=NULL if this is a type tuple
|
||||
|
||||
TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
const char *kind();
|
||||
Type *getType();
|
||||
int needThis();
|
||||
|
||||
TupleDeclaration *isTupleDeclaration() { return this; }
|
||||
|
||||
// LDC we need this
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct TypedefDeclaration : Declaration
|
||||
{
|
||||
Type *basetype;
|
||||
Initializer *init;
|
||||
int sem; // 0: semantic() has not been run
|
||||
// 1: semantic() is in progress
|
||||
// 2: semantic() has been run
|
||||
// 3: semantic2() has been run
|
||||
int inuse; // used to detect typedef cycles
|
||||
|
||||
TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
Type *getType();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#ifdef _DH
|
||||
Type *htype;
|
||||
Type *hbasetype;
|
||||
#endif
|
||||
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
int cvMember(unsigned char *p);
|
||||
|
||||
TypedefDeclaration *isTypedefDeclaration() { return this; }
|
||||
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct AliasDeclaration : Declaration
|
||||
{
|
||||
Dsymbol *aliassym;
|
||||
Dsymbol *overnext; // next in overload list
|
||||
int inSemantic;
|
||||
|
||||
AliasDeclaration(Loc loc, Identifier *ident, Type *type);
|
||||
AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
const char *kind();
|
||||
Type *getType();
|
||||
Dsymbol *toAlias();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#ifdef _DH
|
||||
Type *htype;
|
||||
Dsymbol *haliassym;
|
||||
#endif
|
||||
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
AliasDeclaration *isAliasDeclaration() { return this; }
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct VarDeclaration : Declaration
|
||||
{
|
||||
Initializer *init;
|
||||
unsigned offset;
|
||||
int noauto; // no auto semantics
|
||||
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
|
||||
int inuse;
|
||||
int ctorinit; // it has been initialized in a ctor
|
||||
int onstack; // 1: it has been allocated on the stack
|
||||
// 2: on stack, run destructor anyway
|
||||
int canassign; // it can be assigned to
|
||||
Dsymbol *aliassym; // if redone as alias to another symbol
|
||||
Expression *value; // when interpreting, this is the value
|
||||
// (NULL if value not determinable)
|
||||
Scope *scope; // !=NULL means context to use
|
||||
|
||||
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
const char *kind();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#ifdef _DH
|
||||
Type *htype;
|
||||
Initializer *hinit;
|
||||
#endif
|
||||
int needThis();
|
||||
int isImportedSymbol();
|
||||
int isDataseg();
|
||||
int hasPointers();
|
||||
int canTakeAddressOf();
|
||||
int needsAutoDtor();
|
||||
Expression *callAutoDtor(Scope *sc);
|
||||
ExpInitializer *getExpInitializer();
|
||||
Expression *getConstInitializer();
|
||||
void checkCtorConstInit();
|
||||
void checkNestedReference(Scope *sc, Loc loc);
|
||||
Dsymbol *toAlias();
|
||||
|
||||
Symbol *toSymbol();
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
|
||||
// Eliminate need for dynamic_cast
|
||||
VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
|
||||
|
||||
// LDC
|
||||
AnonDeclaration* anonDecl;
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
// This is a shell around a back end symbol
|
||||
|
||||
struct SymbolDeclaration : Declaration
|
||||
{
|
||||
Symbol *sym;
|
||||
StructDeclaration *dsym;
|
||||
|
||||
SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym);
|
||||
|
||||
Symbol *toSymbol();
|
||||
|
||||
// Eliminate need for dynamic_cast
|
||||
SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; }
|
||||
};
|
||||
|
||||
struct ClassInfoDeclaration : VarDeclaration
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
ClassInfoDeclaration(ClassDeclaration *cd);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
Symbol *toSymbol();
|
||||
|
||||
ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct ModuleInfoDeclaration : VarDeclaration
|
||||
{
|
||||
Module *mod;
|
||||
|
||||
ModuleInfoDeclaration(Module *mod);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
Symbol *toSymbol();
|
||||
};
|
||||
|
||||
struct TypeInfoDeclaration : VarDeclaration
|
||||
{
|
||||
Type *tinfo;
|
||||
|
||||
TypeInfoDeclaration(Type *tinfo, int internal);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
Symbol *toSymbol();
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
virtual void toDt(dt_t **pdt);
|
||||
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
|
||||
|
||||
// LDC
|
||||
virtual void llvmDeclare();
|
||||
virtual void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoStructDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoStructDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoClassDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoClassDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoInterfaceDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoTypedefDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoPointerDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoPointerDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoArrayDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoArrayDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoStaticArrayDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoAssociativeArrayDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoEnumDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoEnumDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoFunctionDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoDelegateDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoTupleDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoTupleDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TypeInfoConstDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoConstDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
|
||||
struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoInvariantDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
|
||||
// LDC
|
||||
void llvmDeclare();
|
||||
void llvmDefine();
|
||||
};
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct ThisDeclaration : VarDeclaration
|
||||
{
|
||||
ThisDeclaration(Type *t);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
};
|
||||
|
||||
enum ILS
|
||||
{
|
||||
ILSuninitialized, // not computed yet
|
||||
ILSno, // cannot inline
|
||||
ILSyes, // can inline
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
#if DMDV2
|
||||
|
||||
enum BUILTIN
|
||||
{
|
||||
BUILTINunknown = -1, // not known if this is a builtin
|
||||
BUILTINnot, // this is not a builtin
|
||||
BUILTINsin, // std.math.sin
|
||||
BUILTINcos, // std.math.cos
|
||||
BUILTINtan, // std.math.tan
|
||||
BUILTINsqrt, // std.math.sqrt
|
||||
BUILTINfabs, // std.math.fabs
|
||||
};
|
||||
|
||||
Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
|
||||
|
||||
#endif
|
||||
|
||||
struct FuncDeclaration : Declaration
|
||||
{
|
||||
Array *fthrows; // Array of Type's of exceptions (not used)
|
||||
Statement *frequire;
|
||||
Statement *fensure;
|
||||
Statement *fbody;
|
||||
|
||||
Identifier *outId; // identifier for out statement
|
||||
VarDeclaration *vresult; // variable corresponding to outId
|
||||
LabelDsymbol *returnLabel; // where the return goes
|
||||
|
||||
DsymbolTable *localsymtab; // used to prevent symbols in different
|
||||
// scopes from having the same name
|
||||
VarDeclaration *vthis; // 'this' parameter (member and nested)
|
||||
VarDeclaration *v_arguments; // '_arguments' parameter
|
||||
#if IN_GCC
|
||||
VarDeclaration *v_argptr; // '_argptr' variable
|
||||
#endif
|
||||
Dsymbols *parameters; // Array of VarDeclaration's for parameters
|
||||
DsymbolTable *labtab; // statement label symbol table
|
||||
Declaration *overnext; // next in overload list
|
||||
Loc endloc; // location of closing curly bracket
|
||||
int vtblIndex; // for member functions, index into vtbl[]
|
||||
int naked; // !=0 if naked
|
||||
int inlineAsm; // !=0 if has inline assembler
|
||||
ILS inlineStatus;
|
||||
int inlineNest; // !=0 if nested inline
|
||||
int cantInterpret; // !=0 if cannot interpret function
|
||||
int semanticRun; // !=0 if semantic3() had been run
|
||||
// this function's frame ptr
|
||||
ForeachStatement *fes; // if foreach body, this is the foreach
|
||||
int introducing; // !=0 if 'introducing' function
|
||||
Type *tintro; // if !=NULL, then this is the type
|
||||
// of the 'introducing' function
|
||||
// this one is overriding
|
||||
int inferRetType; // !=0 if return type is to be inferred
|
||||
Scope *scope; // !=NULL means context to use
|
||||
|
||||
// Things that should really go into Scope
|
||||
int hasReturnExp; // 1 if there's a return exp; statement
|
||||
// 2 if there's a throw statement
|
||||
// 4 if there's an assert(0)
|
||||
// 8 if there's inline asm
|
||||
|
||||
// Support for NRVO (named return value optimization)
|
||||
int nrvo_can; // !=0 means we can do it
|
||||
VarDeclaration *nrvo_var; // variable to replace with shidden
|
||||
Symbol *shidden; // hidden pointer passed to function
|
||||
|
||||
#if DMDV2
|
||||
enum BUILTIN builtin; // set if this is a known, builtin
|
||||
// function we can evaluate at compile
|
||||
// time
|
||||
|
||||
int tookAddressOf; // set if someone took the address of
|
||||
// this function
|
||||
Dsymbols closureVars; // local variables in this function
|
||||
// which are referenced by nested
|
||||
// functions
|
||||
#else
|
||||
int nestedFrameRef; // !=0 if nested variables referenced
|
||||
#endif
|
||||
|
||||
FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int overrides(FuncDeclaration *fd);
|
||||
int findVtblIndex(Array *vtbl, int dim);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
FuncDeclaration *overloadExactMatch(Type *t);
|
||||
FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags = 0);
|
||||
MATCH leastAsSpecialized(FuncDeclaration *g);
|
||||
LabelDsymbol *searchLabel(Identifier *ident);
|
||||
AggregateDeclaration *isThis();
|
||||
AggregateDeclaration *isMember2();
|
||||
int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference
|
||||
void appendExp(Expression *e);
|
||||
void appendState(Statement *s);
|
||||
char *mangle();
|
||||
int isMain();
|
||||
int isWinMain();
|
||||
int isDllMain();
|
||||
enum BUILTIN isBuiltin();
|
||||
int isExport();
|
||||
int isImportedSymbol();
|
||||
int isAbstract();
|
||||
int isCodeseg();
|
||||
int isOverloadable();
|
||||
virtual int isNested();
|
||||
int needThis();
|
||||
virtual int isVirtual();
|
||||
virtual int isFinal();
|
||||
virtual int addPreInvariant();
|
||||
virtual int addPostInvariant();
|
||||
Expression *interpret(InterState *istate, Expressions *arguments);
|
||||
void inlineScan();
|
||||
int canInline(int hasthis, int hdrscan = 0);
|
||||
Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
|
||||
const char *kind();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
FuncDeclaration *isUnique();
|
||||
int needsClosure();
|
||||
|
||||
// LDC: give argument types to runtime functions
|
||||
static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
|
||||
static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
|
||||
|
||||
Symbol *toSymbol();
|
||||
Symbol *toThunkSymbol(int offset); // thunk version
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
void buildClosure(IRState *irs);
|
||||
|
||||
FuncDeclaration *isFuncDeclaration() { return this; }
|
||||
|
||||
// LDC stuff
|
||||
|
||||
// vars declared in this function that nested funcs reference
|
||||
// is this is not empty, nestedFrameRef is set and these VarDecls
|
||||
// probably have nestedref set too, see VarDeclaration::checkNestedReference
|
||||
std::set<VarDeclaration*> nestedVars;
|
||||
|
||||
std::string intrinsicName;
|
||||
|
||||
bool isIntrinsic();
|
||||
bool isVaIntrinsic();
|
||||
|
||||
// we keep our own table of label statements as LabelDsymbolS
|
||||
// don't always carry their corresponding statement along ...
|
||||
typedef std::map<const char*, LabelStatement*> LabelMap;
|
||||
LabelMap labmap;
|
||||
|
||||
// if this is an array operation it gets a little special attention
|
||||
bool isArrayOp;
|
||||
};
|
||||
|
||||
struct FuncAliasDeclaration : FuncDeclaration
|
||||
{
|
||||
FuncDeclaration *funcalias;
|
||||
|
||||
FuncAliasDeclaration(FuncDeclaration *funcalias);
|
||||
|
||||
FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
|
||||
const char *kind();
|
||||
Symbol *toSymbol();
|
||||
};
|
||||
|
||||
struct FuncLiteralDeclaration : FuncDeclaration
|
||||
{
|
||||
enum TOK tok; // TOKfunction or TOKdelegate
|
||||
|
||||
FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
|
||||
ForeachStatement *fes);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
int isNested();
|
||||
int isVirtual();
|
||||
|
||||
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
struct CtorDeclaration : FuncDeclaration
|
||||
{ Arguments *arguments;
|
||||
int varargs;
|
||||
|
||||
CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
CtorDeclaration *isCtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct PostBlitDeclaration : FuncDeclaration
|
||||
{
|
||||
PostBlitDeclaration(Loc loc, Loc endloc);
|
||||
PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct DtorDeclaration : FuncDeclaration
|
||||
{
|
||||
DtorDeclaration(Loc loc, Loc endloc);
|
||||
DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
DtorDeclaration *isDtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StaticCtorDeclaration : FuncDeclaration
|
||||
{
|
||||
StaticCtorDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isStaticConstructor();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StaticDtorDeclaration : FuncDeclaration
|
||||
{ VarDeclaration *vgate; // 'gate' variable
|
||||
|
||||
StaticDtorDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isStaticDestructor();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct InvariantDeclaration : FuncDeclaration
|
||||
{
|
||||
InvariantDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
InvariantDeclaration *isInvariantDeclaration() { return this; }
|
||||
};
|
||||
|
||||
|
||||
struct UnitTestDeclaration : FuncDeclaration
|
||||
{
|
||||
UnitTestDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct NewDeclaration : FuncDeclaration
|
||||
{ Arguments *arguments;
|
||||
int varargs;
|
||||
|
||||
NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
|
||||
NewDeclaration *isNewDeclaration() { return this; }
|
||||
};
|
||||
|
||||
|
||||
struct DeleteDeclaration : FuncDeclaration
|
||||
{ Arguments *arguments;
|
||||
|
||||
DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
int isDelete();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
#ifdef _DH
|
||||
DeleteDeclaration *isDeleteDeclaration() { return this; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* DMD_DECLARATION_H */
|
||||
214
dmd2/delegatize.c
Normal file
214
dmd2/delegatize.c
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "mtype.h"
|
||||
#include "utf.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
|
||||
/********************************************
|
||||
* Convert from expression to delegate that returns the expression,
|
||||
* i.e. convert:
|
||||
* expr
|
||||
* to:
|
||||
* t delegate() { return expr; }
|
||||
*/
|
||||
|
||||
Expression *Expression::toDelegate(Scope *sc, Type *t)
|
||||
{
|
||||
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
|
||||
TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd);
|
||||
FuncLiteralDeclaration *fld =
|
||||
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
|
||||
Expression *e;
|
||||
#if 1
|
||||
sc = sc->push();
|
||||
sc->parent = fld; // set current function to be the delegate
|
||||
e = this;
|
||||
e->scanForNestedRef(sc);
|
||||
sc = sc->pop();
|
||||
#else
|
||||
e = this->syntaxCopy();
|
||||
#endif
|
||||
Statement *s = new ReturnStatement(loc, e);
|
||||
fld->fbody = s;
|
||||
e = new FuncExp(loc, fld);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Perform scanForNestedRef() on an array of Expressions.
|
||||
*/
|
||||
|
||||
void arrayExpressionScanForNestedRef(Scope *sc, Expressions *a)
|
||||
{
|
||||
//printf("arrayExpressionScanForNestedRef(%p)\n", a);
|
||||
if (a)
|
||||
{
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
{ Expression *e = (Expression *)a->data[i];
|
||||
|
||||
if (e)
|
||||
{
|
||||
e->scanForNestedRef(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Expression::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("Expression::scanForNestedRef(%s)\n", toChars());
|
||||
}
|
||||
|
||||
void SymOffExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("SymOffExp::scanForNestedRef(%s)\n", toChars());
|
||||
VarDeclaration *v = var->isVarDeclaration();
|
||||
if (v)
|
||||
v->checkNestedReference(sc, 0);
|
||||
}
|
||||
|
||||
void VarExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("VarExp::scanForNestedRef(%s)\n", toChars());
|
||||
VarDeclaration *v = var->isVarDeclaration();
|
||||
if (v)
|
||||
v->checkNestedReference(sc, 0);
|
||||
}
|
||||
|
||||
void ThisExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
assert(var);
|
||||
var->isVarDeclaration()->checkNestedReference(sc, 0);
|
||||
}
|
||||
|
||||
void SuperExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
ThisExp::scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
void FuncExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("FuncExp::scanForNestedRef(%s)\n", toChars());
|
||||
//fd->parent = sc->parent;
|
||||
}
|
||||
|
||||
void DeclarationExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("DeclarationExp::scanForNestedRef() %s\n", toChars());
|
||||
declaration->parent = sc->parent;
|
||||
}
|
||||
|
||||
void NewExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("NewExp::scanForNestedRef(Scope *sc): %s\n", toChars());
|
||||
|
||||
if (thisexp)
|
||||
thisexp->scanForNestedRef(sc);
|
||||
arrayExpressionScanForNestedRef(sc, newargs);
|
||||
arrayExpressionScanForNestedRef(sc, arguments);
|
||||
}
|
||||
|
||||
void UnaExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
e1->scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
void BinExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
e1->scanForNestedRef(sc);
|
||||
e2->scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
void CallExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
//printf("CallExp::scanForNestedRef(Scope *sc): %s\n", toChars());
|
||||
e1->scanForNestedRef(sc);
|
||||
arrayExpressionScanForNestedRef(sc, arguments);
|
||||
}
|
||||
|
||||
|
||||
void IndexExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
e1->scanForNestedRef(sc);
|
||||
|
||||
if (lengthVar)
|
||||
{ //printf("lengthVar\n");
|
||||
lengthVar->parent = sc->parent;
|
||||
}
|
||||
e2->scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
|
||||
void SliceExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
e1->scanForNestedRef(sc);
|
||||
|
||||
if (lengthVar)
|
||||
{ //printf("lengthVar\n");
|
||||
lengthVar->parent = sc->parent;
|
||||
}
|
||||
if (lwr)
|
||||
lwr->scanForNestedRef(sc);
|
||||
if (upr)
|
||||
upr->scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
|
||||
void ArrayLiteralExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
arrayExpressionScanForNestedRef(sc, elements);
|
||||
}
|
||||
|
||||
|
||||
void AssocArrayLiteralExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
arrayExpressionScanForNestedRef(sc, keys);
|
||||
arrayExpressionScanForNestedRef(sc, values);
|
||||
}
|
||||
|
||||
|
||||
void StructLiteralExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
arrayExpressionScanForNestedRef(sc, elements);
|
||||
}
|
||||
|
||||
|
||||
void TupleExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
arrayExpressionScanForNestedRef(sc, exps);
|
||||
}
|
||||
|
||||
|
||||
void ArrayExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
e1->scanForNestedRef(sc);
|
||||
arrayExpressionScanForNestedRef(sc, arguments);
|
||||
}
|
||||
|
||||
|
||||
void CondExp::scanForNestedRef(Scope *sc)
|
||||
{
|
||||
econd->scanForNestedRef(sc);
|
||||
e1->scanForNestedRef(sc);
|
||||
e2->scanForNestedRef(sc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
2028
dmd2/doc.c
Normal file
2028
dmd2/doc.c
Normal file
File diff suppressed because it is too large
Load Diff
19
dmd2/doc.h
Normal file
19
dmd2/doc.h
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
// 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_DOC_H
|
||||
#define DMD_DOC_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
|
||||
#endif
|
||||
1172
dmd2/dsymbol.c
Normal file
1172
dmd2/dsymbol.c
Normal file
File diff suppressed because it is too large
Load Diff
325
dmd2/dsymbol.h
Normal file
325
dmd2/dsymbol.h
Normal file
@@ -0,0 +1,325 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_DSYMBOL_H
|
||||
#define DMD_DSYMBOL_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "arraytypes.h"
|
||||
|
||||
// llvm
|
||||
#include "../ir/irsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Scope;
|
||||
struct DsymbolTable;
|
||||
struct Declaration;
|
||||
struct TupleDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct AliasDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct StructDeclaration;
|
||||
struct UnionDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct FuncAliasDeclaration;
|
||||
struct FuncLiteralDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct AttribDeclaration;
|
||||
struct Symbol;
|
||||
struct Package;
|
||||
struct Module;
|
||||
struct Import;
|
||||
struct Type;
|
||||
struct TypeTuple;
|
||||
struct WithStatement;
|
||||
struct LabelDsymbol;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct TemplateMixin;
|
||||
struct EnumMember;
|
||||
struct ScopeDsymbol;
|
||||
struct WithScopeSymbol;
|
||||
struct ArrayScopeSymbol;
|
||||
struct SymbolDeclaration;
|
||||
struct Expression;
|
||||
struct DeleteDeclaration;
|
||||
struct HdrGenState;
|
||||
struct OverloadSet;
|
||||
struct TypeInfoDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
|
||||
#if IN_GCC
|
||||
union tree_node;
|
||||
typedef union tree_node TYPE;
|
||||
#else
|
||||
struct TYPE;
|
||||
#endif
|
||||
|
||||
// llvm
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum PROT
|
||||
{
|
||||
PROTundefined,
|
||||
PROTnone, // no access
|
||||
PROTprivate,
|
||||
PROTpackage,
|
||||
PROTprotected,
|
||||
PROTpublic,
|
||||
PROTexport,
|
||||
};
|
||||
|
||||
|
||||
struct Dsymbol : Object
|
||||
{
|
||||
Identifier *ident;
|
||||
Identifier *c_ident;
|
||||
Dsymbol *parent;
|
||||
Symbol *csym; // symbol for code generator
|
||||
Symbol *isym; // import version of csym
|
||||
unsigned char *comment; // documentation comment for this Dsymbol
|
||||
Loc loc; // where defined
|
||||
|
||||
Dsymbol();
|
||||
Dsymbol(Identifier *);
|
||||
char *toChars();
|
||||
char *toPrettyChars();
|
||||
char *locToChars();
|
||||
int equals(Object *o);
|
||||
int isAnonymous();
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void error(const char *format, ...);
|
||||
void checkDeprecated(Loc loc, Scope *sc);
|
||||
Module *getModule();
|
||||
Dsymbol *pastMixin();
|
||||
Dsymbol *toParent();
|
||||
Dsymbol *toParent2();
|
||||
TemplateInstance *inTemplateInstance();
|
||||
|
||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||
|
||||
static Array *arraySyntaxCopy(Array *a);
|
||||
|
||||
virtual const char *kind();
|
||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void semantic(Scope *sc);
|
||||
virtual void semantic2(Scope *sc);
|
||||
virtual void semantic3(Scope *sc);
|
||||
virtual void inlineScan();
|
||||
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
|
||||
virtual int overloadInsert(Dsymbol *s);
|
||||
#ifdef _DH
|
||||
char *toHChars();
|
||||
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#endif
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual void toDocBuffer(OutBuffer *buf);
|
||||
virtual unsigned size(Loc loc);
|
||||
virtual int isforwardRef();
|
||||
virtual void defineRef(Dsymbol *s);
|
||||
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
|
||||
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
|
||||
virtual int isExport(); // is Dsymbol exported?
|
||||
virtual int isImportedSymbol(); // is Dsymbol imported?
|
||||
virtual int isDeprecated(); // is Dsymbol deprecated?
|
||||
virtual int isOverloadable();
|
||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||
virtual Type *getType(); // is this a type?
|
||||
virtual char *mangle();
|
||||
virtual int needThis(); // need a 'this' pointer?
|
||||
virtual enum PROT prot();
|
||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
virtual int oneMember(Dsymbol **ps);
|
||||
static int oneMembers(Array *members, Dsymbol **ps);
|
||||
virtual int hasPointers();
|
||||
virtual void addLocalClass(ClassDeclarations *) { }
|
||||
virtual void checkCtorConstInit() { }
|
||||
|
||||
virtual void addComment(unsigned char *comment);
|
||||
virtual void emitComment(Scope *sc);
|
||||
void emitDitto(Scope *sc);
|
||||
|
||||
// Backend
|
||||
|
||||
virtual Symbol *toSymbol(); // to backend symbol
|
||||
virtual void toObjFile(int multiobj); // compile to .obj file
|
||||
virtual int cvMember(unsigned char *p); // emit cv debug info for member
|
||||
|
||||
Symbol *toImport(); // to backend import symbol
|
||||
static Symbol *toImport(Symbol *s); // to backend import symbol
|
||||
|
||||
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
|
||||
|
||||
// Eliminate need for dynamic_cast
|
||||
virtual Package *isPackage() { return NULL; }
|
||||
virtual Module *isModule() { return NULL; }
|
||||
virtual EnumMember *isEnumMember() { return NULL; }
|
||||
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
|
||||
virtual TemplateInstance *isTemplateInstance() { return NULL; }
|
||||
virtual TemplateMixin *isTemplateMixin() { return NULL; }
|
||||
virtual Declaration *isDeclaration() { return NULL; }
|
||||
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
|
||||
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
|
||||
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
|
||||
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
|
||||
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
|
||||
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
|
||||
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
|
||||
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
|
||||
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
|
||||
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
|
||||
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
|
||||
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
|
||||
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
|
||||
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
|
||||
virtual NewDeclaration *isNewDeclaration() { return NULL; }
|
||||
virtual VarDeclaration *isVarDeclaration() { return NULL; }
|
||||
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
|
||||
virtual StructDeclaration *isStructDeclaration() { return NULL; }
|
||||
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
|
||||
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
|
||||
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
|
||||
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
|
||||
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
|
||||
virtual Import *isImport() { return NULL; }
|
||||
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
|
||||
#ifdef _DH
|
||||
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
|
||||
#endif
|
||||
virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
|
||||
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
|
||||
virtual OverloadSet *isOverloadSet() { return NULL; }
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
|
||||
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
||||
|
||||
// llvm stuff
|
||||
int llvmInternal;
|
||||
|
||||
IrDsymbol ir;
|
||||
};
|
||||
|
||||
// Dsymbol that generates a scope
|
||||
|
||||
struct ScopeDsymbol : Dsymbol
|
||||
{
|
||||
Array *members; // all Dsymbol's in this scope
|
||||
DsymbolTable *symtab; // members[] sorted into table
|
||||
|
||||
Array *imports; // imported ScopeDsymbol's
|
||||
unsigned char *prots; // PROT for each import
|
||||
|
||||
ScopeDsymbol();
|
||||
ScopeDsymbol(Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void importScope(ScopeDsymbol *s, enum PROT protection);
|
||||
int isforwardRef();
|
||||
void defineRef(Dsymbol *s);
|
||||
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
|
||||
Dsymbol *nameCollision(Dsymbol *s);
|
||||
const char *kind();
|
||||
FuncDeclaration *findGetMembers();
|
||||
|
||||
void emitMemberComments(Scope *sc);
|
||||
|
||||
static size_t dim(Array *members);
|
||||
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
|
||||
|
||||
ScopeDsymbol *isScopeDsymbol() { return this; }
|
||||
};
|
||||
|
||||
// With statement scope
|
||||
|
||||
struct WithScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
WithStatement *withstate;
|
||||
|
||||
WithScopeSymbol(WithStatement *withstate);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
WithScopeSymbol *isWithScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Array Index/Slice scope
|
||||
|
||||
struct ArrayScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
Expression *exp; // IndexExp or SliceExp
|
||||
TypeTuple *type; // for tuple[length]
|
||||
TupleDeclaration *td; // for tuples of objects
|
||||
Scope *sc;
|
||||
|
||||
ArrayScopeSymbol(Scope *sc, Expression *e);
|
||||
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
|
||||
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Overload Sets
|
||||
|
||||
struct OverloadSet : Dsymbol
|
||||
{
|
||||
Dsymbols a; // array of Dsymbols
|
||||
|
||||
OverloadSet();
|
||||
void push(Dsymbol *s);
|
||||
OverloadSet *isOverloadSet() { return this; }
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
// Table of Dsymbol's
|
||||
|
||||
struct DsymbolTable : Object
|
||||
{
|
||||
StringTable *tab;
|
||||
|
||||
DsymbolTable();
|
||||
~DsymbolTable();
|
||||
|
||||
// Look up Identifier. Return Dsymbol if found, NULL if not.
|
||||
Dsymbol *lookup(Identifier *ident);
|
||||
|
||||
// Insert Dsymbol in table. Return NULL if already there.
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
|
||||
Dsymbol *update(Dsymbol *s);
|
||||
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
|
||||
};
|
||||
|
||||
#endif /* DMD_DSYMBOL_H */
|
||||
144
dmd2/dump.c
Normal file
144
dmd2/dump.c
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
// 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.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "expression.h"
|
||||
#include "template.h"
|
||||
|
||||
static void indent(int indent)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < indent; i++)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static char *type_print(Type *type)
|
||||
{
|
||||
return type ? type->toChars() : (char *) "null";
|
||||
}
|
||||
|
||||
void dumpExpressions(int i, Expressions *exps)
|
||||
{
|
||||
for (size_t j = 0; j < exps->dim; j++)
|
||||
{ Expression *e = (Expression *)exps->data[j];
|
||||
indent(i);
|
||||
printf("(\n");
|
||||
e->dump(i + 2);
|
||||
indent(i);
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Expression::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type));
|
||||
}
|
||||
|
||||
void IntegerExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %lld type=%s\n", this, (intmax_t)value, type_print(type));
|
||||
}
|
||||
|
||||
void IdentifierExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type));
|
||||
}
|
||||
|
||||
void DsymbolExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s\n", this, s->toChars(), type_print(type));
|
||||
}
|
||||
|
||||
void VarExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type));
|
||||
}
|
||||
|
||||
void UnaExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
}
|
||||
|
||||
void CallExp::dump(int i)
|
||||
{
|
||||
UnaExp::dump(i);
|
||||
dumpExpressions(i, arguments);
|
||||
}
|
||||
|
||||
void SliceExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
if (lwr)
|
||||
lwr->dump(i + 2);
|
||||
if (upr)
|
||||
upr->dump(i + 2);
|
||||
}
|
||||
|
||||
void DotIdExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
}
|
||||
|
||||
void DotVarExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
}
|
||||
|
||||
void DotTemplateInstanceExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
}
|
||||
|
||||
void DelegateExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
}
|
||||
|
||||
void BinExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
if (e2)
|
||||
e2->dump(i + 2);
|
||||
}
|
||||
|
||||
|
||||
4679
dmd2/e2ir.c.nolink
Normal file
4679
dmd2/e2ir.c.nolink
Normal file
File diff suppressed because it is too large
Load Diff
1366
dmd2/entity.c
Normal file
1366
dmd2/entity.c
Normal file
File diff suppressed because it is too large
Load Diff
392
dmd2/enum.c
Normal file
392
dmd2/enum.c
Normal file
@@ -0,0 +1,392 @@
|
||||
|
||||
// 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 <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "enum.h"
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "expression.h"
|
||||
#include "module.h"
|
||||
#include "declaration.h"
|
||||
|
||||
/********************************* EnumDeclaration ****************************/
|
||||
|
||||
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
|
||||
: ScopeDsymbol(id)
|
||||
{
|
||||
this->loc = loc;
|
||||
type = new TypeEnum(this);
|
||||
this->memtype = memtype;
|
||||
maxval = NULL;
|
||||
minval = NULL;
|
||||
defaultval = NULL;
|
||||
sinit = NULL;
|
||||
scope = NULL;
|
||||
isdeprecated = 0;
|
||||
}
|
||||
|
||||
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
Type *t = NULL;
|
||||
if (memtype)
|
||||
t = memtype->syntaxCopy();
|
||||
|
||||
EnumDeclaration *ed;
|
||||
if (s)
|
||||
{ ed = (EnumDeclaration *)s;
|
||||
ed->memtype = t;
|
||||
}
|
||||
else
|
||||
ed = new EnumDeclaration(loc, ident, t);
|
||||
ScopeDsymbol::syntaxCopy(ed);
|
||||
return ed;
|
||||
}
|
||||
|
||||
void EnumDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
Type *t;
|
||||
Scope *sce;
|
||||
|
||||
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
|
||||
//printf("EnumDeclaration::semantic() %s\n", toChars());
|
||||
if (!members) // enum ident;
|
||||
return;
|
||||
|
||||
if (!memtype && !isAnonymous())
|
||||
{ // Set memtype if we can to reduce fwd reference errors
|
||||
memtype = Type::tint32; // case 1) enum ident { ... }
|
||||
}
|
||||
|
||||
if (symtab) // if already done
|
||||
{ if (!scope)
|
||||
return; // semantic() already completed
|
||||
}
|
||||
else
|
||||
symtab = new DsymbolTable();
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
scx = scope; // save so we don't make redundant copies
|
||||
scope = NULL;
|
||||
}
|
||||
|
||||
if (sc->stc & STCdeprecated)
|
||||
isdeprecated = 1;
|
||||
|
||||
parent = sc->parent;
|
||||
|
||||
/* The separate, and distinct, cases are:
|
||||
* 1. enum { ... }
|
||||
* 2. enum : memtype { ... }
|
||||
* 3. enum ident { ... }
|
||||
* 4. enum ident : memtype { ... }
|
||||
*/
|
||||
|
||||
if (memtype)
|
||||
{
|
||||
memtype = memtype->semantic(loc, sc);
|
||||
|
||||
/* Check to see if memtype is forward referenced
|
||||
*/
|
||||
if (memtype->ty == Tenum)
|
||||
{ EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
|
||||
if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
|
||||
{ // memtype is forward referenced, so try again later
|
||||
scope = scx ? scx : new Scope(*sc);
|
||||
scope->setNoFree();
|
||||
scope->module->addDeferredSemantic(this);
|
||||
printf("\tdeferring %s\n", toChars());
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if 0 // Decided to abandon this restriction for D 2.0
|
||||
if (!memtype->isintegral())
|
||||
{ error("base type must be of integral type, not %s", memtype->toChars());
|
||||
memtype = Type::tint32;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
if (isAnonymous())
|
||||
sce = sc;
|
||||
else
|
||||
{ sce = sc->push(this);
|
||||
sce->parent = this;
|
||||
}
|
||||
if (members->dim == 0)
|
||||
error("enum %s must have at least one member", toChars());
|
||||
int first = 1;
|
||||
Expression *elast = NULL;
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
|
||||
Expression *e;
|
||||
|
||||
if (!em)
|
||||
/* The e->semantic(sce) can insert other symbols, such as
|
||||
* template instances and function literals.
|
||||
*/
|
||||
continue;
|
||||
|
||||
//printf(" Enum member '%s'\n",em->toChars());
|
||||
if (em->type)
|
||||
em->type = em->type->semantic(em->loc, sce);
|
||||
e = em->value;
|
||||
if (e)
|
||||
{
|
||||
assert(e->dyncast() == DYNCAST_EXPRESSION);
|
||||
e = e->semantic(sce);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (memtype)
|
||||
{
|
||||
e = e->implicitCastTo(sce, memtype);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
t = memtype;
|
||||
}
|
||||
else if (em->type)
|
||||
{
|
||||
e = e->implicitCastTo(sce, em->type);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
assert(isAnonymous());
|
||||
t = e->type;
|
||||
}
|
||||
else
|
||||
t = e->type;
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
if (memtype)
|
||||
t = memtype;
|
||||
else if (em->type)
|
||||
t = em->type;
|
||||
else
|
||||
t = Type::tint32;
|
||||
e = new IntegerExp(em->loc, 0, Type::tint32);
|
||||
e = e->implicitCastTo(sce, t);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set value to (elast + 1).
|
||||
// But first check that (elast != t.max)
|
||||
assert(elast);
|
||||
e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
|
||||
e = e->semantic(sce);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->toInteger())
|
||||
error("overflow of enum value %s", elast->toChars());
|
||||
|
||||
// Now set e to (elast + 1)
|
||||
e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
|
||||
e = e->semantic(sce);
|
||||
e = e->castTo(sce, elast->type);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
}
|
||||
elast = e;
|
||||
em->value = e;
|
||||
|
||||
// Add to symbol table only after evaluating 'value'
|
||||
if (isAnonymous())
|
||||
{
|
||||
/* Anonymous enum members get added to enclosing scope.
|
||||
*/
|
||||
for (Scope *scx = sce; scx; scx = scx->enclosing)
|
||||
{
|
||||
if (scx->scopesym)
|
||||
{
|
||||
if (!scx->scopesym->symtab)
|
||||
scx->scopesym->symtab = new DsymbolTable();
|
||||
em->addMember(sce, scx->scopesym, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
em->addMember(sc, this, 1);
|
||||
|
||||
/* Compute .min, .max and .default values.
|
||||
* If enum doesn't have a name, we can never identify the enum type,
|
||||
* so there is no purpose for a .min, .max or .default
|
||||
*/
|
||||
if (!isAnonymous())
|
||||
{
|
||||
if (first)
|
||||
{ defaultval = e;
|
||||
minval = e;
|
||||
maxval = e;
|
||||
}
|
||||
else
|
||||
{ Expression *ec;
|
||||
|
||||
/* In order to work successfully with UDTs,
|
||||
* build expressions to do the comparisons,
|
||||
* and let the semantic analyzer and constant
|
||||
* folder give us the result.
|
||||
*/
|
||||
|
||||
// Compute if(e < minval)
|
||||
ec = new CmpExp(TOKlt, em->loc, e, minval);
|
||||
ec = ec->semantic(sce);
|
||||
ec = ec->optimize(WANTvalue | WANTinterpret);
|
||||
if (ec->toInteger())
|
||||
minval = e;
|
||||
|
||||
ec = new CmpExp(TOKgt, em->loc, e, maxval);
|
||||
ec = ec->semantic(sce);
|
||||
ec = ec->optimize(WANTvalue | WANTinterpret);
|
||||
if (ec->toInteger())
|
||||
maxval = e;
|
||||
}
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
//printf("defaultval = %lld\n", defaultval);
|
||||
|
||||
//if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
|
||||
if (sc != sce)
|
||||
sce->pop();
|
||||
//members->print();
|
||||
}
|
||||
|
||||
int EnumDeclaration::oneMember(Dsymbol **ps)
|
||||
{
|
||||
if (isAnonymous())
|
||||
return Dsymbol::oneMembers(members, ps);
|
||||
return Dsymbol::oneMember(ps);
|
||||
}
|
||||
|
||||
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ int i;
|
||||
|
||||
buf->writestring("enum ");
|
||||
if (ident)
|
||||
{ buf->writestring(ident->toChars());
|
||||
buf->writeByte(' ');
|
||||
}
|
||||
if (memtype)
|
||||
{
|
||||
buf->writestring(": ");
|
||||
memtype->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
if (!members)
|
||||
{
|
||||
buf->writeByte(';');
|
||||
buf->writenl();
|
||||
return;
|
||||
}
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
|
||||
if (!em)
|
||||
continue;
|
||||
//buf->writestring(" ");
|
||||
em->toCBuffer(buf, hgs);
|
||||
buf->writeByte(',');
|
||||
buf->writenl();
|
||||
}
|
||||
buf->writeByte('}');
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
Type *EnumDeclaration::getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
const char *EnumDeclaration::kind()
|
||||
{
|
||||
return "enum";
|
||||
}
|
||||
|
||||
int EnumDeclaration::isDeprecated()
|
||||
{
|
||||
return isdeprecated;
|
||||
}
|
||||
|
||||
Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
|
||||
if (scope)
|
||||
// Try one last time to resolve this enum
|
||||
semantic(scope);
|
||||
|
||||
if (!members || !symtab || scope)
|
||||
{ error("is forward referenced when looking for '%s'", ident->toChars());
|
||||
//*(char*)0=0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
|
||||
return s;
|
||||
}
|
||||
|
||||
/********************************* EnumMember ****************************/
|
||||
|
||||
EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
|
||||
: Dsymbol(id)
|
||||
{
|
||||
this->value = value;
|
||||
this->type = type;
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
Expression *e = NULL;
|
||||
if (value)
|
||||
e = value->syntaxCopy();
|
||||
|
||||
Type *t = NULL;
|
||||
if (type)
|
||||
t = type->syntaxCopy();
|
||||
|
||||
EnumMember *em;
|
||||
if (s)
|
||||
{ em = (EnumMember *)s;
|
||||
em->loc = loc;
|
||||
em->value = e;
|
||||
em->type = t;
|
||||
}
|
||||
else
|
||||
em = new EnumMember(loc, ident, e, t);
|
||||
return em;
|
||||
}
|
||||
|
||||
void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (type)
|
||||
type->toCBuffer(buf, ident, hgs);
|
||||
else
|
||||
buf->writestring(ident->toChars());
|
||||
if (value)
|
||||
{
|
||||
buf->writestring(" = ");
|
||||
value->toCBuffer(buf, hgs);
|
||||
}
|
||||
}
|
||||
|
||||
const char *EnumMember::kind()
|
||||
{
|
||||
return "enum member";
|
||||
}
|
||||
|
||||
|
||||
90
dmd2/enum.h
Normal file
90
dmd2/enum.h
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_ENUM_H
|
||||
#define DMD_ENUM_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct Expression;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
|
||||
struct EnumDeclaration : ScopeDsymbol
|
||||
{ /* enum ident : memtype { ... }
|
||||
*/
|
||||
Type *type; // the TypeEnum
|
||||
Type *memtype; // type of the members
|
||||
|
||||
#if DMDV1
|
||||
integer_t maxval;
|
||||
integer_t minval;
|
||||
integer_t defaultval; // default initializer
|
||||
#else
|
||||
Expression *maxval;
|
||||
Expression *minval;
|
||||
Expression *defaultval; // default initializer
|
||||
|
||||
Scope *scope; // !=NULL means context to use
|
||||
#endif
|
||||
int isdeprecated;
|
||||
|
||||
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Type *getType();
|
||||
const char *kind();
|
||||
#if DMDV2
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#endif
|
||||
int isDeprecated(); // is Dsymbol deprecated?
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumDeclaration *isEnumDeclaration() { return this; }
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
int cvMember(unsigned char *p);
|
||||
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
};
|
||||
|
||||
|
||||
struct EnumMember : Dsymbol
|
||||
{
|
||||
Expression *value;
|
||||
Type *type;
|
||||
|
||||
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumMember *isEnumMember() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_ENUM_H */
|
||||
9684
dmd2/expression.c
Normal file
9684
dmd2/expression.c
Normal file
File diff suppressed because it is too large
Load Diff
1609
dmd2/expression.h
Normal file
1609
dmd2/expression.h
Normal file
File diff suppressed because it is too large
Load Diff
3081
dmd2/func.c
Normal file
3081
dmd2/func.c
Normal file
File diff suppressed because it is too large
Load Diff
55
dmd2/gnuc.c
Normal file
55
dmd2/gnuc.c
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// Put functions in here missing from gnu C
|
||||
|
||||
#include "gnuc.h"
|
||||
|
||||
int memicmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{ char c1 = s1[i];
|
||||
char c2 = s2[i];
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
if ('A' <= c1 && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
if ('A' <= c2 && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (;;)
|
||||
{ char c1 = *s1;
|
||||
char c2 = *s2;
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
if ('A' <= c1 && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
if ('A' <= c2 && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if (!c1)
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
8
dmd2/gnuc.h
Normal file
8
dmd2/gnuc.h
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#ifndef _GNUC_H
|
||||
#define _GNUC_H 1
|
||||
|
||||
int memicmp(const char *s1, const char *s2, int n);
|
||||
int stricmp(const char *s1, const char *s2);
|
||||
|
||||
#endif
|
||||
248
dmd2/gpl.txt
Normal file
248
dmd2/gpl.txt
Normal file
@@ -0,0 +1,248 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 1, February 1989
|
||||
|
||||
Copyright (C) 1989 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The license agreements of most software companies try to keep users
|
||||
at the mercy of those companies. By contrast, our General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. The
|
||||
General Public License applies to the Free Software Foundation's
|
||||
software and to any other program whose authors commit to using it.
|
||||
You can use it for your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Specifically, the General Public License is designed to make
|
||||
sure that you have the freedom to give away or sell copies of free
|
||||
software, that you receive source code or can get it if you want it,
|
||||
that you can change the software or use pieces of it in new free
|
||||
programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of a such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must tell them their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any program or other work which
|
||||
contains a notice placed by the copyright holder saying it may be
|
||||
distributed under the terms of this General Public License. The
|
||||
"Program", below, refers to any such program or work, and a "work based
|
||||
on the Program" means either the Program or any work containing the
|
||||
Program or a portion of it, either verbatim or with modifications. Each
|
||||
licensee is addressed as "you".
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source
|
||||
code as you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and
|
||||
disclaimer of warranty; keep intact all the notices that refer to this
|
||||
General Public License and to the absence of any warranty; and give any
|
||||
other recipients of the Program a copy of this General Public License
|
||||
along with the Program. You may charge a fee for the physical act of
|
||||
transferring a copy.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of
|
||||
it, and copy and distribute such modifications under the terms of Paragraph
|
||||
1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating that
|
||||
you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish, that
|
||||
in whole or in part contains the Program or any part thereof, either
|
||||
with or without modifications, to be licensed at no charge to all
|
||||
third parties under the terms of this General Public License (except
|
||||
that you may choose to grant warranty protection to some or all
|
||||
third parties, at your option).
|
||||
|
||||
c) If the modified program normally reads commands interactively when
|
||||
run, you must cause it, when started running for such interactive use
|
||||
in the simplest and most usual way, to print or display an
|
||||
announcement including an appropriate copyright notice and a notice
|
||||
that there is no warranty (or else, saying that you provide a
|
||||
warranty) and that users may redistribute the program under these
|
||||
conditions, and telling the user how to view a copy of this General
|
||||
Public License.
|
||||
|
||||
d) You may charge a fee for the physical act of transferring a
|
||||
copy, and you may at your option offer warranty protection in
|
||||
exchange for a fee.
|
||||
|
||||
Mere aggregation of another independent work with the Program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other work under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute the Program (or a portion or derivative of
|
||||
it, under Paragraph 2) in object code or executable form under the terms of
|
||||
Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal charge
|
||||
for the cost of distribution) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
Source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable file, complete source code means
|
||||
all the source code for all modules it contains; but, as a special
|
||||
exception, it need not include source code for modules which are standard
|
||||
libraries that accompany the operating system on which the executable
|
||||
file runs, or for standard header files or definitions files that
|
||||
accompany that operating system.
|
||||
|
||||
4. You may not copy, modify, sublicense, distribute or transfer the
|
||||
Program except as expressly provided under this General Public License.
|
||||
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
|
||||
the Program is void, and will automatically terminate your rights to use
|
||||
the Program under this License. However, parties who have received
|
||||
copies, or rights to use copies, from you under this General Public
|
||||
License will not have their licenses terminated so long as such parties
|
||||
remain in full compliance.
|
||||
|
||||
5. By copying, distributing or modifying the Program (or any work based
|
||||
on the Program) you indicate your acceptance of this license to do so,
|
||||
and all its terms and conditions.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the original
|
||||
licensor to copy, distribute or modify the Program subject to these
|
||||
terms and conditions. You may not impose any further restrictions on the
|
||||
recipients' exercise of the rights granted herein.
|
||||
|
||||
7. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of the license which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
the license, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
8. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to humanity, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively convey
|
||||
the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19xx name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the
|
||||
appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than `show w' and `show
|
||||
c'; they could even be mouse-clicks or menu items--whatever suits your
|
||||
program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
program `Gnomovision' (a program to direct compilers to make passes
|
||||
at assemblers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
114
dmd2/hdrgen.c
Normal file
114
dmd2/hdrgen.c
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// Initial header generation implementation by Dave Fladebo
|
||||
// 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.
|
||||
|
||||
// Routines to emit header files
|
||||
|
||||
#ifdef _DH
|
||||
|
||||
#define PRETTY_PRINT
|
||||
#define TEST_EMIT_ALL 0 // For Testing
|
||||
|
||||
#define LOG 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#if __DMC__
|
||||
#include <complex.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#else
|
||||
#if _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif POSIX
|
||||
#include "../root/mem.h"
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
|
||||
#include "attrib.h"
|
||||
#include "cond.h"
|
||||
#include "enum.h"
|
||||
#include "import.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#include "staticassert.h"
|
||||
#include "template.h"
|
||||
#include "utf.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "mtype.h"
|
||||
#include "hdrgen.h"
|
||||
|
||||
void argsToCBuffer(OutBuffer *buf, Array *arguments, HdrGenState *hgs);
|
||||
|
||||
void Module::genhdrfile()
|
||||
{
|
||||
OutBuffer hdrbufr;
|
||||
|
||||
hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars());
|
||||
hdrbufr.writenl();
|
||||
|
||||
HdrGenState hgs;
|
||||
memset(&hgs, 0, sizeof(hgs));
|
||||
hgs.hdrgen = 1;
|
||||
|
||||
toCBuffer(&hdrbufr, &hgs);
|
||||
|
||||
// Transfer image to file
|
||||
hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset);
|
||||
hdrbufr.data = NULL;
|
||||
|
||||
char *pt = FileName::path(hdrfile->toChars());
|
||||
if (*pt)
|
||||
FileName::ensurePathExists(pt);
|
||||
mem.free(pt);
|
||||
hdrfile->writev();
|
||||
}
|
||||
|
||||
|
||||
void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (md)
|
||||
{
|
||||
buf->writestring("module ");
|
||||
buf->writestring(md->toChars());
|
||||
buf->writebyte(';');
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
|
||||
s->toHBuffer(buf, hgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
toCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
|
||||
/*************************************/
|
||||
|
||||
#endif // #ifdef _DH
|
||||
34
dmd2/hdrgen.h
Normal file
34
dmd2/hdrgen.h
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// initial header generation implementation by Dave Fladebo
|
||||
// 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.
|
||||
|
||||
|
||||
struct HdrGenState
|
||||
{
|
||||
int hdrgen; // 1 if generating header file
|
||||
int ddoc; // 1 if generating Ddoc file
|
||||
int console; // 1 if writing to console
|
||||
int tpltMember;
|
||||
int inCallExp;
|
||||
int inPtrExp;
|
||||
int inSlcExp;
|
||||
int inDotExp;
|
||||
int inBinExp;
|
||||
int inArrExp;
|
||||
int emitInst;
|
||||
struct
|
||||
{
|
||||
int init;
|
||||
int decl;
|
||||
} FLinit;
|
||||
|
||||
HdrGenState() { memset(this, 0, sizeof(HdrGenState)); }
|
||||
};
|
||||
|
||||
|
||||
718
dmd2/html.c
Normal file
718
dmd2/html.c
Normal file
@@ -0,0 +1,718 @@
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
/* HTML parser
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "html.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "root.h"
|
||||
|
||||
extern int HtmlNamedEntity(unsigned char *p, int length);
|
||||
|
||||
static int isLineSeparator(const unsigned char* p);
|
||||
|
||||
/**********************************
|
||||
* Determine if beginning of tag identifier
|
||||
* or a continuation of a tag identifier.
|
||||
*/
|
||||
|
||||
inline int istagstart(int c)
|
||||
{
|
||||
return (isalpha(c) || c == '_');
|
||||
}
|
||||
|
||||
inline int istag(int c)
|
||||
{
|
||||
return (isalnum(c) || c == '_');
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
Html::Html(const char *sourcename, unsigned char *base, unsigned length)
|
||||
{
|
||||
//printf("Html::Html()\n");
|
||||
this->sourcename = sourcename;
|
||||
this->base = base;
|
||||
p = base;
|
||||
end = base + length;
|
||||
linnum = 1;
|
||||
dbuf = NULL;
|
||||
inCode = 0;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Print error & quit.
|
||||
*/
|
||||
|
||||
void Html::error(const char *format, ...)
|
||||
{
|
||||
if (!global.gag)
|
||||
{
|
||||
printf("%s(%d) : HTML Error: ", sourcename, linnum);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
global.errors++;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Extract all the code from an HTML file,
|
||||
* concatenate it all together, and store in buf.
|
||||
*/
|
||||
|
||||
void Html::extractCode(OutBuffer *buf)
|
||||
{
|
||||
//printf("Html::extractCode()\n");
|
||||
dbuf = buf; // save for other routines
|
||||
buf->reserve(end - p);
|
||||
inCode = 0;
|
||||
while (1)
|
||||
{
|
||||
//printf("p = %p, *p = x%x\n", p, *p);
|
||||
switch (*p)
|
||||
{
|
||||
#if 0 // strings are not recognized outside of tags
|
||||
case '"':
|
||||
case '\'':
|
||||
skipString();
|
||||
continue;
|
||||
#endif
|
||||
case '<':
|
||||
if (p[1] == '!' && isCommentStart())
|
||||
{ // Comments start with <!--
|
||||
scanComment();
|
||||
}
|
||||
else if(p[1] == '!' && isCDATAStart())
|
||||
{
|
||||
scanCDATA();
|
||||
}
|
||||
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
|
||||
skipTag();
|
||||
else if (istagstart(*skipWhite(p + 1)))
|
||||
skipTag();
|
||||
else
|
||||
goto Ldefault;
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
case 0x1a:
|
||||
break; // end of file
|
||||
|
||||
case '&':
|
||||
if (inCode)
|
||||
{ // Translate character entity into ascii for D parser
|
||||
int c;
|
||||
|
||||
c = charEntity();
|
||||
buf->writeUTF8(c);
|
||||
}
|
||||
else
|
||||
p++;
|
||||
continue;
|
||||
|
||||
case '\r':
|
||||
if (p[1] == '\n')
|
||||
goto Ldefault;
|
||||
case '\n':
|
||||
linnum++;
|
||||
// Always extract new lines, so that D lexer counts the
|
||||
// lines right.
|
||||
buf->writeByte(*p);
|
||||
p++;
|
||||
continue;
|
||||
|
||||
default:
|
||||
Ldefault:
|
||||
if (inCode)
|
||||
buf->writeByte(*p);
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
buf->writeByte(0); // ending sentinel
|
||||
//printf("D code is: '%s'\n", (char *)buf->data);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Scan to end of <> tag.
|
||||
* Look for <code> and </code> tags to start/stop D processing.
|
||||
* Input:
|
||||
* p is on opening '<' of tag; it's already verified that
|
||||
* it's a tag by lookahead
|
||||
* Output:
|
||||
* p is past closing '>' of tag
|
||||
*/
|
||||
|
||||
void Html::skipTag()
|
||||
{
|
||||
enum TagState // what parsing state we're in
|
||||
{
|
||||
TStagstart, // start of tag name
|
||||
TStag, // in a tag name
|
||||
TSrest, // following tag name
|
||||
};
|
||||
enum TagState state = TStagstart;
|
||||
int inot;
|
||||
unsigned char *tagstart = NULL;
|
||||
int taglen = 0;
|
||||
|
||||
p++;
|
||||
inot = 0;
|
||||
if (*p == '/')
|
||||
{ inot = 1;
|
||||
p++;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '>': // found end of tag
|
||||
p++;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
state = TSrest;
|
||||
skipString();
|
||||
continue;
|
||||
|
||||
case '<':
|
||||
if (p[1] == '!' && isCommentStart())
|
||||
{ // Comments start with <!--
|
||||
scanComment();
|
||||
}
|
||||
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
|
||||
{ error("nested tag");
|
||||
skipTag();
|
||||
}
|
||||
else if (istagstart(*skipWhite(p + 1)))
|
||||
{ error("nested tag");
|
||||
skipTag();
|
||||
}
|
||||
// Treat comments as if they were whitespace
|
||||
state = TSrest;
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
case 0x1a:
|
||||
error("end of file before end of tag");
|
||||
break; // end of file
|
||||
|
||||
case '\r':
|
||||
if (p[1] == '\n')
|
||||
goto Ldefault;
|
||||
case '\n':
|
||||
linnum++;
|
||||
// Always extract new lines, so that code lexer counts the
|
||||
// lines right.
|
||||
dbuf->writeByte(*p);
|
||||
state = TSrest; // end of tag
|
||||
p++;
|
||||
continue;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
case '\v':
|
||||
if (state == TStagstart)
|
||||
{ p++;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
Ldefault:
|
||||
switch (state)
|
||||
{
|
||||
case TStagstart: // start of tag name
|
||||
assert(istagstart(*p));
|
||||
state = TStag;
|
||||
tagstart = p;
|
||||
taglen = 0;
|
||||
break;
|
||||
|
||||
case TStag:
|
||||
if (istag(*p))
|
||||
{ // Continuing tag name
|
||||
taglen++;
|
||||
}
|
||||
else
|
||||
{ // End of tag name
|
||||
state = TSrest;
|
||||
}
|
||||
break;
|
||||
|
||||
case TSrest:
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// See if we parsed a <code> or </code> tag
|
||||
if (taglen && memicmp((char *) tagstart, (char *) "CODE", taglen) == 0
|
||||
&& *(p - 2) != '/') // ignore "<code />" (XHTML)
|
||||
{
|
||||
if (inot)
|
||||
{ inCode--;
|
||||
if (inCode < 0)
|
||||
inCode = 0; // ignore extra </code>'s
|
||||
}
|
||||
else
|
||||
inCode++;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Scan to end of attribute string.
|
||||
*/
|
||||
|
||||
void Html::skipString()
|
||||
{
|
||||
int tc = *p;
|
||||
|
||||
while (1)
|
||||
{
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case '"':
|
||||
case '\'':
|
||||
if (*p == tc)
|
||||
{ p++;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
case '\r':
|
||||
if (p[1] == '\n')
|
||||
goto Ldefault;
|
||||
case '\n':
|
||||
linnum++;
|
||||
// Always extract new lines, so that D lexer counts the
|
||||
// lines right.
|
||||
dbuf->writeByte(*p);
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
case 0x1a:
|
||||
Leof:
|
||||
error("end of file before closing %c of string", tc);
|
||||
break;
|
||||
|
||||
default:
|
||||
Ldefault:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* If p points to any white space, skip it
|
||||
* and return pointer just past it.
|
||||
*/
|
||||
|
||||
unsigned char *Html::skipWhite(unsigned char *q)
|
||||
{
|
||||
for (; 1; q++)
|
||||
{
|
||||
switch (*q)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\r':
|
||||
case '\n':
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Scan to end of comment.
|
||||
* Comments are defined any of a number of ways.
|
||||
* IE 5.0: <!-- followed by >
|
||||
* "HTML The Definitive Guide": <!-- text with at least one space in it -->
|
||||
* Netscape: <!-- --> comments nest
|
||||
* w3c: whitespace can appear between -- and > of comment close
|
||||
*/
|
||||
|
||||
void Html::scanComment()
|
||||
{
|
||||
// Most of the complexity is dealing with the case that
|
||||
// an arbitrary amount of whitespace can appear between
|
||||
// the -- and the > of a comment close.
|
||||
int scangt = 0;
|
||||
|
||||
//printf("scanComment()\n");
|
||||
if (*p == '\n')
|
||||
{ linnum++;
|
||||
// Always extract new lines, so that D lexer counts the
|
||||
// lines right.
|
||||
dbuf->writeByte(*p);
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
//scangt = 1; // IE 5.0 compatibility
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case '-':
|
||||
if (p[1] == '-')
|
||||
{
|
||||
if (p[2] == '>') // optimize for most common case
|
||||
{
|
||||
p += 3;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
scangt = 1;
|
||||
}
|
||||
else
|
||||
scangt = 0;
|
||||
continue;
|
||||
|
||||
case '>':
|
||||
if (scangt)
|
||||
{ // found -->
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
case '\v':
|
||||
// skip white space
|
||||
continue;
|
||||
|
||||
case '\r':
|
||||
if (p[1] == '\n')
|
||||
goto Ldefault;
|
||||
case '\n':
|
||||
linnum++; // remember to count lines
|
||||
// Always extract new lines, so that D lexer counts the
|
||||
// lines right.
|
||||
dbuf->writeByte(*p);
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
case 0x1a:
|
||||
error("end of file before closing --> of comment");
|
||||
break;
|
||||
|
||||
default:
|
||||
Ldefault:
|
||||
scangt = 0; // it's not -->
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//printf("*p = '%c'\n", *p);
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Determine if we are at the start of a comment.
|
||||
* Input:
|
||||
* p is on the opening '<'
|
||||
* Returns:
|
||||
* 0 if not start of a comment
|
||||
* 1 if start of a comment, p is adjusted to point past --
|
||||
*/
|
||||
|
||||
int Html::isCommentStart()
|
||||
#ifdef __DMC__
|
||||
__out(result)
|
||||
{
|
||||
if (result == 0)
|
||||
;
|
||||
else if (result == 1)
|
||||
{
|
||||
assert(p[-2] == '-' && p[-1] == '-');
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
__body
|
||||
#endif /* __DMC__ */
|
||||
{ unsigned char *s;
|
||||
|
||||
if (p[0] == '<' && p[1] == '!')
|
||||
{
|
||||
for (s = p + 2; 1; s++)
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\f':
|
||||
case '\v':
|
||||
// skip white space, even though spec says no
|
||||
// white space is allowed
|
||||
continue;
|
||||
|
||||
case '-':
|
||||
if (s[1] == '-')
|
||||
{
|
||||
p = s + 2;
|
||||
return 1;
|
||||
}
|
||||
goto No;
|
||||
|
||||
default:
|
||||
goto No;
|
||||
}
|
||||
}
|
||||
}
|
||||
No:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Html::isCDATAStart()
|
||||
{
|
||||
const char * CDATA_START_MARKER = "<![CDATA[";
|
||||
size_t len = strlen(CDATA_START_MARKER);
|
||||
|
||||
if (strncmp((char*)p, CDATA_START_MARKER, len) == 0)
|
||||
{
|
||||
p += len;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Html::scanCDATA()
|
||||
{
|
||||
while(*p && *p != 0x1A)
|
||||
{
|
||||
int lineSepLength = isLineSeparator(p);
|
||||
if (lineSepLength>0)
|
||||
{
|
||||
/* Always extract new lines, so that D lexer counts the lines
|
||||
* right.
|
||||
*/
|
||||
linnum++;
|
||||
dbuf->writeUTF8('\n');
|
||||
p += lineSepLength;
|
||||
continue;
|
||||
}
|
||||
else if (p[0] == ']' && p[1] == ']' && p[2] == '>')
|
||||
{
|
||||
/* end of CDATA section */
|
||||
p += 3;
|
||||
return;
|
||||
}
|
||||
else if (inCode)
|
||||
{
|
||||
/* this CDATA section contains D code */
|
||||
dbuf->writeByte(*p);
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Convert an HTML character entity into a character.
|
||||
* Forms are:
|
||||
* &name; named entity
|
||||
* &#ddd; decimal
|
||||
* &#xhhhh; hex
|
||||
* Input:
|
||||
* p is on the &
|
||||
*/
|
||||
|
||||
int Html::charEntity()
|
||||
{ int c = 0;
|
||||
int v;
|
||||
int hex;
|
||||
unsigned char *pstart = p;
|
||||
|
||||
//printf("Html::charEntity('%c')\n", *p);
|
||||
if (p[1] == '#')
|
||||
{
|
||||
p++;
|
||||
if (p[1] == 'x' || p[1] == 'X')
|
||||
{ p++;
|
||||
hex = 1;
|
||||
}
|
||||
else
|
||||
hex = 0;
|
||||
if (p[1] == ';')
|
||||
goto Linvalid;
|
||||
while (1)
|
||||
{
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case 0:
|
||||
case 0x1a:
|
||||
error("end of file before end of character entity");
|
||||
goto Lignore;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '<': // tag start
|
||||
// Termination is assumed
|
||||
break;
|
||||
|
||||
case ';':
|
||||
// Termination is explicit
|
||||
p++;
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
v = *p - '0';
|
||||
goto Lvalue;
|
||||
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
if (!hex)
|
||||
goto Linvalid;
|
||||
v = (*p - 'a') + 10;
|
||||
goto Lvalue;
|
||||
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
if (!hex)
|
||||
goto Linvalid;
|
||||
v = (*p - 'A') + 10;
|
||||
goto Lvalue;
|
||||
|
||||
Lvalue:
|
||||
if (hex)
|
||||
c = (c << 4) + v;
|
||||
else
|
||||
c = (c * 10) + v;
|
||||
if (c > 0x10FFFF)
|
||||
{
|
||||
error("character entity out of range");
|
||||
goto Lignore;
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
Linvalid:
|
||||
error("invalid numeric character reference");
|
||||
goto Lignore;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a named entity; gather all characters until ;
|
||||
unsigned char *idstart = p + 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case 0:
|
||||
case 0x1a:
|
||||
error("end of file before end of character entity");
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '<': // tag start
|
||||
// Termination is assumed
|
||||
c = HtmlNamedEntity(idstart, p - idstart);
|
||||
if (c == -1)
|
||||
goto Lignore;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
// Termination is explicit
|
||||
c = HtmlNamedEntity(idstart, p - idstart);
|
||||
if (c == -1)
|
||||
goto Lignore;
|
||||
p++;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Kludge to convert non-breaking space to ascii space
|
||||
if (c == 160)
|
||||
c = ' ';
|
||||
|
||||
return c;
|
||||
|
||||
Lignore:
|
||||
//printf("Lignore\n");
|
||||
p = pstart + 1;
|
||||
return '&';
|
||||
}
|
||||
|
||||
/**
|
||||
* identify DOS, Linux, Mac, Next and Unicode line endings
|
||||
* 0 if this is no line separator
|
||||
* >0 the length of the separator
|
||||
* Note: input has to be UTF-8
|
||||
*/
|
||||
static int isLineSeparator(const unsigned char* p)
|
||||
{
|
||||
// Linux
|
||||
if( p[0]=='\n')
|
||||
return 1;
|
||||
|
||||
// Mac & Dos
|
||||
if( p[0]=='\r')
|
||||
return (p[1]=='\n') ? 2 : 1;
|
||||
|
||||
// Unicode (line || paragraph sep.)
|
||||
if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9))
|
||||
return 3;
|
||||
|
||||
// Next
|
||||
if( p[0]==0xC2 && p[1]==0x85)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
43
dmd2/html.h
Normal file
43
dmd2/html.h
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// 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_HTML_H
|
||||
#define DMD_HTML_H 1
|
||||
|
||||
struct OutBuffer;
|
||||
|
||||
struct Html
|
||||
{
|
||||
const char *sourcename;
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
unsigned linnum; // current line number
|
||||
OutBuffer *dbuf; // code source buffer
|
||||
int inCode; // !=0 if in code
|
||||
|
||||
|
||||
Html(const char *sourcename, unsigned char *base, unsigned length);
|
||||
|
||||
void error(const char *format, ...);
|
||||
void extractCode(OutBuffer *buf);
|
||||
void skipTag();
|
||||
void skipString();
|
||||
unsigned char *skipWhite(unsigned char *q);
|
||||
void scanComment();
|
||||
int isCommentStart();
|
||||
void scanCDATA();
|
||||
int isCDATAStart();
|
||||
int charEntity();
|
||||
static int namedEntity(unsigned char *p, int length);
|
||||
};
|
||||
|
||||
#endif
|
||||
441
dmd2/id.c
Normal file
441
dmd2/id.c
Normal file
@@ -0,0 +1,441 @@
|
||||
// File generated by idgen.c
|
||||
#include "id.h"
|
||||
#include "identifier.h"
|
||||
#include "lexer.h"
|
||||
Identifier *Id::IUnknown;
|
||||
Identifier *Id::Object;
|
||||
Identifier *Id::object;
|
||||
Identifier *Id::max;
|
||||
Identifier *Id::min;
|
||||
Identifier *Id::This;
|
||||
Identifier *Id::ctor;
|
||||
Identifier *Id::dtor;
|
||||
Identifier *Id::cpctor;
|
||||
Identifier *Id::_postblit;
|
||||
Identifier *Id::classInvariant;
|
||||
Identifier *Id::unitTest;
|
||||
Identifier *Id::init;
|
||||
Identifier *Id::size;
|
||||
Identifier *Id::__sizeof;
|
||||
Identifier *Id::alignof;
|
||||
Identifier *Id::mangleof;
|
||||
Identifier *Id::stringof;
|
||||
Identifier *Id::tupleof;
|
||||
Identifier *Id::length;
|
||||
Identifier *Id::remove;
|
||||
Identifier *Id::ptr;
|
||||
Identifier *Id::funcptr;
|
||||
Identifier *Id::dollar;
|
||||
Identifier *Id::offset;
|
||||
Identifier *Id::offsetof;
|
||||
Identifier *Id::ModuleInfo;
|
||||
Identifier *Id::ClassInfo;
|
||||
Identifier *Id::classinfo;
|
||||
Identifier *Id::typeinfo;
|
||||
Identifier *Id::outer;
|
||||
Identifier *Id::Exception;
|
||||
Identifier *Id::withSym;
|
||||
Identifier *Id::result;
|
||||
Identifier *Id::returnLabel;
|
||||
Identifier *Id::delegate;
|
||||
Identifier *Id::line;
|
||||
Identifier *Id::empty;
|
||||
Identifier *Id::p;
|
||||
Identifier *Id::coverage;
|
||||
Identifier *Id::__vptr;
|
||||
Identifier *Id::__monitor;
|
||||
Identifier *Id::TypeInfo;
|
||||
Identifier *Id::TypeInfo_Class;
|
||||
Identifier *Id::TypeInfo_Interface;
|
||||
Identifier *Id::TypeInfo_Struct;
|
||||
Identifier *Id::TypeInfo_Enum;
|
||||
Identifier *Id::TypeInfo_Typedef;
|
||||
Identifier *Id::TypeInfo_Pointer;
|
||||
Identifier *Id::TypeInfo_Array;
|
||||
Identifier *Id::TypeInfo_StaticArray;
|
||||
Identifier *Id::TypeInfo_AssociativeArray;
|
||||
Identifier *Id::TypeInfo_Function;
|
||||
Identifier *Id::TypeInfo_Delegate;
|
||||
Identifier *Id::TypeInfo_Tuple;
|
||||
Identifier *Id::TypeInfo_Const;
|
||||
Identifier *Id::TypeInfo_Invariant;
|
||||
Identifier *Id::elements;
|
||||
Identifier *Id::_arguments_typeinfo;
|
||||
Identifier *Id::_arguments;
|
||||
Identifier *Id::_argptr;
|
||||
Identifier *Id::_match;
|
||||
Identifier *Id::destroy;
|
||||
Identifier *Id::postblit;
|
||||
Identifier *Id::LINE;
|
||||
Identifier *Id::FILE;
|
||||
Identifier *Id::DATE;
|
||||
Identifier *Id::TIME;
|
||||
Identifier *Id::TIMESTAMP;
|
||||
Identifier *Id::VENDOR;
|
||||
Identifier *Id::VERSIONX;
|
||||
Identifier *Id::EOFX;
|
||||
Identifier *Id::nan;
|
||||
Identifier *Id::infinity;
|
||||
Identifier *Id::dig;
|
||||
Identifier *Id::epsilon;
|
||||
Identifier *Id::mant_dig;
|
||||
Identifier *Id::max_10_exp;
|
||||
Identifier *Id::max_exp;
|
||||
Identifier *Id::min_10_exp;
|
||||
Identifier *Id::min_exp;
|
||||
Identifier *Id::re;
|
||||
Identifier *Id::im;
|
||||
Identifier *Id::C;
|
||||
Identifier *Id::D;
|
||||
Identifier *Id::Windows;
|
||||
Identifier *Id::Pascal;
|
||||
Identifier *Id::System;
|
||||
Identifier *Id::exit;
|
||||
Identifier *Id::success;
|
||||
Identifier *Id::failure;
|
||||
Identifier *Id::keys;
|
||||
Identifier *Id::values;
|
||||
Identifier *Id::rehash;
|
||||
Identifier *Id::sort;
|
||||
Identifier *Id::reverse;
|
||||
Identifier *Id::dup;
|
||||
Identifier *Id::idup;
|
||||
Identifier *Id::___out;
|
||||
Identifier *Id::___in;
|
||||
Identifier *Id::__int;
|
||||
Identifier *Id::__dollar;
|
||||
Identifier *Id::__LOCAL_SIZE;
|
||||
Identifier *Id::uadd;
|
||||
Identifier *Id::neg;
|
||||
Identifier *Id::com;
|
||||
Identifier *Id::add;
|
||||
Identifier *Id::add_r;
|
||||
Identifier *Id::sub;
|
||||
Identifier *Id::sub_r;
|
||||
Identifier *Id::mul;
|
||||
Identifier *Id::mul_r;
|
||||
Identifier *Id::div;
|
||||
Identifier *Id::div_r;
|
||||
Identifier *Id::mod;
|
||||
Identifier *Id::mod_r;
|
||||
Identifier *Id::eq;
|
||||
Identifier *Id::cmp;
|
||||
Identifier *Id::iand;
|
||||
Identifier *Id::iand_r;
|
||||
Identifier *Id::ior;
|
||||
Identifier *Id::ior_r;
|
||||
Identifier *Id::ixor;
|
||||
Identifier *Id::ixor_r;
|
||||
Identifier *Id::shl;
|
||||
Identifier *Id::shl_r;
|
||||
Identifier *Id::shr;
|
||||
Identifier *Id::shr_r;
|
||||
Identifier *Id::ushr;
|
||||
Identifier *Id::ushr_r;
|
||||
Identifier *Id::cat;
|
||||
Identifier *Id::cat_r;
|
||||
Identifier *Id::assign;
|
||||
Identifier *Id::addass;
|
||||
Identifier *Id::subass;
|
||||
Identifier *Id::mulass;
|
||||
Identifier *Id::divass;
|
||||
Identifier *Id::modass;
|
||||
Identifier *Id::andass;
|
||||
Identifier *Id::orass;
|
||||
Identifier *Id::xorass;
|
||||
Identifier *Id::shlass;
|
||||
Identifier *Id::shrass;
|
||||
Identifier *Id::ushrass;
|
||||
Identifier *Id::catass;
|
||||
Identifier *Id::postinc;
|
||||
Identifier *Id::postdec;
|
||||
Identifier *Id::index;
|
||||
Identifier *Id::indexass;
|
||||
Identifier *Id::slice;
|
||||
Identifier *Id::sliceass;
|
||||
Identifier *Id::call;
|
||||
Identifier *Id::cast;
|
||||
Identifier *Id::match;
|
||||
Identifier *Id::next;
|
||||
Identifier *Id::opIn;
|
||||
Identifier *Id::opIn_r;
|
||||
Identifier *Id::opStar;
|
||||
Identifier *Id::opDot;
|
||||
Identifier *Id::opImplicitCast;
|
||||
Identifier *Id::classNew;
|
||||
Identifier *Id::classDelete;
|
||||
Identifier *Id::apply;
|
||||
Identifier *Id::applyReverse;
|
||||
Identifier *Id::adDup;
|
||||
Identifier *Id::adReverse;
|
||||
Identifier *Id::aaLen;
|
||||
Identifier *Id::aaKeys;
|
||||
Identifier *Id::aaValues;
|
||||
Identifier *Id::aaRehash;
|
||||
Identifier *Id::GNU_asm;
|
||||
Identifier *Id::lib;
|
||||
Identifier *Id::msg;
|
||||
Identifier *Id::startaddress;
|
||||
Identifier *Id::intrinsic;
|
||||
Identifier *Id::va_intrinsic;
|
||||
Identifier *Id::no_typeinfo;
|
||||
Identifier *Id::no_moduleinfo;
|
||||
Identifier *Id::Alloca;
|
||||
Identifier *Id::vastart;
|
||||
Identifier *Id::vacopy;
|
||||
Identifier *Id::vaend;
|
||||
Identifier *Id::vaarg;
|
||||
Identifier *Id::ldc;
|
||||
Identifier *Id::tohash;
|
||||
Identifier *Id::tostring;
|
||||
Identifier *Id::getmembers;
|
||||
Identifier *Id::main;
|
||||
Identifier *Id::WinMain;
|
||||
Identifier *Id::DllMain;
|
||||
Identifier *Id::std;
|
||||
Identifier *Id::math;
|
||||
Identifier *Id::sin;
|
||||
Identifier *Id::cos;
|
||||
Identifier *Id::tan;
|
||||
Identifier *Id::_sqrt;
|
||||
Identifier *Id::fabs;
|
||||
Identifier *Id::isAbstractClass;
|
||||
Identifier *Id::isArithmetic;
|
||||
Identifier *Id::isAssociativeArray;
|
||||
Identifier *Id::isFinalClass;
|
||||
Identifier *Id::isFloating;
|
||||
Identifier *Id::isIntegral;
|
||||
Identifier *Id::isScalar;
|
||||
Identifier *Id::isStaticArray;
|
||||
Identifier *Id::isUnsigned;
|
||||
Identifier *Id::isVirtualFunction;
|
||||
Identifier *Id::isAbstractFunction;
|
||||
Identifier *Id::isFinalFunction;
|
||||
Identifier *Id::hasMember;
|
||||
Identifier *Id::getMember;
|
||||
Identifier *Id::getVirtualFunctions;
|
||||
Identifier *Id::classInstanceSize;
|
||||
Identifier *Id::allMembers;
|
||||
Identifier *Id::derivedMembers;
|
||||
Identifier *Id::isSame;
|
||||
Identifier *Id::compiles;
|
||||
void Id::initialize()
|
||||
{
|
||||
IUnknown = Lexer::idPool("IUnknown");
|
||||
Object = Lexer::idPool("Object");
|
||||
object = Lexer::idPool("object");
|
||||
max = Lexer::idPool("max");
|
||||
min = Lexer::idPool("min");
|
||||
This = Lexer::idPool("this");
|
||||
ctor = Lexer::idPool("__ctor");
|
||||
dtor = Lexer::idPool("__dtor");
|
||||
cpctor = Lexer::idPool("__cpctor");
|
||||
_postblit = Lexer::idPool("__postblit");
|
||||
classInvariant = Lexer::idPool("__invariant");
|
||||
unitTest = Lexer::idPool("__unitTest");
|
||||
init = Lexer::idPool("init");
|
||||
size = Lexer::idPool("size");
|
||||
__sizeof = Lexer::idPool("sizeof");
|
||||
alignof = Lexer::idPool("alignof");
|
||||
mangleof = Lexer::idPool("mangleof");
|
||||
stringof = Lexer::idPool("stringof");
|
||||
tupleof = Lexer::idPool("tupleof");
|
||||
length = Lexer::idPool("length");
|
||||
remove = Lexer::idPool("remove");
|
||||
ptr = Lexer::idPool("ptr");
|
||||
funcptr = Lexer::idPool("funcptr");
|
||||
dollar = Lexer::idPool("__dollar");
|
||||
offset = Lexer::idPool("offset");
|
||||
offsetof = Lexer::idPool("offsetof");
|
||||
ModuleInfo = Lexer::idPool("ModuleInfo");
|
||||
ClassInfo = Lexer::idPool("ClassInfo");
|
||||
classinfo = Lexer::idPool("classinfo");
|
||||
typeinfo = Lexer::idPool("typeinfo");
|
||||
outer = Lexer::idPool("outer");
|
||||
Exception = Lexer::idPool("Exception");
|
||||
withSym = Lexer::idPool("__withSym");
|
||||
result = Lexer::idPool("__result");
|
||||
returnLabel = Lexer::idPool("__returnLabel");
|
||||
delegate = Lexer::idPool("delegate");
|
||||
line = Lexer::idPool("line");
|
||||
empty = Lexer::idPool("");
|
||||
p = Lexer::idPool("p");
|
||||
coverage = Lexer::idPool("__coverage");
|
||||
__vptr = Lexer::idPool("__vptr");
|
||||
__monitor = Lexer::idPool("__monitor");
|
||||
TypeInfo = Lexer::idPool("TypeInfo");
|
||||
TypeInfo_Class = Lexer::idPool("TypeInfo_Class");
|
||||
TypeInfo_Interface = Lexer::idPool("TypeInfo_Interface");
|
||||
TypeInfo_Struct = Lexer::idPool("TypeInfo_Struct");
|
||||
TypeInfo_Enum = Lexer::idPool("TypeInfo_Enum");
|
||||
TypeInfo_Typedef = Lexer::idPool("TypeInfo_Typedef");
|
||||
TypeInfo_Pointer = Lexer::idPool("TypeInfo_Pointer");
|
||||
TypeInfo_Array = Lexer::idPool("TypeInfo_Array");
|
||||
TypeInfo_StaticArray = Lexer::idPool("TypeInfo_StaticArray");
|
||||
TypeInfo_AssociativeArray = Lexer::idPool("TypeInfo_AssociativeArray");
|
||||
TypeInfo_Function = Lexer::idPool("TypeInfo_Function");
|
||||
TypeInfo_Delegate = Lexer::idPool("TypeInfo_Delegate");
|
||||
TypeInfo_Tuple = Lexer::idPool("TypeInfo_Tuple");
|
||||
TypeInfo_Const = Lexer::idPool("TypeInfo_Const");
|
||||
TypeInfo_Invariant = Lexer::idPool("TypeInfo_Invariant");
|
||||
elements = Lexer::idPool("elements");
|
||||
_arguments_typeinfo = Lexer::idPool("_arguments_typeinfo");
|
||||
_arguments = Lexer::idPool("_arguments");
|
||||
_argptr = Lexer::idPool("_argptr");
|
||||
_match = Lexer::idPool("_match");
|
||||
destroy = Lexer::idPool("destroy");
|
||||
postblit = Lexer::idPool("postblit");
|
||||
LINE = Lexer::idPool("__LINE__");
|
||||
FILE = Lexer::idPool("__FILE__");
|
||||
DATE = Lexer::idPool("__DATE__");
|
||||
TIME = Lexer::idPool("__TIME__");
|
||||
TIMESTAMP = Lexer::idPool("__TIMESTAMP__");
|
||||
VENDOR = Lexer::idPool("__VENDOR__");
|
||||
VERSIONX = Lexer::idPool("__VERSION__");
|
||||
EOFX = Lexer::idPool("__EOF__");
|
||||
nan = Lexer::idPool("nan");
|
||||
infinity = Lexer::idPool("infinity");
|
||||
dig = Lexer::idPool("dig");
|
||||
epsilon = Lexer::idPool("epsilon");
|
||||
mant_dig = Lexer::idPool("mant_dig");
|
||||
max_10_exp = Lexer::idPool("max_10_exp");
|
||||
max_exp = Lexer::idPool("max_exp");
|
||||
min_10_exp = Lexer::idPool("min_10_exp");
|
||||
min_exp = Lexer::idPool("min_exp");
|
||||
re = Lexer::idPool("re");
|
||||
im = Lexer::idPool("im");
|
||||
C = Lexer::idPool("C");
|
||||
D = Lexer::idPool("D");
|
||||
Windows = Lexer::idPool("Windows");
|
||||
Pascal = Lexer::idPool("Pascal");
|
||||
System = Lexer::idPool("System");
|
||||
exit = Lexer::idPool("exit");
|
||||
success = Lexer::idPool("success");
|
||||
failure = Lexer::idPool("failure");
|
||||
keys = Lexer::idPool("keys");
|
||||
values = Lexer::idPool("values");
|
||||
rehash = Lexer::idPool("rehash");
|
||||
sort = Lexer::idPool("sort");
|
||||
reverse = Lexer::idPool("reverse");
|
||||
dup = Lexer::idPool("dup");
|
||||
idup = Lexer::idPool("idup");
|
||||
___out = Lexer::idPool("out");
|
||||
___in = Lexer::idPool("in");
|
||||
__int = Lexer::idPool("int");
|
||||
__dollar = Lexer::idPool("$");
|
||||
__LOCAL_SIZE = Lexer::idPool("__LOCAL_SIZE");
|
||||
uadd = Lexer::idPool("opPos");
|
||||
neg = Lexer::idPool("opNeg");
|
||||
com = Lexer::idPool("opCom");
|
||||
add = Lexer::idPool("opAdd");
|
||||
add_r = Lexer::idPool("opAdd_r");
|
||||
sub = Lexer::idPool("opSub");
|
||||
sub_r = Lexer::idPool("opSub_r");
|
||||
mul = Lexer::idPool("opMul");
|
||||
mul_r = Lexer::idPool("opMul_r");
|
||||
div = Lexer::idPool("opDiv");
|
||||
div_r = Lexer::idPool("opDiv_r");
|
||||
mod = Lexer::idPool("opMod");
|
||||
mod_r = Lexer::idPool("opMod_r");
|
||||
eq = Lexer::idPool("opEquals");
|
||||
cmp = Lexer::idPool("opCmp");
|
||||
iand = Lexer::idPool("opAnd");
|
||||
iand_r = Lexer::idPool("opAnd_r");
|
||||
ior = Lexer::idPool("opOr");
|
||||
ior_r = Lexer::idPool("opOr_r");
|
||||
ixor = Lexer::idPool("opXor");
|
||||
ixor_r = Lexer::idPool("opXor_r");
|
||||
shl = Lexer::idPool("opShl");
|
||||
shl_r = Lexer::idPool("opShl_r");
|
||||
shr = Lexer::idPool("opShr");
|
||||
shr_r = Lexer::idPool("opShr_r");
|
||||
ushr = Lexer::idPool("opUShr");
|
||||
ushr_r = Lexer::idPool("opUShr_r");
|
||||
cat = Lexer::idPool("opCat");
|
||||
cat_r = Lexer::idPool("opCat_r");
|
||||
assign = Lexer::idPool("opAssign");
|
||||
addass = Lexer::idPool("opAddAssign");
|
||||
subass = Lexer::idPool("opSubAssign");
|
||||
mulass = Lexer::idPool("opMulAssign");
|
||||
divass = Lexer::idPool("opDivAssign");
|
||||
modass = Lexer::idPool("opModAssign");
|
||||
andass = Lexer::idPool("opAndAssign");
|
||||
orass = Lexer::idPool("opOrAssign");
|
||||
xorass = Lexer::idPool("opXorAssign");
|
||||
shlass = Lexer::idPool("opShlAssign");
|
||||
shrass = Lexer::idPool("opShrAssign");
|
||||
ushrass = Lexer::idPool("opUShrAssign");
|
||||
catass = Lexer::idPool("opCatAssign");
|
||||
postinc = Lexer::idPool("opPostInc");
|
||||
postdec = Lexer::idPool("opPostDec");
|
||||
index = Lexer::idPool("opIndex");
|
||||
indexass = Lexer::idPool("opIndexAssign");
|
||||
slice = Lexer::idPool("opSlice");
|
||||
sliceass = Lexer::idPool("opSliceAssign");
|
||||
call = Lexer::idPool("opCall");
|
||||
cast = Lexer::idPool("opCast");
|
||||
match = Lexer::idPool("opMatch");
|
||||
next = Lexer::idPool("opNext");
|
||||
opIn = Lexer::idPool("opIn");
|
||||
opIn_r = Lexer::idPool("opIn_r");
|
||||
opStar = Lexer::idPool("opStar");
|
||||
opDot = Lexer::idPool("opDot");
|
||||
opImplicitCast = Lexer::idPool("opImplicitCast");
|
||||
classNew = Lexer::idPool("new");
|
||||
classDelete = Lexer::idPool("delete");
|
||||
apply = Lexer::idPool("opApply");
|
||||
applyReverse = Lexer::idPool("opApplyReverse");
|
||||
adDup = Lexer::idPool("_adDupT");
|
||||
adReverse = Lexer::idPool("_adReverse");
|
||||
aaLen = Lexer::idPool("_aaLen");
|
||||
aaKeys = Lexer::idPool("_aaKeys");
|
||||
aaValues = Lexer::idPool("_aaValues");
|
||||
aaRehash = Lexer::idPool("_aaRehash");
|
||||
GNU_asm = Lexer::idPool("GNU_asm");
|
||||
lib = Lexer::idPool("lib");
|
||||
msg = Lexer::idPool("msg");
|
||||
startaddress = Lexer::idPool("startaddress");
|
||||
intrinsic = Lexer::idPool("intrinsic");
|
||||
va_intrinsic = Lexer::idPool("va_intrinsic");
|
||||
no_typeinfo = Lexer::idPool("no_typeinfo");
|
||||
no_moduleinfo = Lexer::idPool("no_moduleinfo");
|
||||
Alloca = Lexer::idPool("alloca");
|
||||
vastart = Lexer::idPool("va_start");
|
||||
vacopy = Lexer::idPool("va_copy");
|
||||
vaend = Lexer::idPool("va_end");
|
||||
vaarg = Lexer::idPool("va_arg");
|
||||
ldc = Lexer::idPool("ldc");
|
||||
tohash = Lexer::idPool("toHash");
|
||||
tostring = Lexer::idPool("toString");
|
||||
getmembers = Lexer::idPool("getMembers");
|
||||
main = Lexer::idPool("main");
|
||||
WinMain = Lexer::idPool("WinMain");
|
||||
DllMain = Lexer::idPool("DllMain");
|
||||
std = Lexer::idPool("std");
|
||||
math = Lexer::idPool("math");
|
||||
sin = Lexer::idPool("sin");
|
||||
cos = Lexer::idPool("cos");
|
||||
tan = Lexer::idPool("tan");
|
||||
_sqrt = Lexer::idPool("sqrt");
|
||||
fabs = Lexer::idPool("fabs");
|
||||
isAbstractClass = Lexer::idPool("isAbstractClass");
|
||||
isArithmetic = Lexer::idPool("isArithmetic");
|
||||
isAssociativeArray = Lexer::idPool("isAssociativeArray");
|
||||
isFinalClass = Lexer::idPool("isFinalClass");
|
||||
isFloating = Lexer::idPool("isFloating");
|
||||
isIntegral = Lexer::idPool("isIntegral");
|
||||
isScalar = Lexer::idPool("isScalar");
|
||||
isStaticArray = Lexer::idPool("isStaticArray");
|
||||
isUnsigned = Lexer::idPool("isUnsigned");
|
||||
isVirtualFunction = Lexer::idPool("isVirtualFunction");
|
||||
isAbstractFunction = Lexer::idPool("isAbstractFunction");
|
||||
isFinalFunction = Lexer::idPool("isFinalFunction");
|
||||
hasMember = Lexer::idPool("hasMember");
|
||||
getMember = Lexer::idPool("getMember");
|
||||
getVirtualFunctions = Lexer::idPool("getVirtualFunctions");
|
||||
classInstanceSize = Lexer::idPool("classInstanceSize");
|
||||
allMembers = Lexer::idPool("allMembers");
|
||||
derivedMembers = Lexer::idPool("derivedMembers");
|
||||
isSame = Lexer::idPool("isSame");
|
||||
compiles = Lexer::idPool("compiles");
|
||||
}
|
||||
226
dmd2/id.h
Normal file
226
dmd2/id.h
Normal file
@@ -0,0 +1,226 @@
|
||||
// File generated by idgen.c
|
||||
#ifndef DMD_ID_H
|
||||
#define DMD_ID_H 1
|
||||
struct Identifier;
|
||||
struct Id
|
||||
{
|
||||
static Identifier *IUnknown;
|
||||
static Identifier *Object;
|
||||
static Identifier *object;
|
||||
static Identifier *max;
|
||||
static Identifier *min;
|
||||
static Identifier *This;
|
||||
static Identifier *ctor;
|
||||
static Identifier *dtor;
|
||||
static Identifier *cpctor;
|
||||
static Identifier *_postblit;
|
||||
static Identifier *classInvariant;
|
||||
static Identifier *unitTest;
|
||||
static Identifier *init;
|
||||
static Identifier *size;
|
||||
static Identifier *__sizeof;
|
||||
static Identifier *alignof;
|
||||
static Identifier *mangleof;
|
||||
static Identifier *stringof;
|
||||
static Identifier *tupleof;
|
||||
static Identifier *length;
|
||||
static Identifier *remove;
|
||||
static Identifier *ptr;
|
||||
static Identifier *funcptr;
|
||||
static Identifier *dollar;
|
||||
static Identifier *offset;
|
||||
static Identifier *offsetof;
|
||||
static Identifier *ModuleInfo;
|
||||
static Identifier *ClassInfo;
|
||||
static Identifier *classinfo;
|
||||
static Identifier *typeinfo;
|
||||
static Identifier *outer;
|
||||
static Identifier *Exception;
|
||||
static Identifier *withSym;
|
||||
static Identifier *result;
|
||||
static Identifier *returnLabel;
|
||||
static Identifier *delegate;
|
||||
static Identifier *line;
|
||||
static Identifier *empty;
|
||||
static Identifier *p;
|
||||
static Identifier *coverage;
|
||||
static Identifier *__vptr;
|
||||
static Identifier *__monitor;
|
||||
static Identifier *TypeInfo;
|
||||
static Identifier *TypeInfo_Class;
|
||||
static Identifier *TypeInfo_Interface;
|
||||
static Identifier *TypeInfo_Struct;
|
||||
static Identifier *TypeInfo_Enum;
|
||||
static Identifier *TypeInfo_Typedef;
|
||||
static Identifier *TypeInfo_Pointer;
|
||||
static Identifier *TypeInfo_Array;
|
||||
static Identifier *TypeInfo_StaticArray;
|
||||
static Identifier *TypeInfo_AssociativeArray;
|
||||
static Identifier *TypeInfo_Function;
|
||||
static Identifier *TypeInfo_Delegate;
|
||||
static Identifier *TypeInfo_Tuple;
|
||||
static Identifier *TypeInfo_Const;
|
||||
static Identifier *TypeInfo_Invariant;
|
||||
static Identifier *elements;
|
||||
static Identifier *_arguments_typeinfo;
|
||||
static Identifier *_arguments;
|
||||
static Identifier *_argptr;
|
||||
static Identifier *_match;
|
||||
static Identifier *destroy;
|
||||
static Identifier *postblit;
|
||||
static Identifier *LINE;
|
||||
static Identifier *FILE;
|
||||
static Identifier *DATE;
|
||||
static Identifier *TIME;
|
||||
static Identifier *TIMESTAMP;
|
||||
static Identifier *VENDOR;
|
||||
static Identifier *VERSIONX;
|
||||
static Identifier *EOFX;
|
||||
static Identifier *nan;
|
||||
static Identifier *infinity;
|
||||
static Identifier *dig;
|
||||
static Identifier *epsilon;
|
||||
static Identifier *mant_dig;
|
||||
static Identifier *max_10_exp;
|
||||
static Identifier *max_exp;
|
||||
static Identifier *min_10_exp;
|
||||
static Identifier *min_exp;
|
||||
static Identifier *re;
|
||||
static Identifier *im;
|
||||
static Identifier *C;
|
||||
static Identifier *D;
|
||||
static Identifier *Windows;
|
||||
static Identifier *Pascal;
|
||||
static Identifier *System;
|
||||
static Identifier *exit;
|
||||
static Identifier *success;
|
||||
static Identifier *failure;
|
||||
static Identifier *keys;
|
||||
static Identifier *values;
|
||||
static Identifier *rehash;
|
||||
static Identifier *sort;
|
||||
static Identifier *reverse;
|
||||
static Identifier *dup;
|
||||
static Identifier *idup;
|
||||
static Identifier *___out;
|
||||
static Identifier *___in;
|
||||
static Identifier *__int;
|
||||
static Identifier *__dollar;
|
||||
static Identifier *__LOCAL_SIZE;
|
||||
static Identifier *uadd;
|
||||
static Identifier *neg;
|
||||
static Identifier *com;
|
||||
static Identifier *add;
|
||||
static Identifier *add_r;
|
||||
static Identifier *sub;
|
||||
static Identifier *sub_r;
|
||||
static Identifier *mul;
|
||||
static Identifier *mul_r;
|
||||
static Identifier *div;
|
||||
static Identifier *div_r;
|
||||
static Identifier *mod;
|
||||
static Identifier *mod_r;
|
||||
static Identifier *eq;
|
||||
static Identifier *cmp;
|
||||
static Identifier *iand;
|
||||
static Identifier *iand_r;
|
||||
static Identifier *ior;
|
||||
static Identifier *ior_r;
|
||||
static Identifier *ixor;
|
||||
static Identifier *ixor_r;
|
||||
static Identifier *shl;
|
||||
static Identifier *shl_r;
|
||||
static Identifier *shr;
|
||||
static Identifier *shr_r;
|
||||
static Identifier *ushr;
|
||||
static Identifier *ushr_r;
|
||||
static Identifier *cat;
|
||||
static Identifier *cat_r;
|
||||
static Identifier *assign;
|
||||
static Identifier *addass;
|
||||
static Identifier *subass;
|
||||
static Identifier *mulass;
|
||||
static Identifier *divass;
|
||||
static Identifier *modass;
|
||||
static Identifier *andass;
|
||||
static Identifier *orass;
|
||||
static Identifier *xorass;
|
||||
static Identifier *shlass;
|
||||
static Identifier *shrass;
|
||||
static Identifier *ushrass;
|
||||
static Identifier *catass;
|
||||
static Identifier *postinc;
|
||||
static Identifier *postdec;
|
||||
static Identifier *index;
|
||||
static Identifier *indexass;
|
||||
static Identifier *slice;
|
||||
static Identifier *sliceass;
|
||||
static Identifier *call;
|
||||
static Identifier *cast;
|
||||
static Identifier *match;
|
||||
static Identifier *next;
|
||||
static Identifier *opIn;
|
||||
static Identifier *opIn_r;
|
||||
static Identifier *opStar;
|
||||
static Identifier *opDot;
|
||||
static Identifier *opImplicitCast;
|
||||
static Identifier *classNew;
|
||||
static Identifier *classDelete;
|
||||
static Identifier *apply;
|
||||
static Identifier *applyReverse;
|
||||
static Identifier *adDup;
|
||||
static Identifier *adReverse;
|
||||
static Identifier *aaLen;
|
||||
static Identifier *aaKeys;
|
||||
static Identifier *aaValues;
|
||||
static Identifier *aaRehash;
|
||||
static Identifier *GNU_asm;
|
||||
static Identifier *lib;
|
||||
static Identifier *msg;
|
||||
static Identifier *startaddress;
|
||||
static Identifier *intrinsic;
|
||||
static Identifier *va_intrinsic;
|
||||
static Identifier *no_typeinfo;
|
||||
static Identifier *no_moduleinfo;
|
||||
static Identifier *Alloca;
|
||||
static Identifier *vastart;
|
||||
static Identifier *vacopy;
|
||||
static Identifier *vaend;
|
||||
static Identifier *vaarg;
|
||||
static Identifier *ldc;
|
||||
static Identifier *tohash;
|
||||
static Identifier *tostring;
|
||||
static Identifier *getmembers;
|
||||
static Identifier *main;
|
||||
static Identifier *WinMain;
|
||||
static Identifier *DllMain;
|
||||
static Identifier *std;
|
||||
static Identifier *math;
|
||||
static Identifier *sin;
|
||||
static Identifier *cos;
|
||||
static Identifier *tan;
|
||||
static Identifier *_sqrt;
|
||||
static Identifier *fabs;
|
||||
static Identifier *isAbstractClass;
|
||||
static Identifier *isArithmetic;
|
||||
static Identifier *isAssociativeArray;
|
||||
static Identifier *isFinalClass;
|
||||
static Identifier *isFloating;
|
||||
static Identifier *isIntegral;
|
||||
static Identifier *isScalar;
|
||||
static Identifier *isStaticArray;
|
||||
static Identifier *isUnsigned;
|
||||
static Identifier *isVirtualFunction;
|
||||
static Identifier *isAbstractFunction;
|
||||
static Identifier *isFinalFunction;
|
||||
static Identifier *hasMember;
|
||||
static Identifier *getMember;
|
||||
static Identifier *getVirtualFunctions;
|
||||
static Identifier *classInstanceSize;
|
||||
static Identifier *allMembers;
|
||||
static Identifier *derivedMembers;
|
||||
static Identifier *isSame;
|
||||
static Identifier *compiles;
|
||||
static void initialize();
|
||||
};
|
||||
#endif
|
||||
101
dmd2/identifier.c
Normal file
101
dmd2/identifier.c
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
// 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.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "identifier.h"
|
||||
#include "mars.h"
|
||||
#include "lexer.h"
|
||||
#include "id.h"
|
||||
|
||||
Identifier::Identifier(const char *string, int value)
|
||||
{
|
||||
//printf("Identifier('%s', %d)\n", string, value);
|
||||
this->string = string;
|
||||
this->value = value;
|
||||
this->len = strlen(string);
|
||||
}
|
||||
|
||||
hash_t Identifier::hashCode()
|
||||
{
|
||||
return String::calcHash(string);
|
||||
}
|
||||
|
||||
int Identifier::equals(Object *o)
|
||||
{
|
||||
return this == o || memcmp(string,o->toChars(),len+1) == 0;
|
||||
}
|
||||
|
||||
int Identifier::compare(Object *o)
|
||||
{
|
||||
return memcmp(string, o->toChars(), len + 1);
|
||||
}
|
||||
|
||||
char *Identifier::toChars()
|
||||
{
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
const char *Identifier::toHChars2()
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
if (this == Id::ctor) p = "this";
|
||||
else if (this == Id::dtor) p = "~this";
|
||||
else if (this == Id::classInvariant) p = "invariant";
|
||||
else if (this == Id::unitTest) p = "unittest";
|
||||
else if (this == Id::dollar) p = "$";
|
||||
else if (this == Id::withSym) p = "with";
|
||||
else if (this == Id::result) p = "result";
|
||||
else if (this == Id::returnLabel) p = "return";
|
||||
else
|
||||
{ p = toChars();
|
||||
if (*p == '_')
|
||||
{
|
||||
if (memcmp(p, "_staticCtor", 11) == 0)
|
||||
p = "static this";
|
||||
else if (memcmp(p, "_staticDtor", 11) == 0)
|
||||
p = "static ~this";
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Identifier::print()
|
||||
{
|
||||
fprintf(stdmsg, "%s",string);
|
||||
}
|
||||
|
||||
int Identifier::dyncast()
|
||||
{
|
||||
return DYNCAST_IDENTIFIER;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
buf.writestring(prefix);
|
||||
buf.printf("%zu", i);
|
||||
|
||||
char *id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return Lexer::idPool(id);
|
||||
}
|
||||
47
dmd2/identifier.h
Normal file
47
dmd2/identifier.h
Normal file
@@ -0,0 +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
|
||||
const char *toHChars2();
|
||||
int dyncast();
|
||||
|
||||
static Identifier *generateId(const char *prefix);
|
||||
static Identifier *generateId(const char *prefix, size_t i);
|
||||
};
|
||||
|
||||
#endif /* DMD_IDENTIFIER_H */
|
||||
355
dmd2/idgen.c
Normal file
355
dmd2/idgen.c
Normal file
@@ -0,0 +1,355 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
// Program to generate string files in d data structures.
|
||||
// Saves much tedious typing, and eliminates typo problems.
|
||||
// Generates:
|
||||
// id.h
|
||||
// id.c
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct Msgtable
|
||||
{
|
||||
const char *ident; // name to use in DMD source
|
||||
const char *name; // name in D executable
|
||||
};
|
||||
|
||||
Msgtable msgtable[] =
|
||||
{
|
||||
{ "IUnknown" },
|
||||
{ "Object" },
|
||||
{ "object" },
|
||||
{ "max" },
|
||||
{ "min" },
|
||||
{ "This", "this" },
|
||||
{ "ctor", "__ctor" },
|
||||
{ "dtor", "__dtor" },
|
||||
{ "cpctor", "__cpctor" },
|
||||
{ "_postblit", "__postblit" },
|
||||
{ "classInvariant", "__invariant" },
|
||||
{ "unitTest", "__unitTest" },
|
||||
{ "init" },
|
||||
{ "size" },
|
||||
{ "__sizeof", "sizeof" },
|
||||
{ "alignof" },
|
||||
{ "mangleof" },
|
||||
{ "stringof" },
|
||||
{ "tupleof" },
|
||||
{ "length" },
|
||||
{ "remove" },
|
||||
{ "ptr" },
|
||||
{ "funcptr" },
|
||||
{ "dollar", "__dollar" },
|
||||
{ "offset" },
|
||||
{ "offsetof" },
|
||||
{ "ModuleInfo" },
|
||||
{ "ClassInfo" },
|
||||
{ "classinfo" },
|
||||
{ "typeinfo" },
|
||||
{ "outer" },
|
||||
{ "Exception" },
|
||||
{ "withSym", "__withSym" },
|
||||
{ "result", "__result" },
|
||||
{ "returnLabel", "__returnLabel" },
|
||||
{ "delegate" },
|
||||
{ "line" },
|
||||
{ "empty", "" },
|
||||
{ "p" },
|
||||
{ "coverage", "__coverage" },
|
||||
{ "__vptr" },
|
||||
{ "__monitor" },
|
||||
|
||||
{ "TypeInfo" },
|
||||
{ "TypeInfo_Class" },
|
||||
{ "TypeInfo_Interface" },
|
||||
{ "TypeInfo_Struct" },
|
||||
{ "TypeInfo_Enum" },
|
||||
{ "TypeInfo_Typedef" },
|
||||
{ "TypeInfo_Pointer" },
|
||||
{ "TypeInfo_Array" },
|
||||
{ "TypeInfo_StaticArray" },
|
||||
{ "TypeInfo_AssociativeArray" },
|
||||
{ "TypeInfo_Function" },
|
||||
{ "TypeInfo_Delegate" },
|
||||
{ "TypeInfo_Tuple" },
|
||||
{ "TypeInfo_Const" },
|
||||
{ "TypeInfo_Invariant" },
|
||||
{ "elements" },
|
||||
{ "_arguments_typeinfo" },
|
||||
{ "_arguments" },
|
||||
{ "_argptr" },
|
||||
{ "_match" },
|
||||
{ "destroy" },
|
||||
{ "postblit" },
|
||||
|
||||
{ "LINE", "__LINE__" },
|
||||
{ "FILE", "__FILE__" },
|
||||
{ "DATE", "__DATE__" },
|
||||
{ "TIME", "__TIME__" },
|
||||
{ "TIMESTAMP", "__TIMESTAMP__" },
|
||||
{ "VENDOR", "__VENDOR__" },
|
||||
{ "VERSIONX", "__VERSION__" },
|
||||
{ "EOFX", "__EOF__" },
|
||||
|
||||
{ "nan" },
|
||||
{ "infinity" },
|
||||
{ "dig" },
|
||||
{ "epsilon" },
|
||||
{ "mant_dig" },
|
||||
{ "max_10_exp" },
|
||||
{ "max_exp" },
|
||||
{ "min_10_exp" },
|
||||
{ "min_exp" },
|
||||
{ "re" },
|
||||
{ "im" },
|
||||
|
||||
{ "C" },
|
||||
{ "D" },
|
||||
{ "Windows" },
|
||||
{ "Pascal" },
|
||||
{ "System" },
|
||||
|
||||
{ "exit" },
|
||||
{ "success" },
|
||||
{ "failure" },
|
||||
|
||||
{ "keys" },
|
||||
{ "values" },
|
||||
{ "rehash" },
|
||||
|
||||
{ "sort" },
|
||||
{ "reverse" },
|
||||
{ "dup" },
|
||||
{ "idup" },
|
||||
|
||||
// For inline assembler
|
||||
{ "___out", "out" },
|
||||
{ "___in", "in" },
|
||||
{ "__int", "int" },
|
||||
{ "__dollar", "$" },
|
||||
{ "__LOCAL_SIZE" },
|
||||
|
||||
// For operator overloads
|
||||
{ "uadd", "opPos" },
|
||||
{ "neg", "opNeg" },
|
||||
{ "com", "opCom" },
|
||||
{ "add", "opAdd" },
|
||||
{ "add_r", "opAdd_r" },
|
||||
{ "sub", "opSub" },
|
||||
{ "sub_r", "opSub_r" },
|
||||
{ "mul", "opMul" },
|
||||
{ "mul_r", "opMul_r" },
|
||||
{ "div", "opDiv" },
|
||||
{ "div_r", "opDiv_r" },
|
||||
{ "mod", "opMod" },
|
||||
{ "mod_r", "opMod_r" },
|
||||
{ "eq", "opEquals" },
|
||||
{ "cmp", "opCmp" },
|
||||
{ "iand", "opAnd" },
|
||||
{ "iand_r", "opAnd_r" },
|
||||
{ "ior", "opOr" },
|
||||
{ "ior_r", "opOr_r" },
|
||||
{ "ixor", "opXor" },
|
||||
{ "ixor_r", "opXor_r" },
|
||||
{ "shl", "opShl" },
|
||||
{ "shl_r", "opShl_r" },
|
||||
{ "shr", "opShr" },
|
||||
{ "shr_r", "opShr_r" },
|
||||
{ "ushr", "opUShr" },
|
||||
{ "ushr_r", "opUShr_r" },
|
||||
{ "cat", "opCat" },
|
||||
{ "cat_r", "opCat_r" },
|
||||
{ "assign", "opAssign" },
|
||||
{ "addass", "opAddAssign" },
|
||||
{ "subass", "opSubAssign" },
|
||||
{ "mulass", "opMulAssign" },
|
||||
{ "divass", "opDivAssign" },
|
||||
{ "modass", "opModAssign" },
|
||||
{ "andass", "opAndAssign" },
|
||||
{ "orass", "opOrAssign" },
|
||||
{ "xorass", "opXorAssign" },
|
||||
{ "shlass", "opShlAssign" },
|
||||
{ "shrass", "opShrAssign" },
|
||||
{ "ushrass", "opUShrAssign" },
|
||||
{ "catass", "opCatAssign" },
|
||||
{ "postinc", "opPostInc" },
|
||||
{ "postdec", "opPostDec" },
|
||||
{ "index", "opIndex" },
|
||||
{ "indexass", "opIndexAssign" },
|
||||
{ "slice", "opSlice" },
|
||||
{ "sliceass", "opSliceAssign" },
|
||||
{ "call", "opCall" },
|
||||
{ "cast", "opCast" },
|
||||
{ "match", "opMatch" },
|
||||
{ "next", "opNext" },
|
||||
{ "opIn" },
|
||||
{ "opIn_r" },
|
||||
{ "opStar" },
|
||||
{ "opDot" },
|
||||
{ "opImplicitCast" },
|
||||
|
||||
{ "classNew", "new" },
|
||||
{ "classDelete", "delete" },
|
||||
|
||||
// For foreach
|
||||
{ "apply", "opApply" },
|
||||
{ "applyReverse", "opApplyReverse" },
|
||||
|
||||
{ "adDup", "_adDupT" },
|
||||
{ "adReverse", "_adReverse" },
|
||||
|
||||
// For internal functions
|
||||
{ "aaLen", "_aaLen" },
|
||||
{ "aaKeys", "_aaKeys" },
|
||||
{ "aaValues", "_aaValues" },
|
||||
{ "aaRehash", "_aaRehash" },
|
||||
|
||||
// For pragma's
|
||||
{ "GNU_asm" },
|
||||
{ "lib" },
|
||||
{ "msg" },
|
||||
{ "startaddress" },
|
||||
|
||||
// LDC pragma's
|
||||
{ "intrinsic" },
|
||||
{ "va_intrinsic" },
|
||||
{ "no_typeinfo" },
|
||||
{ "no_moduleinfo" },
|
||||
{ "Alloca", "alloca" },
|
||||
{ "vastart", "va_start" },
|
||||
{ "vacopy", "va_copy" },
|
||||
{ "vaend", "va_end" },
|
||||
{ "vaarg", "va_arg" },
|
||||
{ "ldc" },
|
||||
|
||||
// For special functions
|
||||
{ "tohash", "toHash" },
|
||||
{ "tostring", "toString" },
|
||||
{ "getmembers", "getMembers" },
|
||||
|
||||
// Special functions
|
||||
//{ "alloca" },
|
||||
{ "main" },
|
||||
{ "WinMain" },
|
||||
{ "DllMain" },
|
||||
|
||||
// Builtin functions
|
||||
{ "std" },
|
||||
{ "math" },
|
||||
{ "sin" },
|
||||
{ "cos" },
|
||||
{ "tan" },
|
||||
{ "_sqrt", "sqrt" },
|
||||
{ "fabs" },
|
||||
|
||||
// Traits
|
||||
{ "isAbstractClass" },
|
||||
{ "isArithmetic" },
|
||||
{ "isAssociativeArray" },
|
||||
{ "isFinalClass" },
|
||||
{ "isFloating" },
|
||||
{ "isIntegral" },
|
||||
{ "isScalar" },
|
||||
{ "isStaticArray" },
|
||||
{ "isUnsigned" },
|
||||
{ "isVirtualFunction" },
|
||||
{ "isAbstractFunction" },
|
||||
{ "isFinalFunction" },
|
||||
{ "hasMember" },
|
||||
{ "getMember" },
|
||||
{ "getVirtualFunctions" },
|
||||
{ "classInstanceSize" },
|
||||
{ "allMembers" },
|
||||
{ "derivedMembers" },
|
||||
{ "isSame" },
|
||||
{ "compiles" },
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned i;
|
||||
|
||||
{
|
||||
fp = fopen("id.h","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.h\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
#if __DMC__
|
||||
fprintf(fp, "#pragma once\n");
|
||||
#endif
|
||||
fprintf(fp, "#ifndef DMD_ID_H\n");
|
||||
fprintf(fp, "#define DMD_ID_H 1\n");
|
||||
fprintf(fp, "struct Identifier;\n");
|
||||
fprintf(fp, "struct Id\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
|
||||
fprintf(fp," static Identifier *%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, " static void initialize();\n");
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
{
|
||||
fp = fopen("id.c","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.c\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
fprintf(fp, "#include \"id.h\"\n");
|
||||
fprintf(fp, "#include \"identifier.h\"\n");
|
||||
fprintf(fp, "#include \"lexer.h\"\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp,"Identifier *Id::%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, "void Id::initialize()\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
|
||||
}
|
||||
|
||||
fprintf(fp, "}\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
462
dmd2/impcnvgen.c
Normal file
462
dmd2/impcnvgen.c
Normal file
@@ -0,0 +1,462 @@
|
||||
|
||||
// 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.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mtype.h"
|
||||
|
||||
TY impcnvResult[TMAX][TMAX];
|
||||
TY impcnvType1[TMAX][TMAX];
|
||||
TY impcnvType2[TMAX][TMAX];
|
||||
int impcnvWarn[TMAX][TMAX];
|
||||
|
||||
int integral_promotion(int t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case Tchar:
|
||||
case Twchar:
|
||||
//case Tbit:
|
||||
case Tbool:
|
||||
case Tint8:
|
||||
case Tuns8:
|
||||
case Tint16:
|
||||
case Tuns16: return Tint32;
|
||||
case Tdchar: return Tuns32;
|
||||
default: return t;
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{ int i, j;
|
||||
|
||||
// Set conversion tables
|
||||
for (i = 0; i < TMAX; i++)
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{ impcnvResult[i][j] = Terror;
|
||||
impcnvType1[i][j] = Terror;
|
||||
impcnvType2[i][j] = Terror;
|
||||
impcnvWarn[i][j] = 0;
|
||||
}
|
||||
|
||||
#define X(t1,t2, nt1,nt2, rt) \
|
||||
impcnvResult[t1][t2] = rt; \
|
||||
impcnvType1[t1][t2] = nt1; \
|
||||
impcnvType2[t1][t2] = nt2;
|
||||
|
||||
/* ======================= */
|
||||
|
||||
#if 0
|
||||
X(Tbit,Tbit, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tint8, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tuns8, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tint16, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tbit,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
#endif
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tbool,Tbool, Tbool,Tbool, Tbool)
|
||||
X(Tbool,Tint8, Tint32,Tint32, Tint32)
|
||||
X(Tbool,Tuns8, Tint32,Tint32, Tint32)
|
||||
X(Tbool,Tint16, Tint32,Tint32, Tint32)
|
||||
X(Tbool,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tbool,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tbool,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tbool,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tbool,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tbool,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tbool,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tbool,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tbool,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tbool,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tbool,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tbool,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tbool,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tbool,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tint8,Tint8, Tint32,Tint32, Tint32)
|
||||
X(Tint8,Tuns8, Tint32,Tint32, Tint32)
|
||||
X(Tint8,Tint16, Tint32,Tint32, Tint32)
|
||||
X(Tint8,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tint8,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tint8,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tuns8,Tuns8, Tint32,Tint32, Tint32)
|
||||
X(Tuns8,Tint16, Tint32,Tint32, Tint32)
|
||||
X(Tuns8,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tuns8,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tuns8,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tint16,Tint16, Tint32,Tint32, Tint32)
|
||||
X(Tint16,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tint16,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tint16,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tuns16,Tuns16, Tint32,Tint32, Tint32)
|
||||
X(Tuns16,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tuns16,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tint32,Tint32, Tint32,Tint32, Tint32)
|
||||
X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tint32,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32)
|
||||
X(Tuns32,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tint64,Tint64, Tint64,Tint64, Tint64)
|
||||
X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64)
|
||||
|
||||
X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
|
||||
X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
|
||||
X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
|
||||
X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
|
||||
X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
|
||||
X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
|
||||
X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
|
||||
X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
|
||||
X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
|
||||
X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
|
||||
X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
|
||||
|
||||
X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80)
|
||||
X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
|
||||
|
||||
X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32)
|
||||
X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
|
||||
X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
|
||||
|
||||
X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32)
|
||||
X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
|
||||
X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
|
||||
X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
|
||||
|
||||
X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64)
|
||||
X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
|
||||
X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
|
||||
|
||||
X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80)
|
||||
X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80)
|
||||
X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32)
|
||||
X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
|
||||
X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
|
||||
X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
|
||||
|
||||
/* ======================= */
|
||||
|
||||
X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
|
||||
|
||||
#undef X
|
||||
|
||||
#define Y(t1,t2) impcnvWarn[t1][t2] = 1;
|
||||
|
||||
#if 0
|
||||
Y(Tint8, Tbit)
|
||||
Y(Tuns8, Tbit)
|
||||
Y(Tint16, Tbit)
|
||||
Y(Tuns16, Tbit)
|
||||
Y(Tint32, Tbit)
|
||||
Y(Tuns32, Tbit)
|
||||
Y(Tint64, Tbit)
|
||||
Y(Tuns64, Tbit)
|
||||
#endif
|
||||
|
||||
Y(Tuns8, Tint8)
|
||||
Y(Tint16, Tint8)
|
||||
Y(Tuns16, Tint8)
|
||||
Y(Tint32, Tint8)
|
||||
Y(Tuns32, Tint8)
|
||||
Y(Tint64, Tint8)
|
||||
Y(Tuns64, Tint8)
|
||||
|
||||
Y(Tint8, Tuns8)
|
||||
Y(Tint16, Tuns8)
|
||||
Y(Tuns16, Tuns8)
|
||||
Y(Tint32, Tuns8)
|
||||
Y(Tuns32, Tuns8)
|
||||
Y(Tint64, Tuns8)
|
||||
Y(Tuns64, Tuns8)
|
||||
|
||||
Y(Tint8, Tchar)
|
||||
Y(Tint16, Tchar)
|
||||
Y(Tuns16, Tchar)
|
||||
Y(Tint32, Tchar)
|
||||
Y(Tuns32, Tchar)
|
||||
Y(Tint64, Tchar)
|
||||
Y(Tuns64, Tchar)
|
||||
|
||||
Y(Tuns16, Tint16)
|
||||
Y(Tint32, Tint16)
|
||||
Y(Tuns32, Tint16)
|
||||
Y(Tint64, Tint16)
|
||||
Y(Tuns64, Tint16)
|
||||
|
||||
Y(Tint16, Tuns16)
|
||||
Y(Tint32, Tuns16)
|
||||
Y(Tuns32, Tuns16)
|
||||
Y(Tint64, Tuns16)
|
||||
Y(Tuns64, Tuns16)
|
||||
|
||||
Y(Tint16, Twchar)
|
||||
Y(Tint32, Twchar)
|
||||
Y(Tuns32, Twchar)
|
||||
Y(Tint64, Twchar)
|
||||
Y(Tuns64, Twchar)
|
||||
|
||||
// Y(Tuns32, Tint32)
|
||||
Y(Tint64, Tint32)
|
||||
Y(Tuns64, Tint32)
|
||||
|
||||
// Y(Tint32, Tuns32)
|
||||
Y(Tint64, Tuns32)
|
||||
Y(Tuns64, Tuns32)
|
||||
|
||||
Y(Tint64, Tdchar)
|
||||
Y(Tuns64, Tdchar)
|
||||
|
||||
Y(Tint64, Tuns64)
|
||||
Y(Tuns64, Tint64)
|
||||
|
||||
for (i = 0; i < TMAX; i++)
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{
|
||||
if (impcnvResult[i][j] == Terror)
|
||||
{
|
||||
impcnvResult[i][j] = impcnvResult[j][i];
|
||||
impcnvType1[i][j] = impcnvType2[j][i];
|
||||
impcnvType2[i][j] = impcnvType1[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{ FILE *fp;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
init();
|
||||
|
||||
fp = fopen("impcnvtab.c","w");
|
||||
|
||||
fprintf(fp,"// This file is generated by impcnvgen.c\n");
|
||||
fprintf(fp,"#include \"mtype.h\"\n");
|
||||
|
||||
fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n");
|
||||
for (i = 0; i < TMAX; i++)
|
||||
{
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{
|
||||
fprintf(fp, "%d,",impcnvResult[i][j]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
|
||||
fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n");
|
||||
for (i = 0; i < TMAX; i++)
|
||||
{
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{
|
||||
fprintf(fp, "%d,",impcnvType1[i][j]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
|
||||
fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n");
|
||||
for (i = 0; i < TMAX; i++)
|
||||
{
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{
|
||||
fprintf(fp, "%d,",impcnvType2[i][j]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
|
||||
fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n");
|
||||
for (i = 0; i < TMAX; i++)
|
||||
{
|
||||
for (j = 0; j < TMAX; j++)
|
||||
{
|
||||
fprintf(fp, "%d,",impcnvWarn[i][j]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
|
||||
fclose(fp);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
182
dmd2/impcnvtab.c
Normal file
182
dmd2/impcnvtab.c
Normal file
@@ -0,0 +1,182 @@
|
||||
// This file is generated by impcnvgen.c
|
||||
#include "mtype.h"
|
||||
unsigned char Type::impcnvResult[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvType1[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,36,25,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,36,26,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,27,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvType2[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvWarn[TMAX][TMAX] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
275
dmd2/import.c
Normal file
275
dmd2/import.c
Normal file
@@ -0,0 +1,275 @@
|
||||
|
||||
// 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.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
#include "import.h"
|
||||
#include "identifier.h"
|
||||
#include "module.h"
|
||||
#include "scope.h"
|
||||
#include "hdrgen.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "id.h"
|
||||
|
||||
/********************************* Import ****************************/
|
||||
|
||||
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic)
|
||||
: Dsymbol(id)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
this->aliasId = aliasId;
|
||||
this->isstatic = isstatic;
|
||||
protection = PROTundefined;
|
||||
pkg = NULL;
|
||||
mod = NULL;
|
||||
|
||||
if (aliasId)
|
||||
this->ident = aliasId;
|
||||
// Kludge to change Import identifier to first package
|
||||
else if (packages && packages->dim)
|
||||
this->ident = (Identifier *)packages->data[0];
|
||||
}
|
||||
|
||||
void Import::addAlias(Identifier *name, Identifier *alias)
|
||||
{
|
||||
if (isstatic)
|
||||
error("cannot have an import bind list");
|
||||
|
||||
if (!aliasId)
|
||||
this->ident = NULL; // make it an anonymous import
|
||||
|
||||
names.push(name);
|
||||
aliases.push(alias);
|
||||
}
|
||||
|
||||
const char *Import::kind()
|
||||
{
|
||||
return isstatic ? (char *)"static import" : (char *)"import";
|
||||
}
|
||||
|
||||
enum PROT Import::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
|
||||
Dsymbol *Import::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
|
||||
Import *si;
|
||||
|
||||
si = new Import(loc, packages, id, aliasId, isstatic);
|
||||
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
void Import::load(Scope *sc)
|
||||
{
|
||||
DsymbolTable *dst;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("Import::load('%s')\n", toChars());
|
||||
|
||||
// See if existing module
|
||||
dst = Package::resolve(packages, NULL, &pkg);
|
||||
|
||||
s = dst->lookup(id);
|
||||
if (s)
|
||||
{
|
||||
if (s->isModule())
|
||||
mod = (Module *)s;
|
||||
else
|
||||
error("package and module have the same name");
|
||||
}
|
||||
|
||||
if (!mod)
|
||||
{
|
||||
// Load module
|
||||
mod = Module::load(loc, packages, id);
|
||||
dst->insert(id, mod); // id may be different from mod->ident,
|
||||
// if so then insert alias
|
||||
if (!mod->importedFrom)
|
||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||
}
|
||||
if (!pkg)
|
||||
pkg = mod;
|
||||
mod->semantic();
|
||||
|
||||
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
|
||||
void Import::semantic(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic('%s')\n", toChars());
|
||||
|
||||
load(sc);
|
||||
|
||||
if (mod)
|
||||
{
|
||||
#if 0
|
||||
if (mod->loc.linnum != 0)
|
||||
{ /* If the line number is not 0, then this is not
|
||||
* a 'root' module, i.e. it was not specified on the command line.
|
||||
*/
|
||||
mod->importedFrom = sc->module->importedFrom;
|
||||
assert(mod->importedFrom);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Default to private importing
|
||||
*/
|
||||
protection = sc->protection;
|
||||
if (!sc->explicitProtection)
|
||||
protection = PROTprivate;
|
||||
|
||||
if (!isstatic && !aliasId && !names.dim)
|
||||
{
|
||||
sc->scopesym->importScope(mod, protection);
|
||||
}
|
||||
|
||||
// Modules need a list of each imported module
|
||||
sc->module->aimports.push(mod);
|
||||
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
|
||||
sc = sc->push(mod);
|
||||
for (size_t i = 0; i < aliasdecls.dim; i++)
|
||||
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
|
||||
|
||||
//printf("\tImport alias semantic('%s')\n", s->toChars());
|
||||
if (!mod->search(loc, (Identifier *)names.data[i], 0))
|
||||
error("%s not found", ((Identifier *)names.data[i])->toChars());
|
||||
|
||||
ad->semantic(sc);
|
||||
ad->protection = protection;
|
||||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
void Import::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic2('%s')\n", toChars());
|
||||
mod->semantic2();
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
}
|
||||
|
||||
Dsymbol *Import::toAlias()
|
||||
{
|
||||
if (aliasId)
|
||||
return mod;
|
||||
return this;
|
||||
}
|
||||
|
||||
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (names.dim == 0)
|
||||
return Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
if (aliasId)
|
||||
result = Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
|
||||
if (!alias)
|
||||
alias = name;
|
||||
|
||||
#if 1
|
||||
TypeIdentifier *tname = new TypeIdentifier(loc, name);
|
||||
#else
|
||||
TypeIdentifier *tname = new TypeIdentifier(loc, NULL);
|
||||
if (packages)
|
||||
{
|
||||
for (size_t j = 0; j < packages->dim; j++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[j];
|
||||
|
||||
if (!tname->ident)
|
||||
tname->ident = pid;
|
||||
else
|
||||
tname->addIdent(pid);
|
||||
}
|
||||
}
|
||||
if (!tname->ident)
|
||||
tname->ident = id;
|
||||
else
|
||||
tname->addIdent(id);
|
||||
tname->addIdent(name);
|
||||
#endif
|
||||
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
|
||||
result |= ad->addMember(sc, sd, memnum);
|
||||
|
||||
aliasdecls.push(ad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
|
||||
|
||||
if (!pkg)
|
||||
load(NULL);
|
||||
|
||||
// Forward it to the package/module
|
||||
return pkg->search(loc, ident, flags);
|
||||
}
|
||||
|
||||
int Import::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
// Allow multiple imports of the same name
|
||||
return s->isImport() != NULL;
|
||||
}
|
||||
|
||||
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (hgs->hdrgen && id == Id::object)
|
||||
return; // object is imported by default
|
||||
|
||||
if (isstatic)
|
||||
buf->writestring("static ");
|
||||
buf->writestring("import ");
|
||||
if (aliasId)
|
||||
{
|
||||
buf->printf("%s = ", aliasId->toChars());
|
||||
}
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
|
||||
buf->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
buf->printf("%s;", id->toChars());
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
67
dmd2/import.h
Normal file
67
dmd2/import.h
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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_IMPORT_H
|
||||
#define DMD_IMPORT_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
|
||||
struct Identifier;
|
||||
struct Scope;
|
||||
struct OutBuffer;
|
||||
struct Module;
|
||||
struct Package;
|
||||
struct AliasDeclaration;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
struct Import : Dsymbol
|
||||
{
|
||||
Array *packages; // array of Identifier's representing packages
|
||||
Identifier *id; // module Identifier
|
||||
Identifier *aliasId;
|
||||
int isstatic; // !=0 if static import
|
||||
enum PROT protection;
|
||||
|
||||
// Pairs of alias=name to bind into current namespace
|
||||
Array names;
|
||||
Array aliases;
|
||||
|
||||
Array aliasdecls; // AliasDeclarations for names/aliases
|
||||
|
||||
Module *mod;
|
||||
Package *pkg; // leftmost package/module
|
||||
|
||||
Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic);
|
||||
void addAlias(Identifier *name, Identifier *alias);
|
||||
|
||||
const char *kind();
|
||||
enum PROT prot();
|
||||
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
void load(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
Dsymbol *toAlias();
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Import *isImport() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_IMPORT_H */
|
||||
300
dmd2/inifile.c
Normal file
300
dmd2/inifile.c
Normal file
@@ -0,0 +1,300 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "mem.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#define LOG 0
|
||||
|
||||
char *skipspace(const char *p);
|
||||
|
||||
#if __GNUC__
|
||||
char *strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#endif /* unix */
|
||||
|
||||
/*****************************
|
||||
* Read and analyze .ini file.
|
||||
* Input:
|
||||
* argv0 program name (argv[0])
|
||||
* inifile .ini file name
|
||||
*/
|
||||
|
||||
void inifile(const char *argv0x, const char *inifilex)
|
||||
{
|
||||
char *argv0 = (char *)argv0x;
|
||||
char *inifile = (char *)inifilex; // do const-correct later
|
||||
char *path; // need path for @P macro
|
||||
char *filename;
|
||||
OutBuffer buf;
|
||||
int i;
|
||||
int k;
|
||||
int envsection = 0;
|
||||
|
||||
#if LOG
|
||||
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
|
||||
#endif
|
||||
if (FileName::absolute(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for inifile in the following sequence of places:
|
||||
* o current directory
|
||||
* o home directory
|
||||
* o directory off of argv0
|
||||
* o /etc/
|
||||
*/
|
||||
if (FileName::exists(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = FileName::combine(getenv("HOME"), inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
filename = FileName::replaceName(argv0, inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
#if POSIX
|
||||
|
||||
#if 0
|
||||
#if __GLIBC__ // This fix by Thomas Kuehne
|
||||
/* argv0 might be a symbolic link,
|
||||
* so try again looking past it to the real path
|
||||
*/
|
||||
char* real_argv0 = realpath(argv0, NULL);
|
||||
if (real_argv0)
|
||||
{
|
||||
filename = FileName::replaceName(real_argv0, inifile);
|
||||
free(real_argv0);
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
}
|
||||
#else
|
||||
#error use of glibc non-standard extension realpath(char*, NULL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// old way; problem is that argv0 might not be on the PATH at all
|
||||
// and some other instance might be found
|
||||
|
||||
// Search PATH for argv0
|
||||
const char *p = getenv("PATH");
|
||||
Array *paths = FileName::splitPath(p);
|
||||
filename = FileName::searchPath(paths, argv0, 0);
|
||||
if (!filename)
|
||||
goto Letc; // argv0 not found on path
|
||||
filename = FileName::replaceName(filename, inifile);
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
#endif
|
||||
|
||||
// Search /etc/ for inifile
|
||||
Letc:
|
||||
filename = FileName::combine((char *)"/etc/", inifile);
|
||||
|
||||
Ldone:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
path = FileName::path(filename);
|
||||
#if LOG
|
||||
printf("\tpath = '%s', filename = '%s'\n", path, filename);
|
||||
#endif
|
||||
|
||||
File file(filename);
|
||||
|
||||
if (file.read())
|
||||
return; // error reading file
|
||||
|
||||
// Parse into lines
|
||||
int eof = 0;
|
||||
for (i = 0; i < file.len && !eof; i++)
|
||||
{
|
||||
int linestart = i;
|
||||
|
||||
for (; i < file.len; i++)
|
||||
{
|
||||
switch (file.buffer[i])
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
// Skip if it was preceded by '\r'
|
||||
if (i && file.buffer[i - 1] == '\r')
|
||||
goto Lskip;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 0x1A:
|
||||
eof = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The line is file.buffer[linestart..i]
|
||||
char *line;
|
||||
int len;
|
||||
char *p;
|
||||
char *pn;
|
||||
|
||||
line = (char *)&file.buffer[linestart];
|
||||
len = i - linestart;
|
||||
|
||||
buf.reset();
|
||||
|
||||
// First, expand the macros.
|
||||
// Macros are bracketed by % characters.
|
||||
|
||||
for (k = 0; k < len; k++)
|
||||
{
|
||||
if (line[k] == '%')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = k + 1; j < len; j++)
|
||||
{
|
||||
if (line[j] == '%')
|
||||
{
|
||||
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
|
||||
{
|
||||
// %@P% is special meaning the path to the .ini file
|
||||
p = path;
|
||||
if (!*p)
|
||||
p = (char *)".";
|
||||
}
|
||||
else
|
||||
{ int len = j - k;
|
||||
char tmp[10]; // big enough most of the time
|
||||
|
||||
if (len <= sizeof(tmp))
|
||||
p = tmp;
|
||||
else
|
||||
p = (char *)alloca(len);
|
||||
len--;
|
||||
memcpy(p, &line[k + 1], len);
|
||||
p[len] = 0;
|
||||
strupr(p);
|
||||
p = getenv(p);
|
||||
if (!p)
|
||||
p = (char *)"";
|
||||
}
|
||||
buf.writestring(p);
|
||||
k = j;
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.writeByte(line[k]);
|
||||
L1:
|
||||
;
|
||||
}
|
||||
|
||||
// Remove trailing spaces
|
||||
while (buf.offset && isspace(buf.data[buf.offset - 1]))
|
||||
buf.offset--;
|
||||
|
||||
p = buf.toChars();
|
||||
|
||||
// The expanded line is in p.
|
||||
// Now parse it for meaning.
|
||||
|
||||
p = skipspace(p);
|
||||
switch (*p)
|
||||
{
|
||||
case ';': // comment
|
||||
case 0: // blank
|
||||
break;
|
||||
|
||||
case '[': // look for [Environment]
|
||||
p = skipspace(p + 1);
|
||||
for (pn = p; isalnum(*pn); pn++)
|
||||
;
|
||||
if (pn - p == 11 &&
|
||||
memicmp(p, "Environment", 11) == 0 &&
|
||||
*skipspace(pn) == ']'
|
||||
)
|
||||
envsection = 1;
|
||||
else
|
||||
envsection = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (envsection)
|
||||
{
|
||||
pn = p;
|
||||
|
||||
// Convert name to upper case;
|
||||
// remove spaces bracketing =
|
||||
for (p = pn; *p; p++)
|
||||
{ if (islower(*p))
|
||||
*p &= ~0x20;
|
||||
else if (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
else if (*p == '=')
|
||||
{
|
||||
p++;
|
||||
while (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
putenv(strdup(pn));
|
||||
#if LOG
|
||||
printf("\tputenv('%s')\n", pn);
|
||||
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Lskip:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Skip spaces.
|
||||
*/
|
||||
|
||||
char *skipspace(const char *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
597
dmd2/init.c
Normal file
597
dmd2/init.c
Normal file
@@ -0,0 +1,597 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "init.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "identifier.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "hdrgen.h"
|
||||
|
||||
/********************************** Initializer *******************************/
|
||||
|
||||
Initializer::Initializer(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
Initializer *Initializer::syntaxCopy()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Initializer *Initializer::semantic(Scope *sc, Type *t)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Type *Initializer::inferType(Scope *sc)
|
||||
{
|
||||
error(loc, "cannot infer type from initializer");
|
||||
return Type::terror;
|
||||
}
|
||||
|
||||
Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
|
||||
{ Initializers *a = NULL;
|
||||
|
||||
if (ai)
|
||||
{
|
||||
a = new Initializers();
|
||||
a->setDim(ai->dim);
|
||||
for (int i = 0; i < a->dim; i++)
|
||||
{ Initializer *e = (Initializer *)ai->data[i];
|
||||
|
||||
e = e->syntaxCopy();
|
||||
a->data[i] = e;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
char *Initializer::toChars()
|
||||
{ OutBuffer *buf;
|
||||
HdrGenState hgs;
|
||||
|
||||
memset(&hgs, 0, sizeof(hgs));
|
||||
buf = new OutBuffer();
|
||||
toCBuffer(buf, &hgs);
|
||||
return buf->toChars();
|
||||
}
|
||||
|
||||
/********************************** VoidInitializer ***************************/
|
||||
|
||||
VoidInitializer::VoidInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
type = NULL;
|
||||
}
|
||||
|
||||
|
||||
Initializer *VoidInitializer::syntaxCopy()
|
||||
{
|
||||
return new VoidInitializer(loc);
|
||||
}
|
||||
|
||||
|
||||
Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
|
||||
{
|
||||
//printf("VoidInitializer::semantic(t = %p)\n", t);
|
||||
type = t;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Expression *VoidInitializer::toExpression()
|
||||
{
|
||||
error(loc, "void initializer has no value");
|
||||
return new IntegerExp(0);
|
||||
}
|
||||
|
||||
|
||||
void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("void");
|
||||
}
|
||||
|
||||
|
||||
/********************************** StructInitializer *************************/
|
||||
|
||||
StructInitializer::StructInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
ad = NULL;
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::syntaxCopy()
|
||||
{
|
||||
StructInitializer *ai = new StructInitializer(loc);
|
||||
|
||||
assert(field.dim == value.dim);
|
||||
ai->field.setDim(field.dim);
|
||||
ai->value.setDim(value.dim);
|
||||
for (int i = 0; i < field.dim; i++)
|
||||
{
|
||||
ai->field.data[i] = field.data[i];
|
||||
|
||||
Initializer *init = (Initializer *)value.data[i];
|
||||
init = init->syntaxCopy();
|
||||
ai->value.data[i] = init;
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
|
||||
void StructInitializer::addInit(Identifier *field, Initializer *value)
|
||||
{
|
||||
//printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
|
||||
this->field.push(field);
|
||||
this->value.push(value);
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
||||
{
|
||||
TypeStruct *ts;
|
||||
int errors = 0;
|
||||
|
||||
//printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
|
||||
vars.setDim(field.dim);
|
||||
t = t->toBasetype();
|
||||
if (t->ty == Tstruct)
|
||||
{ unsigned i;
|
||||
unsigned fieldi = 0;
|
||||
|
||||
ts = (TypeStruct *)t;
|
||||
ad = ts->sym;
|
||||
for (i = 0; i < field.dim; i++)
|
||||
{
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
Initializer *val = (Initializer *)value.data[i];
|
||||
Dsymbol *s;
|
||||
VarDeclaration *v;
|
||||
|
||||
if (id == NULL)
|
||||
{
|
||||
if (fieldi >= ad->fields.dim)
|
||||
{ error(loc, "too many initializers for %s", ad->toChars());
|
||||
field.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = (Dsymbol *)ad->fields.data[fieldi];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//s = ad->symtab->lookup(id);
|
||||
s = ad->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find out which field index it is
|
||||
for (fieldi = 0; 1; fieldi++)
|
||||
{
|
||||
if (fieldi >= ad->fields.dim)
|
||||
{
|
||||
s->error("is not a per-instance initializable field");
|
||||
break;
|
||||
}
|
||||
if (s == (Dsymbol *)ad->fields.data[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||
{
|
||||
val = val->semantic(sc, v->type);
|
||||
value.data[i] = (void *)val;
|
||||
vars.data[i] = (void *)v;
|
||||
}
|
||||
else
|
||||
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
|
||||
errors = 1;
|
||||
}
|
||||
fieldi++;
|
||||
}
|
||||
}
|
||||
else if (t->ty == Tdelegate && value.dim == 0)
|
||||
{ /* Rewrite as empty delegate literal { }
|
||||
*/
|
||||
Arguments *arguments = new Arguments;
|
||||
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
|
||||
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
|
||||
fd->fbody = new CompoundStatement(loc, new Statements());
|
||||
fd->endloc = loc;
|
||||
Expression *e = new FuncExp(loc, fd);
|
||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||
return ie->semantic(sc, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
|
||||
errors = 1;
|
||||
}
|
||||
if (errors)
|
||||
{
|
||||
field.setDim(0);
|
||||
value.setDim(0);
|
||||
vars.setDim(0);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* This works by transforming a struct initializer into
|
||||
* a struct literal. In the future, the two should be the
|
||||
* same thing.
|
||||
*/
|
||||
Expression *StructInitializer::toExpression()
|
||||
{ Expression *e;
|
||||
|
||||
//printf("StructInitializer::toExpression() %s\n", toChars());
|
||||
if (!ad) // if fwd referenced
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
StructDeclaration *sd = ad->isStructDeclaration();
|
||||
if (!sd)
|
||||
return NULL;
|
||||
Expressions *elements = new Expressions();
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
if (field.data[i])
|
||||
goto Lno;
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
Expression *ex = iz->toExpression();
|
||||
if (!ex)
|
||||
goto Lno;
|
||||
elements->push(ex);
|
||||
}
|
||||
e = new StructLiteralExp(loc, sd, elements);
|
||||
e->type = sd->type;
|
||||
return e;
|
||||
|
||||
Lno:
|
||||
delete elements;
|
||||
//error(loc, "struct initializers as expressions are not allowed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
//printf("StructInitializer::toCBuffer()\n");
|
||||
buf->writebyte('{');
|
||||
for (int i = 0; i < field.dim; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
buf->writebyte(',');
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
if (id)
|
||||
{
|
||||
buf->writestring(id->toChars());
|
||||
buf->writebyte(':');
|
||||
}
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (iz)
|
||||
iz->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writebyte('}');
|
||||
}
|
||||
|
||||
/********************************** ArrayInitializer ************************************/
|
||||
|
||||
ArrayInitializer::ArrayInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
dim = 0;
|
||||
type = NULL;
|
||||
sem = 0;
|
||||
}
|
||||
|
||||
Initializer *ArrayInitializer::syntaxCopy()
|
||||
{
|
||||
//printf("ArrayInitializer::syntaxCopy()\n");
|
||||
|
||||
ArrayInitializer *ai = new ArrayInitializer(loc);
|
||||
|
||||
assert(index.dim == value.dim);
|
||||
ai->index.setDim(index.dim);
|
||||
ai->value.setDim(value.dim);
|
||||
for (int i = 0; i < ai->value.dim; i++)
|
||||
{ Expression *e = (Expression *)index.data[i];
|
||||
if (e)
|
||||
e = e->syntaxCopy();
|
||||
ai->index.data[i] = e;
|
||||
|
||||
Initializer *init = (Initializer *)value.data[i];
|
||||
init = init->syntaxCopy();
|
||||
ai->value.data[i] = init;
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
|
||||
void ArrayInitializer::addInit(Expression *index, Initializer *value)
|
||||
{
|
||||
this->index.push(index);
|
||||
this->value.push(value);
|
||||
dim = 0;
|
||||
type = NULL;
|
||||
}
|
||||
|
||||
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
|
||||
{ unsigned i;
|
||||
unsigned length;
|
||||
|
||||
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
|
||||
if (sem) // if semantic() already run
|
||||
return this;
|
||||
sem = 1;
|
||||
type = t;
|
||||
t = t->toBasetype();
|
||||
switch (t->ty)
|
||||
{
|
||||
case Tpointer:
|
||||
case Tsarray:
|
||||
case Tarray:
|
||||
break;
|
||||
|
||||
default:
|
||||
error(loc, "cannot use array to initialize %s", type->toChars());
|
||||
return this;
|
||||
}
|
||||
|
||||
length = 0;
|
||||
for (i = 0; i < index.dim; i++)
|
||||
{ Expression *idx;
|
||||
Initializer *val;
|
||||
|
||||
idx = (Expression *)index.data[i];
|
||||
if (idx)
|
||||
{ idx = idx->semantic(sc);
|
||||
idx = idx->optimize(WANTvalue | WANTinterpret);
|
||||
index.data[i] = (void *)idx;
|
||||
length = idx->toInteger();
|
||||
}
|
||||
|
||||
val = (Initializer *)value.data[i];
|
||||
val = val->semantic(sc, t->nextOf());
|
||||
value.data[i] = (void *)val;
|
||||
length++;
|
||||
if (length == 0)
|
||||
error(loc, "array dimension overflow");
|
||||
if (length > dim)
|
||||
dim = length;
|
||||
}
|
||||
unsigned long amax = 0x80000000;
|
||||
if ((unsigned long) dim * t->nextOf()->size() >= amax)
|
||||
error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size());
|
||||
return this;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* If possible, convert array initializer to array literal.
|
||||
*/
|
||||
|
||||
Expression *ArrayInitializer::toExpression()
|
||||
{ Expressions *elements;
|
||||
Expression *e;
|
||||
|
||||
//printf("ArrayInitializer::toExpression()\n");
|
||||
//static int i; if (++i == 2) halt();
|
||||
elements = new Expressions();
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
if (index.data[i])
|
||||
goto Lno;
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
Expression *ex = iz->toExpression();
|
||||
if (!ex)
|
||||
goto Lno;
|
||||
elements->push(ex);
|
||||
}
|
||||
e = new ArrayLiteralExp(loc, elements);
|
||||
e->type = type;
|
||||
return e;
|
||||
|
||||
Lno:
|
||||
delete elements;
|
||||
error(loc, "array initializers as expressions are not allowed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
* If possible, convert array initializer to associative array initializer.
|
||||
*/
|
||||
|
||||
Initializer *ArrayInitializer::toAssocArrayInitializer()
|
||||
{ Expressions *keys;
|
||||
Expressions *values;
|
||||
Expression *e;
|
||||
|
||||
//printf("ArrayInitializer::toAssocArrayInitializer()\n");
|
||||
//static int i; if (++i == 2) halt();
|
||||
keys = new Expressions();
|
||||
keys->setDim(value.dim);
|
||||
values = new Expressions();
|
||||
values->setDim(value.dim);
|
||||
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
e = (Expression *)index.data[i];
|
||||
if (!e)
|
||||
goto Lno;
|
||||
keys->data[i] = (void *)e;
|
||||
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
e = iz->toExpression();
|
||||
if (!e)
|
||||
goto Lno;
|
||||
values->data[i] = (void *)e;
|
||||
}
|
||||
e = new AssocArrayLiteralExp(loc, keys, values);
|
||||
return new ExpInitializer(loc, e);
|
||||
|
||||
Lno:
|
||||
delete keys;
|
||||
delete values;
|
||||
error(loc, "not an associative array initializer");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Type *ArrayInitializer::inferType(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
if (index.data[i])
|
||||
goto Lno;
|
||||
}
|
||||
if (value.dim)
|
||||
{
|
||||
Initializer *iz = (Initializer *)value.data[0];
|
||||
if (iz)
|
||||
{ Type *t = iz->inferType(sc);
|
||||
t = new TypeSArray(t, new IntegerExp(value.dim));
|
||||
t = t->semantic(loc, sc);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
Lno:
|
||||
error(loc, "cannot infer type from this array initializer");
|
||||
return Type::terror;
|
||||
}
|
||||
|
||||
|
||||
void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writebyte('[');
|
||||
for (int i = 0; i < index.dim; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
buf->writebyte(',');
|
||||
Expression *ex = (Expression *)index.data[i];
|
||||
if (ex)
|
||||
{
|
||||
ex->toCBuffer(buf, hgs);
|
||||
buf->writebyte(':');
|
||||
}
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (iz)
|
||||
iz->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writebyte(']');
|
||||
}
|
||||
|
||||
|
||||
/********************************** ExpInitializer ************************************/
|
||||
|
||||
ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
|
||||
: Initializer(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Initializer *ExpInitializer::syntaxCopy()
|
||||
{
|
||||
return new ExpInitializer(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
|
||||
{
|
||||
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
|
||||
exp = exp->semantic(sc);
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
Type *tb = t->toBasetype();
|
||||
|
||||
/* Look for case of initializing a static array with a too-short
|
||||
* string literal, such as:
|
||||
* char[5] foo = "abc";
|
||||
* Allow this by doing an explicit cast, which will lengthen the string
|
||||
* literal.
|
||||
*/
|
||||
if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
|
||||
{ StringExp *se = (StringExp *)exp;
|
||||
|
||||
if (!se->committed && se->type->ty == Tsarray &&
|
||||
((TypeSArray *)se->type)->dim->toInteger() <
|
||||
((TypeSArray *)t)->dim->toInteger())
|
||||
{
|
||||
exp = se->castTo(sc, t);
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the case of statically initializing an array
|
||||
// with a single member.
|
||||
if (tb->ty == Tsarray &&
|
||||
!tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
|
||||
exp->implicitConvTo(tb->nextOf())
|
||||
)
|
||||
{
|
||||
t = tb->nextOf();
|
||||
}
|
||||
|
||||
exp = exp->implicitCastTo(sc, t);
|
||||
L1:
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
//printf("-ExpInitializer::semantic(): "); exp->print();
|
||||
return this;
|
||||
}
|
||||
|
||||
Type *ExpInitializer::inferType(Scope *sc)
|
||||
{
|
||||
//printf("ExpInitializer::inferType() %s\n", toChars());
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
|
||||
// Give error for overloaded function addresses
|
||||
if (exp->op == TOKsymoff)
|
||||
{ SymOffExp *se = (SymOffExp *)exp;
|
||||
if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
|
||||
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
||||
}
|
||||
|
||||
Type *t = exp->type;
|
||||
return t;
|
||||
//return t->ty == Tsarray ? t : t->toHeadMutable();
|
||||
}
|
||||
|
||||
Expression *ExpInitializer::toExpression()
|
||||
{
|
||||
return exp;
|
||||
}
|
||||
|
||||
|
||||
void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
exp->toCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
130
dmd2/init.h
Normal file
130
dmd2/init.h
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 INIT_H
|
||||
#define INIT_H
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "arraytypes.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Expression;
|
||||
struct Scope;
|
||||
struct Type;
|
||||
struct dt_t;
|
||||
struct AggregateDeclaration;
|
||||
struct VoidInitializer;
|
||||
struct StructInitializer;
|
||||
struct ArrayInitializer;
|
||||
struct ExpInitializer;
|
||||
struct StructInitializer;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
struct Initializer : Object
|
||||
{
|
||||
Loc loc;
|
||||
|
||||
Initializer(Loc loc);
|
||||
virtual Initializer *syntaxCopy();
|
||||
virtual Initializer *semantic(Scope *sc, Type *t);
|
||||
virtual Type *inferType(Scope *sc);
|
||||
virtual Expression *toExpression() = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
char *toChars();
|
||||
|
||||
static Initializers *arraySyntaxCopy(Initializers *ai);
|
||||
|
||||
virtual dt_t *toDt();
|
||||
|
||||
virtual VoidInitializer *isVoidInitializer() { return NULL; }
|
||||
virtual StructInitializer *isStructInitializer() { return NULL; }
|
||||
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
|
||||
virtual ExpInitializer *isExpInitializer() { return NULL; }
|
||||
};
|
||||
|
||||
struct VoidInitializer : Initializer
|
||||
{
|
||||
Type *type; // type that this will initialize to
|
||||
|
||||
VoidInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
dt_t *toDt();
|
||||
|
||||
virtual VoidInitializer *isVoidInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct StructInitializer : Initializer
|
||||
{
|
||||
Identifiers field; // of Identifier *'s
|
||||
Initializers value; // parallel array of Initializer *'s
|
||||
|
||||
Array vars; // parallel array of VarDeclaration *'s
|
||||
AggregateDeclaration *ad; // which aggregate this is for
|
||||
|
||||
StructInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
void addInit(Identifier *field, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
dt_t *toDt();
|
||||
|
||||
StructInitializer *isStructInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct ArrayInitializer : Initializer
|
||||
{
|
||||
Expressions index; // indices
|
||||
Initializers value; // of Initializer *'s
|
||||
unsigned dim; // length of array being initialized
|
||||
Type *type; // type that array will be used to initialize
|
||||
int sem; // !=0 if semantic() is run
|
||||
|
||||
ArrayInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
void addInit(Expression *index, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Type *inferType(Scope *sc);
|
||||
Expression *toExpression();
|
||||
Initializer *toAssocArrayInitializer();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
dt_t *toDt();
|
||||
dt_t *toDtBit(); // for bit arrays
|
||||
|
||||
ArrayInitializer *isArrayInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct ExpInitializer : Initializer
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
ExpInitializer(Loc loc, Expression *exp);
|
||||
Initializer *syntaxCopy();
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Type *inferType(Scope *sc);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
dt_t *toDt();
|
||||
|
||||
virtual ExpInitializer *isExpInitializer() { return this; }
|
||||
};
|
||||
|
||||
#endif
|
||||
1447
dmd2/inline.c
Normal file
1447
dmd2/inline.c
Normal file
File diff suppressed because it is too large
Load Diff
2231
dmd2/interpret.c
Normal file
2231
dmd2/interpret.c
Normal file
File diff suppressed because it is too large
Load Diff
3094
dmd2/lexer.c
Normal file
3094
dmd2/lexer.c
Normal file
File diff suppressed because it is too large
Load Diff
307
dmd2/lexer.h
Normal file
307
dmd2/lexer.h
Normal file
@@ -0,0 +1,307 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_LEXER_H
|
||||
#define DMD_LEXER_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
[ ]
|
||||
{ }
|
||||
< > <= >= == != === !==
|
||||
<< >> <<= >>= >>> >>>=
|
||||
+ - += -=
|
||||
* / % *= /= %=
|
||||
& | ^ &= |= ^=
|
||||
= ! ~
|
||||
++ --
|
||||
. -> : ,
|
||||
? && ||
|
||||
*/
|
||||
|
||||
enum TOK
|
||||
{
|
||||
TOKreserved,
|
||||
|
||||
// Other
|
||||
TOKlparen, TOKrparen,
|
||||
TOKlbracket, TOKrbracket,
|
||||
TOKlcurly, TOKrcurly,
|
||||
TOKcolon, TOKneg,
|
||||
TOKsemicolon, TOKdotdotdot,
|
||||
TOKeof, TOKcast,
|
||||
TOKnull, TOKassert,
|
||||
TOKtrue, TOKfalse,
|
||||
TOKarray, TOKcall,
|
||||
TOKaddress, TOKtypedot,
|
||||
TOKtype, TOKthrow,
|
||||
TOKnew, TOKdelete,
|
||||
TOKstar, TOKsymoff,
|
||||
TOKvar, TOKdotvar,
|
||||
TOKdotti, TOKdotexp,
|
||||
TOKdottype, TOKslice,
|
||||
TOKarraylength, TOKversion,
|
||||
TOKmodule, TOKdollar,
|
||||
TOKtemplate, TOKdottd,
|
||||
TOKdeclaration, TOKtypeof,
|
||||
TOKpragma, TOKdsymbol,
|
||||
TOKtypeid, TOKuadd,
|
||||
TOKremove,
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
TOKle, TOKge,
|
||||
TOKequal, TOKnotequal,
|
||||
TOKidentity, TOKnotidentity,
|
||||
TOKindex, TOKis,
|
||||
TOKtobool,
|
||||
|
||||
// 60
|
||||
// NCEG floating point compares
|
||||
// !<>= <> <>= !> !>= !< !<= !<>
|
||||
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
|
||||
|
||||
TOKshl, TOKshr,
|
||||
TOKshlass, TOKshrass,
|
||||
TOKushr, TOKushrass,
|
||||
TOKcat, TOKcatass, // ~ ~=
|
||||
TOKadd, TOKmin, TOKaddass, TOKminass,
|
||||
TOKmul, TOKdiv, TOKmod,
|
||||
TOKmulass, TOKdivass, TOKmodass,
|
||||
TOKand, TOKor, TOKxor,
|
||||
TOKandass, TOKorass, TOKxorass,
|
||||
TOKassign, TOKnot, TOKtilde,
|
||||
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
|
||||
TOKdot, TOKarrow, TOKcomma,
|
||||
TOKquestion, TOKandand, TOKoror,
|
||||
|
||||
// 104
|
||||
// Numeric literals
|
||||
TOKint32v, TOKuns32v,
|
||||
TOKint64v, TOKuns64v,
|
||||
TOKfloat32v, TOKfloat64v, TOKfloat80v,
|
||||
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
|
||||
|
||||
// Char constants
|
||||
TOKcharv, TOKwcharv, TOKdcharv,
|
||||
|
||||
// Leaf operators
|
||||
TOKidentifier, TOKstring,
|
||||
TOKthis, TOKsuper,
|
||||
TOKhalt, TOKtuple,
|
||||
|
||||
// Basic types
|
||||
TOKvoid,
|
||||
TOKint8, TOKuns8,
|
||||
TOKint16, TOKuns16,
|
||||
TOKint32, TOKuns32,
|
||||
TOKint64, TOKuns64,
|
||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
||||
TOKcent, TOKucent,
|
||||
|
||||
// Aggregates
|
||||
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
|
||||
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
|
||||
TOKmixin,
|
||||
|
||||
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
|
||||
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
|
||||
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
|
||||
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
|
||||
|
||||
// Statements
|
||||
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
|
||||
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
|
||||
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
|
||||
TOKasm, TOKforeach, TOKforeach_reverse,
|
||||
TOKscope,
|
||||
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
|
||||
|
||||
// Contracts
|
||||
TOKbody, TOKinvariant,
|
||||
|
||||
// Testing
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
TOKnothrow,
|
||||
TOKtls,
|
||||
TOKline,
|
||||
TOKfile,
|
||||
TOKshared,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
#if IN_LLVM
|
||||
TOKgep,
|
||||
#endif
|
||||
|
||||
TOKMAX
|
||||
};
|
||||
|
||||
#define CASE_BASIC_TYPES \
|
||||
case TOKwchar: case TOKdchar: \
|
||||
case TOKbit: case TOKbool: case TOKchar: \
|
||||
case TOKint8: case TOKuns8: \
|
||||
case TOKint16: case TOKuns16: \
|
||||
case TOKint32: case TOKuns32: \
|
||||
case TOKint64: case TOKuns64: \
|
||||
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
|
||||
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
|
||||
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
|
||||
case TOKvoid
|
||||
|
||||
#define CASE_BASIC_TYPES_X(t) \
|
||||
case TOKvoid: t = Type::tvoid; goto LabelX; \
|
||||
case TOKint8: t = Type::tint8; goto LabelX; \
|
||||
case TOKuns8: t = Type::tuns8; goto LabelX; \
|
||||
case TOKint16: t = Type::tint16; goto LabelX; \
|
||||
case TOKuns16: t = Type::tuns16; goto LabelX; \
|
||||
case TOKint32: t = Type::tint32; goto LabelX; \
|
||||
case TOKuns32: t = Type::tuns32; goto LabelX; \
|
||||
case TOKint64: t = Type::tint64; goto LabelX; \
|
||||
case TOKuns64: t = Type::tuns64; goto LabelX; \
|
||||
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
|
||||
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
|
||||
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
|
||||
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
|
||||
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
|
||||
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
|
||||
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
|
||||
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
|
||||
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
|
||||
case TOKbit: t = Type::tbit; goto LabelX; \
|
||||
case TOKbool: t = Type::tbool; goto LabelX; \
|
||||
case TOKchar: t = Type::tchar; goto LabelX; \
|
||||
case TOKwchar: t = Type::twchar; goto LabelX; \
|
||||
case TOKdchar: t = Type::tdchar; goto LabelX; \
|
||||
LabelX
|
||||
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
d_int32 int32value;
|
||||
d_uns32 uns32value;
|
||||
d_int64 int64value;
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
|
||||
int isKeyword();
|
||||
void print();
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
int anyToken; // !=0 means seen at least one token
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, unsigned begoffset, unsigned endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
static Identifier *idPool(const char *s);
|
||||
static Identifier *uniqueId(const char *s);
|
||||
static Identifier *uniqueId(const char *s, int num);
|
||||
|
||||
TOK nextToken();
|
||||
TOK peekNext();
|
||||
void scan(Token *t);
|
||||
Token *peek(Token *t);
|
||||
Token *peekPastParen(Token *t);
|
||||
unsigned escapeSequence();
|
||||
TOK wysiwygStringConstant(Token *t, int tc);
|
||||
TOK hexStringConstant(Token *t);
|
||||
#if DMDV2
|
||||
TOK delimitedStringConstant(Token *t);
|
||||
TOK tokenStringConstant(Token *t);
|
||||
#endif
|
||||
TOK escapeStringConstant(Token *t, int wide);
|
||||
TOK charConstant(Token *t, int wide);
|
||||
void stringPostfix(Token *t);
|
||||
unsigned wchar(unsigned u);
|
||||
TOK number(Token *t);
|
||||
TOK inreal(Token *t);
|
||||
void error(const char *format, ...);
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void pragma();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
505
dmd2/link.c.nolink
Normal file
505
dmd2/link.c.nolink
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 <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if linux
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
int executecmd(char *cmd, char *args, int useenv);
|
||||
int executearg0(char *cmd, char *args);
|
||||
|
||||
/****************************************
|
||||
* Write filename to cmdbuf, quoting if necessary.
|
||||
*/
|
||||
|
||||
void writeFilename(OutBuffer *buf, char *filename, size_t len)
|
||||
{
|
||||
/* Loop and see if we need to quote
|
||||
*/
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{ char c = filename[i];
|
||||
|
||||
if (isalnum(c) || c == '_')
|
||||
continue;
|
||||
|
||||
/* Need to quote
|
||||
*/
|
||||
buf->writeByte('"');
|
||||
buf->write(filename, len);
|
||||
buf->writeByte('"');
|
||||
return;
|
||||
}
|
||||
|
||||
/* No quoting necessary
|
||||
*/
|
||||
buf->write(filename, len);
|
||||
}
|
||||
|
||||
void writeFilename(OutBuffer *buf, char *filename)
|
||||
{
|
||||
writeFilename(buf, filename, strlen(filename));
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* Run the linker. Return status of execution.
|
||||
*/
|
||||
|
||||
int runLINK()
|
||||
{
|
||||
#if _WIN32
|
||||
char *p;
|
||||
int i;
|
||||
int status;
|
||||
OutBuffer cmdbuf;
|
||||
|
||||
global.params.libfiles->push((void *) "user32");
|
||||
global.params.libfiles->push((void *) "kernel32");
|
||||
|
||||
for (i = 0; i < global.params.objfiles->dim; i++)
|
||||
{
|
||||
if (i)
|
||||
cmdbuf.writeByte('+');
|
||||
p = (char *)global.params.objfiles->data[i];
|
||||
char *ext = FileName::ext(p);
|
||||
if (ext)
|
||||
// Write name sans extension
|
||||
writeFilename(&cmdbuf, p, ext - p - 1);
|
||||
else
|
||||
writeFilename(&cmdbuf, p);
|
||||
}
|
||||
cmdbuf.writeByte(',');
|
||||
if (global.params.exefile)
|
||||
writeFilename(&cmdbuf, global.params.exefile);
|
||||
else
|
||||
{ /* Generate exe file name from first obj name.
|
||||
* No need to add it to cmdbuf because the linker will default to it.
|
||||
*/
|
||||
char *n = (char *)global.params.objfiles->data[0];
|
||||
n = FileName::name(n);
|
||||
FileName *fn = FileName::forceExt(n, "exe");
|
||||
global.params.exefile = fn->toChars();
|
||||
}
|
||||
|
||||
// Make sure path to exe file exists
|
||||
{ char *p = FileName::path(global.params.exefile);
|
||||
FileName::ensurePathExists(p);
|
||||
mem.free(p);
|
||||
}
|
||||
|
||||
cmdbuf.writeByte(',');
|
||||
if (global.params.run)
|
||||
cmdbuf.writestring("nul");
|
||||
// if (mapfile)
|
||||
// cmdbuf.writestring(output);
|
||||
cmdbuf.writeByte(',');
|
||||
|
||||
for (i = 0; i < global.params.libfiles->dim; i++)
|
||||
{
|
||||
if (i)
|
||||
cmdbuf.writeByte('+');
|
||||
writeFilename(&cmdbuf, (char *) global.params.libfiles->data[i]);
|
||||
}
|
||||
|
||||
if (global.params.deffile)
|
||||
{
|
||||
cmdbuf.writeByte(',');
|
||||
writeFilename(&cmdbuf, global.params.deffile);
|
||||
}
|
||||
|
||||
/* Eliminate unnecessary trailing commas */
|
||||
while (1)
|
||||
{ i = cmdbuf.offset;
|
||||
if (!i || cmdbuf.data[i - 1] != ',')
|
||||
break;
|
||||
cmdbuf.offset--;
|
||||
}
|
||||
|
||||
if (global.params.resfile)
|
||||
{
|
||||
cmdbuf.writestring("/RC:");
|
||||
writeFilename(&cmdbuf, global.params.resfile);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (mapfile)
|
||||
cmdbuf.writestring("/m");
|
||||
if (debuginfo)
|
||||
cmdbuf.writestring("/li");
|
||||
if (codeview)
|
||||
{
|
||||
cmdbuf.writestring("/co");
|
||||
if (codeview3)
|
||||
cmdbuf.writestring(":3");
|
||||
}
|
||||
#else
|
||||
if (global.params.symdebug)
|
||||
cmdbuf.writestring("/co");
|
||||
#endif
|
||||
|
||||
cmdbuf.writestring("/noi");
|
||||
for (i = 0; i < global.params.linkswitches->dim; i++)
|
||||
{
|
||||
cmdbuf.writestring((char *) global.params.linkswitches->data[i]);
|
||||
}
|
||||
cmdbuf.writeByte(';');
|
||||
|
||||
p = cmdbuf.toChars();
|
||||
|
||||
FileName *lnkfilename = NULL;
|
||||
size_t plen = strlen(p);
|
||||
if (plen > 7000)
|
||||
{
|
||||
lnkfilename = FileName::forceExt(global.params.exefile, "lnk");
|
||||
File flnk(lnkfilename);
|
||||
flnk.setbuffer(p, plen);
|
||||
flnk.ref = 1;
|
||||
if (flnk.write())
|
||||
error("error writing file %s", lnkfilename);
|
||||
if (lnkfilename->len() < plen)
|
||||
sprintf(p, "@%s", lnkfilename->toChars());
|
||||
}
|
||||
|
||||
char *linkcmd = getenv("LINKCMD");
|
||||
if (!linkcmd)
|
||||
linkcmd = "link";
|
||||
status = executecmd(linkcmd, p, 1);
|
||||
if (lnkfilename)
|
||||
{
|
||||
remove(lnkfilename->toChars());
|
||||
delete lnkfilename;
|
||||
}
|
||||
return status;
|
||||
#elif linux
|
||||
pid_t childpid;
|
||||
int i;
|
||||
int status;
|
||||
|
||||
// Build argv[]
|
||||
Array argv;
|
||||
|
||||
const char *cc = getenv("CC");
|
||||
if (!cc)
|
||||
cc = "gcc";
|
||||
argv.push((void *)cc);
|
||||
argv.insert(1, global.params.objfiles);
|
||||
|
||||
// None of that a.out stuff. Use explicit exe file name, or
|
||||
// generate one from name of first source file.
|
||||
argv.push((void *)"-o");
|
||||
if (global.params.exefile)
|
||||
{
|
||||
argv.push(global.params.exefile);
|
||||
}
|
||||
else
|
||||
{ // Generate exe file name from first obj name
|
||||
char *n = (char *)global.params.objfiles->data[0];
|
||||
char *e;
|
||||
char *ex;
|
||||
|
||||
n = FileName::name(n);
|
||||
e = FileName::ext(n);
|
||||
if (e)
|
||||
{
|
||||
e--; // back up over '.'
|
||||
ex = (char *)mem.malloc(e - n + 1);
|
||||
memcpy(ex, n, e - n);
|
||||
ex[e - n] = 0;
|
||||
}
|
||||
else
|
||||
ex = (char *)"a.out"; // no extension, so give up
|
||||
argv.push(ex);
|
||||
global.params.exefile = ex;
|
||||
}
|
||||
|
||||
// Make sure path to exe file exists
|
||||
{ char *p = FileName::path(global.params.exefile);
|
||||
FileName::ensurePathExists(p);
|
||||
mem.free(p);
|
||||
}
|
||||
|
||||
argv.insert(argv.dim, global.params.libfiles);
|
||||
|
||||
if (global.params.symdebug)
|
||||
argv.push((void *)"-g");
|
||||
|
||||
argv.push((void *)"-m32");
|
||||
|
||||
if (0 && global.params.exefile)
|
||||
{
|
||||
/* This switch enables what is known as 'smart linking'
|
||||
* in the Windows world, where unreferenced sections
|
||||
* are removed from the executable. It eliminates unreferenced
|
||||
* functions, essentially making a 'library' out of a module.
|
||||
* Although it is documented to work with ld version 2.13,
|
||||
* in practice it does not, but just seems to be ignored.
|
||||
* Thomas Kuehne has verified that it works with ld 2.16.1.
|
||||
* BUG: disabled because it causes exception handling to fail
|
||||
*/
|
||||
argv.push((void *)"-Xlinker");
|
||||
argv.push((void *)"--gc-sections");
|
||||
}
|
||||
|
||||
for (i = 0; i < global.params.linkswitches->dim; i++)
|
||||
{ char *p = (char *)global.params.linkswitches->data[i];
|
||||
if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
|
||||
// Don't need -Xlinker if switch starts with -l
|
||||
argv.push((void *)"-Xlinker");
|
||||
argv.push((void *) p);
|
||||
}
|
||||
|
||||
/* Standard libraries must go after user specified libraries
|
||||
* passed with -l.
|
||||
*/
|
||||
const char *libname = (global.params.symdebug)
|
||||
? global.params.debuglibname
|
||||
: global.params.defaultlibname;
|
||||
char *buf = (char *)malloc(2 + strlen(libname) + 1);
|
||||
strcpy(buf, "-l");
|
||||
strcpy(buf + 2, libname);
|
||||
argv.push((void *)buf); // turns into /usr/lib/libphobos2.a
|
||||
|
||||
argv.push((void *)"-ldruntime");
|
||||
argv.push((void *)"-lpthread");
|
||||
argv.push((void *)"-lm");
|
||||
|
||||
if (!global.params.quiet || global.params.verbose)
|
||||
{
|
||||
// Print it
|
||||
for (i = 0; i < argv.dim; i++)
|
||||
printf("%s ", (char *)argv.data[i]);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
argv.push(NULL);
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp((char *)argv.data[0], (char **)argv.data);
|
||||
perror((char *)argv.data[0]); // failed to execute
|
||||
return -1;
|
||||
}
|
||||
|
||||
waitpid(childpid, &status, 0);
|
||||
|
||||
status=WEXITSTATUS(status);
|
||||
if (status)
|
||||
printf("--- errorlevel %d\n", status);
|
||||
return status;
|
||||
#else
|
||||
printf ("Linking is not yet supported for this version of DMD.\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Delete generated EXE file.
|
||||
*/
|
||||
|
||||
void deleteExeFile()
|
||||
{
|
||||
if (global.params.exefile)
|
||||
{
|
||||
//printf("deleteExeFile() %s\n", global.params.exefile);
|
||||
remove(global.params.exefile);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Execute a rule. Return the status.
|
||||
* cmd program to run
|
||||
* args arguments to cmd, as a string
|
||||
* useenv if cmd knows about _CMDLINE environment variable
|
||||
*/
|
||||
|
||||
#if _WIN32
|
||||
int executecmd(char *cmd, char *args, int useenv)
|
||||
{
|
||||
int status;
|
||||
char *buff;
|
||||
size_t len;
|
||||
|
||||
if (!global.params.quiet || global.params.verbose)
|
||||
{
|
||||
printf("%s %s\n", cmd, args);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if ((len = strlen(args)) > 255)
|
||||
{ char *q;
|
||||
static char envname[] = "@_CMDLINE";
|
||||
|
||||
envname[0] = '@';
|
||||
switch (useenv)
|
||||
{ case 0: goto L1;
|
||||
case 2: envname[0] = '%'; break;
|
||||
}
|
||||
q = (char *) alloca(sizeof(envname) + len + 1);
|
||||
sprintf(q,"%s=%s", envname + 1, args);
|
||||
status = putenv(q);
|
||||
if (status == 0)
|
||||
args = envname;
|
||||
else
|
||||
{
|
||||
L1:
|
||||
error("command line length of %d is too long",len);
|
||||
}
|
||||
}
|
||||
|
||||
status = executearg0(cmd,args);
|
||||
#if _WIN32
|
||||
if (status == -1)
|
||||
status = spawnlp(0,cmd,cmd,args,NULL);
|
||||
#endif
|
||||
// if (global.params.verbose)
|
||||
// printf("\n");
|
||||
if (status)
|
||||
{
|
||||
if (status == -1)
|
||||
printf("Can't run '%s', check PATH\n", cmd);
|
||||
else
|
||||
printf("--- errorlevel %d\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
* Attempt to find command to execute by first looking in the directory
|
||||
* where DMD was run from.
|
||||
* Returns:
|
||||
* -1 did not find command there
|
||||
* !=-1 exit status from command
|
||||
*/
|
||||
|
||||
#if _WIN32
|
||||
int executearg0(char *cmd, char *args)
|
||||
{
|
||||
char *file;
|
||||
char *argv0 = global.params.argv0;
|
||||
|
||||
//printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
|
||||
|
||||
// If cmd is fully qualified, we don't do this
|
||||
if (FileName::absolute(cmd))
|
||||
return -1;
|
||||
|
||||
file = FileName::replaceName(argv0, cmd);
|
||||
|
||||
//printf("spawning '%s'\n",file);
|
||||
#if _WIN32
|
||||
return spawnl(0,file,file,args,NULL);
|
||||
#elif linux
|
||||
char *full;
|
||||
int cmdl = strlen(cmd);
|
||||
|
||||
full = (char*) mem.malloc(cmdl + strlen(args) + 2);
|
||||
if (full == NULL)
|
||||
return 1;
|
||||
strcpy(full, cmd);
|
||||
full [cmdl] = ' ';
|
||||
strcpy(full + cmdl + 1, args);
|
||||
|
||||
int result = system(full);
|
||||
|
||||
mem.free(full);
|
||||
return result;
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************
|
||||
* Run the compiled program.
|
||||
* Return exit status.
|
||||
*/
|
||||
|
||||
int runProgram()
|
||||
{
|
||||
//printf("runProgram()\n");
|
||||
if (global.params.verbose)
|
||||
{
|
||||
printf("%s", global.params.exefile);
|
||||
for (size_t i = 0; i < global.params.runargs_length; i++)
|
||||
printf(" %s", (char *)global.params.runargs[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Build argv[]
|
||||
Array argv;
|
||||
|
||||
argv.push((void *)global.params.exefile);
|
||||
for (size_t i = 0; i < global.params.runargs_length; i++)
|
||||
{ char *a = global.params.runargs[i];
|
||||
|
||||
#if _WIN32
|
||||
// BUG: what about " appearing in the string?
|
||||
if (strchr(a, ' '))
|
||||
{ char *b = (char *)mem.malloc(3 + strlen(a));
|
||||
sprintf(b, "\"%s\"", a);
|
||||
a = b;
|
||||
}
|
||||
#endif
|
||||
argv.push((void *)a);
|
||||
}
|
||||
argv.push(NULL);
|
||||
|
||||
#if _WIN32
|
||||
char *ex = FileName::name(global.params.exefile);
|
||||
if (ex == global.params.exefile)
|
||||
ex = FileName::combine(".", ex);
|
||||
else
|
||||
ex = global.params.exefile;
|
||||
return spawnv(0,ex,(char **)argv.data);
|
||||
#elif linux
|
||||
pid_t childpid;
|
||||
int status;
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
const char *fn = (const char *)argv.data[0];
|
||||
if (!FileName::absolute(fn))
|
||||
{ // Make it "./fn"
|
||||
fn = FileName::combine(".", fn);
|
||||
}
|
||||
execv(fn, (char **)argv.data);
|
||||
perror(fn); // failed to execute
|
||||
return -1;
|
||||
}
|
||||
|
||||
waitpid(childpid, &status, 0);
|
||||
|
||||
status = WEXITSTATUS(status);
|
||||
return status;
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
59
dmd2/lstring.c
Normal file
59
dmd2/lstring.c
Normal file
@@ -0,0 +1,59 @@
|
||||
// lstring.c
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 <stdlib.h>
|
||||
|
||||
#include "dchar.h"
|
||||
#include "mem.h"
|
||||
#include "lstring.h"
|
||||
|
||||
Lstring Lstring::zero = LSTRING_EMPTY();
|
||||
|
||||
Lstring *Lstring::ctor(const dchar *p, unsigned length)
|
||||
{
|
||||
Lstring *s;
|
||||
|
||||
s = alloc(length);
|
||||
memcpy(s->string, p, length * sizeof(dchar));
|
||||
return s;
|
||||
}
|
||||
|
||||
Lstring *Lstring::alloc(unsigned length)
|
||||
{
|
||||
Lstring *s;
|
||||
|
||||
s = (Lstring *)mem.malloc(size(length));
|
||||
s->length = length;
|
||||
s->string[length] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
Lstring *Lstring::append(const Lstring *s)
|
||||
{
|
||||
Lstring *t;
|
||||
|
||||
if (!s->length)
|
||||
return this;
|
||||
t = alloc(length + s->length);
|
||||
memcpy(t->string, string, length * sizeof(dchar));
|
||||
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
|
||||
return t;
|
||||
}
|
||||
|
||||
Lstring *Lstring::substring(int start, int end)
|
||||
{
|
||||
Lstring *t;
|
||||
|
||||
if (start == end)
|
||||
return &zero;
|
||||
t = alloc(end - start);
|
||||
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
|
||||
return t;
|
||||
}
|
||||
72
dmd2/lstring.h
Normal file
72
dmd2/lstring.h
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
// lstring.h
|
||||
// length-prefixed strings
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 LSTRING_H
|
||||
#define LSTRING_H 1
|
||||
|
||||
#include "dchar.h"
|
||||
|
||||
struct Lstring
|
||||
{
|
||||
unsigned length;
|
||||
|
||||
// Disable warning about nonstandard extension
|
||||
#pragma warning (disable : 4200)
|
||||
dchar string[];
|
||||
|
||||
static Lstring zero; // 0 length string
|
||||
|
||||
// No constructors because we want to be able to statically
|
||||
// initialize Lstring's, and Lstrings are of variable size.
|
||||
|
||||
#if M_UNICODE
|
||||
#define LSTRING(p,length) { length, L##p }
|
||||
#else
|
||||
#define LSTRING(p,length) { length, p }
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
#define LSTRING_EMPTY() { 0 }
|
||||
#else
|
||||
#define LSTRING_EMPTY() LSTRING("", 0)
|
||||
#endif
|
||||
|
||||
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
|
||||
static Lstring *ctor(const dchar *p, unsigned length);
|
||||
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
|
||||
static Lstring *alloc(unsigned length);
|
||||
Lstring *clone();
|
||||
|
||||
unsigned len() { return length; }
|
||||
|
||||
dchar *toDchars() { return string; }
|
||||
|
||||
hash_t hash() { return Dchar::calcHash(string, length); }
|
||||
hash_t ihash() { return Dchar::icalcHash(string, length); }
|
||||
|
||||
static int cmp(const Lstring *s1, const Lstring *s2)
|
||||
{
|
||||
int c = s2->length - s1->length;
|
||||
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
|
||||
}
|
||||
|
||||
static int icmp(const Lstring *s1, const Lstring *s2)
|
||||
{
|
||||
int c = s2->length - s1->length;
|
||||
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
|
||||
}
|
||||
|
||||
Lstring *append(const Lstring *s);
|
||||
Lstring *substring(int start, int end);
|
||||
};
|
||||
|
||||
#endif
|
||||
459
dmd2/macro.c
Normal file
459
dmd2/macro.c
Normal file
@@ -0,0 +1,459 @@
|
||||
|
||||
// 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.
|
||||
|
||||
/* Simple macro text processor.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#else
|
||||
#if _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif POSIX
|
||||
#include "../root/mem.h"
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "macro.h"
|
||||
|
||||
#define isidstart(c) (isalpha(c) || (c) == '_')
|
||||
#define isidchar(c) (isalnum(c) || (c) == '_')
|
||||
|
||||
unsigned char *memdup(unsigned char *p, size_t len)
|
||||
{
|
||||
return (unsigned char *)memcpy(mem.malloc(len), p, len);
|
||||
}
|
||||
|
||||
Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
|
||||
{
|
||||
next = NULL;
|
||||
|
||||
#if 1
|
||||
this->name = name;
|
||||
this->namelen = namelen;
|
||||
|
||||
this->text = text;
|
||||
this->textlen = textlen;
|
||||
#else
|
||||
this->name = name;
|
||||
this->namelen = namelen;
|
||||
|
||||
this->text = text;
|
||||
this->textlen = textlen;
|
||||
#endif
|
||||
inuse = 0;
|
||||
}
|
||||
|
||||
|
||||
Macro *Macro::search(unsigned char *name, size_t namelen)
|
||||
{ Macro *table;
|
||||
|
||||
//printf("Macro::search(%.*s)\n", namelen, name);
|
||||
for (table = this; table; table = table->next)
|
||||
{
|
||||
if (table->namelen == namelen &&
|
||||
memcmp(table->name, name, namelen) == 0)
|
||||
{
|
||||
//printf("\tfound %d\n", table->textlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
|
||||
{
|
||||
//printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text);
|
||||
|
||||
Macro *table;
|
||||
|
||||
//assert(ptable);
|
||||
for (table = *ptable; table; table = table->next)
|
||||
{
|
||||
if (table->namelen == namelen &&
|
||||
memcmp(table->name, name, namelen) == 0)
|
||||
{
|
||||
table->text = text;
|
||||
table->textlen = textlen;
|
||||
return table;
|
||||
}
|
||||
}
|
||||
table = new Macro(name, namelen, text, textlen);
|
||||
table->next = *ptable;
|
||||
*ptable = table;
|
||||
return table;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* Given buffer p[0..end], extract argument marg[0..marglen].
|
||||
* Params:
|
||||
* n 0: get entire argument
|
||||
* 1..9: get nth argument
|
||||
* -1: get 2nd through end
|
||||
*/
|
||||
|
||||
unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n)
|
||||
{
|
||||
/* Scan forward for matching right parenthesis.
|
||||
* Nest parentheses.
|
||||
* Skip over $( and $)
|
||||
* Skip over "..." and '...' strings inside HTML tags.
|
||||
* Skip over <!-- ... --> comments.
|
||||
* Skip over previous macro insertions
|
||||
* Set marglen.
|
||||
*/
|
||||
unsigned parens = 1;
|
||||
unsigned char instring = 0;
|
||||
unsigned incomment = 0;
|
||||
unsigned intag = 0;
|
||||
unsigned inexp = 0;
|
||||
unsigned argn = 0;
|
||||
|
||||
unsigned v = 0;
|
||||
|
||||
Largstart:
|
||||
#if 1
|
||||
// Skip first space, if any, to find the start of the macro argument
|
||||
if (v < end && isspace(p[v]))
|
||||
v++;
|
||||
#else
|
||||
// Skip past spaces to find the start of the macro argument
|
||||
for (; v < end && isspace(p[v]); v++)
|
||||
;
|
||||
#endif
|
||||
*pmarg = p + v;
|
||||
|
||||
for (; v < end; v++)
|
||||
{ unsigned char c = p[v];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ',':
|
||||
if (!inexp && !instring && !incomment && parens == 1)
|
||||
{
|
||||
argn++;
|
||||
if (argn == 1 && n == -1)
|
||||
{ v++;
|
||||
goto Largstart;
|
||||
}
|
||||
if (argn == n)
|
||||
break;
|
||||
if (argn + 1 == n)
|
||||
{ v++;
|
||||
goto Largstart;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
case '(':
|
||||
if (!inexp && !instring && !incomment)
|
||||
parens++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
if (!inexp && !instring && !incomment && --parens == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
if (!inexp && !incomment && intag)
|
||||
{
|
||||
if (c == instring)
|
||||
instring = 0;
|
||||
else if (!instring)
|
||||
instring = c;
|
||||
}
|
||||
continue;
|
||||
|
||||
case '<':
|
||||
if (!inexp && !instring && !incomment)
|
||||
{
|
||||
if (v + 6 < end &&
|
||||
p[v + 1] == '!' &&
|
||||
p[v + 2] == '-' &&
|
||||
p[v + 3] == '-')
|
||||
{
|
||||
incomment = 1;
|
||||
v += 3;
|
||||
}
|
||||
else if (v + 2 < end &&
|
||||
isalpha(p[v + 1]))
|
||||
intag = 1;
|
||||
}
|
||||
continue;
|
||||
|
||||
case '>':
|
||||
if (!inexp)
|
||||
intag = 0;
|
||||
continue;
|
||||
|
||||
case '-':
|
||||
if (!inexp &&
|
||||
!instring &&
|
||||
incomment &&
|
||||
v + 2 < end &&
|
||||
p[v + 1] == '-' &&
|
||||
p[v + 2] == '>')
|
||||
{
|
||||
incomment = 0;
|
||||
v += 2;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 0xFF:
|
||||
if (v + 1 < end)
|
||||
{
|
||||
if (p[v + 1] == '{')
|
||||
inexp++;
|
||||
else if (p[v + 1] == '}')
|
||||
inexp--;
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (argn == 0 && n == -1)
|
||||
*pmarg = p + v;
|
||||
*pmarglen = p + v - *pmarg;
|
||||
//printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* Expand macro in place in buf.
|
||||
* Only look at the text in buf from start to end.
|
||||
*/
|
||||
|
||||
void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
|
||||
unsigned char *arg, unsigned arglen)
|
||||
{
|
||||
#if 0
|
||||
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
|
||||
printf("Buf is: '%.*s'\n", *pend - start, buf->data + start);
|
||||
#endif
|
||||
|
||||
static int nest;
|
||||
if (nest > 100) // limit recursive expansion
|
||||
return;
|
||||
nest++;
|
||||
|
||||
unsigned end = *pend;
|
||||
assert(start <= end);
|
||||
assert(end <= buf->offset);
|
||||
|
||||
/* First pass - replace $0
|
||||
*/
|
||||
arg = memdup(arg, arglen);
|
||||
for (unsigned u = start; u + 1 < end; )
|
||||
{
|
||||
unsigned char *p = buf->data; // buf->data is not loop invariant
|
||||
|
||||
/* Look for $0, but not $$0, and replace it with arg.
|
||||
*/
|
||||
if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+'))
|
||||
{
|
||||
if (u > start && p[u - 1] == '$')
|
||||
{ // Don't expand $$0, but replace it with $0
|
||||
buf->remove(u - 1, 1);
|
||||
end--;
|
||||
u += 1; // now u is one past the closing '1'
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char c = p[u + 1];
|
||||
int n = (c == '+') ? -1 : c - '0';
|
||||
|
||||
unsigned char *marg;
|
||||
unsigned marglen;
|
||||
extractArgN(arg, arglen, &marg, &marglen, n);
|
||||
if (marglen == 0)
|
||||
{ // Just remove macro invocation
|
||||
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
|
||||
buf->remove(u, 2);
|
||||
end -= 2;
|
||||
}
|
||||
else if (c == '+')
|
||||
{
|
||||
// Replace '$+' with 'arg'
|
||||
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
|
||||
buf->remove(u, 2);
|
||||
buf->insert(u, marg, marglen);
|
||||
end += marglen - 2;
|
||||
|
||||
// Scan replaced text for further expansion
|
||||
unsigned mend = u + marglen;
|
||||
expand(buf, u, &mend, NULL, 0);
|
||||
end += mend - (u + marglen);
|
||||
u = mend;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace '$1' with '\xFF{arg\xFF}'
|
||||
//printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg);
|
||||
buf->data[u] = 0xFF;
|
||||
buf->data[u + 1] = '{';
|
||||
buf->insert(u + 2, marg, marglen);
|
||||
buf->insert(u + 2 + marglen, "\xFF}", 2);
|
||||
end += -2 + 2 + marglen + 2;
|
||||
|
||||
// Scan replaced text for further expansion
|
||||
unsigned mend = u + 2 + marglen;
|
||||
expand(buf, u + 2, &mend, NULL, 0);
|
||||
end += mend - (u + 2 + marglen);
|
||||
u = mend;
|
||||
}
|
||||
//printf("u = %d, end = %d\n", u, end);
|
||||
//printf("#%.*s#\n", end, &buf->data[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
u++;
|
||||
}
|
||||
|
||||
/* Second pass - replace other macros
|
||||
*/
|
||||
for (unsigned u = start; u + 4 < end; )
|
||||
{
|
||||
unsigned char *p = buf->data; // buf->data is not loop invariant
|
||||
|
||||
/* A valid start of macro expansion is $(c, where c is
|
||||
* an id start character, and not $$(c.
|
||||
*/
|
||||
if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2]))
|
||||
{
|
||||
//printf("\tfound macro start '%c'\n", p[u + 2]);
|
||||
unsigned char *name = p + u + 2;
|
||||
unsigned namelen = 0;
|
||||
|
||||
unsigned char *marg;
|
||||
unsigned marglen;
|
||||
|
||||
unsigned v;
|
||||
/* Scan forward to find end of macro name and
|
||||
* beginning of macro argument (marg).
|
||||
*/
|
||||
for (v = u + 2; v < end; v++)
|
||||
{ unsigned char c = p[v];
|
||||
|
||||
if (!isidchar(c))
|
||||
{ // We've gone past the end of the macro name.
|
||||
namelen = v - (u + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v += extractArgN(p + v, end - v, &marg, &marglen, 0);
|
||||
assert(v <= end);
|
||||
|
||||
if (v < end)
|
||||
{ // v is on the closing ')'
|
||||
if (u > start && p[u - 1] == '$')
|
||||
{ // Don't expand $$(NAME), but replace it with $(NAME)
|
||||
buf->remove(u - 1, 1);
|
||||
end--;
|
||||
u = v; // now u is one past the closing ')'
|
||||
continue;
|
||||
}
|
||||
|
||||
Macro *m = search(name, namelen);
|
||||
if (m)
|
||||
{
|
||||
#if 0
|
||||
if (m->textlen && m->text[0] == ' ')
|
||||
{ m->text++;
|
||||
m->textlen--;
|
||||
}
|
||||
#endif
|
||||
if (m->inuse && marglen == 0)
|
||||
{ // Remove macro invocation
|
||||
buf->remove(u, v + 1 - u);
|
||||
end -= v + 1 - u;
|
||||
}
|
||||
else if (m->inuse && arglen == marglen && memcmp(arg, marg, arglen) == 0)
|
||||
{ // Recursive expansion; just leave in place
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text);
|
||||
#if 1
|
||||
marg = memdup(marg, marglen);
|
||||
// Insert replacement text
|
||||
buf->spread(v + 1, 2 + m->textlen + 2);
|
||||
buf->data[v + 1] = 0xFF;
|
||||
buf->data[v + 2] = '{';
|
||||
memcpy(buf->data + v + 3, m->text, m->textlen);
|
||||
buf->data[v + 3 + m->textlen] = 0xFF;
|
||||
buf->data[v + 3 + m->textlen + 1] = '}';
|
||||
|
||||
end += 2 + m->textlen + 2;
|
||||
|
||||
// Scan replaced text for further expansion
|
||||
m->inuse++;
|
||||
unsigned mend = v + 1 + 2+m->textlen+2;
|
||||
expand(buf, v + 1, &mend, marg, marglen);
|
||||
end += mend - (v + 1 + 2+m->textlen+2);
|
||||
m->inuse--;
|
||||
|
||||
buf->remove(u, v + 1 - u);
|
||||
end -= v + 1 - u;
|
||||
u += mend - (v + 1);
|
||||
#else
|
||||
// Insert replacement text
|
||||
buf->insert(v + 1, m->text, m->textlen);
|
||||
end += m->textlen;
|
||||
|
||||
// Scan replaced text for further expansion
|
||||
m->inuse++;
|
||||
unsigned mend = v + 1 + m->textlen;
|
||||
expand(buf, v + 1, &mend, marg, marglen);
|
||||
end += mend - (v + 1 + m->textlen);
|
||||
m->inuse--;
|
||||
|
||||
buf->remove(u, v + 1 - u);
|
||||
end -= v + 1 - u;
|
||||
u += mend - (v + 1);
|
||||
#endif
|
||||
mem.free(marg);
|
||||
//printf("u = %d, end = %d\n", u, end);
|
||||
//printf("#%.*s#\n", end - u, &buf->data[u]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace $(NAME) with nothing
|
||||
buf->remove(u, v + 1 - u);
|
||||
end -= (v + 1 - u);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
u++;
|
||||
}
|
||||
mem.free(arg);
|
||||
*pend = end;
|
||||
nest--;
|
||||
}
|
||||
44
dmd2/macro.h
Normal file
44
dmd2/macro.h
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// 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_MACRO_H
|
||||
#define DMD_MACRO_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
|
||||
class Macro
|
||||
{
|
||||
Macro *next; // next in list
|
||||
|
||||
unsigned char *name; // macro name
|
||||
size_t namelen; // length of macro name
|
||||
|
||||
unsigned char *text; // macro replacement text
|
||||
size_t textlen; // length of replacement text
|
||||
|
||||
int inuse; // macro is in use (don't expand)
|
||||
|
||||
Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
|
||||
Macro *search(unsigned char *name, size_t namelen);
|
||||
|
||||
public:
|
||||
static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
|
||||
|
||||
void expand(OutBuffer *buf, unsigned start, unsigned *pend,
|
||||
unsigned char *arg, unsigned arglen);
|
||||
};
|
||||
|
||||
#endif
|
||||
60
dmd2/man.c
Normal file
60
dmd2/man.c
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2008-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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib,"shell32.lib")
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
pid_t childpid;
|
||||
const char *args[3];
|
||||
|
||||
const char *browser = getenv("BROWSER");
|
||||
if (browser)
|
||||
browser = strdup(browser);
|
||||
else
|
||||
browser = "firefox";
|
||||
|
||||
args[0] = browser;
|
||||
args[1] = url;
|
||||
args[2] = NULL;
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp(args[0], (char**)args);
|
||||
perror(args[0]); // failed to execute
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
291
dmd2/mangle.c
Normal file
291
dmd2/mangle.c
Normal file
@@ -0,0 +1,291 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "mtype.h"
|
||||
#include "attrib.h"
|
||||
#include "template.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
|
||||
#if TARGET_LINUX
|
||||
char *cpp_mangle(Dsymbol *s);
|
||||
#endif
|
||||
|
||||
char *mangle(Declaration *sthis)
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("::mangle(%s)\n", sthis->toChars());
|
||||
s = sthis;
|
||||
do
|
||||
{
|
||||
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
|
||||
if (s->ident)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (s != sthis && fd)
|
||||
{
|
||||
id = mangle(fd);
|
||||
buf.prependstring(id);
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = s->ident->toChars();
|
||||
int len = strlen(id);
|
||||
char tmp[sizeof(len) * 3 + 1];
|
||||
buf.prependstring(id);
|
||||
sprintf(tmp, "%d", len);
|
||||
buf.prependstring(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
buf.prependstring("0");
|
||||
s = s->parent;
|
||||
} while (s);
|
||||
|
||||
// buf.prependstring("_D");
|
||||
L1:
|
||||
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
|
||||
//printf("sthis->type = %s\n", sthis->type->toChars());
|
||||
FuncDeclaration *fd = sthis->isFuncDeclaration();
|
||||
if (fd && (fd->needThis() || fd->isNested()))
|
||||
buf.writeByte(Type::needThisPrefix());
|
||||
if (sthis->type->deco)
|
||||
buf.writestring(sthis->type->deco);
|
||||
else
|
||||
{ assert(fd->inferRetType);
|
||||
}
|
||||
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return id;
|
||||
}
|
||||
|
||||
char *Declaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
int len = strlen(result);
|
||||
|
||||
assert(len > 0);
|
||||
//printf("mangle: '%s' => '%s'\n", toChars(), result);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
assert(result[i] == '_' ||
|
||||
result[i] == '@' ||
|
||||
isalnum(result[i]) || result[i] & 0x80);
|
||||
}
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
|
||||
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
|
||||
{
|
||||
// If it's not a D declaration, no mangling
|
||||
switch (linkage)
|
||||
{
|
||||
case LINKd:
|
||||
break;
|
||||
|
||||
// LDC
|
||||
case LINKintrinsic:
|
||||
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
case LINKpascal:
|
||||
return ident->toChars();
|
||||
|
||||
case LINKcpp:
|
||||
#if TARGET_LINUX
|
||||
return cpp_mangle(this);
|
||||
#else
|
||||
// Windows C++ mangling is done by C++ back end
|
||||
return ident->toChars();
|
||||
#endif
|
||||
|
||||
case LINKdefault:
|
||||
error("forward declaration");
|
||||
return ident->toChars();
|
||||
|
||||
default:
|
||||
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
char *p = ::mangle(this);
|
||||
OutBuffer buf;
|
||||
buf.writestring("_D");
|
||||
buf.writestring(p);
|
||||
p = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *FuncDeclaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
assert(strlen(result) > 0);
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
if (isMain())
|
||||
return (char *)"_Dmain";
|
||||
|
||||
if (isWinMain() || isDllMain())
|
||||
return ident->toChars();
|
||||
|
||||
assert(this);
|
||||
return Declaration::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *StructDeclaration::mangle()
|
||||
{
|
||||
//printf("StructDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *TypedefDeclaration::mangle()
|
||||
{
|
||||
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *ClassDeclaration::mangle()
|
||||
{
|
||||
Dsymbol *parentsave = parent;
|
||||
|
||||
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
|
||||
|
||||
/* These are reserved to the compiler, so keep simple
|
||||
* names for them.
|
||||
*/
|
||||
if (ident == Id::Exception)
|
||||
{ if (parent->ident == Id::object)
|
||||
parent = NULL;
|
||||
}
|
||||
else if (ident == Id::TypeInfo ||
|
||||
// ident == Id::Exception ||
|
||||
ident == Id::TypeInfo_Struct ||
|
||||
ident == Id::TypeInfo_Class ||
|
||||
ident == Id::TypeInfo_Typedef ||
|
||||
ident == Id::TypeInfo_Tuple ||
|
||||
this == object ||
|
||||
this == classinfo ||
|
||||
this == Module::moduleinfo ||
|
||||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
|
||||
)
|
||||
parent = NULL;
|
||||
|
||||
char *id = Dsymbol::mangle();
|
||||
parent = parentsave;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
char *TemplateInstance::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateInstance::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (tempdecl->parent)
|
||||
{
|
||||
char *p = tempdecl->parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
char *TemplateMixin::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateMixin::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
char *Dsymbol::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("Dsymbol::mangle() '%s'", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
1390
dmd2/mars.c
Normal file
1390
dmd2/mars.c
Normal file
File diff suppressed because it is too large
Load Diff
359
dmd2/mars.h
Normal file
359
dmd2/mars.h
Normal file
@@ -0,0 +1,359 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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_MARS_H
|
||||
#define DMD_MARS_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __DMC__
|
||||
#ifdef DEBUG
|
||||
#undef assert
|
||||
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
/* Changes for the GDC compiler by David Friedman */
|
||||
#endif
|
||||
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
|
||||
struct Array;
|
||||
|
||||
// LDC
|
||||
enum ARCH
|
||||
{
|
||||
ARCHinvalid,
|
||||
ARCHx86,
|
||||
ARCHx86_64,
|
||||
ARCHppc,
|
||||
ARCHppc_64,
|
||||
ARCHarm,
|
||||
ARCHthumb
|
||||
};
|
||||
enum OUTPUTFLAG
|
||||
{
|
||||
OUTPUTFLAGno,
|
||||
OUTPUTFLAGdefault, // for the .o default
|
||||
OUTPUTFLAGset // for -output
|
||||
};
|
||||
|
||||
enum OS
|
||||
{
|
||||
OSinvalid,
|
||||
OSLinux,
|
||||
OSWindows,
|
||||
OSMacOSX,
|
||||
OSFreeBSD
|
||||
};
|
||||
|
||||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
char obj; // write object file
|
||||
char link; // perform link
|
||||
char lib; // write library file instead of object file(s)
|
||||
char multiobj; // break one object file into multiple ones
|
||||
char oneobj; // write one object file instead of multiple ones
|
||||
char trace; // insert profiling hooks
|
||||
char quiet; // suppress non-error messages
|
||||
char verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
char optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
char is64bit; // generate 64 bit code
|
||||
char isLE; // generate little endian code
|
||||
char scheduler; // which scheduler to use
|
||||
char useDeprecated; // allow use of deprecated features
|
||||
char useAssert; // generate runtime code for assert()'s
|
||||
char useInvariants; // generate class invariant checks
|
||||
char useIn; // generate precondition checks
|
||||
char useOut; // generate postcondition checks
|
||||
char useArrayBounds; // generate array bounds checks
|
||||
char useSwitchError; // check for switches without a default
|
||||
char useUnitTests; // generate unittest code
|
||||
char useInline; // inline expand functions
|
||||
char release; // build release version
|
||||
char preservePaths; // !=0 means don't strip path from source file
|
||||
char warnings; // enable warnings
|
||||
char pic; // generate position-independent-code for shared libs
|
||||
char noruntime; // code is not allowed to make implicit calls to the runtime
|
||||
char novalidate;// no bitcode validation
|
||||
char Dversion; // D version number
|
||||
char ignoreUnsupportedPragmas; // rather than error on them
|
||||
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *runtimeImppath; // char* of where to look for the core runtime
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
|
||||
char doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
|
||||
char doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
|
||||
bool dump_source;
|
||||
|
||||
Array *defaultlibnames; // default libraries for non-debug builds
|
||||
Array *debuglibnames; // default libraries for debug builds
|
||||
|
||||
const char *xmlname; // filename for XML output
|
||||
|
||||
// Hidden debug switches
|
||||
char debuga;
|
||||
char debugb;
|
||||
char debugc;
|
||||
char debugf;
|
||||
char debugr;
|
||||
char debugw;
|
||||
char debugx;
|
||||
char debugy;
|
||||
|
||||
char run; // run resulting executable
|
||||
size_t runargs_length;
|
||||
char** runargs; // arguments for executable
|
||||
|
||||
// Linker stuff
|
||||
Array *objfiles;
|
||||
Array *linkswitches;
|
||||
Array *libfiles;
|
||||
char *deffile;
|
||||
char *resfile;
|
||||
char *exefile;
|
||||
|
||||
// LDC stuff
|
||||
const char *llvmArch;
|
||||
char forceBE;
|
||||
char output_ll;
|
||||
char output_bc;
|
||||
char output_s;
|
||||
char output_o;
|
||||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char useInlineAsm;
|
||||
char fqnNames; // use fully qualified object names
|
||||
char noDefaultLib;
|
||||
|
||||
// target stuff
|
||||
const char *targetTriple;
|
||||
const char *dataLayout;
|
||||
};
|
||||
|
||||
struct Global
|
||||
{
|
||||
const char *mars_ext;
|
||||
const char *sym_ext;
|
||||
const char *obj_ext;
|
||||
#if _WIN32
|
||||
const char *obj_ext_alt;
|
||||
#endif
|
||||
const char *ll_ext;
|
||||
const char *bc_ext;
|
||||
const char *s_ext;
|
||||
const char *lib_ext;
|
||||
const char *doc_ext; // for Ddoc generated files
|
||||
const char *ddoc_ext; // for Ddoc macro include files
|
||||
const char *hdr_ext; // for D 'header' import files
|
||||
const char *copyright;
|
||||
const char *written;
|
||||
Array *path; // Array of char*'s which form the import lookup path
|
||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
||||
int structalign;
|
||||
const char *version;
|
||||
const char *ldc_version;
|
||||
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
|
||||
Global();
|
||||
};
|
||||
|
||||
extern Global global;
|
||||
|
||||
#if __GNUC__
|
||||
//#define memicmp strncasecmp
|
||||
//#define stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
#ifdef __DMC__
|
||||
typedef _Complex long double complex_t;
|
||||
#else
|
||||
#ifndef IN_GCC
|
||||
#include "complex_t.h"
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Be careful not to care about sign when using integer_t
|
||||
typedef uint64_t integer_t;
|
||||
|
||||
// Signed and unsigned variants
|
||||
typedef int64_t sinteger_t;
|
||||
typedef uint64_t uinteger_t;
|
||||
|
||||
typedef int8_t d_int8;
|
||||
typedef uint8_t d_uns8;
|
||||
typedef int16_t d_int16;
|
||||
typedef uint16_t d_uns16;
|
||||
typedef int32_t d_int32;
|
||||
typedef uint32_t d_uns32;
|
||||
typedef int64_t d_int64;
|
||||
typedef uint64_t d_uns64;
|
||||
|
||||
typedef float d_float32;
|
||||
typedef double d_float64;
|
||||
typedef long double d_float80;
|
||||
|
||||
typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
#else
|
||||
typedef long double real_t;
|
||||
#endif
|
||||
|
||||
// Modify OutBuffer::writewchar to write the correct size of wchar
|
||||
#if _WIN32
|
||||
#define writewchar writeword
|
||||
#else
|
||||
// This needs a configuration test...
|
||||
#define writewchar write4
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-complex_t.h"
|
||||
#endif
|
||||
|
||||
// taken from GDC
|
||||
// for handling printf incompatibilities
|
||||
#if __MSVCRT__
|
||||
#define PRIuSIZE "Iu"
|
||||
#define PRIxSIZE "Ix"
|
||||
#elif __MINGW32__
|
||||
#define PRIuSIZE "u"
|
||||
#define PRIxSIZE "x"
|
||||
#else
|
||||
#define PRIuSIZE "zu"
|
||||
#define PRIxSIZE "zx"
|
||||
#endif
|
||||
|
||||
struct Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
struct Loc
|
||||
{
|
||||
char *filename;
|
||||
unsigned linnum;
|
||||
|
||||
Loc()
|
||||
{
|
||||
linnum = 0;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(int x)
|
||||
{
|
||||
linnum = x;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(Module *mod, unsigned linnum);
|
||||
|
||||
char *toChars() const;
|
||||
};
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||
// in interface vtbl[]'s
|
||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||
// in the inheritance graph multiple
|
||||
// times, only one is used
|
||||
|
||||
enum LINK
|
||||
{
|
||||
LINKdefault,
|
||||
LINKd,
|
||||
LINKc,
|
||||
LINKcpp,
|
||||
LINKwindows,
|
||||
LINKpascal,
|
||||
|
||||
// LDC
|
||||
LINKintrinsic,
|
||||
};
|
||||
|
||||
enum DYNCAST
|
||||
{
|
||||
DYNCAST_OBJECT,
|
||||
DYNCAST_EXPRESSION,
|
||||
DYNCAST_DSYMBOL,
|
||||
DYNCAST_TYPE,
|
||||
DYNCAST_IDENTIFIER,
|
||||
DYNCAST_TUPLE,
|
||||
};
|
||||
|
||||
enum MATCH
|
||||
{
|
||||
MATCHnomatch, // no match
|
||||
MATCHconvert, // match with conversions
|
||||
#if DMDV2
|
||||
MATCHconst, // match with conversion to const
|
||||
#endif
|
||||
MATCHexact // exact match
|
||||
};
|
||||
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void verror(Loc loc, const char *format, va_list);
|
||||
void fatal();
|
||||
void err_nomem();
|
||||
void inifile(const char *argv0, const char *inifile);
|
||||
void halt();
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
#if IN_GCC
|
||||
#define stdmsg stderr
|
||||
#else
|
||||
#define stdmsg stdout
|
||||
#endif
|
||||
|
||||
#endif /* DMD_MARS_H */
|
||||
265
dmd2/mem.c
Normal file
265
dmd2/mem.c
Normal file
@@ -0,0 +1,265 @@
|
||||
|
||||
/* Copyright (c) 2000 Digital Mars */
|
||||
/* All Rights Reserved */
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#if USE_BOEHM_GC
|
||||
// I needed to perfix the dir after upgrading to gc 7.0
|
||||
#include "gc/gc.h"
|
||||
#endif
|
||||
|
||||
/* This implementation of the storage allocator uses the standard C allocation package.
|
||||
*/
|
||||
|
||||
Mem mem;
|
||||
|
||||
#if USE_BOEHM_GC
|
||||
|
||||
static bool gc_was_init = false;
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
GC_init();
|
||||
gc_was_init = true;
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (s)
|
||||
{
|
||||
p = GC_strdup(s);
|
||||
if (p)
|
||||
return p;
|
||||
error();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *Mem::malloc(size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = GC_malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::calloc(size_t size, size_t n)
|
||||
{ void *p;
|
||||
|
||||
if (!size || !n)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = GC_malloc(size * n);
|
||||
if (!p)
|
||||
error();
|
||||
memset(p, 0, size * n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::realloc(void *p, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
{ if (p)
|
||||
{ GC_free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
else if (!p)
|
||||
{
|
||||
p = GC_malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = GC_realloc(p, size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::free(void *p)
|
||||
{
|
||||
if (p)
|
||||
GC_free(p);
|
||||
}
|
||||
|
||||
void *Mem::mallocdup(void *o, size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = GC_malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
else
|
||||
memcpy(p,o,size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::error()
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
GC_gcollect();
|
||||
}
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
(void) pointer; // necessary for VC /W4
|
||||
}
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
// without this we segfault with gc 7.0
|
||||
if (!gc_was_init) {
|
||||
mem.init();
|
||||
}
|
||||
void *p = GC_malloc(m_size);
|
||||
if (p)
|
||||
return p;
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
void operator delete(void *p)
|
||||
{
|
||||
GC_free(p);
|
||||
}
|
||||
|
||||
#elif !USE_BOEHM_GC
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (s)
|
||||
{
|
||||
p = ::strdup(s);
|
||||
if (p)
|
||||
return p;
|
||||
error();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *Mem::malloc(size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::calloc(size_t size, size_t n)
|
||||
{ void *p;
|
||||
|
||||
if (!size || !n)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size * n);
|
||||
if (!p)
|
||||
error();
|
||||
memset(p, 0, size * n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::realloc(void *p, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
{ if (p)
|
||||
{ ::free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
else if (!p)
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = ::realloc(p, size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::free(void *p)
|
||||
{
|
||||
if (p)
|
||||
::free(p);
|
||||
}
|
||||
|
||||
void *Mem::mallocdup(void *o, size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
else
|
||||
memcpy(p,o,size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::error()
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
}
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // USE_BOEHM_GC
|
||||
51
dmd2/mem.h
Normal file
51
dmd2/mem.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2000-2001 by Chromium Communications
|
||||
// All Rights Reserved
|
||||
|
||||
#ifndef ROOT_MEM_H
|
||||
#define ROOT_MEM_H
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
|
||||
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
|
||||
|
||||
struct GC; // thread specific allocator
|
||||
|
||||
struct Mem
|
||||
{
|
||||
GC *gc; // pointer to our thread specific allocator
|
||||
Mem() { gc = NULL; }
|
||||
|
||||
void init();
|
||||
|
||||
// Derive from Mem to get these storage allocators instead of global new/delete
|
||||
void * operator new(size_t m_size);
|
||||
void * operator new(size_t m_size, Mem *mem);
|
||||
void * operator new(size_t m_size, GC *gc);
|
||||
void operator delete(void *p);
|
||||
|
||||
void * operator new[](size_t m_size);
|
||||
void operator delete[](void *p);
|
||||
|
||||
char *strdup(const char *s);
|
||||
void *malloc(size_t size);
|
||||
void *malloc_uncollectable(size_t size);
|
||||
void *calloc(size_t size, size_t n);
|
||||
void *realloc(void *p, size_t size);
|
||||
void free(void *p);
|
||||
void free_uncollectable(void *p);
|
||||
void *mallocdup(void *o, size_t size);
|
||||
void error();
|
||||
void check(void *p); // validate pointer
|
||||
void fullcollect(); // do full garbage collection
|
||||
void fullcollectNoStack(); // do full garbage collection, no scan stack
|
||||
void mark(void *pointer);
|
||||
void addroots(char* pStart, char* pEnd);
|
||||
void removeroots(char* pStart);
|
||||
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
|
||||
void setStackBottom(void *bottom);
|
||||
GC *getThreadGC(); // get apartment allocator for this thread
|
||||
};
|
||||
|
||||
extern Mem mem;
|
||||
|
||||
#endif /* ROOT_MEM_H */
|
||||
976
dmd2/module.c
Normal file
976
dmd2/module.c
Normal file
@@ -0,0 +1,976 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _MSC_VER || __MINGW32__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#include "gdc_alloca.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "parse.h"
|
||||
#include "scope.h"
|
||||
#include "identifier.h"
|
||||
#include "id.h"
|
||||
#include "import.h"
|
||||
#include "dsymbol.h"
|
||||
#include "hdrgen.h"
|
||||
#include "lexer.h"
|
||||
|
||||
#define MARS 1
|
||||
#include "html.h"
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-dmd-gcc.h"
|
||||
#endif
|
||||
|
||||
ClassDeclaration *Module::moduleinfo;
|
||||
|
||||
Module *Module::rootModule;
|
||||
DsymbolTable *Module::modules;
|
||||
Array Module::amodules;
|
||||
|
||||
Array Module::deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
unsigned Module::dprogress;
|
||||
|
||||
void Module::init()
|
||||
{
|
||||
modules = new DsymbolTable();
|
||||
}
|
||||
|
||||
Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
|
||||
: Package(ident)
|
||||
{
|
||||
FileName *srcfilename;
|
||||
|
||||
// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
|
||||
this->arg = filename;
|
||||
md = NULL;
|
||||
errors = 0;
|
||||
numlines = 0;
|
||||
members = NULL;
|
||||
isHtml = 0;
|
||||
isDocFile = 0;
|
||||
needmoduleinfo = 0;
|
||||
#ifdef IN_GCC
|
||||
strictlyneedmoduleinfo = 0;
|
||||
#endif
|
||||
insearch = 0;
|
||||
searchCacheIdent = NULL;
|
||||
searchCacheSymbol = NULL;
|
||||
searchCacheFlags = 0;
|
||||
semanticstarted = 0;
|
||||
semanticdone = 0;
|
||||
decldefs = NULL;
|
||||
vmoduleinfo = NULL;
|
||||
massert = NULL;
|
||||
marray = NULL;
|
||||
sictor = NULL;
|
||||
sctor = NULL;
|
||||
sdtor = NULL;
|
||||
stest = NULL;
|
||||
sfilename = NULL;
|
||||
root = 0;
|
||||
importedFrom = NULL;
|
||||
srcfile = NULL;
|
||||
objfile = NULL;
|
||||
docfile = NULL;
|
||||
hdrfile = NULL;
|
||||
|
||||
debuglevel = 0;
|
||||
debugids = NULL;
|
||||
debugidsNot = NULL;
|
||||
versionlevel = 0;
|
||||
versionids = NULL;
|
||||
versionidsNot = NULL;
|
||||
|
||||
macrotable = NULL;
|
||||
escapetable = NULL;
|
||||
doppelganger = 0;
|
||||
cov = NULL;
|
||||
covb = NULL;
|
||||
|
||||
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") ||
|
||||
srcfilename->equalsExt("htm") ||
|
||||
srcfilename->equalsExt("xhtml"))
|
||||
{ if (!global.params.useDeprecated)
|
||||
error("html source files is deprecated %s", srcfilename->toChars());
|
||||
isHtml = 1;
|
||||
}
|
||||
else
|
||||
{ error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
srcfile = new File(srcfilename);
|
||||
|
||||
// LDC
|
||||
llvmForceLogging = false;
|
||||
this->doDocComment = doDocComment;
|
||||
this->doHdrGen = doHdrGen;
|
||||
}
|
||||
|
||||
File* Module::buildFilePath(char* forcename, const char* path, const char* ext)
|
||||
{
|
||||
char *argobj;
|
||||
if (forcename)
|
||||
argobj = forcename;
|
||||
else
|
||||
{
|
||||
if (global.params.preservePaths)
|
||||
argobj = (char*)this->arg;
|
||||
else
|
||||
argobj = FileName::name((char*)this->arg);
|
||||
|
||||
if (global.params.fqnNames)
|
||||
{
|
||||
if(md)
|
||||
argobj = FileName::replaceName(argobj, md->toChars());
|
||||
else
|
||||
argobj = FileName::replaceName(argobj, toChars());
|
||||
|
||||
// add ext, otherwise forceExt will make nested.module into nested.bc
|
||||
size_t len = strlen(argobj);
|
||||
size_t extlen = strlen(ext);
|
||||
char* s = (char *)alloca(len + 1 + extlen + 1);
|
||||
memcpy(s, argobj, len);
|
||||
s[len] = '.';
|
||||
memcpy(s + len + 1, ext, extlen + 1);
|
||||
s[len+1+extlen] = 0;
|
||||
argobj = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FileName::absolute(argobj))
|
||||
{
|
||||
argobj = FileName::combine(path, argobj);
|
||||
}
|
||||
|
||||
FileName::ensurePathExists(FileName::path(argobj));
|
||||
|
||||
// always append the extension! otherwise hard to make output switches consistent
|
||||
// if (forcename)
|
||||
// return new File(argobj);
|
||||
// else
|
||||
// allow for .o and .obj on windows
|
||||
#if _WIN32
|
||||
if (ext == global.params.objdir && FileName::ext(argobj)
|
||||
&& stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
|
||||
return new File(argobj);
|
||||
#endif
|
||||
return new File(FileName::forceExt(argobj, ext));
|
||||
}
|
||||
|
||||
void Module::buildTargetFiles()
|
||||
{
|
||||
if(objfile &&
|
||||
(!doDocComment || docfile) &&
|
||||
(!doHdrGen || hdrfile))
|
||||
return;
|
||||
|
||||
if(!objfile)
|
||||
objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.obj_ext);
|
||||
if(doDocComment && !docfile)
|
||||
docfile = Module::buildFilePath(global.params.docname, global.params.docdir, global.doc_ext);
|
||||
if(doHdrGen && !hdrfile)
|
||||
hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext);
|
||||
|
||||
// safety check: never allow obj, doc or hdr file to have the source file's name
|
||||
if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
|
||||
{
|
||||
error("Output object files with the same name as the source file are forbidden");
|
||||
fatal();
|
||||
}
|
||||
if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
|
||||
{
|
||||
error("Output doc files with the same name as the source file are forbidden");
|
||||
fatal();
|
||||
}
|
||||
if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
|
||||
{
|
||||
error("Output header files with the same name as the source file are forbidden");
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
||||
void Module::deleteObjFile()
|
||||
{
|
||||
if (global.params.obj)
|
||||
objfile->remove();
|
||||
//if (global.params.llvmBC)
|
||||
//bcfile->remove();
|
||||
if (doDocComment && docfile)
|
||||
docfile->remove();
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
}
|
||||
|
||||
const char *Module::kind()
|
||||
{
|
||||
return "module";
|
||||
}
|
||||
|
||||
Module *Module::load(Loc loc, Array *packages, Identifier *ident)
|
||||
{ Module *m;
|
||||
char *filename;
|
||||
|
||||
//printf("Module::load(ident = '%s')\n", ident->toChars());
|
||||
|
||||
// Build module filename by turning:
|
||||
// foo.bar.baz
|
||||
// into:
|
||||
// foo\bar\baz
|
||||
filename = ident->toChars();
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
OutBuffer buf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
|
||||
buf.writestring(pid->toChars());
|
||||
#if _WIN32
|
||||
buf.writeByte('\\');
|
||||
#else
|
||||
buf.writeByte('/');
|
||||
#endif
|
||||
}
|
||||
buf.writestring(filename);
|
||||
buf.writeByte(0);
|
||||
filename = (char *)buf.extractData();
|
||||
}
|
||||
|
||||
m = new Module(filename, ident, 0, 0);
|
||||
m->loc = loc;
|
||||
|
||||
/* Search along global.path for .di file, then .d file.
|
||||
*/
|
||||
char *result = NULL;
|
||||
FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
|
||||
FileName *fd = FileName::forceExt(filename, global.mars_ext);
|
||||
char *sdi = fdi->toChars();
|
||||
char *sd = fd->toChars();
|
||||
|
||||
if (FileName::exists(sdi))
|
||||
result = sdi;
|
||||
else if (FileName::exists(sd))
|
||||
result = sd;
|
||||
else if (FileName::absolute(filename))
|
||||
;
|
||||
else if (!global.path)
|
||||
;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < global.path->dim; i++)
|
||||
{
|
||||
char *p = (char *)global.path->data[i];
|
||||
char *n = FileName::combine(p, sdi);
|
||||
if (FileName::exists(n))
|
||||
{ result = n;
|
||||
break;
|
||||
}
|
||||
mem.free(n);
|
||||
n = FileName::combine(p, sd);
|
||||
if (FileName::exists(n))
|
||||
{ result = n;
|
||||
break;
|
||||
}
|
||||
mem.free(n);
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
m->srcfile = new File(result);
|
||||
|
||||
if (global.params.verbose)
|
||||
{
|
||||
printf("import ");
|
||||
if (packages)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
||||
}
|
||||
|
||||
m->read(loc);
|
||||
m->parse();
|
||||
|
||||
#ifdef IN_GCC
|
||||
d_gcc_magic_module(m);
|
||||
#endif
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void Module::read(Loc loc)
|
||||
{
|
||||
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
|
||||
if (srcfile->read())
|
||||
{ error(loc, "cannot read file '%s'", srcfile->toChars());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned readwordLE(unsigned short *p)
|
||||
{
|
||||
#if __I86__
|
||||
return *p;
|
||||
#else
|
||||
return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned readwordBE(unsigned short *p)
|
||||
{
|
||||
return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
|
||||
}
|
||||
|
||||
inline unsigned readlongLE(unsigned *p)
|
||||
{
|
||||
#if __I86__
|
||||
return *p;
|
||||
#else
|
||||
return ((unsigned char *)p)[0] |
|
||||
(((unsigned char *)p)[1] << 8) |
|
||||
(((unsigned char *)p)[2] << 16) |
|
||||
(((unsigned char *)p)[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned readlongBE(unsigned *p)
|
||||
{
|
||||
return ((unsigned char *)p)[3] |
|
||||
(((unsigned char *)p)[2] << 8) |
|
||||
(((unsigned char *)p)[1] << 16) |
|
||||
(((unsigned char *)p)[0] << 24);
|
||||
}
|
||||
|
||||
#if IN_GCC
|
||||
void Module::parse(bool dump_source)
|
||||
#else
|
||||
void Module::parse()
|
||||
#endif
|
||||
{ char *srcname;
|
||||
unsigned char *buf;
|
||||
unsigned buflen;
|
||||
unsigned le;
|
||||
unsigned bom;
|
||||
|
||||
//printf("Module::parse()\n");
|
||||
|
||||
srcname = srcfile->name->toChars();
|
||||
//printf("Module::parse(srcname = '%s')\n", srcname);
|
||||
|
||||
buf = srcfile->buffer;
|
||||
buflen = srcfile->len;
|
||||
|
||||
if (buflen >= 2)
|
||||
{
|
||||
/* Convert all non-UTF-8 formats to UTF-8.
|
||||
* BOM : http://www.unicode.org/faq/utf_bom.html
|
||||
* 00 00 FE FF UTF-32BE, big-endian
|
||||
* FF FE 00 00 UTF-32LE, little-endian
|
||||
* FE FF UTF-16BE, big-endian
|
||||
* FF FE UTF-16LE, little-endian
|
||||
* EF BB BF UTF-8
|
||||
*/
|
||||
|
||||
bom = 1; // assume there's a BOM
|
||||
if (buf[0] == 0xFF && buf[1] == 0xFE)
|
||||
{
|
||||
if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
|
||||
{ // UTF-32LE
|
||||
le = 1;
|
||||
|
||||
Lutf32:
|
||||
OutBuffer dbuf;
|
||||
unsigned *pu = (unsigned *)(buf);
|
||||
unsigned *pumax = &pu[buflen / 4];
|
||||
|
||||
if (buflen & 3)
|
||||
{ error("odd length of UTF-32 char source %u", buflen);
|
||||
fatal();
|
||||
}
|
||||
|
||||
dbuf.reserve(buflen / 4);
|
||||
for (pu += bom; pu < pumax; pu++)
|
||||
{ unsigned u;
|
||||
|
||||
u = le ? readlongLE(pu) : readlongBE(pu);
|
||||
if (u & ~0x7F)
|
||||
{
|
||||
if (u > 0x10FFFF)
|
||||
{ error("UTF-32 value %08x greater than 0x10FFFF", u);
|
||||
fatal();
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); // add 0 as sentinel for scanner
|
||||
buflen = dbuf.offset - 1; // don't include sentinel in count
|
||||
buf = (unsigned char *) dbuf.extractData();
|
||||
}
|
||||
else
|
||||
{ // UTF-16LE (X86)
|
||||
// Convert it to UTF-8
|
||||
le = 1;
|
||||
|
||||
Lutf16:
|
||||
OutBuffer dbuf;
|
||||
unsigned short *pu = (unsigned short *)(buf);
|
||||
unsigned short *pumax = &pu[buflen / 2];
|
||||
|
||||
if (buflen & 1)
|
||||
{ error("odd length of UTF-16 char source %u", buflen);
|
||||
fatal();
|
||||
}
|
||||
|
||||
dbuf.reserve(buflen / 2);
|
||||
for (pu += bom; pu < pumax; pu++)
|
||||
{ unsigned u;
|
||||
|
||||
u = le ? readwordLE(pu) : readwordBE(pu);
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ unsigned u2;
|
||||
|
||||
if (++pu > pumax)
|
||||
{ error("surrogate UTF-16 high value %04x at EOF", u);
|
||||
fatal();
|
||||
}
|
||||
u2 = le ? readwordLE(pu) : readwordBE(pu);
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ error("surrogate UTF-16 low value %04x out of range", u2);
|
||||
fatal();
|
||||
}
|
||||
u = (u - 0xD7C0) << 10;
|
||||
u |= (u2 - 0xDC00);
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ error("unpaired surrogate UTF-16 value %04x", u);
|
||||
fatal();
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ error("illegal UTF-16 value %04x", u);
|
||||
fatal();
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); // add 0 as sentinel for scanner
|
||||
buflen = dbuf.offset - 1; // don't include sentinel in count
|
||||
buf = (unsigned char *) dbuf.extractData();
|
||||
}
|
||||
}
|
||||
else if (buf[0] == 0xFE && buf[1] == 0xFF)
|
||||
{ // UTF-16BE
|
||||
le = 0;
|
||||
goto Lutf16;
|
||||
}
|
||||
else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
|
||||
{ // UTF-32BE
|
||||
le = 0;
|
||||
goto Lutf32;
|
||||
}
|
||||
else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
|
||||
{ // UTF-8
|
||||
|
||||
buf += 3;
|
||||
buflen -= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no BOM. Make use of Arcane Jill's insight that
|
||||
* the first char of D source must be ASCII to
|
||||
* figure out the encoding.
|
||||
*/
|
||||
|
||||
bom = 0;
|
||||
if (buflen >= 4)
|
||||
{ if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
|
||||
{ // UTF-32LE
|
||||
le = 1;
|
||||
goto Lutf32;
|
||||
}
|
||||
else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
|
||||
{ // UTF-32BE
|
||||
le = 0;
|
||||
goto Lutf32;
|
||||
}
|
||||
}
|
||||
if (buflen >= 2)
|
||||
{
|
||||
if (buf[1] == 0)
|
||||
{ // UTF-16LE
|
||||
le = 1;
|
||||
goto Lutf16;
|
||||
}
|
||||
else if (buf[0] == 0)
|
||||
{ // UTF-16BE
|
||||
le = 0;
|
||||
goto Lutf16;
|
||||
}
|
||||
}
|
||||
|
||||
// It's UTF-8
|
||||
if (buf[0] >= 0x80)
|
||||
{ error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IN_GCC
|
||||
// dump utf-8 encoded source
|
||||
if (dump_source)
|
||||
{ // %% srcname could contain a path ...
|
||||
d_gcc_dump_source(srcname, "utf-8", buf, buflen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If it starts with the string "Ddoc", then it's a documentation
|
||||
* source file.
|
||||
*/
|
||||
if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
|
||||
{
|
||||
comment = buf + 4;
|
||||
isDocFile = 1;
|
||||
return;
|
||||
}
|
||||
if (isHtml)
|
||||
{
|
||||
OutBuffer *dbuf = new OutBuffer();
|
||||
Html h(srcname, buf, buflen);
|
||||
h.extractCode(dbuf);
|
||||
buf = dbuf->data;
|
||||
buflen = dbuf->offset;
|
||||
#ifdef IN_GCC
|
||||
// dump extracted source
|
||||
if (dump_source)
|
||||
d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
|
||||
#endif
|
||||
}
|
||||
Parser p(this, buf, buflen, docfile != NULL);
|
||||
p.nextToken();
|
||||
members = p.parseModule();
|
||||
md = p.md;
|
||||
numlines = p.loc.linnum;
|
||||
|
||||
DsymbolTable *dst;
|
||||
|
||||
if (md)
|
||||
{ this->ident = md->id;
|
||||
dst = Package::resolve(md->packages, &this->parent, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = modules;
|
||||
|
||||
/* Check to see if module name is a valid identifier
|
||||
*/
|
||||
if (!Lexer::isValidIdentifier(this->ident->toChars()))
|
||||
error("has non-identifier characters in filename, use module declaration instead");
|
||||
}
|
||||
|
||||
// Update global list of modules
|
||||
if (!dst->insert(this))
|
||||
{
|
||||
if (md)
|
||||
error(loc, "is in multiple packages %s", md->toChars());
|
||||
else
|
||||
error(loc, "is in multiple defined");
|
||||
}
|
||||
else
|
||||
{
|
||||
amodules.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::semantic(Scope* unused_sc)
|
||||
{ int i;
|
||||
|
||||
if (semanticstarted)
|
||||
return;
|
||||
|
||||
//printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
|
||||
semanticstarted = 1;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
// gets imported, it is unaffected by context.
|
||||
Scope *sc = Scope::createGlobal(this); // create root scope
|
||||
|
||||
//printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
|
||||
|
||||
// Add import of "object" if this module isn't "object"
|
||||
if (ident != Id::object)
|
||||
{
|
||||
Import *im = new Import(0, NULL, Id::object, NULL, 0);
|
||||
members->shift(im);
|
||||
}
|
||||
|
||||
// Add all symbols into module's symbol table
|
||||
symtab = new DsymbolTable();
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
s->addMember(NULL, sc->scopesym, 1);
|
||||
}
|
||||
|
||||
// Pass 1 semantic routines: do public side of the definition
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
|
||||
s->semantic(sc);
|
||||
runDeferredSemantic();
|
||||
}
|
||||
|
||||
sc = sc->pop();
|
||||
sc->pop();
|
||||
semanticdone = semanticstarted;
|
||||
//printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
|
||||
}
|
||||
|
||||
void Module::semantic2(Scope* unused_sc)
|
||||
{ int i;
|
||||
|
||||
if (deferred.dim)
|
||||
{
|
||||
for (int i = 0; i < deferred.dim; i++)
|
||||
{
|
||||
Dsymbol *sd = (Dsymbol *)deferred.data[i];
|
||||
|
||||
sd->error("unable to resolve forward reference in definition");
|
||||
}
|
||||
return;
|
||||
}
|
||||
//printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
||||
if (semanticstarted >= 2)
|
||||
return;
|
||||
assert(semanticstarted == 1);
|
||||
semanticstarted = 2;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
// gets imported, it is unaffected by context.
|
||||
Scope *sc = Scope::createGlobal(this); // create root scope
|
||||
//printf("Module = %p\n", sc.scopesym);
|
||||
|
||||
// Pass 2 semantic routines: do initializers and function bodies
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
s->semantic2(sc);
|
||||
}
|
||||
|
||||
sc = sc->pop();
|
||||
sc->pop();
|
||||
semanticdone = semanticstarted;
|
||||
//printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
||||
}
|
||||
|
||||
void Module::semantic3(Scope* unused_sc)
|
||||
{ int i;
|
||||
|
||||
//printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
|
||||
if (semanticstarted >= 3)
|
||||
return;
|
||||
assert(semanticstarted == 2);
|
||||
semanticstarted = 3;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
// gets imported, it is unaffected by context.
|
||||
Scope *sc = Scope::createGlobal(this); // create root scope
|
||||
//printf("Module = %p\n", sc.scopesym);
|
||||
|
||||
// Pass 3 semantic routines: do initializers and function bodies
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
//printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
|
||||
s->semantic3(sc);
|
||||
}
|
||||
|
||||
sc = sc->pop();
|
||||
sc->pop();
|
||||
semanticdone = semanticstarted;
|
||||
}
|
||||
|
||||
void Module::inlineScan()
|
||||
{ int i;
|
||||
|
||||
if (semanticstarted >= 4)
|
||||
return;
|
||||
assert(semanticstarted == 3);
|
||||
semanticstarted = 4;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
// gets imported, it is unaffected by context.
|
||||
//printf("Module = %p\n", sc.scopesym);
|
||||
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
//if (global.params.verbose)
|
||||
//printf("inline scan symbol %s\n", s->toChars());
|
||||
|
||||
s->inlineScan();
|
||||
}
|
||||
semanticdone = semanticstarted;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
*/
|
||||
|
||||
// is this used anywhere?
|
||||
/*
|
||||
void Module::gensymfile()
|
||||
{
|
||||
OutBuffer buf;
|
||||
HdrGenState hgs;
|
||||
|
||||
//printf("Module::gensymfile()\n");
|
||||
|
||||
buf.printf("// Sym file generated from '%s'", srcfile->toChars());
|
||||
buf.writenl();
|
||||
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
|
||||
s->toCBuffer(&buf, &hgs);
|
||||
}
|
||||
|
||||
// Transfer image to file
|
||||
symfile->setbuffer(buf.data, buf.offset);
|
||||
buf.data = NULL;
|
||||
|
||||
symfile->writev();
|
||||
}*/
|
||||
|
||||
/**********************************
|
||||
* Determine if we need to generate an instance of ModuleInfo
|
||||
* for this Module.
|
||||
*/
|
||||
|
||||
int Module::needModuleInfo()
|
||||
{
|
||||
return needmoduleinfo;
|
||||
}
|
||||
|
||||
Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
/* Since modules can be circularly referenced,
|
||||
* need to stop infinite recursive searches.
|
||||
*/
|
||||
|
||||
//printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
|
||||
Dsymbol *s;
|
||||
if (insearch)
|
||||
s = NULL;
|
||||
else if (searchCacheIdent == ident && searchCacheFlags == flags)
|
||||
s = searchCacheSymbol;
|
||||
else
|
||||
{
|
||||
insearch = 1;
|
||||
s = ScopeDsymbol::search(loc, ident, flags);
|
||||
insearch = 0;
|
||||
|
||||
searchCacheIdent = ident;
|
||||
searchCacheSymbol = s;
|
||||
searchCacheFlags = flags;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Can't run semantic on s now, try again later.
|
||||
*/
|
||||
|
||||
void Module::addDeferredSemantic(Dsymbol *s)
|
||||
{
|
||||
// Don't add it if it is already there
|
||||
for (int i = 0; i < deferred.dim; i++)
|
||||
{
|
||||
Dsymbol *sd = (Dsymbol *)deferred.data[i];
|
||||
|
||||
if (sd == s)
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("Module::addDeferredSemantic('%s')\n", s->toChars());
|
||||
deferred.push(s);
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
* Run semantic() on deferred symbols.
|
||||
*/
|
||||
|
||||
void Module::runDeferredSemantic()
|
||||
{
|
||||
size_t len;
|
||||
|
||||
static int nested;
|
||||
if (nested)
|
||||
return;
|
||||
//if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
|
||||
nested++;
|
||||
|
||||
do
|
||||
{
|
||||
dprogress = 0;
|
||||
len = deferred.dim;
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
Dsymbol **todo;
|
||||
Dsymbol *tmp;
|
||||
if (len == 1)
|
||||
{
|
||||
todo = &tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
|
||||
assert(todo);
|
||||
}
|
||||
memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
|
||||
deferred.setDim(0);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Dsymbol *s = todo[i];
|
||||
|
||||
s->semantic(NULL);
|
||||
//printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
|
||||
}
|
||||
//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
|
||||
} while (deferred.dim < len || dprogress); // while making progress
|
||||
nested--;
|
||||
//printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
|
||||
}
|
||||
|
||||
/* =========================== ModuleDeclaration ===================== */
|
||||
|
||||
ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id)
|
||||
{
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
char *ModuleDeclaration::toChars()
|
||||
{
|
||||
OutBuffer buf;
|
||||
int i;
|
||||
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
|
||||
buf.writestring(pid->toChars());
|
||||
buf.writeByte('.');
|
||||
}
|
||||
}
|
||||
buf.writestring(id->toChars());
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
|
||||
/* =========================== Package ===================== */
|
||||
|
||||
Package::Package(Identifier *ident)
|
||||
: ScopeDsymbol(ident)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const char *Package::kind()
|
||||
{
|
||||
return "package";
|
||||
}
|
||||
|
||||
|
||||
DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
|
||||
{
|
||||
DsymbolTable *dst = Module::modules;
|
||||
Dsymbol *parent = NULL;
|
||||
|
||||
//printf("Package::resolve()\n");
|
||||
if (ppkg)
|
||||
*ppkg = NULL;
|
||||
|
||||
if (packages)
|
||||
{ int i;
|
||||
|
||||
for (i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
Dsymbol *p;
|
||||
|
||||
p = dst->lookup(pid);
|
||||
if (!p)
|
||||
{
|
||||
p = new Package(pid);
|
||||
dst->insert(p);
|
||||
p->parent = parent;
|
||||
((ScopeDsymbol *)p)->symtab = new DsymbolTable();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(p->isPackage());
|
||||
if (p->isModule())
|
||||
{ p->error("module and package have the same name");
|
||||
fatal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
parent = p;
|
||||
dst = ((Package *)p)->symtab;
|
||||
if (ppkg && !*ppkg)
|
||||
*ppkg = (Package *)p;
|
||||
}
|
||||
if (pparent)
|
||||
{
|
||||
*pparent = parent;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
194
dmd2/module.h
Normal file
194
dmd2/module.h
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_MODULE_H
|
||||
#define DMD_MODULE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct ModuleInfoDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct ModuleDeclaration;
|
||||
struct Macro;
|
||||
struct Escape;
|
||||
struct VarDeclaration;
|
||||
struct Library;
|
||||
|
||||
// Back end
|
||||
#if IN_LLVM
|
||||
struct DValue;
|
||||
typedef DValue elem;
|
||||
#else
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node elem;
|
||||
#else
|
||||
struct elem;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Package : ScopeDsymbol
|
||||
{
|
||||
Package(Identifier *ident);
|
||||
const char *kind();
|
||||
|
||||
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
|
||||
|
||||
Package *isPackage() { return this; }
|
||||
|
||||
virtual void semantic(Scope *sc) { }
|
||||
};
|
||||
|
||||
struct Module : Package
|
||||
{
|
||||
static Module *rootModule;
|
||||
static DsymbolTable *modules; // symbol table of all modules
|
||||
static Array amodules; // array of all modules
|
||||
static Array deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
static unsigned dprogress; // progress resolving the deferred list
|
||||
static void init();
|
||||
|
||||
static ClassDeclaration *moduleinfo;
|
||||
|
||||
|
||||
const char *arg; // original argument name
|
||||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||
File *srcfile; // input source file
|
||||
|
||||
File *objfile; // output object file
|
||||
File *docfile; // output doc file
|
||||
File *hdrfile; // output hdr file
|
||||
|
||||
unsigned errors; // if any errors in file
|
||||
unsigned numlines; // number of lines in source file
|
||||
int isHtml; // if it is an HTML file
|
||||
int isDocFile; // if it is a documentation input file, not D source
|
||||
int needmoduleinfo;
|
||||
#ifdef IN_GCC
|
||||
int strictlyneedmoduleinfo;
|
||||
#endif
|
||||
|
||||
int insearch;
|
||||
Identifier *searchCacheIdent;
|
||||
Dsymbol *searchCacheSymbol; // cached value of search
|
||||
int searchCacheFlags; // cached flags
|
||||
|
||||
int semanticstarted; // has semantic() been started?
|
||||
int semanticdone; // has semantic() been done?
|
||||
int root; // != 0 if this is a 'root' module,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
Module *importedFrom; // module from command line we're imported from,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
|
||||
Array *decldefs; // top level declarations for this Module
|
||||
|
||||
Array aimports; // all imported modules
|
||||
|
||||
ModuleInfoDeclaration *vmoduleinfo;
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
Array *debugidsNot; // forward referenced debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
Array *versionidsNot; // forward referenced version identifiers
|
||||
|
||||
Macro *macrotable; // document comment macros
|
||||
struct Escape *escapetable; // document comment escapes
|
||||
|
||||
int doDocComment; // enable generating doc comments for this module
|
||||
int doHdrGen; // enable generating header file for this module
|
||||
|
||||
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
|
||||
~Module();
|
||||
|
||||
static Module *load(Loc loc, Array *packages, Identifier *ident);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
void read(Loc loc); // read file
|
||||
#if IN_GCC
|
||||
void parse(bool dump_source = false); // syntactic parse
|
||||
#else
|
||||
void parse(); // syntactic parse
|
||||
#endif
|
||||
void semantic(Scope* unused_sc = NULL); // semantic analysis
|
||||
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
|
||||
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
|
||||
void inlineScan(); // scan for functions to inline
|
||||
#ifdef _DH
|
||||
void genhdrfile(); // generate D import file
|
||||
#endif
|
||||
void genobjfile(int multiobj, char** envp);
|
||||
// void gensymfile();
|
||||
void gendocfile();
|
||||
int needModuleInfo();
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
void runDeferredSemantic();
|
||||
|
||||
// Back end
|
||||
|
||||
int doppelganger; // sub-module
|
||||
Symbol *cov; // private uint[] __coverage;
|
||||
unsigned *covb; // bit array of valid code line numbers
|
||||
|
||||
Symbol *sictor; // module order independent constructor
|
||||
Symbol *sctor; // module constructor
|
||||
Symbol *sdtor; // module destructor
|
||||
Symbol *stest; // module unit test
|
||||
|
||||
Symbol *sfilename; // symbol for filename
|
||||
|
||||
Symbol *massert; // module assert function
|
||||
Symbol *toModuleAssert(); // get module assert function
|
||||
|
||||
Symbol *marray; // module array bounds function
|
||||
Symbol *toModuleArray(); // get module array bounds function
|
||||
|
||||
|
||||
static Symbol *gencritsec();
|
||||
elem *toEfilename();
|
||||
elem *toEmodulename();
|
||||
|
||||
Symbol *toSymbol();
|
||||
void genmoduleinfo();
|
||||
|
||||
// LDC
|
||||
void buildTargetFiles();
|
||||
File* buildFilePath(char* forcename, const char* path, const char* ext);
|
||||
Module *isModule() { return this; }
|
||||
|
||||
bool llvmForceLogging;
|
||||
|
||||
// array ops emitted in this module already
|
||||
StringTable arrayfuncs;
|
||||
};
|
||||
|
||||
|
||||
struct ModuleDeclaration
|
||||
{
|
||||
Identifier *id;
|
||||
Array *packages; // array of Identifier's representing packages
|
||||
|
||||
ModuleDeclaration(Array *packages, Identifier *id);
|
||||
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
#endif /* DMD_MODULE_H */
|
||||
6383
dmd2/mtype.c
Normal file
6383
dmd2/mtype.c
Normal file
File diff suppressed because it is too large
Load Diff
808
dmd2/mtype.h
Normal file
808
dmd2/mtype.h
Normal file
@@ -0,0 +1,808 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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_MTYPE_H
|
||||
#define DMD_MTYPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "arraytypes.h"
|
||||
#include "expression.h"
|
||||
|
||||
// llvm
|
||||
#include "../ir/irtype.h"
|
||||
|
||||
struct Scope;
|
||||
struct Identifier;
|
||||
struct Expression;
|
||||
struct StructDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct TypeInfoDeclaration;
|
||||
struct Dsymbol;
|
||||
struct TemplateInstance;
|
||||
struct CppMangleState;
|
||||
enum LINK;
|
||||
|
||||
struct TypeBasic;
|
||||
struct HdrGenState;
|
||||
|
||||
// Back end
|
||||
#if IN_GCC
|
||||
union tree_node; typedef union tree_node TYPE;
|
||||
typedef TYPE type;
|
||||
#else
|
||||
typedef struct TYPE type;
|
||||
#endif
|
||||
struct Symbol;
|
||||
|
||||
enum ENUMTY
|
||||
{
|
||||
Tarray, // dynamic array
|
||||
Tsarray, // static array
|
||||
Taarray, // associative array
|
||||
Tpointer,
|
||||
Treference,
|
||||
Tfunction,
|
||||
Tident,
|
||||
Tclass,
|
||||
Tstruct,
|
||||
Tenum,
|
||||
Ttypedef,
|
||||
Tdelegate,
|
||||
|
||||
Tnone,
|
||||
Tvoid,
|
||||
Tint8,
|
||||
Tuns8,
|
||||
Tint16,
|
||||
Tuns16,
|
||||
Tint32,
|
||||
Tuns32,
|
||||
Tint64,
|
||||
Tuns64,
|
||||
Tfloat32,
|
||||
Tfloat64,
|
||||
Tfloat80,
|
||||
|
||||
Timaginary32,
|
||||
Timaginary64,
|
||||
Timaginary80,
|
||||
|
||||
Tcomplex32,
|
||||
Tcomplex64,
|
||||
Tcomplex80,
|
||||
|
||||
Tbit,
|
||||
Tbool,
|
||||
Tchar,
|
||||
Twchar,
|
||||
Tdchar,
|
||||
|
||||
Terror,
|
||||
Tinstance,
|
||||
Ttypeof,
|
||||
Ttuple,
|
||||
Tslice,
|
||||
Treturn,
|
||||
TMAX
|
||||
};
|
||||
typedef unsigned char TY; // ENUMTY
|
||||
|
||||
#define Tascii Tchar
|
||||
|
||||
extern int Tsize_t;
|
||||
extern int Tptrdiff_t;
|
||||
|
||||
|
||||
struct Type : Object
|
||||
{
|
||||
TY ty;
|
||||
unsigned char mod; // modifiers MODxxxx
|
||||
#define MODconst 1 // type is const
|
||||
#define MODinvariant 2 // type is invariant
|
||||
#define MODshared 4 // type is shared
|
||||
char *deco;
|
||||
Type *cto; // MODconst ? mutable version of this type : const version
|
||||
Type *ito; // MODinvariant ? mutable version of this type : invariant version
|
||||
Type *pto; // merged pointer to this type
|
||||
Type *rto; // reference to this type
|
||||
Type *arrayof; // array of this type
|
||||
TypeInfoDeclaration *vtinfo; // TypeInfo object for this Type
|
||||
|
||||
type *ctype; // for back end
|
||||
|
||||
#define tvoid basic[Tvoid]
|
||||
#define tint8 basic[Tint8]
|
||||
#define tuns8 basic[Tuns8]
|
||||
#define tint16 basic[Tint16]
|
||||
#define tuns16 basic[Tuns16]
|
||||
#define tint32 basic[Tint32]
|
||||
#define tuns32 basic[Tuns32]
|
||||
#define tint64 basic[Tint64]
|
||||
#define tuns64 basic[Tuns64]
|
||||
#define tfloat32 basic[Tfloat32]
|
||||
#define tfloat64 basic[Tfloat64]
|
||||
#define tfloat80 basic[Tfloat80]
|
||||
|
||||
#define timaginary32 basic[Timaginary32]
|
||||
#define timaginary64 basic[Timaginary64]
|
||||
#define timaginary80 basic[Timaginary80]
|
||||
|
||||
#define tcomplex32 basic[Tcomplex32]
|
||||
#define tcomplex64 basic[Tcomplex64]
|
||||
#define tcomplex80 basic[Tcomplex80]
|
||||
|
||||
#define tbit basic[Tbit]
|
||||
#define tbool basic[Tbool]
|
||||
#define tchar basic[Tchar]
|
||||
#define twchar basic[Twchar]
|
||||
#define tdchar basic[Tdchar]
|
||||
|
||||
// Some special types
|
||||
#define tshiftcnt tint32 // right side of shift expression
|
||||
// #define tboolean tint32 // result of boolean expression
|
||||
#define tboolean tbool // result of boolean expression
|
||||
#define tindex tint32 // array/ptr index
|
||||
static Type *tvoidptr; // void*
|
||||
#define terror basic[Terror] // for error recovery
|
||||
|
||||
#define tsize_t basic[Tsize_t] // matches size_t alias
|
||||
#define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias
|
||||
#define thash_t tsize_t // matches hash_t alias
|
||||
|
||||
static ClassDeclaration *typeinfo;
|
||||
static ClassDeclaration *typeinfoclass;
|
||||
static ClassDeclaration *typeinfointerface;
|
||||
static ClassDeclaration *typeinfostruct;
|
||||
static ClassDeclaration *typeinfotypedef;
|
||||
static ClassDeclaration *typeinfopointer;
|
||||
static ClassDeclaration *typeinfoarray;
|
||||
static ClassDeclaration *typeinfostaticarray;
|
||||
static ClassDeclaration *typeinfoassociativearray;
|
||||
static ClassDeclaration *typeinfoenum;
|
||||
static ClassDeclaration *typeinfofunction;
|
||||
static ClassDeclaration *typeinfodelegate;
|
||||
static ClassDeclaration *typeinfotypelist;
|
||||
static ClassDeclaration *typeinfoconst;
|
||||
static ClassDeclaration *typeinfoinvariant;
|
||||
|
||||
static Type *basic[TMAX];
|
||||
static unsigned char mangleChar[TMAX];
|
||||
static unsigned char sizeTy[TMAX];
|
||||
static StringTable stringtable;
|
||||
|
||||
// These tables are for implicit conversion of binary ops;
|
||||
// the indices are the type of operand one, followed by operand two.
|
||||
static unsigned char impcnvResult[TMAX][TMAX];
|
||||
static unsigned char impcnvType1[TMAX][TMAX];
|
||||
static unsigned char impcnvType2[TMAX][TMAX];
|
||||
|
||||
// If !=0, give warning on implicit conversion
|
||||
static unsigned char impcnvWarn[TMAX][TMAX];
|
||||
|
||||
Type(TY ty);
|
||||
virtual Type *syntaxCopy();
|
||||
int equals(Object *o);
|
||||
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
|
||||
int covariant(Type *t);
|
||||
char *toChars();
|
||||
static char needThisPrefix();
|
||||
static void init();
|
||||
d_uns64 size();
|
||||
virtual d_uns64 size(Loc loc);
|
||||
virtual unsigned alignsize();
|
||||
virtual Type *semantic(Loc loc, Scope *sc);
|
||||
virtual void toDecoBuffer(OutBuffer *buf, int flag = 0);
|
||||
Type *merge();
|
||||
virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
||||
virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
#if TARGET_LINUX
|
||||
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
virtual int isintegral();
|
||||
virtual int isfloating(); // real, imaginary, or complex
|
||||
virtual int isreal();
|
||||
virtual int isimaginary();
|
||||
virtual int iscomplex();
|
||||
virtual int isscalar();
|
||||
virtual int isunsigned();
|
||||
virtual int isauto();
|
||||
virtual int isString();
|
||||
virtual int isAssignable();
|
||||
virtual int checkBoolean(); // if can be converted to boolean value
|
||||
virtual void checkDeprecated(Loc loc, Scope *sc);
|
||||
int isConst() { return mod == MODconst; }
|
||||
int isInvariant() { return mod == MODinvariant; }
|
||||
int isMutable() { return mod == 0; }
|
||||
Type *constOf();
|
||||
Type *invariantOf();
|
||||
Type *mutableOf();
|
||||
Type *pointerTo();
|
||||
Type *referenceTo();
|
||||
Type *arrayOf();
|
||||
virtual Type *makeConst();
|
||||
virtual Type *makeInvariant();
|
||||
virtual Dsymbol *toDsymbol(Scope *sc);
|
||||
virtual Type *toBasetype();
|
||||
virtual Type *toHeadMutable();
|
||||
virtual int isBaseOf(Type *t, int *poffset);
|
||||
virtual MATCH constConv(Type *to);
|
||||
virtual MATCH implicitConvTo(Type *to);
|
||||
virtual ClassDeclaration *isClassHandle();
|
||||
virtual Expression *getProperty(Loc loc, Identifier *ident);
|
||||
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
virtual unsigned memalign(unsigned salign);
|
||||
virtual Expression *defaultInit(Loc loc = 0);
|
||||
virtual int isZeroInit(); // if initializer is 0
|
||||
virtual dt_t **toDt(dt_t **pdt);
|
||||
Identifier *getTypeInfoIdent(int internal);
|
||||
virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Expression *getInternalTypeInfo(Scope *sc);
|
||||
Expression *getTypeInfo(Scope *sc);
|
||||
virtual TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
virtual int builtinTypeInfo();
|
||||
virtual Type *reliesOnTident();
|
||||
virtual Expression *toExpression();
|
||||
virtual int hasPointers();
|
||||
virtual Type *nextOf();
|
||||
|
||||
static void error(Loc loc, const char *format, ...);
|
||||
|
||||
// For backend
|
||||
virtual unsigned totym();
|
||||
virtual type *toCtype();
|
||||
virtual type *toCParamtype();
|
||||
virtual Symbol *toSymbol();
|
||||
|
||||
// For eliminating dynamic_cast
|
||||
virtual TypeBasic *isTypeBasic();
|
||||
|
||||
// LDC
|
||||
IrType ir;
|
||||
};
|
||||
|
||||
struct TypeNext : Type
|
||||
{
|
||||
Type *next;
|
||||
|
||||
TypeNext(TY ty, Type *next);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void checkDeprecated(Loc loc, Scope *sc);
|
||||
Type *reliesOnTident();
|
||||
Type *nextOf();
|
||||
Type *makeConst();
|
||||
Type *makeInvariant();
|
||||
MATCH constConv(Type *to);
|
||||
};
|
||||
|
||||
struct TypeBasic : Type
|
||||
{
|
||||
const char *dstring;
|
||||
unsigned flags;
|
||||
|
||||
TypeBasic(TY ty);
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
char *toChars();
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
int isintegral();
|
||||
int isbit();
|
||||
int isfloating();
|
||||
int isreal();
|
||||
int isimaginary();
|
||||
int iscomplex();
|
||||
int isscalar();
|
||||
int isunsigned();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
int builtinTypeInfo();
|
||||
|
||||
// For eliminating dynamic_cast
|
||||
TypeBasic *isTypeBasic();
|
||||
};
|
||||
|
||||
struct TypeArray : TypeNext
|
||||
{
|
||||
TypeArray(TY ty, Type *next);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
};
|
||||
|
||||
// Static array, one with a fixed dimension
|
||||
struct TypeSArray : TypeArray
|
||||
{
|
||||
Expression *dim;
|
||||
|
||||
TypeSArray(Type *t, Expression *dim);
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
int isString();
|
||||
int isZeroInit();
|
||||
unsigned memalign(unsigned salign);
|
||||
MATCH constConv(Type *to);
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
dt_t **toDtElem(dt_t **pdt, Expression *e);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *toExpression();
|
||||
int hasPointers();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
type *toCParamtype();
|
||||
};
|
||||
|
||||
// Dynamic array, no dimension
|
||||
struct TypeDArray : TypeArray
|
||||
{
|
||||
TypeDArray(Type *t);
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
int isString();
|
||||
int isZeroInit();
|
||||
int checkBoolean();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int builtinTypeInfo();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypeAArray : TypeArray
|
||||
{
|
||||
Type *index; // key type
|
||||
|
||||
TypeAArray(Type *t, Type *index);
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
Expression *defaultInit(Loc loc);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
int isZeroInit();
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
// Back end
|
||||
Symbol *aaGetSymbol(const char *func, int flags);
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypePointer : TypeNext
|
||||
{
|
||||
TypePointer(Type *t);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
MATCH implicitConvTo(Type *to);
|
||||
int isscalar();
|
||||
// LDC: pointers are unsigned
|
||||
int isunsigned() { return TRUE; };
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypeReference : TypeNext
|
||||
{
|
||||
TypeReference(Type *t);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
};
|
||||
|
||||
enum RET
|
||||
{
|
||||
RETregs = 1, // returned in registers
|
||||
RETstack = 2, // returned on stack
|
||||
};
|
||||
|
||||
struct TypeFunction : TypeNext
|
||||
{
|
||||
// .next is the return type
|
||||
|
||||
Arguments *parameters; // function parameters
|
||||
int varargs; // 1: T t, ...) style for variable number of arguments
|
||||
// 2: T t ...) style for variable number of arguments
|
||||
bool isnothrow; // true: nothrow
|
||||
bool ispure; // true: pure
|
||||
bool isref; // true: returns a reference
|
||||
enum LINK linkage; // calling convention
|
||||
|
||||
int inuse;
|
||||
|
||||
TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Type *reliesOnTident();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
int callMatch(Expression *ethis, Expressions *toargs);
|
||||
type *toCtype();
|
||||
enum RET retStyle();
|
||||
|
||||
unsigned totym();
|
||||
|
||||
// LDC
|
||||
bool retInPtr;
|
||||
bool usesThis;
|
||||
bool usesNest;
|
||||
unsigned retAttrs;
|
||||
unsigned thisAttrs; // also used for nest
|
||||
|
||||
bool reverseParams;
|
||||
size_t reverseIndex;
|
||||
};
|
||||
|
||||
struct TypeDelegate : TypeNext
|
||||
{
|
||||
// .next is a TypeFunction
|
||||
|
||||
TypeDelegate(Type *t);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
int hasPointers();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypeQualified : Type
|
||||
{
|
||||
Loc loc;
|
||||
Array idents; // array of Identifier's representing ident.ident.ident etc.
|
||||
|
||||
TypeQualified(TY ty, Loc loc);
|
||||
void syntaxCopyHelper(TypeQualified *t);
|
||||
void addIdent(Identifier *ident);
|
||||
void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
|
||||
d_uns64 size(Loc loc);
|
||||
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
|
||||
Expression **pe, Type **pt, Dsymbol **ps);
|
||||
};
|
||||
|
||||
struct TypeIdentifier : TypeQualified
|
||||
{
|
||||
Identifier *ident;
|
||||
|
||||
TypeIdentifier(Loc loc, Identifier *ident);
|
||||
Type *syntaxCopy();
|
||||
//char *toChars();
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
Type *reliesOnTident();
|
||||
Expression *toExpression();
|
||||
};
|
||||
|
||||
/* Similar to TypeIdentifier, but with a TemplateInstance as the root
|
||||
*/
|
||||
struct TypeInstance : TypeQualified
|
||||
{
|
||||
TemplateInstance *tempinst;
|
||||
|
||||
TypeInstance(Loc loc, TemplateInstance *tempinst);
|
||||
Type *syntaxCopy();
|
||||
//char *toChars();
|
||||
//void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
};
|
||||
|
||||
struct TypeTypeof : TypeQualified
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
TypeTypeof(Loc loc, Expression *exp);
|
||||
Type *syntaxCopy();
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
};
|
||||
|
||||
struct TypeReturn : TypeQualified
|
||||
{
|
||||
TypeReturn(Loc loc);
|
||||
Type *syntaxCopy();
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
};
|
||||
|
||||
struct TypeStruct : Type
|
||||
{
|
||||
StructDeclaration *sym;
|
||||
|
||||
TypeStruct(StructDeclaration *sym);
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
char *toChars();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
unsigned memalign(unsigned salign);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
int isAssignable();
|
||||
int checkBoolean();
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
Type *toHeadMutable();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypeEnum : Type
|
||||
{
|
||||
EnumDeclaration *sym;
|
||||
|
||||
TypeEnum(EnumDeclaration *sym);
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
char *toChars();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
int isintegral();
|
||||
int isfloating();
|
||||
int isscalar();
|
||||
int isunsigned();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
Type *toBasetype();
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
};
|
||||
|
||||
struct TypeTypedef : Type
|
||||
{
|
||||
TypedefDeclaration *sym;
|
||||
|
||||
TypeTypedef(TypedefDeclaration *sym);
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
char *toChars();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
int isbit();
|
||||
int isintegral();
|
||||
int isfloating();
|
||||
int isreal();
|
||||
int isimaginary();
|
||||
int iscomplex();
|
||||
int isscalar();
|
||||
int isunsigned();
|
||||
int checkBoolean();
|
||||
int isAssignable();
|
||||
Type *toBasetype();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
Type *toHeadMutable();
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
type *toCParamtype();
|
||||
};
|
||||
|
||||
struct TypeClass : Type
|
||||
{
|
||||
ClassDeclaration *sym;
|
||||
|
||||
TypeClass(ClassDeclaration *sym);
|
||||
d_uns64 size(Loc loc);
|
||||
char *toChars();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
ClassDeclaration *isClassHandle();
|
||||
int isBaseOf(Type *t, int *poffset);
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit();
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
int isauto();
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
Type *toHeadMutable();
|
||||
MATCH constConv(Type *to);
|
||||
#if TARGET_LINUX
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
type *toCtype();
|
||||
|
||||
Symbol *toSymbol();
|
||||
};
|
||||
|
||||
struct TypeTuple : Type
|
||||
{
|
||||
Arguments *arguments; // types making up the tuple
|
||||
|
||||
TypeTuple(Arguments *arguments);
|
||||
TypeTuple(Expressions *exps);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
int equals(Object *o);
|
||||
Type *reliesOnTident();
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
};
|
||||
|
||||
struct TypeSlice : TypeNext
|
||||
{
|
||||
Expression *lwr;
|
||||
Expression *upr;
|
||||
|
||||
TypeSlice(Type *next, Expression *lwr, Expression *upr);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
//enum InOut { None, In, Out, InOut, Lazy };
|
||||
|
||||
struct Argument : Object
|
||||
{
|
||||
//enum InOut inout;
|
||||
unsigned storageClass;
|
||||
Type *type;
|
||||
Identifier *ident;
|
||||
Expression *defaultArg;
|
||||
|
||||
Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
|
||||
Argument *syntaxCopy();
|
||||
Type *isLazyArray();
|
||||
void toDecoBuffer(OutBuffer *buf);
|
||||
static Arguments *arraySyntaxCopy(Arguments *args);
|
||||
static char *argsTypesToChars(Arguments *args, int varargs);
|
||||
static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs);
|
||||
static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
|
||||
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
|
||||
static int isTPL(Arguments *arguments);
|
||||
static size_t dim(Arguments *arguments);
|
||||
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
||||
|
||||
// LDC
|
||||
unsigned llvmAttrs;
|
||||
};
|
||||
|
||||
extern int PTRSIZE;
|
||||
extern int REALSIZE;
|
||||
extern int REALPAD;
|
||||
extern int Tsize_t;
|
||||
extern int Tptrdiff_t;
|
||||
|
||||
#endif /* DMD_MTYPE_H */
|
||||
744
dmd2/opover.c
Normal file
744
dmd2/opover.c
Normal file
@@ -0,0 +1,744 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <complex>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#elif POSIX
|
||||
#include "../root/mem.h"
|
||||
#elif _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#endif
|
||||
|
||||
//#include "port.h"
|
||||
#include "mtype.h"
|
||||
#include "init.h"
|
||||
#include "expression.h"
|
||||
#include "id.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "template.h"
|
||||
|
||||
static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
|
||||
static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments);
|
||||
static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
|
||||
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
|
||||
|
||||
/******************************** Expression **************************/
|
||||
|
||||
|
||||
/***********************************
|
||||
* Determine if operands of binary op can be reversed
|
||||
* to fit operator overload.
|
||||
*/
|
||||
|
||||
int Expression::isCommutative()
|
||||
{
|
||||
return FALSE; // default is no reverse
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Get Identifier for operator overload.
|
||||
*/
|
||||
|
||||
Identifier *Expression::opId()
|
||||
{
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Get Identifier for reverse operator overload,
|
||||
* NULL if not supported for this operator.
|
||||
*/
|
||||
|
||||
Identifier *Expression::opId_r()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************* Operators *****************************/
|
||||
|
||||
Identifier *UAddExp::opId() { return Id::uadd; }
|
||||
|
||||
Identifier *NegExp::opId() { return Id::neg; }
|
||||
|
||||
Identifier *ComExp::opId() { return Id::com; }
|
||||
|
||||
Identifier *CastExp::opId() { return Id::cast; }
|
||||
|
||||
Identifier *InExp::opId() { return Id::opIn; }
|
||||
Identifier *InExp::opId_r() { return Id::opIn_r; }
|
||||
|
||||
Identifier *PostExp::opId() { return (op == TOKplusplus)
|
||||
? Id::postinc
|
||||
: Id::postdec; }
|
||||
|
||||
int AddExp::isCommutative() { return TRUE; }
|
||||
Identifier *AddExp::opId() { return Id::add; }
|
||||
Identifier *AddExp::opId_r() { return Id::add_r; }
|
||||
|
||||
Identifier *MinExp::opId() { return Id::sub; }
|
||||
Identifier *MinExp::opId_r() { return Id::sub_r; }
|
||||
|
||||
int MulExp::isCommutative() { return TRUE; }
|
||||
Identifier *MulExp::opId() { return Id::mul; }
|
||||
Identifier *MulExp::opId_r() { return Id::mul_r; }
|
||||
|
||||
Identifier *DivExp::opId() { return Id::div; }
|
||||
Identifier *DivExp::opId_r() { return Id::div_r; }
|
||||
|
||||
Identifier *ModExp::opId() { return Id::mod; }
|
||||
Identifier *ModExp::opId_r() { return Id::mod_r; }
|
||||
|
||||
Identifier *ShlExp::opId() { return Id::shl; }
|
||||
Identifier *ShlExp::opId_r() { return Id::shl_r; }
|
||||
|
||||
Identifier *ShrExp::opId() { return Id::shr; }
|
||||
Identifier *ShrExp::opId_r() { return Id::shr_r; }
|
||||
|
||||
Identifier *UshrExp::opId() { return Id::ushr; }
|
||||
Identifier *UshrExp::opId_r() { return Id::ushr_r; }
|
||||
|
||||
int AndExp::isCommutative() { return TRUE; }
|
||||
Identifier *AndExp::opId() { return Id::iand; }
|
||||
Identifier *AndExp::opId_r() { return Id::iand_r; }
|
||||
|
||||
int OrExp::isCommutative() { return TRUE; }
|
||||
Identifier *OrExp::opId() { return Id::ior; }
|
||||
Identifier *OrExp::opId_r() { return Id::ior_r; }
|
||||
|
||||
int XorExp::isCommutative() { return TRUE; }
|
||||
Identifier *XorExp::opId() { return Id::ixor; }
|
||||
Identifier *XorExp::opId_r() { return Id::ixor_r; }
|
||||
|
||||
Identifier *CatExp::opId() { return Id::cat; }
|
||||
Identifier *CatExp::opId_r() { return Id::cat_r; }
|
||||
|
||||
Identifier * AssignExp::opId() { return Id::assign; }
|
||||
Identifier * AddAssignExp::opId() { return Id::addass; }
|
||||
Identifier * MinAssignExp::opId() { return Id::subass; }
|
||||
Identifier * MulAssignExp::opId() { return Id::mulass; }
|
||||
Identifier * DivAssignExp::opId() { return Id::divass; }
|
||||
Identifier * ModAssignExp::opId() { return Id::modass; }
|
||||
Identifier * AndAssignExp::opId() { return Id::andass; }
|
||||
Identifier * OrAssignExp::opId() { return Id::orass; }
|
||||
Identifier * XorAssignExp::opId() { return Id::xorass; }
|
||||
Identifier * ShlAssignExp::opId() { return Id::shlass; }
|
||||
Identifier * ShrAssignExp::opId() { return Id::shrass; }
|
||||
Identifier *UshrAssignExp::opId() { return Id::ushrass; }
|
||||
Identifier * CatAssignExp::opId() { return Id::catass; }
|
||||
|
||||
int EqualExp::isCommutative() { return TRUE; }
|
||||
Identifier *EqualExp::opId() { return Id::eq; }
|
||||
|
||||
int CmpExp::isCommutative() { return TRUE; }
|
||||
Identifier *CmpExp::opId() { return Id::cmp; }
|
||||
|
||||
Identifier *ArrayExp::opId() { return Id::index; }
|
||||
Identifier *PtrExp::opId() { return Id::opStar; }
|
||||
|
||||
/************************************
|
||||
* Operator overload.
|
||||
* Check for operator overload, if so, replace
|
||||
* with function call.
|
||||
* Return NULL if not an operator overload.
|
||||
*/
|
||||
|
||||
Expression *UnaExp::op_overload(Scope *sc)
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
Dsymbol *fd;
|
||||
Type *t1 = e1->type->toBasetype();
|
||||
|
||||
if (t1->ty == Tclass)
|
||||
{
|
||||
ad = ((TypeClass *)t1)->sym;
|
||||
goto L1;
|
||||
}
|
||||
else if (t1->ty == Tstruct)
|
||||
{
|
||||
ad = ((TypeStruct *)t1)->sym;
|
||||
|
||||
L1:
|
||||
fd = search_function(ad, opId());
|
||||
if (fd)
|
||||
{
|
||||
if (op == TOKarray)
|
||||
{
|
||||
Expression *e;
|
||||
ArrayExp *ae = (ArrayExp *)this;
|
||||
|
||||
e = new DotIdExp(loc, e1, fd->ident);
|
||||
e = new CallExp(loc, e, ae->arguments);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewrite +e1 as e1.add()
|
||||
return build_overload(loc, sc, e1, NULL, fd->ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Expression *BinExp::op_overload(Scope *sc)
|
||||
{
|
||||
//printf("BinExp::op_overload() (%s)\n", toChars());
|
||||
|
||||
AggregateDeclaration *ad;
|
||||
Type *t1 = e1->type->toBasetype();
|
||||
Type *t2 = e2->type->toBasetype();
|
||||
Identifier *id = opId();
|
||||
Identifier *id_r = opId_r();
|
||||
|
||||
Match m;
|
||||
Expressions args1;
|
||||
Expressions args2;
|
||||
int argsset = 0;
|
||||
|
||||
AggregateDeclaration *ad1;
|
||||
if (t1->ty == Tclass)
|
||||
ad1 = ((TypeClass *)t1)->sym;
|
||||
else if (t1->ty == Tstruct)
|
||||
ad1 = ((TypeStruct *)t1)->sym;
|
||||
else
|
||||
ad1 = NULL;
|
||||
|
||||
AggregateDeclaration *ad2;
|
||||
if (t2->ty == Tclass)
|
||||
ad2 = ((TypeClass *)t2)->sym;
|
||||
else if (t2->ty == Tstruct)
|
||||
ad2 = ((TypeStruct *)t2)->sym;
|
||||
else
|
||||
ad2 = NULL;
|
||||
|
||||
Dsymbol *s = NULL;
|
||||
Dsymbol *s_r = NULL;
|
||||
FuncDeclaration *fd = NULL;
|
||||
TemplateDeclaration *td = NULL;
|
||||
if (ad1 && id)
|
||||
{
|
||||
s = search_function(ad1, id);
|
||||
}
|
||||
if (ad2 && id_r)
|
||||
{
|
||||
s_r = search_function(ad2, id_r);
|
||||
}
|
||||
|
||||
if (s || s_r)
|
||||
{
|
||||
/* Try:
|
||||
* a.opfunc(b)
|
||||
* b.opfunc_r(a)
|
||||
* and see which is better.
|
||||
*/
|
||||
Expression *e;
|
||||
FuncDeclaration *lastf;
|
||||
|
||||
args1.setDim(1);
|
||||
args1.data[0] = (void*) e1;
|
||||
args2.setDim(1);
|
||||
args2.data[0] = (void*) e2;
|
||||
argsset = 1;
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.last = MATCHnomatch;
|
||||
|
||||
if (s)
|
||||
{
|
||||
fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
|
||||
}
|
||||
}
|
||||
|
||||
lastf = m.lastf;
|
||||
|
||||
if (s_r)
|
||||
{
|
||||
fd = s_r->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args1);
|
||||
}
|
||||
else
|
||||
{ td = s_r->isTemplateDeclaration();
|
||||
templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
|
||||
}
|
||||
}
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
// Error, ambiguous
|
||||
error("overloads %s and %s both match argument list for %s",
|
||||
m.lastf->type->toChars(),
|
||||
m.nextf->type->toChars(),
|
||||
m.lastf->toChars());
|
||||
}
|
||||
else if (m.last == MATCHnomatch)
|
||||
{
|
||||
m.lastf = m.anyf;
|
||||
}
|
||||
|
||||
if (op == TOKplusplus || op == TOKminusminus)
|
||||
// Kludge because operator overloading regards e++ and e--
|
||||
// as unary, but it's implemented as a binary.
|
||||
// Rewrite (e1 ++ e2) as e1.postinc()
|
||||
// Rewrite (e1 -- e2) as e1.postdec()
|
||||
e = build_overload(loc, sc, e1, NULL, id);
|
||||
else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
|
||||
// Rewrite (e1 op e2) as e1.opfunc(e2)
|
||||
e = build_overload(loc, sc, e1, e2, id);
|
||||
else
|
||||
// Rewrite (e1 op e2) as e2.opfunc_r(e1)
|
||||
e = build_overload(loc, sc, e2, e1, id_r);
|
||||
return e;
|
||||
}
|
||||
|
||||
if (isCommutative())
|
||||
{
|
||||
s = NULL;
|
||||
s_r = NULL;
|
||||
if (ad1 && id_r)
|
||||
{
|
||||
s_r = search_function(ad1, id_r);
|
||||
}
|
||||
if (ad2 && id)
|
||||
{
|
||||
s = search_function(ad2, id);
|
||||
}
|
||||
|
||||
if (s || s_r)
|
||||
{
|
||||
/* Try:
|
||||
* a.opfunc_r(b)
|
||||
* b.opfunc(a)
|
||||
* and see which is better.
|
||||
*/
|
||||
Expression *e;
|
||||
FuncDeclaration *lastf;
|
||||
|
||||
if (!argsset)
|
||||
{ args1.setDim(1);
|
||||
args1.data[0] = (void*) e1;
|
||||
args2.setDim(1);
|
||||
args2.data[0] = (void*) e2;
|
||||
}
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.last = MATCHnomatch;
|
||||
|
||||
if (s_r)
|
||||
{
|
||||
fd = s_r->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ td = s_r->isTemplateDeclaration();
|
||||
templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
|
||||
}
|
||||
}
|
||||
lastf = m.lastf;
|
||||
|
||||
if (s)
|
||||
{
|
||||
fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args1);
|
||||
}
|
||||
else
|
||||
{ td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
|
||||
}
|
||||
}
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
// Error, ambiguous
|
||||
error("overloads %s and %s both match argument list for %s",
|
||||
m.lastf->type->toChars(),
|
||||
m.nextf->type->toChars(),
|
||||
m.lastf->toChars());
|
||||
}
|
||||
else if (m.last == MATCHnomatch)
|
||||
{
|
||||
m.lastf = m.anyf;
|
||||
}
|
||||
|
||||
if (lastf && m.lastf == lastf ||
|
||||
id_r && m.last == MATCHnomatch)
|
||||
// Rewrite (e1 op e2) as e1.opfunc_r(e2)
|
||||
e = build_overload(loc, sc, e1, e2, id_r);
|
||||
else
|
||||
// Rewrite (e1 op e2) as e2.opfunc(e1)
|
||||
e = build_overload(loc, sc, e2, e1, id);
|
||||
|
||||
// When reversing operands of comparison operators,
|
||||
// need to reverse the sense of the op
|
||||
switch (op)
|
||||
{
|
||||
case TOKlt: op = TOKgt; break;
|
||||
case TOKgt: op = TOKlt; break;
|
||||
case TOKle: op = TOKge; break;
|
||||
case TOKge: op = TOKle; break;
|
||||
|
||||
// Floating point compares
|
||||
case TOKule: op = TOKuge; break;
|
||||
case TOKul: op = TOKug; break;
|
||||
case TOKuge: op = TOKule; break;
|
||||
case TOKug: op = TOKul; break;
|
||||
|
||||
// These are symmetric
|
||||
case TOKunord:
|
||||
case TOKlg:
|
||||
case TOKleg:
|
||||
case TOKue:
|
||||
break;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Utility to build a function call out of this reference and argument.
|
||||
*/
|
||||
|
||||
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
|
||||
{
|
||||
Expression *e;
|
||||
|
||||
//printf("build_overload(id = '%s')\n", id->toChars());
|
||||
//earg->print();
|
||||
//earg->type->print();
|
||||
e = new DotIdExp(loc, ethis, id);
|
||||
|
||||
if (earg)
|
||||
e = new CallExp(loc, e, earg);
|
||||
else
|
||||
e = new CallExp(loc, e);
|
||||
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Search for function funcid in aggregate ad.
|
||||
*/
|
||||
|
||||
Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
|
||||
{
|
||||
Dsymbol *s;
|
||||
FuncDeclaration *fd;
|
||||
TemplateDeclaration *td;
|
||||
|
||||
s = ad->search(0, funcid, 0);
|
||||
if (s)
|
||||
{ Dsymbol *s2;
|
||||
|
||||
//printf("search_function: s = '%s'\n", s->kind());
|
||||
s2 = s->toAlias();
|
||||
//printf("search_function: s2 = '%s'\n", s2->kind());
|
||||
fd = s2->isFuncDeclaration();
|
||||
if (fd && fd->type->ty == Tfunction)
|
||||
return fd;
|
||||
|
||||
td = s2->isTemplateDeclaration();
|
||||
if (td)
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Given array of arguments and an aggregate type,
|
||||
* if any of the argument types are missing, attempt to infer
|
||||
* them from the aggregate type.
|
||||
*/
|
||||
|
||||
void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr)
|
||||
{
|
||||
if (!arguments || !arguments->dim)
|
||||
return;
|
||||
|
||||
/* Return if no arguments need types.
|
||||
*/
|
||||
for (size_t u = 0; 1; u++)
|
||||
{ if (u == arguments->dim)
|
||||
return;
|
||||
Argument *arg = (Argument *)arguments->data[u];
|
||||
if (!arg->type)
|
||||
break;
|
||||
}
|
||||
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
Argument *arg = (Argument *)arguments->data[0];
|
||||
Type *taggr = aggr->type;
|
||||
if (!taggr)
|
||||
return;
|
||||
Type *tab = taggr->toBasetype();
|
||||
switch (tab->ty)
|
||||
{
|
||||
case Tarray:
|
||||
case Tsarray:
|
||||
case Ttuple:
|
||||
if (arguments->dim == 2)
|
||||
{
|
||||
if (!arg->type)
|
||||
arg->type = Type::tsize_t; // key type
|
||||
arg = (Argument *)arguments->data[1];
|
||||
}
|
||||
if (!arg->type && tab->ty != Ttuple)
|
||||
arg->type = tab->nextOf(); // value type
|
||||
break;
|
||||
|
||||
case Taarray:
|
||||
{ TypeAArray *taa = (TypeAArray *)tab;
|
||||
|
||||
if (arguments->dim == 2)
|
||||
{
|
||||
if (!arg->type)
|
||||
arg->type = taa->index; // key type
|
||||
arg = (Argument *)arguments->data[1];
|
||||
}
|
||||
if (!arg->type)
|
||||
arg->type = taa->next; // value type
|
||||
break;
|
||||
}
|
||||
|
||||
case Tclass:
|
||||
ad = ((TypeClass *)tab)->sym;
|
||||
goto Laggr;
|
||||
|
||||
case Tstruct:
|
||||
ad = ((TypeStruct *)tab)->sym;
|
||||
goto Laggr;
|
||||
|
||||
Laggr:
|
||||
#if 0
|
||||
if (arguments->dim == 1)
|
||||
{
|
||||
if (!arg->type)
|
||||
{
|
||||
/* Look for an opNext() overload
|
||||
*/
|
||||
Dsymbol *s = search_function(ad, Id::next);
|
||||
fd = s ? s->isFuncDeclaration() : NULL;
|
||||
if (!fd)
|
||||
goto Lapply;
|
||||
arg->type = fd->type->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Lapply:
|
||||
{ /* Look for an
|
||||
* int opApply(int delegate(ref Type [, ...]) dg);
|
||||
* overload
|
||||
*/
|
||||
Dsymbol *s = search_function(ad,
|
||||
(op == TOKforeach_reverse) ? Id::applyReverse
|
||||
: Id::apply);
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{ inferApplyArgTypesX(fd, arguments);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
if (td)
|
||||
{ inferApplyArgTypesZ(td, arguments);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Tdelegate:
|
||||
{
|
||||
if (0 && aggr->op == TOKdelegate)
|
||||
{ DelegateExp *de = (DelegateExp *)aggr;
|
||||
|
||||
FuncDeclaration *fd = de->func->isFuncDeclaration();
|
||||
if (fd)
|
||||
inferApplyArgTypesX(fd, arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break; // ignore error, caught later
|
||||
}
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Recursive helper function,
|
||||
* analogous to func.overloadResolveX().
|
||||
*/
|
||||
|
||||
int fp3(void *param, FuncDeclaration *f)
|
||||
{
|
||||
Arguments *arguments = (Arguments *)param;
|
||||
TypeFunction *tf = (TypeFunction *)f->type;
|
||||
if (inferApplyArgTypesY(tf, arguments) == 1)
|
||||
return 0;
|
||||
if (arguments->dim == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
|
||||
{
|
||||
overloadApply(fstart, &fp3, arguments);
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Infer arguments from type of function.
|
||||
* Returns:
|
||||
* 0 match for this function
|
||||
* 1 no match for this function
|
||||
*/
|
||||
|
||||
static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
|
||||
{ size_t nparams;
|
||||
Argument *p;
|
||||
|
||||
if (Argument::dim(tf->parameters) != 1)
|
||||
goto Lnomatch;
|
||||
p = Argument::getNth(tf->parameters, 0);
|
||||
if (p->type->ty != Tdelegate)
|
||||
goto Lnomatch;
|
||||
tf = (TypeFunction *)p->type->nextOf();
|
||||
assert(tf->ty == Tfunction);
|
||||
|
||||
/* We now have tf, the type of the delegate. Match it against
|
||||
* the arguments, filling in missing argument types.
|
||||
*/
|
||||
nparams = Argument::dim(tf->parameters);
|
||||
if (nparams == 0 || tf->varargs)
|
||||
goto Lnomatch; // not enough parameters
|
||||
if (arguments->dim != nparams)
|
||||
goto Lnomatch; // not enough parameters
|
||||
|
||||
for (size_t u = 0; u < nparams; u++)
|
||||
{
|
||||
Argument *arg = (Argument *)arguments->data[u];
|
||||
Argument *param = Argument::getNth(tf->parameters, u);
|
||||
if (arg->type)
|
||||
{ if (!arg->type->equals(param->type))
|
||||
{
|
||||
/* Cannot resolve argument types. Indicate an
|
||||
* error by setting the number of arguments to 0.
|
||||
*/
|
||||
arguments->dim = 0;
|
||||
goto Lmatch;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
arg->type = param->type;
|
||||
}
|
||||
Lmatch:
|
||||
return 0;
|
||||
|
||||
Lnomatch:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Infer foreach arg types from a template function opApply which looks like:
|
||||
* int opApply(alias int func(ref uint))() { ... }
|
||||
*/
|
||||
|
||||
#if 0
|
||||
void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments)
|
||||
{
|
||||
for (TemplateDeclaration *td = tstart; td; td = td->overnext)
|
||||
{
|
||||
if (!td->scope)
|
||||
{
|
||||
error("forward reference to template %s", td->toChars());
|
||||
return;
|
||||
}
|
||||
if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
|
||||
{
|
||||
error("is not a function template");
|
||||
return;
|
||||
}
|
||||
if (!td->parameters || td->parameters->dim != 1)
|
||||
continue;
|
||||
TemplateParameter *tp = (TemplateParameter *)td->parameters->data[0];
|
||||
TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
|
||||
if (!tap || !tap->specType || tap->specType->ty != Tfunction)
|
||||
continue;
|
||||
TypeFunction *tf = (TypeFunction *)tap->specType;
|
||||
if (inferApplyArgTypesY(tf, arguments) == 0) // found it
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
*/
|
||||
|
||||
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
|
||||
{
|
||||
FuncDeclaration *fd;
|
||||
|
||||
assert(td);
|
||||
fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
|
||||
if (!fd)
|
||||
return;
|
||||
m->anyf = fd;
|
||||
if (m->last >= MATCHexact)
|
||||
{
|
||||
m->nextf = fd;
|
||||
m->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m->last = MATCHexact;
|
||||
m->lastf = fd;
|
||||
m->count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
914
dmd2/optimize.c
Normal file
914
dmd2/optimize.c
Normal file
@@ -0,0 +1,914 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#if __DMC__
|
||||
#include <complex.h>
|
||||
#endif
|
||||
|
||||
#include "lexer.h"
|
||||
#include "mtype.h"
|
||||
#include "expression.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "init.h"
|
||||
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
|
||||
/* %% fix? */
|
||||
extern "C" bool real_isnan (const real_t *);
|
||||
#endif
|
||||
|
||||
static real_t zero; // work around DMC bug for now
|
||||
|
||||
|
||||
/*************************************
|
||||
* If variable has a const initializer,
|
||||
* return that initializer.
|
||||
*/
|
||||
|
||||
Expression *expandVar(int result, VarDeclaration *v)
|
||||
{
|
||||
//printf("expandVar(result = %d, v = %s)\n", result, v ? v->toChars() : "null");
|
||||
Expression *e = NULL;
|
||||
if (v && (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest))
|
||||
{
|
||||
Type *tb = v->type->toBasetype();
|
||||
if (result & WANTinterpret ||
|
||||
v->storage_class & STCmanifest ||
|
||||
(tb->ty != Tsarray && tb->ty != Tstruct)
|
||||
)
|
||||
{
|
||||
if (v->init)
|
||||
{
|
||||
if (v->inuse)
|
||||
goto L1;
|
||||
Expression *ei = v->init->toExpression();
|
||||
if (!ei)
|
||||
goto L1;
|
||||
if (ei->op == TOKconstruct || ei->op == TOKblit)
|
||||
{ AssignExp *ae = (AssignExp *)ei;
|
||||
ei = ae->e2;
|
||||
if (ei->isConst() != 1 && ei->op != TOKstring)
|
||||
goto L1;
|
||||
if (ei->type != v->type)
|
||||
goto L1;
|
||||
}
|
||||
if (v->scope)
|
||||
{
|
||||
v->inuse++;
|
||||
e = ei->syntaxCopy();
|
||||
e = e->semantic(v->scope);
|
||||
e = e->implicitCastTo(v->scope, v->type);
|
||||
v->scope = NULL;
|
||||
v->inuse--;
|
||||
}
|
||||
else if (!ei->type)
|
||||
{
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
// Should remove the copy() operation by
|
||||
// making all mods to expressions copy-on-write
|
||||
e = ei->copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
goto L1;
|
||||
#else
|
||||
// BUG: what if const is initialized in constructor?
|
||||
e = v->type->defaultInit();
|
||||
e->loc = e1->loc;
|
||||
#endif
|
||||
}
|
||||
if (e->type != v->type)
|
||||
{
|
||||
e = e->castTo(NULL, v->type);
|
||||
}
|
||||
e = e->optimize(result);
|
||||
}
|
||||
}
|
||||
L1:
|
||||
//if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *fromConstInitializer(int result, Expression *e1)
|
||||
{
|
||||
//printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
|
||||
//static int xx; if (xx++ == 10) assert(0);
|
||||
Expression *e = e1;
|
||||
if (e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
e = expandVar(result, v);
|
||||
if (e)
|
||||
{ if (e->type != e1->type)
|
||||
{ // Type 'paint' operation
|
||||
e = e->copy();
|
||||
e->type = e1->type;
|
||||
}
|
||||
}
|
||||
else
|
||||
e = e1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *Expression::optimize(int result)
|
||||
{
|
||||
//printf("Expression::optimize(result = x%x) %s\n", result, toChars());
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *VarExp::optimize(int result)
|
||||
{
|
||||
return fromConstInitializer(result, this);
|
||||
}
|
||||
|
||||
Expression *TupleExp::optimize(int result)
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
exps->data[i] = (void *)e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *ArrayLiteralExp::optimize(int result)
|
||||
{
|
||||
if (elements)
|
||||
{
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
elements->data[i] = (void *)e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *AssocArrayLiteralExp::optimize(int result)
|
||||
{
|
||||
assert(keys->dim == values->dim);
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = (Expression *)keys->data[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
keys->data[i] = (void *)e;
|
||||
|
||||
e = (Expression *)values->data[i];
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
values->data[i] = (void *)e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *StructLiteralExp::optimize(int result)
|
||||
{
|
||||
if (elements)
|
||||
{
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
if (!e)
|
||||
continue;
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
elements->data[i] = (void *)e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *TypeExp::optimize(int result)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *UnaExp::optimize(int result)
|
||||
{
|
||||
e1 = e1->optimize(result);
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *NegExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
if (e1->isConst() == 1)
|
||||
{
|
||||
e = Neg(type, e1);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ComExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
if (e1->isConst() == 1)
|
||||
{
|
||||
e = Com(type, e1);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *NotExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
if (e1->isConst() == 1)
|
||||
{
|
||||
e = Not(type, e1);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *BoolExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
if (e1->isConst() == 1)
|
||||
{
|
||||
e = Bool(type, e1);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *AddrExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
|
||||
|
||||
/* Rewrite &(a,b) as (a,&b)
|
||||
*/
|
||||
if (e1->op == TOKcomma)
|
||||
{ CommaExp *ce = (CommaExp *)e1;
|
||||
AddrExp *ae = new AddrExp(loc, ce->e2);
|
||||
ae->type = type;
|
||||
e = new CommaExp(ce->loc, ce->e1, ae);
|
||||
e->type = type;
|
||||
return e->optimize(result);
|
||||
}
|
||||
|
||||
if (e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e1;
|
||||
if (ve->var->storage_class & STCmanifest)
|
||||
e1 = e1->optimize(result);
|
||||
}
|
||||
else
|
||||
e1 = e1->optimize(result);
|
||||
|
||||
// Convert &*ex to ex
|
||||
if (e1->op == TOKstar)
|
||||
{ Expression *ex;
|
||||
|
||||
ex = ((PtrExp *)e1)->e1;
|
||||
if (type->equals(ex->type))
|
||||
e = ex;
|
||||
else
|
||||
{
|
||||
e = ex->copy();
|
||||
e->type = type;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
#if !IN_LLVM
|
||||
if (e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e1;
|
||||
if (!ve->var->isOut() && !ve->var->isRef() &&
|
||||
!ve->var->isImportedSymbol())
|
||||
{
|
||||
SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
|
||||
se->type = type;
|
||||
return se;
|
||||
}
|
||||
}
|
||||
if (e1->op == TOKindex)
|
||||
{ // Convert &array[n] to &array+n
|
||||
IndexExp *ae = (IndexExp *)e1;
|
||||
|
||||
if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
|
||||
{
|
||||
integer_t index = ae->e2->toInteger();
|
||||
VarExp *ve = (VarExp *)ae->e1;
|
||||
if (ve->type->ty == Tsarray
|
||||
&& !ve->var->isImportedSymbol())
|
||||
{
|
||||
TypeSArray *ts = (TypeSArray *)ve->type;
|
||||
integer_t dim = ts->dim->toInteger();
|
||||
if (index < 0 || index >= dim)
|
||||
error("array index %lld is out of bounds [0..%lld]", index, dim);
|
||||
e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
|
||||
e->type = type;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *PtrExp::optimize(int result)
|
||||
{
|
||||
//printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result);
|
||||
// Convert *&ex to ex
|
||||
if (e1->op == TOKaddress)
|
||||
{ Expression *e;
|
||||
Expression *ex;
|
||||
|
||||
ex = ((AddrExp *)e1)->e1;
|
||||
if (type->equals(ex->type))
|
||||
e = ex;
|
||||
else
|
||||
{
|
||||
e = ex->copy();
|
||||
e->type = type;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
// Constant fold *(&structliteral + offset)
|
||||
if (e1->op == TOKadd)
|
||||
{
|
||||
Expression *e;
|
||||
e = Ptr(type, e1);
|
||||
if (e != EXP_CANT_INTERPRET)
|
||||
return e;
|
||||
}
|
||||
|
||||
if (e1->op == TOKsymoff)
|
||||
{ SymOffExp *se = (SymOffExp *)e1;
|
||||
VarDeclaration *v = se->var->isVarDeclaration();
|
||||
Expression *e = expandVar(result, v);
|
||||
if (e && e->op == TOKstructliteral)
|
||||
{ StructLiteralExp *sle = (StructLiteralExp *)e;
|
||||
e = sle->getField(type, se->offset);
|
||||
if (e != EXP_CANT_INTERPRET)
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
// LDC
|
||||
Expression *DotVarExp::optimize(int result)
|
||||
{
|
||||
e1 = e1->optimize(result);
|
||||
|
||||
// Constant fold structliteral.member
|
||||
if (e1->op == TOKstructliteral)
|
||||
{ StructLiteralExp *se = (StructLiteralExp *)e1;
|
||||
|
||||
VarDeclaration* v;
|
||||
if (v = var->isVarDeclaration())
|
||||
{
|
||||
Expression *e = se->getField(type, v->offset);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
///////////////////////////////////////////
|
||||
|
||||
Expression *CallExp::optimize(int result)
|
||||
{
|
||||
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
|
||||
Expression *e = this;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
if (e1->op == TOKvar)
|
||||
{
|
||||
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
enum BUILTIN b = fd->isBuiltin();
|
||||
if (b)
|
||||
{
|
||||
e = eval_builtin(b, arguments);
|
||||
if (!e) // failed
|
||||
e = this; // evaluate at runtime
|
||||
}
|
||||
else if (result & WANTinterpret)
|
||||
{
|
||||
Expression *eresult = fd->interpret(NULL, arguments);
|
||||
if (eresult && eresult != EXP_VOID_INTERPRET)
|
||||
e = eresult;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *CastExp::optimize(int result)
|
||||
{
|
||||
//printf("CastExp::optimize(result = %d) %s\n", result, toChars());
|
||||
//printf("from %s to %s\n", type->toChars(), to->toChars());
|
||||
//printf("from %s\n", type->toChars());
|
||||
//printf("e1->type %s\n", e1->type->toChars());
|
||||
//printf("type = %p\n", type);
|
||||
assert(type);
|
||||
enum TOK op1 = e1->op;
|
||||
#define X 0
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
|
||||
if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
|
||||
(type->ty == Tpointer || type->ty == Tarray) &&
|
||||
e1->type->nextOf()->size() == type->nextOf()->size()
|
||||
)
|
||||
{
|
||||
e1 = e1->castTo(NULL, type);
|
||||
if (X) printf(" returning1 %s\n", e1->toChars());
|
||||
return e1;
|
||||
}
|
||||
|
||||
if (e1->op == TOKstructliteral &&
|
||||
e1->type->implicitConvTo(type) >= MATCHconst)
|
||||
{
|
||||
e1->type = type;
|
||||
if (X) printf(" returning2 %s\n", e1->toChars());
|
||||
return e1;
|
||||
}
|
||||
|
||||
/* The first test here is to prevent infinite loops
|
||||
*/
|
||||
if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
|
||||
return e1->castTo(NULL, to);
|
||||
if (e1->op == TOKnull &&
|
||||
(type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray))
|
||||
{
|
||||
e1->type = type;
|
||||
if (X) printf(" returning3 %s\n", e1->toChars());
|
||||
return e1;
|
||||
}
|
||||
|
||||
if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
|
||||
{
|
||||
// See if we can remove an unnecessary cast
|
||||
ClassDeclaration *cdfrom;
|
||||
ClassDeclaration *cdto;
|
||||
int offset;
|
||||
|
||||
cdfrom = e1->type->isClassHandle();
|
||||
cdto = type->isClassHandle();
|
||||
if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
|
||||
{
|
||||
e1->type = type;
|
||||
if (X) printf(" returning4 %s\n", e1->toChars());
|
||||
return e1;
|
||||
}
|
||||
}
|
||||
|
||||
// We can convert 'head const' to mutable
|
||||
if (to->constOf()->equals(e1->type->constOf()))
|
||||
// if (to->constConv(e1->type) >= MATCHconst)
|
||||
{
|
||||
e1->type = type;
|
||||
if (X) printf(" returning5 %s\n", e1->toChars());
|
||||
return e1;
|
||||
}
|
||||
|
||||
Expression *e;
|
||||
|
||||
if (e1->isConst())
|
||||
{
|
||||
if (e1->op == TOKsymoff)
|
||||
{
|
||||
if (type->size() == e1->type->size() &&
|
||||
type->toBasetype()->ty != Tsarray)
|
||||
{
|
||||
e1->type = type;
|
||||
return e1;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (to->toBasetype()->ty == Tvoid)
|
||||
e = this;
|
||||
else
|
||||
e = Cast(type, to, e1);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
if (X) printf(" returning6 %s\n", e->toChars());
|
||||
return e;
|
||||
#undef X
|
||||
}
|
||||
|
||||
Expression *BinExp::optimize(int result)
|
||||
{
|
||||
//printf("BinExp::optimize(result = %d) %s\n", result, toChars());
|
||||
if (op != TOKconstruct && op != TOKblit) // don't replace const variable with its initializer
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
|
||||
{
|
||||
if (e2->isConst() == 1)
|
||||
{
|
||||
integer_t i2 = e2->toInteger();
|
||||
d_uns64 sz = e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 > sz)
|
||||
{
|
||||
error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
||||
e2 = new IntegerExp(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *AddExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("AddExp::optimize(%s)\n", toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() && e2->isConst())
|
||||
{
|
||||
if (e1->op == TOKsymoff && e2->op == TOKsymoff)
|
||||
return this;
|
||||
e = Add(type, e1, e2);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *MinExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() && e2->isConst())
|
||||
{
|
||||
if (e2->op == TOKsymoff)
|
||||
return this;
|
||||
e = Min(type, e1, e2);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *MulExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("MulExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Mul(type, e1, e2);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *DivExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("DivExp::optimize(%s)\n", toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Div(type, e1, e2);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ModExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Mod(type, e1, e2);
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
|
||||
{ Expression *ex = e;
|
||||
|
||||
e->e1 = e->e1->optimize(result);
|
||||
e->e2 = e->e2->optimize(result);
|
||||
if (e->e2->isConst() == 1)
|
||||
{
|
||||
integer_t i2 = e->e2->toInteger();
|
||||
d_uns64 sz = e->e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 > sz)
|
||||
{
|
||||
error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
||||
e->e2 = new IntegerExp(0);
|
||||
}
|
||||
if (e->e1->isConst() == 1)
|
||||
ex = (*shift)(e->type, e->e1, e->e2);
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
Expression *ShlExp::optimize(int result)
|
||||
{
|
||||
//printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
|
||||
return shift_optimize(result, this, Shl);
|
||||
}
|
||||
|
||||
Expression *ShrExp::optimize(int result)
|
||||
{
|
||||
//printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
|
||||
return shift_optimize(result, this, Shr);
|
||||
}
|
||||
|
||||
Expression *UshrExp::optimize(int result)
|
||||
{
|
||||
//printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
|
||||
return shift_optimize(result, this, Ushr);
|
||||
}
|
||||
|
||||
Expression *AndExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = And(type, e1, e2);
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *OrExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = Or(type, e1, e2);
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *XorExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = Xor(type, e1, e2);
|
||||
else
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *CommaExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result & WANTinterpret);
|
||||
e2 = e2->optimize(result);
|
||||
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
|
||||
{
|
||||
e = e2;
|
||||
if (e)
|
||||
e->type = type;
|
||||
}
|
||||
else
|
||||
e = this;
|
||||
//printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ArrayLengthExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = this;
|
||||
if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
|
||||
{
|
||||
e = ArrayLength(type, e1);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *EqualExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = this;
|
||||
|
||||
Expression *e1 = fromConstInitializer(result, this->e1);
|
||||
Expression *e2 = fromConstInitializer(result, this->e2);
|
||||
|
||||
e = Equal(op, type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *IdentityExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = this;
|
||||
|
||||
if (this->e1->isConst() && this->e2->isConst())
|
||||
{
|
||||
e = Identity(op, type, this->e1, this->e2);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *IndexExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
|
||||
Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = Index(type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *SliceExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e = this;
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
if (!lwr)
|
||||
{ if (e1->op == TOKstring)
|
||||
{ // Convert slice of string literal into dynamic array
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->nextOf())
|
||||
e = e1->castTo(NULL, t->nextOf()->arrayOf());
|
||||
}
|
||||
return e;
|
||||
}
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
upr = upr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = Slice(type, e1, lwr, upr);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
//printf("-SliceExp::optimize() %s\n", e->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *AndAndExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("AndAndExp::optimize(%d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
|
||||
e = this;
|
||||
if (e1->isBool(FALSE))
|
||||
{
|
||||
e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
|
||||
e->type = type;
|
||||
e = e->optimize(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
|
||||
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
|
||||
error("void has no value");
|
||||
if (e1->isConst())
|
||||
{
|
||||
if (e2->isConst())
|
||||
{ int n1 = e1->isBool(1);
|
||||
int n2 = e2->isBool(1);
|
||||
|
||||
e = new IntegerExp(loc, n1 && n2, type);
|
||||
}
|
||||
else if (e1->isBool(TRUE))
|
||||
e = new BoolExp(loc, e2, type);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *OrOrExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
|
||||
e = this;
|
||||
if (e1->isBool(TRUE))
|
||||
{ // Replace with (e1, 1)
|
||||
e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
|
||||
e->type = type;
|
||||
e = e->optimize(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
|
||||
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
|
||||
error("void has no value");
|
||||
if (e1->isConst())
|
||||
{
|
||||
if (e2->isConst())
|
||||
{ int n1 = e1->isBool(1);
|
||||
int n2 = e2->isBool(1);
|
||||
|
||||
e = new IntegerExp(loc, n1 || n2, type);
|
||||
}
|
||||
else if (e1->isBool(FALSE))
|
||||
e = new BoolExp(loc, e2, type);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *CmpExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("CmpExp::optimize() %s\n", toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
|
||||
Expression *e1 = fromConstInitializer(result, this->e1);
|
||||
Expression *e2 = fromConstInitializer(result, this->e2);
|
||||
|
||||
e = Cmp(op, type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *CatExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("CatExp::optimize(%d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
e = Cat(type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *CondExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
econd = econd->optimize(WANTflags | (result & WANTinterpret));
|
||||
if (econd->isBool(TRUE))
|
||||
e = e1->optimize(result);
|
||||
else if (econd->isBool(FALSE))
|
||||
e = e2->optimize(result);
|
||||
else
|
||||
{ e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
e = this;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
5689
dmd2/parse.c
Normal file
5689
dmd2/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
145
dmd2/parse.h
Normal file
145
dmd2/parse.h
Normal file
@@ -0,0 +1,145 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_PARSE_H
|
||||
#define DMD_PARSE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "arraytypes.h"
|
||||
#include "lexer.h"
|
||||
#include "enum.h"
|
||||
|
||||
struct Type;
|
||||
struct TypeQualified;
|
||||
struct Expression;
|
||||
struct Declaration;
|
||||
struct Statement;
|
||||
struct Import;
|
||||
struct Initializer;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct ConditionalDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct Condition;
|
||||
struct Module;
|
||||
struct ModuleDeclaration;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct StaticAssert;
|
||||
|
||||
/************************************
|
||||
* These control how parseStatement() works.
|
||||
*/
|
||||
|
||||
enum ParseStatementFlags
|
||||
{
|
||||
PSsemi = 1, // empty ';' statements are allowed
|
||||
PSscope = 2, // start a new scope
|
||||
PScurly = 4, // { } statement is required
|
||||
PScurlyscope = 8, // { } starts a new scope
|
||||
};
|
||||
|
||||
|
||||
struct Parser : Lexer
|
||||
{
|
||||
ModuleDeclaration *md;
|
||||
enum LINK linkage;
|
||||
Loc endloc; // set to location of last right curly
|
||||
int inBrackets; // inside [] of array index or slice
|
||||
|
||||
Parser(Module *module, unsigned char *base, unsigned length, int doDocComment);
|
||||
|
||||
Array *parseModule();
|
||||
Array *parseDeclDefs(int once);
|
||||
Array *parseAutoDeclarations(unsigned storageClass, unsigned char *comment);
|
||||
Array *parseBlock();
|
||||
Expression *parseConstraint();
|
||||
TemplateDeclaration *parseTemplateDeclaration();
|
||||
TemplateParameters *parseTemplateParameterList(int flag = 0);
|
||||
Dsymbol *parseMixin();
|
||||
Objects *parseTemplateArgumentList();
|
||||
Objects *parseTemplateArgumentList2();
|
||||
Objects *parseTemplateArgument();
|
||||
StaticAssert *parseStaticAssert();
|
||||
TypeQualified *parseTypeof();
|
||||
enum LINK parseLinkage();
|
||||
Condition *parseDebugCondition();
|
||||
Condition *parseVersionCondition();
|
||||
Condition *parseStaticIfCondition();
|
||||
FuncDeclaration *parseCtor();
|
||||
PostBlitDeclaration *parsePostBlit();
|
||||
DtorDeclaration *parseDtor();
|
||||
StaticCtorDeclaration *parseStaticCtor();
|
||||
StaticDtorDeclaration *parseStaticDtor();
|
||||
InvariantDeclaration *parseInvariant();
|
||||
UnitTestDeclaration *parseUnitTest();
|
||||
NewDeclaration *parseNew();
|
||||
DeleteDeclaration *parseDelete();
|
||||
Arguments *parseParameters(int *pvarargs);
|
||||
EnumDeclaration *parseEnum();
|
||||
Dsymbol *parseAggregate();
|
||||
BaseClasses *parseBaseClasses();
|
||||
Import *parseImport(Array *decldefs, int isstatic);
|
||||
Type *parseType(Identifier **pident = NULL, TemplateParameters **tpl = NULL);
|
||||
Type *parseBasicType();
|
||||
Type *parseBasicType2(Type *t);
|
||||
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL);
|
||||
Array *parseDeclarations(unsigned storage_class);
|
||||
void parseContracts(FuncDeclaration *f);
|
||||
Statement *parseStatement(int flags);
|
||||
Initializer *parseInitializer();
|
||||
Expression *parseDefaultInitExp();
|
||||
void check(Loc loc, enum TOK value);
|
||||
void check(enum TOK value);
|
||||
void check(enum TOK value, const char *string);
|
||||
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
|
||||
int isBasicType(Token **pt);
|
||||
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
|
||||
int isParameters(Token **pt);
|
||||
int isExpression(Token **pt);
|
||||
int isTemplateInstance(Token *t, Token **pt);
|
||||
int skipParens(Token *t, Token **pt);
|
||||
|
||||
Expression *parseExpression();
|
||||
Expression *parsePrimaryExp();
|
||||
Expression *parseUnaryExp();
|
||||
Expression *parsePostExp(Expression *e);
|
||||
Expression *parseMulExp();
|
||||
Expression *parseAddExp();
|
||||
Expression *parseShiftExp();
|
||||
Expression *parseRelExp();
|
||||
Expression *parseEqualExp();
|
||||
Expression *parseCmpExp();
|
||||
Expression *parseAndExp();
|
||||
Expression *parseXorExp();
|
||||
Expression *parseOrExp();
|
||||
Expression *parseAndAndExp();
|
||||
Expression *parseOrOrExp();
|
||||
Expression *parseCondExp();
|
||||
Expression *parseAssignExp();
|
||||
|
||||
Expressions *parseArguments();
|
||||
|
||||
Expression *parseNewExp(Expression *thisexp);
|
||||
|
||||
void addComment(Dsymbol *s, unsigned char *blockComment);
|
||||
};
|
||||
|
||||
#endif /* DMD_PARSE_H */
|
||||
65
dmd2/port.h
Normal file
65
dmd2/port.h
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
|
||||
// Portable wrapper around compiler/system specific things.
|
||||
// The idea is to minimize #ifdef's in the app code.
|
||||
|
||||
#ifndef TYPEDEFS
|
||||
#define TYPEDEFS
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#if _MSC_VER
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
#else
|
||||
typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef double d_time;
|
||||
|
||||
struct Port
|
||||
{
|
||||
static double nan;
|
||||
static double infinity;
|
||||
static double dbl_max;
|
||||
static double dbl_min;
|
||||
|
||||
#if __GNUC__
|
||||
// These conflict with macros in math.h, should rename them
|
||||
#undef isnan
|
||||
#undef isfinite
|
||||
#undef isinfinity
|
||||
#undef signbit
|
||||
#endif
|
||||
static int isNan(double);
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
|
||||
static double floor(double);
|
||||
static double pow(double x, double y);
|
||||
|
||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||
|
||||
static char *ull_to_string(char *buffer, ulonglong ull);
|
||||
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
||||
|
||||
// Convert ulonglong to double
|
||||
static double ull_to_double(ulonglong ull);
|
||||
|
||||
// Get locale-dependent list separator
|
||||
static char *list_separator();
|
||||
static wchar_t *wlist_separator();
|
||||
};
|
||||
|
||||
#endif
|
||||
27
dmd2/readme.txt
Normal file
27
dmd2/readme.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
The D Programming Language
|
||||
Compiler Front End Source
|
||||
Copyright (c) 1999-2002, by Digital Mars
|
||||
www.digitalmars.com
|
||||
All Rights Reserved
|
||||
|
||||
|
||||
This is the source code to the front end Digital Mars D compiler.
|
||||
It covers the lexical analysis, parsing, and semantic analysis
|
||||
of the D Programming Language defined in the documents at
|
||||
www.digitalmars.com/d/
|
||||
|
||||
The optimizer, code generator, and object file generator are not part
|
||||
of this source, hence the source does not currently constitute a complete,
|
||||
compilable program. However, many people have expressed a strong interested
|
||||
in producing a D compiler with the GNU compiler sources. This release should
|
||||
enable that.
|
||||
|
||||
These sources are free, they are redistributable and modifiable
|
||||
under the terms of the GNU General Public License (attached as gpl.txt),
|
||||
or the Artistic License (attached as artistic.txt).
|
||||
|
||||
It does not apply to anything else distributed by Digital Mars,
|
||||
including D compiler executables.
|
||||
|
||||
-Walter Bright
|
||||
1852
dmd2/root.c
Normal file
1852
dmd2/root.c
Normal file
File diff suppressed because it is too large
Load Diff
350
dmd2/root.h
Normal file
350
dmd2/root.h
Normal file
@@ -0,0 +1,350 @@
|
||||
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// 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 ROOT_H
|
||||
#define ROOT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef size_t hash_t;
|
||||
|
||||
#include "dchar.h"
|
||||
|
||||
char *wchar2ascii(wchar_t *);
|
||||
int wcharIsAscii(wchar_t *);
|
||||
char *wchar2ascii(wchar_t *, unsigned len);
|
||||
int wcharIsAscii(wchar_t *, unsigned len);
|
||||
|
||||
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
||||
char *bstr2str(unsigned char *b);
|
||||
void error(const char *format, ...);
|
||||
void error(const wchar_t *format, ...);
|
||||
void warning(const char *format, ...);
|
||||
|
||||
#ifndef TYPEDEFS
|
||||
#define TYPEDEFS
|
||||
|
||||
#if _MSC_VER
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
#else
|
||||
typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
longlong randomx();
|
||||
|
||||
/*
|
||||
* Root of our class library.
|
||||
*/
|
||||
|
||||
struct OutBuffer;
|
||||
struct Array;
|
||||
|
||||
struct Object
|
||||
{
|
||||
Object() { }
|
||||
virtual ~Object() { }
|
||||
|
||||
virtual int equals(Object *o);
|
||||
|
||||
/**
|
||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||
*/
|
||||
virtual hash_t hashCode();
|
||||
|
||||
/**
|
||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||
* Useful for sorting Objects.
|
||||
*/
|
||||
virtual int compare(Object *obj);
|
||||
|
||||
/**
|
||||
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
||||
*/
|
||||
virtual void print();
|
||||
|
||||
virtual char *toChars();
|
||||
virtual dchar *toDchars();
|
||||
virtual void toBuffer(OutBuffer *buf);
|
||||
|
||||
/**
|
||||
* Used as a replacement for dynamic_cast. Returns a unique number
|
||||
* defined by the library user. For Object, the return value is 0.
|
||||
*/
|
||||
virtual int dyncast();
|
||||
|
||||
/**
|
||||
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
|
||||
*/
|
||||
/*virtual*/ // not used, disable for now
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct String : Object
|
||||
{
|
||||
int ref; // != 0 if this is a reference to someone else's string
|
||||
char *str; // the string itself
|
||||
|
||||
String(char *str, int ref = 1);
|
||||
|
||||
~String();
|
||||
|
||||
static hash_t calcHash(const char *str, size_t len);
|
||||
static hash_t calcHash(const char *str);
|
||||
hash_t hashCode();
|
||||
unsigned len();
|
||||
int equals(Object *obj);
|
||||
int compare(Object *obj);
|
||||
char *toChars();
|
||||
void print();
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct FileName : String
|
||||
{
|
||||
FileName(char *str, int ref);
|
||||
FileName(char *path, char *name);
|
||||
hash_t hashCode();
|
||||
int equals(Object *obj);
|
||||
int compare(Object *obj);
|
||||
static int absolute(const char *name);
|
||||
static char *ext(const char *);
|
||||
char *ext();
|
||||
static char *removeExt(const char *str);
|
||||
static char *name(const char *);
|
||||
char *name();
|
||||
static char *path(const char *);
|
||||
static char *replaceName(char *path, char *name);
|
||||
|
||||
static char *combine(const char *path, const char *name);
|
||||
static Array *splitPath(const char *path);
|
||||
static FileName *defaultExt(const char *name, const char *ext);
|
||||
static FileName *forceExt(const char *name, const char *ext);
|
||||
int equalsExt(const char *ext);
|
||||
|
||||
void CopyTo(FileName *to);
|
||||
static char *searchPath(Array *path, const char *name, int cwd);
|
||||
static int exists(const char *name);
|
||||
static void ensurePathExists(const char *path);
|
||||
};
|
||||
|
||||
struct File : Object
|
||||
{
|
||||
int ref; // != 0 if this is a reference to someone else's buffer
|
||||
unsigned char *buffer; // data for our file
|
||||
unsigned len; // amount of data in buffer[]
|
||||
void *touchtime; // system time to use for file
|
||||
|
||||
FileName *name; // name of our file
|
||||
|
||||
File(char *);
|
||||
File(FileName *);
|
||||
~File();
|
||||
|
||||
void mark();
|
||||
|
||||
char *toChars();
|
||||
|
||||
/* Read file, return !=0 if error
|
||||
*/
|
||||
|
||||
int read();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void readv();
|
||||
|
||||
/* Read file, return !=0 if error
|
||||
*/
|
||||
|
||||
int mmread();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void mmreadv();
|
||||
|
||||
/* Write file, return !=0 if error
|
||||
*/
|
||||
|
||||
int write();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void writev();
|
||||
|
||||
/* Return !=0 if file exists.
|
||||
* 0: file doesn't exist
|
||||
* 1: normal file
|
||||
* 2: directory
|
||||
*/
|
||||
|
||||
/* Append to file, return !=0 if error
|
||||
*/
|
||||
|
||||
int append();
|
||||
|
||||
/* Append to file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void appendv();
|
||||
|
||||
/* Return !=0 if file exists.
|
||||
* 0: file doesn't exist
|
||||
* 1: normal file
|
||||
* 2: directory
|
||||
*/
|
||||
|
||||
int exists();
|
||||
|
||||
/* Given wildcard filespec, return an array of
|
||||
* matching File's.
|
||||
*/
|
||||
|
||||
static Array *match(char *);
|
||||
static Array *match(FileName *);
|
||||
|
||||
// Compare file times.
|
||||
// Return <0 this < f
|
||||
// =0 this == f
|
||||
// >0 this > f
|
||||
int compareTime(File *f);
|
||||
|
||||
// Read system file statistics
|
||||
void stat();
|
||||
|
||||
/* Set buffer
|
||||
*/
|
||||
|
||||
void setbuffer(void *buffer, unsigned len)
|
||||
{
|
||||
this->buffer = (unsigned char *)buffer;
|
||||
this->len = len;
|
||||
}
|
||||
|
||||
void checkoffset(size_t offset, size_t nbytes);
|
||||
|
||||
void remove(); // delete file
|
||||
};
|
||||
|
||||
struct OutBuffer : Object
|
||||
{
|
||||
unsigned char *data;
|
||||
unsigned offset;
|
||||
unsigned size;
|
||||
|
||||
OutBuffer();
|
||||
~OutBuffer();
|
||||
void *extractData();
|
||||
void mark();
|
||||
|
||||
void reserve(unsigned nbytes);
|
||||
void setsize(unsigned size);
|
||||
void reset();
|
||||
void write(const void *data, unsigned nbytes);
|
||||
void writebstring(unsigned char *string);
|
||||
void writestring(const char *string);
|
||||
void writedstring(const char *string);
|
||||
void writedstring(const wchar_t *string);
|
||||
void prependstring(const char *string);
|
||||
void writenl(); // write newline
|
||||
void writeByte(unsigned b);
|
||||
void writebyte(unsigned b) { writeByte(b); }
|
||||
void writeUTF8(unsigned b);
|
||||
void writedchar(unsigned b);
|
||||
void prependbyte(unsigned b);
|
||||
void writeword(unsigned w);
|
||||
void writeUTF16(unsigned w);
|
||||
void write4(unsigned w);
|
||||
void write(OutBuffer *buf);
|
||||
void write(Object *obj);
|
||||
void fill0(unsigned nbytes);
|
||||
void align(unsigned size);
|
||||
void vprintf(const char *format, va_list args);
|
||||
void printf(const char *format, ...);
|
||||
#if M_UNICODE
|
||||
void vprintf(const unsigned short *format, va_list args);
|
||||
void printf(const unsigned short *format, ...);
|
||||
#endif
|
||||
void bracket(char left, char right);
|
||||
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
|
||||
void spread(unsigned offset, unsigned nbytes);
|
||||
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
|
||||
void remove(unsigned offset, unsigned nbytes);
|
||||
char *toChars();
|
||||
char *extractString();
|
||||
};
|
||||
|
||||
struct Array : Object
|
||||
{
|
||||
unsigned dim;
|
||||
unsigned allocdim;
|
||||
void **data;
|
||||
|
||||
Array();
|
||||
~Array();
|
||||
void mark();
|
||||
char *toChars();
|
||||
|
||||
void reserve(unsigned nentries);
|
||||
void setDim(unsigned newdim);
|
||||
void fixDim();
|
||||
void push(void *ptr);
|
||||
void *pop();
|
||||
void shift(void *ptr);
|
||||
void insert(unsigned index, void *ptr);
|
||||
void insert(unsigned index, Array *a);
|
||||
void append(Array *a);
|
||||
void remove(unsigned i);
|
||||
void zero();
|
||||
void *tos();
|
||||
void sort();
|
||||
Array *copy();
|
||||
};
|
||||
|
||||
struct Bits : Object
|
||||
{
|
||||
unsigned bitdim;
|
||||
unsigned allocdim;
|
||||
unsigned *data;
|
||||
|
||||
Bits();
|
||||
~Bits();
|
||||
void mark();
|
||||
|
||||
void resize(unsigned bitdim);
|
||||
|
||||
void set(unsigned bitnum);
|
||||
void clear(unsigned bitnum);
|
||||
int test(unsigned bitnum);
|
||||
|
||||
void set();
|
||||
void clear();
|
||||
void copy(Bits *from);
|
||||
Bits *clone();
|
||||
|
||||
void sub(Bits *b);
|
||||
};
|
||||
|
||||
#endif
|
||||
364
dmd2/scope.c
Normal file
364
dmd2/scope.c
Normal file
@@ -0,0 +1,364 @@
|
||||
|
||||
// Copyright (c) 1999-2005 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 <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "init.h"
|
||||
#include "identifier.h"
|
||||
#include "attrib.h"
|
||||
#include "dsymbol.h"
|
||||
#include "scope.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
|
||||
Scope *Scope::freelist = NULL;
|
||||
|
||||
void *Scope::operator new(size_t size)
|
||||
{
|
||||
if (freelist)
|
||||
{
|
||||
Scope *s = freelist;
|
||||
freelist = s->enclosing;
|
||||
//printf("freelist %p\n", s);
|
||||
assert(s->flags & SCOPEfree);
|
||||
s->flags &= ~SCOPEfree;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *p = ::operator new(size);
|
||||
//printf("new %p\n", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
Scope::Scope()
|
||||
{ // Create root scope
|
||||
|
||||
//printf("Scope::Scope() %p\n", this);
|
||||
this->module = NULL;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->enclosing = NULL;
|
||||
this->parent = NULL;
|
||||
this->sw = NULL;
|
||||
this->tf = NULL;
|
||||
this->tfOfTry = NULL;
|
||||
this->tinst = NULL;
|
||||
this->sbreak = NULL;
|
||||
this->scontinue = NULL;
|
||||
this->fes = NULL;
|
||||
this->structalign = global.structalign;
|
||||
this->func = NULL;
|
||||
this->slabel = NULL;
|
||||
this->linkage = LINKd;
|
||||
this->protection = PROTpublic;
|
||||
this->explicitProtection = 0;
|
||||
this->stc = 0;
|
||||
this->offset = 0;
|
||||
this->inunion = 0;
|
||||
this->incontract = 0;
|
||||
this->nofree = 0;
|
||||
this->noctor = 0;
|
||||
this->noaccesscheck = 0;
|
||||
this->intypeof = 0;
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = NULL;
|
||||
}
|
||||
|
||||
Scope::Scope(Scope *enclosing)
|
||||
{
|
||||
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
|
||||
assert(!(enclosing->flags & SCOPEfree));
|
||||
this->module = enclosing->module;
|
||||
this->func = enclosing->func;
|
||||
this->parent = enclosing->parent;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->sw = enclosing->sw;
|
||||
this->tf = enclosing->tf;
|
||||
this->tfOfTry = enclosing->tfOfTry;
|
||||
this->tinst = enclosing->tinst;
|
||||
this->sbreak = enclosing->sbreak;
|
||||
this->scontinue = enclosing->scontinue;
|
||||
this->fes = enclosing->fes;
|
||||
this->structalign = enclosing->structalign;
|
||||
this->enclosing = enclosing;
|
||||
#ifdef DEBUG
|
||||
if (enclosing->enclosing)
|
||||
assert(!(enclosing->enclosing->flags & SCOPEfree));
|
||||
if (this == enclosing->enclosing)
|
||||
{
|
||||
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
|
||||
}
|
||||
assert(this != enclosing->enclosing);
|
||||
#endif
|
||||
this->slabel = NULL;
|
||||
this->linkage = enclosing->linkage;
|
||||
this->protection = enclosing->protection;
|
||||
this->explicitProtection = enclosing->explicitProtection;
|
||||
this->stc = enclosing->stc;
|
||||
this->offset = 0;
|
||||
this->inunion = enclosing->inunion;
|
||||
this->incontract = enclosing->incontract;
|
||||
this->nofree = 0;
|
||||
this->noctor = enclosing->noctor;
|
||||
this->noaccesscheck = enclosing->noaccesscheck;
|
||||
this->intypeof = enclosing->intypeof;
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
assert(this != enclosing);
|
||||
}
|
||||
|
||||
Scope *Scope::createGlobal(Module *module)
|
||||
{
|
||||
Scope *sc;
|
||||
|
||||
sc = new Scope();
|
||||
sc->module = module;
|
||||
sc->scopesym = new ScopeDsymbol();
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
|
||||
// Add top level package as member of this global scope
|
||||
Dsymbol *m = module;
|
||||
while (m->parent)
|
||||
m = m->parent;
|
||||
m->addMember(NULL, sc->scopesym, 1);
|
||||
m->parent = NULL; // got changed by addMember()
|
||||
|
||||
// Create the module scope underneath the global scope
|
||||
sc = sc->push(module);
|
||||
sc->parent = module;
|
||||
return sc;
|
||||
}
|
||||
|
||||
Scope *Scope::push()
|
||||
{
|
||||
//printf("Scope::push()\n");
|
||||
Scope *s = new Scope(this);
|
||||
assert(this != s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::push(ScopeDsymbol *ss)
|
||||
{
|
||||
//printf("Scope::push(%s)\n", ss->toChars());
|
||||
Scope *s = push();
|
||||
s->scopesym = ss;
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::pop()
|
||||
{
|
||||
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
|
||||
Scope *enc = enclosing;
|
||||
|
||||
if (enclosing)
|
||||
enclosing->callSuper |= callSuper;
|
||||
|
||||
if (!nofree)
|
||||
{ enclosing = freelist;
|
||||
freelist = this;
|
||||
flags |= SCOPEfree;
|
||||
}
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
{
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
// regarding when and how constructors can appear.
|
||||
// It merges the results of two paths.
|
||||
// The two paths are callSuper and cs; the result is merged into callSuper.
|
||||
|
||||
if (cs != callSuper)
|
||||
{ int a;
|
||||
int b;
|
||||
|
||||
callSuper |= cs & (CSXany_ctor | CSXlabel);
|
||||
if (cs & CSXreturn)
|
||||
{
|
||||
}
|
||||
else if (callSuper & CSXreturn)
|
||||
{
|
||||
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
|
||||
}
|
||||
else
|
||||
{
|
||||
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
if (a != b)
|
||||
error(loc, "one path skips constructor");
|
||||
callSuper |= cs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
{ Dsymbol *s;
|
||||
Scope *sc;
|
||||
|
||||
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
|
||||
if (ident == Id::empty)
|
||||
{
|
||||
// Look for module scope
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
s = sc->scopesym->isModule();
|
||||
if (s)
|
||||
{
|
||||
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
|
||||
s = sc->scopesym->search(loc, ident, 0);
|
||||
if (s)
|
||||
{
|
||||
if ((global.params.warnings ||
|
||||
global.params.Dversion > 1) &&
|
||||
ident == Id::length &&
|
||||
sc->scopesym->isArrayScopeSymbol() &&
|
||||
sc->enclosing &&
|
||||
sc->enclosing->search(loc, ident, NULL))
|
||||
{
|
||||
// WTF ?
|
||||
if (global.params.warnings)
|
||||
fprintf(stdmsg, "warning - ");
|
||||
error(s->loc, "array 'length' hides other 'length' name in outer scope");
|
||||
}
|
||||
|
||||
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::insert(Dsymbol *s)
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
|
||||
if (!sc->scopesym->symtab)
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
return sc->scopesym->symtab->insert(s);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
ClassDeclaration *Scope::getClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
cd = sc->scopesym->isClassDeclaration();
|
||||
if (cd)
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
AggregateDeclaration *Scope::getStructClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
ad = sc->scopesym->isClassDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
else
|
||||
{ ad = sc->scopesym->isStructDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* For TemplateDeclarations, we need to remember the Scope
|
||||
* where it was declared. So mark the Scope as not
|
||||
* to be free'd.
|
||||
*/
|
||||
|
||||
void Scope::setNoFree()
|
||||
{ Scope *sc;
|
||||
//int i = 0;
|
||||
|
||||
//printf("Scope::setNoFree(this = %p)\n", this);
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
sc->nofree = 1;
|
||||
|
||||
assert(!(flags & SCOPEfree));
|
||||
//assert(sc != sc->enclosing);
|
||||
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
|
||||
//if (++i == 10)
|
||||
//assert(0);
|
||||
}
|
||||
}
|
||||
114
dmd2/scope.h
Normal file
114
dmd2/scope.h
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
// Copyright (c) 1999-2005 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_SCOPE_H
|
||||
#define DMD_SCOPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Array;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct EnclosingHandler;
|
||||
struct AnonDeclaration;
|
||||
enum LINK;
|
||||
enum PROT;
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
FuncDeclaration *func; // function we are in
|
||||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block
|
||||
EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
int inunion; // we're processing members of a union
|
||||
int incontract; // we're inside contract code
|
||||
int nofree; // set if shouldn't free it
|
||||
int noctor; // set if constructor calls aren't allowed
|
||||
int intypeof; // in typeof(exp)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
#define CSXthis_ctor 1 // called this()
|
||||
#define CSXsuper_ctor 2 // called super()
|
||||
#define CSXthis 4 // referenced this
|
||||
#define CSXsuper 8 // referenced super
|
||||
#define CSXlabel 0x10 // seen a label
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
unsigned structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
unsigned stc; // storage class
|
||||
|
||||
unsigned flags;
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
OutBuffer *docbuf; // buffer for documentation output
|
||||
|
||||
static Scope *freelist;
|
||||
static void *operator new(size_t sz);
|
||||
static Scope *createGlobal(Module *module);
|
||||
|
||||
Scope();
|
||||
Scope(Module *module);
|
||||
Scope(Scope *enclosing);
|
||||
|
||||
Scope *push();
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
AggregateDeclaration *getStructClassScope();
|
||||
void setNoFree();
|
||||
};
|
||||
|
||||
#endif /* DMD_SCOPE_H */
|
||||
4328
dmd2/statement.c
Normal file
4328
dmd2/statement.c
Normal file
File diff suppressed because it is too large
Load Diff
932
dmd2/statement.h
Normal file
932
dmd2/statement.h
Normal file
@@ -0,0 +1,932 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_STATEMENT_H
|
||||
#define DMD_STATEMENT_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "arraytypes.h"
|
||||
#include "dsymbol.h"
|
||||
#include "lexer.h"
|
||||
|
||||
struct OutBuffer;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct LabelDsymbol;
|
||||
struct Identifier;
|
||||
struct IfStatement;
|
||||
struct DeclarationStatement;
|
||||
struct DefaultStatement;
|
||||
struct VarDeclaration;
|
||||
struct Condition;
|
||||
struct Module;
|
||||
struct Token;
|
||||
struct InlineCostState;
|
||||
struct InlineDoState;
|
||||
struct InlineScanState;
|
||||
struct ReturnStatement;
|
||||
struct CompoundStatement;
|
||||
struct Argument;
|
||||
struct StaticAssert;
|
||||
struct AsmStatement;
|
||||
struct AsmBlockStatement;
|
||||
struct GotoStatement;
|
||||
struct ScopeStatement;
|
||||
struct TryCatchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct HdrGenState;
|
||||
struct InterState;
|
||||
struct CaseStatement;
|
||||
struct LabelStatement;
|
||||
struct VolatileStatement;
|
||||
struct SynchronizedStatement;
|
||||
|
||||
enum TOK;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
class BasicBlock;
|
||||
class ConstantInt;
|
||||
}
|
||||
|
||||
// Back end
|
||||
struct IRState;
|
||||
struct Blockx;
|
||||
#if IN_LLVM
|
||||
struct DValue;
|
||||
typedef DValue elem;
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
union tree_node; typedef union tree_node block;
|
||||
//union tree_node; typedef union tree_node elem;
|
||||
#else
|
||||
struct block;
|
||||
//struct elem;
|
||||
#endif
|
||||
struct code;
|
||||
|
||||
/* How a statement exits
|
||||
*/
|
||||
enum BE
|
||||
{
|
||||
BEnone = 0,
|
||||
BEfallthru = 1,
|
||||
BEthrow = 2,
|
||||
BEreturn = 4,
|
||||
BEgoto = 8,
|
||||
BEhalt = 0x10,
|
||||
BEbreak = 0x20,
|
||||
BEcontinue = 0x40,
|
||||
BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
|
||||
};
|
||||
|
||||
// LDC this is used for tracking try-finally, synchronized and volatile scopes
|
||||
// definitions in gen/llvmhelpers.cpp
|
||||
struct EnclosingHandler : Object
|
||||
{
|
||||
virtual void emitCode(IRState* p) = 0;
|
||||
virtual EnclosingHandler* getEnclosing() = 0;
|
||||
};
|
||||
struct EnclosingTryFinally : EnclosingHandler
|
||||
{
|
||||
TryFinallyStatement* tf;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {}
|
||||
};
|
||||
struct EnclosingVolatile : EnclosingHandler
|
||||
{
|
||||
VolatileStatement* v;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
|
||||
};
|
||||
struct EnclosingSynchro : EnclosingHandler
|
||||
{
|
||||
SynchronizedStatement* s;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingSynchro(SynchronizedStatement* _tf) : s(_tf) {}
|
||||
};
|
||||
|
||||
struct Statement : Object
|
||||
{
|
||||
Loc loc;
|
||||
|
||||
Statement(Loc loc);
|
||||
virtual Statement *syntaxCopy();
|
||||
|
||||
void print();
|
||||
char *toChars();
|
||||
|
||||
void error(const char *format, ...);
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
|
||||
virtual GotoStatement *isGotoStatement() { return NULL; }
|
||||
virtual AsmStatement *isAsmStatement() { return NULL; }
|
||||
virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
|
||||
#ifdef _DH
|
||||
int incontract;
|
||||
#endif
|
||||
virtual ScopeStatement *isScopeStatement() { return NULL; }
|
||||
virtual Statement *semantic(Scope *sc);
|
||||
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
|
||||
virtual int hasBreak();
|
||||
virtual int hasContinue();
|
||||
virtual int usesEH();
|
||||
virtual int fallOffEnd();
|
||||
virtual int blockExit();
|
||||
virtual int comeFrom();
|
||||
virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
virtual Expression *interpret(InterState *istate);
|
||||
|
||||
virtual int inlineCost(InlineCostState *ics);
|
||||
virtual Expression *doInline(InlineDoState *ids);
|
||||
virtual Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
// Back end
|
||||
virtual void toIR(IRState *irs);
|
||||
|
||||
// Avoid dynamic_cast
|
||||
virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
|
||||
virtual CompoundStatement *isCompoundStatement() { return NULL; }
|
||||
virtual ReturnStatement *isReturnStatement() { return NULL; }
|
||||
virtual IfStatement *isIfStatement() { return NULL; }
|
||||
virtual CaseStatement* isCaseStatement() { return NULL; }
|
||||
};
|
||||
|
||||
struct ExpStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
ExpStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int fallOffEnd();
|
||||
int blockExit();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct CompileStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
CompileStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statements *flatten(Scope *sc);
|
||||
Statement *semantic(Scope *sc);
|
||||
};
|
||||
|
||||
struct DeclarationStatement : ExpStatement
|
||||
{
|
||||
// Doing declarations as an expression, rather than a statement,
|
||||
// makes inlining functions much easier.
|
||||
|
||||
DeclarationStatement(Loc loc, Dsymbol *s);
|
||||
DeclarationStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
|
||||
DeclarationStatement *isDeclarationStatement() { return this; }
|
||||
};
|
||||
|
||||
struct CompoundStatement : Statement
|
||||
{
|
||||
Statements *statements;
|
||||
|
||||
CompoundStatement(Loc loc, Statements *s);
|
||||
CompoundStatement(Loc loc, Statement *s1, Statement *s2);
|
||||
virtual Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
ReturnStatement *isReturnStatement();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
virtual void toIR(IRState *irs);
|
||||
|
||||
virtual CompoundStatement *isCompoundStatement() { return this; }
|
||||
};
|
||||
|
||||
/* The purpose of this is so that continue will go to the next
|
||||
* of the statements, and break will go to the end of the statements.
|
||||
*/
|
||||
struct UnrolledLoopStatement : Statement
|
||||
{
|
||||
Statements *statements;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
UnrolledLoopStatement(Loc loc, Statements *statements);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ScopeStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
|
||||
ScopeStatement(Loc loc, Statement *s);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
ScopeStatement *isScopeStatement() { return this; }
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct WhileStatement : Statement
|
||||
{
|
||||
Expression *condition;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
WhileStatement(Loc loc, Expression *c, Statement *b);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct DoStatement : Statement
|
||||
{
|
||||
Statement *body;
|
||||
Expression *condition;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
DoStatement(Loc loc, Statement *b, Expression *c);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ForStatement : Statement
|
||||
{
|
||||
Statement *init;
|
||||
Expression *condition;
|
||||
Expression *increment;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ForeachStatement : Statement
|
||||
{
|
||||
enum TOK op; // TOKforeach or TOKforeach_reverse
|
||||
Arguments *arguments; // array of Argument*'s
|
||||
Expression *aggr;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
VarDeclaration *key;
|
||||
VarDeclaration *value;
|
||||
|
||||
FuncDeclaration *func; // function we're lexically in
|
||||
|
||||
Array cases; // put breaks, continues, gotos and returns here
|
||||
Array gotos; // forward referenced goto's go here
|
||||
|
||||
ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct ForeachRangeStatement : Statement
|
||||
{
|
||||
enum TOK op; // TOKforeach or TOKforeach_reverse
|
||||
Argument *arg; // loop index variable
|
||||
Expression *lwr;
|
||||
Expression *upr;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
VarDeclaration *key;
|
||||
|
||||
ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
|
||||
Expression *lwr, Expression *upr, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct IfStatement : Statement
|
||||
{
|
||||
Argument *arg;
|
||||
Expression *condition;
|
||||
Statement *ifbody;
|
||||
Statement *elsebody;
|
||||
|
||||
VarDeclaration *match; // for MatchExpression results
|
||||
|
||||
IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
IfStatement *isIfStatement() { return this; }
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ConditionalStatement : Statement
|
||||
{
|
||||
Condition *condition;
|
||||
Statement *ifbody;
|
||||
Statement *elsebody;
|
||||
|
||||
ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct PragmaStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
Expressions *args; // array of Expression's
|
||||
Statement *body;
|
||||
|
||||
PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct StaticAssertStatement : Statement
|
||||
{
|
||||
StaticAssert *sa;
|
||||
|
||||
StaticAssertStatement(StaticAssert *sa);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct SwitchStatement : Statement
|
||||
{
|
||||
Expression *condition;
|
||||
Statement *body;
|
||||
|
||||
DefaultStatement *sdefault;
|
||||
TryFinallyStatement *tf;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
Array gotoCases; // array of unresolved GotoCaseStatement's
|
||||
Array *cases; // array of CaseStatement's
|
||||
int hasNoDefault; // !=0 if no default statement
|
||||
int hasVars; // !=0 if has variable case values
|
||||
|
||||
SwitchStatement(Loc loc, Expression *c, Statement *b);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct CaseStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
Statement *statement;
|
||||
int index; // which case it is (since we sort this)
|
||||
block *cblock; // back end: label for the block
|
||||
|
||||
CaseStatement(Loc loc, Expression *exp, Statement *s);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int compare(Object *obj);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
CaseStatement* isCaseStatement() { return this; }
|
||||
|
||||
// LDC
|
||||
llvm::BasicBlock* bodyBB;
|
||||
llvm::ConstantInt* llvmIdx;
|
||||
};
|
||||
|
||||
struct DefaultStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
#if IN_GCC
|
||||
block *cblock; // back end: label for the block
|
||||
#endif
|
||||
|
||||
DefaultStatement(Loc loc, Statement *s);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LDC
|
||||
llvm::BasicBlock* bodyBB;
|
||||
};
|
||||
|
||||
struct GotoDefaultStatement : Statement
|
||||
{
|
||||
SwitchStatement *sw;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
GotoDefaultStatement(Loc loc);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct GotoCaseStatement : Statement
|
||||
{
|
||||
Expression *exp; // NULL, or which case to goto
|
||||
CaseStatement *cs; // case statement it resolves to
|
||||
EnclosingHandler* enclosinghandler;
|
||||
SwitchStatement *sw;
|
||||
|
||||
GotoCaseStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct SwitchErrorStatement : Statement
|
||||
{
|
||||
SwitchErrorStatement(Loc loc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ReturnStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ReturnStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
ReturnStatement *isReturnStatement() { return this; }
|
||||
};
|
||||
|
||||
struct BreakStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
BreakStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LDC: only set if ident is set: label statement to jump to
|
||||
LabelStatement *target;
|
||||
};
|
||||
|
||||
struct ContinueStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ContinueStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LDC: only set if ident is set: label statement to jump to
|
||||
LabelStatement *target;
|
||||
};
|
||||
|
||||
struct SynchronizedStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
// Back end
|
||||
elem *esync;
|
||||
SynchronizedStatement(Loc loc, elem *esync, Statement *body);
|
||||
void toIR(IRState *irs);
|
||||
llvm::Value* llsync;
|
||||
};
|
||||
|
||||
struct WithStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
Statement *body;
|
||||
VarDeclaration *wthis;
|
||||
|
||||
WithStatement(Loc loc, Expression *exp, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct TryCatchStatement : Statement
|
||||
{
|
||||
Statement *body;
|
||||
Array *catches;
|
||||
|
||||
TryCatchStatement(Loc loc, Statement *body, Array *catches);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
TryCatchStatement *isTryCatchStatement() { return this; }
|
||||
};
|
||||
|
||||
struct Catch : Object
|
||||
{
|
||||
Loc loc;
|
||||
Type *type;
|
||||
Identifier *ident;
|
||||
VarDeclaration *var;
|
||||
Statement *handler;
|
||||
|
||||
Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
|
||||
Catch *syntaxCopy();
|
||||
void semantic(Scope *sc);
|
||||
int blockExit();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct TryFinallyStatement : Statement
|
||||
{
|
||||
Statement *body;
|
||||
Statement *finalbody;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct OnScopeStatement : Statement
|
||||
{
|
||||
TOK tok;
|
||||
Statement *statement;
|
||||
|
||||
OnScopeStatement(Loc loc, TOK tok, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
int blockExit();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ThrowStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
|
||||
ThrowStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct VolatileStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
VolatileStatement(Loc loc, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct GotoStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
LabelDsymbol *label;
|
||||
TryFinallyStatement *tf;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
GotoStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
GotoStatement *isGotoStatement() { return this; }
|
||||
};
|
||||
|
||||
struct LabelStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
Statement *statement;
|
||||
TryFinallyStatement *tf;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
block *lblock; // back end
|
||||
int isReturnLabel;
|
||||
|
||||
LabelStatement(Loc loc, Identifier *ident, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int fallOffEnd();
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LDC
|
||||
bool asmLabel; // for labels inside inline assembler
|
||||
};
|
||||
|
||||
struct LabelDsymbol : Dsymbol
|
||||
{
|
||||
LabelStatement *statement;
|
||||
|
||||
LabelDsymbol(Identifier *ident);
|
||||
LabelDsymbol *isLabel();
|
||||
};
|
||||
|
||||
struct AsmStatement : Statement
|
||||
{
|
||||
Token *tokens;
|
||||
code *asmcode;
|
||||
unsigned asmalign; // alignment of this statement
|
||||
unsigned refparam; // !=0 if function parameter is referenced
|
||||
unsigned naked; // !=0 if function is to be naked
|
||||
unsigned regs; // mask of registers modified
|
||||
|
||||
AsmStatement(Loc loc, Token *tokens);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int comeFrom();
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual AsmStatement *isAsmStatement() { return this; }
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LDC
|
||||
// non-zero if this is a branch, contains the target labels identifier
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct AsmBlockStatement : CompoundStatement
|
||||
{
|
||||
EnclosingHandler* enclosinghandler;
|
||||
TryFinallyStatement* tf;
|
||||
|
||||
AsmBlockStatement(Loc loc, Statements *s);
|
||||
Statements *flatten(Scope *sc);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
|
||||
CompoundStatement *isCompoundStatement() { return NULL; }
|
||||
AsmBlockStatement *isAsmBlockStatement() { return this; }
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
#endif /* DMD_STATEMENT_H */
|
||||
114
dmd2/staticassert.c
Normal file
114
dmd2/staticassert.c
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
// Copyright (c) 1999-2007 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>
|
||||
|
||||
#include "dsymbol.h"
|
||||
#include "staticassert.h"
|
||||
#include "expression.h"
|
||||
#include "id.h"
|
||||
#include "hdrgen.h"
|
||||
#include "scope.h"
|
||||
#include "template.h"
|
||||
|
||||
/********************************* AttribDeclaration ****************************/
|
||||
|
||||
StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
|
||||
: Dsymbol(Id::empty)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->exp = exp;
|
||||
this->msg = msg;
|
||||
}
|
||||
|
||||
Dsymbol *StaticAssert::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
StaticAssert *sa;
|
||||
|
||||
assert(!s);
|
||||
sa = new StaticAssert(loc, exp->syntaxCopy(), msg ? msg->syntaxCopy() : NULL);
|
||||
return sa;
|
||||
}
|
||||
|
||||
int StaticAssert::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
return 0; // we didn't add anything
|
||||
}
|
||||
|
||||
void StaticAssert::semantic(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
void StaticAssert::semantic2(Scope *sc)
|
||||
{
|
||||
Expression *e;
|
||||
|
||||
//printf("StaticAssert::semantic2() %s\n", toChars());
|
||||
e = exp->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(FALSE))
|
||||
{
|
||||
if (msg)
|
||||
{ HdrGenState hgs;
|
||||
OutBuffer buf;
|
||||
|
||||
msg = msg->semantic(sc);
|
||||
msg = msg->optimize(WANTvalue | WANTinterpret);
|
||||
hgs.console = 1;
|
||||
msg->toCBuffer(&buf, &hgs);
|
||||
error("%s", buf.toChars());
|
||||
}
|
||||
else
|
||||
error("is false");
|
||||
if(sc->tinst)
|
||||
sc->tinst->printInstantiationTrace();
|
||||
if (!global.gag)
|
||||
fatal();
|
||||
}
|
||||
else if (!e->isBool(TRUE))
|
||||
{
|
||||
error("(%s) is not evaluatable at compile time", exp->toChars());
|
||||
}
|
||||
}
|
||||
|
||||
int StaticAssert::oneMember(Dsymbol **ps)
|
||||
{
|
||||
//printf("StaticAssert::oneMember())\n");
|
||||
*ps = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void StaticAssert::inlineScan()
|
||||
{
|
||||
}
|
||||
|
||||
void StaticAssert::toObjFile(int multiobj)
|
||||
{
|
||||
}
|
||||
|
||||
const char *StaticAssert::kind()
|
||||
{
|
||||
return "static assert";
|
||||
}
|
||||
|
||||
void StaticAssert::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring(kind());
|
||||
buf->writeByte('(');
|
||||
exp->toCBuffer(buf, hgs);
|
||||
if (msg)
|
||||
{
|
||||
buf->writeByte(',');
|
||||
msg->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writestring(");");
|
||||
buf->writenl();
|
||||
}
|
||||
43
dmd2/staticassert.h
Normal file
43
dmd2/staticassert.h
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// 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_STATICASSERT_H
|
||||
#define DMD_STATICASSERT_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Expression;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
struct StaticAssert : Dsymbol
|
||||
{
|
||||
Expression *exp;
|
||||
Expression *msg;
|
||||
|
||||
StaticAssert(Loc loc, Expression *exp, Expression *msg);
|
||||
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void inlineScan();
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toObjFile(int multiobj);
|
||||
const char *kind();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
#endif
|
||||
139
dmd2/stringtable.c
Normal file
139
dmd2/stringtable.c
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
// 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 <stdlib.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "mem.h"
|
||||
#include "dchar.h"
|
||||
#include "lstring.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
StringTable::StringTable(unsigned size)
|
||||
{
|
||||
table = (void **)mem.calloc(size, sizeof(void *));
|
||||
tabledim = size;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
StringTable::~StringTable()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
// Zero out dangling pointers to help garbage collector.
|
||||
// Should zero out StringEntry's too.
|
||||
for (i = 0; i < count; i++)
|
||||
table[i] = NULL;
|
||||
|
||||
mem.free(table);
|
||||
table = NULL;
|
||||
}
|
||||
|
||||
struct StringEntry
|
||||
{
|
||||
StringEntry *left;
|
||||
StringEntry *right;
|
||||
hash_t hash;
|
||||
|
||||
StringValue value;
|
||||
|
||||
static StringEntry *alloc(const dchar *s, unsigned len);
|
||||
};
|
||||
|
||||
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
|
||||
{
|
||||
StringEntry *se;
|
||||
|
||||
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
|
||||
se->value.lstring.length = len;
|
||||
se->hash = Dchar::calcHash(s,len);
|
||||
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
|
||||
return se;
|
||||
}
|
||||
|
||||
void **StringTable::search(const dchar *s, unsigned len)
|
||||
{
|
||||
hash_t hash;
|
||||
unsigned u;
|
||||
int cmp;
|
||||
StringEntry **se;
|
||||
|
||||
//printf("StringTable::search(%p,%d)\n",s,len);
|
||||
hash = Dchar::calcHash(s,len);
|
||||
u = hash % tabledim;
|
||||
se = (StringEntry **)&table[u];
|
||||
//printf("\thash = %d, u = %d\n",hash,u);
|
||||
while (*se)
|
||||
{
|
||||
cmp = (*se)->hash - hash;
|
||||
if (cmp == 0)
|
||||
{
|
||||
cmp = (*se)->value.lstring.len() - len;
|
||||
if (cmp == 0)
|
||||
{
|
||||
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
|
||||
if (cmp == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmp < 0)
|
||||
se = &(*se)->left;
|
||||
else
|
||||
se = &(*se)->right;
|
||||
}
|
||||
//printf("\treturn %p, %p\n",se, (*se));
|
||||
return (void **)se;
|
||||
}
|
||||
|
||||
StringValue *StringTable::lookup(const dchar *s, unsigned len)
|
||||
{ StringEntry *se;
|
||||
|
||||
se = *(StringEntry **)search(s,len);
|
||||
if (se)
|
||||
return &se->value;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringValue *StringTable::update(const dchar *s, unsigned len)
|
||||
{ StringEntry **pse;
|
||||
StringEntry *se;
|
||||
|
||||
pse = (StringEntry **)search(s,len);
|
||||
se = *pse;
|
||||
if (!se) // not in table: so create new entry
|
||||
{
|
||||
se = StringEntry::alloc(s, len);
|
||||
*pse = se;
|
||||
}
|
||||
return &se->value;
|
||||
}
|
||||
|
||||
StringValue *StringTable::insert(const dchar *s, unsigned len)
|
||||
{ StringEntry **pse;
|
||||
StringEntry *se;
|
||||
|
||||
pse = (StringEntry **)search(s,len);
|
||||
se = *pse;
|
||||
if (se)
|
||||
return NULL; // error: already in table
|
||||
else
|
||||
{
|
||||
se = StringEntry::alloc(s, len);
|
||||
*pse = se;
|
||||
}
|
||||
return &se->value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
48
dmd2/stringtable.h
Normal file
48
dmd2/stringtable.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
|
||||
|
||||
#ifndef STRINGTABLE_H
|
||||
#define STRINGTABLE_H
|
||||
|
||||
#if __SC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "lstring.h"
|
||||
|
||||
struct StringValue
|
||||
{
|
||||
union
|
||||
{ int intvalue;
|
||||
void *ptrvalue;
|
||||
dchar *string;
|
||||
};
|
||||
Lstring lstring;
|
||||
};
|
||||
|
||||
struct StringTable : Object
|
||||
{
|
||||
void **table;
|
||||
unsigned count;
|
||||
unsigned tabledim;
|
||||
|
||||
StringTable(unsigned size = 37);
|
||||
~StringTable();
|
||||
|
||||
StringValue *lookup(const dchar *s, unsigned len);
|
||||
StringValue *insert(const dchar *s, unsigned len);
|
||||
StringValue *update(const dchar *s, unsigned len);
|
||||
|
||||
private:
|
||||
void **search(const dchar *s, unsigned len);
|
||||
};
|
||||
|
||||
#endif
|
||||
508
dmd2/struct.c
Normal file
508
dmd2/struct.c
Normal file
@@ -0,0 +1,508 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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 <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "statement.h"
|
||||
|
||||
/********************************* AggregateDeclaration ****************************/
|
||||
|
||||
AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
: ScopeDsymbol(id)
|
||||
{
|
||||
this->loc = loc;
|
||||
|
||||
storage_class = 0;
|
||||
protection = PROTpublic;
|
||||
type = NULL;
|
||||
handle = NULL;
|
||||
structsize = 0; // size of struct
|
||||
alignsize = 0; // size of struct for alignment purposes
|
||||
structalign = 0; // struct member alignment in effect
|
||||
hasUnions = 0;
|
||||
sizeok = 0; // size not determined yet
|
||||
isdeprecated = 0;
|
||||
inv = NULL;
|
||||
aggNew = NULL;
|
||||
aggDelete = NULL;
|
||||
|
||||
stag = NULL;
|
||||
sinit = NULL;
|
||||
scope = NULL;
|
||||
dtor = NULL;
|
||||
|
||||
ctor = NULL;
|
||||
defaultCtor = NULL;
|
||||
}
|
||||
|
||||
enum PROT AggregateDeclaration::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
|
||||
void AggregateDeclaration::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("AggregateDeclaration::semantic2(%s)\n", toChars());
|
||||
if (scope)
|
||||
{ error("has forward references");
|
||||
return;
|
||||
}
|
||||
if (members)
|
||||
{
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
s->semantic2(sc);
|
||||
}
|
||||
sc->pop();
|
||||
}
|
||||
}
|
||||
|
||||
void AggregateDeclaration::semantic3(Scope *sc)
|
||||
{ int i;
|
||||
|
||||
//printf("AggregateDeclaration::semantic3(%s)\n", toChars());
|
||||
if (members)
|
||||
{
|
||||
sc = sc->push(this);
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
s->semantic3(sc);
|
||||
}
|
||||
sc->pop();
|
||||
}
|
||||
}
|
||||
|
||||
void AggregateDeclaration::inlineScan()
|
||||
{ int i;
|
||||
|
||||
//printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
|
||||
if (members)
|
||||
{
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
//printf("inline scan aggregate symbol '%s'\n", s->toChars());
|
||||
s->inlineScan();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned AggregateDeclaration::size(Loc loc)
|
||||
{
|
||||
//printf("AggregateDeclaration::size() = %d\n", structsize);
|
||||
if (!members)
|
||||
error(loc, "unknown size");
|
||||
if (sizeok != 1)
|
||||
{ error(loc, "no size yet for forward reference");
|
||||
//*(char*)0=0;
|
||||
}
|
||||
return structsize;
|
||||
}
|
||||
|
||||
Type *AggregateDeclaration::getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
int AggregateDeclaration::isDeprecated()
|
||||
{
|
||||
return isdeprecated;
|
||||
}
|
||||
|
||||
/****************************
|
||||
* Do byte or word alignment as necessary.
|
||||
* Align sizes of 0, as we may not know array sizes yet.
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset)
|
||||
{
|
||||
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
|
||||
if (salign > 1)
|
||||
{ int sa;
|
||||
|
||||
switch (size)
|
||||
{ case 1:
|
||||
break;
|
||||
case 2:
|
||||
case_2:
|
||||
*poffset = (*poffset + 1) & ~1; // align to word
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
if (salign == 2)
|
||||
goto case_2;
|
||||
*poffset = (*poffset + 3) & ~3; // align to dword
|
||||
break;
|
||||
default:
|
||||
*poffset = (*poffset + salign - 1) & ~(salign - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//printf("result = %d\n",offset);
|
||||
}
|
||||
|
||||
|
||||
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
{
|
||||
unsigned memsize; // size of member
|
||||
unsigned memalignsize; // size of member for alignment purposes
|
||||
unsigned xalign; // alignment boundaries
|
||||
|
||||
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
|
||||
assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
|
||||
|
||||
// Check for forward referenced types which will fail the size() call
|
||||
Type *t = v->type->toBasetype();
|
||||
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
|
||||
{ TypeStruct *ts = (TypeStruct *)t;
|
||||
|
||||
if (ts->sym == this)
|
||||
{
|
||||
error("cannot have field %s with same struct type", v->toChars());
|
||||
}
|
||||
|
||||
if (ts->sym->sizeok != 1)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (t->ty == Tident)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
|
||||
memsize = v->type->size(loc);
|
||||
memalignsize = v->type->alignsize();
|
||||
xalign = v->type->memalign(sc->structalign);
|
||||
alignmember(xalign, memalignsize, &sc->offset);
|
||||
v->offset = sc->offset;
|
||||
sc->offset += memsize;
|
||||
if (sc->offset > structsize)
|
||||
structsize = sc->offset;
|
||||
if (sc->structalign < memalignsize)
|
||||
memalignsize = sc->structalign;
|
||||
if (alignsize < memalignsize)
|
||||
alignsize = memalignsize;
|
||||
//printf("\talignsize = %d\n", alignsize);
|
||||
|
||||
v->storage_class |= STCfield;
|
||||
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
|
||||
fields.push(v);
|
||||
}
|
||||
|
||||
|
||||
/********************************* StructDeclaration ****************************/
|
||||
|
||||
StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
||||
: AggregateDeclaration(loc, id)
|
||||
{
|
||||
zeroInit = 0; // assume false until we do semantic processing
|
||||
hasIdentityAssign = 0;
|
||||
cpctor = NULL;
|
||||
postblit = NULL;
|
||||
|
||||
// For forward references
|
||||
type = new TypeStruct(this);
|
||||
}
|
||||
|
||||
Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
StructDeclaration *sd;
|
||||
|
||||
if (s)
|
||||
sd = (StructDeclaration *)s;
|
||||
else
|
||||
sd = new StructDeclaration(loc, ident);
|
||||
ScopeDsymbol::syntaxCopy(sd);
|
||||
return sd;
|
||||
}
|
||||
|
||||
void StructDeclaration::semantic(Scope *sc)
|
||||
{ int i;
|
||||
Scope *sc2;
|
||||
|
||||
//printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
||||
|
||||
//static int count; if (++count == 20) *(char*)0=0;
|
||||
|
||||
assert(type);
|
||||
if (!members) // if forward reference
|
||||
return;
|
||||
|
||||
if (symtab)
|
||||
{ if (!scope)
|
||||
return; // semantic() already completed
|
||||
}
|
||||
else
|
||||
symtab = new DsymbolTable();
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
scx = scope; // save so we don't make redundant copies
|
||||
scope = NULL;
|
||||
}
|
||||
|
||||
parent = sc->parent;
|
||||
handle = type->pointerTo();
|
||||
structalign = sc->structalign;
|
||||
protection = sc->protection;
|
||||
storage_class |= sc->stc;
|
||||
if (sc->stc & STCdeprecated)
|
||||
isdeprecated = 1;
|
||||
assert(!isAnonymous());
|
||||
if (sc->stc & STCabstract)
|
||||
error("structs, unions cannot be abstract");
|
||||
if (storage_class & STCinvariant)
|
||||
type = type->invariantOf();
|
||||
else if (storage_class & STCconst)
|
||||
type = type->constOf();
|
||||
|
||||
if (sizeok == 0) // if not already done the addMember step
|
||||
{
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
|
||||
s->addMember(sc, this, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sizeok = 0;
|
||||
sc2 = sc->push(this);
|
||||
sc2->stc &= storage_class & (STCconst | STCinvariant);
|
||||
sc2->parent = this;
|
||||
if (isUnionDeclaration())
|
||||
sc2->inunion = 1;
|
||||
sc2->protection = PROTpublic;
|
||||
sc2->explicitProtection = 0;
|
||||
|
||||
int members_dim = members->dim;
|
||||
for (i = 0; i < members_dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
s->semantic(sc2);
|
||||
if (isUnionDeclaration())
|
||||
sc2->offset = 0;
|
||||
#if 0
|
||||
if (sizeok == 2)
|
||||
{ //printf("forward reference\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The TypeInfo_Struct is expecting an opEquals and opCmp with
|
||||
* a parameter that is a pointer to the struct. But if there
|
||||
* isn't one, but is an opEquals or opCmp with a value, write
|
||||
* another that is a shell around the value:
|
||||
* int opCmp(struct *p) { return opCmp(*p); }
|
||||
*/
|
||||
|
||||
TypeFunction *tfeqptr;
|
||||
{
|
||||
Arguments *arguments = new Arguments;
|
||||
Argument *arg = new Argument(STCin, handle, Id::p, NULL);
|
||||
|
||||
arguments->push(arg);
|
||||
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
|
||||
}
|
||||
|
||||
TypeFunction *tfeq;
|
||||
{
|
||||
Arguments *arguments = new Arguments;
|
||||
Argument *arg = new Argument(STCin, type, NULL, NULL);
|
||||
|
||||
arguments->push(arg);
|
||||
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeq = (TypeFunction *)tfeq->semantic(0, sc);
|
||||
}
|
||||
|
||||
Identifier *id = Id::eq;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Dsymbol *s = search_function(this, id);
|
||||
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
|
||||
if (!fd)
|
||||
{ fd = fdx->overloadExactMatch(tfeq);
|
||||
if (fd)
|
||||
{ // Create the thunk, fdptr
|
||||
FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
|
||||
Expression *e = new IdentifierExp(loc, Id::p);
|
||||
e = new PtrExp(loc, e);
|
||||
Expressions *args = new Expressions();
|
||||
args->push(e);
|
||||
e = new IdentifierExp(loc, id);
|
||||
e = new CallExp(loc, e, args);
|
||||
fdptr->fbody = new ReturnStatement(loc, e);
|
||||
ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
|
||||
assert(s);
|
||||
s->members->push(fdptr);
|
||||
fdptr->addMember(sc, s, 1);
|
||||
fdptr->semantic(sc2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id = Id::cmp;
|
||||
}
|
||||
|
||||
dtor = buildDtor(sc2);
|
||||
postblit = buildPostBlit(sc2);
|
||||
cpctor = buildCpCtor(sc2);
|
||||
buildOpAssign(sc2);
|
||||
|
||||
sc2->pop();
|
||||
|
||||
if (sizeok == 2)
|
||||
{ // semantic() failed because of forward references.
|
||||
// Unwind what we did, and defer it for later
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
structalign = 0;
|
||||
|
||||
scope = scx ? scx : new Scope(*sc);
|
||||
scope->setNoFree();
|
||||
scope->module->addDeferredSemantic(this);
|
||||
//printf("\tdeferring %s\n", toChars());
|
||||
return;
|
||||
}
|
||||
|
||||
// 0 sized struct's are set to 1 byte
|
||||
if (structsize == 0)
|
||||
{
|
||||
structsize = 1;
|
||||
alignsize = 1;
|
||||
}
|
||||
|
||||
// Round struct size up to next alignsize boundary.
|
||||
// This will ensure that arrays of structs will get their internals
|
||||
// aligned properly.
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
|
||||
sizeok = 1;
|
||||
Module::dprogress++;
|
||||
|
||||
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
||||
|
||||
// Determine if struct is all zeros or not
|
||||
zeroInit = 1;
|
||||
for (i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd && !vd->isDataseg())
|
||||
{
|
||||
if (vd->init)
|
||||
{
|
||||
// Should examine init to see if it is really all 0's
|
||||
zeroInit = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vd->type->isZeroInit())
|
||||
{
|
||||
zeroInit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for special member functions.
|
||||
*/
|
||||
ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
|
||||
inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0);
|
||||
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
|
||||
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
|
||||
|
||||
if (sc->func)
|
||||
{
|
||||
semantic2(sc);
|
||||
semantic3(sc);
|
||||
}
|
||||
}
|
||||
|
||||
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ int i;
|
||||
|
||||
buf->printf("%s ", kind());
|
||||
if (!isAnonymous())
|
||||
buf->writestring(toChars());
|
||||
if (!members)
|
||||
{
|
||||
buf->writeByte(';');
|
||||
buf->writenl();
|
||||
return;
|
||||
}
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writeByte('}');
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
|
||||
const char *StructDeclaration::kind()
|
||||
{
|
||||
return "struct";
|
||||
}
|
||||
|
||||
/********************************* UnionDeclaration ****************************/
|
||||
|
||||
UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
|
||||
: StructDeclaration(loc, id)
|
||||
{
|
||||
}
|
||||
|
||||
Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
UnionDeclaration *ud;
|
||||
|
||||
if (s)
|
||||
ud = (UnionDeclaration *)s;
|
||||
else
|
||||
ud = new UnionDeclaration(loc, ident);
|
||||
StructDeclaration::syntaxCopy(ud);
|
||||
return ud;
|
||||
}
|
||||
|
||||
|
||||
const char *UnionDeclaration::kind()
|
||||
{
|
||||
return "union";
|
||||
}
|
||||
|
||||
|
||||
4615
dmd2/template.c
Normal file
4615
dmd2/template.c
Normal file
File diff suppressed because it is too large
Load Diff
362
dmd2/template.h
Normal file
362
dmd2/template.h
Normal file
@@ -0,0 +1,362 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// 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.
|
||||
|
||||
#ifndef DMD_TEMPLATE_H
|
||||
#define DMD_TEMPLATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "root.h"
|
||||
#include "arraytypes.h"
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
|
||||
|
||||
struct OutBuffer;
|
||||
struct Identifier;
|
||||
struct TemplateInstance;
|
||||
struct TemplateParameter;
|
||||
struct TemplateTypeParameter;
|
||||
struct TemplateThisParameter;
|
||||
struct TemplateValueParameter;
|
||||
struct TemplateAliasParameter;
|
||||
struct TemplateTupleParameter;
|
||||
struct Type;
|
||||
struct TypeTypeof;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct AliasDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct HdrGenState;
|
||||
enum MATCH;
|
||||
|
||||
struct Tuple : Object
|
||||
{
|
||||
Objects objects;
|
||||
|
||||
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
|
||||
};
|
||||
|
||||
|
||||
struct TemplateDeclaration : ScopeDsymbol
|
||||
{
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
|
||||
Expression *constraint;
|
||||
|
||||
Array instances; // array of TemplateInstance's
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
TemplateDeclaration *overroot; // first in overnext list
|
||||
|
||||
Scope *scope;
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
||||
Expression *constraint, Array *decldefs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
// void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
|
||||
MATCH leastAsSpecialized(TemplateDeclaration *td2);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
|
||||
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
|
||||
|
||||
TemplateDeclaration *isTemplateDeclaration() { return this; }
|
||||
|
||||
TemplateTupleParameter *isVariadic();
|
||||
int isOverloadable();
|
||||
|
||||
// LDC
|
||||
std::string intrinsicName;
|
||||
};
|
||||
|
||||
struct TemplateParameter
|
||||
{
|
||||
/* For type-parameter:
|
||||
* template Foo(ident) // specType is set to NULL
|
||||
* template Foo(ident : specType)
|
||||
* For value-parameter:
|
||||
* template Foo(valType ident) // specValue is set to NULL
|
||||
* template Foo(valType ident : specValue)
|
||||
* For alias-parameter:
|
||||
* template Foo(alias ident)
|
||||
* For this-parameter:
|
||||
* template Foo(this ident)
|
||||
*/
|
||||
|
||||
Loc loc;
|
||||
Identifier *ident;
|
||||
|
||||
Declaration *sparam;
|
||||
|
||||
TemplateParameter(Loc loc, Identifier *ident);
|
||||
|
||||
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
||||
virtual TemplateValueParameter *isTemplateValueParameter();
|
||||
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
||||
virtual TemplateThisParameter *isTemplateThisParameter();
|
||||
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
||||
|
||||
virtual TemplateParameter *syntaxCopy() = 0;
|
||||
virtual void declareParameter(Scope *sc) = 0;
|
||||
virtual void semantic(Scope *) = 0;
|
||||
virtual void print(Object *oarg, Object *oded) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual Object *specialization() = 0;
|
||||
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
|
||||
/* If TemplateParameter's match as far as overloading goes.
|
||||
*/
|
||||
virtual int overloadMatch(TemplateParameter *) = 0;
|
||||
|
||||
/* Match actual argument against parameter.
|
||||
*/
|
||||
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
|
||||
|
||||
/* Create dummy argument based on parameter.
|
||||
*/
|
||||
virtual void *dummyArg() = 0;
|
||||
};
|
||||
|
||||
struct TemplateTypeParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateTypeParameter *isTemplateTypeParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TemplateThisParameter : TemplateTypeParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* this ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateThisParameter *isTemplateThisParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TemplateValueParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* valType ident : specValue = defaultValue
|
||||
*/
|
||||
|
||||
Type *valType;
|
||||
Expression *specValue;
|
||||
Expression *defaultValue;
|
||||
|
||||
static Expression *edummy;
|
||||
|
||||
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
|
||||
|
||||
TemplateValueParameter *isTemplateValueParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateAliasParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* specType ident : specAlias = defaultAlias
|
||||
*/
|
||||
|
||||
Type *specType;
|
||||
Object *specAlias;
|
||||
Object *defaultAlias;
|
||||
|
||||
static Dsymbol *sdummy;
|
||||
|
||||
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
|
||||
|
||||
TemplateAliasParameter *isTemplateAliasParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateTupleParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident ...
|
||||
*/
|
||||
|
||||
TemplateTupleParameter(Loc loc, Identifier *ident);
|
||||
|
||||
TemplateTupleParameter *isTemplateTupleParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateInstance : ScopeDsymbol
|
||||
{
|
||||
/* Given:
|
||||
* foo!(args) =>
|
||||
* name = foo
|
||||
* tiargs = args
|
||||
*/
|
||||
Identifier *name;
|
||||
//Array idents;
|
||||
Objects *tiargs; // Array of Types/Expressions of template
|
||||
// instance arguments [int*, char, 10*10]
|
||||
|
||||
Objects tdtypes; // Array of Types/Expressions corresponding
|
||||
// to TemplateDeclaration.parameters
|
||||
// [int, char, 100]
|
||||
|
||||
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
|
||||
TemplateInstance *inst; // refer to existing instance
|
||||
ScopeDsymbol *argsym; // argument symbol table
|
||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||
// sole member
|
||||
WithScopeSymbol *withsym; // if a member of a with statement
|
||||
int semanticdone; // has semantic() been done?
|
||||
int semantictiargsdone; // has semanticTiargs() been done?
|
||||
int nest; // for recursion detection
|
||||
int havetempdecl; // 1 if used second constructor
|
||||
Dsymbol *isnested; // if referencing local symbols, this is the context
|
||||
int errors; // 1 if compiled with errors
|
||||
#ifdef IN_GCC
|
||||
/* On some targets, it is necessary to know whether a symbol
|
||||
will be emitted in the output or not before the symbol
|
||||
is used. This can be different from getModule(). */
|
||||
Module * objFileModule;
|
||||
#endif
|
||||
|
||||
TemplateInstance(Loc loc, Identifier *temp_id);
|
||||
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
||||
static Objects *arraySyntaxCopy(Objects *objs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *toAlias(); // resolve real symbol
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
|
||||
// Internal
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
||||
void semanticTiargs(Scope *sc);
|
||||
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
|
||||
TemplateDeclaration *findBestMatch(Scope *sc);
|
||||
void declareParameters(Scope *sc);
|
||||
int isNested(Objects *tiargs);
|
||||
Identifier *genIdent();
|
||||
|
||||
TemplateInstance *isTemplateInstance() { return this; }
|
||||
AliasDeclaration *isAliasDeclaration();
|
||||
|
||||
// LDC
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
void printInstantiationTrace();
|
||||
};
|
||||
|
||||
struct TemplateMixin : TemplateInstance
|
||||
{
|
||||
Array *idents;
|
||||
Type *tqual;
|
||||
|
||||
Scope *scope; // for forward referencing
|
||||
|
||||
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
int hasPointers();
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
|
||||
TemplateMixin *isTemplateMixin() { return this; }
|
||||
};
|
||||
|
||||
Expression *isExpression(Object *o);
|
||||
Dsymbol *isDsymbol(Object *o);
|
||||
Type *isType(Object *o);
|
||||
Tuple *isTuple(Object *o);
|
||||
Type *getType(Object *o);
|
||||
Dsymbol *getDsymbol(Object *o);
|
||||
|
||||
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
|
||||
|
||||
#endif /* DMD_TEMPLATE_H */
|
||||
45
dmd2/total.h
Normal file
45
dmd2/total.h
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
// 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_TOTAL_H
|
||||
#define DMD_TOTAL_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "arraytypes.h"
|
||||
#include "mars.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
#include "identifier.h"
|
||||
#include "enum.h"
|
||||
#include "aggregate.h"
|
||||
#include "mtype.h"
|
||||
#include "expression.h"
|
||||
#include "declaration.h"
|
||||
#include "statement.h"
|
||||
#include "scope.h"
|
||||
#include "import.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "cond.h"
|
||||
#include "version.h"
|
||||
|
||||
#endif /* DMD_TOTAL_H */
|
||||
440
dmd2/traits.c
Normal file
440
dmd2/traits.c
Normal file
@@ -0,0 +1,440 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 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 <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
|
||||
#if IN_GCC
|
||||
// Issues with using -include total.h (defines integer_t) and then complex.h fails...
|
||||
#undef integer_t
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#elif _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif linux
|
||||
#include "../root/mem.h"
|
||||
#endif
|
||||
|
||||
//#include "port.h"
|
||||
#include "mtype.h"
|
||||
#include "init.h"
|
||||
#include "expression.h"
|
||||
#include "template.h"
|
||||
#include "utf.h"
|
||||
#include "enum.h"
|
||||
#include "scope.h"
|
||||
#include "statement.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "import.h"
|
||||
#include "id.h"
|
||||
#include "dsymbol.h"
|
||||
#include "module.h"
|
||||
#include "attrib.h"
|
||||
#include "hdrgen.h"
|
||||
#include "parse.h"
|
||||
|
||||
#define LOGSEMANTIC 0
|
||||
|
||||
/************************************************
|
||||
* Delegate to be passed to overloadApply() that looks
|
||||
* for virtual functions.
|
||||
*/
|
||||
|
||||
struct Pvirtuals
|
||||
{
|
||||
Expression *e1;
|
||||
Expressions *exps;
|
||||
};
|
||||
|
||||
static int fpvirtuals(void *param, FuncDeclaration *f)
|
||||
{ Pvirtuals *p = (Pvirtuals *)param;
|
||||
|
||||
if (f->isVirtual())
|
||||
{ Expression *e;
|
||||
|
||||
if (p->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)p->e1;
|
||||
e = new DotVarExp(0, dve->e1, f);
|
||||
}
|
||||
else
|
||||
e = new DsymbolExp(0, f);
|
||||
p->exps->push(e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************ TraitsExp ************************************/
|
||||
|
||||
Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
#if LOGSEMANTIC
|
||||
printf("TraitsExp::semantic() %s\n", toChars());
|
||||
#endif
|
||||
if (ident != Id::compiles && ident != Id::isSame)
|
||||
TemplateInstance::semanticTiargs(loc, sc, args, 1);
|
||||
size_t dim = args ? args->dim : 0;
|
||||
Object *o;
|
||||
FuncDeclaration *f;
|
||||
|
||||
#define ISTYPE(cond) \
|
||||
for (size_t i = 0; i < dim; i++) \
|
||||
{ Type *t = getType((Object *)args->data[i]); \
|
||||
if (!t) \
|
||||
goto Lfalse; \
|
||||
if (!(cond)) \
|
||||
goto Lfalse; \
|
||||
} \
|
||||
if (!dim) \
|
||||
goto Lfalse; \
|
||||
goto Ltrue;
|
||||
|
||||
#define ISDSYMBOL(cond) \
|
||||
for (size_t i = 0; i < dim; i++) \
|
||||
{ Dsymbol *s = getDsymbol((Object *)args->data[i]); \
|
||||
if (!s) \
|
||||
goto Lfalse; \
|
||||
if (!(cond)) \
|
||||
goto Lfalse; \
|
||||
} \
|
||||
if (!dim) \
|
||||
goto Lfalse; \
|
||||
goto Ltrue;
|
||||
|
||||
|
||||
|
||||
if (ident == Id::isArithmetic)
|
||||
{
|
||||
ISTYPE(t->isintegral() || t->isfloating())
|
||||
}
|
||||
else if (ident == Id::isFloating)
|
||||
{
|
||||
ISTYPE(t->isfloating())
|
||||
}
|
||||
else if (ident == Id::isIntegral)
|
||||
{
|
||||
ISTYPE(t->isintegral())
|
||||
}
|
||||
else if (ident == Id::isScalar)
|
||||
{
|
||||
ISTYPE(t->isscalar())
|
||||
}
|
||||
else if (ident == Id::isUnsigned)
|
||||
{
|
||||
ISTYPE(t->isunsigned())
|
||||
}
|
||||
else if (ident == Id::isAssociativeArray)
|
||||
{
|
||||
ISTYPE(t->toBasetype()->ty == Taarray)
|
||||
}
|
||||
else if (ident == Id::isStaticArray)
|
||||
{
|
||||
ISTYPE(t->toBasetype()->ty == Tsarray)
|
||||
}
|
||||
else if (ident == Id::isAbstractClass)
|
||||
{
|
||||
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
|
||||
}
|
||||
else if (ident == Id::isFinalClass)
|
||||
{
|
||||
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
|
||||
}
|
||||
else if (ident == Id::isAbstractFunction)
|
||||
{
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
|
||||
}
|
||||
else if (ident == Id::isVirtualFunction)
|
||||
{
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
|
||||
}
|
||||
else if (ident == Id::isFinalFunction)
|
||||
{
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
|
||||
}
|
||||
else if (ident == Id::hasMember ||
|
||||
ident == Id::getMember ||
|
||||
ident == Id::getVirtualFunctions)
|
||||
{
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
Object *o = (Object *)args->data[0];
|
||||
Expression *e = isExpression((Object *)args->data[1]);
|
||||
if (!e)
|
||||
{ error("expression expected as second argument of __traits %s", ident->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->op != TOKstring)
|
||||
{ error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
StringExp *se = (StringExp *)e;
|
||||
se = se->toUTF8(sc);
|
||||
if (se->sz != 1)
|
||||
{ error("string must be chars");
|
||||
goto Lfalse;
|
||||
}
|
||||
Identifier *id = Lexer::idPool((char *)se->string);
|
||||
|
||||
Type *t = isType(o);
|
||||
e = isExpression(o);
|
||||
Dsymbol *s = isDsymbol(o);
|
||||
if (t)
|
||||
e = new TypeDotIdExp(loc, t, id);
|
||||
else if (e)
|
||||
e = new DotIdExp(loc, e, id);
|
||||
else if (s)
|
||||
{ e = new DsymbolExp(loc, s);
|
||||
e = new DotIdExp(loc, e, id);
|
||||
}
|
||||
else
|
||||
{ error("invalid first argument");
|
||||
goto Lfalse;
|
||||
}
|
||||
|
||||
if (ident == Id::hasMember)
|
||||
{ /* Take any errors as meaning it wasn't found
|
||||
*/
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
e = e->semantic(sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors)
|
||||
{ if (global.gag == 0)
|
||||
global.errors = errors;
|
||||
goto Lfalse;
|
||||
}
|
||||
else
|
||||
goto Ltrue;
|
||||
}
|
||||
else if (ident == Id::getMember)
|
||||
{
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
else if (ident == Id::getVirtualFunctions)
|
||||
{
|
||||
unsigned errors = global.errors;
|
||||
Expression *ex = e;
|
||||
e = e->semantic(sc);
|
||||
if (errors < global.errors)
|
||||
error("%s cannot be resolved", ex->toChars());
|
||||
|
||||
/* Create tuple of virtual function overloads of e
|
||||
*/
|
||||
//e->dump(0);
|
||||
Expressions *exps = new Expressions();
|
||||
FuncDeclaration *f;
|
||||
if (e->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e;
|
||||
f = ve->var->isFuncDeclaration();
|
||||
}
|
||||
else if (e->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)e;
|
||||
f = dve->var->isFuncDeclaration();
|
||||
}
|
||||
else
|
||||
f = NULL;
|
||||
Pvirtuals p;
|
||||
p.exps = exps;
|
||||
p.e1 = e;
|
||||
overloadApply(f, fpvirtuals, &p);
|
||||
|
||||
TupleExp *tup = new TupleExp(loc, exps);
|
||||
return tup->semantic(sc);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
else if (ident == Id::classInstanceSize)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (Object *)args->data[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ClassDeclaration *cd;
|
||||
if (!s || (cd = s->isClassDeclaration()) == NULL)
|
||||
{
|
||||
error("first argument is not a class");
|
||||
goto Lfalse;
|
||||
}
|
||||
return new IntegerExp(loc, cd->structsize, Type::tsize_t);
|
||||
}
|
||||
else if (ident == Id::allMembers || ident == Id::derivedMembers)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (Object *)args->data[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ScopeDsymbol *sd;
|
||||
if (!s)
|
||||
{
|
||||
error("argument has no members");
|
||||
goto Lfalse;
|
||||
}
|
||||
if ((sd = s->isScopeDsymbol()) == NULL)
|
||||
{
|
||||
error("%s %s has no members", s->kind(), s->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
Expressions *exps = new Expressions;
|
||||
while (1)
|
||||
{ size_t dim = ScopeDsymbol::dim(sd->members);
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i);
|
||||
//printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
|
||||
if (sm->ident)
|
||||
{
|
||||
//printf("\t%s\n", sm->ident->toChars());
|
||||
char *str = sm->ident->toChars();
|
||||
|
||||
/* Skip if already present in exps[]
|
||||
*/
|
||||
for (size_t j = 0; j < exps->dim; j++)
|
||||
{ StringExp *se2 = (StringExp *)exps->data[j];
|
||||
if (strcmp(str, (char *)se2->string) == 0)
|
||||
goto Lnext;
|
||||
}
|
||||
|
||||
StringExp *se = new StringExp(loc, str);
|
||||
exps->push(se);
|
||||
}
|
||||
Lnext:
|
||||
;
|
||||
}
|
||||
ClassDeclaration *cd = sd->isClassDeclaration();
|
||||
if (cd && cd->baseClass && ident == Id::allMembers)
|
||||
sd = cd->baseClass; // do again with base class
|
||||
else
|
||||
break;
|
||||
}
|
||||
Expression *e = new ArrayLiteralExp(loc, exps);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
else if (ident == Id::compiles)
|
||||
{
|
||||
/* Determine if all the objects - types, expressions, or symbols -
|
||||
* compile without error
|
||||
*/
|
||||
if (!dim)
|
||||
goto Lfalse;
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Object *o = (Object *)args->data[i];
|
||||
Type *t;
|
||||
Expression *e;
|
||||
Dsymbol *s;
|
||||
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
|
||||
t = isType(o);
|
||||
if (t)
|
||||
{ t->resolve(loc, sc, &e, &t, &s);
|
||||
if (t)
|
||||
t->semantic(loc, sc);
|
||||
else if (e)
|
||||
e->semantic(sc);
|
||||
}
|
||||
else
|
||||
{ e = isExpression(o);
|
||||
if (e)
|
||||
e->semantic(sc);
|
||||
}
|
||||
|
||||
global.gag--;
|
||||
if (errors != global.errors)
|
||||
{ if (global.gag == 0)
|
||||
global.errors = errors;
|
||||
goto Lfalse;
|
||||
}
|
||||
}
|
||||
goto Ltrue;
|
||||
}
|
||||
else if (ident == Id::isSame)
|
||||
{ /* Determine if two symbols are the same
|
||||
*/
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
TemplateInstance::semanticTiargs(loc, sc, args, 0);
|
||||
Object *o1 = (Object *)args->data[0];
|
||||
Object *o2 = (Object *)args->data[1];
|
||||
Dsymbol *s1 = getDsymbol(o1);
|
||||
Dsymbol *s2 = getDsymbol(o2);
|
||||
|
||||
#if 0
|
||||
printf("o1: %p\n", o1);
|
||||
printf("o2: %p\n", o2);
|
||||
if (!s1)
|
||||
{ Expression *ea = isExpression(o1);
|
||||
if (ea)
|
||||
printf("%s\n", ea->toChars());
|
||||
Type *ta = isType(o1);
|
||||
if (ta)
|
||||
printf("%s\n", ta->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
else
|
||||
printf("%s %s\n", s1->kind(), s1->toChars());
|
||||
#endif
|
||||
if (!s1 && !s2)
|
||||
{ Expression *ea1 = isExpression(o1);
|
||||
Expression *ea2 = isExpression(o2);
|
||||
if (ea1 && ea2 && ea1->equals(ea2))
|
||||
goto Ltrue;
|
||||
}
|
||||
|
||||
if (!s1 || !s2)
|
||||
goto Lfalse;
|
||||
|
||||
s1 = s1->toAlias();
|
||||
s2 = s2->toAlias();
|
||||
|
||||
if (s1 == s2)
|
||||
goto Ltrue;
|
||||
else
|
||||
goto Lfalse;
|
||||
}
|
||||
else
|
||||
{ error("unrecognized trait %s", ident->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
Lnottype:
|
||||
error("%s is not a type", o->toChars());
|
||||
goto Lfalse;
|
||||
|
||||
Ldimerror:
|
||||
error("wrong number of arguments %d", dim);
|
||||
goto Lfalse;
|
||||
|
||||
|
||||
Lfalse:
|
||||
return new IntegerExp(loc, 0, Type::tbool);
|
||||
|
||||
Ltrue:
|
||||
return new IntegerExp(loc, 1, Type::tbool);
|
||||
}
|
||||
|
||||
|
||||
323
dmd2/unialpha.c
Normal file
323
dmd2/unialpha.c
Normal file
@@ -0,0 +1,323 @@
|
||||
|
||||
// Copyright (c) 2003 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 <assert.h>
|
||||
|
||||
/*******************************
|
||||
* Return !=0 if unicode alpha.
|
||||
* Use table from C99 Appendix D.
|
||||
*/
|
||||
|
||||
int isUniAlpha(unsigned u)
|
||||
{
|
||||
static unsigned short table[][2] =
|
||||
{
|
||||
{ 0x00AA, 0x00AA },
|
||||
{ 0x00B5, 0x00B5 },
|
||||
{ 0x00B7, 0x00B7 },
|
||||
{ 0x00BA, 0x00BA },
|
||||
{ 0x00C0, 0x00D6 },
|
||||
{ 0x00D8, 0x00F6 },
|
||||
{ 0x00F8, 0x01F5 },
|
||||
{ 0x01FA, 0x0217 },
|
||||
{ 0x0250, 0x02A8 },
|
||||
{ 0x02B0, 0x02B8 },
|
||||
{ 0x02BB, 0x02BB },
|
||||
{ 0x02BD, 0x02C1 },
|
||||
{ 0x02D0, 0x02D1 },
|
||||
{ 0x02E0, 0x02E4 },
|
||||
{ 0x037A, 0x037A },
|
||||
{ 0x0386, 0x0386 },
|
||||
{ 0x0388, 0x038A },
|
||||
{ 0x038C, 0x038C },
|
||||
{ 0x038E, 0x03A1 },
|
||||
{ 0x03A3, 0x03CE },
|
||||
{ 0x03D0, 0x03D6 },
|
||||
{ 0x03DA, 0x03DA },
|
||||
{ 0x03DC, 0x03DC },
|
||||
{ 0x03DE, 0x03DE },
|
||||
{ 0x03E0, 0x03E0 },
|
||||
{ 0x03E2, 0x03F3 },
|
||||
{ 0x0401, 0x040C },
|
||||
{ 0x040E, 0x044F },
|
||||
{ 0x0451, 0x045C },
|
||||
{ 0x045E, 0x0481 },
|
||||
{ 0x0490, 0x04C4 },
|
||||
{ 0x04C7, 0x04C8 },
|
||||
{ 0x04CB, 0x04CC },
|
||||
{ 0x04D0, 0x04EB },
|
||||
{ 0x04EE, 0x04F5 },
|
||||
{ 0x04F8, 0x04F9 },
|
||||
{ 0x0531, 0x0556 },
|
||||
{ 0x0559, 0x0559 },
|
||||
{ 0x0561, 0x0587 },
|
||||
{ 0x05B0, 0x05B9 },
|
||||
{ 0x05BB, 0x05BD },
|
||||
{ 0x05BF, 0x05BF },
|
||||
{ 0x05C1, 0x05C2 },
|
||||
{ 0x05D0, 0x05EA },
|
||||
{ 0x05F0, 0x05F2 },
|
||||
{ 0x0621, 0x063A },
|
||||
{ 0x0640, 0x0652 },
|
||||
{ 0x0660, 0x0669 },
|
||||
{ 0x0670, 0x06B7 },
|
||||
{ 0x06BA, 0x06BE },
|
||||
{ 0x06C0, 0x06CE },
|
||||
{ 0x06D0, 0x06DC },
|
||||
{ 0x06E5, 0x06E8 },
|
||||
{ 0x06EA, 0x06ED },
|
||||
{ 0x06F0, 0x06F9 },
|
||||
{ 0x0901, 0x0903 },
|
||||
{ 0x0905, 0x0939 },
|
||||
{ 0x093D, 0x093D },
|
||||
{ 0x093E, 0x094D },
|
||||
{ 0x0950, 0x0952 },
|
||||
{ 0x0958, 0x0963 },
|
||||
{ 0x0966, 0x096F },
|
||||
{ 0x0981, 0x0983 },
|
||||
{ 0x0985, 0x098C },
|
||||
{ 0x098F, 0x0990 },
|
||||
{ 0x0993, 0x09A8 },
|
||||
{ 0x09AA, 0x09B0 },
|
||||
{ 0x09B2, 0x09B2 },
|
||||
{ 0x09B6, 0x09B9 },
|
||||
{ 0x09BE, 0x09C4 },
|
||||
{ 0x09C7, 0x09C8 },
|
||||
{ 0x09CB, 0x09CD },
|
||||
{ 0x09DC, 0x09DD },
|
||||
{ 0x09DF, 0x09E3 },
|
||||
{ 0x09E6, 0x09EF },
|
||||
{ 0x09F0, 0x09F1 },
|
||||
{ 0x0A02, 0x0A02 },
|
||||
{ 0x0A05, 0x0A0A },
|
||||
{ 0x0A0F, 0x0A10 },
|
||||
{ 0x0A13, 0x0A28 },
|
||||
{ 0x0A2A, 0x0A30 },
|
||||
{ 0x0A32, 0x0A33 },
|
||||
{ 0x0A35, 0x0A36 },
|
||||
{ 0x0A38, 0x0A39 },
|
||||
{ 0x0A3E, 0x0A42 },
|
||||
{ 0x0A47, 0x0A48 },
|
||||
{ 0x0A4B, 0x0A4D },
|
||||
{ 0x0A59, 0x0A5C },
|
||||
{ 0x0A5E, 0x0A5E },
|
||||
{ 0x0A66, 0x0A6F },
|
||||
{ 0x0A74, 0x0A74 },
|
||||
{ 0x0A81, 0x0A83 },
|
||||
{ 0x0A85, 0x0A8B },
|
||||
{ 0x0A8D, 0x0A8D },
|
||||
{ 0x0A8F, 0x0A91 },
|
||||
{ 0x0A93, 0x0AA8 },
|
||||
{ 0x0AAA, 0x0AB0 },
|
||||
{ 0x0AB2, 0x0AB3 },
|
||||
{ 0x0AB5, 0x0AB9 },
|
||||
{ 0x0ABD, 0x0AC5 },
|
||||
{ 0x0AC7, 0x0AC9 },
|
||||
{ 0x0ACB, 0x0ACD },
|
||||
{ 0x0AD0, 0x0AD0 },
|
||||
{ 0x0AE0, 0x0AE0 },
|
||||
{ 0x0AE6, 0x0AEF },
|
||||
{ 0x0B01, 0x0B03 },
|
||||
{ 0x0B05, 0x0B0C },
|
||||
{ 0x0B0F, 0x0B10 },
|
||||
{ 0x0B13, 0x0B28 },
|
||||
{ 0x0B2A, 0x0B30 },
|
||||
{ 0x0B32, 0x0B33 },
|
||||
{ 0x0B36, 0x0B39 },
|
||||
{ 0x0B3D, 0x0B3D },
|
||||
{ 0x0B3E, 0x0B43 },
|
||||
{ 0x0B47, 0x0B48 },
|
||||
{ 0x0B4B, 0x0B4D },
|
||||
{ 0x0B5C, 0x0B5D },
|
||||
{ 0x0B5F, 0x0B61 },
|
||||
{ 0x0B66, 0x0B6F },
|
||||
{ 0x0B82, 0x0B83 },
|
||||
{ 0x0B85, 0x0B8A },
|
||||
{ 0x0B8E, 0x0B90 },
|
||||
{ 0x0B92, 0x0B95 },
|
||||
{ 0x0B99, 0x0B9A },
|
||||
{ 0x0B9C, 0x0B9C },
|
||||
{ 0x0B9E, 0x0B9F },
|
||||
{ 0x0BA3, 0x0BA4 },
|
||||
{ 0x0BA8, 0x0BAA },
|
||||
{ 0x0BAE, 0x0BB5 },
|
||||
{ 0x0BB7, 0x0BB9 },
|
||||
{ 0x0BBE, 0x0BC2 },
|
||||
{ 0x0BC6, 0x0BC8 },
|
||||
{ 0x0BCA, 0x0BCD },
|
||||
{ 0x0BE7, 0x0BEF },
|
||||
{ 0x0C01, 0x0C03 },
|
||||
{ 0x0C05, 0x0C0C },
|
||||
{ 0x0C0E, 0x0C10 },
|
||||
{ 0x0C12, 0x0C28 },
|
||||
{ 0x0C2A, 0x0C33 },
|
||||
{ 0x0C35, 0x0C39 },
|
||||
{ 0x0C3E, 0x0C44 },
|
||||
{ 0x0C46, 0x0C48 },
|
||||
{ 0x0C4A, 0x0C4D },
|
||||
{ 0x0C60, 0x0C61 },
|
||||
{ 0x0C66, 0x0C6F },
|
||||
{ 0x0C82, 0x0C83 },
|
||||
{ 0x0C85, 0x0C8C },
|
||||
{ 0x0C8E, 0x0C90 },
|
||||
{ 0x0C92, 0x0CA8 },
|
||||
{ 0x0CAA, 0x0CB3 },
|
||||
{ 0x0CB5, 0x0CB9 },
|
||||
{ 0x0CBE, 0x0CC4 },
|
||||
{ 0x0CC6, 0x0CC8 },
|
||||
{ 0x0CCA, 0x0CCD },
|
||||
{ 0x0CDE, 0x0CDE },
|
||||
{ 0x0CE0, 0x0CE1 },
|
||||
{ 0x0CE6, 0x0CEF },
|
||||
{ 0x0D02, 0x0D03 },
|
||||
{ 0x0D05, 0x0D0C },
|
||||
{ 0x0D0E, 0x0D10 },
|
||||
{ 0x0D12, 0x0D28 },
|
||||
{ 0x0D2A, 0x0D39 },
|
||||
{ 0x0D3E, 0x0D43 },
|
||||
{ 0x0D46, 0x0D48 },
|
||||
{ 0x0D4A, 0x0D4D },
|
||||
{ 0x0D60, 0x0D61 },
|
||||
{ 0x0D66, 0x0D6F },
|
||||
{ 0x0E01, 0x0E3A },
|
||||
{ 0x0E40, 0x0E5B },
|
||||
// { 0x0E50, 0x0E59 },
|
||||
{ 0x0E81, 0x0E82 },
|
||||
{ 0x0E84, 0x0E84 },
|
||||
{ 0x0E87, 0x0E88 },
|
||||
{ 0x0E8A, 0x0E8A },
|
||||
{ 0x0E8D, 0x0E8D },
|
||||
{ 0x0E94, 0x0E97 },
|
||||
{ 0x0E99, 0x0E9F },
|
||||
{ 0x0EA1, 0x0EA3 },
|
||||
{ 0x0EA5, 0x0EA5 },
|
||||
{ 0x0EA7, 0x0EA7 },
|
||||
{ 0x0EAA, 0x0EAB },
|
||||
{ 0x0EAD, 0x0EAE },
|
||||
{ 0x0EB0, 0x0EB9 },
|
||||
{ 0x0EBB, 0x0EBD },
|
||||
{ 0x0EC0, 0x0EC4 },
|
||||
{ 0x0EC6, 0x0EC6 },
|
||||
{ 0x0EC8, 0x0ECD },
|
||||
{ 0x0ED0, 0x0ED9 },
|
||||
{ 0x0EDC, 0x0EDD },
|
||||
{ 0x0F00, 0x0F00 },
|
||||
{ 0x0F18, 0x0F19 },
|
||||
{ 0x0F20, 0x0F33 },
|
||||
{ 0x0F35, 0x0F35 },
|
||||
{ 0x0F37, 0x0F37 },
|
||||
{ 0x0F39, 0x0F39 },
|
||||
{ 0x0F3E, 0x0F47 },
|
||||
{ 0x0F49, 0x0F69 },
|
||||
{ 0x0F71, 0x0F84 },
|
||||
{ 0x0F86, 0x0F8B },
|
||||
{ 0x0F90, 0x0F95 },
|
||||
{ 0x0F97, 0x0F97 },
|
||||
{ 0x0F99, 0x0FAD },
|
||||
{ 0x0FB1, 0x0FB7 },
|
||||
{ 0x0FB9, 0x0FB9 },
|
||||
{ 0x10A0, 0x10C5 },
|
||||
{ 0x10D0, 0x10F6 },
|
||||
{ 0x1E00, 0x1E9B },
|
||||
{ 0x1EA0, 0x1EF9 },
|
||||
{ 0x1F00, 0x1F15 },
|
||||
{ 0x1F18, 0x1F1D },
|
||||
{ 0x1F20, 0x1F45 },
|
||||
{ 0x1F48, 0x1F4D },
|
||||
{ 0x1F50, 0x1F57 },
|
||||
{ 0x1F59, 0x1F59 },
|
||||
{ 0x1F5B, 0x1F5B },
|
||||
{ 0x1F5D, 0x1F5D },
|
||||
{ 0x1F5F, 0x1F7D },
|
||||
{ 0x1F80, 0x1FB4 },
|
||||
{ 0x1FB6, 0x1FBC },
|
||||
{ 0x1FBE, 0x1FBE },
|
||||
{ 0x1FC2, 0x1FC4 },
|
||||
{ 0x1FC6, 0x1FCC },
|
||||
{ 0x1FD0, 0x1FD3 },
|
||||
{ 0x1FD6, 0x1FDB },
|
||||
{ 0x1FE0, 0x1FEC },
|
||||
{ 0x1FF2, 0x1FF4 },
|
||||
{ 0x1FF6, 0x1FFC },
|
||||
{ 0x203F, 0x2040 },
|
||||
{ 0x207F, 0x207F },
|
||||
{ 0x2102, 0x2102 },
|
||||
{ 0x2107, 0x2107 },
|
||||
{ 0x210A, 0x2113 },
|
||||
{ 0x2115, 0x2115 },
|
||||
{ 0x2118, 0x211D },
|
||||
{ 0x2124, 0x2124 },
|
||||
{ 0x2126, 0x2126 },
|
||||
{ 0x2128, 0x2128 },
|
||||
{ 0x212A, 0x2131 },
|
||||
{ 0x2133, 0x2138 },
|
||||
{ 0x2160, 0x2182 },
|
||||
{ 0x3005, 0x3007 },
|
||||
{ 0x3021, 0x3029 },
|
||||
{ 0x3041, 0x3093 },
|
||||
{ 0x309B, 0x309C },
|
||||
{ 0x30A1, 0x30F6 },
|
||||
{ 0x30FB, 0x30FC },
|
||||
{ 0x3105, 0x312C },
|
||||
{ 0x4E00, 0x9FA5 },
|
||||
{ 0xAC00, 0xD7A3 },
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
//printf("%x\n", table[i][0]);
|
||||
assert(table[i][0] <= table[i][1]);
|
||||
if (i < sizeof(table) / sizeof(table[0]) - 1)
|
||||
assert(table[i][1] < table[i + 1][0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (u > 0xD7A3)
|
||||
goto Lisnot;
|
||||
|
||||
// Binary search
|
||||
int mid;
|
||||
int low;
|
||||
int high;
|
||||
|
||||
low = 0;
|
||||
high = sizeof(table) / sizeof(table[0]) - 1;
|
||||
while (low <= high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
if (u < table[mid][0])
|
||||
high = mid - 1;
|
||||
else if (u > table[mid][1])
|
||||
low = mid + 1;
|
||||
else
|
||||
goto Lis;
|
||||
}
|
||||
|
||||
Lisnot:
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
assert(u < table[i][0] || u > table[i][1]);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
Lis:
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
if (u >= table[i][0] && u <= table[i][1])
|
||||
return 1;
|
||||
}
|
||||
assert(0); // should have been in table
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
193
dmd2/utf.c
Normal file
193
dmd2/utf.c
Normal file
@@ -0,0 +1,193 @@
|
||||
// utf.c
|
||||
// Copyright (c) 2003 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.
|
||||
|
||||
// Description of UTF-8 at:
|
||||
// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "utf.h"
|
||||
|
||||
int utf_isValidDchar(dchar_t c)
|
||||
{
|
||||
return c < 0xD800 ||
|
||||
(c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF);
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Decode a single UTF-8 character sequence.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
{
|
||||
dchar_t V;
|
||||
size_t i = *pidx;
|
||||
unsigned char u = s[i];
|
||||
|
||||
assert(i >= 0 && i < len);
|
||||
|
||||
if (u & 0x80)
|
||||
{ unsigned n;
|
||||
unsigned char u2;
|
||||
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
for (n = 1; ; n++)
|
||||
{
|
||||
if (n > 4)
|
||||
goto Lerr; // only do the first 4 of 6 encodings
|
||||
if (((u << n) & 0x80) == 0)
|
||||
{
|
||||
if (n == 1)
|
||||
goto Lerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick off (7 - n) significant bits of B from first byte of octet
|
||||
V = (dchar_t)(u & ((1 << (7 - n)) - 1));
|
||||
|
||||
if (i + (n - 1) >= len)
|
||||
goto Lerr; // off end of string
|
||||
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
u2 = s[i + 1];
|
||||
if ((u & 0xFE) == 0xC0 ||
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
goto Lerr; // overlong combination
|
||||
|
||||
for (unsigned j = 1; j != n; j++)
|
||||
{
|
||||
u = s[i + j];
|
||||
if ((u & 0xC0) != 0x80)
|
||||
goto Lerr; // trailing bytes are 10xxxxxx
|
||||
V = (V << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!utf_isValidDchar(V))
|
||||
goto Lerr;
|
||||
i += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = (dchar_t) u;
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(utf_isValidDchar(V));
|
||||
*pidx = i;
|
||||
*presult = V;
|
||||
return NULL;
|
||||
|
||||
Lerr:
|
||||
*presult = (dchar_t) s[i];
|
||||
*pidx = i + 1;
|
||||
return "invalid UTF-8 sequence";
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Validate a UTF-8 string.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
const char *utf_validateString(unsigned char *s, size_t len)
|
||||
{
|
||||
size_t idx;
|
||||
const char *err = NULL;
|
||||
dchar_t dc;
|
||||
|
||||
for (idx = 0; idx < len; )
|
||||
{
|
||||
err = utf_decodeChar(s, len, &idx, &dc);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Decode a single UTF-16 character sequence.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
|
||||
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
{
|
||||
const char *msg;
|
||||
size_t i = *pidx;
|
||||
unsigned u = s[i];
|
||||
|
||||
assert(i >= 0 && i < len);
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ unsigned u2;
|
||||
|
||||
if (i + 1 == len)
|
||||
{ msg = "surrogate UTF-16 high value past end of string";
|
||||
goto Lerr;
|
||||
}
|
||||
u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ msg = "surrogate UTF-16 low value out of range";
|
||||
goto Lerr;
|
||||
}
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
i += 2;
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ msg = "unpaired surrogate UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ msg = "illegal UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(utf_isValidDchar(u));
|
||||
*pidx = i;
|
||||
*presult = (dchar_t)u;
|
||||
return NULL;
|
||||
|
||||
Lerr:
|
||||
*presult = (dchar_t)s[i];
|
||||
*pidx = i + 1;
|
||||
return msg;
|
||||
}
|
||||
|
||||
26
dmd2/utf.h
Normal file
26
dmd2/utf.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Compiler implementation of the D programming language
|
||||
// utf.h
|
||||
// Copyright (c) 2003-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.
|
||||
|
||||
#ifndef DMD_UTF_H
|
||||
#define DMD_UTF_H
|
||||
|
||||
|
||||
typedef unsigned dchar_t;
|
||||
|
||||
int utf_isValidDchar(dchar_t c);
|
||||
|
||||
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
|
||||
const char *utf_validateString(unsigned char *s, size_t len);
|
||||
|
||||
extern int isUniAlpha(dchar_t);
|
||||
|
||||
#endif
|
||||
181
dmd2/version.c
Normal file
181
dmd2/version.c
Normal file
@@ -0,0 +1,181 @@
|
||||
|
||||
// Copyright (c) 1999-2005 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 <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "identifier.h"
|
||||
#include "dsymbol.h"
|
||||
#include "cond.h"
|
||||
#include "version.h"
|
||||
#include "module.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* DebugSymbol's happen for statements like:
|
||||
* debug = identifier;
|
||||
* debug = integer;
|
||||
*/
|
||||
|
||||
DebugSymbol::DebugSymbol(Loc loc, Identifier *ident)
|
||||
: Dsymbol(ident)
|
||||
{
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
DebugSymbol::DebugSymbol(Loc loc, unsigned level)
|
||||
: Dsymbol()
|
||||
{
|
||||
this->level = level;
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
DebugSymbol *ds = new DebugSymbol(loc, ident);
|
||||
ds->level = level;
|
||||
return ds;
|
||||
}
|
||||
|
||||
int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
//printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars());
|
||||
Module *m;
|
||||
|
||||
// Do not add the member to the symbol table,
|
||||
// just make sure subsequent debug declarations work.
|
||||
m = sd->isModule();
|
||||
if (ident)
|
||||
{
|
||||
if (!m)
|
||||
error("declaration must be at module level");
|
||||
else
|
||||
{
|
||||
if (findCondition(m->debugidsNot, ident))
|
||||
error("defined after use");
|
||||
if (!m->debugids)
|
||||
m->debugids = new Array();
|
||||
m->debugids->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m)
|
||||
error("level declaration must be at module level");
|
||||
else
|
||||
m->debuglevel = level;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DebugSymbol::semantic(Scope *sc)
|
||||
{
|
||||
//printf("DebugSymbol::semantic() %s\n", toChars());
|
||||
}
|
||||
|
||||
void DebugSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("debug = ");
|
||||
if (ident)
|
||||
buf->writestring(ident->toChars());
|
||||
else
|
||||
buf->printf("%u", level);
|
||||
buf->writestring(";");
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
const char *DebugSymbol::kind()
|
||||
{
|
||||
return "debug";
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* VersionSymbol's happen for statements like:
|
||||
* version = identifier;
|
||||
* version = integer;
|
||||
*/
|
||||
|
||||
VersionSymbol::VersionSymbol(Loc loc, Identifier *ident)
|
||||
: Dsymbol(ident)
|
||||
{
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
VersionSymbol::VersionSymbol(Loc loc, unsigned level)
|
||||
: Dsymbol()
|
||||
{
|
||||
this->level = level;
|
||||
this->loc = loc;
|
||||
}
|
||||
|
||||
Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
VersionSymbol *ds = new VersionSymbol(loc, ident);
|
||||
ds->level = level;
|
||||
return ds;
|
||||
}
|
||||
|
||||
int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
//printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars());
|
||||
Module *m;
|
||||
|
||||
// Do not add the member to the symbol table,
|
||||
// just make sure subsequent debug declarations work.
|
||||
m = sd->isModule();
|
||||
if (ident)
|
||||
{
|
||||
VersionCondition::checkPredefined(loc, ident->toChars());
|
||||
if (!m)
|
||||
error("declaration must be at module level");
|
||||
else
|
||||
{
|
||||
if (findCondition(m->versionidsNot, ident))
|
||||
error("defined after use");
|
||||
if (!m->versionids)
|
||||
m->versionids = new Array();
|
||||
m->versionids->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m)
|
||||
error("level declaration must be at module level");
|
||||
else
|
||||
m->versionlevel = level;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VersionSymbol::semantic(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
void VersionSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("version = ");
|
||||
if (ident)
|
||||
buf->writestring(ident->toChars());
|
||||
else
|
||||
buf->printf("%u", level);
|
||||
buf->writestring(";");
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
const char *VersionSymbol::kind()
|
||||
{
|
||||
return "version";
|
||||
}
|
||||
|
||||
|
||||
51
dmd2/version.h
Normal file
51
dmd2/version.h
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
// 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_VERSION_H
|
||||
#define DMD_VERSION_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct OutBuffer;
|
||||
struct HdrGenState;
|
||||
|
||||
struct DebugSymbol : Dsymbol
|
||||
{
|
||||
unsigned level;
|
||||
|
||||
DebugSymbol(Loc loc, Identifier *ident);
|
||||
DebugSymbol(Loc loc, unsigned level);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
struct VersionSymbol : Dsymbol
|
||||
{
|
||||
unsigned level;
|
||||
|
||||
VersionSymbol(Loc loc, Identifier *ident);
|
||||
VersionSymbol(Loc loc, unsigned level);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
#endif /* DMD_VERSION_H */
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
const LLStructType* DtoArrayType(Type* arrayTy)
|
||||
{
|
||||
assert(arrayTy->next);
|
||||
const LLType* elemty = DtoType(arrayTy->next);
|
||||
assert(arrayTy->nextOf());
|
||||
const LLType* elemty = DtoType(arrayTy->nextOf());
|
||||
if (elemty == LLType::VoidTy)
|
||||
elemty = LLType::Int8Ty;
|
||||
return LLStructType::get(DtoSize_t(), getPtrToType(elemty), 0);
|
||||
@@ -39,7 +39,7 @@ const LLArrayType* DtoStaticArrayType(Type* t)
|
||||
t = t->toBasetype();
|
||||
assert(t->ty == Tsarray);
|
||||
TypeSArray* tsa = (TypeSArray*)t;
|
||||
Type* tnext = tsa->next;
|
||||
Type* tnext = tsa->nextOf();
|
||||
|
||||
const LLType* elemty = DtoType(tnext);
|
||||
if (elemty == LLType::VoidTy)
|
||||
@@ -238,8 +238,8 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
|
||||
|
||||
std::vector<LLConstant*> inits(tdim, NULL);
|
||||
|
||||
Type* arrnext = arrinittype->next;
|
||||
const LLType* elemty = DtoType(arrinittype->next);
|
||||
Type* arrnext = arrinittype->nextOf();
|
||||
const LLType* elemty = DtoType(arrinittype->nextOf());
|
||||
|
||||
assert(arrinit->index.dim == arrinit->value.dim);
|
||||
for (unsigned i=0,j=0; i < tdim; ++i)
|
||||
@@ -289,7 +289,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
|
||||
}
|
||||
|
||||
if (!v)
|
||||
v = DtoConstInitializer(t->next, init);
|
||||
v = DtoConstInitializer(t->nextOf(), init);
|
||||
assert(v);
|
||||
|
||||
inits[i] = v;
|
||||
@@ -447,7 +447,7 @@ DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
|
||||
assert(arrayType->toBasetype()->ty == Tarray);
|
||||
|
||||
// decide on what runtime function to call based on whether the type is zero initialized
|
||||
bool zeroInit = arrayType->toBasetype()->next->isZeroInit();
|
||||
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
|
||||
|
||||
// call runtime
|
||||
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_arraysetlengthT" : "_d_arraysetlengthiT" );
|
||||
@@ -583,7 +583,7 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
|
||||
llvm::Value *len1, *src1, *res;
|
||||
|
||||
// handle prefix case, eg. int~int[]
|
||||
if (t2->next && t1 == t2->next->toBasetype())
|
||||
if (t2->nextOf() && t1 == t2->nextOf()->toBasetype())
|
||||
{
|
||||
len1 = DtoArrayLen(e2);
|
||||
res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
|
||||
@@ -733,7 +733,7 @@ LLValue* DtoArrayCompare(Loc& loc, TOK op, DValue* l, DValue* r)
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
Type* t = l->getType()->toBasetype()->next->toBasetype();
|
||||
Type* t = l->getType()->toBasetype()->nextOf()->toBasetype();
|
||||
if (t->ty == Tchar)
|
||||
res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false);
|
||||
else
|
||||
@@ -851,7 +851,7 @@ LLValue* DtoArrayPtr(DValue* v)
|
||||
if (DSliceValue* s = v->isSlice())
|
||||
return s->ptr;
|
||||
else if (v->isNull())
|
||||
return getNullPtr(getPtrToType(DtoType(t->next)));
|
||||
return getNullPtr(getPtrToType(DtoType(t->nextOf())));
|
||||
else if (v->isLVal())
|
||||
return DtoLoad(DtoGEPi(v->getLVal(), 0,1), ".ptr");
|
||||
return gIR->ir->CreateExtractValue(v->getRVal(), 1, ".ptr");
|
||||
@@ -896,7 +896,7 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
||||
Logger::cout() << "to array" << '\n';
|
||||
|
||||
const LLType* ptrty = DtoArrayType(totype)->getContainedType(1);
|
||||
const LLType* ety = DtoTypeNotVoid(fromtype->next);
|
||||
const LLType* ety = DtoTypeNotVoid(fromtype->nextOf());
|
||||
|
||||
if (DSliceValue* usl = u->isSlice()) {
|
||||
if (Logger::enabled())
|
||||
@@ -905,7 +905,7 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
||||
Logger::cout() << "from: " << *usl->ptr << " to: " << *ptrty << '\n';
|
||||
}
|
||||
rval = DtoBitCast(usl->ptr, ptrty);
|
||||
if (fromtype->next->size() == totype->next->size())
|
||||
if (fromtype->nextOf()->size() == totype->nextOf()->size())
|
||||
rval2 = DtoArrayLen(usl);
|
||||
else
|
||||
rval2 = DtoArrayCastLength(DtoArrayLen(usl), ety, ptrty->getContainedType(0));
|
||||
@@ -920,7 +920,7 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
||||
assert(isaPointer(uval->getType()));
|
||||
const LLArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
|
||||
|
||||
if(arrty->getNumElements()*fromtype->next->size() % totype->next->size() != 0)
|
||||
if(arrty->getNumElements()*fromtype->nextOf()->size() % totype->nextOf()->size() != 0)
|
||||
{
|
||||
error(loc, "invalid cast from '%s' to '%s', the element sizes don't line up", fromtype->toChars(), totype->toChars());
|
||||
fatal();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user