fixes #271
This commit is contained in:
parent
c98696d742
commit
a22c1f444f
9 changed files with 54 additions and 38 deletions
|
|
@ -132,7 +132,7 @@ const
|
||||||
errNumberOutOfRange: "number $1 out of valid range",
|
errNumberOutOfRange: "number $1 out of valid range",
|
||||||
errNnotAllowedInCharacter: "\\n not allowed in character literal",
|
errNnotAllowedInCharacter: "\\n not allowed in character literal",
|
||||||
errClosingBracketExpected: "closing ']' expected, but end of file reached",
|
errClosingBracketExpected: "closing ']' expected, but end of file reached",
|
||||||
errMissingFinalQuote: "missing final \'",
|
errMissingFinalQuote: "missing final \' for character literal",
|
||||||
errIdentifierExpected: "identifier expected, but found \'$1\'",
|
errIdentifierExpected: "identifier expected, but found \'$1\'",
|
||||||
errNewlineExpected: "newline expected, but found \'$1\'",
|
errNewlineExpected: "newline expected, but found \'$1\'",
|
||||||
errInvalidModuleName: "invalid module name: '$1'",
|
errInvalidModuleName: "invalid module name: '$1'",
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ proc fixImmediateParams(n: PNode): PNode
|
||||||
proc activate(c: PContext, n: PNode)
|
proc activate(c: PContext, n: PNode)
|
||||||
proc semQuoteAst(c: PContext, n: PNode): PNode
|
proc semQuoteAst(c: PContext, n: PNode): PNode
|
||||||
|
|
||||||
|
proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
|
||||||
|
|
||||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||||
if formal.kind != tyError and actual.kind != tyError:
|
if formal.kind != tyError and actual.kind != tyError:
|
||||||
LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
|
LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||||
|
|
|
||||||
|
|
@ -84,15 +84,34 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
|
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
|
||||||
args])
|
args])
|
||||||
|
|
||||||
proc instantiateGenericConverters(c: PContext, n: PNode, x: TCandidate) {.
|
|
||||||
noinline.}=
|
proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) =
|
||||||
for i in 1 .. <n.len:
|
|
||||||
var a = n.sons[i]
|
|
||||||
if a.kind == nkHiddenCallConv and a.sons[0].kind == nkSym and
|
if a.kind == nkHiddenCallConv and a.sons[0].kind == nkSym and
|
||||||
isGenericRoutine(a.sons[0].sym):
|
isGenericRoutine(a.sons[0].sym):
|
||||||
let finalCallee = generateInstance(c, a.sons[0].sym, x.bindings, n.info)
|
let finalCallee = generateInstance(c, a.sons[0].sym, x.bindings, a.info)
|
||||||
a.sons[0].sym = finalCallee
|
a.sons[0].sym = finalCallee
|
||||||
a.sons[0].typ = finalCallee.typ
|
a.sons[0].typ = finalCallee.typ
|
||||||
|
#a.typ = finalCallee.typ.sons[0]
|
||||||
|
|
||||||
|
proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||||
|
assert n.kind in nkCallKinds
|
||||||
|
if x.genericConverter:
|
||||||
|
for i in 1 .. <n.len:
|
||||||
|
instGenericConvertersArg(c, n.sons[i], x)
|
||||||
|
|
||||||
|
proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||||
|
var m: TCandidate
|
||||||
|
initCandidate(m, f)
|
||||||
|
result = paramTypesMatch(c, m, f, a, arg, nil)
|
||||||
|
if m.genericConverter and result != nil:
|
||||||
|
instGenericConvertersArg(c, result, m)
|
||||||
|
|
||||||
|
proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode =
|
||||||
|
var m: TCandidate
|
||||||
|
initCandidate(m, f)
|
||||||
|
result = paramTypesMatch(c, m, f, n.typ, n, nil)
|
||||||
|
if m.genericConverter and result != nil:
|
||||||
|
instGenericConvertersArg(c, result, m)
|
||||||
|
|
||||||
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
assert x.state == csMatch
|
assert x.state == csMatch
|
||||||
|
|
@ -111,8 +130,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
if ContainsGenericType(result.typ): result.typ = errorType(c)
|
if ContainsGenericType(result.typ): result.typ = errorType(c)
|
||||||
return
|
return
|
||||||
result = x.call
|
result = x.call
|
||||||
if x.genericConverter:
|
instGenericConvertersSons(c, result, x)
|
||||||
instantiateGenericConverters(c, result, x)
|
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
result.typ = finalCallee.typ.sons[0]
|
result.typ = finalCallee.typ.sons[0]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
else:
|
else:
|
||||||
result = m.call
|
result = m.call
|
||||||
|
instGenericConvertersSons(c, result, m)
|
||||||
# we assume that a procedure that calls something indirectly
|
# we assume that a procedure that calls something indirectly
|
||||||
# has side-effects:
|
# has side-effects:
|
||||||
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
||||||
|
|
|
||||||
|
|
@ -594,7 +594,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
addSon(result, copyTree(arg))
|
addSon(result, copyTree(arg))
|
||||||
inc(m.convMatches)
|
inc(m.convMatches)
|
||||||
m.genericConverter = srca == isGeneric or destIsGeneric
|
m.genericConverter = srca == isGeneric or destIsGeneric
|
||||||
return
|
return result
|
||||||
|
|
||||||
proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
arg: PNode): PNode =
|
arg: PNode): PNode =
|
||||||
|
|
@ -705,7 +705,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
else:
|
else:
|
||||||
result = userConvMatch(c, m, base(f), a, arg)
|
result = userConvMatch(c, m, base(f), a, arg)
|
||||||
|
|
||||||
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
proc ParamTypesMatch*(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
arg, argOrig: PNode): PNode =
|
arg, argOrig: PNode): PNode =
|
||||||
if arg == nil or arg.kind notin nkSymChoices:
|
if arg == nil or arg.kind notin nkSymChoices:
|
||||||
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
|
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
|
||||||
|
|
@ -752,26 +752,11 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best],
|
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best],
|
||||||
argOrig)
|
argOrig)
|
||||||
|
|
||||||
proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
|
|
||||||
var m: TCandidate
|
|
||||||
initCandidate(m, f)
|
|
||||||
result = paramTypesMatch(c, m, f, a, arg, nil)
|
|
||||||
|
|
||||||
proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode =
|
|
||||||
var m: TCandidate
|
|
||||||
initCandidate(m, f)
|
|
||||||
result = paramTypesMatch(c, m, f, n.typ, n, nil)
|
|
||||||
|
|
||||||
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
|
||||||
var m: TCandidate
|
|
||||||
initCandidate(m, f)
|
|
||||||
result = paramTypesMatch(c, m, f, a, ast.emptyNode, nil) != nil
|
|
||||||
|
|
||||||
proc setSon(father: PNode, at: int, son: PNode) =
|
proc setSon(father: PNode, at: int, son: PNode) =
|
||||||
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
||||||
father.sons[at] = son
|
father.sons[at] = son
|
||||||
|
|
||||||
proc matchesAux*(c: PContext, n, nOrig: PNode,
|
proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
m: var TCandidate, marker: var TIntSet) =
|
m: var TCandidate, marker: var TIntSet) =
|
||||||
template checkConstraint(n: expr) {.immediate, dirty.} =
|
template checkConstraint(n: expr) {.immediate, dirty.} =
|
||||||
if not formal.constraint.isNil:
|
if not formal.constraint.isNil:
|
||||||
|
|
@ -904,4 +889,13 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||||
setSon(m.call, formal.position + 1, copyTree(formal.ast))
|
setSon(m.call, formal.position + 1, copyTree(formal.ast))
|
||||||
inc(f)
|
inc(f)
|
||||||
|
|
||||||
|
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||||
|
var m: TCandidate
|
||||||
|
initCandidate(m, f)
|
||||||
|
let res = paramTypesMatch(c, m, f, a, ast.emptyNode, nil)
|
||||||
|
#instantiateGenericConverters(c, res, m)
|
||||||
|
# XXX this is used by patterns.nim too; I think it's better to not
|
||||||
|
# instantiate generic converters for that
|
||||||
|
result = res != nil
|
||||||
|
|
||||||
include suggest
|
include suggest
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ path="$lib/ecmas"
|
||||||
path="$lib/pure/unidecode"
|
path="$lib/pure/unidecode"
|
||||||
|
|
||||||
@if nimbabel:
|
@if nimbabel:
|
||||||
babelpath="$home/babeltest/"
|
babelpath="$home/.babel/libs/"
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@if release or quick:
|
@if release or quick:
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,11 @@ Core
|
||||||
|
|
||||||
* `threads <threads.html>`_
|
* `threads <threads.html>`_
|
||||||
Nimrod thread support. **Note**: This is part of the system module. Do not
|
Nimrod thread support. **Note**: This is part of the system module. Do not
|
||||||
import it explicitely.
|
import it explicitly.
|
||||||
|
|
||||||
* `channels <channels.html>`_
|
* `channels <channels.html>`_
|
||||||
Nimrod message passing support for threads. **Note**: This is part of the
|
Nimrod message passing support for threads. **Note**: This is part of the
|
||||||
system module. Do not import it explicitely.
|
system module. Do not import it explicitly.
|
||||||
|
|
||||||
* `locks <locks.html>`_
|
* `locks <locks.html>`_
|
||||||
Locks and condition variables for Nimrod.
|
Locks and condition variables for Nimrod.
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,17 @@ discard """
|
||||||
0'''
|
0'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
iterator count(x: int, skip: bool): int {.closure.} =
|
iterator count[T](x: T, skip: bool): int {.closure.} =
|
||||||
if skip: return x+10
|
if skip: return x+10
|
||||||
else: yield x+1
|
else: yield x+1
|
||||||
|
|
||||||
if skip: return x+10
|
if skip: return x+10
|
||||||
else: yield x+2
|
else: yield x+2
|
||||||
|
|
||||||
proc takeProc(x: iterator (x: int, skip: bool): int) =
|
proc takeProc[T](x: iterator (x: T, skip: bool): int) =
|
||||||
echo x(4, false)
|
echo x(4, false)
|
||||||
echo x(4, true)
|
echo x(4, true)
|
||||||
echo x(4, false)
|
echo x(4, false)
|
||||||
|
|
||||||
takeProc(count)
|
takeProc(count[int])
|
||||||
|
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -87,6 +87,7 @@ GC
|
||||||
Optimizations
|
Optimizations
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
- optimize 'if' with a constant condition
|
||||||
- escape analysis for string/seq seems to be easy to do too;
|
- escape analysis for string/seq seems to be easy to do too;
|
||||||
even further write barrier specialization
|
even further write barrier specialization
|
||||||
- inlining of first class functions
|
- inlining of first class functions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue