Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nimony: implements instantiationInfo #382

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions lib/std/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,39 @@ proc addr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.}

proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.}
proc sizeof*(x: typedesc): int {.magic: "SizeOf", noSideEffect.}

proc instantiationInfo*(index = -1, fullPaths = false): tuple[
filename: string, line: int, column: int] {.magic: "InstantiationInfo", noSideEffect.}
## Provides access to the compiler's instantiation stack line information
## of a template.
##
## While similar to the `caller info`:idx: of other languages, it is determined
## at compile time.
##
## This proc is mostly useful for meta programming (eg. `assert` template)
## to retrieve information about the current filename and line number.
## Example:
##
## ```nim
## import std/strutils
##
## template testException(exception, code: untyped): typed =
## try:
## let pos = instantiationInfo()
## discard(code)
## echo "Test failure at $1:$2 with '$3'" % [pos.filename,
## $pos.line, astToStr(code)]
## assert false, "A test expecting failure succeeded?"
## except exception:
## discard
##
## proc tester(pos: int): int =
## let
## a = @[1, 2, 3]
## result = a[pos]
##
## when isMainModule:
## testException(IndexDefect, tester(30))
## testException(IndexDefect, tester(1))
## # --> Test failure at example.nim:20 with 'tester(1)'
## ```
2 changes: 1 addition & 1 deletion src/hexer/duplifier.nim
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ proc tr(c: var Context; n: var Cursor; e: Expects) =
DefinedX, HighX, LowX, TypeofX, UnpackX, EnumToStrX, IsMainModuleX, QuotedX,
DerefX, HderefX, AddrX, HaddrX:
trSons c, n, WantNonOwner
of DefaultObjX, DefaultTupX:
of DefaultObjX, DefaultTupX, InstantiationInfoX:
raiseAssert "nodekind should have been eliminated in sem.nim"
of NoExpr:
case n.stmtKind
Expand Down
1 change: 1 addition & 0 deletions src/nimony/magics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ proc magicToTag*(m: TMagic): (string, int) =
of mDefaultTup: res DefaultTupX
of mOpenArray: res OpenArrayT
of mEnsureMove: res EnsureMoveX
of mInstantiationInfo: res InstantiationInfoX
else: ("", 0)

when isMainModule:
Expand Down
1 change: 1 addition & 0 deletions src/nimony/nimony_model.nim
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type
ArrAtX = "arrat"
TupAtX = "tupat" # tup[0] syntax
EnsureMoveX = "emove" # note that `move` can be written in standard Nim
InstantiationInfoX = "instantiationinfo"

TypeKind* = enum
NoType
Expand Down
48 changes: 46 additions & 2 deletions src/nimony/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
## Most important task is to turn identifiers into symbols and to perform
## type checking.

import std / [tables, sets, syncio, formatfloat, assertions, packedsets, strutils]
import std / [os, tables, sets, syncio, formatfloat, assertions, packedsets, strutils]
include nifprelude
import nimony_model, symtabs, builtintypes, decls, symparser, asthelpers,
programs, sigmatch, magics, reporters, nifconfig, nifindexes,
Expand Down Expand Up @@ -787,7 +787,7 @@ proc addFn(c: var SemContext; fn: FnCandidate; fnOrig: Cursor; args: openArray[I
if n.kind == ParLe:
if n.exprKind in {DefinedX, DeclaredX, CompilesX, TypeofX,
LowX, HighX, AddrX, EnumToStrX, DefaultObjX, DefaultTupX,
ArrAtX, DerefX, TupAtX}:
ArrAtX, DerefX, TupAtX, InstantiationInfoX}:
# magic needs semchecking after overloading
result = MagicCallNeedsSemcheck
else:
Expand Down Expand Up @@ -3930,6 +3930,48 @@ proc semTupAt(c: var SemContext; it: var Item) =
wantParRi c, it.n
commonType c, it, exprStart, expected

proc semInstantiationInfo(c: var SemContext, it: var Item) =
let info = it.n.info
let expected = it.typ
let exprStart = c.dest.len

c.dest.addParLe(TupleConstrX, info)
inc it.n

# TODO: info stack
let idx: xint = evalOrdinal(c, it.n)
if idx.isNaN:
c.buildErr it.n.info, "cannot evaluate at compile time: " & toString(it.n)
skip it.n
let useFullPaths = evalOrdinal(c, it.n)
if useFullPaths.isNaN:
c.buildErr it.n.info, "cannot evaluate at compile time: " & toString(it.n)
skip it.n

let (file, line, col) = unpack(pool.man, info)

let filename: string
if useFullPaths == createXint(1'i64):
filename = absolutePath(pool.files[file])
else:
filename = pool.files[file]
c.dest.addStrLit filename, info
c.dest.addIntLit line, info
c.dest.addIntLit col, info

wantParRi c, it.n

let typeStart = c.dest.len

c.dest.buildTree TupleT, info:
c.dest.addSubtree c.types.stringType
c.dest.addSubtree c.types.intType
c.dest.addSubtree c.types.intType

it.typ = typeToCursor(c, typeStart)
c.dest.shrink typeStart
commonType c, it, exprStart, expected

proc getDottedIdent(n: var Cursor): string =
let isError = n.kind == ParLe and n.tagId == ErrT
if isError:
Expand Down Expand Up @@ -4738,6 +4780,8 @@ proc semExpr(c: var SemContext; it: var Item; flags: set[SemFlag] = {}) =
semObjDefault c, it
of DefaultTupX:
semTupleDefault c, it
of InstantiationInfoX:
semInstantiationInfo c, it
of LowX:
semLow c, it
of HighX:
Expand Down
2 changes: 1 addition & 1 deletion src/nimony/typenav.nim
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ proc getTypeImpl(c: var TypeCache; n: Cursor): Cursor =
result = c.builtins.boolType
of NegX, NegInfX, NanX, InfX:
result = c.builtins.floatType
of EnumToStrX, DefaultObjX, DefaultTupX:
of EnumToStrX, DefaultObjX, DefaultTupX, InstantiationInfoX:
result = c.builtins.stringType
of SizeofX:
result = c.builtins.intType
Expand Down
8 changes: 7 additions & 1 deletion tests/nimony/sysbasics/tbasics.nif
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,10 @@
(pointer) 5
(cast 5
(pointer) 14 m.3)) 4,4
(call ~4 foo3.0.tbawx6nu81 1 m2.0))))
(call ~4 foo3.0.tbawx6nu81 1 m2.0))) 4,35
(let :sInfo.0.tbawx6nu81 . . 25
(tuple
(string)
(i -1)
(i -1)) 25
(tup "tests/nimony/sysbasics/tbasics.nim" +36 +29)))
3 changes: 3 additions & 0 deletions tests/nimony/sysbasics/tbasics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ block:
foo3(m)
let m2 = cast[pointer](m)
foo3(m2)


let sInfo = instantiationInfo(-1, false)
Loading