diff options
author | Araq <rumpf_a@web.de> | 2012-08-24 17:33:04 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-24 17:33:04 +0200 |
commit | d17caa86e841489d92165d9caa13c2d8bc86afd5 (patch) | |
tree | 9504e5dd71501887da52fbc1f0fd39294ef913ea | |
parent | afcff024a1ab335032aa8a98d844f6fbc701170e (diff) | |
download | Nim-d17caa86e841489d92165d9caa13c2d8bc86afd5.tar.gz |
objects with no ancestor are not implicitely final
-rwxr-xr-x | compiler/ast.nim | 5 | ||||
-rwxr-xr-x | compiler/condsyms.nim | 1 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 8 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 2 | ||||
-rwxr-xr-x | doc/manual.txt | 13 | ||||
-rwxr-xr-x | doc/tut2.txt | 6 | ||||
-rwxr-xr-x | lib/pure/pegs.nim | 2 | ||||
-rwxr-xr-x | lib/pure/xmldom.nim | 2 | ||||
-rwxr-xr-x | lib/system.nim | 7 | ||||
-rwxr-xr-x | lib/system/alloc.nim | 2 | ||||
-rwxr-xr-x | lib/wrappers/gtk/glib2.nim | 6 | ||||
-rwxr-xr-x | lib/wrappers/python.nim | 2 | ||||
-rwxr-xr-x | tests/run/tpegs.nim | 2 | ||||
-rwxr-xr-x | todo.txt | 5 | ||||
-rwxr-xr-x | web/news.txt | 3 |
15 files changed, 44 insertions, 22 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index bb78fcd57..ae8beace7 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index d273f5335..8c8d02612 100755 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -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 diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index cbdf63a1c..47abd0178 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index d05adab3b..5b6183005 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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}: diff --git a/doc/manual.txt b/doc/manual.txt index e0fee2a31..6fccd0ca3 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -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 diff --git a/doc/tut2.txt b/doc/tut2.txt index d897319fc..96507bcb1 100755 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -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 diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index e37c072f1..4e31ffc0c 100755 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -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 diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index 97cf3caeb..47e94243e 100755 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -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 diff --git a/lib/system.nim b/lib/system.nim index 01b85a4d6..b40f161f1 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -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. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 53c20316c..5182d5ccf 100755 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -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... diff --git a/lib/wrappers/gtk/glib2.nim b/lib/wrappers/gtk/glib2.nim index b69b708fe..4151ba954 100755 --- a/lib/wrappers/gtk/glib2.nim +++ b/lib/wrappers/gtk/glib2.nim @@ -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, diff --git a/lib/wrappers/python.nim b/lib/wrappers/python.nim index 3d0b923e2..3e6543765 100755 --- a/lib/wrappers/python.nim +++ b/lib/wrappers/python.nim @@ -341,7 +341,7 @@ type float*: float64 imag*: float64 - TPyObject*{.pure.} = object + TPyObject*{.pure, inheritable.} = object ob_refcnt*: int ob_type*: PPyTypeObject diff --git a/tests/run/tpegs.nim b/tests/run/tpegs.nim index 315833326..e64cd8fef 100755 --- a/tests/run/tpegs.nim +++ b/tests/run/tpegs.nim @@ -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 diff --git a/todo.txt b/todo.txt index c49e80980..58e3e067e 100755 --- a/todo.txt +++ b/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? diff --git a/web/news.txt b/web/news.txt index bbac003f1..f67e4d74b 100755 --- a/web/news.txt +++ b/web/news.txt @@ -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 |