changeset 96:ce7ed8f59b99 trunk

[svn r100] Moved test/ray.d to demos/ray.d. Cleanups.
author lindquist
date Mon, 12 Nov 2007 07:58:44 +0100
parents 71b8fecdae38
children c4e161556a21
files demos/ray.d dmd/aggregate.h gen/arrays.cpp gen/dvalue.cpp gen/elem.cpp gen/elem.h gen/statements.cpp gen/structs.cpp gen/symbol.h gen/tocsym.cpp gen/todebug.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp gen/typinf.cpp test/ray.d
diffstat 16 files changed, 240 insertions(+), 376 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/ray.d	Mon Nov 12 07:58:44 2007 +0100
@@ -0,0 +1,118 @@
+//import std.stdio, std.math, std.string;
+//import tools.base;
+
+int atoi(char[] s) {
+    int i, fac=1;
+    bool neg = (s.length) && (s[0] == '-');
+    char[] a = neg ? s[1..$] : s;
+    foreach_reverse(c; a) {
+        i += (c-'0') * fac;
+        fac *= 10;
+    }
+    return !neg ? i : -i;
+}
+
+pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
+double sqrt(double val);
+
+double delta;
+static this() { delta=sqrt(real.epsilon); }
+
+struct Vec {
+  double x, y, z;
+  Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); }
+  Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); }
+  Vec opMul(double a) { return Vec(x*a, y*a, z*a); }
+  double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; }
+  Vec unitise() { return opMul(1.0/sqrt(dot(*this))); }
+}
+
+struct Pair(T, U) { T first; U second; }
+typedef Pair!(double, Vec) Hit;
+
+struct Ray { Vec orig, dir; }
+
+class Scene {
+  //abstract void intersect(ref Hit, ref Ray);
+  void intersect(ref Hit, ref Ray) {}
+}
+
+class Sphere : Scene {
+  Vec center;
+  double radius;
+  //mixin This!("center, radius");
+  this(ref Vec c, double r)
+  {
+    center = c;
+    radius = r;
+  }
+  double ray_sphere(ref Ray ray) {
+    auto v = center - ray.orig, b = v.dot(ray.dir), disc=b*b - v.dot(v) + radius*radius;
+    if (disc < 0) return double.infinity;
+    auto d = sqrt(disc), t2 = b + d;
+    if (t2 < 0) return double.infinity;
+    auto t1 = b - d;
+    return (t1 > 0 ? t1 : t2);
+  }
+  void intersect(ref Hit hit, ref Ray ray) {
+    auto lambda = ray_sphere(ray);
+    if (lambda < hit.first)
+      hit = Hit(lambda, (ray.orig + lambda*ray.dir - center).unitise);
+  }
+}
+
+class Group : Scene {
+  Sphere bound;
+  Scene[] children;
+  //mixin This!("bound, children");
+  this (Sphere s, Scene[] c)
+  {
+    bound = s;
+    children = c;
+  }
+  void intersect(ref Hit hit, ref Ray ray) {
+    auto l = bound.ray_sphere(ray);
+    if (l < hit.first) foreach (child; children) child.intersect(hit, ray);
+  }
+}
+
+double ray_trace(ref Vec light, ref Ray ray, Scene s) {
+  auto hit=Hit(double.infinity, Vec(0, 0, 0));
+  s.intersect(hit, ray);
+  if (hit.first == double.infinity) return 0.0;
+  auto g = hit.second.dot(light);
+  if (g >= 0) return 0.0;
+  auto p = ray.orig + ray.dir*hit.first + hit.second*delta;
+  auto hit2=Hit(double.infinity, Vec(0, 0, 0));
+  s.intersect(hit2, Ray(p, light*-1.0));
+  return (hit2.first < double.infinity ? 0 : -g);
+}
+
+Scene create(int level, ref Vec c, double r) {
+  auto s = new Sphere(c, r);
+  if (level == 1) return s;
+  Scene[] children;
+  children ~= s;
+  double rn = 3*r/sqrt(12.0);
+  for (int dz=-1; dz<=1; dz+=2)
+    for (int dx=-1; dx<=1; dx+=2)
+      children~=create(level-1, c + Vec(dx, 1, dz)*rn, r/2);
+  return new Group(new Sphere(c, 3*r), children);
+}
+
+void main(string[] args) {
+  int level = (args.length==3 ? args[1].atoi() : 9),
+    n = (args.length==3 ? args[2].atoi() : 512), ss = 4;
+  auto light = Vec(-1, -3, 2).unitise();
+  auto s=create(level, Vec(0, -1, 0), 1);
+  printf("P5\n%d %d\n255", n, n);
+  for (int y=n-1; y>=0; --y)
+    for (int x=0; x<n; ++x) {
+      double g=0;
+      for (int d=0; d<ss*ss; ++d) {
+        auto dir=Vec(x+(d%ss)*1.0/ss-n/2.0, y+(d/ss)*1.0/ss-n/2.0, n).unitise();
+    g += ray_trace(light, Ray(Vec(0, 0, -4), dir), s);
+      }
+      printf("%c", cast(ubyte)(0.5 + 255.0 * g / (ss*ss)));
+    }
+}
--- a/dmd/aggregate.h	Mon Nov 12 06:43:33 2007 +0100
+++ b/dmd/aggregate.h	Mon Nov 12 07:58:44 2007 +0100
@@ -101,7 +101,7 @@
     Symbol *toInitializer();
 
     bool llvmInProgress;
-    llvm::Type* llvmType;
+    const llvm::Type* llvmType;
     llvm::Constant* llvmVtbl;
     llvm::ConstantStruct* llvmConstVtbl;
     llvm::Constant* llvmInitZ;
--- a/gen/arrays.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/arrays.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -42,7 +42,7 @@
 const llvm::ArrayType* DtoStaticArrayType(Type* t)
 {
     if (t->llvmType)
-        return llvm::cast<llvm::ArrayType>(t->llvmType);
+        return isaArray(t->llvmType);
 
     assert(t->ty == Tsarray);
     assert(t->next);
@@ -68,7 +68,7 @@
     new llvm::StoreInst(zerolen, len, gIR->scopebb());
 
     llvm::Value* ptr = DtoGEPi(v,0,1,"tmp",gIR->scopebb());
-    const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(ptr->getType()->getContainedType(0));
+    const llvm::PointerType* pty = isaPointer(ptr->getType()->getContainedType(0));
     llvm::Value* nullptr = llvm::ConstantPointerNull::get(pty);
     new llvm::StoreInst(nullptr, ptr, gIR->scopebb());
 }
@@ -93,12 +93,12 @@
     else
     {
         Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
-        if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
+        const llvm::ArrayType* arrty = isaArray(src->getType()->getContainedType(0));
+        if (!arrty)
         {
             Logger::cout() << "invalid: " << *src << '\n';
             assert(0);
         }
-        const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
         llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
 
         llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
@@ -115,16 +115,16 @@
 
 void DtoArrayInit(llvm::Value* l, llvm::Value* r)
 {
-    const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType());
+    const llvm::PointerType* ptrty = isaPointer(l->getType());
     const llvm::Type* t = ptrty->getContainedType(0);
-    const llvm::ArrayType* arrty = llvm::dyn_cast<llvm::ArrayType>(t);
+    const llvm::ArrayType* arrty = isaArray(t);
     if (arrty)
     {
         llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb());
         llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
         DtoArrayInit(ptr, dim, r);
     }
-    else if (llvm::isa<llvm::StructType>(t))
+    else if (isaStruct(t))
     {
         llvm::Value* dim = DtoLoad(DtoGEPi(l, 0,0, "tmp"));
         llvm::Value* ptr = DtoLoad(DtoGEPi(l, 0,1, "tmp"));
@@ -140,9 +140,9 @@
 
 static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
 {
-    if (llvm::isa<llvm::ArrayType>(pt)) {
-        size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
-        size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
+    if (const llvm::ArrayType* arrty = isaArray(pt)) {
+        size_t n = checkRectArrayInit(arrty->getElementType(), finalty);
+        size_t ne = arrty->getNumElements();
         if (n) return n * ne;
         return ne;
     }
@@ -159,12 +159,12 @@
     const llvm::Type* finalTy;
     if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
         assert(finalTy == t);
-        llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
+        llvm::Constant* c = isaConstant(dim);
         assert(c);
         dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
         ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
     }
-    else if (llvm::isa<llvm::StructType>(t)) {
+    else if (isaStruct(t)) {
         assert(0);
     }
     else {
@@ -178,7 +178,7 @@
 
     const char* funcname = NULL;
 
-    if (llvm::isa<llvm::PointerType>(t)) {
+    if (isaPointer(t)) {
         funcname = "_d_array_init_pointer";
 
         const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
@@ -227,15 +227,14 @@
 void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
 {
     Logger::cout() << "DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n";
-    const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0));
-    //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType());
-    
+    const llvm::StructType* st = isaStruct(arr->getType()->getContainedType(0));
+
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
     llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
     new llvm::StoreInst(dim, arrdim, gIR->scopebb());
-    
+
     llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
     new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
 }
@@ -336,25 +335,25 @@
         size_t elembsz = gTargetData->getTypeSize(ret->getType());
         llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
 
-        if (llvm::isa<llvm::ConstantInt>(e->len)) {
-            sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast<llvm::Constant>(e->len));
+        if (isaConstantInt(e->len)) {
+            sz = llvm::ConstantExpr::getMul(elemsz, isaConstant(e->len));
         }
         else {
             sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb());
         }
     }
-    else if (llvm::isa<llvm::ArrayType>(t)) {
+    else if (isaArray(t)) {
         ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
 
         size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
         llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
 
-        size_t numelements = llvm::cast<llvm::ArrayType>(t)->getNumElements();
+        size_t numelements = isaArray(t)->getNumElements();
         llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
 
         sz = llvm::ConstantExpr::getMul(elemsz, nelems);
     }
-    else if (llvm::isa<llvm::StructType>(t)) {
+    else if (isaStruct(t)) {
         ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb());
         ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
 
@@ -560,9 +559,9 @@
     assert(fn);
 
     assert(l->getType() == r->getType());
-    assert(llvm::isa<llvm::PointerType>(l->getType()));
+    assert(isaPointer(l->getType()));
     const llvm::Type* arrty = l->getType()->getContainedType(0);
-    assert(llvm::isa<llvm::ArrayType>(arrty));
+    assert(isaArray(arrty));
     
     llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
     llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
@@ -591,10 +590,9 @@
 
     Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n';
     assert(l->getType() == r->getType());
-    assert(llvm::isa<llvm::PointerType>(l->getType()));
-    const llvm::Type* arrty = l->getType()->getContainedType(0);
-    assert(llvm::isa<llvm::StructType>(arrty));
-    const llvm::StructType* structType = llvm::cast<llvm::StructType>(arrty);
+    assert(isaPointer(l->getType()));
+    const llvm::StructType* structType = isaStruct(l->getType()->getContainedType(0));
+    assert(structType);
     const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0);
 
     std::vector<const llvm::Type*> arrTypes;
@@ -605,7 +603,7 @@
     llvm::Value* llmem = l;
     llvm::Value* rrmem = r;
 
-    if (arrty != arrType) {
+    if (structType != arrType) {
         llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
 
         llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
@@ -665,7 +663,7 @@
         llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
 
         llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
-        const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(lp->getType());
+        const llvm::PointerType* pty = isaPointer(lp->getType());
         llvm::Value* rp = llvm::ConstantPointerNull::get(pty);
         llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
 
@@ -691,10 +689,10 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
 {
-    assert(llvm::isa<llvm::ArrayType>(t));
-    const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
+    const llvm::ArrayType* at = isaArray(t);
+    assert(at);
 
-    if (llvm::isa<llvm::ArrayType>(at->getElementType()))
+    if (isaArray(at->getElementType()))
     {
         c = DtoConstStaticArray(at->getElementType(), c);
     }
@@ -721,7 +719,7 @@
     else if (t->ty == Tsarray) {
         llvm::Value* rv = v->getRVal();
         Logger::cout() << "casting: " << *rv << '\n';
-        const llvm::ArrayType* t = llvm::cast<llvm::ArrayType>(rv->getType()->getContainedType(0));
+        const llvm::ArrayType* t = isaArray(rv->getType()->getContainedType(0));
         return DtoConstSize_t(t->getNumElements());
     }
     assert(0);
--- a/gen/dvalue.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/dvalue.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -53,7 +53,7 @@
     else {
         if (rval) return rval;
         Logger::cout() << "val: " << *val << '\n';
-        if (llvm::isa<llvm::Argument>(val)) {
+        if (isaArgument(val)) {
             if (var && (var->isRef() || var->isOut()))
                 return DtoLoad(val);
         }
--- a/gen/elem.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
-#include <iostream>
-
-#include "gen/llvm.h"
-
-#include "gen/elem.h"
-#include "gen/irstate.h"
-#include "gen/logger.h"
-#include "gen/dvalue.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem::elem(Expression* e)
-{
-    exp = e;
-
-    mem = 0;
-    val = 0;
-    arg = 0;
-
-    type = NONE;
-    inplace = false;
-    field = false;
-    callconv = (unsigned)-1;
-    isthis = false;
-    istypeinfo = false;
-    temp = false;
-
-    vardecl = 0;
-    funcdecl = 0;
-
-    dvalue = 0;
-}
-
-elem::~elem()
-{
-    delete dvalue;
-}
-
-llvm::Value* elem::getValue()
-{
-    if (dvalue && !dvalue->isSlice()) {
-        Logger::println("HAS DVALUE");
-        return dvalue->getRVal();
-    }
-
-    assert(val || mem);
-    switch(type)
-    {
-    case NONE:
-        assert(0 && "type == NONE");
-        break;
-
-    case VAR:
-    case REF:
-    case ARRAYLEN:
-        if (val) {
-            return val;
-        }
-        else {
-            if (!llvm::isa<llvm::PointerType>(mem->getType()))
-            {
-                Logger::cout() << "unexpected type: " << *mem->getType() << '\n';
-                assert(0);
-            }
-            const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(mem->getType());
-            if (!pt->getElementType()->isFirstClassType()) {
-                return mem;
-            }
-            else {
-                return gIR->ir->CreateLoad(mem, "tmp");
-            }
-        }
-
-    case VAL:
-    case NUL:
-    case FUNC:
-    case CONST:
-    case SLICE:
-        return val ? val : mem;
-    }
-    assert(0 && "type == invalid value");
-    return 0;
-}
-*/
--- a/gen/elem.h	Mon Nov 12 06:43:33 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#ifndef LLVMDC_GEN_ELEM_H
-#define LLVMDC_GEN_ELEM_H
-
-#include "dvalue.h"
-typedef DValue elem;
-
-/*
-
-#include "root.h"
-#include "declaration.h"
-#include "aggregate.h"
-
-struct DValue;
-
-// represents a value. be it a constant literal, a variable etc.
-// maintains all the information for doing load/store appropriately
-struct elem : Object
-{
-    enum {
-        NONE,
-        VAR,
-        VAL,
-        FUNC,
-        CONST,
-        NUL,
-        REF,
-        SLICE,
-        ARRAYLEN
-    };
-
-public:
-    elem(Expression* e);
-    virtual ~elem();
-
-    Expression* exp;
-
-    llvm::Value* mem;
-    llvm::Value* val;
-    llvm::Value* arg;
-    int type;
-    bool inplace;
-    bool field;
-    unsigned callconv;
-    bool isthis;
-    bool istypeinfo;
-    bool temp;
-
-    VarDeclaration* vardecl;
-    FuncDeclaration* funcdecl;
-
-    llvm::Value* getValue();
-    //llvm::Value* getMemory();
-
-    DValue* dvalue;
-
-    bool isNull()   {return !(mem || val);}
-};
-
-*/
-
-#endif // LLVMDC_GEN_ELEM_H
--- a/gen/statements.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/statements.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -10,13 +10,11 @@
 
 #include "total.h"
 #include "init.h"
-#include "symbol.h"
 #include "mtype.h"
 #include "hdrgen.h"
 #include "port.h"
 
 #include "gen/irstate.h"
-#include "gen/elem.h"
 #include "gen/logger.h"
 #include "gen/tollvm.h"
 #include "gen/runtime.h"
@@ -539,8 +537,9 @@
         // get the case value
         DValue* e = cs->exp->toElem(p);
         DConstValue* ce = e->isConst();
-        assert(ce && llvm::isa<llvm::ConstantInt>(ce->c));
-        llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(ce->c);
+        assert(ce);
+        llvm::ConstantInt* ec = isaConstantInt(ce->c);
+        assert(ec);
         delete e;
 
         // create the case bb with a nice label
@@ -675,9 +674,10 @@
     {
         Logger::println("foreach over static array");
         val = aggrval->getRVal();
-        assert(llvm::isa<llvm::PointerType>(val->getType()));
-        assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
-        size_t nelems = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
+        assert(isaPointer(val->getType()));
+        const llvm::ArrayType* arrty = isaArray(val->getType()->getContainedType(0));
+        assert(arrty);
+        size_t nelems = arrty->getNumElements();
         assert(nelems > 0);
         niters = llvm::ConstantInt::get(keytype,nelems,false);
     }
@@ -688,13 +688,6 @@
             Logger::println("foreach over slice");
             niters = slice->len;
             assert(niters);
-            if (llvm::isa<llvm::ConstantInt>(niters)) {
-                llvm::ConstantInt* ci = llvm::cast<llvm::ConstantInt>(niters);
-                Logger::println("const num iters: %u", ci);
-            }
-            else {
-                Logger::cout() << "numiters: " << *niters <<'\n';
-            }
             val = slice->ptr;
             assert(val);
         }
--- a/gen/structs.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/structs.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -78,7 +78,7 @@
     Logger::println("DtoConstStructInitializer: %s", si->toChars());
     LOG_SCOPE;
 
-    const llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
+    const llvm::StructType* structtype = isaStruct(si->ad->llvmType);
     Logger::cout() << "llvm struct type: " << *structtype << '\n';
 
     assert(si->value.dim == si->vars.dim);
--- a/gen/tocsym.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/tocsym.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -21,7 +21,6 @@
 #include "init.h"
 #include "attrib.h"
 #include "lexer.h"
-#include "symbol.h"
 
 /********************************* SymbolDeclaration ****************************/
 
--- a/gen/todebug.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/todebug.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -47,7 +47,7 @@
     }
     */
     std::vector<const llvm::Type*> elems(2, Ty(Int32Ty));
-    const llvm::StructType* t = llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
+    const llvm::StructType* t = isaStruct(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
 
     /*
     %llvm.dbg.compile_units       = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 17 } ;; DW_TAG_compile_unit
@@ -101,11 +101,11 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
 const llvm::StructType* GetDwarfCompileUnitType() {
-    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.compile_unit.type"));
+    return isaStruct(gIR->module->getTypeByName("llvm.dbg.compile_unit.type"));
 }
 
 const llvm::StructType* GetDwarfSubProgramType() {
-    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.subprogram.type"));
+    return isaStruct(gIR->module->getTypeByName("llvm.dbg.subprogram.type"));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/toir.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/toir.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -16,13 +16,11 @@
 
 #include "total.h"
 #include "init.h"
-#include "symbol.h"
 #include "mtype.h"
 #include "hdrgen.h"
 #include "port.h"
 
 #include "gen/irstate.h"
-#include "gen/elem.h"
 #include "gen/logger.h"
 #include "gen/tollvm.h"
 #include "gen/runtime.h"
@@ -249,7 +247,7 @@
     Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     const llvm::Type* t = DtoType(type);
-    if (llvm::isa<llvm::PointerType>(t)) {
+    if (isaPointer(t)) {
         Logger::println("pointer");
         llvm::Constant* i = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)value,false);
         return llvm::ConstantExpr::getIntToPtr(i, t);
@@ -305,7 +303,7 @@
     LOG_SCOPE;
     const llvm::Type* t = DtoType(type);
     if (type->ty == Tarray) {
-        assert(llvm::isa<llvm::StructType>(t));
+        assert(isaStruct(t));
         return llvm::ConstantAggregateZero::get(t);
     }
     else {
@@ -752,11 +750,11 @@
 
     /*
     llvm::Value* left = l->getValue();
-    if (llvm::isa<llvm::PointerType>(left->getType()))
+    if (isaPointer(left->getType()))
         left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb());
 
     llvm::Value* right = r->getValue();
-    if (llvm::isa<llvm::PointerType>(right->getType()))
+    if (isaPointer(right->getType()))
         right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb());
 
     e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb());
@@ -765,7 +763,7 @@
     const llvm::Type* totype = DtoType(type);
     if (e->val->getType() != totype) {
         assert(0);
-        assert(llvm::isa<llvm::PointerType>(e->val->getType()));
+        assert(isaPointer(e->val->getType()));
         assert(llvm::isa<llvm::IntegerType>(totype));
         e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb());
     }
@@ -1104,6 +1102,10 @@
             const llvm::Type* llt = DtoType(type);
             if (DtoIsPassedByRef(t))
                 llt = llvm::PointerType::get(llt);
+            // TODO
+            if (strcmp(global.params.llvmArch, "x86") != 0) {
+                warning("va_arg for C variadic functions is broken for anything but x86");
+            }
             return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
         }
         else if (fndecl->llvmInternal == LLVMalloca) {
@@ -1136,10 +1138,10 @@
         llfnty = llvm::cast<llvm::FunctionType>(funcval->getType());
     }
     // pointer to something
-    else if (llvm::isa<llvm::PointerType>(funcval->getType())) {
+    else if (isaPointer(funcval->getType())) {
         // pointer to function pointer - I think this not really supposed to happen, but does :/
         // seems like sometimes we get a func* other times a func**
-        if (llvm::isa<llvm::PointerType>(funcval->getType()->getContainedType(0))) {
+        if (isaPointer(funcval->getType()->getContainedType(0))) {
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
         }
         // function pointer
@@ -1148,7 +1150,7 @@
             llfnty = llvm::cast<llvm::FunctionType>(funcval->getType()->getContainedType(0));
         }
         // struct pointer - delegate
-        else if (llvm::isa<llvm::StructType>(funcval->getType()->getContainedType(0))) {
+        else if (isaStruct(funcval->getType()->getContainedType(0))) {
             funcval = DtoGEP(funcval,zero,one,"tmp",p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
             const llvm::Type* ty = funcval->getType()->getContainedType(0);
@@ -1178,7 +1180,7 @@
         if (topexp && topexp->e2 == this) {
             assert(topexp->v);
             llvm::Value* tlv = topexp->v->getLVal();
-            assert(llvm::isa<llvm::StructType>(tlv->getType()->getContainedType(0)));
+            assert(isaStruct(tlv->getType()->getContainedType(0)));
             llargs[j] = tlv;
             if (DtoIsPassedByRef(tf->next)) {
                 isInPlace = true;
@@ -1262,7 +1264,7 @@
             for (unsigned i=0; i<vtype->getNumElements(); ++i)
                 p->ir->CreateStore(vvalues[i], DtoGEPi(mem,0,i,"tmp"));
 
-            //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j)));
+            //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(isaPointer(llfnty->getParamType(j)));
             assert(Type::typeinfo->llvmInitZ);
             const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType());
             Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
@@ -1448,8 +1450,8 @@
                 llvm::Value* uval = u->getRVal();
                 if (fromtype->ty == Tsarray) {
                     Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
-                    assert(llvm::isa<llvm::PointerType>(uval->getType()));
-                    const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(uval->getType()->getContainedType(0));
+                    assert(isaPointer(uval->getType()));
+                    const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
                     rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
                     rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
                     rval = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb());
@@ -2479,7 +2481,7 @@
     else {
         llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
         if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) {
-            r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
+            r = llvm::ConstantPointerNull::get(isaPointer(l->getType()));
         }
         Logger::cout() << "l = " << *l << " r = " << *r << '\n';
         eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
@@ -2660,7 +2662,7 @@
     }
 
     llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb());
-    const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(context->getType()->getContainedType(0));
+    const llvm::PointerType* pty = isaPointer(context->getType()->getContainedType(0));
     llvm::Value* llvmNested = p->func().decl->llvmNested;
     if (llvmNested == NULL) {
         llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty);
@@ -2709,8 +2711,8 @@
             mem = p->topexp()->v->getLVal();
         }
         assert(mem);
-        if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
-            !llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
+        if (!isaPointer(mem->getType()) ||
+            !isaArray(mem->getType()->getContainedType(0)))
         {
             assert(ty->ty == Tarray);
             // we need to give this array literal storage
@@ -2748,8 +2750,8 @@
 
     const llvm::Type* t = DtoType(type);
     Logger::cout() << "array literal has llvm type: " << *t << '\n';
-    assert(llvm::isa<llvm::ArrayType>(t));
-    const llvm::ArrayType* arrtype = llvm::cast<llvm::ArrayType>(t);
+    assert(isaArray(t));
+    const llvm::ArrayType* arrtype = isaArray(t);
 
     assert(arrtype->getNumElements() == elements->dim);
     std::vector<llvm::Constant*> vals(elements->dim, NULL);
@@ -2851,7 +2853,7 @@
 
     assert(DtoDType(type)->ty == Tstruct);
     const llvm::Type* t = DtoType(type);
-    const llvm::StructType* st = llvm::cast<llvm::StructType>(t);
+    const llvm::StructType* st = isaStruct(t);
     return llvm::ConstantStruct::get(st,vals);
 }
 
@@ -3130,7 +3132,7 @@
 int AsmStatement::comeFrom()
 {
     assert(0);
-    return FALSE;
+    return 0;
 }
 
 void
--- a/gen/tollvm.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/tollvm.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -259,11 +259,11 @@
             arg->llvmCopy = true;
 
         const llvm::Type* at = DtoType(argT);
-        if (llvm::isa<llvm::StructType>(at)) {
+        if (isaStruct(at)) {
             Logger::println("struct param");
             paramvec.push_back(llvm::PointerType::get(at));
         }
-        else if (llvm::isa<llvm::ArrayType>(at)) {
+        else if (isaArray(at)) {
             Logger::println("sarray param");
             assert(argT->ty == Tsarray);
             //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
@@ -271,14 +271,9 @@
         }
         else if (llvm::isa<llvm::OpaqueType>(at)) {
             Logger::println("opaque param");
-            if (argT->ty == Tstruct || argT->ty == Tclass)
-                paramvec.push_back(llvm::PointerType::get(at));
-            else
-            assert(0);
+            assert(argT->ty == Tstruct || argT->ty == Tclass);
+            paramvec.push_back(llvm::PointerType::get(at));
         }
-        /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
-            paramvec.push_back(llvm::PointerType::get(at));
-        }*/
         else {
             if (!arg->llvmCopy) {
                 Logger::println("ref param");
@@ -346,7 +341,7 @@
             Logger::print("isMember = this is: %s\n", ad->type->toChars());
             thisty = DtoType(ad->type);
             Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
+            if (isaStruct(thisty) || thisty == gIR->topstruct().recty.get())
                 thisty = llvm::PointerType::get(thisty);
         }
         else
@@ -609,7 +604,7 @@
             return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb());
         }
     }
-    else if (llvm::isa<llvm::PointerType>(t)) {
+    else if (isaPointer(t)) {
         const llvm::Type* st = DtoSize_t();
         llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb());
         llvm::Value* zero = llvm::ConstantInt::get(st, 0, false);
@@ -880,7 +875,7 @@
     else
     assert(0);
 
-    llvm::Function* func = llvm::cast_or_null<llvm::Function>(fn);
+    llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
     assert(func);
     assert(func->isIntrinsic());
     fdecl->llvmValue = func;
@@ -1099,7 +1094,7 @@
         else {
             llvm::Value* allocaInst = 0;
             llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
-            //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
+
             const llvm::Type* realtypell = DtoType(realtype);
             const llvm::PointerType* pty = llvm::PointerType::get(realtypell);
             if (argty == Tstruct) {
@@ -1397,7 +1392,7 @@
 
 bool DtoCanLoad(llvm::Value* ptr)
 {
-    if (llvm::isa<llvm::PointerType>(ptr->getType())) {
+    if (isaPointer(ptr->getType())) {
         return ptr->getType()->getContainedType(0)->isFirstClassType();
     }
     return false;
@@ -1413,16 +1408,31 @@
     return llvm::dyn_cast<llvm::PointerType>(v->getType());
 }
 
+const llvm::PointerType* isaPointer(const llvm::Type* t)
+{
+    return llvm::dyn_cast<llvm::PointerType>(t);
+}
+
 const llvm::ArrayType* isaArray(llvm::Value* v)
 {
     return llvm::dyn_cast<llvm::ArrayType>(v->getType());
 }
 
+const llvm::ArrayType* isaArray(const llvm::Type* t)
+{
+    return llvm::dyn_cast<llvm::ArrayType>(t);
+}
+
 const llvm::StructType* isaStruct(llvm::Value* v)
 {
     return llvm::dyn_cast<llvm::StructType>(v->getType());
 }
 
+const llvm::StructType* isaStruct(const llvm::Type* t)
+{
+    return llvm::dyn_cast<llvm::StructType>(t);
+}
+
 llvm::Constant* isaConstant(llvm::Value* v)
 {
     return llvm::dyn_cast<llvm::Constant>(v);
@@ -1433,6 +1443,11 @@
     return llvm::dyn_cast<llvm::ConstantInt>(v);
 }
 
+llvm::Argument* isaArgument(llvm::Value* v)
+{
+    return llvm::dyn_cast<llvm::Argument>(v);
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 
 bool DtoIsTemplateInstance(Dsymbol* s)
--- a/gen/tollvm.h	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/tollvm.h	Mon Nov 12 07:58:44 2007 +0100
@@ -77,10 +77,14 @@
 
 // llvm::dyn_cast wrappers
 const llvm::PointerType* isaPointer(llvm::Value* v);
+const llvm::PointerType* isaPointer(const llvm::Type* t);
 const llvm::ArrayType* isaArray(llvm::Value* v);
+const llvm::ArrayType* isaArray(const llvm::Type* t);
 const llvm::StructType* isaStruct(llvm::Value* v);
+const llvm::StructType* isaStruct(const llvm::Type* t);
 llvm::Constant* isaConstant(llvm::Value* v);
 llvm::ConstantInt* isaConstantInt(llvm::Value* v);
+llvm::Argument* isaArgument(llvm::Value* v);
 
 // basic operations
 void DtoAssign(DValue* lhs, DValue* rhs);
--- a/gen/toobj.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/toobj.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -32,7 +32,6 @@
 #include "scope.h"
 
 #include "gen/irstate.h"
-#include "gen/elem.h"
 #include "gen/logger.h"
 #include "gen/tollvm.h"
 #include "gen/arrays.h"
@@ -332,7 +331,7 @@
 
     Logger::println("doing struct fields");
 
-    llvm::StructType* structtype = 0;
+    const llvm::StructType* structtype = 0;
     std::vector<llvm::Constant*> fieldinits;
 
     if (gIR->topstruct().offsets.empty())
@@ -427,7 +426,7 @@
     {
         llvm::PATypeHolder& pa = gIR->topstruct().recty;
         llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = llvm::cast<llvm::StructType>(pa.get());
+        structtype = isaStruct(pa.get());
     }
 
     ts->llvmType = structtype;
@@ -587,13 +586,13 @@
         fieldinits.push_back(i->second.init);
     }
 
-    llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
+    const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
     // refine abstract types for stuff like: class C {C next;}
     if (gIR->topstruct().recty != 0)
     {
         llvm::PATypeHolder& pa = gIR->topstruct().recty;
         llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = llvm::cast<llvm::StructType>(pa.get());
+        structtype = isaStruct(pa.get());
     }
 
     ts->llvmType = structtype;
@@ -664,8 +663,8 @@
 
     // refine for final vtable type
     llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
-    svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
-    structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
+    svtbl_ty = isaStruct(pa.get());
+    structtype = isaStruct(gIR->topstruct().recty.get());
     ts->llvmType = structtype;
     llvmType = structtype;
 
@@ -793,7 +792,7 @@
                     _init = ts->sym->llvmInitZ;
                 }
                 // array single value init
-                else if (llvm::isa<llvm::ArrayType>(_type))
+                else if (isaArray(_type))
                 {
                     _init = DtoConstStaticArray(_type, _init);
                 }
@@ -833,19 +832,19 @@
         {
             if (t->ty == Tsarray)
             {
-                const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
+                const llvm::ArrayType* arrty = isaArray(_type);
                 uint64_t n = arrty->getNumElements();
                 std::vector<llvm::Constant*> vals(n,_init);
                 _init = llvm::ConstantArray::get(arrty, vals);
             }
             else if (t->ty == Tarray)
             {
-                assert(llvm::isa<llvm::StructType>(_type));
+                assert(isaStruct(_type));
                 _init = llvm::ConstantAggregateZero::get(_type);
             }
             else if (t->ty == Tstruct)
             {
-                const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
+                const llvm::StructType* structty = isaStruct(_type);
                 TypeStruct* ts = (TypeStruct*)t;
                 assert(ts);
                 assert(ts->sym);
--- a/gen/typinf.cpp	Mon Nov 12 06:43:33 2007 +0100
+++ b/gen/typinf.cpp	Mon Nov 12 07:58:44 2007 +0100
@@ -277,7 +277,7 @@
 
     llvm::Constant* initZ = base->llvmInitZ;
     assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+    const llvm::StructType* stype = isaStruct(initZ->getType());
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(initZ->getOperand(0));
@@ -287,7 +287,7 @@
     TypedefDeclaration *sd = tc->sym;
 
     // TypeInfo base
-    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
+    //const llvm::PointerType* basept = isaPointer(initZ->getOperand(1)->getType());
     //sinits.push_back(llvm::ConstantPointerNull::get(basept));
     Logger::println("generating base typeinfo");
     //sd->basetype = sd->basetype->merge();
@@ -341,7 +341,7 @@
 
     llvm::Constant* initZ = base->llvmInitZ;
     assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+    const llvm::StructType* stype = isaStruct(initZ->getType());
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(initZ->getOperand(0));
@@ -351,7 +351,7 @@
     EnumDeclaration *sd = tc->sym;
 
     // TypeInfo base
-    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
+    //const llvm::PointerType* basept = isaPointer(initZ->getOperand(1)->getType());
     //sinits.push_back(llvm::ConstantPointerNull::get(basept));
     Logger::println("generating base typeinfo");
     //sd->basetype = sd->basetype->merge();
@@ -403,7 +403,7 @@
 
     llvm::Constant* initZ = base->llvmInitZ;
     assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+    const llvm::StructType* stype = isaStruct(initZ->getType());
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(initZ->getOperand(0));
@@ -538,7 +538,7 @@
     ClassDeclaration* base = Type::typeinfostruct;
     base->toObjFile();
 
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
+    const llvm::StructType* stype = isaStruct(base->llvmType);
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(base->llvmVtbl);
@@ -609,7 +609,7 @@
 #endif
 
     Logger::println("************** B");
-    const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
+    const llvm::PointerType* ptty = isaPointer(stype->getElementType(3));
 
     s = search_function(sd, Id::tohash);
     fdx = s ? s->isFuncDeclaration() : NULL;
@@ -637,7 +637,7 @@
     for (int i = 0; i < 2; i++)
     {
         Logger::println("************** C %d", i);
-        ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
+        ptty = isaPointer(stype->getElementType(4+i));
         if (fdx)
         {
             fd = fdx->overloadExactMatch(tfeqptr);
@@ -662,7 +662,7 @@
     }
 
     Logger::println("************** D");
-    ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
+    ptty = isaPointer(stype->getElementType(6));
     s = search_function(sd, Id::tostring);
     fdx = s ? s->isFuncDeclaration() : NULL;
     if (fdx)
@@ -881,7 +881,7 @@
     inits.push_back(c);
 
     // build the initializer
-    const llvm::StructType* st = llvm::cast<llvm::StructType>(cinfo->llvmInitZ->getType());
+    const llvm::StructType* st = isaStruct(cinfo->llvmInitZ->getType());
     llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
     Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
 
--- a/test/ray.d	Mon Nov 12 06:43:33 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-//import std.stdio, std.math, std.string;
-//import tools.base;
-
-int atoi(char[] s) {
-    int i, fac=1;
-    bool neg = (s.length) && (s[0] == '-');
-    char[] a = neg ? s[1..$] : s;
-    foreach_reverse(c; a) {
-        i += (c-'0') * fac;
-        fac *= 10;
-    }
-    return !neg ? i : -i;
-}
-
-pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
-double sqrt(double val);
-
-double delta;
-static this() { delta=sqrt(real.epsilon); }
-
-struct Vec {
-  double x, y, z;
-  Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); }
-  Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); }
-  Vec opMul(double a) { return Vec(x*a, y*a, z*a); }
-  double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; }
-  Vec unitise() { return opMul(1.0/sqrt(dot(*this))); }
-}
-
-struct Pair(T, U) { T first; U second; }
-typedef Pair!(double, Vec) Hit;
-
-struct Ray { Vec orig, dir; }
-
-class Scene {
-  //abstract void intersect(ref Hit, ref Ray);
-  void intersect(ref Hit, ref Ray) {}
-}
-
-class Sphere : Scene {
-  Vec center;
-  double radius;
-  //mixin This!("center, radius");
-  this(ref Vec c, double r)
-  {
-    center = c;
-    radius = r;
-  }
-  double ray_sphere(ref Ray ray) {
-    auto v = center - ray.orig, b = v.dot(ray.dir), disc=b*b - v.dot(v) + radius*radius;
-    if (disc < 0) return double.infinity;
-    auto d = sqrt(disc), t2 = b + d;
-    if (t2 < 0) return double.infinity;
-    auto t1 = b - d;
-    return (t1 > 0 ? t1 : t2);
-  }
-  void intersect(ref Hit hit, ref Ray ray) {
-    auto lambda = ray_sphere(ray);
-    if (lambda < hit.first)
-      hit = Hit(lambda, (ray.orig + lambda*ray.dir - center).unitise);
-  }
-}
-
-class Group : Scene {
-  Sphere bound;
-  Scene[] children;
-  //mixin This!("bound, children");
-  this (Sphere s, Scene[] c)
-  {
-    bound = s;
-    children = c;
-  }
-  void intersect(ref Hit hit, ref Ray ray) {
-    auto l = bound.ray_sphere(ray);
-    if (l < hit.first) foreach (child; children) child.intersect(hit, ray);
-  }
-}
-
-double ray_trace(ref Vec light, ref Ray ray, Scene s) {
-  auto hit=Hit(double.infinity, Vec(0, 0, 0));
-  s.intersect(hit, ray);
-  if (hit.first == double.infinity) return 0.0;
-  auto g = hit.second.dot(light);
-  if (g >= 0) return 0.0;
-  auto p = ray.orig + ray.dir*hit.first + hit.second*delta;
-  auto hit2=Hit(double.infinity, Vec(0, 0, 0));
-  s.intersect(hit2, Ray(p, light*-1.0));
-  return (hit2.first < double.infinity ? 0 : -g);
-}
-
-Scene create(int level, ref Vec c, double r) {
-  auto s = new Sphere(c, r);
-  if (level == 1) return s;
-  Scene[] children;
-  children ~= s;
-  double rn = 3*r/sqrt(12.0);
-  for (int dz=-1; dz<=1; dz+=2)
-    for (int dx=-1; dx<=1; dx+=2)
-      children~=create(level-1, c + Vec(dx, 1, dz)*rn, r/2);
-  return new Group(new Sphere(c, 3*r), children);
-}
-
-void main(string[] args) {
-  int level = (args.length==3 ? args[1].atoi() : 9),
-    n = (args.length==3 ? args[2].atoi() : 512), ss = 4;
-  auto light = Vec(-1, -3, 2).unitise();
-  auto s=create(level, Vec(0, -1, 0), 1);
-  printf("P5\n%d %d\n255", n, n);
-  for (int y=n-1; y>=0; --y)
-    for (int x=0; x<n; ++x) {
-      double g=0;
-      for (int d=0; d<ss*ss; ++d) {
-        auto dir=Vec(x+(d%ss)*1.0/ss-n/2.0, y+(d/ss)*1.0/ss-n/2.0, n).unitise();
-    g += ray_trace(light, Ray(Vec(0, 0, -4), dir), s);
-      }
-      printf("%c", cast(ubyte)(0.5 + 255.0 * g / (ss*ss)));
-    }
-}