OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Понедельник, 20 Август, 2018 06:02

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 54 ]  На страницу 1, 2, 3  След.
Автор Сообщение
 Заголовок сообщения: Активные структуры данных
СообщениеДобавлено: Понедельник, 05 Май, 2008 01:28 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
К уже поднимавшемуся вопросу об активных структурах данных.

Непейвода, Скопин Основания программирования, п. 13.4.1 писал(а):
Конечно, реализовывать аналитические вычисления можно самыми разнообразными способами. Можно упрятать реализацию всех нужных преобразований в каком-либо прикладном пакете (как это сделано, например, в Maple) и даже не заметить, что мы имеем дело с сентенциальными по сути своей задачами. Однако этот путь ведёт лишь к таким решениям, которые нужны "здесь и сейчас": программист, к примеру, не сможет подсказать программе символического дифференцирования, что она имеет дело с неким частным случаем, для которого можно резко сократить перебор вариантов. Когда требуется проводить подобные преобразования систематически, удобнее снабдить перерабатываемые данные дополнительными атрибутами, направляющими вычисления в нужное русло. Иными словами, полезно делать структурные единицы данных активными (выделение авторов - И.Е.). А это - привнесение в программу, обрабатывающую такие данные, элементов сентенциального стиля, пусть даже без использования подходящей языковой поддержки. Преимущества, которые при этом появляются, непосредственно следуют из того, что данный вид обработки является сентенциальным по своей сути, требующим адекватных средств реализации.


Сентенциальным стилем называется прогр-е в терминах "широких", "умных" трансформаций данных по правилам, типа Рефала или Пролога (хотя они совершенно непохожи по принципам и механизмам).

Интересно. Info21 пришёл к активным структурам в символьных задачах. Я с другого бока - от задач трансляции (как раз Рефал-транслятор на КП).

(Кстати, фанатам ФП повод поразмыслить, почему Оберон тут катит не хуже Хаскелей.... Природа задач-то тут не функциональная (это только кажется, что если слово "функция", так сразу на порядок "математичнее"), так что язык в данном случае только материал для реализации. Так что лучше ему быть проще, чтоб ненужными побочными эффектами не сбивал с генеральной линии...)

Прошу воспринимать как мысли вслух...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Понедельник, 05 Май, 2008 21:59 

Зарегистрирован: Воскресенье, 28 Май, 2006 22:12
Сообщения: 1328
МОжет я чего-то не уловил, но я так и не понял по цитированному фрАгменту, что подразумевалось под активностью структур данных?...
Мда...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Понедельник, 05 Май, 2008 22:08 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
То, что инициатива по тонкостям обработки частей сложных структур данных исходит от самих этих частей структур...
Данные "умные" и "вмешиваются", направляют процесс своей обработки.

То, что в банальном случае называют виртуализацией и реализуют через ООП. А оберонщики додумались через шину сообщений по структуре данных...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 01:04 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
То, что в банальном случае называют виртуализацией и реализуют через ООП. А оберонщики додумались через шину сообщений по структуре данных...


А можно примерчик с этими самыми сообщениями?

P.S. Помнится мы это уже обсуждали в контексте "виртуальность vs сообщения", но до кода дело так и не дошло. Я думаю конкретный пример был бы полезен в деле популяризации обероновской message bus, безотносительно нашего спора.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 01:19 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Вот пример с активным синтаксическим деревом транслятора Рефала-0.
RocotStructs - реализация общих древовидных выражений, т.е. списков, термы которых могут быть тоже списками (типа объектных выражений Рефала, в общем).
Соответственно, описаны разные типы узлов синтаксического дерева языка, в комментарии в теле RECORD - структура динамически размещаемых подузлов, если есть.

Пример, конечно, простенький. У Info21, как я понял из некоторых его рассказов, узлы нижних уровней могут отвечать на запросы верхних (типа, а знает ли функция точно свою производную и т.п.).

Код:
MODULE RocotRefal0Front;

(*
   Syntax specification in EBNF:

   Program   =   {   Function [ ";" ]   } .
   Function   =   FuncName  "{"   Sentence {   ";" Sentence   }   [";"]   "}" .
   Sentence   =   Pattern {"," Condition} "=" Expression .
   Pattern    =   [Template] [FreeVar] [Template] [FreeVar] [Template] .
   Template   =   (String | CharVar) {Template} .
   Condition   =   "<"FuncName (CharVar | FreeVar) ">"  ":"  ("T" OR "F") .
   Expression    =   (String | CharVar | FreeVar | FunctionCall) .
   FunctionCall   =   "<"FuncName Expression ">" .

   FuncName   =   LatinLetter {   LatinLetter | Digit | "_" | "-"   } .
   Identifier   =   { LatinLetter | Digit } .
   CharVar   =   "s"Identifier .
   FreeVar   =   "e"Identifier .
   String   =   "'"{ NormalChar | "\"SpecialChar | CharSig | CharCode | lineBreak } "'" .

   NormalChar   =   ~SpecialChar .
   SpecialChar   =   "\"   |   """   |   '"" .
   CharSig   =   "\n"   |   "\t" .
   CharCode   =   "\"Digit{Digit} .
*)

   IMPORT Structs := RocotStructs, Strings := RocotStrings, Text := RocotText, Log;

   TYPE
      Name* = ARRAY 256 OF CHAR;

      Program* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         (* SymTab { Function } *)
      END;

      Function* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         name*: Name;
         (* Sentence { Sentence } *)
      END;

      Sentence* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         (* SymTab Pattern { Condition } Expression *)
      END;

      Pattern* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         (* { Template | FreeVar } *)
      END;

      Condition* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         predicate*: Name;
         expect*: BOOLEAN
         (* VarRef *)
      END;

      Template* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         (* (Char | CharVar | VarRef) { Char | CharVar | VarRef } *)
      END;

      Char* = POINTER TO EXTENSIBLE RECORD (Structs.Term)
         c*: CHAR;
         encode*: BOOLEAN
      END;

      Variable* = POINTER TO ABSTRACT RECORD (Structs.Term)
         name*: Name
      END;

      FreeVar* = POINTER TO EXTENSIBLE RECORD (Variable) END;
 
      CharVar* = POINTER TO EXTENSIBLE RECORD (Variable) END;

      VarRef* = POINTER TO EXTENSIBLE RECORD (Structs.Term)
         var*: Variable
      END;

      Expression* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         traits*: SET
         (* { Char | VarRef | FuncCall } *)
      END;

      FuncCall* = POINTER TO EXTENSIBLE RECORD (Structs.Expr)
         funcName*: Name;
         (* Expression *)
      END;

      Message = ABSTRACT RECORD (Structs.Message) error: INTEGER END;
      NewFuncMsg = RECORD (Message) END;
      FuncNameMsg = RECORD (Message) name: Name END;
      NewSentMsg = RECORD (Message) END;
      BeginExprMsg = RECORD (Message) END;
      EndExprMsg = RECORD (Message) END;
      CharMsg = RECORD (Message) char: CHAR; encode: BOOLEAN END;
      VarMsg = ABSTRACT RECORD (Message) symTab: Structs.SymTab; name: Name END;
      CharVarMsg = RECORD (VarMsg) END;
      FreeVarMsg = RECORD (VarMsg) END;
      NewCondMsg = RECORD (Message) END;

(* ... опущены всякие вещи ... *)

   PROCEDURE (t: Template) HandleMsg* (VAR msg: Structs.Message);
      VAR c: Char;
            lastVar: ANYPTR;
            var: CharVar;
            ref: VarRef;
   BEGIN
      WITH msg: CharMsg DO
         NEW(c); c.c := msg.char; c.encode := msg.encode;
         t.Insert(c, t.last)      
      | msg: CharVarMsg DO
         lastVar := msg.symTab.Look(msg.name);
         IF ~ ((lastVar = NIL) OR (lastVar IS CharVar)) THEN
            msg.error := sameNameForDifVars
         ELSIF lastVar = NIL THEN
            NEW(var);
            var.name := msg.name$;
            msg.symTab.Add(msg.name, var);
            t.Insert(var, t.last)
         ELSE
            NEW(ref); ref.var := lastVar(Variable);
            t.Insert(ref, t.last)
         END
      ELSE END
   END HandleMsg;

   PROCEDURE (p: Pattern) HandleMsg* (VAR msg: Structs.Message);
      VAR tem: Template;
            lastVar: ANYPTR;
            var: FreeVar;
            ref: VarRef;
   BEGIN
      IF (msg IS CharMsg) OR (msg IS CharVarMsg) THEN
         IF (p.last = NIL) OR ~(p.last IS Template) THEN
            NEW(tem);
            p.Insert(tem, p.last)
         END;
         p.last(Template).HandleMsg(msg)
      END;
      WITH msg: FreeVarMsg DO
         lastVar := msg.symTab.Look(msg.name);
         IF (p.last # NIL) & (p.last IS FreeVar) THEN
            msg.error := unexpectedFreeVar
         ELSIF lastVar # NIL THEN
            IF lastVar IS FreeVar THEN
               msg.error := duplicatedFreeVar;
            ELSE
               msg.error := sameNameForDifVars
            END
         ELSE
            NEW(var); var.name := msg.name$;
            p.Insert(var, p.last); msg.symTab.Add(var.name, var)
         END   
      ELSE END
   END HandleMsg;

   PROCEDURE (c: Condition) HandleMsg* (VAR msg: Structs.Message);
      VAR lastVar: ANYPTR;
            ref: VarRef;
   BEGIN
      WITH msg: FuncNameMsg DO
         c.predicate := msg.name$
      | msg: CharVarMsg DO
         lastVar := msg.symTab.Look(msg.name);
         IF ~( (lastVar # NIL) & (lastVar IS CharVar) ) THEN
            msg.error := unknownVariable
         ELSE
            NEW(ref); ref.var := lastVar(Variable)(CharVar);
            c.Insert(ref, c.last)
         END
      | msg: CharMsg DO
         CASE msg.char OF
         | 'T': c.expect := TRUE
         | 'F': c.expect := FALSE
         END
      ELSE END   
   END HandleMsg;

   PROCEDURE (fc: FuncCall) HandleMsg* (VAR msg: Structs.Message);
   BEGIN
      WITH msg: FuncNameMsg DO
         fc.funcName := msg.name
      ELSE END   
   END HandleMsg;

   PROCEDURE ^ (s: Sentence) GetFreeVars* (OUT e1, e2: FreeVar), NEW;

   PROCEDURE (e: Expression) CheckFreeVar (VAR msg: FreeVarMsg), NEW;
      VAR e1, e2: FreeVar;
   BEGIN
      UpSentence(e).GetFreeVars(e1, e2);
      IF (e1 # NIL) & (msg.name = e1.name) THEN
         IF e.traits * {exprFirstFreeVar, exprSecondFreeVar} # {} THEN
            msg.error := wrongFreeVarOrder
         ELSE
            INCL(e.traits, exprFirstFreeVar)
         END
      ELSIF (e2 # NIL) & (msg.name = e2.name) THEN
         IF exprSecondFreeVar IN e.traits THEN
            msg.error := wrongFreeVarOrder
         ELSE
            INCL(e.traits, exprSecondFreeVar)
         END
      ELSE
         msg.error := unknownVariable
      END
   END CheckFreeVar;

   PROCEDURE (e: Expression) HandleMsg* (VAR msg: Structs.Message);
      VAR c: Char;
            lastVar: ANYPTR;
            ref: VarRef;
            fc: FuncCall;
            fe: Expression;
            base: Structs.Expr;
   BEGIN
      IF msg IS FreeVarMsg THEN e.CheckFreeVar(msg(FreeVarMsg)) END;
      IF (msg IS Message) & (msg(Message).error = 0) THEN
         IF (e.last # NIL) & (e.last IS Expression) THEN
            e.last.HandleMsg(msg)
         ELSE
            WITH msg: CharMsg DO
               NEW(c); c.c := msg.char; c.encode := msg.encode;
               e.Insert(c, e.last)
            | msg: CharVarMsg DO
               lastVar := msg.symTab.Look(msg.name);
               IF ~ ( (lastVar # NIL) & (lastVar IS CharVar) ) THEN
                  msg.error := unknownVariable
               ELSE
                  NEW(ref); ref.var := lastVar(CharVar);
                  e.Insert(ref, e.last)
               END
            | msg: FreeVarMsg DO
               lastVar := msg.symTab.First(msg.name); msg.symTab.End;
               IF ~ ( (lastVar # NIL) & (lastVar IS FreeVar) ) THEN
                  msg.error := unknownVariable
               ELSE
                  NEW(ref); ref.var := lastVar(FreeVar);
                  e.Insert(ref, e.last)
               END
            | msg: BeginExprMsg DO
               NEW(fc);
               e.Insert(fc, e.last)
            | msg: FuncNameMsg DO
               e.last(FuncCall).HandleMsg(msg);
               NEW(fe);
               e.Insert(fe, e.last)
            | msg: EndExprMsg DO
               base := e.Expr();
               WITH base: Expression DO
                  base.last(Expression).prev(FuncCall).Paste(base, e, e, NIL)
               | base: Sentence DO
               (* nothing *)
               END
            | msg: Message DO
               e.last.HandleMsg(msg)
            ELSE END
         END
      END
   END HandleMsg;

   PROCEDURE (s: Sentence) HandleMsg* (VAR msg: Structs.Message);
      VAR cond: Condition;
            e: Expression;
   BEGIN
      WITH msg: CharMsg DO
         s.last.HandleMsg(msg)
      | msg: VarMsg DO
         msg.symTab := s.first(Structs.SymTab);
         s.last.HandleMsg(msg)
      | msg: NewCondMsg DO
         NEW(cond);
         s.Insert(cond, s.last)
      | msg: BeginExprMsg DO
         IF (s.last # NIL) & (s.last IS Expression) THEN
            s.last.HandleMsg(msg)
         ELSE
            NEW(e); s.Insert(e, s.last)
         END
      | msg: EndExprMsg DO
         s.last(Expression).HandleMsg(msg)
      | msg: Message DO
         s.last.HandleMsg(msg)
      ELSE END
   END HandleMsg;

   PROCEDURE (s: Sentence) GetFreeVars* (OUT e1, e2: FreeVar), NEW;
      VAR t: Structs.Term;
   BEGIN
      e1 := NIL; e2 := NIL;
      t := s.first(Structs.SymTab).next(Pattern).first;
      WHILE (t # NIL) & ~(t IS FreeVar) DO t := t.next END;
      IF t # NIL THEN
         e1 := t(FreeVar);
         t := t.next;
         WHILE (t # NIL) & ~(t IS FreeVar) DO t := t.next END;
         IF t # NIL THEN e2 := t(FreeVar) END
      END
   END GetFreeVars;

   PROCEDURE (f: Function) HandleMsg* (VAR msg: Structs.Message);
      VAR s: Sentence;
            nsm: NewSentMsg;
            symTab: Structs.SymTab;
            pat: Pattern;
            ok: BOOLEAN;
   BEGIN
      WITH msg: NewSentMsg DO
         NEW(s); symTab := Structs.dir.NewSymTab(7); s.Insert(symTab, s.last);
         NEW(pat); s.Insert(pat, s.last);
         f.Insert(s, f.last)
      | msg: FuncNameMsg DO
         IF f.first = NIL THEN
            f.name := msg.name$;
            f.HandleMsg(nsm);
            f.Expr()(Program).first(Structs.SymTab).AddUnicum(f.name, f, ok);
            IF ~ok THEN
               msg.error := duplicatedFuncName
            END
         ELSE
            f.last.HandleMsg(msg)
         END
      | msg: Message DO
            f.last.HandleMsg(msg)
      ELSE END
   END HandleMsg;

   PROCEDURE (p: Program) HandleMsg* (VAR msg: Structs.Message);
      VAR f: Function;
   BEGIN
      WITH msg: NewFuncMsg DO
         msg.error := 0;
         NEW(f);
         p.Insert(f, p.last)
      | msg: Message DO
         msg.error := 0;
         p.last.HandleMsg(msg)
      ELSE END   
   END HandleMsg;


А вот связующий слой, который получает вызовы-события от синт. анализатора и трансформирует соотв. фрагмент исходника в сообщение, которое посылает корню дерева:

Код:
   PROCEDURE EmitNewFunc (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: NewFuncMsg;
   BEGIN
      par(Parser).program.HandleMsg(msg);
      error := msg.error
   END EmitNewFunc;

   PROCEDURE EmitFuncName (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: FuncNameMsg;
   BEGIN
      Strings.Extract(in, p, q - p, msg.name);
      par(Parser).program.HandleMsg(msg);
      IF msg.error = 0 THEN p := q ELSE error := msg.error END
   END EmitFuncName;

   PROCEDURE EmitNewSent (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: NewSentMsg;
   BEGIN
      par(Parser).program.HandleMsg(msg);
      error := msg.error
   END EmitNewSent;

   PROCEDURE EmitBeginExpr (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: BeginExprMsg;
   BEGIN
      par(Parser).program.HandleMsg(msg);
      error := msg.error
   END EmitBeginExpr;

   PROCEDURE EmitEndExpr (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: EndExprMsg;
   BEGIN
      par(Parser).program.HandleMsg(msg);
      error := msg.error
   END EmitEndExpr;

   PROCEDURE EmitChar (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: CharMsg;
   BEGIN
      msg.char := in[p]; msg.encode :=  (msg.char = 0DX) OR (msg.char = 09X);
      par(Parser).program.HandleMsg(msg);
      IF msg.error = 0 THEN p := q ELSE error := msg.error END
   END EmitChar;

   PROCEDURE EmitInvalidChar (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
   BEGIN
      error := unexpectedChar
   END EmitInvalidChar;

   PROCEDURE EmitCharCode (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR xs: ARRAY 16 OF CHAR;
            x, res: INTEGER;
            msg: CharMsg;
   BEGIN
      Strings.Extract(in, p, q-p, xs);
      Strings.StringToInt(xs, x, res);
      IF ~( (res = 0) OR (x < 65536) ) THEN
         error := tooLongCharCode
      ELSE
         msg.char := CHR(SHORT(x)); msg.encode := TRUE;
         par(Parser).program.HandleMsg(msg);
         IF msg.error = 0 THEN p := q ELSE error := msg.error END
      END
   END EmitCharCode;

   PROCEDURE EmitCharVar (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: CharVarMsg;
   BEGIN
      Strings.Extract(in, p, q - p, msg.name);
      par(Parser).program.HandleMsg(msg);
      IF msg.error = 0 THEN p := q ELSE error := msg.error END
   END EmitCharVar;

   PROCEDURE EmitFreeVar (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: FreeVarMsg;
   BEGIN
      Strings.Extract(in, p, q - p, msg.name);
      par(Parser).program.HandleMsg(msg);
      IF msg.error = 0 THEN p := q ELSE error := msg.error END
   END EmitFreeVar;

   PROCEDURE EmitNewCond (VAR par: ANYREC; VAR in: ARRAY OF CHAR; VAR p: INTEGER; q: INTEGER; VAR out: ARRAY OF CHAR; VAR r: INTEGER; OUT error: INTEGER);
      VAR msg: NewCondMsg;
   BEGIN
      par(Parser).program.HandleMsg(msg);
      error := msg.error
   END EmitNewCond;


Процедурки получаются маленькие, обозримые, очевидные... Не сравнить с тем, как обычно в ручную написанных на императиве трансляторах...

Ну и для полноты вот сам синт. анализатор Рефала-0, раскрученный на нём самом - он обращается к вышепоказанным процедурам Emit...

Код:
RocotRefal0 (parserParam = TRUE; funcPrefix = 'Parse'; exceptProc = 'SyntaxError');
   Preprocess {
      '\n' e1   =   ' ' <Preprocess e1>;
      '\t' e1   =   ' ' <Preprocess e1>;
      '\'' e1   =   '\'' <PreString e1>;
      '/*' e1   =   '  ' <PreComment e1>;
      s1 e2   =   s1 <Preprocess e2>;
      e1   =   e1 /* ''   =   '' */
   }

   PreComment {
      '*/' e1   =   '  ' <Preprocess  e1>;
      s1 e2   =   ' ' <PreComment e2>
   }

   PreString {
      '\'' e1   =   '\'' <Preprocess e1>;
      '\\\\' e1   =   '\\\\' <PreString e1>;
      '\\\'' e1   =   '\\\'' <PreString e1>;
      s1 e2   =   s1 <PreString e2>
   }

   Expect {
      sC sC e1   =   e1;
      sC ' ' e1   =   <Expect sC e1>
   }

   Optional {
      sC sC e1   =   e1;
      sC ' ' e1   =   <Optional sC e1>;
      sC e1   =   e1
   }

   Main {
      e1   =   <Program <Preprocess e1>>
   }

   Program {
      /* Program = { Function [";"] } . */
      ''   =   '';
      ' ' e1   =   <Program e1>;
      e1   =   <Program <Optional ';' <Function e1>>>
   }

   Function {
      /* Function = FuncName "{" Sentence { ";" Sentence } [";"] "}" . */
      e1   =   <EmitNewFunc> <Expect '}' <Block <Sentence <Expect '{' <FuncName e1>>>>>
   }

   FuncName {
      s1 eName s2 e3, <IsFirstFuncChar s1>: 'T', <IsFuncChar s2>: 'F' =
            <EmitFuncName s1 eName> s2 e3
   }

   Block {
      ' ' e1   =   <Block e1>;
      ';' e1   =   <Block <EmitNewSent><Sentence e1>>;
      e1   =   e1
   }

   /* Sentence & sentence pattern */

   Sentence {
      /* Sentence = Pattern {"," Condition} "=" Expression . */
      e1   =   <Expression
               <Expect '=' <CondSection <Pattern e1>>><EmitBeginExpr>>
            <EmitEndExpr>
   }

   Pattern {
      /* Pattern =   | Template | [Template] FreeVar [Template] |
         [Template] FreeVar Template FreeVar [Template] . */
      e1   =               <Template<FreePart<Template<FreePart<Template e1>>>>>
   }

   FreePart {
      'e' e1   =   <FreeVar 'e' e1>;
      e1   =   e1
   }

   Template {
      /* Template = (String | CharVar) {Template} . */
      ' ' e1   =   <Template e1>;
      '\'' e1   =   <Template <String e1>>;
      's' e1   =   <Template <CharVar 's' e1>>;
      e1   =   e1
   }

   /* Pattern elements */

   String {
      '\'' e1   =   e1;
      '\\\'' e1   =   <EmitChar '\''> <String e1>;
      '\\\"' e1   =   <EmitChar '\"'> <String e1>;
      '\\\\' e1   =   <EmitChar '\\'> <String e1>;
      '\\\n' e1   =   <String e1>; /* \ to skip end of line; else it be included in string directly */
      '\\n' e1   =   <EmitChar '\n'> <String e1>;
      '\\t' e1   =   <EmitChar '\t'> <String e1>;
      '\\' s1 e2, <IsDigit s1>: 'T'
         =   <String <CharCode s1 e2>>;
      '\"' e1   =   <EmitInvalidChar> e1;
      '\\' e1   =   <EmitInvalidChar> e1;
      s1 e2   =   <EmitChar s1> <String e2>
   }

   CharCode {
      eCode s1 e2, <IsDigit s1>: 'F' = <EmitCharCode eCode> s1 e2
   }

   CharVar {
      ' ' e1   =   <CharVar e1>;
      's' s1 eIndex s2 e3, <IsIndexChar s1>: 'T', <IsIndexChar s2>: 'F' =
            <EmitCharVar s1 eIndex> s2 e3
   }

   FreeVar {
      ' ' e1   =   <FreeVar e1>;
      'e' s1 eIndex s2 e3, <IsIndexChar s1>: 'T', <IsIndexChar s2>: 'F' =
            <EmitFreeVar s1 eIndex> s2 e3
   }

   /* Condition list */

   CondSection {
      /* CondSection =   {"," Condition} . */
      ' ' e1   =   <CondSection e1>;
      ',' e1   =   <CondSection <EmitNewCond> <Condition e1> >;
      e1   =   e1
   }

   Condition {
      /* Condition = "<"Function Charvar ">"  ":"  ("T" OR "F") . */
      ' ' e1   =   <Condition e1>;
      '<' e1   =   <CondConst <Expect ':' <Expect '>' <CharVar <FuncName e1>>>>>
   }

   CondConst {
      ' ' e1   =   <CondConst e1>;
      '\'T\'' e1   =   <EmitChar 'T'> e1;
      '\'F\'' e1   =   <EmitChar 'F'> e1
   }

   /* Substitute expression */

   Expression {
      /* Expression = {String | CharVar | FreeVar | FunctionCall}. */
      ' ' e1   =   <Expression e1>;
      '\'' e1   =    <Expression <String e1>>;
      's' e1   =   <Expression <CharVar 's' e1>>;
      'e' e1   =   <Expression <FreeVar 'e' e1>>;
      '<' e1   =   <Expression <Expect '>' <EmitBeginExpr>
                  <Expression <FuncName e1>>
               <EmitEndExpr> >
            >;
      e1   =   e1
   }


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 03:58 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
Вот пример с активным синтаксическим деревом транслятора Рефала-0.


Если я правильно понял, то все это всего лишь "ручная" реалиазация диспетчеризации по динамическому типу аргумента. Т.е., если бы язык поддерживал вот такой полиморфизм:

Код:
PROCEDURE HandleMsg(VAR msg: Structs.Message, VAR expr: Structs.Expr);
PROCEDURE HandleMsg(VAR msg: FuncNameMsg, VAR expr: Function);


То все стало бы еще намного проще, декларативенее и без всяких message bus :) Поправьте, если я чего-то упустил.

P.S. Причем такое решение (без "активности" со стороны обрабатываемых елементов дерева) я считаю идеологически более чистым. Во всяком случае для этого примера.

P.S.S. Гуглить можно по фразе "двойная диспетчеризация".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 05:13 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Vlad писал(а):
То все стало бы еще намного проще, декларативенее и без всяких message bus :) Поправьте, если я чего-то упустил.

IMHO, это разрушит ряд механизмов, на которых основана работа Оберона как системы.
Например, схему родительского управления (parental control). Визуальные объекты в Обероне являются узлами иерархической структуры, и сообщение (по крайней мере, при широковещании) проходит от "старших" объектов к "младшим".
Работа этого механизма основана на тождестве интерфейса обработчиков сообщений. Ваше же ценное предложение, думается, его разрушает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 13:20 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Vlad писал(а):
P.S.S. Гуглить можно по фразе "двойная диспетчеризация".


Да, я отмечал неоднократно (например, в статье "Некоторые идеи архитектуры Оберон-систем"), что шина сообщений даёт именно двойную диспетчеризацию (виртуализацию).

Мне лично кажется, что явный оператор (pattern-mathcing, так сказать, по типу сообщения) идейно лучше полиморфизма, т.к. подчёркивает принятие решений именно объектом-обработчиком, а не неким middle-слоем (компилятор, промежуточная таблица и т.п.) Принятие решений может быть сложным и параметризоваться не только типом входящего сообщения, но и внутренним состоянием объекта, получившего сообщение.
И хозяин-барин, как оформить этот код обработки - сначала ли дать ветвление по типу сообщения, или по чему-то другому... Введение отдельных методов разрушает это единство.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 19:41 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
Да, я отмечал неоднократно (например, в статье "Некоторые идеи архитектуры Оберон-систем"), что шина сообщений даёт именно двойную диспетчеризацию (виртуализацию).


Да, ее можно использовать для реализации двойной диспетчеризации. Только говорить о какой-то эксклюзивности message bus уже не приходится. В смысле конкретно это пример в случае "прямой" поддержки двойной диспетчеризации будет выглядеть намного приятнее.

Илья Ермаков писал(а):
Мне лично кажется, что явный оператор (pattern-mathcing, так сказать, по типу сообщения) идейно лучше полиморфизма, т.к. подчёркивает принятие решений именно объектом-обработчиком, а не неким middle-слоем (компилятор, промежуточная таблица и т.п.) Принятие решений может быть сложным и параметризоваться не только типом входящего сообщения, но и внутренним состоянием объекта, получившего сообщение.
И хозяин-барин, как оформить этот код обработки - сначала ли дать ветвление по типу сообщения, или по чему-то другому... Введение отдельных методов разрушает это единство.


Аргументы из серии "на асме я могу прыгнуть в середину цикла". Или "зачем мне AWAIT если есть критические секции и мьютексы" ;) Двойная диспетчеризация более высокоуровневый механизм. Если вам нужно учесть внутреннее состояние и еще не знаю какие детали - пожалуйста, используйте более низкоуровневый (со всеми вытекающими) механизм.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 19:45 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
AVC писал(а):
Например, схему родительского управления (parental control). Визуальные объекты в Обероне являются узлами иерархической структуры, и сообщение (по крайней мере, при широковещании) проходит от "старших" объектов к "младшим".
Работа этого механизма основана на тождестве интерфейса обработчиков сообщений. Ваше же ценное предложение, думается, его разрушает.


Не разрушает, а дополняет. В тривиальных случаях (обработка конкретного сообщение и делегирование всех остальных) все становится проще. Не в тривиальных - закатываем рукава и углубляемся в код.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 19:50 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Высокоуровневый - а от чего особо страшного он нас абстрагирует?

Я бы тут кроме высокоуровневости ввёл критерий "отбалдистости". Сообщения и принятие решения при их анализе - это довольно естественнная, умственно осязаемая абстракция. А эти механизмы перегрузки, полиморфизм - уже нечто сфантазированное, скомбинированное. Можно придумать так, а можно этак... Прозрачность теряется, появляется интеллектуальный произвол... Мне не нравится. Сейчас многие проблемы пытаются решить такими произвольными, скомбинированными средствами - Немерле и т.п. такое же ощущение оставляют. Короче, "катит всё, что внутренне непротиворечиво", как в чистой математике. Чёткий смысл теряется.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 20:12 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
Высокоуровневый - а от чего особо страшного он нас абстрагирует?


От заглядывания во внутренности HandleMessage (помноженного на количество этих HandleMessage). Мало?

P.S. Ну и от мартышкиного труда по написанию HandleMessage. Ну и от возможности сделать дурацкую ошбку, которую в такой архитектуре можно будет долго искать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 20:20 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Так при разбиении на отдельные варианты их станет в несколько раз больше, а связность уменьшится...

Кроме того, логика обработки сообщений является внутренним делом получателя и не должна в общем случае светиться в его интерфейсе (это уж отдельный вопрос о поддержке описания протоколов).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 20:32 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
Так при разбиении на отдельные варианты их станет в несколько раз больше


Это плохо? Лучше все в одной куче? Лично меня напрягает разносить switch по функциям, когда он со временем становится неприлично большим.

Илья Ермаков писал(а):
а связность уменьшится...


Чего с чем?

Илья Ермаков писал(а):
Кроме того, логика обработки сообщений является внутренним делом получателя и не должна в общем случае светиться в его интерфейсе (это уж отдельный вопрос о поддержке описания протоколов).


А никто и не заставляет светиться в интерфейсе.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Вторник, 06 Май, 2008 22:11 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Цитата:
Илья Ермаков писал(а):
Так при разбиении на отдельные варианты их станет в несколько раз больше

Это плохо? Лучше все в одной куче? Лично меня напрягает разносить switch по функциям, когда он со временем становится неприлично большим.


А чего ему становиться неприлично большим? Если объект обрабатывает слишком много сообщений, то это повод его порезать на части и делегировать часть сообщений подузлам (есть такой принцип смоллтокеров - объект должен стремиться ничего не делать сам, а искать "негров", которым делегировать :-) ).
А если сами блоки действий большие, то я лучше вынесу их в отдельные процедуры, вызываемые из одного общего распознавателя сообщений ("сортировщика писем" :-) ).

Цитата:
Илья Ермаков писал(а):
а связность уменьшится...

Чего с чем?

Различных веток логики единого блока принятия решений...

Цитата:
А никто и не заставляет светиться в интерфейсе.

Пардон, а как же не светиться, если на каждый чих заводить по отдельному методу?

А может быть ещё уйма разнообразных случаев. Например, обработчик может выполнять некоторые стартовые общие действия. Или разбирать тип частично, выполнять эти действия для семейства сообщений, потом доразбирать тип точнее - и ещё что-то делать... Блин, мне так и представляется сразу горячий эстонский парень какой-нибудь, с пеной у рта доказывающий, что нужно расширять механизм методов-обработчиков в языке, чтобы они могли вызываться для одного сообщения по очереди, от общего сопоставления к конкретному... А потом ещё "усовершенствуем" чё-нить :-)

А если мне эту логику надо поменять, то это, кстати, сразу в интерфейс пойдёт :-) И всем клиентским модулям мозги пудрить будет... Дурдом.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Среда, 07 Май, 2008 06:15 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
Различных веток логики единого блока принятия решений...


Все равно не понял...

Илья Ермаков писал(а):
Цитата:
А никто и не заставляет светиться в интерфейсе.

Пардон, а как же не светиться, если на каждый чих заводить по отдельному методу?


Метод это еще не интерфейс. Странно слышать такое от оберонщика :) Откуда у вас такие ассоциации?

Илья Ермаков писал(а):
А может быть ещё уйма разнообразных случаев. Например, обработчик может выполнять некоторые стартовые общие действия. Или разбирать тип частично, выполнять эти действия для семейства сообщений, потом доразбирать тип точнее - и ещё что-то делать... Блин, мне так и представляется сразу горячий эстонский парень какой-нибудь, с пеной у рта доказывающий, что нужно расширять механизм методов-обработчиков в языке, чтобы они могли вызываться для одного сообщения по очереди, от общего сопоставления к конкретному... А потом ещё "усовершенствуем" чё-нить :-)


Ну так и не тяните этот механизм в язык. Дайте возможность его описать на языке. И эстонские парни будут довольны :) Вот в C++, например, можно... ;) Не удивительно, что этот message bus никому не нужен, кроме оберонщиков ;)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Среда, 07 Май, 2008 08:05 

Зарегистрирован: Среда, 17 Январь, 2007 03:59
Сообщения: 225
Vlad писал(а):
Не удивительно, что этот message bus никому не нужен, кроме оберонщиков ;)


Гуглите Message Bus и увидите кому оно нужно :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Среда, 07 Май, 2008 12:30 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Vlad писал(а):
AVC писал(а):
Работа этого механизма основана на тождестве интерфейса обработчиков сообщений. Ваше же ценное предложение, думается, его разрушает.


Не разрушает, а дополняет.

Вот так мы и общаемся: я говорю Вам, что такой-то системный механизм основан на тождестве интерфейсов обработчиков, а Вы мне отвечаете, что отказ от тождества здорово этот механизм дополнит.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Среда, 07 Май, 2008 13:46 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Vlad писал(а):
Ну так и не тяните этот механизм в язык. Дайте возможность его описать на языке. И эстонские парни будут довольны :) Вот в C++, например, можно... ;) Не удивительно, что этот message bus никому не нужен, кроме оберонщиков ;)

Ну-ка пример в студию... Как это можно организовать динамический выбор одного из перегруженных методов по динамическому типу параметра? Двойная диспетчеризация на основе шаблонов - фишка известная, Элджера читали, как же... Статично и неинтересно.

К вопросу об интерфейсе и методах, так что, у нас методы уже в интерфейс перестают входить? Сделать их private нельзя... Или я не так понимаю предлагаемое решение.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные структуры данных
СообщениеДобавлено: Среда, 07 Май, 2008 13:52 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8971
Откуда: Россия, Орёл
Цитата:
Vlad писал(а):
Илья Ермаков писал(а):
Различных веток логики единого блока принятия решений...

Все равно не понял...


Объекту поступило сообщение. Это его внутреннее суверенное дело, чего и как он делает с ним дальше. Есть одна точка на его входе, в которой принимается решение (может быть, сразу же будет разрулено на те же отдельные методы, но уже свои внутренние). Зачем всовывать сторонний внешний механизм, который чего-то ещё до объекта сортирует?

"Чиста философски", всю корреспонденцию в полной мере интерпретировать способен только получатель. Так зачем пытаться делать какую-то неполную интерпретацию на его входе? Заставить почтальона разбираться в типах моих писем и раскладывать мне их по ящикам на двери? Так он и знать не должен про эти типы, его дело - доставить....


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 54 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2018, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB