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

every symbol becomes 1st class; defines 0-cost lambda and aliases; generics/iterators/templates/etc can be passed to any routine #11992

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f9f2942
[aliassym] passing symbols to a routine works; does not work if symbo…
timotheecour Aug 21, 2019
1203fe2
fixup
timotheecour Aug 21, 2019
2d4c8ed
add tests; add std/lambdas
timotheecour Aug 21, 2019
f65ccbe
fix tests
timotheecour Aug 21, 2019
6195882
fixup
timotheecour Aug 21, 2019
bb30c34
fixup
timotheecour Aug 21, 2019
0edac69
add test for https://github.com/nim-lang/Nim/issues/5702
timotheecour Aug 21, 2019
e563ae4
fix cpp exportc, refs #12144
timotheecour Aug 21, 2019
7b8b5bd
workaround for #12020 (caused by new gensym handling for params)
timotheecour Sep 8, 2019
40899ce
MyType.myAlias(args) now works
timotheecour Jun 11, 2020
f3689d1
lambdaStatic: lambda can replace static[T]
timotheecour Jun 11, 2020
2ba2625
lambdaType: alias can replace typedesc[T]
timotheecour Jun 12, 2020
15e9267
recycle tyOptDeprecated => tyAliasSym
timotheecour Jun 18, 2020
f15f121
fixups
timotheecour Jun 18, 2020
576df76
close https://github.com/nim-lang/Nim/issues/9679
timotheecour Jun 19, 2020
23ab426
make lambda `~>` robust to symbols in scope, introducing `replaceSym`
timotheecour Jun 19, 2020
a43ac02
alias2 now controlled by pushable {.experimental:"alias".}
timotheecour Jun 22, 2020
ff13926
runnableExamples + doc comments for std/lambdas
timotheecour Jun 22, 2020
a056411
fix tests
timotheecour Jun 23, 2020
b2f961e
move elementType
timotheecour Jun 23, 2020
b4a6e98
_
timotheecour Jul 4, 2020
a022e50
fixup after rebase
timotheecour Nov 2, 2020
5df8e61
address comment: avoid importc/exportc as a way to circumvent cyclic …
timotheecour Nov 2, 2020
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
24 changes: 15 additions & 9 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -427,16 +427,17 @@ type
# instantiation and prior to this it has the potential to
# be any type.

tyOptDeprecated
# 'out' parameter. Comparable to a 'var' parameter but every
# path must assign a value to it before it can be read from.
tyAliasSym
## type of symbol alias

tyVoid
# now different from tyEmpty, hurray!

static:
# remind us when TTypeKind stops to fit in a single 64-bit word
assert TTypeKind.high.ord <= 63
# remind us when TTypeKind stops to fit in a single 64-bit word
# consider merging some types if profiling shows a slowdown (though it's
# unlikely)

const
tyPureObject* = tyTuple
Expand Down Expand Up @@ -499,7 +500,7 @@ type
tfFromGeneric, # type is an instantiation of a generic; this is needed
# because for instantiations of objects, structural
# type equality has to be used
tfUnresolved, # marks unresolved typedesc/static params: e.g.
tfUnresolved, # marks unresolved typedesc/static/aliasSym params: e.g.
# proc foo(T: typedesc, list: seq[T]): var T
# proc foo(L: static[int]): array[L, int]
# can be attached to ranges to indicate that the range
Expand Down Expand Up @@ -588,7 +589,8 @@ type
# file (it is loaded on demand, which may
# mean: never)
skPackage, # symbol is a package (used for canonicalization)
skAlias # an alias (needs to be resolved immediately)
skAlias, # an alias (needs to be resolved immediately)
skAliasGroup # nkOpenSymChoice as a symbol
TSymKinds* = set[TSymKind]

const
Expand Down Expand Up @@ -680,8 +682,9 @@ type
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
mSymIsInstantiationOf, mNodeId

mSymIsInstantiationOf, mNodeId,
mAlias2,
mAliasSym,

# things that we can evaluate safely at compile time, even if not asked for it:
const
Expand Down Expand Up @@ -832,6 +835,7 @@ type
procInstCache*: seq[PInstantiation]
gcUnsafetyReason*: PSym # for better error messages wrt gcsafe
transformedBody*: PNode # cached body after transf pass
aliasTarget*: PSym # used for skTemplate
of skModule, skPackage:
# modules keep track of the generic symbols they use from other modules.
# this is because in incremental compilation, when a module is about to
Expand All @@ -848,6 +852,8 @@ type
guard*: PSym
bitsize*: int
alignment*: int # for alignment
of skAliasGroup:
nodeAliasGroup*: PNode
else: nil
magic*: TMagic
typ*: PType
Expand Down Expand Up @@ -1212,7 +1218,7 @@ proc astdef*(s: PSym): PNode =

proc isMetaType*(t: PType): bool =
return t.kind in tyMetaTypes or
(t.kind == tyStatic and t.n == nil) or
(t.kind in {tyStatic, tyAliasSym} and t.n == nil) or
tfHasMeta in t.flags

proc isUnresolvedStatic*(t: PType): bool =
Expand Down
3 changes: 1 addition & 2 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ proc mapType(typ: PType): TJSTypeKind =
of tyGenericParam, tyGenericBody, tyGenericInvocation,
tyNone, tyFromExpr, tyForward, tyEmpty,
tyUntyped, tyTyped, tyTypeDesc, tyBuiltInTypeClass, tyCompositeTypeClass,
tyAnd, tyOr, tyNot, tyAnything, tyVoid:
tyAnd, tyOr, tyNot, tyAnything, tyVoid, tyAliasSym:
result = etyNone
of tyGenericInst, tyInferred, tyAlias, tyUserTypeClass, tyUserTypeClassInst,
tySink, tyOwned:
Expand All @@ -210,7 +210,6 @@ proc mapType(typ: PType): TJSTypeKind =
else: result = etyNone
of tyProc: result = etyProc
of tyCString: result = etyString
of tyOptDeprecated: doAssert false

proc mapType(p: PProc; typ: PType): TJSTypeKind =
result = mapType(typ)
Expand Down
3 changes: 1 addition & 2 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -785,13 +785,12 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
tyTypeDesc, tyGenericInvocation, tyForward, tyStatic:
tyTypeDesc, tyGenericInvocation, tyForward, tyStatic, tyAliasSym:
#internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t))
discard
of tyOrdinal, tyRange, tyInferred,
tyGenericInst, tyAlias, tySink:
fillBody(c, lastSon(t), body, x, y)
of tyOptDeprecated: doAssert false

proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
kind: TTypeAttachedOp; info: TLineInfo;
Expand Down
39 changes: 30 additions & 9 deletions compiler/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,28 @@ iterator walkScopes*(scope: PScope): PScope =
yield current
current = current.parent

proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
if s == nil or s.kind != skAlias:
result = s
else:
result = s.owner
if conf.cmd == cmdPretty:
prettybase.replaceDeprecated(conf, n.info, s, result)
proc skipAlias*(s: PSym; info: TLineInfo; conf: ConfigRef): PSym =
result = s
while true:
if result == nil: return result
if result.kind in {skParam, skConst} and result.typ != nil and result.typ.kind == tyAliasSym and result.typ.n != nil:
# `result.typ.n` can be nil for a proc declaration param
result = result.typ.n.sym
if result.nodeAliasGroup.kind == nkSym:
result = result.nodeAliasGroup.sym
elif result.kind == skAlias:
let old = result
result=result.owner
if conf.cmd == cmdPretty:
prettybase.replaceDeprecated(conf, info, old, result)
else:
message(conf, info, warnDeprecated, "use " & result.name.s & " instead; " &
old.name.s & " is deprecated")
else:
message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &
s.name.s & " is deprecated")
return result

proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
skipAlias(s, n.info, conf)

proc isShadowScope*(s: PScope): bool {.inline.} = s.parent != nil and s.parent.depthLevel == s.depthLevel

Expand Down Expand Up @@ -153,6 +165,7 @@ type
symChoiceIndex*: int
scope*: PScope
inSymChoice: IntSet
n2*: PNode

proc getSymRepr*(conf: ConfigRef; s: PSym, getDeclarationPath = true): string =
case s.kind
Expand Down Expand Up @@ -379,6 +392,13 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
if result != nil and result.kind == skStub: loadStub(result)

proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
defer:
if result != nil and result.kind == skAliasGroup:
result = initOverloadIter(o, c, result.nodeAliasGroup)
o.n2 = n
if n.typ != nil and n.typ.kind == tyAliasSym:
return initOverloadIter(o, c, n.typ.n.sym.nodeAliasGroup)

case n.kind
of nkIdent, nkAccQuoted:
var ident = considerQuotedIdent(c, n)
Expand Down Expand Up @@ -436,6 +456,7 @@ proc lastOverloadScope*(o: TOverloadIter): int =
else: result = -1

proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
let n = o.n2 # consider removing `n` from params
case o.mode
of oimDone:
result = nil
Expand Down
3 changes: 2 additions & 1 deletion compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ type
## Note: this feature can't be localized with {.push.}
vmopsDanger,
strictFuncs,
views
views,
featureAlias = "alias",

LegacyFeature* = enum
allowSemcheckedAstModification,
Expand Down
52 changes: 50 additions & 2 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ when not defined(leanCompiler):
import spawn

# implementation

proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
proc semExprNoType(c: PContext, n: PNode): PNode
Expand Down Expand Up @@ -450,6 +449,15 @@ const
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
errFloatToString = "cannot convert '$1' to '$2'"

proc isMacroRealGeneric(s: PSym): bool =
if s.kind != skMacro: return false
if s.ast == nil: return false
let n = s.ast
if n[genericParamsPos].kind == nkEmpty: return false
for ai in n[genericParamsPos]:
if ai.typ.kind == tyAliasSym:
return true

proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =
pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
Expand All @@ -468,7 +476,47 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,

#if c.evalContext == nil:
# c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym)
template evalMacroCallAux: untyped =
evalMacroCall(c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym)

proc evalAux(): PNode = # MOVE
# c.p.wasForwarded = proto != nil
# TODO: cleanup afterwards the changes to avoid affecting original macro
var oldPrc = sym
pushProcCon(c, oldPrc)
pushOwner(c, oldPrc)
pushInfoContext(c.config, oldPrc.info)
openScope(c)
#[
var n = oldPrc.ast
n.sons[bodyPos] = copyTree(s.getBody)
instantiateBody(c, n, oldPrc.typ.n, oldPrc, s)
]#
let procParams = sym.typ.n
for i in 1 ..< procParams.len:
let pi = procParams[i]
# SEE: instantiateBody
if pi.kind == nkSym and pi.sym.typ != nil and pi.sym.typ.kind == tyAliasSym:
pi.sym.typ = n.sons[i].typ # TODO: undo that after; or operate on different copy
doAssert sym.kind == skMacro
addParamOrResult(c, pi.sym, sym.kind)
# paramsTypeCheck(c, s.typ) # TODO?
maybeAddResult(c, sym, n) # CHECKME: n or sym.ast?
sym.ast[bodyPos] = hloBody(c, semProcBody(c, sym.ast[bodyPos]))

result = evalMacroCallAux()
# skipping trackProc

closeScope(c)
popInfoContext(c.config)
popOwner(c)
popProcCon(c)

if isMacroRealGeneric(sym):
result = evalAux()
else:
result = evalMacroCallAux()

if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags)
if c.config.macrosToExpand.hasKey(sym.name.s):
Expand Down
5 changes: 4 additions & 1 deletion compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,10 @@ proc semResolvedCall(c: PContext, x: TCandidate,
of skType:
x.call.add newSymNode(s, n.info)
else:
internalAssert c.config, false
if s.kind == skParam and s.typ != nil and s.typ.kind == tyAliasSym: # IMPROVE ; TODO: only for `aliassym`, not `typed` ?
x.call.add s.ast
else:
internalAssert c.config, false

result = x.call
instGenericConvertersSons(c, result, x)
Expand Down
Loading