diff options
author | Araq <rumpf_a@web.de> | 2011-04-22 10:53:43 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-04-22 10:53:43 +0200 |
commit | 8dda362fa67bcf75a24f2a60b7a124fdea319a64 (patch) | |
tree | 7e43b56fd522040989c5c64ddfef9ffab08b8594 | |
parent | 1985ac69951932d2882b63b13f9dcd853dd80c43 (diff) | |
download | Nim-8dda362fa67bcf75a24f2a60b7a124fdea319a64.tar.gz |
slices are first class citizens
-rwxr-xr-x | build.bat | 20 | ||||
-rwxr-xr-x | compiler/parser.nim | 41 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 28 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 19 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 42 | ||||
-rwxr-xr-x | compiler/trees.nim | 12 | ||||
-rwxr-xr-x | doc/grammar.txt | 29 | ||||
-rwxr-xr-x | doc/manual.txt | 66 | ||||
-rwxr-xr-x | lib/system.nim | 27 | ||||
-rwxr-xr-x | lib/wrappers/tcl.nim | 2 | ||||
-rw-r--r-- | tests/accept/compile/ttableconstr.nim | 16 | ||||
-rwxr-xr-x | todo.txt | 2 |
12 files changed, 177 insertions, 127 deletions
diff --git a/build.bat b/build.bat index 34086269c..04e48bea8 100755 --- a/build.bat +++ b/build.bat @@ -65,8 +65,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/streams.c -o build/1_1/streams.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/streams.c -o build/1_1/streams.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/wordrecg.c -o build/1_1/wordrecg.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/wordrecg.c -o build/1_1/wordrecg.o -ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/scanner.c -o build/1_1/scanner.o -%CC% %COMP_FLAGS% -Ibuild -c build/1_1/scanner.c -o build/1_1/scanner.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/lexer.c -o build/1_1/lexer.o +%CC% %COMP_FLAGS% -Ibuild -c build/1_1/lexer.c -o build/1_1/lexer.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/lexbase.c -o build/1_1/lexbase.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/lexbase.c -o build/1_1/lexbase.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/llstream.c -o build/1_1/llstream.o @@ -77,16 +77,16 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/main.c -o build/1_1/main.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/main.c -o build/1_1/main.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/syntaxes.c -o build/1_1/syntaxes.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/syntaxes.c -o build/1_1/syntaxes.o -ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/pnimsyn.c -o build/1_1/pnimsyn.o -%CC% %COMP_FLAGS% -Ibuild -c build/1_1/pnimsyn.c -o build/1_1/pnimsyn.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/parser.c -o build/1_1/parser.o +%CC% %COMP_FLAGS% -Ibuild -c build/1_1/parser.c -o build/1_1/parser.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/pbraces.c -o build/1_1/pbraces.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/pbraces.c -o build/1_1/pbraces.o -ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/ptmplsyn.c -o build/1_1/ptmplsyn.o -%CC% %COMP_FLAGS% -Ibuild -c build/1_1/ptmplsyn.c -o build/1_1/ptmplsyn.o -ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rnimsyn.c -o build/1_1/rnimsyn.o -%CC% %COMP_FLAGS% -Ibuild -c build/1_1/rnimsyn.c -o build/1_1/rnimsyn.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/filters.c -o build/1_1/filters.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/filters.c -o build/1_1/filters.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/renderer.c -o build/1_1/renderer.o +%CC% %COMP_FLAGS% -Ibuild -c build/1_1/renderer.c -o build/1_1/renderer.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/filter_tmpl.c -o build/1_1/filter_tmpl.o +%CC% %COMP_FLAGS% -Ibuild -c build/1_1/filter_tmpl.c -o build/1_1/filter_tmpl.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodread.c -o build/1_1/rodread.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodread.c -o build/1_1/rodread.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodwrite.c -o build/1_1/rodwrite.o @@ -152,8 +152,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/transf.c -o build/1_1/transf.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o %CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o -ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/semtypinst.o build/1_1/sigmatch.o build/1_1/suggest.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o -%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/semtypinst.o build/1_1/sigmatch.o build/1_1/suggest.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o +ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/lexer.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/parser.o build/1_1/pbraces.o build/1_1/filters.o build/1_1/renderer.o build/1_1/filter_tmpl.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/semtypinst.o build/1_1/sigmatch.o build/1_1/suggest.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o +%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/lexer.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/parser.o build/1_1/pbraces.o build/1_1/filters.o build/1_1/renderer.o build/1_1/filter_tmpl.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/semtypinst.o build/1_1/sigmatch.o build/1_1/suggest.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o ECHO SUCCESS diff --git a/compiler/parser.nim b/compiler/parser.nim index b579d20be..c7e9cbac7 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -123,7 +123,8 @@ proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = result = newNodeP(kind, p) result.intVal = intVal -proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, p: TParser): PNode = +proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, + p: TParser): PNode = result = newNodeP(kind, p) result.floatVal = floatVal @@ -147,16 +148,18 @@ proc getPrecedence(tok: PToken): int = case tok.tokType of tkOpr: case tok.ident.s[0] - of '$', '^': result = 7 - of '*', '%', '/', '\\': result = 6 - of '+', '-', '~', '|': result = 5 - of '&': result = 4 - of '=', '<', '>', '!': result = 3 - else: result = 0 - of tkDiv, tkMod, tkShl, tkShr: result = 6 - of tkIn, tkNotIn, tkIs, tkIsNot: result = 3 - of tkAnd: result = 2 - of tkOr, tkXor: result = 1 + of '$', '^': result = 9 + of '*', '%', '/', '\\': result = 8 + of '+', '-', '~', '|': result = 7 + of '&': result = 6 + of '=', '<', '>', '!': result = 4 + of '.': result = 5 + else: result = 1 + of tkDiv, tkMod, tkShl, tkShr: result = 8 + of tkIn, tkNotIn, tkIs, tkIsNot, tkNot: result = 4 + of tkDotDot: result = 5 + of tkAnd: result = 3 + of tkOr, tkXor: result = 2 else: result = - 10 proc isOperator(tok: PToken): bool = @@ -202,7 +205,7 @@ proc parseSymbol(p: var TParser): PNode = addSon(result, newIdentNodeP(getIdent("()"), p)) getTok(p) eat(p, tkParRi) - of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: + of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot: var id = p.tok.ident getTok(p) if p.tok.tokType == tkEquals: @@ -494,7 +497,7 @@ proc identOrLiteral(p: var TParser): PNode = proc primary(p: var TParser): PNode = # prefix operator? - if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr): + if isOperator(p.tok): result = newNodeP(nkPrefix, p) var a = newIdentNodeP(p.tok.ident, p) addSon(result, a) @@ -553,18 +556,8 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken = opPrec = getPrecedence(nextop) result = op # return first untreated operator -proc otherExpr(p: var TParser): PNode = - discard lowestExprAux(p, result, - 1) - proc lowestExpr(p: var TParser): PNode = - result = otherExpr(p) - while p.tok.tokType == tkDotDot: - getTok(p) - optInd(p, result) - var a = result - result = newNodeP(nkRange, p) - addSon(result, a) - addSon(result, otherExpr(p)) + discard lowestExprAux(p, result, - 1) proc parseIfExpr(p: var TParser): PNode = result = newNodeP(nkIfExpr, p) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8f8a1dc17..56de998f5 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -828,15 +828,20 @@ proc semSetConstr(c: PContext, n: PNode): PNode = # only semantic checking for all elements, later type checking: var typ: PType = nil for i in countup(0, sonsLen(n) - 1): - if n.sons[i].kind == nkRange: - checkSonsLen(n.sons[i], 2) - n.sons[i].sons[0] = semExprWithType(c, n.sons[i].sons[0]) + if isRange(n.sons[i]): + checkSonsLen(n.sons[i], 3) n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1]) + n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2]) if typ == nil: + typ = skipTypes(n.sons[i].sons[1].typ, + {tyGenericInst, tyVar, tyOrdinal}) + n.sons[i].typ = n.sons[i].sons[2].typ # range node needs type too + elif n.sons[i].kind == nkRange: + # already semchecked + if typ == nil: typ = skipTypes(n.sons[i].sons[0].typ, {tyGenericInst, tyVar, tyOrdinal}) - n.sons[i].typ = n.sons[i].sons[1].typ # range node needs type too - else: + else: n.sons[i] = semExprWithType(c, n.sons[i]) if typ == nil: typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal}) @@ -848,11 +853,12 @@ proc semSetConstr(c: PContext, n: PNode): PNode = addSon(result.typ, typ) for i in countup(0, sonsLen(n) - 1): var m: PNode - if n.sons[i].kind == nkRange: + if isRange(n.sons[i]): m = newNodeI(nkRange, n.sons[i].info) - addSon(m, fitNode(c, typ, n.sons[i].sons[0])) addSon(m, fitNode(c, typ, n.sons[i].sons[1])) - else: + addSon(m, fitNode(c, typ, n.sons[i].sons[2])) + elif n.sons[i].kind == nkRange: m = n.sons[i] # already semchecked + else: m = fitNode(c, typ, n.sons[i]) addSon(result, m) @@ -1086,7 +1092,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = checkMinSonsLen(n, 2) of nkSymChoice: GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments})) - else: - #InternalError(n.info, nodeKindToStr[n.kind]); - GlobalError(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments})) + else: + GlobalError(n.info, errInvalidExpressionX, + renderTree(n, {renderNoComments})) incl(result.flags, nfSem) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 71d523540..0a3daf79c 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -339,11 +339,11 @@ proc semConst(c: PContext, n: PNode): PNode = if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) var def = semAndEvalConstExpr(c, a.sons[2]) # check type compability between def.typ and typ: - if (typ != nil): + if typ != nil: def = fitRemoveHiddenConv(c, typ, def) - else: + else: typ = def.typ - if not typeAllowed(typ, skConst): + if not typeAllowed(typ, skConst): GlobalError(a.info, errXisNoType, typeToString(typ)) v.typ = typ v.ast = def # no need to copy @@ -423,25 +423,12 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = var b = newNodeI(nkBreakStmt, n.info) b.add(ast.emptyNode) stmts.add(b) - -proc createCountupNode(c: PContext, rangeNode: PNode): PNode = - # convert ``in 3..5`` to ``in countup(3, 5)`` - checkSonsLen(rangeNode, 2) - result = newNodeI(nkCall, rangeNode.info) - var countUp = StrTableGet(magicsys.systemModule.Tab, getIdent"countup") - if countUp == nil: GlobalError(rangeNode.info, errSystemNeeds, "countup") - newSons(result, 3) - result.sons[0] = newSymNode(countup) - result.sons[1] = rangeNode.sons[0] - result.sons[2] = rangeNode.sons[1] proc semFor(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 3) var length = sonsLen(n) openScope(c.tab) - if n.sons[length-2].kind == nkRange: - n.sons[length-2] = createCountupNode(c, n.sons[length-2]) n.sons[length-2] = semExprWithType(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] if call.kind != nkCall or call.sons[0].kind != nkSym or diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index bb0bcdf93..ed9b9f4d5 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -116,14 +116,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType = else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct") proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = - if (n.kind != nkRange): InternalError(n.info, "semRangeAux") - checkSonsLen(n, 2) + assert IsRange(n) + checkSonsLen(n, 3) result = newOrPrevType(tyRange, prev, c) result.n = newNodeI(nkRange, n.info) - if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty): + if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): GlobalError(n.Info, errRangeIsEmpty) - var a = semConstExpr(c, n.sons[0]) - var b = semConstExpr(c, n.sons[1]) + var a = semConstExpr(c, n[1]) + var b = semConstExpr(c, n[2]) if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch) if not (a.typ.kind in {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): @@ -138,7 +138,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = proc semRange(c: PContext, n: PNode, prev: PType): PType = result = nil if sonsLen(n) == 2: - if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev) + if isRange(n[1]): result = semRangeAux(c, n[1], prev) else: GlobalError(n.sons[0].info, errRangeExpected) else: GlobalError(n.info, errXExpectsOneTypeParam, "range") @@ -148,7 +148,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyArray, prev, c) if sonsLen(n) == 3: # 3 = length(array indx base) - if n.sons[1].kind == nkRange: indx = semRangeAux(c, n.sons[1], nil) + if isRange(n[1]): indx = semRangeAux(c, n[1], nil) else: indx = semTypeNode(c, n.sons[1], nil) addSon(result, indx) if indx.kind == tyGenericInst: indx = lastSon(indx) @@ -276,26 +276,26 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) = if overlap(t.sons[i].sons[j], ex): LocalError(ex.info, errDuplicateCaseLabel) -proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) = - ex = semConstExpr(c, ex) +proc semBranchExpr(c: PContext, t, e: PNode): PNode = + result = semConstExpr(c, e) checkMinSonsLen(t, 1) - if (cmpTypes(t.sons[0].typ, ex.typ) <= isConvertible): - typeMismatch(ex, t.sons[0].typ, ex.typ) + if cmpTypes(t.sons[0].typ, result.typ) <= isConvertible: + typeMismatch(result, t.sons[0].typ, result.typ) proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, covered: var biggestInt) = for i in countup(0, sonsLen(branch) - 2): var b = branch.sons[i] - if b.kind == nkRange: - checkSonsLen(b, 2) - semBranchExpr(c, t, b.sons[0]) - semBranchExpr(c, t, b.sons[1]) - if emptyRange(b.sons[0], b.sons[1]): - #MessageOut(renderTree(t)); - GlobalError(b.info, errRangeIsEmpty) - covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1 - else: - semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param! + if isRange(b): + checkSonsLen(b, 3) + var r = newNodeI(nkRange, b.info) + r.add(semBranchExpr(c, t, b.sons[1])) + r.add(semBranchExpr(c, t, b.sons[2])) + if emptyRange(r[0], r[1]): GlobalError(b.info, errRangeIsEmpty) + covered = covered + getOrdValue(r[1]) - getOrdValue(r[0]) + 1 + branch.sons[i] = r + else: + branch.sons[i] = semBranchExpr(c, t, b) inc(covered) checkForOverlap(c, t, branch.sons[i], branchIndex) diff --git a/compiler/trees.nim b/compiler/trees.nim index 54f688103..3c8775b87 100755 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2008 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -10,7 +10,7 @@ # tree helper routines import - ast, astalgo, lexer, msgs, strutils + ast, astalgo, lexer, msgs, strutils, wordrecg proc getMagic*(op: PNode): TMagic @@ -106,7 +106,8 @@ proc getOpSym(op: PNode): PSym = proc getMagic(op: PNode): TMagic = case op.kind - of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: + of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkPrefix, nkPostfix, + nkInfix: case op.sons[0].Kind of nkSym: result = op.sons[0].sym.magic else: result = mNone @@ -138,3 +139,8 @@ proc SwapOperands(op: PNode) = var tmp = op.sons[1] op.sons[1] = op.sons[2] op.sons[2] = tmp + +proc IsRange*(n: PNode): bool {.inline.} = + result = n.kind == nkInfix and n[0].kind == nkIdent and + n[0].ident.id == ord(wDotDot) + diff --git a/doc/grammar.txt b/doc/grammar.txt index 4ab5845a8..837a93003 100755 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -1,26 +1,27 @@ module ::= ([COMMENT] [SAD] stmt)* comma ::= ',' [COMMENT] [IND] -operator ::= OP0 | OR | XOR | AND | OP3 | OP4 | OP5 | OP6 | OP7 +operator ::= OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 + | 'or' | 'xor' | 'and' | 'is' | 'isnot' | 'in' | 'notin' - | 'div' | 'mod' | 'shl' | 'shr' | 'not' + | 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..' -prefixOperator ::= OP0 | OP3 | OP4 | OP5 | OP6 | OP7 | 'not' +prefixOperator ::= operator optInd ::= [COMMENT] [IND] optPar ::= [IND] | [SAD] -lowestExpr ::= otherExpr ('..' optInd otherExpr)* -otherExpr ::= orExpr (OP0 optInd orExpr)* -orExpr ::= andExpr (OR | 'xor' optInd andExpr)* -andExpr ::= cmpExpr ('and' optInd cmpExpr)* -cmpExpr ::= ampExpr (OP3 | 'is' | 'isnot' | 'in' | 'notin' optInd ampExpr)* -ampExpr ::= plusExpr (OP4 optInd plusExpr)* -plusExpr ::= mulExpr (OP5 optInd mulExpr)* -mulExpr ::= dollarExpr (OP6 | 'div' | 'mod' | 'shl' | 'shr' optInd dollarExpr)* -dollarExpr ::= primary (OP7 optInd primary)* +lowestExpr ::= orExpr (OP1 optInd orExpr)* +orExpr ::= andExpr (OP2 optInd andExpr)* +andExpr ::= cmpExpr (OP3 optInd cmpExpr)* +cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)* +sliceExpr ::= ampExpr (OP5 optInd ampExpr)* +ampExpr ::= plusExpr (OP6 optInd plusExpr)* +plusExpr ::= mulExpr (OP7 optInd mulExpr)* +mulExpr ::= dollarExpr (OP8 optInd dollarExpr)* +dollarExpr ::= primary (OP9 optInd primary)* -indexExpr ::= '..' [expr] | expr ['=' expr] +indexExpr ::= expr ['=' expr] castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')' addrExpr ::= 'addr' '(' optInd expr optPar ')' @@ -120,7 +121,7 @@ caseStmt ::= 'case' expr [':'] ('of' exprList ':' stmt)* ('elif' expr ':' stmt)* ['else' ':' stmt] whileStmt ::= 'while' expr ':' stmt -forStmt ::= 'for' symbol (comma symbol)* 'in' expr ['..' expr] ':' stmt +forStmt ::= 'for' symbol (comma symbol)* 'in' expr ':' stmt exceptList ::= [qualifiedIdent (comma qualifiedIdent)*] tryStmt ::= 'try' ':' stmt diff --git a/doc/manual.txt b/doc/manual.txt index f9c1fe333..e230861fb 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -346,29 +346,38 @@ notation: ``0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64`` is approximately 1.72826e35 according to the IEEE floating point standard. + +Operators +--------- + +In Nimrod one can define his own operators. An `operator`:idx: is any +combination of the following characters:: + + = + - * / < > + @ $ ~ & % | + ! ? ^ . : \ +These keywords are also operators: +``and or not xor shl shr div mod in notin is isnot``. + +`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they +are used for other notational purposes. + +``*:`` is as a special case the two tokens `*`:tok: and `:`:tok: +(to support ``var v*: T``). + Other tokens ------------ The following strings denote other tokens:: - ( ) { } [ ] , ; [. .] {. .} (. .) - : = ^ .. ` - -`..`:tok: takes precedence over other tokens that contain a dot: `{..}`:tok: are -the three tokens `{`:tok:, `..`:tok:, `}`:tok: and not the two tokens -`{.`:tok:, `.}`:tok:. - -In Nimrod one can define his own operators. An `operator`:idx: is any -combination of the following characters that is not listed above:: - - + - * / < > - = @ $ ~ & % - ! ? ^ . | \ - -These keywords are also operators: -``and or not xor shl shr div mod in notin is isnot``. + ` ( ) { } [ ] , ; [. .] {. .} (. .) + + +The `slice`:idx: operator `..`:tok: takes precedence over other tokens that +contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: +and not the two tokens `{.`:tok:, `.}`:tok:. Syntax @@ -378,7 +387,7 @@ This section lists Nimrod's standard syntax in ENBF. How the parser receives indentation tokens is already described in the `Lexical Analysis`_ section. Nimrod allows user-definable operators. -Binary operators have 8 different levels of precedence. For user-defined +Binary operators have 9 different levels of precedence. For user-defined operators, the precedence depends on the first character the operator consists of. All binary operators are left-associative, except binary operators starting with (or only consisting of) ``^``. @@ -386,14 +395,15 @@ with (or only consisting of) ``^``. ================ ============================================== ================== =============== Precedence level Operators First characters Terminal symbol ================ ============================================== ================== =============== - 7 (highest) ``$ ^`` OP7 - 6 ``* / div mod shl shr %`` ``* % \ /`` OP6 - 5 ``+ -`` ``+ ~ |`` OP5 - 4 ``&`` ``&`` OP4 - 3 ``== <= < >= > != in not_in is isnot`` ``= < > !`` OP3 - 2 ``and`` OP2 - 1 ``or xor`` OP1 - 0 (lowest) ``? @ ` : .`` OP0 + 9 (highest) ``$ ^`` OP9 + 8 ``* / div mod shl shr %`` ``* % \ /`` OP8 + 7 ``+ -`` ``+ ~ |`` OP7 + 6 ``&`` ``&`` OP6 + 5 ``..`` ``.`` OP5 + 4 ``== <= < >= > != in not_in is isnot not`` ``= < > !`` OP4 + 3 ``and`` OP3 + 2 ``or xor`` OP2 + 1 (lowest) `` @ : ? `` OP1 ================ ============================================== ================== =============== @@ -2948,7 +2958,11 @@ string expressions in general: proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} **Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant -strings, because they are precompiled. +strings, because they are precompiled. + +**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime +because of order of initialization problems. + Dynlib pragma for export ------------------------ diff --git a/lib/system.nim b/lib/system.nim index 46ca5b61d..f5757d475 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -115,6 +115,26 @@ type seq*{.magic: "Seq".}[T] ## Generic type to construct sequences. set*{.magic: "Set".}[T] ## Generic type to construct bit sets. +type + TSlice* {.final, pure.}[T] = object ## builtin slice type + a*, b*: T ## the bounds + +proc `..`*[T](a, b: T): TSlice[T] {.noSideEffect, inline.} = + ## `slice`:idx: operator that constructs an interval ``[a, b]``, both `a` + ## and `b` are inclusive. Slices can also be used in the set constructor + ## and in ordinal case statements, but then they are special-cased by the + ## compiler. + result.a = a + result.b = b + +proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} = + ## `slice`:idx: operator that constructs an interval ``[low(T), b]`` + result.a = low(b) + result.b = b + +proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} = + result = value >= s.a and value <= s.b + when not defined(EcmaScript) and not defined(NimrodVM): type TGenericSeq {.compilerproc, pure.} = object @@ -1040,6 +1060,13 @@ iterator countup*[S, T](a: S, b: T, step = 1): T {.inline.} = yield res inc(res, step) +iterator `..`*[S, T](a: S, b: T): T {.inline.} = + ## An alias for `countup`. + var res: T = a + while res <= b: + yield res + inc res + proc min*(x, y: int): int {.magic: "MinI", noSideEffect.} proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.} proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.} diff --git a/lib/wrappers/tcl.nim b/lib/wrappers/tcl.nim index 6f0368574..8836a4296 100755 --- a/lib/wrappers/tcl.nim +++ b/lib/wrappers/tcl.nim @@ -42,7 +42,7 @@ elif defined(macosx): dllName = "libtcl(8.5|8.4|8.3|8.2|8.1).dylib" else: const - dllName = "libtcl(8.5|8.4|8.3|8.2|8.1).so.(1|0)" + dllName = "libtcl(8.5|8.4|8.3|8.2|8.1).so(|.1|.0)" const TCL_DESTROYED* = 0xDEADDEAD TCL_OK* = 0 diff --git a/tests/accept/compile/ttableconstr.nim b/tests/accept/compile/ttableconstr.nim new file mode 100644 index 000000000..9433e9985 --- /dev/null +++ b/tests/accept/compile/ttableconstr.nim @@ -0,0 +1,16 @@ +# Test if the new table constructor syntax works: + +template ignoreExpr(e: expr): stmt = + nil + +# test first class '..' syntactical citizen: +ignoreExpr x <> 2..4 +# test table constructor: +ignoreExpr({:}) +ignoreExpr({2: 3, "key": "value"}) + +# NEW: +assert 56 in 50..100 + +assert 56 in ..60 + diff --git a/todo.txt b/todo.txt index e26f613f9..96818da7d 100755 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,5 @@ - clean up the tests! +- fake-consts and semantic checking for table constructor High priority (version 0.9.0) @@ -28,7 +29,6 @@ To implement * hash tables and sets; count tables; ordered dicts * distinct types for array/seq indexes -* constant sequences * implement closures for the C code generator * GC: marker procs for native Nimrod GC and Boehm GC |