Система программирования PascalABC.NET
Дипломная работа - Компьютеры, программирование
Другие дипломы по предмету Компьютеры, программирование
end;
Функция, позволяющая получить из обычного массива массив System.Array:
function GetNullBasedArray(arr: object): System.Array;fi: FieldInfo;:= arr.GetType.GetField(InternalNullBasedArrayName);fi = nil then:= nilResult := System.Array(fi.GetValue(arr));
end;
Функция, которая позволяет вычислить размер типа:
function RunTimeSizeOf(t: System.Type): integer;: System.Type;: object;: array of FieldInfo;: System.Array;: integer;: FieldInfo;t.IsPrimitive thent = typeof(integer) then:= sizeof(integer)if t = typeof(real) then:= sizeof(real)if t = typeof(boolean) then:= sizeof(boolean)if t = typeof(char) then:= sizeof(char)if t = typeof(byte) then:= sizeof(byte)if t = typeof(shortint) then:= sizeof(shortint)if t = typeof(smallint) then:= sizeof(smallint)if t = typeof(word) then:= sizeof(word)if t = typeof(longword) then:= sizeof(longword)if t = typeof(longint) then:= sizeof(longint)if t = typeof(uint64) then:= sizeof(uint64)if t = typeof(single) then:= sizeof(single)if t.IsValueType then:= Activator.CreateInstance(t);:= t.GetFields;:= 0;i:=0 to fa.Length-1 do:= Result + RunTimeSizeOf(fa[i].FieldType):= t.GetField(InternalNullBasedArrayName);fi = nil thennew Exception('Bad Type in RunTimeSizeOf');:= Activator.CreateInstance(t);:= GetNullBasedArray(elem);:= NullBasedArray.GetType.GetElementType;:= RunTimeSizeOf(t1)*NullBasedArray.Length;
end;;
Приведем алгоритм работы последней функции:
Если это примитивный тип то
результат := sizeof(тип)
иначе
если это не ссылочный тип то
результат := просматриваем все поля вычисляя их размер
иначе
//это обычный массив
получаем массив индексируемый с нуля
результат := разимер элемента массива * количество элементов
Процедура чтения одного элемента из типизированного файла имеет вид:
function TypedFileReadT(f: TypedFile; t: System.Type): object;: System.Type;: object;: array of FieldInfo;: System.Array;: integer;t.IsPrimitive thent = typeof(integer) then:= f.br.ReadInt32if t = typeof(real) then:= f.br.ReadDoubleif t = typeof(boolean) then:= f.br.ReadBooleanif t = typeof(char) then:= f.br.ReadCharif t = typeof(byte) then:= f.br.ReadByteif t = typeof(shortint) then:= f.br.ReadSByteif t = typeof(smallint) then:= f.br.ReadInt16if t = typeof(word) then:= f.br.ReadUInt16if t = typeof(longword) then:= f.br.ReadUInt32if t = typeof(longint) then:= f.br.ReadInt64if t = typeof(uint64) then:= f.br.ReadUInt64if t = typeof(single) then:= f.br.ReadSingleif t.IsValueType then:= Activator.CreateInstance(t);:= t.GetFields;i:=0 to fa.Length-1 do[i].SetValue(elem,TypedFileReadT(f,fa[i].FieldType));:= elem;:= Activator.CreateInstance(t);:= GetNullBasedArray(elem);NullBasedArray<>nil then:= NullBasedArray.GetType.GetElementType;i:=0 to NullBasedArray.Length-1 do.SetValue(TypedFileReadT(f,t1),i);;:= elem;;;
Приведем алгоритм работы процедуры чтения:
Если это примитивный тип то
считать из файла элемент соответствующего типа
иначе
если это не ссылочный тип то
создать элемент этого типа
просматриваем все поля и считываем элементы
соответствующего типа
иначе
//это обычный массив
создать такой массив
получаем массив индексируемый с нуля
выясняем тип элементов массива и его длину
считываем необходимое количество элементов
соответствующего типа
Процедура записи одного элемента из типизированного файла имеет вид:
procedure Write(f: TypedFile; val: object);: System.Type;: array of FieldInfo;: integer;: System.Array;:=val.GetType;t.IsPrimitive thent = typeof(integer) then.bw.Write(integer(val))if t = typeof(real) then.bw.Write(real(val))if t = typeof(char) then.bw.Write(char(val))if t = typeof(boolean) then.bw.Write(boolean(val))if t = typeof(byte) then.bw.Write(byte(val))if t = typeof(shortint) then.bw.Write(shortint(val))if t = typeof(smallint) then.bw.Write(smallint(val))if t = typeof(word) then.bw.Write(word(val))if t = typeof(longword) then.bw.Write(longword(val))if t = typeof(longint) then.bw.Write(longint(val))if t = typeof(uint64) then.bw.Write(uint64(val))if t = typeof(single) then.bw.Write(single(val))if t.IsValueType then:= t.GetFields;i:=0 to fa.Length-1 do(f,fa[i].GetValue(val));:= GetNullBasedArray(val);NullBasedArray<>nil theni:=0 to NullBasedArray.Length-1 do(f,NullBasedArray.GetValue(i));
end;;
Алгоритм данной процедуры аналогичен алгоритму чтения из типизированного файла.
Функция, возвращающая размер файла:
function FileSize(f: TypedFile): longint;
beginf.fs.Length mod f.ElementSize <> 0 thennew Exception('Bad typed file size');:= f.fs.Length div f.ElementSize;
end;
Функция, возвращающая текущую позицию в файле:
function FilePos(f: TypedFile): longint;:= f.fs.Position div f.ElementSize;
end;
Процедура, осуществляющая переход к записи с номером n:
procedure Seek(f: TypedFile; n: integer);.fs.Position := n*f.ElementSize;
end;
Процедура, осуществляющая обрезание файла с текущей позиции:
function Eof(f: TypedFile): boolean;f.fs <> nil then:= f.fs.Position = f.fs.Lengthraise new Exception('File not opened');
end;
Как видно из кода, эти файлы реализованы на базе стандартных потоков System.IO.BinaryReader и System.IO.BinaryWriter. Обращение к компонентам элемента файла реализовано с помощью рефлексии. Процедура write полностью реализована на самом языке PascalABC.NET за исключением проверок параметров во время этапа компиляции.
7.2.4.2 Генерация узла семантического дерева
Процесс семантического анализа типизированых файлов происходит следующим образом: во время компиляции семантический анализатор находит уже переведенный в семантическое дерево тип TypedFile. В начале блока, где обявляется переменная этого типа, вставляются команды создания этого типа с параметром - типом элементов.
public void visit(SyntaxTree.file_type _file_type)
{
//Типизированый файл_node el_type =_strong(_file_type.file_of_type);(!CanUseThisTypeForTypedFiles(el_type))new InvalidElementTypeForTypedFile(el_type, get_location(_file_type.file_of_type));_value(context.create_typed_file_type(el_type, get_location(_file_type)));
}
Перевод бинарного файла происходит аналогично, за исключением того, что ему не нужно знать тип своих элементов.
7.2.4.3 Проверки этапа компиляции
На этапе компиляции необходимо делается проверка на допустимость элементов для типизированных файлов. Данная проверка раеализована с помощю рекурсивной функции CanUseThisTypeForTypedFiles:bool CanUseThisTypeForTypedFiles(type_node el_type)
{(el_type.is_value)
{
//проверка на пимитивный тип(SystemLibrary.CanUseThisTypeForTypedFiles(el_type))true;
//это запись(el_type is common_type_node)
{_type_node ctn = el_type as common_type_node;(class_field cf in ctn.fields)(!CanUseThisTypeForTypedFiles(cf.type))false;true;
}
//Это откомпилированная запись(el_type is compiled_type_node)
{_type_node ctn = el_type as_type_node;.Reflection.FieldInfo[] fields =.compiled_type.GetFields();(System.Reflection.FieldInfo fi in fields)(!fi.IsStatic)(!CanUseThisTypeForTypedFiles(_type_node.get_type_node(fi.FieldType)))false;true;
}
}(IsBoudedArray(el_type))
{
//это обычный массив_array_interface bai = (bounded_array_interface)el_type.get_internal_interface(internal_interface_kind.bounded_array_interface);CanUseThisTypeForTypedFiles(bai.element_type);
}false;
}
С помощью рекурсии обходятся все поля типа и проверяются на допустимость для типизированного файла. Необходимо отметить, что хотя в .NET массив представлятся ссылочным типом, в PascalABC.NET о