checkpoint

This commit is contained in:
ringabout
2023-08-23 18:19:39 +08:00
parent a4781dc4bc
commit 52bf954ba5
11 changed files with 131 additions and 12 deletions

View File

@@ -231,7 +231,7 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # 51 flags!
TSymFlag* = enum # 52 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
@@ -316,6 +316,7 @@ type
sfByCopy # param is marked as pass bycopy
sfMember # proc is a C++ member of a type
sfCodegenDecl # type, proc, global or proc param is marked as codegenDecl
sfToplevelDecl
TSymFlags* = set[TSymFlag]

View File

@@ -222,6 +222,7 @@ type
strictDefs,
strictCaseObjects,
inferGenericTypes
noforwardDecl
LegacyFeature* = enum
allowSemcheckedAstModification,

View File

@@ -81,9 +81,9 @@ proc prePass(c: PContext; n: PNode) =
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
let feature = parseEnum[Feature](name.strVal)
if feature == codeReordering:
c.features.incl feature
c.module.flags.incl sfReorder
# if feature == codeReordering:
c.features.incl feature
c.module.flags.incl sfReorder
except ValueError:
discard
else:

View File

@@ -34,7 +34,7 @@ proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
var it: TIdentIter
result = initIdentIter(it, scope.symbols, fn.name)
while result != nil:
if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags):
if result.kind == fn.kind and result.typ != nil: #and sameType(result.typ, fn.typ, flags):
case equalParams(result.typ.n, fn.typ.n)
of paramsEqual:
if (sfExported notin result.flags) and (sfExported in fn.flags):

View File

@@ -762,6 +762,58 @@ proc isEmptyTree(n: PNode): bool =
of nkEmpty, nkCommentStmt: result = true
else: result = false
proc decl(c: PContext, n: PNode, kind: TSymKind): PNode =
if n[0].kind == nkIdent:
var s = newSym(kind, n[0].ident, c.idgen, getCurrOwner(c), n.info)
s.flags.incl sfToplevelDecl
# pragmaCallable(c, s, n, allRoutinePragmas)
result = n
if n[^1].kind != nkEmpty:
if s.kind in OverloadableSyms:
addInterfaceOverloadableSymAt(c, c.currentScope, s)
else:
addInterfaceDeclAt(c, c.currentScope, s)
result[0] = newSymNode(s)
else:
result = n
import reorder
proc semSignature(c: PContext, n: PNode): PNode =
case n.kind
of nkProcDef:
result = decl(c, n, skProc)
of nkMethodDef:
result = decl(c, n, skMethod)
of nkConverterDef:
result = decl(c, n, skConverter)
of nkMacroDef:
result = decl(c, n, skMacro)
of nkTemplateDef:
result = decl(c, n, skTemplate)
of nkIteratorDef:
result = decl(c, n, skIterator)
of nkIncludeStmt:
result = n
for i in 0..<n.len:
var f = checkModuleName(c.config, n[i])
if f != InvalidFileIdx:
if containsOrIncl(c.includedFiles, f.int):
localError(c.config, n[i].info, "recursive dependency: '$1'" %
toMsgFilename(c.config, f))
else:
let nn = includeModule(c.graph, c.module, f)
result = semSignature(c, nn)
excl(c.includedFiles, f.int)
of nkStmtList:
result = copyNode(n)
for i in 0..<n.len:
result.add semSignature(c, n[i])
else:
result = n
proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
if c.topStmts == 0 and not isImportSystemStmt(c.graph, n):
if sfSystemModule notin c.module.flags and not isEmptyTree(n):
@@ -775,6 +827,9 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = semAllTypeSections(c, n)
else:
result = n
# if noforwardDecl in c.features:
# debug result
result = semSignature(c, result)
result = semStmt(c, result, {})
when false:
# Code generators are lazy now and can deal with undeclared procs, so these

View File

@@ -1726,6 +1726,7 @@ proc semProcAnnotation(c: PContext, prc: PNode;
validPragmas: TSpecialWords): PNode =
# Mirrored with semVarMacroPragma
result = nil
doAssert prc != nil
var n = prc[pragmasPos]
if n == nil or n.kind == nkEmpty: return
for i in 0..<n.len:
@@ -2175,6 +2176,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
var (proto, comesFromShadowScope) =
if isAnon: (nil, false)
else: searchForProc(c, declarationScope, s)
# if sfToplevelDecl in s.flags and proto != nil:
# # symTabRemove(declarationScope.symbols, proto)
# s.flags.incl proto.flags # copy flags of forward decls
# proto = nil
if proto == nil and sfForward in s.flags and n[bodyPos].kind != nkEmpty:
## In cases such as a macro generating a proc with a gensymmed name we
## know `searchForProc` will not find it and sfForward will be set. In
@@ -2204,11 +2211,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# pragma analysis further down.
s.typ.callConv = lastOptionEntry(c).defaultCC
if not hasProto and sfGenSym notin s.flags: #and not isAnon:
if s.kind in OverloadableSyms:
addInterfaceOverloadableSymAt(c, declarationScope, s)
else:
addInterfaceDeclAt(c, declarationScope, s)
pragmaCallable(c, s, n, validPragmas)
if not hasProto:
@@ -2218,6 +2220,18 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
setEffectsForProcType(c.graph, s.typ, n[pragmasPos], s)
s.typ.flags.incl tfEffectSystemWorkaround
let isForwards = n[bodyPos].kind == nkEmpty and {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone
# delay
if ((sfToplevelDecl notin s.flags or
{sfImportc, sfBorrow, sfError} * s.flags != {} or
s.magic != mNone
) and
not hasProto and sfGenSym notin s.flags): #and not isAnon:
if s.kind in OverloadableSyms:
addInterfaceOverloadableSymAt(c, declarationScope, s)
else:
addInterfaceDeclAt(c, declarationScope, s)
# To ease macro generation that produce forwarded .async procs we now
# allow a bit redundancy in the pragma declarations. The rule is
# a prototype's pragma list must be a superset of the current pragma
@@ -2240,7 +2254,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
onDef(n[namePos].info, s)
if hasProto:
if sfForward notin proto.flags and proto.magic == mNone:
if sfForward notin proto.flags and sfToplevelDecl notin proto.flags and proto.magic == mNone:
wrongRedefinition(c, n.info, proto.name.s, proto.info)
if not comesFromShadowScope:
excl(proto.flags, sfForward)
@@ -2389,7 +2403,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return
#if s.magic != mNone: return
#if s.ast.isNil: return
# if s.ast.isNil: return
if s.ast == nil:
debug s
discard semProcAux(c, s.ast, s.kind, {})
proc semIterator(c: PContext, n: PNode): PNode =

View File

@@ -2473,6 +2473,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
m.state = csMatch # until proven otherwise
m.firstMismatch = MismatchInfo()
doAssert m.callee != nil
m.call = newNodeIT(n.kind, n.info, m.callee.base)
m.call.add n[0]

11
tests/forward/t1.nim Normal file
View File

@@ -0,0 +1,11 @@
{.experimental: "noforwardDecl".}
proc bar(x: int) =
var s = 1
inc s, x
foo(s)
proc foo(x: int) =
echo x
bar(999)

14
tests/forward/t2.nim Normal file
View File

@@ -0,0 +1,14 @@
{.experimental: "noforwardDecl".}
proc foo(x: int)
proc bar(x: int) =
var s = 1
inc s, x
foo(s)
proc foo(x: int) =
echo x
bar(999)

15
tests/forward/t3.nim Normal file
View File

@@ -0,0 +1,15 @@
{.experimental: "noforwardDecl".}
proc bar(x: int) =
var s = 1
inc s, x
foo(s)
proc foo(x: int)
proc foo(x: int) =
echo x
bar(999)

5
tests/options/test.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#include "nimbase.h"
struct Foo {
int a;
};