summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-04-05 22:43:37 +0300
committerZahary Karadjov <zahary@gmail.com>2012-04-05 22:43:37 +0300
commit98b7bdaa5050a9b3709e8a27fd44477a2a28e4f7 (patch)
tree157eb8698991070783a0926ce775a55bbbdfda27
parent6d80583d5a0e776fc9f4214fb96a532f3ebd5550 (diff)
downloadNim-98b7bdaa5050a9b3709e8a27fd44477a2a28e4f7.tar.gz
when expressions, proper rendering for nkDo and nkLambda and parser support for x.type and x.addr
-rwxr-xr-xcompiler/ast.nim7
-rwxr-xr-xcompiler/parser.nim31
-rwxr-xr-xcompiler/renderer.nim26
-rwxr-xr-xcompiler/semexprs.nim3
-rwxr-xr-xcompiler/semstmts.nim4
-rwxr-xr-xweb/news.txt3
6 files changed, 55 insertions, 19 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 897501ee5..972ba7924 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -143,7 +143,7 @@ type
     nkPragma,             # a pragma statement
     nkPragmaBlock,        # a pragma with a block
     nkIfStmt,             # an if statement
-    nkWhenStmt,           # a when statement
+    nkWhenStmt,           # a when expression or statement
     nkForStmt,            # a for statement
     nkWhileStmt,          # a while statement
     nkCaseStmt,           # a case statement
@@ -246,6 +246,11 @@ const
   sfImmediate* = sfDeadCodeElim  # macro or template is immediately expanded
                                  # without considering any possible overloads
 
+const
+  # getting ready for the future expr/stmt merge
+  nkWhen* = nkWhenStmt
+  nkWhenExpr* = nkWhenStmt
+
 type
   TTypeKind* = enum  # order is important!
                      # Don't forget to change hti.nim if you make a change here
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 2ba04ed1b..9563849c6 100755
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -264,16 +264,26 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
     optInd(p, a)
   eat(p, endTok)
 
-proc newDotExpr(p: var TParser, a: PNode): PNode =
+proc dotExpr(p: var TParser, a: PNode): PNode =
   getTok(p)
   optInd(p, a)
-  result = newNodeI(nkDotExpr, a.info)
-  addSon(result, a)
-  addSon(result, parseSymbol(p))
+  case p.tok.tokType
+  of tkType:
+    result = newNodeP(nkTypeOfExpr, p)
+    getTok(p)
+    addSon(result, a)
+  of tkAddr:
+    result = newNodeP(nkAddr, p)
+    getTok(p)
+    addSon(result, a)
+  else:
+    result = newNodeI(nkDotExpr, a.info)
+    addSon(result, a)
+    addSon(result, parseSymbol(p))
 
 proc qualifiedIdent(p: var TParser): PNode = 
   result = parseSymbol(p)     #optInd(p, result);
-  if p.tok.tokType == tkDot: result = newDotExpr(p, result)
+  if p.tok.tokType == tkDot: result = dotExpr(p, result)
 
 proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) = 
   getTok(p)
@@ -477,7 +487,7 @@ proc primary(p: var TParser): PNode =
       exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
       parseDoBlocks(p, result)
     of tkDot:
-      result = newDotExpr(p, result)
+      result = dotExpr(p, result)
       result = parseGStrLit(p, result)
     of tkBracketLe: 
       result = indexExprList(p, result, nkBracketExpr, tkBracketRi)
@@ -506,8 +516,8 @@ proc lowestExprAux(p: var TParser, limit: int): PNode =
 proc lowestExpr(p: var TParser): PNode = 
   result = lowestExprAux(p, -1)
 
-proc parseIfExpr(p: var TParser): PNode = 
-  result = newNodeP(nkIfExpr, p)
+proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode = 
+  result = newNodeP(kind, p)
   while true: 
     getTok(p)                 # skip `if`, `elif`
     var branch = newNodeP(nkElifExpr, p)
@@ -707,7 +717,8 @@ proc parseExpr(p: var TParser): PNode =
   of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
   of tkTuple: result = parseTuple(p)
   of tkProc: result = parseProcExpr(p, true)
-  of tkIf: result = parseIfExpr(p)
+  of tkIf: result = parseIfExpr(p, nkIfExpr)
+  of tkWhen: result = parseIfExpr(p, nkWhenExpr)
   else: result = lowestExpr(p)
   
 proc parseTypeDesc(p: var TParser): PNode = 
@@ -718,7 +729,7 @@ proc isExprStart(p: TParser): bool =
   case p.tok.tokType
   of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkBind, 
      tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, 
-     tkTuple, tkType: 
+     tkTuple, tkType, tkWhen:
     result = true
   else: result = false
   
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 0be578a1a..6545b2e72 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -349,7 +349,8 @@ proc lsub(n: PNode): int =
   of nkBind: result = lsons(n) + len("bind_")
   of nkBindStmt: result = lcomma(n) + len("bind_")
   of nkCheckedFieldExpr: result = lsub(n.sons[0])
-  of nkLambda, nkDo: result = lsons(n) + len("lambda__=_") # XXX: render nkDo
+  of nkLambda: result = lsons(n) + len("proc__=_")
+  of nkDo: result = lsons(n) + len("do__:_")
   of nkConstDef, nkIdentDefs: 
     result = lcomma(n, 0, - 3)
     var L = sonsLen(n)
@@ -673,7 +674,17 @@ proc gident(g: var TSrcGen, n: PNode) =
     t = tkOpr
   put(g, t, s)
   if n.kind == nkSym and renderIds in g.flags: put(g, tkIntLit, $n.sym.id)
+
+proc doParamsAux(g: var TSrcGen, params: PNode) =
+  if params.len > 1:
+    put(g, tkParLe, "(")
+    gcomma(g, params, 1)
+    put(g, tkParRi, ")")
   
+  if params.sons[0].kind != nkEmpty: 
+    putWithSpace(g, tkOpr, "->")
+    gsub(g, params.sons[0])
+
 proc gsub(g: var TSrcGen, n: PNode, c: TContext) = 
   if isNil(n): return
   var 
@@ -800,14 +811,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     gsub(g, n.sons[0])
   of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: 
     gsub(g, n.sons[0])
-  of nkLambda, nkDo: # XXX: nkDo is rendered as regular lambda
-    assert(n.sons[genericParamsPos].kind == nkEmpty)
-    putWithSpace(g, tkLambda, "lambda")
+  of nkLambda:
+    putWithSpace(g, tkLambda, "proc")
     gsub(g, n.sons[paramsPos])
     gsub(g, n.sons[pragmasPos])
     put(g, tkSpaces, Space)
     putWithSpace(g, tkEquals, "=")
     gsub(g, n.sons[bodyPos])
+  of nkDo:
+    putWithSpace(g, tkDo, "do")
+    doParamsAux(g, n.sons[paramsPos])
+    gsub(g, n.sons[pragmasPos])
+    put(g, tkColon, ":")
+    gsub(g, n.sons[bodyPos])
   of nkConstDef, nkIdentDefs: 
     gcomma(g, n, 0, - 3)
     var L = sonsLen(n)
@@ -956,7 +972,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkIfStmt: 
     putWithSpace(g, tkIf, "if")
     gif(g, n)
-  of nkWhenStmt, nkRecWhen: 
+  of nkWhen, nkRecWhen: 
     putWithSpace(g, tkWhen, "when")
     gif(g, n)
   of nkWhileStmt: gwhile(g, n)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 2475492cc..8ab4c5f63 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1356,6 +1356,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       result = semIndirectOp(c, n, flags)
   of nkMacroStmt: 
     result = semMacroStmt(c, n)
+  of nkWhenExpr:
+    result = semWhen(c, n, false)
+    result = semExpr(c, result)
   of nkBracketExpr: 
     checkMinSonsLen(n, 1)
     var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 2de496b9a..0449c5644 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -25,13 +25,13 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
   for i in countup(0, sonsLen(n) - 1): 
     var it = n.sons[i]
     case it.kind
-    of nkElifBranch: 
+    of nkElifBranch, nkElifExpr: 
       checkSonsLen(it, 2)
       var e = semAndEvalConstExpr(c, it.sons[0])
       if e.kind != nkIntLit: InternalError(n.info, "semWhen")
       if e.intVal != 0 and result == nil:
         setResult(it.sons[1]) 
-    of nkElse:
+    of nkElse, nkElseExpr:
       checkSonsLen(it, 1)
       if result == nil: 
         setResult(it.sons[0])
diff --git a/web/news.txt b/web/news.txt
index fd2a50606..dd1d55a18 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -58,7 +58,8 @@ Language Additions
 - Added explicit ``static`` sections for enforced compile time evaluation.
 - ``addr`` is now treated like a prefix operator syntactically.
 - Added ``global`` pragma that can be used to introduce new global variables
-  from within procs. 
+  from within procs.
+- when expressions are now allowed just like if expressions
 
 
 2012-02-09 Version 0.8.14 released