Merge branch 'master' of gh:/Araq/Nimrod into upstream
This commit is contained in:
commit
3f1e9b3a25
942 changed files with 13790 additions and 3241 deletions
3
.gitignore
vendored
Executable file → Normal file
3
.gitignore
vendored
Executable file → Normal file
|
|
@ -16,6 +16,7 @@ compiler/c2nim/nimcache
|
|||
compiler/pas2nim/nimcache
|
||||
misc
|
||||
doc/*.html
|
||||
doc/*.pdf
|
||||
doc/*.idx
|
||||
/web/upload
|
||||
koch
|
||||
|
|
@ -28,6 +29,8 @@ examples/cross_todo/nimrod_backend/backend
|
|||
examples/cross_todo/nimrod_backend/testbackend
|
||||
examples/cross_todo/nimrod_backend/todo.sqlite3
|
||||
examples/cross_todo/nimrod_commandline/nimtodo
|
||||
install.sh
|
||||
deinstall.sh
|
||||
|
||||
# iOS specific wildcards.
|
||||
*.mode1v3
|
||||
|
|
|
|||
0
build.bat
Executable file → Normal file
0
build.bat
Executable file → Normal file
23
compiler/ast.nim
Executable file → Normal file
23
compiler/ast.nim
Executable file → Normal file
|
|
@ -71,21 +71,25 @@ type
|
|||
nkDotCall, # used to temporarily flag a nkCall node;
|
||||
# this is used
|
||||
# for transforming ``s.len`` to ``len(s)``
|
||||
|
||||
nkCommand, # a call like ``p 2, 4`` without parenthesis
|
||||
nkCall, # a call like p(x, y) or an operation like +(a, b)
|
||||
nkCallStrLit, # a call with a string literal
|
||||
# x"abc" has two sons: nkIdent, nkRStrLit
|
||||
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
|
||||
nkInfix, # a call like (a + b)
|
||||
nkPrefix, # a call like !a
|
||||
nkPostfix, # something like a! (also used for visibility)
|
||||
nkHiddenCallConv, # an implicit type conversion via a type converter
|
||||
|
||||
nkExprEqExpr, # a named parameter with equals: ''expr = expr''
|
||||
nkExprColonExpr, # a named parameter with colon: ''expr: expr''
|
||||
nkIdentDefs, # a definition like `a, b: typeDesc = expr`
|
||||
# either typeDesc or expr may be nil; used in
|
||||
# formal parameters, var statements, etc.
|
||||
nkVarTuple, # a ``var (a, b) = expr`` construct
|
||||
nkInfix, # a call like (a + b)
|
||||
nkPrefix, # a call like !a
|
||||
nkPostfix, # something like a! (also used for visibility)
|
||||
nkPar, # syntactic (); may be a tuple constructor
|
||||
nkObjConstr, # object constructor: T(a: 1, b: 2)
|
||||
nkCurly, # syntactic {}
|
||||
nkCurlyExpr, # an expression like a{i}
|
||||
nkBracket, # syntactic []
|
||||
|
|
@ -109,7 +113,6 @@ type
|
|||
nkHiddenStdConv, # an implicit standard type conversion
|
||||
nkHiddenSubConv, # an implicit type conversion from a subtype
|
||||
# to a supertype
|
||||
nkHiddenCallConv, # an implicit type conversion via a type converter
|
||||
nkConv, # a type conversion
|
||||
nkCast, # a type cast
|
||||
nkStaticExpr, # a static expr
|
||||
|
|
@ -476,7 +479,7 @@ type
|
|||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
||||
mNBindSym, mNCallSite,
|
||||
mNBindSym, mLocals, mNCallSite,
|
||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
||||
mInstantiationInfo, mGetTypeInfo
|
||||
|
||||
|
|
@ -520,7 +523,7 @@ type
|
|||
TNodeSeq* = seq[PNode]
|
||||
PType* = ref TType
|
||||
PSym* = ref TSym
|
||||
TNode*{.final.} = object # on a 32bit machine, this takes 32 bytes
|
||||
TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes
|
||||
typ*: PType
|
||||
comment*: string
|
||||
info*: TLineInfo
|
||||
|
|
@ -591,6 +594,7 @@ type
|
|||
TLib* = object of lists.TListEntry # also misused for headers!
|
||||
kind*: TLibKind
|
||||
generated*: bool # needed for the backends:
|
||||
isOverriden*: bool
|
||||
name*: PRope
|
||||
path*: PNode # can be a string literal!
|
||||
|
||||
|
|
@ -605,7 +609,7 @@ type
|
|||
PInstantiation* = ref TInstantiation
|
||||
|
||||
PLib* = ref TLib
|
||||
TSym* = object of TIdObj
|
||||
TSym* {.acyclic.} = object of TIdObj
|
||||
# proc and type instantiations are cached in the generic symbol
|
||||
case kind*: TSymKind
|
||||
of skType:
|
||||
|
|
@ -653,7 +657,8 @@ type
|
|||
constraint*: PNode # additional constraints like 'lit|result'
|
||||
|
||||
TTypeSeq* = seq[PType]
|
||||
TType* = object of TIdObj # types are identical iff they have the
|
||||
TType* {.acyclic.} = object of TIdObj # \
|
||||
# types are identical iff they have the
|
||||
# same id; there may be multiple copies of a type
|
||||
# in memory!
|
||||
kind*: TTypeKind # kind of type
|
||||
|
|
@ -759,7 +764,7 @@ const
|
|||
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
||||
|
||||
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
||||
nkCommand, nkCallStrLit}
|
||||
nkCommand, nkCallStrLit, nkHiddenCallConv}
|
||||
|
||||
nkLambdaKinds* = {nkLambda, nkDo}
|
||||
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
|
||||
|
|
|
|||
4
compiler/astalgo.nim
Executable file → Normal file
4
compiler/astalgo.nim
Executable file → Normal file
|
|
@ -156,6 +156,10 @@ proc skipConv*(n: PNode): PNode =
|
|||
result = n.sons[1]
|
||||
else: result = n
|
||||
|
||||
proc skipConvTakeType*(n: PNode): PNode =
|
||||
result = n.skipConv
|
||||
result.typ = n.typ
|
||||
|
||||
proc SameValue*(a, b: PNode): bool =
|
||||
result = false
|
||||
case a.kind
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ iterator chosen(packages: PStringTable): string =
|
|||
|
||||
proc addBabelPath(p: string, info: TLineInfo) =
|
||||
if not contains(options.searchPaths, p):
|
||||
Message(info, hintPath, p)
|
||||
if gVerbosity >= 1: Message(info, hintPath, p)
|
||||
lists.PrependStr(options.lazyPaths, p)
|
||||
|
||||
proc addPathWithNimFiles(p: string, info: TLineInfo) =
|
||||
|
|
@ -83,7 +83,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
|
|||
if k == pcDir and p[pos] != '.':
|
||||
addPackage(packages, p)
|
||||
for p in packages.chosen:
|
||||
addPathWithNimFiles(p, info)
|
||||
addBabelPath(p, info)
|
||||
|
||||
proc babelPath*(path: string, info: TLineInfo) =
|
||||
addPathRec(path, info)
|
||||
|
|
|
|||
0
compiler/bitsets.nim
Executable file → Normal file
0
compiler/bitsets.nim
Executable file → Normal file
4
compiler/c2nim/c2nim.nim
Executable file → Normal file
4
compiler/c2nim/c2nim.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# c2nim - C to Nimrod source converter
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -15,7 +15,7 @@ const
|
|||
Version = NimrodVersion
|
||||
Usage = """
|
||||
c2nim - C to Nimrod source converter
|
||||
(c) 2012 Andreas Rumpf
|
||||
(c) 2013 Andreas Rumpf
|
||||
Usage: c2nim [options] inputfile [options]
|
||||
Options:
|
||||
-o, --out:FILE set output filename
|
||||
|
|
|
|||
0
compiler/c2nim/clex.nim
Executable file → Normal file
0
compiler/c2nim/clex.nim
Executable file → Normal file
11
compiler/c2nim/cparse.nim
Executable file → Normal file
11
compiler/c2nim/cparse.nim
Executable file → Normal file
|
|
@ -955,15 +955,22 @@ proc enumSpecifier(p: var TParser): PNode =
|
|||
result = newNodeP(nkConstSection, p)
|
||||
getTok(p, result)
|
||||
var i = 0
|
||||
var hasUnknown = false
|
||||
while true:
|
||||
var name = skipIdentExport(p)
|
||||
var val: PNode
|
||||
if p.tok.xkind == pxAsgn:
|
||||
getTok(p, name)
|
||||
val = constantExpression(p)
|
||||
if val.kind == nkIntLit: i = int(val.intVal)+1
|
||||
else: parMessage(p, errXExpected, "int literal")
|
||||
if val.kind == nkIntLit:
|
||||
i = int(val.intVal)+1
|
||||
hasUnknown = false
|
||||
else:
|
||||
hasUnknown = true
|
||||
else:
|
||||
if hasUnknown:
|
||||
parMessage(p, warnUser, "computed const value may be wrong: " &
|
||||
name.renderTree)
|
||||
val = newIntNodeP(nkIntLit, i, p)
|
||||
inc(i)
|
||||
var c = createConst(name, ast.emptyNode, val, p)
|
||||
|
|
|
|||
0
compiler/c2nim/cpp.nim
Executable file → Normal file
0
compiler/c2nim/cpp.nim
Executable file → Normal file
0
compiler/c2nim/nimrod.cfg
Executable file → Normal file
0
compiler/c2nim/nimrod.cfg
Executable file → Normal file
14
compiler/c2nim/tests/systest.c
Executable file → Normal file
14
compiler/c2nim/tests/systest.c
Executable file → Normal file
|
|
@ -9,6 +9,20 @@ extern "C" {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* 8bit, color or not */
|
||||
CV_LOAD_IMAGE_UNCHANGED =-1,
|
||||
/* 8bit, gray */
|
||||
CV_LOAD_IMAGE_GRAYSCALE =0,
|
||||
/* ?, color */
|
||||
CV_LOAD_IMAGE_COLOR =1,
|
||||
/* any depth, ? */
|
||||
CV_LOAD_IMAGE_ANYDEPTH =2,
|
||||
/* ?, any color */
|
||||
CV_LOAD_IMAGE_ANYCOLOR =4
|
||||
};
|
||||
|
||||
typedef void (*callback_t) (int rc);
|
||||
typedef const char* (*callback2)(int rc, long L, const char* buffer);
|
||||
|
||||
|
|
|
|||
0
compiler/c2nim/tests/systest2.c
Executable file → Normal file
0
compiler/c2nim/tests/systest2.c
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
|
|||
269
compiler/ccgexprs.nim
Executable file → Normal file
269
compiler/ccgexprs.nim
Executable file → Normal file
|
|
@ -195,6 +195,46 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
|||
addrLoc(dest), rdLoc(src))
|
||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||
|
||||
proc asgnComplexity(n: PNode): int =
|
||||
if n != nil:
|
||||
case n.kind
|
||||
of nkSym: result = 1
|
||||
of nkRecCase:
|
||||
# 'case objects' are too difficult to inline their assignment operation:
|
||||
result = 100
|
||||
of nkRecList:
|
||||
for t in items(n):
|
||||
result += asgnComplexity(t)
|
||||
else: nil
|
||||
|
||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
||||
|
||||
proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
|
||||
result.k = locField
|
||||
result.s = a.s
|
||||
result.t = t
|
||||
result.r = rdLoc(a).con(".").con(field)
|
||||
result.heapRoot = a.heapRoot
|
||||
|
||||
proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
for i in 0 .. <dest.t.len:
|
||||
let t = dest.t.sons[i]
|
||||
let field = ropef("Field$1", i.toRope)
|
||||
genAssignment(p, optAsgnLoc(dest, t, field),
|
||||
optAsgnLoc(src, t, field), flags)
|
||||
|
||||
proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||
t: PNode) =
|
||||
if t == nil: return
|
||||
case t.kind
|
||||
of nkSym:
|
||||
let field = t.sym
|
||||
genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
|
||||
optAsgnLoc(src, field.typ, field.loc.r), flags)
|
||||
of nkRecList:
|
||||
for child in items(t): genOptAsgnObject(p, dest, src, flags, child)
|
||||
else: nil
|
||||
|
||||
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
# Consider:
|
||||
# type TMyFastString {.shallow.} = string
|
||||
|
|
@ -251,10 +291,29 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
|||
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||
addrLoc(dest), rdLoc(src))
|
||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||
of tyTuple, tyObject, tyProc:
|
||||
of tyProc:
|
||||
if needsComplexAssignment(dest.t):
|
||||
# optimize closure assignment:
|
||||
let a = optAsgnLoc(dest, dest.t, "ClEnv".toRope)
|
||||
let b = optAsgnLoc(src, dest.t, "ClEnv".toRope)
|
||||
genRefAssign(p, a, b, flags)
|
||||
linefmt(p, cpsStmts, "$1.ClPrc = $2.ClPrc;$n", rdLoc(dest), rdLoc(src))
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||
of tyTuple:
|
||||
if needsComplexAssignment(dest.t):
|
||||
if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags)
|
||||
else: genGenericAsgn(p, dest, src, flags)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||
of tyObject:
|
||||
# XXX: check for subtyping?
|
||||
if needsComplexAssignment(dest.t):
|
||||
genGenericAsgn(p, dest, src, flags)
|
||||
if asgnComplexity(dest.t.n) <= 4:
|
||||
discard getTypeDesc(p.module, dest.t)
|
||||
genOptAsgnObject(p, dest, src, flags, dest.t.n)
|
||||
else:
|
||||
genGenericAsgn(p, dest, src, flags)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||
of tyArray, tyArrayConstr:
|
||||
|
|
@ -574,6 +633,28 @@ proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
|||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||
result = a.t
|
||||
|
||||
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
a: TLoc
|
||||
i: int
|
||||
initLocExpr(p, e.sons[0], a)
|
||||
d.inheritLocation(a)
|
||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||
var ty = a.t
|
||||
var r = rdLoc(a)
|
||||
case e.sons[1].kind
|
||||
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||
else: internalError(e.info, "genTupleElem")
|
||||
when false:
|
||||
if ty.n != nil:
|
||||
var field = ty.n.sons[i].sym
|
||||
if field == nil: InternalError(e.info, "genTupleElem")
|
||||
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
||||
appf(r, ".$1", [field.loc.r])
|
||||
else:
|
||||
appf(r, ".Field$1", [toRope(i)])
|
||||
putIntoDest(p, d, ty.sons[i], r)
|
||||
|
||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
var ty = genRecordFieldAux(p, e, d, a)
|
||||
|
|
@ -598,38 +679,42 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
|||
appf(r, ".$1", [field.loc.r])
|
||||
putIntoDest(p, d, field.typ, r)
|
||||
|
||||
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
a: TLoc
|
||||
i: int
|
||||
initLocExpr(p, e.sons[0], a)
|
||||
d.inheritLocation(a)
|
||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||
var ty = a.t
|
||||
var r = rdLoc(a)
|
||||
case e.sons[1].kind
|
||||
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||
else: internalError(e.info, "genTupleElem")
|
||||
when false:
|
||||
if ty.n != nil:
|
||||
var field = ty.n.sons[i].sym
|
||||
if field == nil: InternalError(e.info, "genTupleElem")
|
||||
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
||||
appf(r, ".$1", [field.loc.r])
|
||||
else:
|
||||
appf(r, ".Field$1", [toRope(i)])
|
||||
putIntoDest(p, d, ty.sons[i], r)
|
||||
|
||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||
|
||||
proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
|
||||
var test, u, v: TLoc
|
||||
for i in countup(1, sonsLen(e) - 1):
|
||||
var it = e.sons[i]
|
||||
assert(it.kind in nkCallKinds)
|
||||
assert(it.sons[0].kind == nkSym)
|
||||
let op = it.sons[0].sym
|
||||
if op.magic == mNot: it = it.sons[1]
|
||||
assert(it.sons[2].kind == nkSym)
|
||||
initLoc(test, locNone, it.typ, OnStack)
|
||||
InitLocExpr(p, it.sons[1], u)
|
||||
initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
|
||||
v.r = ropef("$1.$2", [obj, it.sons[2].sym.loc.r])
|
||||
genInExprAux(p, it, u, v, test)
|
||||
let id = NodeTableTestOrSet(p.module.dataCache,
|
||||
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||
let strLit = if id == gBackendId: getStrLit(p.module, field.name.s)
|
||||
else: con("TMP", toRope(id))
|
||||
if op.magic == mNot:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
rdLoc(test), strLit)
|
||||
else:
|
||||
linefmt(p, cpsStmts,
|
||||
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
rdLoc(test), strLit)
|
||||
|
||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
a, u, v, test: TLoc
|
||||
f, field, op: PSym
|
||||
ty: PType
|
||||
r, strLit: PRope
|
||||
id: int
|
||||
it: PNode
|
||||
if optFieldCheck in p.options:
|
||||
var
|
||||
a: TLoc
|
||||
f, field: PSym
|
||||
ty: PType
|
||||
r: PRope
|
||||
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
||||
r = rdLoc(a)
|
||||
f = e.sons[0].sons[1].sym
|
||||
|
|
@ -643,30 +728,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
|||
if field == nil: InternalError(e.info, "genCheckedRecordField")
|
||||
if field.loc.r == nil:
|
||||
InternalError(e.info, "genCheckedRecordField") # generate the checks:
|
||||
for i in countup(1, sonsLen(e) - 1):
|
||||
it = e.sons[i]
|
||||
assert(it.kind in nkCallKinds)
|
||||
assert(it.sons[0].kind == nkSym)
|
||||
op = it.sons[0].sym
|
||||
if op.magic == mNot: it = it.sons[1]
|
||||
assert(it.sons[2].kind == nkSym)
|
||||
initLoc(test, locNone, it.typ, OnStack)
|
||||
InitLocExpr(p, it.sons[1], u)
|
||||
initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
|
||||
v.r = ropef("$1.$2", [r, it.sons[2].sym.loc.r])
|
||||
genInExprAux(p, it, u, v, test)
|
||||
id = NodeTableTestOrSet(p.module.dataCache,
|
||||
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
|
||||
else: strLit = con("TMP", toRope(id))
|
||||
if op.magic == mNot:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
rdLoc(test), strLit)
|
||||
else:
|
||||
linefmt(p, cpsStmts,
|
||||
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
rdLoc(test), strLit)
|
||||
genFieldCheck(p, e, r, field)
|
||||
app(r, rfmt(nil, ".$1", field.loc.r))
|
||||
putIntoDest(p, d, field.typ, r)
|
||||
else:
|
||||
|
|
@ -913,10 +975,9 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
|||
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
||||
# seq->data[seq->len-1] = x;
|
||||
let seqAppendPattern = if gCmd != cmdCompileToCpp:
|
||||
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
|
||||
else:
|
||||
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
|
||||
|
||||
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
|
||||
else:
|
||||
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
|
||||
var a, b, dest: TLoc
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
|
|
@ -935,20 +996,12 @@ proc genReset(p: BProc, n: PNode) =
|
|||
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
|
||||
|
||||
proc genNew(p: BProc, e: PNode) =
|
||||
var
|
||||
a, b: TLoc
|
||||
reftype, bt: PType
|
||||
sizeExpr: PRope
|
||||
refType = skipTypes(e.sons[1].typ, abstractVarRange)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: PRope) =
|
||||
var sizeExpr = sizeExpr
|
||||
let refType = skipTypes(a.t, abstractVarRange)
|
||||
var b: TLoc
|
||||
initLoc(b, locExpr, a.t, OnHeap)
|
||||
# 'genNew' also handles 'unsafeNew':
|
||||
if e.len == 3:
|
||||
var se: TLoc
|
||||
InitLocExpr(p, e.sons[2], se)
|
||||
sizeExpr = se.rdLoc
|
||||
else:
|
||||
if sizeExpr.isNil:
|
||||
sizeExpr = ropef("sizeof($1)",
|
||||
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange)))
|
||||
let args = [getTypeDesc(p.module, reftype),
|
||||
|
|
@ -965,9 +1018,20 @@ proc genNew(p: BProc, e: PNode) =
|
|||
else:
|
||||
b.r = ropecg(p.module, "($1) #newObj($2, $3)", args)
|
||||
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
|
||||
bt = skipTypes(refType.sons[0], abstractRange)
|
||||
let bt = skipTypes(refType.sons[0], abstractRange)
|
||||
genObjectInit(p, cpsStmts, bt, a, false)
|
||||
|
||||
proc genNew(p: BProc, e: PNode) =
|
||||
var a: TLoc
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
# 'genNew' also handles 'unsafeNew':
|
||||
if e.len == 3:
|
||||
var se: TLoc
|
||||
InitLocExpr(p, e.sons[2], se)
|
||||
rawGenNew(p, a, se.rdLoc)
|
||||
else:
|
||||
rawGenNew(p, a, nil)
|
||||
|
||||
proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
||||
let seqtype = skipTypes(dest.t, abstractVarRange)
|
||||
let args = [getTypeDesc(p.module, seqtype),
|
||||
|
|
@ -975,7 +1039,10 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
|||
var call: TLoc
|
||||
initLoc(call, locExpr, dest.t, OnHeap)
|
||||
if dest.s == OnHeap and usesNativeGC():
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
||||
if canFormAcycle(dest.t):
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
||||
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
||||
else:
|
||||
|
|
@ -988,6 +1055,44 @@ proc genNewSeq(p: BProc, e: PNode) =
|
|||
InitLocExpr(p, e.sons[2], b)
|
||||
genNewSeqAux(p, a, b.rdLoc)
|
||||
|
||||
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
var tmp: TLoc
|
||||
var t = e.typ.skipTypes(abstractInst)
|
||||
getTemp(p, t, tmp)
|
||||
let isRef = t.kind == tyRef
|
||||
var r = rdLoc(tmp)
|
||||
if isRef:
|
||||
rawGenNew(p, tmp, nil)
|
||||
t = t.sons[0].skipTypes(abstractInst)
|
||||
r = ropef("(*$1)", r)
|
||||
# XXX object initialization? but not necessary for temps, is it?
|
||||
discard getTypeDesc(p.module, t)
|
||||
for i in 1 .. <e.len:
|
||||
let it = e.sons[i]
|
||||
var tmp2: TLoc
|
||||
tmp2.r = r
|
||||
var field: PSym = nil
|
||||
var ty = t
|
||||
while ty != nil:
|
||||
field = lookupInRecord(ty.n, it.sons[0].sym.name)
|
||||
if field != nil: break
|
||||
if gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup")
|
||||
ty = GetUniqueType(ty.sons[0])
|
||||
if field == nil or field.loc.r == nil: InternalError(e.info, "genObjConstr")
|
||||
if it.len == 3 and optFieldCheck in p.options:
|
||||
genFieldCheck(p, it.sons[2], r, field)
|
||||
app(tmp2.r, ".")
|
||||
app(tmp2.r, field.loc.r)
|
||||
tmp2.k = locTemp
|
||||
tmp2.t = field.loc.t
|
||||
tmp2.s = onHeap
|
||||
tmp2.heapRoot = tmp.r
|
||||
expr(p, it.sons[1], tmp2)
|
||||
if d.k == locNone:
|
||||
d = tmp
|
||||
else:
|
||||
genAssignment(p, d, tmp, {})
|
||||
|
||||
proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
||||
var arr: TLoc
|
||||
if d.k == locNone:
|
||||
|
|
@ -995,7 +1100,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
|||
# generate call to newSeq before adding the elements per hand:
|
||||
genNewSeqAux(p, d, intLiteral(sonsLen(t)))
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
|
||||
initLoc(arr, locExpr, elemType(skipTypes(t.typ, typedescInst)), OnHeap)
|
||||
arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
|
||||
arr.s = OnHeap # we know that sequences are on the heap
|
||||
expr(p, t.sons[i], arr)
|
||||
|
|
@ -1226,8 +1331,14 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
|||
var a, b, x, y: TLoc
|
||||
if (e.sons[1].Kind == nkCurly) and fewCmps(e.sons[1]):
|
||||
# a set constructor but not a constant set:
|
||||
# do not emit the set, but generate a bunch of comparisons
|
||||
initLocExpr(p, e.sons[2], a)
|
||||
# do not emit the set, but generate a bunch of comparisons; and if we do
|
||||
# so, we skip the unnecessary range check: This is a semantical extension
|
||||
# that code now relies on. :-/ XXX
|
||||
let ea = if e.sons[2].kind in {nkChckRange, nkChckRange64}:
|
||||
e.sons[2].sons[0]
|
||||
else:
|
||||
e.sons[2]
|
||||
initLocExpr(p, ea, a)
|
||||
initLoc(b, locExpr, e.typ, OnUnknown)
|
||||
b.r = toRope("(")
|
||||
var length = sonsLen(e.sons[1])
|
||||
|
|
@ -1467,8 +1578,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
of mNewFinalize: genNewFinalize(p, e)
|
||||
of mNewSeq: genNewSeq(p, e)
|
||||
of mSizeOf:
|
||||
let t = e.sons[1].typ.skipTypes({tyTypeDesc})
|
||||
putIntoDest(p, d, e.typ, ropef("((NI)sizeof($1))",
|
||||
[getTypeDesc(p.module, e.sons[1].typ)]))
|
||||
[getTypeDesc(p.module, t)]))
|
||||
of mChr: genCast(p, e, d)
|
||||
of mOrd: genOrd(p, e, d)
|
||||
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
||||
|
|
@ -1755,6 +1867,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
|||
exprComplexConst(p, e, d)
|
||||
else:
|
||||
genTupleConstr(p, e, d)
|
||||
of nkObjConstr: genObjConstr(p, e, d)
|
||||
of nkCast: genCast(p, e, d)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d)
|
||||
of nkHiddenAddr, nkAddr: genAddr(p, e, d)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
## is needed for incremental compilation.
|
||||
|
||||
import
|
||||
ast, astalgo, ropes, options, strutils, lexbase, msgs, cgendata, rodutils,
|
||||
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
|
||||
intsets, platform, llstream
|
||||
|
||||
# Careful! Section marks need to contain a tabulator so that they cannot
|
||||
|
|
@ -45,11 +45,8 @@ const
|
|||
]
|
||||
NimMergeEndMark = "/*\tNIM_merge_END:*/"
|
||||
|
||||
template mergeSectionsEnabled: expr =
|
||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||
|
||||
proc genSectionStart*(fs: TCFileSection): PRope =
|
||||
if mergeSectionsEnabled:
|
||||
if compilationCachePresent:
|
||||
result = toRope(tnl)
|
||||
app(result, "/*\t")
|
||||
app(result, CFileSectionNames[fs])
|
||||
|
|
@ -57,11 +54,11 @@ proc genSectionStart*(fs: TCFileSection): PRope =
|
|||
app(result, tnl)
|
||||
|
||||
proc genSectionEnd*(fs: TCFileSection): PRope =
|
||||
if mergeSectionsEnabled:
|
||||
if compilationCachePresent:
|
||||
result = toRope(NimMergeEndMark & tnl)
|
||||
|
||||
proc genSectionStart*(ps: TCProcSection): PRope =
|
||||
if mergeSectionsEnabled:
|
||||
if compilationCachePresent:
|
||||
result = toRope(tnl)
|
||||
app(result, "/*\t")
|
||||
app(result, CProcSectionNames[ps])
|
||||
|
|
@ -69,7 +66,7 @@ proc genSectionStart*(ps: TCProcSection): PRope =
|
|||
app(result, tnl)
|
||||
|
||||
proc genSectionEnd*(ps: TCProcSection): PRope =
|
||||
if mergeSectionsEnabled:
|
||||
if compilationCachePresent:
|
||||
result = toRope(NimMergeEndMark & tnl)
|
||||
|
||||
proc writeTypeCache(a: TIdTable, s: var string) =
|
||||
|
|
@ -122,8 +119,8 @@ proc skipWhite(L: var TBaseLexer) =
|
|||
var pos = L.bufpos
|
||||
while true:
|
||||
case ^pos
|
||||
of CR: pos = lexbase.HandleCR(L, pos)
|
||||
of LF: pos = lexbase.HandleLF(L, pos)
|
||||
of CR: pos = nimlexbase.HandleCR(L, pos)
|
||||
of LF: pos = nimlexbase.HandleLF(L, pos)
|
||||
of ' ': inc pos
|
||||
else: break
|
||||
L.bufpos = pos
|
||||
|
|
@ -132,8 +129,8 @@ proc skipUntilCmd(L: var TBaseLexer) =
|
|||
var pos = L.bufpos
|
||||
while true:
|
||||
case ^pos
|
||||
of CR: pos = lexbase.HandleCR(L, pos)
|
||||
of LF: pos = lexbase.HandleLF(L, pos)
|
||||
of CR: pos = nimlexbase.HandleCR(L, pos)
|
||||
of LF: pos = nimlexbase.HandleLF(L, pos)
|
||||
of '\0': break
|
||||
of '/':
|
||||
if ^(pos+1) == '*' and ^(pos+2) == '\t':
|
||||
|
|
@ -156,11 +153,11 @@ when false:
|
|||
while true:
|
||||
case buf[pos]
|
||||
of CR:
|
||||
pos = lexbase.HandleCR(L, pos)
|
||||
pos = nimlexbase.HandleCR(L, pos)
|
||||
buf = L.buf
|
||||
result.data.add(tnl)
|
||||
of LF:
|
||||
pos = lexbase.HandleLF(L, pos)
|
||||
pos = nimlexbase.HandleLF(L, pos)
|
||||
buf = L.buf
|
||||
result.data.add(tnl)
|
||||
of '\0':
|
||||
|
|
@ -182,11 +179,11 @@ proc readVerbatimSection(L: var TBaseLexer): PRope =
|
|||
while true:
|
||||
case buf[pos]
|
||||
of CR:
|
||||
pos = lexbase.HandleCR(L, pos)
|
||||
pos = nimlexbase.HandleCR(L, pos)
|
||||
buf = L.buf
|
||||
r.add(tnl)
|
||||
of LF:
|
||||
pos = lexbase.HandleLF(L, pos)
|
||||
pos = nimlexbase.HandleLF(L, pos)
|
||||
buf = L.buf
|
||||
r.add(tnl)
|
||||
of '\0':
|
||||
|
|
|
|||
33
compiler/ccgstmts.nim
Executable file → Normal file
33
compiler/ccgstmts.nim
Executable file → Normal file
|
|
@ -16,7 +16,8 @@ const
|
|||
# above X strings a hash-switch for strings is generated
|
||||
|
||||
proc registerGcRoot(p: BProc, v: PSym) =
|
||||
if gSelectedGc == gcMarkAndSweep and containsGarbageCollectedRef(v.loc.t):
|
||||
if gSelectedGc in {gcMarkAndSweep, gcGenerational} and
|
||||
containsGarbageCollectedRef(v.loc.t):
|
||||
# we register a specialized marked proc here; this has the advantage
|
||||
# that it works out of the box for thread local storage then :-)
|
||||
let prc = genTraverseProcForGlobal(p.module, v)
|
||||
|
|
@ -44,7 +45,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
|||
if t.kind == tyTuple:
|
||||
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
||||
else:
|
||||
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
|
||||
if t.n.sons[i].kind != nkSym: InternalError(n.info, "genVarTuple")
|
||||
field.r = ropef("$1.$2",
|
||||
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
|
||||
putLocIntoDest(p, v.loc, field)
|
||||
|
|
@ -63,19 +64,23 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
|
|||
result = len(p.blocks)
|
||||
setlen(p.blocks, result + 1)
|
||||
p.blocks[result].id = p.labels
|
||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
|
||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
|
||||
|
||||
proc assignLabel(b: var TBlock): PRope {.inline.} =
|
||||
b.label = con("LA", b.id.toRope)
|
||||
result = b.label
|
||||
|
||||
proc blockBody(b: var TBlock): PRope {.inline.} =
|
||||
return b.sections[cpsLocals].con(b.sections[cpsInit]).con(b.sections[cpsStmts])
|
||||
proc blockBody(b: var TBlock): PRope =
|
||||
result = b.sections[cpsLocals]
|
||||
if b.frameLen > 0:
|
||||
result.appf("F.len+=$1;$n", b.frameLen.toRope)
|
||||
result.app(b.sections[cpsInit])
|
||||
result.app(b.sections[cpsStmts])
|
||||
|
||||
proc endBlock(p: BProc, blockEnd: PRope) =
|
||||
let topBlock = p.blocks.len - 1
|
||||
let topBlock = p.blocks.len-1
|
||||
# the block is merged into the parent block
|
||||
app(p.blocks[topBlock - 1].sections[cpsStmts], p.blocks[topBlock].blockBody)
|
||||
app(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
|
||||
setlen(p.blocks, topBlock)
|
||||
# this is done after the block is popped so $n is
|
||||
# properly indented when pretty printing is enabled
|
||||
|
|
@ -83,10 +88,13 @@ proc endBlock(p: BProc, blockEnd: PRope) =
|
|||
|
||||
proc endBlock(p: BProc) =
|
||||
let topBlock = p.blocks.len - 1
|
||||
let blockEnd = if p.blocks[topBlock].label != nil:
|
||||
var blockEnd = if p.blocks[topBlock].label != nil:
|
||||
rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
|
||||
else:
|
||||
~"}$n"
|
||||
let frameLen = p.blocks[topBlock].frameLen
|
||||
if frameLen > 0:
|
||||
blockEnd.appf("F.len-=$1;$n", frameLen.toRope)
|
||||
endBlock(p, blockEnd)
|
||||
|
||||
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
|
||||
|
|
@ -799,12 +807,9 @@ proc genPragma(p: BProc, n: PNode) =
|
|||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
case whichPragma(it)
|
||||
of wEmit:
|
||||
genEmit(p, it)
|
||||
of wBreakpoint:
|
||||
genBreakPoint(p, it)
|
||||
of wWatchpoint:
|
||||
genWatchpoint(p, it)
|
||||
of wEmit: genEmit(p, it)
|
||||
of wBreakpoint: genBreakPoint(p, it)
|
||||
of wWatchpoint: genWatchpoint(p, it)
|
||||
else: nil
|
||||
|
||||
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||
|
|
|
|||
0
compiler/ccgthreadvars.nim
Executable file → Normal file
0
compiler/ccgthreadvars.nim
Executable file → Normal file
|
|
@ -59,7 +59,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
|
|||
if typ == nil: return
|
||||
var p = c.p
|
||||
case typ.kind
|
||||
of tyGenericInst, tyGenericBody:
|
||||
of tyGenericInst, tyGenericBody, tyTypeDesc:
|
||||
genTraverseProc(c, accessor, lastSon(typ))
|
||||
of tyArrayConstr, tyArray:
|
||||
let arraySize = lengthOrd(typ.sons[0])
|
||||
|
|
@ -111,10 +111,11 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
|
|||
lineF(p, cpsInit, "a = ($1)p;$n", t)
|
||||
|
||||
c.p = p
|
||||
assert typ.kind != tyTypedesc
|
||||
if typ.kind == tySequence:
|
||||
genTraverseProcSeq(c, "a".toRope, typ)
|
||||
else:
|
||||
if skipTypes(typ.sons[0], abstractInst).kind in {tyArrayConstr, tyArray}:
|
||||
if skipTypes(typ.sons[0], typedescInst).kind in {tyArrayConstr, tyArray}:
|
||||
# C's arrays are broken beyond repair:
|
||||
genTraverseProc(c, "a".toRope, typ.sons[0])
|
||||
else:
|
||||
|
|
|
|||
20
compiler/ccgtypes.nim
Executable file → Normal file
20
compiler/ccgtypes.nim
Executable file → Normal file
|
|
@ -194,7 +194,7 @@ proc mapType(typ: PType): TCTypeKind =
|
|||
else: internalError("mapType")
|
||||
of tyRange: result = mapType(typ.sons[0])
|
||||
of tyPtr, tyVar, tyRef:
|
||||
var base = skipTypes(typ.sons[0], abstractInst)
|
||||
var base = skipTypes(typ.sons[0], typedescInst)
|
||||
case base.kind
|
||||
of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
|
||||
else: result = ctPtr
|
||||
|
|
@ -208,7 +208,7 @@ proc mapType(typ: PType): TCTypeKind =
|
|||
else: InternalError("mapType")
|
||||
|
||||
proc mapReturnType(typ: PType): TCTypeKind =
|
||||
if skipTypes(typ, abstractInst).kind == tyArray: result = ctPtr
|
||||
if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
|
||||
else: result = mapType(typ)
|
||||
|
||||
proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope
|
||||
|
|
@ -224,10 +224,10 @@ proc isInvalidReturnType(rettype: PType): bool =
|
|||
else:
|
||||
case mapType(rettype)
|
||||
of ctArray:
|
||||
result = not (skipTypes(rettype, abstractInst).kind in
|
||||
result = not (skipTypes(rettype, typedescInst).kind in
|
||||
{tyVar, tyRef, tyPtr})
|
||||
of ctStruct:
|
||||
result = needsComplexAssignment(skipTypes(rettype, abstractInst))
|
||||
result = needsComplexAssignment(skipTypes(rettype, typedescInst))
|
||||
else: result = false
|
||||
|
||||
const
|
||||
|
|
@ -253,7 +253,7 @@ proc getGlobalTempName(): PRope =
|
|||
result = rfmt(nil, "TMP$1", toRope(backendId()))
|
||||
|
||||
proc ccgIntroducedPtr(s: PSym): bool =
|
||||
var pt = skipTypes(s.typ, abstractInst)
|
||||
var pt = skipTypes(s.typ, typedescInst)
|
||||
assert skResult != s.kind
|
||||
if tfByRef in pt.flags: return true
|
||||
elif tfByCopy in pt.flags: return false
|
||||
|
|
@ -280,13 +280,13 @@ proc fillResult(param: PSym) =
|
|||
proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
|
||||
when false:
|
||||
if t.Kind in {tyRef, tyPtr, tyVar}:
|
||||
var b = skipTypes(t.sons[0], abstractInst)
|
||||
var b = skipTypes(t.sons[0], typedescInst)
|
||||
if b.kind == tySet and mapSetType(b) == ctArray:
|
||||
return getTypeDescAux(m, b, check)
|
||||
result = getTypeDescAux(m, t, check)
|
||||
|
||||
proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||
if param.typ.skipTypes({tyVar}).kind notin {tyArray, tyOpenArray}:
|
||||
if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray}:
|
||||
result = OnStack
|
||||
else:
|
||||
result = OnUnknown
|
||||
|
|
@ -572,7 +572,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
|||
assert(CacheGetType(m.typeCache, t) == nil)
|
||||
IdTablePut(m.typeCache, t, con(result, "*"))
|
||||
if not isImportedType(t):
|
||||
if skipTypes(t.sons[0], abstractInst).kind != tyEmpty:
|
||||
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
|
||||
const
|
||||
cppSeq = "struct $2 : #TGenericSeq {$n"
|
||||
cSeq = "struct $2 {$n" &
|
||||
|
|
@ -744,7 +744,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope =
|
|||
if objType.sym == nil:
|
||||
InternalError(d.info, "anonymous obj with discriminator")
|
||||
result = ropef("NimDT_$1_$2", [
|
||||
toRope(objType.sym.name.s), toRope(d.name.s)])
|
||||
toRope(objType.sym.name.s.mangle), toRope(d.name.s.mangle)])
|
||||
|
||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope =
|
||||
discard cgsym(m, "TNimNode")
|
||||
|
|
@ -915,7 +915,7 @@ include ccgtrav
|
|||
proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||
var t = getUniqueType(typ)
|
||||
result = ropef("NTI$1", [toRope(t.id)])
|
||||
let owner = typ.skipTypes(abstractPtrs).owner.getModule
|
||||
let owner = typ.skipTypes(typedescPtrs).owner.getModule
|
||||
if owner != m.module:
|
||||
# make sure the type info is created in the owner module
|
||||
discard genTypeInfo(owner.bmod, typ)
|
||||
|
|
|
|||
4
compiler/ccgutils.nim
Executable file → Normal file
4
compiler/ccgutils.nim
Executable file → Normal file
|
|
@ -80,13 +80,13 @@ proc GetUniqueType*(key: PType): PType =
|
|||
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
||||
# produced instead of ``NI``.
|
||||
result = key
|
||||
of tyEmpty, tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString,
|
||||
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
|
||||
tyCString, tyNone, tyBigNum:
|
||||
result = gCanonicalTypes[k]
|
||||
if result == nil:
|
||||
gCanonicalTypes[k] = key
|
||||
result = key
|
||||
of tyGenericParam, tyTypeClass:
|
||||
of tyGenericParam, tyTypeClass, tyTypeDesc:
|
||||
InternalError("GetUniqueType")
|
||||
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
||||
result = GetUniqueType(lastSon(key))
|
||||
|
|
|
|||
37
compiler/cgen.nim
Executable file → Normal file
37
compiler/cgen.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -276,11 +276,11 @@ proc genLineDir(p: BProc, t: PNode) =
|
|||
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
linefmt(p, cpsStmts, "#endb($1);$n", toRope(line))
|
||||
linefmt(p, cpsStmts, "#endb($1, $2);$n",
|
||||
line.toRope, makeCString(toFilename(t.info)))
|
||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||
{optLineTrace, optStackTrace}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
|
||||
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
||||
line.toRope, t.info.quotedFilename)
|
||||
|
||||
|
|
@ -470,12 +470,13 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
|||
# XXX work around a bug: No type information for open arrays possible:
|
||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||
var a = con("&", s.loc.r)
|
||||
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
|
||||
if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r
|
||||
lineF(p, cpsInit,
|
||||
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
|
||||
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
|
||||
[p.maxFrameLen.toRope, makeCString(normalize(s.name.s)), a,
|
||||
genTypeInfo(p.module, s.loc.t)])
|
||||
inc(p.frameLen)
|
||||
inc(p.maxFrameLen)
|
||||
inc p.blocks[p.blocks.len-1].frameLen
|
||||
|
||||
proc assignLocalVar(p: BProc, s: PSym) =
|
||||
#assert(s.loc.k == locNone) // not yet assigned
|
||||
|
|
@ -488,7 +489,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
|||
if sfRegister in s.flags: app(decl, " register")
|
||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||
# app(decl, " GC_GUARD")
|
||||
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
|
||||
if sfVolatile in s.flags or p.nestedTryStmts.len > 0:
|
||||
app(decl, " volatile")
|
||||
appf(decl, " $1;$n", [s.loc.r])
|
||||
line(p, cpsLocals, decl)
|
||||
|
|
@ -574,6 +575,8 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
|||
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
||||
var s: TStringSeq = @[]
|
||||
libCandidates(lib.path.strVal, s)
|
||||
if gVerbosity >= 2:
|
||||
MsgWriteln("Dependency: " & lib.path.strVal)
|
||||
var loadlib: PRope = nil
|
||||
for i in countup(0, high(s)):
|
||||
inc(m.labels)
|
||||
|
|
@ -693,10 +696,11 @@ proc retIsNotVoid(s: PSym): bool =
|
|||
|
||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||
discard cgsym(p.module, "pushFrame")
|
||||
if p.frameLen > 0:
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "TVarSlot")
|
||||
result = rfmt(nil, "\tnimfrs($1, $2, $3)$N",
|
||||
procname, filename, p.frameLen.toRope)
|
||||
result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
|
||||
procname, filename, p.maxFrameLen.toRope,
|
||||
p.blocks[0].frameLen.toRope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
|
||||
|
||||
|
|
@ -890,6 +894,12 @@ proc getFileHeader(cfilenoext: string): PRope =
|
|||
result = getCopyright(cfilenoext)
|
||||
addIntTypes(result)
|
||||
|
||||
proc genFilenames(m: BModule): PRope =
|
||||
discard cgsym(m, "dbgRegisterFilename")
|
||||
result = nil
|
||||
for i in 0.. <fileInfos.len:
|
||||
result.appf("dbgRegisterFilename($1);$n", fileInfos[i].projPath.makeCString)
|
||||
|
||||
proc genMainProc(m: BModule) =
|
||||
const
|
||||
CommonMainBody =
|
||||
|
|
@ -948,6 +958,8 @@ proc genMainProc(m: BModule) =
|
|||
nimMain = PosixNimMain
|
||||
otherMain = PosixCMain
|
||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||
if optEndb in gOptions:
|
||||
gBreakpoints.app(m.genFilenames)
|
||||
|
||||
let initStackBottomCall = if emulatedThreadVars() or
|
||||
platform.targetOS == osStandalone: "".toRope
|
||||
|
|
@ -1244,7 +1256,7 @@ proc updateCachedModule(m: BModule) =
|
|||
let cfile = getCFile(m)
|
||||
let cfilenoext = changeFileExt(cfile, "")
|
||||
|
||||
if mergeRequired(m):
|
||||
if mergeRequired(m) and sfMainModule notin m.module.flags:
|
||||
mergeFiles(cfile, m)
|
||||
genInitCode(m)
|
||||
finishTypeDescriptions(m)
|
||||
|
|
@ -1254,8 +1266,7 @@ proc updateCachedModule(m: BModule) =
|
|||
|
||||
addFileToLink(cfilenoext)
|
||||
|
||||
proc cgenCaasUpdate* =
|
||||
# XXX(zah): clean-up the fromCache mess
|
||||
proc updateCachedModules* =
|
||||
for m in cgenModules():
|
||||
if m.fromCache: m.updateCachedModule
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,10 @@ type
|
|||
id*: int # the ID of the label; positive means that it
|
||||
label*: PRope # generated text for the label
|
||||
# nil if label is not used
|
||||
nestedTryStmts*: int # how many try statements is it nested into
|
||||
sections*: TCProcSections # the code beloging
|
||||
isLoop*: bool # whether block is a loop
|
||||
nestedTryStmts*: int16 # how many try statements is it nested into
|
||||
frameLen*: int16
|
||||
|
||||
TCProc{.final.} = object # represents C proc that is currently generated
|
||||
prc*: PSym # the Nimrod proc that this C proc belongs to
|
||||
|
|
@ -74,9 +75,7 @@ type
|
|||
options*: TOptions # options that should be used for code
|
||||
# generation; this is the same as prc.options
|
||||
# unless prc == nil
|
||||
frameLen*: int # current length of frame descriptor
|
||||
sendClosure*: PType # closure record type that we pass
|
||||
receiveClosure*: PType # closure record type that we get
|
||||
maxFrameLen*: int # max length of frame descriptor
|
||||
module*: BModule # used to prevent excessive parameter passing
|
||||
withinLoop*: int # > 0 if we are within a loop
|
||||
gcFrameId*: natural # for the GC stack marking
|
||||
|
|
|
|||
4
compiler/cgmeth.nim
Executable file → Normal file
4
compiler/cgmeth.nim
Executable file → Normal file
|
|
@ -108,8 +108,8 @@ proc methodDef*(s: PSym, fromCache: bool) =
|
|||
|
||||
proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||
# returns true iff the position is relevant
|
||||
var t = methods[0].typ.sons[col]
|
||||
if skipTypes(t, skipPtrs).kind == tyObject:
|
||||
var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
|
||||
if t.kind == tyObject:
|
||||
for i in countup(1, high(methods)):
|
||||
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
|
||||
if not SameType(t2, t):
|
||||
|
|
|
|||
0
compiler/charsets.nim
Executable file → Normal file
0
compiler/charsets.nim
Executable file → Normal file
35
compiler/commands.nim
Executable file → Normal file
35
compiler/commands.nim
Executable file → Normal file
|
|
@ -65,8 +65,13 @@ proc writeCommandLineUsage() =
|
|||
MsgWriteln(getCommandLineDesc())
|
||||
helpWritten = true
|
||||
|
||||
proc addPrefix(switch: string): string =
|
||||
if len(switch) == 1: result = "-" & switch
|
||||
else: result = "--" & switch
|
||||
|
||||
proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
|
||||
LocalError(info, errInvalidCmdLineOption, switch)
|
||||
if switch == " ": LocalError(info, errInvalidCmdLineOption, "-")
|
||||
else: LocalError(info, errInvalidCmdLineOption, addPrefix(switch))
|
||||
|
||||
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
|
||||
info: TLineInfo) =
|
||||
|
|
@ -98,10 +103,10 @@ proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass,
|
|||
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
||||
|
||||
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
if arg == "": LocalError(info, errCmdLineArgExpected, switch)
|
||||
if arg == "": LocalError(info, errCmdLineArgExpected, addPrefix(switch))
|
||||
|
||||
proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
if arg != "": LocalError(info, errCmdLineNoArgExpected, switch)
|
||||
if arg != "": LocalError(info, errCmdLineNoArgExpected, addPrefix(switch))
|
||||
|
||||
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
||||
info: TLineInfo) =
|
||||
|
|
@ -143,6 +148,7 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
|||
of "refc": result = gSelectedGC == gcRefc
|
||||
of "v2": result = gSelectedGC == gcV2
|
||||
of "markandsweep": result = gSelectedGC == gcMarkAndSweep
|
||||
of "generational": result = gSelectedGC == gcGenerational
|
||||
of "none": result = gSelectedGC == gcNone
|
||||
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
of "opt":
|
||||
|
|
@ -190,8 +196,13 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
|||
of "patterns": result = contains(gOptions, optPatterns)
|
||||
else: InvalidCmdLineOption(passCmd1, switch, info)
|
||||
|
||||
proc processPath(path: string): string =
|
||||
result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath,
|
||||
proc processPath(path: string, notRelativeToProj = false): string =
|
||||
let p = if notRelativeToProj or os.isAbsolute(path) or
|
||||
'$' in path or path[0] == '.':
|
||||
path
|
||||
else:
|
||||
options.gProjectPath / path
|
||||
result = UnixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
|
||||
"home", removeTrailingDirSep(os.getHomeDir()),
|
||||
"projectname", options.gProjectName,
|
||||
"projectpath", options.gProjectPath])
|
||||
|
|
@ -206,6 +217,11 @@ proc track(arg: string, info: TLineInfo) =
|
|||
LocalError(info, errInvalidNumber, a[2])
|
||||
msgs.addCheckpoint(newLineInfo(a[0], line, column))
|
||||
|
||||
proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
if pass in {passCmd2, passPP}:
|
||||
expectArg(switch, arg, pass, info)
|
||||
options.inclDynlibOverride(arg)
|
||||
|
||||
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
var
|
||||
theOS: TSystemOS
|
||||
|
|
@ -218,7 +234,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
|||
of "babelpath":
|
||||
if pass in {passCmd2, passPP}:
|
||||
expectArg(switch, arg, pass, info)
|
||||
let path = processPath(arg)
|
||||
let path = processPath(arg, notRelativeToProj=true)
|
||||
babelpath(path, info)
|
||||
of "excludepath":
|
||||
expectArg(switch, arg, pass, info)
|
||||
|
|
@ -280,6 +296,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
|||
of "markandsweep":
|
||||
gSelectedGC = gcMarkAndSweep
|
||||
defineSymbol("gcmarkandsweep")
|
||||
of "generational":
|
||||
gSelectedGC = gcGenerational
|
||||
defineSymbol("gcgenerational")
|
||||
of "none":
|
||||
gSelectedGC = gcNone
|
||||
defineSymbol("nogc")
|
||||
|
|
@ -439,7 +458,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
|||
incl(gGlobalOptions, optGenScript)
|
||||
of "lib":
|
||||
expectArg(switch, arg, pass, info)
|
||||
libpath = processPath(arg)
|
||||
libpath = processPath(arg, notRelativeToProj=true)
|
||||
of "putenv":
|
||||
expectArg(switch, arg, pass, info)
|
||||
splitSwitch(arg, key, val, pass, info)
|
||||
|
|
@ -471,6 +490,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
|||
of "listfullpaths":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
gListFullPaths = true
|
||||
of "dynliboverride":
|
||||
dynlibOverride(switch, arg, pass, info)
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||
else: InvalidCmdLineOption(pass, switch, info)
|
||||
|
|
|
|||
8
compiler/condsyms.nim
Executable file → Normal file
8
compiler/condsyms.nim
Executable file → Normal file
|
|
@ -10,7 +10,7 @@
|
|||
# This module handles the conditional symbols.
|
||||
|
||||
import
|
||||
ast, astalgo, msgs, hashes, platform, strutils, idents
|
||||
ast, astalgo, hashes, platform, strutils, idents
|
||||
|
||||
var gSymbols*: TStrTable
|
||||
|
||||
|
|
@ -35,14 +35,12 @@ proc isDefined*(symbol: PIdent): bool =
|
|||
proc isDefined*(symbol: string): bool =
|
||||
result = isDefined(getIdent(symbol))
|
||||
|
||||
proc ListSymbols*() =
|
||||
iterator definedSymbolNames*: string =
|
||||
var it: TTabIter
|
||||
var s = InitTabIter(it, gSymbols)
|
||||
OutWriteln("-- List of currently defined symbols --")
|
||||
while s != nil:
|
||||
if s.position == 1: OutWriteln(s.name.s)
|
||||
if s.position == 1: yield s.name.s
|
||||
s = nextIter(it, gSymbols)
|
||||
OutWriteln("-- End of list --")
|
||||
|
||||
proc countDefinedSymbols*(): int =
|
||||
var it: TTabIter
|
||||
|
|
|
|||
0
compiler/crc.nim
Executable file → Normal file
0
compiler/crc.nim
Executable file → Normal file
0
compiler/depends.nim
Executable file → Normal file
0
compiler/depends.nim
Executable file → Normal file
0
compiler/docgen.nim
Executable file → Normal file
0
compiler/docgen.nim
Executable file → Normal file
|
|
@ -142,10 +142,10 @@ proc getField(n: PNode; position: int): PSym =
|
|||
else: nil
|
||||
|
||||
proc packObject(x: PNode, typ: PType, res: pointer) =
|
||||
InternalAssert x.kind == nkPar
|
||||
InternalAssert x.kind in {nkObjConstr, nkPar}
|
||||
# compute the field's offsets:
|
||||
discard typ.getSize
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
internalAssert it.sons[0].kind == nkSym
|
||||
|
|
@ -257,11 +257,11 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
|
|||
unpackObjectAdd(x, typ.n, result)
|
||||
else:
|
||||
result = n
|
||||
if result.kind != nkPar:
|
||||
if result.kind notin {nkObjConstr, nkPar}:
|
||||
GlobalError(n.info, "cannot map value from FFI")
|
||||
if typ.n.isNil:
|
||||
GlobalError(n.info, "cannot unpack unnamed tuple")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
for i in countup(ord(n.kind == nkObjConstr), sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
internalAssert it.sons[0].kind == nkSym
|
||||
|
|
|
|||
111
compiler/evals.nim
Executable file → Normal file
111
compiler/evals.nim
Executable file → Normal file
|
|
@ -249,7 +249,7 @@ proc getNullValueAux(obj: PNode, result: PNode) =
|
|||
else: InternalError(result.info, "getNullValueAux")
|
||||
|
||||
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
var t = skipTypes(typ, abstractRange)
|
||||
var t = skipTypes(typ, abstractRange-{tyTypeDesc})
|
||||
result = emptyNode
|
||||
case t.kind
|
||||
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
||||
|
|
@ -274,6 +274,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
|||
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||
addSon(result, getNullValue(elemType(t), info))
|
||||
of tyTuple:
|
||||
# XXX nkExprColonExpr is out of fashion ...
|
||||
result = newNodeIT(nkPar, info, t)
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
||||
|
|
@ -295,6 +296,8 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
|||
#assert(a.sons[0].kind == nkSym) can happen for transformed vars
|
||||
if a.sons[2].kind != nkEmpty:
|
||||
result = evalAux(c, a.sons[2], {})
|
||||
if result.kind in {nkType..nkNilLit}:
|
||||
result = result.copyNode
|
||||
if isSpecial(result): return
|
||||
else:
|
||||
result = getNullValue(a.sons[0].typ, a.sons[0].info)
|
||||
|
|
@ -451,22 +454,28 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
if isSpecial(result): return
|
||||
var x = result
|
||||
if x.kind != nkPar: return raiseCannotEval(c, n.info)
|
||||
# this is performance critical:
|
||||
var field = n.sons[1].sym
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
#InternalError(it.info, "evalFieldAccess")
|
||||
if it.sons[0].sym.name.id == field.name.id:
|
||||
result = x.sons[i].sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
stackTrace(c, n, errFieldXNotFound, field.name.s)
|
||||
result = emptyNode
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
when false:
|
||||
var field = n.sons[1].sym
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
#InternalError(it.info, "evalFieldAccess")
|
||||
if it.sons[0].sym.name.id == field.name.id:
|
||||
result = x.sons[i].sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
stackTrace(c, n, errFieldXNotFound, field.name.s)
|
||||
result = emptyNode
|
||||
|
||||
proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||
var a = n.sons[0]
|
||||
|
|
@ -896,13 +905,13 @@ proc evalParseExpr(c: PEvalContext, n: PNode): PNode =
|
|||
if sonsLen(ast) != 1:
|
||||
GlobalError(code.info, errExprExpected, "multiple statements")
|
||||
result = ast.sons[0]
|
||||
result.typ = newType(tyExpr, c.module)
|
||||
#result.typ = newType(tyExpr, c.module)
|
||||
|
||||
proc evalParseStmt(c: PEvalContext, n: PNode): PNode =
|
||||
var code = evalAux(c, n.sons[1], {})
|
||||
result = parseString(code.getStrValue, code.info.toFilename,
|
||||
code.stringStartingLine)
|
||||
result.typ = newType(tyStmt, c.module)
|
||||
#result.typ = newType(tyStmt, c.module)
|
||||
|
||||
proc evalTypeTrait*(n: PNode, context: PSym): PNode =
|
||||
## XXX: This should be pretty much guaranteed to be true
|
||||
|
|
@ -994,9 +1003,9 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
|||
case expandedSym.kind
|
||||
of skTemplate:
|
||||
let genSymOwner = if c.tos != nil and c.tos.prc != nil:
|
||||
c.tos.prc
|
||||
else:
|
||||
c.module
|
||||
c.tos.prc
|
||||
else:
|
||||
c.module
|
||||
result = evalTemplate(macroCall, expandedSym, genSymOwner)
|
||||
of skMacro:
|
||||
# At this point macroCall.sons[0] is nkSym node.
|
||||
|
|
@ -1090,7 +1099,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
|||
result = evalAux(c, n.sons[2], {efLValue})
|
||||
if isSpecial(result): return
|
||||
addSon(a, result)
|
||||
result = emptyNode
|
||||
result = a
|
||||
of mNAddMultiple:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
|
|
@ -1098,7 +1107,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
|||
result = evalAux(c, n.sons[2], {efLValue})
|
||||
if isSpecial(result): return
|
||||
for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
|
||||
result = emptyNode
|
||||
result = a
|
||||
of mNDel:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
|
|
@ -1341,13 +1350,21 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
result = emptyNode
|
||||
dec(gNestedEvals)
|
||||
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
|
||||
case n.kind # atoms:
|
||||
of nkEmpty: result = n
|
||||
case n.kind
|
||||
of nkSym: result = evalSym(c, n, flags)
|
||||
of nkType..nkNilLit: result = copyNode(n) # end of atoms
|
||||
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkInfix,
|
||||
nkPrefix, nkPostfix:
|
||||
of nkType..nkNilLit:
|
||||
# nkStrLit is VERY common in the traces, so we should avoid
|
||||
# the 'copyNode' here.
|
||||
result = n #.copyNode
|
||||
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
|
||||
of nkCommand..nkHiddenCallConv:
|
||||
result = evalMagicOrCall(c, n)
|
||||
of nkDotExpr: result = evalFieldAccess(c, n, flags)
|
||||
of nkBracketExpr:
|
||||
result = evalArrayAccess(c, n, flags)
|
||||
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
|
||||
of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
|
||||
of nkCurly, nkBracket, nkRange:
|
||||
# flags need to be passed here for mNAddMultiple :-(
|
||||
# XXX this is not correct in every case!
|
||||
|
|
@ -1370,12 +1387,23 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
if isSpecial(result): return
|
||||
a.sons[i] = result
|
||||
result = a
|
||||
of nkBracketExpr: result = evalArrayAccess(c, n, flags)
|
||||
of nkDotExpr: result = evalFieldAccess(c, n, flags)
|
||||
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
|
||||
of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
|
||||
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
|
||||
of nkObjConstr:
|
||||
let t = skipTypes(n.typ, abstractInst)
|
||||
var a: PNode
|
||||
if t.kind == tyRef:
|
||||
result = newNodeIT(nkRefTy, n.info, t)
|
||||
a = getNullValue(t.sons[0], n.info)
|
||||
addSon(result, a)
|
||||
else:
|
||||
a = getNullValue(t, n.info)
|
||||
result = a
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
let value = evalAux(c, it.sons[1], flags)
|
||||
if isSpecial(value): return value
|
||||
a.sons[it.sons[0].sym.position] = value
|
||||
else: return raiseCannotEval(c, n.info)
|
||||
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
||||
of nkWhileStmt: result = evalWhile(c, n)
|
||||
of nkCaseStmt: result = evalCase(c, n)
|
||||
|
|
@ -1414,6 +1442,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
result = raiseCannotEval(c, n.info)
|
||||
of nkRefTy:
|
||||
result = evalAux(c, n.sons[0], flags)
|
||||
of nkEmpty:
|
||||
# nkEmpty occurs once in each trace that I looked at
|
||||
result = n
|
||||
else: InternalError(n.info, "evalAux: " & $n.kind)
|
||||
if result == nil:
|
||||
InternalError(n.info, "evalAux: returned nil " & $n.kind)
|
||||
|
|
@ -1464,11 +1495,13 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
|||
c.callsite = nOrig
|
||||
var s = newStackFrame()
|
||||
s.call = n
|
||||
setlen(s.params, n.len)
|
||||
var L = n.safeLen
|
||||
if L == 0: L = 1
|
||||
setlen(s.params, L)
|
||||
# return value:
|
||||
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
||||
# setup parameters:
|
||||
for i in 1 .. < n.len: s.params[i] = setupMacroParam(n.sons[i])
|
||||
for i in 1 .. < L: s.params[i] = setupMacroParam(n.sons[i])
|
||||
pushStackFrame(c, s)
|
||||
discard eval(c, sym.getBody)
|
||||
result = s.params[0]
|
||||
|
|
@ -1483,7 +1516,13 @@ proc myOpen(module: PSym): PPassContext =
|
|||
pushStackFrame(c, newStackFrame())
|
||||
result = c
|
||||
|
||||
var oldErrorCount: int
|
||||
|
||||
proc myProcess(c: PPassContext, n: PNode): PNode =
|
||||
# don't eval errornous code:
|
||||
if oldErrorCount != msgs.gErrorCounter:
|
||||
oldErrorCount = msgs.gErrorCounter
|
||||
return n
|
||||
result = eval(PEvalContext(c), n)
|
||||
|
||||
const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
|
||||
|
|
|
|||
64
compiler/extccomp.nim
Executable file → Normal file
64
compiler/extccomp.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -391,33 +391,6 @@ proc resetCompilationLists* =
|
|||
initLinkedList(externalToCompile)
|
||||
initLinkedList(toLink)
|
||||
|
||||
proc footprint(filename: string): TCrc32 =
|
||||
result = crcFromFile(filename) ><
|
||||
platform.OS[targetOS].name ><
|
||||
platform.CPU[targetCPU].name ><
|
||||
extccomp.CC[extccomp.ccompiler].name
|
||||
|
||||
proc externalFileChanged(filename: string): bool =
|
||||
var crcFile = toGeneratedFile(filename, "crc")
|
||||
var currentCrc = int(footprint(filename))
|
||||
var f: TFile
|
||||
if open(f, crcFile, fmRead):
|
||||
var line = newStringOfCap(40)
|
||||
if not f.readLine(line): line = "0"
|
||||
close(f)
|
||||
var oldCrc = parseInt(line)
|
||||
result = oldCrc != currentCrc
|
||||
else:
|
||||
result = true
|
||||
if result:
|
||||
if open(f, crcFile, fmWrite):
|
||||
f.writeln($currentCrc)
|
||||
close(f)
|
||||
|
||||
proc addExternalFileToCompile*(filename: string) =
|
||||
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
||||
appendStr(externalToCompile, filename)
|
||||
|
||||
proc addFileToLink*(filename: string) =
|
||||
prependStr(toLink, filename)
|
||||
# BUGFIX: was ``appendStr``
|
||||
|
|
@ -536,6 +509,34 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
|||
"nimrod", quoteIfContainsWhite(getPrefixDir()),
|
||||
"lib", quoteIfContainsWhite(libpath)])
|
||||
|
||||
proc footprint(filename: string): TCrc32 =
|
||||
result = crcFromFile(filename) ><
|
||||
platform.OS[targetOS].name ><
|
||||
platform.CPU[targetCPU].name ><
|
||||
extccomp.CC[extccomp.ccompiler].name ><
|
||||
getCompileCFileCmd(filename, true)
|
||||
|
||||
proc externalFileChanged(filename: string): bool =
|
||||
var crcFile = toGeneratedFile(filename, "crc")
|
||||
var currentCrc = int(footprint(filename))
|
||||
var f: TFile
|
||||
if open(f, crcFile, fmRead):
|
||||
var line = newStringOfCap(40)
|
||||
if not f.readLine(line): line = "0"
|
||||
close(f)
|
||||
var oldCrc = parseInt(line)
|
||||
result = oldCrc != currentCrc
|
||||
else:
|
||||
result = true
|
||||
if result:
|
||||
if open(f, crcFile, fmWrite):
|
||||
f.writeln($currentCrc)
|
||||
close(f)
|
||||
|
||||
proc addExternalFileToCompile*(filename: string) =
|
||||
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
||||
appendStr(externalToCompile, filename)
|
||||
|
||||
proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||
isExternal: bool) =
|
||||
var it = PStrEntry(list.head)
|
||||
|
|
@ -572,7 +573,12 @@ proc CallCCompiler*(projectfile: string) =
|
|||
else:
|
||||
res = execProcesses(cmds, {poUseShell, poParentStreams},
|
||||
gNumberOfProcessors)
|
||||
if res != 0: rawMessage(errExecutionOfProgramFailed, [])
|
||||
if res != 0:
|
||||
if gNumberOfProcessors <= 1:
|
||||
rawMessage(errExecutionOfProgramFailed, [])
|
||||
else:
|
||||
rawMessage(errGenerated, " execution of an external program failed; " &
|
||||
"rerun with --parallelBuild:1 to see the error message")
|
||||
if optNoLinking notin gGlobalOptions:
|
||||
# call the linker:
|
||||
var it = PStrEntry(toLink.head)
|
||||
|
|
|
|||
6
compiler/filter_tmpl.nim
Executable file → Normal file
6
compiler/filter_tmpl.nim
Executable file → Normal file
|
|
@ -98,6 +98,12 @@ proc parseLine(p: var TTmplParser) =
|
|||
of wElif, wOf, wElse, wExcept, wFinally:
|
||||
LLStreamWrite(p.outp, repeatChar(p.indent - 2))
|
||||
LLStreamWrite(p.outp, substr(p.x, d))
|
||||
of wLet, wVar, wConst, wType:
|
||||
LLStreamWrite(p.outp, repeatChar(p.indent))
|
||||
LLStreamWrite(p.outp, substr(p.x, d))
|
||||
if not p.x.contains({':', '='}):
|
||||
# no inline element --> treat as block:
|
||||
inc(p.indent, 2)
|
||||
else:
|
||||
LLStreamWrite(p.outp, repeatChar(p.indent))
|
||||
LLStreamWrite(p.outp, substr(p.x, d))
|
||||
|
|
|
|||
0
compiler/filters.nim
Executable file → Normal file
0
compiler/filters.nim
Executable file → Normal file
0
compiler/idents.nim
Executable file → Normal file
0
compiler/idents.nim
Executable file → Normal file
0
compiler/importer.nim
Executable file → Normal file
0
compiler/importer.nim
Executable file → Normal file
98
compiler/ecmasgen.nim → compiler/jsgen.nim
Executable file → Normal file
98
compiler/ecmasgen.nim → compiler/jsgen.nim
Executable file → Normal file
|
|
@ -20,22 +20,22 @@ import
|
|||
# implementation
|
||||
|
||||
type
|
||||
TEcmasGen = object of TPassContext
|
||||
TJSGen = object of TPassContext
|
||||
module: PSym
|
||||
|
||||
BModule = ref TEcmasGen
|
||||
TEcmasTypeKind = enum # necessary JS "types"
|
||||
BModule = ref TJSGen
|
||||
TJSTypeKind = enum # necessary JS "types"
|
||||
etyNone, # no type
|
||||
etyNull, # null type
|
||||
etyProc, # proc type
|
||||
etyBool, # bool type
|
||||
etyInt, # Ecmascript's int
|
||||
etyFloat, # Ecmascript's float
|
||||
etyString, # Ecmascript's string
|
||||
etyObject, # Ecmascript's reference to an object
|
||||
etyInt, # JavaScript's int
|
||||
etyFloat, # JavaScript's float
|
||||
etyString, # JavaScript's string
|
||||
etyObject, # JavaScript's reference to an object
|
||||
etyBaseIndex # base + index needed
|
||||
TCompRes{.final.} = object
|
||||
kind: TEcmasTypeKind
|
||||
kind: TJSTypeKind
|
||||
com: PRope # computation part
|
||||
# address if this is a (address, index)-tuple
|
||||
res: PRope # result part; index if this is an
|
||||
|
|
@ -44,7 +44,6 @@ type
|
|||
TBlock{.final.} = object
|
||||
id: int # the ID of the label; positive means that it
|
||||
# has been used (i.e. the label should be emitted)
|
||||
nestedTryStmts: int # how many try statements is it nested into
|
||||
isLoop: bool # whether it's a 'block' or 'while'
|
||||
|
||||
TGlobals{.final.} = object
|
||||
|
|
@ -57,12 +56,11 @@ type
|
|||
TProc{.final.} = object
|
||||
procDef: PNode
|
||||
prc: PSym
|
||||
data: PRope
|
||||
locals: PRope
|
||||
options: TOptions
|
||||
module: BModule
|
||||
g: PGlobals
|
||||
BeforeRetNeeded: bool
|
||||
nestedTryStmts: int
|
||||
unique: int
|
||||
blocks: seq[TBlock]
|
||||
|
||||
|
|
@ -91,7 +89,7 @@ const
|
|||
MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray,
|
||||
tySet, tyVar, tyRef, tyPtr, tyBigNum, tyVarargs}
|
||||
|
||||
proc mapType(typ: PType): TEcmasTypeKind =
|
||||
proc mapType(typ: PType): TJSTypeKind =
|
||||
var t = skipTypes(typ, abstractInst)
|
||||
case t.kind
|
||||
of tyVar, tyRef, tyPtr:
|
||||
|
|
@ -485,10 +483,6 @@ proc genLineDir(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
||||
appf(r.com, "F.line = $1;$n", [toRope(line)])
|
||||
|
||||
proc finishTryStmt(p: var TProc, r: var TCompRes, howMany: int) =
|
||||
for i in countup(1, howMany):
|
||||
app(r.com, "excHandler = excHandler.prev;" & tnl)
|
||||
|
||||
proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
cond, stmt: TCompRes
|
||||
|
|
@ -498,7 +492,6 @@ proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
length = len(p.blocks)
|
||||
setlen(p.blocks, length + 1)
|
||||
p.blocks[length].id = - p.unique
|
||||
p.blocks[length].nestedTryStmts = p.nestedTryStmts
|
||||
p.blocks[length].isLoop = true
|
||||
labl = p.unique
|
||||
gen(p, n.sons[0], cond)
|
||||
|
|
@ -543,7 +536,6 @@ proc genTryStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
if optStackTrace in p.Options: app(r.com, "framePtr = F;" & tnl)
|
||||
app(r.com, "try {" & tnl)
|
||||
length = sonsLen(n)
|
||||
inc(p.nestedTryStmts)
|
||||
genStmt(p, n.sons[0], a)
|
||||
app(r.com, mergeStmt(a))
|
||||
i = 1
|
||||
|
|
@ -571,8 +563,6 @@ proc genTryStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
appf(epart, "$1}$n", [mergeStmt(a)])
|
||||
inc(i)
|
||||
if epart != nil: appf(r.com, "} catch (EXC) {$n$1", [epart])
|
||||
finishTryStmt(p, r, p.nestedTryStmts)
|
||||
dec(p.nestedTryStmts)
|
||||
app(r.com, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
|
||||
if (i < length) and (n.sons[i].kind == nkFinally):
|
||||
genStmt(p, n.sons[i].sons[0], a)
|
||||
|
|
@ -605,8 +595,8 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
if cond.com != nil: appf(r.com, "$1;$n", [cond.com])
|
||||
stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString
|
||||
if stringSwitch:
|
||||
useMagic(p, "toEcmaStr")
|
||||
appf(r.com, "switch (toEcmaStr($1)) {$n", [cond.res])
|
||||
useMagic(p, "toJSStr")
|
||||
appf(r.com, "switch (toJSStr($1)) {$n", [cond.res])
|
||||
else:
|
||||
appf(r.com, "switch ($1) {$n", [cond.res])
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
|
|
@ -619,17 +609,17 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
v = copyNode(e.sons[0])
|
||||
while (v.intVal <= e.sons[1].intVal):
|
||||
gen(p, v, cond)
|
||||
if cond.com != nil: internalError(v.info, "ecmasgen.genCaseStmt")
|
||||
if cond.com != nil: internalError(v.info, "jsgen.genCaseStmt")
|
||||
appf(r.com, "case $1: ", [cond.res])
|
||||
Inc(v.intVal)
|
||||
else:
|
||||
gen(p, e, cond)
|
||||
if cond.com != nil: internalError(e.info, "ecmasgen.genCaseStmt")
|
||||
if cond.com != nil: internalError(e.info, "jsgen.genCaseStmt")
|
||||
if stringSwitch:
|
||||
case e.kind
|
||||
of nkStrLit..nkTripleStrLit: appf(r.com, "case $1: ",
|
||||
[makeJSString(e.strVal)])
|
||||
else: InternalError(e.info, "ecmasgen.genCaseStmt: 2")
|
||||
else: InternalError(e.info, "jsgen.genCaseStmt: 2")
|
||||
else:
|
||||
appf(r.com, "case $1: ", [cond.res])
|
||||
genStmt(p, lastSon(it), stmt)
|
||||
|
|
@ -637,7 +627,7 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
of nkElse:
|
||||
genStmt(p, it.sons[0], stmt)
|
||||
appf(r.com, "default: $n$1break;$n", [mergeStmt(stmt)])
|
||||
else: internalError(it.info, "ecmasgen.genCaseStmt")
|
||||
else: internalError(it.info, "jsgen.genCaseStmt")
|
||||
appf(r.com, "}$n", [])
|
||||
|
||||
proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes)
|
||||
|
|
@ -655,7 +645,6 @@ proc genBlock(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
sym.loc.a = idx
|
||||
setlen(p.blocks, idx + 1)
|
||||
p.blocks[idx].id = - p.unique # negative because it isn't used yet
|
||||
p.blocks[idx].nestedTryStmts = p.nestedTryStmts
|
||||
labl = p.unique
|
||||
if n.kind == nkBlockExpr: genStmtListExpr(p, n.sons[1], r)
|
||||
else: genStmt(p, n.sons[1], r)
|
||||
|
|
@ -682,7 +671,6 @@ proc genBreakStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
if idx < 0 or not p.blocks[idx].isLoop:
|
||||
InternalError(n.info, "no loop to break")
|
||||
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
|
||||
finishTryStmt(p, r, p.nestedTryStmts - p.blocks[idx].nestedTryStmts)
|
||||
appf(r.com, "break L$1;$n", [toRope(p.blocks[idx].id)])
|
||||
|
||||
proc genAsmStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
|
|
@ -692,7 +680,7 @@ proc genAsmStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
case n.sons[i].Kind
|
||||
of nkStrLit..nkTripleStrLit: app(r.com, n.sons[i].strVal)
|
||||
of nkSym: app(r.com, mangleName(n.sons[i].sym))
|
||||
else: InternalError(n.sons[i].info, "ecmasgen: genAsmStmt()")
|
||||
else: InternalError(n.sons[i].info, "jsgen: genAsmStmt()")
|
||||
|
||||
proc genIfStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
|
|
@ -758,7 +746,7 @@ proc generateHeader(p: var TProc, typ: PType): PRope =
|
|||
|
||||
const
|
||||
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
|
||||
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkStringToCString,
|
||||
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString,
|
||||
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
|
||||
nkCommand, nkHiddenCallConv, nkCallStrLit}
|
||||
|
||||
|
|
@ -967,7 +955,8 @@ proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||
var r2: TCompRes
|
||||
genProc(p, s, r2)
|
||||
app(p.g.code, mergeStmt(r2))
|
||||
app(p.locals, mergeStmt(r2))
|
||||
#app(r.com, mergeStmt(r2))
|
||||
else:
|
||||
if s.loc.r == nil:
|
||||
InternalError(n.info, "symbol has no generated name: " & s.name.s)
|
||||
|
|
@ -1152,6 +1141,8 @@ proc genConstant(p: var TProc, c: PSym, r: var TCompRes) =
|
|||
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
||||
genLineDir(p, c.ast, r)
|
||||
genVarInit(p, c, c.ast, r)
|
||||
app(p.g.code, r.com)
|
||||
r.com = nil
|
||||
|
||||
when false:
|
||||
proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
|
|
@ -1276,7 +1267,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
binaryStmt(p, n, r, "", "$1 += $2")
|
||||
else:
|
||||
binaryStmt(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)")
|
||||
# XXX: make a copy of $2, because of ECMAScript's sucking semantics
|
||||
# XXX: make a copy of $2, because of Javascript's sucking semantics
|
||||
of mAppendSeqElem: binaryStmt(p, n, r, "", "$1.push($2)")
|
||||
of mConStrStr: genConStrStr(p, n, r)
|
||||
of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
|
||||
|
|
@ -1367,6 +1358,21 @@ proc genTupleConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
||||
r.res.app("}")
|
||||
|
||||
proc genObjConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
# XXX inheritance?
|
||||
var a: TCompRes
|
||||
r.res = toRope("{")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
if i > 0: app(r.res, ", ")
|
||||
var it = n.sons[i]
|
||||
InternalAssert it.kind == nkExprColonExpr
|
||||
gen(p, it.sons[1], a)
|
||||
r.com = mergeExpr(r.com, a.com)
|
||||
var f = it.sons[0].sym
|
||||
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||
appf(r.res, "$1: $2", [f.loc.r, a.res])
|
||||
r.res.app("}")
|
||||
|
||||
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
var dest = skipTypes(n.typ, abstractVarRange)
|
||||
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
|
|
@ -1395,8 +1401,8 @@ proc convStrToCStr(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
else:
|
||||
gen(p, n.sons[0], r)
|
||||
if r.res == nil: InternalError(n.info, "convStrToCStr")
|
||||
useMagic(p, "toEcmaStr")
|
||||
r.res = ropef("toEcmaStr($1)", [r.res])
|
||||
useMagic(p, "toJSStr")
|
||||
r.res = ropef("toJSStr($1)", [r.res])
|
||||
|
||||
proc convCStrToStr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
# we do an optimization here as this is likely to slow down
|
||||
|
|
@ -1418,7 +1424,6 @@ proc genReturnStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
|
||||
else:
|
||||
genLineDir(p, n, r)
|
||||
finishTryStmt(p, r, p.nestedTryStmts)
|
||||
app(r.com, "break BeforeRet;" & tnl)
|
||||
|
||||
proc genProcBody(p: var TProc, prc: PSym, r: TCompRes): PRope =
|
||||
|
|
@ -1451,16 +1456,17 @@ proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) =
|
|||
resultAsgn = nil
|
||||
name = mangleName(prc)
|
||||
header = generateHeader(p, prc.typ)
|
||||
if (prc.typ.sons[0] != nil) and sfPure notin prc.flags:
|
||||
if prc.typ.sons[0] != nil and sfPure notin prc.flags:
|
||||
resultSym = prc.ast.sons[resultPos].sym
|
||||
resultAsgn = ropef("var $1 = $2;$n", [mangleName(resultSym),
|
||||
resultAsgn = ropef("var $# = $#;$n", [mangleName(resultSym),
|
||||
createVar(p, resultSym.typ, isIndirect(resultSym))])
|
||||
gen(p, prc.ast.sons[resultPos], a)
|
||||
if a.com != nil: appf(returnStmt, "$1;$n", [a.com])
|
||||
returnStmt = ropef("return $1;$n", [a.res])
|
||||
returnStmt = ropef("return $#;$n", [a.res])
|
||||
genStmt(p, prc.getBody, r)
|
||||
r.com = ropef("function $1($2) {$n$3$4$5}$n",
|
||||
[name, header, resultAsgn, genProcBody(p, prc, r), returnStmt])
|
||||
r.com = ropef("function $#($#) {$n$#$#$#$#}$n",
|
||||
[name, header, p.locals, resultAsgn,
|
||||
genProcBody(p, prc, r), returnStmt])
|
||||
r.res = nil
|
||||
#if gVerbosity >= 3:
|
||||
# echo "END generated code for: " & prc.name.s
|
||||
|
|
@ -1513,8 +1519,9 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
of nkProcDef, nkMethodDef, nkConverterDef:
|
||||
var s = n.sons[namePos].sym
|
||||
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
||||
var r2: TCompRes
|
||||
genSym(p, n.sons[namePos], r2)
|
||||
#var r2: TCompRes
|
||||
genSym(p, n.sons[namePos], r)
|
||||
r.res = nil
|
||||
of nkGotoState, nkState:
|
||||
internalError(n.info, "first class iterators not implemented")
|
||||
else:
|
||||
|
|
@ -1566,6 +1573,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
|||
of nkCurly: genSetConstr(p, n, r)
|
||||
of nkBracket: genArrayConstr(p, n, r)
|
||||
of nkPar: genTupleConstr(p, n, r)
|
||||
of nkObjConstr: genObjConstr(p, n, r)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||
|
|
@ -1626,7 +1634,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
|||
if m.module == nil: InternalError(n.info, "myProcess")
|
||||
initProc(p, globals, m, nil, m.module.options)
|
||||
genModule(p, n, r)
|
||||
app(p.g.code, p.data)
|
||||
app(p.g.code, p.locals)
|
||||
app(p.g.code, mergeStmt(r))
|
||||
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
|
|
@ -1660,10 +1668,10 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
|||
discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
|
||||
|
||||
proc myOpenCached(s: PSym, rd: PRodReader): PPassContext =
|
||||
InternalError("symbol files are not possible with the Ecmas code generator")
|
||||
InternalError("symbol files are not possible with the JS code generator")
|
||||
result = nil
|
||||
|
||||
proc myOpen(s: PSym): PPassContext =
|
||||
result = newModule(s)
|
||||
|
||||
const ecmasgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose)
|
||||
const JSgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose)
|
||||
|
|
@ -322,7 +322,7 @@ proc generateThunk(prc: PNode, dest: PType): PNode =
|
|||
|
||||
# we cannot generate a proper thunk here for GC-safety reasons (see internal
|
||||
# documentation):
|
||||
if gCmd == cmdCompileToEcmaScript: return prc
|
||||
if gCmd == cmdCompileToJS: return prc
|
||||
result = newNodeIT(nkClosure, prc.info, dest)
|
||||
var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
|
||||
conv.add(emptyNode)
|
||||
|
|
@ -391,7 +391,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
|
|||
gatherVars(o, inner, body)
|
||||
# dummy closure param needed?
|
||||
if inner.closureParam == nil and n.sym.typ.callConv == ccClosure:
|
||||
assert tfCapturesEnv notin n.sym.typ.flags
|
||||
#assert tfCapturesEnv notin n.sym.typ.flags
|
||||
dummyClosureParam(o, inner)
|
||||
# only transform if it really needs a closure:
|
||||
if inner.closureParam != nil:
|
||||
|
|
@ -443,10 +443,15 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
|
|||
for i in countup(0, sonsLen(n) - 1):
|
||||
searchForInnerProcs(o, n.sons[i])
|
||||
|
||||
proc newAsgnStmt(le, ri: PNode): PNode =
|
||||
result = newNodeI(nkFastAsgn, ri.info)
|
||||
result.add(le)
|
||||
result.add(ri)
|
||||
proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
|
||||
# Bugfix: unfortunately we cannot use 'nkFastAsgn' here as that would
|
||||
# mean to be able to capture string literals which have no GC header.
|
||||
# However this can only happen if the capture happens through a parameter,
|
||||
# which is however the only case when we generate an assignment in the first
|
||||
# place.
|
||||
result = newNodeI(nkAsgn, info, 2)
|
||||
result.sons[0] = le
|
||||
result.sons[1] = ri
|
||||
|
||||
proc addVar*(father, v: PNode) =
|
||||
var vpart = newNodeI(nkIdentDefs, v.info)
|
||||
|
|
@ -481,13 +486,13 @@ proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
|
|||
if local.kind == skParam:
|
||||
# maybe later: (sfByCopy in local.flags)
|
||||
# add ``env.param = param``
|
||||
result.add(newAsgnStmt(fieldAccess, newSymNode(local)))
|
||||
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
|
||||
IdNodeTablePut(o.localsToAccess, local, fieldAccess)
|
||||
# add support for 'up' references:
|
||||
for e, field in items(scope.deps):
|
||||
# add ``env.up = env2``
|
||||
result.add(newAsgnStmt(indirectAccess(env, field, env.info),
|
||||
newSymNode(getClosureVar(o, e))))
|
||||
newSymNode(getClosureVar(o, e)), env.info))
|
||||
|
||||
proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
||||
if n == nil: return nil
|
||||
|
|
@ -543,7 +548,7 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
|||
if x != nil: n.sons[i] = x
|
||||
|
||||
proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
||||
if body.kind == nkEmpty or gCmd == cmdCompileToEcmaScript:
|
||||
if body.kind == nkEmpty or gCmd == cmdCompileToJS:
|
||||
# ignore forward declaration:
|
||||
result = body
|
||||
else:
|
||||
|
|
@ -566,7 +571,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
|||
result = ex
|
||||
|
||||
proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
|
||||
if body.kind == nkEmpty or gCmd == cmdCompileToEcmaScript:
|
||||
if body.kind == nkEmpty or gCmd == cmdCompileToJS:
|
||||
result = body
|
||||
else:
|
||||
var o = newOuterContext(module)
|
||||
|
|
|
|||
19
compiler/lexer.nim
Executable file → Normal file
19
compiler/lexer.nim
Executable file → Normal file
|
|
@ -16,7 +16,7 @@
|
|||
# DOS or Macintosh text files, even when it is not the native format.
|
||||
|
||||
import
|
||||
hashes, options, msgs, strutils, platform, idents, lexbase, llstream,
|
||||
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
|
||||
wordrecg
|
||||
|
||||
const
|
||||
|
|
@ -530,10 +530,10 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
|
|||
case L.buf[pos]
|
||||
of CR:
|
||||
registerLine()
|
||||
result = lexbase.HandleCR(L, pos)
|
||||
result = nimlexbase.HandleCR(L, pos)
|
||||
of LF:
|
||||
registerLine()
|
||||
result = lexbase.HandleLF(L, pos)
|
||||
result = nimlexbase.HandleLF(L, pos)
|
||||
else: result = pos
|
||||
|
||||
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||
|
|
@ -559,7 +559,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
|||
pos = HandleCRLF(L, pos)
|
||||
buf = L.buf
|
||||
add(tok.literal, tnl)
|
||||
of lexbase.EndOfFile:
|
||||
of nimlexbase.EndOfFile:
|
||||
var line2 = L.linenumber
|
||||
L.LineNumber = line
|
||||
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
|
||||
|
|
@ -581,7 +581,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
|||
else:
|
||||
inc(pos) # skip '"'
|
||||
break
|
||||
elif c in {CR, LF, lexbase.EndOfFile}:
|
||||
elif c in {CR, LF, nimlexbase.EndOfFile}:
|
||||
lexMessage(L, errClosingQuoteExpected)
|
||||
break
|
||||
elif (c == '\\') and not rawMode:
|
||||
|
|
@ -675,10 +675,12 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
|||
# a comment ends if the next line does not start with the # on the same
|
||||
# column after only whitespace
|
||||
tok.tokType = tkComment
|
||||
# iNumber contains the number of '\n' in the token
|
||||
tok.iNumber = 0
|
||||
var col = getColNumber(L, pos)
|
||||
while true:
|
||||
var lastBackslash = -1
|
||||
while buf[pos] notin {CR, LF, lexbase.EndOfFile}:
|
||||
while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
|
||||
if buf[pos] == '\\': lastBackslash = pos+1
|
||||
add(tok.literal, buf[pos])
|
||||
inc(pos)
|
||||
|
|
@ -686,7 +688,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
|||
# a backslash is a continuation character if only followed by spaces
|
||||
# plus a newline:
|
||||
while buf[lastBackslash] == ' ': inc(lastBackslash)
|
||||
if buf[lastBackslash] notin {CR, LF, lexbase.EndOfFile}:
|
||||
if buf[lastBackslash] notin {CR, LF, nimlexbase.EndOfFile}:
|
||||
# false positive:
|
||||
lastBackslash = -1
|
||||
|
||||
|
|
@ -699,6 +701,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
|||
if buf[pos] == '#' and (col == indent or lastBackslash > 0):
|
||||
tok.literal.add "\n"
|
||||
col = indent
|
||||
inc tok.iNumber
|
||||
else:
|
||||
if buf[pos] > ' ':
|
||||
L.indentAhead = indent
|
||||
|
|
@ -838,7 +841,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
|||
else:
|
||||
if c in OpChars:
|
||||
getOperator(L, tok)
|
||||
elif c == lexbase.EndOfFile:
|
||||
elif c == nimlexbase.EndOfFile:
|
||||
tok.toktype = tkEof
|
||||
else:
|
||||
tok.literal = c & ""
|
||||
|
|
|
|||
0
compiler/lists.nim
Executable file → Normal file
0
compiler/lists.nim
Executable file → Normal file
0
compiler/llstream.nim
Executable file → Normal file
0
compiler/llstream.nim
Executable file → Normal file
0
compiler/lookups.nim
Executable file → Normal file
0
compiler/lookups.nim
Executable file → Normal file
5
compiler/magicsys.nim
Executable file → Normal file
5
compiler/magicsys.nim
Executable file → Normal file
|
|
@ -38,7 +38,10 @@ proc newSysType(kind: TTypeKind, size: int): PType =
|
|||
|
||||
proc getSysSym(name: string): PSym =
|
||||
result = StrTableGet(systemModule.tab, getIdent(name))
|
||||
if result == nil: rawMessage(errSystemNeeds, name)
|
||||
if result == nil:
|
||||
rawMessage(errSystemNeeds, name)
|
||||
result = newSym(skError, getIdent(name), systemModule, systemModule.info)
|
||||
result.typ = newType(tyError, systemModule)
|
||||
if result.kind == skStub: loadStub(result)
|
||||
|
||||
proc sysTypeFromName*(name: string): PType =
|
||||
|
|
|
|||
66
compiler/main.nim
Executable file → Normal file
66
compiler/main.nim
Executable file → Normal file
|
|
@ -14,7 +14,7 @@ import
|
|||
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
|
||||
os, lists, condsyms, rodread, rodwrite, ropes, trees, times,
|
||||
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
||||
cgen, ecmasgen, cgendata,
|
||||
cgen, jsgen, cgendata, json, nversion,
|
||||
platform, nimconf, importer, passaux, depends, evals, types, idgen,
|
||||
tables, docgen2, service, magicsys, parser, crc, ccgutils
|
||||
|
||||
|
|
@ -155,7 +155,8 @@ proc compileModule(fileIdx: int32, flags: TSymFlags): PSym =
|
|||
growCache gMemCacheData, fileIdx
|
||||
gMemCacheData[fileIdx].needsRecompile = Probing
|
||||
result = newModule(fileIdx)
|
||||
var rd = handleSymbolFile(result)
|
||||
#var rd = handleSymbolFile(result)
|
||||
var rd: PRodReader
|
||||
result.flags = result.flags + flags
|
||||
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
|
||||
rd = handleSymbolFile(result)
|
||||
|
|
@ -251,8 +252,8 @@ proc CommandCompileToC =
|
|||
|
||||
compileProject()
|
||||
|
||||
if optCaasEnabled in gGlobalOptions:
|
||||
cgenCaasUpdate()
|
||||
if compilationCachePresent:
|
||||
updateCachedModules()
|
||||
|
||||
if gCmd != cmdRun:
|
||||
extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
|
||||
|
|
@ -301,18 +302,19 @@ when has_LLVM_Backend:
|
|||
#registerPass(cleanupPass())
|
||||
compileProject()
|
||||
|
||||
proc CommandCompileToEcmaScript =
|
||||
proc CommandCompileToJS =
|
||||
#incl(gGlobalOptions, optSafeCode)
|
||||
setTarget(osEcmaScript, cpuEcmaScript)
|
||||
setTarget(osJS, cpuJS)
|
||||
#initDefines()
|
||||
DefineSymbol("nimrod") # 'nimrod' is always defined
|
||||
DefineSymbol("ecmascript")
|
||||
DefineSymbol("ecmascript") # For backward compatibility
|
||||
DefineSymbol("js")
|
||||
semanticPasses()
|
||||
registerPass(ecmasgenPass)
|
||||
registerPass(jsgenPass)
|
||||
compileProject()
|
||||
|
||||
proc InteractivePasses =
|
||||
incl(gGlobalOptions, optSafeCode)
|
||||
#incl(gGlobalOptions, optSafeCode)
|
||||
#setTarget(osNimrodVM, cpuNimrodVM)
|
||||
initDefines()
|
||||
DefineSymbol("nimrodvm")
|
||||
|
|
@ -390,6 +392,15 @@ proc wantMainModule =
|
|||
|
||||
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
|
||||
|
||||
proc requireMainModuleOption =
|
||||
if optMainModule.len == 0:
|
||||
Fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
|
||||
else:
|
||||
gProjectName = optMainModule
|
||||
gProjectFull = gProjectPath / gProjectName
|
||||
|
||||
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
|
||||
|
||||
proc resetMemory =
|
||||
resetCompilationLists()
|
||||
ccgutils.resetCaches()
|
||||
|
|
@ -464,6 +475,7 @@ proc MainCommand =
|
|||
of "cpp", "compiletocpp":
|
||||
extccomp.cExt = ".cpp"
|
||||
gCmd = cmdCompileToCpp
|
||||
if cCompiler == ccGcc: setCC("gpp")
|
||||
wantMainModule()
|
||||
DefineSymbol("cpp")
|
||||
CommandCompileToC()
|
||||
|
|
@ -481,10 +493,10 @@ proc MainCommand =
|
|||
CommandCompileToC()
|
||||
else:
|
||||
rawMessage(errInvalidCommandX, command)
|
||||
of "js", "compiletoecmascript":
|
||||
gCmd = cmdCompileToEcmaScript
|
||||
of "js", "compiletojs":
|
||||
gCmd = cmdCompileToJS
|
||||
wantMainModule()
|
||||
CommandCompileToEcmaScript()
|
||||
CommandCompileToJS()
|
||||
of "compiletollvm":
|
||||
gCmd = cmdCompileToLLVM
|
||||
wantMainModule()
|
||||
|
|
@ -526,9 +538,30 @@ proc MainCommand =
|
|||
wantMainModule()
|
||||
CommandGenDepend()
|
||||
of "dump":
|
||||
gCmd = cmdDump
|
||||
condsyms.ListSymbols()
|
||||
for it in iterSearchPath(searchPaths): MsgWriteln(it)
|
||||
gcmd = cmdDump
|
||||
if getconfigvar("dump.format") == "json":
|
||||
requireMainModuleOption()
|
||||
|
||||
var definedSymbols = newJArray()
|
||||
for s in definedSymbolNames(): definedSymbols.elems.add(%s)
|
||||
|
||||
var libpaths = newJArray()
|
||||
for dir in itersearchpath(searchpaths): libpaths.elems.add(%dir)
|
||||
|
||||
var dumpdata = % [
|
||||
(key: "version", val: %VersionAsString),
|
||||
(key: "project_path", val: %gProjectFull),
|
||||
(key: "defined_symbols", val: definedSymbols),
|
||||
(key: "lib_paths", val: libpaths)
|
||||
]
|
||||
|
||||
outWriteLn($dumpdata)
|
||||
else:
|
||||
outWriteLn("-- list of currently defined symbols --")
|
||||
for s in definedSymbolNames(): outWriteLn(s)
|
||||
outWriteLn("-- end of list --")
|
||||
|
||||
for it in iterSearchPath(searchpaths): msgWriteLn(it)
|
||||
of "check":
|
||||
gCmd = cmdCheck
|
||||
wantMainModule()
|
||||
|
|
@ -558,13 +591,14 @@ proc MainCommand =
|
|||
wantMainModule()
|
||||
CommandSuggest()
|
||||
of "serve":
|
||||
isServing = true
|
||||
gGlobalOptions.incl(optCaasEnabled)
|
||||
msgs.gErrorMax = high(int) # do not stop after first error
|
||||
serve(MainCommand)
|
||||
else:
|
||||
rawMessage(errInvalidCommandX, command)
|
||||
|
||||
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun}:
|
||||
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun, cmdDump}:
|
||||
rawMessage(hintSuccessX, [$gLinesCompiled,
|
||||
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
|
||||
formatSize(getTotalMem())])
|
||||
|
|
|
|||
24
compiler/msgs.nim
Executable file → Normal file
24
compiler/msgs.nim
Executable file → Normal file
|
|
@ -83,7 +83,9 @@ type
|
|||
errInvalidCommandX, errXOnlyAtModuleScope,
|
||||
errXNeedsParamObjectType,
|
||||
errTemplateInstantiationTooNested, errInstantiationFrom,
|
||||
errInvalidIndexValueForTuple, errCommandExpectsFilename, errXExpected,
|
||||
errInvalidIndexValueForTuple, errCommandExpectsFilename,
|
||||
errMainModuleMustBeSpecified,
|
||||
errXExpected,
|
||||
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
||||
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
||||
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
|
||||
|
|
@ -301,6 +303,7 @@ const
|
|||
errInstantiationFrom: "instantiation from here",
|
||||
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
|
||||
errCommandExpectsFilename: "command expects a filename argument",
|
||||
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
|
||||
errXExpected: "\'$1\' expected",
|
||||
errInvalidSectionStart: "invalid section start",
|
||||
errGridTableNotImplemented: "grid table is not implemented",
|
||||
|
|
@ -506,6 +509,8 @@ var gCodegenLineInfo* = newLineInfo(int32(1), 1, 1)
|
|||
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
|
||||
raise newException(ERecoverableError, msg)
|
||||
|
||||
proc sourceLine*(i: TLineInfo): PRope
|
||||
|
||||
var
|
||||
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent}
|
||||
gErrorCounter*: int = 0 # counts the number of errors
|
||||
|
|
@ -523,8 +528,8 @@ proc SuggestWriteln*(s: string) =
|
|||
stdoutSocket.send(s & "\c\L")
|
||||
|
||||
proc SuggestQuit*() =
|
||||
if isNil(stdoutSocket): quit(0)
|
||||
else:
|
||||
if not isServing: quit(0)
|
||||
elif not isNil(stdoutSocket):
|
||||
stdoutSocket.send("\c\L")
|
||||
raise newException(ESuggestDone, "suggest done")
|
||||
|
||||
|
|
@ -707,6 +712,11 @@ proc rawMessage*(msg: TMsgKind, arg: string) =
|
|||
var
|
||||
lastError = UnknownLineInfo()
|
||||
|
||||
proc writeSurroundingSrc(info: TLineInfo) =
|
||||
const indent = " "
|
||||
MsgWriteln(indent & info.sourceLine.data)
|
||||
MsgWriteln(indent & repeatChar(info.col, ' ') & '^')
|
||||
|
||||
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
eh: TErrorHandling) =
|
||||
var frmt: string
|
||||
|
|
@ -732,6 +742,8 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
|||
coordToStr(info.col), getMessageStr(msg, arg)]
|
||||
if not ignoreMsg:
|
||||
MsgWriteln(s)
|
||||
if optPrintSurroundingSrc and msg in errMin..errMax:
|
||||
info.writeSurroundingSrc
|
||||
handleError(msg, eh, s)
|
||||
|
||||
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
|
|
@ -771,6 +783,12 @@ proc addSourceLine*(fileIdx: int32, line: string) =
|
|||
|
||||
proc sourceLine*(i: TLineInfo): PRope =
|
||||
if i.fileIndex < 0: return nil
|
||||
|
||||
if not optPreserveOrigSource and
|
||||
fileInfos[i.fileIndex].lines.len == 0:
|
||||
for line in lines(i.toFullPath):
|
||||
addSourceLine i.fileIndex, line.string
|
||||
|
||||
InternalAssert i.fileIndex < fileInfos.len and
|
||||
i.line <= fileInfos[i.fileIndex].lines.len
|
||||
|
||||
|
|
|
|||
0
compiler/nimconf.nim
Executable file → Normal file
0
compiler/nimconf.nim
Executable file → Normal file
0
compiler/lexbase.nim → compiler/nimlexbase.nim
Executable file → Normal file
0
compiler/lexbase.nim → compiler/nimlexbase.nim
Executable file → Normal file
2
compiler/nimrod.cfg
Executable file → Normal file
2
compiler/nimrod.cfg
Executable file → Normal file
|
|
@ -6,7 +6,7 @@ hint[XDeclaredButNotUsed]:off
|
|||
path:"llvm"
|
||||
path:"$projectPath/.."
|
||||
|
||||
path:"$nimrod/packages/docutils"
|
||||
path:"$lib/packages/docutils"
|
||||
|
||||
define:booting
|
||||
|
||||
|
|
|
|||
54
compiler/nimrod.dot
Executable file → Normal file
54
compiler/nimrod.dot
Executable file → Normal file
|
|
@ -472,32 +472,32 @@ cgen -> wordrecg;
|
|||
cgen -> rnimsyn;
|
||||
cgen -> treetab;
|
||||
cgen -> cgmeth;
|
||||
ecmasgen -> ast;
|
||||
ecmasgen -> astalgo;
|
||||
ecmasgen -> strutils;
|
||||
ecmasgen -> nhashes;
|
||||
ecmasgen -> trees;
|
||||
ecmasgen -> platform;
|
||||
ecmasgen -> magicsys;
|
||||
ecmasgen -> extccomp;
|
||||
ecmasgen -> options;
|
||||
ecmasgen -> nversion;
|
||||
ecmasgen -> nimsets;
|
||||
ecmasgen -> msgs;
|
||||
ecmasgen -> crc;
|
||||
ecmasgen -> bitsets;
|
||||
ecmasgen -> idents;
|
||||
ecmasgen -> lists;
|
||||
ecmasgen -> types;
|
||||
ecmasgen -> os;
|
||||
ecmasgen -> times;
|
||||
ecmasgen -> ropes;
|
||||
ecmasgen -> math;
|
||||
ecmasgen -> passes;
|
||||
ecmasgen -> ccgutils;
|
||||
ecmasgen -> wordrecg;
|
||||
ecmasgen -> rnimsyn;
|
||||
ecmasgen -> rodread;
|
||||
jsgen -> ast;
|
||||
jsgen -> astalgo;
|
||||
jsgen -> strutils;
|
||||
jsgen -> nhashes;
|
||||
jsgen -> trees;
|
||||
jsgen -> platform;
|
||||
jsgen -> magicsys;
|
||||
jsgen -> extccomp;
|
||||
jsgen -> options;
|
||||
jsgen -> nversion;
|
||||
jsgen -> nimsets;
|
||||
jsgen -> msgs;
|
||||
jsgen -> crc;
|
||||
jsgen -> bitsets;
|
||||
jsgen -> idents;
|
||||
jsgen -> lists;
|
||||
jsgen -> types;
|
||||
jsgen -> os;
|
||||
jsgen -> times;
|
||||
jsgen -> ropes;
|
||||
jsgen -> math;
|
||||
jsgen -> passes;
|
||||
jsgen -> ccgutils;
|
||||
jsgen -> wordrecg;
|
||||
jsgen -> rnimsyn;
|
||||
jsgen -> rodread;
|
||||
interact -> llstream;
|
||||
interact -> strutils;
|
||||
interact -> ropes;
|
||||
|
|
@ -561,7 +561,7 @@ main -> passes;
|
|||
main -> docgen;
|
||||
main -> extccomp;
|
||||
main -> cgen;
|
||||
main -> ecmasgen;
|
||||
main -> jsgen;
|
||||
main -> platform;
|
||||
main -> interact;
|
||||
main -> nimconf;
|
||||
|
|
|
|||
5
compiler/nimrod.ini
Executable file → Normal file
5
compiler/nimrod.ini
Executable file → Normal file
|
|
@ -57,8 +57,6 @@ Files: "compiler/*.nim"
|
|||
Files: "build/empty.txt"
|
||||
Files: "bin/empty.txt"
|
||||
|
||||
Files: "packages/docutils/*.nim"
|
||||
|
||||
|
||||
[Lib]
|
||||
Files: "lib/nimbase.h"
|
||||
|
|
@ -84,7 +82,8 @@ Files: "lib/wrappers/zip/libzip_all.c"
|
|||
|
||||
Files: "lib/windows/*.nim"
|
||||
Files: "lib/posix/*.nim"
|
||||
Files: "lib/ecmas/*.nim"
|
||||
Files: "lib/js/*.nim"
|
||||
Files: "lib/packages/docutils/*.nim"
|
||||
|
||||
|
||||
[Other]
|
||||
|
|
|
|||
2
compiler/nimrod.nim
Executable file → Normal file
2
compiler/nimrod.nim
Executable file → Normal file
|
|
@ -60,7 +60,7 @@ proc HandleCmdLine() =
|
|||
if gCmd == cmdRun:
|
||||
tccgen.run()
|
||||
if optRun in gGlobalOptions:
|
||||
if gCmd == cmdCompileToEcmaScript:
|
||||
if gCmd == cmdCompileToJS:
|
||||
var ex = quoteIfContainsWhite(
|
||||
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
|
||||
execExternalProgram("node " & ex & ' ' & service.arguments)
|
||||
|
|
|
|||
4
compiler/nimsets.nim
Executable file → Normal file
4
compiler/nimsets.nim
Executable file → Normal file
|
|
@ -98,13 +98,13 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
|||
result.typ = settype
|
||||
result.info = info
|
||||
e = 0
|
||||
while e < high(s) * elemSize:
|
||||
while e < len(s) * elemSize:
|
||||
if bitSetIn(s, e):
|
||||
a = e
|
||||
b = e
|
||||
while true:
|
||||
Inc(b)
|
||||
if (b > high(s) * elemSize) or not bitSetIn(s, b): break
|
||||
if (b >= len(s) * elemSize) or not bitSetIn(s, b): break
|
||||
Dec(b)
|
||||
if a == b:
|
||||
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
|
||||
|
|
|
|||
2
compiler/nversion.nim
Executable file → Normal file
2
compiler/nversion.nim
Executable file → Normal file
|
|
@ -18,5 +18,5 @@ const
|
|||
VersionPatch* = 1
|
||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
||||
|
||||
RodFileVersion* = "1210" # modify this if the rod-format changes!
|
||||
RodFileVersion* = "1212" # modify this if the rod-format changes!
|
||||
|
||||
|
|
|
|||
33
compiler/options.nim
Executable file → Normal file
33
compiler/options.nim
Executable file → Normal file
|
|
@ -68,7 +68,7 @@ type # please make sure we have under 32 options
|
|||
TCommands* = enum # Nimrod's commands
|
||||
# **keep binary compatible**
|
||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||
cmdCompileToEcmaScript, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||
cmdCompileToJS, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||
cmdGenDepend, cmdDump,
|
||||
cmdCheck, # semantic checking for whole project
|
||||
cmdParse, # parse a single file (for debugging)
|
||||
|
|
@ -81,7 +81,7 @@ type # please make sure we have under 32 options
|
|||
cmdRun # run the project via TCC backend
|
||||
TStringSeq* = seq[string]
|
||||
TGCMode* = enum # the selected GC
|
||||
gcNone, gcBoehm, gcMarkAndSweep, gcRefc, gcV2
|
||||
gcNone, gcBoehm, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
|
||||
|
||||
const
|
||||
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
|
||||
|
|
@ -99,16 +99,26 @@ var
|
|||
searchPaths*, lazyPaths*: TLinkedList
|
||||
outFile*: string = ""
|
||||
headerFile*: string = ""
|
||||
gVerbosity*: int # how verbose the compiler is
|
||||
gVerbosity* = 1 # how verbose the compiler is
|
||||
gNumberOfProcessors*: int # number of processors
|
||||
gWholeProject*: bool # for 'doc2': output any dependency
|
||||
gWholeProject*: bool # for 'doc2': output any dependency
|
||||
gEvalExpr* = "" # expression for idetools --eval
|
||||
gLastCmdTime*: float # when caas is enabled, we measure each command
|
||||
gListFullPaths*: bool
|
||||
isServing*: bool = false
|
||||
|
||||
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
||||
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
||||
|
||||
template compilationCachePresent*: expr =
|
||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||
|
||||
template optPreserveOrigSource*: expr =
|
||||
optEmbedOrigSrc in gGlobalOptions
|
||||
|
||||
template optPrintSurroundingSrc*: expr =
|
||||
gVerbosity >= 2
|
||||
|
||||
const
|
||||
genSubDir* = "nimcache"
|
||||
NimExt* = "nim"
|
||||
|
|
@ -123,6 +133,7 @@ const
|
|||
# additional configuration variables:
|
||||
var
|
||||
gConfigVars* = newStringTable(modeStyleInsensitive)
|
||||
gDllOverrides = newStringtable(modeCaseInsensitive)
|
||||
libpath* = ""
|
||||
gProjectName* = "" # holds a name like 'nimrod'
|
||||
gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
|
||||
|
|
@ -255,6 +266,20 @@ proc libCandidates*(s: string, dest: var seq[string]) =
|
|||
else:
|
||||
add(dest, s)
|
||||
|
||||
proc canonDynlibName(s: string): string =
|
||||
let start = if s.startsWith("lib"): 3 else: 0
|
||||
let ende = strutils.find(s, {'(', ')', '.'})
|
||||
if ende >= 0:
|
||||
result = s.substr(start, ende-1)
|
||||
else:
|
||||
result = s.substr(start)
|
||||
|
||||
proc inclDynlibOverride*(lib: string) =
|
||||
gDllOverrides[lib.canonDynlibName] = "true"
|
||||
|
||||
proc isDynlibOverride*(lib: string): bool =
|
||||
result = gDllOverrides.hasKey(lib.canonDynlibName)
|
||||
|
||||
proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||
var a = 0
|
||||
var b = len(x) - 1
|
||||
|
|
|
|||
|
|
@ -187,21 +187,24 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
|||
else:
|
||||
result = arLValue
|
||||
of nkDotExpr:
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
||||
{tyVar, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
else:
|
||||
result = isAssignable(owner, n.sons[0])
|
||||
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
|
||||
result = arDiscriminant
|
||||
of nkBracketExpr:
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
||||
{tyVar, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
else:
|
||||
result = isAssignable(owner, n.sons[0])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
# Object and tuple conversions are still addressable, so we skip them
|
||||
# XXX why is 'tyOpenArray' allowed here?
|
||||
if skipTypes(n.typ, abstractPtrs).kind in {tyOpenArray, tyTuple, tyObject}:
|
||||
if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
|
||||
{tyOpenArray, tyTuple, tyObject}:
|
||||
result = isAssignable(owner, n.sons[1])
|
||||
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
|
||||
# types that are equal modulo distinction preserve l-value:
|
||||
|
|
|
|||
2
compiler/parsecfg.nim
Executable file → Normal file
2
compiler/parsecfg.nim
Executable file → Normal file
|
|
@ -12,7 +12,7 @@
|
|||
# standard library.
|
||||
|
||||
import
|
||||
llstream, nhashes, strutils, lexbase
|
||||
llstream, nhashes, strutils, nimlexbase
|
||||
|
||||
type
|
||||
TCfgEventKind* = enum
|
||||
|
|
|
|||
43
compiler/parser.nim
Executable file → Normal file
43
compiler/parser.nim
Executable file → Normal file
|
|
@ -254,10 +254,16 @@ proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
|
|||
optPar(p)
|
||||
eat(p, endToken)
|
||||
|
||||
proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
|
||||
proc exprColonEqExpr(p: var TParser): PNode =
|
||||
var a = parseExpr(p)
|
||||
if p.tok.tokType == tok:
|
||||
result = newNodeP(kind, p)
|
||||
if p.tok.tokType == tkColon:
|
||||
result = newNodeP(nkExprColonExpr, p)
|
||||
getTok(p)
|
||||
#optInd(p, result)
|
||||
addSon(result, a)
|
||||
addSon(result, parseExpr(p))
|
||||
elif p.tok.tokType == tkEquals:
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
getTok(p)
|
||||
#optInd(p, result)
|
||||
addSon(result, a)
|
||||
|
|
@ -309,14 +315,13 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
|||
optInd(p, a)
|
||||
eat(p, endTok)
|
||||
|
||||
proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
||||
endTok, sepTok: TTokType, result: PNode) =
|
||||
proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
|
||||
(p.tok.tokType != tkSad) and (p.tok.tokType != tkInd):
|
||||
var a = exprColonEqExpr(p, elemKind, sepTok)
|
||||
var a = exprColonEqExpr(p)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
|
|
@ -324,10 +329,10 @@ proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
|||
optPar(p)
|
||||
eat(p, endTok)
|
||||
|
||||
proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
|
||||
endTok, sepTok: TTokType): PNode =
|
||||
proc exprColonEqExprList(p: var TParser, kind: TNodeKind,
|
||||
endTok: TTokType): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
exprColonEqExprListAux(p, elemKind, endTok, sepTok, result)
|
||||
exprColonEqExprListAux(p, endTok, result)
|
||||
|
||||
proc setOrTableConstr(p: var TParser): PNode =
|
||||
result = newNodeP(nkCurly, p)
|
||||
|
|
@ -338,7 +343,7 @@ proc setOrTableConstr(p: var TParser): PNode =
|
|||
result.kind = nkTableConstr
|
||||
else:
|
||||
while p.tok.tokType notin {tkCurlyRi, tkEof, tkSad, tkInd}:
|
||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
||||
var a = exprColonEqExpr(p)
|
||||
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
|
|
@ -473,14 +478,13 @@ proc identOrLiteral(p: var TParser): PNode =
|
|||
getTok(p)
|
||||
of tkParLe:
|
||||
# () constructor
|
||||
result = exprColonEqExprList(p, nkPar, nkExprColonExpr, tkParRi, tkColon)
|
||||
result = exprColonEqExprList(p, nkPar, tkParRi)
|
||||
of tkCurlyLe:
|
||||
# {} constructor
|
||||
result = setOrTableConstr(p)
|
||||
of tkBracketLe:
|
||||
# [] constructor
|
||||
result = exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi,
|
||||
tkColon)
|
||||
result = exprColonEqExprList(p, nkBracket, tkBracketRi)
|
||||
of tkCast:
|
||||
result = parseCast(p)
|
||||
else:
|
||||
|
|
@ -496,8 +500,11 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
|||
var a = result
|
||||
result = newNodeP(nkCall, p)
|
||||
addSon(result, a)
|
||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
||||
parseDoBlocks(p, result)
|
||||
exprColonEqExprListAux(p, tkParRi, result)
|
||||
if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
|
||||
result.kind = nkObjConstr
|
||||
else:
|
||||
parseDoBlocks(p, result)
|
||||
of tkDo:
|
||||
var a = result
|
||||
result = newNodeP(nkCall, p)
|
||||
|
|
@ -564,7 +571,7 @@ proc parsePragma(p: var TParser): PNode =
|
|||
optInd(p, result)
|
||||
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
||||
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
||||
var a = exprColonEqExpr(p)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
|
|
@ -739,7 +746,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
|||
proc isExprStart(p: TParser): bool =
|
||||
case p.tok.tokType
|
||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
|
||||
tkProc, tkIterator, tkBind,
|
||||
tkProc, tkIterator, tkBind, tkAddr,
|
||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
||||
tkTuple, tkObject, tkType, tkWhen, tkCase, tkShared:
|
||||
result = true
|
||||
|
|
@ -1202,7 +1209,7 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
|||
|
||||
proc newCommentStmt(p: var TParser): PNode =
|
||||
result = newNodeP(nkCommentStmt, p)
|
||||
result.info.line = result.info.line - int16(1)
|
||||
result.info.line = result.info.line - int16(1) - int16(p.tok.iNumber)
|
||||
|
||||
type
|
||||
TDefParser = proc (p: var TParser): PNode {.nimcall.}
|
||||
|
|
|
|||
0
compiler/pas2nim/nimrod.cfg
Executable file → Normal file
0
compiler/pas2nim/nimrod.cfg
Executable file → Normal file
0
compiler/pas2nim/pas2nim.nim
Executable file → Normal file
0
compiler/pas2nim/pas2nim.nim
Executable file → Normal file
0
compiler/pas2nim/paslex.nim
Executable file → Normal file
0
compiler/pas2nim/paslex.nim
Executable file → Normal file
0
compiler/pas2nim/pasparse.nim
Executable file → Normal file
0
compiler/pas2nim/pasparse.nim
Executable file → Normal file
0
compiler/passaux.nim
Executable file → Normal file
0
compiler/passaux.nim
Executable file → Normal file
0
compiler/passes.nim
Executable file → Normal file
0
compiler/passes.nim
Executable file → Normal file
0
compiler/pbraces.nim
Executable file → Normal file
0
compiler/pbraces.nim
Executable file → Normal file
0
compiler/pendx.nim
Executable file → Normal file
0
compiler/pendx.nim
Executable file → Normal file
8
compiler/platform.nim
Executable file → Normal file
8
compiler/platform.nim
Executable file → Normal file
|
|
@ -21,7 +21,7 @@ type
|
|||
# conditionals to condsyms (end of module).
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osAix, osPalmos, osQnx, osAmiga,
|
||||
osAtari, osNetware, osMacos, osMacosx, osHaiku, osEcmaScript, osNimrodVM,
|
||||
osAtari, osNetware, osMacos, osMacosx, osHaiku, osJS, osNimrodVM,
|
||||
osStandalone
|
||||
|
||||
type
|
||||
|
|
@ -136,7 +136,7 @@ const
|
|||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
||||
(name: "EcmaScript", parDir: "..",
|
||||
(name: "JS", parDir: "..",
|
||||
dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A",
|
||||
pathSep: ":", dirSep: "/",
|
||||
|
|
@ -155,7 +155,7 @@ type
|
|||
# alias conditionals to condsyms (end of module).
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuArm,
|
||||
cpuEcmaScript, cpuNimrodVM, cpuAVR
|
||||
cpuJS, cpuNimrodVM, cpuAVR
|
||||
|
||||
type
|
||||
TEndian* = enum
|
||||
|
|
@ -177,7 +177,7 @@ const
|
|||
(name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
(name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "ecmascript", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
|
||||
(name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
|
||||
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16)]
|
||||
|
||||
|
|
|
|||
7
compiler/pragmas.nim
Executable file → Normal file
7
compiler/pragmas.nim
Executable file → Normal file
|
|
@ -202,6 +202,8 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
|||
result = newLib(kind)
|
||||
result.path = path
|
||||
Append(c.libs, result)
|
||||
if path.kind in {nkStrLit..nkTripleStrLit}:
|
||||
result.isOverriden = options.isDynLibOverride(path.strVal)
|
||||
|
||||
proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr:
|
||||
|
|
@ -225,8 +227,9 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
|||
else:
|
||||
if n.kind == nkExprColonExpr:
|
||||
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||
addToLib(lib, sym)
|
||||
incl(sym.loc.flags, lfDynamicLib)
|
||||
if not lib.isOverriden:
|
||||
addToLib(lib, sym)
|
||||
incl(sym.loc.flags, lfDynamicLib)
|
||||
else:
|
||||
incl(sym.loc.flags, lfExportLib)
|
||||
# since we'll be loading the dynlib symbols dynamically, we must use
|
||||
|
|
|
|||
37
compiler/procfind.nim
Executable file → Normal file
37
compiler/procfind.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -14,10 +14,6 @@ import
|
|||
ast, astalgo, msgs, semdata, types, trees
|
||||
|
||||
proc equalGenericParams(procA, procB: PNode): bool =
|
||||
var a, b: PSym
|
||||
result = procA == procB
|
||||
if result: return
|
||||
if (procA == nil) or (procB == nil): return
|
||||
if sonsLen(procA) != sonsLen(procB): return
|
||||
for i in countup(0, sonsLen(procA) - 1):
|
||||
if procA.sons[i].kind != nkSym:
|
||||
|
|
@ -26,11 +22,11 @@ proc equalGenericParams(procA, procB: PNode): bool =
|
|||
if procB.sons[i].kind != nkSym:
|
||||
InternalError(procB.info, "equalGenericParams")
|
||||
return
|
||||
a = procA.sons[i].sym
|
||||
b = procB.sons[i].sym
|
||||
if (a.name.id != b.name.id) or
|
||||
let a = procA.sons[i].sym
|
||||
let b = procB.sons[i].sym
|
||||
if a.name.id != b.name.id or
|
||||
not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return
|
||||
if (a.ast != nil) and (b.ast != nil):
|
||||
if a.ast != nil and b.ast != nil:
|
||||
if not ExprStructuralEquivalent(a.ast, b.ast): return
|
||||
result = true
|
||||
|
||||
|
|
@ -39,10 +35,23 @@ proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
|
|||
# the same the sym in the symbol table is returned, else nil.
|
||||
var it: TIdentIter
|
||||
result = initIdentIter(it, c.tab.stack[tos], fn.Name)
|
||||
while result != nil:
|
||||
if (result.Kind == fn.kind):
|
||||
if equalGenericParams(result.ast.sons[genericParamsPos],
|
||||
fn.ast.sons[genericParamsPos]):
|
||||
if isGenericRoutine(fn):
|
||||
# we simply check the AST; this is imprecise but nearly the best what
|
||||
# can be done; this doesn't work either though as type constraints are
|
||||
# not kept in the AST ..
|
||||
while result != nil:
|
||||
if result.Kind == fn.kind and isGenericRoutine(result):
|
||||
let genR = result.ast.sons[genericParamsPos]
|
||||
let genF = fn.ast.sons[genericParamsPos]
|
||||
if ExprStructuralEquivalent(genR, genF) and
|
||||
ExprStructuralEquivalent(result.ast.sons[paramsPos],
|
||||
fn.ast.sons[paramsPos]) and
|
||||
equalGenericParams(genR, genF):
|
||||
return
|
||||
result = NextIdentIter(it, c.tab.stack[tos])
|
||||
else:
|
||||
while result != nil:
|
||||
if result.Kind == fn.kind and not isGenericRoutine(result):
|
||||
case equalParams(result.typ.n, fn.typ.n)
|
||||
of paramsEqual:
|
||||
return
|
||||
|
|
@ -51,7 +60,7 @@ proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
|
|||
return
|
||||
of paramsNotEqual:
|
||||
nil
|
||||
result = NextIdentIter(it, c.tab.stack[tos])
|
||||
result = NextIdentIter(it, c.tab.stack[tos])
|
||||
|
||||
when false:
|
||||
proc paramsFitBorrow(child, parent: PNode): bool =
|
||||
|
|
|
|||
0
compiler/readme.txt
Executable file → Normal file
0
compiler/readme.txt
Executable file → Normal file
4
compiler/renderer.nim
Executable file → Normal file
4
compiler/renderer.nim
Executable file → Normal file
|
|
@ -367,7 +367,7 @@ proc lsub(n: PNode): int =
|
|||
else: result = len(atom(n))
|
||||
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||
result = len(atom(n))
|
||||
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern:
|
||||
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr:
|
||||
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
||||
|
|
@ -779,7 +779,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
||||
of nkCharLit: put(g, tkCharLit, atom(n))
|
||||
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
||||
of nkCall, nkConv, nkDotCall, nkPattern:
|
||||
of nkCall, nkConv, nkDotCall, nkPattern, nkObjConstr:
|
||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1)
|
||||
|
|
|
|||
307
compiler/rodread.nim
Executable file → Normal file
307
compiler/rodread.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -127,7 +127,7 @@ type
|
|||
options: TOptions
|
||||
reason: TReasonForRecompile
|
||||
modDeps: seq[int32]
|
||||
files: TStringSeq
|
||||
files: seq[int32]
|
||||
dataIdx: int # offset of start of data section
|
||||
convertersIdx: int # offset of start of converters section
|
||||
initIdx, interfIdx, compilerProcsIdx, methodsIdx: int
|
||||
|
|
@ -140,6 +140,7 @@ type
|
|||
memfile: TMemFile # unfortunately there is no point in time where we
|
||||
# can close this! XXX
|
||||
methods*: TSymSeq
|
||||
inViewMode: bool
|
||||
|
||||
PRodReader* = ref TRodReader
|
||||
|
||||
|
|
@ -381,8 +382,14 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
|||
result.id = id
|
||||
IdTablePut(r.syms, result, result)
|
||||
if debugIds: registerID(result)
|
||||
elif (result.id != id):
|
||||
elif result.id != id:
|
||||
InternalError(info, "decodeSym: wrong id")
|
||||
elif result.kind != skStub and not r.inViewMode:
|
||||
# we already loaded the symbol
|
||||
return
|
||||
else:
|
||||
reset(result[])
|
||||
result.id = id
|
||||
result.kind = k
|
||||
result.name = ident # read the rest of the symbol description:
|
||||
if r.s[r.pos] == '^':
|
||||
|
|
@ -495,7 +502,7 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
|
|||
IdTablePut(r.syms, s, s)
|
||||
StrTableAdd(rodCompilerProcs, s)
|
||||
|
||||
proc processIndex(r: PRodReader, idx: var TIndex) =
|
||||
proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) =
|
||||
var key, val, tmp: int
|
||||
inc(r.pos, 2) # skip "(\10"
|
||||
inc(r.line)
|
||||
|
|
@ -509,6 +516,7 @@ proc processIndex(r: PRodReader, idx: var TIndex) =
|
|||
key = idx.lastIdxKey + 1
|
||||
val = tmp + idx.lastIdxVal
|
||||
IITablePut(idx.tab, key, val)
|
||||
if not outf.isNil: outf.write(key, " ", val, "\n")
|
||||
idx.lastIdxKey = key
|
||||
idx.lastIdxVal = val
|
||||
setID(key) # ensure that this id will not be used
|
||||
|
|
@ -523,7 +531,7 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
|
|||
# new command forces us to consider it here :-)
|
||||
case old
|
||||
of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||
cmdCompileToEcmaScript, cmdCompileToLLVM:
|
||||
cmdCompileToJS, cmdCompileToLLVM:
|
||||
if new in {cmdDoc, cmdCheck, cmdIdeTools, cmdPretty, cmdDef,
|
||||
cmdInteractive}:
|
||||
return false
|
||||
|
|
@ -576,9 +584,10 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
|||
inc(r.pos, 2) # skip "(\10"
|
||||
inc(r.line)
|
||||
while r.s[r.pos] != ')':
|
||||
var relativePath = decodeStr(r.s, r.pos)
|
||||
var resolvedPath = relativePath.findModule
|
||||
r.files.add(if resolvedPath.len > 0: resolvedPath else: relativePath)
|
||||
let relativePath = decodeStr(r.s, r.pos)
|
||||
let resolvedPath = relativePath.findModule
|
||||
let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
|
||||
r.files.add(finalPath.fileInfoIdx)
|
||||
inc(r.pos) # skip #10
|
||||
inc(r.line)
|
||||
if r.s[r.pos] == ')': inc(r.pos)
|
||||
|
|
@ -586,7 +595,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
|||
inc(r.pos, 2) # skip "(\10"
|
||||
inc(r.line)
|
||||
while r.s[r.pos] != ')':
|
||||
w = r.files[decodeVInt(r.s, r.pos)]
|
||||
w = r.files[decodeVInt(r.s, r.pos)].toFullPath
|
||||
inc(r.pos) # skip ' '
|
||||
inclCrc = decodeVInt(r.s, r.pos)
|
||||
if r.reason == rrNone:
|
||||
|
|
@ -599,7 +608,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
|||
of "DEPS":
|
||||
inc(r.pos) # skip ':'
|
||||
while r.s[r.pos] > '\x0A':
|
||||
r.modDeps.add int32(decodeVInt(r.s, r.pos))
|
||||
r.modDeps.add(r.files[int32(decodeVInt(r.s, r.pos))])
|
||||
if r.s[r.pos] == ' ': inc(r.pos)
|
||||
of "INTERF":
|
||||
r.interfIdx = r.pos + 2
|
||||
|
|
@ -670,11 +679,9 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
|||
add(version, r.s[r.pos])
|
||||
inc(r.pos)
|
||||
if r.s[r.pos] == '\x0A': inc(r.pos)
|
||||
if version == RodFileVersion:
|
||||
if version != RodFileVersion:
|
||||
# since ROD files are only for caching, no backwards compatibility is
|
||||
# needed
|
||||
processRodFile(r, crc)
|
||||
else:
|
||||
result = nil
|
||||
else:
|
||||
result = nil
|
||||
|
|
@ -719,8 +726,14 @@ proc findSomeWhere(id: int) =
|
|||
echo "found id ", id, " in ", gMods[i].filename
|
||||
|
||||
proc getReader(moduleId: int): PRodReader =
|
||||
InternalAssert moduleId >= 0 and moduleId < gMods.len
|
||||
result = gMods[moduleId].rd
|
||||
# we can't index 'gMods' here as it's indexed by a *file index* which is not
|
||||
# the module ID! We could introduce a mapping ID->PRodReader but I'll leave
|
||||
# this for later versions if benchmarking shows the linear search causes
|
||||
# problems:
|
||||
for i in 0 .. <gMods.len:
|
||||
result = gMods[i].rd
|
||||
if result != nil and result.moduleId == moduleId: return result
|
||||
return nil
|
||||
|
||||
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||
result = PSym(IdTableGet(r.syms, id))
|
||||
|
|
@ -810,6 +823,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
|
|||
if r == nil:
|
||||
result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
|
||||
else:
|
||||
processRodFile(r, crc)
|
||||
result = r.reason
|
||||
if result == rrNone:
|
||||
# check modules it depends on
|
||||
|
|
@ -860,6 +874,8 @@ proc rawLoadStub(s: PSym) =
|
|||
if d == invalidKey: InternalError("loadStub: invalid key")
|
||||
var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
|
||||
if rs != s:
|
||||
#echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
|
||||
# "\ns: ", toHex(cast[int](s.position), int.sizeof * 2)
|
||||
InternalError(rs.info, "loadStub: wrong symbol")
|
||||
elif rs.id != theId:
|
||||
InternalError(rs.info, "loadStub: wrong ID")
|
||||
|
|
@ -894,3 +910,264 @@ proc getBody*(s: PSym): PNode =
|
|||
|
||||
InitIdTable(gTypeTable)
|
||||
InitStrTable(rodCompilerProcs)
|
||||
|
||||
# viewer:
|
||||
proc writeNode(f: TFile; n: PNode) =
|
||||
f.write("(")
|
||||
if n != nil:
|
||||
f.write($n.kind)
|
||||
if n.typ != nil:
|
||||
f.write('^')
|
||||
f.write(n.typ.id)
|
||||
case n.kind
|
||||
of nkCharLit..nkInt64Lit:
|
||||
if n.intVal != 0:
|
||||
f.write('!')
|
||||
f.write(n.intVal)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if n.floatVal != 0.0:
|
||||
f.write('!')
|
||||
f.write($n.floatVal)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if n.strVal != "":
|
||||
f.write('!')
|
||||
f.write(n.strVal.escape)
|
||||
of nkIdent:
|
||||
f.write('!')
|
||||
f.write(n.ident.s)
|
||||
of nkSym:
|
||||
f.write('!')
|
||||
f.write(n.sym.id)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
writeNode(f, n.sons[i])
|
||||
f.write(")")
|
||||
|
||||
proc writeSym(f: TFile; s: PSym) =
|
||||
if s == nil:
|
||||
f.write("{}\n")
|
||||
return
|
||||
f.write("{")
|
||||
f.write($s.kind)
|
||||
f.write('+')
|
||||
f.write(s.id)
|
||||
f.write('&')
|
||||
f.write(s.name.s)
|
||||
if s.typ != nil:
|
||||
f.write('^')
|
||||
f.write(s.typ.id)
|
||||
if s.owner != nil:
|
||||
f.write('*')
|
||||
f.write(s.owner.id)
|
||||
if s.flags != {}:
|
||||
f.write('$')
|
||||
f.write($s.flags)
|
||||
if s.magic != mNone:
|
||||
f.write('@')
|
||||
f.write($s.magic)
|
||||
if s.options != gOptions:
|
||||
f.write('!')
|
||||
f.write($s.options)
|
||||
if s.position != 0:
|
||||
f.write('%')
|
||||
f.write($s.position)
|
||||
if s.offset != -1:
|
||||
f.write('`')
|
||||
f.write($s.offset)
|
||||
if s.constraint != nil:
|
||||
f.write('#')
|
||||
f.writeNode(s.constraint)
|
||||
if s.ast != nil:
|
||||
f.writeNode(s.ast)
|
||||
f.write("}\n")
|
||||
|
||||
proc writeType(f: TFile; t: PType) =
|
||||
if t == nil:
|
||||
f.write("[]\n")
|
||||
return
|
||||
f.write('[')
|
||||
f.write($t.kind)
|
||||
f.write('+')
|
||||
f.write($t.id)
|
||||
if t.n != nil:
|
||||
f.writeNode(t.n)
|
||||
if t.flags != {}:
|
||||
f.write('$')
|
||||
f.write($t.flags)
|
||||
if t.callConv != low(t.callConv):
|
||||
f.write('?')
|
||||
f.write($t.callConv)
|
||||
if t.owner != nil:
|
||||
f.write('*')
|
||||
f.write($t.owner.id)
|
||||
if t.sym != nil:
|
||||
f.write('&')
|
||||
f.write(t.sym.id)
|
||||
if t.size != -1:
|
||||
f.write('/')
|
||||
f.write($t.size)
|
||||
if t.align != 2:
|
||||
f.write('=')
|
||||
f.write($t.align)
|
||||
if t.containerID != 0:
|
||||
f.write('@')
|
||||
f.write($t.containerID)
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
if t.sons[i] == nil:
|
||||
f.write("^()")
|
||||
else:
|
||||
f.write('^')
|
||||
f.write($t.sons[i].id)
|
||||
f.write("]\n")
|
||||
|
||||
proc viewFile(rodfile: string) =
|
||||
var r = newRodReader(rodfile, 0, 0)
|
||||
if r == nil:
|
||||
rawMessage(errGenerated, "cannot open file (or maybe wrong version):" &
|
||||
rodfile)
|
||||
return
|
||||
r.inViewMode = true
|
||||
var outf = system.open(rodfile.changeFileExt(".rod.txt"), fmWrite)
|
||||
while r.s[r.pos] != '\0':
|
||||
let section = rdWord(r)
|
||||
case section
|
||||
of "CRC":
|
||||
inc(r.pos) # skip ':'
|
||||
outf.writeln("CRC:", $decodeVInt(r.s, r.pos))
|
||||
of "ID":
|
||||
inc(r.pos) # skip ':'
|
||||
r.moduleID = decodeVInt(r.s, r.pos)
|
||||
setID(r.moduleID)
|
||||
outf.writeln("ID:", $r.moduleID)
|
||||
of "OPTIONS":
|
||||
inc(r.pos) # skip ':'
|
||||
r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
|
||||
outf.writeln("OPTIONS:", $r.options)
|
||||
of "GOPTIONS":
|
||||
inc(r.pos) # skip ':'
|
||||
let dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos)))
|
||||
outf.writeln("GOPTIONS:", $dep)
|
||||
of "CMD":
|
||||
inc(r.pos) # skip ':'
|
||||
let dep = cast[TCommands](int32(decodeVInt(r.s, r.pos)))
|
||||
outf.writeln("CMD:", $dep)
|
||||
of "DEFINES":
|
||||
inc(r.pos) # skip ':'
|
||||
var d = 0
|
||||
outf.write("DEFINES:")
|
||||
while r.s[r.pos] > '\x0A':
|
||||
let w = decodeStr(r.s, r.pos)
|
||||
inc(d)
|
||||
outf.write(" ", w)
|
||||
if r.s[r.pos] == ' ': inc(r.pos)
|
||||
outf.write("\n")
|
||||
of "FILES":
|
||||
inc(r.pos, 2) # skip "(\10"
|
||||
inc(r.line)
|
||||
outf.write("FILES(\n")
|
||||
while r.s[r.pos] != ')':
|
||||
let relativePath = decodeStr(r.s, r.pos)
|
||||
let resolvedPath = relativePath.findModule
|
||||
let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
|
||||
r.files.add(finalPath.fileInfoIdx)
|
||||
inc(r.pos) # skip #10
|
||||
inc(r.line)
|
||||
outf.writeln finalPath
|
||||
if r.s[r.pos] == ')': inc(r.pos)
|
||||
outf.write(")\n")
|
||||
of "INCLUDES":
|
||||
inc(r.pos, 2) # skip "(\10"
|
||||
inc(r.line)
|
||||
outf.write("INCLUDES(\n")
|
||||
while r.s[r.pos] != ')':
|
||||
let w = r.files[decodeVInt(r.s, r.pos)]
|
||||
inc(r.pos) # skip ' '
|
||||
let inclCrc = decodeVInt(r.s, r.pos)
|
||||
if r.s[r.pos] == '\x0A':
|
||||
inc(r.pos)
|
||||
inc(r.line)
|
||||
outf.write(w, " ", inclCrc, "\n")
|
||||
if r.s[r.pos] == ')': inc(r.pos)
|
||||
outf.write(")\n")
|
||||
of "DEPS":
|
||||
inc(r.pos) # skip ':'
|
||||
outf.write("DEPS:")
|
||||
while r.s[r.pos] > '\x0A':
|
||||
let v = int32(decodeVInt(r.s, r.pos))
|
||||
r.modDeps.add(r.files[v])
|
||||
if r.s[r.pos] == ' ': inc(r.pos)
|
||||
outf.write(" ", r.files[v])
|
||||
outf.write("\n")
|
||||
of "INTERF", "COMPILERPROCS":
|
||||
inc r.pos, 2
|
||||
if section == "INTERF": r.interfIdx = r.pos
|
||||
else: r.compilerProcsIdx = r.pos
|
||||
outf.write(section, "(\n")
|
||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||
let w = decodeStr(r.s, r.pos)
|
||||
inc(r.pos)
|
||||
let key = decodeVInt(r.s, r.pos)
|
||||
inc(r.pos) # #10
|
||||
outf.write(w, " ", key, "\n")
|
||||
if r.s[r.pos] == ')': inc r.pos
|
||||
outf.write(")\n")
|
||||
of "INDEX":
|
||||
outf.write(section, "(\n")
|
||||
processIndex(r, r.index, outf)
|
||||
outf.write(")\n")
|
||||
of "IMPORTS":
|
||||
outf.write(section, "(\n")
|
||||
processIndex(r, r.imports, outf)
|
||||
outf.write(")\n")
|
||||
of "CONVERTERS", "METHODS":
|
||||
inc r.pos
|
||||
if section == "METHODS": r.methodsIdx = r.pos
|
||||
else: r.convertersIdx = r.pos
|
||||
outf.write(section, ":")
|
||||
while r.s[r.pos] > '\x0A':
|
||||
let d = decodeVInt(r.s, r.pos)
|
||||
outf.write(" ", $d)
|
||||
if r.s[r.pos] == ' ': inc(r.pos)
|
||||
outf.write("\n")
|
||||
of "DATA":
|
||||
inc(r.pos, 2)
|
||||
r.dataIdx = r.pos
|
||||
outf.write("DATA(\n")
|
||||
while r.s[r.pos] != ')':
|
||||
if r.s[r.pos] == '(':
|
||||
outf.writeNode decodeNode(r, UnknownLineInfo())
|
||||
outf.write("\n")
|
||||
elif r.s[r.pos] == '[':
|
||||
outf.writeType decodeType(r, UnknownLineInfo())
|
||||
else:
|
||||
outf.writeSym decodeSym(r, UnknownLineInfo())
|
||||
if r.s[r.pos] == '\x0A':
|
||||
inc(r.pos)
|
||||
inc(r.line)
|
||||
if r.s[r.pos] == ')': inc r.pos
|
||||
outf.write(")\n")
|
||||
of "INIT":
|
||||
outf.write("INIT(\n")
|
||||
inc r.pos, 2
|
||||
r.initIdx = r.pos
|
||||
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||
let d = decodeVInt(r.s, r.pos)
|
||||
inc(r.pos) # #10
|
||||
#let p = r.pos
|
||||
#r.pos = d + r.dataIdx
|
||||
#outf.writeNode decodeNode(r, UnknownLineInfo())
|
||||
#outf.write("\n")
|
||||
#r.pos = p
|
||||
if r.s[r.pos] == ')': inc r.pos
|
||||
outf.write("<not supported by viewer>)\n")
|
||||
else:
|
||||
InternalError("invalid section: '" & section &
|
||||
"' at " & $r.line & " in " & r.filename)
|
||||
skipSection(r)
|
||||
if r.s[r.pos] == '\x0A':
|
||||
inc(r.pos)
|
||||
inc(r.line)
|
||||
outf.close
|
||||
|
||||
when isMainModule:
|
||||
viewFile(paramStr(1).addFileExt(rodExt))
|
||||
|
|
|
|||
0
compiler/rodutils.nim
Executable file → Normal file
0
compiler/rodutils.nim
Executable file → Normal file
3
compiler/rodwrite.nim
Executable file → Normal file
3
compiler/rodwrite.nim
Executable file → Normal file
|
|
@ -205,6 +205,9 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
|||
return
|
||||
# we need no surrounding [] here because the type is in a line of its own
|
||||
if t.kind == tyForward: InternalError("encodeType: tyForward")
|
||||
# for the new rodfile viewer we use a preceeding [ so that the data section
|
||||
# can easily be disambiguated:
|
||||
add(result, '[')
|
||||
encodeVInt(ord(t.kind), result)
|
||||
add(result, '+')
|
||||
encodeVInt(t.id, result)
|
||||
|
|
|
|||
0
compiler/ropes.nim
Executable file → Normal file
0
compiler/ropes.nim
Executable file → Normal file
18
compiler/sem.nim
Executable file → Normal file
18
compiler/sem.nim
Executable file → Normal file
|
|
@ -19,19 +19,15 @@ import
|
|||
|
||||
# implementation
|
||||
|
||||
type
|
||||
TExprFlag = enum
|
||||
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType
|
||||
TExprFlags = set[TExprFlag]
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.procvar.}
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.
|
||||
procvar.}
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode
|
||||
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semProcBody(c: PContext, n: PNode): PNode
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
||||
proc changeType(n: PNode, newType: PType)
|
||||
proc changeType(n: PNode, newType: PType, check: bool)
|
||||
|
||||
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
||||
|
|
@ -200,14 +196,12 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
|
|||
addSon(n, prc.ast)
|
||||
c.lastGenericIdx = c.generics.len
|
||||
|
||||
proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} =
|
||||
result = semExpr(c, n, {})
|
||||
|
||||
proc myOpen(module: PSym): PPassContext =
|
||||
var c = newContext(module)
|
||||
if c.p != nil: InternalError(module.info, "sem.myOpen")
|
||||
c.semConstExpr = semConstExpr
|
||||
c.semExpr = semExprNoFlags
|
||||
c.semExpr = semExpr
|
||||
c.semOperand = semOperand
|
||||
c.semConstBoolExpr = semConstBoolExpr
|
||||
c.semOverloadedCall = semOverloadedCall
|
||||
c.semTypeNode = semTypeNode
|
||||
|
|
|
|||
9
compiler/semcall.nim
Executable file → Normal file
9
compiler/semcall.nim
Executable file → Normal file
|
|
@ -85,7 +85,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
|||
#writeMatches(alt)
|
||||
if c.inCompilesContext > 0:
|
||||
# quick error message for performance of 'compiles' built-in:
|
||||
GlobalError(n.Info, errAmbiguousCallXYZ, "")
|
||||
GlobalError(n.Info, errGenerated, "ambiguous call")
|
||||
elif gErrorCounter == 0:
|
||||
# don't cascade errors
|
||||
var args = "("
|
||||
|
|
@ -174,7 +174,10 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
|||
# common case; check the only candidate has the right
|
||||
# number of generic type parameters:
|
||||
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
|
||||
return explicitGenericInstError(n)
|
||||
let expected = safeLen(s.ast.sons[genericParamsPos])
|
||||
LocalError(n.info, errGenerated, "cannot instantiate: " & renderTree(n) &
|
||||
"; got " & $(n.len-1) & " type(s) but expected " & $expected)
|
||||
return n
|
||||
result = explicitGenericSym(c, n, s)
|
||||
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
||||
# choose the generic proc with the proper number of type parameters.
|
||||
|
|
@ -204,7 +207,7 @@ proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym =
|
|||
call.add(newIdentNode(fn.name, fn.info))
|
||||
for i in 1.. <fn.typ.n.len:
|
||||
let param = fn.typ.n.sons[i]
|
||||
let t = skipTypes(param.typ, abstractVar)
|
||||
let t = skipTypes(param.typ, abstractVar-{tyTypeDesc})
|
||||
call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct))
|
||||
var resolved = semOverloadedCall(c, call, call, {fn.kind})
|
||||
if resolved != nil:
|
||||
|
|
|
|||
8
compiler/semdata.nim
Executable file → Normal file
8
compiler/semdata.nim
Executable file → Normal file
|
|
@ -40,6 +40,11 @@ type
|
|||
genericSym*: PSym
|
||||
inst*: PInstantiation
|
||||
|
||||
TExprFlag* = enum
|
||||
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
|
||||
efAllowDestructor
|
||||
TExprFlags* = set[TExprFlag]
|
||||
|
||||
PContext* = ref TContext
|
||||
TContext* = object of TPassContext # a context represents a module
|
||||
module*: PSym # the module sym belonging to the context
|
||||
|
|
@ -64,7 +69,8 @@ type
|
|||
# to some new symbol in a generic instantiation
|
||||
libs*: TLinkedList # all libs used by this module
|
||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
||||
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
||||
filter: TSymKinds): PNode {.nimcall.}
|
||||
|
|
|
|||
245
compiler/semexprs.nim
Executable file → Normal file
245
compiler/semexprs.nim
Executable file → Normal file
|
|
@ -10,18 +10,6 @@
|
|||
# this module does the semantic checking for expressions
|
||||
# included from sem.nim
|
||||
|
||||
proc restoreOldStyleType(n: PNode) =
|
||||
# XXX: semExprWithType used to return the same type
|
||||
# for nodes such as (100) or (int).
|
||||
# This is inappropriate. The type of the first expression
|
||||
# should be "int", while the type of the second one should
|
||||
# be typedesc(int).
|
||||
#
|
||||
# This is strictly for backward compatibility until
|
||||
# the transition to types as first-class values is complete.
|
||||
if n.typ.kind == tyTypeDesc and n.typ.sonsLen == 1:
|
||||
n.typ = n.typ.sons[0]
|
||||
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||
markUsed(n, s)
|
||||
pushInfoContext(n.info)
|
||||
|
|
@ -31,9 +19,38 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
|||
|
||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
|
||||
proc newDeref(n: PNode): PNode {.inline.} =
|
||||
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
|
||||
addSon(result, n)
|
||||
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||
var smoduleId = getModule(s).id
|
||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||
|
||||
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||
let n = n.skipConv
|
||||
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
|
||||
skConverter}:
|
||||
performProcvarCheck(c, n, n.sym)
|
||||
|
||||
proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} =
|
||||
if efAllowDestructor notin flags and n.kind in nkCallKinds+{nkObjConstr}:
|
||||
if instantiateDestructor(c, n.typ):
|
||||
LocalError(n.info, errGenerated,
|
||||
"usage of a type with a destructor in a non destructible context")
|
||||
|
||||
proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# same as 'semExprWithType' but doesn't check for proc vars
|
||||
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:
|
||||
# XXX tyGenericInst here?
|
||||
if result.typ.kind == tyVar: result = newDeref(result)
|
||||
else:
|
||||
LocalError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semExpr(c, n, flags)
|
||||
|
|
@ -42,7 +59,10 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
#raiseRecoverableError("")
|
||||
result = errorNode(c, n)
|
||||
if result.typ != nil:
|
||||
# XXX tyGenericInst here?
|
||||
semProcvarCheck(c, result)
|
||||
if result.typ.kind == tyVar: result = newDeref(result)
|
||||
semDestructorCheck(c, result, flags)
|
||||
else:
|
||||
LocalError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
|
|
@ -57,6 +77,9 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
LocalError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
else:
|
||||
semProcvarCheck(c, result)
|
||||
semDestructorCheck(c, result, flags)
|
||||
|
||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
|
|
@ -66,20 +89,11 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
|
|||
result.typ = s.typ
|
||||
result.info = n.info
|
||||
|
||||
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||
# XXX this not correct; it's valid to pass to templates and macros.
|
||||
# We really need another post nkCallConv check for this. Or maybe do it
|
||||
# in transform().
|
||||
var smoduleId = getModule(s).id
|
||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||
|
||||
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
case s.kind
|
||||
of skConst:
|
||||
markUsed(n, s)
|
||||
case skipTypes(s.typ, abstractInst).kind
|
||||
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
|
||||
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||
tyTuple, tySet, tyUInt..tyUInt64:
|
||||
result = inlineConst(n, s)
|
||||
|
|
@ -149,7 +163,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
|
|||
result = convNotNeedeed
|
||||
return
|
||||
var d = skipTypes(castDest, abstractVar)
|
||||
var s = skipTypes(src, abstractVar)
|
||||
var s = skipTypes(src, abstractVar-{tyTypeDesc})
|
||||
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
|
||||
d = base(d)
|
||||
s = base(s)
|
||||
|
|
@ -158,7 +172,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
|
|||
elif d.Kind == tyObject and s.Kind == tyObject:
|
||||
result = checkConversionBetweenObjects(d, s)
|
||||
elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
|
||||
(skipTypes(src, abstractVarRange).Kind in IntegralTypes):
|
||||
(skipTypes(src, abstractVarRange-{tyTypeDesc}).Kind in IntegralTypes):
|
||||
# accept conversion between integral types
|
||||
else:
|
||||
# we use d, s here to speed up that operation a bit:
|
||||
|
|
@ -185,7 +199,7 @@ proc isCastable(dst, src: PType): bool =
|
|||
else:
|
||||
result = (ds >= ss) or
|
||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||
(skipTypes(src, abstractInst).kind in IntegralTypes)
|
||||
(skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
|
||||
|
||||
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||
result = n.kind in nkSymChoices
|
||||
|
|
@ -238,15 +252,15 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
|||
LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
restoreOldStyleType(n.sons[1])
|
||||
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
case typ.Kind
|
||||
of tySequence, tyString, tyOpenArray, tyVarargs:
|
||||
n.typ = getSysType(tyInt)
|
||||
of tyArrayConstr, tyArray:
|
||||
n.typ = n.sons[1].typ.sons[0] # indextype
|
||||
n.typ = typ.sons[0] # indextype
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
|
||||
n.typ = n.sons[1].typ
|
||||
# do not skip the range!
|
||||
n.typ = n.sons[1].typ.skipTypes(abstractVar)
|
||||
else: LocalError(n.info, errInvalidArgForX, opToStr[m])
|
||||
result = n
|
||||
|
||||
|
|
@ -255,7 +269,7 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
|||
LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
n.typ = getSysType(tyInt)
|
||||
result = n
|
||||
|
||||
|
|
@ -265,10 +279,10 @@ proc semOf(c: PContext, n: PNode): PNode =
|
|||
n.sons[2] = semExprWithType(c, n.sons[2])
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[2])
|
||||
let a = skipTypes(n.sons[1].typ, typedescPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, typedescPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||
|
||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||
LocalError(n.info, errXExpectsObjectTypes, "of")
|
||||
|
|
@ -319,7 +333,7 @@ proc semIs(c: PContext, n: PNode): PNode =
|
|||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
const flags = {efDetermineType}
|
||||
for i in countup(1, n.sonsLen- 1):
|
||||
for i in countup(1, n.sonsLen-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||
var info = a.sons[0].info
|
||||
|
|
@ -340,11 +354,11 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
|||
for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i])
|
||||
result = semExpr(c, result)
|
||||
|
||||
proc changeType(n: PNode, newType: PType) =
|
||||
proc changeType(n: PNode, newType: PType, check: bool) =
|
||||
case n.kind
|
||||
of nkCurly, nkBracket:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
changeType(n.sons[i], elemType(newType))
|
||||
changeType(n.sons[i], elemType(newType), check)
|
||||
of nkPar:
|
||||
if newType.kind != tyTuple:
|
||||
InternalError(n.info, "changeType: no tuple type for constructor")
|
||||
|
|
@ -359,15 +373,21 @@ proc changeType(n: PNode, newType: PType) =
|
|||
if f == nil:
|
||||
internalError(m.info, "changeType(): invalid identifier")
|
||||
return
|
||||
changeType(n.sons[i].sons[1], f.typ)
|
||||
changeType(n.sons[i].sons[1], f.typ, check)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var m = n.sons[i]
|
||||
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
|
||||
addSon(a, newSymNode(newType.n.sons[i].sym))
|
||||
addSon(a, m)
|
||||
changeType(m, newType.sons[i])
|
||||
changeType(m, newType.sons[i], check)
|
||||
n.sons[i] = a
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if check:
|
||||
let value = n.intVal
|
||||
if value < firstOrd(newType) or value > lastOrd(newType):
|
||||
LocalError(n.info, errGenerated, "cannot convert " & $value &
|
||||
" to " & typeToString(newType))
|
||||
else: nil
|
||||
n.typ = newType
|
||||
|
||||
|
|
@ -384,7 +404,7 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
|
|||
typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
|
||||
result = typ
|
||||
|
||||
proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = newNodeI(nkBracket, n.info)
|
||||
result.typ = newTypeS(tyArrayConstr, c)
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
|
|
@ -413,7 +433,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
|
|||
localError(x.info, errInvalidOrderInArrayConstructor)
|
||||
x = x.sons[1]
|
||||
|
||||
n.sons[i] = semExprWithType(c, x)
|
||||
n.sons[i] = semExprWithType(c, x, flags*{efAllowDestructor})
|
||||
addSon(result, fitNode(c, typ, n.sons[i]))
|
||||
inc(lastIndex)
|
||||
addSonSkipIntLit(result.typ, typ)
|
||||
|
|
@ -447,11 +467,11 @@ proc fixAbstractType(c: PContext, n: PNode) =
|
|||
elif skipTypes(it.sons[1].typ, abstractVar).kind in
|
||||
{tyNil, tyArrayConstr, tyTuple, tySet}:
|
||||
var s = skipTypes(it.typ, abstractVar)
|
||||
changeType(it.sons[1], s)
|
||||
changeType(it.sons[1], s, check=true)
|
||||
n.sons[i] = it.sons[1]
|
||||
of nkBracket:
|
||||
# an implicitely constructed array (passed to an open array):
|
||||
n.sons[i] = semArrayConstr(c, it)
|
||||
n.sons[i] = semArrayConstr(c, it, {})
|
||||
else:
|
||||
nil
|
||||
#if (it.typ == nil):
|
||||
|
|
@ -485,7 +505,8 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
|||
case n.kind
|
||||
of nkSym:
|
||||
# n.sym.typ can be nil in 'check' mode ...
|
||||
if n.sym.typ != nil and skipTypes(n.sym.typ, abstractInst).kind != tyVar:
|
||||
if n.sym.typ != nil and
|
||||
skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||
incl(n.sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
of nkDotExpr:
|
||||
|
|
@ -493,16 +514,16 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
|||
if n.sons[1].kind != nkSym:
|
||||
internalError(n.info, "analyseIfAddressTaken")
|
||||
return
|
||||
if skipTypes(n.sons[1].sym.typ, abstractInst).kind != tyVar:
|
||||
if skipTypes(n.sons[1].sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||
incl(n.sons[1].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1)
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind != tyVar:
|
||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||
if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
else:
|
||||
result = newHiddenAddrTaken(c, n) # BUGFIX!
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
|
||||
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
checkMinSonsLen(n, 1)
|
||||
|
|
@ -517,16 +538,24 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
|||
|
||||
if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
|
||||
# BUGFIX: check for L-Value still needs to be done for the arguments!
|
||||
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
if i < sonsLen(t) and t.sons[i] != nil and
|
||||
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
|
||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||
if n.sons[i].kind != nkHiddenAddr:
|
||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||
return
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
if n.sons[i].kind == nkHiddenCallConv:
|
||||
# we need to recurse explicitly here as converters can create nested
|
||||
# calls and then they wouldn't be analysed otherwise
|
||||
analyseIfAddressTakenInCall(c, n.sons[i])
|
||||
semProcvarCheck(c, n.sons[i])
|
||||
if i < sonsLen(t) and
|
||||
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
||||
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
|
||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||
if n.sons[i].kind != nkHiddenAddr:
|
||||
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
|
||||
|
||||
include semmagic
|
||||
|
||||
|
|
@ -541,11 +570,12 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
|||
call.add(n.sons[0])
|
||||
var allConst = true
|
||||
for i in 1 .. < n.len:
|
||||
let a = getConstExpr(c.module, n.sons[i])
|
||||
if a != nil: call.add(a)
|
||||
else:
|
||||
var a = getConstExpr(c.module, n.sons[i])
|
||||
if a == nil:
|
||||
allConst = false
|
||||
call.add(n.sons[i])
|
||||
a = n.sons[i]
|
||||
if a.kind == nkHiddenStdConv: a = a.sons[1]
|
||||
call.add(a)
|
||||
if allConst:
|
||||
result = semfold.getConstExpr(c.module, call)
|
||||
if result.isNil: result = n
|
||||
|
|
@ -617,6 +647,7 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
|||
flags: TExprFlags): PNode =
|
||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = nil
|
||||
checkMinSonsLen(n, 1)
|
||||
|
|
@ -635,8 +666,9 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
let nOrig = n.copyTree
|
||||
semOpAux(c, n)
|
||||
var t: PType = nil
|
||||
if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst)
|
||||
if (t != nil) and (t.kind == tyProc):
|
||||
if n.sons[0].typ != nil:
|
||||
t = skipTypes(n.sons[0].typ, abstractInst-{tyTypedesc})
|
||||
if t != nil and t.kind == tyProc:
|
||||
# This is a proc variable, apply normal overload resolution
|
||||
var m: TCandidate
|
||||
initCandidate(m, t)
|
||||
|
|
@ -668,7 +700,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
# we assume that a procedure that calls something indirectly
|
||||
# has side-effects:
|
||||
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
||||
elif (t != nil) and t.kind == tyTypeDesc:
|
||||
elif t != nil and t.kind == tyTypeDesc:
|
||||
if n.len == 1: return semObjConstr(c, n, flags)
|
||||
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
||||
result = semConv(c, n, symFromType(destType, n.info))
|
||||
return
|
||||
|
|
@ -694,7 +727,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# this seems to be a hotspot in the compiler!
|
||||
let nOrig = n.copyTree
|
||||
semOpAux(c, n)
|
||||
#semLazyOpAux(c, n)
|
||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||
if result == nil:
|
||||
result = overloadedCallOpr(c, n)
|
||||
|
|
@ -706,6 +739,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee)
|
||||
else:
|
||||
semFinishOperands(c, n)
|
||||
activate(c, n)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
|
|
@ -714,7 +748,8 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc buildStringify(c: PContext, arg: PNode): PNode =
|
||||
if arg.typ != nil and skipTypes(arg.typ, abstractInst).kind == tyString:
|
||||
if arg.typ != nil and
|
||||
skipTypes(arg.typ, abstractInst-{tyTypeDesc}).kind == tyString:
|
||||
result = arg
|
||||
else:
|
||||
result = newNodeI(nkCall, arg.info)
|
||||
|
|
@ -752,7 +787,7 @@ proc discardCheck(result: PNode) =
|
|||
# XXX too much work and fixing would break bootstrapping:
|
||||
#Message(n.info, warnNilStatement)
|
||||
result.typ = nil
|
||||
elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError and
|
||||
elif not ImplicitlyDiscardable(result) and result.typ.kind != tyError and
|
||||
gCmd != cmdInteractive:
|
||||
localError(result.info, errDiscardValue)
|
||||
|
||||
|
|
@ -845,12 +880,13 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
return semSym(c, n, s, flags)
|
||||
|
||||
n.sons[0] = semExprWithType(c, n.sons[0], flags)
|
||||
restoreOldStyleType(n.sons[0])
|
||||
#restoreOldStyleType(n.sons[0])
|
||||
var i = considerAcc(n.sons[1])
|
||||
var ty = n.sons[0].typ
|
||||
var f: PSym = nil
|
||||
result = nil
|
||||
if isTypeExpr(n.sons[0]):
|
||||
if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.len == 1:
|
||||
if ty.kind == tyTypeDesc: ty = ty.sons[0]
|
||||
case ty.kind
|
||||
of tyEnum:
|
||||
# look up if the identifier belongs to the enum:
|
||||
|
|
@ -971,7 +1007,8 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
checkSonsLen(n, 2)
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i], flags)
|
||||
n.sons[i] = semExprWithType(c, n.sons[i],
|
||||
flags*{efInTypeof, efDetermineType})
|
||||
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||
if arg != nil:
|
||||
|
|
@ -1082,11 +1119,13 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
|||
localError(a.info, errXCannotBeAssignedTo,
|
||||
renderTree(a, {renderNoComments}))
|
||||
else:
|
||||
var
|
||||
rhs = semExprWithType(c, n.sons[1])
|
||||
let
|
||||
lhs = n.sons[0]
|
||||
if lhs.kind == nkSym and lhs.sym.kind == skResult and
|
||||
lhs.sym.typ.kind == tyGenericParam:
|
||||
lhsIsResult = lhs.kind == nkSym and lhs.sym.kind == skResult
|
||||
var
|
||||
rhs = semExprWithType(c, n.sons[1],
|
||||
if lhsIsResult: {efAllowDestructor} else: {})
|
||||
if lhsIsResult and lhs.sym.typ.kind == tyGenericParam:
|
||||
if matchTypeClass(lhs.typ, rhs.typ):
|
||||
InternalAssert c.p.resultSym != nil
|
||||
lhs.typ = rhs.typ
|
||||
|
|
@ -1128,7 +1167,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
|||
# ``result``:
|
||||
if result.kind == nkSym and result.sym == c.p.resultSym:
|
||||
nil
|
||||
elif result.kind == nkNilLit or ImplicitelyDiscardable(result):
|
||||
elif result.kind == nkNilLit or ImplicitlyDiscardable(result):
|
||||
# intended semantic: if it's 'discardable' and the context allows for it,
|
||||
# discard it. This is bad for chaining but nicer for C wrappers.
|
||||
# ambiguous :-(
|
||||
|
|
@ -1531,7 +1570,7 @@ proc checkPar(n: PNode): TParKind =
|
|||
LocalError(n.sons[i].info, errNamedExprNotAllowed)
|
||||
return paNone
|
||||
|
||||
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = newNodeI(nkPar, n.info)
|
||||
var typ = newTypeS(tyTuple, c)
|
||||
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
||||
|
|
@ -1545,7 +1584,8 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
|||
else: id = n.sons[i].sons[0].sym.name
|
||||
if ContainsOrIncl(ids, id.id):
|
||||
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
|
||||
flags*{efAllowDestructor})
|
||||
var f = newSymS(skField, n.sons[i].sons[0], c)
|
||||
f.typ = skipIntLit(n.sons[i].sons[1].typ)
|
||||
rawAddSon(typ, f.typ)
|
||||
|
|
@ -1554,14 +1594,56 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
|||
addSon(result, n.sons[i])
|
||||
result.typ = typ
|
||||
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode): PNode =
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n # we don't modify n, but compute the type:
|
||||
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i])
|
||||
n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
|
||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||
result.typ = typ
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var t = semTypeNode(c, n.sons[0], nil)
|
||||
result = n
|
||||
result.typ = t
|
||||
result.kind = nkObjConstr
|
||||
t = skipTypes(t, abstractInst)
|
||||
if t.kind == tyRef: t = skipTypes(t.sons[0], abstractInst)
|
||||
if t.kind != tyObject:
|
||||
localError(n.info, errGenerated, "object constructor needs an object type")
|
||||
return
|
||||
var ids = initIntSet()
|
||||
for i in 1.. <n.len:
|
||||
let it = n.sons[i]
|
||||
if it.kind != nkExprColonExpr or it.sons[0].kind notin {nkSym, nkIdent}:
|
||||
localError(n.info, errNamedExprExpected)
|
||||
break
|
||||
var id: PIdent
|
||||
if it.sons[0].kind == nkIdent: id = it.sons[0].ident
|
||||
else: id = it.sons[0].sym.name
|
||||
if ContainsOrIncl(ids, id.id):
|
||||
localError(it.info, errFieldInitTwice, id.s)
|
||||
var e = semExprWithType(c, it.sons[1], flags*{efAllowDestructor})
|
||||
var
|
||||
check: PNode = nil
|
||||
f: PSym
|
||||
while true:
|
||||
check = nil
|
||||
f = lookupInRecordAndBuildCheck(c, it, t.n, id, check)
|
||||
if f != nil: break
|
||||
if t.sons[0] == nil: break
|
||||
t = skipTypes(t.sons[0], {tyGenericInst})
|
||||
if f != nil and fieldVisible(c, f):
|
||||
it.sons[0] = newSymNode(f)
|
||||
e = fitNode(c, f.typ, e)
|
||||
# small hack here in a nkObjConstr the ``nkExprColonExpr`` node can have
|
||||
# 3 childen the last being the field check
|
||||
if check != nil: it.add(check)
|
||||
else:
|
||||
localError(it.info, errUndeclaredFieldX, id.s)
|
||||
it.sons[1] = e
|
||||
# XXX object field name check for 'case objects' if the kind is static?
|
||||
|
||||
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkMinSonsLen(n, 1)
|
||||
|
|
@ -1655,7 +1737,7 @@ proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
|||
proc fixImmediateParams(n: PNode): PNode =
|
||||
# XXX: Temporary work-around until we carry out
|
||||
# the planned overload resolution reforms
|
||||
for i in 1 .. <n.len:
|
||||
for i in 1 .. <safeLen(n):
|
||||
if n[i].kind == nkDo: n.sons[i] = n[i][bodyPos]
|
||||
|
||||
result = n
|
||||
|
|
@ -1690,7 +1772,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
semCaptureSym(s, c.p.owner)
|
||||
result = semSym(c, n, s, flags)
|
||||
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
||||
performProcvarCheck(c, n, s)
|
||||
#performProcvarCheck(c, n, s)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
if result.kind == nkSym:
|
||||
markIndirect(c, result.sym)
|
||||
|
|
@ -1769,6 +1851,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
# XXX think about this more (``set`` procs)
|
||||
if n.len == 2:
|
||||
result = semConv(c, n, s)
|
||||
elif n.len == 1:
|
||||
result = semObjConstr(c, n, flags)
|
||||
elif Contains(c.AmbiguousSymbols, s.id):
|
||||
LocalError(n.info, errUseQualifier, s.name.s)
|
||||
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||
|
|
@ -1807,11 +1891,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of nkPar:
|
||||
case checkPar(n)
|
||||
of paNone: result = errorNode(c, n)
|
||||
of paTuplePositions: result = semTuplePositionsConstr(c, n)
|
||||
of paTupleFields: result = semTupleFieldsConstr(c, n)
|
||||
of paTuplePositions: result = semTuplePositionsConstr(c, n, flags)
|
||||
of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
|
||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||
of nkCurly: result = semSetConstr(c, n)
|
||||
of nkBracket: result = semArrayConstr(c, n)
|
||||
of nkBracket: result = semArrayConstr(c, n, flags)
|
||||
of nkObjConstr: result = semObjConstr(c, n, flags)
|
||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||
of nkDerefExpr: result = semDeref(c, n)
|
||||
of nkAddr:
|
||||
|
|
|
|||
41
compiler/semfold.nim
Executable file → Normal file
41
compiler/semfold.nim
Executable file → Normal file
|
|
@ -458,16 +458,23 @@ proc getAppType(n: PNode): PNode =
|
|||
else:
|
||||
result = newStrNodeT("console", n)
|
||||
|
||||
proc foldConv*(n, a: PNode): PNode =
|
||||
proc rangeCheck(n: PNode, value: biggestInt) =
|
||||
if value < firstOrd(n.typ) or value > lastOrd(n.typ):
|
||||
LocalError(n.info, errGenerated, "cannot convert " & $value &
|
||||
" to " & typeToString(n.typ))
|
||||
|
||||
proc foldConv*(n, a: PNode; check = false): PNode =
|
||||
# XXX range checks?
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt..tyInt64:
|
||||
case skipTypes(a.typ, abstractRange).kind
|
||||
of tyFloat..tyFloat64: result = newIntNodeT(system.toInt(getFloat(a)), n)
|
||||
of tyFloat..tyFloat64:
|
||||
result = newIntNodeT(system.toInt(getFloat(a)), n)
|
||||
of tyChar: result = newIntNodeT(getOrdValue(a), n)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
if check: rangeCheck(n, result.intVal)
|
||||
of tyFloat..tyFloat64:
|
||||
case skipTypes(a.typ, abstractRange).kind
|
||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||
|
|
@ -490,7 +497,7 @@ proc getArrayConstr(m: PSym, n: PNode): PNode =
|
|||
|
||||
proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||
var x = getConstExpr(m, n.sons[0])
|
||||
if x == nil: return
|
||||
if x == nil or x.typ.skipTypes({tyGenericInst}).kind == tyTypeDesc: return
|
||||
|
||||
var y = getConstExpr(m, n.sons[1])
|
||||
if y == nil: return
|
||||
|
|
@ -519,10 +526,10 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
|||
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
||||
# a real field access; proc calls have already been transformed
|
||||
var x = getConstExpr(m, n.sons[0])
|
||||
if x == nil or x.kind != nkPar: return
|
||||
if x == nil or x.kind notin {nkObjConstr, nkPar}: return
|
||||
|
||||
var field = n.sons[1].sym
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
|
|
@ -542,6 +549,11 @@ proc foldConStrStr(m: PSym, n: PNode): PNode =
|
|||
if a == nil: return nil
|
||||
result.strVal.add(getStrOrChar(a))
|
||||
|
||||
proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
|
||||
result = newSymNode(s, info)
|
||||
result.typ = newType(tyTypeDesc, s.owner)
|
||||
result.typ.addSonSkipIntLit(s.typ)
|
||||
|
||||
proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = nil
|
||||
case n.kind
|
||||
|
|
@ -569,6 +581,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
|||
if sfFakeConst notin s.flags: result = copyTree(s.ast)
|
||||
elif s.kind in {skProc, skMethod}: # BUGFIX
|
||||
result = n
|
||||
elif s.kind in {skType, skGenericParam}:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
of nkCharLit..nkNilLit:
|
||||
result = copyNode(n)
|
||||
of nkIfExpr:
|
||||
|
|
@ -587,11 +601,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
|||
LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
||||
"sizeof")
|
||||
result = nil
|
||||
elif skipTypes(a.typ, abstractInst).kind in {tyArray,tyObject,tyTuple}:
|
||||
elif skipTypes(a.typ, typedescInst).kind in
|
||||
IntegralTypes+NilableTypes+{tySet}:
|
||||
#{tyArray,tyObject,tyTuple}:
|
||||
result = newIntNodeT(getSize(a.typ), n)
|
||||
else:
|
||||
result = nil
|
||||
# XXX: size computation for complex types is still wrong
|
||||
else:
|
||||
result = newIntNodeT(getSize(a.typ), n)
|
||||
of mLow:
|
||||
result = newIntNodeT(firstOrd(n.sons[1].typ), n)
|
||||
of mHigh:
|
||||
|
|
@ -647,6 +663,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
|||
if a == nil: return nil
|
||||
result.sons[i] = a
|
||||
incl(result.flags, nfAllConst)
|
||||
of nkObjConstr:
|
||||
result = copyTree(n)
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
var a = getConstExpr(m, n.sons[i].sons[1])
|
||||
if a == nil: return nil
|
||||
result.sons[i].sons[1] = a
|
||||
incl(result.flags, nfAllConst)
|
||||
of nkPar:
|
||||
# tuple constructor
|
||||
result = copyTree(n)
|
||||
|
|
@ -679,7 +702,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
|||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
|
||||
var a = getConstExpr(m, n.sons[1])
|
||||
if a == nil: return
|
||||
result = foldConv(n, a)
|
||||
result = foldConv(n, a, check=n.kind == nkHiddenStdConv)
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n)
|
||||
else:
|
||||
|
|
|
|||
8
compiler/semgnrc.nim
Executable file → Normal file
8
compiler/semgnrc.nim
Executable file → Normal file
|
|
@ -63,12 +63,12 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
|||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skGenericParam:
|
||||
result = newSymNode(s, n.info)
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
of skParam:
|
||||
result = n
|
||||
of skType:
|
||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||
result = newSymNode(s, n.info)
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
else:
|
||||
result = n
|
||||
else: result = newSymNode(s, n.info)
|
||||
|
|
@ -157,12 +157,12 @@ proc semGenericStmt(c: PContext, n: PNode,
|
|||
result.sons[0] = symChoice(c, n.sons[0], s, scOption)
|
||||
first = 1
|
||||
of skGenericParam:
|
||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||
result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
|
||||
first = 1
|
||||
of skType:
|
||||
# bad hack for generics:
|
||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||
result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
|
||||
first = 1
|
||||
else:
|
||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||
|
|
|
|||
0
compiler/seminst.nim
Executable file → Normal file
0
compiler/seminst.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -23,9 +23,10 @@ proc expectIntLit(c: PContext, n: PNode): int =
|
|||
proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkPar, n.info, n.typ)
|
||||
let idx = expectIntLit(c, n.sons[1])
|
||||
let useFullPaths = expectIntLit(c, n.sons[2])
|
||||
let info = getInfoContext(idx)
|
||||
var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
|
||||
filename.strVal = ToFilename(info)
|
||||
filename.strVal = if useFullPaths != 0: info.toFullPath else: info.ToFilename
|
||||
var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
|
||||
line.intVal = ToLinenumber(info)
|
||||
result.add(filename)
|
||||
|
|
@ -73,6 +74,33 @@ proc semBindSym(c: PContext, n: PNode): PNode =
|
|||
else:
|
||||
LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
|
||||
|
||||
proc semLocals(c: PContext, n: PNode): PNode =
|
||||
var counter = 0
|
||||
var tupleType = newTypeS(tyTuple, c)
|
||||
result = newNodeIT(nkPar, n.info, tupleType)
|
||||
tupleType.n = newNodeI(nkRecList, n.info)
|
||||
# for now we skip openarrays ...
|
||||
for i in countdown(c.tab.tos-1, ModuleTablePos+1):
|
||||
for it in items(c.tab.stack[i]):
|
||||
# XXX parameters' owners are wrong for generics; this caused some pain
|
||||
# for closures too; we should finally fix it.
|
||||
#if it.owner != c.p.owner: return result
|
||||
if it.kind in skLocalVars and
|
||||
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
|
||||
{tyVarargs, tyOpenArray, tyTypeDesc, tyExpr, tyStmt, tyEmpty}:
|
||||
|
||||
var field = newSym(skField, it.name, getCurrOwner(), n.info)
|
||||
field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
|
||||
field.position = counter
|
||||
inc(counter)
|
||||
|
||||
addSon(tupleType.n, newSymNode(field))
|
||||
addSonSkipIntLit(tupleType, field.typ)
|
||||
|
||||
var a = newSymNode(it, result.info)
|
||||
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
|
||||
result.add(a)
|
||||
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
|
|
@ -86,5 +114,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
|||
of mOrd: result = semOrd(c, n)
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mNBindSym: result = semBindSym(c, n)
|
||||
of mLocals: result = semLocals(c, n)
|
||||
else: result = n
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ import
|
|||
# Second semantic checking pass over the AST. Necessary because the old
|
||||
# way had some inherent problems. Performs:
|
||||
#
|
||||
# * procvar checks
|
||||
# * effect+exception tracking
|
||||
# * closure analysis
|
||||
# * checks for invalid usages of compiletime magics (not implemented)
|
||||
# * checks for invalid usages of PNimNode (not implemented)
|
||||
# * later: will do an escape analysis for closures at least
|
||||
|
|
|
|||
168
compiler/semstmts.nim
Executable file → Normal file
168
compiler/semstmts.nim
Executable file → Normal file
|
|
@ -119,11 +119,11 @@ proc semWhile(c: PContext, n: PNode): PNode =
|
|||
closeScope(c.tab)
|
||||
|
||||
proc toCover(t: PType): biggestInt =
|
||||
var t2 = skipTypes(t, abstractVarRange)
|
||||
var t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
|
||||
if t2.kind == tyEnum and enumHasHoles(t2):
|
||||
result = sonsLen(t2.n)
|
||||
else:
|
||||
result = lengthOrd(skipTypes(t, abstractVar))
|
||||
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
|
||||
|
||||
proc semCase(c: PContext, n: PNode): PNode =
|
||||
# check selector:
|
||||
|
|
@ -133,7 +133,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
|||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
var chckCovered = false
|
||||
var covered: biggestint = 0
|
||||
case skipTypes(n.sons[0].Typ, abstractVarRange).Kind
|
||||
case skipTypes(n.sons[0].Typ, abstractVarRange-{tyTypeDesc}).Kind
|
||||
of tyInt..tyInt64, tyChar, tyEnum:
|
||||
chckCovered = true
|
||||
of tyFloat..tyFloat128, tyString, tyError:
|
||||
|
|
@ -166,10 +166,10 @@ proc semCase(c: PContext, n: PNode): PNode =
|
|||
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||
result = fitNode(c, typ, n)
|
||||
if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
changeType(result.sons[1], typ)
|
||||
changeType(result.sons[1], typ, check=true)
|
||||
result = result.sons[1]
|
||||
elif not sameType(result.typ, typ):
|
||||
changeType(result, typ)
|
||||
changeType(result, typ, check=false)
|
||||
|
||||
proc findShadowedVar(c: PContext, v: PSym): PSym =
|
||||
for i in countdown(c.tab.tos - 2, ModuleTablePos+1):
|
||||
|
|
@ -207,7 +207,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
|||
typ = nil
|
||||
var def: PNode
|
||||
if a.sons[length-1].kind != nkEmpty:
|
||||
def = semExprWithType(c, a.sons[length-1])
|
||||
def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
|
||||
# BUGFIX: ``fitNode`` is needed here!
|
||||
# check type compability between def.typ and typ:
|
||||
if typ != nil: def = fitNode(c, typ, def)
|
||||
|
|
@ -301,52 +301,109 @@ proc semConst(c: PContext, n: PNode): PNode =
|
|||
addSon(b, copyTree(def))
|
||||
addSon(result, b)
|
||||
|
||||
proc transfFieldLoopBody(n: PNode, forLoop: PNode,
|
||||
tupleType: PType,
|
||||
tupleIndex, first: int): PNode =
|
||||
type
|
||||
TFieldInstCtx = object # either 'tup[i]' or 'field' is valid
|
||||
tupleType: PType # if != nil we're traversing a tuple
|
||||
tupleIndex: int
|
||||
field: PSym
|
||||
replaceByFieldName: bool
|
||||
|
||||
proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
case n.kind
|
||||
of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
|
||||
of nkIdent:
|
||||
result = n
|
||||
var L = sonsLen(forLoop)
|
||||
# field name:
|
||||
if first > 0:
|
||||
if c.replaceByFieldName:
|
||||
if n.ident.id == forLoop[0].ident.id:
|
||||
if tupleType.n == nil:
|
||||
# ugh, there are no field names:
|
||||
result = newStrNode(nkStrLit, "")
|
||||
else:
|
||||
result = newStrNode(nkStrLit, tupleType.n.sons[tupleIndex].sym.name.s)
|
||||
let fieldName = if c.tupleType.isNil: c.field.name.s
|
||||
elif c.tupleType.n.isNil: "Field" & $c.tupleIndex
|
||||
else: c.tupleType.n.sons[c.tupleIndex].sym.name.s
|
||||
result = newStrNode(nkStrLit, fieldName)
|
||||
return
|
||||
# other fields:
|
||||
for i in first..L-3:
|
||||
for i in ord(c.replaceByFieldName)..L-3:
|
||||
if n.ident.id == forLoop[i].ident.id:
|
||||
var call = forLoop.sons[L-2]
|
||||
var tupl = call.sons[i+1-first]
|
||||
result = newNodeI(nkBracketExpr, n.info)
|
||||
result.add(tupl)
|
||||
result.add(newIntNode(nkIntLit, tupleIndex))
|
||||
var tupl = call.sons[i+1-ord(c.replaceByFieldName)]
|
||||
if c.field.isNil:
|
||||
result = newNodeI(nkBracketExpr, n.info)
|
||||
result.add(tupl)
|
||||
result.add(newIntNode(nkIntLit, c.tupleIndex))
|
||||
else:
|
||||
result = newNodeI(nkDotExpr, n.info)
|
||||
result.add(tupl)
|
||||
result.add(newSymNode(c.field, n.info))
|
||||
break
|
||||
else:
|
||||
if n.kind == nkContinueStmt:
|
||||
localError(n.info, errGenerated,
|
||||
"'continue' not supported in a 'fields' loop")
|
||||
result = copyNode(n)
|
||||
newSons(result, sonsLen(n))
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
result.sons[i] = transfFieldLoopBody(n.sons[i], forLoop,
|
||||
tupleType, tupleIndex, first)
|
||||
result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
|
||||
|
||||
type
|
||||
TFieldsCtx = object
|
||||
c: PContext
|
||||
m: TMagic
|
||||
|
||||
proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
|
||||
case typ.kind
|
||||
of nkSym:
|
||||
var fc: TFieldInstCtx # either 'tup[i]' or 'field' is valid
|
||||
fc.field = typ.sym
|
||||
fc.replaceByFieldName = c.m == mFieldPairs
|
||||
openScope(c.c.tab)
|
||||
inc c.c.InUnrolledContext
|
||||
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
|
||||
father.add(SemStmt(c.c, body))
|
||||
dec c.c.InUnrolledContext
|
||||
closeScope(c.c.tab)
|
||||
of nkNilLit: nil
|
||||
of nkRecCase:
|
||||
let L = forLoop.len
|
||||
let call = forLoop.sons[L-2]
|
||||
if call.len > 2:
|
||||
LocalError(forLoop.info, errGenerated,
|
||||
"parallel 'fields' iterator does not work for 'case' objects")
|
||||
return
|
||||
# iterate over the selector:
|
||||
semForObjectFields(c, typ[0], forLoop, father)
|
||||
# we need to generate a case statement:
|
||||
var caseStmt = newNodeI(nkCaseStmt, forLoop.info)
|
||||
# generate selector:
|
||||
var access = newNodeI(nkDotExpr, forLoop.info, 2)
|
||||
access.sons[0] = call.sons[1]
|
||||
access.sons[1] = newSymNode(typ.sons[0].sym, forLoop.info)
|
||||
caseStmt.add(semExprWithType(c.c, access))
|
||||
# copy the branches over, but replace the fields with the for loop body:
|
||||
for i in 1 .. <typ.len:
|
||||
var branch = copyTree(typ[i])
|
||||
let L = branch.len
|
||||
branch.sons[L-1] = newNodeI(nkStmtList, forLoop.info)
|
||||
semForObjectFields(c, typ[i].lastSon, forLoop, branch[L-1])
|
||||
caseStmt.add(branch)
|
||||
father.add(caseStmt)
|
||||
of nkRecList:
|
||||
for t in items(typ): semForObjectFields(c, t, forLoop, father)
|
||||
else:
|
||||
illFormedAst(typ)
|
||||
|
||||
proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
# so that 'break' etc. work as expected, we produce
|
||||
# a 'while true: stmt; break' loop ...
|
||||
result = newNodeI(nkWhileStmt, n.info)
|
||||
result = newNodeI(nkWhileStmt, n.info, 2)
|
||||
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
|
||||
if trueSymbol == nil:
|
||||
LocalError(n.info, errSystemNeeds, "true")
|
||||
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
||||
trueSymbol.typ = getSysType(tyBool)
|
||||
|
||||
result.add(newSymNode(trueSymbol, n.info))
|
||||
result.sons[0] = newSymNode(trueSymbol, n.info)
|
||||
var stmts = newNodeI(nkStmtList, n.info)
|
||||
result.add(stmts)
|
||||
result.sons[1] = stmts
|
||||
|
||||
var length = sonsLen(n)
|
||||
var call = n.sons[length-2]
|
||||
|
|
@ -354,23 +411,34 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
|||
LocalError(n.info, errWrongNumberOfVariables)
|
||||
return result
|
||||
|
||||
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
|
||||
if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!")
|
||||
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
|
||||
if tupleTypeA.kind notin {tyTuple, tyObject}:
|
||||
localError(n.info, errGenerated, "no object or tuple type")
|
||||
return result
|
||||
for i in 1..call.len-1:
|
||||
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar)
|
||||
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
|
||||
if not SameType(tupleTypeA, tupleTypeB):
|
||||
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
|
||||
|
||||
Inc(c.p.nestedLoopCounter)
|
||||
var loopBody = n.sons[length-1]
|
||||
for i in 0..sonsLen(tupleTypeA)-1:
|
||||
openScope(c.tab)
|
||||
var body = transfFieldLoopBody(loopBody, n, tupleTypeA, i,
|
||||
ord(m==mFieldPairs))
|
||||
inc c.InUnrolledContext
|
||||
stmts.add(SemStmt(c, body))
|
||||
dec c.InUnrolledContext
|
||||
closeScope(c.tab)
|
||||
if tupleTypeA.kind == tyTuple:
|
||||
var loopBody = n.sons[length-1]
|
||||
for i in 0..sonsLen(tupleTypeA)-1:
|
||||
openScope(c.tab)
|
||||
var fc: TFieldInstCtx
|
||||
fc.tupleType = tupleTypeA
|
||||
fc.tupleIndex = i
|
||||
fc.replaceByFieldName = m == mFieldPairs
|
||||
var body = instFieldLoopBody(fc, loopBody, n)
|
||||
inc c.InUnrolledContext
|
||||
stmts.add(SemStmt(c, body))
|
||||
dec c.InUnrolledContext
|
||||
closeScope(c.tab)
|
||||
else:
|
||||
var fc: TFieldsCtx
|
||||
fc.m = m
|
||||
fc.c = c
|
||||
semForObjectFields(fc, tupleTypeA.n, n, stmts)
|
||||
Dec(c.p.nestedLoopCounter)
|
||||
var b = newNodeI(nkBreakStmt, n.info)
|
||||
b.add(ast.emptyNode)
|
||||
|
|
@ -416,10 +484,17 @@ proc semForVars(c: PContext, n: PNode): PNode =
|
|||
n.sons[length-1] = SemStmt(c, n.sons[length-1])
|
||||
Dec(c.p.nestedLoopCounter)
|
||||
|
||||
proc newDeref(n: PNode): PNode {.inline.} =
|
||||
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
|
||||
addSon(result, n)
|
||||
|
||||
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
||||
result = newNodeI(nkCall, arg.info)
|
||||
result.add(newIdentNode(it.getIdent, arg.info))
|
||||
result.add(arg)
|
||||
if arg.typ != nil and arg.typ.kind == tyVar:
|
||||
result.add newDeref(arg)
|
||||
else:
|
||||
result.add arg
|
||||
result = semExprNoDeref(c, result, {efWantIterator})
|
||||
|
||||
proc semFor(c: PContext, n: PNode): PNode =
|
||||
|
|
@ -705,8 +780,7 @@ proc activate(c: PContext, n: PNode) =
|
|||
# XXX: This proc is part of my plan for getting rid of
|
||||
# forward declarations. stay tuned.
|
||||
when false:
|
||||
# well for now it breaks code ... I added the test case in main.nim of the
|
||||
# compiler itself to break bootstrapping :P
|
||||
# well for now it breaks code ...
|
||||
case n.kind
|
||||
of nkLambdaKinds:
|
||||
discard semLambda(c, n, {})
|
||||
|
|
@ -994,7 +1068,7 @@ proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
|
|||
result = nil
|
||||
|
||||
proc generateDestructor(c: PContext, t: PType): PNode =
|
||||
## generate a destructor for a user-defined object ot tuple type
|
||||
## generate a destructor for a user-defined object or tuple type
|
||||
## returns nil if the destructor turns out to be trivial
|
||||
|
||||
template addLine(e: expr): stmt =
|
||||
|
|
@ -1029,7 +1103,7 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool =
|
|||
|
||||
if t.destructor != nil:
|
||||
# XXX: This is not entirely correct for recursive types, but we need
|
||||
# it temporarily to hide the "destroy is alrady defined" problem
|
||||
# it temporarily to hide the "destroy is already defined" problem
|
||||
return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
|
||||
|
||||
case t.kind
|
||||
|
|
@ -1071,8 +1145,8 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool =
|
|||
else:
|
||||
return false
|
||||
|
||||
proc insertDestructors(c: PContext, varSection: PNode):
|
||||
tuple[outer: PNode, inner: PNode] =
|
||||
proc insertDestructors(c: PContext,
|
||||
varSection: PNode): tuple[outer, inner: PNode] =
|
||||
# Accepts a var or let section.
|
||||
#
|
||||
# When a var section has variables with destructors
|
||||
|
|
@ -1128,7 +1202,7 @@ proc insertDestructors(c: PContext, varSection: PNode):
|
|||
|
||||
return
|
||||
|
||||
proc ImplicitelyDiscardable(n: PNode): bool =
|
||||
proc ImplicitlyDiscardable(n: PNode): bool =
|
||||
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
||||
sfDiscardable in n.sons[0].sym.flags
|
||||
|
||||
|
|
@ -1179,7 +1253,7 @@ proc semStmtList(c: PContext, n: PNode): PNode =
|
|||
# a statement list (s; e) has the type 'e':
|
||||
if result.kind == nkStmtList and result.len > 0:
|
||||
var lastStmt = lastSon(result)
|
||||
if lastStmt.kind != nkNilLit and not ImplicitelyDiscardable(lastStmt):
|
||||
if lastStmt.kind != nkNilLit and not ImplicitlyDiscardable(lastStmt):
|
||||
result.typ = lastStmt.typ
|
||||
#localError(lastStmt.info, errGenerated,
|
||||
# "Last expression must be explicitly returned if it " &
|
||||
|
|
|
|||
0
compiler/semtempl.nim
Executable file → Normal file
0
compiler/semtempl.nim
Executable file → Normal file
6
compiler/semthreads.nim
Executable file → Normal file
6
compiler/semthreads.nim
Executable file → Normal file
|
|
@ -311,6 +311,12 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
|||
# container construction:
|
||||
result = toNil # nothing until later
|
||||
for i in 0..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||
of nkObjConstr:
|
||||
if n.typ != nil and containsGarbageCollectedRef(n.typ):
|
||||
result = toMine
|
||||
else:
|
||||
result = toNil # nothing until later
|
||||
for i in 1..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||
of nkAddr, nkHiddenAddr:
|
||||
var a = lvalueSym(n)
|
||||
if a.kind == nkSym:
|
||||
|
|
|
|||
21
compiler/semtypes.nim
Executable file → Normal file
21
compiler/semtypes.nim
Executable file → Normal file
|
|
@ -45,7 +45,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
|||
e = newSymS(skEnumField, n.sons[i].sons[0], c)
|
||||
var v = semConstExpr(c, n.sons[i].sons[1])
|
||||
var strVal: PNode = nil
|
||||
case skipTypes(v.typ, abstractInst).kind
|
||||
case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind
|
||||
of tyTuple:
|
||||
if sonsLen(v) == 2:
|
||||
strVal = v.sons[1] # second tuple part is the string value
|
||||
|
|
@ -222,10 +222,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
|||
let bound = result.typ.sons[0].sym
|
||||
if bound != nil:
|
||||
return bound
|
||||
else:
|
||||
return result.typ.sym
|
||||
else:
|
||||
return result.typ.sym
|
||||
return result
|
||||
if result.typ.sym == nil:
|
||||
LocalError(n.info, errTypeExpected)
|
||||
return errorSym(c, n)
|
||||
return result.typ.sym
|
||||
if result.kind != skType:
|
||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||
var ov: TOverloadIter
|
||||
|
|
@ -323,8 +324,8 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode
|
|||
checkMinSonsLen(t, 1)
|
||||
let ac = semConstExpr(c, a)
|
||||
let bc = semConstExpr(c, b)
|
||||
let at = fitNode(c, t.sons[0].typ, ac)
|
||||
let bt = fitNode(c, t.sons[0].typ, bc)
|
||||
let at = fitNode(c, t.sons[0].typ, ac).skipConvTakeType
|
||||
let bt = fitNode(c, t.sons[0].typ, bc).skipConvTakeType
|
||||
|
||||
result = newNodeI(nkRange, a.info)
|
||||
result.add(at)
|
||||
|
|
@ -388,7 +389,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
|||
return
|
||||
incl(a.sons[0].sym.flags, sfDiscriminant)
|
||||
var covered: biggestInt = 0
|
||||
var typ = skipTypes(a.sons[0].Typ, abstractVar)
|
||||
var typ = skipTypes(a.sons[0].Typ, abstractVar-{tyTypeDesc})
|
||||
if not isOrdinalType(typ):
|
||||
LocalError(n.info, errSelectorMustBeOrdinal)
|
||||
elif firstOrd(typ) < 0:
|
||||
|
|
@ -873,6 +874,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
if s.typ == nil:
|
||||
if s.kind != skError: LocalError(n.info, errTypeExpected)
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
elif s.kind == skParam and s.typ.kind == tyTypeDesc:
|
||||
assert s.typ.len > 0
|
||||
InternalAssert prev == nil
|
||||
result = s.typ.sons[0]
|
||||
elif prev == nil:
|
||||
result = s.typ
|
||||
else:
|
||||
|
|
|
|||
0
compiler/semtypinst.nim
Executable file → Normal file
0
compiler/semtypinst.nim
Executable file → Normal file
|
|
@ -73,6 +73,9 @@ proc serve*(action: proc (){.nimcall.}) =
|
|||
var line = stdin.readLine.string
|
||||
if line == "quit": quit()
|
||||
execute line
|
||||
echo ""
|
||||
FlushFile(stdout)
|
||||
|
||||
of "tcp", "":
|
||||
var server = Socket()
|
||||
let p = getConfigVar("server.port")
|
||||
|
|
@ -83,11 +86,10 @@ proc serve*(action: proc (){.nimcall.}) =
|
|||
new(stdoutSocket)
|
||||
while true:
|
||||
accept(server, stdoutSocket)
|
||||
discard stdoutSocket.recvLine(inp)
|
||||
stdoutSocket.readLine(inp)
|
||||
execute inp.string
|
||||
stdoutSocket.send("\c\L")
|
||||
stdoutSocket.close()
|
||||
else:
|
||||
echo "Invalid server.type:", typ
|
||||
quit 1
|
||||
|
||||
|
|
|
|||
118
compiler/sigmatch.nim
Executable file → Normal file
118
compiler/sigmatch.nim
Executable file → Normal file
|
|
@ -97,6 +97,45 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
|||
a.baseTypeMatch = b.baseTypeMatch
|
||||
copyIdTable(a.bindings, b.bindings)
|
||||
|
||||
proc sumGeneric(t: PType): int =
|
||||
var t = t
|
||||
while true:
|
||||
case t.kind
|
||||
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyArrayConstr,
|
||||
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody:
|
||||
t = t.lastSon
|
||||
inc result
|
||||
of tyVar:
|
||||
# but do not make 'var T' more specific than 'T'!
|
||||
t = t.sons[0]
|
||||
of tyGenericInvokation, tyTuple:
|
||||
result = ord(t.kind == tyGenericInvokation)
|
||||
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||
break
|
||||
of tyGenericParam, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: break
|
||||
else: return 0
|
||||
|
||||
proc complexDisambiguation(a, b: PType): int =
|
||||
var x, y: int
|
||||
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
|
||||
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
|
||||
result = x - y
|
||||
when false:
|
||||
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
|
||||
|
||||
if a.len > 1 and b.len > 1:
|
||||
let aa = a.sons[1].sumGeneric
|
||||
let bb = b.sons[1].sumGeneric
|
||||
var a = a
|
||||
var b = b
|
||||
|
||||
if aa < bb: swap(a, b)
|
||||
# all must be better
|
||||
for i in 2 .. <min(a.len, b.len):
|
||||
if not a.sons[i].betterThan(b.sons[i]): return 0
|
||||
# a must be longer or of the same length as b:
|
||||
result = a.len - b.len
|
||||
|
||||
proc cmpCandidates*(a, b: TCandidate): int =
|
||||
result = a.exactMatches - b.exactMatches
|
||||
if result != 0: return
|
||||
|
|
@ -110,9 +149,12 @@ proc cmpCandidates*(a, b: TCandidate): int =
|
|||
if result != 0: return
|
||||
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
||||
result = a.calleeScope - b.calleeScope
|
||||
if result != 0: return
|
||||
if result != 0: return
|
||||
# the other way round because of other semantics:
|
||||
result = b.inheritancePenalty - a.inheritancePenalty
|
||||
if result != 0: return
|
||||
# prefer more specialized generic over more general generic:
|
||||
result = complexDisambiguation(a.callee, b.callee)
|
||||
|
||||
proc writeMatches*(c: TCandidate) =
|
||||
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
||||
|
|
@ -130,11 +172,18 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
|||
GlobalError(n.info, errTypeMismatch, "")
|
||||
var result = msgKindToString(errTypeMismatch)
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
#debug(n.sons[i].typ)
|
||||
var nt = n.sons[i].typ
|
||||
if n.sons[i].kind == nkExprEqExpr:
|
||||
add(result, renderTree(n.sons[i].sons[0]))
|
||||
add(result, ": ")
|
||||
let nt = n.sons[i].typ
|
||||
if nt.isNil:
|
||||
n.sons[i].sons[1] = c.semOperand(c, n.sons[i].sons[1])
|
||||
nt = n.sons[i].sons[1].typ
|
||||
n.sons[i].typ = nt
|
||||
else:
|
||||
if nt.isNil:
|
||||
n.sons[i] = c.semOperand(c, n.sons[i])
|
||||
nt = n.sons[i].typ
|
||||
if nt.kind == tyError: return
|
||||
add(result, typeToString(nt))
|
||||
if i != sonsLen(n) - 1: add(result, ", ")
|
||||
|
|
@ -146,7 +195,6 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
|||
if sym.kind in RoutineKinds:
|
||||
add(candidates, getProcHeader(sym))
|
||||
add(candidates, "\n")
|
||||
#debug(sym.typ)
|
||||
sym = nextOverloadIter(o, c, n.sons[0])
|
||||
if candidates != "":
|
||||
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
||||
|
|
@ -314,6 +362,22 @@ proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
|
|||
result = if matchTypeClass(c.bindings, f, a): isGeneric
|
||||
else: isNone
|
||||
|
||||
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
||||
let
|
||||
a0 = firstOrd(a)
|
||||
a1 = lastOrd(a)
|
||||
f0 = firstOrd(f)
|
||||
f1 = lastOrd(f)
|
||||
if a0 == f0 and a1 == f1:
|
||||
result = isEqual
|
||||
elif a0 >= f0 and a1 <= f1:
|
||||
result = isConvertible
|
||||
elif a0 <= f1 and f0 <= a1:
|
||||
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||
result = isConvertible
|
||||
else:
|
||||
result = isNone
|
||||
|
||||
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
# is a subtype of f?
|
||||
result = isNone
|
||||
|
|
@ -338,6 +402,8 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
|||
result = typeRel(c, base(f), base(a))
|
||||
# bugfix: accept integer conversions here
|
||||
#if result < isGeneric: result = isNone
|
||||
if result notin {isNone, isGeneric}:
|
||||
result = typeRangeRel(f, a)
|
||||
elif skipTypes(f, {tyRange}).kind == a.kind:
|
||||
result = isIntConv
|
||||
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
|
||||
|
|
@ -655,7 +721,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
|||
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
|
||||
of isSubrange:
|
||||
inc(m.subtypeMatches)
|
||||
result = copyTree(arg)
|
||||
#result = copyTree(arg)
|
||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||
of isGeneric:
|
||||
inc(m.genericMatches)
|
||||
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
|
||||
|
|
@ -669,7 +736,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
|||
result = copyTree(arg)
|
||||
result.typ = getInstantiatedType(c, arg, m, f)
|
||||
# BUG: f may not be the right key!
|
||||
if skipTypes(result.typ, abstractVar).kind in {tyTuple}:
|
||||
if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||
# BUGFIX: use ``result.typ`` and not `f` here
|
||||
of isFromIntLit:
|
||||
|
|
@ -680,7 +747,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
|||
of isEqual:
|
||||
inc(m.exactMatches)
|
||||
result = copyTree(arg)
|
||||
if skipTypes(f, abstractVar).kind in {tyTuple}:
|
||||
if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||
of isNone:
|
||||
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
||||
|
|
@ -756,6 +823,28 @@ proc setSon(father: PNode, at: int, son: PNode) =
|
|||
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
||||
father.sons[at] = son
|
||||
|
||||
# we are allowed to modify the calling node in the 'prepare*' procs:
|
||||
proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
|
||||
if formal.kind == tyExpr and formal.len != 1:
|
||||
# {tyTypeDesc, tyExpr, tyStmt, tyProxy}:
|
||||
# a.typ == nil is valid
|
||||
result = a
|
||||
elif a.typ.isNil:
|
||||
result = c.semOperand(c, a, {efDetermineType})
|
||||
else:
|
||||
result = a
|
||||
|
||||
proc prepareOperand(c: PContext; a: PNode): PNode =
|
||||
if a.typ.isNil:
|
||||
result = c.semOperand(c, a, {efDetermineType})
|
||||
else:
|
||||
result = a
|
||||
|
||||
proc prepareNamedParam(a: PNode) =
|
||||
if a.sons[0].kind != nkIdent:
|
||||
var info = a.sons[0].info
|
||||
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
|
||||
|
||||
proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
m: var TCandidate, marker: var TIntSet) =
|
||||
template checkConstraint(n: expr) {.immediate, dirty.} =
|
||||
|
|
@ -780,6 +869,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
if n.sons[a].kind == nkExprEqExpr:
|
||||
# named param
|
||||
# check if m.callee has such a param:
|
||||
prepareNamedParam(n.sons[a])
|
||||
if n.sons[a].sons[0].kind != nkIdent:
|
||||
LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
|
||||
m.state = csNoMatch
|
||||
|
|
@ -795,6 +885,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
m.state = csNoMatch
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
|
||||
n.sons[a].typ = n.sons[a].sons[1].typ
|
||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a].sons[1], nOrig.sons[a].sons[1])
|
||||
if arg == nil:
|
||||
|
|
@ -815,13 +907,16 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
# too many arguments?
|
||||
if tfVarArgs in m.callee.flags:
|
||||
# is ok... but don't increment any counters...
|
||||
if skipTypes(n.sons[a].typ, abstractVar).kind == tyString:
|
||||
# we have no formal here to snoop at:
|
||||
n.sons[a] = prepareOperand(c, n.sons[a])
|
||||
if skipTypes(n.sons[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
|
||||
addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString),
|
||||
copyTree(n.sons[a]), m, c))
|
||||
else:
|
||||
addSon(m.call, copyTree(n.sons[a]))
|
||||
elif formal != nil:
|
||||
m.baseTypeMatch = false
|
||||
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a], nOrig.sons[a])
|
||||
if (arg != nil) and m.baseTypeMatch and (container != nil):
|
||||
|
|
@ -843,6 +938,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
m.state = csNoMatch
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a], nOrig.sons[a])
|
||||
if arg == nil:
|
||||
|
|
@ -861,6 +957,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
inc(a)
|
||||
inc(f)
|
||||
|
||||
proc semFinishOperands*(c: PContext, n: PNode) =
|
||||
# this needs to be called to ensure that after overloading resolution every
|
||||
# argument has been sem'checked:
|
||||
for i in 1 .. <n.len:
|
||||
n.sons[i] = prepareOperand(c, n.sons[i])
|
||||
|
||||
proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
# for 'suggest' support:
|
||||
var marker = initIntSet()
|
||||
|
|
|
|||
0
compiler/suggest.nim
Executable file → Normal file
0
compiler/suggest.nim
Executable file → Normal file
0
compiler/syntaxes.nim
Executable file → Normal file
0
compiler/syntaxes.nim
Executable file → Normal file
0
compiler/tccgen.nim
Executable file → Normal file
0
compiler/tccgen.nim
Executable file → Normal file
7
compiler/transf.nim
Executable file → Normal file
7
compiler/transf.nim
Executable file → Normal file
|
|
@ -323,10 +323,10 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
|||
of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32:
|
||||
# we don't include uint and uint64 here as these are no ordinal types ;-)
|
||||
if not isOrdinalType(source):
|
||||
# XXX int64 -> float conversion?
|
||||
# float -> int conversions. ugh.
|
||||
result = transformSons(c, n)
|
||||
elif firstOrd(dest) <= firstOrd(source) and
|
||||
lastOrd(source) <= lastOrd(dest):
|
||||
elif firstOrd(n.typ) <= firstOrd(n.sons[1].typ) and
|
||||
lastOrd(n.sons[1].typ) <= lastOrd(n.typ):
|
||||
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
||||
# but no range check:
|
||||
result = transformSons(c, n)
|
||||
|
|
@ -341,6 +341,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
|||
result[1] = newIntTypeNode(nkIntLit, firstOrd(dest), source).PTransNode
|
||||
result[2] = newIntTypeNode(nkIntLit, lastOrd(dest), source).PTransNode
|
||||
of tyFloat..tyFloat128:
|
||||
# XXX int64 -> float conversion?
|
||||
if skipTypes(n.typ, abstractVar).kind == tyRange:
|
||||
result = newTransNode(nkChckRangeF, n, 3)
|
||||
dest = skipTypes(n.typ, abstractVar)
|
||||
|
|
|
|||
2
compiler/trees.nim
Executable file → Normal file
2
compiler/trees.nim
Executable file → Normal file
|
|
@ -115,7 +115,7 @@ proc isDeepConstExpr*(n: PNode): bool =
|
|||
result = true
|
||||
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||
result = isDeepConstExpr(n.sons[1])
|
||||
of nkCurly, nkBracket, nkPar, nkClosure:
|
||||
of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure:
|
||||
for i in 0 .. <n.len:
|
||||
if not isDeepConstExpr(n.sons[i]): return false
|
||||
result = true
|
||||
|
|
|
|||
0
compiler/treetab.nim
Executable file → Normal file
0
compiler/treetab.nim
Executable file → Normal file
82
compiler/types.nim
Executable file → Normal file
82
compiler/types.nim
Executable file → Normal file
|
|
@ -49,16 +49,18 @@ proc isOrdinalType*(t: PType): bool
|
|||
proc enumHasHoles*(t: PType): bool
|
||||
const
|
||||
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
||||
tyConst, tyMutable}
|
||||
tyConst, tyMutable, tyTypeDesc}
|
||||
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
|
||||
tyConst, tyMutable}
|
||||
tyConst, tyMutable, tyTypeDesc}
|
||||
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal,
|
||||
tyConst, tyMutable}
|
||||
tyConst, tyMutable, tyTypeDesc}
|
||||
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||
tyConst, tyMutable}
|
||||
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal}
|
||||
tyConst, tyMutable, tyTypeDesc}
|
||||
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
|
||||
tyTypeDesc}
|
||||
|
||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable}
|
||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable,
|
||||
tyTypeDesc}
|
||||
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
||||
typedescInst* = abstractInst + {tyTypeDesc}
|
||||
|
||||
|
|
@ -327,7 +329,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
|||
result = false
|
||||
if typ == nil: return
|
||||
if tfAcyclic in typ.flags: return
|
||||
var t = skipTypes(typ, abstractInst)
|
||||
var t = skipTypes(typ, abstractInst-{tyTypeDesc})
|
||||
if tfAcyclic in t.flags: return
|
||||
case t.kind
|
||||
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
|
||||
|
|
@ -344,11 +346,10 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
|||
#if t.kind == tyObject and tfFinal notin t.flags:
|
||||
# # damn inheritance may introduce cycles:
|
||||
# result = true
|
||||
of tyProc: result = typ.callConv == ccClosure
|
||||
else: nil
|
||||
|
||||
proc canFormAcycle(typ: PType): bool =
|
||||
# XXX as I expect cycles introduced by closures are very rare, we pretend
|
||||
# they can't happen here.
|
||||
var marker = InitIntSet()
|
||||
result = canFormAcycleAux(marker, typ, typ.id)
|
||||
|
||||
|
|
@ -393,26 +394,31 @@ proc rangeToStr(n: PNode): string =
|
|||
assert(n.kind == nkRange)
|
||||
result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
|
||||
|
||||
const
|
||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
|
||||
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"float", "float32", "float64", "float128",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"bignum", "const ",
|
||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"]
|
||||
|
||||
proc consToStr(t: PType): string =
|
||||
if t.len > 0: result = t.typeToString
|
||||
else: result = typeToStr[t.kind].strip
|
||||
|
||||
proc constraintsToStr(t: PType): string =
|
||||
let sep = if tfAny in t.flags: " or " else: " and "
|
||||
result = ""
|
||||
for i in countup(0, t.sons.len - 1):
|
||||
for i in countup(0, t.len - 1):
|
||||
if i > 0: result.add(sep)
|
||||
result.add(t.sons[i].typeToString)
|
||||
result.add(t.sons[i].consToStr)
|
||||
|
||||
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
const
|
||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
|
||||
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"float", "float32", "float64", "float128",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"bignum", "const ",
|
||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"]
|
||||
var t = typ
|
||||
result = ""
|
||||
if t == nil: return
|
||||
|
|
@ -433,12 +439,15 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
|||
add(result, typeToString(t.sons[i]))
|
||||
add(result, ']')
|
||||
of tyTypeDesc:
|
||||
if t.sons == nil or t.sons.len == 0: result = "typedesc"
|
||||
if t.len == 0: result = "typedesc"
|
||||
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
||||
of tyTypeClass:
|
||||
result = constraintsToStr(t)
|
||||
case t.len
|
||||
of 0: result = "typeclass[]"
|
||||
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
|
||||
else: result = constraintsToStr(t)
|
||||
of tyExpr:
|
||||
if t.sons.len == 0: result = "expr"
|
||||
if t.len == 0: result = "expr"
|
||||
else: result = "expr[" & constraintsToStr(t) & "]"
|
||||
of tyArray:
|
||||
if t.sons[0].kind == tyRange:
|
||||
|
|
@ -477,7 +486,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
|||
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
||||
result = typeToStr[t.kind] & typeToString(t.sons[0])
|
||||
of tyRange:
|
||||
result = "range " & rangeToStr(t.n)
|
||||
result = "range " & rangeToStr(t.n) & "(" & typeToString(t.sons[0]) & ")"
|
||||
of tyProc:
|
||||
result = if tfIterator in t.flags: "iterator (" else: "proc ("
|
||||
for i in countup(1, sonsLen(t) - 1):
|
||||
|
|
@ -534,7 +543,7 @@ proc firstOrd(t: PType): biggestInt =
|
|||
else:
|
||||
assert(t.n.sons[0].kind == nkSym)
|
||||
result = t.n.sons[0].sym.position
|
||||
of tyGenericInst, tyDistinct, tyConst, tyMutable:
|
||||
of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc:
|
||||
result = firstOrd(lastSon(t))
|
||||
else:
|
||||
InternalError("invalid kind for first(" & $t.kind & ')')
|
||||
|
|
@ -567,7 +576,7 @@ proc lastOrd(t: PType): biggestInt =
|
|||
of tyEnum:
|
||||
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
||||
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
||||
of tyGenericInst, tyDistinct, tyConst, tyMutable:
|
||||
of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc:
|
||||
result = lastOrd(lastSon(t))
|
||||
of tyProxy: result = 0
|
||||
else:
|
||||
|
|
@ -833,7 +842,8 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
of tyGenericInst:
|
||||
result = sameTypeAux(lastSon(a), lastSon(b), c)
|
||||
of tyTypeDesc:
|
||||
if TypeDescExactMatch in c.flags:
|
||||
if c.cmp == dcEqIgnoreDistinct: result = false
|
||||
elif TypeDescExactMatch in c.flags:
|
||||
CycleCheck()
|
||||
result = sameChildrenAux(x, y, c) and sameFlags(a, b)
|
||||
else:
|
||||
|
|
@ -938,7 +948,8 @@ proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool =
|
|||
of tyTypeClass:
|
||||
match = matchTypeClass(bindings, req, t)
|
||||
else: nil
|
||||
elif t.kind in {tyObject}:
|
||||
elif t.kind in {tyObject} and req.len != 0:
|
||||
# empty 'object' is fine as constraint in a type class
|
||||
match = sameType(t, req)
|
||||
|
||||
if tfAny in typeClass.flags:
|
||||
|
|
@ -962,11 +973,11 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
|||
result = true
|
||||
if typ == nil: return
|
||||
if ContainsOrIncl(marker, typ.id): return
|
||||
var t = skipTypes(typ, abstractInst)
|
||||
var t = skipTypes(typ, abstractInst-{tyTypeDesc})
|
||||
case t.kind
|
||||
of tyVar:
|
||||
if kind == skConst: return false
|
||||
var t2 = skipTypes(t.sons[0], abstractInst)
|
||||
var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
|
||||
case t2.kind
|
||||
of tyVar:
|
||||
result = false # ``var var`` is always an invalid type:
|
||||
|
|
@ -982,6 +993,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
|||
result = typeAllowedAux(marker, t.sons[0], skResult)
|
||||
of tyExpr, tyStmt, tyTypeDesc:
|
||||
result = true
|
||||
# XXX er ... no? these should not be allowed!
|
||||
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation,
|
||||
tyTypeClass:
|
||||
result = false
|
||||
|
|
@ -994,7 +1006,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
|||
of tyGenericInst, tyDistinct:
|
||||
result = typeAllowedAux(marker, lastSon(t), kind)
|
||||
of tyRange:
|
||||
result = skipTypes(t.sons[0], abstractInst).kind in
|
||||
result = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind in
|
||||
{tyChar, tyEnum, tyInt..tyFloat128}
|
||||
of tyOpenArray, tyVarargs:
|
||||
result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
|
||||
|
|
@ -1162,6 +1174,8 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
|
|||
result = align(result, a)
|
||||
of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
|
||||
result = computeSizeAux(lastSon(typ), a)
|
||||
of tyTypeDesc:
|
||||
result = (if typ.len == 1: computeSizeAux(typ.sons[0], a) else: -1)
|
||||
of tyProxy: result = 1
|
||||
else:
|
||||
#internalError("computeSizeAux()")
|
||||
|
|
|
|||
0
compiler/wordrecg.nim
Executable file → Normal file
0
compiler/wordrecg.nim
Executable file → Normal file
0
config/nimdoc.cfg
Executable file → Normal file
0
config/nimdoc.cfg
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue