summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-09-03 19:45:04 +0200
committerAraq <rumpf_a@web.de>2014-09-03 19:45:04 +0200
commit201a08e9a54cf129aca33d43d57cadd29e564149 (patch)
tree80cdd55e84eff96ad134f3879b85dc479aa3f699
parentd1d7d9e3fe0c306ebbe1c21b0ec0a27ea1e05528 (diff)
downloadNim-201a08e9a54cf129aca33d43d57cadd29e564149.tar.gz
fixes #903, fixes #1513
-rw-r--r--compiler/commands.nim34
-rw-r--r--compiler/main.nim6
-rw-r--r--compiler/nim.nim6
-rw-r--r--compiler/pretty.nim12
-rw-r--r--compiler/service.nim30
-rw-r--r--compiler/vmgen.nim25
-rw-r--r--lib/pure/asynchttpserver.nim2
-rw-r--r--tests/vm/tasmparser.nim174
-rw-r--r--tests/vm/tcompiletimetable.nim11
-rw-r--r--todo.txt4
10 files changed, 249 insertions, 55 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 54d2ed6a4..2a2e0c4ee 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -26,7 +26,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
 
 import 
   os, msgs, options, nversion, condsyms, strutils, extccomp, platform, lists, 
-  wordrecg, parseutils, nimblecmd, idents
+  wordrecg, parseutils, nimblecmd, idents, parseopt
 
 # but some have deps to imported modules. Yay.
 bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
@@ -43,7 +43,7 @@ type
   TCmdLinePass* = enum 
     passCmd1,                 # first pass over the command line
     passCmd2,                 # second pass over the command line
-    passPP                    # preprocessor called ProcessCommand()
+    passPP                    # preprocessor called processCommand()
 
 proc processCommand*(switch: string, pass: TCmdLinePass)
 proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
@@ -573,3 +573,33 @@ proc processCommand(switch: string, pass: TCmdLinePass) =
   var cmd, arg: string
   splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
   processSwitch(cmd, arg, pass, gCmdLineInfo)
+
+
+var
+  arguments* = ""
+    # the arguments to be passed to the program that
+    # should be run
+
+proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
+  # 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)
+
+proc processArgument*(pass: TCmdLinePass; p: OptParser; 
+                      argsCount: var int): bool =
+  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)
+      result = true
+  inc argsCount
diff --git a/compiler/main.nim b/compiler/main.nim
index 58833f60c..0bb057df5 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -164,12 +164,6 @@ proc commandEval(exp: string) =
   var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
   evalNim(echoExp.parseString, makeStdinModule())
 
-proc commandPrettyOld =
-  var projectFile = addFileExt(mainCommandArg(), NimExt)
-  var module = parseFile(projectFile.fileInfoIdx)
-  if module != nil:
-    renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
-
 proc commandPretty =
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 27222ca57..a87e0a1ac 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -58,7 +58,7 @@ proc handleCmdLine() =
     if msgs.gErrorCounter == 0:
       when hasTinyCBackend:
         if gCmd == cmdRun:
-          tccgen.run(service.arguments)
+          tccgen.run(commands.arguments)
       if optRun in gGlobalOptions:
         if gCmd == cmdCompileToJS:
           var ex: string
@@ -67,7 +67,7 @@ proc handleCmdLine() =
           else:
             ex = quoteShell(
               completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
-          execExternalProgram("node " & ex & ' ' & service.arguments)
+          execExternalProgram("node " & ex & ' ' & commands.arguments)
         else:
           var binPath: string
           if options.outFile.len > 0:
@@ -77,7 +77,7 @@ proc handleCmdLine() =
             # Figure out ourselves a valid binary name.
             binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
           var ex = quoteShell(binPath)
-          execExternalProgram(ex & ' ' & service.arguments)
+          execExternalProgram(ex & ' ' & commands.arguments)
 
 when declared(GC_setMaxPause):
   GC_setMaxPause 2_000
diff --git a/compiler/pretty.nim b/compiler/pretty.nim
index dfc164208..6ee931951 100644
--- a/compiler/pretty.nim
+++ b/compiler/pretty.nim
@@ -14,14 +14,20 @@ import
   strutils, os, options, ast, astalgo, msgs, ropes, idents, passes,
   intsets, strtabs, semdata, prettybase
 
+
+type
+  StyleCheck* {.pure.} = enum None, Confirm, Auto
+
+var
+  gOverWrite* = true
+  gStyleCheck*: StyleCheck
+  gCheckExtern*: bool
+
 type
   TGen = object of TPassContext
     module*: PSym
   PGen = ref TGen
 
-var
-  gCheckExtern: bool
-
 proc overwriteFiles*() =
   let overWrite = options.getConfigVar("pretty.overwrite").normalize != "off"
   let doStrip = options.getConfigVar("pretty.strip").normalize == "on"
diff --git a/compiler/service.nim b/compiler/service.nim
index f0eeb0ed5..4a1b296cd 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -25,39 +25,17 @@ var
   lastCaasCmd* = ""
     # in caas mode, the list of defines and options will be given at start-up?
     # it's enough to check that the previous compilation command is the same?
-  arguments* = ""
-    # the arguments to be passed to the program that
-    # should be run
 
 proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
   var p = parseopt.initOptParser(cmd)
   var argsCount = 0
-  while true: 
+  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 cmdEnd: break
+    of cmdLongoption, cmdShortOption: processSwitch(pass, p)
     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 processArgument(pass, p, argsCount): break
   if pass == passCmd2:
     if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
       rawMessage(errArgsNeedRunOption, [])
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 05c894ee3..718c07243 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -43,18 +43,19 @@ type
 proc debugInfo(info: TLineInfo): string =
   result = info.toFilename.splitFile.name & ":" & $info.line
 
-proc codeListing(c: PCtx, result: var string, start=0) =
+proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
-  
-  for i in start.. < c.code.len:
+
+  let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
+  for i in start..last:
     let x = c.code[i]
     if x.opcode in relativeJumps:
       jumpTargets.incl(i+x.regBx-wordExcess)
 
   # for debugging purposes
   var i = start
-  while i < c.code.len:
+  while i <= last:
     if i in jumpTargets: result.addf("L$1:\n", i)
     let x = c.code[i]
 
@@ -82,9 +83,9 @@ proc codeListing(c: PCtx, result: var string, start=0) =
     result.add("\n")
     inc i
 
-proc echoCode*(c: PCtx, start=0) {.deprecated.} =
+proc echoCode*(c: PCtx; start=0; last = -1) {.deprecated.} =
   var buf = ""
-  codeListing(c, buf, start)
+  codeListing(c, buf, start, last)
   echo buf
 
 proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
@@ -495,6 +496,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
   c.freeTempRange(x, n.len)
 
 template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
+proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
 
 proc needsAsgnPatch(n: PNode): bool = 
   n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
@@ -637,8 +639,10 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   c.freeTemp(tmp)
 
 proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
+  var x = n.sons[1]
+  if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0]
   let
-    dest = c.genx(n.sons[1], {gfAddrOf})
+    dest = c.genx(x)
     tmp = c.genx(n.sons[2])
   c.gABC(n, opc, dest, tmp, 0)
   #c.genAsgnPatch(n.sons[1], dest)
@@ -1053,6 +1057,8 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
   # nkAddr we must not use 'unneededIndirection', but for deref we use it.
   if not isAddr and unneededIndirection(n.sons[0]):
     gen(c, n.sons[0], dest, newflags)
+  elif isGlobal(n.sons[0]):
+    gen(c, n.sons[0], dest, flags+{gfAddrOf})
   else:
     let tmp = c.genx(n.sons[0], newflags)
     if dest < 0: dest = c.getTemp(n.typ)
@@ -1062,6 +1068,9 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
         c.gABC(n, opcNodeToReg, dest, dest)
     elif c.prc.slots[tmp].kind >= slotTempUnknown:
       gABC(c, n, opcAddrNode, dest, tmp)
+      # XXX this can still be wrong sometimes; hopefully it's only generated
+      # in call contexts, where it is safe
+      #message(n.info, warnUser, "suspicious opcode used")
     else:
       gABC(c, n, opcAddrReg, dest, tmp)
     c.freeTemp(tmp)
@@ -1247,6 +1256,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
       c.gABx(n, opcLdGlobal, cc, s.position)
       c.gABC(n, opcNodeToReg, dest, cc)
       c.freeTemp(cc)
+    elif gfAddrOf in flags:
+      c.gABx(n, opcLdGlobalAddr, dest, s.position)
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
   else:
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index e2e9e1881..c2cb7e15c 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -187,7 +187,7 @@ proc processClient(client: PAsyncSocket, address: string,
       request.client.close()
       break
 
-proc serve*(server: PAsyncHttpServer, port: TPort,
+proc serve*(server: PAsyncHttpServer, port: Port,
             callback: proc (request: TRequest): PFuture[void] {.closure,gcsafe.},
             address = "") {.async.} =
   ## Starts the process of listening for incoming HTTP connections on the
diff --git a/tests/vm/tasmparser.nim b/tests/vm/tasmparser.nim
new file mode 100644
index 000000000..24ccb2ec8
--- /dev/null
+++ b/tests/vm/tasmparser.nim
@@ -0,0 +1,174 @@
+
+# bug #1513
+
+import os, parseutils, strutils, ropes, macros
+
+var
+  code {.compileTime.} = ""
+  start {.compileTime.} = 0
+  line {.compileTime.} = 1
+  cpp {.compileTime.} = ""
+  token {.compileTime.} = ""
+
+proc log (msg: string) {.compileTime.} =
+    echo msg
+
+proc asmx64 () {.compileTime} =
+
+  #log "code = $1" % code
+
+  const asmx64pre = "{.emit: \"\"\"{x64asm& x= *x64asm_ptr(`asm0`); try {"
+  const asmx64post = "} catch (Xbyak::Error e) { printf (\"asmx64 error: %s\\n\", e.what ()); }}\"\"\".} "
+
+  const xp = "x."
+
+  const symbolStart = { '_', 'a'..'z', 'A' .. 'Z' }
+  const symbol = { '0'..'9' } + symbolStart
+  const eolComment = { ';' }
+  const endOfLine = { '\l', '\r' }
+  const leadingWhiteSpace = { ' ' }
+
+  const end_or_comment = endOfLine + eolComment + { '\0' }
+
+  const passthrough_start = { '{', '`' }
+  const passthrough_end = { '}', '`', '\0' }
+
+  const end_or_symbol_or_comment_or_passthrough = symbolStart + end_or_comment + passthrough_start
+
+
+  proc abortAsmParse (err:string) =
+    #
+
+  let codeLen = code.len
+  #let codeEnd = codeLen-1
+  cpp.add asmx64pre
+
+  #log "{$1}\n" % [code]
+
+  type asmParseState = enum leading, mnemonic, betweenArguments, arguments, endCmd, skipToEndOfLine
+
+  var state:asmParseState = leading
+
+  proc checkEnd (err:string) =
+    let ch = code [start]
+    if int (ch) == 0:
+      abortAsmParse (err)
+
+  proc get_passthrough () =
+    inc start
+    let prev_start = start
+    let prev_token = token
+    start += code.parseUntil (token, passthrough_end, start)
+    checkEnd ("Failed to find passthrough end delimiter from offset $1 for:$2\n$3" % [$prev_start, $(code [prev_start-prev_token.len..prev_start]), token[1..token.len-1]])
+    inc start
+    cpp.add "`"
+    cpp.add token
+    cpp.add "`"
+
+  var inparse = true
+
+  proc checkCmdEnd () =
+    if codeLen == start:
+      state = endCmd
+      inparse = false
+
+  while inparse:
+    checkCmdEnd ()
+
+    log ("state=$1 start=$2" % [$state, $start])
+
+    case state:
+    of leading:
+      
+      echo "b100 ", start
+      start += code.skipWhile (leadingWhiteSpace, start)
+      echo "b200 ", start
+      let ch = code [start]
+      if ch in endOfLine:
+        inc (line)
+        #echo "c100 ", start, ' ', code 
+        start += code.skipWhile (endOfline, start)
+        #echo "c200 ", start, ' ', code 
+        continue
+      elif ch in symbolStart:
+        state = mnemonic
+      elif ch in eolComment:
+        state = skipToEndOfLine
+      elif ch in passthrough_start:
+        get_passthrough ()        
+        echo "d100 ", start
+        start += code.parseUntil (token, end_or_symbol_or_comment_or_passthrough, start)
+        echo "d200 ", start
+        cpp.add token
+        state = mnemonic
+      elif int (ch) == 0:
+        break
+      else:
+        abortAsmParse ("after '$3' illegal character at offset $1: $2" % [$start, $(int (ch)), token])
+
+    of mnemonic:
+      echo "e100 ", start
+      start += code.parseWhile (token, symbol, start)
+      echo "e200 ", start
+      cpp.add xp
+      cpp.add token
+      cpp.add "("
+      state = betweenArguments
+
+    of betweenArguments:
+      let tmp = start
+      let rcode = code
+      start += rcode.parseUntil (token, end_or_symbol_or_comment_or_passthrough, tmp)
+      cpp.add token
+
+      if codeLen <= start:
+        state = endCmd
+        continue
+        
+      let ch = code [start]
+      if ch in passthrough_start:
+        get_passthrough ()
+        continue
+      if (ch in {'x', 'X'}) and ('0' == code [start-1]):
+        token = $(code [start])
+        cpp.add token
+        inc start
+        continue
+      state = arguments
+
+    of arguments:
+      if code [start] in end_or_comment:
+        state = endCmd
+        continue
+      start += code.parseWhile (token, symbol, start)
+      cpp.add xp
+      cpp.add token
+      state = betweenArguments
+
+    of endCmd:
+      cpp.add ");\n"
+      state = skipToEndOfLine
+    
+    of skipToEndOfLine:
+      echo "a100 ", start
+      start += code.skipUntil (endOfLine, start)
+      echo "a200 ", start
+      start += code.skipWhile (endOfline, start)
+      echo "a300 ", start
+      inc line
+      state = leading
+
+  cpp.add asmx64post
+
+  echo ($cpp)
+
+macro asmx64x (code_in:expr) : stmt =
+  code = $code_in
+  echo ("code.len = $1, code = >>>$2<<<" % [$code.len, code])
+  asmx64 ()
+  discard result
+
+asmx64x """
+    mov rax, {m}
+    ret
+"""
diff --git a/tests/vm/tcompiletimetable.nim b/tests/vm/tcompiletimetable.nim
index f1d3ecd4e..df6ead56f 100644
--- a/tests/vm/tcompiletimetable.nim
+++ b/tests/vm/tcompiletimetable.nim
@@ -2,18 +2,19 @@ discard """
   msg: '''2
 3
 4:2
-  '''
+Got Hi
+Got Hey'''
 """
 
 # bug #404
 
-import macros, tables
+import macros, tables, strtabs
 
 var ZOOT{.compileTime.} = initTable[int, int](2)
 var iii {.compiletime.} = 1
 
 macro zoo:stmt=
-  zoot[iii] = iii*2
+  ZOOT[iii] = iii*2
   inc iii
   echo iii
 
@@ -29,9 +30,7 @@ tupleUnpack
 
 # bug #903
 
-import strtabs
-
-var x {.compileTime.}: PStringTable
+var x {.compileTime.}: StringTableRef
 
 macro addStuff(stuff, body: expr): stmt {.immediate.} =
   result = newNimNode(nnkStmtList)
diff --git a/todo.txt b/todo.txt
index 319704925..acdec7547 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,9 @@
 version 0.10
 ============
 
-- Test nim pretty on various babel packages
+- Write new nimfix tool
+- Test nimfix on various babel packages
+- Pegs do not work at compile-time
 
 
 version 0.9.6