summary refs log tree commit diff stats
path: root/compiler/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/plugins')
-rw-r--r--compiler/plugins/active.nim24
-rw-r--r--compiler/plugins/customast.nim136
-rw-r--r--compiler/plugins/itersgen.nim46
-rw-r--r--compiler/plugins/locals.nim39
-rw-r--r--compiler/plugins/plugins.nimble0
5 files changed, 245 insertions, 0 deletions
diff --git a/compiler/plugins/active.nim b/compiler/plugins/active.nim
new file mode 100644
index 000000000..19c320aae
--- /dev/null
+++ b/compiler/plugins/active.nim
@@ -0,0 +1,24 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Include file that imports all plugins that are active.
+
+import
+  ".." / [pluginsupport, idents, ast], locals, itersgen
+
+const
+  plugins: array[2, Plugin] = [
+    ("stdlib", "system", "iterToProc", iterToProcImpl),
+    ("stdlib", "system", "locals", semLocals)
+  ]
+
+proc getPlugin*(ic: IdentCache; fn: PSym): Transformation =
+  for p in plugins:
+    if pluginMatches(ic, p, fn): return p.t
+  return nil
diff --git a/compiler/plugins/customast.nim b/compiler/plugins/customast.nim
new file mode 100644
index 000000000..87461ae39
--- /dev/null
+++ b/compiler/plugins/customast.nim
@@ -0,0 +1,136 @@
+# This file exists to make it overridable via
+# patchFile("plugins", "customast.nim", "customast.nim")
+
+## This also serves as a blueprint for a possible implementation.
+
+import "$nim" / compiler / [lineinfos, idents]
+
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+
+import "$nim" / compiler / nodekinds
+export nodekinds
+
+type
+  PNode* = ref TNode
+  TNode*{.final, acyclic.} = object
+    case kind*: TNodeKind
+    of nkCharLit..nkUInt64Lit:
+      intVal: BiggestInt
+    of nkFloatLit..nkFloat128Lit:
+      floatVal: BiggestFloat
+    of nkStrLit..nkTripleStrLit:
+      strVal: string
+    of nkSym:
+      discard
+    of nkIdent:
+      ident: PIdent
+    else:
+      son, next, last: PNode # linked structure instead of a `seq`
+    info*: TLineInfo
+
+const
+  bodyPos* = 6
+  paramsPos* = 3
+
+proc comment*(n: PNode): string =
+  result = ""
+
+proc `comment=`*(n: PNode, a: string) =
+  discard "XXX implement me"
+
+proc add*(father, son: PNode) =
+  assert son != nil
+  if father.son == nil:
+    father.son = son
+    father.last = son
+  else:
+    father.last.next = son
+    father.last = son
+
+template firstSon*(n: PNode): PNode = n.son
+template secondSon*(n: PNode): PNode = n.son.next
+
+proc replaceFirstSon*(n, newson: PNode) {.inline.} =
+  let old = n.son
+  n.son = newson
+  newson.next = old
+
+proc replaceSon*(n: PNode; i: int; newson: PNode) =
+  assert i > 0
+  assert newson.next == nil
+  var i = i
+  var it = n.son
+  while i > 0:
+    it = it.next
+    dec i
+  let old = it.next
+  it.next = newson
+  newson.next = old
+
+template newNodeImpl(info2) =
+  result = PNode(kind: kind, info: info2)
+
+proc newNode*(kind: TNodeKind): PNode =
+  ## new node with unknown line info, no type, and no children
+  newNodeImpl(unknownLineInfo)
+
+proc newNode*(kind: TNodeKind, info: TLineInfo): PNode =
+  ## new node with line info, no type, and no children
+  newNodeImpl(info)
+
+proc newTree*(kind: TNodeKind; info: TLineInfo; child: PNode): PNode =
+  result = newNode(kind, info)
+  result.son = child
+
+proc newAtom*(ident: PIdent, info: TLineInfo): PNode =
+  result = newNode(nkIdent)
+  result.ident = ident
+  result.info = info
+
+proc newAtom*(kind: TNodeKind, intVal: BiggestInt, info: TLineInfo): PNode =
+  result = newNode(kind, info)
+  result.intVal = intVal
+
+proc newAtom*(kind: TNodeKind, floatVal: BiggestFloat, info: TLineInfo): PNode =
+  result = newNode(kind, info)
+  result.floatVal = floatVal
+
+proc newAtom*(kind: TNodeKind; strVal: sink string; info: TLineInfo): PNode =
+  result = newNode(kind, info)
+  result.strVal = strVal
+
+proc lastSon*(n: PNode): PNode {.inline.} = n.last
+proc setLastSon*(n: PNode, s: PNode) =
+  assert s.next == nil
+  n.last = s
+  if n.son == nil: n.son = s
+
+proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
+                 params,
+                 name, pattern, genericParams,
+                 pragmas, exceptions: PNode): PNode =
+  result = newNode(kind, info)
+  result.add name
+  result.add pattern
+  result.add genericParams
+  result.add params
+  result.add pragmas
+  result.add exceptions
+  result.add body
+
+template transitionNodeKindCommon(k: TNodeKind) =
+  let obj {.inject.} = n[]
+  n[] = TNode(kind: k, info: obj.info)
+  # n.comment = obj.comment # shouldn't be needed, the address doesnt' change
+
+proc transitionSonsKind*(n: PNode, kind: range[nkComesFrom..nkTupleConstr]) =
+  transitionNodeKindCommon(kind)
+  n.son = obj.son
+
+template hasSon*(n: PNode): bool = n.son != nil
+template has2Sons*(n: PNode): bool = n.son != nil and n.son.next != nil
+
+proc isNewStyleConcept*(n: PNode): bool {.inline.} =
+  assert n.kind == nkTypeClassTy
+  result = n.firstSon.kind == nkEmpty
diff --git a/compiler/plugins/itersgen.nim b/compiler/plugins/itersgen.nim
new file mode 100644
index 000000000..e2c97bdc5
--- /dev/null
+++ b/compiler/plugins/itersgen.nim
@@ -0,0 +1,46 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Plugin to transform an inline iterator into a data structure.
+
+import ".." / [ast, modulegraphs, lookups, semdata, lambdalifting, msgs]
+
+proc iterToProcImpl*(c: PContext, n: PNode): PNode =
+  result = newNodeI(nkStmtList, n.info)
+  let iter = n[1]
+  if iter.kind != nkSym or iter.sym.kind != skIterator:
+    localError(c.config, iter.info, "first argument needs to be an iterator")
+    return
+  if n[2].typ.isNil:
+    localError(c.config, n[2].info, "second argument needs to be a type")
+    return
+  if n[3].kind != nkIdent:
+    localError(c.config, n[3].info, "third argument needs to be an identifier")
+    return
+
+  let t = n[2].typ.skipTypes({tyTypeDesc, tyGenericInst})
+  if t.kind notin {tyRef, tyPtr} or t.elementType.kind != tyObject:
+    localError(c.config, n[2].info,
+        "type must be a non-generic ref|ptr to object with state field")
+    return
+  let body = liftIterToProc(c.graph, iter.sym, getBody(c.graph, iter.sym), t, c.idgen)
+
+  let prc = newSym(skProc, n[3].ident, c.idgen, iter.sym.owner, iter.sym.info)
+  prc.typ = copyType(iter.sym.typ, c.idgen, prc)
+  excl prc.typ.flags, tfCapturesEnv
+  prc.typ.n.add newSymNode(getEnvParam(iter.sym))
+  prc.typ.rawAddSon t
+  let orig = iter.sym.ast
+  prc.ast = newProcNode(nkProcDef, n.info,
+              body = body, params = orig[paramsPos], name = newSymNode(prc),
+              pattern = c.graph.emptyNode, genericParams = c.graph.emptyNode,
+              pragmas = orig[pragmasPos], exceptions = c.graph.emptyNode)
+
+  prc.ast.add iter.sym.ast[resultPos]
+  addInterfaceDecl(c, prc)
diff --git a/compiler/plugins/locals.nim b/compiler/plugins/locals.nim
new file mode 100644
index 000000000..d3046cd65
--- /dev/null
+++ b/compiler/plugins/locals.nim
@@ -0,0 +1,39 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## The builtin 'system.locals' implemented as a plugin.
+
+import ".." / [ast, astalgo,
+  magicsys, lookups, semdata, lowerings]
+
+proc semLocals*(c: PContext, n: PNode): PNode =
+  var counter = 0
+  var tupleType = newTypeS(tyTuple, c)
+  result = newNodeIT(nkTupleConstr, n.info, tupleType)
+  tupleType.n = newNodeI(nkRecList, n.info)
+  let owner = getCurrOwner(c)
+  # for now we skip openarrays ...
+  for scope in localScopesFrom(c, c.currentScope):
+    for it in items(scope.symbols):
+      if it.kind in skLocalVars and
+          it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
+            {tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
+
+        if it.owner == owner:
+          var field = newSym(skField, it.name, c.idgen, owner, n.info)
+          field.typ = it.typ.skipTypes({tyVar})
+          field.position = counter
+          inc(counter)
+
+          tupleType.n.add newSymNode(field)
+          addSonSkipIntLit(tupleType, field.typ, c.idgen)
+
+          var a = newSymNode(it, result.info)
+          if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
+          result.add(a)
diff --git a/compiler/plugins/plugins.nimble b/compiler/plugins/plugins.nimble
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/compiler/plugins/plugins.nimble