bugfixes; step one for 'var T' as return type support
This commit is contained in:
parent
e7135c449d
commit
2f066395ba
27 changed files with 234 additions and 68 deletions
|
|
@ -187,7 +187,7 @@ type
|
||||||
TNodeKinds* = set[TNodeKind]
|
TNodeKinds* = set[TNodeKind]
|
||||||
|
|
||||||
type
|
type
|
||||||
TSymFlag* = enum # already 30 flags!
|
TSymFlag* = enum # already 29 flags!
|
||||||
sfUsed, # read access of sym (for warnings) or simply used
|
sfUsed, # read access of sym (for warnings) or simply used
|
||||||
sfStar, # symbol has * visibility
|
sfStar, # symbol has * visibility
|
||||||
sfMinus, # symbol has - visibility
|
sfMinus, # symbol has - visibility
|
||||||
|
|
@ -204,7 +204,6 @@ type
|
||||||
sfRegister, # variable should be placed in a register
|
sfRegister, # variable should be placed in a register
|
||||||
sfPure, # object is "pure" that means it has no type-information
|
sfPure, # object is "pure" that means it has no type-information
|
||||||
|
|
||||||
sfResult, # variable is 'result' in proc
|
|
||||||
sfNoSideEffect, # proc has no side effects
|
sfNoSideEffect, # proc has no side effects
|
||||||
sfSideEffect, # proc may have side effects; cannot prove it has none
|
sfSideEffect, # proc may have side effects; cannot prove it has none
|
||||||
sfMainModule, # module is the main module
|
sfMainModule, # module is the main module
|
||||||
|
|
@ -293,6 +292,7 @@ type
|
||||||
skType, # a type
|
skType, # a type
|
||||||
skConst, # a constant
|
skConst, # a constant
|
||||||
skVar, # a variable
|
skVar, # a variable
|
||||||
|
skResult, # special 'result' variable
|
||||||
skProc, # a proc
|
skProc, # a proc
|
||||||
skMethod, # a method
|
skMethod, # a method
|
||||||
skIterator, # an iterator
|
skIterator, # an iterator
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||||
case n.sym.kind
|
case n.sym.kind
|
||||||
of skParam, skForVar, skTemp:
|
of skParam, skForVar, skTemp:
|
||||||
result = OnStack
|
result = OnStack
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
if sfGlobal in n.sym.flags: result = OnHeap
|
if sfGlobal in n.sym.flags: result = OnHeap
|
||||||
else: result = OnStack
|
else: result = OnStack
|
||||||
of skConst:
|
of skConst:
|
||||||
|
|
@ -206,6 +206,10 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# This function replaces all other methods for generating
|
# This function replaces all other methods for generating
|
||||||
# the assignment operation in C.
|
# the assignment operation in C.
|
||||||
|
if src.t != nil and src.t.kind == tyPtr:
|
||||||
|
# little HACK to suppor the new 'var T' as return type:
|
||||||
|
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
|
return
|
||||||
var ty = skipTypes(dest.t, abstractVarRange)
|
var ty = skipTypes(dest.t, abstractVarRange)
|
||||||
case ty.kind
|
case ty.kind
|
||||||
of tyRef:
|
of tyRef:
|
||||||
|
|
@ -1648,7 +1652,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
genComplexConst(p, sym, d)
|
genComplexConst(p, sym, d)
|
||||||
of skEnumField:
|
of skEnumField:
|
||||||
putIntoDest(p, d, e.typ, toRope(sym.position))
|
putIntoDest(p, d, e.typ, toRope(sym.position))
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
|
if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
|
||||||
if ((sym.loc.r == nil) or (sym.loc.t == nil)):
|
if ((sym.loc.r == nil) or (sym.loc.t == nil)):
|
||||||
InternalError(e.info, "expr: var not init " & sym.name.s)
|
InternalError(e.info, "expr: var not init " & sym.name.s)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ proc mangleName(s: PSym): PRope =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skMethod, skConverter, skConst:
|
of skProc, skMethod, skConverter, skConst:
|
||||||
result = toRope("@")
|
result = toRope("@")
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
if sfGlobal in s.flags: result = toRope("@")
|
if sfGlobal in s.flags: result = toRope("@")
|
||||||
else: result = toRope("%")
|
else: result = toRope("%")
|
||||||
of skForVar, skTemp, skParam, skType, skEnumField, skModule:
|
of skForVar, skTemp, skParam, skType, skEnumField, skModule:
|
||||||
|
|
@ -153,7 +153,7 @@ proc getGlobalTempName(): PRope =
|
||||||
|
|
||||||
proc ccgIntroducedPtr(s: PSym): bool =
|
proc ccgIntroducedPtr(s: PSym): bool =
|
||||||
var pt = s.typ
|
var pt = s.typ
|
||||||
assert(not (sfResult in s.flags))
|
assert skResult != s.kind
|
||||||
case pt.Kind
|
case pt.Kind
|
||||||
of tyObject:
|
of tyObject:
|
||||||
# XXX quick hack floatSize*2 for the pegs module under 64bit
|
# XXX quick hack floatSize*2 for the pegs module under 64bit
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ proc cgsym(m: BModule, name: string): PRope =
|
||||||
if sym != nil:
|
if sym != nil:
|
||||||
case sym.kind
|
case sym.kind
|
||||||
of skProc, skMethod, skConverter: genProc(m, sym)
|
of skProc, skMethod, skConverter: genProc(m, sym)
|
||||||
of skVar: genVarPrototype(m, sym)
|
of skVar, skResult: genVarPrototype(m, sym)
|
||||||
of skType: discard getTypeDesc(m, sym.typ)
|
of skType: discard getTypeDesc(m, sym.typ)
|
||||||
else: InternalError("cgsym: " & name)
|
else: InternalError("cgsym: " & name)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -810,7 +810,7 @@ proc generateDoc(d: PDoc, n: PNode) =
|
||||||
|
|
||||||
proc genSection(d: PDoc, kind: TSymKind) =
|
proc genSection(d: PDoc, kind: TSymKind) =
|
||||||
const sectionNames: array[skModule..skTemplate, string] = [
|
const sectionNames: array[skModule..skTemplate, string] = [
|
||||||
"Imports", "Types", "Consts", "Vars", "Procs", "Methods",
|
"Imports", "Types", "Consts", "Vars", "Vars", "Procs", "Methods",
|
||||||
"Iterators", "Converters", "Macros", "Templates"
|
"Iterators", "Converters", "Macros", "Templates"
|
||||||
]
|
]
|
||||||
if d.section[kind] == nil: return
|
if d.section[kind] == nil: return
|
||||||
|
|
|
||||||
|
|
@ -832,7 +832,7 @@ proc genAddr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
s = n.sons[0].sym
|
s = n.sons[0].sym
|
||||||
if s.loc.r == nil: InternalError(n.info, "genAddr: 3")
|
if s.loc.r == nil: InternalError(n.info, "genAddr: 3")
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
if mapType(n.typ) == etyObject:
|
if mapType(n.typ) == etyObject:
|
||||||
# make addr() a no-op:
|
# make addr() a no-op:
|
||||||
r.kind = etyNone
|
r.kind = etyNone
|
||||||
|
|
@ -863,7 +863,7 @@ proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if s.loc.r == nil:
|
if s.loc.r == nil:
|
||||||
InternalError(n.info, "symbol has no generated name: " & s.name.s)
|
InternalError(n.info, "symbol has no generated name: " & s.name.s)
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skParam, skTemp:
|
of skVar, skParam, skTemp, skResult:
|
||||||
var k = mapType(s.typ)
|
var k = mapType(s.typ)
|
||||||
if k == etyBaseIndex:
|
if k == etyBaseIndex:
|
||||||
r.kind = etyBaseIndex
|
r.kind = etyBaseIndex
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
|
||||||
# which can be modified.
|
# which can be modified.
|
||||||
var x = c
|
var x = c
|
||||||
while x != nil:
|
while x != nil:
|
||||||
if sfResult in sym.flags:
|
if sym.kind == skResult:
|
||||||
result = x.params[0]
|
result = x.params[0]
|
||||||
if result == nil: result = emptyNode
|
if result == nil: result = emptyNode
|
||||||
return
|
return
|
||||||
|
|
@ -425,7 +425,8 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode =
|
||||||
proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
case n.sym.kind
|
case n.sym.kind
|
||||||
of skProc, skConverter, skMacro: result = n.sym.ast.sons[codePos]
|
of skProc, skConverter, skMacro: result = n.sym.ast.sons[codePos]
|
||||||
of skVar, skForVar, skTemp: result = evalVariable(c.tos, n.sym, flags)
|
of skVar, skForVar, skTemp, skResult:
|
||||||
|
result = evalVariable(c.tos, n.sym, flags)
|
||||||
of skParam:
|
of skParam:
|
||||||
# XXX what about LValue?
|
# XXX what about LValue?
|
||||||
result = c.tos.params[n.sym.position + 1]
|
result = c.tos.params[n.sym.position + 1]
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ proc UseMagic(m: BModule, name: string) =
|
||||||
if sym != nil:
|
if sym != nil:
|
||||||
case sym.kind
|
case sym.kind
|
||||||
of skProc, skMethod, skConverter: genProc(m, sym)
|
of skProc, skMethod, skConverter: genProc(m, sym)
|
||||||
of skVar: genVarPrototype(m, sym)
|
of skVar, skResult: genVarPrototype(m, sym)
|
||||||
of skType: discard getTypeDesc(m, sym.typ)
|
of skType: discard getTypeDesc(m, sym.typ)
|
||||||
else: InternalError("useMagic: " & name)
|
else: InternalError("useMagic: " & name)
|
||||||
elif not (sfSystemModule in m.module.flags):
|
elif not (sfSystemModule in m.module.flags):
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ type
|
||||||
errResultCannotBeOpenArray, errSizeTooBig, errSetTooBig,
|
errResultCannotBeOpenArray, errSizeTooBig, errSetTooBig,
|
||||||
errBaseTypeMustBeOrdinal, errInheritanceOnlyWithNonFinalObjects,
|
errBaseTypeMustBeOrdinal, errInheritanceOnlyWithNonFinalObjects,
|
||||||
errInheritanceOnlyWithEnums, errIllegalRecursionInTypeX,
|
errInheritanceOnlyWithEnums, errIllegalRecursionInTypeX,
|
||||||
errCannotInstantiateX, errExprHasNoAddress, errVarForOutParamNeeded,
|
errCannotInstantiateX, errExprHasNoAddress, errXStackEscape,
|
||||||
|
errVarForOutParamNeeded,
|
||||||
errPureTypeMismatch, errTypeMismatch, errButExpected, errButExpectedX,
|
errPureTypeMismatch, errTypeMismatch, errButExpected, errButExpectedX,
|
||||||
errAmbiguousCallXYZ, errWrongNumberOfArguments, errXCannotBePassedToProcVar,
|
errAmbiguousCallXYZ, errWrongNumberOfArguments, errXCannotBePassedToProcVar,
|
||||||
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
||||||
|
|
@ -227,6 +228,7 @@ const
|
||||||
errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'",
|
errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'",
|
||||||
errCannotInstantiateX: "cannot instantiate: \'$1\'",
|
errCannotInstantiateX: "cannot instantiate: \'$1\'",
|
||||||
errExprHasNoAddress: "expression has no address",
|
errExprHasNoAddress: "expression has no address",
|
||||||
|
errXStackEscape: "address of '$1' may not escape its stack frame",
|
||||||
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
|
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
|
||||||
errPureTypeMismatch: "type mismatch",
|
errPureTypeMismatch: "type mismatch",
|
||||||
errTypeMismatch: "type mismatch: got (",
|
errTypeMismatch: "type mismatch: got (",
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,10 @@ proc addResult(c: PContext, t: PType, info: TLineInfo)
|
||||||
proc addResultNode(c: PContext, n: PNode)
|
proc addResultNode(c: PContext, n: PNode)
|
||||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
||||||
|
|
||||||
|
proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||||
|
if not typeAllowed(typ, skConst):
|
||||||
|
GlobalError(typ.n.info, errXisNoType, typeToString(typ))
|
||||||
|
|
||||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
result = semExprWithType(c, n)
|
result = semExprWithType(c, n)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,31 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||||
|
|
||||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
|
||||||
|
proc newDeref(n: PNode): PNode {.inline.} =
|
||||||
|
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
|
||||||
|
addSon(result, n)
|
||||||
|
|
||||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, n, flags)
|
result = semExpr(c, n, flags)
|
||||||
if result.kind == nkEmpty:
|
if result.kind == nkEmpty:
|
||||||
# do not produce another redundant error message:
|
# do not produce another redundant error message:
|
||||||
raiseRecoverableError()
|
raiseRecoverableError()
|
||||||
if result.typ != nil:
|
if result.typ != nil:
|
||||||
if result.typ.kind == tyVar:
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
|
|
||||||
addSon(d, result)
|
|
||||||
result = d
|
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errExprXHasNoType,
|
GlobalError(n.info, errExprXHasNoType,
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
|
|
||||||
|
proc semExprWithTypeNoDeref(c: PContext, n: PNode,
|
||||||
|
flags: TExprFlags = {}): PNode =
|
||||||
|
result = semExpr(c, n, flags)
|
||||||
|
if result.kind == nkEmpty:
|
||||||
|
# do not produce another redundant error message:
|
||||||
|
raiseRecoverableError()
|
||||||
|
if result.typ == nil:
|
||||||
|
GlobalError(n.info, errExprXHasNoType,
|
||||||
|
renderTree(result, {renderNoComments}))
|
||||||
|
|
||||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = symChoice(c, n, s)
|
result = symChoice(c, n, s)
|
||||||
|
|
||||||
|
|
@ -67,7 +78,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
of skMacro: result = semMacroExpr(c, n, s)
|
of skMacro: result = semMacroExpr(c, n, s)
|
||||||
of skTemplate: result = semTemplateExpr(c, n, s)
|
of skTemplate: result = semTemplateExpr(c, n, s)
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
# if a proc accesses a global variable, it is not side effect free:
|
# if a proc accesses a global variable, it is not side effect free:
|
||||||
if sfGlobal in s.flags: incl(c.p.owner.flags, sfSideEffect)
|
if sfGlobal in s.flags: incl(c.p.owner.flags, sfSideEffect)
|
||||||
|
|
@ -330,33 +341,37 @@ type
|
||||||
TAssignableResult = enum
|
TAssignableResult = enum
|
||||||
arNone, # no l-value and no discriminant
|
arNone, # no l-value and no discriminant
|
||||||
arLValue, # is an l-value
|
arLValue, # is an l-value
|
||||||
|
arLocalLValue, # is an l-value, but local var; must not escape
|
||||||
|
# its stack frame!
|
||||||
arDiscriminant # is a discriminant
|
arDiscriminant # is a discriminant
|
||||||
|
|
||||||
proc isAssignable(n: PNode): TAssignableResult =
|
proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||||
result = arNone
|
result = arNone
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if n.sym.kind in {skVar, skTemp}: result = arLValue
|
if n.sym.kind in {skVar, skResult, skTemp}:
|
||||||
|
if c.p.owner.id == n.sym.owner.id: result = arLocalLValue
|
||||||
|
else: result = arLValue
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(n.sons[0])
|
result = isAssignable(c, n.sons[0])
|
||||||
if result == arLValue and sfDiscriminant in n.sons[1].sym.flags:
|
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
|
||||||
result = arDiscriminant
|
result = arDiscriminant
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(n.sons[0])
|
result = isAssignable(c, n.sons[0])
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||||
# Object and tuple conversions are still addressable, so we skip them
|
# Object and tuple conversions are still addressable, so we skip them
|
||||||
if skipTypes(n.typ, abstractPtrs).kind in {tyOpenArray, tyTuple, tyObject}:
|
if skipTypes(n.typ, abstractPtrs).kind in {tyOpenArray, tyTuple, tyObject}:
|
||||||
result = isAssignable(n.sons[1])
|
result = isAssignable(c, n.sons[1])
|
||||||
of nkHiddenDeref, nkDerefExpr:
|
of nkHiddenDeref, nkDerefExpr:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||||
result = isAssignable(n.sons[0])
|
result = isAssignable(c, n.sons[0])
|
||||||
else:
|
else:
|
||||||
nil
|
nil
|
||||||
|
|
||||||
|
|
@ -367,7 +382,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
||||||
addSon(result, n)
|
addSon(result, n)
|
||||||
if isAssignable(n) != arLValue:
|
if isAssignable(c, n) notin {arLValue, arLocalLValue}:
|
||||||
localError(n.info, errVarForOutParamNeeded)
|
localError(n.info, errVarForOutParamNeeded)
|
||||||
|
|
||||||
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -403,7 +418,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
if i < sonsLen(t) and t.sons[i] != nil and
|
if i < sonsLen(t) and t.sons[i] != nil and
|
||||||
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
||||||
if isAssignable(n.sons[i]) != arLValue:
|
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
|
||||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||||
return
|
return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
|
@ -751,6 +766,29 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
globalError(n.Info, errUndeclaredFieldX, id.s)
|
globalError(n.Info, errUndeclaredFieldX, id.s)
|
||||||
|
|
||||||
|
proc takeImplicitAddr(c: PContext, n: PNode): PNode =
|
||||||
|
case n.kind
|
||||||
|
of nkHiddenAddr, nkAddr: return n
|
||||||
|
of nkHiddenDeref, nkDerefExpr: return n.sons[0]
|
||||||
|
of nkBracketExpr:
|
||||||
|
if len(n) == 1: return n.sons[0]
|
||||||
|
else: nil
|
||||||
|
var valid = isAssignable(c, n)
|
||||||
|
if valid != arLValue:
|
||||||
|
if valid == arLocalLValue:
|
||||||
|
GlobalError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
|
||||||
|
else:
|
||||||
|
GlobalError(n.info, errExprHasNoAddress)
|
||||||
|
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
|
||||||
|
result.add(n)
|
||||||
|
|
||||||
|
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||||
|
if le.kind == nkHiddenDeref:
|
||||||
|
var x = le.sons[0]
|
||||||
|
if x.typ.kind == tyVar and x.kind == nkSym and x.sym.kind == skResult:
|
||||||
|
n.sons[0] = x # 'result[]' --> 'result'
|
||||||
|
n.sons[1] = takeImplicitAddr(c, ri)
|
||||||
|
|
||||||
proc semAsgn(c: PContext, n: PNode): PNode =
|
proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
var a = n.sons[0]
|
var a = n.sons[0]
|
||||||
|
|
@ -762,8 +800,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
if a == nil:
|
if a == nil:
|
||||||
return propertyWriteAccess(c, n, n[0])
|
return propertyWriteAccess(c, n, n[0])
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
# a[i..j] = x
|
# a[i] = x
|
||||||
# --> `[..]=`(a, i, j, x)
|
# --> `[]=`(a, i, x)
|
||||||
a = semSubscript(c, a, {efLValue})
|
a = semSubscript(c, a, {efLValue})
|
||||||
if a == nil:
|
if a == nil:
|
||||||
result = buildOverloadedSubscripts(n.sons[0], inAsgn=true)
|
result = buildOverloadedSubscripts(n.sons[0], inAsgn=true)
|
||||||
|
|
@ -772,15 +810,19 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
a = semExprWithType(c, a, {efLValue})
|
a = semExprWithType(c, a, {efLValue})
|
||||||
n.sons[0] = a
|
n.sons[0] = a
|
||||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
# a = b # both are vars, means: a[] = b[]
|
||||||
|
# a = b # b no 'var T' means: a = addr(b)
|
||||||
var le = a.typ
|
var le = a.typ
|
||||||
if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone:
|
if skipTypes(le, {tyGenericInst}).kind != tyVar and
|
||||||
|
IsAssignable(c, a) == arNone:
|
||||||
# Direct assignment to a discriminant is allowed!
|
# Direct assignment to a discriminant is allowed!
|
||||||
localError(a.info, errXCannotBeAssignedTo,
|
localError(a.info, errXCannotBeAssignedTo,
|
||||||
renderTree(a, {renderNoComments}))
|
renderTree(a, {renderNoComments}))
|
||||||
else:
|
else:
|
||||||
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
n.sons[1] = fitNode(c, le, n.sons[1])
|
n.sons[1] = fitNode(c, le, n.sons[1])
|
||||||
fixAbstractType(c, n)
|
fixAbstractType(c, n)
|
||||||
|
asgnToResultVar(c, n, n.sons[0], n.sons[1])
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
||||||
|
|
@ -1144,7 +1186,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||||
if isAssignable(n.sons[0]) != arLValue:
|
if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}:
|
||||||
GlobalError(n.info, errExprHasNoAddress)
|
GlobalError(n.info, errExprHasNoAddress)
|
||||||
n.typ = makePtrType(c, n.sons[0].typ)
|
n.typ = makePtrType(c, n.sons[0].typ)
|
||||||
of nkHiddenAddr, nkHiddenDeref:
|
of nkHiddenAddr, nkHiddenDeref:
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
result.typ = newTypeS(tyProc, c)
|
result.typ = newTypeS(tyProc, c)
|
||||||
addSon(result.typ, nil)
|
addSon(result.typ, nil)
|
||||||
result.typ.callConv = fn.typ.callConv
|
result.typ.callConv = fn.typ.callConv
|
||||||
|
ParamsTypeCheck(c, result.typ)
|
||||||
var oldPrc = GenericCacheGet(c, entry)
|
var oldPrc = GenericCacheGet(c, entry)
|
||||||
if oldPrc == nil:
|
if oldPrc == nil:
|
||||||
# add it here, so that recursive generic procs are possible:
|
# add it here, so that recursive generic procs are possible:
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ proc SemReturn(c: PContext, n: PNode): PNode =
|
||||||
addSon(a, n.sons[0])
|
addSon(a, n.sons[0])
|
||||||
n.sons[0] = semAsgn(c, a)
|
n.sons[0] = semAsgn(c, a)
|
||||||
# optimize away ``result = result``:
|
# optimize away ``result = result``:
|
||||||
if n[0][1].kind == nkSym and sfResult in n[0][1].sym.flags:
|
if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult:
|
||||||
n.sons[0] = ast.emptyNode
|
n.sons[0] = ast.emptyNode
|
||||||
|
|
||||||
proc SemYield(c: PContext, n: PNode): PNode =
|
proc SemYield(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -544,10 +544,9 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
|
||||||
|
|
||||||
proc addResult(c: PContext, t: PType, info: TLineInfo) =
|
proc addResult(c: PContext, t: PType, info: TLineInfo) =
|
||||||
if t != nil:
|
if t != nil:
|
||||||
var s = newSym(skVar, getIdent"result", getCurrOwner())
|
var s = newSym(skResult, getIdent"result", getCurrOwner())
|
||||||
s.info = info
|
s.info = info
|
||||||
s.typ = t
|
s.typ = t
|
||||||
incl(s.flags, sfResult)
|
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
addDecl(c, s)
|
addDecl(c, s)
|
||||||
c.p.resultSym = s
|
c.p.resultSym = s
|
||||||
|
|
@ -569,6 +568,7 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
semParamList(c, n.sons[ParamsPos], nil, s)
|
semParamList(c, n.sons[ParamsPos], nil, s)
|
||||||
addParams(c, s.typ.n)
|
addParams(c, s.typ.n)
|
||||||
|
ParamsTypeCheck(c, s.typ)
|
||||||
else:
|
else:
|
||||||
s.typ = newTypeS(tyProc, c)
|
s.typ = newTypeS(tyProc, c)
|
||||||
addSon(s.typ, nil)
|
addSon(s.typ, nil)
|
||||||
|
|
@ -664,6 +664,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
if sfBorrow in s.flags:
|
if sfBorrow in s.flags:
|
||||||
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||||
|
ParamsTypeCheck(c, s.typ)
|
||||||
pushProcCon(c, s)
|
pushProcCon(c, s)
|
||||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||||
addResult(c, s.typ.sons[0], n.info)
|
addResult(c, s.typ.sons[0], n.info)
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ proc analyseSym(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
result = c.mapping[v.id]
|
result = c.mapping[v.id]
|
||||||
if result != toUndefined: return
|
if result != toUndefined: return
|
||||||
case v.kind
|
case v.kind
|
||||||
of skVar:
|
of skVar, skResult:
|
||||||
result = toNil
|
result = toNil
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
if sfThreadVar in v.flags:
|
if sfThreadVar in v.flags:
|
||||||
|
|
@ -192,9 +192,13 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
if prc.ast.sons[codePos].kind == nkEmpty and
|
if prc.ast.sons[codePos].kind == nkEmpty and
|
||||||
{sfNoSideEffect, sfThread, sfImportc} * prc.flags == {}:
|
{sfNoSideEffect, sfThread, sfImportc} * prc.flags == {}:
|
||||||
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
||||||
|
if result == toUndefined: result = toNil
|
||||||
if prc.typ.sons[0] != nil:
|
if prc.typ.sons[0] != nil:
|
||||||
if prc.ast.len > resultPos:
|
if prc.ast.len > resultPos:
|
||||||
result = newCtx.mapping[prc.ast.sons[resultPos].sym.id]
|
result = newCtx.mapping[prc.ast.sons[resultPos].sym.id]
|
||||||
|
# if the proc body does not set 'result', nor 'return's something
|
||||||
|
# explicitely, it returns a binary zero, so 'toNil' is correct:
|
||||||
|
if result == toUndefined: result = toNil
|
||||||
else:
|
else:
|
||||||
result = toNil
|
result = toNil
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -480,8 +480,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
# n.sons[0] contains the pragmas (if any). We process these later...
|
# n.sons[0] contains the pragmas (if any). We process these later...
|
||||||
checkSonsLen(n, 3)
|
checkSonsLen(n, 3)
|
||||||
if n.sons[1].kind != nkEmpty:
|
if n.sons[1].kind != nkEmpty:
|
||||||
base = semTypeNode(c, n.sons[1].sons[0], nil)
|
base = skipTypes(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs)
|
||||||
var concreteBase = skipGenericInvokation(skipTypes(base, skipPtrs))
|
var concreteBase = skipGenericInvokation(base)
|
||||||
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
|
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
|
||||||
addInheritedFields(c, check, pos, concreteBase)
|
addInheritedFields(c, check, pos, concreteBase)
|
||||||
else:
|
else:
|
||||||
|
|
@ -528,7 +528,7 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
||||||
|
|
||||||
proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType =
|
proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType =
|
||||||
result = semTypeNode(c, n, nil)
|
result = semTypeNode(c, n, nil)
|
||||||
if (genericParams != nil) and (sonsLen(genericParams) == 0):
|
if genericParams != nil and sonsLen(genericParams) == 0:
|
||||||
result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
|
result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
|
||||||
#if result.kind == tyGenericInvokation: debug(result)
|
#if result.kind == tyGenericInvokation: debug(result)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
|
||||||
var found = false
|
var found = false
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar: found = sfGlobal notin s.flags
|
of skVar: found = sfGlobal notin s.flags
|
||||||
of skTemp, skForVar, skParam: found = true
|
of skTemp, skForVar, skParam, skResult: found = true
|
||||||
else: nil
|
else: nil
|
||||||
if found and owner.id != s.owner.id and not ContainsOrIncl(marked, s.id):
|
if found and owner.id != s.owner.id and not ContainsOrIncl(marked, s.id):
|
||||||
incl(s.flags, sfInClosure)
|
incl(s.flags, sfInClosure)
|
||||||
|
|
|
||||||
|
|
@ -759,7 +759,7 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool =
|
||||||
if not result: return
|
if not result: return
|
||||||
|
|
||||||
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
assert(kind in {skVar, skConst, skParam})
|
assert(kind in {skVar, skConst, skParam, skResult})
|
||||||
# if we have already checked the type, return true, because we stop the
|
# if we have already checked the type, return true, because we stop the
|
||||||
# evaluation if something is wrong:
|
# evaluation if something is wrong:
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -773,13 +773,14 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
of tyVar:
|
of tyVar:
|
||||||
result = false # ``var var`` is always an invalid type:
|
result = false # ``var var`` is always an invalid type:
|
||||||
of tyOpenArray:
|
of tyOpenArray:
|
||||||
result = (kind == skParam) and typeAllowedAux(marker, t2, kind)
|
result = kind == skParam and typeAllowedAux(marker, t2, kind)
|
||||||
else: result = (kind != skConst) and typeAllowedAux(marker, t2, kind)
|
else:
|
||||||
|
result = kind in {skParam, skResult} and typeAllowedAux(marker, t2, kind)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
for i in countup(1, sonsLen(t) - 1):
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
result = typeAllowedAux(marker, t.sons[i], skParam)
|
result = typeAllowedAux(marker, t.sons[i], skParam)
|
||||||
if not result: return
|
if not result: return
|
||||||
if t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skVar)
|
if t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skResult)
|
||||||
of tyExpr, tyStmt, tyTypeDesc:
|
of tyExpr, tyStmt, tyTypeDesc:
|
||||||
result = true
|
result = true
|
||||||
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation:
|
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation:
|
||||||
|
|
@ -799,9 +800,10 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
|
result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
result = (kind != skConst) and typeAllowedAux(marker, t.sons[0], skVar) or
|
result = (kind != skConst) and typeAllowedAux(marker, t.sons[0], skVar) or
|
||||||
(t.sons[0].kind == tyEmpty)
|
t.sons[0].kind == tyEmpty
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = typeAllowedAux(marker, t.sons[1], skVar)
|
result = typeAllowedAux(marker, t.sons[1], skVar) or
|
||||||
|
t.sons[1].kind == tyEmpty
|
||||||
of tyPtr, tyRef:
|
of tyPtr, tyRef:
|
||||||
result = typeAllowedAux(marker, t.sons[0], skVar)
|
result = typeAllowedAux(marker, t.sons[0], skVar)
|
||||||
of tyArrayConstr, tyTuple, tySet:
|
of tyArrayConstr, tyTuple, tySet:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2010 Dominik Picheta
|
# (c) Copyright 2011 Dominik Picheta
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -87,7 +87,7 @@ proc checkReply(smtp: TSMTP, reply: string) =
|
||||||
proc connect*(address: string, port = 25,
|
proc connect*(address: string, port = 25,
|
||||||
ssl = false, debug = false): TSMTP =
|
ssl = false, debug = false): TSMTP =
|
||||||
## Establishes a connection with a SMTP server.
|
## Establishes a connection with a SMTP server.
|
||||||
## May fail with EInvalidReply or with a socket errors.
|
## May fail with EInvalidReply or with a socket error.
|
||||||
|
|
||||||
if not ssl:
|
if not ssl:
|
||||||
result.sock = socket()
|
result.sock = socket()
|
||||||
|
|
@ -125,7 +125,6 @@ proc sendmail*(smtp: TSMTP, fromaddr: string,
|
||||||
## Sends `msg` from `fromaddr` to `toaddr`.
|
## Sends `msg` from `fromaddr` to `toaddr`.
|
||||||
## Messages may be formed using ``createMessage`` by converting the
|
## Messages may be formed using ``createMessage`` by converting the
|
||||||
## TMessage into a string.
|
## TMessage into a string.
|
||||||
## This function sends the QUIT command when finished.
|
|
||||||
|
|
||||||
smtp.debugSend("MAIL FROM:<" & fromaddr & ">\c\L")
|
smtp.debugSend("MAIL FROM:<" & fromaddr & ">\c\L")
|
||||||
smtp.checkReply("250")
|
smtp.checkReply("250")
|
||||||
|
|
@ -140,7 +139,8 @@ proc sendmail*(smtp: TSMTP, fromaddr: string,
|
||||||
smtp.debugSend(".\c\L")
|
smtp.debugSend(".\c\L")
|
||||||
smtp.checkReply("250")
|
smtp.checkReply("250")
|
||||||
|
|
||||||
# quit
|
proc close*(smtp: TSMTP) =
|
||||||
|
## Disconnects from the SMTP server and closes the socket.
|
||||||
smtp.debugSend("QUIT\c\L")
|
smtp.debugSend("QUIT\c\L")
|
||||||
if not smtp.ssl:
|
if not smtp.ssl:
|
||||||
smtp.sock.close()
|
smtp.sock.close()
|
||||||
|
|
@ -201,6 +201,6 @@ when isMainModule:
|
||||||
smtp.auth("someone", "password")
|
smtp.auth("someone", "password")
|
||||||
smtp.sendmail("someone@gmail.com",
|
smtp.sendmail("someone@gmail.com",
|
||||||
@["someone@yahoo.com", "someone@gmail.com"], $msg)
|
@["someone@yahoo.com", "someone@gmail.com"], $msg)
|
||||||
|
smtp.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,14 @@ proc `[]`*(t: PStringTable, key: string): string {.rtl, extern: "nstGet".} =
|
||||||
if index >= 0: result = t.data[index].val
|
if index >= 0: result = t.data[index].val
|
||||||
else: result = ""
|
else: result = ""
|
||||||
|
|
||||||
|
proc modGet*(t: PStringTable, key: string): var string {.
|
||||||
|
rtl, extern: "nstTake".} =
|
||||||
|
## retrieves the location at ``t[key]``. If `key` is not in `t`, the
|
||||||
|
## ``EInvalidValue`` exception is raised.
|
||||||
|
var index = RawGet(t, key)
|
||||||
|
if index >= 0: result = t.data[index].val
|
||||||
|
else: raise newException(EInvalidValue, "key does not exist: " & key)
|
||||||
|
|
||||||
proc hasKey*(t: PStringTable, key: string): bool {.rtl, extern: "nst$1".} =
|
proc hasKey*(t: PStringTable, key: string): bool {.rtl, extern: "nst$1".} =
|
||||||
## returns true iff `key` is in the table `t`.
|
## returns true iff `key` is in the table `t`.
|
||||||
result = rawGet(t, key) >= 0
|
result = rawGet(t, key) >= 0
|
||||||
|
|
@ -213,4 +221,6 @@ when isMainModule:
|
||||||
assert x["k"] == "v"
|
assert x["k"] == "v"
|
||||||
assert x["11"] == "22"
|
assert x["11"] == "22"
|
||||||
assert x["565"] == "67"
|
assert x["565"] == "67"
|
||||||
|
x.modGet("11") = "23"
|
||||||
|
assert x["11"] == "23"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4505,3 +4505,5 @@ proc G_TYPE_GSTRING*(): GType =
|
||||||
proc g_thread_init*(vtable: pointer) {.
|
proc g_thread_init*(vtable: pointer) {.
|
||||||
cdecl, dynlib: gobjectlib, importc: "g_thread_init".}
|
cdecl, dynlib: gobjectlib, importc: "g_thread_init".}
|
||||||
|
|
||||||
|
proc g_timeout_add*(interval: guint, function, data: gpointer): guint {.
|
||||||
|
cdecl, dynlib: gliblib, importc: "g_timeout_add".}
|
||||||
|
|
|
||||||
23
tests/accept/run/teventemitter.nim
Normal file
23
tests/accept/run/teventemitter.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import tables
|
||||||
|
import lists
|
||||||
|
type
|
||||||
|
TEventArgs = object of TObject
|
||||||
|
type
|
||||||
|
TEventEmitter = object of TObject
|
||||||
|
events*: TTable[string, TDoublyLinkedList[proc(e : TEventArgs)]]
|
||||||
|
proc on*(emitter : var TEventEmitter, event : string, func : proc(e : TEventArgs)) =
|
||||||
|
if hasKey(emitter.events, event) == false:
|
||||||
|
var list: TDoublyLinkedList[proc(e : TEventArgs)]
|
||||||
|
add(emitter.events,event,list) #if not, add it.
|
||||||
|
append(emitter.events[event], func) #adds the function to the event's list. I get a error here too.
|
||||||
|
|
||||||
|
proc emit*(emitter : TEventEmitter, event : string, args : TEventArgs) =
|
||||||
|
for func in items(emitter.events[event]):
|
||||||
|
func(args) #call function with args.
|
||||||
|
proc initEmitter(emitter : TEventEmitter) =
|
||||||
|
emitter.events = initTable[string, TSinglyLinkedList[TObject]]()
|
||||||
|
|
||||||
|
var ee : TEventEmitter
|
||||||
|
ee.on("print", proc(e : TEventArgs) = echo("pie"))
|
||||||
|
ee.emit("print")
|
||||||
|
|
||||||
15
tests/accept/run/tvarres1.nim
Normal file
15
tests/accept/run/tvarres1.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
discard """
|
||||||
|
output: "45"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var
|
||||||
|
g = 5
|
||||||
|
|
||||||
|
proc p(): var int =
|
||||||
|
var bla = addr(g) #: array [0..7, int]
|
||||||
|
result = bla[]
|
||||||
|
|
||||||
|
p() = 45
|
||||||
|
|
||||||
|
echo g
|
||||||
|
|
||||||
20
tests/accept/run/tvarres2.nim
Normal file
20
tests/accept/run/tvarres2.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
discard """
|
||||||
|
output: "45 hallo"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
TKachel = tuple[i: int, s: string]
|
||||||
|
TSpielwiese = object
|
||||||
|
k: seq[TKachel]
|
||||||
|
|
||||||
|
var
|
||||||
|
spielwiese: TSpielwiese
|
||||||
|
newSeq(spielwiese.k, 64)
|
||||||
|
|
||||||
|
proc at*(s: var TSpielwiese, x, y: int): var TKachel =
|
||||||
|
result = s.k[y * 8 + x]
|
||||||
|
|
||||||
|
spielwiese.at(3, 4) = (45, "hallo")
|
||||||
|
|
||||||
|
echo spielwiese.at(3,4)[0], " ", spielwiese.at(3,4)[1]
|
||||||
|
|
||||||
17
tests/reject/tvarres1.nim
Normal file
17
tests/reject/tvarres1.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
file: "tvarres1.nim"
|
||||||
|
line: 12
|
||||||
|
errormsg: "address of 'bla' may not escape its stack frame"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var
|
||||||
|
g = 5
|
||||||
|
|
||||||
|
proc p(): var int =
|
||||||
|
var bla: int
|
||||||
|
result = bla
|
||||||
|
|
||||||
|
p() = 45
|
||||||
|
|
||||||
|
echo g
|
||||||
|
|
||||||
16
tests/reject/tvarres2.nim
Normal file
16
tests/reject/tvarres2.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
file: "tvarres1.nim"
|
||||||
|
line: 11
|
||||||
|
errormsg: "expression has no address"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var
|
||||||
|
g = 5
|
||||||
|
|
||||||
|
proc p(): var int =
|
||||||
|
result = 89
|
||||||
|
|
||||||
|
p() = 45
|
||||||
|
|
||||||
|
echo g
|
||||||
|
|
||||||
8
todo.txt
8
todo.txt
|
|
@ -1,8 +1,11 @@
|
||||||
Version 0.8.14
|
Version 0.8.14
|
||||||
==============
|
==============
|
||||||
|
|
||||||
- ``var T`` as a return type; easy to prove that location does not escape its
|
- ``var T`` as a return type:
|
||||||
stack frame
|
* for iterators
|
||||||
|
* add ``modGet`` for generics
|
||||||
|
* documentation
|
||||||
|
* provide ``mod`` as an alternative syntax for ``var``
|
||||||
- document Nimrod's two phase symbol lookup for generics
|
- document Nimrod's two phase symbol lookup for generics
|
||||||
- optional indentation for 'case' statement
|
- optional indentation for 'case' statement
|
||||||
- make threadvar efficient again on linux after testing
|
- make threadvar efficient again on linux after testing
|
||||||
|
|
@ -41,7 +44,6 @@ version 0.9.XX
|
||||||
proc specialization in the code gen
|
proc specialization in the code gen
|
||||||
- resizing of strings/sequences could take into account the memory that
|
- resizing of strings/sequences could take into account the memory that
|
||||||
is allocated
|
is allocated
|
||||||
- typeAllowed() for parameters...
|
|
||||||
- find a way to reintroduce the cleanup() pass for C code generation: this
|
- find a way to reintroduce the cleanup() pass for C code generation: this
|
||||||
is hard because of partial evaluation --> symbol files will fix this as
|
is hard because of partial evaluation --> symbol files will fix this as
|
||||||
a side effect
|
a side effect
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue