Эмуляция объектов на скриптах. Добавлено наследование классов.
Реализация:
Object.ms.dict
Тест:
Object.ms.script
Запись Object2 class Object3 - описывает Object3 наследующийся от Object2.
Реализация:
Object.ms.dict
UNIT Object.ms.dict
USES
 Bind.ms.dict
;
EXPORTS
 Bind.ms.dict
USES
 core.ms.dict
 macro.ms.dict
 NoCapsLock.ms.dict
 implementation.ms.dict
 params.ms.dict
 axiom_push.ms.dict
 Documentation.ms.dict
 WordsRTTI.ms.dict
 arrays.ms.dict
 io.ms.dict
 Debug.ms.dict
 CompileTimeVar.ms.dict
;
EXPORTS
 CompileTimeVar.ms.dict
EXPORTS
 implementation.ms.dict
USES
 InheritsAndImplementsNew.ms.dict
;
EXPORTS
 InheritsAndImplementsNew.ms.dict
WordAlias Log .
WordAlias %R .Implemented.Words
WordAlias %G .Inherited.Words
OBJECT FUNCTION DoMember 
 OBJECT IN aMember
 aMember DO >>> Result
; // DoMember
BOOLEAN FUNCTION FilterMember 
 OBJECT IN aMember
 Result := ( aMember NotValid ! )
; // FilterMember
 
ARRAY FUNCTION %ClassRTTIList
 IN %S
 Literal IN aName
 VAR l_List
 %S %% ( aName |N ) >>> l_List
 if ( l_List NotValid ) then
  ( Result := [] )
 else 
  ( Result := ( l_List CodeIterator ) )
; // %ClassRTTIList
ARRAY CompileTime-VAR g_MetaListPoducerNames []
 %REMARK 'Список содержащий пары (имя списка, указатель на массив)'
CONST cMetaListPoducerNamesElementSize 2
ARRAY FUNCTION MetaListPoducerIt
 g_MetaListPoducerNames .slice> cMetaListPoducerNamesElementSize >>> Result
; // MetaListPoducerIt
CONST cMetaListPrefix '%'
ARRAY FUNCTION MapToName
 ARRAY IN aArray
 aArray .map> |N >>> Result
; // MapToName
CONST cResult 'Result'
CONST cSelf 'Self'
MACRO DefineMetaList
  Literal IN aWordName
  Literal IN aDoc
 %SUMMARY 'Определяет список мета-информации к элементу. И итератор к нему' ;
 STRING VAR l_WordName
 aWordName |N >>> l_WordName
 [ cMetaListPrefix l_WordName ] strings:Cat >>> l_WordName
 STRING VAR l_ListName
 [ '.' l_WordName '.It' ] strings:Cat >>> l_ListName
 l_WordName array:AddTo g_MetaListPoducerNames
 STRING VAR l_ListForValues
 [ 'g_' l_WordName ] strings:Cat >>> l_ListForValues
 axiom:PushSymbol ARRAY
 axiom:PushSymbol CompileTime-VAR
 axiom:PushStringAsSymbol l_ListForValues
 axiom:PushSymbol []
 axiom:PushSymbol [EXECUTE]
 axiom:PushSymbol (
 axiom:PushSymbol @
 axiom:PushStringAsSymbol l_ListForValues
 axiom:PushSymbol array:AddTo 
 axiom:PushSymbol g_MetaListPoducerNames
 axiom:PushSymbol )
 axiom:PushSymbol NamedWordProducer
 [ 
  l_WordName
  l_ListName 
 ] Ctx:Parser:PushArray
 axiom:PushSymbol ARRAY
 axiom:PushSymbol FUNCTION
 axiom:PushStringAsSymbol l_ListName
 axiom:PushSymbol TtfwWord
 axiom:PushSymbol IN
 axiom:PushStringAsSymbol cSelf
 axiom:PushSymbol %SUMMARY
 aDoc |N Ctx:Parser:PushString
 axiom:PushSymbol ; 
 axiom:PushStringAsSymbol cSelf
 axiom:PushSymbol %ClassRTTIList
 axiom:PushStringAsSymbol l_ListName 
 axiom:PushSymbol MapToName
 axiom:PushSymbol >>>
 axiom:PushStringAsSymbol cResult
 axiom:PushSymbol ; 
; // DefineMetaList
  PROCEDURE MakeAlias
    STRING IN aProp
    ^ IN aLambda
   axiom:PushSymbol WordAlias
   aProp aLambda DO
  ; // MakeAlias
DefineMetaList Properties 'Свойства класса'
DefineMetaList Methods 'Методы класса'
DefineMetaList MetaMethods 'Методы мета-класса'
DefineMetaList Constructors 'Конструкторы класса'
: CompileSetWordProducerForCompiledClass
  TtfwWord IN aWord
 aWord
 axiom:PushImmediateSymbol Ctx:SetWordProducerForCompiledClass
; // CompileSetWordProducerForCompiledClass
STACK_CHANGING_MACRO class_impl
  Literal IN aName
 %SUMMARY 'Реализация класса.
 Тут мы будем хранить всю информацию о классе - предки, поля, методы'
 ;
 @SELF CompileSetWordProducerForCompiledClass
 axiom:PushSymbol : 
 aName |N Ctx:Parser:PushSymbol
; // class_impl
STRING CompileTime-VAR g_CurrentClass ''
BOOLEAN CompileTime-VAR g_InstanceSizeDefined false
BOOLEAN CompileTime-VAR g_ConstructorsCopied false
TtfwWord type ObjectClass
ObjectClass CompileTime-VAR g_CurrentClassImpl nil
ObjectClass CompileTime-VAR g_CurrentClassParent nil
CONST cMetaPrefix 'c:'
CONST cFieldPrefix 'Offset:'
STRING FUNCTION FieldPrefix
 [ cMetaPrefix cFieldPrefix ] strings:Cat >>> Result
; // FieldPrefix
PRIVATE STRING operator MakeFieldOffsetName
  STRING IN aName
 %SUMMARY 'Делает имя для доступа к полю' ; 
 [ FieldPrefix aName ] strings:Cat >>> Result
; // MakeFieldOffsetName
INTEGER type FieldOffset
// - смещение поля
FieldOffset CompileTime-VAR g_ClassFieldOffset 0
VOID operator define_member
  STRING IN aName
  FieldOffset IN aOffset
 axiom:PushSymbol implementation
 g_CurrentClassImpl pop:Word:Name Ctx:Parser:PushSymbol
 axiom:PushSymbol Const
 aName MakeFieldOffsetName Ctx:Parser:PushSymbol
 aOffset Ctx:Parser:PushInt
 axiom:PushSymbol end.
; // define_member
MACRO member
  Literal IN aName
  STRING VAR l_Name
 %SUMMARY 'Определяет член текущего класса' ;
 g_InstanceSizeDefined ?FAIL [ 'Класс ' g_CurrentClass ' уже определён. Нельзя доопределять его члены.' ]
 aName |N >>> l_Name
 Ctx:ClearTypeInfo
 l_Name g_ClassFieldOffset define_member
 Inc g_ClassFieldOffset
; // member
PRIVATE STRING operator MakeMethodSignaturePrim
 STRING IN aClass
 STRING IN aName
 [ aClass ':' aName ] strings:Cat >>> Result
; // MakeMethodSignaturePrim
CONST cClassImplPrefix '_:'
STRING FUNCTION ClassImplName
  STRING IN aName
 [ cClassImplPrefix aName ] strings:Cat >>> Result
; // ClassImplName
Const ClassRefSuffix 'Class'
STRING FUNCTION ClassRefName
  STRING IN aName
 [ aName ClassRefSuffix ] strings:Cat >>> Result
; // ClassRefName
STRING CompileTime-VAR g_CurrentClassMethod ''
STRING CompileTime-VAR g_CurrentClassMethodModifiers ''
PRIVATE VOID operator MakeMethodSignature
 STRING IN aName
 STRING VAR l_Signature
 g_CurrentClass aName MakeMethodSignaturePrim >>> l_Signature
 if ( l_Signature IsWordDeclared ) then
 begin
  axiom:PushSymbol REDEFINITION
 end
 axiom:PushSymbol :
 axiom:PushStringAsSymbol l_Signature
; // MakeMethodSignature
PRIVATE VOID operator MakeSelfParam
 axiom:PushStringAsSymbol g_CurrentClass
 axiom:PushSymbol in
 axiom:PushStringAsSymbol cSelf
; // MakeSelfParam
MACRO method
  Literal IN aName
  ^ IN aParams
 %SUMMARY 'Метод объекта' ;
 STRING VAR l_Name
 aName |N >>> l_Name
 l_Name @SELF bindInPlace
 
 l_Name MakeMethodSignature
 MakeSelfParam
 @SELF NameOf right aParams axiom:Params:PushWithOtherStereo
 l_Name array:?AddTo g_%Methods
; // method
MACRO readonly
  Literal IN aName
 %SUMMARY 'read-only свойство объекта' ;
 STRING VAR l_Name
 aName |N >>> l_Name
 l_Name @SELF bindInPlace
 l_Name MakeMethodSignature
 MakeSelfParam
 l_Name array:?AddTo g_%Properties
; // readonly
STACK_CHANGING_MACRO class_method
  Literal IN aName
  
 %SUMMARY 'Метод класса' ;
 g_CurrentClassMethod '' == ?ASSURE 'Вложенные методы класса пока не поддерживаются'
 TtfwWordInfo VAR l_WordInfo
 Ctx:WordInfo >>> l_WordInfo
 STRING VAR l_TypeInfo
 l_WordInfo pop:WordInfo:TypeName >>> g_CurrentClassMethodModifiers
 STRING VAR l_Name
 aName |N >>> l_Name
 l_Name >>> g_CurrentClassMethod
 l_Name bindAndRestoreContext
 @SELF CompileSetWordProducerForCompiledClass
 axiom:PushSymbol :
 STRING VAR l_ClassName
 g_CurrentClass >>> l_ClassName
 
 l_ClassName ClassRefName >>> l_ClassName
 STRING VAR l_ClassMethodName
 
 l_ClassName l_Name MakeMethodSignaturePrim >>> l_ClassMethodName
 axiom:PushStringAsSymbol l_ClassMethodName
 axiom:PushStringAsSymbol l_ClassName
 axiom:PushSymbol in
 axiom:PushStringAsSymbol cSelf
 l_Name array:?AddTo g_%MetaMethods
; // class_method
CONST cObjectName 'Object'
CONST cInstanceSizeName 'Instance:Size'
STRING FUNCTION InstanceSizeName
 [ cMetaPrefix cInstanceSizeName ] strings:Cat >>> Result
; // InstanceSizeName
CONST cClassParentName 'Class:Parent'
STRING FUNCTION ClassParentName
 [ cMetaPrefix cClassParentName ] strings:Cat >>> Result
; // ClassParentName
CONST cClassTypePrefix 'ClassOf::'
STRING FUNCTION ClassOfName
  STRING IN aClassName
 [ cClassTypePrefix aClassName ] strings:Cat >>> Result
; // ClassOfName
MACRO ClassOf
  Literal IN aName
 STRING VAR l_ClassName
 aName |N ClassOfName >>> l_ClassName
 l_ClassName IsWordDeclared ?ASSURE [ 'Класс ' l_ClassName ' не определён' ]
 axiom:PushStringAsSymbol l_ClassName
; // ClassOf
PROCEDURE ClearMetaLists
 MetaListPoducerIt .for> ( 
   STRING IN aName 
   TtfwWord IN aVar
  [] aVar pop:Word:SetValue
 ) // MetaListPoducerIt .for>
; // ClearMetaLists
PROCEDURE ClearClassInfo
 g_CurrentClass := ''
 g_CurrentClassImpl := nil
 g_CurrentClassParent := nil
 g_InstanceSizeDefined := false
 g_ConstructorsCopied := false
 g_ClassFieldOffset := 0 
 ClearMetaLists
; // ClearClassInfo
MACRO class
 Literal IN aName
 ( g_CurrentClass = '' ) ?ASSURE 'Вложенные классы пока не поддерживаются'
 TtfwWordInfo VAR l_WordInfo
 Ctx:WordInfo >>> l_WordInfo
 Ctx:ClearTypeInfo
 ClearClassInfo
 aName |N >>> g_CurrentClass
 STRING VAR l_TypeInfo
 l_WordInfo pop:WordInfo:TypeName >>> l_TypeInfo
 STRING VAR l_CurrentClassParentName
 if ( l_TypeInfo <> '' ) then
 begin
  l_TypeInfo 'ARRAY' == ?FAIL [ 'Множественное наследование пока не поддерживается. Класс: ' g_CurrentClass ' Заявленные предки ' l_TypeInfo ]
  l_TypeInfo ' ' string:Pos -1 == ?ASSURE [ 'Множественное наследование пока не поддерживается. Класс: ' g_CurrentClass ' Заявленные предки ' l_TypeInfo ]
  l_TypeInfo >>> l_CurrentClassParentName
 end
 else
 begin
  cObjectName >>> l_CurrentClassParentName
 end
 STRING VAR l_CurrentClassImpl
 g_CurrentClass ClassImplName >>> l_CurrentClassImpl
 STRING VAR l_ClassRefName
 g_CurrentClass ClassRefName >>> l_ClassRefName
 if ( g_CurrentClass !== cObjectName ) then
 begin
  axiom:PushImmediateSymbol (
  l_CurrentClassParentName ClassOfName Ctx:Parser:PushSymbol 
  axiom:PushSymbol >>> 
  axiom:PushSymbol g_CurrentClassParent
  axiom:PushSymbol )
  axiom:PushSymbol ObjectClass
  axiom:PushSymbol type
  axiom:PushStringAsSymbol l_ClassRefName
 end // g_CurrentClass !== cObjectName
 axiom:PushStringAsSymbol l_ClassRefName
 axiom:PushSymbol class_impl
 axiom:PushStringAsSymbol l_CurrentClassImpl
 if ( g_CurrentClass !== cObjectName ) then
 begin
  axiom:PushSymbol %INHERITS
  axiom:PushSymbol @
  l_CurrentClassParentName ClassImplName Ctx:Parser:PushSymbol
  axiom:PushSymbol ;
 end
 axiom:PushSymbol @SELF
 axiom:PushSymbol >>>
 axiom:PushStringAsSymbol cResult
 axiom:PushSymbol FieldOffset
 axiom:PushSymbol CompileTime-VAR
 axiom:PushStringAsSymbol InstanceSizeName
 0 Ctx:Parser:PushInt
 axiom:PushSymbol ObjectClass
 axiom:PushSymbol CompileTime-VAR
 axiom:PushStringAsSymbol ClassParentName
 axiom:PushSymbol g_CurrentClassParent
 axiom:PushSymbol ;
 axiom:PushImmediateSymbol (
 axiom:PushStringAsSymbol l_CurrentClassImpl
 axiom:PushSymbol >>>
 axiom:PushSymbol g_CurrentClassImpl
 axiom:PushSymbol )
 axiom:PushSymbol array
 axiom:PushSymbol type
 axiom:PushStringAsSymbol g_CurrentClass
 axiom:PushSymbol WordAlias
 g_CurrentClass ClassOfName Ctx:Parser:PushSymbol
 axiom:PushStringAsSymbol l_CurrentClassImpl
 if ( g_CurrentClass !== cObjectName ) then
 begin
  axiom:PushStringAsSymbol 'classExpander'
  axiom:PushStringAsSymbol l_CurrentClassImpl
 end
; // class
class Object
ObjectClass member VMT
//STRING member Fake
//INTEGER member Fake1
: FieldByOffset
 Object in Self
 FieldOffset right anOffset
 anOffset Self [i]
; // FieldByOffset
PRIVATE operator do_get_member
  STRING IN aName
 
 %SUMMARY 'Определяет способ доступа к члену класса' ;
 axiom:PushSymbol FieldByOffset
 axiom:PushSymbol (
 g_CurrentClass ClassImplName Ctx:Parser:PushSymbol
 axiom:PushSymbol ::
 aName MakeFieldOffsetName Ctx:Parser:PushSymbol 
 axiom:PushSymbol )
; // do_get_member
MACRO read
 Literal IN aName
 axiom:PushStringAsSymbol cSelf
 aName |N do_get_member
 axiom:PushSymbol >>>
 axiom:PushStringAsSymbol cResult
 axiom:PushSymbol ;
; // read
ObjectClass readonly class read VMT
MACRO class_method_end
 axiom:PushSymbol ;
 g_CurrentClassMethodModifiers axiom:PushWordInfo
 axiom:PushSymbol readonly
 axiom:PushStringAsSymbol g_CurrentClassMethod
 axiom:PushStringAsSymbol cSelf
 axiom:PushStringAsSymbol '.class'
 [ '.' g_CurrentClassMethod ] strings:Cat Ctx:Parser:PushSymbol
 if ( g_CurrentClassMethodModifiers IsNil ! ) then
 begin 
  axiom:PushSymbol >>> 
  axiom:PushStringAsSymbol cResult
 end // g_CurrentClassMethodModifiers IsNil !
 axiom:PushSymbol ;
 '' >>> g_CurrentClassMethod
 '' >>> g_CurrentClassMethodModifiers
; // class_method_end
STRING class_method ClassName
 %SUMMARY 'Возвращает имя класса' ;
 Self |N ':' string:Split >>> Result DROP
class_method_end // ClassName
FieldOffset class_method FieldOffset
  // - этод метод можно сделать КОМПИЛИРУЕМЫМ
  Literal IN aFieldName
 
 %SUMMARY 'Вычисляет смещение поля класса' ;
 STRING VAR l_FieldName
 aFieldName |N >>> l_FieldName
 l_FieldName MakeFieldOffsetName >>> l_FieldName
 TtfwWord VAR l_FieldVAR
 Self %% l_FieldName >>> l_FieldVAR
 l_FieldVAR IsNil ?FAIL [ 'Поле ' l_FieldName ' на классе ' Self .ClassName ' не определено' ]
 l_FieldVAR DO >>> Result
class_method_end // FieldOffset
INTEGER class_method InstanceSize
 %SUMMARY 'Возвращает размер экземпляров класса' ;
 Self %% InstanceSizeName DO >>> Result
class_method_end // InstanceSize
ObjectClass class_method ClassParent
 %SUMMARY 'Возвращает родительский класс' ;
 Self %% ClassParentName DO >>> Result
class_method_end // ClassParent
STRING class_method ClassParentName
  %SUMMARY 'Возвращает имя родительского класса' ;
 ObjectClass VAR l_ClassParent
 Self %% ClassParentName DO >>> l_ClassParent
 if ( l_ClassParent IsNil ) then
 begin
  '<base>' >>> Result
 end
 else
 begin
  l_ClassParent .ClassName >>> Result
 end
class_method_end // ClassParentName
class_method Print
 %SUMMARY 'Печатает класс' ;
 if ( Self IsNil ) then
 begin
  '<base>' .
 end
 else
 begin
  Self .ClassName Print
 end
class_method_end // Print
CONST cDefConstructorName 'new'
PROCEDURE DefineInstanceSize
 %SUMMARY 'Определяем размер экземпляров класса' ;
 if ( g_InstanceSizeDefined ! ) then
 begin
  g_InstanceSizeDefined := true
  TtfwWord VAR l_InstanceSizeVAR
  g_CurrentClassImpl %% InstanceSizeName >>> l_InstanceSizeVAR
  l_InstanceSizeVAR IsNil ?FAIL [ 'Переменная для размера класса ' g_CurrentClass ' почему-то не определена' ]
  l_InstanceSizeVAR DO =0 ?ASSURE [ 'Размер класса ' g_CurrentClass ' почему-то уже определён' ]
  g_ClassFieldOffset l_InstanceSizeVAR pop:Word:SetValue
 end // g_InstanceSizeDefined !
; // DefineInstanceSize
FORWARD CopyConstructors
STACK_CHANGING_MACRO constructor
  Literal IN aName
  ^ IN aParams
 %SUMMARY 'Конструктор объектов';
 STRING VAR l_Name
 aName |N >>> l_Name
 DefineInstanceSize
 // - тут определяем размер экземпляров класса
 if ( l_Name <> cDefConstructorName ) then
 begin
  if ( g_ConstructorsCopied ! ) then
  begin
   l_Name Log
   CopyConstructors
  end // g_ConstructorsCopied !
 end // l_Name <> cDefConstructorName
 else
 begin
  g_ConstructorsCopied := true
 end // l_Name <> cDefConstructorName
 g_CurrentClass l_Name MakeMethodSignaturePrim Log
 @SELF CompileSetWordProducerForCompiledClass
 axiom:PushStringAsSymbol g_CurrentClass
 l_Name MakeMethodSignature
 @SELF NameOf right aParams axiom:Params:PushWithOtherStereo
 axiom:PushSymbol WordAlias
 axiom:PushStringAsSymbol cSelf
 axiom:PushStringAsSymbol cResult
 l_Name array:?AddTo g_%Constructors
; // constructor
PROCEDURE def_constructor_do
 axiom:PushSymbol constructor
 axiom:PushStringAsSymbol cDefConstructorName
 axiom:PushSymbol ()
; // def_constructor_do
MACRO def_constructor
 def_constructor_do
; // def_constructor
PROCEDURE def_constructor_empty_do
 def_constructor_do
 axiom:PushStringAsSymbol 'new['
 axiom:PushSymbol ] 
 axiom:PushSymbol >>> 
 axiom:PushStringAsSymbol cResult
 axiom:PushSymbol ;
; // def_constructor_empty_do
MACRO def_constructor_empty
 def_constructor_empty_do
; // def_constructor_empty
PROCEDURE CopyConstructors
 DefineInstanceSize
 if ( g_ConstructorsCopied ! ) then
 begin
  if ( g_CurrentClass !== cObjectName ) then
  begin
   g_CurrentClassImpl IsNil ?FAIL [ 'Нет текущего определяемого класса. Возможное имя класса ' g_CurrentClass ]
   g_ConstructorsCopied := true
   g_CurrentClassImpl %G .for> (
    ObjectClass IN anItem
    anItem .%Constructors.It .for> ( 
     STRING IN aProp
     if ( aProp = cDefConstructorName ) then
     begin
      def_constructor_empty_do
     end
    ) // anItem .%Constructors.It .for>
   ) // anImpl %G .for>
  end // ( g_CurrentClass !== cObjectName ) 
 end // ( g_ConstructorsCopied ! )
; // CopyConstructors
MACRO classExpander
  ^ IN anImpl
 ObjectClass VAR l_Impl 
 anImpl |@ >>> l_Impl
 %SUMMARY 'Тут можно копировать поля и методы' ;
 l_Impl %G .for> ( 
  ObjectClass IN anItem
  anItem MembersIterator
   .filter> ( pop:Word:Producer pop:Word:Name NameOf CONST == )
   .filter> ( pop:Word:Name FieldPrefix SWAP StartsStr )  
   .for> 
  ( 
   TtfwWord IN aMember
   STRING VAR l_MemberName
   [ aMember pop:Word:Name FieldPrefix '' string:ReplaceFirst ] strings:Cat >>> l_MemberName
   FieldOffset VAR l_ClassFieldOffset
   aMember DO >>> l_ClassFieldOffset
   l_MemberName l_ClassFieldOffset define_member
   if ( l_ClassFieldOffset >= g_ClassFieldOffset ) then
   // - тут исправляем "кривизну" с сортировкой
   begin
    g_ClassFieldOffset := l_ClassFieldOffset
    Inc g_ClassFieldOffset
   end
  ) // anItem MembersIterator
  PROCEDURE MakeAliasAndAdd
    STRING IN aProp
    ^ IN anArray
    ^ IN aLambda
   ARRAY VAR l_Array
   anArray DO >>> l_Array
  
   aProp array:?AddTo l_Array
  
   aProp MakeAlias ( aLambda DO )
  ; // MakeAliasAndAdd
  PROCEDURE PushMethodSignature
    STRING IN aClass
    STRING IN aName
   aClass aName MakeMethodSignaturePrim Ctx:Parser:PushSymbol
  ; // PushMethodSignature
  PROCEDURE PushMethodSignatureAlias
   STRING IN aProp 
   g_CurrentClass aProp PushMethodSignature
   anItem .ClassName aProp PushMethodSignature
  ; // PushMethodSignatureAlias
  PROCEDURE .for.MakeAliasAndAdd>
   ARRAY IN aArray
   ^ IN anRArray
   ^ IN aLambda
   aArray .for> MakeAliasAndAdd ( anRArray DO ) ( aLambda DO )
  ; // .for.MakeAliasAndAdd>
  anItem .%Properties.It .for.MakeAliasAndAdd> g_%Properties PushMethodSignatureAlias
  anItem .%Methods.It .for.MakeAliasAndAdd> g_%Methods PushMethodSignatureAlias 
  anItem .%MetaMethods.It .for.MakeAliasAndAdd> g_%MetaMethods ( 
   STRING IN aProp
   g_CurrentClass ClassRefName aProp PushMethodSignature
   anItem .ClassName ClassRefName aProp PushMethodSignature
  )
 ) // l_Impl %G .for>
; // classExpander
: ListToNameAsString
  STRING IN aName
  ARRAY IN aList
 %SUMMARY 'Выводит элементы массива как строки в список метаинформации aName' ;
 //aList DO >>> l_List
 //ARRAY VAR l_List
 aName
 %REMARK 'Открываем список'
  aList .for> NameAsString
 ';'
 %REMARK 'Закрываем список'
; // ListToNameAsString
PROCEDURE FinishClassDefinition
 axiom:PushSymbol implementation
 g_CurrentClassImpl pop:Word:Name Ctx:Parser:PushSymbol
 [
   MetaListPoducerIt .for> ( 
     STRING IN aName 
     TtfwWord IN aVar 
    aName aVar DO ListToNameAsString 
   ) // MetaListPoducerIt .for>
 ] Ctx:Parser:PushArray
 axiom:PushSymbol end.
 ClearClassInfo
; // FinishClassDefinition
MACRO class-end
 //DefineInstanceSize
 axiom:PushImmediateSymbol CopyConstructors
 axiom:PushImmediateSymbol FinishClassDefinition
; // class-end
MACRO new[
 INTEGER VAR l_InstanceSize
 ClassOf Object .InstanceSize >>> l_InstanceSize
 Dec l_InstanceSize
 //l_InstanceSize .
 axiom:PushSymbol [
 axiom:PushSymbol @
 g_CurrentClassImpl pop:Word:Name Ctx:Parser:PushSymbol
 
 l_InstanceSize LOOP ( 'uninited member' Ctx:Parser:PushString )
; // new[
def_constructor_empty
VIRTUAL STRING readonly ToPrintable
 Self ToPrintable >>> Result
 [ Self .ClassName ' : ' Result ] strings:Cat >>> Result
 //Self .ClassName >>> Result
; // ToPrintable
VIRTUAL void readonly Print
 Self .ToPrintable Print
; // Print
class-end // Object
Тест:
Object.ms.script
USES io.ms.dict Object.ms.dict Testing.ms.dict ; USES axiom:WordInfo ; Test&Dump ObjectTest ClassOf Object DumpElement ClassOf Object pop:Word:Name Print Object VAR l_Obj l_Obj := Object:new l_Obj .Print l_Obj .ClassName Print //@ l_Obj pop:Word:Info pop:WordInfo:ValueTypes Print //@ l_Obj pop:Word:Info pop:WordInfo:ValueTypes pop:ValueTypes:Name Print l_Obj .ClassName Print ClassOf Object pop:Word:Name Print '--------' Print l_Obj .InstanceSize Print ClassOf Object .FieldOffset VMT Print ClassOf Object .ClassParent Print ClassOf Object .ClassParent .Print ClassOf Object .ClassParentName Print ClassOf Object pop:Word:Name Print ClassOf Object pop:Word:Name Print l_Obj .class Print l_Obj .class .Print class Object1 //def_constructor_empty class-end // Object1 Object1 VAR l_Obj1 l_Obj1 := Object1:new l_Obj1 .Print l_Obj1 .ClassName Print '--------' Print l_Obj1 .InstanceSize Print ClassOf Object1 .FieldOffset VMT Print ClassOf Object1 .ClassParent Print ClassOf Object1 .ClassParent .Print ClassOf Object1 .ClassParentName Print l_Obj1 .class Print l_Obj1 .class .Print class Object2 INTEGER member FakeField INTEGER readonly FakeField read FakeField def_constructor //[EXECUTE] ( g_InstanceSizeDefined Msg ) new[ 256 ] >>> Result //Self .FieldOffset 'VMT' Msg ; // new class-end // Object2 Object2 VAR l_Obj2 l_Obj2 := Object2:new l_Obj2 .Print l_Obj2 .ClassName Print '--------' Print l_Obj2 .InstanceSize Print ClassOf Object2 .FieldOffset VMT Print ClassOf Object2 .FieldOffset FakeField Print ClassOf Object2 .ClassParent Print ClassOf Object2 .ClassParent .Print ClassOf Object2 .ClassParentName Print ClassOf Object2 .FieldOffset FakeField Print l_Obj2 .FakeField Print l_Obj2 .class Print l_Obj2 .class .Print //l_Obj2 .member FakeField Print Object2 class Object3 def_constructor new[ 257 ] >>> Result ; // new class-end // Object3 '--------' Print ClassOf Object3 Print ClassOf Object3 ObjectClass:ClassName Print ClassOf Object3 ObjectClass:ClassParent Print ClassOf Object3 ObjectClass:ClassParentName Print '--------' Print ClassOf Object3 .Print ClassOf Object3 .ClassName Print ClassOf Object3 .ClassParent Print ClassOf Object3 .ClassParentName Print Object3 VAR l_Obj3 l_Obj3 := Object3:new l_Obj3 .Print l_Obj3 .ClassName Print '--------' Print l_Obj3 .InstanceSize Print ClassOf Object3 .FieldOffset VMT Print ClassOf Object3 .FieldOffset FakeField Print ClassOf Object3 .ClassParent Print ClassOf Object3 .ClassParent .Print ClassOf Object3 .ClassParentName Print ClassOf Object3 .FieldOffset FakeField Print l_Obj3 .FakeField Print l_Obj3 .class Print l_Obj3 .class .Print class Object4 //def_constructor_empty class-end // Object4 Object4 VAR l_Obj4 l_Obj4 := Object4:new l_Obj4 .Print l_Obj4 .ClassName Print '--------' Print l_Obj4 .InstanceSize Print ClassOf Object4 .FieldOffset VMT Print ClassOf Object4 .ClassParent Print ClassOf Object4 .ClassParent .Print ClassOf Object4 .ClassParentName Print l_Obj4 .class Print l_Obj4 .class .Print ; // ObjectTest ObjectTest
Запись Object2 class Object3 - описывает Object3 наследующийся от Object2.
