summary refs log tree commit diff stats
path: root/nim/semexprs.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/semexprs.pas')
-rwxr-xr-xnim/semexprs.pas59
1 files changed, 41 insertions, 18 deletions
diff --git a/nim/semexprs.pas b/nim/semexprs.pas
index 43eb9ac6f..91c909dfd 100755
--- a/nim/semexprs.pas
+++ b/nim/semexprs.pas
@@ -374,15 +374,34 @@ begin
   end
 end;
 
-function isAssignable(n: PNode): bool;
+type
+  TAssignableResult = (
+    arNone,              // no l-value and no discriminant
+    arLValue,            // is an l-value
+    arDiscriminant       // is a discriminant
+  );
+
+function isAssignable(n: PNode): TAssignableResult;
 begin
-  result := false;
+  result := arNone;
   case n.kind of
-    nkSym: result := (n.sym.kind in [skVar, skTemp]);
-    nkDotExpr, nkQualified, nkBracketExpr: begin
+    nkSym: begin
+      if (n.sym.kind in [skVar, skTemp]) then
+        result := arLValue
+    end;
+    nkDotExpr: begin
+      checkMinSonsLen(n, 1);
+      if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then
+        result := arLValue
+      else
+        result := isAssignable(n.sons[0]);
+      if (result = arLValue) and (sfDiscriminant in n.sons[1].sym.flags) then
+        result := arDiscriminant
+    end;
+    nkBracketExpr: begin
       checkMinSonsLen(n, 1);
       if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then
-        result := true
+        result := arLValue
       else
         result := isAssignable(n.sons[0]);
     end;
@@ -393,7 +412,7 @@ begin
       if skipTypes(n.typ, abstractPtrs).kind in [tyOpenArray, tyTuple, tyObject] then
         result := isAssignable(n.sons[1])
     end;
-    nkHiddenDeref, nkDerefExpr: result := true;
+    nkHiddenDeref, nkDerefExpr: result := arLValue;
     nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
       result := isAssignable(n.sons[0]);
     else begin end
@@ -409,7 +428,7 @@ begin
   else begin
     result := newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ));
     addSon(result, n);
-    if not isAssignable(n) then begin
+    if isAssignable(n) <> arLValue then begin
       liMessage(n.info, errVarForOutParamNeeded);
     end
   end
@@ -425,7 +444,7 @@ begin
         result := newHiddenAddrTaken(c, n);
       end
     end;
-    nkDotExpr, nkQualified: begin
+    nkDotExpr: begin
       checkSonsLen(n, 2);
       if n.sons[1].kind <> nkSym then
         internalError(n.info, 'analyseIfAddressTaken');
@@ -499,7 +518,7 @@ begin
   prc := n.sons[0];
   checkMinSonsLen(n, 1);
   case n.sons[0].kind of
-    nkDotExpr, nkQualified: begin
+    nkDotExpr: begin
       checkSonsLen(n.sons[0], 2);
       n.sons[0] := semDotExpr(c, n.sons[0]);
       if n.sons[0].kind = nkDotCall then begin // it is a static call!
@@ -595,7 +614,7 @@ begin
       else
         result := SymtabGet(c.Tab, n.ident); // no need for stub loading
     end;
-    nkDotExpr, nkQualified: begin
+    nkDotExpr: begin
       result := nil;
       if onlyCurrentScope then exit;
       checkSonsLen(n, 2);
@@ -1174,8 +1193,14 @@ begin
     liMessage(n.info, errATypeHasNoValue);
   case s.kind of
     skProc, skMethod, skIterator, skConverter: begin
-      if (s.magic <> mNone) then
-        liMessage(n.info, errInvalidContextForBuiltinX, s.name.s);
+      if not (sfProcVar in s.flags) 
+      and (s.typ.callConv = ccDefault)
+      and (getModule(s).id <> c.module.id) then
+        liMessage(n.info, warnXisPassedToProcVar, s.name.s);
+      // XXX change this to errXCannotBePassedToProcVar after version 0.8.2
+      // TODO VERSION 0.8.4
+      //if (s.magic <> mNone) then
+      //  liMessage(n.info, errInvalidContextForBuiltinX, s.name.s);
       result := symChoice(c, n, s);
     end;
     skConst: begin
@@ -1253,10 +1278,7 @@ begin
       (*s := n.sym;
       include(s.flags, sfUsed);
       if (s.kind = skType) and not (efAllowType in flags) then
-        liMessage(n.info, errATypeHasNoValue);
-      if (s.magic <> mNone) and
-          (s.kind in [skProc, skMethod, skIterator, skConverter]) then
-        liMessage(n.info, errInvalidContextForBuiltinX, s.name.s); *)
+        liMessage(n.info, errATypeHasNoValue);*)
       // because of the changed symbol binding, this does not mean that we
       // don't have to check the symbol for semantics here again!
       result := semSym(c, n, n.sym, flags);
@@ -1279,7 +1301,7 @@ begin
       if result.typ = nil then result.typ := getSysType(tyString);
     nkCharLit:
       if result.typ = nil then result.typ := getSysType(tyChar);
-    nkQualified, nkDotExpr: begin
+    nkDotExpr: begin
       result := semDotExpr(c, n, flags);
       if result.kind = nkDotCall then begin
         result.kind := nkCall;
@@ -1364,7 +1386,8 @@ begin
       result := n;
       checkSonsLen(n, 1);
       n.sons[0] := semExprWithType(c, n.sons[0]);
-      if not isAssignable(n.sons[0]) then liMessage(n.info, errExprHasNoAddress);
+      if isAssignable(n.sons[0]) <> arLValue then 
+        liMessage(n.info, errExprHasNoAddress);
       n.typ := makePtrType(c, n.sons[0].typ);
     end;
     nkHiddenAddr, nkHiddenDeref: begin