mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-18 18:47:16 +00:00
objects with no ancestor are not implicitely final
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -341,7 +341,7 @@ type
|
||||
float*: float64
|
||||
imag*: float64
|
||||
|
||||
TPyObject*{.pure.} = object
|
||||
TPyObject*{.pure, inheritable.} = object
|
||||
ob_refcnt*: int
|
||||
ob_type*: PPyTypeObject
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
5
todo.txt
5
todo.txt
@@ -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?
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user