diff options
-rw-r--r-- | compiler/vm.nim | 11 | ||||
-rw-r--r-- | compiler/vmgen.nim | 12 | ||||
-rw-r--r-- | lib/system/ansi_c.nim | 9 | ||||
-rw-r--r-- | tests/vm/tstringnil.nim | 50 |
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 |