summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/vm.nim11
-rw-r--r--compiler/vmgen.nim12
-rw-r--r--lib/system/ansi_c.nim9
-rw-r--r--tests/vm/tstringnil.nim50
4 files changed, 70 insertions, 12 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 2da242771..ad0d3b0a1 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -454,8 +454,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcLdStrIdx:
       decodeBC(rkInt)
       let idx = regs[rc].intVal.int
-      if idx <=% regs[rb].node.strVal.len:
-        regs[ra].intVal = regs[rb].node.strVal[idx].ord
+      let s = regs[rb].node.strVal
+      if s.isNil:
+        stackTrace(c, tos, pc, errNilAccess)
+      elif idx <=% s.len:
+        regs[ra].intVal = s[idx].ord
       else:
         stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcWrArr:
@@ -1058,7 +1061,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
     of opcIsNil:
       decodeB(rkInt)
-      regs[ra].intVal = ord(regs[rb].node.kind == nkNilLit)
+      let node = regs[rb].node
+      regs[ra].intVal = ord(node.kind == nkNilLit or
+        (node.kind in {nkStrLit..nkTripleStrLit} and node.strVal.isNil))
     of opcNBindSym:
       decodeBx(rkNode)
       regs[ra].node = copyTree(c.constants.sons[rbx])
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index fe909b887..7397a562c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -370,8 +370,8 @@ proc sameConstant*(a, b: PNode): bool =
     of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
     of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
     of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
-    of nkType: result = a.typ == b.typ
-    of nkEmpty, nkNilLit: result = true
+    of nkType, nkNilLit: result = a.typ == b.typ
+    of nkEmpty: result = true
     else:
       if sonsLen(a) == sonsLen(b):
         for i in countup(0, sonsLen(a) - 1):
@@ -1350,7 +1350,9 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     result = newNodeIT(nkUIntLit, info, t)
   of tyFloat..tyFloat128: 
     result = newNodeIT(nkFloatLit, info, t)
-  of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
+  of tyCString, tyString:
+    result = newNodeIT(nkStrLit, info, t)
+  of tyVar, tyPointer, tyPtr, tySequence, tyExpr,
      tyStmt, tyTypeDesc, tyStatic, tyRef:
     result = newNodeIT(nkNilLit, info, t)
   of tyProc:
@@ -1570,7 +1572,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
       genLit(c, n, dest)
   of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
   of nkNilLit:
-    if not n.typ.isEmptyType: genLit(c, n, dest)
+    if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest)
     else: unused(n, dest)
   of nkAsgn, nkFastAsgn: 
     unused(n, dest)
@@ -1647,7 +1649,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     if allowCast in c.features:
       genConv(c, n, n.sons[1], dest, opcCast)
     else:
-      localError(n.info, errGenerated, "VM is not allowed to 'cast'")
+      globalError(n.info, errGenerated, "VM is not allowed to 'cast'")
   else:
     internalError n.info, "cannot generate VM code for " & n.renderTree
 
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 6bc44719f..9406f26c9 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -33,10 +33,11 @@ type
 
   C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
 
-var
-  c_stdin {.importc: "stdin", nodecl.}: C_TextFileStar
-  c_stdout {.importc: "stdout", nodecl.}: C_TextFileStar
-  c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
+when not defined(vm):
+  var
+    c_stdin {.importc: "stdin", nodecl.}: C_TextFileStar
+    c_stdout {.importc: "stdout", nodecl.}: C_TextFileStar
+    c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
 
 # constants faked as variables:
 when not declared(SIGINT):
diff --git a/tests/vm/tstringnil.nim b/tests/vm/tstringnil.nim
new file mode 100644
index 000000000..5070dd6b7
--- /dev/null
+++ b/tests/vm/tstringnil.nim
@@ -0,0 +1,50 @@
+# bug #1744
+
+import macros
+
+type
+  SuiteTest = object
+    suiteName: string
+    suiteDesc: string
+    testName: string
+    testDesc: string
+    testBlock: PNimrodNode
+
+proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tests: seq[SuiteTest]]  {.compileTime.} =
+  var
+    tests:seq[SuiteTest] = @[]
+
+  for child in suiteBloc.children():
+    case $child[0].ident:
+    of "test":
+
+      var testObj = SuiteTest()
+      if suiteName.kind == nnkNilLit:
+        testObj.suiteName = nil
+      else:
+        testObj.suiteName = $suiteName
+      if suiteDesc.kind == nnkNilLit:
+        testObj.suiteDesc = nil
+      else:
+        testObj.suiteDesc = suiteDesc.strVal
+      testObj.testName = $child[1] # should not ever be nil
+      if child[2].kind == nnkNilLit:
+        testObj.testDesc = nil
+      else:
+        testObj.testDesc = child[2].strVal
+      testObj.testBlock = child[3][6]
+
+      tests.add(testObj)
+
+    else:
+      discard
+
+  return (tests: tests)
+ 
+macro suite(suiteName, suiteDesc: expr, suiteBloc: stmt): stmt {.immediate.} =
+  let contents = buildSuiteContents(suiteName, suiteDesc, suiteBloc)
+
+# Test above
+suite basics, "Description of such":
+  test(t5, nil):
+    assert false