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:
Zahary Karadjov 2013-12-19 01:06:38 +02:00
commit 027f30610e
22 changed files with 135 additions and 110 deletions

View file

@ -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:

View file

@ -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))

View file

@ -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,

View file

@ -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])

View file

@ -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,

View file

@ -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

View file

@ -965,6 +965,7 @@ 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:
when true:
if mode in {pmTypeDesc, pmTypeDef}: if mode in {pmTypeDesc, pmTypeDef}:
result = parseProcExpr(p, false) result = parseProcExpr(p, false)
result.kind = nkIteratorTy result.kind = nkIteratorTy
@ -973,6 +974,9 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
parMessage(p, errExprExpected, p.tok) parMessage(p, errExprExpected, p.tok)
getTok(p) # we must consume a token here to prevend endless loops! getTok(p) # we must consume a token here to prevend endless loops!
result = ast.emptyNode result = ast.emptyNode
else:
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
result.kind = nkIteratorTy
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)

View file

@ -282,8 +282,11 @@ 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))
when true:
template `~`*(r: string): PRope = r.ropef
else:
{.push stack_trace: off, line_trace: off.} {.push stack_trace: off, line_trace: off.}
proc `~`*(r: expr[string]): PRope = proc `~`*(r: static[string]): PRope =
# this is the new optimized "to rope" operator # this is the new optimized "to rope" operator
# the mnemonic is that `~` looks a bit like a rope :) # the mnemonic is that `~` looks a bit like a rope :)
var r {.global.} = r.ropef var r {.global.} = r.ropef

View file

@ -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)

View file

@ -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:

View file

@ -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:

View file

@ -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})

View file

@ -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:
# proc(a, b: expr)
# no constraints, treat like generic param
result = addImplicitGeneric(newTypeS(tyGenericParam, c)) result = addImplicitGeneric(newTypeS(tyGenericParam, c))
else: of tyStatic:
# proc(a: expr{string}, b: expr{nkLambda}) # proc(a: expr{string}, b: expr{nkLambda})
# overload on compile time values and AST trees # overload on compile time values and AST trees
result = addImplicitGeneric(c.newTypeWithSons(tyExpr, paramType.sons)) result = addImplicitGeneric(c.newTypeWithSons(tyStatic, 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)

View file

@ -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)

View file

@ -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,20 +894,18 @@ 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
else:
if a.kind == tyExpr:
InternalAssert a.len > 0 InternalAssert a.len > 0
r = typeRel(m, f.lastSon, a.lastSon) r = typeRel(m, f.lastSon, a.lastSon)
else: else:
let match = matchTypeClass(m.bindings, fMaybeExpr, a) let match = matchTypeClass(m.bindings, fMaybeStatic, a)
if not match: r = isNone if not match: r = isNone
else: else:
# XXX: Ideally, this should happen much earlier somewhere near # XXX: Ideally, this should happen much earlier somewhere near
@ -919,15 +917,16 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
var evaluated = c.semConstExpr(c, arg) var evaluated = c.semConstExpr(c, arg)
if evaluated != nil: if evaluated != nil:
r = isGeneric r = isGeneric
arg.typ = newTypeS(tyExpr, c) arg.typ = newTypeS(tyStatic, c)
arg.typ.sons = @[evaluated.typ] arg.typ.sons = @[evaluated.typ]
arg.typ.n = evaluated 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:

View file

@ -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

View file

@ -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)

View file

@ -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,7 +286,8 @@ 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):
template emit*(e: static[string]): stmt =
## accepts a single string argument and treats it as nimrod code ## accepts a single string argument and treats it as nimrod code
## that should be inserted verbatim in the program ## that should be inserted verbatim in the program
## Example: ## Example:

View file

@ -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:

View file

@ -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

View file

@ -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"

View file

@ -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