added 'sig' feature; removed tfShared support in the compiler

This commit is contained in:
Andreas Rumpf 2016-02-28 19:56:41 +01:00
commit 38dee2095c
17 changed files with 62 additions and 57 deletions

View file

@ -221,6 +221,7 @@ type
nkGotoState, # used for the state machine (for iterators) nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (for iterators) nkState, # give a label to a code section (for iterators)
nkBreakState, # special break statement for easier code generation nkBreakState, # special break statement for easier code generation
nkSigSection
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]
type type
@ -459,7 +460,7 @@ type
tfByCopy, # pass object/tuple by copy (C backend) tfByCopy, # pass object/tuple by copy (C backend)
tfByRef, # pass object/tuple by reference (C backend) tfByRef, # pass object/tuple by reference (C backend)
tfIterator, # type is really an iterator, not a tyProc tfIterator, # type is really an iterator, not a tyProc
tfShared, # type is 'shared' tfPartial, # type is declared as 'partial'
tfNotNil, # type cannot be 'nil' tfNotNil, # type cannot be 'nil'
tfNeedsInit, # type constains a "not nil" constraint somewhere or some tfNeedsInit, # type constains a "not nil" constraint somewhere or some
@ -534,7 +535,7 @@ const
skError* = skUnknown skError* = skUnknown
# type flags that are essential for type equality: # type flags that are essential for type equality:
eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr} eqTypeFlags* = {tfIterator, tfNotNil, tfVarIsPtr}
type type
TMagic* = enum # symbols that require compiler magic: TMagic* = enum # symbols that require compiler magic:

View file

@ -158,7 +158,6 @@ proc hashType(c: var MD5Context, t: PType) =
if tfThread in t.flags: c &= ".thread" if tfThread in t.flags: c &= ".thread"
else: else:
for i in 0.. <t.len: c.hashType(t.sons[i]) for i in 0.. <t.len: c.hashType(t.sons[i])
if tfShared in t.flags: c &= "shared"
if tfNotNil in t.flags: c &= "not nil" if tfNotNil in t.flags: c &= "not nil"
proc canonConst(n: PNode): TUid = proc canonConst(n: PNode): TUid =

View file

@ -44,7 +44,8 @@ type
tkLet, tkLet,
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
tkObject, tkOf, tkOr, tkOut, tkObject, tkOf, tkOr, tkOut,
tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkStatic, tkProc, tkPtr, tkRaise, tkRef, tkReturn,
tkShl, tkShr, tkSig, tkStatic,
tkTemplate, tkTemplate,
tkTry, tkTuple, tkType, tkUsing, tkTry, tkTuple, tkType, tkUsing,
tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
@ -81,7 +82,7 @@ const
"macro", "method", "mixin", "mod", "macro", "method", "mixin", "mod",
"nil", "not", "notin", "object", "of", "or", "nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "out", "proc", "ptr", "raise", "ref", "return",
"shl", "shr", "static", "shl", "shr", "sig", "static",
"template", "template",
"try", "tuple", "type", "using", "try", "tuple", "type", "using",
"var", "when", "while", "with", "without", "xor", "var", "when", "while", "with", "without", "xor",

View file

@ -1938,6 +1938,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkLet: result = parseSection(p, nkLetSection, parseVariable) of tkLet: result = parseSection(p, nkLetSection, parseVariable)
of tkWhen: result = parseIfOrWhen(p, nkWhenStmt) of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
of tkVar: result = parseSection(p, nkVarSection, parseVariable) of tkVar: result = parseSection(p, nkVarSection, parseVariable)
of tkSig: result = parseSection(p, nkSigSection, parseVariable)
of tkBind: result = parseBind(p, nkBindStmt) of tkBind: result = parseBind(p, nkBindStmt)
of tkMixin: result = parseBind(p, nkMixinStmt) of tkMixin: result = parseBind(p, nkMixinStmt)
of tkUsing: result = parseBind(p, nkUsingStmt) of tkUsing: result = parseBind(p, nkUsingStmt)

View file

@ -460,7 +460,7 @@ proc lsub(n: PNode): int =
else: else:
result = len("enum") result = len("enum")
of nkEnumFieldDef: result = lsons(n) + 3 of nkEnumFieldDef: result = lsons(n) + 3
of nkVarSection, nkLetSection: of nkVarSection, nkLetSection, nkSigSection:
if sonsLen(n) > 1: result = MaxLineLen + 1 if sonsLen(n) > 1: result = MaxLineLen + 1
else: result = lsons(n) + len("var_") else: result = lsons(n) + len("var_")
of nkReturnStmt: result = lsub(n.sons[0]) + len("return_") of nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
@ -1173,11 +1173,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
initContext(a) initContext(a)
incl(a.flags, rfInConstExpr) incl(a.flags, rfInConstExpr)
gsection(g, n, a, tkConst, "const") gsection(g, n, a, tkConst, "const")
of nkVarSection, nkLetSection: of nkVarSection, nkLetSection, nkSigSection:
var L = sonsLen(n) var L = sonsLen(n)
if L == 0: return if L == 0: return
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var") if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
else: putWithSpace(g, tkLet, "let") elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
else: putWithSpace(g, tkSig, "sig")
if L > 1: if L > 1:
gcoms(g) gcoms(g)
indentNL(g) indentNL(g)

View file

@ -105,6 +105,7 @@ type
instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo; instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
op: TTypeAttachedOp): PSym {.nimcall.} op: TTypeAttachedOp): PSym {.nimcall.}
selfName*: PIdent selfName*: PIdent
signatures*: TStrTable
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s result.genericSym = s
@ -178,6 +179,8 @@ proc newContext(module: PSym): PContext =
initStrTable(result.userPragmas) initStrTable(result.userPragmas)
result.generics = @[] result.generics = @[]
result.unknownIdents = initIntSet() result.unknownIdents = initIntSet()
initStrTable(result.signatures)
proc inclSym(sq: var TSymSeq, s: PSym) = proc inclSym(sq: var TSymSeq, s: PSym) =
var L = len(sq) var L = len(sq)

View file

@ -2354,6 +2354,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if not n.sons[0].typ.isEmptyType and not implicitlyDiscardable(n.sons[0]): if not n.sons[0].typ.isEmptyType and not implicitlyDiscardable(n.sons[0]):
localError(n.info, errGenerated, "'defer' takes a 'void' expression") localError(n.info, errGenerated, "'defer' takes a 'void' expression")
#localError(n.info, errGenerated, "'defer' not allowed in this context") #localError(n.info, errGenerated, "'defer' not allowed in this context")
of nkSigSection: result = semSigSection(c, n)
else: else:
localError(n.info, errInvalidExpressionX, localError(n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))

View file

@ -386,6 +386,27 @@ proc isDiscardUnderscore(v: PSym): bool =
v.flags.incl(sfGenSym) v.flags.incl(sfGenSym)
result = true result = true
proc semSigSection(c: PContext; n: PNode): PNode =
result = ast.emptyNode
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a)
checkMinSonsLen(a, 3)
var length = sonsLen(a)
if a.sons[length-2].kind != nkEmpty:
let typ = semTypeNode(c, a.sons[length-2], nil)
for j in countup(0, length-3):
let v = semIdentDef(c, a.sons[j], skParam)
v.typ = typ
strTableIncl(c.signatures, v)
else:
localError(a.info, "'sig' section must have a type")
var def: PNode
if a.sons[length-1].kind != nkEmpty:
localError(a.info, "'sig' sections cannot contain assignments")
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode var b: PNode
result = copyNode(n) result = copyNode(n)

View file

@ -934,14 +934,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
def = fitNode(c, typ, def) def = fitNode(c, typ, def)
if not hasType and not hasDefault: if not hasType and not hasDefault:
if isType: localError(a.info, "':' expected") if isType: localError(a.info, "':' expected")
let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything if kind in {skTemplate, skMacro}:
if tdef == tyAnything: typ = newTypeS(tyExpr, c)
message(a.info, warnTypelessParam, renderTree(n)) elif skipTypes(typ, {tyGenericInst}).kind == tyEmpty:
typ = newTypeS(tdef, c) continue
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
for j in countup(0, length-3): for j in countup(0, length-3):
var arg = newSymG(skParam, a.sons[j], c) var arg = newSymG(skParam, a.sons[j], c)
if not hasType and not hasDefault and kind notin {skTemplate, skMacro}:
let param = strTableGet(c.signatures, arg.name)
if param != nil: typ = param.typ
else:
localError(a.info, "typeless parameters are obsolete")
typ = errorType(c)
let lifted = liftParamType(c, kind, genericParams, typ, let lifted = liftParamType(c, kind, genericParams, typ,
arg.name.s, arg.info) arg.name.s, arg.info)
let finalType = if lifted != nil: lifted else: typ.skipIntLit let finalType = if lifted != nil: lifted else: typ.skipIntLit
@ -1307,11 +1311,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkType: result = n.typ of nkType: result = n.typ
of nkStmtListType: result = semStmtListType(c, n, prev) of nkStmtListType: result = semStmtListType(c, n, prev)
of nkBlockType: result = semBlockType(c, n, prev) of nkBlockType: result = semBlockType(c, n, prev)
of nkSharedTy:
checkSonsLen(n, 1)
result = semTypeNode(c, n.sons[0], prev)
result = freshType(result, prev)
result.flags.incl(tfShared)
else: else:
localError(n.info, errTypeExpected) localError(n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
@ -1387,15 +1386,6 @@ proc processMagicType(c: PContext, m: PSym) =
rawAddSon(m.typ, newTypeS(tyNone, c)) rawAddSon(m.typ, newTypeS(tyNone, c))
of mPNimrodNode: of mPNimrodNode:
incl m.typ.flags, tfTriggersCompileTime incl m.typ.flags, tfTriggersCompileTime
of mShared:
setMagicType(m, tyObject, 0)
m.typ.n = newNodeI(nkRecList, m.info)
incl m.typ.flags, tfShared
of mGuarded:
setMagicType(m, tyObject, 0)
m.typ.n = newNodeI(nkRecList, m.info)
incl m.typ.flags, tfShared
rawAddSon(m.typ, sysTypeFromName"shared")
else: localError(m.info, errTypeExpected) else: localError(m.info, errTypeExpected)
proc semGenericConstraints(c: PContext, x: PType): PType = proc semGenericConstraints(c: PContext, x: PType): PType =

View file

@ -14,22 +14,11 @@ import ast, astalgo, msgs, types, magicsys, semdata, renderer
const const
tfInstClearedFlags = {tfHasMeta} tfInstClearedFlags = {tfHasMeta}
proc sharedPtrCheck(info: TLineInfo, t: PType) =
if t.kind == tyPtr and t.len > 1:
if t.sons[0].sym.magic == mShared:
incl(t.flags, tfShared)
#if t.sons[0].sym.magic == mGuarded: incl(t.flags, tfGuarded)
if tfHasGCedMem in t.flags or t.isGCedMem:
localError(info, errGenerated,
"shared memory may not refer to GC'ed thread local memory")
proc checkPartialConstructedType(info: TLineInfo, t: PType) = proc checkPartialConstructedType(info: TLineInfo, t: PType) =
if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
localError(info, errInvalidPragmaX, "acyclic") localError(info, errInvalidPragmaX, "acyclic")
elif t.kind == tyVar and t.sons[0].kind == tyVar: elif t.kind == tyVar and t.sons[0].kind == tyVar:
localError(info, errVarVarTypeNotAllowed) localError(info, errVarVarTypeNotAllowed)
else:
sharedPtrCheck(info, t)
proc checkConstructedType*(info: TLineInfo, typ: PType) = proc checkConstructedType*(info: TLineInfo, typ: PType) =
var t = typ.skipTypes({tyDistinct}) var t = typ.skipTypes({tyDistinct})
@ -40,8 +29,6 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) =
localError(info, errVarVarTypeNotAllowed) localError(info, errVarVarTypeNotAllowed)
elif computeSize(t) == szIllegalRecursion: elif computeSize(t) == szIllegalRecursion:
localError(info, errIllegalRecursionInTypeX, typeToString(t)) localError(info, errIllegalRecursionInTypeX, typeToString(t))
else:
sharedPtrCheck(info, t)
when false: when false:
if t.kind == tyObject and t.sons[0] != nil: if t.kind == tyObject and t.sons[0] != nil:
if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:

View file

@ -412,7 +412,6 @@ const
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg} const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
proc addTypeFlags(name: var string, typ: PType) {.inline.} = proc addTypeFlags(name: var string, typ: PType) {.inline.} =
if tfShared in typ.flags: name = "shared " & name
if tfNotNil in typ.flags: name.add(" not nil") if tfNotNil in typ.flags: name.add(" not nil")
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =

View file

@ -30,7 +30,7 @@ type
wInclude, wInterface, wIs, wIsnot, wIterator, wLet, wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
wMacro, wMethod, wMixin, wMod, wNil, wMacro, wMethod, wMixin, wMod, wNil,
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, wShl, wShr, wSig, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar,
wWhen, wWhile, wWith, wWithout, wXor, wYield, wWhen, wWhile, wWith, wWithout, wXor, wYield,
wColon, wColonColon, wEquals, wDot, wDotDot, wColon, wColonColon, wEquals, wDot, wDotDot,
@ -113,7 +113,7 @@ const
"macro", "method", "mixin", "mod", "nil", "not", "notin", "macro", "method", "mixin", "mod", "nil", "not", "notin",
"object", "of", "or", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "out", "proc", "ptr", "raise", "ref", "return",
"shl", "shr", "static", "shl", "shr", "sig", "static",
"template", "try", "tuple", "type", "using", "var", "template", "try", "tuple", "type", "using", "var",
"when", "while", "with", "without", "xor", "when", "while", "with", "without", "xor",
"yield", "yield",

View file

@ -71,7 +71,13 @@ type
nnkEnumTy, nnkEnumTy,
nnkEnumFieldDef, nnkEnumFieldDef,
nnkArglist, nnkPattern nnkArglist, nnkPattern
nnkReturnToken nnkReturnToken,
nnkClosure,
nnkGotoState,
nnkState,
nnkBreakState,
nnkSigSection
NimNodeKinds* = set[NimNodeKind] NimNodeKinds* = set[NimNodeKind]
NimTypeKind* = enum NimTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty, ntyNone, ntyBool, ntyChar, ntyEmpty,

View file

@ -56,7 +56,7 @@ const
"generic", "if", "import", "in", "include", "generic", "if", "import", "in", "include",
"interface", "is", "isnot", "iterator", "let", "macro", "method", "interface", "is", "isnot", "iterator", "let", "macro", "method",
"mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
"ptr", "raise", "ref", "return", "shl", "shr", "static", "ptr", "raise", "ref", "return", "shl", "shr", "sig", "static",
"template", "try", "tuple", "type", "using", "var", "when", "while", "with", "template", "try", "tuple", "type", "using", "var", "when", "while", "with",
"without", "xor", "yield"] "without", "xor", "yield"]

View file

@ -279,11 +279,6 @@ when not defined(niminheritable):
when not defined(nimunion): when not defined(nimunion):
{.pragma: unchecked.} {.pragma: unchecked.}
when defined(nimNewShared):
type
`shared`* {.magic: "Shared".}
guarded* {.magic: "Guarded".}
# comparison operators: # comparison operators:
proc `==` *[Enum: enum](x, y: Enum): bool {.magic: "EqEnum", noSideEffect.} proc `==` *[Enum: enum](x, y: Enum): bool {.magic: "EqEnum", noSideEffect.}
## Checks whether values within the *same enum* have the same underlying value ## Checks whether values within the *same enum* have the same underlying value

View file

@ -103,9 +103,9 @@ else:
proc c_setjmp(jmpb: C_JmpBuf): cint {. proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "setjmp".} header: "<setjmp.h>", importc: "setjmp".}
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".} importc: "signal", header: "<signal.h>".}
proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".} proc c_raise(sign: cint) {.importc: "raise", header: "<signal.h>".}
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs",
header: "<stdio.h>".} header: "<stdio.h>".}

View file

@ -316,7 +316,7 @@ when defined(endb):
dbgAborting: bool # whether the debugger wants to abort dbgAborting: bool # whether the debugger wants to abort
when not defined(noSignalHandler): when not defined(noSignalHandler):
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} = proc signalHandler(sign: cint) {.exportc: "signalHandler", noconv.} =
template processSignal(s, action: expr) {.immediate, dirty.} = template processSignal(s, action: expr) {.immediate, dirty.} =
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n") if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
elif s == SIGSEGV: elif s == SIGSEGV:
@ -342,13 +342,13 @@ when not defined(noSignalHandler):
GC_disable() GC_disable()
var buf = newStringOfCap(2000) var buf = newStringOfCap(2000)
rawWriteStackTrace(buf) rawWriteStackTrace(buf)
processSignal(sig, buf.add) # nice hu? currying a la Nim :-) processSignal(sign, buf.add) # nice hu? currying a la Nim :-)
showErrorMessage(buf) showErrorMessage(buf)
GC_enable() GC_enable()
else: else:
var msg: cstring var msg: cstring
template asgn(y: expr) = msg = y template asgn(y: expr) = msg = y
processSignal(sig, asgn) processSignal(sign, asgn)
showErrorMessage(msg) showErrorMessage(msg)
when defined(endb): dbgAborting = true when defined(endb): dbgAborting = true
quit(1) # always quit when SIGABRT quit(1) # always quit when SIGABRT
@ -367,6 +367,6 @@ when not defined(noSignalHandler):
proc setControlCHook(hook: proc () {.noconv.} not nil) = proc setControlCHook(hook: proc () {.noconv.} not nil) =
# ugly cast, but should work on all architectures: # ugly cast, but should work on all architectures:
type SignalHandler = proc (sig: cint) {.noconv, benign.} type SignalHandler = proc (sign: cint) {.noconv, benign.}
{.deprecated: [TSignalHandler: SignalHandler].} {.deprecated: [TSignalHandler: SignalHandler].}
c_signal(SIGINT, cast[SignalHandler](hook)) c_signal(SIGINT, cast[SignalHandler](hook))