mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-05-01 16:01:29 +02:00
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
Added support for array .sort and .reverse properties. Fixed some bugs with pointer arithmetic. Disabled some DMD AST optimizations that was messing things up, destroying valuable information. Added a KDevelop project file, this is what I use for coding LLVMDC now :) Other minor stuff.
This commit is contained in:
@@ -35,10 +35,21 @@ llvmdc internal/aApply.d -c -odobj || exit 1
|
||||
llvmdc internal/aApplyR.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling array runtime support"
|
||||
llvmdc internal/qsort2.d -c -odobj || exit
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1
|
||||
llvmdc internal/adi.d -c -odobj || exit
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling llvm runtime support"
|
||||
rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit
|
||||
rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling garbage collector"
|
||||
llvmdc gc/gclinux.d -c -odobj || exit 1
|
||||
llvmdc gc/gcstub.d -c -odobj -Igc || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling phobos"
|
||||
rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
107
lphobos/gc/gclinux.d
Normal file
107
lphobos/gc/gclinux.d
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
// Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
import std.c.linux.linuxextern;
|
||||
import std.c.linux.linux;
|
||||
|
||||
/+
|
||||
extern (C)
|
||||
{
|
||||
// from <sys/mman.h>
|
||||
void* mmap(void* addr, uint len, int prot, int flags, int fd, uint offset);
|
||||
int munmap(void* addr, uint len);
|
||||
const void* MAP_FAILED = cast(void*)-1;
|
||||
|
||||
// from <bits/mman.h>
|
||||
enum { PROT_NONE = 0, PROT_READ = 1, PROT_WRITE = 2, PROT_EXEC = 4 }
|
||||
enum { MAP_SHARED = 1, MAP_PRIVATE = 2, MAP_TYPE = 0x0F,
|
||||
MAP_FIXED = 0x10, MAP_FILE = 0, MAP_ANON = 0x20 }
|
||||
}
|
||||
+/
|
||||
|
||||
/***********************************
|
||||
* Map memory.
|
||||
*/
|
||||
|
||||
void *os_mem_map(uint nbytes)
|
||||
{ void *p;
|
||||
|
||||
//errno = 0;
|
||||
p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
return (p == MAP_FAILED) ? null : p;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Commit memory.
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_commit(void *base, uint offset, uint nbytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Decommit memory.
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_decommit(void *base, uint offset, uint nbytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Unmap memory allocated with os_mem_map().
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_unmap(void *base, uint nbytes)
|
||||
{
|
||||
return munmap(base, nbytes);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Determine "bottom" of stack (actually the top on x86 systems).
|
||||
*/
|
||||
|
||||
void *os_query_stackBottom()
|
||||
{
|
||||
version (none)
|
||||
{ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
|
||||
static void** libc_stack_end;
|
||||
|
||||
if (libc_stack_end == libc_stack_end.init)
|
||||
{
|
||||
void* handle = dlopen(null, RTLD_NOW);
|
||||
libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end");
|
||||
dlclose(handle);
|
||||
}
|
||||
return *libc_stack_end;
|
||||
}
|
||||
else
|
||||
{ // This doesn't resolve on all versions of Linux
|
||||
return __libc_stack_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Determine base address and size of static data segment.
|
||||
*/
|
||||
|
||||
void os_query_staticdataseg(void **base, uint *nbytes)
|
||||
{
|
||||
*base = cast(void *)&__data_start;
|
||||
*nbytes = cast(byte *)&_end - cast(byte *)&__data_start;
|
||||
}
|
||||
213
lphobos/gc/gcstub.d
Normal file
213
lphobos/gc/gcstub.d
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
// D Garbage Collector stub to prevent linking in gc
|
||||
|
||||
module gcx;
|
||||
|
||||
//debug=PRINTF;
|
||||
|
||||
/***************************************************/
|
||||
|
||||
import object;
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
import win32;
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
import gclinux;
|
||||
}
|
||||
|
||||
|
||||
//alias GC* gc_t;
|
||||
alias GC gc_t;
|
||||
|
||||
struct GCStats { }
|
||||
|
||||
/* ============================ GC =============================== */
|
||||
|
||||
|
||||
//alias int size_t;
|
||||
alias void (*GC_FINALIZER)(void *p, void *dummy);
|
||||
|
||||
const uint GCVERSION = 1; // increment every time we change interface
|
||||
// to GC.
|
||||
|
||||
class GC
|
||||
{
|
||||
uint gcversion = GCVERSION;
|
||||
|
||||
void *gcx; // implementation
|
||||
|
||||
void initialize()
|
||||
{
|
||||
debug(PRINTF) printf("initialize()\n");
|
||||
}
|
||||
|
||||
|
||||
void Dtor()
|
||||
{
|
||||
debug(PRINTF) printf("Dtor()\n");
|
||||
}
|
||||
|
||||
/+invariant
|
||||
{
|
||||
debug(PRINTF) printf("invariant()\n");
|
||||
}+/
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("malloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
void *mallocNoSync(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("mallocNoSync()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void *calloc(size_t size, size_t n)
|
||||
{
|
||||
debug(PRINTF) printf("calloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void *realloc(void *p, size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("realloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void free(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("free()\n");
|
||||
}
|
||||
|
||||
size_t capacity(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("capacity()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("check()\n");
|
||||
}
|
||||
|
||||
|
||||
void setStackBottom(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("setStackBottom()\n");
|
||||
}
|
||||
|
||||
static void scanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
void *ptop;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("scanStaticData()\n");
|
||||
//debug(PRINTF) printf("+GC.scanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
ptop = pbot + nbytes;
|
||||
g.addRange(pbot, ptop);
|
||||
//debug(PRINTF) printf("-GC.scanStaticData()\n");
|
||||
}
|
||||
|
||||
static void unscanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("unscanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
g.removeRange(pbot);
|
||||
}
|
||||
|
||||
|
||||
void addRoot(void *p) // add p to list of roots
|
||||
{
|
||||
debug(PRINTF) printf("addRoot()\n");
|
||||
}
|
||||
|
||||
void removeRoot(void *p) // remove p from list of roots
|
||||
{
|
||||
debug(PRINTF) printf("removeRoot()\n");
|
||||
}
|
||||
|
||||
void addRange(void *pbot, void *ptop) // add range to scan for roots
|
||||
{
|
||||
debug(PRINTF) printf("addRange()\n");
|
||||
}
|
||||
|
||||
void removeRange(void *pbot) // remove range
|
||||
{
|
||||
debug(PRINTF) printf("removeRange()\n");
|
||||
}
|
||||
|
||||
void fullCollect() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("fullCollect()\n");
|
||||
}
|
||||
|
||||
void fullCollectNoStack() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("fullCollectNoStack()\n");
|
||||
}
|
||||
|
||||
void genCollect() // do generational garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("genCollect()\n");
|
||||
}
|
||||
|
||||
void minimize() // minimize physical memory usage
|
||||
{
|
||||
debug(PRINTF) printf("minimize()\n");
|
||||
}
|
||||
|
||||
void setFinalizer(void *p, GC_FINALIZER pFn)
|
||||
{
|
||||
debug(PRINTF) printf("setFinalizer()\n");
|
||||
}
|
||||
|
||||
void enable()
|
||||
{
|
||||
debug(PRINTF) printf("enable()\n");
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
debug(PRINTF) printf("disable()\n");
|
||||
}
|
||||
|
||||
void getStats(out GCStats stats)
|
||||
{
|
||||
debug(PRINTF) printf("getStats()\n");
|
||||
}
|
||||
}
|
||||
803
lphobos/internal/adi.d
Normal file
803
lphobos/internal/adi.d
Normal file
@@ -0,0 +1,803 @@
|
||||
//_ adi.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Dynamic array property support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
//debug=adi; // uncomment to turn on debugging printf's
|
||||
|
||||
//import std.stdio;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
//import std.string;
|
||||
import std.outofmemory;
|
||||
import std.utf;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of chars.
|
||||
* Handled separately because embedded multibyte encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
char[6] tmp;
|
||||
char[6] tmplo;
|
||||
char* lo = a.ptr;
|
||||
char* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
//printf("lo = %d, hi = %d\n", lo, hi);
|
||||
if (clo <= 0x7F && chi <= 0x7F)
|
||||
{
|
||||
//printf("\tascii\n");
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint stridelo = std.utf.UTF8stride[clo];
|
||||
|
||||
uint stridehi = 1;
|
||||
while ((chi & 0xC0) == 0x80)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
//printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
|
||||
if (stridelo == stridehi)
|
||||
{
|
||||
|
||||
memcpy(tmp.ptr, lo, stridelo);
|
||||
memcpy(lo, hi, stridelo);
|
||||
memcpy(hi, tmp.ptr, stridelo);
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi);
|
||||
memcpy(tmplo.ptr, lo, stridelo);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
|
||||
memcpy(lo, tmp.ptr, stridehi);
|
||||
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
string a = "abcd";
|
||||
string r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\u1235\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234\u1235a");
|
||||
|
||||
a = "ab\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234ba");
|
||||
|
||||
a = "\u3026\u2021\u3061\n";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "\n\u3061\u2021\u3026");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of wchars.
|
||||
* Handled separately because embedded multiword encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
wchar[2] tmp;
|
||||
wchar* lo = a.ptr;
|
||||
wchar* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
if ((clo < 0xD800 || clo > 0xDFFF) &&
|
||||
(chi < 0xD800 || chi > 0xDFFF))
|
||||
{
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
|
||||
|
||||
int stridehi = 1;
|
||||
if (chi >= 0xDC00 && chi <= 0xDFFF)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
if (stridelo == stridehi)
|
||||
{ int stmp;
|
||||
|
||||
assert(stridelo == 2);
|
||||
assert(stmp.sizeof == 2 * (*lo).sizeof);
|
||||
stmp = *cast(int*)lo;
|
||||
*cast(int*)lo = *cast(int*)hi;
|
||||
*cast(int*)hi = stmp;
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
|
||||
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
|
||||
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wstring a = "abcd";
|
||||
wstring r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\U00012356\U00012346c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012346\U00012356a");
|
||||
|
||||
a = "ab\U00012345c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012345ba");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverse(Array a, size_t szelem)
|
||||
out (result)
|
||||
{
|
||||
assert(result is *cast(long*)(&a));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
byte* tmp;
|
||||
byte[16] buffer;
|
||||
|
||||
void* lo = a.ptr;
|
||||
void* hi = a.ptr + (a.length - 1) * szelem;
|
||||
|
||||
tmp = buffer.ptr;
|
||||
if (szelem > 16)
|
||||
{
|
||||
//version (Win32)
|
||||
tmp = cast(byte*) alloca(szelem);
|
||||
//else
|
||||
//tmp = new byte[szelem];
|
||||
}
|
||||
|
||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||
{
|
||||
memcpy(tmp, lo, szelem);
|
||||
memcpy(lo, hi, szelem);
|
||||
memcpy(hi, tmp, szelem);
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (szelem > 16)
|
||||
// BUG: bad code is generate for delete pointer, tries
|
||||
// to call delclass.
|
||||
//delete tmp;
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse.unittest\n");
|
||||
|
||||
int[] a = new int[5];
|
||||
int[] b;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
a[i] = i;
|
||||
b = a.reverse;
|
||||
assert(b is a);
|
||||
for (i = 0; i < 5; i++)
|
||||
assert(a[i] == 4 - i);
|
||||
|
||||
struct X20
|
||||
{ // More than 16 bytes in size
|
||||
int a;
|
||||
int b, c, d, e;
|
||||
}
|
||||
|
||||
X20[] c = new X20[5];
|
||||
X20[] d;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{ c[i].a = i;
|
||||
c[i].e = 10;
|
||||
}
|
||||
d = c.reverse;
|
||||
assert(d is c);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(c[i].a == 4 - i);
|
||||
assert(c[i].e == 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property for bit[].
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) bit[] _adReverseBit(bit[] a)
|
||||
out (result)
|
||||
{
|
||||
assert(result is a);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
bit t;
|
||||
int lo, hi;
|
||||
|
||||
lo = 0;
|
||||
hi = a.length - 1;
|
||||
for (; lo < hi; lo++, hi--)
|
||||
{
|
||||
t = a[lo];
|
||||
a[lo] = a[hi];
|
||||
a[hi] = t;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse_Bit[].unittest\n");
|
||||
|
||||
bit[] b;
|
||||
b = new bit[5];
|
||||
static bit[5] data = [1,0,1,1,0];
|
||||
int i;
|
||||
|
||||
b[] = data[];
|
||||
b.reverse;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(b[i] == data[4 - i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ char[4] buf;
|
||||
string t = toUTF8(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ wchar[2] buf;
|
||||
wstring t = toUTF16(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Support for array.sort property for bit[].
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) bit[] _adSortBit(bit[] a)
|
||||
out (result)
|
||||
{
|
||||
assert(result is a);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
size_t lo, hi;
|
||||
|
||||
lo = 0;
|
||||
hi = a.length - 1;
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (lo >= hi)
|
||||
goto Ldone;
|
||||
if (a[lo] == true)
|
||||
break;
|
||||
lo++;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (lo >= hi)
|
||||
goto Ldone;
|
||||
if (a[hi] == false)
|
||||
break;
|
||||
hi--;
|
||||
}
|
||||
|
||||
a[lo] = false;
|
||||
a[hi] = true;
|
||||
|
||||
lo++;
|
||||
hi--;
|
||||
}
|
||||
Ldone:
|
||||
;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.sort_Bit[].unittest\n");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test.
|
||||
*/
|
||||
|
||||
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
//printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
auto sz = ti.tsize();
|
||||
auto p1 = a1.ptr;
|
||||
auto p2 = a2.ptr;
|
||||
|
||||
/+
|
||||
for (int i = 0; i < a1.length; i++)
|
||||
{
|
||||
printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]);
|
||||
}
|
||||
+/
|
||||
|
||||
if (sz == 1)
|
||||
// We should really have a ti.isPOD() check for this
|
||||
return (memcmp(p1, p2, a1.length) == 0);
|
||||
|
||||
for (size_t i = 0; i < a1.length; i++)
|
||||
{
|
||||
if (!ti.equals(p1 + i * sz, p2 + i * sz))
|
||||
return 0; // not equal
|
||||
}
|
||||
return 1; // equal
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
assert(a != "betty");
|
||||
assert(a == "hello");
|
||||
assert(a != "hxxxx");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test for bit arrays.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) int _adEqBit(Array a1, Array a2)
|
||||
{ size_t i;
|
||||
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
auto p1 = cast(byte*)a1.ptr;
|
||||
auto p2 = cast(byte*)a2.ptr;
|
||||
auto n = a1.length / 8;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (p1[i] != p2[i])
|
||||
return 0; // not equal
|
||||
}
|
||||
|
||||
ubyte mask;
|
||||
|
||||
n = a1.length & 7;
|
||||
mask = cast(ubyte)((1 << n) - 1);
|
||||
//printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
|
||||
return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.EqBit unittest\n");
|
||||
|
||||
static bit[] a = [1,0,1,0,1];
|
||||
static bit[] b = [1,0,1];
|
||||
static bit[] c = [1,0,1,0,1,0,1];
|
||||
static bit[] d = [1,0,1,1,1];
|
||||
static bit[] e = [1,0,1,0,1];
|
||||
|
||||
assert(a != b);
|
||||
assert(a != c);
|
||||
assert(a != d);
|
||||
assert(a == e);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
//printf("adCmp()\n");
|
||||
auto len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
auto sz = ti.tsize();
|
||||
void *p1 = a1.ptr;
|
||||
void *p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
{ // We should really have a ti.isPOD() check for this
|
||||
auto c = memcmp(p1, p2, len);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
auto c = ti.compare(p1 + i * sz, p2 + i * sz);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (a1.length == a2.length)
|
||||
return 0;
|
||||
return (a1.length > a2.length) ? 1 : -1;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmpChar(Array a1, Array a2)
|
||||
{
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
|
||||
mov ESI,a1+4[4+ESP] ;
|
||||
mov EDI,a2+4[4+ESP] ;
|
||||
|
||||
mov ECX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
cmp ECX,EDX ;
|
||||
jb GotLength ;
|
||||
|
||||
mov ECX,EDX ;
|
||||
|
||||
GotLength:
|
||||
cmp ECX,4 ;
|
||||
jb DoBytes ;
|
||||
|
||||
// Do alignment if neither is dword aligned
|
||||
test ESI,3 ;
|
||||
jz Aligned ;
|
||||
|
||||
test EDI,3 ;
|
||||
jz Aligned ;
|
||||
DoAlign:
|
||||
mov AL,[ESI] ; //align ESI to dword bounds
|
||||
mov DL,[EDI] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
inc ESI ;
|
||||
inc EDI ;
|
||||
|
||||
test ESI,3 ;
|
||||
|
||||
lea ECX,[ECX-1] ;
|
||||
jnz DoAlign ;
|
||||
Aligned:
|
||||
mov EAX,ECX ;
|
||||
|
||||
// do multiple of 4 bytes at a time
|
||||
|
||||
shr ECX,2 ;
|
||||
jz TryOdd ;
|
||||
|
||||
repe ;
|
||||
cmpsd ;
|
||||
|
||||
jnz UnequalQuad ;
|
||||
|
||||
TryOdd:
|
||||
mov ECX,EAX ;
|
||||
DoBytes:
|
||||
// if still equal and not end of string, do up to 3 bytes slightly
|
||||
// slower.
|
||||
|
||||
and ECX,3 ;
|
||||
jz Equal ;
|
||||
|
||||
repe ;
|
||||
cmpsb ;
|
||||
|
||||
jnz Unequal ;
|
||||
Equal:
|
||||
mov EAX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
sub EAX,EDX ;
|
||||
pop ESI ;
|
||||
|
||||
pop EDI ;
|
||||
ret ;
|
||||
|
||||
UnequalQuad:
|
||||
mov EDX,[EDI-4] ;
|
||||
mov EAX,[ESI-4] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
jnz Unequal ;
|
||||
|
||||
shr EAX,16 ;
|
||||
|
||||
shr EDX,16 ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
Unequal:
|
||||
sbb EAX,EAX ;
|
||||
pop ESI ;
|
||||
|
||||
or EAX,1 ;
|
||||
pop EDI ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
int c;
|
||||
|
||||
//printf("adCmpChar()\n");
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
|
||||
if (!c)
|
||||
c = cast(int)a1.length - cast(int)a2.length;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) int _adCmpBit(Array a1, Array a2)
|
||||
{
|
||||
int len;
|
||||
uint i;
|
||||
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
ubyte *p1 = cast(ubyte*)a1.ptr;
|
||||
ubyte *p2 = cast(ubyte*)a2.ptr;
|
||||
uint n = len / 8;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (p1[i] != p2[i])
|
||||
break; // not equal
|
||||
}
|
||||
for (uint j = i * 8; j < len; j++)
|
||||
{ ubyte mask = cast(ubyte)(1 << j);
|
||||
int c;
|
||||
|
||||
c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
return cast(int)a1.length - cast(int)a2.length;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpBit unittest\n");
|
||||
|
||||
static bit[] a = [1,0,1,0,1];
|
||||
static bit[] b = [1,0,1];
|
||||
static bit[] c = [1,0,1,0,1,0,1];
|
||||
static bit[] d = [1,0,1,1,1];
|
||||
static bit[] e = [1,0,1,0,1];
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(a < c);
|
||||
assert(a <= c);
|
||||
assert(a < d);
|
||||
assert(a <= d);
|
||||
assert(a == e);
|
||||
assert(a <= e);
|
||||
assert(a >= e);
|
||||
}
|
||||
}
|
||||
@@ -143,11 +143,3 @@ void _d_main_args(uint n, char** args, ref char[][] res)
|
||||
res[i] = v[0 .. strlen(v)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ extern(C):
|
||||
|
||||
void exit(int);
|
||||
|
||||
void _d_assert(bool cond, uint line, char* msg)
|
||||
void _d_assert(bool cond, uint line, char[] msg)
|
||||
{
|
||||
if (!cond) {
|
||||
printf("Aborted(%u): %s\n", line, msg);
|
||||
printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
68
lphobos/internal/qsort2.d
Normal file
68
lphobos/internal/qsort2.d
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
/*
|
||||
* Placed into Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*
|
||||
* This is a public domain version of qsort.d.
|
||||
* All it does is call C's qsort(), but runs a little slower since
|
||||
* it needs to synchronize a global variable.
|
||||
*/
|
||||
|
||||
|
||||
//debug=qsort;
|
||||
|
||||
import std.c.stdlib;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void *ptr;
|
||||
}
|
||||
|
||||
private TypeInfo tiglobal;
|
||||
|
||||
extern (C) int cmp(void* p1, void* p2)
|
||||
{
|
||||
return tiglobal.compare(p1, p2);
|
||||
}
|
||||
|
||||
extern (C) long _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
synchronized
|
||||
{
|
||||
tiglobal = ti;
|
||||
std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ struct lldiv_t { long quot,rem; }
|
||||
|
||||
int system(char *);
|
||||
|
||||
pragma(LLVM_internal, "alloca")
|
||||
void *alloca(uint); ///
|
||||
|
||||
void *calloc(size_t, size_t); ///
|
||||
|
||||
@@ -3,23 +3,42 @@ module std.stdio;
|
||||
import std.traits;
|
||||
|
||||
void _writef(T)(T t) {
|
||||
static if(is(T: Object)) _writef(t.toString()); else
|
||||
static if(is(T==char)) printf("%c", t); else
|
||||
static if(is(T: char[])) printf("%.*s", t.length, t.ptr); else
|
||||
static if(isArray!(T)) {
|
||||
_writef('[');
|
||||
if (t.length) _writef(t[0]);
|
||||
for (int i=1; i<t.length; ++i) { _writef(','); _writef(t[i]); }
|
||||
_writef(']');
|
||||
} else
|
||||
static if(is(T: int)) printf("%i", t); else
|
||||
static if(is(T: real)) printf("%f", t); else
|
||||
static assert(false, "Cannot print "~T.stringof);
|
||||
static if (is(T == char)) {
|
||||
printf("%c", t);
|
||||
}
|
||||
else static if (is(T : char[])) {
|
||||
printf("%.*s", t.length, t.ptr);
|
||||
}
|
||||
else static if (is(T : long)) {
|
||||
printf("%ld", t);
|
||||
}
|
||||
else static if (is(T : ulong)) {
|
||||
printf("%lu", t);
|
||||
}
|
||||
else static if (is(T : real)) {
|
||||
printf("%f", t);
|
||||
}
|
||||
else static if (is(T : Object)) {
|
||||
_writef(t.toString());
|
||||
}
|
||||
else static if(isArray!(T)) {
|
||||
_writef('[');
|
||||
if (t.length) {
|
||||
_writef(t[0]);
|
||||
foreach(v; t[1..$]) {
|
||||
_writef(','); _writef(v);
|
||||
}
|
||||
}
|
||||
_writef(']');
|
||||
}
|
||||
else static assert(0, "Cannot writef:"~T.tostring);
|
||||
}
|
||||
|
||||
void writef(T...)(T t) {
|
||||
foreach (v; t) _writef(v);
|
||||
void writef(T...)(T t)
|
||||
{
|
||||
foreach(v;t) _writef(v);
|
||||
}
|
||||
void writefln(T...)(T t) {
|
||||
writef(t, "\n");
|
||||
void writefln(T...)(T t)
|
||||
{
|
||||
writef(t, '\n');
|
||||
}
|
||||
|
||||
@@ -1,15 +1,189 @@
|
||||
|
||||
// Written in the D programming language.
|
||||
|
||||
/**
|
||||
* Templates with which to extract information about
|
||||
* types at compile time.
|
||||
*
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdTraits
|
||||
* Copyright:
|
||||
* Public Domain
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* Tomasz Stachowiak (isStaticArray, isExpressionTuple)
|
||||
*/
|
||||
|
||||
module std.traits;
|
||||
struct TypeHolder(S, T...) {
|
||||
S _ReturnType;
|
||||
T _ParameterTypeTuple;
|
||||
|
||||
/***
|
||||
* Get the type of the return value from a function,
|
||||
* a pointer to function, or a delegate.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits;
|
||||
* int foo();
|
||||
* ReturnType!(foo) x; // x is declared as int
|
||||
* ---
|
||||
*/
|
||||
template ReturnType(alias dg)
|
||||
{
|
||||
alias ReturnType!(typeof(dg)) ReturnType;
|
||||
}
|
||||
TypeHolder!(S, T) *IFTI_gen(S, T...)(S delegate(T) dg) { return null; }
|
||||
TypeHolder!(S, T) *IFTI_gen(S, T...)(S function(T) dg) { return null; }
|
||||
template ParameterTypeTuple(T) {
|
||||
alias typeof(IFTI_gen(T.init)._ParameterTypeTuple) ParameterTypeTuple;
|
||||
|
||||
/** ditto */
|
||||
template ReturnType(dg)
|
||||
{
|
||||
static if (is(dg R == return))
|
||||
alias R ReturnType;
|
||||
else
|
||||
static assert(0, "argument has no return type");
|
||||
}
|
||||
template ReturnType(T) {
|
||||
alias typeof(IFTI_gen(T.init)._ReturnType) ReturnType;
|
||||
|
||||
/***
|
||||
* Get the types of the paramters to a function,
|
||||
* a pointer to function, or a delegate as a tuple.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits;
|
||||
* int foo(int, long);
|
||||
* void bar(ParameterTypeTuple!(foo)); // declares void bar(int, long);
|
||||
* void abc(ParameterTypeTuple!(foo)[1]); // declares void abc(long);
|
||||
* ---
|
||||
*/
|
||||
template ParameterTypeTuple(alias dg)
|
||||
{
|
||||
alias ParameterTypeTuple!(typeof(dg)) ParameterTypeTuple;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
template ParameterTypeTuple(dg)
|
||||
{
|
||||
static if (is(dg P == function))
|
||||
alias P ParameterTypeTuple;
|
||||
else static if (is(dg P == delegate))
|
||||
alias ParameterTypeTuple!(P) ParameterTypeTuple;
|
||||
else static if (is(dg P == P*))
|
||||
alias ParameterTypeTuple!(P) ParameterTypeTuple;
|
||||
else
|
||||
static assert(0, "argument has no parameters");
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Get the types of the fields of a struct or class.
|
||||
* This consists of the fields that take up memory space,
|
||||
* excluding the hidden fields like the virtual function
|
||||
* table pointer.
|
||||
*/
|
||||
|
||||
template FieldTypeTuple(S)
|
||||
{
|
||||
static if (is(S == struct) || is(S == class))
|
||||
alias typeof(S.tupleof) FieldTypeTuple;
|
||||
else
|
||||
static assert(0, "argument is not struct or class");
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Get a TypeTuple of the base class and base interfaces of
|
||||
* this class or interface.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits, std.typetuple, std.stdio;
|
||||
* interface I { }
|
||||
* class A { }
|
||||
* class B : A, I { }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* alias BaseTypeTuple!(B) TL;
|
||||
* writefln(typeid(TL)); // prints: (A,I)
|
||||
* }
|
||||
* ---
|
||||
*/
|
||||
|
||||
template BaseTypeTuple(A)
|
||||
{
|
||||
static if (is(A P == super))
|
||||
alias P BaseTypeTuple;
|
||||
else
|
||||
static assert(0, "argument is not a class or interface");
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
interface I { }
|
||||
class A { }
|
||||
class B : A, I { }
|
||||
|
||||
alias BaseTypeTuple!(B) TL;
|
||||
assert(TL.length == 2);
|
||||
assert(is (TL[0] == A));
|
||||
assert(is (TL[1] == I));
|
||||
}
|
||||
|
||||
/* *******************************************
|
||||
*/
|
||||
template isStaticArray_impl(T)
|
||||
{
|
||||
const T inst = void;
|
||||
|
||||
static if (is(typeof(T.length)))
|
||||
{
|
||||
static if (!is(typeof(T) == typeof(T.init)))
|
||||
{ // abuses the fact that int[5].init == int
|
||||
static if (is(T == typeof(T[0])[inst.length]))
|
||||
{ // sanity check. this check alone isn't enough because dmd complains about dynamic arrays
|
||||
const bool res = true;
|
||||
}
|
||||
else
|
||||
const bool res = false;
|
||||
}
|
||||
else
|
||||
const bool res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool res = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Detect whether type T is a static array.
|
||||
*/
|
||||
template isStaticArray(T)
|
||||
{
|
||||
const bool isStaticArray = isStaticArray_impl!(T).res;
|
||||
}
|
||||
|
||||
|
||||
static assert (isStaticArray!(int[51]));
|
||||
static assert (isStaticArray!(int[][2]));
|
||||
//static assert (isStaticArray!(char[][int][11]));
|
||||
static assert (!isStaticArray!(int[]));
|
||||
//static assert (!isStaticArray!(int[char]));
|
||||
static assert (!isStaticArray!(int[1][]));
|
||||
|
||||
template isArray(T)
|
||||
{
|
||||
const bool isArray=false;
|
||||
}
|
||||
template isArray(T: T[])
|
||||
{
|
||||
const bool isArray=true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the tuple T is an expression tuple.
|
||||
*/
|
||||
template isExpressionTuple(T ...)
|
||||
{
|
||||
static if (is(void function(T)))
|
||||
const bool isExpressionTuple = false;
|
||||
else
|
||||
const bool isExpressionTuple = true;
|
||||
}
|
||||
template isArray(T) { const bool isArray=false; }
|
||||
template isArray(T: T[]) { const bool isArray=true; }
|
||||
|
||||
Reference in New Issue
Block a user