summary refs log blame commit diff stats
path: root/compiler/service.nim
blob: 2b861e1c76500edb890fe0f3d99b5bbdc713e89a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                   
      
                                          
                                            
 


                



                                                                         







                                                                              
 
                                                       





                                     
                                      





                                                                   
                                                   
            
                                                       
















                                                                             



                                 

                         

                     





                                       
                  
             
                       
 
               
                 
                           
                                                        













                                                                           


                                    
#
#
#           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
  times, commands, options, msgs, nimconf,
  extccomp, strutils, os, platform, parseopt

when useCaas:
  import sockets

# 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
  curCaasCmd* = ""
  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: 
    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.}) =
  template execute(cmd) =
    curCaasCmd = cmd
    processCmdLine(passCmd2, cmd)
    action()
    gDirtyBufferIdx = 0
    gDirtyOriginalIdx = 0
    gErrorCounter = 0

  let typ = getConfigVar("server.type")
  case typ
  of "stdin":
    while true:
      var line = stdin.readLine.string
      if line == "quit": quit()
      execute line
      echo ""
      flushFile(stdout)

  of "tcp", "":
    when useCaas:
      var server = socket()
      if server == invalidSocket: osError(osLastError())
      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()
      new(stdoutSocket)
      while true:
        accept(server, stdoutSocket)
        stdoutSocket.readLine(inp)
        execute inp.string
        stdoutSocket.send("\c\L")
        stdoutSocket.close()
    else:
      quit "server.type not supported; compiler built without caas support"
  else:
    echo "Invalid server.type:", typ
    quit 1