Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет nancygold ([info]nancygold)
@ 2024-08-04 01:14:00

Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Настроение: accomplished

How my ECS implementation looks
Still a single macro. Although it does emit the stub getter and setter methods, which the runtime patches with the native code.
The macro looks simple, but implementing it in C/C++ will require many thousands of error-prone lines of code.
That is in addtion to all the table related code.
So ECS is anything but easy to implemnt properly (outside of the basic structure of arrays).

/*******************************************************************************

Column-oriented Struct (aka CLasSifier)

Usage:
  cls tname.parent(@ParentArgs)! @`prefix` @Params @Args
    :
    @Fields
    =
    @InitCode

!                      - Provide `.tname` method

@`prefix`              - Picks custom prefix for the database columns,
                         associated with this type. Default is `tname_`
                         Can be ``



@Params:               - Params to the cls
  \nocvt               - Dont init the `cls` column, which allows
                         converting the unknown `id` entities to this type
  \clearable           - Provides the No.cls_clear_tname method,
                         which clears all tables associated with this type

@Args:
  UpperCaseName        - Normal argument name, usable Fields values and Initcode
  lowerCaseName        - Creates a field and initalizes with that arg
  Name!Value           - Keyword argument with a default value

@Fields:
  name                 - Unitialized field, which defaults to No
  name!!Default        - Unitialized field, which defaults to Default
  name!Value           - Initialized field. Value could reference @Args
  'name'!Value         - Creates a column prefix_name, but doesn't generate
                         the cls.name method.
                         Symta's version of C++ private data fields

*******************************************************************************/
cls Name @Fs =
  OName Name
  NeedsTypePredicate Name(0:['!' &Name]) //wants a type predicate?
  Parent \id
  ParentArgs:
  Name(:['()' &Name @&ParentArgs])
  Name(:['.' &Name &Parent])
  Sink No
  case Parent:
    [`$` Part] =
      Sink = Part
      Parent = \id
      Name(:['.' &Name &Parent])
  Pfx "[Name]_" //part prefix
  case Fs [`@` &Pfx],@R: Fs = R //cls Name@UserPfx @Fs
  Params nocvt!0 clearable!0
  while 1:
    case Fs:
      [`\\` Param],@_ = Params.Param = 1
      [`\\` [`()` Param [@Args]]],@_ = Params.Param = Args
      Else = done
    Fs = Fs.tail
  Body:
  AFs: //auto initialized fields
  case Fs [@FsP [[`|` @L [`=` [] []] @R ]]]: Fs =: @FsP [`=` L.j [`|` @R]]
  case Fs [@FsP [`=` &AFs &Body]]: Fs = FsP
  case Fs [@FsP &Body<[`|` @_]]: Fs = FsP
  //normalize into [Name Value PrefixedName]
  // If Name is `_`, dont produce a database column, only a method
  AFs = AFs{['!' ['@' ['.' PN N]]] V =: N V PN
           ;['!' ['@' PN]] V =: _ V PN
           ;['!' ['!' N]] V =: N ['!' V] "[Pfx][N]"
           ;['!' N] V =: N V "[Pfx][N]"
           ; N =: N No "[Pfx][N]"}
  if NeedsTypePredicate: push [_ 1 Name] AFs //if Object.widget: ...
  //push [_ Name cls]  AFs
  FNs: //field names
  PFNs: //typenanme-prefixed field names
  KVs: //keyworded args default value
  As: //arguments
  FAs: //field arguments
  till Fs.end:
    KV No //keyword value
    case Fs [[`!` _] [`!` _]@_]+[[`!` _]]: Fs =: Fs.head No @Fs.tail
    case Fs [[`!` F] D @R]:
      KV =: D
      Fs =: F @R
    push KV KVs
    AN /Fs
    A AN.title
    push A As
    if AN.is_keyword:
      push AN FNs
      push A FAs
      PAN "[Pfx][AN]"
      Fs(:[`@` &PAN],@&Fs)
      push PAN PFNs
  FNs,FAs,As,KVs,PFNs [FNs FAs As KVs PFNs]{f}
  KAs [As KVs].zip{A,[D] =: ['!' A] D; A,_=:A}.j //args with keywords
  Fields: @[FNs PFNs].zip{?0,?1,No} @AFs.skip(?0><_){?0,?2,?1}
  ParentRig []
  ParentDel []
  Me \Me
  Id form: gid_ Me
  if Parent<>id:
    PR form: Me.$("rig_[Parent]") $@ParentArgs
    push PR ParentRig
    PD form: Me.$("del_[Parent]") 
    push PD ParentDel
  InitedAFs AFs.keep(?1(1:No+['!' V]=0))
  InitCls if Params.nocvt: form (Me = $init_cls_nocvt)
          else form (Me = $init_cls Name)
  Hdr1 form: `|` (cls_set_ Id cls Name)
                $@([PFNs FAs].zip{PFN,A = form: $rig PFN,A})
                $@(InitedAFs{N,V,PN = form: $rig PN,V})
  Hdr form: InitCls
            $@ParentRig
            $@([PFNs FAs].zip{PFN,A = form: $rig PFN,A})
            $@(InitedAFs{N,V,PN = form: $rig PN,V})
  Type form: type Name.Parent $@(KAs): = `|` $@Hdr Body
  Rig1 form: id.$("rig1_[Name]") $@(KAs) = $@Hdr1 Body Me
  Rig form: id.$("rig_[Name]") $@(KAs) = `|` $@Hdr Body Me
  IdS "Id".rand
  Del1F form: `|` (IdS Id) $@(Fields{FN,PFN,V = form: $"T_[PFN]_".del IdS})
  Del1 form: id.$("del1_[Name]") = Del1F
  //Del1 form: id.$("del1_[Name]") = $del $@(Fields{?1})
  Del form: id.$("del_[Name]") = `|` $$("del1_[Name]") $@ParentDel
  AsText form: Name.ser_ = "${[\Name] [Me.ub.t.as_text.drop^2]}"
  //`cls`-types don't have the `__` method
  //Instead they explicitly define accessors for the used fields.
  FAs:
  TblNos:
  for [FN PFN V] Fields:
    SetPrologue 0
    GetPrologue 0
    case V:
      ['!' X] =
        case X [['$' SE] @&X]: //user want 
          SetPrologue = SE
          case X [['$' GE] @&X]: GetPrologue = GE
          X = X.~
          V =: '!' X
        if X^is_constant:
          case X ['$' E]: X = E
          push PFN,X TblNos
          V = No
    FG case V: //field getter: replacing missing elements by the default value
        ['!' X] =
          case GetPrologue:
            ['=' [] PBody] =
              form: Name.FN = `|` PBody (gid_get_ $"T_[PFN]_" Me).@X
            Else = form: Name.FN = (gid_get_ $"T_[PFN]_" Me).@X
        Else = case GetPrologue:
                 ['=' [] PBody] =
                   form: Name.FN = `|` PBody (gid_get_ $"T_[PFN]_" Me)
                 Else = form: Name.FN = cls_get_stub_ Me $"T_[PFN]_"
    push FG FAs
    FSN "=[FN]"
    FS case V: //field setter: assigning default value removes the element
        ['!' V] =
          case SetPrologue:
            ['=' [Var] PBody] =
              form: Name.FSN Var =
                PBody
                if Var><V: ($"T_[PFN]_").del Id
                else gid_set_ $"T_[PFN]_" Me Var
            Else =
              form: Name.FSN ~V =
                if ~V><V: ($"T_[PFN]_").del Id
                else gid_set_ $"T_[PFN]_" Me ~V
        Else =
          case SetPrologue:
            ['=' [Var] PBody] =
              form: Name.FSN Var = `|` PBody (gid_set_ $"T_[PFN]_" Me Var)
            Else = form: Name.FSN ~V = cls_set_stub_ Me ~V $"T_[PFN]_"
    push FS FAs
  if got Sink:
    S form: Name.__ ~Method ~Args = |~Args.0 = $(\Me).Sink; ~Args.apply_method ~Method
    push S FAs
  AsType form: id.$("[Name]_") = ref_ (tag_ (_data Name)) Id
  SetCvt form: No.set_cls_cvt_ Name: ~Id => ref_ (tag_ (_data Name)) ~Id
  push AsType FAs
  push SetCvt FAs
  FTbls map [FN PFN V] Fields: //field tables
    form: $"T_[PFN]_" cls_tbl_ PFN
  SetNos map PFN,NoVal TblNos: //set default value for the tables
    form: $"T_[PFN]_".setNo NoVal
  Clearer:
  if Params.clearable:
    CTbls map [FN PFN V] Fields: form: $"T_[PFN]_".clear
    Clear form: no.$("cls_clear_[Name]") = `;` $@CTbls
    Clearer =: Clear
  form @(`|` $@FTbls $@SetNos Type Rig1 Rig Del1 Del AsText $@FAs $@Clearer)


(Читать комментарии)

Добавить комментарий:

Как:
Identity URL: 
имя пользователя:    
Вы должны предварительно войти в LiveJournal.com
 
E-mail для ответов: 
Вы сможете оставлять комментарии, даже если не введете e-mail.
Но вы не сможете получать уведомления об ответах на ваши комментарии!
Внимание: на указанный адрес будет выслано подтверждение.
Имя пользователя:
Пароль:
Тема:
HTML нельзя использовать в теме сообщения
Сообщение:



Обратите внимание! Этот пользователь включил опцию сохранения IP-адресов пишущих комментарии к его дневнику.