summary refs log tree commit diff stats
path: root/compiler/pragmas.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/pragmas.nim')
-rw-r--r--compiler/pragmas.nim125
1 files changed, 73 insertions, 52 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index a17773aa4..d73494c6e 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -24,7 +24,8 @@ const
     wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
     wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
-    wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe}
+    wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
+    wOverride}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas
   templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
@@ -35,8 +36,8 @@ const
   iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, 
     wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
     wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
-    wTags, wUses, wOperator, wGcSafe}
-  exprPragmas* = {wLine}
+    wTags, wLocks, wGcSafe}
+  exprPragmas* = {wLine, wLocks}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@@ -44,27 +45,27 @@ const
     wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
     wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
     wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
-    wInjectStmt}
+    wInjectStmt, wDeprecated}
   lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
     wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
     wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
-    wRaises, wUses, wTags, wGcSafe}
+    wRaises, wLocks, wTags, wGcSafe}
   typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
     wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
     wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
     wBorrow, wGcSafe}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, 
-    wImportCpp, wImportObjC, wError}
+    wImportCpp, wImportObjC, wError, wGuard}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
     wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
     wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
-    wGensym, wInject, wCodegenDecl}
+    wGensym, wInject, wCodegenDecl, wGuard}
   constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
     wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
   letPragmas* = varPragmas
   procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
-                      wThread, wRaises, wUses, wTags, wGcSafe}
+                      wThread, wRaises, wLocks, wTags, wGcSafe}
   allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
 
 proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
@@ -127,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) =
   incl(s.flags, sfImportc)
   incl(s.flags, sfInfixCall)
   excl(s.flags, sfForward)
+  let m = s.getModule()
+  incl(m.flags, sfCompileToCpp)
 
 proc processImportObjC(s: PSym, extname: string) =
   setExternName(s, extname)
   incl(s.flags, sfImportc)
   incl(s.flags, sfNamedParamCall)
   excl(s.flags, sfForward)
+  let m = s.getModule()
+  incl(m.flags, sfCompileToObjC)
 
 proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
   result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
@@ -513,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
   else:
     invalidPragma(n)
 
-proc pragmaUses(c: PContext, n: PNode) =
-  proc processExc(c: PContext, x: PNode): PNode =
-    if x.kind in {nkAccQuoted, nkIdent, nkSym,
-                  nkOpenSymChoice, nkClosedSymChoice}:
-      if considerQuotedIdent(x).s == "*":
-        return newSymNode(ast.anyGlobal)
-    result = c.semExpr(c, x)
-    if result.kind != nkSym or sfGlobal notin result.sym.flags:
-      localError(x.info, "'$1' is not a global variable" % result.renderTree)
-      result = newSymNode(ast.anyGlobal)
-    
-  if n.kind == nkExprColonExpr:
-    let it = n.sons[1]
-    if it.kind notin {nkCurly, nkBracket}:
-      n.sons[1] = processExc(c, it)
-    else:
-      for i in 0 .. <it.len:
-        it.sons[i] = processExc(c, it.sons[i])
-  else:
-    invalidPragma(n)
-
 proc typeBorrow(sym: PSym, n: PNode) =
   if n.kind == nkExprColonExpr:
     let it = n.sons[1]
@@ -541,11 +525,50 @@ proc typeBorrow(sym: PSym, n: PNode) =
       localError(n.info, "a type can only borrow `.` for now")
   incl(sym.typ.flags, tfBorrowDot)
 
+proc markCompilerProc(s: PSym) =
+  makeExternExport(s, "$1", s.info)
+  incl(s.flags, sfCompilerProc)
+  incl(s.flags, sfUsed)
+  registerCompilerProc(s)
+
+proc deprecatedStmt(c: PContext; pragma: PNode) =
+  let pragma = pragma[1]
+  if pragma.kind != nkBracket:
+    localError(pragma.info, "list of key:value pairs expected"); return
+  for n in pragma:
+    if n.kind in {nkExprColonExpr, nkExprEqExpr}:
+      let dest = qualifiedLookUp(c, n[1])
+      let src = considerQuotedIdent(n[0])
+      let alias = newSym(skAlias, src, dest, n[0].info)
+      incl(alias.flags, sfExported)
+      if sfCompilerProc in dest.flags: markCompilerProc(alias)
+      addInterfaceDecl(c, alias)
+    else:
+      localError(n.info, "key:value pair expected")
+
+proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
+  if it.kind != nkExprColonExpr: 
+    invalidPragma(it); return
+  let n = it[1]
+  if n.kind == nkSym:
+    result = n.sym
+  elif kind == skField:
+    # First check if the guard is a global variable:
+    result = qualifiedLookUp(c, n, {})
+    if result.isNil or result.kind notin {skLet, skVar} or
+        sfGlobal notin result.flags:
+      # We return a dummy symbol; later passes over the type will repair it.
+      # Generic instantiation needs to know about this too. But we're lazy
+      # and perform the lookup on demand instead.
+      result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info)
+  else:
+    result = qualifiedLookUp(c, n)
+
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
                   validPragmas: TSpecialWords): bool =
   var it = n.sons[i]
   var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
-  if key.kind == nkIdent: 
+  if key.kind == nkIdent:
     var userPragma = strTableGet(c.userPragmas, key.ident)
     if userPragma != nil: 
       inc c.instCounter
@@ -577,11 +600,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wAlign:
           if sym.typ == nil: invalidPragma(it)
           var align = expectIntLit(c, it)
-          if not isPowerOfTwo(align) and align != 0: 
+          if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
             localError(it.info, errPowerOfTwoExpected)
           else: 
-            sym.typ.align = align              
-        of wSize: 
+            sym.typ.align = align.int16
+        of wSize:
           if sym.typ == nil: invalidPragma(it)
           var size = expectIntLit(c, it)
           if not isPowerOfTwo(size) or size <= 0 or size > 8: 
@@ -628,11 +651,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           # implies nodecl, because otherwise header would not make sense
           if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
         of wDestructor:
-          if sym.typ.sons.len == 2:
-            sym.flags.incl sfDestructor
-          else:
-            invalidPragma(it)
-        of wNosideeffect: 
+          sym.flags.incl sfOverriden
+          if sym.name.s.normalize != "destroy":
+            localError(n.info, errGenerated, "destructor has to be named 'destroy'")
+        of wOverride:
+          sym.flags.incl sfOverriden
+        of wNosideeffect:
           noVal(it)
           incl(sym.flags, sfNoSideEffect)
           if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
@@ -646,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           processDynLib(c, it, sym)
         of wCompilerproc:
           noVal(it)           # compilerproc may not get a string!
-          if sfFromGeneric notin sym.flags:
-            makeExternExport(sym, "$1", it.info)
-            incl(sym.flags, sfCompilerProc)
-            incl(sym.flags, sfUsed) # suppress all those stupid warnings
-            registerCompilerProc(sym)
-        of wProcVar: 
+          if sfFromGeneric notin sym.flags: markCompilerProc(sym)
+        of wProcVar:
           noVal(it)
           incl(sym.flags, sfProcvar)
-        of wDeprecated: 
-          noVal(it)
-          if sym != nil: incl(sym.flags, sfDeprecated)
+        of wDeprecated:
+          if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
+          elif sym != nil: incl(sym.flags, sfDeprecated)
           else: incl(c.module.flags, sfDeprecated)
         of wVarargs: 
           noVal(it)
@@ -787,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           if sym == nil: invalidPragma(it)
         of wLine: pragmaLine(c, it)
         of wRaises, wTags: pragmaRaisesOrTags(c, it)
-        of wUses: pragmaUses(c, it)
-        of wOperator:
-          if sym == nil: invalidPragma(it)
-          else: sym.position = expectIntLit(c, it)
+        of wGuard:
+          if sym == nil or sym.kind notin {skVar, skLet, skField}:
+            invalidPragma(it)
+          else:
+            sym.guard = pragmaGuard(c, it, sym.kind)
         of wInjectStmt:
           if it.kind != nkExprColonExpr:
             localError(it.info, errExprExpected)