idetools: 'usages' and 'def' should work now; documented js backend

This commit is contained in:
Araq
2012-08-05 12:33:23 +02:00
parent a7a2f464a2
commit c7158af752
14 changed files with 215 additions and 117 deletions

View File

@@ -371,7 +371,7 @@ type
skEnumField, # an identifier in an enum
skForVar, # a for loop variable
skLabel, # a label (for block statement)
skStub # symbol is a stub and not yet loaded from the ROD
skStub, # symbol is a stub and not yet loaded from the ROD
# file (it is loaded on demand, which may
# mean: never)
TSymKinds* = set[TSymKind]
@@ -380,6 +380,7 @@ const
routineKinds* = {skProc, skMethod, skIterator, skConverter,
skMacro, skTemplate}
tfIncompleteStruct* = tfVarargs
skError* = skUnknown
type
TMagic* = enum # symbols that require compiler magic:

View File

@@ -37,7 +37,7 @@ proc considerAcc*(n: PNode): PIdent =
else:
GlobalError(n.info, errIdentifierExpected, renderTree(n))
proc errorSym*(n: PNode): PSym =
proc errorSym*(c: PContext, n: PNode): PSym =
## creates an error symbol to avoid cascading errors (for IDE support)
var m = n
# ensure that 'considerAcc' can't fail:
@@ -46,8 +46,12 @@ proc errorSym*(n: PNode): PSym =
considerAcc(m)
else:
getIdent("err:" & renderTree(m))
result = newSym(skUnknown, ident, getCurrOwner())
result = newSym(skError, ident, getCurrOwner())
result.info = n.info
result.typ = errorType(c)
incl(result.flags, sfDiscardable)
# pretend it's imported from some unknown module to prevent cascading errors:
SymTabAddAt(c.tab, result, ast.ImportTablePos)
type
TOverloadIterMode* = enum
@@ -106,7 +110,6 @@ proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
# add to interface:
if c.module != nil: StrTableAdd(c.module.tab, sym)
else: InternalError(sym.info, "AddInterfaceDeclAux")
#if getCurrOwner().kind == skModule: incl(sym.flags, sfGlobal)
proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
addDeclAt(c, sym, at)
@@ -139,7 +142,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = SymtabGet(c.Tab, n.ident)
if result == nil:
LocalError(n.info, errUndeclaredIdentifier, n.ident.s)
result = errorSym(n)
result = errorSym(c, n)
of nkSym:
result = n.sym
of nkAccQuoted:
@@ -147,7 +150,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = SymtabGet(c.Tab, ident)
if result == nil:
LocalError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(n)
result = errorSym(c, n)
else:
InternalError(n.info, "lookUp")
return
@@ -166,11 +169,11 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
result = SymtabGet(c.Tab, ident)
if result == nil and checkUndeclared in flags:
LocalError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(n)
result = errorSym(c, n)
elif checkAmbiguity in flags and result != nil and
Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, ident.s)
of nkSym:
of nkSym:
result = n.sym
if checkAmbiguity in flags and Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, n.sym.name.s)
@@ -190,11 +193,11 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
result = StrTableGet(m.tab, ident)
if result == nil and checkUndeclared in flags:
LocalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
result = errorSym(n.sons[1])
result = errorSym(c, n.sons[1])
elif checkUndeclared in flags:
LocalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
result = errorSym(n.sons[1])
result = errorSym(c, n.sons[1])
else:
result = nil
if result != nil and result.kind == skStub: loadStub(result)
@@ -231,7 +234,7 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else:
LocalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
result = errorSym(n.sons[1])
result = errorSym(c, n.sons[1])
of nkSymChoice:
o.mode = oimSymChoice
result = n.sons[0].sym

View File

@@ -526,7 +526,7 @@ proc `??`* (info: TLineInfo, filename: string): bool =
# only for debugging purposes
result = filename in info.toFilename
var checkPoints: seq[TLineInfo] = @[]
var checkPoints*: seq[TLineInfo] = @[]
proc addCheckpoint*(info: TLineInfo) =
checkPoints.add(info)
@@ -541,6 +541,7 @@ proc OutWriteln*(s: string) =
proc MsgWriteln*(s: string) =
## Writes to stdout. If --stdout option is given, writes to stderr instead.
if gSilence == 0:
if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
if optStdout in gGlobalOptions: Writeln(stderr, s)
else: Writeln(stdout, s)
@@ -587,7 +588,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
elif eh == doRaise:
raiseRecoverableError(s)
proc `==`(a, b: TLineInfo): bool =
proc `==`*(a, b: TLineInfo): bool =
result = a.line == b.line and a.fileIndex == b.fileIndex
proc writeContext(lastinfo: TLineInfo) =
@@ -637,7 +638,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
frmt = posErrorFormat
# we try to filter error messages so that not two error message
# in the same file and line are produced:
ignoreMsg = lastError == info and eh != doAbort
#ignoreMsg = lastError == info and eh != doAbort
lastError = info
of warnMin..warnMax:
ignoreMsg = optWarns notin gOptions or msg notin gNotes
@@ -661,7 +662,6 @@ proc GlobalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doRaise)
proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
#if gCmd == cmdIdeTools and gErrorCounter > 10: return
liMessage(info, msg, arg, doNothing)
proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") =

View File

@@ -14,7 +14,7 @@ import
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, nimsets, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
suggest, semthreads, intsets, transf, evals, idgen, aliases
semthreads, intsets, transf, evals, idgen, aliases
proc semPass*(): TPass
# implementation
@@ -37,9 +37,10 @@ proc addResultNode(c: PContext, n: PNode)
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
proc typeMismatch(n: PNode, formal, actual: PType) =
LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
typeToString(actual) & ") " &
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
if formal.kind != tyError and actual.kind != tyError:
LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
typeToString(actual) & ") " &
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
result = IndexTypesMatch(c, formal, arg.typ, arg)

View File

@@ -72,7 +72,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
if c.inCompilesContext > 0:
# quick error message for performance of 'compiles' built-in:
GlobalError(n.Info, errAmbiguousCallXYZ, "")
else:
elif gErrorCounter == 0:
# don't cascade errors
var args = "("
for i in countup(1, sonsLen(n) - 1):
if i > 1: add(args, ", ")
@@ -91,8 +92,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
# a generic proc!
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
if not x.proxyMatch:
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
else:
result = x.call
result.sons[0] = newSymNode(finalCallee)
result.typ = finalCallee.typ.sons[0]
if ContainsGenericType(result.typ): result.typ = errorType(c)
return
result = x.call
result.sons[0] = newSymNode(finalCallee)
result.typ = finalCallee.typ.sons[0]

View File

@@ -74,6 +74,8 @@ type
filename*: string # the module's filename
userPragmas*: TStrTable
evalContext*: PEvalContext
UnknownIdents*: TIntSet # ids of all unknown identifiers to prevent
# naming it multiple times
var
gGenericsCache: PGenericsCache # save for modularity
@@ -194,6 +196,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
# we have to give up and use a per-module cache for generic instantiations:
result.generics = newGenericsCache()
assert gGenericsCache == nil
result.UnknownIdents = initIntSet()
proc addConverter(c: PContext, conv: PSym) =
var L = len(c.converters)
@@ -230,6 +233,10 @@ proc errorType*(c: PContext): PType =
## creates a type representing an error state
result = newTypeS(tyError, c)
proc errorNode*(c: PContext, n: PNode): PNode =
result = newNodeI(nkEmpty, n.info)
result.typ = errorType(c)
proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
dest.kind = kind
dest.owner = getCurrOwner()
@@ -243,22 +250,12 @@ proc makeRangeType*(c: PContext, first, last: biggestInt,
result = newTypeS(tyRange, c)
result.n = n
rawAddSon(result, getSysType(tyInt)) # basetype of range
proc markUsed*(n: PNode, s: PSym) =
incl(s.flags, sfUsed)
if {sfDeprecated, sfError} * s.flags != {}:
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
proc markIndirect*(c: PContext, s: PSym) =
proc markIndirect*(c: PContext, s: PSym) {.inline.} =
if s.kind in {skProc, skConverter, skMethod, skIterator}:
incl(s.flags, sfAddrTaken)
# XXX add to 'c' for global analysis
proc useSym*(sym: PSym): PNode =
result = newSymNode(sym)
markUsed(result, sym)
proc illFormedAst*(n: PNode) =
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))

View File

@@ -38,7 +38,8 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags)
if result.kind == nkEmpty:
# do not produce another redundant error message:
raiseRecoverableError("")
#raiseRecoverableError("")
result = errorNode(c, n)
if result.typ != nil:
if result.typ.kind == tyVar: result = newDeref(result)
else:
@@ -50,7 +51,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags)
if result.kind == nkEmpty:
# do not produce another redundant error message:
raiseRecoverableError("")
result = errorNode(c, n)
if result.typ == nil:
LocalError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments}))
@@ -614,8 +615,8 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = nil
var prc = n.sons[0]
checkMinSonsLen(n, 1)
var prc = n.sons[0]
if n.sons[0].kind == nkDotExpr:
checkSonsLen(n.sons[0], 2)
n.sons[0] = semFieldAccess(c, n.sons[0])
@@ -638,19 +639,25 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if m.state != csMatch:
if c.inCompilesContext > 0:
# speed up error generation:
LocalError(n.Info, errTypeMismatch, "")
GlobalError(n.Info, errTypeMismatch, "")
return emptyNode
else:
var hasErrorType = false
var msg = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1):
if i > 1: add(msg, ", ")
add(msg, typeToString(n.sons[i].typ))
add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
typeToString(n.sons[0].typ))
LocalError(n.Info, errGenerated, msg)
return emptyNode
let nt = n.sons[i].typ
add(msg, typeToString(nt))
if nt.kind == tyError:
hasErrorType = true
break
if not hasErrorType:
add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
typeToString(n.sons[0].typ))
LocalError(n.Info, errGenerated, msg)
return errorNode(c, n)
result = nil
else:
else:
result = m.call
# we assume that a procedure that calls something indirectly
# has side-effects:
@@ -663,10 +670,11 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
n.sons[0] = prc
nOrig.sons[0] = prc
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
return emptyNode
if result == nil:
if c.inCompilesContext > 0 or gErrorCounter == 0:
LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
return errorNode(c, n)
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone:
@@ -680,9 +688,9 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
result = overloadedCallOpr(c, n)
if result == nil:
LocalError(n.Info, errGenerated, getNotFoundError(c, n))
return emptyNode
if result == nil:
NotFoundError(c, n)
return errorNode(c, n)
let callee = result.sons[0].sym
case callee.kind
of skMacro: result = semMacroExpr(c, nOrig, callee)
@@ -718,7 +726,7 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
addSon(result, newSymNode(e))
else:
LocalError(n.info, errSystemNeeds, "echo")
addSon(result, emptyNode)
addSon(result, errorNode(c, n))
var arg = buildStringify(c, n)
# problem is: implicit '$' is not checked for semantics yet. So we give up
# and check 'arg' for semantics again:
@@ -732,7 +740,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
if result.typ != nil and result.typ.kind != tyStmt:
if gCmd == cmdInteractive:
result = buildEchoStmt(c, result)
elif not ImplicitelyDiscardable(result):
elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError:
localError(n.info, errDiscardValue)
proc isTypeExpr(n: PNode): bool =
@@ -909,8 +917,9 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSon(result, newIdentNode(i, n.info))
addSon(result, copyTree(n[0]))
else:
LocalError(n.Info, errUndeclaredFieldX, i.s)
result = emptyNode
if not ContainsOrIncl(c.UnknownIdents, i.id):
LocalError(n.Info, errUndeclaredFieldX, i.s)
result = errorNode(c, n)
proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
result = newNodeI(nkCall, n.info)
@@ -992,8 +1001,9 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
else:
LocalError(n.Info, errUndeclaredFieldX, id.s)
result = emptyNode
if not ContainsOrIncl(c.UnknownIdents, id.id):
LocalError(n.Info, errUndeclaredFieldX, id.s)
result = errorNode(c, n)
proc takeImplicitAddr(c: PContext, n: PNode): PNode =
case n.kind
@@ -1116,16 +1126,16 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
if expandedSym == nil:
LocalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
return errorSym(n[0])
return errorSym(c, n[0])
if expandedSym.kind notin {skMacro, skTemplate}:
LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
return errorSym(n[0])
return errorSym(c, n[0])
result = expandedSym
else:
LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
result = errorSym(n)
result = errorSym(c, n)
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
flags: TExprFlags): PNode =
@@ -1395,11 +1405,11 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
result = semTemplateExpr(c, result, s, semCheck)
else:
LocalError(n.info, errXisNoMacroOrTemplate, s.name.s)
result = emptyNode
result = errorNode(c, n)
else:
LocalError(n.info, errInvalidExpressionX,
renderTree(a, {renderNoComments}))
result = emptyNode
result = errorNode(c, n)
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n

View File

@@ -27,8 +27,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
var t = PType(IdTableGet(pt, q.typ))
if t == nil:
LocalError(a.info, errCannotInstantiateX, s.name.s)
break
if t.kind == tyGenericParam:
t = errorType(c)
elif t.kind == tyGenericParam:
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
elif t.kind == tyGenericInvokation:
#t = instGenericContainer(c, a, t)

View File

@@ -79,7 +79,8 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
x.info = n.info
incl(s.flags, sfUsed)
n.sons[0] = x
else:
suggestSym(x, s)
else:
localError(n.info, errInvalidControlFlowX, s.name.s)
elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0):
localError(n.info, errInvalidControlFlowX,
@@ -94,6 +95,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
var labl = newSymS(skLabel, n.sons[0], c)
addDecl(c, labl)
n.sons[0] = newSymNode(labl)
suggestSym(n.sons[0], labl)
n.sons[1] = semStmt(c, n.sons[1])
closeScope(c.tab)
Dec(c.p.nestedBlockCounter)
@@ -132,7 +134,7 @@ proc semCase(c: PContext, n: PNode): PNode =
case skipTypes(n.sons[0].Typ, abstractVarRange).Kind
of tyInt..tyInt64, tyChar, tyEnum:
chckCovered = true
of tyFloat..tyFloat128, tyString:
of tyFloat..tyFloat128, tyString, tyError:
nil
else:
LocalError(n.info, errSelectorMustBeOfCertainTypes)
@@ -229,8 +231,9 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if isTopLevel(c):
result = semIdentWithPragma(c, kind, n, {sfExported})
incl(result.flags, sfGlobal)
else:
else:
result = semIdentWithPragma(c, kind, n, {})
suggestSym(n, result)
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode

View File

@@ -222,8 +222,8 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
amb = nextOverloadIter(ov, c, n)
if amb != nil: result = amb
else:
LocalError(n.info, errTypeExpected)
return errorSym(n)
if result.kind != skError: LocalError(n.info, errTypeExpected)
return errorSym(c, n)
if result.typ.kind != tyGenericParam:
# XXX get rid of this hack!
reset(n[])
@@ -231,7 +231,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
n.sym = result
else:
LocalError(n.info, errIdentifierExpected)
result = errorSym(n)
result = errorSym(c, n)
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
if n.sonsLen == 0: return newConstraint(c, tyTuple)
@@ -827,7 +827,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkIdent, nkDotExpr, nkAccQuoted:
var s = semTypeIdent(c, n)
if s.typ == nil:
LocalError(n.info, errTypeExpected)
if s.kind != skError: LocalError(n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c)
elif prev == nil:
result = s.typ
@@ -845,7 +845,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = prev
markUsed(n, n.sym)
else:
LocalError(n.info, errTypeExpected)
if n.sym.kind != skError: LocalError(n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c)
of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev)

View File

@@ -12,7 +12,7 @@
import
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
magicsys, condsyms, idents
magicsys, condsyms, idents, lexer, options
type
TCandidateState* = enum
@@ -32,6 +32,7 @@ type
bindings*: TIdTable # maps types to types
baseTypeMatch: bool # needed for conversions from T to openarray[T]
# for example
proxyMatch*: bool # to prevent instantiations
inheritancePenalty: int # to prefer closest father object type
TTypeRelation* = enum # order is important!
@@ -43,7 +44,9 @@ type
isGeneric,
isFromIntLit, # conversion *from* int literal; proven safe
isEqual
proc markUsed*(n: PNode, s: PSym)
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
c.exactMatches = 0
c.subtypeMatches = 0
@@ -114,22 +117,26 @@ proc writeMatches*(c: TCandidate) =
Writeln(stdout, "intconv matches: " & $c.intConvMatches)
Writeln(stdout, "generic matches: " & $c.genericMatches)
proc getNotFoundError*(c: PContext, n: PNode): string =
proc NotFoundError*(c: PContext, n: PNode) =
# Gives a detailed error message; this is separated from semOverloadedCall,
# as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error).
if c.InCompilesContext > 0: return ""
result = msgKindToString(errTypeMismatch)
if c.InCompilesContext > 0:
# fail fast:
GlobalError(n.info, errTypeMismatch, "")
var result = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1):
#debug(n.sons[i].typ)
if n.sons[i].kind == nkExprEqExpr:
add(result, renderTree(n.sons[i].sons[0]))
add(result, ": ")
add(result, typeToString(n.sons[i].typ))
let nt = n.sons[i].typ
if nt.kind == tyError: return
add(result, typeToString(nt))
if i != sonsLen(n) - 1: add(result, ", ")
add(result, ')')
var candidates = ""
var o: TOverloadIter
var o: TOverloadIter
var sym = initOverloadIter(o, c, n.sons[0])
while sym != nil:
if sym.kind in {skProc, skMethod, skIterator, skConverter}:
@@ -139,6 +146,7 @@ proc getNotFoundError*(c: PContext, n: PNode): string =
sym = nextOverloadIter(o, c, n.sons[0])
if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
LocalError(n.Info, errGenerated, result)
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
proc concreteType(c: TCandidate, t: PType): PType =
@@ -418,7 +426,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
result = typeRel(c, f.sons[0], x)
if result < isGeneric: result = isNone
of tyForward: InternalError("forward type in typeRel()")
of tyNil:
of tyNil:
if a.kind == f.kind: result = isEqual
of tyTuple:
if a.kind == tyTuple: result = tupleRel(c, f, a)
@@ -539,8 +547,10 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
if result == isGeneric: put(c.bindings, f, a)
else:
result = isNone
of tyExpr, tyStmt, tyProxy:
of tyExpr, tyStmt:
result = isGeneric
of tyProxy:
result = isEqual
else: internalError("typeRel: " & $f.kind)
proc cmpTypes*(f, a: PType): TTypeRelation =
@@ -560,8 +570,13 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
c: PContext): PNode =
result = newNodeI(kind, arg.info)
if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
else: result.typ = f
if containsGenericType(f):
if not m.proxyMatch:
result.typ = getInstantiatedType(c, arg, m, f)
else:
result.typ = errorType(c)
else:
result.typ = f
if result.typ == nil: InternalError(arg.info, "implicitConv")
addSon(result, ast.emptyNode)
addSon(result, arg)
@@ -648,11 +663,12 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
result = copyTree(arg)
if skipTypes(f, abstractVar).kind in {tyTuple}:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
of isNone:
# we test for this here to not slow down ``typeRel``:
of isNone:
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
if a.kind == tyProxy:
inc(m.genericMatches)
return copyTree(arg)
m.proxyMatch = true
return copyTree(arg)
result = userConvMatch(c, m, f, a, arg)
# check for a base type match, which supports openarray[T] without []
# constructor in a call:
@@ -854,3 +870,5 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
# use default value:
setSon(m.call, formal.position + 1, copyTree(formal.ast))
inc(f)
include suggest

View File

@@ -9,15 +9,14 @@
## This file implements features required for IDE support.
import
lexer, idents, ast, astalgo, semdata, msgs, types, sigmatch, options,
renderer
# imported from sigmatch.nim
const
sep = '\t'
sectionSuggest = "sug"
sectionDef = "def"
sectionContext = "con"
sectionUsage = "use"
proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
result = section
@@ -183,6 +182,16 @@ proc findClosestCall(n: PNode): PNode =
result = findClosestCall(n.sons[i])
if result != nil: return
proc isTracked(current: TLineInfo, tokenLen: int): bool =
# the column of an identifier is at its *end*, so we subtract to get the
# start of it.
for i in countup(0, high(checkPoints)):
if current.fileIndex == checkPoints[i].fileIndex:
if current.line == checkPoints[i].line:
let col = checkPoints[i].col
if col >= current.col-tokenLen and col <= current.col:
return true
proc findClosestSym(n: PNode): PNode =
if n.kind == nkSym and msgs.inCheckpoint(n.info) == cpExact:
result = n
@@ -205,7 +214,40 @@ proc fuzzySemCheck(c: PContext, n: PNode): PNode =
for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i]))
var
usageSym: PSym
usageSym*: PSym
lastLineInfo: TLineInfo
proc findUsages(node: PNode, s: PSym) =
if usageSym == nil and isTracked(node.info, s.name.s.len):
usageSym = s
OutWriteln(SymToStr(s, isLocal=false, sectionUsage))
elif s == usageSym:
if lastLineInfo != node.info:
OutWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info))
lastLineInfo = node.info
proc findDefinition(node: PNode, s: PSym) =
if isTracked(node.info, s.name.s.len):
OutWriteln(SymToStr(s, isLocal=false, sectionDef))
quit(0)
proc suggestSym*(n: PNode, s: PSym) {.inline.} =
## misnamed: should be 'symDeclared'
if optUsages in gGlobalOptions:
findUsages(n, s)
if optDef in gGlobalOptions:
findDefinition(n, s)
proc markUsed(n: PNode, s: PSym) =
incl(s.flags, sfUsed)
if {sfDeprecated, sfError} * s.flags != {}:
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
suggestSym(n, s)
proc useSym*(sym: PSym): PNode =
result = newSymNode(sym)
markUsed(result, sym)
proc suggestExpr*(c: PContext, node: PNode) =
var cp = msgs.inCheckpoint(node.info)
@@ -243,25 +285,6 @@ proc suggestExpr*(c: PContext, node: PNode) =
addSon(a, x)
suggestCall(c, a, n, outputs)
if optDef in gGlobalOptions:
let n = findClosestSym(fuzzySemCheck(c, node))
if n != nil:
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
inc outputs
if optUsages in gGlobalOptions:
if usageSym == nil:
let n = findClosestSym(fuzzySemCheck(c, node))
if n != nil:
usageSym = n.sym
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
inc outputs
else:
let n = node
if n.kind == nkSym and n.sym == usageSym:
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef, n.info))
inc outputs
dec(c.InCompilesContext)
if outputs > 0 and optUsages notin gGlobalOptions: quit(0)

View File

@@ -514,3 +514,40 @@ efficient:
of "license": c.license = UnixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key))
The ECMAScript target
=====================
Nimrod can also generate `ECMAScript`:idx: (also known as `JavaScript`:idx:)
code. However, the ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module,
Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not
available. This includes:
* manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* file management
* most modules of the Standard library
* proper 64 bit integer arithmetic
* unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
available! To access the DOM, use the `dom`:idx: module that is only
available for the ECMAScript platform.
To compile a Nimrod module into a ``.js`` file use the ``js`` command; the
default is a ``.js`` file that is supposed to be referenced in an ``.html``
file. However, you can also run the code with `nodejs`:idx:\:
nimrod js -d:nodejs -r examples/hallo.nim
Known bugs
----------
* exception handling does not work

View File

@@ -6,19 +6,11 @@ version 0.9.0
- implicit deref for parameter matching
- ``borrow`` needs to take type classes into account
- ``=`` should be overloadable; requires specialization for ``=``
- optimize genericAssign in the code generator
- fix remaining closure bugs:
- fix evals.nim with closures
- implement "closure tuple consists of a single 'ref'" optimization
- document 'do' notation
- rethink the syntax: distinction between expr and stmt is unfortunate;
indentation handling is quite complex too; problem with exception handling
is that often the scope of ``try`` is wrong and apart from that ``try`` is
a full blown statement; a ``try`` expression might be a good idea to make
error handling more light-weight
Bugs
----
@@ -36,9 +28,15 @@ version 0.9.XX
==============
- JS gen:
- document it
- fix exception handling
- document 'do' notation
- rethink the syntax: distinction between expr and stmt is unfortunate;
indentation handling is quite complex too; problem with exception handling
is that often the scope of ``try`` is wrong and apart from that ``try`` is
a full blown statement; a ``try`` expression might be a good idea to make
error handling more light-weight
- ``=`` should be overloadable; requires specialization for ``=``
- ``hoist`` pragma for loop hoisting
- document destructors; don't work yet when used as expression
- make use of ``tyIter`` to fix the implicit items/pairs issue