added '..^' and '..<' operators; 'nil' is allowed for 'len'; added plugin system to the compiler

This commit is contained in:
Araq
2015-04-22 11:49:41 +02:00
parent 54515241e3
commit 4be0d16520
10 changed files with 85 additions and 18 deletions

View File

@@ -530,12 +530,13 @@ type
TMagic* = enum # symbols that require compiler magic:
mNone,
mDefined, mDefinedInScope, mCompiles,
mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mRoof,
mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mRoof, mPlugin,
mEcho, mShallowCopy, mSlurp, mStaticExec,
mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
mUnaryLt, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
mGCunref,
mLengthStr, mLengthArray, mLengthSeq, mXLenStr, mXLenSeq,
mIncl, mExcl, mCard, mChr,
mGCref, mGCunref,
mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
mDivI64, mModI64, mSucc, mPred,
@@ -590,7 +591,8 @@ type
const
ctfeWhitelist* = {mNone, mUnaryLt, mSucc,
mPred, mInc, mDec, mOrd, mLengthOpenArray,
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr,
mLengthStr, mLengthArray, mLengthSeq, mXLenStr, mXLenSeq,
mIncl, mExcl, mCard, mChr,
mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
mDivI64, mModI64, mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,

View File

@@ -1352,15 +1352,15 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: unaryExpr(p, e, d, "$1Len0")
of tyCString:
useStringh(p.module)
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
else: unaryExpr(p, e, d, "strlen($1)")
if op == mHigh: unaryExpr(p, e, d, "($1 ? (strlen($1)-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? strlen($1) : 0)")
of tyString, tySequence:
if not p.module.compileToCpp:
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "$1->Sup.len")
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->len-1)")
else: unaryExpr(p, e, d, "$1->len")
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
of tyArray, tyArrayConstr:
# YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, rope(lastOrd(typ)))
@@ -1721,6 +1721,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
genArrayLen(p, e, d, op)
of mXLenStr, mXLenSeq:
if not p.module.compileToCpp:
unaryExpr(p, e, d, "($1->Sup.len-1)")
else:
unaryExpr(p, e, d, "$1->len")
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
of mSetLengthStr: genSetLengthStr(p, e, d)

View File

@@ -22,7 +22,8 @@ const
someLt = {mLtI, mLtI64, mLtF64, mLtU, mLtU64, mLtEnum,
mLtCh, mLtB, mLtPtr, mLtStr}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
mXLenStr, mXLenSeq}
someIn = {mInRange, mInSet}

43
compiler/plugins.nim Normal file
View File

@@ -0,0 +1,43 @@
#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Plugin support for the Nim compiler. Right now there are no plugins and they
## need to be build with the compiler, no DLL support.
import ast, semdata, idents
type
Transformation* = proc (c: PContext; n: PNode): PNode {.nimcall.}
Plugin = ref object
fn, module, package: PIdent
t: Transformation
next: Plugin
proc pluginMatches(p: Plugin; s: PSym): bool =
if s.name.id != p.fn.id: return false
let module = s.owner
if module == nil or module.kind != skModule or
module.name.id != p.module.id: return false
let package = module.owner
if package == nil or package.kind != skPackage or
package.name.id != p.package.id: return false
return true
var head: Plugin
proc getPlugin*(fn: PSym): Transformation =
var it = head
while it != nil:
if pluginMatches(it, fn): return it.t
it = it.next
proc registerPlugin*(package, module, fn: string; t: Transformation) =
let oldHead = head
head = Plugin(fn: getIdent(fn), module: getIdent(module),
package: getIdent(package), t: t, next: oldHead)

View File

@@ -16,7 +16,7 @@ import
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity,
semparallel, lowerings
semparallel, lowerings, plugins
when defined(nimfix):
import nimfix.prettybase

View File

@@ -286,9 +286,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
of mNot: result = newIntNodeT(1 - getInt(a), n)
of mCard: result = newIntNodeT(nimsets.cardSet(a), n)
of mBitnotI, mBitnotI64: result = newIntNodeT(not getInt(a), n)
of mLengthStr: result = newIntNodeT(len(getStr(a)), n)
of mLengthStr, mXLenStr: result = newIntNodeT(len(getStr(a)), n)
of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n)
of mLengthSeq, mLengthOpenArray: result = newIntNodeT(sonsLen(a), n) # BUGFIX
of mLengthSeq, mLengthOpenArray, mXLenSeq:
result = newIntNodeT(sonsLen(a), n) # BUGFIX
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
of mToFloat, mToBiggestFloat:
result = newFloatNodeT(toFloat(int(getInt(a))), n)

View File

@@ -196,4 +196,11 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result.add newSymNode(createMagic("-", mSubI), n.info)
result.add lenExprB
result.add n.sons[1]
of mPlugin:
let plugin = getPlugin(n[0].sym)
if plugin.isNil:
localError(n.info, "cannot find plugin " & n[0].sym.name.s)
result = n
else:
result = plugin(c, n)
else: result = n

View File

@@ -742,9 +742,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcNewStr, dest, tmp)
c.freeTemp(tmp)
# XXX buggy
of mLengthOpenArray, mLengthArray, mLengthSeq:
of mLengthOpenArray, mLengthArray, mLengthSeq, mXLenSeq:
genUnaryABI(c, n, dest, opcLenSeq)
of mLengthStr:
of mLengthStr, mXLenStr:
genUnaryABI(c, n, dest, opcLenStr)
of mIncl, mExcl:
unused(n, dest)

View File

@@ -3266,4 +3266,9 @@ template `..<`*(a, b: expr): expr =
## '..' and '<' is required.
a .. <b
proc xlen*(x: string): int {.magic: "XLenStr", noSideEffect.}
proc xlen*[T](x: seq[T]): int {.magic: "XLenSeq", noSideEffect.}
## returns the length of a sequence or a string without testing for 'nil'.
## This is an optimization that rarely makes sense.
{.pop.} #{.push warning[GcMem]: off.}

View File

@@ -1,8 +1,11 @@
version 0.10.4
==============
- make 'nil' work for 'add' and 'len'
- add '..^' and '..<' operators to system
- make 'nil' work for 'add':
- resizeString
- incrSeq
- addChar
version 1.0
===========