diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-10-01 23:48:37 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-10-03 01:59:49 +0300 |
commit | 770d4a997eab25a04cdfd83b325491a2e63bea08 (patch) | |
tree | 54f7302645b240942ed43428586489d7df36377c /compiler | |
parent | 92f70b08f9c4d6108f61f37c29c1b001c6173a19 (diff) | |
download | Nim-770d4a997eab25a04cdfd83b325491a2e63bea08.tar.gz |
implemented case expressions
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ast.nim | 5 | ||||
-rwxr-xr-x | compiler/parser.nim | 8 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 55 |
3 files changed, 63 insertions, 5 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index c6e4d8318..aa94644aa 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -781,6 +781,11 @@ proc add*(father, son: PNode) = proc `[]`*(n: PNode, i: int): PNode {.inline.} = result = n.sons[i] +# son access operators with support for negative indices +template `{}`*(n: PNode, i: int): expr = n[i -| n] +template `{}=`*(n: PNode, i: int, s: PNode): stmt = + n.sons[i -| n] = s + var emptyNode* = newNode(nkEmpty) # There is a single empty node that is shared! Do not overwrite it! diff --git a/compiler/parser.nim b/compiler/parser.nim index cdbe42c7e..7612980c5 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -743,7 +743,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, tkWhen: + tkTuple, tkType, tkWhen, tkCase: result = true else: result = false @@ -763,9 +763,9 @@ proc parseExpr(p: var TParser): PNode = case p.tok.tokType: of tkIf: result = parseIfExpr(p, nkIfExpr) of tkWhen: result = parseIfExpr(p, nkWhenExpr) + of tkCase: result = parseCase(p) else: result = lowestExpr(p) # XXX needs proper support: - #of tkCase: result = parseCase(p) #of tkTry: result = parseTry(p) proc primary(p: var TParser, skipSuffix = false): PNode = @@ -1044,9 +1044,9 @@ proc parseCase(p: var TParser): PNode = if b.kind == nkElse: break if wasIndented: - eat(p, tkDed) + if p.tok.tokType != tkEof: eat(p, tkDed) popInd(p.lex) - + proc parseTry(p: var TParser): PNode = result = newNodeP(nkTryStmt, p) getTok(p) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 17e6e8048..a658f7f44 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1528,6 +1528,57 @@ proc semMacroStmt(c: PContext, n: PNode, flags: TExprFlags, renderTree(a, {renderNoComments})) result = errorNode(c, n) +proc semCaseExpr(c: PContext, caseStmt: PNode): PNode = + # The case expression is simply rewritten to a StmtListExpr: + # var res {.noInit, genSym.}: type(values) + # + # case E + # of X: res = value1 + # of Y: res = value2 + # + # res + var + info = caseStmt.info + resVar = newSym(skVar, getIdent":res", getCurrOwner(), info) + resNode = newSymNode(resVar, info) + resType: PType + + resVar.flags = { sfGenSym, sfNoInit } + + for i in countup(1, caseStmt.len - 1): + var cs = caseStmt[i] + case cs.kind + of nkOfBranch, nkElifBranch, nkElse: + # the value is always the last son regardless of the branch kind + cs.checkMinSonsLen 1 + var value = cs{-1} + if value.kind == nkStmtList: value.kind = nkStmtListExpr + + value = semExprWithType(c, value) + if resType == nil: + resType = value.typ + elif not sameType(resType, value.typ): + # XXX: semeType is a bit too harsh. + # work on finding a common base type. + # this will be useful for arrays/seq too: + # [ref DerivedA, ref DerivedB, ref Base] + typeMismatch(cs, resType, value.typ) + + cs{-1} = newNode(nkAsgn, cs.info, @[resNode, value]) + else: + IllFormedAst(caseStmt) + + result = newNode(nkStmtListExpr, info, @[ + newNode(nkVarSection, info, @[ + newNode(nkIdentDefs, info, @[ + resNode, + symNodeFromType(c, resType, info), + emptyNode])]), + caseStmt, + resNode]) + + result = semStmtListExpr(c, result) + proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = n if gCmd == cmdIdeTools: suggestExpr(c, n) @@ -1707,7 +1758,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkTryStmt: result = semTry(c, n) of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n) of nkForStmt, nkParForStmt: result = semFor(c, n) - of nkCaseStmt: result = semCase(c, n) + of nkCaseStmt: + if efWantStmt in flags: result = semCase(c, n) + else: result = semCaseExpr(c, n) of nkReturnStmt: result = semReturn(c, n) of nkAsmStmt: result = semAsm(c, n) of nkYieldStmt: result = semYield(c, n) |