zipfiles compiles again; added system.shallowCopy

This commit is contained in:
Araq
2011-06-20 23:20:11 +02:00
parent c3f11d1637
commit f1100356b1
7 changed files with 158 additions and 142 deletions

View File

@@ -310,7 +310,7 @@ type
TMagic* = enum # symbols that require compiler magic:
mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs,
mEcho, mCreateThread,
mEcho, mCreateThread, mShallowCopy,
mUnaryLt, mSucc,
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,

View File

@@ -397,7 +397,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
const
FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl,
mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap,
mAppendSeqElem, mNewSeq, mReset}
mAppendSeqElem, mNewSeq, mReset, mShallowCopy}
checkMinSonsLen(n, 1)
var t = n.sons[0].typ
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic in FakeVarParams):
@@ -505,72 +505,25 @@ proc semEcho(c: PContext, n: PNode): PNode =
var arg = semExprWithType(c, n.sons[i])
n.sons[i] = semExpr(c, buildStringify(c, arg))
result = n
proc buildEchoStmt(c: PContext, n: PNode): PNode =
# we MUST not check 'n' for semantics again here!
result = newNodeI(nkCall, n.info)
var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo")
if e == nil: GlobalError(n.info, errSystemNeeds, "echo")
addSon(result, newSymNode(e))
var arg = buildStringify(c, n)
# problem is: implicit '$' is not checked for semantics yet. So we give up
# and check 'arg' for semantics again:
addSon(result, semExpr(c, arg))
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
if onlyCurrentScope:
result = SymtabLocalGet(c.tab, i)
else:
result = SymtabGet(c.Tab, i) # no need for stub loading
proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
case n.kind
of nkIdent:
result = LookupForDefined(c, n.ident, onlyCurrentScope)
of nkDotExpr:
result = nil
if onlyCurrentScope: return
checkSonsLen(n, 2)
var m = LookupForDefined(c, n.sons[0], onlyCurrentScope)
if (m != nil) and (m.kind == skModule):
if (n.sons[1].kind == nkIdent):
var ident = n.sons[1].ident
if m == c.module:
result = StrTableGet(c.tab.stack[ModuleTablePos], ident)
else:
result = StrTableGet(m.tab, ident)
else:
GlobalError(n.sons[1].info, errIdentifierExpected, "")
of nkAccQuoted:
result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
of nkSym:
result = n.sym
else:
GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
checkSonsLen(n, 2)
# we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0)
if LookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
result.intVal = 1
elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and
condsyms.isDefined(n.sons[1].ident):
result.intVal = 1
result.info = n.info
result.typ = getSysType(tyBool)
proc setMs(n: PNode, s: PSym): PNode =
result = n
n.sons[0] = newSymNode(s)
n.sons[0].info = n.info
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
# this is a hotspot in the compiler!
result = n
case s.magic # magics that need special treatment
of mDefined: result = semDefined(c, setMs(n, s), false)
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
of mSizeOf: result = semSizeof(c, setMs(n, s))
of mIs: result = semIs(c, setMs(n, s))
of mEcho: result = semEcho(c, setMs(n, s))
of mCreateThread:
result = semDirectOp(c, n, flags)
if semthreads.needsGlobalAnalysis():
c.threadEntries.add(result)
else: result = semDirectOp(c, n, flags)
proc semExprNoType(c: PContext, n: PNode): PNode =
result = semExpr(c, n)
if result.typ != nil and result.typ.kind != tyStmt:
if gCmd == cmdInteractive:
result = buildEchoStmt(c, result)
else:
localError(n.info, errDiscardValue)
proc isTypeExpr(n: PNode): bool =
case n.kind
@@ -784,6 +737,126 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# overloaded [] operator:
result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
var id = considerAcc(a[1])
result = newNodeI(nkCall, n.info)
addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
# nodes?
addSon(result, a[0])
addSon(result, semExpr(c, n[1]))
result = semDirectCallAnalyseEffects(c, result, {})
if result != nil:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
else:
globalError(n.Info, errUndeclaredFieldX, id.s)
proc semAsgn(c: PContext, n: PNode): PNode =
checkSonsLen(n, 2)
var a = n.sons[0]
case a.kind
of nkDotExpr:
# r.f = x
# --> `f=` (r, x)
a = builtinFieldAccess(c, a, {efLValue})
if a == nil:
return propertyWriteAccess(c, n, n[0])
of nkBracketExpr:
# a[i..j] = x
# --> `[..]=`(a, i, j, x)
a = semSubscript(c, a, {efLValue})
if a == nil:
result = buildOverloadedSubscripts(n.sons[0], inAsgn=true)
add(result, n[1])
return semExprNoType(c, result)
else:
a = semExprWithType(c, a, {efLValue})
n.sons[0] = a
n.sons[1] = semExprWithType(c, n.sons[1])
var le = a.typ
if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone:
# Direct assignment to a discriminant is allowed!
localError(a.info, errXCannotBeAssignedTo,
renderTree(a, {renderNoComments}))
else:
n.sons[1] = fitNode(c, le, n.sons[1])
fixAbstractType(c, n)
result = n
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
if onlyCurrentScope:
result = SymtabLocalGet(c.tab, i)
else:
result = SymtabGet(c.Tab, i) # no need for stub loading
proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
case n.kind
of nkIdent:
result = LookupForDefined(c, n.ident, onlyCurrentScope)
of nkDotExpr:
result = nil
if onlyCurrentScope: return
checkSonsLen(n, 2)
var m = LookupForDefined(c, n.sons[0], onlyCurrentScope)
if (m != nil) and (m.kind == skModule):
if (n.sons[1].kind == nkIdent):
var ident = n.sons[1].ident
if m == c.module:
result = StrTableGet(c.tab.stack[ModuleTablePos], ident)
else:
result = StrTableGet(m.tab, ident)
else:
GlobalError(n.sons[1].info, errIdentifierExpected, "")
of nkAccQuoted:
result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
of nkSym:
result = n.sym
else:
GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
checkSonsLen(n, 2)
# we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0)
if LookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
result.intVal = 1
elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and
condsyms.isDefined(n.sons[1].ident):
result.intVal = 1
result.info = n.info
result.typ = getSysType(tyBool)
proc setMs(n: PNode, s: PSym): PNode =
result = n
n.sons[0] = newSymNode(s)
n.sons[0].info = n.info
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
# this is a hotspot in the compiler!
result = n
case s.magic # magics that need special treatment
of mDefined: result = semDefined(c, setMs(n, s), false)
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
of mSizeOf: result = semSizeof(c, setMs(n, s))
of mIs: result = semIs(c, setMs(n, s))
of mEcho: result = semEcho(c, setMs(n, s))
of mCreateThread:
result = semDirectOp(c, n, flags)
if semthreads.needsGlobalAnalysis():
c.threadEntries.add(result)
of mShallowCopy:
checkSonsLen(n, 3)
result = newNodeI(nkFastAsgn, n.info)
result.add(n[1])
result.add(n[2])
result = semAsgn(c, result)
else: result = semDirectOp(c, n, flags)
proc semIfExpr(c: PContext, n: PNode): PNode =
result = n
checkMinSonsLen(n, 2)

View File

@@ -8,25 +8,6 @@
#
## this module does the semantic checking of statements
proc buildEchoStmt(c: PContext, n: PNode): PNode =
# we MUST not check 'n' for semantics again here!
result = newNodeI(nkCall, n.info)
var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo")
if e == nil: GlobalError(n.info, errSystemNeeds, "echo")
addSon(result, newSymNode(e))
var arg = buildStringify(c, n)
# problem is: implicit '$' is not checked for semantics yet. So we give up
# and check 'arg' for semantics again:
addSon(result, semExpr(c, arg))
proc semExprNoType(c: PContext, n: PNode): PNode =
result = semExpr(c, n)
if result.typ != nil and result.typ.kind != tyStmt:
if gCmd == cmdInteractive:
result = buildEchoStmt(c, result)
else:
localError(n.info, errDiscardValue)
proc semCommand(c: PContext, n: PNode): PNode =
result = semExprNoType(c, n)
@@ -170,54 +151,6 @@ proc semCase(c: PContext, n: PNode): PNode =
localError(n.info, errNotAllCasesCovered)
closeScope(c.tab)
proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
var id = considerAcc(a[1])
result = newNodeI(nkCall, n.info)
addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
# nodes?
addSon(result, a[0])
addSon(result, semExpr(c, n[1]))
result = semDirectCallAnalyseEffects(c, result, {})
if result != nil:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
else:
globalError(n.Info, errUndeclaredFieldX, id.s)
proc semAsgn(c: PContext, n: PNode): PNode =
checkSonsLen(n, 2)
var a = n.sons[0]
case a.kind
of nkDotExpr:
# r.f = x
# --> `f=` (r, x)
a = builtinFieldAccess(c, a, {efLValue})
if a == nil:
return propertyWriteAccess(c, n, n[0])
of nkBracketExpr:
# a[i..j] = x
# --> `[..]=`(a, i, j, x)
a = semSubscript(c, a, {efLValue})
if a == nil:
result = buildOverloadedSubscripts(n.sons[0], inAsgn=true)
add(result, n[1])
return semExprNoType(c, result)
else:
a = semExprWithType(c, a, {efLValue})
n.sons[0] = a
n.sons[1] = semExprWithType(c, n.sons[1])
var le = a.typ
if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone:
# Direct assignment to a discriminant is allowed!
localError(a.info, errXCannotBeAssignedTo,
renderTree(a, {renderNoComments}))
else:
n.sons[1] = fitNode(c, le, n.sons[1])
fixAbstractType(c, n)
result = n
proc SemReturn(c: PContext, n: PNode): PNode =
var
restype: PType

View File

@@ -223,6 +223,8 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/pure/cookies.nim
cp lib/pure/dynlib.nim $libdir/pure/dynlib.nim || exit 1
chmod 644 $libdir/pure/dynlib.nim
cp lib/pure/encodings.nim $libdir/pure/encodings.nim || exit 1
chmod 644 $libdir/pure/encodings.nim
cp lib/pure/gentabs.nim $libdir/pure/gentabs.nim || exit 1
chmod 644 $libdir/pure/gentabs.nim
cp lib/pure/hashes.nim $libdir/pure/hashes.nim || exit 1
@@ -267,6 +269,8 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/pure/redis.nim
cp lib/pure/regexprs.nim $libdir/pure/regexprs.nim || exit 1
chmod 644 $libdir/pure/regexprs.nim
cp lib/pure/romans.nim $libdir/pure/romans.nim || exit 1
chmod 644 $libdir/pure/romans.nim
cp lib/pure/ropes.nim $libdir/pure/ropes.nim || exit 1
chmod 644 $libdir/pure/ropes.nim
cp lib/pure/scgi.nim $libdir/pure/scgi.nim || exit 1
@@ -307,8 +311,6 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/impure/db_sqlite.nim
cp lib/impure/dialogs.nim $libdir/impure/dialogs.nim || exit 1
chmod 644 $libdir/impure/dialogs.nim
cp lib/impure/encodings.nim $libdir/impure/encodings.nim || exit 1
chmod 644 $libdir/impure/encodings.nim
cp lib/impure/graphics.nim $libdir/impure/graphics.nim || exit 1
chmod 644 $libdir/impure/graphics.nim
cp lib/impure/osinfo_posix.nim $libdir/impure/osinfo_posix.nim || exit 1

View File

@@ -113,9 +113,9 @@ type
PZipFileStream* =
ref TZipFileStream ## a reader stream of a file within a zip archive
proc fsClose(s: PZipFileStream) = zip_fclose(s.f)
proc fsReadData(s: PZipFileStream, buffer: pointer, bufLen: int): int =
result = zip_fread(s.f, buffer, bufLen)
proc fsClose(s: PStream) = zip_fclose(PZipFileStream(s).f)
proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int =
result = zip_fread(PZipFileStream(s).f, buffer, bufLen)
proc newZipFileStream(f: PZipFile): PZipFileStream =
new(result)

View File

@@ -801,18 +801,25 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
setLen(x, xl + y.len)
for i in 0..high(y): x[xl+i] = y[i]
proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
## use this instead of `=` for a `shallow copy`:idx:. The shallow copy
## only changes the semantics for sequences and strings (and types which
## contain those). Be careful with the changed semantics though! There
## is a reason why the default assignment does a deep copy of sequences
## and strings.
proc del*[T](x: var seq[T], i: int) {.noSideEffect.} =
## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
## This is an O(1) operation.
var xl = x.len
x[i] = x[xl-1]
shallowCopy(x[i], x[xl-1])
setLen(x, xl-1)
proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} =
## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
## This is an O(n) operation.
var xl = x.len
for j in i..xl-2: x[j] = x[j+1]
for j in i..xl-2: shallowCopy(x[j], x[j+1])
setLen(x, xl-1)
proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} =

View File

@@ -94,7 +94,8 @@ Additions
- The compiler now supports array, sequence and string slicing.
- Added ``system.newStringOfCap``.
- Added ``system.raiseHook``.
- Added ``system.writeFile ``.
- Added ``system.writeFile``.
- Added ``system.shallowCopy``.
- ``system.echo`` is guaranteed to be thread-safe.
- Case statement branches support constant sets for programming convenience.