среда, 28 октября 2015 г.

#1176. Эмуляция объектов на скриптах. Добавлено наследование классов. Только код

Эмуляция объектов на скриптах. Добавлено наследование классов.

Реализация:

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.

Комментариев нет:

Отправить комментарий