mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-15 03:19:22 +00:00
Merge branch 'devel' into experimentalize-reorder
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -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
|
||||
|
||||
|
||||
@@ -50,4 +50,4 @@ script:
|
||||
- ./koch web
|
||||
- ./koch csource
|
||||
- ./koch nimsuggest
|
||||
# - nim c -r nimsuggest/tester
|
||||
- nim c -r nimsuggest/tester
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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 :-)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
85
compiler/cmdlinehelper.nim
Normal file
85
compiler/cmdlinehelper.nim
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 == "/":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
188
doc/manual.rst
188
doc/manual.rst
@@ -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
|
||||
===============================
|
||||
|
||||
|
||||
76
doc/nep1.rst
76
doc/nep1.rst
@@ -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
|
||||
------------------
|
||||
|
||||
|
||||
82
doc/nimc.rst
82
doc/nimc.rst
@@ -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
|
||||
==================
|
||||
|
||||
|
||||
13
doc/tut1.rst
13
doc/tut1.rst
@@ -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:
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
@@ -1,5 +0,0 @@
|
||||
import cgi
|
||||
cgi.setStackTraceStdout()
|
||||
|
||||
var a: string = nil
|
||||
a.add "foobar"
|
||||
@@ -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>")
|
||||
@@ -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>")
|
||||
12
examples/cross_calculator/.gitignore
vendored
12
examples/cross_calculator/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">CrossCalculator</string>
|
||||
</resources>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ -d src ]
|
||||
then
|
||||
~/bin/objctags -R \
|
||||
jni \
|
||||
src
|
||||
fi
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 */;
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ -d src ]
|
||||
then
|
||||
~/bin/objctags -R \
|
||||
build/nimcache \
|
||||
src
|
||||
fi
|
||||
@@ -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
|
||||
@@ -1,7 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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]));
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
@@ -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"
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user