Merge branch 'devel' of https://github.com/Araq/Nim into devel
This commit is contained in:
commit
c461f5a8c6
57 changed files with 652 additions and 436 deletions
|
|
@ -1517,8 +1517,8 @@ proc getStr*(a: PNode): string =
|
|||
proc getStrOrChar*(a: PNode): string =
|
||||
case a.kind
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||
of nkCharLit: result = $chr(int(a.intVal))
|
||||
else:
|
||||
of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
|
||||
else:
|
||||
internalError(a.info, "getStrOrChar")
|
||||
result = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Files: "start.bat"
|
|||
BinPath: r"bin;dist\mingw\bin;dist"
|
||||
|
||||
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html"
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
|
||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
||||
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
|
||||
; for now only NSIS supports optional downloads
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
# Special configuration file for the Nim project
|
||||
|
||||
# gc:markAndSweep
|
||||
|
||||
hint[XDeclaredButNotUsed]:off
|
||||
path:"llvm"
|
||||
path:"$projectPath/.."
|
||||
|
|
|
|||
|
|
@ -67,12 +67,25 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
|||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
else:
|
||||
let x = result.skipConv
|
||||
if x.kind == nkPar and formal.kind != tyExpr:
|
||||
changeType(x, formal, check=true)
|
||||
|
||||
proc inferWithMetatype(c: PContext, formal: PType,
|
||||
arg: PNode, coerceDistincts = false): PNode
|
||||
|
||||
var commonTypeBegin = PType(kind: tyExpr)
|
||||
|
||||
proc isEmptyContainer(t: PType): bool =
|
||||
case t.kind
|
||||
of tyExpr, tyNil: result = true
|
||||
of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
|
||||
of tySet, tySequence, tyOpenArray, tyVarargs:
|
||||
result = t.sons[0].kind == tyEmpty
|
||||
of tyGenericInst: result = isEmptyContainer(t.lastSon)
|
||||
else: result = false
|
||||
|
||||
proc commonType*(x, y: PType): PType =
|
||||
# new type relation that is used for array constructors,
|
||||
# if expressions, etc.:
|
||||
|
|
@ -96,6 +109,13 @@ proc commonType*(x, y: PType): PType =
|
|||
# check for seq[empty] vs. seq[int]
|
||||
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
||||
if a.sons[idx].kind == tyEmpty: return y
|
||||
elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
|
||||
var nt: PType
|
||||
for i in 0.. <a.len:
|
||||
if isEmptyContainer(a.sons[i]) and not isEmptyContainer(b.sons[i]):
|
||||
if nt.isNil: nt = copyType(a, a.owner, false)
|
||||
nt.sons[i] = b.sons[i]
|
||||
if not nt.isNil: result = nt
|
||||
#elif b.sons[idx].kind == tyEmpty: return x
|
||||
elif a.kind == tyRange and b.kind == tyRange:
|
||||
# consider: (range[0..3], range[0..4]) here. We should make that
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
|
|||
# gnrc. params, then it won't be necessary to open a new scope here
|
||||
openScope(c)
|
||||
var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
|
||||
t, ":anon", info)
|
||||
t, ":anon", info)
|
||||
closeScope(c)
|
||||
if lifted != nil: t = lifted
|
||||
|
||||
|
|
@ -429,7 +429,8 @@ proc changeType(n: PNode, newType: PType, check: bool) =
|
|||
for i in countup(0, sonsLen(n) - 1):
|
||||
changeType(n.sons[i], elemType(newType), check)
|
||||
of nkPar:
|
||||
if newType.kind != tyTuple:
|
||||
let tup = newType.skipTypes({tyGenericInst})
|
||||
if tup.kind != tyTuple:
|
||||
internalError(n.info, "changeType: no tuple type for constructor")
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
|
|
@ -437,7 +438,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
|
|||
if m.kind == nkExprColonExpr:
|
||||
m = m.sons[1]
|
||||
n.sons[i] = m
|
||||
changeType(m, newType.sons[i], check)
|
||||
changeType(m, tup.sons[i], check)
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if check:
|
||||
let value = n.intVal
|
||||
|
|
@ -925,18 +926,20 @@ const
|
|||
proc readTypeParameter(c: PContext, typ: PType,
|
||||
paramName: PIdent, info: TLineInfo): PNode =
|
||||
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
|
||||
else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1])
|
||||
|
||||
else: (internalAssert(typ.kind == tyCompositeTypeClass);
|
||||
typ.sons[1].skipGenericAlias)
|
||||
#debug ty
|
||||
let tbody = ty.sons[0]
|
||||
for s in countup(0, tbody.len-2):
|
||||
let tParam = tbody.sons[s]
|
||||
if tParam.sym.name == paramName:
|
||||
if tParam.sym.name.id == paramName.id:
|
||||
let rawTyp = ty.sons[s + 1]
|
||||
if rawTyp.kind == tyStatic:
|
||||
return rawTyp.n
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
||||
#echo "came here: returned nil"
|
||||
|
||||
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
## returns nil if it's not a built-in field access
|
||||
|
|
@ -963,6 +966,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
var ty = n.sons[0].typ
|
||||
var f: PSym = nil
|
||||
result = nil
|
||||
|
||||
if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
|
||||
if ty.kind == tyTypeDesc: ty = ty.base
|
||||
ty = ty.skipTypes(tyDotOpTransparent)
|
||||
|
|
@ -971,7 +975,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
# look up if the identifier belongs to the enum:
|
||||
while ty != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
if f != nil: break
|
||||
if f != nil: break
|
||||
ty = ty.sons[0] # enum inheritance
|
||||
if f != nil:
|
||||
result = newSymNode(f)
|
||||
|
|
@ -983,7 +987,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
of tyTypeParamsHolders:
|
||||
return readTypeParameter(c, ty, i, n.info)
|
||||
of tyObject, tyTuple:
|
||||
if ty.n.kind == nkRecList:
|
||||
if ty.n != nil and ty.n.kind == nkRecList:
|
||||
for field in ty.n:
|
||||
if field.sym.name == i:
|
||||
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
|
||||
|
|
|
|||
|
|
@ -60,13 +60,20 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
|||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skGenericParam:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
if s.typ != nil and s.typ.kind == tyStatic:
|
||||
if s.typ.n != nil:
|
||||
result = s.typ.n
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
styleCheckUse(n.info, s)
|
||||
of skParam:
|
||||
result = n
|
||||
styleCheckUse(n.info, s)
|
||||
of skType:
|
||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||
if (s.typ != nil) and
|
||||
(s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
else:
|
||||
result = n
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
|||
var q = a.sym
|
||||
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
|
||||
continue
|
||||
var s = newSym(skType, q.name, getCurrOwner(), q.info)
|
||||
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
||||
var s = newSym(symKind, q.name, getCurrOwner(), q.info)
|
||||
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
||||
var t = PType(idTableGet(pt, q.typ))
|
||||
if t == nil:
|
||||
|
|
@ -40,6 +41,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
|||
t = generateTypeInstance(c, pt, a, t)
|
||||
#t = ReplaceTypeVarsT(cl, t)
|
||||
s.typ = t
|
||||
if t.kind == tyStatic: s.ast = t.n
|
||||
addDecl(c, s)
|
||||
entry.concreteTypes[i] = t
|
||||
|
||||
|
|
|
|||
|
|
@ -653,7 +653,8 @@ proc checkForMetaFields(n: PNode) =
|
|||
template checkMeta(t) =
|
||||
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
|
||||
localError(n.info, errTIsNotAConcreteType, t.typeToString)
|
||||
|
||||
|
||||
if n.isNil: return
|
||||
case n.kind
|
||||
of nkRecList, nkRecCase:
|
||||
for s in n: checkForMetaFields(s)
|
||||
|
|
|
|||
|
|
@ -214,44 +214,48 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
|
|||
localError(n.info, errXExpectsOneTypeParam, "range")
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var indx, base: PType
|
||||
result = newOrPrevType(tyArray, prev, c)
|
||||
if sonsLen(n) == 3:
|
||||
# 3 = length(array indx base)
|
||||
if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
|
||||
proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||
if isRange(n): result = semRangeAux(c, n, nil)
|
||||
else:
|
||||
let e = semExprWithType(c, n, {efDetermineType})
|
||||
if e.typ.kind == tyFromExpr:
|
||||
result = makeRangeWithStaticExpr(c, e.typ.n)
|
||||
elif e.kind in {nkIntLit..nkUInt64Lit}:
|
||||
result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
|
||||
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
||||
if e.sym.ast != nil:
|
||||
return semArrayIndex(c, e.sym.ast)
|
||||
internalAssert c.inGenericContext > 0
|
||||
if not isOrdinalType(e.typ.lastSon):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
result = makeRangeWithStaticExpr(c, e)
|
||||
result.flags.incl tfUnresolved
|
||||
elif e.kind in nkCallKinds and hasGenericArguments(e):
|
||||
if not isOrdinalType(e.typ):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
# This is an int returning call, depending on an
|
||||
# yet unknown generic param (see tgenericshardcases).
|
||||
# We are going to construct a range type that will be
|
||||
# properly filled-out in semtypinst (see how tyStaticExpr
|
||||
# is handled there).
|
||||
result = makeRangeWithStaticExpr(c, e)
|
||||
elif e.kind == nkIdent:
|
||||
result = e.typ.skipTypes({tyTypeDesc})
|
||||
else:
|
||||
let e = semExprWithType(c, n.sons[1], {efDetermineType})
|
||||
if e.typ.kind == tyFromExpr:
|
||||
indx = makeRangeWithStaticExpr(c, e.typ.n)
|
||||
elif e.kind in {nkIntLit..nkUInt64Lit}:
|
||||
indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
|
||||
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
||||
if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
|
||||
internalAssert c.inGenericContext > 0
|
||||
if not isOrdinalType(e.typ.lastSon):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
indx = makeRangeWithStaticExpr(c, e)
|
||||
indx.flags.incl tfUnresolved
|
||||
elif e.kind in nkCallKinds and hasGenericArguments(e):
|
||||
if not isOrdinalType(e.typ):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
# This is an int returning call, depending on an
|
||||
# yet unknown generic param (see tgenericshardcases).
|
||||
# We are going to construct a range type that will be
|
||||
# properly filled-out in semtypinst (see how tyStaticExpr
|
||||
# is handled there).
|
||||
indx = makeRangeWithStaticExpr(c, e)
|
||||
elif e.kind == nkIdent:
|
||||
indx = e.typ.skipTypes({tyTypeDesc})
|
||||
let x = semConstExpr(c, e)
|
||||
if x.kind in {nkIntLit..nkUInt64Lit}:
|
||||
result = makeRangeType(c, 0, x.intVal-1, n.info,
|
||||
x.typ.skipTypes({tyTypeDesc}))
|
||||
else:
|
||||
let x = semConstExpr(c, e)
|
||||
if x.kind in {nkIntLit..nkUInt64Lit}:
|
||||
indx = makeRangeType(c, 0, x.intVal-1, n.info,
|
||||
x.typ.skipTypes({tyTypeDesc}))
|
||||
else:
|
||||
indx = x.typ.skipTypes({tyTypeDesc})
|
||||
#localError(n[1].info, errConstExprExpected)
|
||||
result = x.typ.skipTypes({tyTypeDesc})
|
||||
#localError(n[1].info, errConstExprExpected)
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(tyArray, prev, c)
|
||||
if sonsLen(n) == 3:
|
||||
# 3 = length(array indx base)
|
||||
var indx = semArrayIndex(c, n[1])
|
||||
addSonSkipIntLit(result, indx)
|
||||
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
||||
if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
|
||||
|
|
|
|||
|
|
@ -517,6 +517,16 @@ proc maybeSkipDistinct(t: PType, callee: PSym): PType =
|
|||
else:
|
||||
result = t
|
||||
|
||||
proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
|
||||
# Consider this example:
|
||||
# type Value[N: static[int]] = object
|
||||
# proc foo[N](a: Value[N], r: range[0..(N-1)])
|
||||
# Here, N-1 will be initially nkStaticExpr that can be evaluated only after
|
||||
# N is bound to a concrete value during the matching of the first param.
|
||||
# This proc is used to evaluate such static expressions.
|
||||
let instantiated = replaceTypesInBody(c.c, c.bindings, n)
|
||||
result = c.c.semExpr(c.c, instantiated)
|
||||
|
||||
proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
# typeRel can be used to establish various relationships between types:
|
||||
#
|
||||
|
|
@ -620,6 +630,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
# bugfix: accept integer conversions here
|
||||
#if result < isGeneric: result = isNone
|
||||
if result notin {isNone, isGeneric}:
|
||||
# resolve any late-bound static expressions
|
||||
# that may appear in the range:
|
||||
for i in 0..1:
|
||||
if f.n[i].kind == nkStaticExpr:
|
||||
f.n.sons[i] = tryResolvingStaticExpr(c, f.n[i])
|
||||
result = typeRangeRel(f, a)
|
||||
else:
|
||||
if skipTypes(f, {tyRange}).kind == a.kind:
|
||||
|
|
@ -964,6 +979,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
of tyStatic:
|
||||
if aOrig.kind == tyStatic:
|
||||
result = typeRel(c, f.lastSon, a)
|
||||
if result != isNone and f.n != nil:
|
||||
if not exprStructuralEquivalent(f.n, a.n):
|
||||
result = isNone
|
||||
if result != isNone: put(c.bindings, f, aOrig)
|
||||
else:
|
||||
result = isNone
|
||||
|
|
@ -1006,15 +1024,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
|
||||
of tyFromExpr:
|
||||
# fix the expression, so it contains the already instantiated types
|
||||
let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
|
||||
let reevaluted = c.c.semExpr(c.c, instantiated)
|
||||
case reevaluted.typ.kind
|
||||
let reevaluated = tryResolvingStaticExpr(c, f.n)
|
||||
case reevaluated.typ.kind
|
||||
of tyTypeDesc:
|
||||
result = typeRel(c, a, reevaluted.typ.base)
|
||||
result = typeRel(c, a, reevaluated.typ.base)
|
||||
of tyStatic:
|
||||
result = typeRel(c, a, reevaluted.typ.base)
|
||||
if result != isNone and reevaluted.typ.n != nil:
|
||||
if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n):
|
||||
result = typeRel(c, a, reevaluated.typ.base)
|
||||
if result != isNone and reevaluated.typ.n != nil:
|
||||
if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
|
||||
result = isNone
|
||||
else:
|
||||
localError(f.n.info, errTypeExpected)
|
||||
|
|
@ -1083,6 +1100,11 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
|||
arg: PNode): PNode =
|
||||
# arg.typ can be nil in 'suggest':
|
||||
if isNil(arg.typ): return nil
|
||||
|
||||
# sem'checking for 'echo' needs to be re-entrant:
|
||||
# XXX we will revisit this issue after 0.10.2 is released
|
||||
if f == arg.typ and arg.kind == nkHiddenStdConv: return arg
|
||||
|
||||
var call = newNodeI(nkCall, arg.info)
|
||||
call.add(f.n.copyTree)
|
||||
call.add(arg.copyTree)
|
||||
|
|
|
|||
|
|
@ -74,9 +74,6 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) =
|
|||
suggestWriteln(symToStr(s, isLocal=true, sectionSuggest))
|
||||
inc outputs
|
||||
|
||||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template wholeSymTab(cond, section: expr) {.immediate.} =
|
||||
var isLocal = true
|
||||
for scope in walkScopes(c.currentScope):
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ proc lastOrd*(t: PType): BiggestInt
|
|||
proc lengthOrd*(t: PType): BiggestInt
|
||||
type
|
||||
TPreferedDesc* = enum
|
||||
preferName, preferDesc, preferExported, preferModuleInfo
|
||||
preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
|
||||
|
||||
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
||||
proc base*(t: PType): PType
|
||||
|
|
@ -411,11 +411,13 @@ const
|
|||
"UserTypeClassInst", "CompositeTypeClass",
|
||||
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
|
||||
|
||||
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
|
||||
|
||||
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
var t = typ
|
||||
result = ""
|
||||
if t == nil: return
|
||||
if prefer in {preferName, preferModuleInfo} and t.sym != nil and
|
||||
if prefer in preferToResolveSymbols and t.sym != nil and
|
||||
sfAnon notin t.sym.flags:
|
||||
if t.kind == tyInt and isIntLit(t):
|
||||
return t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||
|
|
@ -428,20 +430,26 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
|||
if not isIntLit(t) or prefer == preferExported:
|
||||
result = typeToStr[t.kind]
|
||||
else:
|
||||
result = "int literal(" & $t.n.intVal & ")"
|
||||
if prefer == preferGenericArg:
|
||||
result = $t.n.intVal
|
||||
else:
|
||||
result = "int literal(" & $t.n.intVal & ")"
|
||||
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
||||
result = typeToString(t.sons[0]) & '['
|
||||
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
|
||||
if i > 1: add(result, ", ")
|
||||
add(result, typeToString(t.sons[i]))
|
||||
add(result, typeToString(t.sons[i], preferGenericArg))
|
||||
add(result, ']')
|
||||
of tyTypeDesc:
|
||||
if t.base.kind == tyNone: result = "typedesc"
|
||||
else: result = "typedesc[" & typeToString(t.base) & "]"
|
||||
of tyStatic:
|
||||
internalAssert t.len > 0
|
||||
result = "static[" & typeToString(t.sons[0]) & "]"
|
||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||
if prefer == preferGenericArg and t.n != nil:
|
||||
result = t.n.renderTree
|
||||
else:
|
||||
result = "static[" & typeToString(t.sons[0]) & "]"
|
||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||
of tyUserTypeClass:
|
||||
internalAssert t.sym != nil and t.sym.owner != nil
|
||||
return t.sym.owner.name.s
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ type
|
|||
slotTempInt, # some temporary int
|
||||
slotTempFloat, # some temporary float
|
||||
slotTempStr, # some temporary string
|
||||
slotTempComplex # some complex temporary (s.node field is used)
|
||||
slotTempComplex, # some complex temporary (s.node field is used)
|
||||
slotTempPerm # slot is temporary but permanent (hack)
|
||||
|
||||
PProc* = ref object
|
||||
blocks*: seq[TBlock] # blocks; temp data structure
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# types that use the 'node' field; the reason is that slots are
|
||||
# re-used in a register based VM. Example:
|
||||
#
|
||||
# .. code-block:: nimrod
|
||||
# .. code-block:: nim
|
||||
# let s = a & b # no matter what, create fresh node
|
||||
# s = a & b # no matter what, keep the node
|
||||
#
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
# this copy depends on the involved types.
|
||||
|
||||
import
|
||||
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||
trees, intsets, rodread, magicsys, options, lowerings
|
||||
|
||||
from os import splitFile
|
||||
|
|
@ -58,6 +58,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
|
|||
if i in jumpTargets: result.addf("L$1:\n", i)
|
||||
let x = c.code[i]
|
||||
|
||||
result.add($i)
|
||||
let opc = opcode(x)
|
||||
if opc in {opcConv, opcCast}:
|
||||
let y = c.code[i+1]
|
||||
|
|
@ -188,7 +189,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
|
|||
|
||||
proc freeTemp(c: PCtx; r: TRegister) =
|
||||
let c = c.prc
|
||||
if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false
|
||||
if c.slots[r].kind in {slotSomeTemp..slotTempComplex}: c.slots[r].inUse = false
|
||||
|
||||
proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||
# if register pressure is high, we re-use more aggressively:
|
||||
|
|
@ -1074,8 +1075,10 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
|||
c.gABC(n, opcNodeToReg, dest, dest)
|
||||
elif c.prc.slots[tmp].kind >= slotTempUnknown:
|
||||
gABC(c, n, opcAddrNode, dest, tmp)
|
||||
# XXX this can still be wrong sometimes; hopefully it's only generated
|
||||
# in call contexts, where it is safe
|
||||
# hack ahead; in order to fix bug #1781 we mark the temporary as
|
||||
# permanent, so that it's not used for anything else:
|
||||
c.prc.slots[tmp].kind = slotTempPerm
|
||||
# XXX this is still a hack
|
||||
#message(n.info, warnUser, "suspicious opcode used")
|
||||
else:
|
||||
gABC(c, n, opcAddrReg, dest, tmp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue