Merge branch 'devel' into experimentalize-reorder

This commit is contained in:
awr1
2018-09-04 16:33:52 -05:00
committed by GitHub
241 changed files with 6388 additions and 12619 deletions

6
.gitignore vendored
View File

@@ -48,7 +48,10 @@ xcuserdata/
/compiler/nimrod.dot
/reject.json
/run.json
/testresults.html
# for `nim doc foo.nim`
/*.html
#/testresults.html #covered by /*.html
/testresults.json
testament.db
/csources
@@ -62,3 +65,4 @@ dist/
testresults/
test.txt
/test.ini

View File

@@ -50,4 +50,4 @@ script:
- ./koch web
- ./koch csource
- ./koch nimsuggest
# - nim c -r nimsuggest/tester
- nim c -r nimsuggest/tester

View File

@@ -72,6 +72,7 @@
- ``lineInfoObj`` now returns absolute path instead of project path.
It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc.
- ``net.sendTo`` no longer returns an int and now raises an ``OSError``.
- `threadpool`'s `await` and derivatives have been renamed to `blockUntil`
to avoid confusions with `await` from the `async` macro.
@@ -107,6 +108,7 @@
- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt``.
- Added the proc ``flush`` for memory mapped files.
- Added the ``MemMapFileStream``.
- Added a simple interpreting event parser template ``eventParser`` to the ``pegs`` module.
- Added ``macros.copyLineInfo`` to copy lineInfo from other node.
- Added ``system.ashr`` an arithmetic right shift for integers.
@@ -139,6 +141,8 @@
- The ``pegs`` module now exports getters for the fields of its ``Peg`` and ``NonTerminal``
object types. ``Peg``s with child nodes now have the standard ``items`` and ``pairs``
iterators.
- The ``accept`` socket procedure defined in the ``net`` module can now accept
a nil socket.
### Language additions

View File

@@ -628,6 +628,7 @@ type
mIsPartOf, mAstToStr, mParallel,
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved,
mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
@@ -656,7 +657,7 @@ type
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo,
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
mException, mBuiltinType
mException, mBuiltinType, mSymOwner
# things that we can evaluate safely at compile time, even if not asked for it:
const
@@ -1020,13 +1021,16 @@ proc isCallExpr*(n: PNode): bool =
proc discardSons*(father: PNode)
proc len*(n: PNode): int {.inline.} =
if isNil(n.sons): result = 0
else: result = len(n.sons)
when defined(nimNoNilSeqs):
result = len(n.sons)
else:
if isNil(n.sons): result = 0
else: result = len(n.sons)
proc safeLen*(n: PNode): int {.inline.} =
## works even for leaves.
if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0
else: result = len(n.sons)
if n.kind in {nkNone..nkNilLit}: result = 0
else: result = len(n)
proc safeArrLen*(n: PNode): int {.inline.} =
## works for array-like objects (strings passed as openArray in VM).
@@ -1036,7 +1040,8 @@ proc safeArrLen*(n: PNode): int {.inline.} =
proc add*(father, son: PNode) =
assert son != nil
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
type Indexable = PNode | PType
@@ -1088,9 +1093,9 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
result.id = getID()
when debugIds:
registerId(result)
#if result.id == 93289:
#if result.id == 77131:
# writeStacktrace()
# MessageOut(name.s & " has id: " & toString(result.id))
# echo name.s
proc isMetaType*(t: PType): bool =
return t.kind in tyMetaTypes or
@@ -1134,19 +1139,16 @@ const # for all kind of hash tables:
proc copyStrTable*(dest: var TStrTable, src: TStrTable) =
dest.counter = src.counter
if isNil(src.data): return
setLen(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
proc copyIdTable*(dest: var TIdTable, src: TIdTable) =
dest.counter = src.counter
if isNil(src.data): return
newSeq(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) =
dest.counter = src.counter
if isNil(src.data): return
setLen(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
@@ -1243,7 +1245,8 @@ proc newStrNode*(strVal: string; info: TLineInfo): PNode =
proc addSon*(father, son: PNode) =
assert son != nil
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
@@ -1268,14 +1271,14 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
new(result)
result.kind = kind
result.owner = owner
result.size = - 1
result.size = -1
result.align = 2 # default alignment
result.id = getID()
result.lockLevel = UnspecifiedLockLevel
when debugIds:
registerId(result)
when false:
if result.id == 205734:
if result.id == 76426:
echo "KNID ", kind
writeStackTrace()
@@ -1287,16 +1290,22 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
if a.r == nil: a.r = b.r
proc newSons*(father: PNode, length: int) =
if isNil(father.sons):
newSeq(father.sons, length)
else:
when defined(nimNoNilSeqs):
setLen(father.sons, length)
else:
if isNil(father.sons):
newSeq(father.sons, length)
else:
setLen(father.sons, length)
proc newSons*(father: PType, length: int) =
if isNil(father.sons):
newSeq(father.sons, length)
else:
when defined(nimNoNilSeqs):
setLen(father.sons, length)
else:
if isNil(father.sons):
newSeq(father.sons, length)
else:
setLen(father.sons, length)
proc sonsLen*(n: PType): int = n.sons.len
proc len*(n: PType): int = n.sons.len
@@ -1464,20 +1473,26 @@ proc propagateToOwner*(owner, elem: PType) =
owner.flags.incl tfHasGCedMem
proc rawAddSon*(father, son: PType) =
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
if not son.isNil: propagateToOwner(father, son)
proc rawAddSonNoPropagationOfTypeFlags*(father, son: PType) =
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
proc addSonNilAllowed*(father, son: PNode) =
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
proc delSon*(father: PNode, idx: int) =
if isNil(father.sons): return
when defined(nimNoNilSeqs):
if father.len == 0: return
else:
if isNil(father.sons): return
var length = sonsLen(father)
for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
setLen(father.sons, length - 1)
@@ -1579,15 +1594,17 @@ proc getInt*(a: PNode): BiggestInt =
case a.kind
of nkCharLit..nkUInt64Lit: result = a.intVal
else:
raiseRecoverableError("cannot extract number from invalid AST node")
#internalError(a.info, "getInt")
doAssert false, "getInt"
#doAssert false, "getInt"
#result = 0
proc getFloat*(a: PNode): BiggestFloat =
case a.kind
of nkFloatLiterals: result = a.floatVal
else:
doAssert false, "getFloat"
raiseRecoverableError("cannot extract number from invalid AST node")
#doAssert false, "getFloat"
#internalError(a.info, "getFloat")
#result = 0.0
@@ -1601,7 +1618,8 @@ proc getStr*(a: PNode): string =
else:
result = nil
else:
doAssert false, "getStr"
raiseRecoverableError("cannot extract string from invalid AST node")
#doAssert false, "getStr"
#internalError(a.info, "getStr")
#result = ""
@@ -1610,7 +1628,8 @@ proc getStrOrChar*(a: PNode): string =
of nkStrLit..nkTripleStrLit: result = a.strVal
of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
else:
doAssert false, "getStrOrChar"
raiseRecoverableError("cannot extract string from invalid AST node")
#doAssert false, "getStrOrChar"
#internalError(a.info, "getStrOrChar")
#result = ""

View File

@@ -206,7 +206,7 @@ proc makeYamlString*(s: string): Rope =
const MaxLineLength = 64
result = nil
var res = "\""
for i in countup(0, if s.isNil: -1 else: (len(s)-1)):
for i in 0 ..< s.len:
if (i + 1) mod MaxLineLength == 0:
add(res, '\"')
add(res, "\n")
@@ -314,10 +314,7 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
addf(result, ",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
if n.strVal.isNil:
addf(result, ",$N$1\"strVal\": null", [istr])
else:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
addf(result, ",$N$1\"sym\": $2",
[istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
@@ -395,10 +392,7 @@ proc debugTree(conf: ConfigRef; n: PNode, indent: int, maxRecDepth: int;
addf(result, ",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
if n.strVal.isNil:
addf(result, ",$N$1\"strVal\": null", [istr])
else:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
addf(result, ",$N$1\"sym\": $2_$3",
[istr, rope(n.sym.name.s), rope(n.sym.id)])
@@ -759,10 +753,6 @@ proc idNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode =
if index >= 0: result = t.data[index].val
else: result = nil
proc idNodeTableGetLazy*(t: TIdNodeTable, key: PIdObj): PNode =
if not isNil(t.data):
result = idNodeTableGet(t, key)
proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) =
var h: Hash
h = key.id and high(data)
@@ -789,10 +779,6 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
idNodeTableRawInsert(t.data, key, val)
inc(t.counter)
proc idNodeTablePutLazy*(t: var TIdNodeTable, key: PIdObj, val: PNode) =
if isNil(t.data): initIdNodeTable(t)
idNodeTablePut(t, key, val)
iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
for i in 0 .. high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)

View File

@@ -124,15 +124,19 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar and
not compileToCpp(p.module):
result = "(*$1)$3, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
else:
result = "$1$3, ($1 ? $1->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
result = "$1$3, $2" % [a.rdLoc, lenExpr(p, a), dataField(p)]
of tyArray:
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
of tyPtr, tyRef:
case lastSon(a.t).kind
of tyString, tySequence:
result = "(*$1)$3, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
of tyArray:
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
else:

View File

@@ -65,13 +65,13 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
of tyString:
# with the new semantics for 'nil' strings, we can map "" to nil and
# save tons of allocations:
if n.strVal.len == 0 and optNilSeqs notin p.options:
if n.strVal.len == 0 and optNilSeqs notin p.options and
p.config.selectedGc != gcDestructors:
result = genNilStringLiteral(p.module, n.info)
else:
result = genStringLiteral(p.module, n)
else:
if n.strVal.isNil: result = rope("NIM_NIL")
else: result = makeCString(n.strVal)
result = makeCString(n.strVal)
of nkFloatLit, nkFloat64Lit:
result = rope(n.floatVal.toStrMaxPrecision)
of nkFloat32Lit:
@@ -165,7 +165,7 @@ proc canMove(n: PNode): bool =
# result = false
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if dest.storage == OnStack or not usesNativeGC(p.config):
if dest.storage == OnStack or not usesWriteBarrier(p.config):
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
elif dest.storage == OnHeap:
# location is on heap
@@ -255,9 +255,13 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# tfShallow flag for the built-in string type too! So we check only
# here for this flag, where it is reasonably safe to do so
# (for objects, etc.):
if needToCopy notin flags or
if p.config.selectedGC == gcDestructors:
linefmt(p, cpsStmts,
"$1.len = $2.len; $1.p = $2.p;$n",
rdLoc(dest), rdLoc(src))
elif needToCopy notin flags or
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
if dest.storage == OnStack or not usesNativeGC(p.config):
if dest.storage == OnStack or not usesWriteBarrier(p.config):
linefmt(p, cpsStmts,
"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest))
@@ -280,17 +284,21 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
of tyRef:
genRefAssign(p, dest, src, flags)
of tySequence:
if (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
if p.config.selectedGC == gcDestructors:
genGenericAsgn(p, dest, src, flags)
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
genRefAssign(p, dest, src, flags)
else:
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
addrLoc(p.config, dest), rdLoc(src),
genTypeInfo(p.module, dest.t, dest.lode.info))
of tyString:
if (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
if p.config.selectedGC == gcDestructors:
genGenericAsgn(p, dest, src, flags)
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
genRefAssign(p, dest, src, flags)
else:
if dest.storage == OnStack or not usesNativeGC(p.config):
if dest.storage == OnStack or not usesWriteBarrier(p.config):
linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
elif dest.storage == OnHeap:
# we use a temporary to care for the dreaded self assignment:
@@ -453,6 +461,13 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
initLocExpr(p, e.sons[2], b)
lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b))
proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr")
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
lineCg(p, cpsStmts, frmt, addrLoc(p.config, a), rdLoc(b))
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a: TLoc
if d.k != locNone: internalError(p.config, e.info, "unaryStmt")
@@ -889,8 +904,8 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
of tySequence, tyString:
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"(!$3 || (NU)($1) >= (NU)($3->$4) || (NU)($2) >= (NU)($3->$4))) #raiseIndexError();$n",
rdLoc(a), rdLoc(b), rdLoc(arr), lenField(p))
"((NU)($1) >= (NU)$3 || (NU)($2) >= (NU)$3)) #raiseIndexError();$n",
rdLoc(a), rdLoc(b), lenExpr(p, arr))
else: discard
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
@@ -914,12 +929,12 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
if optBoundsCheck in p.options:
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
linefmt(p, cpsStmts,
"if (!$2 || (NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
rdLoc(b), rdLoc(a), lenField(p))
"if ((NU)($1) > (NU)$2) #raiseIndexError();$n",
rdLoc(b), lenExpr(p, a))
else:
linefmt(p, cpsStmts,
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
rdLoc(b), rdLoc(a), lenField(p))
"if ((NU)($1) >= (NU)$2) #raiseIndexError();$n",
rdLoc(b), lenExpr(p, a))
if d.k == locNone: d.storage = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
a.r = ropecg(p.module, "(*$1)", a.r)
@@ -1010,6 +1025,12 @@ proc genEcho(p: BProc, n: PNode) =
proc gcUsage(conf: ConfigRef; n: PNode) =
if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
proc strLoc(p: BProc; d: TLoc): Rope =
if p.config.selectedGc == gcDestructors:
result = addrLoc(p.config, d)
else:
result = rdLoc(d)
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
# <Nim code>
# s = 'Hello ' & name & ', how do you feel?' & 'z'
@@ -1037,13 +1058,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
inc(L)
add(appends, ropecg(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
add(appends, ropecg(p.module, "#appendChar($1, $2);$n", strLoc(p, tmp), rdLoc(a)))
else:
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
inc(L, len(e.sons[i + 1].strVal))
else:
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
add(appends, ropecg(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
add(lens, lenExpr(p, a))
add(lens, " + ")
add(appends, ropecg(p.module, "#appendString($1, $2);$n", strLoc(p, tmp), rdLoc(a)))
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
add(p.s(cpsStmts), appends)
if d.k == locNone:
@@ -1076,19 +1098,24 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
inc(L)
add(appends, ropecg(p.module, "#appendChar($1, $2);$n",
rdLoc(dest), rdLoc(a)))
strLoc(p, dest), rdLoc(a)))
else:
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
inc(L, len(e.sons[i + 2].strVal))
else:
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
add(lens, lenExpr(p, a))
add(lens, " + ")
add(appends, ropecg(p.module, "#appendString($1, $2);$n",
rdLoc(dest), rdLoc(a)))
initLoc(call, locCall, e, OnHeap)
call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, rope(L)])
genAssignment(p, dest, call, {})
strLoc(p, dest), rdLoc(a)))
if p.config.selectedGC == gcDestructors:
linefmt(p, cpsStmts, "#prepareAdd($1, $2$3);$n",
addrLoc(p.config, dest), lens, rope(L))
else:
initLoc(call, locCall, e, OnHeap)
call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, rope(L)])
genAssignment(p, dest, call, {})
gcUsage(p.config, e)
add(p.s(cpsStmts), appends)
gcUsage(p.config, e)
proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
# seq &= x -->
@@ -1151,7 +1178,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
addf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
let args = [getTypeDesc(p.module, typ), ti, sizeExpr]
if a.storage == OnHeap and usesNativeGC(p.config):
if a.storage == OnHeap and usesWriteBarrier(p.config):
# use newObjRC1 as an optimization
if canFormAcycle(a.t):
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc)
@@ -1182,7 +1209,7 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
genTypeInfo(p.module, seqtype, dest.lode.info), length]
var call: TLoc
initLoc(call, locExpr, dest.lode, OnHeap)
if dest.storage == OnHeap and usesNativeGC(p.config):
if dest.storage == OnHeap and usesWriteBarrier(p.config):
if canFormAcycle(dest.t):
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc)
else:
@@ -1201,10 +1228,16 @@ proc genNewSeq(p: BProc, e: PNode) =
var a, b: TLoc
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
let lenIsZero = optNilSeqs notin p.options and
e[2].kind == nkIntLit and e[2].intVal == 0
genNewSeqAux(p, a, b.rdLoc, lenIsZero)
gcUsage(p.config, e)
if p.config.selectedGC == gcDestructors:
let seqtype = skipTypes(e.sons[1].typ, abstractVarRange)
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
a.rdLoc, b.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype))
else:
let lenIsZero = optNilSeqs notin p.options and
e[2].kind == nkIntLit and e[2].intVal == 0
genNewSeqAux(p, a, b.rdLoc, lenIsZero)
gcUsage(p.config, e)
proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
let seqtype = skipTypes(e.typ, abstractVarRange)
@@ -1448,7 +1481,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
of tyString, tySequence:
putIntoDest(p, b, e,
"$1$3, ($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p), dataField(p)], a.storage)
"$1$3, $2" % [rdLoc(a), lenExpr(p, a), dataField(p)], a.storage)
of tyArray:
putIntoDest(p, b, e,
"$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))], a.storage)
@@ -1492,28 +1525,19 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
of tyString:
if not p.module.compileToCpp:
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->Sup.len-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? $1->Sup.len : 0)")
else:
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
var a: TLoc
initLocExpr(p, e.sons[1], a)
var x = lenExpr(p, a)
if op == mHigh: x = "($1-1)" % [x]
putIntoDest(p, d, e, x)
of tySequence:
# we go through a temporary here because people write bullshit code.
var a, tmp: TLoc
initLocExpr(p, e[1], a)
getIntTemp(p, tmp)
var frmt: FormatStr
if not p.module.compileToCpp:
if op == mHigh:
frmt = "$1 = ($2 ? ($2->Sup.len-1) : -1);$n"
else:
frmt = "$1 = ($2 ? $2->Sup.len : 0);$n"
else:
if op == mHigh:
frmt = "$1 = ($2 ? ($2->len-1) : -1);$n"
else:
frmt = "$1 = ($2 ? $2->len : 0);$n"
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
var x = lenExpr(p, a)
if op == mHigh: x = "($1-1)" % [x]
lineCg(p, cpsStmts, "$1 = $2;$n", tmp.r, x)
putIntoDest(p, d, e, tmp.r)
of tyArray:
# YYY: length(sideeffect) is optimized away incorrectly?
@@ -1522,6 +1546,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: internalError(p.config, e.info, "genArrayLen()")
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
if p.config.selectedGc == gcDestructors:
genCall(p, e, d)
return
var a, b, call: TLoc
assert(d.k == locNone)
var x = e.sons[1]
@@ -1542,16 +1569,19 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
gcUsage(p.config, e)
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
var a, b, call: TLoc
if d.k != locNone: internalError(p.config, e.info, "genSetLengthStr")
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
if p.config.selectedGc == gcDestructors:
binaryStmtAddr(p, e, d, "#setLengthStrV2($1, $2);$n")
else:
var a, b, call: TLoc
if d.k != locNone: internalError(p.config, e.info, "genSetLengthStr")
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
initLoc(call, locCall, e, OnHeap)
call.r = ropecg(p.module, "#setLengthStr($1, $2)", [
rdLoc(a), rdLoc(b)])
genAssignment(p, a, call, {})
gcUsage(p.config, e)
initLoc(call, locCall, e, OnHeap)
call.r = ropecg(p.module, "#setLengthStr($1, $2)", [
rdLoc(a), rdLoc(b)])
genAssignment(p, a, call, {})
gcUsage(p.config, e)
proc genSwap(p: BProc, e: PNode, d: var TLoc) =
# swap(a, b) -->
@@ -1803,11 +1833,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
initLocExpr(p, e.sons[2], x)
putIntoDest(p, d, e,
ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
ropecg(p.module, "($1 == 0)", lenExpr(p, x)))
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
initLocExpr(p, e.sons[1], x)
putIntoDest(p, d, e,
ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
ropecg(p.module, "($1 == 0)", lenExpr(p, x)))
else:
binaryExpr(p, e, d, "#eqStrings($1, $2)")
@@ -1868,14 +1898,21 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mConStrStr: genStrConcat(p, e, d)
of mAppendStrCh:
var dest, b, call: TLoc
initLoc(call, locCall, e, OnHeap)
initLocExpr(p, e.sons[1], dest)
initLocExpr(p, e.sons[2], b)
call.r = ropecg(p.module, "#addChar($1, $2)", [rdLoc(dest), rdLoc(b)])
genAssignment(p, dest, call, {})
if p.config.selectedGC == gcDestructors:
binaryStmtAddr(p, e, d, "#nimAddCharV1($1, $2);$n")
else:
var dest, b, call: TLoc
initLoc(call, locCall, e, OnHeap)
initLocExpr(p, e.sons[1], dest)
initLocExpr(p, e.sons[2], b)
call.r = ropecg(p.module, "#addChar($1, $2)", [rdLoc(dest), rdLoc(b)])
genAssignment(p, dest, call, {})
of mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem: genSeqElemAppend(p, e, d)
of mAppendSeqElem:
if p.config.selectedGc == gcDestructors:
genCall(p, e, d)
else:
genSeqElemAppend(p, e, d)
of mEqStr: genStrEquals(p, e, d)
of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
@@ -1924,8 +1961,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
mInSet:
genSetOp(p, e, d, op)
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit,
mParseBiggestFloat:
of mCopyStr, mCopyStrLast:
genCall(p, e, d)
of mNewString, mNewStringOfCap, mExit, mParseBiggestFloat:
var opr = e.sons[0].sym
if lfNoDecl notin opr.loc.flags:
discard cgsym(p.module, $opr.loc.r)
@@ -2509,7 +2547,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
var t = skipTypes(n.typ, abstractInst)
if t.kind == tySequence:
result = genConstSeq(p, n, n.typ)
elif t.kind == tyProc and t.callConv == ccClosure and not n.sons.isNil and
elif t.kind == tyProc and t.callConv == ccClosure and n.len > 0 and
n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit:
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
# this behaviour is needed since closure_var = nil must be
@@ -2522,6 +2560,13 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
result = genConstSimpleList(p, n)
of nkObjConstr:
result = genConstObjConstr(p, n)
of nkStrLit..nkTripleStrLit:
if p.config.selectedGc == gcDestructors:
result = genStringLiteralV2Const(p.module, n)
else:
var d: TLoc
initLocExpr(p, n, d)
result = rdLoc(d)
else:
var d: TLoc
initLocExpr(p, n, d)

View File

@@ -53,20 +53,36 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope =
result = getTempName(m)
addf(m.s[cfsData], " static const NIM_CHAR $1[$2] = $3;$n",
[result, rope(len(s)+1), makeCString(s)])
addf(m.s[cfsData], "static const struct {$n" &
" NI cap; void* allocator; NIM_CHAR data[$2];$n" &
"} $1 = { $2, NIM_NIL, $3 };$n",
[result, rope(len(s)), makeCString(s)])
proc genStringLiteralV2(m: BModule; n: PNode): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
if id == m.labels:
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
let pureLit = genStringLiteralDataOnlyV2(m, n.strVal)
result = getTempName(m)
addf(m.s[cfsData], "static const #NimStringV2 $1 = {$2, $2, $3};$n",
[result, rope(len(n.strVal)+1), pureLit])
addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(len(n.strVal)), pureLit])
else:
result = m.tmpBase & rope(id)
proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
var pureLit: Rope
if id == m.labels:
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
pureLit = genStringLiteralDataOnlyV2(m, n.strVal)
else:
pureLit = m.tmpBase & rope(id)
result = "{$1, (NimStrPayload*)&$2}" % [rope(len(n.strVal)), pureLit]
# ------ Version selector ---------------------------------------------------
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope =

View File

@@ -16,7 +16,7 @@ const
# above X strings a hash-switch for strings is generated
proc registerGcRoot(p: BProc, v: PSym) =
if p.config.selectedGC in {gcMarkAndSweep, gcGenerational, gcV2, gcRefc} and
if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} 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 :-)

View File

@@ -7,8 +7,7 @@
# distribution, for details about the copyright.
#
## Generates traversal procs for the C backend. Traversal procs are only an
## optimization; the GC works without them too.
## Generates traversal procs for the C backend.
# included from cgen.nim
@@ -61,6 +60,7 @@ proc parentObj(accessor: Rope; m: BModule): Rope {.inline.} =
else:
result = accessor
proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType)
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
if typ == nil: return
@@ -93,8 +93,18 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
let typ = getUniqueType(typ)
for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i])
of tyRef, tyString, tySequence:
of tyRef:
lineCg(p, cpsStmts, c.visitorFrmt, accessor)
of tySequence:
if tfHasAsgn notin typ.flags:
lineCg(p, cpsStmts, c.visitorFrmt, accessor)
elif containsGarbageCollectedRef(typ.lastSon):
# destructor based seqs are themselves not traced but their data is, if
# they contain a GC'ed type:
genTraverseProcSeq(c, accessor, typ)
of tyString:
if tfHasAsgn notin typ.flags:
lineCg(p, cpsStmts, c.visitorFrmt, accessor)
of tyProc:
if typ.callConv == ccClosure:
lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor))
@@ -107,8 +117,11 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
var i: TLoc
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
let oldCode = p.s(cpsStmts)
lineF(p, cpsStmts, "for ($1 = 0; $1 < ($2 ? $2->$3 : 0); $1++) {$n",
[i.r, accessor, lenField(c.p)])
var a: TLoc
a.r = accessor
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, lenExpr(c.p, a)])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.sons[0])
if p.s(cpsStmts).len == oldLen:

View File

@@ -282,7 +282,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
of tyString:
case detectStrVersion(m)
of 2:
discard cgsym(m, "string")
discard cgsym(m, "NimStringV2")
result = typeNameOrLiteral(m, typ, "NimStringV2")
else:
discard cgsym(m, "NimStringDesc")
@@ -324,6 +324,10 @@ proc getForwardStructFormat(m: BModule): string =
if m.compileToCpp: result = "$1 $2;$n"
else: result = "typedef $1 $2 $2;$n"
proc seqStar(m: BModule): string =
if m.config.selectedGC == gcDestructors: result = ""
else: result = "*"
proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
result = cacheGetType(m.forwTypeCache, sig)
if result != nil: return
@@ -355,8 +359,11 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
result = getTypeForward(m, t, hashType(t))
pushType(m, t)
of tySequence:
result = getTypeForward(m, t, hashType(t)) & "*"
pushType(m, t)
if m.config.selectedGC == gcDestructors:
result = getTypeDescAux(m, t, check)
else:
result = getTypeForward(m, t, hashType(t)) & seqStar(m)
pushType(m, t)
else:
result = getTypeDescAux(m, t, check)
@@ -442,7 +449,9 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
of nkRecCase:
if n.sons[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
add(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
let uname = rope(mangle(n.sons[0].sym.name.s) & 'U')
# prefix mangled name with "_U" to avoid clashes with other field names,
# since identifiers are not allowed to start with '_'
let uname = rope("_U" & mangle(n.sons[0].sym.name.s))
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, uname]
else: uname
var unionBody: Rope = nil
@@ -487,7 +496,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
addf(result, "$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname])
elif fieldType.kind in {tySequence, tyOpt}:
elif fieldType.kind == tySequence and m.config.selectedGC != gcDestructors:
# we need to use a weak dependency here for trecursive_table.
addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
elif field.bitsize != 0:
@@ -601,6 +610,15 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
result = if result.kind == tyGenericInst: result.sons[1]
else: result.elemType
proc getSeqPayloadType(m: BModule; t: PType): Rope =
result = getTypeForward(m, t, hashType(t)) & "_Content"
when false:
var check = initIntSet()
# XXX remove this duplication:
appcg(m, m.s[cfsSeqTypes],
"struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE]; };$n",
[getTypeDescAux(m, t.sons[0], check), result])
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
# returns only the type's name
var t = origTyp.skipTypes(irrelevantForBackend)
@@ -641,7 +659,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
of tySequence:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
result = name & "*" & star
result = name & seqStar(m) & star
m.typeCache[sig] = result
pushType(m, et)
else:
@@ -705,20 +723,29 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
[structOrUnion(t), result])
m.forwTypeCache[sig] = result
assert(cacheGetType(m.typeCache, sig) == nil)
m.typeCache[sig] = result & "*"
m.typeCache[sig] = result & seqStar(m)
if not isImportedType(t):
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
const
cppSeq = "struct $2 : #TGenericSeq {$n"
cSeq = "struct $2 {$n" &
" #TGenericSeq Sup;$n"
appcg(m, m.s[cfsSeqTypes],
(if m.compileToCpp: cppSeq else: cSeq) &
" $1 data[SEQ_DECL_SIZE];$n" &
if m.config.selectedGC == gcDestructors:
appcg(m, m.s[cfsTypes],
"typedef struct{ NI cap;void* allocator;$1 data[SEQ_DECL_SIZE];}$2_Content;$n" &
"struct $2 {$n" &
" NI len; $2_Content* p;$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
else:
appcg(m, m.s[cfsSeqTypes],
(if m.compileToCpp: cppSeq else: cSeq) &
" $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
elif m.config.selectedGC == gcDestructors:
internalError(m.config, "cannot map the empty seq type to a C type")
else:
result = rope("TGenericSeq")
add(result, "*")
add(result, seqStar(m))
of tyArray:
var n: BiggestInt = lengthOrd(m.config, t)
if n <= 0: n = 1 # make an array of at least one element
@@ -1177,7 +1204,13 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
else:
let x = fakeClosureType(m, t.owner)
genTupleInfo(m, x, x, result, info)
of tySequence, tyRef, tyOptAsRef:
of tySequence:
if tfHasAsgn notin t.flags:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
of tyRef, tyOptAsRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)

View File

@@ -230,22 +230,31 @@ proc getTempName(m: BModule): Rope =
result = m.tmpBase & rope(m.labels)
inc m.labels
proc rdLoc(a: TLoc): Rope =
# 'read' location (deref if indirect)
result = a.r
if lfIndirect in a.flags: result = "(*$1)" % [result]
proc lenField(p: BProc): Rope =
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
proc lenExpr(p: BProc; a: TLoc): Rope =
if p.config.selectedGc == gcDestructors:
result = rdLoc(a) & ".len"
else:
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
proc dataField(p: BProc): Rope =
result = rope"->data"
if p.config.selectedGc == gcDestructors:
result = rope".p->data"
else:
result = rope"->data"
include ccgliterals
include ccgtypes
# ------------------------------ Manager of temporaries ------------------
proc rdLoc(a: TLoc): Rope =
# 'read' location (deref if indirect)
result = a.r
if lfIndirect in a.flags: result = "(*$1)" % [result]
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
result = a.r
if lfIndirect notin a.flags and mapType(conf, a.t) != ctArray:
@@ -325,7 +334,9 @@ proc resetLoc(p: BProc, loc: var TLoc) =
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
let typ = loc.t
if not isComplexValueType(typ):
if p.config.selectedGc == gcDestructors and skipTypes(typ, abstractInst).kind in {tyString, tySequence}:
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", rdLoc(loc))
elif not isComplexValueType(typ):
linefmt(p, cpsStmts, "$1 = ($2)0;$n", rdLoc(loc),
getTypeDesc(p.module, typ))
else:
@@ -694,9 +705,10 @@ proc containsResult(n: PNode): bool =
for i in 0..<n.safeLen:
if containsResult(n[i]): return true
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt} +
declarativeDefs
proc easyResultAsgn(n: PNode): PNode =
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt} +
declarativeDefs
case n.kind
of nkStmtList, nkStmtListExpr:
var i = 0
@@ -712,6 +724,105 @@ proc easyResultAsgn(n: PNode): PNode =
if result != nil: incl n.flags, nfPreventCg
else: discard
type
InitResultEnum = enum Unknown, InitSkippable, InitRequired
proc allPathsAsgnResult(n: PNode): InitResultEnum =
# Exceptions coming from calls don't have not be considered here:
#
# proc bar(): string = raise newException(...)
#
# proc foo(): string =
# # optimized out: 'reset(result)'
# result = bar()
#
# try:
# a = foo()
# except:
# echo "a was not written to"
#
template allPathsInBranch(it) =
let a = allPathsAsgnResult(it)
case a
of InitRequired: return InitRequired
of InitSkippable: discard
of Unknown:
# sticky, but can be overwritten by InitRequired:
result = Unknown
result = Unknown
case n.kind
of nkStmtList, nkStmtListExpr:
for it in n:
result = allPathsAsgnResult(it)
if result != Unknown: return result
of nkAsgn, nkFastAsgn:
if n[0].kind == nkSym and n[0].sym.kind == skResult:
if not containsResult(n[1]): result = InitSkippable
else: result = InitRequired
elif containsResult(n):
result = InitRequired
of nkReturnStmt:
if n.len > 0:
result = allPathsAsgnResult(n[0])
of nkIfStmt, nkIfExpr:
var exhaustive = false
result = InitSkippable
for it in n:
# Every condition must not use 'result':
if it.len == 2 and containsResult(it[0]):
return InitRequired
if it.len == 1: exhaustive = true
allPathsInBranch(it.lastSon)
# if the 'if' statement is not exhaustive and yet it touched 'result'
# in some way, say Unknown.
if not exhaustive: result = Unknown
of nkCaseStmt:
if containsResult(n[0]): return InitRequired
result = InitSkippable
var exhaustive = skipTypes(n[0].typ,
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString}
for i in 1..<n.len:
let it = n[i]
allPathsInBranch(it.lastSon)
if it.kind == nkElse: exhaustive = true
if not exhaustive: result = Unknown
of nkWhileStmt:
# some dubious code can assign the result in the 'while'
# condition and that would be fine. Everything else isn't:
result = allPathsAsgnResult(n[0])
if result == Unknown:
result = allPathsAsgnResult(n[1])
# we cannot assume that the 'while' loop is really executed at least once:
if result == InitSkippable: result = Unknown
of harmless:
result = Unknown
of nkGotoState, nkBreakState:
# give up for now.
result = InitRequired
of nkSym:
# some path reads from 'result' before it was written to!
if n.sym.kind == skResult: result = InitRequired
of nkTryStmt:
# We need to watch out for the following problem:
# try:
# result = stuffThatRaises()
# except:
# discard "result was not set"
#
# So ... even if the assignment to 'result' is the very first
# assignment this is not good enough! The only pattern we allow for
# is 'finally: result = x'
result = InitSkippable
for it in n:
if it.kind == nkFinally:
result = allPathsAsgnResult(it.lastSon)
else:
allPathsInBranch(it.lastSon)
else:
for i in 0..<safeLen(n):
allPathsInBranch(n[i])
proc genProcAux(m: BModule, prc: PSym) =
var p = newProc(prc, m)
var header = genProcHeader(m, prc)
@@ -738,7 +849,16 @@ proc genProcAux(m: BModule, prc: PSym) =
else:
fillResult(p.config, resNode)
assignParam(p, res)
if sfNoInit notin prc.flags: resetLoc(p, res.loc)
# We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)'
# to 'unsureAsgn(result, x)'
# Sketch why this is correct: If 'result' points to a stack location
# the 'unsureAsgn' is a nop. If it points to a global variable the
# global is either 'nil' or points to valid memory and so the RC operation
# succeeds without touching not-initialized memory.
if sfNoInit in prc.flags: discard
elif allPathsAsgnResult(prc.getBody) == InitSkippable: discard
else:
resetLoc(p, res.loc)
if skipTypes(res.typ, abstractInst).kind == tyArray:
#incl(res.loc.flags, lfIndirect)
res.loc.storage = OnUnknown

View File

@@ -239,7 +239,7 @@ proc toStmtList(n: PNode): PNode =
proc addGotoOut(n: PNode, gotoOut: PNode): PNode =
# Make sure `n` is a stmtlist, and ends with `gotoOut`
result = toStmtList(n)
if result.len != 0 and result.sons[^1].kind != nkGotoState:
if result.len == 0 or result.sons[^1].kind != nkGotoState:
result.add(gotoOut)
proc newTempVar(ctx: var Ctx, typ: PType): PSym =
@@ -678,7 +678,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = ex
result.add(n)
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
var ns = false
for i in 0 ..< n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
@@ -687,9 +687,9 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
needsSplit = true
result = newNodeI(nkStmtListExpr, n.info)
result.typ = n.typ
let (st, ex) = exprToStmtList(n[1])
let (st, ex) = exprToStmtList(n[^1])
result.add(st)
n[1] = ex
n[^1] = ex
result.add(n)
of nkAsgn, nkFastAsgn:

View File

@@ -0,0 +1,85 @@
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
# TODO: nimfix should use this; currently out of sync
import
compiler/[options, idents, nimconf, scriptconfig, extccomp, commands, msgs, lineinfos, modulegraphs, condsyms],
std/os
type
NimProg* = ref object
suggestMode*: bool
supportsStdinFile*: bool
processCmdLine*: proc(pass: TCmdLinePass, cmd: string; config: ConfigRef)
mainCommand*: proc(graph: ModuleGraph)
proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
condsyms.initDefines(conf.symbols)
defineSymbol conf.symbols, name
proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
self.processCmdLine(passCmd1, "", conf)
if self.supportsStdinFile and conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = "stdinfile"
conf.projectPath = canonicalizePath(conf, getCurrentDir())
conf.projectIsStdin = true
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
let p = splitFile(conf.projectFull)
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
conf.projectPath = canonicalizePath(conf, dir)
conf.projectName = p.name
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
loadConfigs(DefaultConfig, cache, conf) # load all config files
if self.suggestMode:
conf.command = "nimsuggest"
proc runNimScriptIfExists(path: string)=
if fileExists(path):
runNimScript(cache, path, freshDefines = false, conf)
# Caution: make sure this stays in sync with `loadConfigs`
if optSkipSystemConfigFile notin conf.globalOptions:
runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
if optSkipUserConfigFile notin conf.globalOptions:
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(conf.projectPath, fromRoot = true, inclusive = false):
runNimScriptIfExists(dir / DefaultConfigNims)
if optSkipProjConfigFile notin conf.globalOptions:
runNimScriptIfExists(conf.projectPath / DefaultConfigNims)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
if not self.suggestMode:
runNimScriptIfExists(scriptFile)
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile.cmpPaths(conf.projectFull) == 0:
return false
else:
if scriptFile.cmpPaths(conf.projectFull) != 0:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")
let graph = newModuleGraph(cache, conf)
graph.suggestMode = self.suggestMode
self.mainCommand(graph)
return true

View File

@@ -131,7 +131,10 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
else: break
inc(i)
if i >= len(switch): arg = ""
elif switch[i] in {':', '=', '['}: arg = substr(switch, i + 1)
# cmd:arg => (cmd,arg)
elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
# cmd[sub]:rest => (cmd,[sub]:rest)
elif switch[i] == '[': arg = substr(switch, i)
else: invalidCmdLineOption(conf, pass, switch, info)
proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
@@ -167,14 +170,20 @@ proc expectNoArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info:
proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
info: TLineInfo; orig: string; conf: ConfigRef) =
var id = "" # arg = "X]:on|off"
var id = "" # arg = key:val or [key]:val; with val=on|off
var i = 0
var n = hintMin
while i < len(arg) and (arg[i] != ']'):
var isBracket = false
if i < len(arg) and arg[i] == '[':
isBracket = true
inc(i)
while i < len(arg) and (arg[i] notin {':', '=', ']'}):
add(id, arg[i])
inc(i)
if i < len(arg) and (arg[i] == ']'): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if isBracket:
if i < len(arg) and arg[i] == ']': inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if i < len(arg) and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint:
@@ -215,7 +224,8 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
of "refc": result = conf.selectedGC == gcRefc
of "v2": result = conf.selectedGC == gcV2
of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
of "generational": result = conf.selectedGC == gcGenerational
of "generational": result = false
of "destructors": result = conf.selectedGC == gcDestructors
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "stack", "regions": result = conf.selectedGC == gcRegions
@@ -436,9 +446,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "markandsweep":
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "generational":
conf.selectedGC = gcGenerational
defineSymbol(conf.symbols, "gcgenerational")
of "destructors":
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")
of "go":
conf.selectedGC = gcGo
defineSymbol(conf.symbols, "gogc")
@@ -641,7 +651,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
else: localError(conf, info, "invalid option for --symbolFiles: " & arg)
of "skipcfg":
expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optSkipConfigFile)
incl(conf.globalOptions, optSkipSystemConfigFile)
of "skipprojcfg":
expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optSkipProjConfigFile)
@@ -742,11 +752,11 @@ proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
# hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
# we fix this here
# we transform it to (key = hint, val = [X]:off)
var bracketLe = strutils.find(p.key, '[')
if bracketLe >= 0:
var key = substr(p.key, 0, bracketLe - 1)
var val = substr(p.key, bracketLe + 1) & ':' & p.val
var val = substr(p.key, bracketLe) & ':' & p.val
processSwitch(key, val, pass, gCmdLineInfo, config)
else:
processSwitch(p.key, p.val, pass, gCmdLineInfo, config)

View File

@@ -13,6 +13,7 @@ import
strtabs, platform, strutils, idents
from options import Feature
from lineinfos import HintsToStr, WarningsToStr
const
catNone = "false"
@@ -74,6 +75,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNoZeroTerminator")
defineSymbol("nimNotNil")
defineSymbol("nimVmExportFixed")
defineSymbol("nimHasSymOwnerInMacro")
defineSymbol("nimNewRuntime")
defineSymbol("nimIncrSeqV3")
defineSymbol("nimAshr")
defineSymbol("nimNoNilSeqs")
@@ -82,3 +85,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasNilSeqs")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)
for s in WarningsToStr:
defineSymbol("nimHasWarning" & s)
for s in HintsToStr:
defineSymbol("nimHasHint" & s)

View File

@@ -100,12 +100,12 @@ Rule Pattern Transformed into
finally: `=destroy`(x)
1.2 var x: sink T; stmts var x: sink T; stmts; ensureEmpty(x)
2 x = f() `=sink`(x, f())
3 x = lastReadOf z `=sink`(x, z)
3 x = lastReadOf z `=sink`(x, z); wasMoved(z)
4.1 y = sinkParam `=sink`(y, sinkParam)
4.2 x = y `=`(x, y) # a copy
5.1 f_sink(g()) f_sink(g())
5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read
5.3 f_sink(move y) f_sink(y); reset(y) # explicit moves empties 'y'
5.3 f_sink(move y) f_sink(y); wasMoved(y) # explicit moves empties 'y'
5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
@@ -258,8 +258,10 @@ proc registerDropBit(c: var Con; s: PSym) =
c.toDropBit[s.id] = result
# generate:
# if not sinkParam_AliveBit: `=destroy`(sinkParam)
c.destroys.add newTree(nkIfStmt,
newTree(nkElifBranch, newSymNode result, genDestroy(c, s.typ, newSymNode s)))
let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink})
if t.destructor != nil:
c.destroys.add newTree(nkIfStmt,
newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s)))
proc p(n: PNode; c: var Con): PNode
@@ -282,6 +284,11 @@ proc destructiveMoveSink(n: PNode; c: var Con): PNode =
newIntTypeNode(nkIntLit, 0, getSysType(c.graph, n.info, tyBool)))
result.add n
proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, magicname, m)))
result.add n
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
if ri.kind in constrExprs:
result = genSink(c, ri.typ, dest)
@@ -290,8 +297,10 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
recurse(ri, ri2)
result.add ri2
elif ri.kind == nkSym and isHarmlessVar(ri.sym, c):
result = genSink(c, ri.typ, dest)
result.add p(ri, c)
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, ri.typ, dest)
snk.add p(ri, c)
result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved))
elif ri.kind == nkSym and isSinkParam(ri.sym):
result = genSink(c, ri.typ, dest)
result.add destructiveMoveSink(ri, c)
@@ -313,11 +322,9 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
result.add newTree(nkAsgn, tmp, p(n, c))
result.add tmp
proc genReset(n: PNode; c: var Con): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, "reset", mReset)))
# The mReset builtin does not take the address:
result.add n
proc genWasMoved(n: PNode; c: var Con): PNode =
# The mWasMoved builtin does not take the address.
result = genMagicCall(n, c, "wasMoved", mWasMoved)
proc destructiveMoveVar(n: PNode; c: var Con): PNode =
# generate: (let tmp = v; reset(v); tmp)
@@ -334,7 +341,7 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode =
add(v, vpart)
result.add v
result.add genReset(n, c)
result.add genWasMoved(n, c)
result.add tempAsNode
proc p(n: PNode; c: var Con): PNode =

View File

@@ -14,7 +14,7 @@
import
ast, strutils, strtabs, options, msgs, os, ropes, idents,
wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
packages/docutils/rst, packages/docutils/rstgen, times,
packages/docutils/rst, packages/docutils/rstgen,
packages/docutils/highlite, sempass2, json, xmltree, cgi,
typesrenderer, astalgo, modulepaths, lineinfos, sequtils
@@ -31,6 +31,7 @@ type
isPureRst: bool
conf*: ConfigRef
cache*: IdentCache
exampleCounter: int
PDoc* = ref TDocumentor ## Alias to type less.
@@ -284,11 +285,56 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
[rope(esc(d.target, literal))])
proc testExample(d: PDoc; ex: PNode) =
if d.conf.errorCounter > 0: return
let outputDir = d.conf.getNimcacheDir / "runnableExamples"
createDir(outputDir)
inc d.exampleCounter
let outp = outputDir / extractFilename(d.filename.changeFileExt"" &
"_examples" & $d.exampleCounter & ".nim")
#let nimcache = outp.changeFileExt"" & "_nimcache"
renderModule(ex, d.filename, outp, conf = d.conf)
let backend = if isDefined(d.conf, "js"): "js"
elif isDefined(d.conf, "cpp"): "cpp"
elif isDefined(d.conf, "objc"): "objc"
else: "c"
if os.execShellCmd(os.getAppFilename() & " " & backend &
" --nimcache:" & outputDir & " -r " & outp) != 0:
quit "[Examples] failed: see " & outp
else:
# keep generated source file `outp` to allow inspection.
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp])
removeFile(outp.changeFileExt(ExeExt))
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
proc prepareExamples(d: PDoc; n: PNode) =
var runnableExamples = newTree(nkStmtList,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
testExample(d, runnableExamples)
proc isRunnableExample(n: PNode): bool =
# Templates and generics don't perform symbol lookups.
result = n.kind == nkSym and n.sym.magic == mRunnableExamples or
n.kind == nkIdent and n.ident.s == "runnableExamples"
proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
case n.kind
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mRunnableExamples and
if isRunnableExample(n[0]) and
n.len >= 2 and n.lastSon.kind == nkStmtList:
prepareExamples(d, n)
dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n",
"\n\\textbf{$1}\n", [rope"Examples:"])
inc d.listingCounter
@@ -627,6 +673,10 @@ proc generateDoc*(d: PDoc, n: PNode) =
of nkImportStmt:
for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i])
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
of nkCallKinds:
var comm: Rope = nil
getAllRunnableExamples(d, n, comm)
if comm > nil: add(d.modDesc, comm)
else: discard
proc add(d: PDoc; j: JsonNode) =
@@ -787,14 +837,13 @@ proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string =
proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
var content = genOutFile(d)
var success = true
if optStdout in d.conf.globalOptions:
writeRope(stdout, content)
else:
let outfile = getOutFile2(d.conf, filename, outExt, "htmldocs")
success = writeRope(content, outfile)
if not success:
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, filename)
createDir(outfile.parentDir)
if not writeRope(content, outfile):
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, outfile)
proc writeOutputJson*(d: PDoc, filename, outExt: string,
useWarning = false) =

View File

@@ -21,12 +21,15 @@ type
module: PSym
PGen = ref TGen
template shouldProcess(g): bool =
(g.module.owner.id == g.doc.conf.mainPackageId and optWholeProject in g.doc.conf.globalOptions) or
sfMainModule in g.module.flags
template closeImpl(body: untyped) {.dirty.} =
var g = PGen(p)
let useWarning = sfMainModule notin g.module.flags
#echo g.module.name.s, " ", g.module.owner.id, " ", gMainPackageId
if (g.module.owner.id == g.doc.conf.mainPackageId and optWholeProject in g.doc.conf.globalOptions) or
sfMainModule in g.module.flags:
if shouldProcess(g):
body
try:
generateIndex(g.doc)
@@ -35,27 +38,29 @@ template closeImpl(body: untyped) {.dirty.} =
proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
writeOutput(g.doc, toFilename(graph.config, FileIndex g.module.position), HtmlExt, useWarning)
writeOutput(g.doc, toFullPath(graph.config, FileIndex g.module.position), HtmlExt, useWarning)
proc closeJson(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
writeOutputJson(g.doc, toFilename(graph.config, FileIndex g.module.position), ".json", useWarning)
writeOutputJson(g.doc, toFullPath(graph.config, FileIndex g.module.position), ".json", useWarning)
proc processNode(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
generateDoc(g.doc, n)
if shouldProcess(g):
generateDoc(g.doc, n)
proc processNodeJson(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
generateJson(g.doc, n)
if shouldProcess(g):
generateJson(g.doc, n)
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
var g: PGen
new(g)
g.module = module
var d = newDocumentor(toFilename(graph.config, FileIndex module.position), graph.cache, graph.config)
var d = newDocumentor(toFullPath(graph.config, FileIndex module.position), graph.cache, graph.config)
d.hasToc = true
g.doc = d
result = g

View File

@@ -24,9 +24,15 @@ proc readExceptSet*(c: PContext, n: PNode): IntSet =
result.incl(ident.id)
proc importPureEnumField*(c: PContext; s: PSym) =
var check = strTableGet(c.importTable.symbols, s.name)
let check = strTableGet(c.importTable.symbols, s.name)
if check == nil:
strTableAdd(c.pureEnumFields, s)
let checkB = strTableGet(c.pureEnumFields, s.name)
if checkB == nil:
strTableAdd(c.pureEnumFields, s)
else:
# mark as ambigous:
incl(c.ambiguousSymbols, checkB.id)
incl(c.ambiguousSymbols, s.id)
proc rawImportSymbol(c: PContext, s: PSym) =
# This does not handle stubs, because otherwise loading on demand would be
@@ -164,7 +170,16 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
suggestSym(c.config, n.info, result, c.graph.usageSym, false)
importStmtResult.add newStrNode(toFullPath(c.config, f), n.info)
proc transformImportAs(c: PContext; n: PNode): PNode =
if n.kind == nkInfix and considerQuotedIdent(c, n[0]).s == "as":
result = newNodeI(nkImportAs, n.info)
result.add n.sons[1]
result.add n.sons[2]
else:
result = n
proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
let it = transformImportAs(c, it)
let m = myImportModule(c, it, importStmtResult)
if m != nil:
var emptySet: IntSet
@@ -174,26 +189,33 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
#importForwarded(c, m.ast, emptySet)
proc evalImport(c: PContext, n: PNode): PNode =
#result = n
result = newNodeI(nkImportStmt, n.info)
for i in countup(0, sonsLen(n) - 1):
let it = n.sons[i]
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
let sep = it[0]
let dir = it[1]
let a = newNodeI(nkInfix, it.info)
a.add sep
a.add dir
a.add sep # dummy entry, replaced in the loop
var imp = newNodeI(nkInfix, it.info)
imp.add sep
imp.add dir
imp.add sep # dummy entry, replaced in the loop
for x in it[2]:
a.sons[2] = x
impMod(c, a, result)
# transform `a/b/[c as d]` to `/a/b/c as d`
if x.kind == nkInfix and x.sons[0].ident.s == "as":
let impAs = copyTree(x)
imp.sons[2] = x.sons[1]
impAs.sons[1] = imp
impMod(c, imp, result)
else:
imp.sons[2] = x
impMod(c, imp, result)
else:
impMod(c, it, result)
proc evalFrom(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
if m != nil:
n.sons[0] = newSymNode(m)
@@ -205,6 +227,7 @@ proc evalFrom(c: PContext, n: PNode): PNode =
proc evalImportExcept*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
if m != nil:
n.sons[0] = newSymNode(m)

View File

@@ -243,7 +243,8 @@ proc mangleName(m: BModule, s: PSym): Rope =
x.add("HEX" & toHex(ord(c), 2))
inc i
result = rope(x)
if s.name.s != "this" and s.kind != skField:
# From ES5 on reserved words can be used as object field names
if s.kind != skField:
if optHotCodeReloading in m.config.options:
# When hot reloading is enabled, we must ensure that the names
# of functions and types will be preserved across rebuilds:
@@ -271,9 +272,7 @@ proc escapeJSString(s: string): string =
result.add("\"")
proc makeJSString(s: string, escapeNonAscii = true): Rope =
if s.isNil:
result = "null".rope
elif escapeNonAscii:
if escapeNonAscii:
result = strutils.escape(s).rope
else:
result = escapeJSString(s).rope
@@ -1369,7 +1368,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
let length = int(lengthOrd(p.config, t))
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
if not jsTyp.isNil:
if jsTyp.len > 0:
result = "new $1($2)" % [rope(jsTyp), rope(length)]
elif length > 32:
useMagic(p, "arrayConstr")

View File

@@ -223,6 +223,9 @@ type
proc `==`*(a, b: FileIndex): bool {.borrow.}
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
raise newException(ERecoverableError, msg)
const
InvalidFileIDX* = FileIndex(-1)

View File

@@ -244,7 +244,7 @@ else:
template fixSpelling(n: PNode; ident: PIdent; op: untyped) = discard
proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
var err = "Error: ambiguous identifier: '" & s.name.s & "'"
var err = "ambiguous identifier: '" & s.name.s & "'"
var ti: TIdentIter
var candidate = initIdentIter(ti, c.importTable.symbols, s.name)
var i = 0
@@ -259,7 +259,7 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string) =
var err = "undeclared identifier: '" & name & "'"
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency: "
err.add "\nThis might be caused by a recursive module dependency:\n"
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = ""

View File

@@ -120,7 +120,8 @@ proc skipIntLit*(t: PType): PType {.inline.} =
result = t
proc addSonSkipIntLit*(father, son: PType) =
if isNil(father.sons): father.sons = @[]
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
let s = son.skipIntLit
add(father.sons, s)
propagateToOwner(father, s)

View File

@@ -126,13 +126,6 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
of nkInfix:
let n0 = n[0]
let n1 = n[1]
if n0.kind == nkIdent and n0.ident.s == "as":
# XXX hack ahead:
n.kind = nkImportAs
n.sons[0] = n.sons[1]
n.sons[1] = n.sons[2]
n.sons.setLen(2)
return getModuleName(conf, n.sons[0])
when false:
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
if n0.kind == nkIdent and n0.ident.s == "/":

View File

@@ -102,9 +102,6 @@ proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
proc newLineInfo*(conf: ConfigRef; filename: string, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(fileInfoIdx(conf, filename), line, col)
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
raise newException(ERecoverableError, msg)
proc concat(strings: openarray[string]): string =
var totalLen = 0
@@ -176,7 +173,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0:
result = "???"
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isNil:
elif conf.m.fileInfos[fileIdx.int32].dirtyFile.len > 0:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else:
result = conf.m.fileInfos[fileIdx.int32].fullPath

View File

@@ -21,7 +21,7 @@ when defined(i386) and defined(windows) and defined(vcc):
import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt,
nodejs, scriptconfig, idents, modulegraphs, lineinfos
nodejs, scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper
when hasTinyCBackend:
import tccgen
@@ -57,69 +57,43 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
condsyms.initDefines(conf.symbols)
let self = NimProg(
supportsStdinFile: true,
processCmdLine: processCmdLine,
mainCommand: mainCommand
)
self.initDefinesProg(conf, "nim_compiler")
if paramCount() == 0:
writeCommandLineUsage(conf, conf.helpWritten)
else:
# Process command line arguments:
processCmdLine(passCmd1, "", conf)
if conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = "stdinfile"
conf.projectPath = canonicalizePath(conf, getCurrentDir())
conf.projectIsStdin = true
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
let p = splitFile(conf.projectFull)
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
conf.projectPath = canonicalizePath(conf, dir)
conf.projectName = p.name
return
self.processCmdLineAndProjectPath(conf)
if not self.loadConfigsAndRunMainCommand(cache, conf): return
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter != 0: return
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
if optRun in conf.globalOptions:
if conf.cmd == cmdCompileToJS:
var ex: string
if conf.outFile.len > 0:
ex = conf.outFile.prependCurDir.quoteShell
else:
ex = quoteShell(
completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())
loadConfigs(DefaultConfig, cache, conf) # load all config files
let scriptFile = conf.projectFull.changeFileExt("nims")
if fileExists(scriptFile):
runNimScript(cache, scriptFile, freshDefines=false, conf)
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if scriptFile == conf.projectFull: return
elif fileExists(conf.projectPath / "config.nims"):
# directory wide NimScript file
runNimScript(cache, conf.projectPath / "config.nims", freshDefines=false, conf)
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars(conf)
processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")
mainCommand(newModuleGraph(cache, conf))
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter == 0:
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
if optRun in conf.globalOptions:
if conf.cmd == cmdCompileToJS:
var ex: string
if conf.outFile.len > 0:
ex = conf.outFile.prependCurDir.quoteShell
else:
ex = quoteShell(
completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
else:
var binPath: string
if conf.outFile.len > 0:
# If the user specified an outFile path, use that directly.
binPath = conf.outFile.prependCurDir
else:
# Figure out ourselves a valid binary name.
binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
var ex = quoteShell(binPath)
execExternalProgram(conf, ex & ' ' & conf.arguments)
var binPath: string
if conf.outFile.len > 0:
# If the user specified an outFile path, use that directly.
binPath = conf.outFile.prependCurDir
else:
# Figure out ourselves a valid binary name.
binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
var ex = quoteShell(binPath)
execExternalProgram(conf, ex & ' ' & conf.arguments)
when declared(GC_setMaxPause):
GC_setMaxPause 2_000

View File

@@ -140,18 +140,19 @@ when isMainModule:
doAssert v"#aaaqwe" < v"1.1" # We cannot assume that a branch is newer.
doAssert v"#a111" < v"#head"
let conf = newConfigRef()
var rr = newStringTable()
addPackage rr, "irc-#a111"
addPackage rr, "irc-#head"
addPackage rr, "irc-0.1.0"
addPackage rr, "irc"
addPackage rr, "another"
addPackage rr, "another-0.1"
addPackage conf, rr, "irc-#a111", unknownLineInfo()
addPackage conf, rr, "irc-#head", unknownLineInfo()
addPackage conf, rr, "irc-0.1.0", unknownLineInfo()
#addPackage conf, rr, "irc", unknownLineInfo()
#addPackage conf, rr, "another", unknownLineInfo()
addPackage conf, rr, "another-0.1", unknownLineInfo()
addPackage rr, "ab-0.1.3"
addPackage rr, "ab-0.1"
addPackage rr, "justone"
addPackage conf, rr, "ab-0.1.3", unknownLineInfo()
addPackage conf, rr, "ab-0.1", unknownLineInfo()
addPackage conf, rr, "justone-1.0", unknownLineInfo()
doAssert toSeq(rr.chosen) ==
@["irc-#head", "another-0.1", "ab-0.1.3", "justone"]
@["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]

View File

@@ -175,9 +175,9 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketLe:
# BUGFIX: val, not s!
# BUGFIX: do not copy '['!
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, '[')
add(val, tokToStr(tok))
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketRi: confTok(L, tok, config, condStack)
@@ -219,10 +219,10 @@ proc readConfigFile(
closeLexer(L)
return true
proc getUserConfigPath(filename: string): string =
proc getUserConfigPath*(filename: string): string =
result = joinPath([getConfigDir(), "nim", filename])
proc getSystemConfigPath(conf: ConfigRef; filename: string): string =
proc getSystemConfigPath*(conf: ConfigRef; filename: string): string =
# try standard configuration file (installation did not distribute files
# the UNIX way)
let p = getPrefixDir(conf)
@@ -241,7 +241,7 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
if readConfigFile(configPath, cache, conf):
add(configFiles, configPath)
if optSkipConfigFile notin conf.globalOptions:
if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg))
if optSkipUserConfigFile notin conf.globalOptions:
@@ -263,4 +263,5 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
readConfigFile(projectConfig)
for filename in configFiles:
# delayed to here so that `hintConf` is honored
rawMessage(conf, hintConf, filename)

View File

@@ -12,6 +12,7 @@ import
prefixmatches
from terminal import isatty
from times import utc, fromUnix, local, getTime, format, DateTime
const
hasTinyCBackend* = defined(tinyc)
@@ -54,10 +55,10 @@ type # please make sure we have under 32 options
optGenMapping, # generate a mapping file
optRun, # run the compiled project
optCheckNep1, # check that the names adhere to NEP-1
optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file
optSkipUserConfigFile, # skip the users's config file
optSkipParentConfigFiles, # skip parent dir's config files
optSkipSystemConfigFile, # skip the system's cfg/nims config file
optSkipProjConfigFile, # skip the project's cfg/nims config file
optSkipUserConfigFile, # skip the users's cfg/nims config file
optSkipParentConfigFiles, # skip parent dir's cfg/nims config files
optNoMain, # do not generate a "main" proc
optUseColors, # use colors for hints, warnings, and errors
optThreads, # support for multi-threading
@@ -104,8 +105,8 @@ type
cmdJsonScript # compile a .json build file
TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcNone, gcBoehm, gcGo, gcRegions, gcMarkAndSweep, gcRefc,
gcV2, gcGenerational
gcNone, gcBoehm, gcGo, gcRegions, gcMarkAndSweep, gcDestructors,
gcRefc, gcV2
IdeCmd* = enum
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
@@ -260,6 +261,24 @@ const
optPatterns, optNilCheck, optMoveCheck}
DefaultGlobalOptions* = {optThreadAnalysis}
proc getSrcTimestamp(): DateTime =
try:
result = utc(fromUnix(parseInt(getEnv("SOURCE_DATE_EPOCH",
"not a number"))))
except ValueError:
# Environment variable malformed.
# https://reproducible-builds.org/specs/source-date-epoch/: "If the
# value is malformed, the build process SHOULD exit with a non-zero
# error code", which this doesn't do. This uses local time, because
# that maintains compatibility with existing usage.
result = utc getTime()
proc getDateStr*(): string =
result = format(getSrcTimestamp(), "yyyy-MM-dd")
proc getClockStr*(): string =
result = format(getSrcTimestamp(), "HH:mm:ss")
template newPackageCache*(): untyped =
newStringTable(when FileSystemCaseSensitive:
modeCaseInsensitive
@@ -374,7 +393,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
else: discard
proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd in {cmdDoc, cmdIdeTools}
proc usesNativeGC*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
template compilationCachePresent*(conf: ConfigRef): untyped =
conf.symbolFiles in {v2Sf, writeOnlySf}
@@ -392,6 +411,7 @@ const
TexExt* = "tex"
IniExt* = "ini"
DefaultConfig* = "nim.cfg"
DefaultConfigNims* = "config.nims"
DocConfig* = "nimdoc.cfg"
DocTexConfig* = "nimdoc.tex.cfg"

View File

@@ -33,7 +33,8 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
result = file.splitFile.name
break packageSearch
# we also store if we didn't find anything:
if result.isNil: result = ""
when not defined(nimNoNilSeqs):
if result.isNil: result = ""
for d in myParentDirs(path):
#echo "set cache ", d, " |", result, "|", parents
conf.packageCache[d] = result

View File

@@ -71,6 +71,7 @@ const
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
wThread, wRaises, wLocks, wTags, wGcSafe}
forVarPragmas* = {wInject, wGensym}
allRoutinePragmas* = methodPragmas + iteratorPragmas + lambdaPragmas
proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
@@ -95,7 +96,9 @@ const
errIntLiteralExpected = "integer literal expected"
proc invalidPragma*(c: PContext; n: PNode) =
localError(c.config, n.info, "invalid pragma: " % renderTree(n, {renderNoComments}))
localError(c.config, n.info, "invalid pragma: " & renderTree(n, {renderNoComments}))
proc illegalCustomPragma*(c: PContext, n: PNode, s: PSym) =
localError(c.config, n.info, "cannot attach a custom pragma to '" & s.name.s & "'")
proc pragmaAsm*(c: PContext, n: PNode): char =
result = '\0'
@@ -336,6 +339,20 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
of wPatterns: {optPatterns}
else: {}
proc processExperimental(c: PContext; n: PNode) =
if n.kind notin nkPragmaCallKinds or n.len != 2:
c.features.incl oldExperimentalFeatures
else:
n[1] = c.semConstExpr(c, n[1])
case n[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
c.features.incl parseEnum[Feature](n[1].strVal)
except ValueError:
localError(c.config, n[1].info, "unknown experimental feature")
else:
localError(c.config, n.info, errStringLiteralExpected)
proc tryProcessOption(c: PContext, n: PNode, resOptions: var TOptions): bool =
result = true
if n.kind notin nkPragmaCallKinds or n.len != 2: result = false
@@ -343,6 +360,9 @@ proc tryProcessOption(c: PContext, n: PNode, resOptions: var TOptions): bool =
elif n.sons[0].kind != nkIdent: result = false
else:
let sw = whichKeyword(n.sons[0].ident)
if sw == wExperimental:
processExperimental(c, n)
return true
let opts = pragmaToOptions(sw)
if opts != {}:
onOff(c, n, opts, resOptions)
@@ -381,6 +401,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
x.defaultCC = y.defaultCC
x.dynlib = y.dynlib
x.notes = c.config.notes
x.features = c.features
c.optionStack.add(x)
for i in countup(start, sonsLen(n) - 1):
if not tryProcessOption(c, n.sons[i], c.config.options):
@@ -400,6 +421,7 @@ proc processPop(c: PContext, n: PNode) =
else:
c.config.options = c.optionStack[^1].options
c.config.notes = c.optionStack[^1].notes
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)
proc processDefine(c: PContext, n: PNode) =
@@ -710,9 +732,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
elif n.kind == nkExprColonExpr:
result.kind = n.kind # pragma(arg) -> pragma: arg
proc processExperimental(c: PContext; n: PNode; s: PSym) =
if not isTopLevel(c):
localError(c.config, n.info, "'experimental' pragma only valid as toplevel statement")
proc processExperimental(c: PContext; n: PNode) =
if n.kind notin nkPragmaCallKinds or n.len != 2:
c.features.incl oldExperimentalFeatures
else:
@@ -1065,7 +1085,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else:
it.sons[1] = c.semExpr(c, it.sons[1])
of wExperimental:
processExperimental(c, it, sym)
if not isTopLevel(c):
localError(c.config, n.info, "'experimental' pragma only valid as toplevel statement or in a 'push' environment")
processExperimental(c, it)
of wThis:
if it.kind in nkPragmaCallKinds and it.len == 2:
c.selfName = considerQuotedIdent(c, it[1])
@@ -1090,9 +1112,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else: sym.flags.incl sfUsed
of wLiftLocals: discard
else: invalidPragma(c, it)
else:
elif sym.kind in {skField,skProc,skFunc,skConverter,skMethod,skType}:
n.sons[i] = semCustomPragma(c, it)
else:
illegalCustomPragma(c, it, sym)
proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
validPragmas: TSpecialWords) =

View File

@@ -175,7 +175,7 @@ proc put(g: var TSrcGen, kind: TTokType, s: string) =
g.pendingWhitespace = s.len
proc putComment(g: var TSrcGen, s: string) =
if s.isNil: return
if s.len == 0: return
var i = 0
let hi = len(s) - 1
var isCode = (len(s) >= 2) and (s[1] != ' ')
@@ -216,7 +216,7 @@ proc putComment(g: var TSrcGen, s: string) =
optNL(g)
proc maxLineLength(s: string): int =
if s.isNil: return 0
if s.len == 0: return 0
var i = 0
let hi = len(s) - 1
var lineLen = 0
@@ -752,7 +752,8 @@ proc gproc(g: var TSrcGen, n: PNode) =
gsub(g, n.sons[genericParamsPos])
g.inGenericParams = oldInGenericParams
gsub(g, n.sons[paramsPos])
gsub(g, n.sons[pragmasPos])
if renderNoPragmas notin g.flags:
gsub(g, n.sons[pragmasPos])
if renderNoBody notin g.flags:
if n.sons[bodyPos].kind != nkEmpty:
put(g, tkSpaces, Space)
@@ -1297,17 +1298,16 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkContinue, "continue")
gsub(g, n, 0)
of nkPragma:
if renderNoPragmas notin g.flags:
if g.inPragma <= 0:
inc g.inPragma
#if not previousNL(g):
put(g, tkSpaces, Space)
put(g, tkCurlyDotLe, "{.")
gcomma(g, n, emptyContext)
put(g, tkCurlyDotRi, ".}")
dec g.inPragma
else:
gcomma(g, n, emptyContext)
if g.inPragma <= 0:
inc g.inPragma
#if not previousNL(g):
put(g, tkSpaces, Space)
put(g, tkCurlyDotLe, "{.")
gcomma(g, n, emptyContext)
put(g, tkCurlyDotRi, ".}")
dec g.inPragma
else:
gcomma(g, n, emptyContext)
of nkImportStmt, nkExportStmt:
if n.kind == nkImportStmt:
putWithSpace(g, tkImport, "import")

View File

@@ -171,7 +171,7 @@ proc runNimScript*(cache: IdentCache; scriptName: string;
incl(m.flags, sfMainModule)
graph.vm = setupVM(m, cache, scriptName, graph)
graph.compileSystemModule()
graph.compileSystemModule() # TODO: see why this unsets hintConf in conf.notes
discard graph.processModule(m, llStreamOpen(scriptName, fmRead))
# ensure we load 'system.nim' again for the real non-config stuff!

View File

@@ -607,28 +607,6 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
#if c.config.cmd == cmdIdeTools: findSuggest(c, n)
rod.storeNode(c.graph, c.module, result)
proc testExamples(c: PContext) =
let outputDir = c.config.getNimcacheDir / "runnableExamples"
createDir(outputDir)
let inp = toFullPath(c.config, c.module.info)
let outp = outputDir / extractFilename(inp.changeFileExt"" & "_examples.nim")
let nimcache = outp.changeFileExt"" & "_nimcache"
renderModule(c.runnableExamples, inp, outp, conf = c.config)
let backend = if isDefined(c.config, "js"): "js"
elif isDefined(c.config, "cpp"): "cpp"
elif isDefined(c.config, "objc"): "objc"
else: "c"
if os.execShellCmd(os.getAppFilename() & " " & backend & " --nimcache:" & nimcache & " -r " & outp) != 0:
quit "[Examples] failed: see " & outp
else:
# keep generated source file `outp` to allow inspection.
rawMessage(c.config, hintSuccess, ["runnableExamples: " & outp])
removeFile(outp.changeFileExt(ExeExt))
try:
removeDir(nimcache)
except OSError:
discard
proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
var c = PContext(context)
if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
@@ -644,7 +622,6 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
popOwner(c)
popProcCon(c)
storeRemaining(c.graph, c.module)
if c.runnableExamples != nil: testExamples(c)
const semPass* = makePass(myOpen, myProcess, myClose,
isFrontend = true)

View File

@@ -197,13 +197,10 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind
of tyNone, tyEmpty, tyVoid: discard
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
tyPtr, tyString, tyRef, tyOpt:
tyPtr, tyRef, tyOpt:
defaultOp(c, t, body, x, y)
of tyArray, tySequence:
of tyArray:
if {tfHasAsgn, tfUncheckedArray} * t.flags == {tfHasAsgn}:
if t.kind == tySequence:
# XXX add 'nil' handling here
body.add newSeqCall(c.c, x, y)
let i = declareCounter(c, body, firstOrd(c.c.config, t))
let whileLoop = genWhileLoop(c, i, x)
let elemType = t.lastSon
@@ -213,6 +210,27 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add whileLoop
else:
defaultOp(c, t, body, x, y)
of tySequence:
# note that tfHasAsgn is propagated so we need the check on
# 'selectedGC' here to determine if we have the new runtime.
if c.c.config.selectedGC == gcDestructors:
discard considerOverloadedOp(c, t, body, x, y)
elif tfHasAsgn in t.flags:
body.add newSeqCall(c.c, x, y)
let i = declareCounter(c, body, firstOrd(c.c.config, t))
let whileLoop = genWhileLoop(c, i, x)
let elemType = t.lastSon
liftBodyAux(c, elemType, whileLoop.sons[1], x.at(i, elemType),
y.at(i, elemType))
addIncStmt(c, whileLoop.sons[1], i)
body.add whileLoop
else:
defaultOp(c, t, body, x, y)
of tyString:
if tfHasAsgn in t.flags:
discard considerOverloadedOp(c, t, body, x, y)
else:
defaultOp(c, t, body, x, y)
of tyObject, tyDistinct:
if not considerOverloadedOp(c, t, body, x, y):
if t.sons[0] != nil:

View File

@@ -138,7 +138,9 @@ proc effectProblem(f, a: PType; result: var string) =
proc renderNotLValue(n: PNode): string =
result = $n
if n.kind in {nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv} and n.len == 2:
if n.kind == nkHiddenCallConv and n.len > 1:
result = $n[0] & "(" & result & ")"
elif n.kind in {nkHiddenStdConv, nkHiddenSubConv} and n.len == 2:
result = typeToString(n.typ.skipTypes(abstractVar)) & "(" & result & ")"
proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
@@ -164,8 +166,20 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
prefer = preferModuleInfo
break
when false:
# we pretend procs are attached to the type of the first
# argument in order to remove plenty of candidates. This is
# comparable to what C# does and C# is doing fine.
var filterOnlyFirst = false
for err in errors:
if err.firstMismatch > 1:
filterOnlyFirst = true
break
var candidates = ""
for err in errors:
when false:
if filterOnlyFirst and err.firstMismatch == 1: continue
if err.sym.kind in routineKinds and err.sym.ast != nil:
add(candidates, renderTree(err.sym.ast,
{renderNoBody, renderNoComments, renderNoPragmas}))
@@ -175,15 +189,18 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
if err.firstMismatch != 0 and n.len > 1:
let cond = n.len > 2
if cond:
candidates.add(" first type mismatch at position: " & $err.firstMismatch &
"\n required type: ")
candidates.add(" first type mismatch at position: " & $abs(err.firstMismatch))
if err.firstMismatch >= 0: candidates.add("\n required type: ")
else: candidates.add("\n unknown named parameter: " & $n[-err.firstMismatch][0])
var wanted, got: PType = nil
if err.firstMismatch < err.sym.typ.len:
if err.firstMismatch < 0:
discard
elif err.firstMismatch < err.sym.typ.len:
wanted = err.sym.typ.sons[err.firstMismatch]
if cond: candidates.add typeToString(wanted)
else:
if cond: candidates.add "none"
if err.firstMismatch < n.len:
if err.firstMismatch > 0 and err.firstMismatch < n.len:
if cond:
candidates.add "\n but expression '"
candidates.add renderTree(n[err.firstMismatch])

View File

@@ -22,6 +22,7 @@ type
defaultCC*: TCallingConvention
dynlib*: PLib
notes*: TNoteKinds
features*: set[Feature]
otherPragmas*: PNode # every pragma can be pushed
POptionEntry* = ref TOptionEntry
@@ -140,7 +141,6 @@ type
# the generic type has been constructed completely. See
# tests/destructor/topttree.nim for an example that
# would otherwise fail.
runnableExamples*: PNode
template config*(c: PContext): ConfigRef = c.graph.config

View File

@@ -800,7 +800,9 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
analyseIfAddressTakenInCall(c, result)
if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
if result.typ != nil: liftTypeBoundOps(c, result.typ, n.info)
if result.typ != nil and
not (result.typ.kind == tySequence and result.typ.sons[0].kind == tyEmpty):
liftTypeBoundOps(c, result.typ, n.info)
#result = patchResolvedTypeBoundOp(c, result)
if c.matchedConcept == nil:
result = evalAtCompileTime(c, result)
@@ -1389,8 +1391,8 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
n.sons[1] = semConstExpr(c, n.sons[1])
if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
{tyInt..tyInt64}:
var idx = getOrdValue(n.sons[1])
if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
let idx = getOrdValue(n.sons[1])
if idx >= 0 and idx < len(arr): n.typ = arr.sons[int(idx)]
else: localError(c.config, n.info, "invalid index value for tuple subscript")
result = n
else:
@@ -1565,6 +1567,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
n.sons[1] = fitNode(c, le, rhs, n.info)
liftTypeBoundOps(c, lhs.typ, lhs.info)
#liftTypeBoundOps(c, n.sons[0].typ, n.sons[0].info)
fixAbstractType(c, n)
asgnToResultVar(c, n, n.sons[0], n.sons[1])
@@ -1950,13 +1953,6 @@ proc setMs(n: PNode, s: PSym): PNode =
n.sons[0] = newSymNode(s)
n.sons[0].info = n.info
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
# this is a hotspot in the compiler!
# DON'T forget to update ast.SpecialSemMagics if you add a magic here!
@@ -2030,16 +2026,17 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = magicsAfterOverloadResolution(c, result, flags)
of mRunnableExamples:
if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
if sfMainModule in c.module.flags:
let inp = toFullPath(c.config, c.module.info)
if c.runnableExamples == nil:
c.runnableExamples = newTree(nkStmtList,
newTree(nkImportStmt, newStrNode(nkStrLit, expandFilename(inp))))
let imports = newTree(nkStmtList)
var saved_lastSon = copyTree n.lastSon
extractImports(saved_lastSon, imports)
for imp in imports: c.runnableExamples.add imp
c.runnableExamples.add newTree(nkBlockStmt, c.graph.emptyNode, copyTree saved_lastSon)
when false:
if sfMainModule in c.module.flags:
let inp = toFullPath(c.config, c.module.info)
if c.runnableExamples == nil:
c.runnableExamples = newTree(nkStmtList,
newTree(nkImportStmt, newStrNode(nkStrLit, expandFilename(inp))))
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: c.runnableExamples.add imp
c.runnableExamples.add newTree(nkBlockStmt, c.graph.emptyNode, copyTree savedLastSon)
result = setMs(n, s)
else:
result = c.graph.emptyNode
@@ -2082,7 +2079,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
typ = commonType(typ, it.sons[1].typ)
result = n # when nimvm is not elimited until codegen
else:
var e = semConstExpr(c, it.sons[0])
let e = forceBool(c, semConstExpr(c, it.sons[0]))
if e.kind != nkIntLit:
# can happen for cascading errors, assume false
# InternalError(n.info, "semWhen")

View File

@@ -11,7 +11,7 @@
# and evaluation phase
import
strutils, options, ast, astalgo, trees, treetab, nimsets, times,
strutils, options, ast, astalgo, trees, treetab, nimsets,
nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
commands, magicsys, modulegraphs, strtabs, lineinfos
@@ -450,21 +450,38 @@ proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
localError(g.config, n.info, "cannot convert " & $value &
" to " & typeToString(n.typ))
proc foldConv*(n, a: PNode; g: ModuleGraph; check = false): PNode =
proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
let dstTyp = skipTypes(n.typ, abstractRange)
let srcTyp = skipTypes(a.typ, abstractRange)
# XXX range checks?
case skipTypes(n.typ, abstractRange).kind
of tyInt..tyInt64, tyUInt..tyUInt64:
case skipTypes(a.typ, abstractRange).kind
case dstTyp.kind
of tyInt..tyInt64, tyUint..tyUInt64:
case srcTyp.kind
of tyFloat..tyFloat64:
result = newIntNodeT(int(getFloat(a)), n, g)
of tyChar: result = newIntNodeT(getOrdValue(a), n, g)
of tyChar:
result = newIntNodeT(getOrdValue(a), n, g)
of tyUInt8..tyUInt32, tyInt8..tyInt32:
let fromSigned = srcTyp.kind in tyInt..tyInt64
let toSigned = dstTyp.kind in tyInt..tyInt64
let mask = lastOrd(g.config, dstTyp, fixedUnsigned=true)
var val =
if toSigned:
a.getOrdValue mod mask
else:
a.getOrdValue and mask
result = newIntNodeT(val, n, g)
else:
result = a
result.typ = n.typ
if check and result.kind in {nkCharLit..nkUInt64Lit}:
rangeCheck(n, result.intVal, g)
of tyFloat..tyFloat64:
case skipTypes(a.typ, abstractRange).kind
case srcTyp.kind
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
else:
@@ -549,19 +566,6 @@ proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
result = nil
proc getSrcTimestamp(): DateTime =
try:
result = utc(fromUnix(parseInt(getEnv("SOURCE_DATE_EPOCH",
"not a number"))))
except ValueError:
# Environment variable malformed.
# https://reproducible-builds.org/specs/source-date-epoch/: "If the
# value is malformed, the build process SHOULD exit with a non-zero
# error code", which this doesn't do. This uses local time, because
# that maintains compatibility with existing usage.
result = local(getTime())
case n.kind
of nkSym:
var s = n.sym
@@ -571,10 +575,8 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of skConst:
case s.magic
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n, g)
of mCompileDate: result = newStrNodeT(format(getSrcTimestamp(),
"yyyy-MM-dd"), n, g)
of mCompileTime: result = newStrNodeT(format(getSrcTimestamp(),
"HH:mm:ss"), n, g)
of mCompileDate: result = newStrNodeT(getDateStr(), n, g)
of mCompileTime: result = newStrNodeT(getClockStr(), n, g)
of mCpuEndian: result = newIntNodeT(ord(CPU[g.config.target.targetCPU].endian), n, g)
of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.targetOS].name), n, g)
of mHostCPU: result = newStrNodeT(platform.CPU[g.config.target.targetCPU].name.toLowerAscii, n, g)
@@ -742,7 +744,8 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var a = getConstExpr(m, n.sons[1], g)
if a == nil: return
result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
# XXX: we should enable `check` for other conversion types too
result = foldConv(n, a, g, check=n.kind == nkHiddenSubConv)
of nkCast:
var a = getConstExpr(m, n.sons[1], g)
if a == nil: return

View File

@@ -215,7 +215,7 @@ proc semGenericStmt(c: PContext, n: PNode,
checkMinSonsLen(n, 1, c.config)
let fn = n.sons[0]
var s = qualifiedLookUp(c, fn, {})
if s == nil and
if s == nil and
{withinMixin, withinConcept}*flags == {} and
fn.kind in {nkIdent, nkAccQuoted} and
considerQuotedIdent(c, fn).id notin ctx.toMixin:
@@ -225,7 +225,7 @@ proc semGenericStmt(c: PContext, n: PNode,
var mixinContext = false
if s != nil:
incl(s.flags, sfUsed)
mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles}
mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles, mRunnableExamples}
let sc = symChoice(c, fn, s, if s.isMixedIn: scForceOpen else: scOpen)
case s.kind
of skMacro:

View File

@@ -326,7 +326,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
# no need to instantiate generic templates/macros:
internalAssert c.config, fn.kind notin {skMacro, skTemplate}
# generates an instantiated proc
if c.instCounter > 1000: internalError(c.config, fn.ast.info, "nesting too deep")
if c.instCounter > 50:
globalError(c.config, info, "generic instantiation too nested")
inc(c.instCounter)
# careful! we copy the whole AST including the possibly nil body!
var n = copyTree(fn.ast)

View File

@@ -323,13 +323,13 @@ proc catches(tracked: PEffects, e: PType) =
dec L
else:
inc i
if not isNil(tracked.exc.sons):
if tracked.exc.len > 0:
setLen(tracked.exc.sons, L)
else:
assert L == 0
proc catchesAll(tracked: PEffects) =
if not isNil(tracked.exc.sons):
if tracked.exc.len > 0:
setLen(tracked.exc.sons, tracked.bottom)
proc track(tracked: PEffects, n: PNode)

View File

@@ -567,6 +567,8 @@ proc symForVar(c: PContext, n: PNode): PSym =
let m = if n.kind == nkPragmaExpr: n.sons[0] else: n
result = newSymG(skForVar, m, c)
styleCheckDef(c.config, result)
if n.kind == nkPragmaExpr:
pragma(c, result, n.sons[1], forVarPragmas)
proc semForVars(c: PContext, n: PNode): PNode =
result = n
@@ -802,7 +804,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
if not isImportedException(typ, c.config):
if typ.kind != tyRef or typ.lastSon.kind != tyObject:
localError(c.config, n.info, errExprCannotBeRaised)
if not isException(typ.lastSon):
if typ.len > 0 and not isException(typ.lastSon):
localError(c.config, n.info, "raised object of type $1 does not inherit from Exception",
[typeToString(typ)])
@@ -1056,8 +1058,8 @@ proc checkForMetaFields(c: PContext; n: PNode) =
case t.kind
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef,
tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink:
let start = int ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start ..< t.sons.len:
let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start ..< t.len:
checkMeta(t.sons[i])
else:
checkMeta(t)
@@ -1376,7 +1378,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon
elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
else: break
if obj.kind in {tyObject, tyDistinct}:
if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
if obj.destructor.isNil:
obj.destructor = s
else:
@@ -1398,7 +1400,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
if t.kind == tyGenericBody: t = t.lastSon
elif t.kind == tyGenericInvocation: t = t.sons[0]
else: break
if t.kind in {tyObject, tyDistinct, tyEnum}:
if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}:
if t.deepCopy.isNil: t.deepCopy = s
else:
localError(c.config, n.info, errGenerated,
@@ -1427,7 +1429,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
elif objB.kind in {tyGenericInvocation, tyGenericInst}:
objB = objB.sons[0]
else: break
if obj.kind in {tyObject, tyDistinct} and sameType(obj, objB):
if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, objB):
let opr = if s.name.s == "=": addr(obj.assignment) else: addr(obj.sink)
if opr[].isNil:
opr[] = s
@@ -1592,7 +1594,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags:
localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
("'" & proto.name.s & "' from " & c.config$proto.info))
if sfForward notin proto.flags:
if sfForward notin proto.flags and proto.magic == mNone:
wrongRedefinition(c, n.info, proto.name.s)
excl(proto.flags, sfForward)
closeScope(c) # close scope with wrong parameter symbols
@@ -1609,7 +1611,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[pragmasPos] = proto.ast.sons[pragmasPos]
if n.sons[namePos].kind != nkSym: internalError(c.config, n.info, "semProcAux")
n.sons[namePos].sym = proto
if importantComments(c.config) and not isNil(proto.ast.comment):
if importantComments(c.config) and proto.ast.comment.len > 0:
n.comment = proto.ast.comment
proto.ast = n # needed for code generation
popOwner(c)
@@ -1658,7 +1660,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
openScope(c)
n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
closeScope(c)
fixupInstantiatedSymbols(c, s)
if s.magic == mNone:
fixupInstantiatedSymbols(c, s)
if s.kind == skMethod: semMethodPrototype(c, s, n)
if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc:

View File

@@ -210,7 +210,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
if s != nil and s.owner == c.owner and sfGenSym in s.flags:
styleCheckUse(n.info, s)
replaceIdentBySym(c.c, n, newSymNode(s, n.info))
else:
elif not (n.kind == nkSym and sfGenSym in n.sym.flags):
let local = newGenSym(k, ident, c)
addPrelimDecl(c.c, local)
styleCheckDef(c.c.config, n.info, local)

View File

@@ -145,9 +145,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
localError(c.config, n.info, errXExpectsOneTypeParam % "set")
addSonSkipIntLit(result, errorType(c))
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType =
result = newOrPrevType(kind, prev, c)
proc semContainerArg(c: PContext; n: PNode, kindStr: string; result: PType) =
if sonsLen(n) == 2:
var base = semTypeNode(c, n.sons[1], nil)
if base.kind == tyVoid:
@@ -157,6 +155,11 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
localError(c.config, n.info, errXExpectsOneTypeParam % kindStr)
addSonSkipIntLit(result, errorType(c))
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType =
result = newOrPrevType(kind, prev, c)
semContainerArg(c, n, kindStr, result)
proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVarargs, prev, c)
if sonsLen(n) == 2 or sonsLen(n) == 3:
@@ -1507,7 +1510,24 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mRange: result = semRange(c, n, prev)
of mSet: result = semSet(c, n, prev)
of mOrdinal: result = semOrdinal(c, n, prev)
of mSeq: result = semContainer(c, n, tySequence, "seq", prev)
of mSeq:
if c.config.selectedGc == gcDestructors:
let s = c.graph.sysTypes[tySequence]
assert s != nil
assert prev == nil
result = copyType(s, s.owner, keepId=false)
# XXX figure out why this has children already...
result.sons.setLen 0
result.n = nil
if c.config.selectedGc == gcDestructors:
result.flags = {tfHasAsgn}
else:
result.flags = {}
semContainerArg(c, n, "seq", result)
else:
result = semContainer(c, n, tySequence, "seq", prev)
if c.config.selectedGc == gcDestructors:
incl result.flags, tfHasAsgn
of mOpt: result = semContainer(c, n, tyOpt, "opt", prev)
of mVarargs: result = semVarargs(c, n, prev)
of mTypeDesc, mTypeTy:
@@ -1687,6 +1707,9 @@ proc processMagicType(c: PContext, m: PSym) =
of mString:
setMagicType(c.config, m, tyString, c.config.target.ptrSize)
rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
when false:
if c.config.selectedGc == gcDestructors:
incl m.typ.flags, tfHasAsgn
of mCstring:
setMagicType(c.config, m, tyCString, c.config.target.ptrSize)
rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
@@ -1726,6 +1749,10 @@ proc processMagicType(c: PContext, m: PSym) =
setMagicType(c.config, m, tySet, 0)
of mSeq:
setMagicType(c.config, m, tySequence, 0)
if c.config.selectedGc == gcDestructors:
incl m.typ.flags, tfHasAsgn
assert c.graph.sysTypes[tySequence] == nil
c.graph.sysTypes[tySequence] = m.typ
of mOpt:
setMagicType(c.config, m, tyOpt, 0)
of mOrdinal:

View File

@@ -1921,6 +1921,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
result.typ.n = arg
return
let oldInheritancePenalty = m.inheritancePenalty
var r = typeRel(m, f, a)
# This special typing rule for macros and templates is not documented
@@ -2002,7 +2003,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
if arg.typ == nil:
result = arg
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple or
m.inheritancePenalty > 0:
m.inheritancePenalty > oldInheritancePenalty:
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
elif arg.typ.isEmptyContainer:
result = arg.copyTree
@@ -2131,6 +2132,10 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
styleCheckUse(arg.info, arg.sons[best].sym)
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
argOrig)
when false:
if m.calleeSym != nil and m.calleeSym.name.s == "[]":
echo m.c.config $ arg.info, " for ", m.calleeSym.name.s, " ", m.c.config $ m.calleeSym.info
writeMatches(m)
proc setSon(father: PNode, at: int, son: PNode) =
let oldLen = father.len
@@ -2226,12 +2231,20 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
formal = m.callee.n.sons[f].sym
incl(marker, formal.position)
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1, container)
if n.sons[a].kind == nkHiddenStdConv:
doAssert n.sons[a].sons[0].kind == nkEmpty and
n.sons[a].sons[1].kind == nkArgList and
n.sons[a].sons[1].len == 0
# Steal the container and pass it along
setSon(m.call, formal.position + 1, n.sons[a].sons[1])
else:
incrIndexType(container.typ)
addSon(container, n.sons[a])
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1, container)
else:
incrIndexType(container.typ)
addSon(container, n.sons[a])
elif n.sons[a].kind == nkExprEqExpr:
# named param
# check if m.callee has such a param:
@@ -2239,11 +2252,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
if n.sons[a].sons[0].kind != nkIdent:
localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
m.state = csNoMatch
m.firstMismatch = -a
return
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
if formal == nil:
# no error message!
m.state = csNoMatch
m.firstMismatch = -a
return
if containsOrIncl(marker, formal.position):
# already in namedParams, so no match
@@ -2261,6 +2276,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
n.sons[a].sons[1], n.sons[a].sons[1])
if arg == nil:
m.state = csNoMatch
m.firstMismatch = a
return
checkConstraint(n.sons[a].sons[1])
if m.baseTypeMatch:
@@ -2379,6 +2395,11 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
if m.magic in {mArrGet, mArrPut}:
m.state = csMatch
m.call = n
# Note the following doesn't work as it would produce ambiguities.
# Instead we patch system.nim, see bug #8049.
when false:
inc m.genericMatches
inc m.exactMatches
return
var marker = initIntSet()
matchesAux(c, n, nOrig, m, marker)
@@ -2390,7 +2411,10 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
if not containsOrIncl(marker, formal.position):
if formal.ast == nil:
if formal.typ.kind == tyVarargs:
var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
# For consistency with what happens in `matchesAux` select the
# container node kind accordingly
let cnKind = if formal.typ.isVarargsUntyped: nkArgList else: nkBracket
var container = newNodeIT(cnKind, n.info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1,
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
else:

View File

@@ -47,7 +47,7 @@ template origModuleName(m: PSym): string = m.name.s
proc findDocComment(n: PNode): PNode =
if n == nil: return nil
if not isNil(n.comment): return n
if n.comment.len > 0: return n
if n.kind in {nkStmtList, nkStmtListExpr, nkObjectTy, nkRecList} and n.len > 0:
result = findDocComment(n.sons[0])
if result != nil: return
@@ -434,7 +434,7 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
## misnamed: should be 'symDeclared'
when defined(nimsuggest):
if conf.suggestVersion == 0:
if s.allUsages.isNil:
if s.allUsages.len == 0:
s.allUsages = @[info]
else:
s.addNoDup(info)

View File

@@ -39,24 +39,24 @@ proc setupEnvironment =
addIncludePath(gTinyC, libpath)
when defined(windows):
addSysincludePath(gTinyC, nimrodDir / "tinyc/win32/include")
addSysincludePath(gTinyC, nimrodDir / "tinyc/include")
addSysincludePath(gTinyC, nimDir / "tinyc/win32/include")
addSysincludePath(gTinyC, nimDir / "tinyc/include")
when defined(windows):
defineSymbol(gTinyC, "_WIN32", nil)
# we need Mingw's headers too:
var gccbin = getConfigVar("gcc.path") % ["nim", nimDir]
addSysincludePath(gTinyC, gccbin /../ "include")
#addFile(nimrodDir / r"tinyc\win32\wincrt1.o")
addFile(nimrodDir / r"tinyc\win32\alloca86.o")
addFile(nimrodDir / r"tinyc\win32\chkstk.o")
#addFile(nimrodDir / r"tinyc\win32\crt1.o")
#addFile(nimDir / r"tinyc\win32\wincrt1.o")
addFile(nimDir / r"tinyc\win32\alloca86.o")
addFile(nimDir / r"tinyc\win32\chkstk.o")
#addFile(nimDir / r"tinyc\win32\crt1.o")
#addFile(nimrodDir / r"tinyc\win32\dllcrt1.o")
#addFile(nimrodDir / r"tinyc\win32\dllmain.o")
addFile(nimrodDir / r"tinyc\win32\libtcc1.o")
#addFile(nimDir / r"tinyc\win32\dllcrt1.o")
#addFile(nimDir / r"tinyc\win32\dllmain.o")
addFile(nimDir / r"tinyc\win32\libtcc1.o")
#addFile(nimrodDir / r"tinyc\win32\lib\crt1.c")
#addFile(nimrodDir / r"tinyc\lib\libtcc1.c")
#addFile(nimDir / r"tinyc\win32\lib\crt1.c")
#addFile(nimDir / r"tinyc\lib\libtcc1.c")
else:
addSysincludePath(gTinyC, "/usr/include")
when defined(amd64):

View File

@@ -1050,8 +1050,8 @@ proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode =
when useEffectSystem: trackTopLevelStmt(g, module, result)
#if n.info ?? "temp.nim":
# echo renderTree(result, {renderIds})
if c.needsDestroyPass:
result = injectDestructorCalls(g, module, result)
#if c.needsDestroyPass:
# result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf)
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
@@ -1063,6 +1063,6 @@ proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
liftDefer(c, result)
# expressions are not to be injected with destructor calls as that
# the list of top level statements needs to be collected before.
if c.needsDestroyPass:
result = injectDestructorCalls(g, module, result)
#if c.needsDestroyPass:
# result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf)

View File

@@ -29,8 +29,7 @@ proc hashTree(n: PNode): Hash =
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
result = result !& toInt(n.floatVal)
of nkStrLit..nkTripleStrLit:
if not n.strVal.isNil:
result = result !& hash(n.strVal)
result = result !& hash(n.strVal)
else:
for i in countup(0, sonsLen(n) - 1):
result = result !& hashTree(n.sons[i])

View File

@@ -278,6 +278,8 @@ proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
proc isGCRef(t: PType): bool =
result = t.kind in GcTypeKinds or
(t.kind == tyProc and t.callConv == ccClosure)
if result and t.kind in {tyString, tySequence} and tfHasAsgn in t.flags:
result = false
proc containsGarbageCollectedRef*(typ: PType): bool =
# returns true if typ contains a reference, sequence or string (all the
@@ -759,9 +761,10 @@ proc initSameTypeClosure: TSameTypeClosure =
discard
proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
result = not isNil(c.s) and c.s.contains((a.id, b.id))
result = c.s.len > 0 and c.s.contains((a.id, b.id))
if not result:
if isNil(c.s): c.s = @[]
when not defined(nimNoNilSeqs):
if isNil(c.s): c.s = @[]
c.s.add((a.id, b.id))
proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool
@@ -1341,14 +1344,23 @@ proc computeSizeAux(conf: ConfigRef; typ: PType, a: var BiggestInt): BiggestInt
if typ.callConv == ccClosure: result = 2 * conf.target.ptrSize
else: result = conf.target.ptrSize
a = conf.target.ptrSize
of tyString, tyNil:
of tyString:
if tfHasAsgn in typ.flags:
result = conf.target.ptrSize * 2
else:
result = conf.target.ptrSize
of tyNil:
result = conf.target.ptrSize
a = result
of tyCString, tySequence, tyPtr, tyRef, tyVar, tyLent, tyOpenArray:
let base = typ.lastSon
if base == typ or (base.kind == tyTuple and base.size==szIllegalRecursion):
result = szIllegalRecursion
else: result = conf.target.ptrSize
else:
if typ.kind == tySequence and tfHasAsgn in typ.flags:
result = conf.target.ptrSize * 2
else:
result = conf.target.ptrSize
a = result
of tyArray:
let elemSize = computeSizeAux(conf, typ.sons[1], a)

View File

@@ -29,7 +29,6 @@ proc renderPlainSymbolName*(n: PNode): string =
else:
result = ""
#internalError(n.info, "renderPlainSymbolName() with " & $n.kind)
assert(not result.isNil)
proc renderType(n: PNode): string =
## Returns a string with the node type or the empty string.
@@ -80,7 +79,6 @@ proc renderType(n: PNode): string =
for i in 1 ..< len(n): result.add(renderType(n[i]) & ',')
result[len(result)-1] = ']'
else: result = ""
assert(not result.isNil)
proc renderParamTypes(found: var seq[string], n: PNode) =

View File

@@ -81,14 +81,16 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
msgWriteln(c.config, s)
proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
msg: string, n: PNode = nil) =
msg: string, lineInfo: TLineInfo) =
msgWriteln(c.config, "stack trace: (most recent call last)")
stackTraceAux(c, tos, pc)
# XXX test if we want 'globalError' for every mode
let lineInfo = if n == nil: c.debug[pc] else: n.info
if c.mode == emRepl: globalError(c.config, lineInfo, msg)
else: localError(c.config, lineInfo, msg)
proc stackTrace(c: PCtx, tos: PStackFrame, pc: int, msg: string) =
stackTrace(c, tos, pc, msg, c.debug[pc])
proc bailOut(c: PCtx; tos: PStackFrame) =
stackTrace(c, tos, c.exceptionInstr, "unhandled exception: " &
c.currentExceptionA.sons[3].skipColon.strVal)
@@ -242,7 +244,8 @@ template getstr(a: untyped): untyped =
(if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal)))
proc pushSafePoint(f: PStackFrame; pc: int) =
if f.safePoints.isNil: f.safePoints = @[]
when not defined(nimNoNilSeqs):
if f.safePoints.isNil: f.safePoints = @[]
f.safePoints.add(pc)
proc popSafePoint(f: PStackFrame) =
@@ -255,7 +258,7 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
var f = tos
while true:
while f.safePoints.isNil or f.safePoints.len == 0:
while f.safePoints.len == 0:
f = f.next
if f.isNil: return (-1, nil)
var pc2 = f.safePoints[f.safePoints.high]
@@ -270,7 +273,7 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
abstractPtrs)
else: nil
#echo typeToString(exceptType), " ", typeToString(raisedType)
if exceptType.isNil or inheritanceDiff(exceptType, raisedType) <= 0:
if exceptType.isNil or inheritanceDiff(raisedType, exceptType) <= 0:
# mark exception as handled but keep it in B for
# the getCurrentException() builtin:
c.currentExceptionB = c.currentExceptionA
@@ -297,7 +300,6 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
discard f.safePoints.pop
proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
if f.safePoints.isNil: return -1
for s in f.safePoints:
var pc = s
while c.code[pc].opcode == opcExcept:
@@ -531,9 +533,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeBC(rkInt)
let idx = regs[rc].intVal.int
let s = regs[rb].node.strVal
if s.isNil:
stackTrace(c, tos, pc, errNilAccess)
elif idx <% s.len:
if idx <% s.len:
regs[ra].intVal = s[idx].ord
elif idx == s.len and optLaxStrings in c.config.options:
regs[ra].intVal = 0
@@ -820,7 +820,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].intVal = ord((regs[rb].node.kind == nkNilLit and
regs[rc].node.kind == nkNilLit) or
regs[rb].node == regs[rc].node)
of opcEqNimrodNode:
of opcEqNimNode:
decodeBC(rkInt)
regs[ra].intVal =
ord(exprStructuralEquivalent(regs[rb].node, regs[rc].node,
@@ -920,6 +920,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.flags.incl nfIsRef
else:
stackTrace(c, tos, pc, "node is not a symbol")
of opcSymOwner:
decodeB(rkNode)
let a = regs[rb].node
if a.kind == nkSym:
regs[ra].node = if a.sym.owner.isNil: newNode(nkNilLit)
else: newSymNode(a.sym.skipGenericOwner)
regs[ra].node.flags.incl nfIsRef
else:
stackTrace(c, tos, pc, "node is not a symbol")
of opcEcho:
let rb = instr.regB
if rb == 1:
@@ -1220,7 +1229,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# Note that `nfIsRef` + `nkNilLit` represents an allocated
# reference with the value `nil`, so `isNil` should be false!
(node.kind == nkNilLit and nfIsRef notin node.flags) or
(node.kind in {nkStrLit..nkTripleStrLit} and node.strVal.isNil) or
(not node.typ.isNil and node.typ.kind == tyProc and
node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and
node.sons[1].kind == nkNilLit))
@@ -1325,6 +1333,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.typ, c.debug[pc])
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
else:
stackTrace(c, tos, pc, "node has no type")
of 1:
@@ -1332,6 +1342,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(rkInt)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
regs[ra].intVal = ord(regs[rb].node.typ.kind)
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
regs[ra].intVal = ord(regs[rb].node.sym.typ.kind)
#else:
# stackTrace(c, tos, pc, "node has no type")
of 2:
@@ -1339,6 +1351,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc])
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
else:
stackTrace(c, tos, pc, "node has no type")
else:
@@ -1346,6 +1360,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.typ, c.debug[pc])
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
else:
stackTrace(c, tos, pc, "node has no type")
of opcNStrVal:
@@ -1380,15 +1396,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
c.debug[pc], c.config)[0]
else:
globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
of opcNError:
of opcNError, opcNWarning, opcNHint:
decodeB(rkNode)
let a = regs[ra].node
let b = regs[rb].node
stackTrace(c, tos, pc, a.strVal, if b.kind == nkNilLit: nil else: b)
of opcNWarning:
message(c.config, c.debug[pc], warnUser, regs[ra].node.strVal)
of opcNHint:
message(c.config, c.debug[pc], hintUser, regs[ra].node.strVal)
let info = if b.kind == nkNilLit: c.debug[pc] else: b.info
if instr.opcode == opcNError:
stackTrace(c, tos, pc, a.strVal, info)
elif instr.opcode == opcNWarning:
message(c.config, info, warnUser, a.strVal)
elif instr.opcode == opcNHint:
message(c.config, info, hintUser, a.strVal)
of opcParseExprToAst:
decodeB(rkNode)
# c.debug[pc].line.int - countLines(regs[rb].strVal) ?
@@ -1396,9 +1414,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= errMax:
if error.len == 0 and msg <= errMax:
error = formatMsg(conf, info, msg, arg))
if not error.isNil:
if error.len > 0:
c.errorFlag = error
elif sonsLen(ast) != 1:
c.errorFlag = formatMsg(c.config, c.debug[pc], errGenerated,
@@ -1411,9 +1429,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= errMax:
if error.len == 0 and msg <= errMax:
error = formatMsg(conf, info, msg, arg))
if not error.isNil:
if error.len > 0:
c.errorFlag = error
else:
regs[ra].node = ast
@@ -1726,7 +1744,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
inc pc
let typ = c.types[c.code[pc].regBx - wordExcess]
createStrKeepNode(regs[ra])
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
when not defined(nimNoNilSeqs):
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config)
of opcToNarrowInt:
decodeBC(rkInt)

View File

@@ -62,7 +62,7 @@ type
opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu,
opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat,
opcLeFloat, opcLtFloat, opcLeu, opcLtu,
opcEqRef, opcEqNimrodNode, opcSameNodeType,
opcEqRef, opcEqNimNode, opcSameNodeType,
opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr,
@@ -141,7 +141,8 @@ type
opcSetType, # dest.typ = types[Bx]
opcTypeTrait,
opcMarshalLoad, opcMarshalStore,
opcToNarrowInt
opcToNarrowInt,
opcSymOwner
TBlock* = object
label*: PSym

View File

@@ -1118,6 +1118,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
of mNLen: genUnaryABI(c, n, dest, opcLenSeq, nimNodeFlag)
of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner)
of mNChild: genBinaryABC(c, n, dest, opcNChild)
of mNSetChild: genVoidABC(c, n, dest, opcNSetChild)
of mNDel: genVoidABC(c, n, dest, opcNDel)
@@ -1178,7 +1179,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mNBindSym: genBindSym(c, n, dest)
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimNode)
of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)
of mNLineInfo:
case n[0].sym.name.s
@@ -1192,10 +1193,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
else: internalAssert c.config, false
of mNHint:
unused(c, n, dest)
genUnaryStmt(c, n, opcNHint)
genBinaryStmt(c, n, opcNHint)
of mNWarning:
unused(c, n, dest)
genUnaryStmt(c, n, opcNWarning)
genBinaryStmt(c, n, opcNWarning)
of mNError:
if n.len <= 1:
# query error condition:

View File

@@ -127,7 +127,7 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet;
storeAny(s, t.lastSon, a, stored, conf)
s.add("]")
of tyString, tyCString:
if a.kind == nkNilLit or a.strVal.isNil: s.add("null")
if a.kind == nkNilLit: s.add("null")
else: s.add(escapeJson(a.strVal))
of tyInt..tyInt64, tyUInt..tyUInt64: s.add($a.intVal)
of tyFloat..tyFloat128: s.add($a.floatVal)

View File

@@ -17,8 +17,7 @@ About this document
===================
**Note**: This document is a draft! Several of Nim's features may need more
precise wording. This manual is constantly evolving until the 1.0 release and is
not to be considered as the final proper specification.
precise wording. This manual is constantly evolving into a proper specification.
This document describes the lexis, the syntax, and the semantics of Nim.
@@ -433,7 +432,7 @@ Numerical constants are of a single type and have the form::
UINT64_LIT = INT_LIT ['\''] ('u' | 'U') '64'
exponent = ('e' | 'E' ) ['+' | '-'] digit ( ['_'] digit )*
FLOAT_LIT = digit (['_'] digit)* (('.' (['_'] digit)* [exponent]) |exponent)
FLOAT_LIT = digit (['_'] digit)* (('.' digit (['_'] digit)* [exponent]) |exponent)
FLOAT32_SUFFIX = ('f' | 'F') ['32']
FLOAT32_LIT = HEX_LIT '\'' FLOAT32_SUFFIX
| (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] FLOAT32_SUFFIX
@@ -504,7 +503,7 @@ following characters::
These keywords are also operators:
``and or not xor shl shr div mod in notin is isnot of``.
`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they
`.`:tok: `=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they
are used for other notational purposes.
``*:`` is as a special case treated as the two tokens `*`:tok: and `:`:tok:
@@ -618,6 +617,55 @@ The grammar's start symbol is ``module``.
Order of evaluation
===================
Order of evaluation is strictly left-to-right, inside-out as it is typical for most others
imperative programming languages:
.. code-block:: nim
:test: "nim c $1"
var s = ""
proc p(arg: int): int =
s.add $arg
result = arg
discard p(p(1) + p(2))
doAssert s == "123"
Assignments are not special, the left-hand-side expression is evaluated before the
right-hand side:
.. code-block:: nim
:test: "nim c $1"
var v = 0
proc getI(): int =
result = v
inc v
var a, b: array[0..2, int]
proc someCopy(a: var int; b: int) = a = b
a[getI()] = getI()
doAssert a == [1, 0, 0]
v = 0
someCopy(b[getI()], getI())
doAssert b == [1, 0, 0]
Rationale: Consistency with overloaded assignment or assignment-like operations,
``a = b`` can be read as ``performSomeCopy(a, b)``.
Types
=====
@@ -888,8 +936,12 @@ Now the following holds::
ord(south) == 2
ord(west) == 3
# Also allowed:
ord(Direction.west) == 3
Thus, north < east < south < west. The comparison operators can be used
with enumeration types.
with enumeration types. Instead of ``north`` etc, the enum value can also
be qualified with the enum type that it resides in, ``Direction.north``.
For better interfacing to other programming languages, the fields of enum
types can be assigned an explicit ordinal value. However, the ordinal values
@@ -925,18 +977,25 @@ As can be seen from the example, it is possible to both specify a field's
ordinal value and its string value by using a tuple. It is also
possible to only specify one of them.
An enum can be marked with the ``pure`` pragma so that it's fields are not
added to the current scope, so they always need to be accessed
via ``MyEnum.value``:
An enum can be marked with the ``pure`` pragma so that it's fields are
added to a special module specific hidden scope that is only queried
as the last attempt. Only non-ambiguous symbols are added to this scope.
But one can always access these via type qualification written
as ``MyEnum.value``:
.. code-block:: nim
type
MyEnum {.pure.} = enum
valueA, valueB, valueC, valueD
valueA, valueB, valueC, valueD, amb
echo valueA # error: Unknown identifier
echo MyEnum.valueA # works
OtherEnum {.pure.} = enum
valueX, valueY, valueZ, amb
echo valueA # MyEnum.valueA
echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb
echo MyEnum.amb # OK.
String type
@@ -945,6 +1004,11 @@ All string literals are of the type ``string``. A string in Nim is very
similar to a sequence of characters. However, strings in Nim are both
zero-terminated and have a length field. One can retrieve the length with the
builtin ``len`` procedure; the length never counts the terminating zero.
The terminating zero cannot be accessed unless the string is converted
to the ``cstring`` type first. The terminating zero assures that this
conversion can be done in O(1) and without any allocations.
The assignment operator for strings always copies the string.
The ``&`` operator concatenates strings.
@@ -2925,6 +2989,10 @@ name ``c`` should default to type ``Context``, ``n`` should default to
proc bar(c, n, counter) = ...
proc baz(c, n) = ...
proc mixedMode(c, n; x, y: int) =
# 'c' is inferred to be of the type 'Context'
# 'n' is inferred to be of the type 'Node'
# But 'x' and 'y' are of type 'int'.
The ``using`` section uses the same indentation based grouping syntax as
a ``var`` or ``let`` section.
@@ -2932,6 +3000,9 @@ a ``var`` or ``let`` section.
Note that ``using`` is not applied for ``template`` since untyped template
parameters default to the type ``system.untyped``.
Mixing parameters that should use the ``using`` declaration with parameters
that are explicitly typed is possible and requires a semicolon between them.
If expression
-------------
@@ -3045,6 +3116,19 @@ the address of variables, but one can't use it on variables declared through
# Error: expression has no address
The unsafeAddr operator
-----------------------
For easier interoperability with other compiled languages such as C, retrieving
the address of a ``let`` variable, a parameter or a ``for`` loop variable, the
``unsafeAddr`` operation can be used:
.. code-block:: nim
let myArray = [1, 2, 3]
foreignProcThatTakesAnAddr(unsafeAddr myArray)
Procedures
==========
@@ -4327,6 +4411,34 @@ be inferred to have the equivalent of the `any` type class and thus they will
match anything without discrimination.
Generic inference restrictions
------------------------------
The types ``var T`` and ``typedesc[T]`` cannot be inferred in a generic
instantiation. The following is not allowed:
.. code-block:: nim
:test: "nim c $1"
:status: 1
proc g[T](f: proc(x: T); x: T) =
f(x)
proc c(y: int) = echo y
proc v(y: var int) =
y += 100
var i: int
# allowed: infers 'T' to be of type 'int'
g(c, 42)
# not valid: 'T' is not inferred to be of type 'var int'
g(v, i)
# also not allowed: explict instantiation via 'var int'
g[var int](v, i)
Concepts
--------
@@ -4573,7 +4685,7 @@ type is an instance of it:
.. code-block:: nim
:test: "nim c $1"
import future, typetraits
import sugar, typetraits
type
Functor[A] = concept f
@@ -5399,12 +5511,17 @@ type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop:
newFor.add x[^2][1]
newFor.add body
result.add newFor
# now wrap the whole macro in a block to create a new scope
result = quote do:
block: `result`
for a, b in enumerate(items([1, 2, 3])):
echo a, " ", b
for a2, b2 in enumerate([1, 2, 3, 5]):
echo a2, " ", b2
# without wrapping the macro in a block, we'd need to choose different
# names for `a` and `b` here to avoid redefinition errors
for a, b in enumerate([1, 2, 3, 5]):
echo a, " ", b
Currently for loop macros must be enabled explicitly
@@ -5414,12 +5531,11 @@ via ``{.experimental: "forLoopMacros".}``.
Case statement macros
---------------------
A macro that needs to be called `match`:idx: can be used to
rewrite ``case`` statements in order to
implement `pattern matching`:idx: for certain types. The following
example implements a simplistic form of pattern matching for tuples,
leveraging the existing equality operator for tuples (as provided in
``system.==``):
A macro that needs to be called `match`:idx: can be used to rewrite
``case`` statements in order to implement `pattern matching`:idx: for
certain types. The following example implements a simplistic form of
pattern matching for tuples, leveraging the existing equality operator
for tuples (as provided in ``system.==``):
.. code-block:: nim
:test: "nim c $1"
@@ -6448,6 +6564,11 @@ The deprecated pragma is used to mark a symbol as deprecated:
proc p() {.deprecated.}
var x {.deprecated.}: char
This pragma can also take in an optional warning string to relay to developers.
.. code-block:: nim
proc thing(x: bool) {.deprecated: "See arguments of otherThing()".}
It can also be used as a statement, in that case it takes a list of *renamings*.
.. code-block:: nim
@@ -6456,7 +6577,6 @@ It can also be used as a statement, in that case it takes a list of *renamings*.
Stream = ref object
{.deprecated: [TFile: File, PStream: Stream].}
noSideEffect pragma
-------------------
The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
@@ -6942,12 +7062,36 @@ Example:
.. code-block:: nim
{.experimental: "parallel".}
proc useUsing(bar, foo) =
proc useParallel() =
parallel:
for i in 0..4:
echo "echo in parallel"
As a top level statement, the experimental pragma enables a feature for the
rest of the module it's enabled in. This is problematic for macro and generic
instantiations that cross a module scope. Currently these usages have to be
put into a ``.push/pop`` environment:
.. code-block:: nim
# client.nim
proc useParallel*[T](unused: T) =
# use a generic T here to show the problem.
{.push experimental: "parallel".}
parallel:
for i in 0..4:
echo "echo in parallel"
{.pop.}
.. code-block:: nim
import client
useParallel(1)
Implementation Specific Pragmas
===============================

View File

@@ -60,7 +60,7 @@ Spacing and Whitespace Conventions
Naming Conventions
-------------------------
------------------
Note: While the rules outlined below are the *current* naming conventions,
these conventions have not always been in place. Previously, the naming
@@ -147,6 +147,80 @@ changed in the future.
an in-place version should get an ``-In`` suffix (``replaceIn`` for this example).
The stdlib API is designed to be **easy to use** and consistent. Ease of use is
measured by the number of calls to achieve a concrete high level action. The
ultimate goal is that the programmer can *guess* a name.
The library uses a simple naming scheme that makes use of common abbreviations
to keep the names short but meaningful.
------------------- ------------ --------------------------------------
English word To use Notes
------------------- ------------ --------------------------------------
initialize initT ``init`` is used to create a
value type ``T``
new newP ``new`` is used to create a
reference type ``P``
find find should return the position where
something was found; for a bool result
use ``contains``
contains contains often short for ``find() >= 0``
append add use ``add`` instead of ``append``
compare cmp should return an int with the
``< 0`` ``== 0`` or ``> 0`` semantics;
for a bool result use ``sameXYZ``
put put, ``[]=`` consider overloading ``[]=`` for put
get get, ``[]`` consider overloading ``[]`` for get;
consider to not use ``get`` as a
prefix: ``len`` instead of ``getLen``
length len also used for *number of elements*
size size, len size should refer to a byte size
capacity cap
memory mem implies a low-level operation
items items default iterator over a collection
pairs pairs iterator over (key, value) pairs
delete delete, del del is supposed to be faster than
delete, because it does not keep
the order; delete keeps the order
remove delete, del inconsistent right now
include incl
exclude excl
command cmd
execute exec
environment env
variable var
value value, val val is preferred, inconsistent right
now
executable exe
directory dir
path path path is the string "/usr/bin" (for
example), dir is the content of
"/usr/bin"; inconsistent right now
extension ext
separator sep
column col, column col is preferred, inconsistent right
now
application app
configuration cfg
message msg
argument arg
object obj
parameter param
operator opr
procedure proc
function func
coordinate coord
rectangle rect
point point
symbol sym
literal lit
string str
identifier ident
indentation indent
------------------- ------------ --------------------------------------
Coding Conventions
------------------

View File

@@ -143,6 +143,9 @@ which may be used in conjunction with the `compile time define
pragmas<manual.html#implementation-specific-pragmas-compile-time-define-pragmas>`_
to override symbols during build time.
Compile time symbols are completely **case insensitive** and underscores are
ignored too. ``--define:FOO`` and ``--define:foo`` are identical.
Configuration files
-------------------
@@ -326,40 +329,41 @@ The standard library supports a growing number of ``useX`` conditional defines
affecting how some features are implemented. This section tries to give a
complete list.
================== =========================================================
Define Effect
================== =========================================================
``release`` Turns off runtime checks and turns on the optimizer.
``useWinAnsi`` Modules like ``os`` and ``osproc`` use the Ansi versions
of the Windows API. The default build uses the Unicode
version.
``useFork`` Makes ``osproc`` use ``fork`` instead of ``posix_spawn``.
``useNimRtl`` Compile and link against ``nimrtl.dll``.
``useMalloc`` Makes Nim use C's `malloc`:idx: instead of Nim's
own memory manager, ableit prefixing each allocation with
its size to support clearing memory on reallocation.
This only works with ``gc:none``.
``useRealtimeGC`` Enables support of Nim's GC for *soft* realtime
systems. See the documentation of the `gc <gc.html>`_
for further information.
``nodejs`` The JS target is actually ``node.js``.
``ssl`` Enables OpenSSL support for the sockets module.
``memProfiler`` Enables memory profiling for the native GC.
``uClibc`` Use uClibc instead of libc. (Relevant for Unix-like OSes)
``checkAbi`` When using types from C headers, add checks that compare
what's in the Nim file with what's in the C header
(requires a C compiler with _Static_assert support, like
any C11 compiler)
``tempDir`` This symbol takes a string as its value, like
``--define:tempDir:/some/temp/path`` to override the
temporary directory returned by ``os.getTempDir()``.
The value **should** end with a directory separator
character. (Relevant for the Android platform)
``useShPath`` This symbol takes a string as its value, like
``--define:useShPath:/opt/sh/bin/sh`` to override the
path for the ``sh`` binary, in cases where it is not
located in the default location ``/bin/sh``
================== =========================================================
====================== =========================================================
Define Effect
====================== =========================================================
``release`` Turns off runtime checks and turns on the optimizer.
``useWinAnsi`` Modules like ``os`` and ``osproc`` use the Ansi versions
of the Windows API. The default build uses the Unicode
version.
``useFork`` Makes ``osproc`` use ``fork`` instead of ``posix_spawn``.
``useNimRtl`` Compile and link against ``nimrtl.dll``.
``useMalloc`` Makes Nim use C's `malloc`:idx: instead of Nim's
own memory manager, ableit prefixing each allocation with
its size to support clearing memory on reallocation.
This only works with ``gc:none``.
``useRealtimeGC`` Enables support of Nim's GC for *soft* realtime
systems. See the documentation of the `gc <gc.html>`_
for further information.
``nodejs`` The JS target is actually ``node.js``.
``ssl`` Enables OpenSSL support for the sockets module.
``memProfiler`` Enables memory profiling for the native GC.
``uClibc`` Use uClibc instead of libc. (Relevant for Unix-like OSes)
``checkAbi`` When using types from C headers, add checks that compare
what's in the Nim file with what's in the C header
(requires a C compiler with _Static_assert support, like
any C11 compiler)
``tempDir`` This symbol takes a string as its value, like
``--define:tempDir:/some/temp/path`` to override the
temporary directory returned by ``os.getTempDir()``.
The value **should** end with a directory separator
character. (Relevant for the Android platform)
``useShPath`` This symbol takes a string as its value, like
``--define:useShPath:/opt/sh/bin/sh`` to override the
path for the ``sh`` binary, in cases where it is not
located in the default location ``/bin/sh``.
``noSignalHandler`` Disable the crash handler from ``system.nim``.
====================== =========================================================
@@ -529,6 +533,16 @@ See the documentation of Nim's soft realtime `GC <gc.html>`_ for further
information.
Signal handling in Nim
======================
The Nim programming language has no concept of Posix's signal handling
mechanisms. However, the standard library offers some rudimentary support
for signal handling, in particular, segmentation faults are turned into
fatal errors that produce a stack trace. This can be disabled with the
``-d:noSignalHandler`` switch.
Debugging with Nim
==================

View File

@@ -1112,21 +1112,12 @@ proc can convert it to its underlying integer value.
For better interfacing to other programming languages, the symbols of enum
types can be assigned an explicit ordinal value. However, the ordinal values
must be in ascending order. A symbol whose ordinal value is not
explicitly given is assigned the value of the previous symbol + 1.
An explicit ordered enum can have *holes*:
.. code-block:: nim
:test: "nim c $1"
type
MyEnum = enum
a = 2, b = 4, c = 89
must be in ascending order.
Ordinal types
-------------
Enumerations without holes, integer types, ``char`` and ``bool`` (and
Enumerations, integer types, ``char`` and ``bool`` (and
subranges) are called ordinal types. Ordinal types have quite
a few special operations:

View File

@@ -1,114 +0,0 @@
# Horrible example of how to interface with a C++ engine ... ;-)
{.link: "/usr/lib/libIrrlicht.so".}
{.emit: """
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
""".}
const
irr = "<irrlicht/irrlicht.h>"
type
TDimension2d {.final, header: irr, importc: "dimension2d".} = object
Tvector3df {.final, header: irr, importc: "vector3df".} = object
TColor {.final, header: irr, importc: "SColor".} = object
TIrrlichtDevice {.final, header: irr, importc: "IrrlichtDevice".} = object
TIVideoDriver {.final, header: irr, importc: "IVideoDriver".} = object
TISceneManager {.final, header: irr, importc: "ISceneManager".} = object
TIGUIEnvironment {.final, header: irr, importc: "IGUIEnvironment".} = object
TIAnimatedMesh {.final, header: irr, importc: "IAnimatedMesh".} = object
TIAnimatedMeshSceneNode {.final, header: irr,
importc: "IAnimatedMeshSceneNode".} = object
TITexture {.final, header: irr, importc: "ITexture".} = object
PIrrlichtDevice = ptr TIrrlichtDevice
PIVideoDriver = ptr TIVideoDriver
PISceneManager = ptr TISceneManager
PIGUIEnvironment = ptr TIGUIEnvironment
PIAnimatedMesh = ptr TIAnimatedMesh
PIAnimatedMeshSceneNode = ptr TIAnimatedMeshSceneNode
PITexture = ptr TITexture
proc dimension2d(x, y: cint): TDimension2d {.
header: irr, importc: "dimension2d<u32>".}
proc vector3df(x,y,z: cint): Tvector3df {.
header: irr, importc: "vector3df".}
proc SColor(r,g,b,a: cint): TColor {.
header: irr, importc: "SColor".}
proc createDevice(): PIrrlichtDevice {.
header: irr, importc: "createDevice".}
proc run(device: PIrrlichtDevice): bool {.
header: irr, importcpp: "run".}
proc getVideoDriver(dev: PIrrlichtDevice): PIVideoDriver {.
header: irr, importcpp: "getVideoDriver".}
proc getSceneManager(dev: PIrrlichtDevice): PISceneManager {.
header: irr, importcpp: "getSceneManager".}
proc getGUIEnvironment(dev: PIrrlichtDevice): PIGUIEnvironment {.
header: irr, importcpp: "getGUIEnvironment".}
proc getMesh(smgr: PISceneManager, path: cstring): PIAnimatedMesh {.
header: irr, importcpp: "getMesh".}
proc drawAll(smgr: PISceneManager) {.
header: irr, importcpp: "drawAll".}
proc drawAll(guienv: PIGUIEnvironment) {.
header: irr, importcpp: "drawAll".}
proc drop(dev: PIrrlichtDevice) {.
header: irr, importcpp: "drop".}
proc getTexture(driver: PIVideoDriver, path: cstring): PITexture {.
header: irr, importcpp: "getTexture".}
proc endScene(driver: PIVideoDriver) {.
header: irr, importcpp: "endScene".}
proc beginScene(driver: PIVideoDriver, a, b: bool, c: TColor) {.
header: irr, importcpp: "beginScene".}
proc addAnimatedMeshSceneNode(
smgr: PISceneManager, mesh: PIAnimatedMesh): PIAnimatedMeshSceneNode {.
header: irr, importcpp: "addAnimatedMeshSceneNode".}
proc setMaterialTexture(n: PIAnimatedMeshSceneNode, x: cint, t: PITexture) {.
header: irr, importcpp: "setMaterialTexture".}
proc addCameraSceneNode(smgr: PISceneManager, x: cint, a, b: TVector3df) {.
header: irr, importcpp: "addCameraSceneNode".}
var device = createDevice()
if device == nil: quit "device is nil"
var driver = device.getVideoDriver()
var smgr = device.getSceneManager()
var guienv = device.getGUIEnvironment()
var mesh = smgr.getMesh("/home/andreas/download/irrlicht-1.7.2/media/sydney.md2")
if mesh == nil:
device.drop()
quit "no mesh!"
var node = smgr.addAnimatedMeshSceneNode(mesh)
if node != nil:
#node->setMaterialFlag(EMF_LIGHTING, false)
#node->setMD2Animation(scene::EMAT_STAND)
node.setMaterialTexture(0,
driver.getTexture(
"/home/andreas/download/irrlicht-1.7.2/media/media/sydney.bmp"))
smgr.addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0))
while device.run():
driver.beginScene(true, true, SColor(255,100,101,140))
smgr.drawAll()
guienv.drawAll()
driver.endScene()
device.drop()

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env python
import BaseHTTPServer
import CGIHTTPServer
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ('localhost', 8008)
handler.cgi_directories = ['/']
httpd = server(server_address, handler)
httpd.serve_forever()

View File

@@ -1,5 +0,0 @@
import cgi
cgi.setStackTraceStdout()
var a: string = nil
a.add "foobar"

View File

@@ -1,7 +0,0 @@
import cgi
write(stdout, "Content-type: text/html\n\n")
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
write(stdout, "<html><head><title>Test</title></head><body>\n")
write(stdout, "Hello!")
writeLine(stdout, "</body></html>")

View File

@@ -1,12 +0,0 @@
# Test/show CGI module
import strtabs, cgi
var myData = readData()
validateData(myData, "name", "password")
writeContentType()
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
write(stdout, "<html><head><title>Test</title></head><body>\n")
writeLine(stdout, "name: " & myData["name"])
writeLine(stdout, "password: " & myData["password"])
writeLine(stdout, "</body></html>")

View File

@@ -1,12 +0,0 @@
# Android specific absolute paths.
android/bin/
android/gen/
android/jni/backend-jni.h
android/libs/
android/local.properties
android/obj/
android/tags
# iOS specific absolute paths
ios/resources/ui/*.m
ios/tags

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.nimrod.crosscalculator"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="3" />
<application android:label="@string/app_name" android:debuggable="true">
<activity android:name=".CrossCalculator"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="CrossCalculator" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" default="debug">
<target name="nim">
<exec executable="scripts/nimbuild.sh" failonerror="true">
</exec>
</target>
<target name="jni">
<exec executable="scripts/jnibuild.sh" failonerror="true">
</exec>
</target>
<target name="ndk">
<exec executable="ndk-build" failonerror="true">
</exec>
</target>
<target name="-post-compile" depends="nim, jni, ndk">
</target>
</project>

View File

@@ -1,32 +0,0 @@
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nimrod
LOCAL_SRC_FILES := nimcache/backend.c nimcache/system.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/nimcache
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := backend-jni
LOCAL_SRC_FILES := backend-jni.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_STATIC_LIBRARIES := nimrod
include $(BUILD_SHARED_LIBRARY)

View File

@@ -1,42 +0,0 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <android/log.h>
#include <string.h>
#include "backend-jni.h"
#include "backend.h"
#define TAG "backend-jni.c"
jint JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_myAdd
(JNIEnv *env, jobject thiz, jint a, jint b)
{
char buf[256];
const jint ret = myAdd(a, b);
// Using logging from inside the native bridge to log-debug.
sprintf(buf, "a %d + b %d = ret %d", a, b, ret);
__android_log_write(ANDROID_LOG_DEBUG, TAG, buf);
return ret;
}
void JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_initNimMain
(JNIEnv *env, jclass thiz)
{
NimMain();
__android_log_write(ANDROID_LOG_DEBUG, TAG, "Nimrod initialised");
}
// vim:tabstop=2 shiftwidth=2 syntax=c

View File

@@ -1,14 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-3

View File

@@ -1,24 +0,0 @@
In this directory you will find the Android platform cross-calculator sample.
Due to the nature of Android being java and Nim generating C code, the build
process is slightly more complex because jni code has to be written to bridge
both languages. In a distant future it may be possible for Nim to generate
the whole jni bridge, but for the moment this is manual work.
For the jni bridge to work first the java code is compiled with the Nim code
just declared as a native method which will be resolved at runtime. The scripts
nimbuild.sh and jnibuild.sh are in charge of building the Nim code and
generating the jni bridge from the java code respectively. Finally, the
ndk-build command from the android ndk tools has to be run to build the binary
library which will be installed along the final apk.
All these steps are wrapped in the ant build script through the customization
of the -post-compile rule. If you have the android ndk tools installed and you
modify scripts/nimbuild.sh to point to the directory where you have Nim
installed on your system, you can simply run "ant debug" to build everything.
Once the apk is built you can install it on your device or emulator with the
command "adb install bin/CrossCalculator-debug.apk".
This example runs against the Android level 3 API, meaning devices from
Android 1.5 and above should be able to run the generated binary.

View File

@@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Crossplatform Nimrod calculator"
android:textSize="20dip" >
</TextView>
<TextView
android:id="@+id/value_a"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:text="Value A: " >
</TextView>
<EditText
android:id="@+id/edit_text_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/title"
android:ems="10"
android:inputType="number" />
<TextView
android:id="@+id/value_b"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/edit_text_a"
android:text="Value B: " >
</TextView>
<EditText
android:id="@+id/edit_text_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/edit_text_a"
android:ems="10"
android:inputType="number" />
<Button
android:id="@+id/add_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/edit_text_b"
android:scrollbarAlwaysDrawVerticalTrack="false"
android:selectAllOnFocus="false"
android:text="Add!"
android:visibility="visible" />
<TextView
android:id="@+id/result_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/add_button" />
</RelativeLayout>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CrossCalculator</string>
</resources>

View File

@@ -1,22 +0,0 @@
#!/bin/sh
# Force errors to fail script.
set -e
# If we are running from inside the scripts subdir, get out.
if [ ! -d src ]
then
cd ..
fi
# Ok, are we out now?
if [ -d src ]
then
javah -classpath bin/classes \
-o jni/backend-jni.h \
com.github.nimrod.crosscalculator.CrossCalculator
else
echo "Uh oh, bin/classes directory not found?"
echo "Try compiling your java code, or opening in eclipse."
exit 1
fi

View File

@@ -1,34 +0,0 @@
#!/bin/sh
# Set this to the local or full path of your nimrod compiler
PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
# Set this to the location of the nimbase.h file so
# the script can update it if it changes.
PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
# Force errors to fail script.
set -e
# If we are running from inside the scripts subdir, get out.
if [ ! -d src ]
then
cd ..
fi
DEST_NIMBASE=jni/nimcache/nimbase.h
# Ok, are we out now?
if [ -d src ]
then
$PATH_TO_NIMROD c --noMain --app:lib \
--nimcache:jni/nimcache --cpu:arm --os:linux \
--compileOnly --header ../nimrod_backend/*.nim
if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
then
echo "Updating nimbase.h"
cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
fi
else
echo "Uh oh, src directory not found?"
exit 1
fi

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if [ ! -d src ]
then
cd ..
fi
if [ -d src ]
then
~/bin/objctags -R \
jni \
src
fi

View File

@@ -1,80 +0,0 @@
package com.github.nimrod.crosscalculator;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class CrossCalculator extends Activity
{
private static final String TAG = "CrossCalculator";
private TextView result_text;
private EditText edit_text_a, edit_text_b;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.cross_calculator);
final Button button = (Button)findViewById(R.id.add_button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { addButtonClicked(); } });
result_text = (TextView)findViewById(R.id.result_text);
edit_text_a = (EditText)findViewById(R.id.edit_text_a);
edit_text_b = (EditText)findViewById(R.id.edit_text_b);
}
/** Handles clicks on the addition button.
* Reads the values form the input fields and performs the calculation.
*/
private void addButtonClicked()
{
int a = 0, b = 0;
String errors = "";
final String a_text = edit_text_a.getText().toString();
final String b_text = edit_text_b.getText().toString();
try {
a = Integer.valueOf(a_text, 10);
} catch (NumberFormatException e) {
errors += "Can't parse a value '" + a_text + "'. ";
}
try {
b = Integer.valueOf(b_text, 10);
} catch (NumberFormatException e) {
errors += "Can't parse b value '" + b_text + "'";
}
final int c = myAdd(a, b);
result_text.setText("myAdd(" + a + ", " + b + ") = " + c);
if (errors.length() > 0) {
Log.e(TAG, errors);
Toast.makeText(this, errors, Toast.LENGTH_SHORT).show();
}
}
/* A native method that is implemented by the
* 'backend-jni' native library, which is packaged
* with this application. Adds to integers.
*/
public native int myAdd(int a, int b);
/* A native method used to initialise Nimrod.
*/
static public native void initNimMain();
/* this is used to load the 'backend-jni' library on application
* startup. The library has already been unpacked into
* /data/data/com.github.nimrod.backendjni/lib/libbackend-jni.so at
* installation time by the package manager.
*/
static {
System.loadLibrary("backend-jni");
initNimMain();
}
}

View File

@@ -1,337 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422915BC8611005EFF20 /* UIKit.framework */; };
D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422B15BC8611005EFF20 /* Foundation.framework */; };
D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422D15BC8611005EFF20 /* CoreGraphics.framework */; };
D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; };
D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; };
D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; };
D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* stdlib_system.m */; };
D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
D531422515BC8611005EFF20 /* cross-calculator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross-calculator.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D531422915BC8611005EFF20 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
D531422B15BC8611005EFF20 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D531422D15BC8611005EFF20 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "cross-calculator-Info.plist"; path = "resources/plist/cross-calculator-Info.plist"; sourceTree = "<group>"; };
D531424915BC87B6005EFF20 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = src/AppDelegate.h; sourceTree = "<group>"; };
D531424A15BC87B6005EFF20 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = src/AppDelegate.m; sourceTree = "<group>"; };
D531424B15BC87B6005EFF20 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = src/main.m; sourceTree = "<group>"; };
D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cross-calculator-Prefix.pch"; path = "src/cross-calculator-Prefix.pch"; sourceTree = "<group>"; };
D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = "<group>"; };
D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = "<group>"; };
D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = "<group>"; };
D531427115BC94B1005EFF20 /* stdlib_system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = stdlib_system.m; path = build/nimcache/stdlib_system.m; sourceTree = "<group>"; };
D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = "<group>"; };
D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = "<group>"; };
D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = "<group>"; };
D5B6F94615FA8D4C0084A85B /* NRViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NRViewController.m; path = src/NRViewController.m; sourceTree = "<group>"; };
D5B6F96315FB448D0084A85B /* NRViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = NRViewController.xib; path = resources/ui/NRViewController.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D531422215BC8610005EFF20 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */,
D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */,
D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D531421A15BC8610005EFF20 = {
isa = PBXGroup;
children = (
D531426A15BC93D5005EFF20 /* build */,
D531424515BC874E005EFF20 /* resources */,
D531426615BC91E1005EFF20 /* scripts */,
D531424815BC87AD005EFF20 /* src */,
D531422815BC8611005EFF20 /* Frameworks */,
D531422615BC8611005EFF20 /* Products */,
);
sourceTree = "<group>";
};
D531422615BC8611005EFF20 /* Products */ = {
isa = PBXGroup;
children = (
D531422515BC8611005EFF20 /* cross-calculator.app */,
);
name = Products;
sourceTree = "<group>";
};
D531422815BC8611005EFF20 /* Frameworks */ = {
isa = PBXGroup;
children = (
D531422915BC8611005EFF20 /* UIKit.framework */,
D531422B15BC8611005EFF20 /* Foundation.framework */,
D531422D15BC8611005EFF20 /* CoreGraphics.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
D531424515BC874E005EFF20 /* resources */ = {
isa = PBXGroup;
children = (
D531424615BC8756005EFF20 /* plist */,
D5B6F96115FB447C0084A85B /* ui */,
);
name = resources;
sourceTree = "<group>";
};
D531424615BC8756005EFF20 /* plist */ = {
isa = PBXGroup;
children = (
D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */,
);
name = plist;
sourceTree = "<group>";
};
D531424815BC87AD005EFF20 /* src */ = {
isa = PBXGroup;
children = (
D531424915BC87B6005EFF20 /* AppDelegate.h */,
D531424A15BC87B6005EFF20 /* AppDelegate.m */,
D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */,
D531424B15BC87B6005EFF20 /* main.m */,
D5B6F94515FA8D4C0084A85B /* NRViewController.h */,
D5B6F94615FA8D4C0084A85B /* NRViewController.m */,
);
name = src;
sourceTree = "<group>";
};
D531426615BC91E1005EFF20 /* scripts */ = {
isa = PBXGroup;
children = (
D531426715BC91EF005EFF20 /* tags.sh */,
D531426815BC91EF005EFF20 /* xcode_prebuild.sh */,
);
name = scripts;
sourceTree = "<group>";
};
D531426A15BC93D5005EFF20 /* build */ = {
isa = PBXGroup;
children = (
D531426E15BC94A6005EFF20 /* nimrod */,
);
name = build;
sourceTree = "<group>";
};
D531426E15BC94A6005EFF20 /* nimrod */ = {
isa = PBXGroup;
children = (
D592E19015C7120F005258EA /* backend.h */,
D531426F15BC94B1005EFF20 /* backend.m */,
D592E19115C71415005258EA /* nimbase.h */,
D531427115BC94B1005EFF20 /* stdlib_system.m */,
);
name = nimrod;
sourceTree = "<group>";
};
D5B6F96115FB447C0084A85B /* ui */ = {
isa = PBXGroup;
children = (
D5B6F96315FB448D0084A85B /* NRViewController.xib */,
);
name = ui;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D531422415BC8610005EFF20 /* cross-calculator */ = {
isa = PBXNativeTarget;
buildConfigurationList = D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */;
buildPhases = (
D531426915BC926C005EFF20 /* ShellScript */,
D531422115BC8610005EFF20 /* Sources */,
D531422215BC8610005EFF20 /* Frameworks */,
D531422315BC8610005EFF20 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "cross-calculator";
productName = "cross-calculator";
productReference = D531422515BC8611005EFF20 /* cross-calculator.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D531421C15BC8610005EFF20 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
ORGANIZATIONNAME = "Electric Hands Software";
};
buildConfigurationList = D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = D531421A15BC8610005EFF20;
productRefGroup = D531422615BC8611005EFF20 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D531422415BC8610005EFF20 /* cross-calculator */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D531422315BC8610005EFF20 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
D531426915BC926C005EFF20 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = scripts/xcode_prebuild.sh;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D531422115BC8610005EFF20 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */,
D531424E15BC87B6005EFF20 /* main.m in Sources */,
D531427215BC94B1005EFF20 /* backend.m in Sources */,
D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */,
D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
D531423B15BC8611005EFF20 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv7,
armv6,
);
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
D531423C15BC8611005EFF20 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv7,
armv6,
);
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
D531423E15BC8611005EFF20 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
D531423F15BC8611005EFF20 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D531423B15BC8611005EFF20 /* Debug */,
D531423C15BC8611005EFF20 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D531423E15BC8611005EFF20 /* Debug */,
D531423F15BC8611005EFF20 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D531421C15BC8610005EFF20 /* Project object */;
}

View File

@@ -1,13 +0,0 @@
In this directory you will find the iOS platform cross-calculator sample.
The iOS version of the code builds a view controller in charge of displaying
the interface to the user. The Nim backend code is compiled into C code and
put into build/nimrod as a pre-build phase of the project.
When the calculate button is used the view controller calls the Nim code to
delegate the logic of the operation and puts the result in a label for display.
All interface error checks are implemented in the view controller.
This version of the iOS project is known to work with Xcode 4.2 and Xcode
4.4.1. The final binary can be deployed on iOS 3.x to 5.x supporting all iOS
platforms and versions available at the moment.

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFiles</key>
<array/>
<key>CFBundleIdentifier</key>
<string>com.github.nimrod.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>UIApplicationExitsOnSuspend</key>
<true/>
</dict>
</plist>

View File

@@ -1,479 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">0</int>
<string key="IBDocument.SystemVersion">11E53</string>
<string key="IBDocument.InterfaceBuilderVersion">2549</string>
<string key="IBDocument.AppKitVersion">1138.47</string>
<string key="IBDocument.HIToolboxVersion">569.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1498</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIButton</string>
<string>IBUILabel</string>
<string>IBUITextField</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="975951072">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="191373211">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIButton" id="467453084">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{0, -10}, {320, 480}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">1</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<object class="NSColor" key="IBUIHighlightedTitleColor" id="95215378">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<object class="NSColor" key="IBUINormalTitleShadowColor" id="1056499111">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC41AA</bytes>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="686052398">
<int key="type">2</int>
<double key="pointSize">15</double>
</object>
<object class="NSFont" key="IBUIFont" id="594372787">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">15</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUILabel" id="353054360">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">306</int>
<string key="NSFrameSize">{320, 34}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="525225214"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<int key="IBUITag">2</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Nim Crossplatform Calculator</string>
<object class="NSColor" key="IBUITextColor" id="128895179">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MCAwIDAAA</bytes>
</object>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<int key="IBUITextAlignment">1</int>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">2</int>
<double key="pointSize">18</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">18</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUILabel" id="525225214">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">294</int>
<string key="NSFrame">{{20, 42}, {165, 31}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1040444341"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<int key="IBUITag">3</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Value A:</string>
<reference key="IBUITextColor" ref="128895179"/>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="768572949">
<int key="type">1</int>
<double key="pointSize">17</double>
</object>
<object class="NSFont" key="IBUIFont" id="972319481">
<string key="NSName">Helvetica</string>
<double key="NSSize">17</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUILabel" id="904781109">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">294</int>
<string key="NSFrame">{{20, 81}, {165, 31}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1041721572"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<int key="IBUITag">4</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Value B:</string>
<reference key="IBUITextColor" ref="128895179"/>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<reference key="IBUIFontDescription" ref="768572949"/>
<reference key="IBUIFont" ref="972319481"/>
</object>
<object class="IBUIButton" id="557594991">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">291</int>
<string key="NSFrame">{{193, 124}, {107, 37}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">5</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Add!</string>
<reference key="IBUIHighlightedTitleColor" ref="95215378"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="1056499111"/>
<reference key="IBUIFontDescription" ref="686052398"/>
<reference key="IBUIFont" ref="594372787"/>
</object>
<object class="IBUILabel" id="360864196">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 124}, {60, 37}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="521073831"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<int key="IBUITag">6</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Result:</string>
<reference key="IBUITextColor" ref="128895179"/>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<reference key="IBUIFontDescription" ref="768572949"/>
<reference key="IBUIFont" ref="972319481"/>
</object>
<object class="IBUILabel" id="521073831">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">294</int>
<string key="NSFrame">{{88, 124}, {97, 37}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="557594991"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<int key="IBUITag">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText"/>
<reference key="IBUITextColor" ref="128895179"/>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<reference key="IBUIFontDescription" ref="768572949"/>
<reference key="IBUIFont" ref="972319481"/>
</object>
<object class="IBUITextField" id="1040444341">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">291</int>
<string key="NSFrame">{{193, 42}, {107, 31}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="904781109"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUITag">8</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentVerticalAlignment">0</int>
<string key="IBUIText"/>
<int key="IBUIBorderStyle">3</int>
<string key="IBUIPlaceholder">Integer</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace" id="433120901">
<int key="NSID">2</int>
</object>
</object>
<int key="IBUITextAlignment">1</int>
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
<float key="IBUIMinimumFontSize">17</float>
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
<int key="IBUIKeyboardType">4</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<int key="IBUIClearButtonMode">1</int>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="836805198">
<int key="type">1</int>
<double key="pointSize">14</double>
</object>
<object class="NSFont" key="IBUIFont" id="700927782">
<string key="NSName">Helvetica</string>
<double key="NSSize">14</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUITextField" id="1041721572">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">291</int>
<string key="NSFrame">{{193, 81}, {107, 31}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="360864196"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUITag">9</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentVerticalAlignment">0</int>
<string key="IBUIText"/>
<int key="IBUIBorderStyle">3</int>
<string key="IBUIPlaceholder">Integer</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
<reference key="NSCustomColorSpace" ref="433120901"/>
</object>
<int key="IBUITextAlignment">1</int>
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
<float key="IBUIMinimumFontSize">17</float>
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
<int key="IBUIKeyboardType">4</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<int key="IBUIClearButtonMode">1</int>
<reference key="IBUIFontDescription" ref="836805198"/>
<reference key="IBUIFont" ref="700927782"/>
</object>
</array>
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="353054360"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<reference key="NSCustomColorSpace" ref="433120901"/>
</object>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords"/>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="191373211"/>
<array class="NSMutableArray" key="children">
<reference ref="353054360"/>
<reference ref="525225214"/>
<reference ref="904781109"/>
<reference ref="557594991"/>
<reference ref="360864196"/>
<reference ref="521073831"/>
<reference ref="1040444341"/>
<reference ref="1041721572"/>
<reference ref="467453084"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="975951072"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">14</int>
<reference key="object" ref="1041721572"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">13</int>
<reference key="object" ref="1040444341"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">12</int>
<reference key="object" ref="521073831"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">11</int>
<reference key="object" ref="360864196"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">10</int>
<reference key="object" ref="557594991"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="904781109"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="525225214"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="353054360"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">22</int>
<reference key="object" ref="467453084"/>
<reference key="parent" ref="191373211"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">NRViewController</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">22</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">NRViewController</string>
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="backgroundTouched">id</string>
<string key="calculateButtonTouched">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="backgroundTouched">
<string key="name">backgroundTouched</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="calculateButtonTouched">
<string key="name">calculateButtonTouched</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="aText">UITextField</string>
<string key="bText">UITextField</string>
<string key="calculateButton">UIButton</string>
<string key="resultLabel">UILabel</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="aText">
<string key="name">aText</string>
<string key="candidateClassName">UITextField</string>
</object>
<object class="IBToOneOutletInfo" key="bText">
<string key="name">bText</string>
<string key="candidateClassName">UITextField</string>
</object>
<object class="IBToOneOutletInfo" key="calculateButton">
<string key="name">calculateButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="resultLabel">
<string key="name">resultLabel</string>
<string key="candidateClassName">UILabel</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NRViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<real value="0.0" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">1498</string>
</data>
</archive>

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if [ ! -d src ]
then
cd ..
fi
if [ -d src ]
then
~/bin/objctags -R \
build/nimcache \
src
fi

View File

@@ -1,35 +0,0 @@
#!/bin/sh
# Set this to the full path of your nimrod compiler
# since Xcode doesn't inherit your user environment.
PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
# Set this to the location of the nimbase.h file so
# the script can update it if it changes.
PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
# Force errors to fail script.
set -e
# If we are running from inside the scripts subdir, get out.
if [ ! -d src ]
then
cd ..
fi
DEST_NIMBASE=build/nimcache/nimbase.h
# Ok, are we out now?
if [ -d src ]
then
$PATH_TO_NIMROD objc --noMain --app:lib \
--nimcache:./build/nimcache --compileOnly \
--header --cpu:i386 ../nimrod_backend/backend.nim
if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
then
echo "Updating nimbase.h"
cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
fi
else
echo "Uh oh, src directory not found?"
exit 1
fi

View File

@@ -1,7 +0,0 @@
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -1,39 +0,0 @@
#import "AppDelegate.h"
#import "NRViewController.h"
@interface AppDelegate ()
@property (nonatomic, retain) NRViewController *viewController;
@end
@implementation AppDelegate
@synthesize viewController = _viewController;
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.viewController = [[NRViewController new] autorelease];
if ([self.window respondsToSelector:@selector(setRootViewController:)])
self.window.rootViewController = self.viewController;
else
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
@end

View File

@@ -1,11 +0,0 @@
@interface NRViewController : UIViewController
@property (nonatomic, retain) IBOutlet UIButton *calculateButton;
@property (nonatomic, retain) IBOutlet UITextField *aText;
@property (nonatomic, retain) IBOutlet UITextField *bText;
@property (nonatomic, retain) IBOutlet UILabel *resultLabel;
- (IBAction)calculateButtonTouched;
- (IBAction)backgroundTouched;
@end

View File

@@ -1,210 +0,0 @@
#import "NRViewController.h"
#import "backend.h"
@implementation NRViewController
@synthesize aText = _aText;
@synthesize bText = _bText;
@synthesize calculateButton = _calculateButton;
@synthesize resultLabel = _resultLabel;
- (void)dealloc
{
[_aText release];
[_bText release];
[_calculateButton release];
[_resultLabel release];
[super dealloc];
}
- (void)viewDidUnload
{
self.calculateButton = nil;
self.aText = nil;
self.bText = nil;
self.resultLabel = nil;
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
/// User wants to calculate the inputs. Well, do it!
- (IBAction)calculateButtonTouched
{
// Dismiss all keyboards.
[self backgroundTouched];
// Call Nim code, store the result and display it.
const int a = [self.aText.text intValue];
const int b = [self.bText.text intValue];
const int c = myAdd(a, b);
self.resultLabel.text = [NSString stringWithFormat:@"%d + %d = %d",
a, b, c];
}
/// If the user touches the background, dismiss any visible keyboard.
- (IBAction)backgroundTouched
{
[self.aText resignFirstResponder];
[self.bText resignFirstResponder];
}
/** Custom loadView method for backwards compatibility.
* Unfortunately I've been unable to coerce Xcode 4.4 to generate nib files
* which are compatible with my trusty iOS 3.0 ipod touch so in order to be
* fully compatible for all devices we have to build the interface manually in
* code rather than through the keyed archivers provided by the interface
* builder.
*
* Rather than recreating the user interface manually in code the tool nib2obj
* was used on the xib file and slightly modified to fit the original property
* names. Which means here is a lot of garbage you would never write in real
* life. Please ignore the following "wall of code" for the purposes of
* learning Nim, this is all just because Apple can't be bothered to
* maintain backwards compatibility properly.
*/
- (void)loadView
{
[super loadView];
self.calculateButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.calculateButton.autoresizesSubviews = YES;
self.calculateButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
self.calculateButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
self.calculateButton.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
self.calculateButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.calculateButton.frame = CGRectMake(193.0, 124.0, 107.0, 37.0);
self.calculateButton.tag = 5;
[self.calculateButton setTitle:@"Add!" forState:UIControlStateNormal];
[self.calculateButton addTarget:self
action:@selector(calculateButtonTouched)
forControlEvents:UIControlEventTouchUpInside];
UILabel *label11 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 124.0, 60.0, 37.0)];
label11.adjustsFontSizeToFitWidth = YES;
label11.autoresizesSubviews = YES;
label11.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
label11.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
label11.frame = CGRectMake(20.0, 124.0, 60.0, 37.0);
label11.tag = 6;
label11.text = @"Result:";
UILabel *label4 = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 34.0)];
label4.adjustsFontSizeToFitWidth = YES;
label4.autoresizesSubviews = YES;
label4.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
label4.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
label4.frame = CGRectMake(0.0, 0.0, 320.0, 34.0);
label4.tag = 2;
label4.text = @"Nim Crossplatform Calculator";
label4.textAlignment = UITextAlignmentCenter;
UIButton *background_button = [UIButton buttonWithType:UIButtonTypeCustom];
background_button.autoresizesSubviews = YES;
background_button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
background_button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
background_button.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
background_button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
background_button.frame = CGRectMake(0.0, -10.0, 320.0, 480.0);
background_button.tag = 1;
[background_button addTarget:self action:@selector(backgroundTouched)
forControlEvents:UIControlEventTouchDown];
self.resultLabel = [[[UILabel alloc] initWithFrame:CGRectMake(88.0, 124.0, 97.0, 37.0)] autorelease];
self.resultLabel.adjustsFontSizeToFitWidth = YES;
self.resultLabel.autoresizesSubviews = YES;
self.resultLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
self.resultLabel.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
self.resultLabel.frame = CGRectMake(88.0, 124.0, 97.0, 37.0);
self.resultLabel.tag = 7;
self.resultLabel.text = @"";
self.aText = [[[UITextField alloc] initWithFrame:CGRectMake(193.0, 42.0, 107.0, 31.0)] autorelease];
self.aText.adjustsFontSizeToFitWidth = YES;
self.aText.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.aText.autocorrectionType = UITextAutocorrectionTypeDefault;
self.aText.autoresizesSubviews = YES;
self.aText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
self.aText.borderStyle = UITextBorderStyleRoundedRect;
self.aText.clearButtonMode = UITextFieldViewModeWhileEditing;
self.aText.clearsOnBeginEditing = NO;
self.aText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
self.aText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
self.aText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.aText.enablesReturnKeyAutomatically = NO;
self.aText.frame = CGRectMake(193.0, 42.0, 107.0, 31.0);
self.aText.keyboardAppearance = UIKeyboardAppearanceDefault;
self.aText.keyboardType = UIKeyboardTypeNumberPad;
self.aText.placeholder = @"Integer";
self.aText.returnKeyType = UIReturnKeyDefault;
self.aText.tag = 8;
self.aText.text = @"";
self.aText.textAlignment = UITextAlignmentCenter;
UILabel *label7 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 42.0, 165.0, 31.0)];
label7.adjustsFontSizeToFitWidth = YES;
label7.autoresizesSubviews = YES;
label7.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
label7.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
label7.frame = CGRectMake(20.0, 42.0, 165.0, 31.0);
label7.tag = 3;
label7.text = @"Value A:";
UILabel *label8 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 81.0, 165.0, 31.0)];
label8.adjustsFontSizeToFitWidth = YES;
label8.autoresizesSubviews = YES;
label8.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
label8.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
label8.frame = CGRectMake(20.0, 81.0, 165.0, 31.0);
label8.tag = 4;
label8.text = @"Value B:";
self.bText = [[[UITextField alloc]
initWithFrame:CGRectMake(193.0, 81.0, 107.0, 31.0)] autorelease];
self.bText.adjustsFontSizeToFitWidth = YES;
self.bText.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.bText.autocorrectionType = UITextAutocorrectionTypeDefault;
self.bText.autoresizesSubviews = YES;
self.bText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
self.bText.borderStyle = UITextBorderStyleRoundedRect;
self.bText.clearButtonMode = UITextFieldViewModeWhileEditing;
self.bText.clearsOnBeginEditing = NO;
self.bText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
self.bText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
self.bText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.bText.enablesReturnKeyAutomatically = NO;
self.bText.frame = CGRectMake(193.0, 81.0, 107.0, 31.0);
self.bText.keyboardAppearance = UIKeyboardAppearanceDefault;
self.bText.keyboardType = UIKeyboardTypeNumberPad;
self.bText.placeholder = @"Integer";
self.bText.returnKeyType = UIReturnKeyDefault;
self.bText.tag = 9;
self.bText.text = @"";
self.bText.textAlignment = UITextAlignmentCenter;
self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view.backgroundColor = [UIColor colorWithWhite:1.000 alpha:1.000];
self.view.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
self.view.tag = 0;
[self.view addSubview:background_button];
[self.view addSubview:label4];
[self.view addSubview:label7];
[self.view addSubview:label8];
[self.view addSubview:self.calculateButton];
[self.view addSubview:label11];
[self.view addSubview:self.resultLabel];
[self.view addSubview:self.aText];
[self.view addSubview:self.bText];
}
@end

View File

@@ -1,10 +0,0 @@
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

View File

@@ -1,13 +0,0 @@
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "backend.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
NimMain();
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}

View File

@@ -1,140 +0,0 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<Version Value="7"/>
<General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<UseXPManifest Value="True"/>
<ActiveEditorIndexAtStart Value="1"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<Language Value=""/>
<CharSet Value=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="LCL"/>
</Item1>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="nimlaz.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="nimlaz"/>
<CursorPos X="17" Y="21"/>
<TopLine Value="1"/>
<EditorIndex Value="1"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="unit1.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="Unit1"/>
<CursorPos X="26" Y="27"/>
<TopLine Value="2"/>
<EditorIndex Value="0"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
</Unit1>
</Units>
<JumpHistory Count="12" HistoryIndex="11">
<Position1>
<Filename Value="unit1.pas"/>
<Caret Line="27" Column="1" TopLine="1"/>
</Position1>
<Position2>
<Filename Value="unit1.pas"/>
<Caret Line="15" Column="3" TopLine="1"/>
</Position2>
<Position3>
<Filename Value="unit1.pas"/>
<Caret Line="17" Column="26" TopLine="1"/>
</Position3>
<Position4>
<Filename Value="unit1.pas"/>
<Caret Line="16" Column="18" TopLine="1"/>
</Position4>
<Position5>
<Filename Value="unit1.pas"/>
<Caret Line="20" Column="43" TopLine="2"/>
</Position5>
<Position6>
<Filename Value="unit1.pas"/>
<Caret Line="21" Column="48" TopLine="16"/>
</Position6>
<Position7>
<Filename Value="nimlaz.lpr"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position7>
<Position8>
<Filename Value="unit1.pas"/>
<Caret Line="52" Column="17" TopLine="9"/>
</Position8>
<Position9>
<Filename Value="unit1.pas"/>
<Caret Line="51" Column="12" TopLine="9"/>
</Position9>
<Position10>
<Filename Value="nimlaz.lpr"/>
<Caret Line="21" Column="3" TopLine="1"/>
</Position10>
<Position11>
<Filename Value="nimlaz.lpr"/>
<Caret Line="20" Column="1" TopLine="1"/>
</Position11>
<Position12>
<Filename Value="nimlaz.lpr"/>
<Caret Line="21" Column="7" TopLine="1"/>
</Position12>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="8"/>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)/"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -1,21 +0,0 @@
program nimlaz;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms
{ you can add units after this }, Unit1, LResources;
{$IFDEF WINDOWS}{$R nimlaz.rc}{$ENDIF}
begin
{$I nimlaz.lrs}
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
#define RT_MANIFEST 24
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "nimlaz.manifest"

View File

@@ -1,8 +0,0 @@
This example demonstrates how to use Nim with Lazarus. The GUI is generated
with Lazarus, while the "backend" is written in Nim. To compile the example,
use this command:
nim c --app:gui --no_main --no_linking backend.nim
Open the ``nimlaz.lpi`` file in Lazarus and run the program.

View File

@@ -1,46 +0,0 @@
object Form1: TForm1
Left = 553
Height = 111
Top = 464
Width = 448
ActiveControl = SpinEdit1
Caption = 'Sum'
ClientHeight = 111
ClientWidth = 448
OnCreate = FormCreate
LCLVersion = '0.9.28.2'
object Label1: TLabel
Left = 8
Height = 18
Top = 72
Width = 34
Caption = 'Sum:'
ParentColor = False
end
object SpinEdit1: TSpinEdit
Left = 8
Height = 27
Top = 8
Width = 436
Anchors = [akTop, akLeft, akRight]
OnChange = SpinEdit1Change
TabOrder = 0
end
object SpinEdit2: TSpinEdit
Left = 8
Height = 27
Top = 40
Width = 436
Anchors = [akTop, akLeft, akRight]
OnChange = SpinEdit1Change
TabOrder = 1
end
object Edit1: TEdit
Left = 48
Height = 27
Top = 72
Width = 396
Anchors = [akTop, akLeft, akRight]
TabOrder = 2
end
end

View File

@@ -1,58 +0,0 @@
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
Spin, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
SpinEdit1: TSpinEdit;
SpinEdit2: TSpinEdit;
procedure FormCreate(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{ TForm1 }
{$link nimcache/lib/system.o}
{$link nimcache/backend.o}
{$link nimcache/nim__dat.o}
{$linklib c}
procedure NimMain; cdecl; external;
function myAdd(x, y: longint): longint; cdecl; external;
procedure TForm1.FormCreate(Sender: TObject);
begin
// we initialize the Nim data structures here:
NimMain();
end;
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
Edit1.text := IntToStr(myAdd(SpinEdit1.Value, SpinEdit2.Value));
end;
initialization
{$I unit1.lrs}
end.

View File

@@ -1,5 +0,0 @@
# Backend for the different user interfaces.
proc myAdd*(x, y: int): int {.cdecl, exportc.} =
result = x + y

Some files were not shown because too many files have changed in this diff Show More