templates can access hidden fields

This commit is contained in:
Araq
2013-12-25 14:53:00 +01:00
parent 4d01408a46
commit 9e92455a53
6 changed files with 61 additions and 42 deletions

View File

@@ -146,29 +146,18 @@ 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)
@@ -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.

View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -0,0 +1,9 @@
discard """
output: 33
"""
import mcan_access_hidden_field
var myfoo = createFoo(33, 44)
echo myfoo.geta

View File

@@ -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