static params: expr[T] is now static[T]
This introduces tyStatic and successfully bootstraps and handles few simple test cases. Static params within macros are no longer treated as PNimrodNodes - they are now equivalent to constants of the designated type.
This commit is contained in:
parent
7120491d05
commit
027f30610e
22 changed files with 135 additions and 110 deletions
|
|
@ -192,6 +192,7 @@ type
|
||||||
nkObjectTy, # object body
|
nkObjectTy, # object body
|
||||||
nkTupleTy, # tuple body
|
nkTupleTy, # tuple body
|
||||||
nkTypeClassTy, # user-defined type class
|
nkTypeClassTy, # user-defined type class
|
||||||
|
nkStaticTy, # ``static[T]``
|
||||||
nkRecList, # list of object parts
|
nkRecList, # list of object parts
|
||||||
nkRecCase, # case section of object
|
nkRecCase, # case section of object
|
||||||
nkRecWhen, # when section of object
|
nkRecWhen, # when section of object
|
||||||
|
|
@ -336,12 +337,13 @@ type
|
||||||
tyIter, # unused
|
tyIter, # unused
|
||||||
tyProxy # used as errornous type (for idetools)
|
tyProxy # used as errornous type (for idetools)
|
||||||
tyTypeClass
|
tyTypeClass
|
||||||
|
tyParametricTypeClass # structured similarly to tyGenericInst
|
||||||
|
# lastSon is the body of the type class
|
||||||
tyAnd
|
tyAnd
|
||||||
tyOr
|
tyOr
|
||||||
tyNot
|
tyNot
|
||||||
tyAnything
|
tyAnything
|
||||||
tyParametricTypeClass # structured similarly to tyGenericInst
|
tyStatic
|
||||||
# lastSon is the body of the type class
|
|
||||||
|
|
||||||
const
|
const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
|
|
@ -1232,7 +1234,7 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||||
if tfShared in elem.flags:
|
if tfShared in elem.flags:
|
||||||
owner.flags.incl tfHasShared
|
owner.flags.incl tfHasShared
|
||||||
|
|
||||||
if elem.kind in {tyExpr, tyTypeDesc}:
|
if elem.kind in {tyExpr, tyStatic, tyTypeDesc}:
|
||||||
owner.flags.incl tfHasMeta
|
owner.flags.incl tfHasMeta
|
||||||
elif elem.kind in {tyString, tyRef, tySequence} or
|
elif elem.kind in {tyString, tyRef, tySequence} or
|
||||||
elem.kind == tyProc and elem.callConv == ccClosure:
|
elem.kind == tyProc and elem.callConv == ccClosure:
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ proc GetUniqueType*(key: PType): PType =
|
||||||
result = key
|
result = key
|
||||||
of tyTypeDesc, tyTypeClasses:
|
of tyTypeDesc, tyTypeClasses:
|
||||||
InternalError("value expected, but got a type")
|
InternalError("value expected, but got a type")
|
||||||
of tyGenericParam:
|
of tyGenericParam, tyStatic:
|
||||||
InternalError("GetUniqueType")
|
InternalError("GetUniqueType")
|
||||||
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
||||||
result = GetUniqueType(lastSon(key))
|
result = GetUniqueType(lastSon(key))
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ when compileTimeRopeFmt:
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0)
|
yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0)
|
||||||
|
|
||||||
macro rfmt(m: BModule, fmt: expr[string], args: varargs[PRope]): expr =
|
macro rfmt(m: BModule, fmt: static[string], args: varargs[PRope]): expr =
|
||||||
## Experimental optimized rope-formatting operator
|
## Experimental optimized rope-formatting operator
|
||||||
## The run-time code it produces will be very fast, but will it speed up
|
## The run-time code it produces will be very fast, but will it speed up
|
||||||
## the compilation of nimrod itself or will the macro execution time
|
## the compilation of nimrod itself or will the macro execution time
|
||||||
|
|
@ -209,7 +209,7 @@ when compileTimeRopeFmt:
|
||||||
of ffParam:
|
of ffParam:
|
||||||
result.add(args[frag.intValue])
|
result.add(args[frag.intValue])
|
||||||
else:
|
else:
|
||||||
template rfmt(m: BModule, fmt: expr[string], args: varargs[PRope]): expr =
|
template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
|
||||||
ropecg(m, fmt, args)
|
ropecg(m, fmt, args)
|
||||||
|
|
||||||
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ proc mapType(t: ast.PType): ptr libffi.TType =
|
||||||
of tyFloat, tyFloat64: result = addr libffi.type_double
|
of tyFloat, tyFloat64: result = addr libffi.type_double
|
||||||
of tyFloat32: result = addr libffi.type_float
|
of tyFloat32: result = addr libffi.type_float
|
||||||
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyNil:
|
tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyStatic, tyNil:
|
||||||
result = addr libffi.type_pointer
|
result = addr libffi.type_pointer
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
result = mapType(t.sons[0])
|
result = mapType(t.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ proc evalMacroCall*(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode
|
||||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
|
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
|
||||||
|
|
||||||
proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
|
proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
|
||||||
|
if defined(debug): writeStackTrace()
|
||||||
result = newNodeI(nkExceptBranch, info)
|
result = newNodeI(nkExceptBranch, info)
|
||||||
# creating a nkExceptBranch without sons
|
# creating a nkExceptBranch without sons
|
||||||
# means that it could not be evaluated
|
# means that it could not be evaluated
|
||||||
|
|
@ -264,7 +265,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
result = newNodeIt(nkFloatLit, info, t)
|
result = newNodeIt(nkFloatLit, info, t)
|
||||||
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyProc:
|
tyStmt, tyTypeDesc, tyStatic, tyProc:
|
||||||
result = newNodeIT(nkNilLit, info, t)
|
result = newNodeIT(nkNilLit, info, t)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
|
|
@ -358,7 +359,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc aliasNeeded(n: PNode, flags: TEvalFlags): bool =
|
proc aliasNeeded(n: PNode, flags: TEvalFlags): bool =
|
||||||
result = efLValue in flags or n.typ == nil or
|
result = efLValue in flags or n.typ == nil or
|
||||||
n.typ.kind in {tyExpr, tyStmt, tyTypeDesc}
|
n.typ.kind in {tyExpr, tyStatic, tyStmt, tyTypeDesc}
|
||||||
|
|
||||||
proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
|
proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
|
||||||
# We need to return a node to the actual value,
|
# We need to return a node to the actual value,
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||||
result = etyObject
|
result = etyObject
|
||||||
of tyNil: result = etyNull
|
of tyNil: result = etyNull
|
||||||
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone,
|
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone,
|
||||||
tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClasses:
|
tyForward, tyEmpty, tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
|
||||||
result = etyNone
|
result = etyNone
|
||||||
of tyProc: result = etyProc
|
of tyProc: result = etyProc
|
||||||
of tyCString: result = etyString
|
of tyCString: result = etyString
|
||||||
|
|
|
||||||
|
|
@ -965,14 +965,18 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||||
of tkTuple: result = parseTuple(p, mode == pmTypeDef)
|
of tkTuple: result = parseTuple(p, mode == pmTypeDef)
|
||||||
of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
|
of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
|
||||||
of tkIterator:
|
of tkIterator:
|
||||||
if mode in {pmTypeDesc, pmTypeDef}:
|
when true:
|
||||||
result = parseProcExpr(p, false)
|
if mode in {pmTypeDesc, pmTypeDef}:
|
||||||
result.kind = nkIteratorTy
|
result = parseProcExpr(p, false)
|
||||||
|
result.kind = nkIteratorTy
|
||||||
|
else:
|
||||||
|
# no anon iterators for now:
|
||||||
|
parMessage(p, errExprExpected, p.tok)
|
||||||
|
getTok(p) # we must consume a token here to prevend endless loops!
|
||||||
|
result = ast.emptyNode
|
||||||
else:
|
else:
|
||||||
# no anon iterators for now:
|
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
|
||||||
parMessage(p, errExprExpected, p.tok)
|
result.kind = nkIteratorTy
|
||||||
getTok(p) # we must consume a token here to prevend endless loops!
|
|
||||||
result = ast.emptyNode
|
|
||||||
of tkEnum:
|
of tkEnum:
|
||||||
if mode == pmTypeDef:
|
if mode == pmTypeDef:
|
||||||
result = parseEnum(p)
|
result = parseEnum(p)
|
||||||
|
|
@ -995,9 +999,13 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||||
getTokNoInd(p)
|
getTokNoInd(p)
|
||||||
addSon(result, primary(p, pmNormal))
|
addSon(result, primary(p, pmNormal))
|
||||||
of tkStatic:
|
of tkStatic:
|
||||||
result = newNodeP(nkStaticExpr, p)
|
let info = parLineInfo(p)
|
||||||
getTokNoInd(p)
|
getTokNoInd(p)
|
||||||
addSon(result, primary(p, pmNormal))
|
let next = primary(p, pmNormal)
|
||||||
|
if next.kind == nkBracket and next.sonsLen == 1:
|
||||||
|
result = newNode(nkStaticTy, info, @[next.sons[0]])
|
||||||
|
else:
|
||||||
|
result = newNode(nkStaticExpr, info, @[next])
|
||||||
of tkBind:
|
of tkBind:
|
||||||
result = newNodeP(nkBind, p)
|
result = newNodeP(nkBind, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
|
||||||
|
|
@ -282,13 +282,16 @@ proc ropef(frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||||
app(result, substr(frmt, start, i - 1))
|
app(result, substr(frmt, start, i - 1))
|
||||||
assert(RopeInvariant(result))
|
assert(RopeInvariant(result))
|
||||||
|
|
||||||
{.push stack_trace: off, line_trace: off.}
|
when true:
|
||||||
proc `~`*(r: expr[string]): PRope =
|
template `~`*(r: string): PRope = r.ropef
|
||||||
# this is the new optimized "to rope" operator
|
else:
|
||||||
# the mnemonic is that `~` looks a bit like a rope :)
|
{.push stack_trace: off, line_trace: off.}
|
||||||
var r {.global.} = r.ropef
|
proc `~`*(r: static[string]): PRope =
|
||||||
return r
|
# this is the new optimized "to rope" operator
|
||||||
{.pop.}
|
# the mnemonic is that `~` looks a bit like a rope :)
|
||||||
|
var r {.global.} = r.ropef
|
||||||
|
return r
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
proc appf(c: var PRope, frmt: TFormatStr, args: varargs[PRope]) =
|
proc appf(c: var PRope, frmt: TFormatStr, args: varargs[PRope]) =
|
||||||
app(c, ropef(frmt, args))
|
app(c, ropef(frmt, args))
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
# if a proc accesses a global variable, it is not side effect free:
|
# if a proc accesses a global variable, it is not side effect free:
|
||||||
if sfGlobal in s.flags:
|
if sfGlobal in s.flags:
|
||||||
incl(c.p.owner.flags, sfSideEffect)
|
incl(c.p.owner.flags, sfSideEffect)
|
||||||
elif s.kind == skParam and s.typ.kind == tyExpr and s.typ.n != nil:
|
elif s.kind == skParam and s.typ.kind == tyStatic and s.typ.n != nil:
|
||||||
# XXX see the hack in sigmatch.nim ...
|
# XXX see the hack in sigmatch.nim ...
|
||||||
return s.typ.n
|
return s.typ.n
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
|
|
@ -111,7 +111,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
# var len = 0 # but won't be called
|
# var len = 0 # but won't be called
|
||||||
# genericThatUsesLen(x) # marked as taking a closure?
|
# genericThatUsesLen(x) # marked as taking a closure?
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
if s.typ.kind == tyExpr:
|
if s.typ.kind == tyStatic:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
elif s.ast != nil:
|
elif s.ast != nil:
|
||||||
|
|
@ -668,6 +668,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
else:
|
else:
|
||||||
result = semOverloadedCall(c, n, nOrig,
|
result = semOverloadedCall(c, n, nOrig,
|
||||||
{skProc, skMethod, skConverter, skMacro, skTemplate})
|
{skProc, skMethod, skConverter, skMacro, skTemplate})
|
||||||
|
|
||||||
if result != nil:
|
if result != nil:
|
||||||
if result.sons[0].kind != nkSym:
|
if result.sons[0].kind != nkSym:
|
||||||
InternalError("semOverloadedCallAnalyseEffects")
|
InternalError("semOverloadedCallAnalyseEffects")
|
||||||
|
|
@ -937,7 +938,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
let tParam = tbody.sons[s]
|
let tParam = tbody.sons[s]
|
||||||
if tParam.sym.name == i:
|
if tParam.sym.name == i:
|
||||||
let rawTyp = ty.sons[s + 1]
|
let rawTyp = ty.sons[s + 1]
|
||||||
if rawTyp.kind == tyExpr:
|
if rawTyp.kind == tyStatic:
|
||||||
return rawTyp.n
|
return rawTyp.n
|
||||||
else:
|
else:
|
||||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||||
|
|
@ -1882,7 +1883,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkBind:
|
of nkBind:
|
||||||
Message(n.info, warnDeprecated, "bind")
|
Message(n.info, warnDeprecated, "bind")
|
||||||
result = semExpr(c, n.sons[0], flags)
|
result = semExpr(c, n.sons[0], flags)
|
||||||
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
|
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy, nkStaticTy:
|
||||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||||
result.typ = makeTypeDesc(c, typ)
|
result.typ = makeTypeDesc(c, typ)
|
||||||
#result = symNodeFromType(c, typ, n.info)
|
#result = symNodeFromType(c, typ, n.info)
|
||||||
|
|
|
||||||
|
|
@ -587,7 +587,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of skType:
|
of skType:
|
||||||
result = newSymNodeTypeDesc(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
if s.typ.kind == tyExpr:
|
if s.typ.kind == tyStatic:
|
||||||
result = s.typ.n
|
result = s.typ.n
|
||||||
result.typ = s.typ.sons[0]
|
result.typ = s.typ.sons[0]
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
||||||
if a.kind != nkSym:
|
if a.kind != nkSym:
|
||||||
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
||||||
var q = a.sym
|
var q = a.sym
|
||||||
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyExpr}+tyTypeClasses:
|
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
|
||||||
continue
|
continue
|
||||||
var s = newSym(skType, q.name, getCurrOwner(), q.info)
|
var s = newSym(skType, q.name, getCurrOwner(), q.info)
|
||||||
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
||||||
|
|
@ -145,11 +145,11 @@ proc lateInstantiateGeneric(c: PContext, invocation: PType, info: TLineInfo): PT
|
||||||
pushInfoContext(info)
|
pushInfoContext(info)
|
||||||
for i in 0 .. <s.typ.n.sons.len:
|
for i in 0 .. <s.typ.n.sons.len:
|
||||||
let genericParam = s.typ.n[i].sym
|
let genericParam = s.typ.n[i].sym
|
||||||
let symKind = if genericParam.typ.kind == tyExpr: skConst
|
let symKind = if genericParam.typ.kind == tyStatic: skConst
|
||||||
else: skType
|
else: skType
|
||||||
|
|
||||||
var boundSym = newSym(symKind, s.typ.n[i].sym.name, s, info)
|
var boundSym = newSym(symKind, s.typ.n[i].sym.name, s, info)
|
||||||
boundSym.typ = invocation.sons[i+1].skipTypes({tyExpr})
|
boundSym.typ = invocation.sons[i+1].skipTypes({tyStatic})
|
||||||
boundSym.ast = invocation.sons[i+1].n
|
boundSym.ast = invocation.sons[i+1].n
|
||||||
addDecl(c, boundSym)
|
addDecl(c, boundSym)
|
||||||
# XXX: copyTree would have been unnecessary here if semTypeNode
|
# XXX: copyTree would have been unnecessary here if semTypeNode
|
||||||
|
|
@ -200,7 +200,7 @@ proc fixupProcType(c: PContext, genericType: PType,
|
||||||
result = inst.concreteTypes[genericType.sym.position]
|
result = inst.concreteTypes[genericType.sym.position]
|
||||||
if tfUnresolved in genericType.flags:
|
if tfUnresolved in genericType.flags:
|
||||||
result = result.sons[0]
|
result = result.sons[0]
|
||||||
of tyExpr:
|
of tyStatic:
|
||||||
result = inst.concreteTypes[genericType.sym.position]
|
result = inst.concreteTypes[genericType.sym.position]
|
||||||
of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc,
|
of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc,
|
||||||
tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs:
|
tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs:
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ proc semLocals(c: PContext, n: PNode): PNode =
|
||||||
#if it.owner != c.p.owner: return result
|
#if it.owner != c.p.owner: return result
|
||||||
if it.kind in skLocalVars and
|
if it.kind in skLocalVars and
|
||||||
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
|
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
|
||||||
{tyVarargs, tyOpenArray, tyTypeDesc, tyExpr, tyStmt, tyEmpty}:
|
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyExpr, tyStmt, tyEmpty}:
|
||||||
|
|
||||||
var field = newSym(skField, it.name, getCurrOwner(), n.info)
|
var field = newSym(skField, it.name, getCurrOwner(), n.info)
|
||||||
field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
|
field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
let e = semExprWithType(c, n.sons[1], {efDetermineType})
|
let e = semExprWithType(c, n.sons[1], {efDetermineType})
|
||||||
if e.kind in {nkIntLit..nkUInt64Lit}:
|
if e.kind in {nkIntLit..nkUInt64Lit}:
|
||||||
indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
|
indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
|
||||||
elif e.kind == nkSym and e.typ.kind == tyExpr:
|
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
||||||
if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
|
if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
|
||||||
InternalAssert c.InGenericContext > 0
|
InternalAssert c.InGenericContext > 0
|
||||||
if not isOrdinalType(e.typ.lastSon):
|
if not isOrdinalType(e.typ.lastSon):
|
||||||
|
|
@ -206,7 +206,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
indx = e.typ.skipTypes({tyTypeDesc})
|
indx = e.typ.skipTypes({tyTypeDesc})
|
||||||
addSonSkipIntLit(result, indx)
|
addSonSkipIntLit(result, indx)
|
||||||
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
||||||
if indx.kind notin {tyGenericParam, tyExpr}:
|
if indx.kind notin {tyGenericParam, tyStatic}:
|
||||||
if not isOrdinalType(indx):
|
if not isOrdinalType(indx):
|
||||||
LocalError(n.sons[1].info, errOrdinalTypeExpected)
|
LocalError(n.sons[1].info, errOrdinalTypeExpected)
|
||||||
elif enumHasHoles(indx):
|
elif enumHasHoles(indx):
|
||||||
|
|
@ -579,7 +579,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
incl(result.flags, tfFinal)
|
incl(result.flags, tfFinal)
|
||||||
|
|
||||||
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||||
if kind == skMacro and param.typ.kind != tyTypeDesc:
|
if kind == skMacro and param.typ.kind notin {tyTypeDesc, tyStatic}:
|
||||||
# within a macro, every param has the type PNimrodNode!
|
# within a macro, every param has the type PNimrodNode!
|
||||||
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
||||||
let nn = getSysSym"PNimrodNode"
|
let nn = getSysSym"PNimrodNode"
|
||||||
|
|
@ -629,15 +629,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
addImplicitGenericImpl(e, paramTypId)
|
addImplicitGenericImpl(e, paramTypId)
|
||||||
|
|
||||||
case paramType.kind:
|
case paramType.kind:
|
||||||
of tyExpr:
|
of tyAnything:
|
||||||
if paramType.sonsLen == 0:
|
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||||
# proc(a, b: expr)
|
of tyStatic:
|
||||||
# no constraints, treat like generic param
|
# proc(a: expr{string}, b: expr{nkLambda})
|
||||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
# overload on compile time values and AST trees
|
||||||
else:
|
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, paramType.sons))
|
||||||
# proc(a: expr{string}, b: expr{nkLambda})
|
|
||||||
# overload on compile time values and AST trees
|
|
||||||
result = addImplicitGeneric(c.newTypeWithSons(tyExpr, paramType.sons))
|
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if tfUnresolved notin paramType.flags:
|
if tfUnresolved notin paramType.flags:
|
||||||
# naked typedescs are not bindOnce types
|
# naked typedescs are not bindOnce types
|
||||||
|
|
@ -743,7 +740,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
if not containsGenericType(typ):
|
if not containsGenericType(typ):
|
||||||
def = fitNode(c, typ, def)
|
def = fitNode(c, typ, def)
|
||||||
if not (hasType or hasDefault):
|
if not (hasType or hasDefault):
|
||||||
typ = newTypeS(tyExpr, c)
|
let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything
|
||||||
|
typ = newTypeS(tdef, c)
|
||||||
|
|
||||||
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
||||||
for j in countup(0, length-3):
|
for j in countup(0, length-3):
|
||||||
|
|
@ -1000,6 +998,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
|
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
|
||||||
of nkVarTy: result = semVarType(c, n, prev)
|
of nkVarTy: result = semVarType(c, n, prev)
|
||||||
of nkDistinctTy: result = semDistinct(c, n, prev)
|
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||||
|
of nkStaticTy:
|
||||||
|
result = newOrPrevType(tyStatic, prev, c)
|
||||||
|
var base = semTypeNode(c, n.sons[0], nil)
|
||||||
|
result.rawAddSon(base)
|
||||||
of nkProcTy, nkIteratorTy:
|
of nkProcTy, nkIteratorTy:
|
||||||
if n.sonsLen == 0:
|
if n.sonsLen == 0:
|
||||||
result = newConstraint(c, tyProc)
|
result = newConstraint(c, tyProc)
|
||||||
|
|
@ -1105,7 +1107,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
|
|
||||||
if constraint.kind != nkEmpty:
|
if constraint.kind != nkEmpty:
|
||||||
typ = semTypeNode(c, constraint, nil)
|
typ = semTypeNode(c, constraint, nil)
|
||||||
if typ.kind != tyExpr or typ.len == 0:
|
if typ.kind != tyStatic or typ.len == 0:
|
||||||
if typ.kind == tyTypeDesc:
|
if typ.kind == tyTypeDesc:
|
||||||
if typ.len == 0:
|
if typ.len == 0:
|
||||||
typ = newTypeS(tyTypeDesc, c)
|
typ = newTypeS(tyTypeDesc, c)
|
||||||
|
|
@ -1116,7 +1118,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
def = semConstExpr(c, def)
|
def = semConstExpr(c, def)
|
||||||
if typ == nil:
|
if typ == nil:
|
||||||
if def.typ.kind != tyTypeDesc:
|
if def.typ.kind != tyTypeDesc:
|
||||||
typ = newTypeWithSons(c, tyExpr, @[def.typ])
|
typ = newTypeWithSons(c, tyStatic, @[def.typ])
|
||||||
else:
|
else:
|
||||||
if not containsGenericType(def.typ):
|
if not containsGenericType(def.typ):
|
||||||
def = fitNode(c, typ, def)
|
def = fitNode(c, typ, def)
|
||||||
|
|
@ -1132,7 +1134,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
# of the parameter will be stored in the
|
# of the parameter will be stored in the
|
||||||
# attached symbol.
|
# attached symbol.
|
||||||
var s = case finalType.kind
|
var s = case finalType.kind
|
||||||
of tyExpr:
|
of tyStatic:
|
||||||
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
||||||
else:
|
else:
|
||||||
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = lookupTypeVar(cl, t)
|
result = lookupTypeVar(cl, t)
|
||||||
if result.kind == tyGenericInvokation:
|
if result.kind == tyGenericInvokation:
|
||||||
result = handleGenericInvokation(cl, result)
|
result = handleGenericInvokation(cl, result)
|
||||||
of tyExpr:
|
of tyStatic:
|
||||||
if t.sym != nil and t.sym.kind == skGenericParam:
|
if t.sym != nil and t.sym.kind == skGenericParam:
|
||||||
result = lookupTypeVar(cl, t)
|
result = lookupTypeVar(cl, t)
|
||||||
of tyGenericInvokation:
|
of tyGenericInvokation:
|
||||||
|
|
@ -215,7 +215,7 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
|
||||||
else:
|
else:
|
||||||
if t.kind == tyArray:
|
if t.kind == tyArray:
|
||||||
let idxt = t.sons[0]
|
let idxt = t.sons[0]
|
||||||
if idxt.kind == tyExpr and
|
if idxt.kind == tyStatic and
|
||||||
idxt.sym != nil and idxt.sym.kind == skGenericParam:
|
idxt.sym != nil and idxt.sym.kind == skGenericParam:
|
||||||
let value = lookupTypeVar(cl, idxt).n
|
let value = lookupTypeVar(cl, idxt).n
|
||||||
t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info)
|
t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info)
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ proc sumGeneric(t: PType): int =
|
||||||
result = ord(t.kind == tyGenericInvokation)
|
result = ord(t.kind == tyGenericInvokation)
|
||||||
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||||
break
|
break
|
||||||
of tyGenericParam, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: break
|
of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc, tyTypeClass: break
|
||||||
else: return 0
|
else: return 0
|
||||||
|
|
||||||
proc complexDisambiguation(a, b: PType): int =
|
proc complexDisambiguation(a, b: PType): int =
|
||||||
|
|
@ -894,40 +894,39 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||||
arg = argSemantized
|
arg = argSemantized
|
||||||
|
|
||||||
let
|
let
|
||||||
a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
|
a0 = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
|
||||||
else: argType
|
else: argType
|
||||||
fMaybeExpr = f.skipTypes({tyDistinct})
|
a = if a0 != nil: a0.skipTypes({tyStatic}) else: a0
|
||||||
|
fMaybeStatic = f.skipTypes({tyDistinct})
|
||||||
|
|
||||||
case fMaybeExpr.kind
|
case fMaybeStatic.kind
|
||||||
of tyExpr:
|
of tyStatic:
|
||||||
if fMaybeExpr.sonsLen == 0:
|
if a.kind == tyStatic:
|
||||||
r = isGeneric
|
InternalAssert a.len > 0
|
||||||
|
r = typeRel(m, f.lastSon, a.lastSon)
|
||||||
else:
|
else:
|
||||||
if a.kind == tyExpr:
|
let match = matchTypeClass(m.bindings, fMaybeStatic, a)
|
||||||
InternalAssert a.len > 0
|
if not match: r = isNone
|
||||||
r = typeRel(m, f.lastSon, a.lastSon)
|
|
||||||
else:
|
else:
|
||||||
let match = matchTypeClass(m.bindings, fMaybeExpr, a)
|
# XXX: Ideally, this should happen much earlier somewhere near
|
||||||
if not match: r = isNone
|
# semOpAux, but to do that, we need to be able to query the
|
||||||
else:
|
# overload set to determine whether compile-time value is expected
|
||||||
# XXX: Ideally, this should happen much earlier somewhere near
|
# for the param before entering the full-blown sigmatch algorithm.
|
||||||
# semOpAux, but to do that, we need to be able to query the
|
# This is related to the immediate pragma since querying the
|
||||||
# overload set to determine whether compile-time value is expected
|
# overload set could help there too.
|
||||||
# for the param before entering the full-blown sigmatch algorithm.
|
var evaluated = c.semConstExpr(c, arg)
|
||||||
# This is related to the immediate pragma since querying the
|
if evaluated != nil:
|
||||||
# overload set could help there too.
|
r = isGeneric
|
||||||
var evaluated = c.semConstExpr(c, arg)
|
arg.typ = newTypeS(tyStatic, c)
|
||||||
if evaluated != nil:
|
arg.typ.sons = @[evaluated.typ]
|
||||||
r = isGeneric
|
arg.typ.n = evaluated
|
||||||
arg.typ = newTypeS(tyExpr, c)
|
|
||||||
arg.typ.sons = @[evaluated.typ]
|
|
||||||
arg.typ.n = evaluated
|
|
||||||
|
|
||||||
if r == isGeneric:
|
if r == isGeneric:
|
||||||
put(m.bindings, f, arg.typ)
|
put(m.bindings, f, arg.typ)
|
||||||
|
|
||||||
of tyTypeClass, tyParametricTypeClass:
|
of tyTypeClass, tyParametricTypeClass:
|
||||||
if fMaybeExpr.n != nil:
|
if fMaybeStatic.n != nil:
|
||||||
let match = matchUserTypeClass(c, m, arg, fMaybeExpr, a)
|
let match = matchUserTypeClass(c, m, arg, fMaybeStatic, a)
|
||||||
if match != nil:
|
if match != nil:
|
||||||
r = isGeneric
|
r = isGeneric
|
||||||
arg = match
|
arg = match
|
||||||
|
|
@ -935,6 +934,9 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||||
r = isNone
|
r = isNone
|
||||||
else:
|
else:
|
||||||
r = typeRel(m, f, a)
|
r = typeRel(m, f, a)
|
||||||
|
of tyExpr:
|
||||||
|
r = isGeneric
|
||||||
|
put(m.bindings, f, arg.typ)
|
||||||
else:
|
else:
|
||||||
r = typeRel(m, f, a)
|
r = typeRel(m, f, a)
|
||||||
|
|
||||||
|
|
@ -961,6 +963,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||||
result = argOrig[bodyPos]
|
result = argOrig[bodyPos]
|
||||||
elif f.kind == tyTypeDesc:
|
elif f.kind == tyTypeDesc:
|
||||||
result = arg
|
result = arg
|
||||||
|
elif f.kind == tyStatic:
|
||||||
|
result = arg.typ.n
|
||||||
else:
|
else:
|
||||||
result = argOrig
|
result = argOrig
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ const
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
"bignum", "const ",
|
"bignum", "const ",
|
||||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
||||||
"ParametricTypeClass", "and", "or", "not", "any"]
|
"ParametricTypeClass", "and", "or", "not", "any", "static"]
|
||||||
|
|
||||||
proc consToStr(t: PType): string =
|
proc consToStr(t: PType): string =
|
||||||
if t.len > 0: result = t.typeToString
|
if t.len > 0: result = t.typeToString
|
||||||
|
|
@ -445,6 +445,9 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if t.len == 0: result = "typedesc"
|
if t.len == 0: result = "typedesc"
|
||||||
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
||||||
|
of tyStatic:
|
||||||
|
InternalAssert t.len > 0
|
||||||
|
result = "static[" & constraintsToStr(t) & "]"
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
if t.n != nil: return t.sym.owner.name.s
|
if t.n != nil: return t.sym.owner.name.s
|
||||||
case t.len
|
case t.len
|
||||||
|
|
@ -828,9 +831,9 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
if a.kind != b.kind: return false
|
if a.kind != b.kind: return false
|
||||||
case a.Kind
|
case a.Kind
|
||||||
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
|
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
|
||||||
tyInt..tyBigNum, tyStmt:
|
tyInt..tyBigNum, tyStmt, tyExpr:
|
||||||
result = sameFlags(a, b)
|
result = sameFlags(a, b)
|
||||||
of tyExpr:
|
of tyStatic:
|
||||||
result = ExprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
|
result = ExprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
IfFastObjectTypeCheckFailed(a, b):
|
IfFastObjectTypeCheckFailed(a, b):
|
||||||
|
|
@ -1038,7 +1041,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
|
||||||
if not result: break
|
if not result: break
|
||||||
if result and t.sons[0] != nil:
|
if result and t.sons[0] != nil:
|
||||||
result = typeAllowedAux(marker, t.sons[0], skResult, flags)
|
result = typeAllowedAux(marker, t.sons[0], skResult, flags)
|
||||||
of tyExpr, tyStmt, tyTypeDesc:
|
of tyExpr, tyStmt, tyTypeDesc, tyStatic:
|
||||||
result = true
|
result = true
|
||||||
# XXX er ... no? these should not be allowed!
|
# XXX er ... no? these should not be allowed!
|
||||||
of tyEmpty:
|
of tyEmpty:
|
||||||
|
|
@ -1314,7 +1317,7 @@ proc compatibleEffects*(formal, actual: PType): bool =
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc isCompileTimeOnly*(t: PType): bool {.inline.} =
|
proc isCompileTimeOnly*(t: PType): bool {.inline.} =
|
||||||
result = t.kind in {tyTypedesc, tyExpr}
|
result = t.kind in {tyTypedesc, tyStatic}
|
||||||
|
|
||||||
proc containsCompileTimeOnly*(t: PType): bool =
|
proc containsCompileTimeOnly*(t: PType): bool =
|
||||||
if isCompileTimeOnly(t): return true
|
if isCompileTimeOnly(t): return true
|
||||||
|
|
|
||||||
|
|
@ -777,7 +777,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
|
|
||||||
const
|
const
|
||||||
atomicTypes = {tyBool, tyChar,
|
atomicTypes = {tyBool, tyChar,
|
||||||
tyExpr, tyStmt, tyTypeDesc,
|
tyExpr, tyStmt, tyTypeDesc, tyStatic,
|
||||||
tyEnum,
|
tyEnum,
|
||||||
tyOrdinal,
|
tyOrdinal,
|
||||||
tyRange,
|
tyRange,
|
||||||
|
|
@ -938,7 +938,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
result = newNodeIt(nkFloatLit, info, t)
|
result = newNodeIt(nkFloatLit, info, t)
|
||||||
of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
|
of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyProc, tyRef:
|
tyStmt, tyTypeDesc, tyStatic, tyProc, tyRef:
|
||||||
result = newNodeIT(nkNilLit, info, t)
|
result = newNodeIT(nkNilLit, info, t)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ type
|
||||||
nnkBindStmt, nnkMixinStmt, nnkUsingStmt,
|
nnkBindStmt, nnkMixinStmt, nnkUsingStmt,
|
||||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
||||||
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
|
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
|
||||||
nnkTupleTy, nnkTypeClassTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
nnkTupleTy, nnkTypeClassTy, nnkStaticTy,
|
||||||
|
nnkRecList, nnkRecCase, nnkRecWhen,
|
||||||
nnkRefTy, nnkPtrTy, nnkVarTy,
|
nnkRefTy, nnkPtrTy, nnkVarTy,
|
||||||
nnkConstTy, nnkMutableTy,
|
nnkConstTy, nnkMutableTy,
|
||||||
nnkDistinctTy,
|
nnkDistinctTy,
|
||||||
|
|
@ -285,14 +286,15 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
|
||||||
## if not `ex`:
|
## if not `ex`:
|
||||||
## echo `info` & ": Check failed: " & `expString`
|
## echo `info` & ": Check failed: " & `expString`
|
||||||
|
|
||||||
template emit*(e: expr[string]): stmt =
|
when not defined(booting):
|
||||||
## accepts a single string argument and treats it as nimrod code
|
template emit*(e: static[string]): stmt =
|
||||||
## that should be inserted verbatim in the program
|
## accepts a single string argument and treats it as nimrod code
|
||||||
## Example:
|
## that should be inserted verbatim in the program
|
||||||
##
|
## Example:
|
||||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
##
|
||||||
##
|
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||||
eval: result = e.parseStmt
|
##
|
||||||
|
eval: result = e.parseStmt
|
||||||
|
|
||||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||||
## checks that `n` is of kind `k`. If this is not the case,
|
## checks that `n` is of kind `k`. If this is not the case,
|
||||||
|
|
|
||||||
|
|
@ -2641,7 +2641,7 @@ when hostOS != "standalone":
|
||||||
x[j+i] = item[j]
|
x[j+i] = item[j]
|
||||||
inc(j)
|
inc(j)
|
||||||
|
|
||||||
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
|
proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
|
||||||
## Special compile-time procedure that checks whether `x` can be compiled
|
## Special compile-time procedure that checks whether `x` can be compiled
|
||||||
## without any semantic error.
|
## without any semantic error.
|
||||||
## This can be used to check whether a type supports some operation:
|
## This can be used to check whether a type supports some operation:
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ discard """
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc foo(s: expr[string]): string =
|
proc foo(s: static[string]): string =
|
||||||
static: echo s
|
static: echo s
|
||||||
|
|
||||||
const R = s.toUpper
|
const R = s.toUpper
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@ discard """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
TFoo[T; Val: expr[string]] = object
|
TFoo[T; Val: static[string]] = object
|
||||||
data: array[4, T]
|
data: array[4, T]
|
||||||
|
|
||||||
TBar[T; I: expr[int]] = object
|
TBar[T; I: static[int]] = object
|
||||||
data: array[I, T]
|
data: array[I, T]
|
||||||
|
|
||||||
TA1[T; I: expr[int]] = array[I, T]
|
#TA1[T; I: static[int]] = array[I, T]
|
||||||
TA2[T; I: expr[int]] = array[0..I, T]
|
#TA2[T; I: static[int]] = array[0..I, T]
|
||||||
TA3[T; I: expr[int]] = array[I-1, T]
|
TA3[T; I: static[int]] = array[I-1, T]
|
||||||
|
|
||||||
proc takeFoo(x: TFoo) =
|
proc takeFoo(x: TFoo) =
|
||||||
echo "abracadabra"
|
echo "abracadabra"
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -38,7 +38,6 @@ version 0.9.x
|
||||||
- macros as type pragmas
|
- macros as type pragmas
|
||||||
- implicit deref for parameter matching
|
- implicit deref for parameter matching
|
||||||
- lazy overloading resolution:
|
- lazy overloading resolution:
|
||||||
* get rid of ``expr[typ]``, use perhaps ``static[typ]`` instead
|
|
||||||
* special case ``tyStmt``
|
* special case ``tyStmt``
|
||||||
- FFI:
|
- FFI:
|
||||||
* test libffi on windows
|
* test libffi on windows
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue