diff options
-rwxr-xr-x | compiler/main.nim | 13 | ||||
-rw-r--r-- | compiler/service.nim | 71 | ||||
-rwxr-xr-x | compiler/suggest.nim | 21 | ||||
-rwxr-xr-x | doc/nimrodc.txt | 1 | ||||
-rwxr-xr-x | doc/tut1.txt | 10 | ||||
-rwxr-xr-x | doc/tut2.txt | 4 | ||||
-rwxr-xr-x | lib/system/alloc.nim | 3 | ||||
-rwxr-xr-x | packages/docutils/rst.nim | 15 | ||||
-rwxr-xr-x | readme.txt | 2 | ||||
-rwxr-xr-x | web/index.txt | 26 | ||||
-rwxr-xr-x | web/question.txt | 16 |
11 files changed, 142 insertions, 40 deletions
diff --git a/compiler/main.nim b/compiler/main.nim index 37feabd17..dec393c50 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -16,7 +16,7 @@ import wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, ecmasgen, platform, nimconf, importer, passaux, depends, evals, types, idgen, - tables, docgen2 + tables, docgen2, service const has_LLVM_Backend = false @@ -292,5 +292,16 @@ proc MainCommand = gCmd = cmdIdeTools wantMainModule() CommandSuggest() + of "serve": + gCmd = cmdIdeTools + msgs.gErrorMax = high(int) # do not stop after first error + semanticPasses() + # no need to write rod files and would slow down things: + #registerPass(rodwrite.rodwritePass()) + discard CompileModule(options.libpath / "system", {sfSystemModule}) + service.serve(proc () = + let projectFile = gProjectFull + discard CompileModule(projectFile, {sfMainModule}) + ) else: rawMessage(errInvalidCommandX, command) diff --git a/compiler/service.nim b/compiler/service.nim new file mode 100644 index 000000000..95fb11022 --- /dev/null +++ b/compiler/service.nim @@ -0,0 +1,71 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Implements the "compiler as a service" feature. + +import + sockets, + times, commands, options, msgs, nimconf, + extccomp, strutils, os, platform, main, parseopt + +# We cache modules and the dependency graph. However, we don't check for +# file changes but expect the client to tell us about them, otherwise the +# repeated CRC calculations may turn out to be too slow. + +var + arguments: string = "" # the arguments to be passed to the program that + # should be run + +proc ProcessCmdLine(pass: TCmdLinePass, cmd: string) = + # XXX remove duplication with nimrod.nim + var p = parseopt.initOptParser(cmd) + var argsCount = 0 + while true: + parseopt.next(p) + case p.kind + of cmdEnd: break + of cmdLongOption, cmdShortOption: + # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") + # we fix this here + var bracketLe = strutils.find(p.key, '[') + if bracketLe >= 0: + var key = substr(p.key, 0, bracketLe - 1) + var val = substr(p.key, bracketLe + 1) & ':' & p.val + ProcessSwitch(key, val, pass, gCmdLineInfo) + else: + ProcessSwitch(p.key, p.val, pass, gCmdLineInfo) + of cmdArgument: + if argsCount == 0: + options.command = p.key + else: + if pass == passCmd1: options.commandArgs.add p.key + if argsCount == 1: + # support UNIX style filenames anywhere for portable build scripts: + options.gProjectName = unixToNativePath(p.key) + arguments = cmdLineRest(p) + break + inc argsCount + + if pass == passCmd2: + if optRun notin gGlobalOptions and arguments != "": + rawMessage(errArgsNeedRunOption, []) + +proc serve*(action: proc (){.nimcall.}) = + var server = Socket() + let p = getConfigVar("server.port") + let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort + server.bindAddr(port, getConfigVar("server.address")) + var inp = "".TaintedString + server.listen() + while true: + var client = InvalidSocket + accept(server, client) + discard client.recvLine(inp) + processCmdLine(passCmd2, inp.string) + action() diff --git a/compiler/suggest.nim b/compiler/suggest.nim index daecf44b8..d33f9a7bd 100755 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -18,6 +18,11 @@ const sectionContext = "con" sectionUsage = "use" +proc SuggestWriteln(s: string) = + if gSilence == 0: + Writeln(stdout, s) + + proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string = result = section result.add(sep) @@ -51,7 +56,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = proc suggestField(c: PContext, s: PSym, outputs: var int) = if filterSym(s) and fieldVisible(c, s): - OutWriteln(SymToStr(s, isLocal=true, sectionSuggest)) + SuggestWriteln(SymToStr(s, isLocal=true, sectionSuggest)) inc outputs when not defined(nimhygiene): @@ -62,7 +67,7 @@ template wholeSymTab(cond, section: expr) {.immediate.} = for item in items(c.tab.stack[i]): let it {.inject.} = item if cond: - OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, section)) + SuggestWriteln(SymToStr(it, isLocal = i > ModuleTablePos, section)) inc outputs proc suggestSymList(c: PContext, list: PNode, outputs: var int) = @@ -120,7 +125,7 @@ proc suggestEverything(c: PContext, n: PNode, outputs: var int) = for i in countdown(c.tab.tos-1, 1): for it in items(c.tab.stack[i]): if filterSym(it): - OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal = i > ModuleTablePos, sectionSuggest)) inc outputs proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) = @@ -134,12 +139,12 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) = # all symbols accessible, because we are in the current module: for it in items(c.tab.stack[ModuleTablePos]): if filterSym(it): - OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest)) inc outputs else: for it in items(n.sym.tab): if filterSym(it): - OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest)) inc outputs else: # fallback: @@ -224,15 +229,15 @@ var proc findUsages(node: PNode, s: PSym) = if usageSym == nil and isTracked(node.info, s.name.s.len): usageSym = s - OutWriteln(SymToStr(s, isLocal=false, sectionUsage)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage)) elif s == usageSym: if lastLineInfo != node.info: - OutWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info)) lastLineInfo = node.info proc findDefinition(node: PNode, s: PSym) = if isTracked(node.info, s.name.s.len): - OutWriteln(SymToStr(s, isLocal=false, sectionDef)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionDef)) quit(0) proc suggestSym*(n: PNode, s: PSym) {.inline.} = diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 7b969c3bb..117d226a6 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -159,6 +159,7 @@ Define Effect systems. See the documentation of the `gc <gc.html>`_ for further information. ``nodejs`` The EcmaScript target is actually ``node.js``. +``ssl`` Enables OpenSSL support for the sockets module. ================== ========================================================= diff --git a/doc/tut1.txt b/doc/tut1.txt index 833d364df..c6e4edb82 100755 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -16,10 +16,10 @@ Introduction </p></blockquote> -This document is a tutorial for the programming language *Nimrod*. After this -tutorial you will have a decent knowledge of Nimrod. This tutorial assumes -that you are familiar with basic programming concepts like variables, types -or statements. +This document is a tutorial for the programming language *Nimrod*. +This tutorial assumes that you are familiar with basic programming concepts +like variables, types or statements but is kept very basic. The manual +contains many more examples of the advanced language features. @@ -593,7 +593,7 @@ caller, a ``var`` parameter can be used: In the example, ``res`` and ``remainder`` are `var parameters`. Var parameters can be modified by the procedure and the changes are -visible to the caller. Note that the above example would better make usage of +visible to the caller. Note that the above example would better make use of a tuple as a return value instead of using var parameters. diff --git a/doc/tut2.txt b/doc/tut2.txt index 3882296be..149d444f0 100755 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -16,7 +16,9 @@ Introduction This document is a tutorial for the advanced constructs of the *Nimrod* -programming language. +programming language. **Note that this document is somewhat obsolete as +the `manual <manual.html>`_ contains many more examples of the advanced +language features.** Pragmas diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 82755ca86..d6093c5b1 100755 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -729,7 +729,8 @@ template InstantiateForRegion(allocator: expr) = proc interiorAllocatedPtr*(p: pointer): pointer = result = interiorAllocatedPtr(allocator, p) - proc isAllocatedPtr*(p: pointer): bool = + proc isAllocatedPtr*(p: pointer): bool = + let p = cast[pointer](cast[TAddress](p)-%TAddress(sizeof(TCell))) result = isAllocatedPtr(allocator, p) proc deallocOsPages = deallocOsPages(allocator) diff --git a/packages/docutils/rst.nim b/packages/docutils/rst.nim index 333ef11d9..debbd2520 100755 --- a/packages/docutils/rst.nim +++ b/packages/docutils/rst.nim @@ -818,7 +818,7 @@ proc getDirective(p: var TRstParser): string = proc parseComment(p: var TRstParser): PRstNode = case p.tok[p.idx].kind of tkIndent, tkEof: - if p.tok[p.idx + 1].kind == tkIndent: + if p.tok[p.idx].kind != tkEof and p.tok[p.idx + 1].kind == tkIndent: inc(p.idx) # empty comment else: var indent = p.tok[p.idx].ival @@ -1348,9 +1348,20 @@ proc parseSectionWrapper(p: var TRstParser): PRstNode = while (result.kind == rnInner) and (len(result) == 1): result = result.sons[0] +proc `$`(t: TToken): string = + result = $t.kind & ' ' & (if isNil(t.symbol): "NIL" else: t.symbol) + proc parseDoc(p: var TRstParser): PRstNode = result = parseSectionWrapper(p) - if p.tok[p.idx].kind != tkEof: rstMessage(p, meGeneralParseError) + if p.tok[p.idx].kind != tkEof: + when false: + assert isAllocatedPtr(cast[pointer](p.tok)) + for i in 0 .. high(p.tok): + assert isNil(p.tok[i].symbol) or + isAllocatedPtr(cast[pointer](p.tok[i].symbol)) + echo "index: ", p.idx, " length: ", high(p.tok), "##", + p.tok[p.idx-1], p.tok[p.idx], p.tok[p.idx+1] + rstMessage(p, meGeneralParseError) type TDirFlag = enum diff --git a/readme.txt b/readme.txt index e2ac5c7c4..c4d3b2ba7 100755 --- a/readme.txt +++ b/readme.txt @@ -11,7 +11,7 @@ can be used to create domain specific languages. *Nimrod* is a compiled, garbage-collected systems programming language which has an excellent productivity/performance ratio. Nimrod's design -focuses on the 3E: efficiency, expressiveness, elegance (in the order of +focuses on efficiency, expressiveness, elegance (in the order of priority). See the file ``install.txt`` for installation instructions. See the file diff --git a/web/index.txt b/web/index.txt index 26725ffe9..03f11ed49 100755 --- a/web/index.txt +++ b/web/index.txt @@ -8,23 +8,20 @@ Home -- D. E. Knuth -**This page is about the Nimrod programming language, which combines Lisp's -power with Python's readability and C's performance.** +**Nimrod combines Lisp's power with Python's readability and C's performance.** Welcome to Nimrod ----------------- -**Nimrod** is a new statically typed, imperative -programming language, that supports procedural, object oriented, functional -and generic programming styles while remaining simple and efficient. -A special feature that Nimrod inherited from Lisp is that Nimrod's abstract -syntax tree (*AST*) is part of the specification - this allows a powerful -macro system which allows domain specific languages. - -Nimrod is a compiled, garbage-collected systems programming language -which has an excellent productivity/performance ratio. Nimrod's design -focuses on the 3E: efficiency, expressiveness, elegance (in the order of -priority). +**Nimrod** is a statically typed, imperative programming language that tries to +give the programmer ultimate power without compromises on runtime efficiency. +This means it focuses on compile-time mechanisms in all their +various forms. Beneath a nice infix/indentation based syntax with a +powerful (AST based, hygienic) macro system lies a semantic model that supports +a soft realtime GC on thread local heaps. Asynchronous message passing is used +between threads, so no "stop the world" mechanism is necessary. An unsafe +shared memory heap is also provided for the increased efficiency that results +from that model. .. container:: snippet @@ -33,7 +30,8 @@ priority). .. code-block:: nimrod import strutils - echo "Type in a list of ints of ints (separate by whitespace): " + # Prints the maximum integer from a list of integers + # delimited by whitespace read from stdin. let tokens = stdin.readLine.split echo tokens.each(parseInt).max, " is the maximum." diff --git a/web/question.txt b/web/question.txt index ffa26a364..46cbb4f88 100755 --- a/web/question.txt +++ b/web/question.txt @@ -9,13 +9,15 @@ General What is Nimrod? --------------- -Nimrod is a new statically typed, imperative -programming language, that supports procedural, functional, object oriented and -generic programming styles while remaining simple and efficient. A special -feature that Nimrod inherited from Lisp is that Nimrod's abstract syntax tree -(*AST*) is part of the specification - this allows a powerful macro system which -can be used to create domain specific languages. Nimrod does not sacrifice -flexibility for speed. You get both. +Nimrod is a statically typed, imperative programming language that tries to +give the programmer ultimate power without compromises on runtime efficiency. +This means it focuses on compile-time mechanisms in all their +various forms. Beneath a nice infix/indentation based syntax with a +powerful (AST based, hygienic) macro system lies a semantic model that supports +a soft realtime GC on thread local heaps. Asynchronous message passing is used +between threads, so no "stop the world" mechanism is necessary. An unsafe +shared memory heap is also provided for the increased efficiency that results +from that model. .. Don't give me that marketing crap. What is Nimrod? |