diff gen/functions.cpp @ 719:7261ff0f95ff

Implemented first class delegates. closes #101
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 22 Oct 2008 21:50:08 +0200
parents 30b42a283c8e
children e177ae483f8e
line wrap: on
line diff
--- a/gen/functions.cpp	Wed Oct 22 20:00:57 2008 +0200
+++ b/gen/functions.cpp	Wed Oct 22 21:50:08 2008 +0200
@@ -123,15 +123,24 @@
 
         const LLType* at = DtoType(argT);
 
+        // handle lazy args
+        if (arg->storageClass & STClazy)
+        {
+            Logger::println("lazy param");
+            TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
+            TypeDelegate *ltd = new TypeDelegate(ltf);
+            at = DtoType(ltd);
+            paramvec.push_back(at);
+        }
         // opaque types need special handling
-        if (llvm::isa<llvm::OpaqueType>(at)) {
+        else if (llvm::isa<llvm::OpaqueType>(at)) {
             Logger::println("opaque param");
             assert(argT->ty == Tstruct || argT->ty == Tclass);
             paramvec.push_back(getPtrToType(at));
         }
-        // structs and delegates are passed as a reference, but by value
-        else if (argT->ty == Tstruct || argT->ty == Tdelegate) {
-            Logger::println("struct/sarray param");
+        // structs are passed as a reference, but by value
+        else if (argT->ty == Tstruct) {
+            Logger::println("struct param");
             if (!refOrOut)
                 arg->llvmAttrs |= llvm::Attribute::ByVal;
             paramvec.push_back(getPtrToType(at));
@@ -156,23 +165,6 @@
                 arg->llvmAttrs |= ea;
             paramvec.push_back(at);
         }
-
-        // handle lazy args
-        if (arg->storageClass & STClazy)
-        {
-            if (Logger::enabled())
-                Logger::cout() << "for lazy got: " << *paramvec.back() << '\n';
-
-            TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
-            TypeDelegate *ltd = new TypeDelegate(ltf);
-            at = getPtrToType(DtoType(ltd));
-
-            if (Logger::enabled())
-                Logger::cout() << "lazy updated to: " << *at << '\n';
-
-            paramvec.back() = at;
-            // lazy doesn't need byval as the delegate is not visible to the user
-        }
     }
 
     // construct function type
@@ -652,13 +644,14 @@
             IrLocal* irloc = vd->ir.irLocal;
             assert(irloc);
 
-            bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
+            bool refout = vd->storage_class & (STCref | STCout);
+            bool lazy = vd->storage_class & STClazy;
 
-            if (refoutlazy)
+            if (refout)
             {
                 continue;
             }
-            else if (DtoIsPassedByRef(vd->type))
+            else if (!lazy && DtoIsPassedByRef(vd->type))
             {
                 LLValue* vdirval = irloc->value;
                 if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr()))
@@ -875,6 +868,13 @@
         else
             arg = new DImValue(argexp->type, arg->getRVal());
     }
+    // lazy arg
+    else if (fnarg && (fnarg->storageClass & STClazy))
+    {
+        assert(argexp->type->toBasetype()->ty == Tdelegate);
+        assert(!arg->isLVal());
+        return arg;
+    }
     // byval arg, but expr has no storage yet
     else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
     {