nimsuggest: more precise cursor tracking
This commit is contained in:
parent
da821a22d9
commit
4755795416
24 changed files with 104 additions and 81 deletions
8
nimsuggest/tests/dep_v1.nim
Normal file
8
nimsuggest/tests/dep_v1.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
type
|
||||
Foo* = object
|
||||
x*, y*: int
|
||||
9
nimsuggest/tests/dep_v2.nim
Normal file
9
nimsuggest/tests/dep_v2.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
type
|
||||
Foo* = object
|
||||
x*, y*: int
|
||||
z*: string
|
||||
27
nimsuggest/tests/tchk1.nim
Normal file
27
nimsuggest/tests/tchk1.nim
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# test we get some suggestion at the end of the file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
type
|
||||
|
||||
|
||||
template foo() =
|
||||
|
||||
proc main =
|
||||
|
||||
#[!]#
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>chk $1
|
||||
chk;;skUnknown;;;;Hint;;???;;-1;;-1;;"tchk1 [Processing]";;0
|
||||
chk;;skUnknown;;;;Error;;$file;;12;;0;;"identifier expected, but found \'keyword template\'";;0
|
||||
chk;;skUnknown;;;;Error;;$file;;14;;0;;"complex statement requires indentation";;0
|
||||
chk;;skUnknown;;;;Error;;$file;;12;;0;;"implementation of \'foo\' expected";;0
|
||||
chk;;skUnknown;;;;Error;;$file;;17;;0;;"invalid indentation";;0
|
||||
chk;;skUnknown;;;;Hint;;$file;;12;;9;;"\'foo\' is declared but not used [XDeclaredButNotUsed]";;0
|
||||
chk;;skUnknown;;;;Hint;;$file;;14;;5;;"\'tchk1.main()\' is declared but not used [XDeclaredButNotUsed]";;0
|
||||
"""
|
||||
12
nimsuggest/tests/tcursor_at_end.nim
Normal file
12
nimsuggest/tests/tcursor_at_end.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# test we get some suggestion at the end of the file
|
||||
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skProc;;tcursor_at_end.main;;proc ();;$file;;10;;5;;"";;*
|
||||
"""
|
||||
|
||||
|
||||
proc main = discard
|
||||
|
||||
#[!]#
|
||||
16
nimsuggest/tests/tdef1.nim
Normal file
16
nimsuggest/tests/tdef1.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>def $1
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
|
||||
>def $1
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
|
||||
"""
|
||||
|
||||
proc hello(): string =
|
||||
## Return hello
|
||||
"Hello"
|
||||
|
||||
hel#[!]#lo()
|
||||
|
||||
# v uncompleted id for sug (13,2)
|
||||
he
|
||||
14
nimsuggest/tests/tdot1.nim
Normal file
14
nimsuggest/tests/tdot1.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skField;;x;;int;;$file;;11;;4;;"";;100;;None
|
||||
sug;;skField;;y;;int;;$file;;11;;7;;"";;100;;None
|
||||
sug;;skProc;;tdot1.main;;proc (f: Foo);;$file;;13;;5;;"";;100;;None
|
||||
"""
|
||||
|
||||
type
|
||||
Foo = object
|
||||
x, y: int
|
||||
|
||||
proc main(f: Foo) =
|
||||
if f.#[!]#:
|
||||
29
nimsuggest/tests/tdot2.nim
Normal file
29
nimsuggest/tests/tdot2.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Test basic editing. We replace the 'false' by 'true' to
|
||||
# see whether then the z field is suggested.
|
||||
|
||||
const zField = 0i32
|
||||
|
||||
type
|
||||
Foo = object
|
||||
x, y: int
|
||||
when zField == 1i32:
|
||||
z: string
|
||||
|
||||
proc main(f: Foo) =
|
||||
f.#[!]#
|
||||
|
||||
# the tester supports the spec section at the bottom of the file and
|
||||
# this way, the line numbers more often stay the same
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skField;;x;;int;;$file;;8;;4;;"";;100;;None
|
||||
sug;;skField;;y;;int;;$file;;8;;7;;"";;100;;None
|
||||
sug;;skProc;;tdot2.main;;proc (f: Foo);;$file;;12;;5;;"";;100;;None
|
||||
!edit 0i32 1i32
|
||||
>sug $1
|
||||
sug;;skField;;x;;int;;$file;;8;;4;;"";;100;;None
|
||||
sug;;skField;;y;;int;;$file;;8;;7;;"";;100;;None
|
||||
sug;;skField;;z;;string;;$file;;10;;6;;"";;100;;None
|
||||
sug;;skProc;;tdot2.main;;proc (f: Foo);;$file;;12;;5;;"";;100;;None
|
||||
"""
|
||||
27
nimsuggest/tests/tdot3.nim
Normal file
27
nimsuggest/tests/tdot3.nim
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Test basic module dependency recompilations.
|
||||
|
||||
import dep
|
||||
|
||||
proc main(f: Foo) =
|
||||
f.#[!]#
|
||||
|
||||
# the tester supports the spec section at the bottom of the file and
|
||||
# this way, the line numbers more often stay the same
|
||||
|
||||
discard """
|
||||
!copy dep_v1.nim dep.nim
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skField;;x;;int;;*dep.nim;;8;;4;;"";;100;;None
|
||||
sug;;skField;;y;;int;;*dep.nim;;8;;8;;"";;100;;None
|
||||
sug;;skProc;;tdot3.main;;proc (f: Foo);;$file;;5;;5;;"";;100;;None
|
||||
|
||||
!copy dep_v2.nim dep.nim
|
||||
>mod $path/dep.nim
|
||||
>sug $1
|
||||
sug;;skField;;x;;int;;*dep.nim;;8;;4;;"";;100;;None
|
||||
sug;;skField;;y;;int;;*dep.nim;;8;;8;;"";;100;;None
|
||||
sug;;skField;;z;;string;;*dep.nim;;9;;4;;"";;100;;None
|
||||
sug;;skProc;;tdot3.main;;proc (f: Foo);;$file;;5;;5;;"";;100;;None
|
||||
!del dep.nim
|
||||
"""
|
||||
7
nimsuggest/tests/tinclude.nim
Normal file
7
nimsuggest/tests/tinclude.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
discard """
|
||||
$nimsuggest --tester compiler/nim.nim
|
||||
>def compiler/semexprs.nim:13:50
|
||||
def;;skType;;ast.PSym;;PSym;;*ast.nim;;669;;2;;"";;100
|
||||
>def compiler/semexprs.nim:13:50
|
||||
def;;skType;;ast.PSym;;PSym;;*ast.nim;;669;;2;;"";;100
|
||||
"""
|
||||
14
nimsuggest/tests/tno_deref.nim
Normal file
14
nimsuggest/tests/tno_deref.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
var x: ptr int
|
||||
|
||||
proc foo(y: ptr int) =
|
||||
discard
|
||||
|
||||
x.#[!]#
|
||||
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skProc;;tno_deref.foo;;proc (y: ptr int)*;;$file;;4;;5;;"";;100;;None
|
||||
*
|
||||
"""
|
||||
9
nimsuggest/tests/tstrutils.nim
Normal file
9
nimsuggest/tests/tstrutils.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
discard """
|
||||
$nimsuggest --tester lib/pure/strutils.nim
|
||||
>def lib/pure/strutils.nim:2300:6
|
||||
def;;skTemplate;;system.doAssert;;proc (cond: bool, msg: string): typed;;*/lib/system.nim;;*;;9;;"same as `assert` but is always turned on and not affected by the\x0A``--assertions`` command line switch.";;100
|
||||
"""
|
||||
|
||||
# Line 2300 in strutils.nim is doAssert and this is unlikely to change
|
||||
# soon since there are a whole lot of doAsserts there.
|
||||
|
||||
28
nimsuggest/tests/tsug_regression.nim
Normal file
28
nimsuggest/tests/tsug_regression.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# test we only get suggestions, not error messages:
|
||||
|
||||
import tables, sets, parsecfg
|
||||
|
||||
type X = object
|
||||
|
||||
proc main =
|
||||
# bug #52
|
||||
var
|
||||
set0 = initSet[int]()
|
||||
set1 = initSet[X]()
|
||||
set2 = initSet[ref int]()
|
||||
|
||||
map0 = initTable[int, int]()
|
||||
map1 = initOrderedTable[string, int]()
|
||||
cfg = loadConfig("file")
|
||||
map0.#[!]#
|
||||
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skProc;;tables.getOrDefault;;proc (t: Table[getOrDefault.A, getOrDefault.B], key: A): B;;$lib/pure/collections/tables.nim;;178;;5;;"";;100;;None
|
||||
sug;;skProc;;tables.hasKey;;proc (t: Table[hasKey.A, hasKey.B], key: A): bool;;$lib/pure/collections/tables.nim;;233;;5;;"returns true iff `key` is in the table `t`.";;100;;None
|
||||
sug;;skProc;;tables.add;;proc (t: var Table[add.A, add.B], key: A, val: B);;$lib/pure/collections/tables.nim;;297;;5;;"puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.";;100;;None
|
||||
sug;;skIterator;;tables.allValues;;iterator (t: Table[allValues.A, allValues.B], key: A): B{.inline.};;$lib/pure/collections/tables.nim;;225;;9;;"iterates over any value in the table `t` that belongs to the given `key`.";;100;;None
|
||||
sug;;skProc;;tables.clear;;proc (t: var Table[clear.A, clear.B]);;$lib/pure/collections/tables.nim;;121;;5;;"Resets the table so that it is empty.";;100;;None
|
||||
*
|
||||
"""
|
||||
213
nimsuggest/tests/twithin_macro.nim
Normal file
213
nimsuggest/tests/twithin_macro.nim
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
|
||||
import macros
|
||||
|
||||
macro class*(head, body: untyped): untyped =
|
||||
# The macro is immediate, since all its parameters are untyped.
|
||||
# This means, it doesn't resolve identifiers passed to it.
|
||||
|
||||
var typeName, baseName: NimNode
|
||||
|
||||
# flag if object should be exported
|
||||
var exported: bool
|
||||
|
||||
if head.kind == nnkInfix and head[0].ident == !"of":
|
||||
# `head` is expression `typeName of baseClass`
|
||||
# echo head.treeRepr
|
||||
# --------------------
|
||||
# Infix
|
||||
# Ident !"of"
|
||||
# Ident !"Animal"
|
||||
# Ident !"RootObj"
|
||||
typeName = head[1]
|
||||
baseName = head[2]
|
||||
|
||||
elif head.kind == nnkInfix and head[0].ident == !"*" and
|
||||
head[2].kind == nnkPrefix and head[2][0].ident == !"of":
|
||||
# `head` is expression `typeName* of baseClass`
|
||||
# echo head.treeRepr
|
||||
# --------------------
|
||||
# Infix
|
||||
# Ident !"*"
|
||||
# Ident !"Animal"
|
||||
# Prefix
|
||||
# Ident !"of"
|
||||
# Ident !"RootObj"
|
||||
typeName = head[1]
|
||||
baseName = head[2][1]
|
||||
exported = true
|
||||
|
||||
else:
|
||||
quit "Invalid node: " & head.lispRepr
|
||||
|
||||
# The following prints out the AST structure:
|
||||
#
|
||||
# import macros
|
||||
# dumptree:
|
||||
# type X = ref object of Y
|
||||
# z: int
|
||||
# --------------------
|
||||
# StmtList
|
||||
# TypeSection
|
||||
# TypeDef
|
||||
# Ident !"X"
|
||||
# Empty
|
||||
# RefTy
|
||||
# ObjectTy
|
||||
# Empty
|
||||
# OfInherit
|
||||
# Ident !"Y"
|
||||
# RecList
|
||||
# IdentDefs
|
||||
# Ident !"z"
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
|
||||
# create a type section in the result
|
||||
result =
|
||||
if exported:
|
||||
# mark `typeName` with an asterisk
|
||||
quote do:
|
||||
type `typeName`* = ref object of `baseName`
|
||||
else:
|
||||
quote do:
|
||||
type `typeName` = ref object of `baseName`
|
||||
|
||||
# echo treeRepr(body)
|
||||
# --------------------
|
||||
# StmtList
|
||||
# VarSection
|
||||
# IdentDefs
|
||||
# Ident !"name"
|
||||
# Ident !"string"
|
||||
# Empty
|
||||
# IdentDefs
|
||||
# Ident !"age"
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
# MethodDef
|
||||
# Ident !"vocalize"
|
||||
# Empty
|
||||
# Empty
|
||||
# FormalParams
|
||||
# Ident !"string"
|
||||
# Empty
|
||||
# Empty
|
||||
# StmtList
|
||||
# StrLit ...
|
||||
# MethodDef
|
||||
# Ident !"age_human_yrs"
|
||||
# Empty
|
||||
# Empty
|
||||
# FormalParams
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
# Empty
|
||||
# StmtList
|
||||
# DotExpr
|
||||
# Ident !"this"
|
||||
# Ident !"age"
|
||||
|
||||
# var declarations will be turned into object fields
|
||||
var recList = newNimNode(nnkRecList)
|
||||
|
||||
# expected name of constructor
|
||||
let ctorName = newIdentNode("new" & $typeName)
|
||||
|
||||
# Iterate over the statements, adding `this: T`
|
||||
# to the parameters of functions, unless the
|
||||
# function is a constructor
|
||||
for node in body.children:
|
||||
case node.kind:
|
||||
|
||||
of nnkMethodDef, nnkProcDef:
|
||||
# check if it is the ctor proc
|
||||
if node.name.kind != nnkAccQuoted and node.name.basename == ctorName:
|
||||
# specify the return type of the ctor proc
|
||||
node.params[0] = typeName
|
||||
else:
|
||||
# inject `self: T` into the arguments
|
||||
node.params.insert(1, newIdentDefs(ident("self"), typeName))
|
||||
result.add(node)
|
||||
|
||||
of nnkVarSection:
|
||||
# variables get turned into fields of the type.
|
||||
for n in node.children:
|
||||
recList.add(n)
|
||||
|
||||
else:
|
||||
result.add(node)
|
||||
|
||||
# Inspect the tree structure:
|
||||
#
|
||||
# echo result.treeRepr
|
||||
# --------------------
|
||||
# StmtList
|
||||
# TypeSection
|
||||
# TypeDef
|
||||
# Ident !"Animal"
|
||||
# Empty
|
||||
# RefTy
|
||||
# ObjectTy
|
||||
# Empty
|
||||
# OfInherit
|
||||
# Ident !"RootObj"
|
||||
# Empty <= We want to replace this
|
||||
# MethodDef
|
||||
# ...
|
||||
|
||||
result[0][0][2][0][2] = recList
|
||||
|
||||
# Lets inspect the human-readable version of the output
|
||||
#echo repr(result)
|
||||
|
||||
# ---
|
||||
|
||||
class Animal of RootObj:
|
||||
var name: string
|
||||
var age: int
|
||||
method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods
|
||||
method age_human_yrs: int {.base.} = self.age # `this` is injected
|
||||
proc `$`: string = "animal:" & self.name & ":" & $self.age
|
||||
|
||||
class Dog of Animal:
|
||||
method vocalize: string = "woof"
|
||||
method age_human_yrs: int = self.age * 7
|
||||
proc `$`: string = "dog:" & self.name & ":" & $self.age
|
||||
|
||||
class Cat of Animal:
|
||||
method vocalize: string = "meow"
|
||||
proc `$`: string = "cat:" & self.name & ":" & $self.age
|
||||
|
||||
class Rabbit of Animal:
|
||||
proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type
|
||||
result = Rabbit(name: name, age: age)
|
||||
method vocalize: string = "meep"
|
||||
proc `$`: string =
|
||||
self.#[!]#
|
||||
result = "rabbit:" & self.name & ":" & $self.age
|
||||
|
||||
# ---
|
||||
|
||||
var animals: seq[Animal] = @[]
|
||||
animals.add(Dog(name: "Sparky", age: 10))
|
||||
animals.add(Cat(name: "Mitten", age: 10))
|
||||
|
||||
for a in animals:
|
||||
echo a.vocalize()
|
||||
echo a.age_human_yrs()
|
||||
|
||||
let r = newRabbit("Fluffy", 3)
|
||||
echo r.vocalize()
|
||||
echo r.age_human_yrs()
|
||||
echo r
|
||||
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;None
|
||||
sug;;skField;;name;;string;;$file;;166;;6;;"";;100;;None
|
||||
sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;None
|
||||
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;168;;9;;"";;100;;None
|
||||
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;184;;9;;"";;100;;None
|
||||
sug;;skMacro;;twithin_macro.class;;proc (head: untyped, body: untyped): untyped{.gcsafe, locks: <unknown>.};;$file;;4;;6;;"";;50;;None*
|
||||
"""
|
||||
209
nimsuggest/tests/twithin_macro_prefix.nim
Normal file
209
nimsuggest/tests/twithin_macro_prefix.nim
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
|
||||
import macros
|
||||
|
||||
macro class*(head, body: untyped): untyped =
|
||||
# The macro is immediate, since all its parameters are untyped.
|
||||
# This means, it doesn't resolve identifiers passed to it.
|
||||
|
||||
var typeName, baseName: NimNode
|
||||
|
||||
# flag if object should be exported
|
||||
var exported: bool
|
||||
|
||||
if head.kind == nnkInfix and head[0].ident == !"of":
|
||||
# `head` is expression `typeName of baseClass`
|
||||
# echo head.treeRepr
|
||||
# --------------------
|
||||
# Infix
|
||||
# Ident !"of"
|
||||
# Ident !"Animal"
|
||||
# Ident !"RootObj"
|
||||
typeName = head[1]
|
||||
baseName = head[2]
|
||||
|
||||
elif head.kind == nnkInfix and head[0].ident == !"*" and
|
||||
head[2].kind == nnkPrefix and head[2][0].ident == !"of":
|
||||
# `head` is expression `typeName* of baseClass`
|
||||
# echo head.treeRepr
|
||||
# --------------------
|
||||
# Infix
|
||||
# Ident !"*"
|
||||
# Ident !"Animal"
|
||||
# Prefix
|
||||
# Ident !"of"
|
||||
# Ident !"RootObj"
|
||||
typeName = head[1]
|
||||
baseName = head[2][1]
|
||||
exported = true
|
||||
|
||||
else:
|
||||
quit "Invalid node: " & head.lispRepr
|
||||
|
||||
# The following prints out the AST structure:
|
||||
#
|
||||
# import macros
|
||||
# dumptree:
|
||||
# type X = ref object of Y
|
||||
# z: int
|
||||
# --------------------
|
||||
# StmtList
|
||||
# TypeSection
|
||||
# TypeDef
|
||||
# Ident !"X"
|
||||
# Empty
|
||||
# RefTy
|
||||
# ObjectTy
|
||||
# Empty
|
||||
# OfInherit
|
||||
# Ident !"Y"
|
||||
# RecList
|
||||
# IdentDefs
|
||||
# Ident !"z"
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
|
||||
# create a type section in the result
|
||||
result =
|
||||
if exported:
|
||||
# mark `typeName` with an asterisk
|
||||
quote do:
|
||||
type `typeName`* = ref object of `baseName`
|
||||
else:
|
||||
quote do:
|
||||
type `typeName` = ref object of `baseName`
|
||||
|
||||
# echo treeRepr(body)
|
||||
# --------------------
|
||||
# StmtList
|
||||
# VarSection
|
||||
# IdentDefs
|
||||
# Ident !"name"
|
||||
# Ident !"string"
|
||||
# Empty
|
||||
# IdentDefs
|
||||
# Ident !"age"
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
# MethodDef
|
||||
# Ident !"vocalize"
|
||||
# Empty
|
||||
# Empty
|
||||
# FormalParams
|
||||
# Ident !"string"
|
||||
# Empty
|
||||
# Empty
|
||||
# StmtList
|
||||
# StrLit ...
|
||||
# MethodDef
|
||||
# Ident !"age_human_yrs"
|
||||
# Empty
|
||||
# Empty
|
||||
# FormalParams
|
||||
# Ident !"int"
|
||||
# Empty
|
||||
# Empty
|
||||
# StmtList
|
||||
# DotExpr
|
||||
# Ident !"this"
|
||||
# Ident !"age"
|
||||
|
||||
# var declarations will be turned into object fields
|
||||
var recList = newNimNode(nnkRecList)
|
||||
|
||||
# expected name of constructor
|
||||
let ctorName = newIdentNode("new" & $typeName)
|
||||
|
||||
# Iterate over the statements, adding `this: T`
|
||||
# to the parameters of functions, unless the
|
||||
# function is a constructor
|
||||
for node in body.children:
|
||||
case node.kind:
|
||||
|
||||
of nnkMethodDef, nnkProcDef:
|
||||
# check if it is the ctor proc
|
||||
if node.name.kind != nnkAccQuoted and node.name.basename == ctorName:
|
||||
# specify the return type of the ctor proc
|
||||
node.params[0] = typeName
|
||||
else:
|
||||
# inject `self: T` into the arguments
|
||||
node.params.insert(1, newIdentDefs(ident("self"), typeName))
|
||||
result.add(node)
|
||||
|
||||
of nnkVarSection:
|
||||
# variables get turned into fields of the type.
|
||||
for n in node.children:
|
||||
recList.add(n)
|
||||
|
||||
else:
|
||||
result.add(node)
|
||||
|
||||
# Inspect the tree structure:
|
||||
#
|
||||
# echo result.treeRepr
|
||||
# --------------------
|
||||
# StmtList
|
||||
# TypeSection
|
||||
# TypeDef
|
||||
# Ident !"Animal"
|
||||
# Empty
|
||||
# RefTy
|
||||
# ObjectTy
|
||||
# Empty
|
||||
# OfInherit
|
||||
# Ident !"RootObj"
|
||||
# Empty <= We want to replace this
|
||||
# MethodDef
|
||||
# ...
|
||||
|
||||
result[0][0][2][0][2] = recList
|
||||
|
||||
# Lets inspect the human-readable version of the output
|
||||
#echo repr(result)
|
||||
|
||||
# ---
|
||||
|
||||
class Animal of RootObj:
|
||||
var name: string
|
||||
var age: int
|
||||
method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods
|
||||
method age_human_yrs: int {.base.} = self.age # `this` is injected
|
||||
proc `$`: string = "animal:" & self.name & ":" & $self.age
|
||||
|
||||
class Dog of Animal:
|
||||
method vocalize: string = "woof"
|
||||
method age_human_yrs: int = self.age * 7
|
||||
proc `$`: string = "dog:" & self.name & ":" & $self.age
|
||||
|
||||
class Cat of Animal:
|
||||
method vocalize: string = "meow"
|
||||
proc `$`: string = "cat:" & self.name & ":" & $self.age
|
||||
|
||||
class Rabbit of Animal:
|
||||
proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type
|
||||
result = Rabbit(name: name, age: age)
|
||||
method vocalize: string = "meep"
|
||||
proc `$`: string =
|
||||
self.ag#[!]#
|
||||
result = "rabbit:" & self.name & ":" & $self.age
|
||||
|
||||
# ---
|
||||
|
||||
var animals: seq[Animal] = @[]
|
||||
animals.add(Dog(name: "Sparky", age: 10))
|
||||
animals.add(Cat(name: "Mitten", age: 10))
|
||||
|
||||
for a in animals:
|
||||
echo a.vocalize()
|
||||
echo a.age_human_yrs()
|
||||
|
||||
let r = newRabbit("Fluffy", 3)
|
||||
echo r.vocalize()
|
||||
echo r.age_human_yrs()
|
||||
echo r
|
||||
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;Prefix
|
||||
sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;Prefix
|
||||
"""
|
||||
Loading…
Add table
Add a link
Reference in a new issue