summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-09-22 22:43:36 +0200
committerAraq <rumpf_a@web.de>2012-09-22 22:43:36 +0200
commit759b3201ad7f60ee865f9c0cec57d6ce63c74b73 (patch)
tree234e76619824ce081d9b1eaf469242d36de1936e /compiler
parent3ef146b0eacb8781dd0e352925001de342d6cc9d (diff)
downloadNim-759b3201ad7f60ee865f9c0cec57d6ce63c74b73.tar.gz
proc bodies can be expressions with a type
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim1
-rwxr-xr-xcompiler/parser.nim7
-rwxr-xr-xcompiler/renderer.nim4
-rwxr-xr-xcompiler/sem.nim1
-rwxr-xr-xcompiler/semexprs.nim28
-rwxr-xr-xcompiler/seminst.nim2
-rwxr-xr-xcompiler/semstmts.nim2
-rwxr-xr-xcompiler/semtempl.nim23
8 files changed, 59 insertions, 9 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 434e09dd9..e556ac671 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -176,6 +176,7 @@ type
     nkFromStmt,           # a from * import statement
     nkIncludeStmt,        # an include statement
     nkBindStmt,           # a bind statement
+    nkMixinStmt,          # a mixin statement
     nkCommentStmt,        # a comment statement
     nkStmtListExpr,       # a statement list followed by an expr; this is used
                           # to allow powerful multi-line templates
diff --git a/compiler/parser.nim b/compiler/parser.nim
index b359c6e3d..cdbe42c7e 100755
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1461,8 +1461,8 @@ proc parseVariable(p: var TParser): PNode =
   else: result = parseIdentColonEquals(p, {withPragma})
   indAndComment(p, result)    # special extension!
   
-proc parseBind(p: var TParser): PNode =
-  result = newNodeP(nkBindStmt, p)
+proc parseBind(p: var TParser, k: TNodeKind): PNode =
+  result = newNodeP(k, p)
   getTok(p)
   optInd(p, result)
   while true:
@@ -1523,7 +1523,8 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   of tkLet: result = parseSection(p, nkLetSection, parseVariable)
   of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
   of tkVar: result = parseSection(p, nkVarSection, parseVariable)
-  of tkBind: result = parseBind(p)
+  of tkBind: result = parseBind(p, nkBindStmt)
+  of tkMixin: result = parseBind(p, nkMixinStmt)
   else: result = simpleStmt(p)
   
 proc parseStmt(p: var TParser): PNode = 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 8a8e1e849..cf8dd65c6 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -386,6 +386,7 @@ proc lsub(n: PNode): int =
   of nkDotExpr: result = lsons(n) + 1
   of nkBind: result = lsons(n) + len("bind_")
   of nkBindStmt: result = lcomma(n) + len("bind_")
+  of nkMixinStmt: result = lcomma(n) + len("mixin_")
   of nkCheckedFieldExpr: result = lsub(n.sons[0])
   of nkLambda: result = lsons(n) + len("proc__=_")
   of nkDo: result = lsons(n) + len("do__:_")
@@ -1152,6 +1153,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkBindStmt: 
     putWithSpace(g, tkBind, "bind")
     gcomma(g, n, c)
+  of nkMixinStmt:
+    putWithSpace(g, tkMixin, "mixin")
+    gcomma(g, n, c)
   of nkElifBranch: 
     optNL(g)
     putWithSpace(g, tkElif, "elif")
diff --git a/compiler/sem.nim b/compiler/sem.nim
index e1f2fb21c..315ff92cd 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -30,6 +30,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc semExprNoType(c: PContext, n: PNode): PNode
 proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
+proc semProcBody(c: PContext, n: PNode): PNode
 
 proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
 proc changeType(n: PNode, newType: PType)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 8a42a7090..89789f269 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -706,11 +706,10 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
   # and check 'arg' for semantics again:
   addSon(result, semExpr(c, arg))
 
-proc semExprNoType(c: PContext, n: PNode): PNode =
+proc discardCheck(result: PNode) =
   proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
     result = isCallExpr(n) and n.sons[0].kind == nkSym and 
              sfDiscardable in n.sons[0].sym.flags
-  result = semExpr(c, n, {efWantStmt})
   if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
     if result.kind == nkNilLit:
       # XXX too much work and fixing would break bootstrapping:
@@ -718,7 +717,11 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
       result.typ = nil
     elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError and
         gCmd != cmdInteractive:
-      localError(n.info, errDiscardValue)
+      localError(result.info, errDiscardValue)
+
+proc semExprNoType(c: PContext, n: PNode): PNode =
+  result = semExpr(c, n, {efWantStmt})
+  discardCheck(result)
   
 proc isTypeExpr(n: PNode): bool = 
   case n.kind
@@ -1061,11 +1064,28 @@ proc SemReturn(c: PContext, n: PNode): PNode =
       addSon(a, n.sons[0])
       n.sons[0] = semAsgn(c, a)
       # optimize away ``result = result``:
-      if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: 
+      if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym: 
         n.sons[0] = ast.emptyNode
     else:
       LocalError(n.info, errNoReturnTypeDeclared)
 
+proc semProcBody(c: PContext, n: PNode): PNode =
+  openScope(c.tab)
+  result = semExpr(c, n)
+  if c.p.resultSym != nil and not isEmptyType(result.typ):
+    # transform ``expr`` to ``result = expr``, but not if the expr is already
+    # ``result``:
+    if result.kind == nkSym and result.sym == c.p.resultSym: 
+      nil
+    else:
+      var a = newNodeI(nkAsgn, n.info, 2)
+      a.sons[0] = newSymNode(c.p.resultSym)
+      a.sons[1] = result
+      result = semAsgn(c, a)
+  else:
+    discardCheck(result)
+  closeScope(c.tab)
+
 proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
   var t = skipTypes(restype, {tyGenericInst})
   case t.kind
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 135f9bba9..ba950422f 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -93,7 +93,7 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
     var symMap: TIdTable
     InitIdTable symMap
     freshGenSyms(b, result, symMap)
-    b = semStmtScope(c, b)
+    b = semProcBody(c, b)
     b = hloBody(c, b)
     n.sons[bodyPos] = transformBody(c.module, b, result)
     #echo "code instantiated ", result.name.s
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 666c57cd1..8a82e629a 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -767,7 +767,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         addResult(c, s.typ.sons[0], n.info, kind)
       if sfImportc notin s.flags:
         # no semantic checking for importc:
-        let semBody = hloBody(c, semStmtScope(c, n.sons[bodyPos]))
+        let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
         # unfortunately we cannot skip this step when in 'system.compiles'
         # context as it may even be evaluated in 'system.compiles':
         n.sons[bodyPos] = transformBody(c.module, semBody, s)
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 8e36aac20..1444255ff 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -90,6 +90,29 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
     else:
       illFormedAst(a)
   result = newNodeI(nkNilLit, n.info)
+
+when false:
+  # not active before 0.9.0 is out
+  proc semMixinStmt(c: PContext, n: PNode, toMixin: var TIntSet): PNode =
+    for i in 0 .. < n.len:
+      var a = n.sons[i]
+      # If 'a' is an overloaded symbol, we used to use the first symbol
+      # as a 'witness' and use the fact that subsequent lookups will yield
+      # the same symbol!
+      # This is however not true anymore for hygienic templates as semantic
+      # processing for them changes the symbol table...
+      let s = QualifiedLookUp(c, a)
+      if s != nil:
+        # we need to mark all symbols:
+        let sc = symChoice(c, n, s, scForceOpen)
+        if sc.kind == nkSym:
+          toMixin.incl(sc.sym.id)
+        else:
+          for x in items(sc): toMixin.incl(x.sym.id)
+      else:
+        # do nothing: identifiers are already not bound:
+        nil
+    result = newNodeI(nkNilLit, n.info)
   
 proc replaceIdentBySym(n: var PNode, s: PNode) =
   case n.kind