summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-02-24 00:13:15 +0100
committerAraq <rumpf_a@web.de>2015-02-24 00:13:28 +0100
commit752052e903c8f238a6e3a6f67ae36ee7e0943801 (patch)
tree6118e60ccd1cc87f21830779dd2cc47207c09626 /compiler
parent9080d3a9a9483b84745e391e699493c31d85cb34 (diff)
downloadNim-752052e903c8f238a6e3a6f67ae36ee7e0943801.tar.gz
implements a type API for macros
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim14
-rw-r--r--compiler/semtypes.nim19
-rw-r--r--compiler/vm.nim20
-rw-r--r--compiler/vmdeps.nim125
-rw-r--r--compiler/vmgen.nim7
5 files changed, 163 insertions, 22 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 28b34095b..6afc1db26 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -945,6 +945,13 @@ template `{}`*(n: PNode, i: int): expr = n[i -| n]
 template `{}=`*(n: PNode, i: int, s: PNode): stmt =
   n.sons[i -| n] = s
 
+when defined(useNodeIds):
+  const nodeIdToDebug* = -1 # 884953 # 612794
+  #612840 # 612905 # 614635 # 614637 # 614641
+  # 423408
+  #429107 # 430443 # 441048 # 441090 # 441153
+  var gNodeId: int
+
 proc newNode*(kind: TNodeKind): PNode = 
   new(result)
   result.kind = kind
@@ -1061,13 +1068,6 @@ proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) =
 proc discardSons*(father: PNode) = 
   father.sons = nil
 
-when defined(useNodeIds):
-  const nodeIdToDebug* = -1 # 884953 # 612794
-  #612840 # 612905 # 614635 # 614637 # 614641
-  # 423408
-  #429107 # 430443 # 441048 # 441090 # 441153
-  var gNodeId: int
-
 proc withInfo*(n: PNode, info: TLineInfo): PNode =
   n.info = info
   return n
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 7cd748829..d9c7b6c92 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -332,10 +332,15 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
       if result.typ.kind != tyGenericParam:
         # XXX get rid of this hack!
         var oldInfo = n.info
+        when defined(useNodeIds):
+          let oldId = n.id
         reset(n[])
+        when defined(useNodeIds):
+          n.id = oldId
         n.kind = nkSym
         n.sym = result
         n.info = oldInfo
+        n.typ = result.typ
     else:
       localError(n.info, errIdentifierExpected)
       result = errorSym(c, n)
@@ -1179,11 +1184,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     var typeExpr = semExpr(c, n)
     if typeExpr.typ.kind != tyTypeDesc:
       localError(n.info, errTypeExpected)
-      return errorType(c)
-    result = typeExpr.typ.base
-    if result.isMetaType:
-      var preprocessed = semGenericStmt(c, n)
-      return makeTypeFromExpr(c, preprocessed)
+      result = errorType(c)
+    else:
+      result = typeExpr.typ.base
+      if result.isMetaType:
+        var preprocessed = semGenericStmt(c, n)
+        result = makeTypeFromExpr(c, preprocessed)
   of nkIdent, nkAccQuoted:
     var s = semTypeIdent(c, n)
     if s.typ == nil: 
@@ -1254,7 +1260,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   else:
     localError(n.info, errTypeExpected)
     result = newOrPrevType(tyError, prev, c)
-  
+  n.typ = result
+
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
   m.typ.kind = kind
   m.typ.align = size.int16
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 891718274..e96b89f49 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -123,8 +123,12 @@ proc createStrKeepNode(x: var TFullReg) =
   if x.node.isNil:
     x.node = newNode(nkStrLit)
   elif x.node.kind == nkNilLit:
+    when defined(useNodeIds):
+      let id = x.node.id
     system.reset(x.node[])
     x.node.kind = nkStrLit
+    when defined(useNodeIds):
+      x.node.id = id
   elif x.node.kind notin {nkStrLit..nkTripleStrLit} or
       nfAllConst in x.node.flags:
     # XXX this is hacky; tests/txmlgen triggers it:
@@ -1133,7 +1137,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       else:
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
     of opcNGetType:
-      internalError(c.debug[pc], "unknown opcode " & $instr.opcode)
+      let rb = instr.regB
+      let rc = instr.regC
+      if rc == 0:
+        ensureKind(rkNode)
+        if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
+          regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc])
+        else:
+          stackTrace(c, tos, pc, errGenerated, "node has no type")
+      else:
+        # typeKind opcode:
+        ensureKind(rkInt)
+        if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
+          regs[ra].intVal = ord(regs[rb].node.typ.kind)
+        #else:
+        #  stackTrace(c, tos, pc, errGenerated, "node has no type")
     of opcNStrVal:
       decodeB(rkNode)
       createStr regs[ra]
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index c44910b81..7fa88de6e 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -1,13 +1,13 @@
 #
 #
 #           The Nim Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-import ast, types, msgs, osproc, streams, options
+import ast, types, msgs, osproc, streams, options, idents
 
 proc readOutput(p: Process): string =
   result = ""
@@ -19,11 +19,14 @@ proc readOutput(p: Process): string =
   discard p.waitForExit
 
 proc opGorge*(cmd, input: string): string =
-  var p = startProcess(cmd, options={poEvalCommand})
-  if input.len != 0:
-    p.inputStream.write(input)
-    p.inputStream.close()
-  result = p.readOutput
+  try:
+    var p = startProcess(cmd, options={poEvalCommand})
+    if input.len != 0:
+      p.inputStream.write(input)
+      p.inputStream.close()
+    result = p.readOutput
+  except IOError, OSError:
+    result = ""
 
 proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = 
   try:
@@ -36,3 +39,111 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
   except IOError:
     localError(info, errCannotOpenFile, file)
     result = ""
+
+proc atomicTypeX(name: string; t: PType; info: TLineInfo): PNode =
+  let sym = newSym(skType, getIdent(name), t.owner, info)
+  result = newSymNode(sym)
+  result.typ = t
+
+proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode
+
+proc mapTypeToBracket(name: string; t: PType; info: TLineInfo): PNode =
+  result = newNodeIT(nkBracketExpr, info, t)
+  result.add atomicTypeX(name, t, info)
+  for i in 0 .. < t.len:
+    result.add mapTypeToAst(t.sons[i], info)
+
+proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
+  template atomicType(name): expr = atomicTypeX(name, t, info)
+
+  case t.kind
+  of tyNone: result = atomicType("none")
+  of tyBool: result = atomicType("bool")
+  of tyChar: result = atomicType("char")
+  of tyNil: result = atomicType("nil")
+  of tyExpr: result = atomicType("expr")
+  of tyStmt: result = atomicType("stmt")
+  of tyEmpty: result = atomicType"void"
+  of tyArrayConstr, tyArray:
+    result = newNodeIT(nkBracketExpr, info, t)
+    result.add atomicType("array")
+    result.add mapTypeToAst(t.sons[0], info)
+    result.add mapTypeToAst(t.sons[1], info)
+  of tyTypeDesc:
+    if t.base != nil:
+      result = newNodeIT(nkBracketExpr, info, t)
+      result.add atomicType("typeDesc")
+      result.add mapTypeToAst(t.base, info)
+    else:
+      result = atomicType"typeDesc"
+  of tyGenericInvocation:
+    result = newNodeIT(nkBracketExpr, info, t)
+    for i in 0 .. < t.len:
+      result.add mapTypeToAst(t.sons[i], info)
+  of tyGenericInst, tyGenericBody, tyOrdinal, tyUserTypeClassInst:
+    result = mapTypeToAst(t.lastSon, info)
+  of tyGenericParam, tyDistinct, tyForward: result = atomicType(t.sym.name.s)
+  of tyObject:
+    if allowRecursion:
+      result = newNodeIT(nkObjectTy, info, t)
+      if t.sons[0] == nil:
+        result.add ast.emptyNode
+      else:
+        result.add mapTypeToAst(t.sons[0], info)
+      result.add copyTree(t.n)
+    else:
+      result = atomicType(t.sym.name.s)
+  of tyEnum:
+    result = newNodeIT(nkEnumTy, info, t)
+    result.add copyTree(t.n)
+  of tyTuple: result = mapTypeToBracket("tuple", t, info)
+  of tySet: result = mapTypeToBracket("set", t, info)
+  of tyPtr: result = mapTypeToBracket("ptr", t, info)
+  of tyRef: result = mapTypeToBracket("ref", t, info)
+  of tyVar: result = mapTypeToBracket("var", t, info)
+  of tySequence: result = mapTypeToBracket("sequence", t, info)
+  of tyProc: result = mapTypeToBracket("proc", t, info)
+  of tyOpenArray: result = mapTypeToBracket("openArray", t, info)
+  of tyRange:
+    result = newNodeIT(nkBracketExpr, info, t)
+    result.add atomicType("range")
+    result.add t.n.sons[0].copyTree
+    result.add t.n.sons[1].copyTree
+  of tyPointer: result = atomicType"pointer"
+  of tyString: result = atomicType"string"
+  of tyCString: result = atomicType"cstring"
+  of tyInt: result = atomicType"int"
+  of tyInt8: result = atomicType"int8"
+  of tyInt16: result = atomicType"int16"
+  of tyInt32: result = atomicType"int32"
+  of tyInt64: result = atomicType"int64"
+  of tyFloat: result = atomicType"float"
+  of tyFloat32: result = atomicType"float32"
+  of tyFloat64: result = atomicType"float64"
+  of tyFloat128: result = atomicType"float128"
+  of tyUInt: result = atomicType"uint"
+  of tyUInt8: result = atomicType"uint8"
+  of tyUInt16: result = atomicType"uint16"
+  of tyUInt32: result = atomicType"uint32"
+  of tyUInt64: result = atomicType"uint64"
+  of tyBigNum: result = atomicType"bignum"
+  of tyConst: result = mapTypeToBracket("const", t, info)
+  of tyMutable: result = mapTypeToBracket("mutable", t, info)
+  of tyVarargs: result = mapTypeToBracket("varargs", t, info)
+  of tyIter: result = mapTypeToBracket("iter", t, info)
+  of tyProxy: result = atomicType"error"
+  of tyBuiltInTypeClass: result = mapTypeToBracket("builtinTypeClass", t, info)
+  of tyUserTypeClass: result = mapTypeToBracket("userTypeClass", t, info)
+  of tyCompositeTypeClass: result = mapTypeToBracket("compositeTypeClass", t, info)
+  of tyAnd: result = mapTypeToBracket("and", t, info)
+  of tyOr: result = mapTypeToBracket("or", t, info)
+  of tyNot: result = mapTypeToBracket("not", t, info)
+  of tyAnything: result = atomicType"anything"
+  of tyStatic, tyFromExpr, tyFieldAccessor:
+    result = newNodeIT(nkBracketExpr, info, t)
+    result.add atomicType("static")
+    if t.n != nil:
+      result.add t.n.copyTree
+
+proc opMapTypeToAst*(t: PType; info: TLineInfo): PNode =
+  result = mapTypeToAst(t, info, true)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index f367d4cf9..5b7b0b0fd 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -950,7 +950,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
   of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol)
   of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
-  of mNGetType: genUnaryABC(c, n, dest, opcNGetType)
+  of mNGetType:
+    let tmp = c.genx(n.sons[1])
+    if dest < 0: dest = c.getTemp(n.typ)
+    c.gABC(n, opcNGetType, dest, tmp, if n[0].sym.name.s == "typeKind": 1 else: 0)
+    c.freeTemp(tmp)
+    #genUnaryABC(c, n, dest, opcNGetType)
   of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
   of mNSetIntVal:
     unused(n, dest)