Skip to content

Commit

Permalink
wip fold not nil
Browse files Browse the repository at this point in the history
  • Loading branch information
Clyybber committed Feb 29, 2024
1 parent f46227d commit c3acc15
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 7 deletions.
3 changes: 3 additions & 0 deletions compiler/mir/mirgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ proc genTypeExpr(c: var TCtx, n: PNode): Value =
if n[^1].typ.kind == tyTypeDesc:
genTypeExpr(c, n.lastSon)
else:
#echo "nooo"
# HACK: this is big hack. Consider the following case:
#
# .. code-block:: nim
Expand Down Expand Up @@ -2051,9 +2052,11 @@ proc generateCode*(graph: ModuleGraph, env: var MirEnv,
# situtations like the example above, it's simpler, faster, and more
# intuitive to either evaluate them directly when analying the type
# expression or during ``semfold``
#echo "ha",n.kind
c.builder.useSource(c.sp, n)
c.use genTypeExpr(c, n)
else:
#echo "ho"
c.builder.useSource(c.sp, n)
# XXX: restructure the ``mirgen`` API to use a dedicated procedure for
# generating expression code
Expand Down
6 changes: 5 additions & 1 deletion compiler/sem/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,12 @@ proc evalConstExpr(c: PContext, n: PNode): PNode =
# we first perform constant folding in the AST and then attempt to fold
# the expression. This is a bit more efficient than doing it the other way
# around
#echo "befo ",n.kind,' ',n.typ.kind
result = foldInAst(c.module, n, c.idgen, c.graph)
#echo "afe ",result.kind,' ',result.typ.kind
if (let f = getConstExprError(c.module, result, c.idgen, c.graph); f != nil):
# constant folding was successful or resulted in an error
#echo "a"
return f

# evaluate the expression with the VM:
Expand Down Expand Up @@ -730,7 +733,8 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# More restrictive version.
result = semExprWithType(c, result, flags)
of tyTypeDesc:
if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
#if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListExpr)
if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListExpr)
result = semTypeNode2(c, result, nil)
if result.kind != nkError:
result.typ = makeTypeDesc(c, result.typ)
Expand Down
20 changes: 20 additions & 0 deletions compiler/sem/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2913,6 +2913,26 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
of mSizeOf:
markUsed(c, n.info, s)
result = semSizeof(c, setMs(n, s))
of mNot:
markUsed(c, n.info, s)
if n.len == 3 and n[2].kind == nkNilLit:

result = semTypeNode2(c, n, nil)
# a type expression is of type ``typeDesc[T]``
result.typ = makeTypeDesc(c, result.typ.skipTypes({tyTypeDesc}))

when false:
# T not nil
n[1] = semExprWithType(c, n[1])
n.typ = getSysType(c.graph, n.info, tyInt)
result.typ = makeTypeDesc(c, typExpr.typ)


result = freshType(c, result, prev)
result.flags.incl(tfNotNil)
else:
assert false, "haha" & $n
result = semDirectOp(c, n, flags)
else:
result = semDirectOp(c, n, flags)

Expand Down
56 changes: 55 additions & 1 deletion compiler/sem/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,38 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
if s.kind != skProc and s.kind != skFunc: return
try:
case s.magic
of mNot:
if n.len == 3 and n[2].kind == nkNilLit:
# echo "TODO",n.len,'|',n
# echo n.info

# result = semTypeNode(c, n, nil)
# # a type expression is of type ``typeDesc[T]``
# result.typ = makeTypeDesc(c, result.typ.skipTypes({tyTypeDesc}))

# result = newType(tyError, nextTypeId(g.idgen), g.owners[^1])
# result.flags.incl tfNotNil

# # T not nil
# n[1] = semExprWithType(c, n[1])
# n.typ = getSysType(c.graph, n.info, tyInt)
# result.typ = makeTypeDesc(c, typExpr.typ)

let res = n[1].typ.skipTypes({tyTypeDesc})
#echo "XOLA ",n[2].kind
#echo "magic XOLOL",res.kind

var newTyp = copyType(res, nextTypeId idgen, res.owner)
copyTypeProps(g, idgen.module, newTyp , res)
#result = freshType(c, result, prev)
newTyp .flags.incl(tfNotNil)

var newTyp2 = newType(tyTypeDesc, nextTypeId(idgen), res.owner)
incl newTyp2 .flags, tfCheckedForDestructor
newTyp2.addSonSkipIntLit(newTyp, idgen)

result = newNodeIT(nkType, n.info, newTyp2)

of mNone:
# If it has no sideEffect, `evalAtCompileTime` should evaluate it
return
Expand Down Expand Up @@ -849,7 +881,29 @@ proc foldConstExprAux(m: PSym, n: PNode, idgen: IdGenerator, g: ModuleGraph): Fo
of nkBracket, nkCurly, nkTupleConstr, nkRange, nkAddr, nkHiddenAddr,
nkHiddenDeref, nkDerefExpr, nkBracketExpr, nkCallKinds, nkIfExpr,
nkElifExpr, nkElseExpr, nkElse, nkElifBranch:
for it in n.items:
if n.kind == nkInfix and n.len == 3 and n[2].kind == nkNilLit and
$n[0] == "not": # n[0].sym is an ident...
# echo "haha", $n
# echo n[0].kind
# echo n[0].getMagic()

let res = n[1].typ.skipTypes({tyTypeDesc})
#echo "XOLA ",n[2].kind
#echo "XOLOL",res.kind

var newTyp = copyType(res, nextTypeId idgen, res.owner)
copyTypeProps(g, idgen.module, newTyp , res)
#result = freshType(c, result, prev)
newTyp .flags.incl(tfNotNil)

var newTyp2 = newType(tyTypeDesc, nextTypeId(idgen), res.owner)
incl newTyp2 .flags, tfCheckedForDestructor
newTyp2.addSonSkipIntLit(newTyp, idgen)


result.node = newNodeIT(nkType, n.info, newTyp2)
else:
for it in n.items:
result.add foldConstExprAux(m, it, idgen, g)
of nkCast, nkConv, nkHiddenStdConv, nkHiddenSubConv, nkBlockExpr, nkBlockType:
# the first slot only holds the type/label, which we don't need to traverse
Expand Down
6 changes: 3 additions & 3 deletions compiler/sem/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
# I suggest revisiting this once the language decides on whether
# `not nil` should be the default. We can then map nilable refs
# to other types such as `Option[T]`.
result = makeTypeFromExpr(c, newTree(nkStmtListType, n.copyTree))
result = makeTypeFromExpr(c, n.copyTree)
of NilableTypes + {tyGenericInvocation, tyForward}:
result = freshType(c, result, prev)
result.flags.incl(tfNotNil)
Expand Down Expand Up @@ -2162,7 +2162,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkWhenStmt:
var whenResult = semWhen(c, n, false)
if whenResult.kind == nkStmtList:
whenResult.transitionSonsKind(nkStmtListType)
whenResult.transitionSonsKind(nkStmtListExpr)
result = semTypeNode(c, whenResult, prev)
of nkBracketExpr:
checkMinSonsLen(n, 2, c.config)
Expand Down Expand Up @@ -2312,7 +2312,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else:
result = semProcTypeWithScope(c, n, prev, skProc)
of nkEnumTy: result = semEnum(c, n, prev)
of nkStmtListType: result = semStmtListType(c, n, prev)
of nkStmtListType, nkStmtListExpr: result = semStmtListType(c, n, prev)
of nkBlockType: result = semBlockType(c, n, prev)
of nkError:
localReport(c.config, n, reportSem rsemTypeExpected)
Expand Down
6 changes: 4 additions & 2 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
##
## .. include:: ./system_overview.rst


type
float* {.magic: Float.} ## Default floating point type.
float32* {.magic: Float32.} ## 32 bit floating point type.
Expand Down Expand Up @@ -63,7 +62,6 @@ proc `$`*[Enum: enum](x: Enum): string {.magic: "EnumToStr", noSideEffect.}

include "system/basic_types"


proc runnableExamples*(rdoccmd = "", body: untyped) {.magic: "RunnableExamples".} =
## A section you should use to mark `runnable example`:idx: code with.
##
Expand Down Expand Up @@ -3043,3 +3041,7 @@ when defined(nimDebugUtils):
{.define(nimCompilerDebug).}
n
{.undef(nimCompilerDebug).}

proc `not`*(a: typedesc[ref], b: typeof(nil)): typedesc {.magic: "Not".}
proc `not`*(a: ref, b: typeof(nil)): typedesc {.magic: "Not".}

0 comments on commit c3acc15

Please sign in to comment.