Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Вниз

Объясните пожалуйста дельфисту, что такое шаблоны в Си?   Найти похожие ветки 

 
Mystic ©   (2007-11-01 16:37) [80]

> Есть мнение что это промежуточный асемблер…

Это мне показал cordbg.exe. Скомпилировано в релизе.


 
clickmaker ©   (2007-11-01 16:37) [81]


> что это промежуточный асемблер

а что это (сорри за серость)?


 
homm ©   (2007-11-01 16:41) [82]

> [81] clickmaker ©   (01.11.07 16:37)
> а что это (сорри за серость)?

Асемблерные команды, понимаемые jit компилятором. Промежуточное представление кпрограммы, до того, как она оттранслируется во время выполнеия в машинные кода.


 
clickmaker ©   (2007-11-01 16:42) [83]


> Асемблерные команды, понимаемые jit компилятором

видимо jit туповат все-таки... если банальный if ему так надо разжевать :)


 
Mystic ©   (2007-11-01 16:59) [84]

> Асемблерные команды, понимаемые jit компилятором.

Эти ассемблерные команды, пониамемые JIT-компилятором, называются иструкциями CIL. Там есть такие команды, как box, callvirt, castclass, newobj, newarr и т. д. Тут же нативный AMD64 ассемблер. Я не пробовал, как это скомпилируется в 32-битной Windows, может там оптимизатор получше. Но под 64 битами результаты устрашающе угнетающие.

К тому же как можно упростить этот "промежуточный" код? По большому счету никак, он и так оптимизирован на уровне ассемблерных инструкций. Оптимизировать его надо было уровнями выше.


 
clickmaker ©   (2007-11-01 17:01) [85]


> ;            if (Color == System.Drawing.Color.Black)
> 0000008d  lea         rcx,[rsp+20h]

судя по всему, там какая-то предварительная работа... только вот, хрен знает, зачем
ну не может один if в такую простыню развернуться. Хоть на 32-бит, хоть на 64, хоть на Марсе...


 
Mystic ©   (2007-11-01 17:24) [86]

> clickmaker ©   (01.11.07 17:01) [85]

Второй if разворачивается в аналогичную конструкцию (32 бита). Может у кого-то получится это сделать более оптимально?

--- C:\Mu\Labs\cs\test1\Program.cs ---------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 class Program
 {
   static void Main(string[] args)
   {
     System.Drawing.Color Color = System.Drawing.Color.Black;
00000000  push        ebp  
00000001  mov         ebp,esp
00000003  push        edi  
00000004  push        esi  
00000005  sub         esp,64h
00000008  mov         esi,ecx
0000000a  lea         edi,[ebp-6Ch]
0000000d  mov         ecx,18h
00000012  xor         eax,eax
00000014  rep stos    dword ptr es:[edi]
00000016  mov         ecx,esi
00000018  mov         dword ptr [ebp-0Ch],ecx
0000001b  cmp         dword ptr ds:[0092885Ch],0
00000022  je          00000029
00000024  call        79421156
00000029  lea         ecx,[ebp-2Ch]
0000002c  call        7A191508
00000031  lea         edi,[ebp-1Ch]
00000034  lea         esi,[ebp-2Ch]
00000037  movs        dword ptr es:[edi],dword ptr [esi]
00000038  movs        dword ptr es:[edi],dword ptr [esi]
00000039  movs        dword ptr es:[edi],dword ptr [esi]
0000003a  movs        dword ptr es:[edi],dword ptr [esi]
     if (Color != System.Drawing.Color.Black)
0000003b  lea         edi,[ebp-3Ch]
0000003e  lea         esi,[ebp-1Ch]
00000041  movs        dword ptr es:[edi],dword ptr [esi]
00000042  movs        dword ptr es:[edi],dword ptr [esi]
00000043  movs        dword ptr es:[edi],dword ptr [esi]
00000044  movs        dword ptr es:[edi],dword ptr [esi]
00000045  lea         ecx,[ebp-4Ch]
00000048  call        7A191508
0000004d  lea         eax,[ebp-3Ch]
00000050  push        dword ptr [eax+0Ch]
00000053  push        dword ptr [eax+8]
00000056  push        dword ptr [eax+4]
00000059  push        dword ptr [eax]
0000005b  lea         eax,[ebp-4Ch]
0000005e  push        dword ptr [eax+0Ch]
00000061  push        dword ptr [eax+8]
00000064  push        dword ptr [eax+4]
00000067  push        dword ptr [eax]
00000069  call        7A18C808
0000006e  mov         esi,eax
00000070  test        esi,esi
00000072  je          0000007F
       System.Console.WriteLine("Catastrophic execution");
00000074  mov         ecx,dword ptr ds:[0228307Ch]
0000007a  call        78747F3C
     if (Color == System.Drawing.Color.White)
0000007f  lea         edi,[ebp-5Ch]
00000082  lea         esi,[ebp-1Ch]
00000085  movs        dword ptr es:[edi],dword ptr [esi]
00000086  movs        dword ptr es:[edi],dword ptr [esi]
00000087  movs        dword ptr es:[edi],dword ptr [esi]
00000088  movs        dword ptr es:[edi],dword ptr [esi]
00000089  lea         ecx,[ebp-6Ch]
0000008c  call        7A18A2B4
00000091  lea         eax,[ebp-5Ch]
00000094  push        dword ptr [eax+0Ch]
00000097  push        dword ptr [eax+8]
0000009a  push        dword ptr [eax+4]
0000009d  push        dword ptr [eax]
0000009f  lea         eax,[ebp-6Ch]
000000a2  push        dword ptr [eax+0Ch]
000000a5  push        dword ptr [eax+8]
000000a8  push        dword ptr [eax+4]
000000ab  push        dword ptr [eax]
000000ad  call        7A18A424
000000b2  mov         esi,eax
000000b4  test        esi,esi
000000b6  je          000000C3
       System.Console.WriteLine("Catastrophic execution");
000000b8  mov         ecx,dword ptr ds:[0228307Ch]
000000be  call        78747F3C
   }
000000c3  nop              
000000c4  lea         esp,[ebp-8]
000000c7  pop         esi  
000000c8  pop         edi  
000000c9  pop         ebp  
000000ca  ret              


 
Mystic ©   (2007-11-01 18:02) [87]

Хорошо, протестировал сей момент:

Исходник C#, test1.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 class Program
 {
   static void Main(string[] args)
   {
     System.DateTime begin = System.DateTime.Now;
   
     for (int i=0; i<50000000; ++i)
     {
       System.Drawing.Color Color = System.Drawing.Color.Black;
       if (Color != System.Drawing.Color.Black)
         System.Console.WriteLine("Catastrophic execution");
       if (Color == System.Drawing.Color.White)
         System.Console.WriteLine("Catastrophic execution");
     }

     System.DateTime end = System.DateTime.Now;
     

     Console.WriteLine(end - begin);
   }
 }
}


Исходник C++, test2.cpp

#include <iostream>
#include "windows.h"

namespace System
{
 namespace Drawing
 {
   class Color
   {
     private:
       int value;
       Color(const int _value): value(_value) {}
     public:
       Color(const Color& color): value(color.value) {}
       static const Color White;
       static const Color Black;
       friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
       friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
   };
   
   const Color Color::White(0x00FFFFFF);
   const Color Color::Black(0x00000000);
 }
}

int main()
{
 LARGE_INTEGER begin, end, f;

 QueryPerformanceFrequency(&f);
 double frequency = static_cast<double>(f.QuadPart);
 
 QueryPerformanceCounter(&begin);
 for (int i=0; i<50000000; ++i)
 {
   System::Drawing::Color Color = System::Drawing::Color::Black;
   if (Color != System::Drawing::Color::Black)
     std::cout << "Catastrophic execution" << std::endl;
   if (Color == System::Drawing::Color::White)
     std::cout << "Catastrophic execution" << std::endl;
 }
 QueryPerformanceCounter(&end);
 
 std::cout << (end.QuadPart - begin.QuadPart) / frequency << std::endl;
return 0;
}


Результаты:


C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:05.7343750

C:\Mu\Labs\cs\test2\Release>test2.exe
0.0569969


Итого, разница примерно в 100 раз :)


 
Mystic ©   (2007-11-01 18:03) [88]

Что видно по ассемблерному коду C++:

#include <iostream>

namespace System
{
 namespace Drawing
 {
   class Color
   {
     private:
       int value;
       Color(const int _value): value(_value) {}
     public:
       Color(const Color& color): value(color.value) {}
       static const Color White;
       static const Color Black;
       friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
       friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
   };
   
   const Color Color::White(0x00FFFFFF);
   const Color Color::Black(0x00000000);
 }
}

int main()
{
 System::Drawing::Color Color = System::Drawing::Color::Black;
00401000  mov         eax,dword ptr [System::Drawing::Color::Black (403374h)]
 if (Color != System::Drawing::Color::Black)
   std::cout << "Catastrophic execution" << std::endl;
 if (Color == System::Drawing::Color::White)
00401005  cmp         eax,dword ptr [System::Drawing::Color::White (40301Ch)]
0040100B  jne         main+2Ah (40102Ah)
   std::cout << "Catastrophic execution" << std::endl;
0040100D  mov         eax,dword ptr [__imp_std::endl (402038h)]
00401012  mov         ecx,dword ptr [__imp_std::cout (402054h)]
00401018  push        eax  
00401019  push        ecx  
0040101A  call        std::operator<<<std::char_traits<char> > (401160h)
0040101F  add         esp,4
00401022  mov         ecx,eax
00401024  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402040h)]
 
return 0;
0040102A  xor         eax,eax
}
0040102C  ret  


 
homm ©   (2007-11-01 18:09) [89]

> [87] Mystic ©   (01.11.07 18:02)
> Итого, разница примерно в 100 раз :)

Жесть :)
Где там госпадин Alkid ?


 
Amoeba ©   (2007-11-01 18:21) [90]


> vpbar ©   (01.11.07 14:05) [29]
>
> Alkid ©   (01.11.07 13:58) [27]
> Для таких случаев можно симулировать :)
> http://www.delphikingdom.com/asp/viewitem.asp?catalogid=744
> и ww.delphikingdom.com/asp/viewitem.asp?catalogid=453 есть
> статья получше. Но ссылку не помню.
>

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=891


 
Alkid ©   (2007-11-01 18:23) [91]


> Жесть :)
> Где там госпадин Alkid ?

Я тут. :)
Если заметите, здесь не чисто вычислительная задача, а задача связанная с вводом-выводом :)
А они там действительно могут подтормаживать.


 
Джо ©   (2007-11-01 18:31) [92]

К сожалению, большинство *реальных* программ не занимаются только вычислением. Я готов признать, что для вычисления a := sqrt(b*sin(c)/123) в .Net генерится хороший, грамотный машинный код, врял ли, конечно, он быстрее кода, скомпилированного из C++, но все же он будет *достаточно быстр*.
Но в *реальных* программах, как правило, встречаются сравнения, условные переходы (господин Mystic уже показал, во что они компилятся) и (ужас!) операции ввода-вывода.
Так что, надо признать, что все эти тесты скорости программ под .Net никакого *практического* применения не имеют.


 
Джо ©   (2007-11-01 18:33) [93]

Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)


 
Mystic ©   (2007-11-01 18:40) [94]


> Если заметите, здесь не чисто вычислительная задача, а задача
> связанная с вводом-выводом :)


Ввод-вывод не выполняется :) Единственный вывод этих программ вначале и в конце, так что это вычислительная задача :)

Вообще-то примеры тут несколько некорректны, потому что указывают на наэффективность реализации System.Drawing.Color. Если сляпать похожий класс самому, то разница будет примерно в 20 раз:

C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:00.9843750


Нет, если алгоритмический код выполнять в процедурном стиле, все мелкие функции инлайнить ручками, то мы и в C# приблизимся к результату C++. Что и показывают тесты. Скажем, если в этом примере не использовать класс MyColor, а вместо использовать int, медоды заменить статическими вызовами, а самые мелкие из них инлайнить руками... Но для этого надо специально извращаться, код в результате будет негибкий :) А для тестов, чтобы показать могучесть JIT-компилятора---самый раз

Программа:


using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 struct MyColor
 {
   private int value;
   
   private MyColor(int _value)
   {
     value = _value;
   }
   
   static public bool operator == (MyColor color1, MyColor color2)
   {
     return color1.value == color2.value;
   }

   static public bool operator !=(MyColor color1, MyColor color2)
   {
     return color1.value != color2.value;
   }
   
   static public MyColor White
   {
     get
     {
       /* avoid boxing/unboxing operations in case of return new MyColor(0x00FFFFFF) */
       MyColor retVal;
       retVal.value = 0x00FFFFFF;
       return retVal;
     }
   }

   static public MyColor Black
   {
     get
     {
       MyColor retVal;
       retVal.value = 0x00000000;
       return retVal;
     }
   }
 }

 class Program
 {
   static void Main(string[] args)
   {
     /* JIT compilation of MyColor"s methods */
     MyColor t1 = MyColor.White;
     MyColor t2 = MyColor.Black;
     if ((t1==t2) == (t1 != t2))
       System.Console.WriteLine("Catastrophic execution");
     
     System.DateTime begin = System.DateTime.Now;
   
     for (int i=0; i<50000000; ++i)
     {
       MyColor Color = MyColor.Black;
       if (Color != MyColor.Black)
         System.Console.WriteLine("Catastrophic execution");
       if (Color == MyColor.White)
         System.Console.WriteLine("Catastrophic execution");
     }

     System.DateTime end = System.DateTime.Now;
     

     Console.WriteLine(end - begin);
   }
 }
}


 
isasa ©   (2007-11-01 19:29) [95]

Джо ©   (01.11.07 18:33) [93]

Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)


В основном тормозят из-за криворукости писателей, которые во время "тяжелых" операций пытаются визуализировать ход их выполнения.
Пример, использование TMemo для показа добавления большого числа строк(т.е. TMemo.Add(...) внутри большого цикла).

Про Java молчу, там и без этого (при Resize окна) видно, что графический движок оставляет желать лучшего ...


 
wicked ©   (2007-11-01 21:12) [96]

> Джо ©   (01.11.07 18:33) [93]

> Собственно, это даже не нужно доказывать теоретически, ибо
> видно и «на глазок» — все программы на Дотнет, которые я
> видел, тормозили.
> То же самое с Джавой. Можно сколько угодно рассуждать о
> тестах скорости, о быстроте выполнения, но, опять же, «на
> глазок» — они тормозят и все тут :)

да.... для определения "тормознутости" можно глянуть Paint.NET (дотнет) или Eclipse (джава)...

> isasa ©   (01.11.07 19:29) [95]

>
> Про Java молчу, там и без этого (при Resize окна) видно,
>  что графический движок оставляет желать лучшего ...

там много движков - AWT, Swing, SWT - который из них?


 
Джо ©   (2007-11-01 21:43) [97]

> [96] wicked ©   (01.11.07 21:12)
> да.... для определения "тормознутости" можно глянуть Paint.NET
> (дотнет) или Eclipse (джава)...

Оба продукта тормознутые.


 
@!!ex ©   (2007-11-01 22:17) [98]

У Paint.NET даже установщик тормозит...
Хотя софтина приятная.


 
Джо ©   (2007-11-01 22:44) [99]

Но, видимо, рекордсмен тормозов — это ДжБилдер, не ко сну будь упомянут :)


 
Efir   (2007-11-02 00:34) [100]

Ну почему же, Paint.Net вполне быстро работает. Последние версии неплохо оптимизированы.


 
Mystic ©   (2007-11-05 18:12) [101]

Никто не спорит, что на C# можно писать оптимизированные с учетом производительности программы. Но... отсутствие inline функций заставляет реализовывать inline-ы руками (Copy + Paste). Далее, экземпляры классов (и структур) помещаются не в регистрах, а в памяти (чтобы можно было взять адрес при передаче по ссылке). Ну и необходимо знать не только как писать оптимальные программы, но и ньюансы .NET (что получится в CLI инструкциях, как эти инструкции потом переведутся в ассемблер, boxing/unboxing).


 
oxffff ©   (2007-11-05 19:22) [102]


> Mystic ©   (05.11.07 18:12) [101]


> Далее, экземпляры классов (и структур) помещаются не в регистрах,
>  а в памяти (чтобы можно было взять адрес при передаче по
> ссылке).


А что в других языках структуры в регистрах хранятся?
:)

Теперь что касаемо inline.

Method Implementation Flags
The nonterminal symbol <impl> in the method definition form denotes the implementation flags of the method (the ImplFlags entry of a Method record).
The implementation flags are

..............
noinlining (0x0008). The runtime is not allowed to inline the method—that is, to
replace the method call with explicit insertion of the method’s IL code.


Даже возможно IL Inlining in High-Level Languages с помощью спецсредств.


 
Юрий Зотов ©   (2007-11-05 19:53) [103]

> Alkid ©   (01.11.07 13:58) [27]

Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер, абсолютно универсальный, абсолютно типобезопасный и без всяких шаблонов?


 
Сусл ©   (2007-11-05 19:56) [104]


> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
>  абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?


я хочу. очень.
только - проверка типов в compile-time, а не в runtime.


 
Юрий Зотов ©   (2007-11-05 20:10) [105]

> Сусл ©   (05.11.07 19:56) [104]

Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с BeforeCompile способен проверить что угодно.


 
Alkid ©   (2007-11-05 20:26) [106]


> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
>  абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?

Очень хочу, но именно Compile-time проверку типов :)
Касательно IDE-эксперта - это хотелось поподробнее. Меня терзают смутные сомнения, что это будет тот "шаблонатор", только не в компилятор встроенный, а "сбоку" прикрученный.


 
Mystic ©   (2007-11-05 20:52) [107]

> А что в других языках структуры в регистрах хранятся?
> :)


Если помещаются в регистр---почему нет? Если я объявлю
class A { private: int x; }, то если это возможно, то локальные переменные обычно размещаются в регистрах.

А вот в .NET 64 я не так давно видел такую картину: по стандарту stdcall переменные передаются в регистрах (их там дофига от R8 до R15). Поэтому вызов функции сводился к тому, что значения из памяти копировались в регистры. Потом происходил вызов функции. а затем переменные из памяти копировались в стек, где и положено быть локальным переменным :)

> Теперь что касаемо inline.
И как это легко использовать?

> Меня терзают смутные сомнения, что это будет тот "шаблонатор",
>  только не в компилятор встроенный, а "сбоку" прикрученный.


А какая, собственно говоря, разница? Чем Вас так не устраивает прикрученность сбоку? LEX + YACC удобная библиотека для лексического и синтаксического анализа, но ее тоже можно назвать прикрученной сбоку, потому как что в C++, что в Delphi она генерируют код. Написать утилиту, которая принимает на вход файл описаний и генерирует нужные контейнеры это дело одного дня.


 
Юрий Зотов ©   (2007-11-05 20:53) [108]

> Alkid ©   (05.11.07 20:26) [106]

ОК, значит будем считать, что все прекрасно понимают, что проверка типа в run-time  - абсолютно не проблема:


type
 TSafeContainer = class(...)
 protected
   class procedure TMyContainer.GetItemClass: TClass; virtual; abstract;
   class procedure CheckItemClass(Item: TObject; Strict: boolean); dynamic;
 public
   procedure Add(Item: TObject);
   procedure Insert(Item: TObject; Index: Integer);
   procedure Append(Item: TObject);
   // и т.п.
 end;

// И вызываем этот метод из Add, Insert, Append и т.п.
class procedure TSafeContainer.CheckItemClass(Item: TObject; Strict: boolean);
begin
 if ... then
   raise ...
end;

class procedure TSafeContainerDescendantExample.GetItemClass: TClass;
begin
 Result := TНужный_класс
end;


Тперь что касается Compile-time: задача, конечно, намного сложнее, но в принципе, решаема. В IDE можно (и даже несложно) вживить собственный эксперт, метод которого будет автоматически вызываться средой перед компиляцией проекта. В этом методе, вообще говоря, можно сделать что угодно, хоть собственный препроцессор наваять.


 
oxffff ©   (2007-11-05 21:09) [109]


> Mystic ©   (05.11.07 20:52) [107]
> > А что в других языках структуры в регистрах хранятся?
> > :)
>
> Если помещаются в регистр---почему нет? Если я объявлю
> class A { private: int x; }, то если это возможно, то локальные
> переменные обычно размещаются в регистрах.
>
> А вот в .NET 64 я не так давно видел такую картину: по стандарту
> stdcall переменные передаются в регистрах (их там дофига
> от R8 до R15). Поэтому вызов функции сводился к тому, что
> значения из памяти копировались в регистры. Потом происходил
> вызов функции. а затем переменные из памяти копировались
> в стек, где и положено быть локальным переменным :)


Что касаемо classA, то его нельзя разместить в регистре по причине того, что экземпляр класса содерживат еще дополнительные служебный поля, кроме поля X. Вы наверное имели ввиду value type.
Которые могут быть размещены в регистре при размере value type в int.

В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.
:)

Что касаемо передачи stdcall, то все передается через стек.


 
Mystic ©   (2007-11-05 21:33) [110]

> Которые могут быть размещены в регистре при размере value
> type в int.


Может быть и могут, я не видел.

В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.

Это понятно. Я говорю о том, как JIT в реализации .NET на платформе x86 использует регистры.

Что касаемо передачи stdcall, то все передается через стек.
Это справедливо для 32-х битной среде. В 64-х битной среде STDCALL == FASTCALL.


 
Mystic ©   (2007-11-05 21:38) [111]

Тут описано соглашения вызова функций для AMD64:
http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx
Других пока что нет :)


 
Сусл ©   (2007-11-05 21:39) [112]


> Юрий Зотов ©   (05.11.07 20:10) [105]
> Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с
> BeforeCompile способен проверить что угодно.


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

К тому же, Юра, позволь заметить следующую вещь. К сожалению в дельфи нет доступа к распарсеному тексту. Ну то есть - либо исх. код, либо готовый бинирник. В java есть возможность обращаться а байт-коду, который, конечно, намного легче для использования, нежели исх. код. Я недавно читал статью про статическое тестирование (напомню, что традиционно под термином понимается выявление ошибок на основе изучения кода без его выполнения). В частности там были обсуждены некоторые приблуды к eclipse, которые позволяют выполнять статическое тестирование программ на java на основе расширяемых шаблонов. Ну так вот. Все инструменты опираются на использование байт-кода. Сам понимаешь, что сделать твой эксперт в таком случае на порядок проще.

Резюм, я бы не говорил, что сделать такой эксперт ТЕБЕ вообще возможно (имеется в виду экономическая целесообразность). Почему я выделил ТЕБЕ? А потому, что ты, хоть и способный программист, но не имеешь доступа к внутреннему дереву компиляции кода на Delphi. Я уверен, что эксперты от самого CodeGear имеет естественно недокументированный доступ к такому дереву. Иначе объяснить относительно качественную работу экспертов рефакторинга объяснить сложно.


 
Mystic ©   (2007-11-05 21:50) [113]

> Знаешь, Юра, "способен" и "проворачивает" две огромные разницы.
> Ты и за месяц это не напиешь.


Думаю, что ты не понял основной идеи :) Смотри, есть некоторый файл, который содержит нечто следующее:


OUTPUT myutils.pas
USES MyUnit1, MyUnit2, MyUnit2
LIST TMyObj1 ITEM IS CLASS TMyClass1
DICTIONARY TMyObj2 KEY IS Integer VALUE IS RECORD TRecord1


Эту же информацию можно задать и в GUI эксперта. На основании этой информации генерируется исходник

uses myutils;
interface
uses MyUnit1, MyUnit2, MyUnit2;
type
 TMyObj1 = class
 private
...................
 public
   constructor Create;
   destructor Destroy; override;
   procedure Add(Value: TMyObj1);
   property Items[I: Integer]: TMyObj1 read GetItem write SetItem default;
 end;

...............

implementation

......................

end.


Этот исходник включается в проект, автоматически обновляется и используется :)


 
Черный Шаман   (2007-11-05 21:58) [114]


> Alkid ©   (01.11.07 13:58) [27]


Там есть ClassName и Published свойства которые можно достать в рантайм. Все отлично и без шаблонов можно сделать с использованием особенностей RTTI, причем все отлично читается и понимается потом.


 
Черный Шаман   (2007-11-05 22:14) [115]


> homm ©   (01.11.07 14:57) [46]
>
> > [41] Alkid ©   (01.11.07 14:50)
> > Видишь ли, это сейчас для всего, кроме embedded систем
> и
> > мобильный платформ, на которых я ни разу не специализируюсь,
>
> > уже ОЧЕНЬ МАЛЕНЬКИЙ недостаток.
>
> Ага, уже любой пенсионер на свою пенсию и из любой деревни
> может выкачать из инета 30 метров. ;)


На компакте со всеми программами использующими .NET всегда лежит сама среда. А 700 МБ или 4.7 Гб(DVD) для всех хватит. DVD-RW(хороший Asus/Nec) стоит 37$, вполне бюджетно для пенсионера.


 
Alkid ©   (2007-11-05 22:20) [116]


> А какая, собственно говоря, разница? Чем Вас так не устраивает
> прикрученность сбоку? LEX + YACC удобная библиотека для
> лексического и синтаксического анализа, но ее тоже можно
> назвать прикрученной сбоку, потому как что в C++, что в
> Delphi она генерируют код. Написать утилиту, которая принимает
> на вход файл описаний и генерирует нужные контейнеры это
> дело одного дня.

Да я и не спорю, просто тогда это и получаются те самые "шаблоны в Дельфи", о ненужности которых постоянно твердят некоторые участники форума.


 
Alkid ©   (2007-11-05 22:21) [117]


> ОК, значит будем считать, что все прекрасно понимают, что
> проверка типа в run-time  - абсолютно не проблема:

Гм. А где метод Get? Он-то в данном случае наиболее интересен. Точнее тип его возвращаемого значения. И еще точнее - надо ли каждый раз при взятии элемента из контейнера делать приведение типов от более общего к частному?


 
Alkid ©   (2007-11-05 22:24) [118]


> Там есть ClassName и Published свойства которые можно достать
> в рантайм. Все отлично и без шаблонов можно сделать с использованием
> особенностей RTTI, причем все отлично читается и понимается
> потом.

Тем, что
1. Этот контейнер не ловит во время компиляции попыток положить в него объект не того класса. Он их ловит только во время исполнения.
2. Использование RTTI снижает производительность операции добавления элемента в контейнер.
3. Взятие элемента из контейнера будет требовать явно прописанного в коде приведения типов, что будет замусоривать исходники.

Это не фатальные недостатки, в конце концов люди жили раньше с одним TObjectList`ом и выкручивались (равно как и с ArrayList в .NET до появления дженериков).


 
Юрий Зотов ©   (2007-11-05 22:43) [119]

> Сусл ©   (05.11.07 21:39) [112]

Дима, я не то что за месяц, я и за 3 месяца вряд ли это напишу. И никто не говорил, что это простая задача. Но решаемая.

Эксперту для проверки валидности класса Item"ов нужен доступ:

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

б). К исходникам проекта. Такой доступ у него тоже есть (через интерфейсы BorlandIDEServices).

Все. Ни какому дереву компиляции доступ не требуется. Да, придется писать парсер. Да, непростой. Да, многое, помимо парсера тоже не будет очень уж просто. Ну и что? Разве это означает принципиальную невозможность? Не означает.

И при чем тут какая-то там экономическая целесообразность? Зачем притягивать за уши аргументы, не имеющие к сабжу никакого отношения?

Уж не говоря о способе [113], когда исходник юнита генерится "на лету".


 
oxffff ©   (2007-11-05 23:30) [120]


> Юрий Зотов ©   (05.11.07 22:43) [119]
> > Сусл ©   (05.11.07 21:39) [112]
>
> Дима, я не то что за месяц, я и за 3 месяца вряд ли это
> напишу. И никто не говорил, что это простая задача. Но решаемая.
>


Есть готовые реализации парсера Delphi. Причем с исходниками.

DGrok?



Страницы: 1 2 3 4 5 вся ветка

Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.75 MB
Время: 0.07 c
15-1194438356
werb
2007-11-07 15:25
2007.12.09
dll список функций


2-1195029126
Новичок
2007-11-14 11:32
2007.12.09
Как сделать TIMESTAMP при сохранения записи.


2-1194928312
San1712
2007-11-13 07:31
2007.12.09
При копировании в Clipboard русских символов изменяется их код-ка


1-1189948331
andreil
2007-09-16 17:12
2007.12.09
Ошибка времени выполнения


15-1194605822
boriskb
2007-11-09 13:57
2007.12.09
Это что? Сайт вроде солидный





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский