summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sem.nim32
-rw-r--r--doc/manual.txt40
-rw-r--r--lib/system/sysio.nim8
-rw-r--r--tests/templates/mcan_access_hidden_field.nim9
-rw-r--r--tests/templates/tcan_access_hidden_field.nim9
-rw-r--r--web/news.txt5
6 files changed, 61 insertions, 42 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index ed3c0e045..d0fc5bfe1 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -146,30 +146,19 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym
 proc semStmtScope(c: PContext, n: PNode): PNode
 
-proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
+proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
   if not typeAllowed(typ, skConst):
-    LocalError(typ.n.info, errXisNoType, typeToString(typ))
+    localError(typ.n.info, errXisNoType, typeToString(typ))
 
 proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
 proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
 proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
-proc IsOpImpl(c: PContext, n: PNode): PNode
+proc isOpImpl(c: PContext, n: PNode): PNode
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
                   semCheck: bool = true): PNode
 
 when false:
-  proc symFromType(t: PType, info: TLineInfo): PSym =
-    if t.sym != nil: return t.sym
-    result = newSym(skType, getIdent"AnonType", t.owner, info)
-    result.flags.incl sfAnon
-    result.typ = t
-
-  proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
-    result = newSymNode(symFromType(t, info), info)
-    result.typ = makeTypeDesc(c, t)
-
-when false:
   proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
     result = newEvalContext(c.module, mode)
     result.getType = proc (n: PNode): PNode =
@@ -184,12 +173,6 @@ when false:
     result.handleIsOperator = proc (n: PNode): PNode =
       result = IsOpImpl(c, n)
 
-  proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode = 
-    result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e)
-
-  proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode = 
-    result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e)
-
 proc semConstExpr(c: PContext, n: PNode): PNode =
   var e = semExprWithType(c, n)
   if e == nil:
@@ -226,7 +209,9 @@ include hlo, seminst, semcall
 proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = 
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100:
-    GlobalError(s.info, errTemplateInstantiationTooNested)
+    globalError(s.info, errTemplateInstantiationTooNested)
+  let oldFriend = c.friendModule
+  c.friendModule = s.owner.getModule
 
   result = n
   if s.typ.sons[0] == nil:
@@ -250,6 +235,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
       result = fitNode(c, s.typ.sons[0], result)
       #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
+  c.friendModule = oldFriend
 
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, 
                   semCheck: bool = true): PNode = 
@@ -316,7 +302,7 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
   result = myOpen(module)
   for m in items(rd.methods): methodDef(m, true)
 
-proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
+proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
   result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
   if c.lastGenericIdx < c.generics.len:
@@ -331,7 +317,7 @@ proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
     result = buildEchoStmt(c, result)
   result = transformStmt(c.module, result)
     
-proc RecoverContext(c: PContext) = 
+proc recoverContext(c: PContext) = 
   # clean up in case of a semantic error: We clean up the stacks, etc. This is
   # faster than wrapping every stack operation in a 'try finally' block and 
   # requires far less code.
diff --git a/doc/manual.txt b/doc/manual.txt
index 0a9aec8d0..fd3db1b0d 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -1268,12 +1268,13 @@ exclude ``nil`` as a valid value with the `not nil`:idx: annotation:
   # compiler catches this:
   p(nil)
   
-  # but not this:
+  # and also this:
   var x: PObject
   p(x)
 
-As shown in the example this is merely an annotation for documentation purposes;
-for now the compiler can only catch the most trivial type violations.
+The compiler ensures that every code path initializes variables which contain
+not nilable pointers. The details of this analysis are still to be specified
+here.
 
 
 Procedural type
@@ -1504,8 +1505,8 @@ The ``void`` type is particularly useful for generic code:
     else:
       p(x)
 
-  proc intProc(x: int) = nil
-  proc emptyProc() = nil
+  proc intProc(x: int) = discard
+  proc emptyProc() = discard
 
   callProc[int](intProc, 12)
   callProc[void](emptyProc)
@@ -1767,6 +1768,15 @@ been declared with the `discardable`:idx: pragma:
     
   p(3, 4) # now valid
 
+An empty ``discard`` statement is often used as a null statement:
+
+.. code-block:: nimrod
+  proc classify(s: string) =
+    case s[0]
+    of SymChars, '_': echo "an identifier"
+    of '0'..'9': echo "a number"
+    else: discard
+
 
 Var statement
 -------------
@@ -1816,7 +1826,7 @@ If a proc is annotated with the ``noinit`` pragma this refers to its implicit
 ``result`` variable:
 
 .. code-block:: nimrod
-  proc returnUndefinedValue: int {.noinit.} = nil
+  proc returnUndefinedValue: int {.noinit.} = discard
 
 
 The implicit initialization can be also prevented by the `requiresInit`:idx:
@@ -3207,7 +3217,7 @@ Nimrod also allows for type classes and regular types to be specified
 as `type constraints`:idx: of the generic type parameter:
 
 .. code-block:: nimrod
-  proc onlyIntOrString[T: int|string](x, y: T) = nil
+  proc onlyIntOrString[T: int|string](x, y: T) = discard
   
   onlyIntOrString(450, 616) # valid
   onlyIntOrString(5.0, 0.0) # type mismatch
@@ -3782,7 +3792,7 @@ regular expressions:
   macro case_token(n: stmt): stmt =
     # creates a lexical analyzer from regular expressions
     # ... (implementation is an exercise for the reader :-)
-    nil
+    discard
 
   case_token: # this colon tells the parser it is a macro statement
   of r"[A-Za-z_]+[A-Za-z_0-9]*":
@@ -3811,17 +3821,17 @@ Whole routines (procs, iterators etc.) can also be passed to a template or
 a macro via the pragma notation: 
 
 .. code-block:: nimrod
-  template m(s: stmt) = nil
+  template m(s: stmt) = discard
 
-  proc p() {.m.} = nil
+  proc p() {.m.} = discard
 
 This is a simple syntactic transformation into:
 
 .. code-block:: nimrod
-  template m(s: stmt) = nil
+  template m(s: stmt) = discard
 
   m:
-    proc p() = nil
+    proc p() = discard
 
 
 Special Types
@@ -4142,9 +4152,9 @@ all the arguments, but also the matched operators in reverse polish notation:
     TMatrix = object
       dummy: int
 
-  proc `*`(a, b: TMatrix): TMatrix = nil
-  proc `+`(a, b: TMatrix): TMatrix = nil
-  proc `-`(a, b: TMatrix): TMatrix = nil
+  proc `*`(a, b: TMatrix): TMatrix = discard
+  proc `+`(a, b: TMatrix): TMatrix = discard
+  proc `-`(a, b: TMatrix): TMatrix = discard
   proc `$`(a: TMatrix): string = result = $a.dummy
   proc mat21(): TMatrix =
     result.dummy = 21
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 41dbcd817..82b4b183a 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -106,7 +106,7 @@ proc write(f: TFile, b: bool) =
 proc write(f: TFile, r: float32) = fprintf(f, "%g", r)
 proc write(f: TFile, r: biggestFloat) = fprintf(f, "%g", r)
 
-proc write(f: TFile, c: Char) = putc(c, f)
+proc write(f: TFile, c: char) = putc(c, f)
 proc write(f: TFile, a: varargs[string, `$`]) =
   for x in items(a): write(f, x)
 
@@ -184,7 +184,7 @@ when defined(windows) and not defined(useWinAnsi):
   proc wfreopen(filename, mode: widecstring, stream: TFile): TFile {.
     importc: "_wfreopen", nodecl.}
 
-  proc fopen(filename, mode: CString): pointer =
+  proc fopen(filename, mode: cstring): pointer =
     var f = newWideCString(filename)
     var m = newWideCString(mode)
     result = wfopen(f, m)
@@ -195,7 +195,7 @@ when defined(windows) and not defined(useWinAnsi):
     result = wfreopen(f, m, stream)
 
 else:
-  proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
+  proc fopen(filename, mode: cstring): pointer {.importc: "fopen", noDecl.}
   proc freopen(filename, mode: cstring, stream: TFile): TFile {.
     importc: "freopen", nodecl.}
 
@@ -229,7 +229,7 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
   f = fdopen(filehandle, FormatOpen[mode])
   result = f != nil
 
-proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
+proc fwrite(buf: pointer, size, n: int, f: TFile): int {.
   importc: "fwrite", noDecl.}
 
 proc readBuffer(f: TFile, buffer: pointer, len: int): int =
diff --git a/tests/templates/mcan_access_hidden_field.nim b/tests/templates/mcan_access_hidden_field.nim
new file mode 100644
index 000000000..bf3592701
--- /dev/null
+++ b/tests/templates/mcan_access_hidden_field.nim
@@ -0,0 +1,9 @@
+
+type
+  Foo* = object
+    fooa, foob: int
+
+proc createFoo*(a, b: int): Foo = Foo(fooa: a, foob: b)
+
+template geta*(f: Foo): expr = f.fooa
+
diff --git a/tests/templates/tcan_access_hidden_field.nim b/tests/templates/tcan_access_hidden_field.nim
new file mode 100644
index 000000000..a6f6490cc
--- /dev/null
+++ b/tests/templates/tcan_access_hidden_field.nim
@@ -0,0 +1,9 @@
+discard """
+  output: 33
+"""
+
+import mcan_access_hidden_field
+
+var myfoo = createFoo(33, 44)
+
+echo myfoo.geta
diff --git a/web/news.txt b/web/news.txt
index d6d269649..7deda8dad 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -30,6 +30,10 @@ Changes affecting backwards compatibility
 - ``os.parentDir`` now returns "" if there is no parent dir.
 - In CGI scripts stacktraces are shown user only if cgi.setStackTraceStdout
   is used.
+- The symbol binding rules for clean templates changed: ``bind`` for any
+  symbol that's not a parameter is now the default. ``mixin`` can be used
+  to require instantiation scope for a symbol.
+
 
 Compiler Additions
 ------------------
@@ -60,6 +64,7 @@ Language Additions
 - Added ``delegator pragma`` for handling calls to missing procs and fields at
   compile-time.
 - Support for user-defined type classes has been added.
+- Exported templates are allowed to access hidden fields.
 
 
 Tools improvements