objects with no ancestor are not implicitely final

This commit is contained in:
Araq
2012-08-24 17:33:04 +02:00
parent afcff024a1
commit d17caa86e8
15 changed files with 44 additions and 22 deletions

View File

@@ -305,7 +305,7 @@ type
tyBigNum,
tyConst, tyMutable, tyVarargs,
tyIter, # unused
tyProxy # currently unused
tyProxy # used as errornous type (for idetools)
tyTypeClass,
const
@@ -328,10 +328,11 @@ type
nfSem # node has been checked for semantics
TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 15 for efficiency reasons (now: 13)
TTypeFlag* = enum # keep below 15 for efficiency reasons (now: 14)
tfVarargs, # procedure has C styled varargs
tfNoSideEffect, # procedure type does not allow side effects
tfFinal, # is the object final?
tfInheritable, # is the object inheritable?
tfAcyclic, # type is acyclic (for GC optimization)
tfEnumHasHoles, # enum cannot be mapped into a range
tfShallow, # type can be shallow copied on assignment

View File

@@ -57,6 +57,7 @@ proc InitDefines*() =
DefineSymbol("nimrod") # 'nimrod' is always defined
# for bootstrapping purposes and old code:
DefineSymbol("nimhygiene")
DefineSymbol("niminheritable")
# add platform specific symbols:
case targetCPU

View File

@@ -48,7 +48,7 @@ const
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern, wShallow,
wImportcpp, wImportobjc, wError, wIncompleteStruct, wByCopy, wByRef,
wGenSym, wInject}
wInheritable, wGenSym, wInject}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportcpp, wImportobjc, wError}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@@ -584,7 +584,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
noVal(it)
if sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfFinal)
of wAcyclic:
of wInheritable:
noVal(it)
if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it)
else: incl(sym.typ.flags, tfInheritable)
of wAcyclic:
noVal(it)
if sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfAcyclic)

View File

@@ -545,6 +545,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
var s = newSymS(skType, newIdentNode(getIdent("dummy"), n.info), c)
s.typ = result
pragma(c, s, n.sons[0], typePragmas)
if base == nil and tfInheritable notin result.flags:
incl(result.flags, tfFinal)
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
if kind == skMacro and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:

View File

@@ -970,9 +970,10 @@ in future versions of the compiler.
person = ("Peter", 30)
The implementation aligns the fields for best access performance. The alignment
is compatible with the way the C compiler does it. For consistency
with ``object`` declarations, tuples in a ``type`` section can also be defined
with indentation instead of ``[]``:
is compatible with the way the C compiler does it.
For consistency with ``object`` declarations, tuples in a ``type`` section
can also be defined with indentation instead of ``[]``:
.. code-block:: nimrod
@@ -988,7 +989,7 @@ the ``of`` operator can be used to determine the object's type.
.. code-block:: nimrod
type
TPerson = object
TPerson {.inheritable.} = object
name*: string # the * means that `name` is accessible from other modules
age: int # no * means that the field is hidden
@@ -1002,7 +1003,9 @@ the ``of`` operator can be used to determine the object's type.
Object fields that should be visible from outside the defining module, have to
be marked by ``*``. In contrast to tuples, different object types are
never *equivalent*.
never *equivalent*. Objects that have no ancestor are implicitely ``final``
and thus have no hidden type field. One can use the ``inheritable`` pragma to
introduce new object roots apart from ``system.TObject``.
Object variants

View File

@@ -74,7 +74,11 @@ section.
Inheritance is done with the ``object of`` syntax. Multiple inheritance is
currently not supported. If an object type has no suitable ancestor, ``TObject``
can be used as its ancestor, but this is only a convention.
can be used as its ancestor, but this is only a convention. Objects that have
no ancestor are implicitely ``final``. You can use the ``inheritable`` pragma
to introduce new object roots apart from ``system.TObject``. (This is used
in the GTK wrapper for instance.)
**Note**: Composition (*has-a* relation) is often preferable to inheritance
(*is-a* relation) for simple code reuse. Since objects are value types in

View File

@@ -1057,7 +1057,7 @@ type
charset: set[char] ## if kind == tkCharSet
index: int ## if kind == tkBackref
TPegLexer = object ## the lexer object.
TPegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself
LineNumber: int ## the current line number

View File

@@ -58,7 +58,7 @@ type
Features: seq[Feature] # Read-Only
PNode* = ref Node
Node = object
Node = object of TObject
attributes*: seq[PAttr]
childNodes*: seq[PNode]
FLocalName: string # Read-only

View File

@@ -171,9 +171,12 @@ proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
result = value >= s.a and value <= s.b
when not defined(niminheritable):
{.pragma: inheritable.}
when not defined(EcmaScript) and not defined(NimrodVM):
type
TGenericSeq {.compilerproc, pure.} = object
TGenericSeq {.compilerproc, pure, inheritable.} = object
len, reserved: int
PGenericSeq {.exportc.} = ptr TGenericSeq
# len and space without counting the terminating zero:
@@ -197,7 +200,7 @@ type
## is an int type ranging from one to the maximum value
## of an int. This type is often useful for documentation and debugging.
TObject* {.exportc: "TNimObject".} =
TObject* {.exportc: "TNimObject", inheritable.} =
object ## the root of Nimrod's object hierarchy. Objects should
## inherit from TObject or one of its descendants. However,
## objects that have no ancestor are allowed.

View File

@@ -113,7 +113,7 @@ type
PChunk = ptr TBaseChunk
PBigChunk = ptr TBigChunk
PSmallChunk = ptr TSmallChunk
TBaseChunk {.pure.} = object
TBaseChunk {.pure, inheritable.} = object
prevSize: int # size of previous chunk; for coalescing
size: int # if < PageSize it is a small chunk
used: bool # later will be optimized into prevSize...

View File

@@ -107,7 +107,7 @@ type
g_class*: PGTypeClass
PGTypeInterface* = ptr TGTypeInterface
TGTypeInterface*{.pure.} = object
TGTypeInterface*{.pure, inheritable.} = object
g_type*: GType
g_instance_type*: GType
@@ -993,7 +993,7 @@ proc plugin_complete_interface_info*(plugin: PGTypePlugin,
dynlib: gliblib, importc: "g_type_plugin_complete_interface_info".}
type
PGObject* = ptr TGObject
TGObject*{.pure.} = object
TGObject*{.pure, inheritable.} = object
g_type_instance*: TGTypeInstance
ref_count*: guint
qdata*: PGData
@@ -1006,7 +1006,7 @@ type
TGWeakNotify* = proc (data: gpointer, where_the_object_was: PGObject){.cdecl.}
PGObjectConstructParam* = ptr TGObjectConstructParam
PGObjectClass* = ptr TGObjectClass
TGObjectClass*{.pure.} = object
TGObjectClass*{.pure, inheritable.} = object
g_type_class*: TGTypeClass
construct_properties*: PGSList
constructor*: proc (theType: GType, n_construct_properties: guint,

View File

@@ -341,7 +341,7 @@ type
float*: float64
imag*: float64
TPyObject*{.pure.} = object
TPyObject*{.pure, inheritable.} = object
ob_refcnt*: int
ob_type*: PPyTypeObject

View File

@@ -1052,7 +1052,7 @@ type
charset: set[char] ## if kind == tkCharSet
index: int ## if kind == tkBackref
TPegLexer = object ## the lexer object.
TPegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself
LineNumber: int ## the current line number

View File

@@ -1,13 +1,14 @@
version 0.9.0
=============
- ``final`` should be the default for objects
- implement "closure tuple consists of a single 'ref'" optimization
- implement for loop transformation for first class iterators
- implicit deref for parameter matching
- optimize genericAssign in the code generator
- the lookup rules for generics really are too permissive
- the lookup rules for generics really are too permissive; global scope only
doesn't fly with closures though; for a start add a warning when processing
generic code
- fix remaining closure bugs:
- test evals.nim with closures
- what about macros with closures?

View File

@@ -108,6 +108,9 @@ Changes affecting backwards compatibility
- The Nimrod type system now distinguishes ``openarray`` from ``varargs``.
- Templates are now ``hygienic``. Use the ``dirty`` pragma to get the old
behaviour.
- Objects that have no ancestor are now implicitely ``final``. Use
the ``inheritable`` pragma to introduce new object roots apart
from ``TObject``.
Compiler Additions