about summary refs log tree commit diff stats
Commit message (Expand)AuthorAgeFilesLines
...
* windows which have set transient_for hint inherit the transient_for window ta...arg@localhost.10kloc.org2006-08-212-2/+7
* after switching to OpenBSD again, I switched back to a saner color schemearg@localhost.10kloc.org2006-08-212-8/+10
* applied Sanders focus_* patches, removed the unnecessary clean-prefix from th...Anselm R.Garbe2006-08-212-28/+32
* small renamings of two static functionsAnselm R.Garbe2006-08-212-5/+5
* small changes to dwm.1, rearranged order within main event loopAnselm R.Garbe2006-08-213-11/+13
* applied Sanders patchAnselm R.Garbe2006-08-181-6/+2
* made a new client position strategy similiar to that one proposed by Sander, ...Anselm R.Garbe2006-08-181-7/+7
* fixed a bug reported by sanderAnselm R.Garbe2006-08-171-1/+1
* applied the shorter xprop commandAnselm R.Garbe2006-08-171-1/+1
* centering apps only if transient_for is not(!) setAnselm R.Garbe2006-08-171-9/+1
* fixed issue Sander reportedAnselm R.Garbe2006-08-171-4/+3
* corrected order of cleanup code Anselm R.Garbe2006-08-161-1/+1
* condition was insufficientAnselm R.Garbe2006-08-161-2/+2
* fixed issue reported by sanderAnselm R.Garbe2006-08-162-3/+6
* added general centralization rule for new clients (works around various borke...Anselm R.Garbe2006-08-162-2/+14
* removed leading ;Anselm R.Garbe2006-08-161-1/+1
* added sample command to config.default.h to highlight how to query class:inst...Anselm R.Garbe2006-08-161-0/+2
* applied another config.mk patch made by sanderAnselm R.Garbe2006-08-161-1/+1
* we close stdin as wellAnselm R.Garbe2006-08-161-3/+4
* simplified sort | uniq into sort -u (on my boxes all sort support -u)Anselm R.Garbe2006-08-161-1/+1
* fixing small bug in config.mkAnselm R.Garbe2006-08-151-2/+2
* adding forgetten whitespaceAnselm R.Garbe2006-08-151-1/+1
* added gmane archive to dwm.htmlAnselm R.Garbe2006-08-151-1/+1
* Added tag 0.9 for changeset fae61afa861755636c4a1070694209ace8efbb6cAnselm R.Garbe2006-08-151-0/+1
* prepared dwm-0.9 0.9Ancolor: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#
#
#           The Nim Compiler
#        (c) Copyright 2013 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Template evaluation engine. Now hygienic.

import
  strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
  rodread

type
  TemplCtx {.pure, final.} = object
    owner, genSymOwner: PSym
    instLines: bool   # use the instantiation lines numbers
    mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
                      # new symbol

proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
  result = copyNode(a)
  if ctx.instLines: result.info = b.info

proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
  template handleParam(param) =
    let x = param
    if x.kind == nkArgList:
      for y in items(x): result.add(y)
    else:
      result.add copyTree(x)

  case templ.kind
  of nkSym:
    var s = templ.sym
    if s.owner.id == c.owner.id:
      if s.kind == skParam and sfGenSym notin s.flags:
        handleParam actual.sons[s.position]
      elif s.kind == skGenericParam or
           s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam:
        handleParam actual.sons[s.owner.typ.len + s.position - 1]
      else:
        internalAssert sfGenSym in s.flags
        var x = PSym(idTableGet(c.mapping, s))
        if x == nil:
          x = copySym(s, false)
          x.owner = c.genSymOwner
          idTablePut(c.mapping, s, x)
        result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
    else:
      result.add copyNode(c, templ, actual)
  of nkNone..nkIdent, nkType..nkNilLit: # atom
    result.add copyNode(c, templ, actual)
  else:
    var res = copyNode(c, templ, actual)
    for i in countup(0, sonsLen(templ) - 1):
      evalTemplateAux(templ.sons[i], actual, c, res)
    result.add res

proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
  # if the template has zero arguments, it can be called without ``()``
  # `n` is then a nkSym or something similar
  var totalParams = case n.kind
    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: n.len-1
    else: 0

  var
    # XXX: Since immediate templates are not subject to the
    # standard sigmatching algorithm, they will have a number
    # of deficiencies when it comes to generic params:
    # Type dependencies between the parameters won't be honoured
    # and the bound generic symbols won't be resolvable within
    # their bodies. We could try to fix this, but it may be
    # wiser to just deprecate immediate templates and macros
    # now that we have working untyped parameters.
    genericParams = if sfImmediate in s.flags or fromHlo: 0
                    else: s.ast[genericParamsPos].len
    expectedRegularParams = <s.typ.len
    givenRegularParams = totalParams - genericParams
  if givenRegularParams < 0: givenRegularParams = 0

  if totalParams > expectedRegularParams + genericParams:
    globalError(n.info, errWrongNumberOfArguments)

  if totalParams < genericParams:
    globalError(n.info, errMissingGenericParamsForTemplate,
                n.renderTree)

  result = newNodeI(nkArgList, n.info)
  for i in 1 .. givenRegularParams:
    result.addSon n[i]

  # handle parameters with default values, which were
  # not supplied by the user
  for i in givenRegularParams+1 .. expectedRegularParams:
    let default = s.typ.n.sons[i].sym.ast
    if default.isNil or default.kind == nkEmpty:
      localError(n.info, errWrongNumberOfArguments)
      addSon(result, ast.emptyNode)
    else:
      addSon(result, default.copyTree)

  # add any generic paramaters
  for i in 1 .. genericParams:
    result.addSon n.sons[givenRegularParams + i]

var evalTemplateCounter* = 0
  # to prevent endless recursion in templates instantiation

proc wrapInComesFrom*(info: TLineInfo; res: PNode): PNode =
  when true:
    result = res
    result.info = info
    if result.kind in {nkStmtList, nkStmtListExpr} and result.len > 0:
      result.lastSon.info = info
    when false:
      # this hack is required to
      var x = result
      while x.kind == nkStmtListExpr: x = x.lastSon
      if x.kind in nkCallKinds:
        for i in 1..<x.len:
          if x[i].kind in nkCallKinds:
            x.sons[i].info = info
  else:
    result = newNodeI(nkPar, info)
    result.add res

proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
  inc(evalTemplateCounter)
  if evalTemplateCounter > 100:
    globalError(n.info, errTemplateInstantiationTooNested)
    result = n

  # replace each param by the corresponding node:
  var args = evalTemplateArgs(n, tmpl, fromHlo)
  var ctx: TemplCtx
  ctx.owner = tmpl
  ctx.genSymOwner = genSymOwner
  initIdTable(ctx.mapping)

  let body = tmpl.getBody
  if isAtom(body):
    result = newNodeI(nkPar, body.info)
    evalTemplateAux(body, args, ctx, result)
    if result.len == 1: result = result.sons[0]
    else:
      localError(result.info, errIllFormedAstX,
                  renderTree(result, {renderNoComments}))
  else:
    result = copyNode(body)
    #ctx.instLines = body.kind notin {nkStmtList, nkStmtListExpr,
    #                                 nkBlockStmt, nkBlockExpr}
    #if ctx.instLines: result.info = n.info
    for i in countup(0, safeLen(body) - 1):
      evalTemplateAux(body.sons[i], args, ctx, result)
  result.flags.incl nfFromTemplate
  result = wrapInComesFrom(n.info, result)
  dec(evalTemplateCounter)