diff options
Diffstat (limited to 'tests/objects')
30 files changed, 1852 insertions, 0 deletions
diff --git a/tests/objects/m19342.c b/tests/objects/m19342.c new file mode 100644 index 000000000..113f65309 --- /dev/null +++ b/tests/objects/m19342.c @@ -0,0 +1,12 @@ +struct Node +{ + int data[25]; +}; + + +struct Node hello(int name) { + struct Node x = {999, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9, + 1, 2, 3, 4, 5}; + return x; +} \ No newline at end of file diff --git a/tests/objects/mobject_default_value.nim b/tests/objects/mobject_default_value.nim new file mode 100644 index 000000000..224549501 --- /dev/null +++ b/tests/objects/mobject_default_value.nim @@ -0,0 +1,15 @@ +type + Clean = object + mem: int + Default* = object + poi: int = 12 + clc: Clean + se*: range[0'i32 .. high(int32)] + + NonDefault* = object + poi: int + + PrellDeque*[T] = object + pendingTasks*: range[0'i32 .. high(int32)] + head: T + tail: T diff --git a/tests/objects/t12753.nim b/tests/objects/t12753.nim new file mode 100644 index 000000000..1009433be --- /dev/null +++ b/tests/objects/t12753.nim @@ -0,0 +1,22 @@ +discard """ + output: ''' +(v: [(v: [0.0, 1.1]), (v: [2.2, 3.3])]) +(v: [(v: [0.0, 1.1]), (v: [2.2, 3.3])]) +''' +""" + +type + V = object + v:array[2,float] + M = object + v:array[2,V] + +var + a = M(v:[ V(v:[0.0,1.0]), V(v:[2.0,3.0]) ]) + b = M(v:[ V(v:[0.0,0.1]), V(v:[0.2,0.3]) ]) + +echo M(v: [V(v: [b.v[0].v[0] + a.v[0].v[0], b.v[0].v[1] + a.v[0].v[1]]), + V(v: [b.v[1].v[0] + a.v[1].v[0], b.v[1].v[1] + a.v[1].v[1]])]) +b = M(v: [V(v: [b.v[0].v[0] + a.v[0].v[0], b.v[0].v[1] + a.v[0].v[1]]), + V(v: [b.v[1].v[0] + a.v[1].v[0], b.v[1].v[1] + a.v[1].v[1]])]) +echo b diff --git a/tests/objects/t17437.nim b/tests/objects/t17437.nim new file mode 100644 index 000000000..b5c0e0525 --- /dev/null +++ b/tests/objects/t17437.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim check $file" + errormsg: "" + nimout: ''' +t17437.nim(20, 16) Error: undeclared identifier: 'x' +t17437.nim(20, 16) Error: expression 'x' has no type (or is ambiguous) +t17437.nim(20, 19) Error: incorrect object construction syntax +t17437.nim(20, 19) Error: incorrect object construction syntax +t17437.nim(20, 12) Error: expression '' has no type (or is ambiguous) +''' +""" + +# bug #17437 invalid object construction should result in error + +type + V = ref object + x, y: int + +proc m = + var v = V(x: x, y) + +m() diff --git a/tests/objects/t19342.nim b/tests/objects/t19342.nim new file mode 100644 index 000000000..d40d15a4b --- /dev/null +++ b/tests/objects/t19342.nim @@ -0,0 +1,18 @@ +discard """ + targets: "c cpp" +""" + +{.compile: "m19342.c".} + +# bug #19342 +type + Node* {.bycopy.} = object + data: array[25, cint] + +proc myproc(name: cint): Node {.importc: "hello", cdecl.} + +proc parse = + let node = myproc(10) + doAssert node.data[0] == 999 + +parse() diff --git a/tests/objects/t19342_2.nim b/tests/objects/t19342_2.nim new file mode 100644 index 000000000..6f6d0f2b3 --- /dev/null +++ b/tests/objects/t19342_2.nim @@ -0,0 +1,18 @@ +discard """ + targets: "c cpp" +""" + +{.compile: "m19342.c".} + +# bug #19342 +type + Node* {.byRef.} = object + data: array[25, cint] + +proc myproc(name: cint): Node {.importc: "hello", cdecl.} + +proc parse = + let node = myproc(10) + doAssert node.data[0] == 999 + +parse() \ No newline at end of file diff --git a/tests/objects/t20972.nim b/tests/objects/t20972.nim new file mode 100644 index 000000000..6383dc9b1 --- /dev/null +++ b/tests/objects/t20972.nim @@ -0,0 +1,15 @@ +discard """ + matrix: "--mm:refc -d:release; --mm:orc -d:release" +""" + +{.passC: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -Wall -Wextra -pedantic -flto".} +{.passL: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -flto".} + +# bug #20972 +type ForkedEpochInfo = object + case kind: bool + of true, false: discard +var info = ForkedEpochInfo(kind: true) +doAssert info.kind +info.kind = false +doAssert not info.kind diff --git a/tests/objects/t22301.nim b/tests/objects/t22301.nim new file mode 100644 index 000000000..8746bf584 --- /dev/null +++ b/tests/objects/t22301.nim @@ -0,0 +1,17 @@ +discard """ + errormsg: "branch initialization with a runtime discriminator is not supported for a branch whose fields have default values." +""" + +# bug #22301 +type + Enum = enum A, B + Object = object + case a: Enum + of A: + integer: int = 200 + of B: + time: string + +let x = A +let s = Object(a: x) +echo s \ No newline at end of file diff --git a/tests/objects/t3734.nim b/tests/objects/t3734.nim new file mode 100644 index 000000000..cebef6081 --- /dev/null +++ b/tests/objects/t3734.nim @@ -0,0 +1,17 @@ +discard """ +output: "i0" +""" + +type + Application = object + config: void + i: int + f: void + +proc printFields(rec: Application) = + for k, v in fieldPairs(rec): + echo k, v + +var app: Application + +printFields(app) diff --git a/tests/objects/t4318.nim b/tests/objects/t4318.nim new file mode 100644 index 000000000..beadd6909 --- /dev/null +++ b/tests/objects/t4318.nim @@ -0,0 +1,17 @@ +discard """ + matrix: "--mm:refc" +""" + + +type + A = object of RootObj + B = object of A + +method identify(a:A) {.base.} = echo "A" +method identify(b:B) = echo "B" + +var b: B + +doAssertRaises(ObjectAssignmentDefect): + var a: A = b + discard a diff --git a/tests/objects/tdefaultfieldscheck.nim b/tests/objects/tdefaultfieldscheck.nim new file mode 100644 index 000000000..8a05439d9 --- /dev/null +++ b/tests/objects/tdefaultfieldscheck.nim @@ -0,0 +1,16 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: +''' +tdefaultfieldscheck.nim(14, 17) Error: type mismatch: got <string> but expected 'int' +''' +""" + + +type + Date* = object + goal: float = 7 + name: int = "string" + +echo default(Date) diff --git a/tests/objects/tdefaultrangetypescheck.nim b/tests/objects/tdefaultrangetypescheck.nim new file mode 100644 index 000000000..71e7ac59b --- /dev/null +++ b/tests/objects/tdefaultrangetypescheck.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "cannot convert 0 to range 1..5(int)" + line: 9 +""" + +type + Point = object + y: int + x: range[1..5] = 0 + +echo default(Point) diff --git a/tests/objects/tillegal_recursion.nim b/tests/objects/tillegal_recursion.nim new file mode 100644 index 000000000..428c2e445 --- /dev/null +++ b/tests/objects/tillegal_recursion.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "Cannot inherit from: 'Foo:ObjectType'" + line: 7 +""" +# bug #1691 +type + Foo = ref object of Foo diff --git a/tests/objects/tillegal_recursion2.nim b/tests/objects/tillegal_recursion2.nim new file mode 100644 index 000000000..ce2279f04 --- /dev/null +++ b/tests/objects/tillegal_recursion2.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "Cannot inherit from: 'Foo'" + line: 6 +""" +type + Foo = object of Foo diff --git a/tests/objects/tillegal_recursion3.nim b/tests/objects/tillegal_recursion3.nim new file mode 100644 index 000000000..c80f29e28 --- /dev/null +++ b/tests/objects/tillegal_recursion3.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "Cannot inherit from: 'Foo'" + line: 6 +""" +type + Foo = object of ref Foo diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim new file mode 100644 index 000000000..ce67c4490 --- /dev/null +++ b/tests/objects/tobj_asgn_dont_slice.nim @@ -0,0 +1,25 @@ +discard """ + matrix: "--mm:refc" + outputsub: '''ObjectAssignmentDefect''' + exitcode: "1" +""" + +# bug #7637 +type + Fruit = object of RootObj + name*: string + Apple = object of Fruit + Pear = object of Fruit + +method eat(f: Fruit) {.base.} = + raise newException(Exception, "PURE VIRTUAL CALL") + +method eat(f: Apple) = + echo "fruity" + +method eat(f: Pear) = + echo "juicy" + +let basket = [Apple(name:"a"), Pear(name:"b")] + +eat(basket[0]) diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim new file mode 100644 index 000000000..ee5a5b221 --- /dev/null +++ b/tests/objects/tobjconstr.nim @@ -0,0 +1,79 @@ +discard """ + output: ''' +(k: kindA, a: (x: "abc", z: @[1, 1, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 2, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 3, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 4, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 5, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 6, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 7, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 8, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 9, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 10, 3]), method: ()) +(y: 0, x: 123) +(y: 678, x: 123) +(z: 89, y: 0, x: 128) +(y: 678, x: 123) +(y: 678, x: 123) +(y: 0, x: 123) +(y: 678, x: 123) +(y: 123, x: 678) +''' +""" + +type + TArg = object + x: string + z: seq[int] + TKind = enum kindXY, kindA + TEmpty = object + TDummy = ref object + case k: TKind + of kindXY: x, y: int + of kindA: + a: TArg + `method`: TEmpty # bug #1791 + +proc main() = + for i in 1..10: + let d = TDummy(k: kindA, a: TArg(x: "abc", z: @[1,i,3]), `method`: TEmpty()) + echo d[] + +main() + +# bug #6294 +type + A = object of RootObj + x*: int + B = object of A + y*: int + BS = object of B + C = object of BS + z*: int + +proc main2 = + # inherited fields are ignored, so no fields are set + when true: + var + o: B + o = B(x: 123) + echo o + o = B(y: 678, x: 123) + echo o + + # inherited fields are ignored + echo C(x: 128, z: 89) # (y: 0, x: 0) + echo B(y: 678, x: 123) # (y: 678, x: 0) + echo B(x: 123, y: 678) # (y: 678, x: 0) + + when true: + # correct, both with `var` and `let`; + var b=B(x: 123) + echo b # (y: 0, x: 123) + b=B(y: 678, x: 123) + echo b # (y: 678, x: 123) + b=B(y: b.x, x: b.y) + echo b # (y: 123, x: 678) + +main2() +GC_fullCollect() diff --git a/tests/objects/tobjconstr2.nim b/tests/objects/tobjconstr2.nim new file mode 100644 index 000000000..cf4a694b4 --- /dev/null +++ b/tests/objects/tobjconstr2.nim @@ -0,0 +1,57 @@ +discard """ + output: '''42 +Foo''' +""" + +type TFoo{.exportc.} = object + x:int + +var s{.exportc.}: seq[TFoo] = @[] + +s.add TFoo(x: 42) + +echo s[0].x + + +# bug #563 +type + Foo {.inheritable.} = + object + x: int + + Bar = + object of Foo + y: int + +var a = Bar(y: 100, x: 200) # works +var b = Bar(x: 100, y: 200) # used to fail + +# bug 1275 + +type + Graphic = object of RootObj + case kind: range[0..1] + of 0: + radius: float + of 1: + size: tuple[w, h: float] + +var d = Graphic(kind: 1, size: (12.9, 6.9)) + +# bug #1274 +type + K = enum Koo, Kar + Graphic2 = object of RootObj + case kind: K + of Koo: + radius: float + of Kar: + size: tuple[w, h: float] + +type NamedGraphic = object of Graphic2 + name: string + +var ngr = NamedGraphic(kind: Koo, radius: 6.9, name: "Foo") +echo ngr.name + +GC_fullCollect() diff --git a/tests/objects/tobjcov.nim b/tests/objects/tobjcov.nim new file mode 100644 index 000000000..a12f74702 --- /dev/null +++ b/tests/objects/tobjcov.nim @@ -0,0 +1,24 @@ +discard """ +action: compile +targets: "c" +""" + +# Covariance is not type safe: +# Note: `nim cpp` makes it a compile error (after codegen), even with: +# `var f = cast[proc (x: var TA) {.nimcall.}](cast[pointer](bp))`, which +# currently removes all the `cast` in cgen'd code, hence the compile error. + +type + TA = object of RootObj + a: int + TB = object of TA + b: array[0..5000_000, int] + +proc ap(x: var TA) = x.a = -1 +proc bp(x: var TB) = x.b[high(x.b)] = -1 + +# in Nim proc (x: TB) is compatible to proc (x: TA), +# but this is not type safe: +var f = cast[proc (x: var TA) {.nimcall.}](bp) +var a: TA +f(a) # bp expects a TB, but gets a TA diff --git a/tests/objects/tobject.nim b/tests/objects/tobject.nim new file mode 100644 index 000000000..a185bebcb --- /dev/null +++ b/tests/objects/tobject.nim @@ -0,0 +1,74 @@ + +type Obj = object + foo: int + +proc makeObj(x: int): Obj = + result.foo = x + +block: # object basic methods + block: # it should convert an object to a string + var obj = makeObj(1) + # Should be "obj: (foo: 1)" or similar. + doAssert($obj == "(foo: 1)") + block: # it should test equality based on fields + doAssert(makeObj(1) == makeObj(1)) + +# bug #10203 + +type + TMyObj = TYourObj + TYourObj = object of RootObj + x, y: int + +proc init: TYourObj = + result.x = 0 + result.y = -1 + +proc f(x: var TYourObj) = + discard + +var m: TMyObj = init() +f(m) + +var a: TYourObj = m +var b: TMyObj = a + +# bug #10195 +type + InheritableFoo {.inheritable.} = ref object + InheritableBar = ref object of InheritableFoo # ERROR. + +block: # bug #14698 + const N = 3 + type Foo[T] = ref object + x1: int + when N == 2: + x2: float + when N == 3: + x3: seq[int] + else: + x4: char + x4b: array[9, char] + + let t = Foo[float](x1: 1) + doAssert $(t[]) == "(x1: 1, x3: @[])" + doAssert t.sizeof == int.sizeof + type Foo1 = object + x1: int + x3: seq[int] + doAssert t[].sizeof == Foo1.sizeof + +# bug #147 +type + TValue* {.pure, final.} = object of RootObj + a: int + PValue = ref TValue + PPValue = ptr PValue + + +var x: PValue +new x +var sp: PPValue = addr x + +sp.a = 2 +doAssert sp.a == 2 diff --git a/tests/objects/tobject3.nim b/tests/objects/tobject3.nim new file mode 100644 index 000000000..9ff1743ce --- /dev/null +++ b/tests/objects/tobject3.nim @@ -0,0 +1,95 @@ +discard """ + output: '''TBar2 +TFoo +''' +""" + +## XXX this output needs to be adapted for VCC which produces different results. + +# It turned out that it's hard to generate correct for these two test cases at +# the same time. + +type + TFoo = ref object of RootObj + Data: int + TBar = ref object of TFoo + nil + TBar2 = ref object of TBar + d2: int + +template super(self: TBar): TFoo = self + +template super(self: TBar2): TBar = self + +proc Foo(self: TFoo) = + echo "TFoo" + +#proc Foo(self: TBar) = +# echo "TBar" +# Foo(super(self)) +# works when this code is uncommented + +proc Foo(self: TBar2) = + echo "TBar2" + Foo(super(self)) + +var b: TBar2 +new(b) + +Foo(b) + +# bug #837 +type + PView* = ref TView + TView* {.inheritable.} = object + data: int + + PWindow* = ref TWindow + TWindow* = object of TView + data3: int + + PDesktop* = ref TDesktop + TDesktop* = object of TView + data2: int + +proc makeDesktop(): PDesktop = new(TDesktop) + +proc makeWindow(): PWindow = new(TWindow) + +proc thisCausesError(a: PView, b: PView) = + discard + +var dd = makeDesktop() +var aa = makeWindow() + +thisCausesError(dd, aa) + +# bug #5892 +type + Foo6 = distinct array[4, float32] + AnotherFoo = distinct array[4, float32] + + AbstractAnimationSampler* = ref object of RootObj + + AnimationSampler*[T] = ref object of AbstractAnimationSampler + sampleImpl: proc(s: AnimationSampler[T], p: float): T + + ArrayAnimationSampler*[T] = ref object of AnimationSampler[T] + +proc newArrayAnimationSampler*[T](): ArrayAnimationSampler[T] = + result.new() + result.sampleImpl = nil + +discard newArrayAnimationSampler[Foo6]() +discard newArrayAnimationSampler[AnotherFoo]() + +type + DefaultIsNone* = pointer | ptr | ref | proc {.nimcall.} | cstring | cstringArray + OptionKind* {.pure.} = enum None, Some + OptionA* [T] = object of RootObj + when T is DefaultIsNone: + value: T + else: + value: T + kind: OptionKind + SomeA* [T] = object of OptionA[T] diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim new file mode 100644 index 000000000..0cd05e4f3 --- /dev/null +++ b/tests/objects/tobject_default_value.nim @@ -0,0 +1,780 @@ +discard """ + matrix: "-d:nimPreviewRangeDefault --mm:refc; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc" + targets: "c cpp js" +""" + +import std/[times, macros, tables] + +type + Guess = object + poi: DateTime + + GuessDistinct = distinct Guess + +block: + var x: Guess + discard Guess() + + var y: GuessDistinct + + discard y + + discard GuessDistinct(x) + + +import mobject_default_value + +block: + let x = Default() + doAssert x.se == 0'i32 + +block: + let x = default(Default) + doAssert x.se == 0'i32 +# echo Default(poi: 12) +# echo Default(poi: 17) + +# echo NonDefault(poi: 77) + +block: + var x: Default + doAssert x.se == 0'i32 + +type + ObjectBase = object of RootObj + value = 12 + + ObjectBaseDistinct = distinct ObjectBase + + DinstinctInObject = object + data: ObjectBaseDistinct + + Object = object of ObjectBase + time: float = 1.2 + date: int + scale: range[1..10] + + Object2 = object + name: Object + + Object3 = object + obj: Object2 + + ObjectTuple = tuple + base: ObjectBase + typ: int + obj: Object + + TupleInObject = object + size = 777 + data: ObjectTuple + + Ref = ref object of ObjectBase + + RefInt = ref object of Ref + data = 73 + + Ref2 = ref object of ObjectBase + + RefInt2 = ref object of Ref + data = 73 + +var t {.threadvar.}: Default +# var m1, m2 {.threadvar.}: Default + +block: + doAssert t.se == 0'i32 + +block: # ARC/ORC cannot bind destructors twice, so it cannot + # be moved into main + block: + var x: Ref + new(x) + doAssert x.value == 12, "Ref.value = " & $x.value + + var y: RefInt + new(y) + doAssert y.value == 12 + doAssert y.data == 73 + + block: + var x: Ref2 + new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref") + doAssert x.value == 12, "Ref.value = " & $x.value + + proc call(x: RefInt2) = + discard "call RefInt" + + var y: RefInt2 + new(y, call) + doAssert y.value == 12 + doAssert y.data == 73 + +template main {.dirty.} = + block: # bug #16744 + type + R = range[1..10] + Obj = object + r: R + + var + rVal: R = default(R) # Works fine + objVal = default(Obj) + + doAssert rVal == 1 + doAssert objVal.r == 1 + + block: # bug #16744 + type + R = range[1..10] + Obj = object + r: R + + var + rVal: R = default(R) # Works fine + objVal = Obj() + + doAssert rVal == 1 # it should be 1 + doAssert objVal.r == 1 + + block: # bug #3608 + type + abc = ref object + w: range[2..100] + + proc createABC(): abc = + new(result) + result.w = 20 + + doAssert createABC().w == 20 + + block: + var x = new ObjectBase + doAssert x.value == 12 + + proc hello(): ref ObjectBase = + new result + + let z = hello() + doAssert z.value == 12 + + block: + var base = ObjectBase() + var x: ObjectBaseDistinct = ObjectBaseDistinct(base) + doAssert ObjectBase(x).value == 12 + let y = ObjectBaseDistinct(default(ObjectBase)) + doAssert ObjectBase(y).value == 12 + + let m = ObjectBaseDistinct(ObjectBase()) + doAssert ObjectBase(m).value == 12 + + proc hello(): ObjectBaseDistinct = + result = ObjectBaseDistinct(default(ObjectBase)) + + let z = hello() + doAssert ObjectBase(z).value == 12 + + block: + var x: DinstinctInObject + x.data = ObjectBaseDistinct(default(ObjectBase)) + + doAssert ObjectBase(x.data).value == 12 + + block: + var x = Object() + doAssert x.value == 12 + doAssert x.time == 1.2 + doAssert x.scale == 1 + + let y = default(Object) + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + var x1, x2, x3 = default(Object) + doAssert x1.value == 12 + doAssert x1.time == 1.2 + doAssert x1.scale == 1 + doAssert x2.value == 12 + doAssert x2.time == 1.2 + doAssert x2.scale == 1 + doAssert x3.value == 12 + doAssert x3.time == 1.2 + doAssert x3.scale == 1 + + block: + var x = new Object + doAssert x[] == default(Object) + + block: + var x = default(Object2) + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + + block: + let x = Object2() + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + + block: + var x: ref Object2 + new x + doAssert x[] == default(Object2) + + block: + var x = default(Object3) + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + + block: + var x = Object3() + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + + when nimvm: + # todo + discard "fixme" + else: + when defined(gcArc) or defined(gcOrc): + block: #seq + var x = newSeq[Object](10) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: seq[Object] + setLen(x, 5) + let y = x[^1] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var my = @[1, 2, 3, 4, 5] + my.setLen(0) + my.setLen(5) + doAssert my == @[0, 0, 0, 0, 0] + + block: + var my = "hello" + my.setLen(0) + my.setLen(5) + doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']""" + + block: # array + var x: array[10, Object] = default(array[10, Object]) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: # array + var x {.noinit.}: array[10, Object] + discard x + + block: # tuple + var x = default(ObjectTuple) + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x = default(TupleInObject) + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 + + type + ObjectArray = object + data: array[10, Object] + + block: + var x = default(ObjectArray) + let y = x.data[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: PrellDeque[int] + doAssert x.pendingTasks == 0 + + type + Color = enum + Red, Blue, Yellow + + ObjectVarint = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + ObjectVarint1 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + + block: + var x = ObjectVarint(kind: Red) + doAssert x.kind == Red + doAssert x.data == 10 + + block: + var x = ObjectVarint(kind: Blue) + doAssert x.kind == Blue + doAssert x.fill == "123" + + block: + var x = ObjectVarint(kind: Yellow) + doAssert x.kind == Yellow + doAssert typeof(x.time) is float32 + + block: + var x = default(ObjectVarint1) + doAssert x.kind == Blue + doAssert x.fill2 == "123" + x.cry = 326 + + type + ObjectVarint2 = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + block: + var x = ObjectVarint2(kind: Blue) + doAssert x.fill == "123" + + block: + type + Color = enum + Red, Blue, Yellow + + type + ObjectVarint3 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + case name: Color = Blue + of Blue: + go = 12 + else: + temp = 66 + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + + block: + var x = default(ObjectVarint3) + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + + block: + var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) + doAssert x.kind == Blue + doAssert x.name == Red + doAssert x.temp == 99 + + block: + type + Default = tuple + id: int = 1 + obj: ObjectBase + name: string + + Class = object + def: Default + + Member = object + def: Default = (id: 777, obj: ObjectBase(), name: "fine") + + block: + var x = default(Default) + doAssert x.id == 1 + doAssert x.obj == default(ObjectBase) + doAssert x.name == "" + + block: + var x = default(Class) + doAssert x.def == default(Default) + doAssert x.def.id == 1 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "" + + block: + var x = default(Member) + doAssert x.def.id == 777 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "fine" + + block: + var x {.noinit.} = 12 + doAssert x == 12 + + type + Pure = object + id: int = 12 + + var y {.noinit.}: Pure + doAssert y.id == 0 + + var z {.noinit.}: Pure = Pure(id: 77) + doAssert z.id == 77 + + block: # bug #20681 + type A = object + d: DateTime = DateTime() + + let x = default(A) + doAssert $x == "(d: Uninitialized DateTime)" + + block: # bug #20715 + block: + type + Foo = enum + A + B + + Bar = object + case foo: Foo + of A: + t: range[-1..2] + else: discard + + var d = default(Bar) + doAssert d.t == -1 + + block: + type + Foo = enum + A + B + + Bar = object + case foo: Foo + of A: + t: range[0..2] + else: discard + + var d = default(Bar) + doAssert d.t == 0 + + block: # bug #20740 + block: + proc foo(x: static DateTime = Datetime()) = + discard + + foo() + + block: + macro foo(x: static DateTime) = + discard x + + macro foo2: untyped = + var x = DateTime() + + result = quote do: + foo(`x`) + + foo2() + + + block: # issue #20699 + type + Either[A,B] = object + case kind:bool + of false: + b: B + of true: + a: A + O = object of RootRef + + proc oToEither(o:O):Either[O,void] = + Either[O,void](kind:true,a: o) + + discard oToEither(O()) + + block: # bug #20695 + type + Default = object + tabs: Table[string, int] = initTable[string, int]() + + let d = default(Default) + doAssert d.tabs.len == 0 + + block: + type + Default = object + tabs: Table[string, int] = Table[string, int]() + + let d = default(Default) + doAssert d.tabs.len == 0 + + + block: + type DjangoDateTime = distinct DateTime + + type Default = object + data: DjangoDateTime = DjangoDateTime(DateTime()) + + let x = default(Default) + doAssert x.data is DjangoDateTime + + block: + type DjangoDateTime = distinct DateTime + + type Default = object + data = DjangoDateTime(DateTime()) + + let x = default(Default) + doAssert x.data is DjangoDateTime + + block: + type + Result2 = object + case o: bool + of false: + e: float + of true: + v {.requiresInit.} : int = 1 + + proc startSessionSync(): Result2 = + return Result2(o: true) + + proc mainSync = + let ff = startSessionSync() + doAssert ff.v == 1 + + mainSync() + + block: + type + Result2 = object + v {.requiresInit.} : int = 1 + + proc startSessionSync(): Result2 = + return Result2() + + proc mainSync = + let ff = startSessionSync() + doAssert ff.v == 1 + + mainSync() + + block: # bug #21801 + func evaluate(i: int): float = + 0.0 + + func evaluate(): float = + 0.0 + + type SearchOptions = object + evaluation: proc(): float = evaluate + + block: + func evaluate(): float = + 0.0 + + type SearchOptions = object + evaluation: proc(): float = evaluate + + block: + func evaluate(i: int): float = + 0.0 + + type SearchOptions = object + evaluation = evaluate + block: + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + + template `?`[T, E](self: Result[T, E]): auto = + let v = (self) + if not v.oResultPrivate: + when compiles(`assignResult?`(default(typeof(result)))): + when typeof(result) is typeof(v): + `assignResult?`(v) + elif E is void: + `assignResult?`(err(typeof(result))) + else: + `assignResult?`(err(typeof(result), v.eResultPrivate)) + return + else: + return + when typeof(result) is typeof(v): + v + elif E is void: + err(typeof(result)) + else: + err(typeof(result), v.eResultPrivate) + + when not(T is void): + v.vResultPrivate + + type R = Result[int, string] + + proc testAssignResult() = + var assigned: bool + template `assignResult?`(v: Result) = + assigned = true + result = v + + proc failed(): Result[int, string] = + discard + + proc calling(): Result[int, string] = + let _ = ? failed() + doAssert false + + let r = calling() + doAssert assigned + + when nimvm: + when not defined(js): + testAssignResult() + else: + testAssignResult() + + block: # bug #22123 + type Thing = object + x: float32 = 1 + + type ThingWithArray = object + arr: array[256, float32] + n: float32 = 1 + + type Container = ref object + thing: array[5, Thing] + thing_with_array: array[5, ThingWithArray] + + var foo = new Container + doAssert int(foo.thing[0].x) == 1 + + block: # bug #22613 + type + K = enum + A = "a" + B = "b" + T = object + case kind: K = B + of A: + a: int + of B: + b: float + + doAssert T().kind == B + + block: # bug #22926 + type + Direction = enum + North + South + East + West + + ArrayObj1 = object + list: array[Direction, int] + + ArrayObj2 = object + list: array[Direction, int] = [1, 2, 3, 4] + + block: + var a: ArrayObj1 + doAssert a.list[West] == 0 + var b = default ArrayObj1 + doAssert b.list[North] == 0 + + + block: + var a: ArrayObj2 + doAssert a.list[West] == 0 + var b = default ArrayObj2 + doAssert b.list[North] == 1 + + block: + type limited_float = range[1.2..20.0] + doAssert default(limited_float) == 1.2 + + + block: + type + range1 = range[1..10] + range2 = range[-1..10] + + proc foo = + doAssert default(range1) == 1 + doAssert default(range2) == -1 + + let s = default(array[5, range1]) + doAssert s == [range1 1, 1, 1, 1, 1] + + foo() + + block: + type + Object = object + id: range[1.2..29.3] + + var s = default(Object) + doAssert s.id == 1.2 + + block: # bug #23943 + type limited_int = range[1..20] + var d: limited_int; + doAssert d == 1 + +static: main() +main() diff --git a/tests/objects/tobjects_issues.nim b/tests/objects/tobjects_issues.nim new file mode 100644 index 000000000..f1a416d04 --- /dev/null +++ b/tests/objects/tobjects_issues.nim @@ -0,0 +1,117 @@ +discard """ + output: ''' +tbObj of TC true +true +5 +true +is Nil false +''' +""" + + +block t1053: + type + TA = object of RootObj + a: int + TB = object of TA + b: int + TC = object of TB + c: int + + proc test(p: TA) = + if p of TB: + echo "tbObj of TC ", p of TC + + var v = TC() + v.a = 1 + v.b = 2 + v.c = 3 + test(v) + + + +block t924: + type + MyObject = object of RootObj + x: int + var asd: MyObject + + proc isMyObject(obj: RootObj) = + echo obj of MyObject + if obj of MyObject: + let a = MyObject(obj) + echo a.x + + asd.x = 5 + isMyObject(asd) + + + +block t4673: + type + BaseObj[T] = ref object of RootObj + SomeObj = ref object of BaseObj[int] + + proc doSomething[T](o: BaseObj[T]) = + echo "true" + var o = new(SomeObj) + o.doSomething() # Error: cannot instantiate: 'T' + + + +block t1658: + type + Loop = ref object + onBeforeSelect: proc (L: Loop) + + var L: Loop + new L + L.onBeforeSelect = proc (bar: Loop) = + echo "is Nil ", bar.isNil + + L.onBeforeSelect(L) + + + +block t2508: + type + GenericNodeObj[T] = ref object + obj: T + Node = ref object + children: seq[Node] + parent: Node + nodeObj: GenericNodeObj[int] + + proc newNode(nodeObj: GenericNodeObj): Node = + result = Node(nodeObj: nodeObj) + newSeq(result.children, 10) + + var genericObj = GenericNodeObj[int]() + var myNode = newNode(genericObj) + + + +block t2540: + type + BaseSceneNode[T] = ref object of RootObj + children: seq[BaseSceneNode[T]] + parent: BaseSceneNode[T] + SceneNode[T] = ref object of BaseSceneNode[T] + SomeObj = ref object + + proc newSceneNode[T](): SceneNode[T] = + new result + result.children = @[] + + var aNode = newSceneNode[SomeObj]() + + +block t3038: + type + Data[T] = ref object of RootObj + data: T + Type = ref object of RootObj + SubType[T] = ref object of Type + data: Data[T] + SubSubType = ref object of SubType[int] + SubSubSubType = ref object of SubSubType diff --git a/tests/objects/tobjects_various.nim b/tests/objects/tobjects_various.nim new file mode 100644 index 000000000..55db9312e --- /dev/null +++ b/tests/objects/tobjects_various.nim @@ -0,0 +1,120 @@ +discard """ + output: ''' +34 +b +wohoo +baz +''' +""" + + +block tobject2: + # Tests the object implementation + type + TPoint2d {.inheritable.} = object + x, y: int + TPoint3d = object of TPoint2d + z: int # added a field + + proc getPoint( p: var TPoint2d) = + writeLine(stdout, p.x) + + var p: TPoint3d + + TPoint2d(p).x = 34 + p.y = 98 + p.z = 343 + + getPoint(p) + + + +block tofopr: + type + TMyType {.inheritable.} = object + len: int + data: string + + TOtherType = object of TMyType + + proc p(x: TMyType): bool = + return x of TOtherType + + var + m: TMyType + n: TOtherType + + doAssert p(m) == false + doAssert p(n) + + + +block toop: + type + TA = object of RootObj + x, y: int + TB = object of TA + z: int + TC = object of TB + whatever: string + + proc p(a: var TA) = echo "a" + proc p(b: var TB) = echo "b" + + var c: TC + p(c) + + + +block tfefobjsyntax: + type + Foo = object + a, b: int + s: string + FooBar = object of RootObj + n, m: string + Baz = object of FooBar + + proc invoke(a: ref Baz) = + echo "baz" + + # check object construction: + let x = (ref Foo)(a: 0, b: 45, s: "wohoo") + echo x.s + + var y: ref FooBar = (ref Baz)(n: "n", m: "m") + invoke((ref Baz)(y)) + + + +block t3012: + type + A {.inheritable.} = object + C {.inheritable.} = ref object + + type + AA = ref object of A + CC = ref object of C + + + +block t7244: + type + Foo = ref object of RootRef + Bar = ref object of Foo + + proc test(foo: var Foo) = discard + proc test(bar: var Bar) = test(Foo(bar)) + + +import std/macros + +#bug #20856 +macro ensureImplWorksOnConstr(t: typed): untyped = + expectKind(t, nnkObjConstr) + doAssert t[0].getTypeInst.getImpl.repr == "A = object" + doAssert t[0].getImpl.repr == "A = object" + +type A = object + +ensureImplWorksOnConstr(A()) diff --git a/tests/objects/tobjpragma.nim b/tests/objects/tobjpragma.nim new file mode 100644 index 000000000..789b3ec4e --- /dev/null +++ b/tests/objects/tobjpragma.nim @@ -0,0 +1,53 @@ +discard """ + output: ''' +2 +3 +9 +257 +1 +2 +3 +''' +disabled: "true" +""" + +# Disabled since some versions of GCC ignore the 'packed' attribute + +# Test + +type + Foo {.packed.} = object + a: int8 + b: int8 + + Bar {.packed.} = object + a: int8 + b: int16 + + Daz {.packed.} = object + a: int32 + b: int8 + c: int32 + + +var f = Foo(a: 1, b: 1) +var b: Bar +var d: Daz + +echo sizeof(f) +echo sizeof(b) +echo sizeof(d) +echo (cast[ptr int16](f.addr)[]) + +type + Union {.union.} = object + a: int8 + b: int8 + +var u: Union +u.a = 1 +echo u.b +u.a = 2 +echo u.b +u.b = 3 +echo u.a diff --git a/tests/objects/toop1.nim b/tests/objects/toop1.nim new file mode 100644 index 000000000..3e9b24990 --- /dev/null +++ b/tests/objects/toop1.nim @@ -0,0 +1,85 @@ +discard """ + output: "34[]o 5" +""" +# Test the stuff in the tutorial +import macros + +type + TFigure = object of RootObj # abstract base class: + draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this + +proc init(f: var TFigure) = + f.draw = nil + +type + TCircle = object of TFigure + radius: int + +proc drawCircle(my: var TCircle) = stdout.writeLine("o " & $my.radius) + +proc init(my: var TCircle) = + init(TFigure(my)) # call base constructor + my.radius = 5 + my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawCircle) + +type + TRectangle = object of TFigure + width, height: int + +proc drawRectangle(my: var TRectangle) = stdout.write("[]") + +proc init(my: var TRectangle) = + init(TFigure(my)) # call base constructor + my.width = 5 + my.height = 10 + my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle) + +macro `!` (n: varargs[untyped]): typed = + let n = callsite() + result = newNimNode(nnkCall, n) + var dot = newNimNode(nnkDotExpr, n) + dot.add(n[1]) # obj + if n[2].kind == nnkCall: + # transforms ``obj!method(arg1, arg2, ...)`` to + # ``(obj.method)(obj, arg1, arg2, ...)`` + dot.add(n[2][0]) # method + result.add(dot) + result.add(n[1]) # obj + for i in 1..n[2].len-1: + result.add(n[2][i]) + else: + # transforms ``obj!method`` to + # ``(obj.method)(obj)`` + dot.add(n[2]) # method + result.add(dot) + result.add(n[1]) # obj + +type + TSocket* = object of RootObj + FHost: int # cannot be accessed from the outside of the module + # the `F` prefix is a convention to avoid clashes since + # the accessors are named `host` + +proc `host=`*(s: var TSocket, value: int) {.inline.} = + ## setter of hostAddr + s.FHost = value + +proc host*(s: TSocket): int {.inline.} = + ## getter of hostAddr + return s.FHost + +var + s: TSocket +s.host = 34 # same as `host=`(s, 34) +stdout.write(s.host) + +# now use these classes: +var + r: TRectangle + c: TCircle +init(r) +init(c) +r!draw +c!draw() + +#OUT 34[]o 5 diff --git a/tests/objects/trequireinit.nim b/tests/objects/trequireinit.nim new file mode 100644 index 000000000..202667b02 --- /dev/null +++ b/tests/objects/trequireinit.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "The MPlayerObj type doesn't have a default value. The following fields must be initialized: foo." +""" + +type + MPlayerObj* {.requiresInit.} = object + foo: range[5..10] = 5 + +var a: MPlayerObj +echo a.foo \ No newline at end of file diff --git a/tests/objects/tunsafenew.nim b/tests/objects/tunsafenew.nim new file mode 100644 index 000000000..6c1b33cd9 --- /dev/null +++ b/tests/objects/tunsafenew.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "conversion from int literal(-1) to Natural is invalid" +""" + +type + Obj = object + case b: bool + else: discard +var o: ref Obj +unsafeNew(o, -1) \ No newline at end of file diff --git a/tests/objects/tunsafenew2.nim b/tests/objects/tunsafenew2.nim new file mode 100644 index 000000000..83112bcfc --- /dev/null +++ b/tests/objects/tunsafenew2.nim @@ -0,0 +1,15 @@ +discard """ +valgrind: "leaks" +matrix: "-d:useMalloc" +targets: "c cpp" +""" + +type + Obj = object + case b: bool + else: discard + a: UncheckedArray[byte] + +var o: ref Obj +unsafeNew(o, sizeof(Obj) + 512) +zeroMem(addr o.a, 512) diff --git a/tests/objects/twhen1.nim b/tests/objects/twhen1.nim new file mode 100644 index 000000000..fe072a46b --- /dev/null +++ b/tests/objects/twhen1.nim @@ -0,0 +1,89 @@ +const Z = 0 + +type + Foo[T] = object + when true: + u: int + else: + v: int + Foo1[T] = object + when T is int: + x: T + elif true: + z: char + Foo2[x:static[int]] = object + when (x and 1) == 1: + x: array[x+1,int] + else: + x: array[x,int] + + Foo3 = Foo2[128] + + # #8417 + Foo4[A: static[int]] = object + when Z == 0: + discard + else: + discard + +block: + var x: Foo[int] = Foo[int](u: 42) + doAssert x.u == 42 + +# Don't evaluate `when` branches before the type is instantiated +block: + var x: Foo1[bool] = Foo1[bool](z: 'o') + doAssert x.z == 'o' + +block: + var x: Foo2[3] + doAssert x.x.len == 4 + +block: + var x: Foo2[4] + doAssert x.x.len == 4 + +block: + var x: Foo3 + doAssert x.x.len == 128 + +block: + var x: Foo4[0] + +type + MyObject = object + x: int + when (NimMajor, NimMinor) >= (1, 1): + y: int +discard MyObject(x: 100, y: 200) + +block: # Ensure when evaluates properly in objects + type X[bits: static int] = object #22474 + when bits >= 256: + data32: byte + else: + data16: byte + + static: + discard X[255]().data16 + discard X[256]().data32 + + + type ComplexExprObject[S: static string, I: static int, Y: static auto] = object + when 'h' in S and I < 10 and Y isnot float: + a: int + elif I > 30: + b: int + elif typeof(Y) is float: + c: int + else: + d: int + + static: + discard ComplexExprObject["hello", 9, 300i32]().a + discard ComplexExprObject["", 40, 30f]().b + discard ComplexExprObject["", 20, float 30]().c + discard ComplexExprObject["", 20, ""]().d + + + |