19477 lines
1 MiB
19477 lines
1 MiB
// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
|
||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||
//Посетитель синтаксического дерева.
|
||
using System;
|
||
using System.Linq;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using PascalABCCompiler.SyntaxTree;
|
||
using PascalABCCompiler.TreeRealization;
|
||
|
||
using SyntaxTreeBuilder = PascalABCCompiler.SyntaxTree.SyntaxTreeBuilder;
|
||
using SymTable = SymbolTable;
|
||
using array_const = PascalABCCompiler.TreeRealization.array_const;
|
||
using compiler_directive = PascalABCCompiler.TreeRealization.compiler_directive;
|
||
using empty_statement = PascalABCCompiler.TreeRealization.empty_statement;
|
||
using for_node = PascalABCCompiler.TreeRealization.for_node;
|
||
using goto_statement = PascalABCCompiler.TreeRealization.goto_statement;
|
||
using if_node = PascalABCCompiler.TreeRealization.if_node;
|
||
using labeled_statement = PascalABCCompiler.TreeRealization.labeled_statement;
|
||
using question_colon_expression = PascalABCCompiler.TreeRealization.question_colon_expression;
|
||
using repeat_node = PascalABCCompiler.TreeRealization.repeat_node;
|
||
using sizeof_operator = PascalABCCompiler.TreeRealization.sizeof_operator;
|
||
using typeof_operator = PascalABCCompiler.TreeRealization.typeof_operator;
|
||
using while_node = PascalABCCompiler.TreeRealization.while_node;
|
||
using TreeConverter.LambdaExpressions.Closure;
|
||
using TreeConverter.LambdaExpressions;
|
||
|
||
namespace PascalABCCompiler.TreeConverter
|
||
{
|
||
// Сахарный узел синтаксического дерева. Не генерируется автоматически, поскольку содержит ссылку на узел семантического дерева
|
||
// Нужен только при генерации синтаксических узлов на семантическом уровне, т.е. для синтаксического сахара
|
||
/* public class semantic_type_node : SyntaxTree.type_definition
|
||
{
|
||
public type_node type { get; set; }
|
||
public semantic_type_node(type_node t)
|
||
{
|
||
type = t;
|
||
}
|
||
}*/
|
||
|
||
public partial class syntax_tree_visitor : SyntaxTree.WalkingVisitorNew // SSM 02.01.17 менять на визитор с другим порядком обхода можно, но бессмысленно
|
||
// Порядок обхода не важен поскольку все узлы visit переопределяются
|
||
// SSM 02.01.17 Использование ReplaceStatement из BaseChangeVisitor плохо изучено - что-то не работает
|
||
// Поэтому используется явный Parent и ReplaceStatement из узла statement_list
|
||
{
|
||
public convertion_data_and_alghoritms convertion_data_and_alghoritms;
|
||
|
||
internal returner ret;
|
||
|
||
internal document current_document;
|
||
|
||
public compilation_context context;
|
||
public ContextChanger contextChanger;
|
||
|
||
internal using_namespace_list using_list = new using_namespace_list();
|
||
internal using_namespace_list interface_using_list = new using_namespace_list();
|
||
|
||
// SSM 6/08/15 Стек для хранения вложенных лямбд для одной цели - вычислить истинный тип выражения, присваиваемого Result. Это нужно для выбора перегруженной функции, у которой параметр лямбда и один из типов возвращаемого значения в точности совпадает с типом возвращаемого значения лямбды
|
||
internal Stack<function_lambda_definition> stflambda = new Stack<function_lambda_definition>();
|
||
|
||
//TODO: Загнать в request.
|
||
motivation_keeper motivation_keeper = new motivation_keeper();
|
||
|
||
private PascalABCCompiler.TreeRealization.unit_node_list _referenced_units;
|
||
|
||
private common_unit_node _compiled_unit;
|
||
|
||
private common_unit_node _system_unit;
|
||
internal bool debug=true;
|
||
internal bool debugging=false;
|
||
internal List<Errors.Error> ErrorsList;
|
||
internal List<Errors.CompilerWarning> WarningsList;
|
||
internal Dictionary<SyntaxTree.syntax_tree_node,string> docs;
|
||
public bool for_native_code = false;
|
||
internal Dictionary<SyntaxTree.syntax_tree_node, SyntaxTree.compiler_directive> DirectivesToNodesLinks;
|
||
public bool ThrowCompilationError = true;
|
||
public bool MustVisitBody = true;
|
||
public LambdaProcessingState lambdaProcessingState = LambdaProcessingState.None; //lroman
|
||
|
||
#region (MikhailoMMX) Положение визитора относительно параллельных конструкций
|
||
public ParallelPosition CurrentParallelPosition = ParallelPosition.Outside;
|
||
#endregion
|
||
|
||
private int num = 0;
|
||
|
||
public string UniqueNumStr()
|
||
{
|
||
num++;
|
||
return num.ToString();
|
||
}
|
||
|
||
internal Errors.Error LastError()
|
||
{
|
||
Errors.Error err = ErrorsList[ErrorsList.Count-1];
|
||
ErrorsList.RemoveAt(ErrorsList.Count - 1);
|
||
return err;
|
||
}
|
||
|
||
internal void RemoveLastError()
|
||
{
|
||
ErrorsList.RemoveAt(ErrorsList.Count - 1);
|
||
}
|
||
|
||
internal void AddError(Errors.Error err, bool shouldReturn=false)
|
||
{
|
||
if (ThrowCompilationError || !shouldReturn /*|| err.MustThrow && !shouldReturn*/)
|
||
{
|
||
throw err;
|
||
}
|
||
else
|
||
{
|
||
ErrorsList.Add(err);
|
||
}
|
||
}
|
||
|
||
internal void AddError(location loc, string ErrResourceString, params object[] values)
|
||
{
|
||
Errors.Error err = new SimpleSemanticError(loc, ErrResourceString, values);
|
||
if (ThrowCompilationError)
|
||
{
|
||
throw err;
|
||
}
|
||
else
|
||
{
|
||
ErrorsList.Add(err);
|
||
}
|
||
}
|
||
|
||
internal void AddWarning(Errors.CompilerWarning err)
|
||
{
|
||
WarningsList.Add(err);
|
||
}
|
||
|
||
private bool _record_created = false;
|
||
|
||
private bool with_class_name=false;
|
||
|
||
internal bool from_pabc_dll = false;
|
||
|
||
private bool type_section_converting = false;
|
||
|
||
private Dictionary<expression_node, expressions_list> set_intls = new Dictionary<expression_node, expressions_list>();
|
||
|
||
//(ssyy) Дополнительные ограничения на параметры generic-типа.
|
||
//Например, возможность объявить указатель на этот тип-параметр.
|
||
internal Dictionary<type_node, GenericParameterAbilities> generic_param_abilities =
|
||
new Dictionary<type_node, GenericParameterAbilities>();
|
||
|
||
private GenericParameterAbilities get_type_abilities(type_node t)
|
||
{
|
||
GenericParameterAbilities gpa;
|
||
if (generic_param_abilities.TryGetValue(t, out gpa)) return gpa;
|
||
gpa = new GenericParameterAbilities();
|
||
generic_param_abilities.Add(t, gpa);
|
||
return gpa;
|
||
}
|
||
|
||
private void internal_reset()
|
||
{
|
||
PascalABCCompiler.SystemLibrary.SystemLibInitializer.initialization_properties init_properties =
|
||
new PascalABCCompiler.SystemLibrary.SystemLibInitializer.initialization_properties();
|
||
|
||
init_properties.break_executor = make_break_node;
|
||
init_properties.continue_executor = make_continue_node;
|
||
init_properties.exit_executor = make_exit_node;
|
||
|
||
_system_unit = SystemLibrary.SystemLibInitializer.make_system_unit(convertion_data_and_alghoritms.symbol_table,
|
||
init_properties);
|
||
SystemLibrary.SystemLibrary.system_unit = _system_unit;
|
||
generic_convertions.reset_generics();
|
||
_record_created = false;
|
||
RefTypesForCheckPointersTypeForDotNetFramework.Clear();
|
||
reset_for_interface();
|
||
_is_interface_part = false;
|
||
with_class_name=false;
|
||
generic_param_abilities.Clear();
|
||
current_converted_method_not_in_class_defined = false;
|
||
assign_is_converting = false;
|
||
motivation_keeper.reset();
|
||
SystemLibrary.SystemLibInitializer.NeedsToRestore.Clear();
|
||
type_section_converting = false;
|
||
ThrowCompilationError = true;
|
||
#region MikhailoMMX, реинициализация класса OpenMP
|
||
OpenMP.InternalReset();
|
||
CurrentParallelPosition = ParallelPosition.Outside;
|
||
#endregion
|
||
|
||
lambdaProcessingState = LambdaProcessingState.None; //lroman
|
||
CapturedVariablesSubstitutionClassGenerator.Reset();
|
||
}
|
||
|
||
public syntax_tree_visitor()
|
||
{
|
||
convertion_data_and_alghoritms = new convertion_data_and_alghoritms(this);
|
||
|
||
ret = new returner(this);
|
||
context = new compilation_context(convertion_data_and_alghoritms, this);
|
||
contextChanger = new ContextChanger(context);
|
||
internal_reset();
|
||
}
|
||
|
||
|
||
private void release_system_module()
|
||
{
|
||
SystemUnitAssigned = false;
|
||
SystemLibrary.SystemLibInitializer.format_function = null;
|
||
SystemLibrary.SystemLibInitializer.read_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.write_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.writeln_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.readln_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.TextFileType = null;
|
||
SystemLibrary.SystemLibInitializer.TextFileInitProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.BinaryFileType = null;
|
||
SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = null;
|
||
SystemLibrary.SystemLibInitializer.PointerOutputType = null;
|
||
SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.TypedFileType = null;
|
||
SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.ShortStringType = null;
|
||
SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.TypedSetType = null;
|
||
SystemLibrary.SystemLibInitializer.SetUnionProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SetIntersectProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SetSubtractProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.InSetProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.CreateSetProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.IncludeProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.ExcludeProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.DiapasonType = null;
|
||
SystemLibrary.SystemLibInitializer.CreateDiapason = null;
|
||
SystemLibrary.SystemLibInitializer.CreateObjDiapason = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetEquals = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetInEquals = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetLess = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetLessEqual = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreater = null;
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = null;
|
||
SystemLibrary.SystemLibInitializer.IncProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.DecProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SuccFunction = null;
|
||
SystemLibrary.SystemLibInitializer.PredFunction = null;
|
||
SystemLibrary.SystemLibInitializer.OrdFunction = null;
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = null;
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = null;
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = null;
|
||
SystemLibrary.SystemLibInitializer.ClipProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.ClipFunction = null;
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = null;
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.SetLengthProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.read_short_string_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = null;
|
||
SystemLibrary.SystemLibInitializer.InsertProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.DeleteProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.LowFunction = null;
|
||
SystemLibrary.SystemLibInitializer.HighFunction = null;
|
||
SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.PointerToStringFunction = null;
|
||
SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.PointerOutputConstructor = null;
|
||
SystemLibrary.SystemLibInitializer.StrProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.AssertProcedure = null;
|
||
SystemLibrary.SystemLibInitializer.CheckRangeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = null;
|
||
SystemLibrary.SystemLibInitializer.ArrayCopyFunction = null;
|
||
SystemLibrary.SystemLibInitializer.ObjectType = null;
|
||
SystemLibrary.SystemLibInitializer.StringType = null;
|
||
SystemLibrary.SystemLibInitializer.ConfigVariable = null;
|
||
}
|
||
|
||
internal bool SystemUnitAssigned = false;
|
||
|
||
public static void init_system_module(common_unit_node psystem_unit)
|
||
{
|
||
SystemLibrary.SystemLibInitializer.format_function = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.format_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.write_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.write_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.writeln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.writeln_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.readln_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.TextFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.text_file_name_type_name);
|
||
SystemLibrary.SystemLibInitializer.TextFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TextFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AbstractBinaryFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.PointerOutputType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PointerOutputTypeName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileReadProcedureName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.StringDefaultPropertySetProcedureName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileReadProcedureName);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortString);
|
||
SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.GetCharInShortString);
|
||
SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.SetCharInShortString);
|
||
//SystemLibrary.SystemLibInitializer.ShortStringType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ShortStringTypeName);
|
||
//SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ShortStringTypeInitProcedure);
|
||
SystemLibrary.SystemLibInitializer.TypedSetType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_name);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitProcedure);
|
||
SystemLibrary.SystemLibInitializer.SetUnionProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.union_of_set);
|
||
SystemLibrary.SystemLibInitializer.SetIntersectProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.intersect_of_set);
|
||
SystemLibrary.SystemLibInitializer.SetSubtractProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.subtract_of_set);
|
||
SystemLibrary.SystemLibInitializer.InSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.in_set);
|
||
SystemLibrary.SystemLibInitializer.CreateSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.IncludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.IncludeProcedure);
|
||
SystemLibrary.SystemLibInitializer.ExcludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ExcludeProcedure);
|
||
SystemLibrary.SystemLibInitializer.DiapasonType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.DiapasonType);
|
||
SystemLibrary.SystemLibInitializer.CreateDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateDiapason);
|
||
SystemLibrary.SystemLibInitializer.CreateObjDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateObjDiapason);
|
||
SystemLibrary.SystemLibInitializer.CompareSetEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetEquals);
|
||
SystemLibrary.SystemLibInitializer.CompareSetInEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetInEquals);
|
||
SystemLibrary.SystemLibInitializer.CompareSetLess = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetLess);
|
||
SystemLibrary.SystemLibInitializer.CompareSetLessEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetLessEqual);
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreater = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetGreater);
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetGreaterEqual);
|
||
SystemLibrary.SystemLibInitializer.IncProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.IncProcedure);
|
||
SystemLibrary.SystemLibInitializer.DecProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.DecProcedure);
|
||
SystemLibrary.SystemLibInitializer.SuccFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.SuccFunction);
|
||
SystemLibrary.SystemLibInitializer.PredFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PredFunction);
|
||
SystemLibrary.SystemLibInitializer.OrdFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.OrdFunction);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitProcedureWithBounds);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitWithShortString);
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssignSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssignSetProcedureWithBounds);
|
||
SystemLibrary.SystemLibInitializer.ClipProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipProcedure);
|
||
SystemLibrary.SystemLibInitializer.ClipFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipFunction);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortStringInSetFunction);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortStringInSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_length_for_short_string);
|
||
SystemLibrary.SystemLibInitializer.SetLengthProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_length_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.read_short_string_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_short_string);
|
||
SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_short_string_from_file);
|
||
SystemLibrary.SystemLibInitializer.InsertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,compiler_string_consts.Insert);
|
||
SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,compiler_string_consts.InsertInShortString);
|
||
SystemLibrary.SystemLibInitializer.DeleteProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,compiler_string_consts.Delete);
|
||
SystemLibrary.SystemLibInitializer.LowFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit,compiler_string_consts.Low);
|
||
SystemLibrary.SystemLibInitializer.HighFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit,compiler_string_consts.High);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUsePointerOnType_proc_name);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUseTypeForBinaryFiles_proc_name);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUseTypeForTypedFiles_proc_name);
|
||
SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.RuntimeDetermineType_func_name);
|
||
SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.RuntimeInitializeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.PointerToStringFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PointerToStringFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.GetRuntimeSizeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.StrProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.StrProcedure_func_name);
|
||
SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ChrUnicodeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.AssertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssertProcedure);
|
||
SystemLibrary.SystemLibInitializer.CheckRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.check_in_range);
|
||
SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.check_in_range_char);
|
||
SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CopyWithSizeFunction);
|
||
SystemLibrary.SystemLibInitializer.ArrayCopyFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ArrayCopyFunction);
|
||
SystemLibrary.SystemLibInitializer.ConfigVariable = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.config_variable_name);
|
||
//SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,SystemLibrary.SystemLibrary.string_type,type_compare.less_type,SemanticTree.basic_function_type.none,true);
|
||
//SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibrary.string_type,SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,type_compare.greater_type,SemanticTree.basic_function_type.none,true);
|
||
if (SystemLibrary.SystemLibInitializer.TextFileType.Found)
|
||
SystemLibrary.SystemLibInitializer.TextFileType.TypeNode.type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file;
|
||
if (SemanticRules.GenerateNativeCode)
|
||
{
|
||
SystemLibrary.SystemLibInitializer.ObjectType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ObjectType);
|
||
if (SystemLibrary.SystemLibInitializer.ObjectType.Found)
|
||
SemanticRules.ClassBaseType = SystemLibrary.SystemLibInitializer.ObjectType.sym_info as TreeRealization.type_node;
|
||
SystemLibrary.SystemLibInitializer.StringType = new PascalABCCompiler.SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.StringType);
|
||
if (SystemLibrary.SystemLibInitializer.StringType.Found)
|
||
SemanticRules.StringType = SystemLibrary.SystemLibInitializer.StringType.sym_info as TreeRealization.type_node;
|
||
}
|
||
}
|
||
|
||
public static void init_system_module_from_dll(dot_net_unit_node psystem_unit)
|
||
{
|
||
SystemLibrary.SystemLibInitializer.format_function = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.format_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.write_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.write_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.writeln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.writeln_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.readln_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.TextFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.text_file_name_type_name);
|
||
SystemLibrary.SystemLibInitializer.TextFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TextFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AbstractBinaryFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.PointerOutputType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PointerOutputTypeName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileReadProcedureName);
|
||
SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.BinaryFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.StringDefaultPropertySetProcedureName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileTypeName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileInitProcedureName);
|
||
SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedFileReadProcedureName);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortString);
|
||
SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.GetCharInShortString);
|
||
SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.SetCharInShortString);
|
||
//SystemLibrary.SystemLibInitializer.ShortStringType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ShortStringTypeName);
|
||
//SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ShortStringTypeInitProcedure);
|
||
SystemLibrary.SystemLibInitializer.TypedSetType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_name);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitProcedure);
|
||
SystemLibrary.SystemLibInitializer.SetUnionProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.union_of_set);
|
||
SystemLibrary.SystemLibInitializer.SetIntersectProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.intersect_of_set);
|
||
SystemLibrary.SystemLibInitializer.SetSubtractProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.subtract_of_set);
|
||
SystemLibrary.SystemLibInitializer.InSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.in_set);
|
||
SystemLibrary.SystemLibInitializer.CreateSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.IncludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.IncludeProcedure);
|
||
SystemLibrary.SystemLibInitializer.ExcludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ExcludeProcedure);
|
||
SystemLibrary.SystemLibInitializer.DiapasonType = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.DiapasonType);
|
||
SystemLibrary.SystemLibInitializer.CreateDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateDiapason);
|
||
SystemLibrary.SystemLibInitializer.CreateObjDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CreateObjDiapason);
|
||
SystemLibrary.SystemLibInitializer.CompareSetEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetEquals);
|
||
SystemLibrary.SystemLibInitializer.CompareSetInEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetInEquals);
|
||
SystemLibrary.SystemLibInitializer.CompareSetLess = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetLess);
|
||
SystemLibrary.SystemLibInitializer.CompareSetLessEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetLessEqual);
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreater = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetGreater);
|
||
SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CompareSetGreaterEqual);
|
||
SystemLibrary.SystemLibInitializer.IncProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.IncProcedure);
|
||
SystemLibrary.SystemLibInitializer.DecProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.DecProcedure);
|
||
SystemLibrary.SystemLibInitializer.SuccFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.SuccFunction);
|
||
SystemLibrary.SystemLibInitializer.PredFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PredFunction);
|
||
SystemLibrary.SystemLibInitializer.OrdFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.OrdFunction);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitProcedureWithBounds);
|
||
SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.TypedSetInitWithShortString);
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssignSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssignSetProcedureWithBounds);
|
||
SystemLibrary.SystemLibInitializer.ClipProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipProcedure);
|
||
SystemLibrary.SystemLibInitializer.ClipFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipFunction);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortStringInSetFunction);
|
||
SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ClipShortStringInSetProcedure);
|
||
SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_length_for_short_string);
|
||
SystemLibrary.SystemLibInitializer.SetLengthProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.set_length_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.read_short_string_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_short_string);
|
||
SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.read_short_string_from_file);
|
||
SystemLibrary.SystemLibInitializer.InsertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.Insert);
|
||
SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.InsertInShortString);
|
||
SystemLibrary.SystemLibInitializer.DeleteProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.Delete);
|
||
SystemLibrary.SystemLibInitializer.LowFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.Low);
|
||
SystemLibrary.SystemLibInitializer.HighFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.High);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUsePointerOnType_proc_name);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUseTypeForBinaryFiles_proc_name);
|
||
SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CheckCanUseTypeForTypedFiles_proc_name);
|
||
SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.RuntimeDetermineType_func_name);
|
||
SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.RuntimeInitializeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.PointerToStringFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.PointerToStringFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.GetRuntimeSizeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.StrProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.StrProcedure_func_name);
|
||
SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ChrUnicodeFunction_func_name);
|
||
SystemLibrary.SystemLibInitializer.AssertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.AssertProcedure);
|
||
SystemLibrary.SystemLibInitializer.CheckRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.check_in_range);
|
||
SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.check_in_range_char);
|
||
SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.CopyWithSizeFunction);
|
||
SystemLibrary.SystemLibInitializer.ArrayCopyFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.ArrayCopyFunction);
|
||
SystemLibrary.SystemLibInitializer.ConfigVariable = new SystemLibrary.UnitDefinitionItem(psystem_unit, compiler_string_consts.config_variable_name);
|
||
//AddSpecialOperatorsToSetType();
|
||
//SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,SystemLibrary.SystemLibrary.string_type,type_compare.less_type,SemanticTree.basic_function_type.none,true);
|
||
//SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibrary.string_type,SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,type_compare.greater_type,SemanticTree.basic_function_type.none,true);
|
||
if (SystemLibrary.SystemLibInitializer.TextFileType.Found)
|
||
SystemLibrary.SystemLibInitializer.TextFileType.TypeNode.type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file;
|
||
}
|
||
|
||
private void get_system_module(common_unit_node psystem_unit)
|
||
{
|
||
init_system_module(psystem_unit);
|
||
//esli zapustili v otladke, to vosstanovim mnozhestvo i procedury sozdanija diapasonov, inache ne budet rabotat
|
||
if (debugging)
|
||
{
|
||
SymbolInfo si = SystemLibrary.SystemLibInitializer.CreateDiapason.SymbolInfo;
|
||
si = SystemLibrary.SystemLibInitializer.CreateObjDiapason.SymbolInfo;
|
||
si = SystemLibrary.SystemLibInitializer.TypedSetType.SymbolInfo;
|
||
}
|
||
//if (SystemLibrary.SystemLibInitializer.TextFileType.Found)
|
||
// SystemLibrary.SystemLibInitializer.TextFileType.GetTypeNodeSpecials().type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file;
|
||
SystemUnitAssigned = true;
|
||
CreateSpecialFields(psystem_unit);
|
||
}
|
||
|
||
private void get_system_module_from_dll(dot_net_unit_node psystem_unit)
|
||
{
|
||
init_system_module_from_dll(psystem_unit);
|
||
//esli zapustili v otladke, to vosstanovim mnozhestvo i procedury sozdanija diapasonov, inache ne budet rabotat
|
||
if (debugging)
|
||
{
|
||
SymbolInfo si = SystemLibrary.SystemLibInitializer.CreateDiapason.SymbolInfo;
|
||
si = SystemLibrary.SystemLibInitializer.CreateObjDiapason.SymbolInfo;
|
||
si = SystemLibrary.SystemLibInitializer.TypedSetType.SymbolInfo;
|
||
}
|
||
//if (SystemLibrary.SystemLibInitializer.TextFileType.Found)
|
||
// SystemLibrary.SystemLibInitializer.TextFileType.GetTypeNodeSpecials().type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file;
|
||
SystemUnitAssigned = true;
|
||
//CreateSpecialFields(psystem_unit);
|
||
}
|
||
|
||
private void AddSpecialOperatorsToSetType()
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.TypedSetType.NotFound)
|
||
return;
|
||
common_type_node tctn = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as common_type_node;
|
||
tctn.type_special_kind = SemanticTree.type_special_kind.base_set_type;
|
||
tctn.scope.AddSymbol(compiler_string_consts.plus_name, SystemLibrary.SystemLibInitializer.SetUnionProcedure.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.mul_name, SystemLibrary.SystemLibInitializer.SetIntersectProcedure.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.in_name, SystemLibrary.SystemLibInitializer.InSetProcedure.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.minus_name, SystemLibrary.SystemLibInitializer.SetSubtractProcedure.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.gr_name, SystemLibrary.SystemLibInitializer.CompareSetGreater.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.greq_name, SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.sm_name, SystemLibrary.SystemLibInitializer.CompareSetLess.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.smeq_name, SystemLibrary.SystemLibInitializer.CompareSetLessEqual.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.eq_name, SystemLibrary.SystemLibInitializer.CompareSetEquals.SymbolInfo);
|
||
tctn.scope.AddSymbol(compiler_string_consts.noteq_name, SystemLibrary.SystemLibInitializer.CompareSetInEquals.SymbolInfo);
|
||
}
|
||
|
||
private void CreateSpecialFields(common_unit_node psystem_unit)
|
||
{
|
||
SymbolInfo si = psystem_unit.scope.Find(compiler_string_consts.IsConsoleApplicationVariableName);
|
||
if (si != null && si.sym_info is namespace_variable)
|
||
{
|
||
namespace_variable_reference nvr = new namespace_variable_reference(si.sym_info as namespace_variable, null);
|
||
psystem_unit.IsConsoleApplicationVariableAssignExpr = make_assign_operator(nvr, psystem_unit.IsConsoleApplicationVariableValue, null);
|
||
}
|
||
}
|
||
|
||
private void UpdateUnitDefinitionItemForUnit(common_unit_node unit)
|
||
{
|
||
if (!from_pabc_dll)
|
||
{
|
||
SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(unit, compiler_string_consts.read_procedure_name);
|
||
SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(unit, compiler_string_consts.readln_procedure_name);
|
||
}
|
||
else
|
||
{
|
||
//SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(unit, compiler_string_consts.read_procedure_name);
|
||
//SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(unit, compiler_string_consts.readln_procedure_name);
|
||
}
|
||
}
|
||
|
||
public void reset()
|
||
{
|
||
_system_unit = null;
|
||
SystemLibrary.SystemLibrary.system_unit = null;
|
||
//SystemLibrary.SystemLibrary.Reset();
|
||
SystemUnitAssigned = false;
|
||
_compiled_unit = null;
|
||
_referenced_units = null;
|
||
current_document = null;
|
||
using_list.clear();
|
||
//_referenced_units.clear();
|
||
ret.reset();
|
||
motivation_keeper.reset();
|
||
context.reset();
|
||
convertion_data_and_alghoritms.reset();
|
||
//compiled_type_node.compiled_types.Clear();
|
||
internal_reset();
|
||
release_system_module();
|
||
WaitedRefTypes.Clear();
|
||
set_intls.Clear();
|
||
NetHelper.NetHelper.reset();
|
||
if (ErrorsList != null)
|
||
ErrorsList.Clear();
|
||
from_pabc_dll = false;
|
||
in_interface_part = false;
|
||
compiled_type_node[] ctns = new compiled_type_node[compiled_type_node.compiled_types.Values.Count];
|
||
compiled_type_node.compiled_types.Values.CopyTo(ctns, 0);
|
||
null_type_node.reset();
|
||
foreach (compiled_type_node ctn in ctns)
|
||
{
|
||
ctn.reinit_scope();
|
||
ctn.clear_generated_names();
|
||
ctn.clear_generated_intersections();
|
||
}
|
||
}
|
||
|
||
public PascalABCCompiler.Errors.SyntaxError parser_error
|
||
{
|
||
get
|
||
{
|
||
return convertion_data_and_alghoritms.parser_error;
|
||
}
|
||
set
|
||
{
|
||
convertion_data_and_alghoritms.parser_error = value;
|
||
}
|
||
}
|
||
public System.Collections.Hashtable bad_nodes_in_syntax_tree
|
||
{
|
||
get
|
||
{
|
||
return convertion_data_and_alghoritms.bad_nodes_in_syntax_tree;
|
||
}
|
||
set
|
||
{
|
||
convertion_data_and_alghoritms.bad_nodes_in_syntax_tree = value;
|
||
}
|
||
|
||
}
|
||
|
||
public PascalABCCompiler.TreeRealization.document CurrentDocument
|
||
{
|
||
get
|
||
{
|
||
return current_document;
|
||
}
|
||
}
|
||
|
||
public SymbolTable.TreeConverterSymbolTable SymbolTable
|
||
{
|
||
get
|
||
{
|
||
return convertion_data_and_alghoritms.symbol_table;
|
||
}
|
||
}
|
||
|
||
public location get_location(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
if (tn.source_context == null)
|
||
{
|
||
return null;
|
||
}
|
||
document d = current_document;
|
||
if (tn.source_context.FileName != null && (d == null || d.file_name != tn.source_context.FileName))
|
||
d = new document(tn.source_context.FileName);
|
||
return new location(tn.source_context.begin_position.line_num, tn.source_context.begin_position.column_num,
|
||
tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, d);
|
||
}
|
||
public location get_right_location(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
if (tn.source_context == null)
|
||
{
|
||
return null;
|
||
}
|
||
return new location(tn.source_context.end_position.line_num, tn.source_context.end_position.column_num,
|
||
tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, current_document);
|
||
}
|
||
|
||
public location get_location_with_check(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
if (tn == null || tn.source_context == null)
|
||
{
|
||
return null;
|
||
}
|
||
document d = current_document;
|
||
if (tn.source_context.FileName != null)
|
||
d = new document(tn.source_context.FileName);
|
||
return new location(tn.source_context.begin_position.line_num, tn.source_context.begin_position.column_num,
|
||
tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, d);
|
||
}
|
||
|
||
public common_unit_node compiled_unit
|
||
{
|
||
get
|
||
{
|
||
return _compiled_unit;
|
||
}
|
||
//TODO: Нужен ли set?
|
||
set
|
||
{
|
||
_compiled_unit = value;
|
||
}
|
||
}
|
||
|
||
public PascalABCCompiler.TreeRealization.unit_node_list referenced_units
|
||
{
|
||
get
|
||
{
|
||
return _referenced_units;
|
||
}
|
||
set
|
||
{
|
||
_referenced_units = value;
|
||
}
|
||
}
|
||
|
||
//TODO: Может вынести всю работу с returner-ами в convertion_data_and_alghoritms?
|
||
//Методы returner-а.
|
||
//Запрос на построение и получение конвертированного поддерева.
|
||
//Нежесткая проверка существования узла.
|
||
private statement_node convert_weak(SyntaxTree.statement st)
|
||
{
|
||
if (st == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(st);
|
||
|
||
//st = prepare_statement(st);
|
||
|
||
statement_node sn = ret.visit(st);
|
||
//sn.loc=get_location(st);
|
||
return sn;
|
||
}
|
||
|
||
private expression_node convert_weak(SyntaxTree.expression expr)
|
||
{
|
||
if (expr == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(expr);
|
||
|
||
//Посмотреть, может вызвать ошибку
|
||
//ssyy
|
||
motivation_keeper.reset();
|
||
//\ssyy
|
||
|
||
expression_node en = ret.visit(expr);
|
||
//en.loc=get_location(expr);
|
||
return en;
|
||
}
|
||
|
||
private type_node convert_weak(SyntaxTree.type_definition type_def)
|
||
{
|
||
if (type_def == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(type_def);
|
||
|
||
return ret.visit(type_def);
|
||
}
|
||
|
||
//Жесткая проверка существования узла. Проверка будет осуществлятся только в DEBUG версии.
|
||
//Будем верить, что в RELEAS-е все будет работать правильно.
|
||
private semantic_node convert_semantic_strong(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
#if (DEBUG)
|
||
if (tn == null)
|
||
{
|
||
throw new CompilerInternalError("This syntax tree node can not be null.");
|
||
}
|
||
#endif
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(tn);
|
||
motivation_keeper.set_motivation_to_expect_semantic_node();
|
||
return ret.visit(tn);
|
||
}
|
||
|
||
internal statement_node convert_strong(SyntaxTree.statement st)
|
||
{
|
||
#if (DEBUG)
|
||
if (st == null)
|
||
{
|
||
throw new CompilerInternalError("This syntax tree node can not be null.");
|
||
}
|
||
#endif
|
||
|
||
#region MikhailoMMX, обработка критических секций OpenMP
|
||
bool isCritical = false;
|
||
SyntaxTree.statement st_orig = st;
|
||
if (OpenMP.LocksFound)
|
||
if (DirectivesToNodesLinks.ContainsKey(st) && OpenMP.IsCriticalDirective(DirectivesToNodesLinks[st]))
|
||
{
|
||
//если перед узлом есть директива omp critical
|
||
isCritical = true;
|
||
OpenMP.TryConvertCritical(ref st, this, DirectivesToNodesLinks[st]);
|
||
OpenMP.DisableDirective(st_orig, DirectivesToNodesLinks);
|
||
}
|
||
#endregion
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(st);
|
||
|
||
//st = prepare_statement(st);
|
||
statement_node sn = null;
|
||
//try
|
||
{
|
||
sn = ret.visit(st);
|
||
// SSM 19/01/17 закомментировал две следующие строчки
|
||
//if (sn == null)
|
||
// sn = new empty_statement(null);
|
||
}
|
||
/*catch (PascalABCCompiler.Errors.Error e)
|
||
{
|
||
if (ThrowCompilationError)
|
||
throw e;
|
||
else
|
||
{
|
||
ErrorsList.Add(e);
|
||
return new empty_statement(null);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
if (ThrowCompilationError)
|
||
throw e;
|
||
else
|
||
return new empty_statement(null);
|
||
}*/
|
||
//sn.loc=get_location(st);
|
||
|
||
#region MikhailoMMX, обработка критических секций OpenMP
|
||
if (isCritical)
|
||
OpenMP.EnableDirective(st_orig, DirectivesToNodesLinks);
|
||
#endregion
|
||
|
||
return sn;
|
||
}
|
||
|
||
internal expression_node convert_strong(SyntaxTree.expression expr)
|
||
{
|
||
#if (DEBUG)
|
||
if (expr == null)
|
||
{
|
||
throw new CompilerInternalError("This syntax tree node can not be null.");
|
||
}
|
||
#endif
|
||
//if (expr.semantic_ex != null) // SSM 3.1.17 - возвращаем кешированное значение
|
||
// return expr.semantic_ex as expression_node;
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(expr);
|
||
|
||
//Посмотреть, может вызвать ошибку
|
||
//ssyy
|
||
motivation_keeper.reset(); // Это можно закомментировать - все тесты проходят SSM 2/1/17
|
||
//\ssyy
|
||
expression_node en = ret.visit(expr);
|
||
//expr.semantic_ex = en; // SSM 3.1.17 кешируем для последующего обращения
|
||
|
||
//en.loc=get_location(expr);
|
||
|
||
return en;
|
||
}
|
||
|
||
internal type_node convert_strong(SyntaxTree.type_definition type_def)
|
||
{
|
||
#if (DEBUG)
|
||
if (type_def == null)
|
||
{
|
||
throw new CompilerInternalError("This syntax tree node can not be null.");
|
||
}
|
||
#endif
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(type_def);
|
||
|
||
type_node tn;
|
||
SyntaxTree.function_header fh = (type_def as SyntaxTree.function_header);
|
||
if (fh != null)
|
||
{
|
||
tn = convert_function_type(fh, get_location(type_def), context.get_delegate_type_name(), null);
|
||
return tn;
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.procedure_header ph = (type_def as SyntaxTree.procedure_header);
|
||
if (ph != null)
|
||
{
|
||
tn = convert_function_type(ph, get_location(type_def), context.get_delegate_type_name(), null);
|
||
return tn;
|
||
}
|
||
}
|
||
if (is_direct_type_decl && !(type_def is SyntaxTree.ref_type)) is_direct_type_decl = false;
|
||
return ret.visit(type_def);
|
||
}
|
||
|
||
public addressed_expression convert_address_strong(SyntaxTree.addressed_value av)
|
||
{
|
||
#if (DEBUG)
|
||
if (av == null)
|
||
{
|
||
throw new CompilerInternalError("This syntax tree node can not be null.");
|
||
}
|
||
#endif
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(av);
|
||
|
||
motivation_keeper.set_motivation_to_expect_address();
|
||
addressed_expression ae = ret.visit(av);
|
||
//ae.loc=get_location(av);
|
||
return ae;
|
||
}
|
||
|
||
//Возвращение конвертированного поддерева.
|
||
private void return_value(statement_node stat)
|
||
{
|
||
ret.return_value(stat);
|
||
}
|
||
|
||
private void return_value(expression_node expr)
|
||
{
|
||
ret.return_value(expr);
|
||
}
|
||
|
||
private void return_value(type_node tn)
|
||
{
|
||
ret.return_value(tn);
|
||
}
|
||
|
||
private void return_addressed_value(addressed_expression ae)
|
||
{
|
||
ret.return_value(ae);
|
||
}
|
||
|
||
private void return_semantic_value(semantic_node se)
|
||
{
|
||
ret.return_value(se);
|
||
}
|
||
|
||
public void weak_node_test_and_visit(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
if (tn != null)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(tn);
|
||
tn.visit(this);
|
||
}
|
||
}
|
||
|
||
public void hard_node_test_and_visit(SyntaxTree.syntax_tree_node tn)
|
||
{
|
||
#if (DEBUG)
|
||
// try
|
||
// {
|
||
if (tn == null)
|
||
{
|
||
throw new CompilerInternalError("This node can not be null");
|
||
}
|
||
#endif
|
||
convertion_data_and_alghoritms.check_node_parser_error(tn);
|
||
if (is_direct_type_decl && !(tn is SyntaxTree.ref_type))
|
||
is_direct_type_decl = false;
|
||
tn.visit(this);
|
||
/*#if (DEBUG)
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
if (tn != null)
|
||
throw new Exception("" + tn.source_context.ToString() + System.Environment.NewLine + e.ToString());
|
||
else throw e;
|
||
}
|
||
#endif*/
|
||
}
|
||
|
||
private void assign_doc_info(definition_node dn, SyntaxTree.syntax_tree_node stn)
|
||
{
|
||
string s = null;
|
||
if (docs != null && docs.TryGetValue(stn, out s) && !string.IsNullOrEmpty(s))
|
||
{
|
||
dn.documentation = s;
|
||
}
|
||
return;
|
||
}
|
||
|
||
//Последний параметер - выходной. Он слдержит список параметров с преобразованиями типов.
|
||
private function_node find_function(string name, location loc, PascalABCCompiler.TreeRealization.expressions_list parameters)
|
||
{
|
||
SymbolInfo si = context.find(name);
|
||
if (si == null)
|
||
{
|
||
AddError(new NoFunctionWithThisName(loc));
|
||
}
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
AddError(new ThisIsNotFunctionName(loc));
|
||
}
|
||
function_node fn = convertion_data_and_alghoritms.select_function(parameters, si, loc);
|
||
return fn;
|
||
}
|
||
|
||
//TODO: Обратить внимание на эту функцию. Ее вызовы не приводят к созданиям узлов преобразования типов.
|
||
private function_node find_function(string name, location loc, params expression_node[] exprs)
|
||
{
|
||
expressions_list exprs_list = new expressions_list();
|
||
exprs_list.AddRange(exprs);
|
||
return find_function(name, loc, exprs_list);
|
||
}
|
||
|
||
private expression_node find_operator(SyntaxTree.Operators ot, expression_node expr, location loc)
|
||
{
|
||
string name = name_reflector.get_name(ot);
|
||
//#if (DEBUG)
|
||
if (name == null)
|
||
{
|
||
if (ot == PascalABCCompiler.SyntaxTree.Operators.AddressOf)
|
||
{
|
||
if (expr.is_addressed == false)
|
||
{
|
||
AddError(expr.location, "CAN_NOT_GET_ADDRESS_FROM_EXPRESSION");
|
||
}
|
||
expression_node res = new get_addr_node(expr, loc);
|
||
return res;
|
||
}
|
||
if (ot == PascalABCCompiler.SyntaxTree.Operators.Dereference)
|
||
{
|
||
}
|
||
throw new CompilerInternalError("Invalid operator name");
|
||
}
|
||
//#endif
|
||
SymbolInfo si = expr.type.find(name, context.CurrentScope);
|
||
if (si == null || si.sym_info is wrapped_definition_node)
|
||
{
|
||
AddError(new OperatorCanNotBeAppliedToThisType(name, expr));
|
||
}
|
||
|
||
expressions_list pars = new expressions_list();
|
||
pars.AddElement(expr);
|
||
|
||
function_node fn = convertion_data_and_alghoritms.select_function(pars, si, loc);
|
||
expr = pars[0];
|
||
if (fn == null)
|
||
{
|
||
AddError(new OperatorCanNotBeAppliedToThisType(name, expr));
|
||
}
|
||
#if (DEBUG)
|
||
convertion_data_and_alghoritms.check_operator(fn);
|
||
#endif
|
||
expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, expr);
|
||
return exp_node;
|
||
}
|
||
|
||
private expression_node find_operator(SyntaxTree.Operators ot, expression_node left, expression_node right, location loc)
|
||
{
|
||
string name = name_reflector.get_name(ot);
|
||
return find_operator(name, left, right, loc);
|
||
}
|
||
|
||
bool CheckExpressionType(expression_node expr)
|
||
{
|
||
if (expr.type == null)
|
||
{
|
||
AddError(expr.location, "TYPE_NOT_DEFINED");
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
internal bool one_way_operation(string name)
|
||
{
|
||
if (name == compiler_string_consts.plusassign_name) return true;
|
||
if (name == compiler_string_consts.minusassign_name) return true;
|
||
if (name == compiler_string_consts.multassign_name) return true;
|
||
if (name == compiler_string_consts.assign_name) return true;
|
||
if (name == compiler_string_consts.divassign_name) return true;
|
||
return false;
|
||
}
|
||
|
||
public expression_node find_operator(string name, expression_node left, expression_node right, location loc, bool no_search_in_extension_methods = true)
|
||
{
|
||
#if (DEBUG)
|
||
if (name == null)
|
||
{
|
||
throw new CompilerInternalError("Invalid operator name");
|
||
}
|
||
#endif
|
||
if (right.semantic_node_type == semantic_node_type.null_const_node)
|
||
{
|
||
if ( !type_table.is_with_nil_allowed(left.type) && !left.type.IsPointer)
|
||
AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
|
||
right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right);
|
||
}
|
||
|
||
type_node left_type = left.type;
|
||
type_node right_type = right.type;
|
||
|
||
if (left_type.semantic_node_type == semantic_node_type.delegated_method)
|
||
{
|
||
delegated_methods dm1 = (delegated_methods)left_type;
|
||
if (dm1.empty_param_method != null)
|
||
{
|
||
if (dm1.empty_param_method.simple_function_node.return_value_type != null)
|
||
{
|
||
left_type = dm1.empty_param_method.simple_function_node.return_value_type;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (right_type.semantic_node_type == semantic_node_type.delegated_method && name != compiler_string_consts.plusassign_name && name != compiler_string_consts.minusassign_name)
|
||
{
|
||
delegated_methods dm2 = (delegated_methods)right_type;
|
||
if (dm2.empty_param_method != null)
|
||
{
|
||
if (dm2.empty_param_method.simple_function_node.return_value_type != null)
|
||
{
|
||
right_type = dm2.empty_param_method.simple_function_node.return_value_type;
|
||
}
|
||
}
|
||
}
|
||
SymbolInfo si = left_type.find_in_type(name, left_type.Scope, no_search_in_extension_methods);
|
||
SymbolInfo added_symbols = null;
|
||
SymbolInfo si2 = null;
|
||
if (left_type != right_type && !one_way_operation(name))
|
||
{
|
||
//SymbolInfo si2 = right_type.find(name, context.CurrentScope);
|
||
if (si != null)
|
||
si = si.copy();
|
||
si2 = right_type.find_in_type(name, right_type.Scope, no_search_in_extension_methods);
|
||
if ((si != null) && (si2 != null))
|
||
{
|
||
//Важная проверка. Возможно один и тот же оператор с одними и теми же типами определен в двух разных классах.
|
||
//Возможно она занимает много времени, но, наверное, от нее нельзя отказаться.
|
||
function_node_list funcs = new function_node_list();
|
||
SymbolInfo sic = si;
|
||
SymbolInfo sic_last = null;
|
||
while (sic != null)
|
||
{
|
||
if (sic.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
BasePCUReader.RestoreSymbols(sic, name);
|
||
}
|
||
#if (DEBUG)
|
||
if (sic.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
throw new CompilerInternalError("Expected operator.");
|
||
}
|
||
#endif
|
||
|
||
function_node fn = ((function_node)(sic.sym_info));
|
||
if (convertion_data_and_alghoritms.is_exist_eq_method_in_list(fn, funcs) == null)
|
||
{
|
||
//break;
|
||
funcs.AddElement(fn);
|
||
}
|
||
sic_last = sic;
|
||
sic = sic.Next;
|
||
}
|
||
sic = si2;
|
||
//TODO: Разобраться с зацикливанием.
|
||
function_node_list fnl = new function_node_list();
|
||
while (sic != null)
|
||
{
|
||
if (sic.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
BasePCUReader.RestoreSymbols(sic, name);
|
||
}
|
||
#if (DEBUG)
|
||
if (sic.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
throw new CompilerInternalError("Expected operator.");
|
||
}
|
||
#endif
|
||
fnl.AddElement(((function_node)(sic.sym_info)));
|
||
sic = sic.Next;
|
||
}
|
||
added_symbols = sic_last;
|
||
foreach (function_node fnode in fnl)
|
||
{
|
||
function_node eq_func = convertion_data_and_alghoritms.find_eq_method_in_list(fnode, funcs);
|
||
if (eq_func != null)
|
||
{
|
||
//TODO: Проверить правильно ли это будет работать.
|
||
if (eq_func != fnode)//zachem eto nuzhno voobshe??
|
||
{
|
||
basic_function_node bbfn1 = fnode as basic_function_node;
|
||
basic_function_node bbfn2 = eq_func as basic_function_node;
|
||
if ((bbfn1 != null) && (bbfn2 != null))
|
||
{
|
||
if (bbfn1.basic_function_type != bbfn2.basic_function_type)
|
||
{
|
||
AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right));
|
||
}
|
||
//sic = sic.Next;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
if (left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type
|
||
|| left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type
|
||
|| left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type
|
||
|| left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type
|
||
|| left.type == SystemLibrary.SystemLibrary.string_type && right.type.type_special_kind == SemanticTree.type_special_kind.short_string
|
||
|| right.type == SystemLibrary.SystemLibrary.string_type && left.type.type_special_kind == SemanticTree.type_special_kind.short_string
|
||
|| left.type.type_special_kind == SemanticTree.type_special_kind.short_string && right.type.type_special_kind == SemanticTree.type_special_kind.short_string
|
||
|| left.type.IsDelegate == right.type.IsDelegate)
|
||
{
|
||
//if (left.type.find_in_type(name) !=null)
|
||
}
|
||
else
|
||
AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right));
|
||
}
|
||
}
|
||
}
|
||
sic_last.Next = new SymbolInfo(fnode);
|
||
sic_last = sic_last.Next;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((si == null) && (si2 != null))
|
||
{
|
||
si = si2;
|
||
}
|
||
}
|
||
}
|
||
//if (si == null)
|
||
{
|
||
if (left_type.semantic_node_type == semantic_node_type.delegated_method && right_type.semantic_node_type == semantic_node_type.delegated_method)
|
||
{
|
||
SymbolInfo saved_si = si;
|
||
SymbolInfo saved_si2 = si2;
|
||
if (!(left is typed_expression))
|
||
AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
|
||
base_function_call bfc = ((left as typed_expression).type as delegated_methods).proper_methods[0];
|
||
left = convertion_data_and_alghoritms.explicit_convert_type(left, CreateDelegate(bfc.simple_function_node));
|
||
si = left.type.find_in_type(name);
|
||
bfc = ((right as typed_expression).type as delegated_methods).proper_methods[0];
|
||
right = convertion_data_and_alghoritms.explicit_convert_type(right, CreateDelegate(bfc.simple_function_node));
|
||
si2 = right.type.find_in_type(name);
|
||
if (saved_si != null)
|
||
si.Next = saved_si;
|
||
else
|
||
saved_si = si;
|
||
if (saved_si2 != null)
|
||
si2.Next = saved_si2;
|
||
else
|
||
saved_si2 = si2;
|
||
if (saved_si == null)
|
||
{
|
||
if (!no_search_in_extension_methods)
|
||
AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
|
||
else
|
||
return find_operator(name, left, right, loc, false);
|
||
}
|
||
|
||
}
|
||
else if (si == null)
|
||
{
|
||
if (!no_search_in_extension_methods)
|
||
AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
|
||
else
|
||
return find_operator(name, left, right, loc, false);
|
||
}
|
||
|
||
}
|
||
|
||
expressions_list pars = null;
|
||
function_node fnsel = null;
|
||
SymbolInfo tmp_si = si;
|
||
while (tmp_si != null)
|
||
{
|
||
if (tmp_si.sym_info is wrapped_definition_node)
|
||
BasePCUReader.RestoreSymbols(tmp_si, name);
|
||
tmp_si = tmp_si.Next;
|
||
}
|
||
pars = new expressions_list();
|
||
pars.AddElement(left);
|
||
pars.AddElement(right);
|
||
bool tmp_throw_error = ThrowCompilationError;
|
||
ThrowCompilationError = !no_search_in_extension_methods;
|
||
|
||
fnsel = convertion_data_and_alghoritms.select_function(pars, si, loc);
|
||
if (!ThrowCompilationError && fnsel == null)
|
||
{
|
||
RemoveLastError();
|
||
ThrowCompilationError = tmp_throw_error;
|
||
return find_operator(name, left, right, loc, false);
|
||
}
|
||
else
|
||
ThrowCompilationError = tmp_throw_error;
|
||
//function_node fnsel=convertion_data_and_alghoritms.select_function(pars,si,loc);
|
||
CheckSpecialFunctionCall(si, pars,loc);
|
||
//TODO: А это зачем? Можно передать в create_simple_function_call pars.
|
||
left = pars[0];
|
||
right = pars[1];
|
||
if (fnsel == null)
|
||
{
|
||
AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc));
|
||
}
|
||
if (added_symbols != null)
|
||
added_symbols.Next = null;
|
||
|
||
if (SystemUnitAssigned && in_check_range_region() && name == compiler_string_consts.assign_name && is_range_checkable(left.type) && is_range_checkable(right.type))
|
||
{
|
||
ordinal_type_interface oti = left.type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (left.type != SystemLibrary.SystemLibrary.char_type && left.type != SystemLibrary.SystemLibrary.uint64_type && !(oti.lower_value is ulong_const_node))
|
||
if(!(oti.lower_value is enum_const_node) && !(oti.lower_value is char_const_node))
|
||
right = convertion_data_and_alghoritms.convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type);
|
||
else if (oti.lower_value is enum_const_node)
|
||
{
|
||
right = convertion_data_and_alghoritms.explicit_convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.explicit_convert_type(right,SystemLibrary.SystemLibrary.int64_type),
|
||
convertion_data_and_alghoritms.explicit_convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.explicit_convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type);
|
||
}
|
||
else if (oti.lower_value is char_const_node)
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckCharRangeFunction.sym_info as common_namespace_function_node, null, right, oti.lower_value,oti.upper_value);
|
||
}
|
||
expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fnsel, loc, left, right);
|
||
return exp_node;
|
||
}
|
||
|
||
internal bool in_check_range_region()
|
||
{
|
||
return false;
|
||
}
|
||
|
||
internal bool is_range_checkable(type_node tn)
|
||
{
|
||
ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null && !tn.IsEnum && tn != SystemLibrary.SystemLibrary.bool_type)
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
private base_function_call_list convert_functions_to_calls(expression_node obj, function_node_list fnl, location loc, bool is_static)
|
||
{
|
||
base_function_call_list ret = new base_function_call_list();
|
||
foreach (function_node fnode in fnl)
|
||
{
|
||
base_function_call bfc = null;
|
||
switch (fnode.semantic_node_type)
|
||
{
|
||
case semantic_node_type.common_namespace_function_node:
|
||
{
|
||
common_namespace_function_node cmfn = fnode as common_namespace_function_node;
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(cmfn, loc);
|
||
if (cmfn.ConnectedToType != null)
|
||
cnfc.parameters.AddElement(obj);
|
||
if (cmfn.is_generic_function && !cmfn.is_generic_function_instance && cmfn.ConnectedToType != null && cmfn.parameters.Count == 1)
|
||
{
|
||
expressions_list parameters = new expressions_list();
|
||
parameters.AddElement(obj);
|
||
function_node inst = null;
|
||
try
|
||
{
|
||
inst = generic_convertions.DeduceFunction(cmfn, parameters, true, loc);
|
||
}
|
||
catch
|
||
{
|
||
continue;
|
||
}
|
||
cnfc = new common_namespace_function_call((common_namespace_function_node)inst, loc);
|
||
if (cmfn.ConnectedToType != null)
|
||
cnfc.parameters.AddElement(obj);
|
||
}
|
||
/*if (cmfn.parameters.Count >= 1 && cmfn.parameters[cmfn.parameters.Count - 1].is_params)
|
||
{
|
||
convertion_data_and_alghoritms.select_function(cnfc.parameters, new SymbolInfo(cmfn), loc);
|
||
|
||
}*/
|
||
bfc = cnfc;
|
||
break;
|
||
}
|
||
case semantic_node_type.basic_function_node:
|
||
{
|
||
//Может здесь стоит и выругаться, но я не буду пока этого делать.
|
||
break;
|
||
}
|
||
case semantic_node_type.common_in_function_function_node:
|
||
{
|
||
common_in_function_function_node ciffn = fnode as common_in_function_function_node;
|
||
int depth = convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(ciffn.scope,
|
||
context.top_function.scope);
|
||
common_in_function_function_call ciffc = new common_in_function_function_call(ciffn, depth, loc);
|
||
bfc = ciffc;
|
||
break;
|
||
}
|
||
case semantic_node_type.common_method_node:
|
||
{
|
||
common_method_node cmn = fnode as common_method_node;
|
||
//Если cmn конструктор - то плохо, но его не должно сюда попасть.
|
||
if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
if (!is_static)
|
||
{
|
||
if (obj == null)
|
||
obj = GetCurrentObjectReference(cmn.cont_type.Scope, cmn, loc);//new this_node(context.converted_type, loc);
|
||
common_method_call cmc = new common_method_call(cmn, obj, loc);
|
||
cmc.virtual_call = !inherited_ident_processing;
|
||
bfc = cmc;
|
||
}
|
||
//ssyy!!! Мне сложно понять предназначение данного кода, но, по-видимому,
|
||
//следует его переписать так.
|
||
else if (cmn.is_constructor)
|
||
{
|
||
if (cmn.parameters.Count == 0)
|
||
{
|
||
if (cmn.cont_type.IsAbstract)
|
||
AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.cont_type.name);
|
||
ret.clear();
|
||
ret.AddElement(new common_constructor_call(cmn, loc));
|
||
return ret;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (is_static)
|
||
{
|
||
common_static_method_call csmc = new common_static_method_call(cmn, loc);
|
||
bfc = csmc;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case semantic_node_type.compiled_function_node:
|
||
{
|
||
compiled_function_node cfn = fnode as compiled_function_node;
|
||
if (cfn.cont_type.Scope == null && cfn is compiled_function_node)
|
||
(cfn.cont_type as compiled_type_node).init_scope();
|
||
|
||
if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
//ispravleno ibond
|
||
//if (is_static)
|
||
{
|
||
|
||
if (cfn.is_generic_function && !cfn.is_generic_function_instance && cfn.ConnectedToType != null && cfn.parameters.Count == 1)
|
||
{
|
||
expressions_list parameters = new expressions_list();
|
||
parameters.AddElement(obj);
|
||
function_node inst = null;
|
||
try
|
||
{
|
||
inst = generic_convertions.DeduceFunction(cfn, parameters, true, loc);
|
||
}
|
||
catch
|
||
{
|
||
continue;
|
||
}
|
||
if (inst is common_namespace_function_node)
|
||
bfc = new common_namespace_function_call((common_namespace_function_node)inst, loc);
|
||
else if (inst is compiled_function_node)
|
||
bfc = new compiled_static_method_call((compiled_function_node)inst, loc);
|
||
else
|
||
bfc = new compiled_static_method_call(cfn, loc);
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc);
|
||
bfc = csmc;
|
||
|
||
}
|
||
if (cfn.ConnectedToType != null)
|
||
bfc.parameters.AddElement(obj);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!is_static)
|
||
{
|
||
if (obj == null)
|
||
obj = GetCurrentObjectReference(cfn.cont_type.Scope, cfn, loc);//new this_node(context.converted_type, loc);
|
||
compiled_function_call cfc = new compiled_function_call(cfn, obj, loc);
|
||
cfc.virtual_call = !inherited_ident_processing;
|
||
bfc = cfc;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case semantic_node_type.compiled_constructor_node:
|
||
{
|
||
//Этот код мы вроде не должны вызывать, но если он все-же вызовется.
|
||
compiled_constructor_node ccn = fnode as compiled_constructor_node;
|
||
compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc);
|
||
bfc = ccc;
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Undefined method type.");
|
||
}
|
||
}
|
||
if (bfc != null)
|
||
{
|
||
ret.AddElement(bfc);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
private base_function_call_list create_possible_delegates_list(expression_node obj, SymbolInfo si, location loc, bool is_static)
|
||
{
|
||
if (si == null)
|
||
{
|
||
return new base_function_call_list();
|
||
}
|
||
function_node_list fnl = new function_node_list();
|
||
while (si != null)
|
||
{
|
||
function_node fn = si.sym_info as function_node;
|
||
if (si.sym_info is compiled_property_node)
|
||
{
|
||
fn = (si.sym_info as compiled_property_node).get_function;
|
||
}
|
||
else if (si.sym_info is common_property_node)
|
||
{
|
||
fn = (si.sym_info as common_property_node).get_function;
|
||
}
|
||
if (convertion_data_and_alghoritms.find_eq_method_in_list(fn, fnl) == null)
|
||
{
|
||
if (!(obj != null && fn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && !fn.is_extension_method))
|
||
{
|
||
if (fn.is_extension_method)
|
||
{
|
||
if (obj != null && (fn.parameters[0].type == obj.type || type_table.compare_types(fn.parameters[0].type, obj.type) == type_compare.greater_type))
|
||
fnl.AddElementFirst(fn);
|
||
else
|
||
fnl.AddElement(fn);
|
||
}
|
||
else
|
||
fnl.AddElement(fn);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
}
|
||
si = si.Next;
|
||
}
|
||
return convert_functions_to_calls(obj, fnl, loc, is_static);
|
||
}
|
||
|
||
private base_function_call_list create_possible_delegates_list(expression_node obj, function_node func, location loc, bool is_static)
|
||
{
|
||
function_node_list fnl = new function_node_list();
|
||
fnl.AddElement(func);
|
||
return convert_functions_to_calls(obj, fnl, loc, is_static);
|
||
}
|
||
|
||
internal typed_expression make_delegate_wrapper(expression_node obj, SymbolInfo si, location loc, bool is_static)
|
||
{
|
||
base_function_call_list fnl = create_possible_delegates_list(obj, si, loc, is_static);
|
||
if (fnl.Count == 0)
|
||
{
|
||
if (is_static)
|
||
{
|
||
AddError(loc, "EXPECTED_STATIC_METHOD");
|
||
}
|
||
else
|
||
{
|
||
AddError(loc, "EXPECTED_NON_STATIC_METHOD");
|
||
}
|
||
}
|
||
delegated_methods dm = new delegated_methods();
|
||
dm.proper_methods.AddRange(fnl);
|
||
typed_expression te = new typed_expression(dm, loc);
|
||
return te;
|
||
}
|
||
|
||
internal typed_expression make_delegate_wrapper(expression_node obj, function_node func, location loc, bool is_static)
|
||
{
|
||
base_function_call_list fnl = create_possible_delegates_list(obj, func, loc, is_static);
|
||
if (fnl.Count == 0)
|
||
{
|
||
if (is_static)
|
||
{
|
||
AddError(loc, "EXPECTED_STATIC_METHOD");
|
||
}
|
||
else
|
||
{
|
||
AddError(loc, "EXPECTED_NON_STATIC_METHOD");
|
||
}
|
||
}
|
||
delegated_methods dm = new delegated_methods();
|
||
dm.proper_methods.AddRange(fnl);
|
||
typed_expression te = new typed_expression(dm, loc);
|
||
return te;
|
||
}
|
||
|
||
private bool check_name_in_current_scope(string name)
|
||
{
|
||
|
||
SymbolTable.Scope cscope = context.CurrentScope, name_scope = context.find(name).scope;
|
||
while (cscope is SymbolTable.BlockScope)
|
||
{
|
||
if (name_scope == cscope)
|
||
return true;
|
||
cscope = cscope.TopScope;
|
||
}
|
||
if (cscope is SymbolTable.UnitImplementationScope && name_scope is SymbolTable.UnitInterfaceScope)
|
||
return cscope.TopScope == name_scope;
|
||
return cscope == name_scope;
|
||
}
|
||
|
||
void checkPolymorphicState(definition_node dn,location loc)
|
||
{
|
||
}
|
||
|
||
private type_node find_type(string name, location loc)
|
||
{
|
||
definition_node di = context.check_name_node_type(name, loc, general_node_type.type_node);
|
||
type_node tn = (type_node)di;
|
||
return tn;
|
||
}
|
||
|
||
//(ssyy) разбил
|
||
private type_node find_type(SyntaxTree.named_type_reference names, location loc)
|
||
{
|
||
definition_node di;
|
||
SyntaxTree.template_type_reference ttr = names as SyntaxTree.template_type_reference;
|
||
if (ttr != null)
|
||
{
|
||
di = ret.visit(names);
|
||
type_node tn = di as type_node;
|
||
if (tn == null)
|
||
{
|
||
AddError(loc, "TYPE_REFERENCE_EXPECTED");
|
||
}
|
||
return tn;
|
||
}
|
||
SymbolInfo si = context.find_definition_node(names, loc);
|
||
if (si == null && attribute_converted)
|
||
{
|
||
names.names[names.names.Count-1].name += "Attribute";
|
||
si = context.find_definition_node(names, loc);
|
||
}
|
||
if (si != null && si.sym_info != null && si.sym_info.general_node_type == general_node_type.generic_indicator)
|
||
{
|
||
generic_indicator gi = si.sym_info as generic_indicator;
|
||
AddError(loc, "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", names.names[names.names.Count - 1].name, gi.generic.generic_params.Count);
|
||
}
|
||
if (si == null || si.sym_info == null)
|
||
{
|
||
check_possible_generic_names(names, loc);
|
||
}
|
||
di = context.check_name_node_type(names.names[names.names.Count - 1].name, si, loc, general_node_type.type_node);
|
||
return (type_node)di;
|
||
}
|
||
|
||
public void check_possible_generic_names(SyntaxTree.named_type_reference names, location loc)
|
||
{
|
||
string tmp = names.names[names.names.Count - 1].name;
|
||
int num;
|
||
string generic_name = compiler_string_consts.GetGenericTypeInformation(tmp, out num);
|
||
List<int> counts;
|
||
bool found = NetHelper.NetHelper.generics_names.TryGetValue(generic_name.ToLower(), out counts);
|
||
if (found)
|
||
{
|
||
foreach (int k in counts)
|
||
{
|
||
names.names[names.names.Count - 1].name = generic_name +
|
||
compiler_string_consts.generic_params_infix + k.ToString();
|
||
SymbolInfo sinfo = context.find_definition_node(names, loc);
|
||
if (sinfo != null)
|
||
{
|
||
names.names[names.names.Count - 1].name = tmp;
|
||
AddError(loc, "GENERIC_TYPE_{0}_NEEDS_{1}_GENERIC_PARAMETERS", generic_name, k);
|
||
break;
|
||
}
|
||
}
|
||
names.names[names.names.Count - 1].name = tmp;
|
||
}
|
||
}
|
||
|
||
|
||
public expression_node make_break_node(location call_location, params expression_node[] parameters)
|
||
{
|
||
if (parameters.Length != 0)
|
||
{
|
||
return null;
|
||
}
|
||
if (context.cycle_stack.Empty)
|
||
{
|
||
AddError(new BreakStatementWithoutComprehensiveCycle(call_location));
|
||
}
|
||
statement_node sn = context.cycle_stack.top();
|
||
switch (sn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.while_node:
|
||
{
|
||
while_node wn = (while_node)sn;
|
||
return new while_break_node(wn, call_location);
|
||
}
|
||
case semantic_node_type.repeat_node:
|
||
{
|
||
repeat_node rn = (repeat_node)sn;
|
||
return new repeat_break_node(rn, call_location);
|
||
}
|
||
case semantic_node_type.for_node:
|
||
{
|
||
for_node fn = (for_node)sn;
|
||
return new for_break_node(fn, call_location);
|
||
}
|
||
case semantic_node_type.foreach_node:
|
||
{
|
||
foreach_node fn = (foreach_node)sn;
|
||
return new foreach_break_node(fn, call_location);
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Undefined cycle type");
|
||
}
|
||
|
||
public expression_node make_continue_node(location call_location, params expression_node[] parameters)
|
||
{
|
||
if (parameters.Length != 0)
|
||
{
|
||
return null;
|
||
}
|
||
if (context.cycle_stack.Empty)
|
||
{
|
||
AddError(new ContinueStatementWithoutComprehensiveCycle(call_location));
|
||
}
|
||
statement_node sn = context.cycle_stack.top();
|
||
switch (sn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.while_node:
|
||
{
|
||
while_node wn = (while_node)sn;
|
||
return new while_continue_node(wn, call_location);
|
||
}
|
||
case semantic_node_type.repeat_node:
|
||
{
|
||
repeat_node rn = (repeat_node)sn;
|
||
return new repeat_continue_node(rn, call_location);
|
||
}
|
||
case semantic_node_type.for_node:
|
||
{
|
||
for_node fn = (for_node)sn;
|
||
return new for_continue_node(fn, call_location);
|
||
}
|
||
case semantic_node_type.foreach_node:
|
||
{
|
||
foreach_node fn = (foreach_node)sn;
|
||
return new foreach_continue_node(fn, call_location);
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Undefined cycle type");
|
||
}
|
||
|
||
public expression_node make_exit_node(location call_location, params expression_node[] parameters)
|
||
{
|
||
if (parameters.Length != 0)
|
||
{
|
||
return null;
|
||
}
|
||
if (!TreeConverter.SemanticRules.EnableExitProcedure)
|
||
AddError(new TreeConverter.UndefinedNameReference(TreeConverter.compiler_string_consts.exit_procedure_name, call_location));
|
||
return new exit_procedure(call_location);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.inherited_message _inherited_message)
|
||
{
|
||
//throw new NotSupportedError(get_location(_inherited_message));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation: return_value(inherited_message_value_reciving(_inherited_message)); break;
|
||
//case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break;
|
||
case motivation.address_reciving:
|
||
case motivation.semantic_node_reciving: AddError(get_location(_inherited_message), "CAN_NOT_ASSIGN_TO_LEFT_PART"); break;
|
||
}
|
||
}
|
||
|
||
private expression_node current_catch_excep;
|
||
|
||
public override void visit(SyntaxTree.try_stmt _try_stmt)
|
||
{
|
||
context.enter_code_block_without_bind();
|
||
context.enter_exception_handlers();
|
||
statement_node try_statements = convert_strong(_try_stmt.stmt_list);
|
||
context.leave_code_block();
|
||
location loc = get_location(_try_stmt);
|
||
exception_filters_list efl = new exception_filters_list();
|
||
SyntaxTree.try_handler_except try_hand_except = _try_stmt.handler as SyntaxTree.try_handler_except;
|
||
if (try_hand_except != null)
|
||
{
|
||
if (try_hand_except.except_block.handlers != null)
|
||
{
|
||
int hand_count = try_hand_except.except_block.handlers.handlers.Count;
|
||
for (int i = 0; i < hand_count; i++)
|
||
{
|
||
SyntaxTree.exception_handler eh = try_hand_except.except_block.handlers.handlers[i];
|
||
type_node filter_type = convert_strong(eh.type_name);
|
||
if (!SemanticRules.GenerateNativeCode && !(filter_type.is_generic_parameter ||
|
||
filter_type == SystemLibrary.SystemLibrary.exception_base_type ||
|
||
type_table.is_derived(SystemLibrary.SystemLibrary.exception_base_type, filter_type)))
|
||
{
|
||
AddError(get_location(eh.type_name), "EXCEPTION_TYPE_MUST_BE_SYSTEM_EXCEPTION_OR_DERIVED_FROM_EXCEPTION");
|
||
}
|
||
current_catch_excep = new int_const_node(2,null);//create_constructor_call(filter_type, new expressions_list(), null);
|
||
local_block_variable_reference lvr = null;
|
||
|
||
context.enter_code_block_without_bind();
|
||
if (eh.variable != null)
|
||
{
|
||
|
||
context.check_name_redefinition = false;
|
||
|
||
local_block_variable lbv = context.add_var_definition(eh.variable.name, get_location(eh.variable), filter_type, SemanticTree.polymorphic_state.ps_common) as local_block_variable;
|
||
context.check_name_redefinition = true;
|
||
lvr = new local_block_variable_reference(lbv, lbv.loc);
|
||
}
|
||
statement_node stm = convert_strong(eh.statements);
|
||
context.leave_code_block();
|
||
|
||
/*if (eh.variable != null)
|
||
{
|
||
context.leave_scope();
|
||
}*/
|
||
exception_filter ef = new exception_filter(filter_type, lvr, stm, get_location(eh));
|
||
efl.AddElement(ef);
|
||
current_catch_excep = null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
context.enter_code_block_without_bind();
|
||
exception_filter ef = new exception_filter(null, null, convert_strong(try_hand_except.except_block.stmt_list), get_location(try_hand_except.except_block.stmt_list));
|
||
context.leave_code_block();
|
||
efl.AddElement(ef);
|
||
}
|
||
if (try_hand_except.except_block.else_stmt_list != null)
|
||
{
|
||
context.enter_code_block_without_bind();
|
||
statement_node else_stm = convert_strong(try_hand_except.except_block.else_stmt_list);
|
||
context.leave_code_block();
|
||
type_node ftype = SystemLibrary.SystemLibrary.object_type;
|
||
exception_filter else_ef = new exception_filter(ftype, null, else_stm, else_stm.location);
|
||
efl.AddElement(else_ef);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
type_node filter_type = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(compiler_string_consts.ExceptionName));
|
||
expression_node current_catch_excep = create_constructor_call(filter_type, new expressions_list(), null);
|
||
local_block_variable_reference lvr = null;
|
||
local_block_variable tmp_var = context.add_var_definition(context.BuildName("$try_temp" + UniqueNumStr()), null, SystemLibrary.SystemLibrary.bool_type, null) as local_block_variable;
|
||
statements_list stm = new statements_list(null);
|
||
SyntaxTree.try_handler_finally try_hndlr_finally = _try_stmt.handler as SyntaxTree.try_handler_finally;
|
||
context.enter_code_block_without_bind();
|
||
statement_node finally_stmt = convert_strong(try_hndlr_finally.stmt_list);
|
||
context.leave_code_block();
|
||
stm.statements.AddElement(finally_stmt);
|
||
basic_function_call bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,null);
|
||
bfc.parameters.AddElement(new local_block_variable_reference(tmp_var,null));
|
||
stm.statements.AddElement(new if_node(bfc,new rethrow_statement_node(null),null,null));
|
||
exception_filter ef = new exception_filter(filter_type, lvr, stm, null);
|
||
efl.AddElement(ef);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,null);
|
||
bfc.parameters.AddElement(new local_block_variable_reference(tmp_var,null));
|
||
bfc.parameters.AddElement(new bool_const_node(true,null));
|
||
|
||
(try_statements as statements_list).statements.AddElement(bfc);
|
||
(try_statements as statements_list).statements.AddElement(new throw_statement_node(current_catch_excep,null));
|
||
return_value(new try_block(try_statements, null, efl, loc));
|
||
context.leave_exception_handlers();
|
||
return;
|
||
}
|
||
statement_node finally_st = null;
|
||
SyntaxTree.try_handler_finally try_handler_finally = _try_stmt.handler as SyntaxTree.try_handler_finally;
|
||
if (try_handler_finally != null)
|
||
{
|
||
context.enter_code_block_without_bind();
|
||
finally_st = convert_strong(try_handler_finally.stmt_list);
|
||
context.leave_code_block();
|
||
}
|
||
try_block tb = new try_block(try_statements, finally_st, efl, loc);
|
||
context.leave_exception_handlers();
|
||
return_value(tb);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.try_handler_except _try_handler_except)
|
||
{
|
||
throw new NotSupportedError(get_location(_try_handler_except));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.try_handler_finally _try_handler_finally)
|
||
{
|
||
throw new NotSupportedError(get_location(_try_handler_finally));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.try_handler _try_handler)
|
||
{
|
||
throw new NotSupportedError(get_location(_try_handler));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.exception_block _exception_block)
|
||
{
|
||
throw new NotSupportedError(get_location(_exception_block));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.exception_handler_list _exception_handler_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_exception_handler_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.exception_ident _exception_ident)
|
||
{
|
||
throw new NotSupportedError(get_location(_exception_ident));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.exception_handler _exception_handler)
|
||
{
|
||
throw new NotSupportedError(get_location(_exception_handler));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.known_type_ident _known_type_ident)
|
||
{
|
||
if (_known_type_ident.type == PascalABCCompiler.SyntaxTree.known_type.string_type)
|
||
{
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: return_value(SystemLibrary.SystemLibrary.string_type); break;
|
||
case motivation.expression_evaluation: return_value(SystemLibrary.SystemLibrary.string_type); break;
|
||
//case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(SystemLibrary.SystemLibrary.string_type); break;
|
||
}
|
||
|
||
return;
|
||
}
|
||
//throw new NotSupportedError(get_location(_known_type_ident));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.file_type _file_type)
|
||
{
|
||
if (_file_type.file_of_type != null)
|
||
{
|
||
//Типизированый файл
|
||
type_node el_type = convert_strong(_file_type.file_of_type);
|
||
check_for_type_allowed(el_type,get_location(_file_type.file_of_type));
|
||
//if (el_type == SystemLibrary.SystemLibrary.void_type)
|
||
// ErrorsList.Add(new VoidNotValid(get_location(_file_type.file_of_type)));
|
||
/*if (el_type == SystemLibrary.SystemLibInitializer.TextFileType.sym_info)
|
||
{
|
||
//Это текстовый файл!!!
|
||
return_value(el_type);
|
||
return;
|
||
}*/
|
||
if (SystemLibrary.SystemLibInitializer.TypedFileType == null || SystemLibrary.SystemLibInitializer.TypedFileInitProcedure == null)
|
||
AddError(new NotSupportedError(get_location(_file_type)));
|
||
if (!CanUseThisTypeForTypedFiles(el_type))
|
||
AddError(get_location(_file_type.file_of_type), "INVALID_ELEMENT_TYPE_FOR_TYPED_FILE", el_type);
|
||
return_value(context.create_typed_file_type(el_type, get_location(_file_type)));
|
||
}
|
||
else
|
||
{
|
||
//Бинарнай файл
|
||
if (SystemLibrary.SystemLibInitializer.BinaryFileType == null)
|
||
AddError(new NotSupportedError(get_location(_file_type)));
|
||
((type_node)SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info).type_special_kind = SemanticTree.type_special_kind.binary_file;
|
||
return_value((type_node)SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info);
|
||
}
|
||
}
|
||
|
||
private bool CanUseThisTypeForFiles(type_node el_type, bool allow_strings)
|
||
{
|
||
if (el_type.is_generic_parameter)
|
||
{
|
||
if (SemanticRules.AllowGenericParametersForFiles)
|
||
{
|
||
if (allow_strings)
|
||
get_type_abilities(el_type).useful_for_binary_files = true;
|
||
else
|
||
get_type_abilities(el_type).useful_for_typed_files = true;
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
if (el_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
return true;
|
||
if (el_type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
if (el_type.element_type == SystemLibrary.SystemLibrary.byte_type || el_type.element_type == SystemLibrary.SystemLibrary.sbyte_type
|
||
|| el_type.element_type == SystemLibrary.SystemLibrary.bool_type || el_type.element_type.IsEnum) return true;
|
||
else if (el_type.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
if (el_type.element_type.base_type == SystemLibrary.SystemLibrary.byte_type || el_type.element_type.base_type == SystemLibrary.SystemLibrary.sbyte_type
|
||
|| el_type.element_type.base_type == SystemLibrary.SystemLibrary.bool_type || el_type.element_type.base_type.IsEnum) return true;
|
||
if (el_type.element_type.base_type == SystemLibrary.SystemLibrary.integer_type)
|
||
{
|
||
ordinal_type_interface oti = el_type.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (((oti.upper_value as int_const_node).constant_value-(oti.lower_value as int_const_node).constant_value) <= 256)
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
if (el_type.is_value)
|
||
{
|
||
generic_instance_type_node gitn = el_type as generic_instance_type_node;
|
||
if (gitn != null)
|
||
{
|
||
List<type_node> ftypes = gitn.all_field_types;
|
||
foreach (type_node ftype in ftypes)
|
||
{
|
||
if (!CanUseThisTypeForFiles(ftype, allow_strings))
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
if (SystemLibrary.SystemLibrary.CanUseThisTypeForTypedFiles(el_type))
|
||
return true;
|
||
if (el_type is common_type_node)
|
||
{
|
||
if (el_type as common_type_node == context.converted_type ||
|
||
(el_type.original_generic != null && el_type.original_generic == context.converted_type))
|
||
return false;
|
||
common_type_node ctn = el_type as common_type_node;
|
||
foreach (class_field cf in ctn.fields)
|
||
if (cf.type.type_special_kind != SemanticTree.type_special_kind.short_string && !CanUseThisTypeForFiles(cf.type, allow_strings))
|
||
return false;
|
||
return true;
|
||
}
|
||
if (el_type is compiled_type_node)
|
||
{
|
||
compiled_type_node ctn = el_type as compiled_type_node;
|
||
if (!ctn.compiled_type.IsLayoutSequential)
|
||
return false;
|
||
System.Reflection.FieldInfo[] fields = ctn.compiled_type.GetFields();
|
||
foreach (System.Reflection.FieldInfo fi in fields)
|
||
if (!fi.IsStatic)
|
||
if (!CanUseThisTypeForFiles(compiled_type_node.get_type_node(fi.FieldType), allow_strings))
|
||
return false;
|
||
return true;
|
||
}
|
||
}
|
||
if (IsBoundedArray(el_type))
|
||
{
|
||
//это обычный массив
|
||
bounded_array_interface bai = (bounded_array_interface)el_type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
return CanUseThisTypeForFiles(bai.element_type, allow_strings);
|
||
}
|
||
if (allow_strings && el_type == SystemLibrary.SystemLibrary.string_type)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private bool CanUseThisTypeForTypedFiles(type_node el_type)
|
||
{
|
||
if (el_type.type_special_kind == SemanticTree.type_special_kind.short_string) return true;
|
||
return CanUseThisTypeForFiles(el_type, false);
|
||
}
|
||
|
||
private bool CanUseThisTypeForBinaryFiles(type_node el_type)
|
||
{
|
||
if (el_type == SystemLibrary.SystemLibrary.string_type || el_type is short_string_type_node) return true;
|
||
return CanUseThisTypeForFiles(el_type, true);
|
||
}
|
||
|
||
internal List<int> get_short_string_lens(type_node tn)
|
||
{
|
||
List<int> lst = new List<int>();
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
lst.Add((tn as short_string_type_node).Length);
|
||
}
|
||
if (tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
if (ctn.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
lst.AddRange(get_short_string_lens(ctn.element_type));
|
||
}
|
||
else if (ctn.type_special_kind == SemanticTree.type_special_kind.record)
|
||
{
|
||
foreach (class_field fld in ctn.fields)
|
||
lst.AddRange(get_short_string_lens(fld.type));
|
||
}
|
||
}
|
||
return lst;
|
||
}
|
||
|
||
internal int get_short_string_size(type_node tn)
|
||
{
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
return (tn as short_string_type_node).Length+1;
|
||
}
|
||
if (tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
if (ctn.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
int len = ((ctn.find_in_type(compiler_string_consts.internal_array_name).sym_info as class_field).type as simple_array).length;
|
||
return len*get_short_string_size(ctn.element_type);
|
||
}
|
||
else if (ctn.type_special_kind == SemanticTree.type_special_kind.record)
|
||
{
|
||
int off = 0;
|
||
foreach (class_field fld in ctn.fields)
|
||
off += get_short_string_size(fld.type);
|
||
return off;
|
||
}
|
||
return 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_typed_file(var_definition_node vdn, type_node element_type)
|
||
{
|
||
location loc = (vdn.type as common_type_node).loc;
|
||
if (!SystemUnitAssigned)
|
||
AddError(new NotSupportedError(loc));
|
||
//Когда заработает наследование конструкторов надо вставить это
|
||
/*
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(new typeof_operator(element_type, loc));
|
||
base_function_call bfc = create_constructor_call(vdn.type, exl, loc);
|
||
expression_node expr = find_operator(compiler_string_consts.assign_name, var_ref, bfc, loc);
|
||
*/
|
||
|
||
type_node tn = vdn.type;
|
||
vdn.type = SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node;
|
||
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(var_ref);
|
||
exl.AddElement(new typeof_operator(element_type, loc));
|
||
List<int> lens = get_short_string_lens(element_type);
|
||
int sz = get_short_string_size(element_type);
|
||
if (sz > 0)
|
||
{
|
||
exl.AddElement(new int_const_node(get_short_string_size(element_type),null));
|
||
for (int i=0; i<lens.Count; i++)
|
||
exl.AddElement(new int_const_node(lens[i],null));
|
||
}
|
||
this.context.save_var_definitions();
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedFileInitProcedure.SymbolInfo, loc);
|
||
this.context.restore_var_definitions();
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray());
|
||
|
||
vdn.type = tn;
|
||
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_text_file(var_definition_node vdn)
|
||
{
|
||
location loc = null;
|
||
if (vdn.type is common_type_node)
|
||
loc = (vdn.type as common_type_node).loc;
|
||
if (!SystemUnitAssigned)
|
||
AddError(new NotSupportedError(loc));
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(var_ref);
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TextFileInitProcedure.SymbolInfo, loc);
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray());
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_binary_file(var_definition_node vdn)
|
||
{
|
||
location loc = null;
|
||
if (vdn.type is common_type_node)
|
||
loc = (vdn.type as common_type_node).loc;
|
||
if (!SystemUnitAssigned)
|
||
AddError(new NotSupportedError(loc));
|
||
type_node tn = vdn.type;
|
||
vdn.type = SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info as type_node;
|
||
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(var_ref);
|
||
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure.SymbolInfo, loc);
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray());
|
||
|
||
vdn.type = tn;
|
||
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_set(var_definition_node vdn)
|
||
{
|
||
location loc = (vdn.type as common_type_node).loc;
|
||
if (!SystemUnitAssigned)
|
||
AddError(new NotSupportedError(loc));
|
||
//Когда заработает наследование конструкторов надо вставить это
|
||
/*
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(new typeof_operator(element_type, loc));
|
||
base_function_call bfc = create_constructor_call(vdn.type, exl, loc);
|
||
expression_node expr = find_operator(compiler_string_consts.assign_name, var_ref, bfc, loc);
|
||
*/
|
||
|
||
type_node tn = vdn.type;
|
||
vdn.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(var_ref);
|
||
bool short_str = false;
|
||
//exl.AddElement(new typeof_operator(element_type, loc));
|
||
if (tn.element_type == SystemLibrary.SystemLibrary.byte_type)
|
||
{
|
||
exl.AddElement(new byte_const_node(byte.MinValue,null));
|
||
exl.AddElement(new byte_const_node(byte.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.sbyte_type)
|
||
{
|
||
exl.AddElement(new sbyte_const_node(sbyte.MinValue,null));
|
||
exl.AddElement(new sbyte_const_node(sbyte.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.short_type)
|
||
{
|
||
exl.AddElement(new short_const_node(short.MinValue,null));
|
||
exl.AddElement(new short_const_node(short.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.ushort_type)
|
||
{
|
||
exl.AddElement(new ushort_const_node(ushort.MinValue,null));
|
||
exl.AddElement(new ushort_const_node(ushort.MaxValue,null));
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.element_type.type_special_kind == SemanticTree.type_special_kind.enum_kind)
|
||
{
|
||
ordinal_type_interface ii = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
exl.AddElement(ii.lower_value);
|
||
exl.AddElement(ii.upper_value);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
short_str = true;
|
||
exl.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length,null));
|
||
}
|
||
function_node fn = null;
|
||
if (short_str)
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString.SymbolInfo, loc);
|
||
else
|
||
if (exl.Count > 1)
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds.SymbolInfo, loc);
|
||
else
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedSetInitProcedure.SymbolInfo, loc);
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray());
|
||
|
||
vdn.type = tn;
|
||
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_set_as_constr(var_definition_node vdn, expression_node init_value)
|
||
{
|
||
location loc = (vdn.type as common_type_node).loc;
|
||
if (!SystemUnitAssigned)
|
||
AddError(new NotSupportedError(loc));
|
||
//Когда заработает наследование конструкторов надо вставить это
|
||
/*
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(new typeof_operator(element_type, loc));
|
||
base_function_call bfc = create_constructor_call(vdn.type, exl, loc);
|
||
expression_node expr = find_operator(compiler_string_consts.assign_name, var_ref, bfc, loc);
|
||
*/
|
||
|
||
type_node tn = vdn.type;
|
||
vdn.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
//exl.AddElement(var_ref);
|
||
//exl.AddElement(new typeof_operator(element_type, loc));
|
||
if (tn.element_type == SystemLibrary.SystemLibrary.byte_type)
|
||
{
|
||
exl.AddElement(new byte_const_node(byte.MinValue,null));
|
||
exl.AddElement(new byte_const_node(byte.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.sbyte_type)
|
||
{
|
||
exl.AddElement(new sbyte_const_node(sbyte.MinValue,null));
|
||
exl.AddElement(new sbyte_const_node(sbyte.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.short_type)
|
||
{
|
||
exl.AddElement(new short_const_node(short.MinValue,null));
|
||
exl.AddElement(new short_const_node(short.MaxValue,null));
|
||
}
|
||
else if (tn.element_type == SystemLibrary.SystemLibrary.ushort_type)
|
||
{
|
||
exl.AddElement(new ushort_const_node(ushort.MinValue,null));
|
||
exl.AddElement(new ushort_const_node(ushort.MaxValue,null));
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.element_type.type_special_kind == SemanticTree.type_special_kind.enum_kind)
|
||
{
|
||
ordinal_type_interface ii = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
exl.AddElement(ii.lower_value);
|
||
exl.AddElement(ii.upper_value);
|
||
}
|
||
exl.AddElement(init_value);
|
||
function_node fn = null;
|
||
if (exl.Count > 1)
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(compiler_string_consts.default_constructor_name), loc);
|
||
}
|
||
else
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(compiler_string_consts.default_constructor_name), loc);
|
||
}
|
||
//expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray());
|
||
expression_node expr = create_static_method_call_with_params(fn, loc, tn, false, exl);
|
||
vdn.type = tn;
|
||
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node get_init_call_for_short_string(var_definition_node vdn)
|
||
{
|
||
location loc = (vdn.type as short_string_type_node).loc;
|
||
|
||
type_node tn = vdn.type;
|
||
//vdn.type = SystemLibrary.SystemLibInitializer.ShortStringType.TypeNode;
|
||
vdn.type = SystemLibrary.SystemLibrary.string_type;
|
||
int Length = (tn as short_string_type_node).Length;
|
||
|
||
expression_node var_ref = create_variable_reference(vdn, loc);
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(var_ref);
|
||
exl.AddElement(new int_const_node(Length, loc));
|
||
expression_node expr = null;
|
||
//if (SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure != null)
|
||
//convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure.SymbolInfo, null, context.converted_type, context.top_function, true);
|
||
|
||
vdn.type = tn;
|
||
|
||
return expr;
|
||
}
|
||
|
||
|
||
public override void visit(SyntaxTree.op_type_node _op_type_node)
|
||
{
|
||
throw new NotSupportedError(get_location(_op_type_node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.raise_stmt _raise_stmt)
|
||
{
|
||
location loc = get_location(_raise_stmt);
|
||
if (_raise_stmt.expr == null)
|
||
{
|
||
if (current_catch_excep == null) AddError(loc, "RAISE_WITHOUT_PARAMETERS_MUST_BE_IN_CATCH_BLOCK");
|
||
return_value(new rethrow_statement_node(loc));
|
||
return;
|
||
}
|
||
expression_node en = convert_strong(_raise_stmt.expr);
|
||
if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression);
|
||
if (!SemanticRules.GenerateNativeCode && (!(type_table.is_derived(SystemLibrary.SystemLibrary.exception_base_type, en.type))) &&
|
||
(en.type != SystemLibrary.SystemLibrary.exception_base_type))
|
||
{
|
||
AddError(loc, "EXCEPTION_TYPE_MUST_BE_SYSTEM_EXCEPTION_OR_DERIVED_FROM_EXCEPTION");
|
||
}
|
||
if (_raise_stmt.address != null)
|
||
{
|
||
AddError(new NotSupportedError(get_location(_raise_stmt.address)));
|
||
}
|
||
return_value(new throw_statement_node(en, loc));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.token_info _token_info)
|
||
{
|
||
throw new NotSupportedError(get_location(_token_info));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.initfinal_part _initfinal_part)
|
||
{
|
||
}
|
||
|
||
private bool is_format_allowed=false;
|
||
|
||
public override void visit(SyntaxTree.format_expr _format_expr)
|
||
{
|
||
if (_format_expr.expr == null || _format_expr.format1 == null)
|
||
AddError(get_location(_format_expr), "BAD_CONSTRUCTED_FORMAT_EXPRESSION");
|
||
//TODO: Добавить проверки.
|
||
if (!SemanticRules.AllowUseFormatExprAnywhere && !is_format_allowed)
|
||
AddError(get_location(_format_expr.expr), "FORMAT_EXPRESSION_CAN_USE_ONLY_IN_THESE_PROCEDURES");
|
||
expression_node expr = convert_strong(_format_expr.expr);
|
||
if (expr is typed_expression)
|
||
expr = convert_typed_expression_to_function_call(expr as typed_expression);
|
||
expression_node par1 = convert_strong(_format_expr.format1);
|
||
par1 = convertion_data_and_alghoritms.convert_type(par1, SystemLibrary.SystemLibrary.integer_type);
|
||
expression_node par2 = convert_weak(_format_expr.format2);
|
||
if (par2 != null)
|
||
{
|
||
if (expr.type != SystemLibrary.SystemLibrary.double_type && expr.type != SystemLibrary.SystemLibrary.float_type)
|
||
{
|
||
AddError(expr.location, "REAL_TYPE_IN_DOUBLE_COLON_EXPRESSION_EXPECTED");
|
||
}
|
||
par2 = convertion_data_and_alghoritms.convert_type(par2, SystemLibrary.SystemLibrary.integer_type);
|
||
}
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(expr);
|
||
exl.AddElement(par1);
|
||
if (par2 != null)
|
||
{
|
||
exl.AddElement(par2);
|
||
}
|
||
location loc = get_location(_format_expr);
|
||
if (!SystemUnitAssigned)
|
||
AddError( new NotSupportedError(loc));
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.format_function.SymbolInfo,
|
||
loc);
|
||
expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray());
|
||
return_value(ret);
|
||
}
|
||
|
||
internal bool inherited_ident_processing = false;
|
||
public override void visit(SyntaxTree.inherited_ident _inherited_ident)
|
||
{
|
||
inherited_ident_processing = true;
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: return_addressed_value(inherited_ident_address_reciving(_inherited_ident)); break;
|
||
case motivation.expression_evaluation: return_value(inherited_ident_value_reciving(_inherited_ident)); break;
|
||
//case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(inherited_ident_semantic_reciving(_inherited_ident)); break;
|
||
}
|
||
inherited_ident_processing = false;
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.property_parameter_list _property_parameter_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_property_parameter_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.property_parameter _property_parameter)
|
||
{
|
||
throw new NotSupportedError(get_location(_property_parameter));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.property_interface _property_interface)
|
||
{
|
||
//throw new NotSupportedError(get_location(_property_interface));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.property_array_default _property_array_default)
|
||
{
|
||
throw new NotSupportedError(get_location(_property_array_default));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.record_type_parts _record_type_parts)
|
||
{
|
||
throw new NotSupportedError(get_location(_record_type_parts));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.var_def_list_for_record _var_def_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_var_def_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.diapason_expr _diapason_expr)
|
||
{
|
||
throw new NotSupportedError(get_location(_diapason_expr));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.case_variants _case_variants)
|
||
{
|
||
throw new NotSupportedError(get_location(_case_variants));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.literal _literal)
|
||
{
|
||
throw new NotSupportedError(get_location(_literal));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.array_of_const_type_definition _array_of_const_type_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_array_of_const_type_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.array_of_named_type_definition _array_of_named_type_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_array_of_named_type_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.proc_block _proc_block)
|
||
{
|
||
throw new NotSupportedError(get_location(_proc_block));
|
||
}
|
||
|
||
private statements_list get_statements_list(statement_node sn)
|
||
{
|
||
statements_list snl = sn as statements_list;
|
||
if (snl != null)
|
||
{
|
||
return snl;
|
||
}
|
||
snl = new statements_list(null);
|
||
snl.statements.AddElement(sn);
|
||
return snl;
|
||
}
|
||
|
||
private statements_list add_first_statement(statement_node list, statement_node statement)
|
||
{
|
||
statements_list snl = get_statements_list(list);
|
||
snl.statements.AddElementFirst(statement);
|
||
return snl;
|
||
}
|
||
|
||
private statements_list add_last_statement(statement_node list, statement_node statement)
|
||
{
|
||
statements_list snl = get_statements_list(list);
|
||
snl.statements.AddElement(statement);
|
||
return snl;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.block _block)
|
||
{
|
||
if (context.converting_block() != block_type.namespace_block && _block.defs != null && _block.defs.defs != null)
|
||
{
|
||
foreach (var def in _block.defs.defs.Where(d => d is const_definition ||
|
||
d is consts_definitions_list ||
|
||
d is variable_definitions))
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(def);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInDeclarationsSection(get_location(lambdaSearcher.FoundLambda))); // SSM 6.06.15 - Хочется убрать это. В разделе описаний лямбды нужны - пусть и без замыканий. Если внутри подпрограммы - не нужны, но Вы же запретили везде!
|
||
}
|
||
}
|
||
}
|
||
if (context.converting_block() == block_type.function_block && context.converted_func_stack.size == 1)
|
||
{
|
||
if (_block.defs != null)
|
||
foreach (declaration decl in _block.defs.defs)
|
||
{
|
||
if (decl is procedure_definition)
|
||
{
|
||
context.has_nested_functions = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
weak_node_test_and_visit(_block.defs);
|
||
if (context.converting_block() == block_type.function_block && context.converted_func_stack.size == 1)
|
||
context.has_nested_functions = false;
|
||
//ssyy добавил генерацию вызова конструктора предка без параметров
|
||
if (context.converting_block() == block_type.function_block)
|
||
{
|
||
common_method_node cmn = context.top_function as common_method_node;
|
||
if (cmn != null && cmn.is_constructor && !(cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static))
|
||
{
|
||
context.allow_inherited_ctor_call = true;
|
||
if (_block.program_code != null && _block.program_code.subnodes != null)
|
||
{
|
||
//(ssyy) Для записей конструктор предка не вызываем.
|
||
bool should_ctor_add = context.converted_type.is_class;
|
||
if (should_ctor_add)
|
||
{
|
||
if (_block.program_code.subnodes.Count > 0)
|
||
{
|
||
SyntaxTree.procedure_call pc = _block.program_code.subnodes[0] as SyntaxTree.procedure_call;
|
||
if (pc != null || _block.program_code.subnodes[0] is SyntaxTree.inherited_message)
|
||
{
|
||
//SyntaxTree.inherited_ident ii = pc.func_name as SyntaxTree.inherited_ident;
|
||
//SyntaxTree.method_call mc = pc.func_name as SyntaxTree.method_call;
|
||
//SyntaxTree.ident id = pc.func_name as SyntaxTree.ident;
|
||
//if (/*ii != null*/id != null || mc != null /*&& mc.dereferencing_value is SyntaxTree.inherited_ident*/)
|
||
{
|
||
//(ssyy) Не уверен, что следующий оператор необходим.
|
||
convertion_data_and_alghoritms.check_node_parser_error(_block.program_code);
|
||
|
||
statement_node inh = convert_strong(_block.program_code.subnodes[0]);
|
||
|
||
compiled_constructor_call c1 = inh as compiled_constructor_call;
|
||
if (c1 != null && !c1._new_obj_awaited)
|
||
{
|
||
should_ctor_add = false;
|
||
}
|
||
else
|
||
{
|
||
common_constructor_call c2 = inh as common_constructor_call;
|
||
if (c2 != null && !c2._new_obj_awaited)
|
||
{
|
||
should_ctor_add = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (should_ctor_add)
|
||
{
|
||
//Пытаемся добавить вызов .ctor() предка...
|
||
//Для начала проверим, есть ли у предка таковой.
|
||
bool not_found = true;
|
||
SymbolInfo sym = context.converted_type.base_type.find_in_type(compiler_string_consts.default_constructor_name, context.CurrentScope);
|
||
while (not_found && sym != null)
|
||
{
|
||
compiled_constructor_node ccn = sym.sym_info as compiled_constructor_node;
|
||
if (ccn != null && ccn.parameters.Count == 0)
|
||
{
|
||
not_found = false;
|
||
}
|
||
else
|
||
{
|
||
common_method_node cnode = sym.sym_info as common_method_node;
|
||
if (cnode != null && cnode.is_constructor && (cnode.parameters.Count == 0 || cnode.parameters[0].default_value != null))
|
||
{
|
||
not_found = false;
|
||
}
|
||
}
|
||
sym = sym.Next;
|
||
}
|
||
if (not_found)
|
||
{
|
||
//У предка нет конструктора по умолчанию
|
||
AddError(get_location(_block.program_code), "INHERITED_CONSTRUCTOR_CALL_EXPECTED");
|
||
}
|
||
else
|
||
{
|
||
//Генерируем вызов .ctor() предка
|
||
SyntaxTree.inherited_ident ii = new SyntaxTree.inherited_ident();
|
||
ii.name = compiler_string_consts.default_constructor_name;
|
||
_block.program_code.subnodes.Insert(0, new SyntaxTree.procedure_call(ii));
|
||
//context.allow_inherited_ctor_call = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
//ssyy
|
||
if (context.converting_block() == block_type.namespace_block)
|
||
{
|
||
context.check_predefinition_defined();
|
||
}
|
||
|
||
if (lambdaProcessingState == LambdaProcessingState.None && _block.program_code != null)
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(_block.program_code);
|
||
var lambdaIsFound = lambdaSearcher.CheckIfContainsLambdas();
|
||
|
||
if ((context.converting_block() == block_type.function_block ||
|
||
context.converting_block() == block_type.namespace_block) &&
|
||
lambdaIsFound)
|
||
// TODO: Пока обрабатываются только блок функции и основной блок, необходимо обрабатывать случаи появлений лямбд в var_def_statement
|
||
{
|
||
if (context.converting_block() == block_type.function_block)
|
||
{
|
||
if (context.func_stack.top().functions_nodes_list.Count > 0)
|
||
{
|
||
AddError(new LambdasNotAllowedWhenNestedSubprogrammesAreUsed(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
|
||
lambdaProcessingState = LambdaProcessingState.TypeInferencePhase;
|
||
visit_program_code(_block.program_code);
|
||
|
||
lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase;
|
||
CapturedVariablesSubstitutionsManager.Substitute(this, _block.defs, _block.program_code);
|
||
|
||
lambdaProcessingState = LambdaProcessingState.FinishPhase;
|
||
|
||
context.code = visit_program_code(_block.program_code);
|
||
|
||
lambdaProcessingState = LambdaProcessingState.None;
|
||
}
|
||
else
|
||
{
|
||
context.code = visit_program_code(_block.program_code);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
context.code = visit_program_code(_block.program_code);
|
||
}
|
||
}
|
||
|
||
private statement_node visit_program_code(statement_list program_code)
|
||
{
|
||
context.enter_code_block_with_bind();
|
||
statement_node sn = convert_strong(program_code);
|
||
context.leave_code_block();
|
||
|
||
return sn;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.diap_expr _diap_expr)
|
||
{
|
||
throw new NotSupportedError(get_location(_diap_expr));
|
||
}
|
||
internal SymbolTable.Scope[] build_referenced_units(unit_node_list referenced_units, bool try_get_system_module)
|
||
{
|
||
List<SymbolTable.Scope> used_units = new List<SymbolTable.Scope>();
|
||
Dictionary<System.Reflection.Assembly, dot_net_unit_node> assembly_references_dict = new Dictionary<System.Reflection.Assembly, dot_net_unit_node>();
|
||
for (int i = 0; i < referenced_units.Count; i++)
|
||
{
|
||
if (referenced_units[i] is dot_net_unit_node)
|
||
if (!assembly_references_dict.ContainsKey((referenced_units[i] as dot_net_unit_node).dotNetScope._assembly))
|
||
assembly_references_dict.Add((referenced_units[i] as dot_net_unit_node).dotNetScope._assembly, referenced_units[i] as dot_net_unit_node);
|
||
}
|
||
dot_net_unit_node[] assembly_references = new dot_net_unit_node[assembly_references_dict.Values.Count];
|
||
assembly_references_dict.Values.CopyTo(assembly_references, 0);
|
||
List<NetHelper.NetScope> def_scopes = new List<NetHelper.NetScope>();
|
||
if (SemanticRules.AllowGlobalVisibilityForPABCDll)
|
||
{
|
||
for (int i = 0; i < assembly_references.Length; i++)
|
||
{
|
||
if (assembly_references[i].dotNetScope.entry_type != null)
|
||
def_scopes.Add(assembly_references[i].dotNetScope);
|
||
}
|
||
}
|
||
//used_units.Add(_system_unit.scope);
|
||
for (int i = 0; i < referenced_units.Count; i++)
|
||
{
|
||
if (!(referenced_units[i] is dot_net_unit_node))
|
||
{
|
||
if (referenced_units[i] is namespace_unit_node)
|
||
{
|
||
for (int j = 0; j < assembly_references.Length; j++)
|
||
{
|
||
using_namespace_list unl = new using_namespace_list();
|
||
unl.AddElement((referenced_units[i] as namespace_unit_node).namespace_name);
|
||
NetHelper.NetScope ns = new PascalABCCompiler.NetHelper.NetScope(unl, assembly_references[j].dotNetScope._assembly, SymbolTable);
|
||
used_units.Add(ns);
|
||
}
|
||
if (_compiled_unit != null)
|
||
_compiled_unit.used_namespaces.Add((referenced_units[i] as namespace_unit_node).namespace_name.namespace_name);
|
||
}
|
||
else
|
||
{
|
||
common_unit_node cun = _referenced_units[i] as common_unit_node;
|
||
if (cun != null)
|
||
{
|
||
if (try_get_system_module && cun.IsSystemUnit)
|
||
{
|
||
get_system_module(cun);
|
||
for (int j = 0; j < def_scopes.Count; j++)
|
||
{
|
||
used_units.Add(new PascalABCCompiler.NetHelper.NetScope(interface_using_list, def_scopes[j]._assembly, SymbolTable));
|
||
}
|
||
}
|
||
used_units.Add(cun.scope);
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Unexpected unit type.");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dot_net_unit_node dun = referenced_units[i] as dot_net_unit_node;
|
||
if (dun.dotNetScope.entry_type != null && dun.dotNetScope.entry_type.Name == "PABCRtl")
|
||
{
|
||
if (try_get_system_module)
|
||
{
|
||
from_pabc_dll = true;
|
||
get_system_module_from_dll(dun);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
List<SymTable.Scope> fetched_used_units = new List<SymTable.Scope>();
|
||
Dictionary<System.Reflection.Assembly, PascalABCCompiler.NetHelper.NetScope> assm_cache = new Dictionary<System.Reflection.Assembly, PascalABCCompiler.NetHelper.NetScope>();
|
||
for (int i = 0; i < used_units.Count; i++)
|
||
{
|
||
PascalABCCompiler.NetHelper.NetScope net_scope = used_units[i] as PascalABCCompiler.NetHelper.NetScope;
|
||
if (net_scope != null)
|
||
{
|
||
PascalABCCompiler.NetHelper.NetScope existing_scope = null;
|
||
if (assm_cache.TryGetValue(net_scope.Assembly, out existing_scope))
|
||
{
|
||
/*if (net_scope.used_namespaces)
|
||
{
|
||
foreach (using_namespace un in net_scope.used_namespaces)
|
||
{
|
||
if (un.namespace_name)
|
||
}
|
||
}*/
|
||
existing_scope.used_namespaces.AddRange(net_scope.used_namespaces);
|
||
}
|
||
else
|
||
{
|
||
if (NetHelper.NetHelper.PABCSystemType == null || net_scope.Assembly != NetHelper.NetHelper.PABCSystemType.Assembly)
|
||
assm_cache.Add(net_scope.Assembly, net_scope);
|
||
fetched_used_units.Add(net_scope);
|
||
}
|
||
}
|
||
else
|
||
fetched_used_units.Add(used_units[i]);
|
||
}
|
||
used_units = fetched_used_units;
|
||
//Если компилими implementation то в начало кладем все что было в interface
|
||
for (int i = 0; i < assembly_references.Length; i++)
|
||
{
|
||
used_units.Add(new PascalABCCompiler.NetHelper.NetScope(interface_using_list, (assembly_references[i] as dot_net_unit_node).dotNetScope._assembly, SymbolTable));
|
||
}
|
||
used_units.Add(_system_unit.scope);
|
||
|
||
return used_units.ToArray();
|
||
}
|
||
|
||
|
||
public void visit_implementation(SyntaxTree.unit_module _unit_module)
|
||
{
|
||
if (_unit_module.initialization_part != null)
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(_unit_module.initialization_part);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInInitializationPartOfModule(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
|
||
if (_unit_module.finalization_part != null)
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(_unit_module.finalization_part);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInFinalizationPartOfModule(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
|
||
//using_list.AddRange(implementation_using_list);
|
||
/*if (_unit_module.implementation_part != null)
|
||
{
|
||
weak_node_test_and_visit(_unit_module.implementation_part.using_namespaces);
|
||
}*/
|
||
|
||
SymbolTable.Scope[] used_units = build_referenced_units(referenced_units,false);
|
||
|
||
_compiled_unit.implementation_scope =
|
||
convertion_data_and_alghoritms.symbol_table.CreateUnitImplementationScope(_compiled_unit.scope, used_units);
|
||
|
||
location loc = null;
|
||
if (_unit_module.unit_name != null)
|
||
{
|
||
loc = get_location(_unit_module.unit_name);
|
||
}
|
||
|
||
common_namespace_node cnsn = context.create_namespace(_unit_module.unit_name.idunit_name.name + compiler_string_consts.ImplementationSectionNamespaceName,
|
||
_compiled_unit, _compiled_unit.implementation_scope, loc);
|
||
|
||
//cnsn.scope=_compiled_unit.implementation_scope;
|
||
|
||
if (_unit_module.implementation_part != null)
|
||
{
|
||
hard_node_test_and_visit(_unit_module.implementation_part);
|
||
}
|
||
|
||
//weak_node_test_and_visit(_unit_module.initialization_part);
|
||
context.enter_code_block_without_bind();
|
||
|
||
statement_node init_statements = convert_weak(_unit_module.initialization_part);
|
||
context.leave_code_block();
|
||
common_namespace_function_node initialization_function = null;
|
||
if (init_statements != null)
|
||
{
|
||
context.check_labels(context.converted_namespace.labels);
|
||
//(ssyy) Блокируем поставленные метки, чтобы не допустить переход из finalization-секции
|
||
//context.block_defined_labels(context.converted_namespace.labels);
|
||
initialization_function = new common_namespace_function_node(compiler_string_consts.initialization_function_name,
|
||
null, init_statements.location, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateScope(context.converted_namespace.scope));
|
||
initialization_function.function_code = init_statements;
|
||
cnsn.functions.AddElement(initialization_function);
|
||
_compiled_unit.main_function = initialization_function;
|
||
context.apply_special_local_vars(_compiled_unit.main_function);
|
||
}
|
||
|
||
context.enter_code_block_without_bind();
|
||
statement_node final_statements = convert_weak(_unit_module.finalization_part);
|
||
context.leave_code_block();
|
||
common_namespace_function_node finalization_function = null;
|
||
if (final_statements != null)
|
||
{
|
||
context.check_labels(context.converted_namespace.labels);
|
||
finalization_function = new common_namespace_function_node(compiler_string_consts.finalization_function_name,
|
||
null, final_statements.location, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateScope(context.converted_namespace.scope));
|
||
finalization_function.function_code = final_statements;
|
||
cnsn.functions.AddElement(finalization_function);
|
||
_compiled_unit.finalization_method = finalization_function;
|
||
context.apply_special_local_vars(_compiled_unit.finalization_method);
|
||
}
|
||
|
||
context.check_all_name_unit_defined(_compiled_unit);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.implementation_node _implementation_node)
|
||
{
|
||
if (_implementation_node.implementation_definitions != null && _implementation_node.implementation_definitions.defs != null)
|
||
{
|
||
foreach (var def in _implementation_node.implementation_definitions.defs.Where(d => d is const_definition ||
|
||
d is consts_definitions_list ||
|
||
d is variable_definitions))
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(def);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInImplementationOfModuleInInit(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
}
|
||
|
||
weak_node_test_and_visit(_implementation_node.implementation_definitions);
|
||
}
|
||
|
||
bool in_interface_part = false;
|
||
|
||
public override void visit(SyntaxTree.interface_node _interface_node)
|
||
{
|
||
if (_interface_node.interface_definitions != null && _interface_node.interface_definitions.defs != null)
|
||
{
|
||
foreach (var def in _interface_node.interface_definitions.defs.Where(d => d is const_definition ||
|
||
d is consts_definitions_list ||
|
||
d is variable_definitions))
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(def);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInInterfacePartOfModuleInInit(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
}
|
||
|
||
weak_node_test_and_visit(_interface_node.interface_definitions);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.typecast_node node)
|
||
{
|
||
|
||
expression_node en = convert_strong(node.expr);
|
||
location loc = get_location(node);
|
||
type_node tp = convert_strong(node.type_def);
|
||
//ssyy
|
||
if (en.type.semantic_node_type == semantic_node_type.delegated_method)
|
||
{
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
}
|
||
//\ssyy
|
||
if (!SemanticRules.IsAsForPointers && (tp.IsPointer || en.type.IsPointer))
|
||
{
|
||
if (node.cast_op == PascalABCCompiler.SyntaxTree.op_typecast.is_op)
|
||
AddError(loc, "OPERATOR_{0}_CAN_NOT_BE_APPLIED_TO_POINTER_TYPE", compiler_string_consts.is_name);
|
||
else
|
||
AddError(loc, "OPERATOR_{0}_CAN_NOT_BE_APPLIED_TO_POINTER_TYPE", compiler_string_consts.as_name);
|
||
}
|
||
else
|
||
if (!(type_table.is_derived(en.type, tp) || type_table.is_derived(tp, en.type) || en.type == tp || en.type == SystemLibrary.SystemLibrary.object_type
|
||
|| en.type.IsInterface || tp.IsInterface))
|
||
{
|
||
AddError(loc, "EXPECTED_DERIVED_CLASSES");
|
||
}
|
||
if (en.type.IsSealed && tp.IsInterface && !en.type.ImplementingInterfaces.Contains(tp))
|
||
{
|
||
AddError(loc, "CAN_NOT_CONVERT_TYPE_{0}_TO_INTERFACE_{1}", en.type.PrintableName, tp.PrintableName);
|
||
}
|
||
if (node.cast_op == PascalABCCompiler.SyntaxTree.op_typecast.is_op)
|
||
{
|
||
is_node isn = new is_node(en, tp, loc);
|
||
return_value(isn);
|
||
}
|
||
else
|
||
{
|
||
if (tp.is_generic_parameter && !tp.is_class)
|
||
AddError(get_location(node.type_def), "OPERATOR_AS_CAN_NOT_BE_USED_WITH_GENERIC_PARAMETER_{0}_WITHOUT_CLASS_CONSTRAINT", tp.name);
|
||
if (tp.is_value_type)
|
||
AddError(get_location(node.type_def), "OPERATOR_AS_MUST_BE_USED_WITCH_A_REFERENCE_TYPE_VALUETYPE{0}", tp.PrintableName);
|
||
as_node asn = new as_node(en, tp, loc);
|
||
return_value(asn);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.inherited_method_call _inherited_method_call)
|
||
{
|
||
throw new NotSupportedError(get_location(_inherited_method_call));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.destructor _destructor)
|
||
{
|
||
if (_destructor.name == null)
|
||
{
|
||
AddError(get_location(_destructor), "DESTRUCTOR_MUST_HAVE_NAME");
|
||
}
|
||
if (context.converting_block() == block_type.type_block)
|
||
{
|
||
if (context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_destructor), "DESTRUCTOR_IN_INTERFACE");
|
||
}
|
||
if (!context.converted_type.is_class)
|
||
{
|
||
AddError(get_location(_destructor), "DESTRUCTOR_NOT_IN_CLASS");
|
||
}
|
||
}
|
||
else if (!(context.converting_block() == block_type.namespace_block && _destructor.name.class_name != null))
|
||
{
|
||
AddError(get_location(_destructor), "DESTRUCTOR_NOT_IN_CLASS");
|
||
}
|
||
if (_destructor.parameters != null && _destructor.parameters.params_list.Count > 0)
|
||
{
|
||
AddError(get_location(_destructor), "DESTRUCTOR_CANNOT_HAVE_PARAMETERS");
|
||
}
|
||
visit_procedure_header(_destructor);
|
||
}
|
||
|
||
//ssyy изменил этот метод из-за изменения концепции конструкторов
|
||
public override void visit(SyntaxTree.constructor _constructor)
|
||
{
|
||
if (context.converting_block() == block_type.type_block)
|
||
{
|
||
if (context.converted_type.IsInterface)
|
||
{
|
||
AddError(new ConstructorInInterface(get_location(_constructor)));
|
||
}
|
||
/*if (!context.converted_type.is_class)
|
||
{
|
||
throw new ConstructorNotInClass(get_location(_constructor));
|
||
}*/
|
||
}
|
||
else if (!(context.converting_block() == block_type.namespace_block && _constructor.name != null && _constructor.name.class_name != null))
|
||
{
|
||
AddError(get_location(_constructor), "CONSTRUCTOR_NOT_IN_CLASS");
|
||
}
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(_constructor.name);
|
||
|
||
if (_constructor.name == null)
|
||
{
|
||
SyntaxTree.ident name = new SyntaxTree.ident(compiler_string_consts.default_constructor_name);
|
||
_constructor.name = new PascalABCCompiler.SyntaxTree.method_name(null, null, name, null);
|
||
_constructor.name.source_context = _constructor.name.meth_name.source_context = _constructor.source_context;
|
||
}
|
||
|
||
if (_constructor.name.meth_name.name.ToLower() != compiler_string_consts.default_constructor_name)
|
||
AddError(get_location(_constructor.name), "CONSTRUCTOR_CAN_HAVE_ONLY_{0}_NAME", compiler_string_consts.default_constructor_name);
|
||
if ((_constructor.name.class_name == null) && (context.converting_block() != block_type.type_block))
|
||
{
|
||
AddError(get_location(_constructor.name), "ONLY_CONSTRUCTOR_OF_TYPE_ALLOWED");
|
||
}
|
||
|
||
foreach (SyntaxTree.procedure_attribute att in _constructor.proc_attributes.proc_attributes)
|
||
{
|
||
if (att.attribute_type == SyntaxTree.proc_attribute.attr_virtual)
|
||
{
|
||
AddError(get_location(att), "CONSTRUCTOR_CAN_NOT_BE_VIRTUAL");
|
||
}
|
||
else if (att.attribute_type == SyntaxTree.proc_attribute.attr_override)
|
||
{
|
||
AddError(get_location(att), "CONSTRUCTOR_CAN_NOT_BE_OVERRIDE");
|
||
}
|
||
else if (att.attribute_type == SyntaxTree.proc_attribute.attr_abstract)
|
||
{
|
||
AddError(get_location(att), "CONSTRUCTOR_CANNOT_BE_ABSTRACT");
|
||
}
|
||
}
|
||
if (_constructor.class_keyword)
|
||
{
|
||
SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static);
|
||
pa.source_context = _constructor.source_context;
|
||
_constructor.proc_attributes.proc_attributes.Add(pa);
|
||
}
|
||
foreach (SyntaxTree.procedure_attribute att in _constructor.proc_attributes.proc_attributes)
|
||
{
|
||
if (att.attribute_type == SyntaxTree.proc_attribute.attr_static)
|
||
{
|
||
//Это статический конструктор
|
||
if (_constructor.parameters != null)
|
||
{
|
||
AddError(get_location(_constructor.name), "STATIC_CONSTRUCTOR_MUST_BE_PARAMETERLESS");
|
||
}
|
||
_constructor.name.meth_name.name = compiler_string_consts.static_ctor_prefix + _constructor.name.meth_name.name;
|
||
visit_procedure_header(_constructor);
|
||
if (context.top_function != null)
|
||
{
|
||
(context.top_function as common_method_node).is_constructor = true;
|
||
(context.top_function as common_method_node).cont_type.static_constr = context.top_function as common_method_node;
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (context.converting_block() == block_type.type_block)
|
||
{
|
||
//Нужно для генерации унаследованных конструкторов
|
||
context.converted_type.has_user_defined_constructor = true;
|
||
|
||
//Нужно для генерации конструктора по умолчанию
|
||
if (_constructor.parameters == null || _constructor.parameters.params_list[0].inital_value != null)
|
||
{
|
||
context.converted_type.has_default_constructor = true;
|
||
}
|
||
}
|
||
|
||
visit_procedure_header(_constructor);
|
||
|
||
if (context.top_function == null)
|
||
{
|
||
return;
|
||
}
|
||
common_method_node cmn = context.top_function as common_method_node;
|
||
|
||
if (cmn == null)
|
||
{
|
||
throw new CompilerInternalError("Constructor is not common_method_node.");
|
||
}
|
||
|
||
context.allow_inherited_ctor_call = true;
|
||
cmn.is_constructor = true;
|
||
cmn.return_value_type = context.converted_type;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.file_type_definition _file_type_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_file_type_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.nil_const _nil_const)
|
||
{
|
||
return_value(new null_const_node(null_type_node.get_type_node(), get_location(_nil_const)));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.class_predefinition _class_predefinition)
|
||
{
|
||
throw new NotSupportedError(get_location(_class_predefinition));
|
||
}
|
||
|
||
private bool statement_expected = false;
|
||
private bool procedure_wait = false;
|
||
public override void visit(SyntaxTree.procedure_call _procedure_call)
|
||
{
|
||
procedure_wait = true;
|
||
SyntaxTree.method_call mc = null;
|
||
mc = _procedure_call.func_name as SyntaxTree.method_call;
|
||
if (mc == null)
|
||
{
|
||
SyntaxTree.ident id = _procedure_call.func_name as SyntaxTree.ident;
|
||
if (id != null)
|
||
{
|
||
mc = new SyntaxTree.method_call();
|
||
mc.dereferencing_value = id;
|
||
//DarkStar Add
|
||
//Добавил т.к. нужно для генерации отладочной инфы
|
||
mc.source_context = id.source_context;
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.addressed_value adrv = _procedure_call.func_name as SyntaxTree.addressed_value;
|
||
if (adrv != null)
|
||
{
|
||
mc = new SyntaxTree.method_call();
|
||
mc.dereferencing_value = adrv;
|
||
//DarkStar Add
|
||
//Добавил т.к. нужно для генерации отладочной инфы
|
||
mc.source_context = adrv.source_context;
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Undefined procedure name");
|
||
}
|
||
}
|
||
}
|
||
//statement_node sn=convert_strong(_procedure_call.func_name);
|
||
statement_node sn = convert_strong(mc);
|
||
//проверяем на случай вызова типа real(a) ...
|
||
if (/*((sn is base_function_call) && (sn as base_function_call).IsExplicitConversion)
|
||
|| (sn is SemanticTree.IReferenceNode)
|
||
|| (sn is SemanticTree.IGetAddrNode)
|
||
|| (sn is null_const_node)
|
||
|| (sn is simple_array_indexing)
|
||
|| (sn is basic_function_call)
|
||
|| (sn is constant_node)
|
||
|| (sn is class_field_reference)*/
|
||
!(sn is base_function_call) && !(sn is exit_procedure) && !(sn is while_break_node) && !(sn is while_continue_node)
|
||
&& !(sn is repeat_break_node) && !(sn is repeat_continue_node) && !(sn is for_break_node) && !(sn is for_continue_node)
|
||
&& !(sn is foreach_break_node) && !(sn is foreach_continue_node)
|
||
)
|
||
AddError(get_location(_procedure_call), "STATEMENT_EXPECTED");
|
||
|
||
return_value(sn);
|
||
//_procedure_call.func_name.visit(this);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variant_record_type _variant_record_type)
|
||
{
|
||
throw new NotSupportedError(get_location(_variant_record_type));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variant_types _variant_types)
|
||
{
|
||
throw new NotSupportedError(get_location(_variant_types));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variant_type _variant_type)
|
||
{
|
||
throw new NotSupportedError(get_location(_variant_type));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variant_list _variant_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_variant_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variant _variant)
|
||
{
|
||
throw new NotSupportedError(get_location(_variant));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.string_num_definition node)
|
||
{
|
||
location loc = get_location(node);
|
||
//if (SystemLibrary.SystemLibInitializer.ShortStringType.NotFound)
|
||
// throw new NotSupportedError(loc);
|
||
type_node tn = find_type(node.name.name, loc);
|
||
if (!(tn == SystemLibrary.SystemLibrary.string_type))
|
||
AddError(new ExpectedType(SystemLibrary.SystemLibrary.string_type.name, loc));
|
||
constant_node cn = convert_strong_to_constant_node(node.num_of_symbols, SystemLibrary.SystemLibrary.integer_type);
|
||
int length = (cn as int_const_node).constant_value;
|
||
if (length < 1 || length > 256)
|
||
AddError(loc, "TYPE_CAN_NOT_HAVE_THIS_SIZE_{0}", SystemLibrary.SystemLibrary.string_type.name);
|
||
return_value(context.create_short_string_type(length, loc));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.literal_const_line _literal_const_line)
|
||
{
|
||
//DarkStar Add
|
||
string s = "";
|
||
SyntaxTree.string_const strc;
|
||
SyntaxTree.sharp_char_const sharpcharconst;
|
||
SyntaxTree.char_const charconst;
|
||
SyntaxTree.syntax_tree_node tnf = _literal_const_line.literals[0], tnl = null;
|
||
for (int i = 0; i < _literal_const_line.literals.Count; i++)
|
||
{
|
||
if ((strc = _literal_const_line.literals[i] as SyntaxTree.string_const) != null)
|
||
s = s + strc.Value;
|
||
else
|
||
if ((sharpcharconst = _literal_const_line.literals[i] as SyntaxTree.sharp_char_const) != null)
|
||
s = s + Convert.ToChar(sharpcharconst.char_num);
|
||
else
|
||
if ((charconst = _literal_const_line.literals[i] as SyntaxTree.char_const) != null)
|
||
s = s + charconst.cconst;
|
||
if (i == _literal_const_line.literals.Count - 1)
|
||
tnl = _literal_const_line.literals[i];
|
||
}
|
||
expression_node en = new string_const_node(s, new location(tnf.source_context.begin_position.line_num, tnf.source_context.begin_position.column_num,
|
||
tnl.source_context.end_position.line_num, tnl.source_context.end_position.column_num, current_document));
|
||
return_value(en);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.sharp_char_const _sharp_char_const)
|
||
{
|
||
return_value(new char_const_node(Convert.ToChar(_sharp_char_const.char_num), get_location(_sharp_char_const)));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.raise_statement _raise_statement)
|
||
{
|
||
throw new NotSupportedError(get_location(_raise_statement));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.char_const _char_const)
|
||
{
|
||
expression_node en = new char_const_node(_char_const.cconst, get_location(_char_const));
|
||
return_value(en);
|
||
}
|
||
|
||
private bool check_if_has_enum_consts(SyntaxTree.enum_type_definition _enum_type_definition)
|
||
{
|
||
bool has_val = false;
|
||
foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators)
|
||
{
|
||
if (en.value != null)
|
||
{
|
||
has_val = true;
|
||
}
|
||
else
|
||
if (has_val)
|
||
AddError(get_location(en), "ALL_ENUM_CONSTANTS_NEEDED");
|
||
}
|
||
return has_val;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.enum_type_definition _enum_type_definition)
|
||
{
|
||
//SSM 15/01/16 - реализация (integer,integer)
|
||
// Если кто-то - не named_type_reference с одним ident, то надо идти по ветке типов - это не м.б.перечисление
|
||
bool is_tuple_type = false;
|
||
foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators)
|
||
{
|
||
if (!((en.name is named_type_reference) && (en.name as named_type_reference).names.Count()==1))
|
||
{
|
||
is_tuple_type = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
bool is_enum = false;
|
||
if (!is_tuple_type) // Значит, все - идентификаторы и сказать пока ничего нельзя
|
||
foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators)
|
||
{
|
||
SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent;
|
||
var si = context.CurrentScope.Find(id.name);
|
||
if ((si==null) || !(si.sym_info is type_node))
|
||
{
|
||
is_enum = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!is_enum) // Значит, это определение типа
|
||
{
|
||
var lt = new List<type_definition>();
|
||
for (var iii=0; iii<_enum_type_definition.enumerators.enumerators.Count(); iii++)
|
||
{
|
||
var en = _enum_type_definition.enumerators.enumerators[iii];
|
||
var name = en.name;
|
||
if (en.value != null)
|
||
AddError(get_location(en.value), "TUPLE_TYPE_ERROR");
|
||
lt.Add(name);
|
||
}
|
||
|
||
var l = new List<ident>();
|
||
l.Add(new ident("?System"));
|
||
l.Add(new ident("Tuple"));
|
||
|
||
var tp = new template_param_list(lt);
|
||
// значит, это Tuple - создать его, обойти и выйти
|
||
var ttr = new SyntaxTree.template_type_reference(new named_type_reference(l), tp);
|
||
visit(ttr);
|
||
return;
|
||
}
|
||
|
||
//end SSM
|
||
|
||
// Если мы здесь - значит, это перечислимый тип
|
||
|
||
//throw new NotSupportedError(get_location(_enum_type_definition));
|
||
//ivan added
|
||
int num = 0;
|
||
List<constant_definition_node> cnsts = new List<constant_definition_node>();
|
||
check_if_has_enum_consts(_enum_type_definition);
|
||
foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators)
|
||
{
|
||
SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent; // это - точно идентификаторы
|
||
|
||
constant_definition_node cdn = context.add_const_definition(id.name, get_location(id));
|
||
if (en.value == null)
|
||
cdn.const_value = new enum_const_node(num++, null, get_location(id));
|
||
else
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(en.value,SystemLibrary.SystemLibrary.integer_type);
|
||
check_for_strong_constant(cn,get_location(en.value));
|
||
cdn.const_value = new enum_const_node((cn as int_const_node).constant_value,null,get_location(id));
|
||
}
|
||
cnsts.Add(cdn);
|
||
}
|
||
common_type_node ctn = context.create_enum_type(null, get_location(_enum_type_definition)); //_enum_type_definition.values
|
||
num = 0;
|
||
foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators)
|
||
{
|
||
SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent;
|
||
constant_definition_node cdn = context.add_const_definition(id.name, get_location(id));
|
||
if (en.value == null)
|
||
cdn.const_value = new enum_const_node(num++, null, get_location(id));
|
||
else
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(en.value,SystemLibrary.SystemLibrary.integer_type);
|
||
check_for_strong_constant(cn,get_location(en.value));
|
||
cdn.const_value = new enum_const_node((cn as int_const_node).constant_value,null,get_location(id));
|
||
}
|
||
cdn.const_value.type = ctn;
|
||
}
|
||
foreach (constant_definition_node cdn in cnsts)
|
||
cdn.const_value.type = ctn;
|
||
internal_interface ii = SystemLibrary.SystemLibrary.integer_type.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
ordinal_type_interface oti_old = (ordinal_type_interface)ii;
|
||
enum_const_node lower_value = new enum_const_node(0, ctn, ctn.loc);
|
||
enum_const_node upper_value = new enum_const_node(ctn.const_defs.Count - 1, ctn, ctn.loc);
|
||
ordinal_type_interface oti_new = new ordinal_type_interface(oti_old.inc_method, oti_old.dec_method,
|
||
oti_old.inc_value_method, oti_old.dec_value_method,
|
||
oti_old.lower_eq_method, oti_old.greater_eq_method, oti_old.lower_method, oti_old.greater_method, lower_value, upper_value, oti_old.value_to_int, oti_old.ordinal_type_to_int);
|
||
|
||
ctn.add_internal_interface(oti_new);
|
||
//foreach (constant_definition_node cdn in cnsts)
|
||
// cdn.const_value.type = ctn;
|
||
//context.leave_block();
|
||
context.leave_record();
|
||
return_value(ctn);
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.record_type _record_type)
|
||
{
|
||
}
|
||
|
||
public override void visit(SyntaxTree.record_const node)
|
||
{
|
||
if (is_typed_const_def)
|
||
{
|
||
record_constant rc = new record_constant(node.rec_consts, get_location(node));
|
||
rc.SetType(new RecordConstType(rc.location));
|
||
return_value(rc);
|
||
}
|
||
else
|
||
{
|
||
record_initializer ri = new record_initializer(node.rec_consts, get_location(node));
|
||
ri.type = new RecordConstType(ri.location);
|
||
return_value(ri);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.record_const_definition _record_const_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_record_const_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.set_type_definition _set_type_definition)
|
||
{
|
||
// throw new NotSupportedError(get_location(_set_type_definition));
|
||
if (SystemLibrary.SystemLibInitializer.TypedSetType == null || SystemLibrary.SystemLibInitializer.CreateSetProcedure == null)
|
||
AddError(new NotSupportedError(get_location(_set_type_definition)));
|
||
type_node el_type = convert_strong(_set_type_definition.of_type);
|
||
if (el_type.IsPointer)
|
||
AddError(get_location(_set_type_definition.of_type), "POINTERS_IN_SETS_NOT_ALLOWED");
|
||
//if (el_type == SystemLibrary.SystemLibrary.void_type)
|
||
// AddError(new VoidNotValid(get_location(_set_type_definition.of_type)));
|
||
check_for_type_allowed(el_type,get_location(_set_type_definition.of_type));
|
||
return_value(context.create_set_type(el_type, get_location(_set_type_definition)));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.known_type_definition _known_type_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_known_type_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.default_indexer_property_node _default_indexer_property_node)
|
||
{
|
||
throw new NotSupportedError(get_location(_default_indexer_property_node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.class_definition _class_definition)
|
||
{
|
||
if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed)
|
||
{
|
||
context.converted_type.SetIsSealed(true);
|
||
if (_class_definition.keyword == SyntaxTree.class_keyword.Interface || _class_definition.keyword == SyntaxTree.class_keyword.TemplateInterface)
|
||
ErrorsList.Add(new SimpleSemanticError(get_location(_class_definition), "INTERFACE_CANNOT_BE_SEALED"));
|
||
}
|
||
if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Abstract) == SyntaxTree.class_attribute.Abstract)
|
||
{
|
||
context.converted_type.SetIsAbstract(true);
|
||
}
|
||
switch (_class_definition.keyword)
|
||
{
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.Class:
|
||
if (context.converted_type.is_value || context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", context.converted_type.name);
|
||
}
|
||
if ((_class_definition.class_parents != null) && (_class_definition.class_parents.types.Count > 0))
|
||
{
|
||
type_node tn = ret.visit(_class_definition.class_parents.types[0]);
|
||
//if (tn == context.converted_type)
|
||
if (type_table.original_types_equals(tn, context.converted_type))
|
||
AddError(new UndefinedNameReference(tn.name, get_location(_class_definition.class_parents.types[0])));
|
||
if (tn.IsSealed)
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "PARENT_TYPE_IS_SALED{0}", tn.name);
|
||
if (tn == SystemLibrary.SystemLibrary.value_type)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_VALUE_TYPE");
|
||
}
|
||
if (tn.IsPointer)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_POINTER");
|
||
}
|
||
if (tn.IsDelegate)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_FUNCTION_TYPE");
|
||
}
|
||
if (tn == SystemLibrary.SystemLibrary.delegate_base_type || tn == SystemLibrary.SystemLibrary.system_delegate_type)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_DELEGATE_TYPE");
|
||
}
|
||
Hashtable used_interfs = new Hashtable();
|
||
//Если tn - это интерфейс
|
||
if (tn.IsInterface)
|
||
{
|
||
//Первым в списке предков идёт интерфейс, поэтому базовым будет object.
|
||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||
|
||
//Добавляем интерфейс
|
||
used_interfs.Add(tn, tn);
|
||
type_table.AddInterface(context.converted_type, tn, get_location(_class_definition.class_parents.types[0]));
|
||
}
|
||
else
|
||
{
|
||
if (tn.ForwardDeclarationOnly)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "FORWARD_DECLARATION_{0}_AS_BASE_TYPE", tn.name);
|
||
}
|
||
if (tn.is_generic_parameter)
|
||
{
|
||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER");
|
||
}
|
||
context.converted_type.SetBaseType(tn);
|
||
}
|
||
//Теперь добавляем интерфейсы.
|
||
//Цикл с единицы, т.к. нулевой элемент уже был рассмотрен.
|
||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 1, used_interfs);
|
||
//for (int i = 1; i < _class_definition.class_parents.types.Count; i++)
|
||
//{
|
||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||
//}
|
||
}
|
||
else
|
||
{
|
||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||
}
|
||
context.converted_type.is_class = true;
|
||
if (_class_definition.body == null &&
|
||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||
{
|
||
if (context.converted_type.ForwardDeclarationOnly)
|
||
{
|
||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||
}
|
||
context.types_predefined.Add(context.converted_type);
|
||
context.converted_type.ForwardDeclarationOnly = true;
|
||
}
|
||
else
|
||
{
|
||
context.converted_type.ForwardDeclarationOnly = false;
|
||
if (_class_definition.body == null)
|
||
{
|
||
generate_inherit_constructors();
|
||
if (!context.converted_type.has_default_constructor)
|
||
{
|
||
generate_default_constructor();
|
||
}
|
||
}
|
||
List<SyntaxTree.ident> names = new List<SyntaxTree.ident>();
|
||
List<SyntaxTree.type_definition> types = new List<SyntaxTree.type_definition>();
|
||
if (((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Auto) == class_attribute.Auto))
|
||
{
|
||
if (_class_definition.class_parents!=null)
|
||
AddError(new AutoClassMustNotHaveParents(get_location(_class_definition)));
|
||
// добавление членов автоклассов. Не забыть сделать, что от автоклассов нельзя наследовать
|
||
SyntaxTreeBuilder.AddMembersForAutoClass(_class_definition,ref names,ref types);
|
||
for (var i = 0; i < types.Count; i++)
|
||
{
|
||
type_node tn = convert_strong(types[i]);
|
||
if (tn.IsPointer)
|
||
AddError(get_location(types[i]), "AUTO_CLASS_MUST_NOT_HAVE_POINTERS");
|
||
}
|
||
}
|
||
//if (!SemanticRules.OrderIndependedNames)
|
||
|
||
weak_node_test_and_visit(_class_definition.body);
|
||
|
||
}
|
||
context.leave_block();
|
||
return;
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.Record:
|
||
common_type_node ctn;
|
||
if (_record_created)
|
||
{
|
||
_record_created = false;
|
||
ctn = context.converted_type;
|
||
}
|
||
else
|
||
{
|
||
ctn = context.create_record_type(get_location(_class_definition), record_type_name);
|
||
if (record_is_generic)
|
||
{
|
||
context.create_generic_indicator(ctn);
|
||
visit_generic_params(ctn, _class_definition.template_args.idents);
|
||
}
|
||
else
|
||
{
|
||
if (_class_definition.template_args != null && _class_definition.template_args.idents != null)
|
||
{
|
||
AddError(get_location(_class_definition.template_args), "GENERIC_TYPE_NOT_ALLOWED_HERE");
|
||
}
|
||
}
|
||
visit_where_list(_class_definition.where_section);
|
||
}
|
||
|
||
if (context.CurrentScope is SymbolTable.BlockScope)
|
||
{
|
||
AddError(get_location(_class_definition), "RECORD_CANNOT_BE_DECLARED_IN_BLOCK");
|
||
ctn.internal_is_value = true;
|
||
context.leave_record();
|
||
return_value(ctn);
|
||
return;
|
||
}
|
||
|
||
//Добавляем интерфейсы - предки.
|
||
if (_class_definition.class_parents != null)
|
||
{
|
||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 0, new Hashtable());
|
||
//for (int i = 0; i < _class_definition.class_parents.types.Count; i++)
|
||
//{
|
||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||
//}
|
||
}
|
||
CheckWaitedRefTypes(ctn);
|
||
record_type_name = null;
|
||
record_is_generic = false;
|
||
context.converted_type.internal_is_value = true;
|
||
if (_class_definition.body == null &&
|
||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||
{
|
||
if (context.converted_type.ForwardDeclarationOnly)
|
||
{
|
||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||
}
|
||
context.types_predefined.Add(context.converted_type);
|
||
context.converted_type.ForwardDeclarationOnly = true;
|
||
}
|
||
else
|
||
{
|
||
context.converted_type.ForwardDeclarationOnly = false;
|
||
weak_node_test_and_visit(_class_definition.body);
|
||
}
|
||
/*if (_class_definition.body != null)
|
||
hard_node_test_and_visit(_class_definition.body);
|
||
else
|
||
{
|
||
context.converted_type.ForwardDeclarationOnly = true;
|
||
}*/
|
||
/*if (_class_definition.body != null)
|
||
foreach (SyntaxTree.var_def_statement var in (_class_definition.body.class_def_blocks[0].members))
|
||
{
|
||
hard_node_test_and_visit(var);
|
||
}*/
|
||
context.leave_record();
|
||
return_value(ctn);
|
||
return;
|
||
//ssyy owns
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.Interface:
|
||
if (context.converted_type.is_value || !context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", context.converted_type.name);
|
||
}
|
||
if (SemanticRules.GenerateNativeCode)
|
||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||
else
|
||
context.converted_type.SetBaseType(SystemLibrary.SystemLibrary.object_type);
|
||
context.converted_type.IsInterface = true;
|
||
context.converted_type.is_class = true;
|
||
//Добавляем интерфейсы - предки.
|
||
if (_class_definition.class_parents != null)
|
||
{
|
||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 0, new Hashtable());
|
||
//for (int i = 0; i < _class_definition.class_parents.types.Count; i++)
|
||
//{
|
||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||
//}
|
||
}
|
||
|
||
InitInterfaceScope(context.converted_type);
|
||
|
||
//if (_class_definition.body == null)
|
||
//{
|
||
//throw new NotSupportedError(get_location(_class_definition));
|
||
// throw new InterfaceForwardDeclaration(get_location(_class_definition));
|
||
//}
|
||
if (_class_definition.body == null &&
|
||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||
{
|
||
if (context.converted_type.ForwardDeclarationOnly)
|
||
{
|
||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||
}
|
||
context.types_predefined.Add(context.converted_type);
|
||
context.converted_type.ForwardDeclarationOnly = true;
|
||
}
|
||
else
|
||
{
|
||
context.converted_type.ForwardDeclarationOnly = false;
|
||
weak_node_test_and_visit(_class_definition.body);
|
||
}
|
||
//hard_node_test_and_visit(_class_definition.body);
|
||
context.leave_block();
|
||
return;
|
||
//\ssyy owns
|
||
default:
|
||
throw new NotSupportedError(get_location(_class_definition));
|
||
}
|
||
}
|
||
|
||
private void VisitAndAddInterfaces(common_type_node t, List<SyntaxTree.named_type_reference> types, int start, Hashtable used_interfaces)
|
||
{
|
||
for (int i = start; i < types.Count; i++)
|
||
{
|
||
type_node interf = ret.visit(types[i]);
|
||
location loc = get_location(types[i]);
|
||
if (used_interfaces[interf] != null)
|
||
{
|
||
AddError(loc, "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", interf.PrintableName);
|
||
}
|
||
used_interfaces.Add(interf, interf);
|
||
type_table.AddInterface(t, interf, loc);
|
||
}
|
||
}
|
||
|
||
private void InitInterfaceScope(common_type_node ctn)
|
||
{
|
||
List<SymbolTable.Scope> interf_scopes = new List<SymbolTable.Scope>(ctn.ImplementingInterfaces.Count);
|
||
foreach (type_node tnode in ctn.ImplementingInterfaces)
|
||
{
|
||
interf_scopes.Add(tnode.Scope);
|
||
}
|
||
(ctn.Scope as SymbolTable.InterfaceScope).TopInterfaceScopeArray =
|
||
interf_scopes.ToArray();
|
||
}
|
||
|
||
private void visit_function_realizations(SyntaxTree.declarations _decls)
|
||
{
|
||
foreach (SyntaxTree.declaration sd in _decls.defs)
|
||
{
|
||
common_namespace_function_node cnfn = context.get_method_to_realize(sd) as common_namespace_function_node;
|
||
if (cnfn != null)
|
||
{
|
||
context.push_function(cnfn);
|
||
|
||
if ((sd as SyntaxTree.procedure_definition).proc_body != null)
|
||
{
|
||
hard_node_test_and_visit((sd as SyntaxTree.procedure_definition).proc_body);
|
||
add_clip_for_set(context.top_function);
|
||
context.leave_block();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void visit_class_member_realizations(SyntaxTree.class_body _class_body)
|
||
{
|
||
foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks)
|
||
{
|
||
foreach (SyntaxTree.declaration sd in clmem.members)
|
||
{
|
||
common_method_node cmn = context.get_method_to_realize(sd) as common_method_node;
|
||
|
||
if (cmn != null)
|
||
{
|
||
// frninja 20/05/16 - ставим флаг is_yield_helper
|
||
if (sd is SyntaxTree.procedure_definition)
|
||
{
|
||
cmn.is_yield_helper = (sd as SyntaxTree.procedure_definition).proc_header.is_yield_helper;
|
||
}
|
||
// end frninja
|
||
|
||
context.push_function(cmn);
|
||
if (!cmn.IsStatic)
|
||
{
|
||
type_node self_type = cmn.cont_type;
|
||
if (cmn.cont_type.is_generic_type_definition)
|
||
self_type = cmn.cont_type.get_instance(cmn.cont_type.generic_params.ConvertAll<type_node>(o => (type_node)o));// new generic_instance_type_node(self_type, self_type.generic_params.ConvertAll<type_node>(o => (type_node)o), self_type.base_type, self_type.name, self_type.type_access_level, self_type.comprehensive_namespace, self_type.loc);
|
||
local_variable lv = new local_variable(compiler_string_consts.self_word, self_type, cmn, null);
|
||
cmn.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(lv));
|
||
cmn.self_variable = lv;
|
||
}
|
||
if ((sd as SyntaxTree.procedure_definition).proc_body != null)
|
||
{
|
||
hard_node_test_and_visit((sd as SyntaxTree.procedure_definition).proc_body);
|
||
add_clip_for_set(context.top_function);
|
||
context.leave_block();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
context.clear_member_bindings();
|
||
}
|
||
|
||
public override void visit(SyntaxTree.class_body _class_body)
|
||
{
|
||
foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks)
|
||
{
|
||
//hard_node_test_and_visit(clmem);
|
||
weak_node_test_and_visit(clmem);
|
||
}
|
||
if (SemanticRules.OrderIndependedMethodNames)
|
||
{
|
||
if (!context.converted_type.is_value && !context.converted_type.IsInterface)
|
||
{
|
||
generate_inherit_constructors();
|
||
}
|
||
if (!context.converted_type.IsInterface && !context.converted_type.has_default_constructor)
|
||
{
|
||
generate_default_constructor();
|
||
}
|
||
|
||
visit_class_member_realizations(_class_body);
|
||
}
|
||
|
||
if (!SemanticRules.OrderIndependedMethodNames)
|
||
{
|
||
if (!context.converted_type.is_value && !context.converted_type.IsInterface)
|
||
{
|
||
generate_inherit_constructors();
|
||
}
|
||
if (!context.converted_type.IsInterface && !context.converted_type.has_default_constructor)
|
||
{
|
||
generate_default_constructor();
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
private bool disable_order_independ;
|
||
|
||
|
||
//ssyy
|
||
public void generate_default_constructor()
|
||
{
|
||
if (!context.converted_type.is_value)
|
||
{
|
||
if (!generic_convertions.type_has_default_ctor(context.converted_type.base_type, true))
|
||
{
|
||
//У предка нет конструктора по умолчанию,
|
||
//невозможно сгенерировать конструктор по умолчанию.
|
||
AddError(context.converted_type.loc, "NO_DEFAULT_CONSTRUCTOR_INT_TYPE_{0}", context.converted_type.base_type.name);
|
||
return;
|
||
}
|
||
}
|
||
|
||
SyntaxTree.class_members clmem = new SyntaxTree.class_members();
|
||
if (context.converted_type.has_user_defined_constructor)
|
||
{
|
||
clmem.access_mod = new SyntaxTree.access_modifer_node(SyntaxTree.access_modifer.protected_modifer);
|
||
}
|
||
else
|
||
{
|
||
clmem.access_mod = new SyntaxTree.access_modifer_node(SyntaxTree.access_modifer.public_modifer);
|
||
}
|
||
SyntaxTree.procedure_attributes_list pal = new PascalABCCompiler.SyntaxTree.procedure_attributes_list();
|
||
//pal.proc_attributes.Add(new PascalABCCompiler.SyntaxTree.procedure_attribute(SyntaxTree.proc_attribute.attr_overload)); attr_overload - убрал отовсюду! ССМ
|
||
SyntaxTree.constructor constr = new PascalABCCompiler.SyntaxTree.constructor();
|
||
constr.name = new SyntaxTree.method_name(null, null, new PascalABCCompiler.SyntaxTree.ident(compiler_string_consts.default_constructor_name), null);
|
||
constr.proc_attributes = pal;
|
||
SyntaxTree.block bl = new SyntaxTree.block();
|
||
bl.program_code = new SyntaxTree.statement_list();
|
||
bl.program_code.left_logical_bracket = new SyntaxTree.token_info("begin");
|
||
bl.program_code.right_logical_bracket = new SyntaxTree.token_info("end");
|
||
clmem.members.Add(new SyntaxTree.procedure_definition(constr, bl));
|
||
disable_order_independ = true;
|
||
clmem.visit(this);
|
||
disable_order_independ = false;
|
||
}
|
||
//\ssyy
|
||
|
||
public override void visit(SyntaxTree.access_modifer_node _access_modifer_node)
|
||
{
|
||
//ssyy
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
if (_access_modifer_node.access_level == SyntaxTree.access_modifer.none)
|
||
{
|
||
context.set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_access_modifer_node), "ACCESS_MODIFER_IN_INTERFACE");
|
||
}
|
||
return;
|
||
}
|
||
//\ssyy
|
||
switch (_access_modifer_node.access_level)
|
||
{
|
||
case SyntaxTree.access_modifer.private_modifer:
|
||
{
|
||
context.set_field_access_level(SemanticTree.field_access_level.fal_private);
|
||
break;
|
||
}
|
||
case SyntaxTree.access_modifer.protected_modifer:
|
||
{
|
||
context.set_field_access_level(SemanticTree.field_access_level.fal_protected);
|
||
break;
|
||
}
|
||
case SyntaxTree.access_modifer.public_modifer:
|
||
{
|
||
context.set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
break;
|
||
}
|
||
case SyntaxTree.access_modifer.internal_modifer:
|
||
{
|
||
context.set_field_access_level(SemanticTree.field_access_level.fal_internal);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.class_members _class_members)
|
||
{
|
||
foreach (var def in _class_members.members.Where(d => d is const_definition ||
|
||
d is consts_definitions_list ||
|
||
d is variable_definitions ||
|
||
d is var_def_statement))
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(def);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInFieldsInitialization(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
}
|
||
|
||
weak_node_test_and_visit(_class_members.access_mod);
|
||
foreach (SyntaxTree.declaration sd in _class_members.members)
|
||
{
|
||
hard_node_test_and_visit(sd);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.index_property _index_property)
|
||
{
|
||
throw new NotSupportedError(get_location(_index_property));
|
||
}
|
||
|
||
//TODO: Если одного из акцессоров нет?
|
||
public override void visit(SyntaxTree.simple_property _simple_property)
|
||
{
|
||
if (_simple_property.accessors == null)
|
||
AddError(get_location(_simple_property), "PROPERTYACCESSOR_{0}_OR_{1}_EXPECTED", compiler_string_consts.PascalReadAccessorName, compiler_string_consts.PascalWriteAccessorName);
|
||
if (_simple_property.property_type == null)
|
||
AddError(get_location(_simple_property.property_name), "TYPE_NAME_EXPECTED");
|
||
common_property_node pn = context.add_property(_simple_property.property_name.name,
|
||
get_location(_simple_property.property_name));
|
||
assign_doc_info(pn, _simple_property);
|
||
//pn.polymorphic_state=SemanticTree.polymorphic_state.ps_common;
|
||
//pn.loc=get_location(_simple_property.property_name);
|
||
if (_simple_property.attr == SyntaxTree.definition_attribute.Static)
|
||
pn.polymorphic_state = SemanticTree.polymorphic_state.ps_static;
|
||
parameter_list pal_big = new parameter_list();
|
||
//TODO: Спросить у Саши как получить тип параметра - var,const и т.д.
|
||
if (_simple_property.parameter_list != null)
|
||
{
|
||
foreach (SyntaxTree.property_parameter pp in _simple_property.parameter_list.parameters)
|
||
{
|
||
parameter_list pal_small = new parameter_list();
|
||
foreach (SyntaxTree.ident id in pp.names.idents)
|
||
{
|
||
common_parameter cp = new common_parameter(id.name, SemanticTree.parameter_type.value, null,
|
||
concrete_parameter_type.cpt_none, get_location(id));
|
||
pal_small.AddElement(cp);
|
||
}
|
||
type_node tn = convert_strong(pp.type);
|
||
foreach (parameter pr in pal_small)
|
||
{
|
||
pr.type = tn;
|
||
}
|
||
pal_big.AddRange(pal_small);
|
||
}
|
||
}
|
||
pn.parameters.AddRange(pal_big);
|
||
pn.internal_property_type = convert_strong(_simple_property.property_type);
|
||
|
||
if (_simple_property.accessors != null)
|
||
{
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors);
|
||
|
||
SymbolInfo si = null;
|
||
//definition_node dn = null;
|
||
|
||
if (_simple_property.accessors.read_accessor != null)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.read_accessor);
|
||
if (_simple_property.accessors.read_accessor.accessor_name == null)
|
||
{
|
||
if (!context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_simple_property.accessors.read_accessor), "ACCESSOR_NAME_EXPECTED");
|
||
}
|
||
pn.internal_get_function = GenerateGetSetMethodForInterfaceProperty(pn, get_location(_simple_property.accessors.read_accessor), true);
|
||
}
|
||
else
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.read_accessor.accessor_name);
|
||
si = context.converted_type.find_in_type(_simple_property.accessors.read_accessor.accessor_name.name, context.CurrentScope);
|
||
|
||
location loc1 = get_location(_simple_property.accessors.read_accessor.accessor_name);
|
||
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(_simple_property.accessors.read_accessor.accessor_name.name, loc1));
|
||
}
|
||
|
||
//dn = check_name_node_type(_simple_property.accessors.read_accessor.accessor_name.name,
|
||
// si, loc1, general_node_type.function_node, general_node_type.variable_node);
|
||
|
||
function_node read_accessor = si.sym_info as function_node;
|
||
|
||
if (read_accessor != null)
|
||
{
|
||
bool good_func = true;
|
||
bool one_func = si.Next == null;
|
||
while (si != null)
|
||
{
|
||
good_func = true;
|
||
if (read_accessor.parameters.Count != pn.parameters.Count)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(new PropertyAndReadAccessorParamsCountConvergence(read_accessor, pn, loc1));
|
||
}
|
||
}
|
||
//TODO: Сверять типы параметров - var, const и т.д.
|
||
else
|
||
{
|
||
for (int i1 = 0; good_func && i1 < read_accessor.parameters.Count; i1++)
|
||
{
|
||
if (read_accessor.parameters[i1].parameter_type != pn.parameters[i1].parameter_type ||
|
||
read_accessor.parameters[i1].type != pn.parameters[i1].type)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc1, "PROPERTY_{0}_AND_READ_ACCESSOR_{1}_PARAMS_TYPE_CONVERGENCE", pn.name, read_accessor.name);
|
||
}
|
||
}
|
||
}
|
||
if (read_accessor.return_value_type == null)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc1, "PROPERTY_READ_ACCESSOR_CAN_NOT_BE_PROCEDURE");
|
||
}
|
||
}
|
||
if (read_accessor.return_value_type != pn.property_type)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc1, "PROPERTY_{0}_AND_READ_ACCESSOR_{1}_RETURN_VALUE_TYPE_CONVERGENCE", pn.name, read_accessor.name);
|
||
}
|
||
}
|
||
if (read_accessor is common_method_node && (read_accessor as common_method_node).is_constructor)
|
||
{
|
||
AddError(loc1, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY");
|
||
}
|
||
}
|
||
if (good_func)
|
||
{
|
||
break;
|
||
}
|
||
si = si.Next;
|
||
if (si != null)
|
||
{
|
||
read_accessor = si.sym_info as function_node;
|
||
}
|
||
}
|
||
if (!good_func)
|
||
{
|
||
AddError(loc1, "NO_OVERLOAD_FUNCTION_{0}_USEFUL_FOR_ACCESSOR", read_accessor.name);
|
||
}
|
||
read_accessor = GenerateGetMethod(pn,read_accessor as common_method_node,pn.loc);
|
||
|
||
}
|
||
else
|
||
{
|
||
class_field cfield = si.sym_info as class_field;
|
||
if (cfield == null)
|
||
{
|
||
AddError(loc1, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY");
|
||
}
|
||
if (_simple_property.parameter_list != null)
|
||
{
|
||
AddError(loc1, "INDEX_PROPERTY_ACCESSOR_CAN_NOT_BE_VARIABLE");
|
||
}
|
||
if (cfield.type != pn.internal_property_type)
|
||
{
|
||
AddError(loc1, "PROPERTY_TYPE_MISMATCH_ACCESSOR_FIELD_TYPE");
|
||
}
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", cfield.name);
|
||
if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", cfield.name);
|
||
read_accessor = GenerateGetMethodForField(pn, compiler_string_consts.GetGetAccessorName(pn.name), cfield, loc1);
|
||
}
|
||
|
||
//Вот здесь уже можем добавить акцессор для чтения.
|
||
pn.internal_get_function = read_accessor;
|
||
}
|
||
if (pn.internal_get_function != null && pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && pn.internal_get_function.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", pn.internal_get_function.name);
|
||
if (pn.internal_get_function != null && pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && pn.internal_get_function.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", pn.internal_get_function.name);
|
||
}
|
||
|
||
if (_simple_property.accessors.write_accessor != null)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.write_accessor);
|
||
if (_simple_property.accessors.write_accessor.accessor_name == null)
|
||
{
|
||
if (!context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_simple_property.accessors.write_accessor), "ACCESSOR_NAME_EXPECTED");
|
||
}
|
||
pn.internal_set_function = GenerateGetSetMethodForInterfaceProperty(pn, get_location(_simple_property.accessors.write_accessor), false);
|
||
}
|
||
else
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.write_accessor.accessor_name);
|
||
si = context.converted_type.find_in_type(_simple_property.accessors.write_accessor.accessor_name.name, context.CurrentScope);
|
||
|
||
location loc2 = get_location(_simple_property.accessors.write_accessor.accessor_name);
|
||
|
||
if (si == null)
|
||
{
|
||
AddError( new UndefinedNameReference(_simple_property.accessors.write_accessor.accessor_name.name, loc2));
|
||
}
|
||
|
||
//dn = check_name_node_type(_simple_property.accessors.write_accessor.accessor_name.name,
|
||
// si, loc2, general_node_type.function_node, general_node_type.variable_node);
|
||
|
||
function_node write_accessor = si.sym_info as function_node;
|
||
|
||
if (write_accessor != null)
|
||
{
|
||
bool good_func = true;
|
||
bool one_func = si.Next == null;
|
||
while (si != null)
|
||
{
|
||
good_func = true;
|
||
if (write_accessor.parameters.Count != pn.parameters.Count + 1)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError( new PropertyAndWriteAccessorParamsCountConvergence(write_accessor, pn, loc2));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//TODO: Сверять типы параметров - var, const и т.д.
|
||
for (int i2 = 0; good_func && i2 < pn.parameters.Count; i2++)
|
||
{
|
||
if (write_accessor.parameters[i2].parameter_type != pn.parameters[i2].parameter_type ||
|
||
write_accessor.parameters[i2].type != pn.parameters[i2].type)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc2, "PROPERTY_{0}_AND_WRITE_ACCESSOR_{1}_PARAMS_TYPE_CONVERGENCE", pn.name ,write_accessor.name);
|
||
}
|
||
}
|
||
}
|
||
if (write_accessor.parameters[write_accessor.parameters.Count - 1].type != pn.property_type ||
|
||
write_accessor.parameters[write_accessor.parameters.Count - 1].parameter_type != PascalABCCompiler.SemanticTree.parameter_type.value)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc2, "PROPERTY_{0}_AND_WRITE_ACCESSOR_LAST_PARAMETER_TYPE_CONVERGENCE", pn.name);
|
||
}
|
||
}
|
||
if (write_accessor.return_value_type != null)
|
||
{
|
||
good_func = false;
|
||
if (one_func)
|
||
{
|
||
AddError(loc2, "PROPERTY_WRITE_ACCESSOR_CAN_NOT_BE_FUNCTION");
|
||
}
|
||
}
|
||
}
|
||
if (good_func)
|
||
{
|
||
break;
|
||
}
|
||
si = si.Next;
|
||
if (si != null)
|
||
{
|
||
write_accessor = si.sym_info as function_node;
|
||
}
|
||
}
|
||
if (!good_func)
|
||
{
|
||
AddError(loc2, "NO_OVERLOAD_FUNCTION_{0}_USEFUL_FOR_ACCESSOR", write_accessor.name);
|
||
}
|
||
if (write_accessor is common_method_node && (write_accessor as common_method_node).is_constructor)
|
||
{
|
||
AddError(loc2, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY");
|
||
}
|
||
write_accessor = GenerateSetMethod(pn, write_accessor as common_method_node, pn.loc);
|
||
}
|
||
else
|
||
{
|
||
class_field cfield = si.sym_info as class_field;
|
||
if (cfield == null)
|
||
{
|
||
AddError(loc2, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY");
|
||
}
|
||
if (_simple_property.parameter_list != null)
|
||
{
|
||
AddError(loc2, "INDEX_PROPERTY_ACCESSOR_CAN_NOT_BE_VARIABLE");
|
||
}
|
||
if (cfield.type != pn.internal_property_type)
|
||
{
|
||
AddError(loc2, "PROPERTY_TYPE_MISMATCH_ACCESSOR_FIELD_TYPE");
|
||
}
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", cfield.name);
|
||
if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", cfield.name);
|
||
write_accessor = GenerateSetMethodForField(pn, compiler_string_consts.GetSetAccessorName(pn.name), cfield, loc2);
|
||
}
|
||
//Вот здесь уже можем добавить акцессор для чтения.
|
||
pn.internal_set_function = write_accessor;
|
||
}
|
||
if (pn.internal_set_function != null && pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && pn.internal_set_function.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", pn.internal_set_function.name);
|
||
if (pn.internal_set_function != null && pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && pn.internal_set_function.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", pn.internal_set_function.name);
|
||
}
|
||
}
|
||
make_attributes_for_declaration(_simple_property,pn);
|
||
//TODO: Можно сделать множество свойств по умолчанию.
|
||
if (_simple_property.array_default != null)
|
||
{
|
||
if (pn.parameters.Count == 0)
|
||
{
|
||
AddError(pn.loc, "DEFAULT_PROPERTY_MUST_BE_INDEXED");
|
||
}
|
||
if (context.converted_type.default_property_node != null)
|
||
{
|
||
AddError(pn.loc, "DUPLICATE_DEFAULT_PROPERTY_IN_CLASS");
|
||
}
|
||
context.converted_type.default_property = pn;
|
||
}
|
||
}
|
||
|
||
private function_node GenerateGetMethod(common_property_node cpn, common_method_node accessor, location loc)
|
||
{
|
||
common_method_node cmn = new common_method_node(
|
||
"get_"+cpn.name, loc, cpn.common_comprehensive_type,
|
||
cpn.polymorphic_state, cpn.field_access_level, null);
|
||
cpn.common_comprehensive_type.methods.AddElement(cmn);
|
||
cmn.return_value_type = cpn.property_type;
|
||
cmn.is_overload = true;
|
||
foreach (common_parameter cp in accessor.parameters)
|
||
{
|
||
common_parameter new_cp = new common_parameter(cp.name, cp.type, cp.parameter_type, cp.common_function, cp.concrete_parameter_type, cp.default_value, loc);
|
||
cmn.parameters.AddElement(new_cp);
|
||
}
|
||
expression_node meth_call;
|
||
if (cpn.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
meth_call = new common_method_call(accessor, new this_node(cpn.common_comprehensive_type, loc), loc);
|
||
foreach (common_parameter cp in cmn.parameters)
|
||
{
|
||
(meth_call as common_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
meth_call = new common_static_method_call(accessor, loc);
|
||
foreach (common_parameter cp in cmn.parameters)
|
||
{
|
||
(meth_call as common_static_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc));
|
||
}
|
||
}
|
||
cmn.function_code = new return_node(meth_call, loc);
|
||
cpn.common_comprehensive_type.scope.AddSymbol("get_" + cpn.name, new SymbolInfo(cmn));
|
||
return cmn;
|
||
}
|
||
|
||
private function_node GenerateSetMethod(common_property_node cpn, common_method_node accessor, location loc)
|
||
{
|
||
common_method_node cmn = new common_method_node(
|
||
"set_" + cpn.name, loc, cpn.common_comprehensive_type,
|
||
cpn.polymorphic_state, cpn.field_access_level, null);
|
||
cpn.common_comprehensive_type.methods.AddElement(cmn);
|
||
//cmn.return_value_type = cpn.property_type;
|
||
cmn.is_overload = true;
|
||
foreach (common_parameter cp in accessor.parameters)
|
||
{
|
||
common_parameter new_cp = new common_parameter(cp.name, cp.type, cp.parameter_type, cp.common_function, cp.concrete_parameter_type, cp.default_value, loc);
|
||
cmn.parameters.AddElement(new_cp);
|
||
}
|
||
expression_node meth_call;
|
||
if (cpn.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
meth_call = new common_method_call(accessor, new this_node(cpn.common_comprehensive_type, loc), loc);
|
||
foreach (common_parameter cp in cmn.parameters)
|
||
{
|
||
(meth_call as common_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
meth_call = new common_static_method_call(accessor, loc);
|
||
foreach (common_parameter cp in cmn.parameters)
|
||
{
|
||
(meth_call as common_static_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc));
|
||
}
|
||
}
|
||
cmn.function_code = meth_call;
|
||
cpn.common_comprehensive_type.scope.AddSymbol("set_" + cpn.name, new SymbolInfo(cmn));
|
||
return cmn;
|
||
}
|
||
|
||
internal function_node GenerateSetMethodForField(common_property_node cpn, string AcessorName, class_field cf, location loc)
|
||
{
|
||
SymbolInfo exist_si = context.find_only_in_namespace(AcessorName);
|
||
if (exist_si != null && exist_si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName);
|
||
}
|
||
while (exist_si != null)
|
||
{
|
||
function_node ff = (function_node)(exist_si.sym_info);
|
||
if (ff.parameters.Count == 1 && ff.parameters[0].type == cf.type)
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName);
|
||
}
|
||
exist_si = exist_si.Next;
|
||
}
|
||
common_method_node cmn = new common_method_node(
|
||
AcessorName, loc, cf.cont_type,
|
||
cf.polymorphic_state, context.get_field_access_level(), null);
|
||
cpn.common_comprehensive_type.methods.AddElement(cmn);
|
||
common_parameter cp = new common_parameter(
|
||
compiler_string_consts.value, cf.type, SemanticTree.parameter_type.value,
|
||
cmn, concrete_parameter_type.cpt_none, null, loc);
|
||
cmn.parameters.AddElement(cp);
|
||
cmn.is_overload = true;
|
||
common_parameter_reference cpr = new common_parameter_reference(cp, 0, loc);
|
||
expression_node var_ref;
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
var_ref = new class_field_reference(cf, new this_node(cf.type, loc), loc);
|
||
}
|
||
else
|
||
{
|
||
var_ref = new static_class_field_reference(cf, loc);
|
||
}
|
||
cmn.function_code = find_operator(compiler_string_consts.assign_name, var_ref, cpr, loc);
|
||
cf.cont_type.scope.AddSymbol(AcessorName, new SymbolInfo(cmn));
|
||
return cmn;
|
||
}
|
||
|
||
internal expression_node make_assign_operator(addressed_expression left, expression_node right, location loc)
|
||
{
|
||
return find_operator(compiler_string_consts.assign_name, left, right, loc);
|
||
}
|
||
|
||
internal function_node GenerateGetMethodForField(common_property_node cpn, string AcessorName, class_field cf, location loc)
|
||
{
|
||
SymbolInfo exist_si = context.find_only_in_namespace(AcessorName);
|
||
if (exist_si != null && exist_si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName);
|
||
}
|
||
while (exist_si != null)
|
||
{
|
||
if (((function_node)(exist_si.sym_info)).parameters.Count == 0)
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName);
|
||
}
|
||
exist_si = exist_si.Next;
|
||
}
|
||
common_method_node cmn = new common_method_node(
|
||
AcessorName, loc, cf.cont_type,
|
||
cf.polymorphic_state, context.get_field_access_level(), null);
|
||
cpn.common_comprehensive_type.methods.AddElement(cmn);
|
||
cmn.return_value_type = cf.type;
|
||
cmn.is_overload = true;
|
||
expression_node var_ref;
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
var_ref = new class_field_reference(cf, new this_node(cf.type, loc), loc);
|
||
}
|
||
else
|
||
{
|
||
var_ref = new static_class_field_reference(cf, loc);
|
||
}
|
||
cmn.function_code = new return_node(var_ref, loc);
|
||
cf.cont_type.scope.AddSymbol(AcessorName, new SymbolInfo(cmn));
|
||
return cmn;
|
||
}
|
||
|
||
private function_node GenerateGetSetMethodForInterfaceProperty(common_property_node pn, location loc, bool get_meth)
|
||
{
|
||
|
||
string AcessorName = (get_meth) ?
|
||
compiler_string_consts.GetGetAccessorName(pn.name) :
|
||
compiler_string_consts.GetSetAccessorName(pn.name);
|
||
SymbolInfo exist_si = context.find_only_in_namespace(AcessorName);
|
||
if (exist_si != null && exist_si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName);
|
||
}
|
||
common_method_node cmn = new common_method_node(
|
||
AcessorName, loc, pn.common_comprehensive_type,
|
||
pn.polymorphic_state, context.get_field_access_level(), null);
|
||
cmn.is_overload = true;
|
||
foreach (common_parameter cp in pn.parameters)
|
||
{
|
||
common_parameter accp = new common_parameter(cp.name, cp.parameter_type, cmn, cp.concrete_parameter_type, cp.loc);
|
||
accp.type = cp.type;
|
||
accp.inital_value = cp.inital_value;
|
||
accp.intrenal_is_params = cp.intrenal_is_params;
|
||
accp.is_ret_value = cp.is_ret_value;
|
||
cmn.parameters.AddElement(accp);
|
||
}
|
||
if (get_meth)
|
||
{
|
||
cmn.return_value_type = pn.internal_property_type;
|
||
}
|
||
else
|
||
{
|
||
//foreach (common_parameter par in cmn.parameters)
|
||
//{
|
||
// if (par.name ==
|
||
//}
|
||
common_parameter accp = new common_parameter(compiler_string_consts.value_in_accessor_name,
|
||
SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null);
|
||
accp.type = pn.internal_property_type;
|
||
cmn.parameters.AddElement(accp);
|
||
}
|
||
while (exist_si != null)
|
||
{
|
||
if (convertion_data_and_alghoritms.function_eq_params(cmn, (function_node)(exist_si.sym_info)))
|
||
{
|
||
AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", cmn.name);
|
||
}
|
||
exist_si = exist_si.Next;
|
||
}
|
||
pn.common_comprehensive_type.methods.AddElement(cmn);
|
||
pn.common_comprehensive_type.scope.AddSymbol(AcessorName, new SymbolInfo(cmn));
|
||
return cmn;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.property_accessors _property_accessors)
|
||
{
|
||
throw new NotSupportedError(get_location(_property_accessors));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.read_accessor_name _read_accessor_name)
|
||
{
|
||
throw new NotSupportedError(get_location(_read_accessor_name));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.write_accessor_name _write_accessor_name)
|
||
{
|
||
throw new NotSupportedError(get_location(_write_accessor_name));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.array_const _array_const)
|
||
{
|
||
if (_array_const.elements != null)
|
||
{
|
||
List<constant_node> elements = new List<constant_node>();
|
||
List<expression_node> exprs = new List<expression_node>();
|
||
foreach (SyntaxTree.expression expr in _array_const.elements.expressions)
|
||
{
|
||
if (is_typed_const_def)
|
||
elements.Add(convert_strong_to_constant_node(expr));
|
||
else
|
||
exprs.Add(convert_strong(expr));
|
||
}
|
||
if (is_typed_const_def)
|
||
{
|
||
array_const arrc = new array_const(elements, get_location(_array_const));
|
||
arrc.SetType(new ArrayConstType(elements[0].type, elements.Count, arrc.location));
|
||
return_value(arrc);
|
||
}
|
||
else
|
||
{
|
||
array_initializer arrc = new array_initializer(exprs, get_location(_array_const));
|
||
arrc.type = new ArrayConstType(exprs[0].type, exprs.Count, arrc.location);
|
||
return_value(arrc);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//это пустой инициализатор записи
|
||
record_constant rc = new record_constant(new List<PascalABCCompiler.SyntaxTree.record_const_definition>(), get_location(_array_const));
|
||
rc.SetType(new RecordConstType(get_location(_array_const)));
|
||
return_value(rc);
|
||
}
|
||
}
|
||
|
||
private expressions_list get_set_initializer(expression_node cnfc)
|
||
{
|
||
return set_intls[cnfc];
|
||
}
|
||
|
||
private void add_set_initializer(expression_node cnfc, expressions_list exprs)
|
||
{
|
||
set_intls[cnfc] = exprs;
|
||
}
|
||
|
||
private expression_node convert_diap_for_set(SyntaxTree.diapason_expr _diapason_expr, out type_node elem_type)
|
||
{
|
||
expression_node left = convert_strong(_diapason_expr.left);
|
||
if (left is typed_expression) left = convert_typed_expression_to_function_call(left as typed_expression);
|
||
expression_node right = convert_strong(_diapason_expr.right);
|
||
if (right is typed_expression) right = convert_typed_expression_to_function_call(right as typed_expression);
|
||
internal_interface ii = left.type.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(new OrdinalTypeExpected(left.location));
|
||
}
|
||
internal_interface iir = right.type.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
if (iir == null)
|
||
{
|
||
AddError(new OrdinalTypeExpected(right.location));
|
||
}
|
||
type_node_list tnl = new type_node_list();
|
||
tnl.AddElement(left.type);
|
||
tnl.AddElement(right.type);
|
||
elem_type = convertion_data_and_alghoritms.select_base_type(tnl);
|
||
expression_node l = convertion_data_and_alghoritms.explicit_convert_type(left, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type);
|
||
expression_node r = convertion_data_and_alghoritms.explicit_convert_type(right, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type);
|
||
if (PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_node cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as common_namespace_function_node;
|
||
if (elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.char_type || elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type || elem_type.IsEnum)
|
||
cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as common_namespace_function_node;
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(cnfn, get_location(_diapason_expr));
|
||
if (elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !elem_type.IsEnum)
|
||
{
|
||
cnfc.parameters.AddElement(l);
|
||
cnfc.parameters.AddElement(r);
|
||
}
|
||
else
|
||
{
|
||
cnfc.parameters.AddElement(left);
|
||
cnfc.parameters.AddElement(right);
|
||
}
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_function_node cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as compiled_function_node;
|
||
if (elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.char_type || elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type || elem_type.IsEnum)
|
||
cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as compiled_function_node;
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(cnfn, get_location(_diapason_expr));
|
||
if (elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !elem_type.IsEnum)
|
||
{
|
||
cnfc.parameters.AddElement(l);
|
||
cnfc.parameters.AddElement(r);
|
||
}
|
||
else
|
||
{
|
||
cnfc.parameters.AddElement(left);
|
||
cnfc.parameters.AddElement(right);
|
||
}
|
||
return cnfc;
|
||
}
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.pascal_set_constant _pascal_set_constant)
|
||
{
|
||
//throw new NotSupportedError(get_location(_pascal_set_constant));
|
||
if (SystemLibrary.SystemLibInitializer.TypedSetType == null || SystemLibrary.SystemLibInitializer.CreateSetProcedure == null)
|
||
AddError(new NotSupportedError(get_location(_pascal_set_constant)));
|
||
expressions_list consts = new expressions_list();
|
||
type_node el_type = null;
|
||
type_node_list types = new type_node_list();
|
||
if (_pascal_set_constant.values != null && _pascal_set_constant.values != null)
|
||
foreach (SyntaxTree.expression e in _pascal_set_constant.values.expressions)
|
||
{
|
||
if (e is SyntaxTree.nil_const)
|
||
ErrorsList.Add(new SimpleSemanticError(get_location(e), "NIL_IN_SET_CONSTRUCTOR_NOT_ALLOWED"));
|
||
else
|
||
if (e is SyntaxTree.diapason_expr)
|
||
{
|
||
consts.AddElement(convert_diap_for_set((e as SyntaxTree.diapason_expr), out el_type));
|
||
if (el_type.IsPointer)
|
||
ErrorsList.Add(new SimpleSemanticError(get_location(e), "POINTERS_IN_SETS_NOT_ALLOWED"));
|
||
types.AddElement(el_type);
|
||
}
|
||
else
|
||
{
|
||
expression_node en = convert_strong(e);
|
||
if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression);
|
||
if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
en.type = SystemLibrary.SystemLibrary.string_type;
|
||
consts.AddElement(en);
|
||
types.AddElement(en.type);
|
||
}
|
||
}
|
||
expressions_list consts_copy = new expressions_list();
|
||
consts_copy.AddRange(consts);
|
||
type_node ctn = null;
|
||
if (consts.Count > 0)
|
||
{
|
||
el_type = convertion_data_and_alghoritms.select_base_type(types);
|
||
ctn = context.create_set_type(el_type, get_location(_pascal_set_constant));
|
||
|
||
}
|
||
else ctn = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
function_node fn = convertion_data_and_alghoritms.select_function(consts, SystemLibrary.SystemLibInitializer.CreateSetProcedure.SymbolInfo, (SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info is common_namespace_function_node)?(SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node).loc:null);
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, get_location(_pascal_set_constant));
|
||
add_set_initializer(cnfc, consts_copy);
|
||
cnfc.ret_type = ctn;
|
||
for (int i = 0; i < consts.Count; i++)
|
||
cnfc.parameters.AddElement(consts[i]);
|
||
return_value(cnfc);
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, get_location(_pascal_set_constant));
|
||
add_set_initializer(cnfc, consts_copy);
|
||
cnfc.ret_type = ctn;
|
||
for (int i = 0; i < consts.Count; i++)
|
||
cnfc.parameters.AddElement(consts[i]);
|
||
return_value(cnfc);
|
||
}
|
||
//return_value(new common_namespace_function_call_as_constant(cnfc,cnfc.location));
|
||
}
|
||
|
||
internal SymbolInfo get_function_instances(SymbolInfo si, List<SyntaxTree.type_definition> type_pars, string name, location loc, bool stop_on_error)
|
||
{
|
||
List<type_node> tparams = visit_type_list(type_pars);
|
||
for (int i = 0; i < tparams.Count; i++)
|
||
{
|
||
CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_generic_useful(tparams[i], loc);
|
||
if (err != null)
|
||
{
|
||
AddError( err);
|
||
}
|
||
}
|
||
SymbolInfo start = null;
|
||
SymbolInfo tek = null;
|
||
while (si != null)
|
||
{
|
||
function_node fn = si.sym_info as function_node;
|
||
if (fn != null)
|
||
{
|
||
function_node inst = fn.get_instance(tparams, stop_on_error, loc);
|
||
if (inst != null)
|
||
{
|
||
SymbolInfo s = new SymbolInfo(inst);
|
||
if (start == null)
|
||
{
|
||
start = tek = s;
|
||
}
|
||
else
|
||
{
|
||
tek.Next = s;
|
||
tek = s;
|
||
}
|
||
}
|
||
}
|
||
si = si.Next;
|
||
}
|
||
if (start == null)
|
||
{
|
||
AddError(loc, "NO_FUNCTIONS_{0}_CAN_BE_USED_WITH_THIS_SPECIFICATION", name);
|
||
}
|
||
return start;
|
||
}
|
||
|
||
private SymbolInfo get_generic_functions(SymbolInfo funcs, bool stop_on_none, location loc)
|
||
{
|
||
SymbolInfo start = null;
|
||
SymbolInfo cur = null;
|
||
while (funcs != null)
|
||
{
|
||
function_node f = funcs.sym_info as function_node;
|
||
if (f.is_generic_function)
|
||
{
|
||
//Проверяем на совпадение
|
||
bool found = false;
|
||
SymbolInfo fsi = start;
|
||
while (fsi != null && fsi != funcs)
|
||
{
|
||
if (convertion_data_and_alghoritms.function_eq_params(fsi.sym_info as function_node, f))
|
||
{
|
||
found = true;
|
||
break;
|
||
}
|
||
fsi = fsi.Next;
|
||
}
|
||
if (!found)
|
||
{
|
||
if (start == null)
|
||
{
|
||
start = funcs;
|
||
}
|
||
else
|
||
{
|
||
cur.Next = funcs;
|
||
}
|
||
cur = funcs;
|
||
}
|
||
}
|
||
funcs = funcs.Next;
|
||
}
|
||
if (start == null)
|
||
{
|
||
if (stop_on_none)
|
||
{
|
||
AddError(loc, "TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS");
|
||
}
|
||
return null;
|
||
}
|
||
cur.Next = null;
|
||
return start;
|
||
}
|
||
|
||
internal void visit_method_call(SyntaxTree.method_call _method_call)
|
||
{
|
||
// frninja 01/03/16 - for iterator capturing (yield)
|
||
if (_method_call.dereferencing_value is yield_unknown_ident)
|
||
{
|
||
var nodeToVisit = new method_call(ProcessUnknownIdent(_method_call.dereferencing_value as yield_unknown_ident), _method_call.parameters);
|
||
visit(nodeToVisit);
|
||
return;
|
||
}
|
||
// end frninja
|
||
|
||
//lroman
|
||
if (_method_call.dereferencing_value is closure_substituting_node)
|
||
{
|
||
var nodeToVisit =
|
||
new method_call(((closure_substituting_node)_method_call.dereferencing_value).substitution,
|
||
_method_call.parameters);
|
||
visit(nodeToVisit);
|
||
return;
|
||
}
|
||
|
||
bool proc_wait = procedure_wait;
|
||
bool lambdas_are_in_parameters = false; //lroman//
|
||
|
||
var syntax_nodes_parameters = _method_call.parameters == null
|
||
? new List<expression>()
|
||
: _method_call.parameters.expressions;
|
||
if (procedure_wait)
|
||
{
|
||
procedure_wait = false;
|
||
}
|
||
//throw new ArgumentNullException("test");
|
||
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
|
||
expression_node expr_node = null;
|
||
expressions_list exprs = new expressions_list();
|
||
|
||
SyntaxTree.ident id = null;
|
||
|
||
SymbolInfo si = null;
|
||
|
||
type_node to_type = null;
|
||
|
||
SyntaxTree.addressed_value deref_value = _method_call.dereferencing_value;
|
||
int templ_args_count = 0;
|
||
//bool needs_generic_type_search = false;
|
||
SyntaxTree.ident_with_templateparams iwt = deref_value as SyntaxTree.ident_with_templateparams;
|
||
if (iwt != null)
|
||
{
|
||
deref_value = iwt.name;
|
||
templ_args_count = iwt.template_params.params_list.Count;
|
||
//needs_generic_type_search = _method_call.parameters.expressions.Count == 1;
|
||
}
|
||
|
||
SyntaxTree.inherited_ident inh_id = deref_value as SyntaxTree.inherited_ident;
|
||
if (inh_id != null)
|
||
{
|
||
inherited_ident_processing = true;
|
||
si = find_in_base(inh_id);
|
||
if (si != null)
|
||
if (si.sym_info is common_method_node)
|
||
{
|
||
if ((si.sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
}
|
||
else
|
||
if (si.sym_info is compiled_function_node)
|
||
{
|
||
if ((si.sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
}
|
||
id = inh_id;
|
||
}
|
||
else
|
||
{
|
||
id = deref_value as SyntaxTree.ident;
|
||
if (id != null)
|
||
{
|
||
if (templ_args_count != 0)
|
||
{
|
||
//Ищем generics
|
||
si = context.find(id.name + compiler_string_consts.generic_params_infix + templ_args_count.ToString());
|
||
if (si != null)
|
||
{
|
||
si = new SymbolInfo(get_generic_instance(si, iwt.template_params.params_list));
|
||
iwt = null;
|
||
}
|
||
}
|
||
if (si == null)
|
||
{
|
||
SyntaxTree.operator_name_ident oni = id as SyntaxTree.operator_name_ident;
|
||
if (oni != null)
|
||
{
|
||
si = context.find(name_reflector.get_name(oni.operator_type));
|
||
}
|
||
else
|
||
{
|
||
si = context.find(id.name);
|
||
if (templ_args_count != 0)
|
||
{
|
||
SymbolInfo conv = ConvertTypeToInstance(si, iwt.template_params.params_list, get_location(id));
|
||
if (conv != null)
|
||
{
|
||
si = conv;
|
||
iwt = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.dot_node _dot_node = deref_value as SyntaxTree.dot_node;
|
||
if (_dot_node != null)
|
||
{
|
||
bool skip_first_parameter = false; //lroman//
|
||
bool has_extension_overload = false;
|
||
semantic_node sn = convert_semantic_strong(_dot_node.left);
|
||
|
||
//SyntaxTree.ident id_right = ConvertOperatorNameToIdent(_dot_node.right as SyntaxTree.ident);
|
||
SyntaxTree.ident id_right = _dot_node.right as SyntaxTree.ident;
|
||
switch (sn.general_node_type)
|
||
{
|
||
case general_node_type.expression:
|
||
{
|
||
expression_node exp = (expression_node)sn;
|
||
if (exp is typed_expression)
|
||
try_convert_typed_expression_to_function_call(ref exp);
|
||
SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident;
|
||
if (oni_right != null)
|
||
{
|
||
si = exp.type.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope);
|
||
}
|
||
else
|
||
{
|
||
si = exp.type.find_in_type(id_right.name, context.CurrentScope);
|
||
if (si != null && si.sym_info != null && si.sym_info.semantic_node_type == semantic_node_type.wrap_def)
|
||
BasePCUReader.RestoreSymbols(si, id_right.name);
|
||
}
|
||
|
||
|
||
//definition_node ddn=check_name_node_type(id_right.name,si,get_location(id_right),
|
||
// general_node_type.function_node,general_node_type.variable_node);
|
||
|
||
location subloc = get_location(id_right);
|
||
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id_right.name, subloc));
|
||
}
|
||
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
if (si.sym_info.general_node_type == general_node_type.type_node)
|
||
{
|
||
to_type = ((type_node)(si.sym_info));
|
||
}
|
||
else
|
||
{
|
||
dot_node_as_expression_dot_ident(exp, id_right, motivation.expression_evaluation, _dot_node.left);
|
||
exp = ret.get_expression();
|
||
internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(subloc, "EXPECTED_DELEGATE");
|
||
}
|
||
delegate_internal_interface dii = ii as delegate_internal_interface;
|
||
si = new SymbolInfo(dii.invoke_method);
|
||
}
|
||
}
|
||
|
||
if (to_type != null)
|
||
{
|
||
if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1))
|
||
{
|
||
AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED");
|
||
}
|
||
}
|
||
SymbolInfo tmp_si = si;
|
||
while (si != null)
|
||
{
|
||
if (si.sym_info is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node;
|
||
if (cnfn.ConnectedToType != null && !cnfn.IsOperator)
|
||
{
|
||
exprs.AddElementFirst(exp);
|
||
skip_first_parameter = true;
|
||
break;
|
||
}
|
||
}
|
||
if (si.sym_info is compiled_function_node)
|
||
{
|
||
compiled_function_node cfn = si.sym_info as compiled_function_node;
|
||
if (cfn.ConnectedToType != null)
|
||
{
|
||
exprs.AddElementFirst(exp);
|
||
skip_first_parameter = true;
|
||
if (cfn.is_generic_function)
|
||
{
|
||
//generic_convertions.DeduceFunction(cfn, exprs);
|
||
//si.sym_info = cfn.get_instance(new List<type_node>(new type_node[] { exp.type }), true, get_location(_method_call));
|
||
}
|
||
break;
|
||
}
|
||
|
||
}
|
||
si = si.Next;
|
||
}
|
||
|
||
si = tmp_si;
|
||
if (skip_first_parameter)
|
||
{
|
||
SymbolInfo new_si = null;
|
||
bool has_obj_methods = false;
|
||
List<SymbolInfo> si_list = new List<SymbolInfo>();
|
||
while (si != null)
|
||
{
|
||
if (si.sym_info is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node;
|
||
if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cnfn.ConnectedToType != null)
|
||
si_list.Add(si);
|
||
if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cnfn.ConnectedToType == null)
|
||
has_obj_methods = true;
|
||
}
|
||
else if (si.sym_info is compiled_function_node)
|
||
{
|
||
compiled_function_node cfn = si.sym_info as compiled_function_node;
|
||
if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cfn.ConnectedToType != null)
|
||
si_list.Add(si);
|
||
if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfn.ConnectedToType == null)
|
||
has_obj_methods = true;
|
||
}
|
||
else if (si.sym_info is common_method_node)
|
||
{
|
||
common_method_node cfn = si.sym_info as common_method_node;
|
||
if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
si_list.Add(si);
|
||
if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
has_obj_methods = true;
|
||
}
|
||
si = si.Next;
|
||
}
|
||
for (int i = 0; i < si_list.Count; i++)
|
||
{
|
||
if (new_si == null)
|
||
{
|
||
new_si = si_list[i];
|
||
si = new_si;
|
||
}
|
||
else
|
||
{
|
||
si.Next = si_list[i];
|
||
si = si.Next;
|
||
}
|
||
}
|
||
if (si != null)
|
||
si.Next = null;
|
||
si = new_si;
|
||
}
|
||
if (_method_call.parameters != null)
|
||
{
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
#region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов
|
||
//lroman//
|
||
if (en is SyntaxTree.function_lambda_definition)
|
||
{
|
||
lambdas_are_in_parameters = true;
|
||
((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
var cen = convert_strong(en);
|
||
exprs.AddElement(cen);
|
||
}
|
||
}
|
||
|
||
expression_node subexpr1 = null;
|
||
|
||
if (to_type != null)
|
||
{
|
||
subexpr1 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type);
|
||
}
|
||
else
|
||
{
|
||
if (iwt != null)
|
||
{
|
||
si = get_generic_functions(si, true, subloc);
|
||
si = get_function_instances(si, iwt.template_params.params_list, id_right.name, subloc, si.Next == null);
|
||
}
|
||
#region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим
|
||
//lroman//
|
||
if (lambdas_are_in_parameters)
|
||
{
|
||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||
function_node_list spf = null;
|
||
try
|
||
{
|
||
ThrowCompilationError = false;
|
||
function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
if (ffn == null)
|
||
{
|
||
if (skip_first_parameter)
|
||
{
|
||
expressions_list ex_list = new expressions_list();
|
||
ex_list.AddRange(exprs);
|
||
ex_list.remove_at(0);
|
||
ffn = convertion_data_and_alghoritms.select_function(ex_list, si, subloc, syntax_nodes_parameters);
|
||
if (ffn == null)
|
||
{
|
||
ThrowCompilationError = true;
|
||
throw LastError();
|
||
}
|
||
RemoveLastError();
|
||
skip_first_parameter = false;
|
||
exprs = ex_list;
|
||
ThrowCompilationError = true;
|
||
}
|
||
else
|
||
{
|
||
ThrowCompilationError = true;
|
||
throw LastError();
|
||
}
|
||
|
||
}
|
||
ThrowCompilationError = true;
|
||
int exprCounter = 0;
|
||
if (skip_first_parameter)
|
||
{
|
||
exprCounter++;
|
||
}
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||
LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
exprs[exprCounter] = convert_strong(en);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
exprCounter++;
|
||
}
|
||
}
|
||
}
|
||
catch (SeveralFunctionsCanBeCalled sf)
|
||
{
|
||
spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||
}
|
||
|
||
Exception lastmultex = null;
|
||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||
{ // exprs - глобальная, поэтому надо копировать
|
||
int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка
|
||
// SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать.
|
||
// не забыть, что аналогичный код есть в create_constructor_call!!!!!!!
|
||
int GoodVersionsCount = 0;
|
||
int GoodVersionsCountWithSameResType = 0;
|
||
for (int i = 0; i < spf.Count; i++) // цикл по версиям
|
||
{
|
||
function_node fnn = spf[i];
|
||
try
|
||
{
|
||
int exprCounter = 0;
|
||
if (skip_first_parameter)
|
||
{
|
||
exprCounter++;
|
||
}
|
||
|
||
expressions_list exprs1 = new expressions_list();
|
||
exprs1.AddRange(exprs); // сделали копию
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var fld = en as SyntaxTree.function_lambda_definition;
|
||
|
||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||
var fl = fld.lambda_visit_mode;
|
||
|
||
// запомнили типы параметров лямбды - SSM
|
||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK == null)
|
||
realparamstype[k] = null;
|
||
else realparamstype[k] = laminftypeK.real_type;
|
||
}
|
||
|
||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||
object realrestype = null;
|
||
if (restype != null)
|
||
realrestype = restype.real_type;
|
||
LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this);
|
||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman
|
||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||
|
||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||
try
|
||
{
|
||
exprs1[exprCounter] = convert_strong(en);
|
||
|
||
type_node resexprtype = fld.RealSemTypeOfResExpr as type_node;
|
||
type_node resformaltype = fld.RealSemTypeOfResult as type_node;
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
|
||
/*compiled_type_node tt;
|
||
tt = fnn.parameters[exprCounter].type as compiled_type_node;
|
||
if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func"))
|
||
{
|
||
resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
}*/
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||
// восстанавливаем сохраненный тип возвращаемого значения
|
||
if (restype != null)
|
||
restype.real_type = realrestype;
|
||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK != null)
|
||
laminftypeK.real_type = realparamstype[k];
|
||
}
|
||
|
||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||
fld.lambda_visit_mode = fl;
|
||
}
|
||
|
||
//contextChanger.RestoreCurrentContext();
|
||
exprCounter++;
|
||
}
|
||
}
|
||
/*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||
{
|
||
spfnum = -2;
|
||
break;
|
||
}*/
|
||
|
||
if (GoodVersionsCountWithSameResType == 0)
|
||
spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения
|
||
GoodVersionsCount += 1;
|
||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||
exprs[j] = exprs1[j];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||
//contextChanger.RestoreCurrentContext();
|
||
lastmultex = e;
|
||
}
|
||
} // конец цикла по версиям
|
||
if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения
|
||
throw new SeveralFunctionsCanBeCalled(subloc, spf);
|
||
if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд
|
||
{
|
||
throw lastmultex;
|
||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||
}
|
||
|
||
int kk = 0;
|
||
if (skip_first_parameter)
|
||
kk++;
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
kk++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this);
|
||
exprs[kk] = convert_strong(en);
|
||
kk++;
|
||
}
|
||
}
|
||
}
|
||
// SSM 21.05.14 end
|
||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
function_node fn = null;
|
||
if (!skip_first_parameter || si.Next == null)
|
||
fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
else
|
||
{
|
||
try
|
||
{
|
||
ThrowCompilationError = false;
|
||
fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
if (fn == null && skip_first_parameter)
|
||
{
|
||
if (si.Next == null)
|
||
{
|
||
ThrowCompilationError = true;
|
||
throw LastError();
|
||
}
|
||
RemoveLastError();
|
||
skip_first_parameter = false;
|
||
si = tmp_si;
|
||
exprs.remove_at(0);
|
||
fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
if (fn == null)
|
||
{
|
||
ThrowCompilationError = true;
|
||
throw LastError();
|
||
}
|
||
// else
|
||
// RemoveLastError(); // ошибка уже убрана чуть выше
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ThrowCompilationError = true;
|
||
if (skip_first_parameter)
|
||
{
|
||
si = tmp_si;
|
||
exprs.remove_at(0);
|
||
fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
}
|
||
else
|
||
throw ex;
|
||
}
|
||
ThrowCompilationError = true;
|
||
}
|
||
SemanticTree.IGenericInstance igi = fn as SemanticTree.IGenericInstance;
|
||
if (igi != null)
|
||
{
|
||
//проверяем на соответствие ограничителям
|
||
int num_err;
|
||
//CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(
|
||
}
|
||
base_function_call bfc = create_not_static_method_call(fn, exp, get_location(id_right), proc_wait);
|
||
bfc.parameters.AddRange(exprs);
|
||
subexpr1 = bfc;
|
||
}
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(subexpr1);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(subexpr1);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(subexpr1.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
namespace_node nsn = (namespace_node)sn;
|
||
if (templ_args_count != 0)
|
||
{
|
||
//Ищем generics
|
||
si = context.find(id_right.name + compiler_string_consts.generic_params_infix + templ_args_count.ToString());
|
||
if (si != null)
|
||
{
|
||
si = new SymbolInfo(get_generic_instance(si, iwt.template_params.params_list));
|
||
iwt = null;
|
||
}
|
||
}
|
||
if (si == null)
|
||
{
|
||
SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident;
|
||
if (oni_right != null)
|
||
{
|
||
si = nsn.find(name_reflector.get_name(oni_right.operator_type));
|
||
}
|
||
else
|
||
{
|
||
si = nsn.find(id_right.name);
|
||
if (templ_args_count != 0)
|
||
{
|
||
SymbolInfo conv = ConvertTypeToInstance(si, iwt.template_params.params_list, get_location(id_right));
|
||
if (conv != null)
|
||
{
|
||
si = conv;
|
||
iwt = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
id = id_right;
|
||
break;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
unit_node un = (unit_node)sn;
|
||
SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident;
|
||
if (oni_right != null)
|
||
{
|
||
si = un.find_only_in_namespace(name_reflector.get_name(oni_right.operator_type));
|
||
}
|
||
else
|
||
{
|
||
si = un.find_only_in_namespace(id_right.name);
|
||
}
|
||
id = id_right;
|
||
break;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = (type_node)sn;
|
||
/*if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
{
|
||
throw new VoidNotValid(get_location(id_right));
|
||
}*/
|
||
check_for_type_allowed(tn, get_location(id_right));
|
||
SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident;
|
||
if (oni_right != null)
|
||
{
|
||
si = tn.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope);
|
||
}
|
||
else
|
||
{
|
||
si = tn.find_in_type(id_right.name, context.CurrentScope);//CurrentScope
|
||
delete_inherited_constructors(ref si, tn);
|
||
delete_extension_methods(ref si, tn); // SSM 2.2.2016 Пока временно закомментировал - в старом коде этого не было. Из-за этого не работает System.Linq.Enumerable.Select
|
||
}
|
||
|
||
//definition_node ddn2=check_name_node_type(id_right.name,si,get_location(id_right),
|
||
// general_node_type.function_node);
|
||
|
||
expression_node exp = null;
|
||
location subloc = get_location(id_right);
|
||
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id_right.name, subloc));
|
||
}
|
||
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
if (si.sym_info.general_node_type == general_node_type.type_node)
|
||
{
|
||
to_type = ((type_node)(si.sym_info));
|
||
}
|
||
else
|
||
{
|
||
dot_node_as_type_ident(tn, id_right, motivation.expression_evaluation);
|
||
exp = ret.get_expression();
|
||
internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(subloc, "EXPECTED_DELEGATE");
|
||
}
|
||
delegate_internal_interface dii = ii as delegate_internal_interface;
|
||
si = new SymbolInfo(dii.invoke_method);
|
||
}
|
||
}
|
||
|
||
if (to_type != null)
|
||
{
|
||
if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1))
|
||
{
|
||
AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED");
|
||
}
|
||
}
|
||
|
||
if (_method_call.parameters != null)
|
||
{
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
#region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов
|
||
//lroman//
|
||
if (en is SyntaxTree.function_lambda_definition)
|
||
{
|
||
lambdas_are_in_parameters = true;
|
||
((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
exprs.AddElement(convert_strong(en));
|
||
}
|
||
}
|
||
|
||
expression_node subexpr2 = null;
|
||
|
||
if (to_type != null)
|
||
{
|
||
subexpr2 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type);
|
||
}
|
||
else
|
||
{
|
||
if (iwt != null)
|
||
{
|
||
si = get_generic_functions(si, true, subloc);
|
||
si = get_function_instances(si, iwt.template_params.params_list, id_right.name, subloc, si.Next == null);
|
||
}
|
||
#region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим
|
||
//lroman//
|
||
if (lambdas_are_in_parameters)
|
||
{
|
||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||
function_node_list spf = null;
|
||
try
|
||
{
|
||
function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
int exprCounter = 0;
|
||
if (skip_first_parameter)
|
||
{
|
||
exprCounter++;
|
||
}
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||
LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
exprs[exprCounter] = convert_strong(en);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
exprCounter++;
|
||
}
|
||
}
|
||
}
|
||
catch (SeveralFunctionsCanBeCalled sf)
|
||
{
|
||
spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||
}
|
||
|
||
Exception lastmultex = null;
|
||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||
{ // exprs - глобальная, поэтому надо копировать
|
||
int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка
|
||
// SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать.
|
||
// не забыть, что аналогичный код есть в create_constructor_call!!!!!!!
|
||
int GoodVersionsCount = 0;
|
||
int GoodVersionsCountWithSameResType = 0;
|
||
for (int i = 0; i < spf.Count; i++) // цикл по версиям
|
||
{
|
||
function_node fnn = spf[i];
|
||
try
|
||
{
|
||
int exprCounter = 0;
|
||
if (skip_first_parameter)
|
||
{
|
||
exprCounter++;
|
||
}
|
||
|
||
expressions_list exprs1 = new expressions_list();
|
||
exprs1.AddRange(exprs); // сделали копию
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var fld = en as SyntaxTree.function_lambda_definition;
|
||
|
||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||
var fl = fld.lambda_visit_mode;
|
||
|
||
// запомнили типы параметров лямбды - SSM
|
||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK == null)
|
||
realparamstype[k] = null;
|
||
else realparamstype[k] = laminftypeK.real_type;
|
||
}
|
||
|
||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||
object realrestype = null;
|
||
if (restype != null)
|
||
realrestype = restype.real_type;
|
||
LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this);
|
||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman
|
||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||
|
||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||
try
|
||
{
|
||
exprs1[exprCounter] = convert_strong(en);
|
||
|
||
type_node resexprtype = fld.RealSemTypeOfResExpr as type_node;
|
||
type_node resformaltype = fld.RealSemTypeOfResult as type_node;
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
|
||
/*compiled_type_node tt;
|
||
tt = fnn.parameters[exprCounter].type as compiled_type_node;
|
||
if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func"))
|
||
{
|
||
resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
}*/
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||
// восстанавливаем сохраненный тип возвращаемого значения
|
||
if (restype != null)
|
||
restype.real_type = realrestype;
|
||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK != null)
|
||
laminftypeK.real_type = realparamstype[k];
|
||
}
|
||
|
||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||
fld.lambda_visit_mode = fl;
|
||
}
|
||
|
||
//contextChanger.RestoreCurrentContext();
|
||
exprCounter++;
|
||
}
|
||
}
|
||
/*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||
{
|
||
spfnum = -2;
|
||
break;
|
||
}*/
|
||
|
||
if (GoodVersionsCountWithSameResType == 0)
|
||
spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения
|
||
GoodVersionsCount += 1;
|
||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||
exprs[j] = exprs1[j];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||
//contextChanger.RestoreCurrentContext();
|
||
lastmultex = e;
|
||
}
|
||
} // конец цикла по версиям
|
||
if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения
|
||
throw new SeveralFunctionsCanBeCalled(subloc, spf);
|
||
if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд
|
||
{
|
||
throw lastmultex;
|
||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||
}
|
||
|
||
int kk = 0;
|
||
if (skip_first_parameter)
|
||
kk++;
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
kk++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this);
|
||
exprs[kk] = convert_strong(en);
|
||
kk++;
|
||
}
|
||
}
|
||
}
|
||
// SSM 21.05.14 end
|
||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
if (!debug && fn == SystemLibrary.SystemLibrary.assert_method)
|
||
{
|
||
// return_value(new empty_statement(null));
|
||
// return;
|
||
}
|
||
/*if ((proc_wait==false)&&(fn.return_value_type==null))
|
||
{
|
||
throw new FunctionExpectedProcedureMeet(fn,get_location(id_right));
|
||
}*/
|
||
|
||
base_function_call bfc2 = null;
|
||
if (exp == null)
|
||
{
|
||
bfc2 = create_static_method_call(fn, subloc, tn, proc_wait);
|
||
}
|
||
else
|
||
{
|
||
bfc2 = create_not_static_method_call(fn, exp, subloc, proc_wait);
|
||
}
|
||
bfc2.parameters.AddRange(exprs);
|
||
subexpr2 = bfc2;
|
||
}
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(subexpr2);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(subexpr2);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(subexpr2.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.expression expr = deref_value as SyntaxTree.expression;
|
||
if (expr != null)
|
||
{
|
||
//throw new CompilerInternalError("Not supported");
|
||
expression_node exp_int = convert_strong(expr);
|
||
location sloc = get_location(expr);
|
||
internal_interface ii = exp_int.type.get_internal_interface(internal_interface_kind.delegate_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(sloc, "EXPECTED_DELEGATE");
|
||
}
|
||
delegate_internal_interface dii = (delegate_internal_interface)ii;
|
||
si = new SymbolInfo(dii.invoke_method);
|
||
|
||
if (_method_call.parameters != null)
|
||
{
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
#region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов
|
||
//lroman//
|
||
if (en is SyntaxTree.function_lambda_definition)
|
||
{
|
||
lambdas_are_in_parameters = true;
|
||
((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
exprs.AddElement(convert_strong(en));
|
||
}
|
||
}
|
||
location subloc = sloc;
|
||
#region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим
|
||
//lroman//
|
||
if (lambdas_are_in_parameters)
|
||
{
|
||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||
function_node_list spf = null;
|
||
try
|
||
{
|
||
function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters);
|
||
int exprCounter = 0;
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||
LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
exprs[exprCounter] = convert_strong(en);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
exprCounter++;
|
||
}
|
||
}
|
||
}
|
||
catch (SeveralFunctionsCanBeCalled sf)
|
||
{
|
||
spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||
}
|
||
|
||
Exception lastmultex = null;
|
||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||
{ // exprs - глобальная, поэтому надо копировать
|
||
int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка
|
||
// SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать.
|
||
// не забыть, что аналогичный код есть в create_constructor_call!!!!!!!
|
||
int GoodVersionsCount = 0;
|
||
int GoodVersionsCountWithSameResType = 0;
|
||
for (int i = 0; i < spf.Count; i++) // цикл по версиям
|
||
{
|
||
function_node fnn = spf[i];
|
||
try
|
||
{
|
||
int exprCounter = 0;
|
||
|
||
|
||
expressions_list exprs1 = new expressions_list();
|
||
exprs1.AddRange(exprs); // сделали копию
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var fld = en as SyntaxTree.function_lambda_definition;
|
||
|
||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||
var fl = fld.lambda_visit_mode;
|
||
|
||
// запомнили типы параметров лямбды - SSM
|
||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK == null)
|
||
realparamstype[k] = null;
|
||
else realparamstype[k] = laminftypeK.real_type;
|
||
}
|
||
|
||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||
object realrestype = null;
|
||
if (restype != null)
|
||
realrestype = restype.real_type;
|
||
LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this);
|
||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman
|
||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||
|
||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||
try
|
||
{
|
||
exprs1[exprCounter] = convert_strong(en);
|
||
|
||
type_node resexprtype = fld.RealSemTypeOfResExpr as type_node;
|
||
type_node resformaltype = fld.RealSemTypeOfResult as type_node;
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
|
||
/*compiled_type_node tt;
|
||
tt = fnn.parameters[exprCounter].type as compiled_type_node;
|
||
if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func"))
|
||
{
|
||
resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
}*/
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||
// восстанавливаем сохраненный тип возвращаемого значения
|
||
if (restype != null)
|
||
restype.real_type = realrestype;
|
||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK != null)
|
||
laminftypeK.real_type = realparamstype[k];
|
||
}
|
||
|
||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||
fld.lambda_visit_mode = fl;
|
||
}
|
||
|
||
//contextChanger.RestoreCurrentContext();
|
||
exprCounter++;
|
||
}
|
||
}
|
||
/*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||
{
|
||
spfnum = -2;
|
||
break;
|
||
}*/
|
||
|
||
if (GoodVersionsCountWithSameResType == 0)
|
||
spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения
|
||
GoodVersionsCount += 1;
|
||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||
exprs[j] = exprs1[j];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||
//contextChanger.RestoreCurrentContext();
|
||
lastmultex = e;
|
||
}
|
||
} // конец цикла по версиям
|
||
if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения
|
||
throw new SeveralFunctionsCanBeCalled(subloc, spf);
|
||
if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд
|
||
{
|
||
throw lastmultex;
|
||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||
}
|
||
|
||
int kk = 0;
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
kk++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this);
|
||
exprs[kk] = convert_strong(en);
|
||
kk++;
|
||
}
|
||
}
|
||
}
|
||
// SSM 21.05.14 end
|
||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
function_node del_func = convertion_data_and_alghoritms.select_function(exprs, si, sloc, syntax_nodes_parameters);
|
||
base_function_call bbfc = create_not_static_method_call(del_func, exp_int, sloc, proc_wait);
|
||
bbfc.parameters.AddRange(exprs);
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bbfc);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bbfc);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bbfc.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Unexpected method name kind");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//definition_node dn=check_name_node_type(id.name,si,get_location(_method_call),general_node_type.function_node);
|
||
|
||
expression_node exp2 = null;
|
||
location subloc2 = get_location(id);
|
||
|
||
List<TreeConverter.SymbolInfo> sibak = new List<TreeConverter.SymbolInfo>();
|
||
TreeConverter.SymbolInfo ssi = si;
|
||
while (ssi != null)
|
||
{
|
||
ssi = ssi.Next;
|
||
sibak.Add(ssi);
|
||
}
|
||
|
||
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id.name, subloc2));
|
||
}
|
||
is_format_allowed = false;
|
||
if (SystemUnitAssigned)
|
||
if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si))
|
||
{
|
||
|
||
expression_node bfcint = make_read_call(si, _method_call.parameters, subloc2);
|
||
if (!proc_wait)
|
||
AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.write_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.StrProcedure.Equal(si))
|
||
{
|
||
is_format_allowed = true;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.ArrayCopyFunction.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
||
{
|
||
location loc = get_location(_method_call);
|
||
expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ArrayCopyFunction.sym_info as function_node, loc, param0);
|
||
function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, param0.type, false);
|
||
en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en);
|
||
return_value(en);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.SetLengthProcedure.Equal(si) || SystemLibrary.SystemLibrary.resize_func == si.sym_info as function_node)
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count >= 2)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
if (!param0.is_addressed)
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node param1 = convert_strong(_method_call.parameters.expressions[1]);
|
||
param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type);
|
||
base_function_call cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info is common_namespace_function_node)
|
||
cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call));
|
||
else
|
||
cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call));
|
||
cnfn.parameters.AddElement(param0);
|
||
cnfn.parameters.AddElement(param1);
|
||
cnfn.parameters.AddElement(new int_const_node((param0.type as short_string_type_node).Length, null));
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(cnfn);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(cnfn);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
else if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
||
{
|
||
int rank = 1;
|
||
if (param0.type is compiled_type_node)
|
||
rank = (param0.type as compiled_type_node).rank;
|
||
else if (param0.type is common_type_node)
|
||
rank = (param0.type as common_type_node).rank;
|
||
if (_method_call.parameters.expressions.Count - 1 != rank)
|
||
AddError(get_location(_method_call), "{0}_PARAMETERS_EXPECTED", rank + 1);
|
||
if (rank > 1)
|
||
{
|
||
type_node tn = param0.type.element_type;
|
||
location loc = get_location(_method_call);
|
||
typeof_operator to = new typeof_operator(tn, loc);
|
||
List<expression_node> lst = new List<expression_node>();
|
||
//размер
|
||
for (int i = 1; i < _method_call.parameters.expressions.Count; i++)
|
||
{
|
||
expression_node expr = convert_strong(_method_call.parameters.expressions[i]); ;
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.integer_type);
|
||
if (expr is int_const_node && (expr as int_const_node).constant_value < 0)
|
||
AddError(expr.location, "NEGATIVE_ARRAY_LENGTH_({0})_NOT_ALLOWED", (expr as int_const_node).constant_value);
|
||
lst.Add(expr);
|
||
}
|
||
//это вызов спецфункции
|
||
|
||
expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(lst.Count, loc));
|
||
common_namespace_function_call cnfc = retv as common_namespace_function_call;
|
||
foreach (expression_node e in lst)
|
||
cnfc.parameters.AddElement(e);
|
||
expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CopyWithSizeFunction.sym_info as function_node, loc, param0, cnfc);
|
||
function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, retv.type, false);
|
||
en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en);
|
||
basic_function_call bfc = new basic_function_call(tn.find(compiler_string_consts.assign_name).sym_info as basic_function_node, loc, param0, en);
|
||
return_value(bfc);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.InsertProcedure.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3)
|
||
{
|
||
//expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
expression_node param1 = convert_strong(_method_call.parameters.expressions[1]);
|
||
//expression_node param2 = convert_strong(_method_call.parameters.expressions[2]);
|
||
if (param1.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
expression_node param2 = convert_strong(_method_call.parameters.expressions[2]);
|
||
param0 = convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.string_type);
|
||
param2 = convertion_data_and_alghoritms.convert_type(param2, SystemLibrary.SystemLibrary.integer_type);
|
||
base_function_call cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info is common_namespace_function_node)
|
||
cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call));
|
||
else
|
||
cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call));
|
||
cnfn.parameters.AddElement(param0);
|
||
cnfn.parameters.AddElement(param1);
|
||
cnfn.parameters.AddElement(param2);
|
||
cnfn.parameters.AddElement(new int_const_node((param1.type as short_string_type_node).Length, null));
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(cnfn);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(cnfn);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.DeleteProcedure.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3)
|
||
{
|
||
//expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
//expression_node param2 = convert_strong(_method_call.parameters.expressions[2]);
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node param1 = convert_strong(_method_call.parameters.expressions[1]);
|
||
expression_node param2 = convert_strong(_method_call.parameters.expressions[2]);
|
||
param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type);
|
||
param2 = convertion_data_and_alghoritms.convert_type(param2, SystemLibrary.SystemLibrary.integer_type);
|
||
base_function_call cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info is common_namespace_function_node)
|
||
cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as common_namespace_function_node, get_location(_method_call));
|
||
else
|
||
cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as compiled_function_node, get_location(_method_call));
|
||
cnfn.parameters.AddElement(param0);
|
||
cnfn.parameters.AddElement(param1);
|
||
cnfn.parameters.AddElement(param2);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(cnfn);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(cnfn);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)
|
||
|| SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 2)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
expression_node param1 = convert_strong(_method_call.parameters.expressions[1]);
|
||
expressions_list args = new expressions_list();
|
||
args.AddElement(param0);
|
||
args.AddElement(param1);
|
||
CheckSpecialFunctionCall(si, args, get_location(_method_call));
|
||
expression_node en_cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call));
|
||
else cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call));
|
||
cnfn.parameters.AddElement(param0);
|
||
cnfn.parameters.AddElement(param1);
|
||
en_cnfn = cnfn;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfn = null;
|
||
if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)) cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as compiled_function_node, get_location(_method_call));
|
||
else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as compiled_function_node, get_location(_method_call));
|
||
cnfn.parameters.AddElement(param0);
|
||
cnfn.parameters.AddElement(param1);
|
||
en_cnfn = cnfn;
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(en_cnfn);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(en_cnfn);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(en_cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.IncProcedure.Equal(si))
|
||
{
|
||
expression_node bfcint = make_inc_call(si, _method_call.parameters, subloc2);
|
||
if (!proc_wait)
|
||
AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.DecProcedure.Equal(si))
|
||
{
|
||
expression_node bfcint = make_dec_call(si, _method_call.parameters, subloc2);
|
||
if (!proc_wait)
|
||
AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.SuccFunction.Equal(si))
|
||
{
|
||
expression_node bfcint = make_succ_call(si, _method_call.parameters, subloc2);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.PredFunction.Equal(si))
|
||
{
|
||
expression_node bfcint = make_pred_call(si, _method_call.parameters, subloc2);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.OrdFunction.Equal(si))
|
||
{
|
||
expression_node bfcint = make_ord_call(si, _method_call.parameters, subloc2);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.LowFunction.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface;
|
||
expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), get_location(_method_call));
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(en);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(en);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.HighFunction.Equal(si))
|
||
{
|
||
if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(_method_call.parameters.expressions[0]);
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface;
|
||
expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.upper_value), get_location(_method_call));
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(en);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(en);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (si == SystemLibrary.SystemLibInitializer.NewProcedure)
|
||
{
|
||
expression_node bfcint = make_new_call(si, _method_call.parameters, subloc2);
|
||
if (!proc_wait)
|
||
AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
else if (si == SystemLibrary.SystemLibInitializer.DisposeProcedure)
|
||
{
|
||
//if (convertion_data_and_alghoritms.select_function(convert_expression_list(_method_call.parameters.expressions), si, subloc2) == SystemLibrary.SystemLibInitializer.DisposeProcedure.sym_info)
|
||
//{
|
||
expression_node bfcint = make_dispose_call(si, _method_call.parameters, subloc2);
|
||
if (!proc_wait)
|
||
AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name);
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(bfcint);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(bfcint);
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED");
|
||
return;
|
||
}
|
||
}
|
||
|
||
return;
|
||
// }
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.AssertProcedure.Equal(si))
|
||
{
|
||
// return_value(new empty_statement(null));
|
||
// return;
|
||
}
|
||
/*else if (SystemLibrary.SystemLibInitializer.IncProcedure != null && SystemLibrary.SystemLibInitializer.IncProcedure.Equal(si))
|
||
{
|
||
expression_node bfcint = make_inc_call(si, _method_call.parameters, subloc2);
|
||
}*/
|
||
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
if (si.sym_info.general_node_type == general_node_type.type_node)
|
||
{
|
||
to_type = ((type_node)(si.sym_info));
|
||
/*if (to_type == SystemLibrary.SystemLibrary.void_type)
|
||
{
|
||
throw new VoidNotValid(subloc2);
|
||
}*/
|
||
check_for_type_allowed(to_type, subloc2);
|
||
}
|
||
else
|
||
{
|
||
exp2 = ident_value_reciving(si, id);
|
||
internal_interface ii = exp2.type.get_internal_interface(internal_interface_kind.delegate_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(subloc2, "EXPECTED_DELEGATE");
|
||
}
|
||
if (exp2 is nonstatic_event_reference)
|
||
{
|
||
nonstatic_event_reference nser = exp2 as nonstatic_event_reference;
|
||
common_event ce = nser.en as common_event;
|
||
if (ce != null)
|
||
exp2 = new class_field_reference(ce.field, new this_node(ce.cont_type, null), null);
|
||
else
|
||
AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name);
|
||
}
|
||
else if (exp2 is static_event_reference)
|
||
{
|
||
static_event_reference nser = exp2 as static_event_reference;
|
||
common_event ce = nser.en as common_event;
|
||
if (ce != null)
|
||
exp2 = new static_class_field_reference(ce.field, null);
|
||
else if (nser.en is common_namespace_event && _compiled_unit.namespaces.IndexOf((nser.en as common_namespace_event).namespace_node) != -1)
|
||
exp2 = new namespace_variable_reference((nser.en as common_namespace_event).field, null);
|
||
else
|
||
AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name);
|
||
}
|
||
delegate_internal_interface dii = ii as delegate_internal_interface;
|
||
si = new SymbolInfo(dii.invoke_method);
|
||
}
|
||
}
|
||
|
||
if (to_type != null)
|
||
{
|
||
if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1))
|
||
{
|
||
AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED");
|
||
}
|
||
}
|
||
|
||
if (_method_call.parameters != null)
|
||
{
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
bool tmp = is_format_allowed;
|
||
|
||
#region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов
|
||
//lroman//
|
||
if (en is SyntaxTree.function_lambda_definition)
|
||
{
|
||
lambdas_are_in_parameters = true;
|
||
((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
exprs.AddElement(convert_strong(en));
|
||
is_format_allowed = tmp;
|
||
}
|
||
if (SystemLibrary.SystemLibInitializer.AssertProcedure != null && SystemLibrary.SystemLibInitializer.AssertProcedure.Equal(si) && _method_call.source_context != null)
|
||
{
|
||
exprs.AddElement(new string_const_node(_method_call.source_context.FileName, null));
|
||
exprs.AddElement(new int_const_node(_method_call.source_context.begin_position.line_num, null));
|
||
}
|
||
}
|
||
is_format_allowed = false;
|
||
CheckSpecialFunctionCall(si, exprs, get_location(_method_call));
|
||
|
||
ssi = si;
|
||
foreach (SymbolInfo sii in sibak)
|
||
{
|
||
ssi.Next = sii;
|
||
ssi = sii;
|
||
}
|
||
|
||
if (to_type != null)
|
||
{
|
||
//(ssyy) К вызову функции здесь явно не приводим, т.к. это излишне.
|
||
expression_node ee = exprs[0];
|
||
bool del = to_type is common_type_node && (to_type as common_type_node).IsDelegate;
|
||
if (!del)
|
||
try_convert_typed_expression_to_function_call(ref ee);
|
||
else
|
||
ee = convert_strong(_method_call.parameters.expressions[0]);
|
||
expr_node = convertion_data_and_alghoritms.explicit_convert_type(ee, to_type);
|
||
//expression_node expr = convert_if_typed_expression_to_function_call(exprs[0]);
|
||
//expr_node = convertion_data_and_alghoritms.explicit_convert_type(expr, to_type);
|
||
}
|
||
else
|
||
{
|
||
if (exp2 == null)
|
||
{
|
||
location mcloc = get_location(_method_call);
|
||
if (iwt != null)
|
||
{
|
||
si = get_generic_functions(si, true, mcloc);
|
||
si = get_function_instances(si, iwt.template_params.params_list, id.name, mcloc, si.Next == null);
|
||
}
|
||
|
||
#region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим
|
||
//lroman//
|
||
if (lambdas_are_in_parameters)
|
||
{
|
||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||
function_node_list spf = null;
|
||
try
|
||
{
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc2, syntax_nodes_parameters);
|
||
int exprCounter = 0;
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
exprs[exprCounter] = convert_strong(en);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
exprCounter++;
|
||
}
|
||
}
|
||
}
|
||
catch (SeveralFunctionsCanBeCalled sf)
|
||
{
|
||
spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||
}
|
||
|
||
Exception lastmultex = null;
|
||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||
{ // exprs - глобальная, поэтому надо копировать
|
||
int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка
|
||
// SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать.
|
||
// не забыть, что аналогичный код есть в create_constructor_call!!!!!!! И еще выше по коду!!! кошмар!!!
|
||
int GoodVersionsCount = 0;
|
||
int GoodVersionsCountWithSameResType = 0;
|
||
for (int i = 0; i < spf.Count; i++) // цикл по версиям
|
||
{
|
||
function_node fn = spf[i];
|
||
try // внутренний try регенерирует исключение, а этот гасит
|
||
{
|
||
int exprCounter = 0;
|
||
expressions_list exprs1 = new expressions_list();
|
||
exprs1.AddRange(exprs); // сделали копию
|
||
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var fld = en as SyntaxTree.function_lambda_definition;
|
||
|
||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||
var fl = fld.lambda_visit_mode;
|
||
|
||
// запомнили типы параметров лямбды - SSM
|
||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK == null)
|
||
realparamstype[k] = null;
|
||
else realparamstype[k] = laminftypeK.real_type;
|
||
}
|
||
|
||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||
object realrestype = null;
|
||
if (restype != null)
|
||
realrestype = restype.real_type;
|
||
|
||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this);
|
||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman
|
||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||
|
||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||
try
|
||
{
|
||
exprs1[exprCounter] = convert_strong(en);
|
||
|
||
// SSM 7/08/15
|
||
|
||
type_node resexprtype = fld.RealSemTypeOfResExpr as type_node;
|
||
type_node resformaltype = fld.RealSemTypeOfResult as type_node;
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
|
||
/*var tt = fn.parameters[exprCounter].type as compiled_type_node;
|
||
if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func"))
|
||
{
|
||
resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
}*/
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||
// восстанавливаем сохраненный тип возвращаемого значения
|
||
if (restype != null)
|
||
restype.real_type = realrestype;
|
||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK != null)
|
||
laminftypeK.real_type = realparamstype[k];
|
||
}
|
||
|
||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||
fld.lambda_visit_mode = fl;
|
||
}
|
||
|
||
//contextChanger.RestoreCurrentContext();
|
||
exprCounter++;
|
||
}
|
||
}
|
||
/*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||
{
|
||
spfnum = -2;
|
||
break;
|
||
}*/
|
||
|
||
if (GoodVersionsCountWithSameResType == 0)
|
||
spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения
|
||
GoodVersionsCount += 1;
|
||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||
exprs[j] = exprs1[j];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||
//contextChanger.RestoreCurrentContext();
|
||
lastmultex = e;
|
||
}
|
||
} //--------------- конец цикла по версиям
|
||
|
||
if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения
|
||
throw new SeveralFunctionsCanBeCalled(subloc2, spf);
|
||
if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд
|
||
{
|
||
throw lastmultex;
|
||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||
}
|
||
|
||
var kk = 0;
|
||
foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
kk++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this);
|
||
exprs[kk] = convert_strong(en);
|
||
kk++;
|
||
}
|
||
}
|
||
}
|
||
// SSM 21.05.14 end
|
||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
expr_node = convertion_data_and_alghoritms.create_full_function_call(exprs, si, mcloc,
|
||
context.converted_type, context.top_function, proc_wait);
|
||
}
|
||
else
|
||
{
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc2, syntax_nodes_parameters);
|
||
base_function_call bbffcc = create_not_static_method_call(fn, exp2, subloc2, proc_wait);
|
||
bbffcc.parameters.AddRange(exprs);
|
||
expr_node = bbffcc;
|
||
}
|
||
}
|
||
|
||
/*if ((proc_wait==false)&&(expr_node.type==null))
|
||
{
|
||
throw new FunctionExpectedProcedureMeet((function_node)dn,get_location(_method_call));
|
||
}*/
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(expr_node);
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(expr_node);
|
||
return;
|
||
}
|
||
case motivation.address_reciving:
|
||
{
|
||
AddError(get_location(_method_call), "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
||
return;
|
||
}
|
||
default:
|
||
{
|
||
//throw new CompilerInternalError("Can not recive address from method call");//!
|
||
AddError(get_location(_method_call), "EXPECTED_VARIABLE");
|
||
return;
|
||
}
|
||
}
|
||
//throw new CompilerInternalError("Error in creation method call");
|
||
|
||
}
|
||
|
||
//remove extension methods when static methods called
|
||
private void delete_extension_methods(ref SymbolInfo si, type_node tn)
|
||
{
|
||
List<SymbolInfo> si_list = new List<SymbolInfo>();
|
||
SymbolInfo tmp_si = si;
|
||
while (tmp_si != null)
|
||
{
|
||
var fn = tmp_si.sym_info as function_node;
|
||
if (fn != null)
|
||
{
|
||
if (fn.is_extension_method)
|
||
{
|
||
compiled_function_node cfn = fn as compiled_function_node;
|
||
if (cfn != null && cfn.cont_type == tn)
|
||
si_list.Add(tmp_si);
|
||
}
|
||
else
|
||
si_list.Add(tmp_si);
|
||
}
|
||
else
|
||
si_list.Add(tmp_si);
|
||
/*if (!(fn != null && fn.is_extension_method))
|
||
si_list.Add(tmp_si);*/
|
||
tmp_si = tmp_si.Next;
|
||
}
|
||
/*tmp_si = si;
|
||
while (tmp_si != null)
|
||
{
|
||
var fn = tmp_si.sym_info as function_node;
|
||
if (fn != null && fn.is_extension_method)
|
||
{
|
||
var b = false;
|
||
foreach (var x in si_list)
|
||
{
|
||
var xn = x.sym_info as function_node;
|
||
if (convertion_data_and_alghoritms.function_eq_params(fn, xn))
|
||
{
|
||
b = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!b)
|
||
si_list.Add(tmp_si);
|
||
}
|
||
tmp_si = tmp_si.Next;
|
||
}*/
|
||
SymbolInfo new_si = null;
|
||
for (int i = 0; i < si_list.Count; i++)
|
||
{
|
||
if (new_si == null)
|
||
{
|
||
new_si = si_list[i];
|
||
si = new_si;
|
||
}
|
||
else
|
||
{
|
||
si.Next = si_list[i];
|
||
si = si.Next;
|
||
}
|
||
}
|
||
if (si != null)
|
||
si.Next = null;
|
||
si = new_si;
|
||
}
|
||
|
||
//ssyy
|
||
//Удаляет конструкторы предков в списке si
|
||
private void delete_inherited_constructors(ref SymbolInfo si, type_node tn)
|
||
{
|
||
SymbolInfo last_sym = null;
|
||
SymbolInfo cur_sym = si;
|
||
while (cur_sym != null)
|
||
{
|
||
type_node comph_type = null;
|
||
bool is_ctor = false;
|
||
common_method_node mnode = cur_sym.sym_info as common_method_node;
|
||
if (mnode != null)
|
||
{
|
||
comph_type = mnode.cont_type;
|
||
is_ctor = mnode.is_constructor;
|
||
}
|
||
else
|
||
{
|
||
compiled_function_node tnode = cur_sym.sym_info as compiled_function_node;
|
||
if (tnode != null)
|
||
{
|
||
comph_type = tnode.cont_type;
|
||
is_ctor = tnode.method_info.IsConstructor;
|
||
}
|
||
}
|
||
//Итак, comph_type - класс, содержащий si.sym_info;
|
||
//is_ctor - является ли оно конструктором
|
||
if (is_ctor && comph_type != tn)
|
||
{
|
||
//Удаляем
|
||
if (last_sym == null)
|
||
{
|
||
si = si.Next;
|
||
}
|
||
else
|
||
{
|
||
last_sym.Next = cur_sym.Next;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
last_sym = cur_sym;
|
||
}
|
||
cur_sym = cur_sym.Next;
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
//TODO: Возможно следует переписать этот метод в более простой форме.
|
||
public override void visit(SyntaxTree.method_call _method_call)
|
||
{
|
||
visit_method_call(_method_call);
|
||
inherited_ident_processing = false;
|
||
}
|
||
|
||
private void ConvertPointersForWrite(expressions_list exprs)
|
||
{
|
||
for (int i = 0; i < exprs.Count; ++i)
|
||
{
|
||
if (exprs[i].type.IsPointer)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.PointerOutputConstructor == null)
|
||
{
|
||
SymbolInfo si = (SystemLibrary.SystemLibInitializer.PointerOutputType.sym_info as common_type_node).find_in_type(compiler_string_consts.default_constructor_name);
|
||
common_method_node cnode = null;
|
||
do
|
||
{
|
||
cnode = si.sym_info as common_method_node;
|
||
if (cnode.parameters.Count != 1)
|
||
{
|
||
cnode = null;
|
||
si = si.Next;
|
||
}
|
||
}
|
||
while (cnode == null);
|
||
SystemLibrary.SystemLibInitializer.PointerOutputConstructor = cnode;
|
||
}
|
||
common_constructor_call cnc = new common_constructor_call(SystemLibrary.SystemLibInitializer.PointerOutputConstructor as common_method_node, exprs[i].location);
|
||
//common_namespace_function_call cnfc = new common_namespace_function_call(
|
||
// SystemLibrary.SystemLibInitializer.PointerToStringFunction.sym_info as common_namespace_function_node,
|
||
// exprs[i].location);
|
||
cnc.parameters.AddElement(exprs[i]);
|
||
exprs[i] = cnc;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ConvertPointersForWriteFromDll(expressions_list exprs)
|
||
{
|
||
for (int i = 0; i < exprs.Count; ++i)
|
||
{
|
||
if (exprs[i].type.IsPointer)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.PointerOutputConstructor == null)
|
||
{
|
||
SymbolInfo si = (SystemLibrary.SystemLibInitializer.PointerOutputType.sym_info as compiled_type_node).find_in_type(compiler_string_consts.default_constructor_name);
|
||
compiled_constructor_node cnode = null;
|
||
do
|
||
{
|
||
cnode = si.sym_info as compiled_constructor_node;
|
||
if (cnode.parameters.Count != 1)
|
||
{
|
||
cnode = null;
|
||
si = si.Next;
|
||
}
|
||
}
|
||
while (cnode == null);
|
||
SystemLibrary.SystemLibInitializer.PointerOutputConstructor = cnode;
|
||
}
|
||
compiled_constructor_call cnc = new compiled_constructor_call(SystemLibrary.SystemLibInitializer.PointerOutputConstructor as compiled_constructor_node, exprs[i].location);
|
||
//common_namespace_function_call cnfc = new common_namespace_function_call(
|
||
// SystemLibrary.SystemLibInitializer.PointerToStringFunction.sym_info as common_namespace_function_node,
|
||
// exprs[i].location);
|
||
cnc.parameters.AddElement(exprs[i]);
|
||
exprs[i] = cnc;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CheckSpecialFunctionCall(SymbolInfo si, expressions_list exprs, location loc)
|
||
{
|
||
if (SystemUnitAssigned)
|
||
{
|
||
bool write_proc = SystemLibrary.SystemLibInitializer.write_procedure.Equal(si);
|
||
if (write_proc && exprs.Count > 1)
|
||
{
|
||
//возможно это запись в типизированый файл
|
||
if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.typed_file)
|
||
//да, точно это типизированый файл!
|
||
{
|
||
//Проверим типы параметров вызова на совпадение с типом элементов файла
|
||
type_node element_type = exprs[0].type.element_type;
|
||
for (int i = 1; i < exprs.Count; i++)
|
||
convertion_data_and_alghoritms.check_convert_type(exprs[i], element_type, exprs[i].location);
|
||
if (element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
for (int i=1; i<exprs.Count; i++)
|
||
{
|
||
//common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null);
|
||
//cmc.parameters.AddElement(exprs[i]);
|
||
//cmc.parameters.AddElement(new int_const_node((element_type as short_string_type_node).Length,null));
|
||
expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(exprs[i],SystemLibrary.SystemLibrary.string_type),new int_const_node((element_type as short_string_type_node).Length,null));
|
||
exprs[i] = cmc;
|
||
}
|
||
}
|
||
//if (exprs[i].type != element_type)
|
||
// throw new ExpectedExprHaveTypeTypedFile(element_type, exprs[i].type, false, get_location(_method_call.parameters.expressions[i]));
|
||
}
|
||
else
|
||
//(ssyy) а может быть, в бинарный!
|
||
if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.binary_file)
|
||
{
|
||
//(ssyy) действительно, бинарный
|
||
for (int i = 1; i < exprs.Count; i++)
|
||
{
|
||
if (!CanUseThisTypeForBinaryFiles(exprs[i].type))
|
||
{
|
||
AddError(exprs[i].location, "CAN_NOT_WRITE_REFERENCE_DATA_TO_BINARY_FILE");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.write_procedure.sym_info is common_namespace_function_node)
|
||
ConvertPointersForWrite(exprs);
|
||
else
|
||
ConvertPointersForWriteFromDll(exprs);
|
||
}
|
||
}
|
||
else if (write_proc || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(si))
|
||
{
|
||
//(ssyy) Преобразуем указатели в строки для вывода write/writeln
|
||
if (SystemLibrary.SystemLibInitializer.writeln_procedure.sym_info is common_namespace_function_node)
|
||
ConvertPointersForWrite(exprs);
|
||
else
|
||
ConvertPointersForWriteFromDll(exprs);
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)
|
||
|| SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(si))
|
||
{
|
||
if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true));
|
||
type_node element_type = exprs[0].type.element_type;
|
||
if (exprs[0].type.type_special_kind != SemanticTree.type_special_kind.base_set_type && exprs[0].type.type_special_kind != SemanticTree.type_special_kind.set_type)
|
||
{
|
||
AddError( new NoFunctionWithSameArguments(loc, true));
|
||
}
|
||
if (element_type != null)
|
||
convertion_data_and_alghoritms.check_convert_type(exprs[1], element_type, exprs[1].location);
|
||
else convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[0].location);
|
||
if (!exprs[0].is_addressed) AddError( new ThisExpressionCanNotBePassedAsVarParameter(exprs[0]));
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.InSetProcedure.Equal(si))
|
||
{
|
||
if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true));
|
||
type_node element_type = exprs[1].type.element_type;
|
||
if (element_type != null)
|
||
{
|
||
//exprs[0] = convertion_data_and_alghoritms.convert_type(exprs[0], element_type, exprs[0].location);
|
||
convertion_data_and_alghoritms.check_convert_type(exprs[0], element_type, exprs[0].location);
|
||
}
|
||
else convertion_data_and_alghoritms.check_convert_type(exprs[0], exprs[1].type, exprs[0].location);
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.SetUnionProcedure.Equal(si)
|
||
|| SystemLibrary.SystemLibInitializer.SetIntersectProcedure.Equal(si) || SystemLibrary.SystemLibInitializer.SetSubtractProcedure.Equal(si))
|
||
{
|
||
if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true));
|
||
convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[1].location);
|
||
}
|
||
|
||
if (si == SystemLibrary.SystemLibInitializer.NewProcedure || si == SystemLibrary.SystemLibInitializer.DisposeProcedure)
|
||
{
|
||
if (exprs[0].type == SystemLibrary.SystemLibrary.pointer_type)
|
||
AddError(exprs[0].location, "EXPECTED_TYPED_POINTER_IN_PROCEDURE{0}", (si.sym_info as function_node).name);
|
||
}
|
||
}
|
||
}
|
||
|
||
private expression_node make_new_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null) AddError( new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node));
|
||
if (parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (!param0.type.IsPointer || param0.type == SystemLibrary.SystemLibrary.pointer_type)
|
||
AddError(new NoFunctionWithSameArguments(loc, true));
|
||
if (!param0.is_addressed)
|
||
{
|
||
bool is_pascal_array_ref = false;
|
||
if (param0.semantic_node_type == semantic_node_type.common_method_call)
|
||
{
|
||
common_method_call cmc = (common_method_call)param0;
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
param0 = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
if (!is_pascal_array_ref)
|
||
{
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
}
|
||
|
||
}
|
||
else AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
}
|
||
if (param0.type is ref_type_node && !can_evaluate_size((param0.type as ref_type_node).pointed_type))
|
||
AddError(loc, "CANNOT_CALL_NEW_BECAUSE_OF_UNDEFINED_SIZE");
|
||
function_node fn = si.sym_info as function_node;
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
|
||
}
|
||
else
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private expression_node make_dispose_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null)
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
if (parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (!param0.type.IsPointer || param0.type == SystemLibrary.SystemLibrary.pointer_type)
|
||
AddError(new NoFunctionWithSameArguments(loc, true));
|
||
if (!param0.is_addressed)
|
||
{
|
||
bool is_pascal_array_ref = false;
|
||
if (param0.semantic_node_type == semantic_node_type.common_method_call)
|
||
{
|
||
common_method_call cmc = (common_method_call)param0;
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
param0 = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
if (!is_pascal_array_ref)
|
||
{
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
return null;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
return null;
|
||
}
|
||
}
|
||
function_node fn = si.sym_info as function_node;
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
|
||
}
|
||
else
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private expression_node make_ord_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null)
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
if (parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression);
|
||
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(param0);
|
||
function_node fn = null;
|
||
try
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(el, si, loc);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
|
||
}
|
||
if (fn != null)
|
||
{
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
}
|
||
else if (param0.type.IsEnum || param0.type.type_special_kind == SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
el = new expressions_list();
|
||
el.AddElement(new int_const_node(1, null));
|
||
fn = convertion_data_and_alghoritms.select_function(el, si, loc);
|
||
//bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
//bfc.ret_type = param0.type;
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
}
|
||
|
||
else
|
||
{
|
||
AddError(new NoFunctionWithSameArguments(loc, false));
|
||
return null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private expression_node make_succ_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null)
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
if (parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression);
|
||
basic_function_call bfc = null;
|
||
int type_flag = 0;
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(param0);
|
||
function_node fn = null;
|
||
try
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(el,si,loc);
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
|
||
}
|
||
if (fn != null)
|
||
{
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
}
|
||
if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum)
|
||
{
|
||
el = new expressions_list();
|
||
el.AddElement(new int_const_node(1,null));
|
||
fn = convertion_data_and_alghoritms.select_function(el,si,loc);
|
||
//bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
//bfc.ret_type = param0.type;
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
cnfc.type = param0.type;
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
cnfc.type = param0.type;
|
||
return cnfc;
|
||
}
|
||
}
|
||
else AddError(new NoFunctionWithSameArguments(loc,false));
|
||
bfc.parameters.AddElement(param0);
|
||
if (type_flag == 0 || type_flag == 3)
|
||
bfc.parameters.AddElement(new int_const_node(1,null));
|
||
else if (type_flag == 1)
|
||
bfc.parameters.AddElement(new long_const_node(1,null));
|
||
else if (type_flag == 2)
|
||
bfc.parameters.AddElement(new ulong_const_node(1,null));
|
||
return bfc;
|
||
}
|
||
AddError(new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
|
||
private expression_node make_pred_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null)
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
if (parameters.expressions.Count == 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression);
|
||
basic_function_call bfc = null;
|
||
int type_flag = 0;
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(param0);
|
||
function_node fn = null;
|
||
try
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(el,si,loc);
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
|
||
}
|
||
if (fn != null)
|
||
{
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
return cnfc;
|
||
}
|
||
}
|
||
else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum)
|
||
{
|
||
el = new expressions_list();
|
||
el.AddElement(new int_const_node(1,null));
|
||
fn = convertion_data_and_alghoritms.select_function(el,si,loc);
|
||
//bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
//bfc.ret_type = param0.type;
|
||
if (fn is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
cnfc.type = param0.type;
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc);
|
||
cnfc.parameters.AddElement(param0);
|
||
cnfc.type = param0.type;
|
||
return cnfc;
|
||
}
|
||
}
|
||
else AddError(new NoFunctionWithSameArguments(loc,false));
|
||
bfc.parameters.AddElement(param0);
|
||
if (type_flag == 0 || type_flag == 3)
|
||
bfc.parameters.AddElement(new int_const_node(1,null));
|
||
else if (type_flag == 1)
|
||
bfc.parameters.AddElement(new long_const_node(1,null));
|
||
else if (type_flag == 2)
|
||
bfc.parameters.AddElement(new ulong_const_node(1,null));
|
||
return bfc;
|
||
}
|
||
AddError(new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
|
||
private expression_node make_inc_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null)
|
||
{
|
||
AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
if (parameters.expressions.Count == 1 || parameters.expressions.Count == 2)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (!param0.is_addressed)
|
||
{
|
||
bool is_pascal_array_ref = false;
|
||
if (param0.semantic_node_type == semantic_node_type.common_method_call)
|
||
{
|
||
common_method_call cmc = (common_method_call)param0;
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
param0 = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
if (!is_pascal_array_ref)
|
||
{
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
}
|
||
|
||
}
|
||
else if (param0 is compiled_function_call)
|
||
{
|
||
compiled_function_call cfc = param0 as compiled_function_call;
|
||
if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type
|
||
&& cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function))
|
||
{
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(cfc.obj);
|
||
exl.AddElement(cfc.parameters[0]);
|
||
basic_function_call bfc2 = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
bfc2.parameters.AddElement(param0);
|
||
expression_node _param1 = null;
|
||
if (parameters.expressions.Count == 2)
|
||
{
|
||
_param1 = convert_strong(parameters.expressions[1]);
|
||
}
|
||
if (_param1 != null)
|
||
bfc2.parameters.AddElement(convertion_data_and_alghoritms.convert_type(_param1,SystemLibrary.SystemLibrary.integer_type));
|
||
else
|
||
bfc2.parameters.AddElement(new int_const_node(1,null));
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(convertion_data_and_alghoritms.convert_type(bfc2,SystemLibrary.SystemLibrary.ushort_type));
|
||
function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc);
|
||
exl.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray()));
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc);
|
||
expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray());
|
||
return ret;
|
||
}
|
||
else
|
||
{
|
||
AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
}
|
||
}
|
||
else AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0));
|
||
}
|
||
else
|
||
check_on_loop_variable(param0);
|
||
expression_node param1 = null;
|
||
int type_flag = 0;
|
||
bool is_uint = false;
|
||
bool is_enum = false;
|
||
if (parameters.expressions.Count == 2)
|
||
{
|
||
param1 = convert_strong(parameters.expressions[1]);
|
||
//param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type);
|
||
}
|
||
basic_function_call ass = null;
|
||
basic_function_call bfc = null;
|
||
if (param0.type == SystemLibrary.SystemLibrary.integer_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.char_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.char_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.byte_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.byte_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.sbyte_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.sbyte_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.short_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.short_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.ushort_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.ushort_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.uint_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.uint_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.uint_add as basic_function_node,loc);
|
||
type_flag = 2;
|
||
is_uint = true;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.int64_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.long_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.long_add as basic_function_node,loc);
|
||
type_flag = 1;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.uint64_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.ulong_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.ulong_add as basic_function_node,loc);
|
||
type_flag = 2;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.bool_type)
|
||
{
|
||
if (param1 == null)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc);
|
||
type_flag = 4;
|
||
}
|
||
else
|
||
{
|
||
basic_function_call mod_expr = new basic_function_call(SystemLibrary.SystemLibrary.int_mod as basic_function_node,loc);
|
||
mod_expr.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type));
|
||
mod_expr.parameters.AddElement(new int_const_node(2,loc));
|
||
basic_function_call condition = new basic_function_call(SystemLibrary.SystemLibrary.int_eq as basic_function_node,loc);
|
||
condition.parameters.AddElement(mod_expr);
|
||
condition.parameters.AddElement(new int_const_node(0,loc));
|
||
basic_function_call not_expr = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc);
|
||
not_expr.parameters.AddElement(param0);
|
||
question_colon_expression qce = new question_colon_expression(condition, param0, not_expr, loc);
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc);
|
||
ass.parameters.AddElement(param0);
|
||
ass.parameters.AddElement(qce);
|
||
type_flag = 5;
|
||
}
|
||
}
|
||
else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc);
|
||
if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
type_node bt = param0.type.base_type;
|
||
if (bt == SystemLibrary.SystemLibrary.int64_type) type_flag = 1;
|
||
else if (bt == SystemLibrary.SystemLibrary.uint64_type) type_flag = 2;
|
||
else if (bt == SystemLibrary.SystemLibrary.uint_type)
|
||
{
|
||
type_flag =2;
|
||
is_uint = true;
|
||
}
|
||
else if (bt.IsEnum)
|
||
{
|
||
is_enum = true;
|
||
}
|
||
}
|
||
else if (param0.type.IsEnum) is_enum = true;
|
||
}
|
||
else AddError(new NoFunctionWithSameArguments(loc,false));
|
||
if (type_flag != 5)
|
||
{
|
||
if (param1 != null)
|
||
switch (type_flag)
|
||
{
|
||
case 0: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); break;
|
||
case 3:
|
||
case 1: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.int64_type); break;
|
||
case 2: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.uint64_type); break;
|
||
}
|
||
if (param0.type != SystemLibrary.SystemLibrary.char_type && !is_enum && param0.type != SystemLibrary.SystemLibrary.bool_type)
|
||
switch (type_flag)
|
||
{
|
||
case 0: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.integer_type)); break;
|
||
case 3:
|
||
case 1: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.int64_type)); break;
|
||
case 2: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.uint64_type)); break;
|
||
}
|
||
|
||
else bfc.parameters.AddElement(param0);
|
||
//bfc.parameters.AddElement(param0);
|
||
|
||
if (param1 == null)
|
||
{
|
||
if (type_flag == 0 || type_flag == 3)
|
||
bfc.parameters.AddElement(new int_const_node(1, null));
|
||
else if (type_flag == 1)
|
||
bfc.parameters.AddElement(new long_const_node(1, null));
|
||
else if (type_flag == 2)
|
||
bfc.parameters.AddElement(new ulong_const_node(1, null));
|
||
}
|
||
else
|
||
bfc.parameters.AddElement(param1);
|
||
ass.parameters.AddElement(param0);
|
||
if (is_uint)
|
||
ass.parameters.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.uint_type));
|
||
else
|
||
if (param0.type == SystemLibrary.SystemLibrary.char_type)
|
||
{
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.ushort_type));
|
||
function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc);
|
||
ass.parameters.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray()));
|
||
}
|
||
else
|
||
ass.parameters.AddElement(bfc);
|
||
}
|
||
return ass;
|
||
}
|
||
|
||
AddError(new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node));
|
||
return null;
|
||
}
|
||
|
||
private expression_node make_dec_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
if (parameters == null) throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node);
|
||
if (parameters.expressions.Count == 1 || parameters.expressions.Count == 2)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (!param0.is_addressed)
|
||
{
|
||
bool is_pascal_array_ref = false;
|
||
if (param0.semantic_node_type == semantic_node_type.common_method_call)
|
||
{
|
||
common_method_call cmc = (common_method_call)param0;
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
param0 = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
is_pascal_array_ref = true;
|
||
|
||
}
|
||
}
|
||
if (!is_pascal_array_ref)
|
||
{
|
||
throw new ThisExpressionCanNotBePassedAsVarParameter(param0);
|
||
}
|
||
|
||
}
|
||
else if (param0 is compiled_function_call)
|
||
{
|
||
compiled_function_call cfc = param0 as compiled_function_call;
|
||
if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type
|
||
&& cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function))
|
||
{
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(cfc.obj);
|
||
exl.AddElement(cfc.parameters[0]);
|
||
basic_function_call bfc2 = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
bfc2.parameters.AddElement(param0);
|
||
expression_node _param1 = null;
|
||
if (parameters.expressions.Count == 2)
|
||
{
|
||
_param1 = convert_strong(parameters.expressions[1]);
|
||
}
|
||
if (_param1 != null)
|
||
bfc2.parameters.AddElement(convertion_data_and_alghoritms.convert_type(_param1,SystemLibrary.SystemLibrary.integer_type));
|
||
else
|
||
bfc2.parameters.AddElement(new int_const_node(1,null));
|
||
expressions_list el = new expressions_list();
|
||
el.AddElement(convertion_data_and_alghoritms.convert_type(bfc2,SystemLibrary.SystemLibrary.ushort_type));
|
||
function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc);
|
||
exl.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray()));
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc);
|
||
expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray());
|
||
return ret;
|
||
}
|
||
else
|
||
{
|
||
throw new ThisExpressionCanNotBePassedAsVarParameter(param0);
|
||
}
|
||
}
|
||
else throw new ThisExpressionCanNotBePassedAsVarParameter(param0);
|
||
}
|
||
else
|
||
check_on_loop_variable(param0);
|
||
expression_node param1 = null;
|
||
int type_flag = 0;
|
||
bool is_uint=false;
|
||
bool is_enum=false;
|
||
if (parameters.expressions.Count == 2)
|
||
{
|
||
param1 = convert_strong(parameters.expressions[1]);
|
||
param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type);
|
||
}
|
||
basic_function_call ass = null;
|
||
basic_function_call bfc = null;
|
||
if (param0.type == SystemLibrary.SystemLibrary.integer_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.char_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.char_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.byte_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.byte_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.sbyte_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.sbyte_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.short_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.short_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.ushort_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.ushort_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.uint_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.uint_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.uint_sub as basic_function_node,loc);
|
||
type_flag = 2;
|
||
is_uint = true;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.int64_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.long_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.long_sub as basic_function_node,loc);
|
||
type_flag = 1;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.uint64_type)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.ulong_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.ulong_sub as basic_function_node,loc);
|
||
type_flag = 2;
|
||
}
|
||
else if (param0.type == SystemLibrary.SystemLibrary.bool_type)
|
||
{
|
||
if (param1 == null)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc);
|
||
type_flag = 4;
|
||
}
|
||
else
|
||
{
|
||
basic_function_call mod_expr = new basic_function_call(SystemLibrary.SystemLibrary.int_mod as basic_function_node,loc);
|
||
mod_expr.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type));
|
||
mod_expr.parameters.AddElement(new int_const_node(2,loc));
|
||
basic_function_call condition = new basic_function_call(SystemLibrary.SystemLibrary.int_eq as basic_function_node,loc);
|
||
condition.parameters.AddElement(mod_expr);
|
||
condition.parameters.AddElement(new int_const_node(0,loc));
|
||
basic_function_call not_expr = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc);
|
||
not_expr.parameters.AddElement(param0);
|
||
question_colon_expression qce = new question_colon_expression(condition, param0, not_expr, loc);
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc);
|
||
ass.parameters.AddElement(param0);
|
||
ass.parameters.AddElement(qce);
|
||
type_flag = 5;
|
||
}
|
||
}
|
||
else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum)
|
||
{
|
||
ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc);
|
||
bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc);
|
||
if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
type_node bt = param0.type.base_type;
|
||
if (bt == SystemLibrary.SystemLibrary.int64_type) type_flag = 1;
|
||
else if (bt == SystemLibrary.SystemLibrary.uint64_type) type_flag = 2;
|
||
else if (bt == SystemLibrary.SystemLibrary.uint_type)
|
||
{
|
||
type_flag =2;
|
||
is_uint = true;
|
||
}
|
||
else if (bt.IsEnum) is_enum = true;
|
||
}
|
||
else if (param0.type.IsEnum) is_enum = true;
|
||
}
|
||
else throw new NoFunctionWithSameArguments(loc,false);
|
||
if (type_flag != 5)
|
||
{
|
||
if (param1 != null)
|
||
switch (type_flag)
|
||
{
|
||
case 0: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); break;
|
||
case 3:
|
||
case 1: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.int64_type); break;
|
||
case 2: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.uint64_type); break;
|
||
}
|
||
//bfc.parameters.AddElement(param0);
|
||
if (param0.type != SystemLibrary.SystemLibrary.char_type && !is_enum && param0.type != SystemLibrary.SystemLibrary.bool_type)
|
||
switch (type_flag)
|
||
{
|
||
case 0: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.integer_type)); break;
|
||
case 3:
|
||
case 1: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.int64_type)); break;
|
||
case 2: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.uint64_type)); break;
|
||
}
|
||
else bfc.parameters.AddElement(param0);
|
||
if (param1 == null)
|
||
{
|
||
if (type_flag == 0 || type_flag == 3)
|
||
bfc.parameters.AddElement(new int_const_node(1, null));
|
||
else if (type_flag == 1)
|
||
bfc.parameters.AddElement(new long_const_node(1, null));
|
||
else if (type_flag == 2)
|
||
bfc.parameters.AddElement(new ulong_const_node(1, null));
|
||
}
|
||
else bfc.parameters.AddElement(param1);
|
||
ass.parameters.AddElement(param0);
|
||
if (is_uint)
|
||
ass.parameters.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.uint_type));
|
||
else
|
||
ass.parameters.AddElement(bfc);
|
||
}
|
||
return ass;
|
||
}
|
||
|
||
throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node);
|
||
}
|
||
|
||
private void check_on_loop_variable(expression_node en)
|
||
{
|
||
if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable)
|
||
if (en.semantic_node_type == semantic_node_type.namespace_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((en as namespace_variable_reference).var))
|
||
AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
else if (en.semantic_node_type == semantic_node_type.local_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((en as local_variable_reference).var))
|
||
AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
else if (en.semantic_node_type == semantic_node_type.local_block_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((en as local_block_variable_reference).var))
|
||
AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
|
||
}
|
||
|
||
private expression_node make_read_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc)
|
||
{
|
||
|
||
// вызов read(a,b,c) разбивается на несколько вызовов, последний возвращается узлом, а остальные добавляются здесь в теле expressions_list exl = new expressions_list();
|
||
expression_node last_call = null;
|
||
expressions_list exl = new expressions_list();
|
||
expression_node file = null;
|
||
bool read_from_file = false;
|
||
bool read_from_text_file = false;
|
||
bool read_from_typed_file = false;
|
||
bool read_from_binary_file = false;
|
||
bool readln_string_file = false;
|
||
if (parameters != null) // если список параметров не пуст
|
||
{
|
||
if (parameters.expressions.Count >= 1)
|
||
{
|
||
expression_node param0 = convert_strong(parameters.expressions[0]);
|
||
if (param0.type != null)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.TextFileType.Found && param0.type == SystemLibrary.SystemLibInitializer.TextFileType.sym_info)
|
||
{
|
||
file = param0;
|
||
read_from_text_file = true;
|
||
}
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.typed_file
|
||
&& parameters.expressions.Count > 1 //это можно внести во внутрь
|
||
)//и побросать приличные исключения
|
||
{
|
||
if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll)
|
||
{
|
||
if (si == SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo)
|
||
{
|
||
file = param0;
|
||
read_from_typed_file = true;
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si))
|
||
{
|
||
file = param0;
|
||
read_from_typed_file = true;
|
||
}
|
||
}
|
||
if (param0.type.type_special_kind == SemanticTree.type_special_kind.binary_file
|
||
&& parameters.expressions.Count > 1 //это можно внести во внутрь
|
||
)//и побросать приличные исключения
|
||
{
|
||
if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll)
|
||
{
|
||
if (si == SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo)
|
||
{
|
||
file = param0;
|
||
read_from_binary_file = true;
|
||
}
|
||
}
|
||
else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si))
|
||
{
|
||
file = param0;
|
||
read_from_binary_file = true;
|
||
}
|
||
}
|
||
}
|
||
read_from_file = read_from_text_file || read_from_typed_file || read_from_binary_file;
|
||
}
|
||
bool first_iteration = true;
|
||
|
||
foreach (SyntaxTree.expression ex in parameters.expressions)
|
||
{
|
||
if (first_iteration && read_from_file)
|
||
{
|
||
first_iteration = false;
|
||
continue;
|
||
}
|
||
if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.size > 0)
|
||
convertion_data_and_alghoritms.statement_list_stack.top().statements.AddElement(last_call);
|
||
expression_node en = convert_strong(ex);
|
||
check_on_loop_variable(en);
|
||
//if (en.type == null)
|
||
//throw new CanNotRead(en.location);
|
||
exl.clear();
|
||
if (read_from_file)
|
||
exl.AddElement(file);
|
||
if (read_from_typed_file)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.TypedFileReadProcedure == null)
|
||
AddError(new NotSupportedError(loc));
|
||
if (en.type != file.type.element_type)
|
||
AddError(new ExpectedExprHaveTypeTypedFile(file.type.element_type, en.type, true, get_location(ex)));
|
||
bool is_char_getter = false;
|
||
if (!en.is_addressed)
|
||
{
|
||
if (en is compiled_function_call)
|
||
{
|
||
compiled_function_call cfc = en as compiled_function_call;
|
||
|
||
if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type
|
||
&& cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function))
|
||
{
|
||
en = new simple_array_indexing((en as compiled_function_call).obj, (en as compiled_function_call).parameters[0], SystemLibrary.SystemLibrary.char_type, en.location);
|
||
is_char_getter = true;
|
||
}
|
||
|
||
}
|
||
}
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc);
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), file);
|
||
//expression_node expr = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc, context.converted_type, context.top_function, true);
|
||
expr = convertion_data_and_alghoritms.explicit_convert_type(expr, file.type.element_type);
|
||
if (is_char_getter)
|
||
expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.sym_info as function_node, loc, (en as simple_array_indexing).simple_arr_expr, (en as simple_array_indexing).ind_expr, expr);
|
||
else
|
||
expr = find_operator(compiler_string_consts.assign_name, en, expr, loc);
|
||
last_call = expr;
|
||
}
|
||
else if (read_from_binary_file)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure == null)
|
||
AddError(new NotSupportedError(loc));
|
||
if (!CanUseThisTypeForBinaryFiles(en.type))
|
||
{
|
||
AddError(en.location, "CAN_NOT_READ_REFERENCE_DATA_FROM_BINARY_FILE");
|
||
}
|
||
exl.AddElement(new typeof_operator(en.type, loc));
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure.SymbolInfo, loc);
|
||
expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray());
|
||
expr = convertion_data_and_alghoritms.explicit_convert_type(expr, en.type);
|
||
expr = find_operator(compiler_string_consts.assign_name, en, expr, loc);
|
||
last_call = expr;
|
||
}
|
||
else
|
||
{
|
||
exl.AddElement(en);
|
||
try
|
||
{
|
||
function_node fn = null;
|
||
if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
exl.AddElement(new int_const_node((en.type as short_string_type_node).Length,null));
|
||
if (!read_from_file)
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_procedure.sym_info as function_node,get_location(ex),exl.ToArray());
|
||
else
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure.sym_info as function_node,get_location(ex),exl.ToArray());
|
||
}
|
||
else if (en.type.type_special_kind == SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
exl.remove(en);
|
||
en.type = en.type.base_type;
|
||
exl.AddElement(en);
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc);
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray());
|
||
}
|
||
else
|
||
{
|
||
/// SSM 21/05/16 - read_from_text_file && - bug fix #161
|
||
if (read_from_text_file && SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si) && parameters.expressions.Count == 2 && en.type == SystemLibrary.SystemLibrary.string_type)
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc);
|
||
readln_string_file = true;
|
||
}
|
||
else
|
||
fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc);
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray());
|
||
}
|
||
//last_call = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc, context.converted_type, context.top_function, true);
|
||
}
|
||
catch (NoFunctionWithSameArguments)
|
||
{
|
||
AddError(en.location, "CAN_NOT_READ");
|
||
}
|
||
}
|
||
first_iteration = false;
|
||
}
|
||
}
|
||
if ((parameters == null) || (parameters.expressions.Count == 0)) // read(), readln()
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si))
|
||
{
|
||
if (read_from_file)
|
||
exl.AddElement(file);
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl,
|
||
SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc);
|
||
if (read_from_file)
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file);
|
||
else
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc);
|
||
}
|
||
}
|
||
if (SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si)) // readln(...)
|
||
{
|
||
if (!readln_string_file)
|
||
{
|
||
if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.size > 0)
|
||
convertion_data_and_alghoritms.statement_list_stack.top().statements.AddElement(last_call);
|
||
exl.clear();
|
||
|
||
if (read_from_file)
|
||
exl.AddElement(file);
|
||
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl,
|
||
SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc);
|
||
if (read_from_file)
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file);
|
||
else
|
||
last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc);
|
||
}
|
||
}
|
||
return last_call;
|
||
}
|
||
|
||
internal expression_node GetCurrentObjectReference(SymbolTable.Scope scope, definition_node dn, location loc)
|
||
{
|
||
if (WithSection)
|
||
if (scope != null)
|
||
if (WithVariables.ContainsKey(scope))
|
||
return WithVariables[scope];
|
||
else
|
||
if (WithTypes.Contains(scope))
|
||
{
|
||
switch (dn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.class_field : if (!(dn as class_field).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field,loc,null)); break;
|
||
case semantic_node_type.compiled_variable_definition : if (!(dn as compiled_variable_definition).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field,loc,null)); break;
|
||
case semantic_node_type.compiled_property_node:
|
||
case semantic_node_type.common_property_node : if ((dn as property_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticPropertyWithType(dn as property_node,loc,null)); break;
|
||
case semantic_node_type.compiled_function_node:
|
||
case semantic_node_type.common_method_node: if ((dn as function_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticMethodWithType((dn as function_node).name,loc)); break;
|
||
}
|
||
}
|
||
if (context.inStaticArea())
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticFromStatic(dn,loc));
|
||
return null;
|
||
}
|
||
else
|
||
return new this_node(context.converted_type, loc);
|
||
}
|
||
bool WithSection = false;
|
||
Dictionary<SymbolTable.Scope, expression_node> WithVariables = new Dictionary<SymbolTable.Scope, expression_node>();
|
||
Stack<SymbolTable.Scope> WithTypes = new Stack<SymbolTable.Scope>();
|
||
|
||
private expression_node create_with_expression(expression_node expr)
|
||
{
|
||
location sl = expr.location;
|
||
switch (expr.semantic_node_type)
|
||
{
|
||
case semantic_node_type.common_namespace_function_call:
|
||
case semantic_node_type.common_in_function_function_call:
|
||
case semantic_node_type.common_method_call:
|
||
case semantic_node_type.common_static_method_call:
|
||
case semantic_node_type.compiled_function_call:
|
||
case semantic_node_type.compiled_constructor_call:
|
||
case semantic_node_type.common_constructor_call:
|
||
case semantic_node_type.compiled_static_method_call:
|
||
return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(compiler_string_consts.GetTempVariableName(), sl, expr.type, expr), sl);
|
||
case semantic_node_type.class_field_reference:
|
||
(expr as class_field_reference).obj = create_with_expression((expr as class_field_reference).obj);
|
||
return expr;
|
||
case semantic_node_type.compiled_variable_reference:
|
||
(expr as compiled_variable_reference).obj = create_with_expression((expr as compiled_variable_reference).obj);
|
||
return expr;
|
||
case semantic_node_type.simple_array_indexing:
|
||
simple_array_indexing sar = expr as simple_array_indexing;
|
||
sar.simple_arr_expr = create_with_expression(sar.simple_arr_expr);
|
||
sar.ind_expr = create_with_expression(sar.ind_expr);
|
||
return sar;
|
||
case semantic_node_type.deref_node:
|
||
(expr as dereference_node).deref_expr = create_with_expression((expr as dereference_node).deref_expr);
|
||
return expr;
|
||
case semantic_node_type.basic_function_call:
|
||
return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(compiler_string_consts.GetTempVariableName(), sl, expr.type, expr), sl);
|
||
case semantic_node_type.as_node:
|
||
return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(compiler_string_consts.GetTempVariableName(), sl, expr.type, expr), sl);
|
||
}
|
||
return expr;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.with_statement _with_statement)
|
||
{
|
||
WithSection = true;
|
||
List<SymbolTable.Scope> Withs = new List<SymbolTable.Scope>();
|
||
List<expression_node> VarRefs = new List<expression_node>();
|
||
List<SymbolTable.Scope> WithTypesList = new List<SymbolTable.Scope>();
|
||
statements_list stl = new statements_list(get_location(_with_statement.do_with), null, null);
|
||
SymbolTable.WithScope WithScope = new SymbolTable.WithScope(SymbolTable, context.CurrentScope, null);
|
||
convertion_data_and_alghoritms.statement_list_stack_push(stl, WithScope);
|
||
foreach (SyntaxTree.expression s_expr in _with_statement.do_with.expressions)
|
||
{
|
||
//expression_node expr = ret.visit(s_expr);
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.set_motivation_to_expect_semantic_node();
|
||
semantic_node sn = ret.visit(s_expr as SyntaxTree.syntax_tree_node);
|
||
motivation_keeper.reset();
|
||
expression_node expr = sn as expression_node;
|
||
if (expr is null_const_node)
|
||
AddError(expr.location, "NIL_IN_THIS_CONTEXT_NOT_ALLOWED");
|
||
if (expr is typed_expression) expr = convert_typed_expression_to_function_call(expr as typed_expression);
|
||
if (expr != null)
|
||
{
|
||
variable_reference vr = expr as variable_reference;
|
||
if (expr.type == null)
|
||
AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH");
|
||
if (expr.type is ref_type_node)
|
||
AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH");
|
||
if (vr == null)
|
||
{
|
||
location sl = get_location(s_expr);
|
||
if (expr.type.type_special_kind != SemanticTree.type_special_kind.record)
|
||
vr = convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(compiler_string_consts.GetTempVariableName(), sl, expr.type, expr), sl);
|
||
else
|
||
expr = create_with_expression(expr);
|
||
}
|
||
if (vr != null && vr is class_field_reference && vr.type.type_special_kind == SemanticTree.type_special_kind.record)
|
||
{
|
||
vr = null;
|
||
expr = create_with_expression(expr);
|
||
}
|
||
if (vr != null)
|
||
{
|
||
VarRefs.Add(vr);
|
||
if (vr.type.Scope == null)
|
||
{
|
||
if (vr.type is compiled_type_node)
|
||
(vr.type as compiled_type_node).scope = new NetHelper.NetTypeScope((vr.type as compiled_type_node).compiled_type, SystemLibrary.SystemLibrary.symtab);
|
||
else
|
||
throw new CompilerInternalError("Cannot create With statement because variable reference scope == null");
|
||
}
|
||
//если не нужны локальные перекрытия, здесь нужна проверка
|
||
Withs.Add(vr.type.Scope);
|
||
}
|
||
else
|
||
{
|
||
VarRefs.Add(expr);
|
||
Withs.Add(expr.type.Scope);
|
||
}
|
||
}
|
||
else if (sn is type_node)
|
||
{
|
||
type_node tn = sn as type_node;
|
||
Withs.Add(tn.Scope);
|
||
while (tn != null)
|
||
{
|
||
if (tn.Scope == null && tn is compiled_type_node)
|
||
{
|
||
(tn as compiled_type_node).init_scope();
|
||
}
|
||
WithTypesList.Add(tn.Scope);
|
||
tn = tn.base_type;
|
||
}
|
||
}
|
||
}
|
||
WithScope.WithScopes = Withs.ToArray();
|
||
|
||
Dictionary<SymbolTable.Scope, expression_node> OldWithVariables = new Dictionary<SymbolTable.Scope, expression_node>();
|
||
foreach (expression_node vr in VarRefs)
|
||
{
|
||
if (WithVariables.ContainsKey(vr.type.Scope))
|
||
{
|
||
//перекрытие области
|
||
if (OldWithVariables.ContainsKey(vr.type.Scope))
|
||
//Это локальные перекрытия
|
||
OldWithVariables[vr.type.Scope] = WithVariables[vr.type.Scope];
|
||
else
|
||
OldWithVariables.Add(vr.type.Scope, WithVariables[vr.type.Scope]);
|
||
WithVariables[vr.type.Scope] = vr;
|
||
}
|
||
else
|
||
{
|
||
//добавляем текущие with
|
||
WithVariables.Add(vr.type.Scope, vr);
|
||
|
||
}
|
||
//ivan dobavil dlja bazovyh klassov
|
||
type_node tn = vr.type.base_type;
|
||
while (tn != null)
|
||
{
|
||
if (tn.Scope == null && tn is compiled_type_node)
|
||
{
|
||
(tn as compiled_type_node).init_scope();
|
||
}
|
||
if (tn.Scope != null)
|
||
if (!WithVariables.ContainsKey(tn.Scope))
|
||
WithVariables.Add(tn.Scope, vr);
|
||
else
|
||
{
|
||
if (OldWithVariables.ContainsKey(tn.Scope))
|
||
//Это локальные перекрытия
|
||
OldWithVariables[tn.Scope] = WithVariables[tn.Scope];
|
||
else
|
||
OldWithVariables.Add(tn.Scope, WithVariables[tn.Scope]);
|
||
WithVariables[tn.Scope] = vr;
|
||
}
|
||
tn = tn.base_type;
|
||
}
|
||
}
|
||
|
||
//Ivan dobavil dlja tipov
|
||
|
||
foreach (SymbolTable.Scope sc in WithTypesList)
|
||
{
|
||
if (!WithTypes.Contains(sc))
|
||
WithTypes.Push(sc);
|
||
}
|
||
|
||
stl.statements.AddElement(ret.visit(_with_statement.what_do));
|
||
|
||
//восстанавливаем перекрытия
|
||
foreach (SymbolTable.Scope sc in OldWithVariables.Keys)
|
||
WithVariables[sc] = OldWithVariables[sc];
|
||
//удаляем текущие with
|
||
foreach (expression_node vr in VarRefs)
|
||
{
|
||
WithVariables.Remove(vr.type.Scope);
|
||
type_node tn = vr.type.base_type;
|
||
while (tn != null)
|
||
{
|
||
if (tn.Scope != null && WithVariables.ContainsKey(tn.Scope))
|
||
WithVariables.Remove(tn.Scope);
|
||
tn = tn.base_type;
|
||
}
|
||
}
|
||
foreach (SymbolTable.Scope sc in WithTypesList)
|
||
{
|
||
WithTypes.Pop();
|
||
}
|
||
|
||
WithSection = WithVariables.Count > 0;
|
||
|
||
convertion_data_and_alghoritms.statement_list_stack_pop();
|
||
return_value(stl);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.labeled_statement _labeled_statement)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_labeled_statement.label_name);
|
||
SymbolInfo si = context.CurrentScope.FindOnlyInScopeAndBlocks(_labeled_statement.label_name.name);
|
||
if (_labeled_statement.to_statement is SyntaxTree.var_statement || _labeled_statement.to_statement is SyntaxTree.assign_var_tuple)
|
||
{
|
||
AddError(get_location(_labeled_statement.label_name), "LABELED_DECLARATION_NOT_ALLOWED");
|
||
}
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(_labeled_statement.label_name.name, get_location(_labeled_statement.label_name)));
|
||
}
|
||
label_node lab = si.sym_info as label_node;
|
||
if (lab == null)
|
||
{
|
||
AddError(get_location(_labeled_statement.label_name), "IDENT_{0}_IS_NOT_LABEL", _labeled_statement.label_name.name);
|
||
}
|
||
// SSM - Patch повторного определения меток в подпрограммах при наличии лямбд
|
||
if (lambdaProcessingState != LambdaProcessingState.FinishPhase)
|
||
if (lab.is_defined)
|
||
{
|
||
AddError(get_location(_labeled_statement.label_name), "LABEL_{0}_REDEFINED", _labeled_statement.label_name.name);
|
||
}
|
||
lab.is_defined = true;
|
||
lab.comprehensive_code_block = context.block_stack.Peek();
|
||
foreach (goto_statement gs in lab.goto_statements)
|
||
{
|
||
if (!context.check_can_goto(lab.comprehensive_code_block, gs.comprehensive_code_block))
|
||
{
|
||
//AddError(gs.location, "BLOCKED_LABEL_{0}_GOTO", lab.name);
|
||
}
|
||
}
|
||
convertion_data_and_alghoritms.check_node_parser_error(_labeled_statement.to_statement);
|
||
statement_node snode = ret.visit((SyntaxTree.statement)_labeled_statement.to_statement);
|
||
labeled_statement las = new labeled_statement(lab, snode, get_location(_labeled_statement));
|
||
ret.return_value((statement_node)las);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.goto_statement _goto_statement)
|
||
{
|
||
SymbolInfo si = context.CurrentScope.FindOnlyInScopeAndBlocks(_goto_statement.label.name);
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(_goto_statement.label.name, get_location(_goto_statement.label)));
|
||
}
|
||
label_node lab = si.sym_info as label_node;
|
||
if (lab == null)
|
||
{
|
||
AddError(get_location(_goto_statement.label), "IDENT_{0}_IS_NOT_LABEL", _goto_statement.label.name);
|
||
}
|
||
//if (lab.goto_blocked)
|
||
//{
|
||
// throw new BlockedLabelGoto(_goto_statement.label.name, get_location(_goto_statement.label));
|
||
//}
|
||
goto_statement gs = new goto_statement(lab, get_location(_goto_statement));
|
||
gs.comprehensive_code_block = context.block_stack.Peek();
|
||
lab.goto_statements.Add(gs);
|
||
if (lab.comprehensive_code_block != null)
|
||
{
|
||
if (!context.check_can_goto(lab.comprehensive_code_block, gs.comprehensive_code_block))
|
||
{
|
||
//AddError(gs.location, "BLOCKED_LABEL_{0}_GOTO", lab.name);
|
||
}
|
||
}
|
||
ret.return_value((statement_node)gs);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.empty_statement _empty_statement)
|
||
{
|
||
return_value(new empty_statement(get_location(_empty_statement)));
|
||
}
|
||
|
||
private addressed_expression create_class_static_field_reference(type_node tn, definition_node dn,
|
||
SyntaxTree.ident id_right)
|
||
{
|
||
switch (dn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.class_field:
|
||
{
|
||
class_field cf = (class_field)dn;
|
||
if (cf.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticFieldWithType(cf, get_location(id_right), tn));
|
||
}
|
||
static_class_field_reference scfr = new static_class_field_reference(cf, get_location(id_right));
|
||
return scfr;
|
||
}
|
||
case semantic_node_type.compiled_variable_definition:
|
||
{
|
||
compiled_variable_definition cvd = (compiled_variable_definition)dn;
|
||
if (cvd.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticFieldWithType(cvd, get_location(id_right), tn));
|
||
}
|
||
static_compiled_variable_reference scvr = new static_compiled_variable_reference(cvd, get_location(id_right));
|
||
return scvr;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Error in create static class field reference.");
|
||
}
|
||
|
||
private addressed_expression create_addressed_with_type_expression(type_node tn, SyntaxTree.ident id_right,
|
||
SymbolInfo si_right)
|
||
{
|
||
definition_node dn = null;
|
||
if (!internal_is_assign)
|
||
dn = context.check_name_node_type(id_right.name, si_right, get_location(id_right),
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node);
|
||
else
|
||
dn = context.check_name_node_type(id_right.name, si_right, get_location(id_right),
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node,general_node_type.constant_definition);
|
||
if (dn.general_node_type == general_node_type.constant_definition)
|
||
AddError(get_location(id_right), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT");
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.variable_node:
|
||
{
|
||
return create_class_static_field_reference(tn, dn, id_right);
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticPropertyWithType(pn, get_location(id_right), tn));
|
||
}
|
||
static_property_reference pr = new static_property_reference(pn, get_location(id_right));
|
||
return pr;
|
||
}
|
||
case general_node_type.event_node:
|
||
{
|
||
if (dn.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
compiled_event ce = (compiled_event)dn;
|
||
if (!ce.is_static)
|
||
{
|
||
//throw new NonStaticAndStaticEvevnt();
|
||
}
|
||
static_event_reference ser = new static_event_reference(ce, get_location(id_right));
|
||
return ser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
common_event ce = (common_event)dn;
|
||
if (!ce.is_static)
|
||
{
|
||
//throw new NonStaticAndStaticEvevnt();
|
||
}
|
||
static_event_reference ser = new static_event_reference(ce, get_location(id_right));
|
||
return ser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_namespace_event)
|
||
{
|
||
common_namespace_event cne = dn as common_namespace_event;
|
||
static_event_reference ser = new static_event_reference(cne, get_location(id_right));
|
||
return ser;
|
||
}
|
||
break;
|
||
}
|
||
default : return null;
|
||
}
|
||
throw new CompilerInternalError("Invalid right type expression");
|
||
}
|
||
|
||
private expressions_list convert_expression_list(List<SyntaxTree.expression> expr_list)
|
||
{
|
||
expressions_list exprs = new expressions_list();
|
||
foreach (SyntaxTree.expression en in expr_list)
|
||
exprs.AddElement(convert_strong(en));
|
||
return exprs;
|
||
}
|
||
|
||
|
||
private base_function_call create_static_method_call_with_params(function_node fn, location loc, type_node tn, bool procedure_allowed, expressions_list parametrs)
|
||
{
|
||
base_function_call bfc = create_static_method_call(fn, loc, tn, procedure_allowed);
|
||
bfc.parameters.AddRange(parametrs);
|
||
return bfc;
|
||
}
|
||
private base_function_call create_static_method_call(function_node fn, location loc, type_node tn, bool procedure_allowed)
|
||
{
|
||
if ((!procedure_allowed) && (fn.return_value_type == null))
|
||
{
|
||
AddError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", fn.name);
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.common_method_node)
|
||
{
|
||
common_method_node cmn = (common_method_node)fn;
|
||
if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
//ssyy изменил
|
||
if (!cmn.is_constructor)
|
||
{
|
||
AddError(new CanNotCallNonStaticMethodWithClass(tn, loc, fn));
|
||
}
|
||
if (cmn.cont_type.IsAbstract)
|
||
ErrorsList.Add(new SimpleSemanticError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.name));
|
||
common_constructor_call csmc2 = new common_constructor_call(cmn, loc);
|
||
return csmc2;
|
||
//if (cmn.pascal_associated_constructor==null)
|
||
//{
|
||
// throw new CanNotCallNonStaticMethodWithClass(tn,loc,fn);
|
||
//}
|
||
//common_constructor_call csmc2=new common_constructor_call(cmn.pascal_associated_constructor,loc);
|
||
//return csmc2;
|
||
//\ssyy
|
||
}
|
||
common_static_method_call csmc = new common_static_method_call(cmn, loc);
|
||
return csmc;
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.compiled_function_node)
|
||
{
|
||
compiled_function_node cfn = (compiled_function_node)fn;
|
||
if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotCallNonStaticMethodWithClass(tn, loc, fn));
|
||
}
|
||
compiled_static_method_call csmc2 = new compiled_static_method_call(cfn, loc);
|
||
return csmc2;
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.compiled_constructor_node)
|
||
{
|
||
compiled_constructor_node ccn = (compiled_constructor_node)fn;
|
||
compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc);
|
||
return ccc;
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.basic_function_node)
|
||
{
|
||
return new basic_function_call(fn as basic_function_node, loc);
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null)
|
||
{
|
||
return new common_namespace_function_call(fn as common_namespace_function_node,loc);
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||
{
|
||
return new indefinite_function_call(fn, loc);
|
||
}
|
||
throw new CompilerInternalError("Invalid method kind");
|
||
}
|
||
|
||
private expression_node create_static_expression(type_node tn, SyntaxTree.ident id_right,
|
||
SymbolInfo si_right)
|
||
{
|
||
definition_node dn = context.check_name_node_type(id_right.name, si_right, get_location(id_right), general_node_type.variable_node,
|
||
general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition);
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.variable_node:
|
||
{
|
||
return create_class_static_field_reference(tn, dn, id_right);
|
||
}
|
||
case general_node_type.constant_definition:
|
||
{
|
||
constant_definition_node cdn = (constant_definition_node)dn;
|
||
return cdn.const_value.get_constant_copy(get_location(id_right));
|
||
}
|
||
case general_node_type.function_node:
|
||
{
|
||
if (dn is compiled_function_node)
|
||
{
|
||
if ((dn as compiled_function_node).ConnectedToType == tn)
|
||
{
|
||
if (si_right.Next != null)
|
||
return create_static_expression(tn, id_right, si_right.Next);
|
||
else
|
||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||
}
|
||
}
|
||
else if (dn is common_namespace_function_node)
|
||
{
|
||
if ((dn as common_namespace_function_node).ConnectedToType == tn)
|
||
{
|
||
if (si_right.Next != null)
|
||
return create_static_expression(tn, id_right, si_right.Next);
|
||
else
|
||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||
}
|
||
}
|
||
if (dn.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||
{
|
||
return new indefinite_reference(dn as indefinite_definition_node, get_location(id_right));
|
||
}
|
||
return make_delegate_wrapper(null, si_right, get_location(id_right), true);
|
||
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticPropertyWithType(pn, get_location(id_right), tn));
|
||
}
|
||
function_node fn = pn.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(pn, get_location(id_right)));
|
||
}
|
||
location lloc = get_location(id_right);
|
||
check_property_no_params(pn, lloc);
|
||
return create_static_method_call(fn, lloc, tn, false);
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Error in creating static expression.");
|
||
}
|
||
|
||
private void dot_node_as_type_ident(type_node tn, SyntaxTree.ident id_right, motivation mot)
|
||
{
|
||
SymbolInfo si_right = tn.find_in_type(id_right.name, context.CurrentScope);
|
||
if (si_right == null)
|
||
{
|
||
AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), tn));
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(create_addressed_with_type_expression(tn, id_right, si_right));
|
||
return;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(create_static_expression(tn, id_right, si_right));
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
if (si_right.sym_info.general_node_type == general_node_type.type_node)
|
||
return_semantic_value(si_right.sym_info as type_node);
|
||
else
|
||
return_semantic_value(create_static_expression(tn, id_right, si_right));
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid motivation");
|
||
}
|
||
|
||
private void dot_node_as_namespace_ident(namespace_node nn, SyntaxTree.ident id_right, motivation mot)
|
||
{
|
||
SymbolInfo si_right = nn.find(id_right.name);
|
||
if (si_right == null)
|
||
{
|
||
AddError(new MemberIsNotDeclaredInNamespace(id_right, get_location(id_right), nn));
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(ident_address_reciving(si_right, id_right));
|
||
return;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(ident_value_reciving(si_right, id_right));
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(ident_semantic_reciving(si_right, id_right));
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Unsupported motivation");
|
||
}
|
||
|
||
private void dot_node_as_unit_ident(common_unit_node cun, SyntaxTree.ident id_right, motivation mot)
|
||
{
|
||
dot_node_as_namespace_ident(cun.namespaces[0], id_right, mot);
|
||
}
|
||
|
||
private void dot_node_as_ident_dot_template_ident(SyntaxTree.ident id_left, SyntaxTree.ident_with_templateparams template_id_right,
|
||
motivation mot)
|
||
{
|
||
SymbolInfo si_left = context.find(id_left.name);
|
||
SyntaxTree.ident id_right = template_id_right.name as SyntaxTree.ident;
|
||
if (si_left == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id_left.name, get_location(id_left)));
|
||
}
|
||
definition_node dn = context.check_name_node_type(id_left.name, si_left, get_location(id_left),
|
||
general_node_type.constant_definition, general_node_type.function_node,
|
||
general_node_type.namespace_node, general_node_type.property_node,
|
||
general_node_type.type_node, general_node_type.variable_node,
|
||
general_node_type.unit_node);
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.constant_definition:
|
||
case general_node_type.function_node:
|
||
case general_node_type.property_node:
|
||
case general_node_type.variable_node:
|
||
{
|
||
expression_node ex_nd = ident_value_reciving(si_left, id_left);
|
||
dot_node_as_expression_dot_template_ident(ex_nd, template_id_right, mot, id_left);
|
||
return;
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
//throw new CompilerInternalError("Unsupported now.");
|
||
namespace_node nn = dn as namespace_node;
|
||
dot_node_as_namespace_ident(nn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = dn as type_node;
|
||
dot_node_as_type_ident(tn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
//throw new NotSupportedError(get_location(id_left));
|
||
dot_node_as_unit_ident((common_unit_node)dn, id_right, mot);
|
||
return;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
private void dot_node_as_ident_dot_ident(SyntaxTree.ident id_left, SyntaxTree.ident id_right,
|
||
motivation mot)
|
||
{
|
||
SymbolInfo si_left = context.find(id_left.name);
|
||
if (si_left == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id_left.name, get_location(id_left)));
|
||
}
|
||
definition_node dn = context.check_name_node_type(id_left.name, si_left, get_location(id_left),
|
||
general_node_type.constant_definition, general_node_type.function_node,
|
||
general_node_type.namespace_node, general_node_type.property_node,
|
||
general_node_type.type_node, general_node_type.variable_node,
|
||
general_node_type.unit_node);
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.constant_definition:
|
||
case general_node_type.function_node:
|
||
case general_node_type.property_node:
|
||
case general_node_type.variable_node:
|
||
{
|
||
expression_node ex_nd = ident_value_reciving(si_left, id_left);
|
||
dot_node_as_expression_dot_ident(ex_nd, id_right, mot, id_left);
|
||
return;
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
//throw new CompilerInternalError("Unsupported now.");
|
||
namespace_node nn = dn as namespace_node;
|
||
dot_node_as_namespace_ident(nn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = dn as type_node;
|
||
dot_node_as_type_ident(tn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
//throw new NotSupportedError(get_location(id_left));
|
||
dot_node_as_unit_ident((common_unit_node)dn, id_right, mot);
|
||
return;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
private expression_node convert_if_typed_expression_to_function_call(expression_node expr)
|
||
{
|
||
if (expr is typed_expression)
|
||
return convert_typed_expression_to_function_call(expr as typed_expression);
|
||
return expr;
|
||
}
|
||
|
||
internal expression_node convert_typed_expression_to_function_call(typed_expression te)
|
||
{
|
||
delegated_methods dm = te.type as delegated_methods;
|
||
if (dm == null)
|
||
{
|
||
return te;
|
||
}
|
||
base_function_call bfc = dm.empty_param_method;
|
||
if (bfc == null)
|
||
{
|
||
return te;
|
||
}
|
||
if (bfc.type == null)
|
||
return te;
|
||
function_node fn = bfc.simple_function_node;
|
||
common_namespace_function_node cnfn = fn as common_namespace_function_node;
|
||
if ((fn.parameters.Count == 1 || cnfn != null && fn.parameters.Count == 2 && cnfn.ConnectedToType != null)
|
||
&& (fn.parameters[fn.parameters.Count - 1].is_params || fn.parameters[fn.parameters.Count - 1].default_value != null)
|
||
|| fn.parameters.Count > 0 && fn.num_of_default_parameters == fn.parameters.Count)
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(bfc.parameters, new SymbolInfo(fn), bfc.location);
|
||
if (fn.polymorphic_state == SemanticTree.polymorphic_state.ps_static || fn is common_namespace_function_node || fn is basic_function_node)
|
||
bfc = convertion_data_and_alghoritms.create_simple_function_call(fn, bfc.location, bfc.parameters.ToArray()) as base_function_call;
|
||
else
|
||
{
|
||
expression_node obj = null;
|
||
if (bfc is common_method_call)
|
||
obj = (bfc as common_method_call).obj;
|
||
else if (bfc is compiled_function_call)
|
||
obj = (bfc as compiled_function_call).obj;
|
||
bfc = convertion_data_and_alghoritms.create_method_call(fn, bfc.location, obj, bfc.parameters.ToArray()) as base_function_call;
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
function_node[] empty_param_methods = dm.empty_param_methods;
|
||
SymbolInfo si = new SymbolInfo(empty_param_methods[0]);
|
||
SymbolInfo root_si = si;
|
||
for (int i = 1; i < empty_param_methods.Length; i++)
|
||
{
|
||
si.Next = new SymbolInfo(empty_param_methods[i]);
|
||
si = si.Next;
|
||
}
|
||
compiled_function_node cfn = fn as compiled_function_node;
|
||
if ((fn.parameters.Count == 1 || cfn != null && fn.parameters.Count == 2 && cfn.ConnectedToType != null)
|
||
&& (fn.parameters[fn.parameters.Count - 1].is_params || fn.parameters[fn.parameters.Count - 1].default_value != null))
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(bfc.parameters, root_si, bfc.location);
|
||
bfc = create_static_method_call_with_params(fn, bfc.location, fn.return_value_type, true, bfc.parameters);
|
||
}
|
||
else if (fn.parameters.Count == 1 && cfn != null && cfn.ConnectedToType != null)
|
||
{
|
||
fn = convertion_data_and_alghoritms.select_function(bfc.parameters, root_si, bfc.location);
|
||
bfc = create_static_method_call_with_params(fn, bfc.location, fn.return_value_type, true, bfc.parameters);
|
||
}
|
||
}
|
||
return bfc;
|
||
}
|
||
|
||
private void try_convert_typed_expression_to_function_call(ref expression_node en)
|
||
{
|
||
if (en.semantic_node_type == semantic_node_type.typed_expression)
|
||
{
|
||
en = convert_typed_expression_to_function_call((typed_expression)en);
|
||
}
|
||
}
|
||
|
||
private addressed_expression create_class_field_reference(expression_node en, definition_node dn, SyntaxTree.ident id_right)
|
||
{
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
if (dn.semantic_node_type == semantic_node_type.class_field)
|
||
{
|
||
class_field cf = (class_field)dn;
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferanceToStaticFieldWithExpression(cf, get_location(id_right), en));
|
||
}
|
||
class_field_reference cfr = new class_field_reference(cf, en, get_location(id_right));
|
||
//return_value(cfr);
|
||
return cfr;
|
||
}
|
||
if (dn.semantic_node_type == semantic_node_type.compiled_variable_definition)
|
||
{
|
||
compiled_variable_definition cfd = (compiled_variable_definition)dn;
|
||
if (cfd.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferanceToStaticFieldWithExpression(cfd, get_location(id_right), en));
|
||
}
|
||
compiled_variable_reference cfr2 = new compiled_variable_reference(cfd, en, get_location(id_right));
|
||
//return_value(cfr2);
|
||
return cfr2;
|
||
}
|
||
#if (DEBUG)
|
||
throw new CompilerInternalError("Invalid variable kind");
|
||
#endif
|
||
return null;
|
||
}
|
||
|
||
private base_function_call create_not_static_method_call(function_node fn, expression_node en, location loc, bool procedure_allowed)
|
||
{
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
if ((!procedure_allowed) && (fn.return_value_type == null))
|
||
{
|
||
AddError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", fn.name);
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.common_method_node)
|
||
{
|
||
common_method_node cmn = (common_method_node)fn;
|
||
if (cmn.is_constructor)
|
||
{
|
||
AddError(loc, "CAN_NOT_CALL_CONSTRUCTOR_AS_PROCEDURE");
|
||
}
|
||
if (cmn.original_function != null && cmn.original_function is compiled_function_node && (cmn.original_function as compiled_function_node).ConnectedToType != null)
|
||
{
|
||
common_static_method_call csmc = new common_static_method_call(cmn, loc);
|
||
return csmc;
|
||
}
|
||
if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotCallStaticMethodWithExpression(en, fn));
|
||
}
|
||
|
||
common_method_call cmc = new common_method_call(cmn, en, loc);
|
||
cmc.virtual_call = !inherited_ident_processing;
|
||
return cmc;
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.compiled_function_node)
|
||
{
|
||
compiled_function_node cfn = (compiled_function_node)fn;
|
||
if (cfn.ConnectedToType != null)
|
||
{
|
||
compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc);
|
||
return csmc;
|
||
}
|
||
else
|
||
{
|
||
if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
if (!cfn.is_extension_method)
|
||
AddError(new CanNotCallStaticMethodWithExpression(en, fn));
|
||
else
|
||
return new compiled_static_method_call(cfn, loc);
|
||
}
|
||
compiled_function_call cfc = new compiled_function_call(cfn, en, loc);
|
||
cfc.virtual_call = !inherited_ident_processing;
|
||
return cfc;
|
||
}
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.compiled_constructor_node)
|
||
{
|
||
AddError(loc, "CAN_NOT_CALL_CONSTRUCTOR_AS_PROCEDURE");
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node,loc);
|
||
//cnfc.parameters.AddElement(en);
|
||
return cnfc;
|
||
}
|
||
if (fn.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||
{
|
||
indefinite_function_call ifc = new indefinite_function_call(fn, loc);
|
||
return ifc;
|
||
}
|
||
throw new CompilerInternalError("Invalid method kind");
|
||
}
|
||
|
||
private expression_node expression_value_reciving(SyntaxTree.ident id_right, SymbolInfo si, expression_node en, bool expected_delegate)
|
||
{
|
||
definition_node dn = context.check_name_node_type(id_right.name, si, get_location(id_right), general_node_type.variable_node,
|
||
general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition);
|
||
switch (dn.general_node_type)
|
||
{
|
||
/*case general_node_type.constant_defenition:
|
||
{
|
||
constant_definition_node cdn=(constant_definition_node)dn;
|
||
return cdn.const_value;
|
||
}*/
|
||
case general_node_type.variable_node:
|
||
{
|
||
return create_class_field_reference(en, dn, id_right);
|
||
}
|
||
case general_node_type.function_node:
|
||
{
|
||
if (dn.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||
{
|
||
return new indefinite_reference(dn as indefinite_definition_node, get_location(id_right));
|
||
}
|
||
if (expected_delegate && en != null)
|
||
{
|
||
SymbolInfo tmp_si = si;
|
||
function_node tmp_fn = null;
|
||
bool has_empty_methods = false;
|
||
bool only_extension_methods = true;
|
||
while (tmp_si != null)
|
||
{
|
||
tmp_fn = tmp_si.sym_info as function_node;
|
||
if (tmp_fn != null)
|
||
{
|
||
if (!tmp_fn.is_extension_method)
|
||
only_extension_methods = false;
|
||
else
|
||
{
|
||
if (tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null))
|
||
has_empty_methods = true;
|
||
}
|
||
}
|
||
tmp_si = tmp_si.Next;
|
||
}
|
||
if (has_empty_methods && only_extension_methods)
|
||
expected_delegate = false;
|
||
}
|
||
if (expected_delegate)
|
||
return make_delegate_wrapper(en, si, get_location(id_right), false);
|
||
else
|
||
{
|
||
function_node tmp_fn = null;
|
||
SymbolInfo tmp_si = si;
|
||
expressions_list pars = new expressions_list();
|
||
if (en != null)
|
||
while (tmp_si != null)
|
||
{
|
||
tmp_fn = tmp_si.sym_info as function_node;
|
||
if (tmp_fn != null && tmp_fn.is_extension_method &&
|
||
(tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null)))
|
||
{
|
||
pars.AddElement(en);
|
||
break;
|
||
}
|
||
tmp_si = tmp_si.Next;
|
||
}
|
||
function_node fn = convertion_data_and_alghoritms.select_function(pars, si, get_location(id_right));
|
||
if (!fn.is_extension_method)
|
||
return create_not_static_method_call(fn, en, get_location(id_right), false);
|
||
else
|
||
return create_static_method_call_with_params(fn, get_location(id_right), fn.return_value_type, false, pars);
|
||
}
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(id_right), pn.comprehensive_type));
|
||
}
|
||
function_node fn = pn.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(pn, get_location(id_right)));
|
||
}
|
||
location lloc = get_location(id_right);
|
||
check_property_no_params(pn, lloc);
|
||
return create_not_static_method_call(fn, en, lloc, false);
|
||
}
|
||
case general_node_type.constant_definition:
|
||
{
|
||
//throw new ConstMemberCannotBeAccessedWithAnInstanceReference((class_constant_definition)dn, get_location(id_right));
|
||
return ((constant_definition_node)dn).const_value;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid class member");
|
||
}
|
||
|
||
private addressed_expression address_expression_reciving(SyntaxTree.ident id_right, SymbolInfo si,
|
||
expression_node en)
|
||
{
|
||
if (si != null && si.sym_info != null &&
|
||
si.sym_info.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||
{
|
||
return new indefinite_reference(si.sym_info as indefinite_definition_node, get_location(id_right));
|
||
}
|
||
definition_node dn = null;
|
||
if (!internal_is_assign)
|
||
dn = context.check_name_node_type(id_right.name, si, get_location(id_right),
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node);
|
||
else
|
||
dn = context.check_name_node_type(id_right.name, si, get_location(id_right),
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node, general_node_type.constant_definition);
|
||
if (dn.general_node_type == general_node_type.constant_definition)
|
||
{
|
||
AddError(get_location(id_right), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT");
|
||
}
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.variable_node:
|
||
{
|
||
return create_class_field_reference(en, dn, id_right);
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(id_right), pn.comprehensive_type));
|
||
}
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
non_static_property_reference pr = new non_static_property_reference(pn, en, get_location(id_right));
|
||
return pr;
|
||
}
|
||
case general_node_type.event_node:
|
||
{
|
||
if (dn.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
compiled_event ce = (compiled_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
//throw new NonStaticAndStaticEvevnt();
|
||
}
|
||
nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right));
|
||
return ser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
common_event ce = (common_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
//throw new NonStaticAndStaticEvevnt();
|
||
}
|
||
nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right));
|
||
return ser;
|
||
}
|
||
break;
|
||
}
|
||
default : return null;
|
||
}
|
||
throw new CompilerInternalError("Undefined expression to address reciving");
|
||
}
|
||
|
||
private bool has_property(ref SymbolInfo si)
|
||
{
|
||
SymbolInfo tmp = si;
|
||
while (tmp != null)
|
||
{
|
||
if (tmp.sym_info is compiled_property_node || tmp.sym_info is common_property_node)
|
||
{
|
||
si = tmp;
|
||
return true;
|
||
}
|
||
tmp = tmp.Next;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private void dot_node_as_expression_dot_template_ident(expression_node en, SyntaxTree.ident_with_templateparams template_id_right, motivation mot, addressed_value syntax_node)
|
||
{
|
||
SyntaxTree.ident id_right = template_id_right.name as ident;
|
||
if (en is typed_expression)
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
SymbolInfo si = en.type.find_in_type(id_right.name, context.CurrentScope);
|
||
if (si == null)
|
||
{
|
||
AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), en.type));
|
||
}
|
||
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(address_expression_reciving(id_right, si, en));
|
||
return;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
//en = expression_value_reciving(id_right, si, en, true);
|
||
//try_convert_typed_expression_to_function_call(ref en);
|
||
//return_value(en);
|
||
if (si.sym_info is function_node && (si.sym_info as function_node).is_extension_method && !has_property(ref si)
|
||
|| si.sym_info is common_method_node && (si.sym_info as common_method_node).is_constructor
|
||
|| si.sym_info is compiled_constructor_node)
|
||
{
|
||
//dot_node dnode = new dot_node(syntax_node, template_id_right);
|
||
template_id_right.name = new dot_node(syntax_node, id_right);
|
||
method_call mc = new method_call(template_id_right, new expression_list());
|
||
mc.visit(this);
|
||
return;
|
||
}
|
||
return_value(expression_value_reciving(id_right, si, en, true));
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
if (si.sym_info is function_node && (si.sym_info as function_node).is_extension_method)
|
||
has_property(ref si);
|
||
return_semantic_value(expression_value_reciving(id_right, si, en, true));
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid motivation.");
|
||
}
|
||
|
||
private void dot_node_as_expression_dot_ident(expression_node en, SyntaxTree.ident id_right, motivation mot, addressed_value syntax_node)
|
||
{
|
||
if (en is typed_expression)
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
SymbolInfo si = en.type.find_in_type(id_right.name, context.CurrentScope);
|
||
if (si == null)
|
||
{
|
||
AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), en.type));
|
||
}
|
||
|
||
try_convert_typed_expression_to_function_call(ref en);
|
||
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(address_expression_reciving(id_right, si, en));
|
||
return;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
//en = expression_value_reciving(id_right, si, en, true);
|
||
//try_convert_typed_expression_to_function_call(ref en);
|
||
//return_value(en);
|
||
if (si.sym_info is function_node && (si.sym_info as function_node).is_extension_method && !has_property(ref si)
|
||
|| si.sym_info is common_method_node && (si.sym_info as common_method_node).is_constructor
|
||
|| si.sym_info is compiled_constructor_node)
|
||
{
|
||
dot_node dnode = new dot_node(syntax_node, id_right);
|
||
method_call mc = new method_call(dnode, new expression_list());
|
||
mc.visit(this);
|
||
return;
|
||
}
|
||
return_value(expression_value_reciving(id_right, si, en, true));
|
||
return;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
if (si.sym_info is function_node && (si.sym_info as function_node).is_extension_method)
|
||
has_property(ref si);
|
||
return_semantic_value(expression_value_reciving(id_right, si, en, true));
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid motivation.");
|
||
}
|
||
|
||
private void dot_node_as_dot_node_dot_ident(SyntaxTree.dot_node left_dot, SyntaxTree.ident id_right,
|
||
motivation mot)
|
||
{
|
||
semantic_node sn = convert_semantic_strong(left_dot);
|
||
switch (sn.general_node_type)
|
||
{
|
||
case general_node_type.expression:
|
||
{
|
||
expression_node en = (expression_node)sn;
|
||
dot_node_as_expression_dot_ident(en, id_right, mot, left_dot);
|
||
return;
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
namespace_node nn = (namespace_node)sn;
|
||
dot_node_as_namespace_ident(nn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = (type_node)sn;
|
||
dot_node_as_type_ident(tn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
throw new CompilerInternalError("Not supported");
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid left dot node kind");
|
||
}
|
||
|
||
private void dot_node_as_dot_node_dot_template_ident(SyntaxTree.dot_node left_dot, SyntaxTree.ident_with_templateparams template_id_right,
|
||
motivation mot)
|
||
{
|
||
semantic_node sn = convert_semantic_strong(left_dot);
|
||
ident id_right = template_id_right.name as ident;
|
||
switch (sn.general_node_type)
|
||
{
|
||
case general_node_type.expression:
|
||
{
|
||
expression_node en = (expression_node)sn;
|
||
dot_node_as_expression_dot_template_ident(en, template_id_right, mot, left_dot);
|
||
return;
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
namespace_node nn = (namespace_node)sn;
|
||
dot_node_as_namespace_ident(nn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = (type_node)sn;
|
||
dot_node_as_type_ident(tn, id_right, mot);
|
||
return;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
throw new CompilerInternalError("Not supported");
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid left dot node kind");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.dot_node _dot_node)
|
||
{
|
||
var mot = motivation_keeper.motivation;
|
||
|
||
SyntaxTree.ident id_left = _dot_node.left as SyntaxTree.ident;
|
||
SyntaxTree.ident id_right = _dot_node.right as SyntaxTree.ident;
|
||
if (_dot_node.right is ident_with_templateparams)
|
||
id_right = (_dot_node.right as ident_with_templateparams).name as ident;
|
||
|
||
// SSM 18.08.16 - пробуем обработать захват enn.ii в yieldах где enn - поле класса и нуждается в переименовании
|
||
// Так же ниже делает lroman
|
||
if (_dot_node.left is yield_unknown_ident)
|
||
{
|
||
var yui = (yield_unknown_ident)_dot_node.left;
|
||
var av = ProcessUnknownIdent(yui);
|
||
var dn = new dot_node(av, _dot_node.right,yui.source_context);
|
||
visit(dn);
|
||
return;
|
||
}
|
||
|
||
//lroman
|
||
if (_dot_node.left is closure_substituting_node)
|
||
{
|
||
var left = (closure_substituting_node)_dot_node.left;
|
||
var dotNodeToVisit = new dot_node(left.substitution, _dot_node.right);
|
||
visit(dotNodeToVisit);
|
||
return;
|
||
}
|
||
motivation_keeper.reset(); // SSM перенес сюда сверху - bug fix #263
|
||
|
||
if (id_left != null)
|
||
{
|
||
if (_dot_node.right is ident_with_templateparams)
|
||
{
|
||
dot_node_as_ident_dot_template_ident(id_left, _dot_node.right as ident_with_templateparams, mot);
|
||
return;
|
||
}
|
||
dot_node_as_ident_dot_ident(id_left, id_right, mot);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.ident_with_templateparams iwt = _dot_node.left as SyntaxTree.ident_with_templateparams;
|
||
if (iwt != null)
|
||
{
|
||
type_node tn = ret.visit((SyntaxTree.syntax_tree_node)iwt) as type_node;
|
||
dot_node_as_type_ident(tn, id_right, mot);
|
||
return;
|
||
}
|
||
SyntaxTree.dot_node left_dot = _dot_node.left as SyntaxTree.dot_node;
|
||
if (left_dot != null)
|
||
{
|
||
if (_dot_node.right is ident_with_templateparams)
|
||
{
|
||
dot_node_as_dot_node_dot_template_ident(left_dot, _dot_node.right as ident_with_templateparams, mot);
|
||
return;
|
||
}
|
||
dot_node_as_dot_node_dot_ident(left_dot, id_right, mot);
|
||
return;
|
||
}
|
||
expression_node en = convert_strong(_dot_node.left);
|
||
if (_dot_node.right is ident_with_templateparams)
|
||
{
|
||
dot_node_as_expression_dot_template_ident(en, _dot_node.right as ident_with_templateparams, mot, _dot_node.left);
|
||
return;
|
||
}
|
||
dot_node_as_expression_dot_ident(en, id_right, mot, _dot_node.left);
|
||
return;
|
||
}
|
||
}
|
||
|
||
private SyntaxTree.ident ConvertOperatorNameToIdent(SyntaxTree.ident opname)
|
||
{
|
||
if (opname is SyntaxTree.operator_name_ident)
|
||
{
|
||
SyntaxTree.ident id = new SyntaxTree.ident(name_reflector.get_name((opname as SyntaxTree.operator_name_ident).operator_type));
|
||
id.source_context = opname.source_context;
|
||
return id;
|
||
}
|
||
return opname;
|
||
}
|
||
|
||
|
||
|
||
private void visit_method_name(SyntaxTree.method_name _method_name)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_method_name);
|
||
convertion_data_and_alghoritms.check_node_parser_error(_method_name.meth_name);
|
||
common_type_node tp = null;
|
||
definition_node def_temp = null;
|
||
SyntaxTree.template_type_name ttn = null;
|
||
bool is_operator = _method_name.meth_name is SyntaxTree.operator_name_ident;
|
||
SyntaxTree.Operators op = PascalABCCompiler.SyntaxTree.Operators.Undefined;
|
||
if(is_operator)
|
||
op=(_method_name.meth_name as SyntaxTree.operator_name_ident).operator_type;
|
||
_method_name.meth_name = ConvertOperatorNameToIdent(_method_name.meth_name);
|
||
bool explicit_impl = false;
|
||
if ((context.converting_block() != block_type.namespace_block) && (_method_name.class_name != null))
|
||
{
|
||
explicit_impl = true;
|
||
}
|
||
if (is_operator && op==SyntaxTree.Operators.AddressOf && SemanticRules.AddressOfOperatorNonOverloaded)
|
||
{
|
||
AddError(get_location(_method_name.meth_name), "NOT_OVERLOADED_OPERATOR");
|
||
}
|
||
bool common_extension_meth = false;
|
||
if (_method_name.class_name != null)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_method_name.class_name);
|
||
location loc_type_name = get_location(_method_name.class_name);
|
||
ttn = _method_name.class_name as SyntaxTree.template_type_name;
|
||
int num_template_args = 0;
|
||
if (ttn != null)
|
||
{
|
||
num_template_args = ttn.template_args.idents.Count;
|
||
}
|
||
common_type_node current_conv_type = context.converted_type;
|
||
def_temp = context.enter_in_type_method(_method_name, _method_name.class_name.name, loc_type_name, num_template_args);
|
||
if (explicit_impl)
|
||
{
|
||
context.converted_type = current_conv_type;
|
||
if (def_temp is type_node && (def_temp as type_node).IsInterface)
|
||
{
|
||
context.converted_explicit_interface_type = def_temp as type_node;
|
||
SymbolInfo si = context.converted_explicit_interface_type.find_in_type(_method_name.meth_name.name);
|
||
if (si == null)
|
||
AddError(new UndefinedNameReference(_method_name.meth_name.name, get_location(_method_name.meth_name)));
|
||
}
|
||
else
|
||
AddError(new OnlyProcedureNameAllowedInClassFunctionDefinition(_method_name.class_name.name,
|
||
get_location(_method_name.class_name)));
|
||
}
|
||
tp = def_temp as common_type_node;
|
||
template_class tc = def_temp as template_class;
|
||
//SyntaxTree.template_type_name ttn = _method_name.class_name as SyntaxTree.template_type_name;
|
||
if (ttn != null && !(def_temp is compiled_type_node))
|
||
{
|
||
int count;
|
||
if (tp == null)
|
||
{
|
||
if (tc != null)
|
||
{
|
||
if (tc.is_synonym)
|
||
{
|
||
AddError(loc_type_name, "CAN_NOT_DEFINE_METHOD_OF_TEMPLATE_TYPE_SYNONYM");
|
||
}
|
||
SyntaxTree.class_definition cl_def = tc.type_dec.type_def as SyntaxTree.class_definition;
|
||
count = cl_def.template_args.idents.Count;
|
||
if (count != ttn.template_args.idents.Count)
|
||
{
|
||
AddError(get_location(ttn), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tc.name, count);
|
||
}
|
||
for (int i = 0; i < count; ++i)
|
||
{
|
||
if (string.Compare(cl_def.template_args.idents[i].name, ttn.template_args.idents[i].name, true) != 0)
|
||
{
|
||
AddError(get_location(ttn.template_args.idents[i]), "PARAMETER_{0}_MUST_BE_NAMED_{1}", cl_def.template_args.idents[i].name, i + 1);
|
||
}
|
||
}
|
||
_method_name.class_name = new SyntaxTree.ident(ttn.name);
|
||
_method_name.class_name.source_context = ttn.source_context;
|
||
return;
|
||
}
|
||
AddError(get_location(ttn), "COULD_NOT_DEFINE_GENERIC_FUNCTION_OF_COMPILED_TYPE");
|
||
}
|
||
if (tp.generic_params == null)
|
||
{
|
||
AddError(get_location(ttn), "{0}_IS_NOT_TEMPLATE_CLASS", tp.PrintableName);
|
||
}
|
||
count = tp.generic_params.Count;
|
||
if (count != ttn.template_args.idents.Count)
|
||
{
|
||
AddError(get_location(ttn), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tp.PrintableName, count);
|
||
}
|
||
for (int i = 0; i < count; ++i)
|
||
{
|
||
if (string.Compare(tp.generic_params[i].name, ttn.template_args.idents[i].name, true) != 0)
|
||
{
|
||
AddError(get_location(ttn.template_args.idents[i]), "PARAMETER_{0}_MUST_BE_NAMED_{1}", tp.generic_params[i].name, i+1);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (tp != null && tp.is_generic_type_definition)
|
||
{
|
||
AddError(get_location(_method_name.class_name), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tp.PrintableName, tp.generic_params.Count);
|
||
}
|
||
if (tc != null)
|
||
{
|
||
AddError(get_location(_method_name.class_name), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tc.name, (tc.type_dec.type_def as SyntaxTree.class_definition).template_args.idents.Count);
|
||
}
|
||
}
|
||
//(ds)проверяем на компилированный тип
|
||
if (!(def_temp is compiled_type_node))
|
||
{
|
||
//(ssyy) проверяем на шаблон
|
||
if (tp == null)
|
||
{
|
||
return;
|
||
}
|
||
if (tp is compiled_generic_instance_type_node || tp is common_generic_instance_type_node)
|
||
AddError(get_location(_method_name), "EXTENSION_METHOD_FOR_GENERIC_INSTANCES");
|
||
SymbolInfo si = tp.scope.FindOnlyInScope(_method_name.meth_name.name);
|
||
|
||
if (tp.original_template == null && ((si == null && this._compiled_unit.namespaces.IndexOf(tp.comprehensive_namespace) == -1) || (si != null && this._compiled_unit.namespaces.IndexOf(tp.comprehensive_namespace) == -1)))
|
||
{
|
||
|
||
if (def_temp is common_type_node)
|
||
{
|
||
common_extension_meth = true;
|
||
common_type_node ctn = def_temp as common_type_node;
|
||
if (ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_wrapper ||
|
||
ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type ||
|
||
ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.base_set_type ||
|
||
ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.binary_file ||
|
||
ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.text_file ||
|
||
ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file)
|
||
AddError(get_location(_method_name), "NO_METHOD_{0}_IN_CLASS_{1}", _method_name.meth_name.name, tp.PrintableName);
|
||
}
|
||
else
|
||
AddError(get_location(_method_name), "NO_METHOD_{0}_IN_CLASS_{1}", _method_name.meth_name.name, tp.PrintableName);
|
||
}
|
||
}
|
||
else if (def_temp as compiled_type_node == SystemLibrary.SystemLibrary.void_type)
|
||
AddError(get_location(_method_name.class_name), "VOID_NOT_VALID");
|
||
}
|
||
else
|
||
{
|
||
if (is_operator && context.converted_type == null && context.converted_template_type == null && !(current_function_header != null && current_function_header.proc_attributes != null && has_extensionmethod_attr(current_function_header.proc_attributes.proc_attributes)) && !(current_function_header != null && current_function_header.template_args != null && current_function_header.template_args.idents.Count > 0))
|
||
{
|
||
AddError(get_location(_method_name), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||
}
|
||
}
|
||
convertion_data_and_alghoritms.check_node_parser_error(_method_name.meth_name);
|
||
location loc_name = get_location(_method_name.meth_name);
|
||
context.extension_method = common_extension_meth;
|
||
if (LambdaHelper.IsLambdaName(_method_name.meth_name) && lambdaProcessingState != LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase) //lroman//
|
||
{
|
||
if (lambdaProcessingState == LambdaProcessingState.None &&
|
||
context.converting_block() == block_type.namespace_block)
|
||
{
|
||
context.create_function(_method_name.meth_name.name, loc_name);
|
||
}
|
||
else
|
||
{
|
||
var addSymbol = (lambdaProcessingState == LambdaProcessingState.TypeInferencePhase &&
|
||
LambdaHelper.IsAuxiliaryLambdaName(_method_name.meth_name)) || lambdaProcessingState == LambdaProcessingState.FinishPhase;
|
||
context.create_lambda_function(_method_name.meth_name.name, loc_name, addSymbol, context.CurrentScope);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (current_function_header != null && current_function_header.proc_attributes != null && has_extensionmethod_attr(current_function_header.proc_attributes.proc_attributes))
|
||
context.create_function(_method_name.meth_name.name, loc_name, false);
|
||
else
|
||
{
|
||
if (!explicit_impl)
|
||
context.create_function(_method_name.meth_name.name, loc_name);
|
||
else
|
||
context.create_function(context.converted_explicit_interface_type.BaseFullName+"."+_method_name.meth_name.name, loc_name);
|
||
}
|
||
}
|
||
context.extension_method = false;
|
||
context.top_function.IsOperator = is_operator;
|
||
if (ttn != null && def_temp is compiled_type_node)
|
||
{
|
||
if (!explicit_impl)
|
||
visit_generic_params(context.top_function, ttn.template_args.idents);
|
||
else
|
||
{
|
||
List<type_node> instance_params = new List<type_node>();
|
||
foreach (ident id in ttn.template_args.idents)
|
||
{
|
||
SymbolInfo si = context.find(id.name);
|
||
if (si == null)
|
||
AddError(new UndefinedNameReference(id.name, get_location(id)));
|
||
if (!(si.sym_info is type_node))
|
||
AddError(new ExpectedType(get_location(id)));
|
||
instance_params.Add(si.sym_info as type_node);
|
||
}
|
||
if (!context.converted_explicit_interface_type.IsInterface)
|
||
AddError(get_location(ttn), "INTERFACE_EXPECTED");
|
||
type_node inst_tn = context.converted_explicit_interface_type.get_instance(instance_params);
|
||
bool found = false;
|
||
if (context.converted_type.ImplementingInterfaces.Count > 0)
|
||
{
|
||
foreach (type_node interf in context.converted_type.ImplementingInterfaces)
|
||
{
|
||
if (interf == inst_tn)
|
||
{
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (!found)
|
||
AddError(get_location(ttn),"CLASS_NOT_IMPLEMENT_THIS_INTERFACE");
|
||
}
|
||
}
|
||
//context.top_function.IsOperator = _method_name.meth_name is SyntaxTree.operator_name_ident;
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.method_name _method_name)
|
||
{
|
||
visit_method_name(_method_name);
|
||
}
|
||
|
||
private void is_case_variant_intersection_with_another(switch_node sn, int_const_node defined_const, location curloc)
|
||
{
|
||
foreach (case_variant_node cv in sn.case_variants)
|
||
{
|
||
foreach (int_const_node cn in cv.case_constants)
|
||
{
|
||
if (cn.constant_value == defined_const.constant_value)
|
||
{
|
||
AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER");
|
||
}
|
||
}
|
||
foreach (case_range_node cr in cv.case_ranges)
|
||
{
|
||
if ((defined_const.constant_value <= cr.high_bound.constant_value) &&
|
||
(defined_const.constant_value >= cr.lower_bound.constant_value))
|
||
{
|
||
AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_DIAPASON");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void is_case_range_intersection_with_another(switch_node sn, case_range_node defined_range, location curloc)
|
||
{
|
||
foreach (case_variant_node cv in sn.case_variants)
|
||
{
|
||
foreach (int_const_node icn in cv.case_constants)
|
||
{
|
||
if ((icn.constant_value >= defined_range.lower_bound.constant_value) &&
|
||
(icn.constant_value <= defined_range.high_bound.constant_value))
|
||
{
|
||
AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_DIAPASON");
|
||
}
|
||
}
|
||
foreach (case_range_node cr in cv.case_ranges)
|
||
{
|
||
if ((cr.lower_bound.constant_value <= defined_range.high_bound.constant_value) &&
|
||
(cr.lower_bound.constant_value >= defined_range.lower_bound.constant_value))
|
||
{
|
||
AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION");
|
||
}
|
||
if ((cr.high_bound.constant_value <= defined_range.high_bound.constant_value) &&
|
||
(cr.high_bound.constant_value >= defined_range.lower_bound.constant_value))
|
||
{
|
||
AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private string_const_node convert_string_const_to_switch(expression_node switch_expr, location loc)
|
||
{
|
||
if (switch_expr is string_const_node)
|
||
return switch_expr as string_const_node;
|
||
string_const_node scn = null;
|
||
if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral)
|
||
scn = new string_const_node((string)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc);
|
||
if (scn == null)
|
||
{
|
||
AddError(loc, "CONSTANT_EXPRESSION_EXPECTED");
|
||
}
|
||
return scn;
|
||
}
|
||
|
||
private int_const_node convert_const_to_switch(expression_node switch_expr,
|
||
ordinal_type_interface oti, type_node case_expr_type, location loc)
|
||
{
|
||
convertion_data_and_alghoritms.convert_type(switch_expr, case_expr_type, loc);
|
||
if (switch_expr is int_const_node)
|
||
return switch_expr as int_const_node;
|
||
//switch_expr = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int,
|
||
// loc, switch_expr);
|
||
int_const_node icn = null;//switch_expr as constant_node;
|
||
|
||
if (switch_expr is byte_const_node)
|
||
icn = new int_const_node((switch_expr as byte_const_node).constant_value, loc);
|
||
else if (switch_expr is sbyte_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as sbyte_const_node).constant_value), loc);
|
||
else if (switch_expr is short_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as short_const_node).constant_value), loc);
|
||
else if (switch_expr is ushort_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as ushort_const_node).constant_value), loc);
|
||
/*else if (switch_expr is uint_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as uint_const_node).constant_value),loc);
|
||
else if (switch_expr is long_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as long_const_node).constant_value),loc);
|
||
else if (switch_expr is ulong_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as ulong_const_node).constant_value),loc);*/
|
||
else if (switch_expr is bool_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as bool_const_node).constant_value), loc);
|
||
else if (switch_expr is char_const_node)
|
||
icn = new int_const_node(Convert.ToInt32((switch_expr as char_const_node).constant_value), loc);
|
||
else if (switch_expr is enum_const_node)
|
||
icn = new int_const_node((switch_expr as enum_const_node).constant_value, loc);
|
||
else if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral)
|
||
icn = new int_const_node((int)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc);
|
||
|
||
//учти здесь модет быть и long!
|
||
//-DarkStar Add
|
||
if (icn == null)
|
||
{
|
||
AddError(loc, "CONSTANT_EXPRESSION_EXPECTED");
|
||
}
|
||
return icn;
|
||
}
|
||
|
||
//TODO: Добавить приведение типов.
|
||
public override void visit(SyntaxTree.case_node _case_node)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_case_node);
|
||
switch_node sn = new switch_node(get_location(_case_node));
|
||
expression_node en = convert_strong(_case_node.param);
|
||
if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression);
|
||
type_node case_expr_type = en.type;
|
||
|
||
internal_interface ii = en.type.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
if (ii == null && en.type != SystemLibrary.SystemLibrary.string_type)
|
||
{
|
||
AddError(new OrdinalOrStringTypeExpected(en.location));
|
||
}
|
||
if (ii != null)
|
||
{
|
||
ordinal_type_interface oti = (ordinal_type_interface)ii;
|
||
en = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, en.location, en);
|
||
|
||
sn.condition = en;
|
||
|
||
foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(cv);
|
||
case_variant_node sem_cv = new case_variant_node(get_location(cv));
|
||
sn.case_variants.AddElement(sem_cv);
|
||
foreach (SyntaxTree.expression expr in cv.conditions.expressions)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(expr);
|
||
SyntaxTree.diapason_expr diap = expr as SyntaxTree.diapason_expr;
|
||
if (diap == null)
|
||
{
|
||
expression_node cn = convert_strong(expr);
|
||
int_const_node icn = convert_const_to_switch(cn, oti, case_expr_type, get_location(expr));
|
||
is_case_variant_intersection_with_another(sn, icn, get_location(expr));
|
||
sem_cv.case_constants.AddElement(icn);
|
||
}
|
||
else
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(diap.left);
|
||
expression_node left = convert_strong(diap.left);
|
||
int_const_node icn_left = convert_const_to_switch(left, oti, case_expr_type, get_location(diap.left));
|
||
|
||
convertion_data_and_alghoritms.check_node_parser_error(diap.right);
|
||
expression_node right = convert_strong(diap.right);
|
||
int_const_node icn_right = convert_const_to_switch(right, oti, case_expr_type, get_location(diap.right));
|
||
//ssyy
|
||
if (icn_left.constant_value > icn_right.constant_value)
|
||
{
|
||
AddError(get_location(diap.right), "LEFT_RANGE_GREATER_THEN_RIGHT");
|
||
}
|
||
//\ssyy
|
||
case_range_node crn = new case_range_node(icn_left, icn_right, get_location(diap));
|
||
is_case_range_intersection_with_another(sn, crn, get_location(expr));
|
||
sem_cv.case_ranges.AddElement(crn);
|
||
}
|
||
}
|
||
context.enter_code_block_with_bind();
|
||
statement_node stmn = convert_strong(cv.exec_if_true);
|
||
context.leave_code_block();
|
||
sem_cv.case_statement = stmn;
|
||
//sn.case_variants.AddElement(sem_cv);
|
||
}
|
||
context.enter_code_block_with_bind();
|
||
statement_node else_statement = convert_weak(_case_node.else_statement);
|
||
context.leave_code_block();
|
||
sn.default_statement = else_statement;
|
||
return_value(sn);
|
||
}
|
||
else
|
||
{
|
||
if_node main_ifn = null;
|
||
if_node ifn = null;
|
||
compiled_function_node str_eq_meth = SystemLibrary.SystemLibrary.string_type.find_in_type("=").sym_info as compiled_function_node;
|
||
Dictionary<string, string> case_constants = new Dictionary<string, string>();
|
||
foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(cv);
|
||
location loc = get_location(cv);
|
||
expression_node eq_node = null;
|
||
List<compiled_static_method_call> eq_calls = new List<compiled_static_method_call>();
|
||
foreach (SyntaxTree.expression expr in cv.conditions.expressions)
|
||
{
|
||
expression_node cn = convert_strong(expr);
|
||
if (cn.type != SystemLibrary.SystemLibrary.string_type)
|
||
AddError(new CanNotConvertTypes(cn, cn.type, SystemLibrary.SystemLibrary.string_type, cn.location));
|
||
string_const_node scn = convert_string_const_to_switch(cn, cn.location);
|
||
if (!case_constants.ContainsKey(scn.constant_value))
|
||
case_constants.Add(scn.constant_value, scn.constant_value);
|
||
else
|
||
AddError(cn.location, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER");
|
||
compiled_static_method_call eq_call = new compiled_static_method_call(str_eq_meth, cn.location);
|
||
eq_call.parameters.AddElement(en);
|
||
eq_call.parameters.AddElement(cn);
|
||
eq_calls.Add(eq_call);
|
||
}
|
||
foreach (compiled_static_method_call eq_call in eq_calls)
|
||
{
|
||
if (eq_node == null)
|
||
eq_node = eq_call;
|
||
else
|
||
eq_node = new basic_function_call(SystemLibrary.SystemLibrary.bool_or as basic_function_node, null, eq_node, eq_call);
|
||
}
|
||
context.enter_code_block_with_bind();
|
||
statement_node stmn = convert_strong(cv.exec_if_true);
|
||
context.leave_code_block();
|
||
if (ifn != null)
|
||
{
|
||
ifn.else_body = new if_node(eq_node, stmn, null, loc);
|
||
ifn = ifn.else_body as if_node;
|
||
}
|
||
else
|
||
ifn = new if_node(eq_node, stmn, null, loc);
|
||
if (main_ifn == null)
|
||
main_ifn = ifn;
|
||
}
|
||
context.enter_code_block_with_bind();
|
||
statement_node else_statement = convert_weak(_case_node.else_statement);
|
||
context.leave_code_block();
|
||
if (ifn == null)
|
||
{
|
||
ifn = new if_node(en, new statements_list(null), null, get_location(_case_node));
|
||
main_ifn = ifn;
|
||
}
|
||
ifn.else_body = else_statement;
|
||
return_value(main_ifn);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.case_variant _case_variant)
|
||
{
|
||
throw new NotSupportedError(get_location(_case_variant));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.get_address _get_address)
|
||
{
|
||
expression_node exp = convert_strong(_get_address.address_of);
|
||
if (!exp.is_addressed)
|
||
{
|
||
AddError(exp.location, "CAN_NOT_GET_ADDRESS_FROM_EXPRESSION");
|
||
}
|
||
expression_node res = new get_addr_node(exp, get_location(_get_address));
|
||
return_value(res);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.hex_constant _hex_constant)
|
||
{
|
||
expression_node en = null;
|
||
if (_hex_constant.val <= Int32.MaxValue && _hex_constant.val >= Int32.MinValue)
|
||
en = new int_const_node((int)_hex_constant.val, get_location(_hex_constant));
|
||
else
|
||
en = new long_const_node(_hex_constant.val, get_location(_hex_constant));
|
||
return_value(en);
|
||
}
|
||
|
||
private System.Collections.Generic.List<compiler_directive> ConvertDirectives(SyntaxTree.compilation_unit cu)
|
||
{
|
||
System.Collections.Generic.List<compiler_directive> list = new System.Collections.Generic.List<compiler_directive>();
|
||
foreach (SyntaxTree.compiler_directive sncd in cu.compiler_directives)
|
||
{
|
||
list.Add(new compiler_directive(sncd.Name.text, sncd.Directive!=null?sncd.Directive.text:"", get_location(sncd)));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
//TODO: Слить как нибудь два следующих метода.
|
||
public override void visit(SyntaxTree.program_module _program_module)
|
||
{
|
||
//MikhailoMMX Инициализация OpenMP
|
||
OpenMP.InitOpenMP(_program_module.compiler_directives, this, _program_module);
|
||
//\MikhailoMMX
|
||
|
||
string namespace_name = "";
|
||
location loc = get_location(_program_module);
|
||
if (_program_module.program_name != null)
|
||
{
|
||
namespace_name = _program_module.program_name.prog_name.name;
|
||
loc = get_location(_program_module.program_name.prog_name);
|
||
}
|
||
|
||
|
||
_compiled_unit = new common_unit_node();
|
||
|
||
_compiled_unit.compiler_directives = ConvertDirectives(_program_module);
|
||
|
||
|
||
SymbolTable.Scope[] used_units = build_referenced_units(referenced_units,true);
|
||
|
||
_compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units);
|
||
|
||
common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc);
|
||
cnsn.is_main = true;
|
||
|
||
reset_for_interface();
|
||
|
||
UpdateUnitDefinitionItemForUnit(_compiled_unit);
|
||
|
||
hard_node_test_and_visit(_program_module.program_block);
|
||
context.check_labels(context.converted_namespace.labels);
|
||
|
||
// frninja 28/04/16 - режем мусорные методы хелперы yield
|
||
{
|
||
var toRemove = cnsn.functions.Where(m => m.is_yield_helper).ToArray();
|
||
foreach (var m in toRemove)
|
||
{
|
||
cnsn.functions.remove(m);
|
||
}
|
||
}
|
||
// end frninja
|
||
|
||
common_namespace_function_node main_function = new common_namespace_function_node(compiler_string_consts.temp_main_function_name,
|
||
null, null, cnsn, null);
|
||
main_function.function_code = context.code;
|
||
context.apply_special_local_vars(main_function);
|
||
cnsn.functions.AddElement(main_function);
|
||
|
||
context.leave_block();
|
||
|
||
_compiled_unit.main_function = main_function;
|
||
}
|
||
|
||
private void reset_for_interface()
|
||
{
|
||
body_exists = false;
|
||
}
|
||
|
||
private bool check_for_dll_entry_module(List<compiler_directive> directives)
|
||
{
|
||
foreach (compiler_directive cd in directives)
|
||
{
|
||
if (string.Compare(cd.name,"apptype",true)==0 && string.Compare(cd.directive,"dll",true)==0)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
internal bool _is_interface_part = false;
|
||
public override void visit(SyntaxTree.unit_module _unit_module)
|
||
{
|
||
//MikhailoMMX Инициализация OpenMP
|
||
OpenMP.InitOpenMP(_unit_module.compiler_directives, this, _unit_module);
|
||
//\MikhailoMMX
|
||
|
||
//current_document=new document(_unit_module.file_name);
|
||
string namespace_name = "";
|
||
_is_interface_part = true;
|
||
location loc = null;
|
||
if (_unit_module.unit_name != null)
|
||
{
|
||
namespace_name = _unit_module.unit_name.idunit_name.name;
|
||
loc = get_location(_unit_module.unit_name.idunit_name);
|
||
if (namespace_name.ToLower() != System.IO.Path.GetFileNameWithoutExtension(_unit_module.file_name).ToLower())
|
||
AddError(loc, "UNIT_NAME_MUST_BE_EQUAL_UNIT_FILE_NAME");
|
||
}
|
||
|
||
|
||
_compiled_unit = new common_unit_node(_unit_module.unit_name.idunit_name.name);
|
||
assign_doc_info(_compiled_unit,_unit_module.unit_name);
|
||
_compiled_unit.compiler_directives = ConvertDirectives(_unit_module);
|
||
|
||
SymbolTable.Scope[] used_units = build_referenced_units(referenced_units,true);
|
||
|
||
_compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units);
|
||
|
||
common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc);
|
||
|
||
_compiled_unit.add_unit_name_to_namespace();
|
||
|
||
if (check_for_dll_entry_module(_compiled_unit.compiler_directives))
|
||
{
|
||
cnsn.is_main = true;
|
||
}
|
||
UpdateUnitDefinitionItemForUnit(_compiled_unit);
|
||
reset_for_interface();
|
||
in_interface_part = false;
|
||
if (_unit_module.implementation_part != null)
|
||
in_interface_part = true;
|
||
hard_node_test_and_visit(_unit_module.interface_part);
|
||
if (_unit_module.implementation_part != null)
|
||
in_interface_part = false;
|
||
if (_unit_module.attributes != null)
|
||
make_attributes_for_declaration(_unit_module, _compiled_unit);
|
||
context.leave_interface_part();
|
||
_is_interface_part = false;
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.compilation_unit _compilation_unit)
|
||
{
|
||
if (_compilation_unit.source_context == null)
|
||
throw new NotSupportedError();
|
||
throw new NotSupportedError(get_location(_compilation_unit));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.program_body _program_body)
|
||
{
|
||
throw new NotSupportedError(get_location(_program_body));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.uses_list _uses_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_uses_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.uses_unit_in _uses_unit_in)
|
||
{
|
||
throw new NotSupportedError(get_location(_uses_unit_in));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.unit_name _unit_name)
|
||
{
|
||
throw new NotSupportedError(get_location(_unit_name));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.consts_definitions_list _consts_definitions_list)
|
||
{
|
||
//ssyy
|
||
if (context.converting_block() == block_type.type_block &&
|
||
context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_consts_definitions_list), "INVALID_INTERFACE_MEMBER");
|
||
}
|
||
//\ssyy
|
||
foreach (SyntaxTree.const_definition cnst in _consts_definitions_list.const_defs)
|
||
cnst.visit(this);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.const_definition _const_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_const_definition));
|
||
}
|
||
|
||
private bool IsBoundedArray(type_node tn)
|
||
{
|
||
return tn.get_internal_interface(internal_interface_kind.bounded_array_interface) != null;
|
||
}
|
||
|
||
private bool IsUnsizedArray(type_node tn)
|
||
{
|
||
return tn.get_internal_interface(internal_interface_kind.unsized_array_interface) != null;
|
||
}
|
||
|
||
private type_node const_def_type=null;
|
||
private bool is_typed_const_def=false;
|
||
|
||
public override void visit(SyntaxTree.typed_const_definition _typed_const_definition)
|
||
{
|
||
location cons_loc = get_location(_typed_const_definition.const_value);
|
||
constant_definition_node cdn = context.add_const_definition(_typed_const_definition.const_name.name, get_location(_typed_const_definition.const_name));
|
||
type_node tn = convert_strong(_typed_const_definition.const_type);
|
||
assign_doc_info(cdn,_typed_const_definition);
|
||
check_for_type_allowed(tn,get_location(_typed_const_definition.const_type));
|
||
if (context.converted_type != null && context.converted_func_stack.Empty)
|
||
if (!constant_in_class_valid(tn))//proverka na primitivnost konstanty v klasse
|
||
AddError(get_location(_typed_const_definition), "CLASS_CONSTANT_CAN_HAVE_ONLY_PRIMITIVE_VALUE");
|
||
if (tn is common_type_node)
|
||
{
|
||
if (!SemanticRules.DefineMethodsInConstantRecord)
|
||
CheckConstantRecordNotBeContainsMethods(tn as common_type_node, get_location(_typed_const_definition.const_type));
|
||
if (!SemanticRules.InheritanceConstantRecord)
|
||
//mnozhestvo zdes iskljuchenie
|
||
if (tn.base_type is common_type_node && tn.base_type.type_special_kind != SemanticTree.type_special_kind.base_set_type/*tn.base_type != SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node*/)
|
||
AddError(get_location(_typed_const_definition.const_type), "CONSTANT_RECORD_CAN_NOT_BE_INHERITANCE");
|
||
}
|
||
const_def_type = tn.element_type;
|
||
is_typed_const_def = true;
|
||
_typed_const_definition.const_value = get_possible_array_const(_typed_const_definition.const_value,tn);
|
||
cdn.const_value = convert_strong_to_constant_node(_typed_const_definition.const_value, tn);
|
||
const_def_type = null;
|
||
is_typed_const_def = false;
|
||
if (cdn is class_constant_definition && cdn.constant_value.value == null)
|
||
AddError(new NotSupportedError(cons_loc));
|
||
}
|
||
|
||
private void CheckConstantRecordNotBeContainsMethods(common_type_node ctn, location loc)
|
||
{
|
||
if (ctn.is_value)
|
||
{
|
||
if (ctn.methods.Count > 0)
|
||
{
|
||
for (int i=0; i<ctn.methods.Count; i++)
|
||
if (ctn.methods[i].loc != null)
|
||
AddError(loc, "CONSTANT_RECORD_CAN_NOT_CONTAINS_METHODS");
|
||
}
|
||
if (ctn.base_type is common_type_node)
|
||
CheckConstantRecordNotBeContainsMethods(ctn.base_type as common_type_node, loc);
|
||
}
|
||
else
|
||
{
|
||
if (IsBoundedArray(ctn) && ctn.element_type is common_type_node)
|
||
CheckConstantRecordNotBeContainsMethods(ctn.element_type as common_type_node, loc);
|
||
}
|
||
}
|
||
|
||
private bool constant_in_class_valid(type_node tn)
|
||
{
|
||
if (tn is common_type_node)
|
||
if (tn.IsEnum) return true;
|
||
else return false;
|
||
if (tn is compiled_type_node)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.simple_const_definition _simple_const_definition)
|
||
{
|
||
constant_definition_node cdn = context.add_const_definition(_simple_const_definition.const_name.name, get_location(_simple_const_definition.const_name));
|
||
cdn.const_value = convert_strong_to_constant_node(_simple_const_definition.const_value);
|
||
cdn.const_value.SetType(DeduceType(cdn.const_value.type, cdn.const_value.location));
|
||
assign_doc_info(cdn,_simple_const_definition);
|
||
if (context.converted_type != null && context.converted_func_stack.Empty)
|
||
if (!constant_in_class_valid(cdn.const_value.type))
|
||
AddError(get_location(_simple_const_definition), "CLASS_CONSTANT_CAN_HAVE_ONLY_PRIMITIVE_VALUE");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.type_declarations _type_declarations)
|
||
{
|
||
EnterTypeDeclarationsSection();
|
||
foreach (SyntaxTree.type_declaration td in _type_declarations.types_decl)
|
||
{
|
||
hard_node_test_and_visit(td);
|
||
}
|
||
LeaveTypeDeclarationsSection();
|
||
}
|
||
|
||
private common_type_node convert_function_type(SyntaxTree.function_header func_header, location loc, string type_name, common_type_node del_type)
|
||
{
|
||
return convert_function_type(func_header.parameters, func_header.return_type, loc, type_name, del_type);
|
||
}
|
||
|
||
private common_type_node convert_function_type(SyntaxTree.procedure_header proc_header, location loc, string type_name, common_type_node del_type)
|
||
{
|
||
return convert_function_type(proc_header.parameters, null, loc, type_name, del_type);
|
||
}
|
||
|
||
private common_type_node convert_function_type(SyntaxTree.formal_parameters syn_parametres, SyntaxTree.type_definition return_type,
|
||
location loc, string type_name, common_type_node del_type)
|
||
{
|
||
//TODO: Добавить аттрибуты функции. Или не надо?
|
||
//TODO: Сообщать о том что class keyword и of object игнорируется.
|
||
parameter_list parameters = new parameter_list();
|
||
bool params_met=false;
|
||
if (syn_parametres != null)
|
||
{
|
||
parameter_list temp_params = new parameter_list();
|
||
foreach (SyntaxTree.typed_parameters tpars in syn_parametres.params_list)
|
||
{
|
||
temp_params.clear();
|
||
SemanticTree.parameter_type pt = SemanticTree.parameter_type.value;
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
switch (tpars.param_kind)
|
||
{
|
||
//TODO: Params parameter.
|
||
case SyntaxTree.parametr_kind.var_parametr:
|
||
{
|
||
pt = SemanticTree.parameter_type.var;
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
break;
|
||
}
|
||
case PascalABCCompiler.SyntaxTree.parametr_kind.const_parametr:
|
||
{
|
||
pt = SemanticTree.parameter_type.value;
|
||
cpt = concrete_parameter_type.cpt_const;
|
||
break;
|
||
}
|
||
case PascalABCCompiler.SyntaxTree.parametr_kind.out_parametr:
|
||
{
|
||
pt = SemanticTree.parameter_type.var;
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
break;
|
||
}
|
||
}
|
||
foreach (SyntaxTree.ident id in tpars.idents.idents)
|
||
{
|
||
common_parameter cp = new common_parameter(id.name, pt, null, cpt, get_location(id));
|
||
parameters.AddElement(cp);
|
||
if (tpars.param_kind == SyntaxTree.parametr_kind.params_parametr)
|
||
{
|
||
cp.intrenal_is_params = true;
|
||
}
|
||
temp_params.AddElement(cp);
|
||
}
|
||
if (tpars.param_kind == SyntaxTree.parametr_kind.params_parametr)
|
||
{
|
||
if (tpars.idents.idents.Count > 1)
|
||
{
|
||
AddError(get_location(tpars.idents.idents[1]), "ONLY_ONE_PARAMS_PARAMETER_ALLOWED");
|
||
}
|
||
}
|
||
|
||
SyntaxTree.array_type arr = tpars.vars_type as SyntaxTree.array_type;
|
||
if (tpars.vars_type is SyntaxTree.class_definition || /*tpars.vars_type is SyntaxTree.enum_type_definition ||*/
|
||
(arr != null && arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null))
|
||
{
|
||
AddError(get_location(tpars.vars_type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM");
|
||
}
|
||
|
||
type_node tp = convert_strong(tpars.vars_type);
|
||
|
||
if (tpars.param_kind == SyntaxTree.parametr_kind.params_parametr)
|
||
{
|
||
internal_interface ii = tp.get_internal_interface(internal_interface_kind.unsized_array_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(get_location(tpars.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED");
|
||
}
|
||
}
|
||
foreach (common_parameter ccp in temp_params)
|
||
{
|
||
ccp.type = tp;
|
||
}
|
||
|
||
|
||
if (params_met)
|
||
{
|
||
AddError(get_location(tpars), "ONLY_LAST_PARAMETER_CAN_BE_PARAMS");
|
||
}
|
||
if (tpars.param_kind == PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr)
|
||
{
|
||
params_met = true;
|
||
}
|
||
}
|
||
|
||
}
|
||
type_node ret_val_type = null;
|
||
if (return_type != null)
|
||
{
|
||
ret_val_type = convert_strong(return_type);
|
||
}
|
||
common_type_node del;
|
||
if (del_type == null)
|
||
{
|
||
del = convertion_data_and_alghoritms.type_constructor.create_delegate(type_name,
|
||
ret_val_type, parameters, context.converted_namespace, loc);
|
||
}
|
||
else
|
||
{
|
||
del = del_type;
|
||
convertion_data_and_alghoritms.type_constructor.init_delegate(del, ret_val_type, parameters, loc);
|
||
}
|
||
context.converted_namespace.types.AddElement(del);
|
||
return del;
|
||
}
|
||
|
||
private string get_template_instance_name(string template_name, System.Collections.Generic.List<string> args)
|
||
{
|
||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||
sb.Append("$");
|
||
sb.Append("template_");
|
||
sb.Append(template_name);
|
||
foreach (string s in args)
|
||
{
|
||
sb.Append("$");
|
||
sb.Append(s);
|
||
}
|
||
return sb.ToString();
|
||
}
|
||
|
||
private string record_type_name = null;
|
||
private bool record_is_generic = false;
|
||
|
||
private void check_where_section(SyntaxTree.class_definition cl_def)
|
||
{
|
||
if (cl_def.where_section != null && cl_def.where_section.defs != null)
|
||
{
|
||
AddError(get_location(cl_def.where_section), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS");
|
||
}
|
||
}
|
||
|
||
//(ssyy) Проверяет параметры шаблона на совпадение друг с другом
|
||
private void check_param_redeclared(List<SyntaxTree.ident> idents)
|
||
{
|
||
for (int i = 0; i < idents.Count; i++)
|
||
for (int j = i + 1; j < idents.Count; j++)
|
||
{
|
||
if (string.Equals(idents[i].name, idents[j].name, StringComparison.InvariantCultureIgnoreCase))
|
||
{
|
||
AddError(get_location(idents[j]), "TEMPLATE_PARAMETER_{0}_REDEFINITION", idents[j].name);
|
||
}
|
||
}
|
||
if (context.top_function != null && context.converted_type != null && context.converted_type.is_generic_type_definition)
|
||
{
|
||
//List<SemanticTree.ICommonTypeNode> gparams = context.converted_type.generic_params;
|
||
foreach (SyntaxTree.ident id in idents)
|
||
foreach(SemanticTree.ICommonTypeNode ictn in context.converted_type.generic_params)
|
||
if (string.Equals(id.name, ictn.name, StringComparison.InvariantCultureIgnoreCase))
|
||
{
|
||
AddError(get_location(id), "TEMPLATE_PARAMETER_{0}_REDEFINITION", id.name);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void visit_generic_params(common_type_node ctn, List<SyntaxTree.ident> idents)
|
||
{
|
||
if (SemanticRules.RuntimeInitVariablesOfGenericParameters)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction != null) // SSM 12/05/15 - из-за отсутствия этого падало при наличии обобщенных классов в системном модуле! Ужас!
|
||
SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction.Restore();
|
||
}
|
||
ctn.is_generic_type_definition = true;
|
||
check_param_redeclared(idents);
|
||
ctn.generic_params = new List<SemanticTree.ICommonTypeNode>();
|
||
foreach (SyntaxTree.ident id in idents)
|
||
{
|
||
common_type_node par = new common_type_node(
|
||
id.name, SemanticTree.type_access_level.tal_public, context.converted_namespace,
|
||
convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null),
|
||
get_location(id));
|
||
SystemLibrary.SystemLibrary.init_reference_type(par);
|
||
par.SetBaseType(SystemLibrary.SystemLibrary.object_type);
|
||
par.generic_type_container = ctn;
|
||
ctn.generic_params.Add(par);
|
||
ctn.scope.AddSymbol(id.name, new SymbolInfo(par));
|
||
if (SemanticRules.RuntimeInitVariablesOfGenericParameters && !ctn.IsInterface && !ctn.IsDelegate)
|
||
{
|
||
class_field cf = new class_field(
|
||
compiler_string_consts.generic_param_kind_prefix + id.name,
|
||
SystemLibrary.SystemLibrary.byte_type,
|
||
ctn, PascalABCCompiler.SemanticTree.polymorphic_state.ps_static,
|
||
SemanticTree.field_access_level.fal_public, null);
|
||
ctn.fields.AddElement(cf);
|
||
par.runtime_initialization_marker = cf;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void visit_generic_params(common_function_node cfn, List<SyntaxTree.ident> idents)
|
||
{
|
||
check_param_redeclared(idents);
|
||
cfn.generic_params = new List<SemanticTree.ICommonTypeNode>();
|
||
foreach (SyntaxTree.ident id in idents)
|
||
{
|
||
common_type_node par = new common_type_node(
|
||
id.name, SemanticTree.type_access_level.tal_public, context.converted_namespace,
|
||
convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null),
|
||
get_location(id));
|
||
SystemLibrary.SystemLibrary.init_reference_type(par);
|
||
par.SetBaseType(SystemLibrary.SystemLibrary.object_type);
|
||
par.generic_function_container = cfn;
|
||
cfn.generic_params.Add(par);
|
||
cfn.scope.AddSymbol(id.name, new SymbolInfo(par));
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.type_declaration _type_declaration)
|
||
{
|
||
//bool is_template_synonym = false;
|
||
//SyntaxTree.array_type at=_type_declaration.type_def as SyntaxTree.array_type;
|
||
template_class tc = null;
|
||
SyntaxTree.template_type_name ttn = _type_declaration.type_name as SyntaxTree.template_type_name;
|
||
SyntaxTree.class_definition cl_def = _type_declaration.type_def as SyntaxTree.class_definition;
|
||
SyntaxTree.function_header function_header = _type_declaration.type_def as SyntaxTree.function_header;
|
||
SyntaxTree.procedure_header procedure_header = _type_declaration.type_def as SyntaxTree.procedure_header;
|
||
if (cl_def != null && (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial && cl_def.keyword != SyntaxTree.class_keyword.Class)
|
||
{
|
||
AddError(get_location(_type_declaration), "ONLY_CLASS_CAN_BE_PARTIAL");
|
||
}
|
||
if (ttn != null && cl_def == null && function_header == null && procedure_header == null)
|
||
{
|
||
location t_loc = get_location(ttn);
|
||
context.check_name_free(ttn.name, t_loc);
|
||
tc = new template_class(_type_declaration, ttn.name,
|
||
context.converted_namespace,
|
||
current_document, using_list);
|
||
tc.is_synonym = true;
|
||
//Проверяем параметры шаблона на совпадение друг с другом
|
||
check_param_redeclared(ttn.template_args.idents);
|
||
context.AddTemplate(ttn.name, tc, t_loc);
|
||
return;
|
||
|
||
//is_template_synonym = true;
|
||
//AddError(new TemplateCanBeClassOnly(get_location(ttn)));
|
||
}
|
||
if ((function_header != null) || (procedure_header != null))
|
||
{
|
||
location loc;
|
||
if (function_header != null)
|
||
loc = get_location(function_header);
|
||
else
|
||
loc = get_location(procedure_header);
|
||
string del_name = _type_declaration.type_name.name;
|
||
if (ttn != null)
|
||
{
|
||
if (context.top_function != null)
|
||
{
|
||
AddError(loc, "GENERIC_DELEGATE_INNER_FUNCTION");
|
||
}
|
||
del_name += compiler_string_consts.generic_params_infix + ttn.template_args.idents.Count;
|
||
}
|
||
context.check_name_free(del_name, loc);
|
||
common_type_node del_type = convertion_data_and_alghoritms.type_constructor.create_delegate_without_init(
|
||
del_name, context.converted_namespace, loc);
|
||
//(ssyy) Обработка дженериков
|
||
common_type_node tmp_converted_type = null;
|
||
if (ttn != null)
|
||
{
|
||
tmp_converted_type = context.converted_type;
|
||
context.converted_type = del_type;
|
||
visit_generic_params(del_type, ttn.template_args.idents);
|
||
}
|
||
if (function_header != null)
|
||
{
|
||
del_type = convert_function_type(function_header, loc, del_name, del_type);
|
||
}
|
||
else
|
||
{
|
||
del_type = convert_function_type(procedure_header, loc, del_name, del_type);
|
||
}
|
||
if (ttn != null)
|
||
{
|
||
context.converted_type = tmp_converted_type;
|
||
}
|
||
//blocks.converted_namespace.types.AddElement(del_type);
|
||
CheckWaitedRefTypes(del_type);
|
||
if (_type_declaration.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_type_declaration,del_type);
|
||
}
|
||
context.converted_namespace.scope.AddSymbol(del_name, new SymbolInfo(del_type));
|
||
return;
|
||
}
|
||
if (cl_def == null && ttn == null)
|
||
{
|
||
string name = _type_declaration.type_name.name;
|
||
location loc = get_location(_type_declaration.type_name);
|
||
context.check_name_free(name, loc);
|
||
is_direct_type_decl = true;
|
||
type_node tn = convert_strong(_type_declaration.type_def);
|
||
assign_doc_info(tn,_type_declaration);
|
||
is_direct_type_decl = false;
|
||
if (_type_declaration.type_def is SyntaxTree.named_type_reference||
|
||
_type_declaration.type_def is SyntaxTree.ref_type || _type_declaration.type_def is SyntaxTree.string_num_definition ||
|
||
tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_kind)// ||
|
||
/*tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type*/
|
||
{
|
||
if (context.converted_func_stack.Empty)
|
||
{
|
||
type_synonym ts = new type_synonym(name, tn, loc);
|
||
assign_doc_info(ts,_type_declaration);
|
||
context.converted_namespace.type_synonyms.Add(ts);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
tn.SetName(context.BuildName(name));
|
||
}
|
||
if (_type_declaration.attributes != null)
|
||
if (_type_declaration.type_def is SyntaxTree.enum_type_definition)
|
||
{
|
||
make_attributes_for_declaration(_type_declaration,tn);
|
||
(tn as common_type_node).add_additional_enum_operations();
|
||
}
|
||
else
|
||
AddError(get_location(_type_declaration.attributes), "ATTRIBUTES_APPLICABLE_ONLY_TO_THESE_TYPES");
|
||
context.add_type(name, tn, loc);
|
||
return;
|
||
}
|
||
//Проверим, что список template-ов не пуст
|
||
bool is_generic = false;
|
||
if (ttn != null && cl_def != null && cl_def.template_args == null)
|
||
{
|
||
cl_def.template_args = ttn.template_args;
|
||
}
|
||
if (cl_def != null && cl_def.template_args != null && cl_def.template_args.idents != null &&
|
||
cl_def.template_args.idents.Count > 0)
|
||
{
|
||
switch (cl_def.keyword)
|
||
{
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateClass:
|
||
cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Class;
|
||
is_generic = false;
|
||
check_where_section(cl_def);
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateRecord:
|
||
cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Record;
|
||
is_generic = false;
|
||
check_where_section(cl_def);
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateInterface:
|
||
cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Interface;
|
||
is_generic = false;
|
||
check_where_section(cl_def);
|
||
break;
|
||
default:
|
||
is_generic = true;
|
||
break;
|
||
}
|
||
|
||
if (!is_generic)
|
||
{
|
||
string t_name = _type_declaration.type_name.name;
|
||
location t_loc = get_location(_type_declaration.type_name);
|
||
SymbolInfo si = context.find_only_in_namespace(t_name);
|
||
|
||
tc = null;
|
||
//Ищем предописание
|
||
if (si != null)
|
||
{
|
||
tc = si.sym_info as template_class;
|
||
if (tc == null || !tc.ForwardDeclarationOnly)
|
||
{
|
||
AddError(new NameRedefinition(t_name, convertion_data_and_alghoritms.get_location(si.sym_info), t_loc));
|
||
}
|
||
SyntaxTree.class_definition prev_cl_def = tc.type_dec.type_def as SyntaxTree.class_definition;
|
||
if (prev_cl_def.keyword != cl_def.keyword || prev_cl_def.template_args.idents.Count != cl_def.template_args.idents.Count)
|
||
{
|
||
AddError(t_loc, "FORWARD_TEMPLATE_{0}_DECLARATION_MISMATCH_DECLARATION", t_name);
|
||
}
|
||
for (int k = 0; k < cl_def.template_args.idents.Count; k++)
|
||
{
|
||
if (string.Compare(cl_def.template_args.idents[k].name, prev_cl_def.template_args.idents[k].name, true) != 0)
|
||
{
|
||
AddError(t_loc, "FORWARD_TEMPLATE_{0}_DECLARATION_MISMATCH_DECLARATION", t_name);
|
||
}
|
||
}
|
||
if (cl_def.body == null)
|
||
{
|
||
AddError(new NameRedefinition(t_name, convertion_data_and_alghoritms.get_location(si.sym_info), t_loc));
|
||
}
|
||
tc.type_dec = _type_declaration;
|
||
tc.ForwardDeclarationOnly = false;
|
||
return;
|
||
}
|
||
|
||
tc = new template_class(_type_declaration, t_name,
|
||
context.converted_namespace,
|
||
current_document, using_list);
|
||
|
||
//Проверяем параметры шаблона на совпадение друг с другом
|
||
check_param_redeclared(cl_def.template_args.idents);
|
||
|
||
tc.ForwardDeclarationOnly = cl_def.body == null;
|
||
context.AddTemplate(t_name, tc, t_loc);
|
||
if (!tc.ForwardDeclarationOnly && template_class.check_template_definitions)
|
||
{
|
||
int count = cl_def.template_args.idents.Count;
|
||
List<type_node> test_types = new List<type_node>(count);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
test_types.Add(new indefinite_type_node(cl_def.template_args.idents[i].name));
|
||
}
|
||
instance(tc, test_types, t_loc);
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
//(ssyy) Теперь проверим на модификатор template
|
||
if (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateClass ||
|
||
cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateRecord ||
|
||
cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateInterface)
|
||
{
|
||
//Ошибка, т.к. нет списка шаблонных параметров.
|
||
AddError(get_location(_type_declaration.type_name), "TEMPLATE_PARAMS_EXPECTED");
|
||
}
|
||
bool predefined_generic = false;
|
||
if (is_generic)
|
||
{
|
||
SymbolInfo si = context.find_only_in_namespace(_type_declaration.type_name.name + compiler_string_consts.generic_params_infix +
|
||
cl_def.template_args.idents.Count.ToString());
|
||
if (!(si != null && si.sym_info is common_type_node && context.types_predefined.IndexOf(si.sym_info as common_type_node) != -1))
|
||
{
|
||
context.check_name_free(_type_declaration.type_name.name, get_location(_type_declaration.type_name));
|
||
}
|
||
else
|
||
predefined_generic = true;
|
||
_type_declaration.type_name.name += compiler_string_consts.generic_params_infix +
|
||
cl_def.template_args.idents.Count.ToString();
|
||
}
|
||
if (cl_def.keyword == SyntaxTree.class_keyword.Record)
|
||
{
|
||
string name = record_type_name = _type_declaration.type_name.name;
|
||
record_is_generic = is_generic;
|
||
location loc = get_location(_type_declaration.type_name);
|
||
context.check_name_free(name, loc);
|
||
//context.create_record_type(loc, record_type_name);
|
||
is_direct_type_decl = true;
|
||
type_node tn = convert_strong(_type_declaration.type_def);
|
||
assign_doc_info(tn,_type_declaration);
|
||
if (_type_declaration.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_type_declaration, tn);
|
||
}
|
||
is_direct_type_decl = false;
|
||
record_type_name = null;
|
||
record_is_generic = false;
|
||
tn.SetName(context.BuildName(name));
|
||
return;
|
||
}
|
||
|
||
//(ssyy) Флаг показывает, создаём ли мы интерфейс
|
||
bool interface_creating = (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface);
|
||
|
||
common_type_node ctn = context.advanced_create_type(_type_declaration.type_name.name, get_location(_type_declaration.type_name), interface_creating, (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial);
|
||
assign_doc_info(ctn,_type_declaration);
|
||
if (is_generic)
|
||
{
|
||
if (predefined_generic)
|
||
{
|
||
if (ctn.generic_params.Count != cl_def.template_args.idents.Count)
|
||
AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH");
|
||
foreach (ident id in cl_def.template_args.idents)
|
||
{
|
||
SymbolInfo si = ctn.find_in_type(id.name);
|
||
if (si == null)
|
||
AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH");
|
||
if (!(si.sym_info is common_type_node && (si.sym_info as common_type_node).is_generic_parameter))
|
||
AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
context.create_generic_indicator(ctn);
|
||
visit_generic_params(ctn, cl_def.template_args.idents);
|
||
}
|
||
}
|
||
if (predefined_generic && cl_def.where_section != null && cl_def.where_section.defs.Count > 0)
|
||
AddError(get_location(cl_def.where_section), "WHERE_SECTION_NOT_ALLOWED");
|
||
visit_where_list(cl_def.where_section);
|
||
CheckWaitedRefTypes(ctn);
|
||
is_direct_type_decl = true;
|
||
hard_node_test_and_visit(_type_declaration.type_def);
|
||
|
||
// frninja 28/04/16 - режем мусорные методы хелперы yield
|
||
{
|
||
var toRemove = ctn.methods.Where(m => m.is_yield_helper).ToArray();
|
||
foreach (var m in toRemove)
|
||
{
|
||
ctn.methods.remove(m);
|
||
}
|
||
}
|
||
// end frninja
|
||
|
||
is_direct_type_decl = false;
|
||
if (_type_declaration.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_type_declaration, ctn);
|
||
}
|
||
}
|
||
|
||
private bool attribute_converted = false;
|
||
private AttributeTargets get_usage_attrs(type_node tn, out bool allowMultiple)
|
||
{
|
||
allowMultiple = false;
|
||
if (tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
for (int i=0; i<ctn.attributes.Count; i++)
|
||
{
|
||
if (ctn.attributes[i].attribute_type == SystemLibrary.SystemLibrary.usage_attribute_type)
|
||
{
|
||
int ind = ctn.attributes[i].prop_names.IndexOf(SystemLibrary.SystemLibrary.usage_attribute_type.find_in_type("AllowMultiple").sym_info as property_node);
|
||
if (ind != -1)
|
||
allowMultiple = (bool)ctn.attributes[i].prop_initializers[ind].get_object_value();
|
||
return (AttributeTargets)ctn.attributes[i].args[0].get_object_value();
|
||
}
|
||
}
|
||
return AttributeTargets.All;
|
||
}
|
||
else
|
||
{
|
||
compiled_type_node ctn = tn as compiled_type_node;
|
||
Attribute attr = Attribute.GetCustomAttribute(ctn.compiled_type,SystemLibrary.SystemLibrary.usage_attribute_type.compiled_type);
|
||
if (attr != null)
|
||
{
|
||
allowMultiple = (attr as AttributeUsageAttribute).AllowMultiple;
|
||
return (attr as AttributeUsageAttribute).ValidOn;
|
||
}
|
||
else
|
||
return AttributeTargets.All;
|
||
}
|
||
}
|
||
|
||
private void check_for_usage_attribute(definition_node dn, AttributeTargets targets, string name, location loc, SemanticTree.attribute_qualifier_kind qualifier)
|
||
{
|
||
switch (dn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.common_type_node :
|
||
{
|
||
common_type_node ctn = dn as common_type_node;
|
||
if (ctn.IsDelegate)
|
||
{
|
||
if ((targets & (AttributeTargets.Delegate)) != (AttributeTargets.Delegate))
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_DELEGATE", name);
|
||
}
|
||
else
|
||
if (ctn.IsInterface)
|
||
{
|
||
if ((targets & AttributeTargets.Interface) != AttributeTargets.Interface)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_INTERFACE", name);
|
||
}
|
||
else
|
||
if (ctn.IsEnum)
|
||
{
|
||
if ((targets & (AttributeTargets.Enum)) != (AttributeTargets.Enum))
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_ENUM", name);
|
||
}
|
||
else
|
||
if (ctn.is_value_type)
|
||
{
|
||
if ((targets & AttributeTargets.Struct) != AttributeTargets.Struct)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_STRUCT", name);
|
||
}
|
||
else
|
||
if ((targets & AttributeTargets.Class) != AttributeTargets.Class)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_CLASS", name);
|
||
}
|
||
break;
|
||
case semantic_node_type.common_method_node:
|
||
if ((dn as common_method_node).is_constructor)
|
||
{
|
||
if ((targets & AttributeTargets.Constructor) != AttributeTargets.Constructor)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_CONSTRUCTOR", name);
|
||
}
|
||
else
|
||
if ((targets & AttributeTargets.Method) != AttributeTargets.Method && qualifier != SemanticTree.attribute_qualifier_kind.return_kind)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_METHOD", name);
|
||
break;
|
||
case semantic_node_type.common_namespace_function_node:
|
||
if ((targets & AttributeTargets.Method) != AttributeTargets.Method && qualifier != SemanticTree.attribute_qualifier_kind.return_kind)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_METHOD", name);
|
||
break;
|
||
case semantic_node_type.class_field:
|
||
if ((targets & AttributeTargets.Field) != AttributeTargets.Field)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_FIELD", name);
|
||
break;
|
||
case semantic_node_type.common_property_node:
|
||
if ((targets & AttributeTargets.Property) != AttributeTargets.Property)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_PROPERTY", name);
|
||
break;
|
||
case semantic_node_type.common_namespace_event:
|
||
case semantic_node_type.common_event:
|
||
if ((targets & AttributeTargets.Event) != AttributeTargets.Event)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_EVENT", name);
|
||
break;
|
||
case semantic_node_type.common_parameter:
|
||
if ((targets & AttributeTargets.Parameter) != AttributeTargets.Parameter)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_FIELD", name);
|
||
break;
|
||
case semantic_node_type.common_unit_node:
|
||
if ((targets & AttributeTargets.Assembly) != AttributeTargets.Assembly)
|
||
AddError(loc, "ATTRIBUTE_{0}_NOT_APPLICABLE_TO_ASSEMBLY", name);
|
||
break;
|
||
}
|
||
}
|
||
|
||
private bool has_field_offset_attribute(attributes_list attrs)
|
||
{
|
||
foreach (attribute_node attr in attrs)
|
||
{
|
||
if (attr.attribute_type == SystemLibrary.SystemLibrary.field_offset_attribute_type)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private void check_all_fields_have_field_offset_attr(common_type_node ctn)
|
||
{
|
||
foreach (class_field cf in ctn.fields)
|
||
{
|
||
if (!has_field_offset_attribute(cf.attributes))
|
||
AddError(cf.loc, "FIELD_MUST_HAVE_FIELD_OFFSET_ATTRIBUTE");
|
||
}
|
||
}
|
||
|
||
private void make_attributes_for_declaration(SyntaxTree.declaration td, definition_node ctn)
|
||
{
|
||
if (td.attributes != null)
|
||
{
|
||
Hashtable ht = new Hashtable();
|
||
foreach (SyntaxTree.simple_attribute_list sal in td.attributes.attributes)
|
||
for (int j = 0; j < sal.attributes.Count; j++)
|
||
{
|
||
SyntaxTree.attribute attr = sal.attributes[j];
|
||
attribute_converted = true;
|
||
type_node tn = convert_strong(attr.type);
|
||
bool is_attr = false;
|
||
type_node tmp = tn;
|
||
while (tmp.base_type != null && !is_attr)
|
||
{
|
||
is_attr = tmp.base_type == SystemLibrary.SystemLibrary.attribute_type;
|
||
tmp = tmp.base_type;
|
||
}
|
||
if (!is_attr)
|
||
AddError(get_location(attr), "CLASS_{0}_NOT_ATTRIBUTE", tn.name);
|
||
bool allowMultiple = false;
|
||
AttributeTargets targets = get_usage_attrs(tn, out allowMultiple);
|
||
if (ht.Contains(tn) && !allowMultiple)
|
||
{
|
||
AddError(get_location(attr), "DUPLICATE_ATTRIBUTE_{0}_APPLICATION", tn.name);
|
||
}
|
||
else
|
||
ht[tn] = tn;
|
||
SemanticTree.attribute_qualifier_kind qualifier = SemanticTree.attribute_qualifier_kind.none_kind;
|
||
if (attr.qualifier != null)
|
||
if (j == 0)
|
||
{
|
||
if (string.Compare(attr.qualifier.name, "return", true) == 0)
|
||
{
|
||
if (context.top_function == null)
|
||
AddError(get_location(attr), "ATTRIBUTE_APPLICABLE_ONLY_TO_METHOD");
|
||
if (context.top_function.return_value_type == null || context.top_function.return_value_type == SystemLibrary.SystemLibrary.void_type)
|
||
AddError(get_location(attr), "EXPECTED_RETURN_VALUE_FOR_ATTRIBUTE");
|
||
throw new NotSupportedError(get_location(attr.qualifier));
|
||
qualifier = SemanticTree.attribute_qualifier_kind.return_kind;
|
||
}
|
||
else
|
||
throw new NotSupportedError(get_location(attr.qualifier));
|
||
}
|
||
else
|
||
AddError(get_location(attr.qualifier), "ATTRIBUTE_QUALIFIER_MUST_BE_FIRST");
|
||
check_for_usage_attribute(ctn, targets, tn.name, get_location(attr), qualifier);
|
||
|
||
attribute_converted = false;
|
||
SyntaxTree.expression_list cnstr_args = new SyntaxTree.expression_list();
|
||
if (attr.arguments != null)
|
||
{
|
||
foreach (SyntaxTree.expression e in attr.arguments.expressions)
|
||
{
|
||
if (e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal
|
||
&& (e as SyntaxTree.bin_expr).left is SyntaxTree.ident)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
cnstr_args.expressions.Add(e);
|
||
}
|
||
}
|
||
}
|
||
expressions_list args = new expressions_list();
|
||
for (int i = 0; i < cnstr_args.expressions.Count; i++)
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]);
|
||
check_for_strong_constant(cn, get_location(cnstr_args.expressions[i]));
|
||
args.AddElement(cn);
|
||
}
|
||
|
||
base_function_call bfc = create_constructor_call(tn, args, get_location(attr));
|
||
if (ctn is common_type_node && tn == SystemLibrary.SystemLibrary.struct_layout_attribute_type)
|
||
{
|
||
if ((System.Runtime.InteropServices.LayoutKind)Convert.ToInt32((args[0] as constant_node).get_object_value()) == System.Runtime.InteropServices.LayoutKind.Explicit)
|
||
{
|
||
check_all_fields_have_field_offset_attr(ctn as common_type_node);
|
||
}
|
||
}
|
||
attribute_node attr_node = new attribute_node(bfc.simple_function_node, tn, get_location(td));
|
||
foreach (expression_node en in bfc.parameters)
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(en, en.type);
|
||
check_for_strong_constant(cn, en.location);
|
||
attr_node.args.Add(cn);
|
||
}
|
||
if (attr.arguments != null)
|
||
{
|
||
for (int i = cnstr_args.expressions.Count; i < attr.arguments.expressions.Count; i++)
|
||
{
|
||
SyntaxTree.expression e = attr.arguments.expressions[i];
|
||
if (!(e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal
|
||
&& (e as SyntaxTree.bin_expr).left is SyntaxTree.ident))
|
||
{
|
||
AddError(get_location(e), "EXPECTED_ATTRIBUTE_INITIALIZER");
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.ident id = (e as SyntaxTree.bin_expr).left as SyntaxTree.ident;
|
||
SymbolInfo si = tn.find_in_type(id.name);
|
||
definition_node dn = context.check_name_node_type(id.name, si, get_location(id), general_node_type.property_node, general_node_type.variable_node);
|
||
type_node mem_tn = null;
|
||
if (dn is property_node)
|
||
{
|
||
property_node pn = dn as property_node;
|
||
attr_node.prop_names.Add(pn);
|
||
if (pn.set_function == null)
|
||
AddError(new ThisPropertyCanNotBeWrited(pn, get_location(id)));
|
||
if (pn.set_function.parameters.Count != 1)
|
||
AddError(get_location(id), "INDEX_PROPERTY_INITIALIZING_NOT_VALID");
|
||
mem_tn = pn.set_function.parameters[0].type;
|
||
}
|
||
else if (dn is var_definition_node)
|
||
{
|
||
attr_node.field_names.Add(dn as var_definition_node);
|
||
mem_tn = (dn as var_definition_node).type;
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Bad general node type for attribute initializer");
|
||
}
|
||
//SyntaxTree.assign tmp_ass = new SyntaxTree.assign(id,(e as SyntaxTree.bin_expr).right,SyntaxTree.Operators.Assignment);
|
||
//tmp_ass.source_context = e.source_context;
|
||
//basic_function_call tmp_bfc = convert_strong(tmp_ass) as basic_function_call;
|
||
constant_node cn = convert_strong_to_constant_node((e as SyntaxTree.bin_expr).right, mem_tn);
|
||
check_for_strong_constant(cn, get_location((e as SyntaxTree.bin_expr).right));
|
||
if (dn is property_node)
|
||
attr_node.prop_initializers.Add(cn);
|
||
else
|
||
attr_node.field_initializers.Add(cn);
|
||
}
|
||
}
|
||
}
|
||
attr_node.qualifier = qualifier;
|
||
ctn.attributes.AddElement(attr_node);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void make_attributes_for_declaration(SyntaxTree.unit_module un, common_unit_node cun)
|
||
{
|
||
if (cun.attributes != null)
|
||
{
|
||
Hashtable ht = new Hashtable();
|
||
foreach (SyntaxTree.simple_attribute_list sal in un.attributes.attributes)
|
||
for (int j = 0; j < sal.attributes.Count; j++)
|
||
{
|
||
SyntaxTree.attribute attr = sal.attributes[j];
|
||
attribute_converted = true;
|
||
type_node tn = convert_strong(attr.type);
|
||
bool is_attr = false;
|
||
type_node tmp = tn;
|
||
while (tmp.base_type != null && !is_attr)
|
||
{
|
||
is_attr = tmp.base_type == SystemLibrary.SystemLibrary.attribute_type;
|
||
tmp = tmp.base_type;
|
||
}
|
||
if (!is_attr)
|
||
AddError(get_location(attr), "CLASS_{0}_NOT_ATTRIBUTE", tn.name);
|
||
bool allowMultiple = false;
|
||
AttributeTargets targets = get_usage_attrs(tn, out allowMultiple);
|
||
if (ht.Contains(tn) && !allowMultiple)
|
||
{
|
||
AddError(get_location(attr), "DUPLICATE_ATTRIBUTE_{0}_APPLICATION", tn.name);
|
||
}
|
||
else
|
||
ht[tn] = tn;
|
||
SemanticTree.attribute_qualifier_kind qualifier = SemanticTree.attribute_qualifier_kind.none_kind;
|
||
if (attr.qualifier != null)
|
||
if (j == 0)
|
||
{
|
||
if (string.Compare(attr.qualifier.name, "return", true) == 0)
|
||
{
|
||
if (context.top_function == null)
|
||
AddError(get_location(attr), "ATTRIBUTE_APPLICABLE_ONLY_TO_METHOD");
|
||
if (context.top_function.return_value_type == null || context.top_function.return_value_type == SystemLibrary.SystemLibrary.void_type)
|
||
AddError(get_location(attr), "EXPECTED_RETURN_VALUE_FOR_ATTRIBUTE");
|
||
throw new NotSupportedError(get_location(attr.qualifier));
|
||
qualifier = SemanticTree.attribute_qualifier_kind.return_kind;
|
||
}
|
||
else
|
||
throw new NotSupportedError(get_location(attr.qualifier));
|
||
}
|
||
else
|
||
AddError(get_location(attr.qualifier), "ATTRIBUTE_QUALIFIER_MUST_BE_FIRST");
|
||
check_for_usage_attribute(cun, targets, tn.name, get_location(attr), qualifier);
|
||
|
||
attribute_converted = false;
|
||
SyntaxTree.expression_list cnstr_args = new SyntaxTree.expression_list();
|
||
if (attr.arguments != null)
|
||
{
|
||
foreach (SyntaxTree.expression e in attr.arguments.expressions)
|
||
{
|
||
if (e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal
|
||
&& (e as SyntaxTree.bin_expr).left is SyntaxTree.ident)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
cnstr_args.expressions.Add(e);
|
||
}
|
||
}
|
||
}
|
||
expressions_list args = new expressions_list();
|
||
for (int i = 0; i < cnstr_args.expressions.Count; i++)
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]);
|
||
check_for_strong_constant(cn, get_location(cnstr_args.expressions[i]));
|
||
args.AddElement(cn);
|
||
}
|
||
|
||
base_function_call bfc = create_constructor_call(tn, args, get_location(attr));
|
||
attribute_node attr_node = new attribute_node(bfc.simple_function_node, tn, get_location(un));
|
||
foreach (expression_node en in bfc.parameters)
|
||
{
|
||
constant_node cn = convert_strong_to_constant_node(en, en.type);
|
||
check_for_strong_constant(cn, en.location);
|
||
attr_node.args.Add(cn);
|
||
}
|
||
if (attr.arguments != null)
|
||
{
|
||
for (int i = cnstr_args.expressions.Count; i < attr.arguments.expressions.Count; i++)
|
||
{
|
||
SyntaxTree.expression e = attr.arguments.expressions[i];
|
||
if (!(e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal
|
||
&& (e as SyntaxTree.bin_expr).left is SyntaxTree.ident))
|
||
{
|
||
AddError(get_location(e), "EXPECTED_ATTRIBUTE_INITIALIZER");
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.ident id = (e as SyntaxTree.bin_expr).left as SyntaxTree.ident;
|
||
SymbolInfo si = tn.find(id.name);
|
||
definition_node dn = context.check_name_node_type(id.name, si, get_location(id), general_node_type.property_node, general_node_type.variable_node);
|
||
type_node mem_tn = null;
|
||
if (dn is property_node)
|
||
{
|
||
property_node pn = dn as property_node;
|
||
attr_node.prop_names.Add(pn);
|
||
if (pn.set_function == null)
|
||
AddError(new ThisPropertyCanNotBeWrited(pn, get_location(id)));
|
||
if (pn.set_function.parameters.Count != 1)
|
||
AddError(get_location(id), "INDEX_PROPERTY_INITIALIZING_NOT_VALID");
|
||
mem_tn = pn.set_function.parameters[0].type;
|
||
}
|
||
else if (dn is var_definition_node)
|
||
{
|
||
attr_node.field_names.Add(dn as var_definition_node);
|
||
mem_tn = (dn as var_definition_node).type;
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Bad general node type for attribute initializer");
|
||
}
|
||
constant_node cn = convert_strong_to_constant_node((e as SyntaxTree.bin_expr).right, mem_tn);
|
||
check_for_strong_constant(cn, get_location((e as SyntaxTree.bin_expr).right));
|
||
if (dn is property_node)
|
||
attr_node.prop_initializers.Add(cn);
|
||
else
|
||
attr_node.field_initializers.Add(cn);
|
||
}
|
||
}
|
||
}
|
||
attr_node.qualifier = qualifier;
|
||
cun.attributes.AddElement(attr_node);
|
||
if (cun.namespaces.Count > 0)
|
||
cun.namespaces[0].attributes.AddElement(attr_node);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void check_for_strong_constant(constant_node cn, location loc)
|
||
{
|
||
switch (cn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.bool_const_node :
|
||
case semantic_node_type.byte_const_node :
|
||
case semantic_node_type.char_const_node :
|
||
case semantic_node_type.sbyte_const_node :
|
||
case semantic_node_type.short_const_node :
|
||
case semantic_node_type.ushort_const_node :
|
||
case semantic_node_type.int_const_node :
|
||
case semantic_node_type.uint_const_node :
|
||
case semantic_node_type.long_const_node :
|
||
case semantic_node_type.ulong_const_node :
|
||
case semantic_node_type.float_const_node :
|
||
case semantic_node_type.double_const_node :
|
||
case semantic_node_type.string_const_node :
|
||
case semantic_node_type.enum_const :
|
||
case semantic_node_type.null_const_node :
|
||
return;
|
||
default:
|
||
AddError(loc, "CONSTANT_EXPRESSION_EXPECTED");
|
||
break;
|
||
}
|
||
}
|
||
|
||
internal void check_for_type_allowed(type_node tn, location loc)
|
||
{
|
||
if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
AddError(loc, "TYPE_{0}_NOT_VALID", tn.name);
|
||
}
|
||
|
||
private void check_cycle_inheritance(common_type_node cnode, type_node base_of_cnode)
|
||
{
|
||
List<common_type_node> base_params = new List<common_type_node>();
|
||
base_params.Add(cnode);
|
||
common_type_node bt = base_of_cnode as common_type_node;
|
||
while (bt != null && bt.is_generic_parameter)
|
||
{
|
||
if (base_params.Contains(bt))
|
||
{
|
||
AddError(bt.loc, "TYPE_{0}_DERIVED_FROM_ITSELF", bt.name);
|
||
}
|
||
base_params.Add(bt);
|
||
bt = bt.base_type as common_type_node;
|
||
}
|
||
}
|
||
|
||
private void visit_where_list(SyntaxTree.where_definition_list where_list)
|
||
{
|
||
if (where_list == null)
|
||
{
|
||
return;
|
||
}
|
||
context.BeginSkipGenericInstanceChecking();
|
||
List<SemanticTree.ICommonTypeNode> gparams = null;
|
||
common_function_node cfn = context.top_function;
|
||
if (cfn != null)
|
||
{
|
||
if (!cfn.is_generic_function)
|
||
{
|
||
AddError(get_location(where_list), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS");
|
||
return;
|
||
}
|
||
gparams = cfn.generic_params;
|
||
}
|
||
else
|
||
{
|
||
if (!context.converted_type.is_generic_type_definition)
|
||
{
|
||
AddError(get_location(where_list), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS");
|
||
return;
|
||
}
|
||
gparams = context.converted_type.generic_params;
|
||
}
|
||
List<common_type_node> used_types = new List<common_type_node>(where_list.defs.Count);
|
||
foreach (SyntaxTree.where_definition wd in where_list.defs)
|
||
{
|
||
bool param_not_found = true;
|
||
foreach (common_type_node param in gparams)
|
||
{
|
||
if (String.Equals(param.name, wd.names.idents[0].name, StringComparison.InvariantCultureIgnoreCase))
|
||
{
|
||
//Нашли нужный шаблонный параметр
|
||
if (used_types.Contains(param))
|
||
{
|
||
AddError(get_location(wd.names), "SPECIFICATORS_FOR_{0}_ALREADY_EXIST", wd.names.idents[0].name);
|
||
}
|
||
add_generic_eliminations(param, wd.types.defs);
|
||
used_types.Add(param);
|
||
param_not_found = false;
|
||
break;
|
||
}
|
||
}
|
||
if (param_not_found)
|
||
{
|
||
AddError(new UndefinedNameReference(wd.names.idents[0].name, get_location(wd.names)));
|
||
}
|
||
}
|
||
context.EndSkipGenericInstanceChecking();
|
||
}
|
||
|
||
//Добавляет ограничители для параметра шаблона
|
||
private void add_generic_eliminations(common_type_node param, List<SyntaxTree.type_definition> specificators)
|
||
{
|
||
Hashtable used_interfs = new Hashtable();
|
||
for (int i = 0; i < specificators.Count; ++i)
|
||
{
|
||
SyntaxTree.declaration_specificator ds = specificators[i] as SyntaxTree.declaration_specificator;
|
||
if (ds != null)
|
||
{
|
||
switch (ds.specificator)
|
||
{
|
||
case SyntaxTree.DeclarationSpecificator.WhereDefClass:
|
||
if (i == 0)
|
||
{
|
||
param.is_class = true;
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(specificators[i]), "CLASS_OR_RECORD_SPECIFICATOR_MUST_BE_FIRST");
|
||
}
|
||
break;
|
||
case SyntaxTree.DeclarationSpecificator.WhereDefValueType:
|
||
if (i == 0)
|
||
{
|
||
param.internal_is_value = true;
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(specificators[i]), "CLASS_OR_RECORD_SPECIFICATOR_MUST_BE_FIRST");
|
||
}
|
||
break;
|
||
case SyntaxTree.DeclarationSpecificator.WhereDefConstructor:
|
||
if (i == specificators.Count - 1)
|
||
{
|
||
generic_parameter_eliminations.add_default_ctor(param);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(specificators[i]), "CONSTRUCTOR_SPECIFICATOR_MUST_BE_LAST");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.named_type_reference ntr = specificators[i] as SyntaxTree.named_type_reference;
|
||
if (ntr == null)
|
||
{
|
||
AddError(get_location(specificators[i]), "SPECIFICATOR_MUST_BE_TYPE_REFERENCE");
|
||
}
|
||
else
|
||
{
|
||
type_node spec_type = ret.visit(ntr);
|
||
if (spec_type is ref_type_node || spec_type == SystemLibrary.SystemLibrary.void_type || spec_type == SystemLibrary.SystemLibrary.pointer_type)
|
||
ErrorsList.Add(new SimpleSemanticError(get_location(specificators[i]), "INAVLID_TYPE"));
|
||
if (spec_type.IsInterface)
|
||
{
|
||
if (used_interfs[spec_type] != null)
|
||
{
|
||
AddError(get_location(specificators[i]), "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", spec_type.PrintableName);
|
||
}
|
||
else
|
||
{
|
||
used_interfs.Add(spec_type, spec_type);
|
||
}
|
||
//Добавляем интерфейс
|
||
type_table.AddInterface(param, spec_type, get_location(specificators[i]));
|
||
}
|
||
else
|
||
{
|
||
if (i != 0)
|
||
{
|
||
AddError(get_location(specificators[i]), "PARENT_SPECIFICATOR_MUST_BE_FIRST");
|
||
}
|
||
else
|
||
{
|
||
//Тип-предок
|
||
if (spec_type == SystemLibrary.SystemLibrary.object_type)
|
||
{
|
||
AddError(get_location(specificators[i]), "OBJECT_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR");
|
||
}
|
||
if (spec_type == SystemLibrary.SystemLibrary.enum_base_type)
|
||
{
|
||
AddError(get_location(specificators[i]), "ENUM_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR");
|
||
}
|
||
check_cycle_inheritance(param, spec_type);
|
||
param.SetBaseType(spec_type);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
InitInterfaceScope(param);
|
||
}
|
||
|
||
private bool is_direct_type_decl = false;
|
||
|
||
private bool FunctionExsistsInSymbolInfo(function_node fn, SymbolInfo si)
|
||
{
|
||
while (si != null)
|
||
{
|
||
if (si.sym_info is function_node)
|
||
if (convertion_data_and_alghoritms.function_eq_params(fn, si.sym_info as function_node))
|
||
return true;
|
||
si = si.Next;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
internal bool body_exists;
|
||
|
||
internal bool current_converted_method_not_in_class_defined = false;
|
||
internal bool assign_is_converting = false;
|
||
|
||
//lroman//
|
||
public void visit_lambda_header(SyntaxTree.function_header _function_header, SyntaxTree.proc_block proc_body)
|
||
{
|
||
hard_node_test_and_visit(_function_header.name);
|
||
if (context.converted_template_type != null)
|
||
{
|
||
return;
|
||
}
|
||
if (_function_header.template_args != null)
|
||
{
|
||
visit_generic_params(context.top_function, _function_header.template_args.idents);
|
||
}
|
||
SymbolInfo si = context.create_special_names();
|
||
weak_node_test_and_visit(_function_header.parameters);
|
||
type_node tn = null;
|
||
|
||
#region Вывод типа возвращаемого значения лямбды
|
||
|
||
//lroman//
|
||
if (LambdaHelper.IsLambdaName(_function_header.name.meth_name))
|
||
{
|
||
if (_function_header.return_type != null && _function_header.return_type is SyntaxTree.lambda_inferred_type)
|
||
LambdaHelper.InferResultType(_function_header, proc_body, this);
|
||
}
|
||
//\lroman//
|
||
|
||
#endregion
|
||
|
||
if (_function_header.return_type == null)
|
||
{
|
||
if (context.top_function.IsOperator)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
}
|
||
if (_function_header.return_type != null)
|
||
{
|
||
check_parameter_on_complex_type(_function_header.return_type);
|
||
tn = convert_strong(_function_header.return_type);
|
||
//if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
// AddError(new VoidNotValid(get_location(_function_header.return_type)));
|
||
check_for_type_allowed(tn,get_location(_function_header.return_type));
|
||
}
|
||
//(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения
|
||
context.top_function.return_value_type = tn;
|
||
assign_doc_info(context.top_function,_function_header);
|
||
if (_function_header.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_function_header, context.top_function);
|
||
}
|
||
if (context.converted_type != null && has_dll_import_attribute(context.top_function))
|
||
AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD");
|
||
if (_function_header.name.class_name != null)
|
||
with_class_name = true;
|
||
if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes))
|
||
{
|
||
SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static);
|
||
pa.source_context = _function_header.source_context;
|
||
_function_header.proc_attributes.proc_attributes.Add(pa);
|
||
}
|
||
weak_node_test_and_visit(_function_header.proc_attributes);
|
||
if (context.top_function.IsOperator)
|
||
{
|
||
common_method_node cmmn = context.top_function as common_method_node;
|
||
//if (cmmn == null)
|
||
//{
|
||
// throw new OverloadOperatorMustBeStaticFunction(get_location(_function_header), context.top_function);
|
||
//}
|
||
if (cmmn != null && cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||
}
|
||
if (cmmn != null && (cmmn.name == compiler_string_consts.implicit_operator_name || cmmn.name == compiler_string_consts.explicit_operator_name))
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName);
|
||
}
|
||
else if (convertion_data_and_alghoritms.eq_type_nodes(tn,cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION");
|
||
}
|
||
}
|
||
with_class_name = false;
|
||
if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator)
|
||
{
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value;
|
||
if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type)
|
||
{
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
pt = PascalABCCompiler.SemanticTree.parameter_type.var;
|
||
}
|
||
if (!has_extensionmethod_attr(_function_header.proc_attributes.proc_attributes))
|
||
{
|
||
common_parameter cp = new common_parameter(compiler_string_consts.self_word, (context.top_function as common_namespace_function_node).ConnectedToType, pt,
|
||
context.top_function, cpt, null, null);
|
||
context.top_function.parameters.AddElementFirst(cp);
|
||
context.top_function.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(cp));
|
||
}
|
||
}
|
||
CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header));
|
||
|
||
bool unique = context.close_function_params(body_exists);
|
||
if (context.top_function.return_value_type == null)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
if (_function_header.where_defs != null)
|
||
{
|
||
if (unique)
|
||
{
|
||
visit_where_list(_function_header.where_defs);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION");
|
||
}
|
||
}
|
||
convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si);
|
||
|
||
//TODO: Разобрать подробнее.
|
||
if (!body_exists)
|
||
{
|
||
if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node)
|
||
|| ((context.func_stack_size_is_one()) && (_is_interface_part)))
|
||
{
|
||
//context.leave_block();
|
||
}
|
||
}
|
||
body_exists = false;
|
||
}
|
||
//\lroman//
|
||
|
||
public override void visit(SyntaxTree.procedure_definition _procedure_definition)
|
||
{
|
||
// SSM 20.07.13 если это - узел с коротким определением функции без типа возвращаемого значения, то вывести этот тип
|
||
var fh = (_procedure_definition.proc_header as SyntaxTree.function_header);
|
||
if (fh != null && fh.return_type == null)
|
||
{
|
||
var bl = _procedure_definition.proc_body as SyntaxTree.block;
|
||
if (bl != null && bl.program_code != null)
|
||
{
|
||
if (bl.program_code.subnodes.Count != 1)
|
||
AddError(get_location(fh.name), "ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED");
|
||
|
||
var ass = bl.program_code.subnodes[0] as SyntaxTree.assign;
|
||
if (ass != null && ass.to is ident && (ass.to as ident).name.ToLower()=="result")
|
||
{
|
||
if (ass.from is nil_const)
|
||
AddError(get_location(ass.from), "CAN_NOT_DEDUCE_TYPE_{0}","nil");
|
||
|
||
// undefined_type означает, что где-то в будущем это надо исправить. Потому что и Result будет этого типа
|
||
var typ = new semantic_type_node(new undefined_type("#Und",null));//SyntaxTreeBuilder.BuildSameType(ass.from);
|
||
fh.return_type = typ;
|
||
}
|
||
else AddError(get_location(fh.name), "ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED");
|
||
}
|
||
}
|
||
//\ SSM
|
||
|
||
var proc_name = _procedure_definition.proc_header != null && _procedure_definition.proc_header.name != null
|
||
? _procedure_definition.proc_header.name.meth_name
|
||
: null;
|
||
if (_procedure_definition.proc_header.attributes != null && context.converted_func_stack.size >= 1)
|
||
AddError(get_location(_procedure_definition.proc_header), "ATTRIBUTES_FOR_NESTED_FUNCTIONS_NOT_ALLOWED");
|
||
if (context.top_function != null && context.top_function.generic_params != null && !LambdaHelper.IsLambdaName(proc_name))
|
||
AddError(get_location(_procedure_definition.proc_header), "NESTED_FUNCTIONS_IN_GENERIC_FUNCTIONS_NOT_ALLOWED");
|
||
if (context.top_function != null && _procedure_definition.proc_header.template_args != null && !LambdaHelper.IsLambdaName(proc_name))
|
||
AddError(get_location(_procedure_definition.proc_header), "GENERIC_NESTED_FUNCTIONS_NOT_ALLOWED");
|
||
if (_procedure_definition.proc_header.name != null)
|
||
current_converted_method_not_in_class_defined = _procedure_definition.proc_header.name.class_name != null;
|
||
else
|
||
{
|
||
if (_procedure_definition.proc_header is SyntaxTree.constructor)
|
||
{
|
||
current_converted_method_not_in_class_defined = false;
|
||
}
|
||
}
|
||
bool must_visit_body = true;
|
||
if (SemanticRules.OrderIndependedMethodNames && !disable_order_independ && context.converting_block() == block_type.type_block && _procedure_definition.proc_body != null)
|
||
{
|
||
if (_procedure_definition.proc_header.name != null)
|
||
{
|
||
if (_procedure_definition.proc_header.name.class_name == null)
|
||
{
|
||
must_visit_body = false;
|
||
context.is_order_independed_method_description = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
must_visit_body = false;
|
||
context.is_order_independed_method_description = true;
|
||
}
|
||
}
|
||
if (SemanticRules.OrderIndependedFunctionNames && !disable_order_independ && context.converting_block() == block_type.namespace_block && _procedure_definition.proc_body != null && _procedure_definition.proc_header.name.class_name == null)
|
||
{
|
||
if (_procedure_definition.proc_header.name != null)
|
||
{
|
||
if (_procedure_definition.proc_header.name.class_name == null)
|
||
{
|
||
must_visit_body = false;
|
||
context.is_order_independed_method_description = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
must_visit_body = false;
|
||
context.is_order_independed_method_description = true;
|
||
}
|
||
}
|
||
//ssyy
|
||
if (context.converting_block() == block_type.type_block &&
|
||
context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_definition), "INVALID_INTERFACE_MEMBER");
|
||
}
|
||
//\ssyy
|
||
|
||
//ssyy добавил
|
||
if (context.converting_block() == block_type.function_block)
|
||
{
|
||
common_method_node cmnode = context.top_function as common_method_node;
|
||
if (cmnode != null && cmnode.is_constructor)
|
||
{
|
||
//throw new NotSupportedError(get_location(_procedure_definition));
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
if (_procedure_definition.proc_body == null)
|
||
{
|
||
body_exists = false;
|
||
}
|
||
else
|
||
{
|
||
body_exists = true;
|
||
}
|
||
|
||
//lroman//
|
||
if (_procedure_definition != null &&
|
||
_procedure_definition.proc_header != null &&
|
||
_procedure_definition.proc_header is SyntaxTree.function_header &&
|
||
_procedure_definition.proc_header.name != null &&
|
||
_procedure_definition.proc_header.name.meth_name != null &&
|
||
LambdaHelper.IsLambdaName(_procedure_definition.proc_header.name.meth_name))
|
||
{
|
||
//!!!!!!!!!!!!!!!!!!
|
||
convertion_data_and_alghoritms.check_node_parser_error(_procedure_definition.proc_header);
|
||
visit_lambda_header(_procedure_definition.proc_header as SyntaxTree.function_header, _procedure_definition.proc_body);
|
||
}
|
||
else
|
||
{
|
||
hard_node_test_and_visit(_procedure_definition.proc_header);
|
||
}
|
||
//\lroman//
|
||
|
||
|
||
//ssyy
|
||
if (context.converted_template_type != null)
|
||
{
|
||
if ((context.converted_template_type.type_dec.type_def as SyntaxTree.class_definition).keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface)
|
||
{
|
||
AddError(new InterfaceFunctionWithBody(get_location(_procedure_definition)));
|
||
}
|
||
context.converted_template_type.external_methods.Add(
|
||
new procedure_definition_info(context.converted_namespace, _procedure_definition));
|
||
context.converted_template_type = null;
|
||
return;
|
||
}
|
||
//\ssyy
|
||
if (context.top_function == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// frninja 20/05/16 - ставим флаг is_yield_helper
|
||
if (context.top_function is common_namespace_function_node)
|
||
{
|
||
(context.top_function as common_namespace_function_node).is_yield_helper = _procedure_definition.proc_header.is_yield_helper;
|
||
}
|
||
// end frninja
|
||
|
||
if (context.converted_explicit_interface_type != null)
|
||
(context.top_function as common_method_node).explicit_interface = context.converted_explicit_interface_type;
|
||
if (has_dll_import_attribute(context.top_function))
|
||
{
|
||
if (_procedure_definition.proc_body != null)
|
||
if (!is_pinvoke(_procedure_definition.proc_body))
|
||
AddError(get_location(_procedure_definition.proc_body), "EXPECTED_EXTERNAL_STATEMENT");
|
||
}
|
||
|
||
if (contextChanger.IsActive())
|
||
{
|
||
must_visit_body = true;
|
||
}
|
||
|
||
if (context.top_function.return_value_type is undefined_type) // значит, это короткое определение функции, и тело есть, и его надо обойти
|
||
{
|
||
must_visit_body = true;
|
||
}
|
||
|
||
// try
|
||
{
|
||
|
||
if (context.top_function.is_forward)
|
||
{
|
||
if (_procedure_definition.proc_body != null)
|
||
{
|
||
AddError(context.top_function.loc, "FORWARD_DEFINITION_WITH_FUNCTION_BODY");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (must_visit_body)
|
||
{
|
||
common_method_node cmn = context.top_function as common_method_node;
|
||
|
||
// frninja 3/06/16 - ставим флаг is_yield_helper для предописанных методов класса
|
||
if (cmn != null)
|
||
cmn.is_yield_helper = _procedure_definition.proc_header.is_yield_helper;
|
||
// end frninja
|
||
|
||
if (cmn != null && !cmn.IsStatic)
|
||
{
|
||
//if (cmn.find_only_in_namespace(compiler_string_consts.self_word) == null)
|
||
//self variable
|
||
//добавляем self, обращение к ней заменяется на this_node
|
||
type_node self_type = cmn.cont_type;
|
||
if (cmn.cont_type.is_generic_type_definition)
|
||
self_type = cmn.cont_type.get_instance(cmn.cont_type.generic_params.ConvertAll<type_node>(o => (type_node)o));
|
||
local_variable lv = new local_variable(compiler_string_consts.self_word, self_type, cmn, null);
|
||
cmn.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(lv));
|
||
cmn.self_variable = lv;
|
||
}
|
||
if (_procedure_definition.proc_body != null)
|
||
{
|
||
hard_node_test_and_visit(_procedure_definition.proc_body);
|
||
}
|
||
|
||
// SSM 12/04/16 - short func definitions - calc return_value_type
|
||
var ttt = context.top_function.return_value_type;
|
||
if (ttt is undefined_type)
|
||
{
|
||
var cd = context.top_function.function_code as statements_list;
|
||
|
||
if (cd == null || cd.statements == null || cd.statements.Count == 0)
|
||
{
|
||
AddError(context.top_function.loc, "IMPOSSIBLE!SHORT_FUNC_WITHOUT_BODY");
|
||
}
|
||
|
||
// Проблема в том, что если в теле короткого определения функции - лямбда
|
||
// и происходит захват переменной, то в тело выносится вызов конструктора сгенерированного класса
|
||
// Поэтому result := ... - это не первый оператор, а последний!!!
|
||
statement_node aa = cd.statements[cd.statements.Count-1];
|
||
var bfc = aa as basic_function_call;
|
||
if (bfc != null)
|
||
{
|
||
var ttt1 = bfc.type;
|
||
context.top_function.return_value_type = ttt1;
|
||
context.top_function.var_definition_nodes_list[0].type = ttt1;
|
||
}
|
||
}
|
||
|
||
add_clip_for_set(context.top_function);
|
||
}
|
||
else // if (!must_visit_body)
|
||
{
|
||
context.add_method_header(_procedure_definition, context.top_function);
|
||
}
|
||
|
||
}
|
||
}
|
||
//finally
|
||
{
|
||
if (_procedure_definition.proc_header.name.class_name != null)
|
||
{
|
||
// frninja 03/06/16 - убираем мусорные методы-хелперы yield
|
||
if (context._ctn != null && (context.top_function is common_method_node) && (context.top_function as common_method_node).is_yield_helper)
|
||
{
|
||
context._ctn.methods.remove(context.top_function as common_method_node);
|
||
}
|
||
// end frninja
|
||
context.leave_type_method();
|
||
}
|
||
context.is_order_independed_method_description = false;
|
||
context.leave_block();
|
||
}
|
||
}
|
||
|
||
internal void add_clip_for_set(common_function_node cfn)
|
||
{
|
||
statements_list sl = cfn.function_code as statements_list;
|
||
if (sl == null) return;
|
||
foreach (common_parameter prm in cfn.parameters)
|
||
{
|
||
if (prm.type.type_special_kind == SemanticTree.type_special_kind.set_type && prm.parameter_type == SemanticTree.parameter_type.value ||
|
||
prm.is_params && prm.type.element_type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
if (!prm.is_params)
|
||
{
|
||
ordinal_type_interface oti = prm.type.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti == null)
|
||
if (prm.type.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
base_function_call cmc2 = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info is common_namespace_function_node)
|
||
cmc2 = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc2 = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info as compiled_function_node, null);
|
||
cmc2.parameters.AddElement(new common_parameter_reference(prm,0,null));
|
||
cmc2.parameters.AddElement(new int_const_node((prm.type.element_type as short_string_type_node).Length,null));
|
||
sl.statements.AddElementFirst(cmc2);
|
||
continue;
|
||
}
|
||
else continue;
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(new common_parameter_reference(prm,0,null));
|
||
|
||
cmc.parameters.AddElement(oti.lower_value);
|
||
cmc.parameters.AddElement(oti.upper_value);
|
||
sl.statements.AddElementFirst(cmc);
|
||
}
|
||
else
|
||
{
|
||
var_definition_node var = context.create_for_temp_variable(prm.type.element_type,null);
|
||
expression_node in_what = new common_parameter_reference(prm,0,null);
|
||
statements_list what_do = new statements_list(null);
|
||
ordinal_type_interface oti = prm.type.element_type.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
bool short_str = false;
|
||
if (oti == null)
|
||
if (prm.type.element_type.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
short_str = true;
|
||
}
|
||
else continue;
|
||
base_function_call cmc = null;
|
||
if (!short_str)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipProcedure.sym_info as compiled_function_node, null);
|
||
}
|
||
else
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure.sym_info as compiled_function_node, null);
|
||
}
|
||
if (var is local_block_variable)
|
||
cmc.parameters.AddElement(new local_block_variable_reference(var as local_block_variable,null));
|
||
else
|
||
cmc.parameters.AddElement(new local_variable_reference(var as local_variable,0,null));
|
||
if (!short_str)
|
||
{
|
||
cmc.parameters.AddElement(oti.lower_value);
|
||
cmc.parameters.AddElement(oti.upper_value);
|
||
}
|
||
else
|
||
{
|
||
cmc.parameters.AddElement(new int_const_node((prm.type.element_type.element_type as short_string_type_node).Length,null));
|
||
}
|
||
what_do.statements.AddElement(cmc);
|
||
foreach_node fn = new foreach_node(var,in_what,what_do,null);
|
||
sl.statements.AddElementFirst(fn);
|
||
}
|
||
}
|
||
else if (prm.type.type_special_kind == SemanticTree.type_special_kind.short_string && prm.parameter_type == SemanticTree.parameter_type.value
|
||
|| prm.is_params && prm.type.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
if (!prm.is_params)
|
||
{
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(new common_parameter_reference(prm, 0, null));
|
||
cmc.parameters.AddElement(new int_const_node((prm.type as short_string_type_node).Length, null));
|
||
concrete_parameter_type tmp_cpt = prm.concrete_parameter_type;
|
||
prm.concrete_parameter_type = concrete_parameter_type.cpt_none;
|
||
sl.statements.AddElementFirst(find_operator(compiler_string_consts.assign_name, new common_parameter_reference(prm, 0, null), cmc, null));
|
||
prm.concrete_parameter_type = tmp_cpt;
|
||
}
|
||
else
|
||
{
|
||
common_parameter_reference cpr = new common_parameter_reference(prm, 0, null);
|
||
compiled_function_node get_func = (prm.type.find_in_type("Length").sym_info as compiled_property_node).get_function as compiled_function_node;
|
||
local_variable var = context.create_for_temp_variable(SystemLibrary.SystemLibrary.integer_type, null) as local_variable;
|
||
local_variable len_var = context.create_for_temp_variable(SystemLibrary.SystemLibrary.integer_type, null) as local_variable;
|
||
statements_list body = new statements_list(null);
|
||
//compiled_property_node item_prop = prm.type.find_in_type("Item").sym_info as compiled_property_node;
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as compiled_function_node, null);
|
||
expression_node cond = new basic_function_call(SystemLibrary.SystemLibrary.int_sm as basic_function_node, null, new local_variable_reference(var, 0, null), new local_variable_reference(len_var, 0, null));
|
||
//compiled_function_call get_item = new compiled_function_call(item_prop.get_function as compiled_function_node,cpr,null);
|
||
//get_item.parameters.AddElement(new local_variable_reference(var,0,null));
|
||
cmc.parameters.AddElement(new simple_array_indexing(cpr, new local_variable_reference(var, 0, null), prm.type.element_type, null));
|
||
cmc.parameters.AddElement(new int_const_node((prm.type.element_type as short_string_type_node).Length, null));
|
||
|
||
body.statements.AddElement(find_operator(compiler_string_consts.assign_name, new simple_array_indexing(cpr, new local_variable_reference(var, 0, null), prm.type.element_type, null), cmc, null));
|
||
body.statements.AddElement(new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node, null, new local_variable_reference(var, 0, null),
|
||
new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node, null, new local_variable_reference(var, 0, null), new int_const_node(1, null))));
|
||
|
||
|
||
while_node wn = new while_node(cond, body, null);
|
||
sl.statements.AddElementFirst(wn);
|
||
sl.statements.AddElementFirst(new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node, null,
|
||
new local_variable_reference(len_var, 0, null), new compiled_function_call(get_func, cpr, null)));
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
internal void CheckOverrideOrReintroduceExpectedWarning(location loc)
|
||
{
|
||
common_method_node cmn = context.top_function as common_method_node;
|
||
if (!current_converted_method_not_in_class_defined && cmn != null && !cmn.IsReintroduce && cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
if (context.FindMethodToOverride(cmn) != null)
|
||
{
|
||
WarningsList.Add(new OverrideOrReintroduceExpected(loc));
|
||
}
|
||
}
|
||
|
||
private procedure_header current_function_header = null;
|
||
|
||
public override void visit(SyntaxTree.function_header _function_header)
|
||
{
|
||
current_function_header = _function_header;
|
||
hard_node_test_and_visit(_function_header.name);
|
||
current_function_header = null;
|
||
if (context.converted_template_type != null)
|
||
{
|
||
return;
|
||
}
|
||
if (_function_header.template_args != null)
|
||
{
|
||
visit_generic_params(context.top_function, _function_header.template_args.idents);
|
||
}
|
||
SymbolInfo si = context.create_special_names();
|
||
weak_node_test_and_visit(_function_header.parameters);
|
||
type_node tn = null;
|
||
if (_function_header.return_type == null)
|
||
{
|
||
if (context.top_function.IsOperator)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
}
|
||
if (_function_header.return_type != null)
|
||
{
|
||
check_parameter_on_complex_type(_function_header.return_type);
|
||
tn = convert_strong(_function_header.return_type);
|
||
check_for_type_allowed(tn,get_location(_function_header.return_type));
|
||
if (_function_header.return_type is function_header || _function_header.return_type is procedure_header)
|
||
check_delegate_on_generic_parameters(tn as common_type_node, get_location(_function_header.return_type));
|
||
}
|
||
//(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения
|
||
context.top_function.return_value_type = tn;
|
||
assign_doc_info(context.top_function,_function_header);
|
||
if (_function_header.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_function_header, context.top_function);
|
||
}
|
||
if (context.converted_type != null && has_dll_import_attribute(context.top_function))
|
||
AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD");
|
||
if (_function_header.name.class_name != null)
|
||
with_class_name = true;
|
||
if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes))
|
||
{
|
||
SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static);
|
||
pa.source_context = _function_header.source_context;
|
||
_function_header.proc_attributes.proc_attributes.Add(pa);
|
||
}
|
||
weak_node_test_and_visit(_function_header.proc_attributes);
|
||
if (context.top_function.IsOperator)
|
||
{
|
||
if (context.top_function is common_method_node)
|
||
{
|
||
common_method_node cmmn = context.top_function as common_method_node;
|
||
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||
}
|
||
|
||
if ((cmmn.name == compiler_string_consts.implicit_operator_name || cmmn.name == compiler_string_consts.explicit_operator_name))
|
||
{
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName);
|
||
}
|
||
else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int expected_params = 2;
|
||
if (cmmn.name == "not")
|
||
expected_params = 1;
|
||
if ((cmmn.name == "+" || cmmn.name == "-"))
|
||
{
|
||
if (cmmn.parameters.Count != 2 && cmmn.parameters.Count != 1)
|
||
AddError(new SimpleSemanticError(cmmn.loc, "OPERATORS_SHOULD_HAVE_1_OR_2_PARAMETERS"));
|
||
}
|
||
else if (cmmn.parameters.Count != expected_params)
|
||
{
|
||
if (expected_params==1)
|
||
AddError(new SimpleSemanticError(cmmn.loc, "OPERATOR_SHOULD_HAVE_1_PARAMETER"));
|
||
else AddError(new SimpleSemanticError(cmmn.loc, "OPERATOR_SHOULD_HAVE_2_PARAMETERS"));
|
||
}
|
||
bool has_types = false;
|
||
foreach (parameter p in cmmn.parameters)
|
||
{
|
||
type_node ptn = p.type;
|
||
if (ptn.is_generic_type_instance)
|
||
ptn = ptn.original_generic;
|
||
if (ptn == cmmn.cont_type)
|
||
has_types = true;
|
||
}
|
||
if (!has_types)
|
||
AddError(new SimpleSemanticError(cmmn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cmmn.cont_type.name));
|
||
}
|
||
}
|
||
else if (context.top_function is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_node cnfn = context.top_function as common_namespace_function_node;
|
||
|
||
if ((cnfn.name == compiler_string_consts.implicit_operator_name || cnfn.name == compiler_string_consts.explicit_operator_name))
|
||
{
|
||
if (cnfn.parameters.Count != 1)
|
||
AddError(new SimpleSemanticError(cnfn.loc,"EXTENSION_METHODS_MUST_HAVE_LEAST_ONE_PARAMETER"));
|
||
if (cnfn.ConnectedToType == null)
|
||
AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_BE_EXTENSION_METHOD"));
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cnfn.ConnectedToType) && !convertion_data_and_alghoritms.eq_type_nodes(cnfn.ConnectedToType as type_node, cnfn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cnfn.ConnectedToType as type_node).PrintableName);
|
||
}
|
||
else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cnfn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int expected_params = 2;
|
||
if (cnfn.name == "not")
|
||
expected_params = 1;
|
||
if (cnfn.name == "+" || cnfn.name == "-")
|
||
{
|
||
if (cnfn.parameters.Count != 2 && cnfn.parameters.Count != 1)
|
||
AddError(new SimpleSemanticError(cnfn.loc, "OPERATORS_SHOULD_HAVE_1_OR_2_PARAMETERS"));
|
||
}
|
||
else if (cnfn.parameters.Count != expected_params)
|
||
{
|
||
if (expected_params == 1)
|
||
AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_HAVE_1_PARAMETER"));
|
||
else AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_HAVE_2_PARAMETERS"));
|
||
}
|
||
bool has_types = false;
|
||
foreach (parameter p in cnfn.parameters)
|
||
{
|
||
type_node ptn = p.type;
|
||
if (ptn.is_generic_type_instance)
|
||
ptn = ptn.original_generic;
|
||
if (cnfn.ConnectedToType != null && (ptn == cnfn.ConnectedToType || ptn == cnfn.ConnectedToType.original_generic))
|
||
has_types = true;
|
||
}
|
||
if (cnfn.ConnectedToType == null)
|
||
AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_BE_EXTENSION_METHOD"));
|
||
if (!has_types)
|
||
AddError(new SimpleSemanticError(cnfn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cnfn.ConnectedToType.name));
|
||
}
|
||
}
|
||
}
|
||
with_class_name = false;
|
||
if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator)
|
||
{
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value;
|
||
if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type)
|
||
{
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
pt = PascalABCCompiler.SemanticTree.parameter_type.var;
|
||
}
|
||
|
||
type_node cur_tn = (context.top_function as common_namespace_function_node).ConnectedToType;
|
||
type_node self_type = cur_tn;
|
||
if (context.top_function.generic_params != null && self_type.is_generic_type_definition)
|
||
{
|
||
self_type = self_type.get_instance(context.top_function.get_generic_params_list());
|
||
}
|
||
if (!has_extensionmethod_attr(_function_header.proc_attributes.proc_attributes))
|
||
{
|
||
common_parameter cp = new common_parameter(compiler_string_consts.self_word, self_type, pt,
|
||
context.top_function, cpt, null, null);
|
||
context.top_function.parameters.AddElementFirst(cp);
|
||
context.top_function.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(cp));
|
||
}
|
||
}
|
||
CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header));
|
||
common_type_node common_converted_type_tmp = context.converted_type;
|
||
compiled_type_node compiled_converted_type_tmp = context.converted_compiled_type;
|
||
common_namespace_function_node cnfn2 = context.top_function as common_namespace_function_node;
|
||
if (cnfn2 != null && cnfn2.ConnectedToType != null)
|
||
{
|
||
if (cnfn2.ConnectedToType is compiled_type_node)
|
||
context.converted_compiled_type = cnfn2.ConnectedToType as compiled_type_node;
|
||
else if (cnfn2.ConnectedToType is common_type_node)
|
||
context.converted_type = cnfn2.ConnectedToType as common_type_node;
|
||
}
|
||
|
||
bool unique = context.close_function_params(body_exists);
|
||
context.converted_type = common_converted_type_tmp;
|
||
context.converted_compiled_type = compiled_converted_type_tmp;
|
||
if (context.top_function.return_value_type == null)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
if (_function_header.where_defs != null)
|
||
{
|
||
if (unique)
|
||
{
|
||
visit_where_list(_function_header.where_defs);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION");
|
||
}
|
||
}
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
if (body_exists)
|
||
{
|
||
AddError(new InterfaceFunctionWithBody(get_location(_function_header)));
|
||
}
|
||
common_method_node cmnode = context.top_function as common_method_node;
|
||
context.set_virtual_abstract(cmnode);
|
||
}
|
||
convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si);
|
||
|
||
if (!body_exists)
|
||
{
|
||
if (_function_header.name.class_name != null && context.converted_explicit_interface_type != null)
|
||
{
|
||
AddError(get_location(_function_header), "EXPLICIT_IMPLEMENTATION_EXPECTED");
|
||
}
|
||
if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node)
|
||
|| ((context.func_stack_size_is_one()) && (_is_interface_part)))
|
||
{
|
||
context.leave_block();
|
||
}
|
||
|
||
}
|
||
body_exists = false;
|
||
}
|
||
|
||
bool has_static_attr(List<SyntaxTree.procedure_attribute> attrs)
|
||
{
|
||
foreach (SyntaxTree.procedure_attribute attr in attrs)
|
||
{
|
||
if (attr.attribute_type == PascalABCCompiler.SyntaxTree.proc_attribute.attr_static)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool has_extensionmethod_attr(List<SyntaxTree.procedure_attribute> attrs)
|
||
{
|
||
foreach (SyntaxTree.procedure_attribute attr in attrs)
|
||
{
|
||
if (attr.attribute_type == PascalABCCompiler.SyntaxTree.proc_attribute.attr_extension)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private bool has_var_char_parameters(common_function_node fn)
|
||
{
|
||
for (int i=0; i<fn.parameters.Count; i++)
|
||
{
|
||
if (fn.parameters[i].type == SystemLibrary.SystemLibrary.char_type && fn.parameters[i].parameter_type == SemanticTree.parameter_type.var)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private void visit_procedure_header(SyntaxTree.procedure_header _procedure_header)
|
||
{
|
||
if (_procedure_header.name != null && _procedure_header.name.meth_name is SyntaxTree.operator_name_ident &&
|
||
!SyntaxTree.OperatorServices.IsAssigmentOperator((_procedure_header.name.meth_name as SyntaxTree.operator_name_ident).operator_type))
|
||
{
|
||
AddError(new OverloadOperatorCanNotBeProcedure(get_location(_procedure_header)));
|
||
}
|
||
if (_procedure_header is SyntaxTree.constructor &&
|
||
(_procedure_header.template_args != null || (_procedure_header.name != null && _procedure_header.name.meth_name != null && _procedure_header.name.meth_name is SyntaxTree.template_type_name)))
|
||
{
|
||
AddError(get_location(_procedure_header), "CONSTRUCTOR_CAN_NOT_BE_GENERIC");
|
||
}
|
||
current_function_header = _procedure_header;
|
||
hard_node_test_and_visit(_procedure_header.name);
|
||
current_function_header = null;
|
||
if (context.converted_template_type != null)
|
||
{
|
||
return;
|
||
}
|
||
if (_procedure_header.template_args != null)
|
||
{
|
||
visit_generic_params(context.top_function, _procedure_header.template_args.idents);
|
||
}
|
||
weak_node_test_and_visit(_procedure_header.parameters);
|
||
if (_procedure_header.name.class_name != null)
|
||
with_class_name = true;
|
||
if (_procedure_header.class_keyword && !has_static_attr(_procedure_header.proc_attributes.proc_attributes))
|
||
{
|
||
SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static);
|
||
pa.source_context = _procedure_header.source_context;
|
||
_procedure_header.proc_attributes.proc_attributes.Add(pa);
|
||
}
|
||
|
||
weak_node_test_and_visit(_procedure_header.proc_attributes);
|
||
with_class_name = false;
|
||
CheckOverrideOrReintroduceExpectedWarning(get_location(_procedure_header));
|
||
if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator)
|
||
{
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value;
|
||
if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type)
|
||
{
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
pt = PascalABCCompiler.SemanticTree.parameter_type.var;
|
||
}
|
||
type_node cur_tn = (context.top_function as common_namespace_function_node).ConnectedToType;
|
||
type_node self_type = cur_tn;
|
||
if (context.top_function.generic_params != null && self_type.is_generic_type_definition)
|
||
{
|
||
self_type = self_type.get_instance(context.top_function.get_generic_params_list());
|
||
}
|
||
if (!has_extensionmethod_attr(_procedure_header.proc_attributes.proc_attributes))
|
||
{
|
||
common_parameter cp = new common_parameter(compiler_string_consts.self_word, self_type, pt,
|
||
context.top_function, cpt, null, null);
|
||
|
||
context.top_function.parameters.AddElementFirst(cp);
|
||
context.top_function.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(cp));
|
||
}
|
||
}
|
||
if (_procedure_header is SyntaxTree.constructor)
|
||
{
|
||
common_method_node cmnode = context.top_function as common_method_node;
|
||
if (cmnode != null)
|
||
{
|
||
cmnode.is_constructor = true;
|
||
cmnode.return_value_type = context.converted_type;
|
||
}
|
||
else if (context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null)
|
||
AddError(get_location(_procedure_header), "EXTENSION_CONSTRUCTOR_NOT_ALLOWED");
|
||
else
|
||
if (context.converted_compiled_type != null)
|
||
AddError(get_location(_procedure_header), "EXTENSION_CONSTRUCTOR_NOT_ALLOWED");
|
||
}
|
||
|
||
bool unique = context.close_function_params(body_exists);
|
||
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
if (body_exists)
|
||
{
|
||
AddError(new InterfaceFunctionWithBody(get_location(_procedure_header)));
|
||
}
|
||
common_method_node cmnode = context.top_function as common_method_node;
|
||
context.set_virtual_abstract(cmnode);
|
||
}
|
||
|
||
if (context.converted_type != null)
|
||
{
|
||
common_method_node cmnode = context.top_function as common_method_node;
|
||
if (cmnode != null && cmnode.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract && body_exists)
|
||
{
|
||
AddError(new AbstractMethodWithBody(get_location(_procedure_header)));
|
||
}
|
||
}
|
||
if (_procedure_header.where_defs != null)
|
||
{
|
||
if (unique)
|
||
{
|
||
visit_where_list(_procedure_header.where_defs);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_procedure_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION");
|
||
}
|
||
}
|
||
assign_doc_info(context.top_function,_procedure_header);
|
||
if (_procedure_header.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_procedure_header, context.top_function);
|
||
}
|
||
if (context.converted_type != null && has_dll_import_attribute(context.top_function))
|
||
AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD");
|
||
if (!body_exists)
|
||
{
|
||
if (_procedure_header.name.class_name != null && context.converted_explicit_interface_type != null)
|
||
{
|
||
AddError(get_location(_procedure_header), "EXPLICIT_IMPLEMENTATION_EXPECTED");
|
||
}
|
||
if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node)
|
||
|| ((context.func_stack_size_is_one()) && (_is_interface_part)))
|
||
{
|
||
context.leave_block();
|
||
if (_procedure_header.name.class_name != null && context.converted_compiled_type != null)
|
||
context.converted_compiled_type = null;
|
||
}
|
||
}
|
||
body_exists = false;
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.procedure_header _procedure_header)
|
||
{
|
||
visit_procedure_header(_procedure_header);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.procedure_attributes_list _procedure_attributes_list)
|
||
{
|
||
bool is_override = false;
|
||
bool is_virtual = false;
|
||
bool is_abstract = false;
|
||
string override_proc_attr=null;
|
||
string virtual_proc_attr=null;
|
||
string abstract_proc_attr = null;
|
||
for (int i = 0; i < _procedure_attributes_list.proc_attributes.Count; i++)
|
||
{
|
||
switch (_procedure_attributes_list.proc_attributes[i].attribute_type)
|
||
{
|
||
case SyntaxTree.proc_attribute.attr_abstract:
|
||
{
|
||
is_abstract = true;
|
||
abstract_proc_attr = _procedure_attributes_list.proc_attributes[i].name;
|
||
}
|
||
break;
|
||
case SyntaxTree.proc_attribute.attr_override:
|
||
{
|
||
is_override = true;
|
||
override_proc_attr = _procedure_attributes_list.proc_attributes[i].name;
|
||
}
|
||
break;
|
||
case SyntaxTree.proc_attribute.attr_virtual:
|
||
{
|
||
is_virtual = true;
|
||
virtual_proc_attr = _procedure_attributes_list.proc_attributes[i].name;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
context.top_function.is_overload = true; // SSM 12/08/15
|
||
context.last_created_function.symbol_kind = symbol_kind.sk_overload_function;
|
||
bool is_forward = false;
|
||
for (int i = 0; i < _procedure_attributes_list.proc_attributes.Count; i++)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(_procedure_attributes_list.proc_attributes[i]);
|
||
for (int j = 0; j < i; j++)
|
||
{
|
||
if (_procedure_attributes_list.proc_attributes[i].attribute_type ==
|
||
_procedure_attributes_list.proc_attributes[j].attribute_type)
|
||
{
|
||
AddError(new DuplicateAttributeDefinition(get_location(_procedure_attributes_list.proc_attributes[j]),
|
||
get_location(_procedure_attributes_list.proc_attributes[i])));
|
||
}
|
||
}
|
||
|
||
switch (_procedure_attributes_list.proc_attributes[i].attribute_type)
|
||
{
|
||
case SyntaxTree.proc_attribute.attr_overload:// ничего не делать - это и так есть
|
||
{
|
||
break;
|
||
}
|
||
case SyntaxTree.proc_attribute.attr_forward:
|
||
{
|
||
if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
//(ssyy) В интерфейсах аттрибуты недопустимы
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER");
|
||
}
|
||
common_namespace_function_node top_function = context.top_function as common_namespace_function_node;
|
||
if (top_function != null && top_function.ConnectedToType != null)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "FORWARD_EXTENSION_METHODS_NOT_ALLOWED");
|
||
}
|
||
|
||
is_forward = true;
|
||
break;
|
||
}
|
||
case SyntaxTree.proc_attribute.attr_virtual:
|
||
{
|
||
|
||
if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
//(ssyy) В интерфейсах аттрибуты недопустимы
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER");
|
||
}
|
||
|
||
//(ssyy) В записях нет виртуальных функций
|
||
if (context.converted_type != null && context.converted_type.is_value)
|
||
{
|
||
AddError(new VirtualMethodInRecord(
|
||
get_location(_procedure_attributes_list.proc_attributes[i])));
|
||
}
|
||
|
||
common_function_node ccfn = context.top_function;
|
||
if (ccfn.semantic_node_type != semantic_node_type.common_method_node)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name);
|
||
}
|
||
common_method_node cmn = ccfn as common_method_node;
|
||
if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD");
|
||
}
|
||
if (is_override)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "USING_MODIFIERS{0}_{1}_TOGETHER_NOT_ALLOWED", cmn,_procedure_attributes_list.proc_attributes[i].name,override_proc_attr);
|
||
}
|
||
if (!context.converted_type.IsAbstract || true)
|
||
{
|
||
is_virtual = true;
|
||
virtual_proc_attr = _procedure_attributes_list.proc_attributes[i].name;
|
||
if (!is_abstract)
|
||
context.set_virtual(cmn);
|
||
}
|
||
break;
|
||
}
|
||
case SyntaxTree.proc_attribute.attr_override:
|
||
case SyntaxTree.proc_attribute.attr_reintroduce:
|
||
{
|
||
if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
//(ssyy) В интерфейсах аттрибуты недопустимы
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER");
|
||
}
|
||
|
||
common_function_node ccfn = context.top_function;
|
||
if (ccfn.semantic_node_type != semantic_node_type.common_method_node)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name);
|
||
}
|
||
common_method_node cmn = ccfn as common_method_node;
|
||
if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD");
|
||
}
|
||
if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_reintroduce)
|
||
{
|
||
cmn.IsReintroduce = true;
|
||
break;
|
||
}
|
||
if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_override && is_virtual)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]),"USING_MODIFIERS{0}_{1}_TOGETHER_NOT_ALLOWED", cmn,_procedure_attributes_list.proc_attributes[i].name,virtual_proc_attr);
|
||
}
|
||
if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_override)
|
||
{
|
||
is_override = true;
|
||
override_proc_attr = _procedure_attributes_list.proc_attributes[i].name;
|
||
}
|
||
|
||
context.set_override(cmn);
|
||
if (is_abstract)
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract;
|
||
if (cmn.field_access_level < cmn.overrided_method.field_access_level)
|
||
AddError(cmn.loc, "CAN_NOT_BE_DOWN_ACCESS_LEVEL_FOR_METH");
|
||
break;
|
||
}
|
||
case SyntaxTree.proc_attribute.attr_static:
|
||
{
|
||
if (with_class_name)
|
||
{
|
||
if (context.top_function != null)
|
||
{
|
||
context.top_function.polymorphic_state = PascalABCCompiler.SemanticTree.polymorphic_state.ps_static;
|
||
break;
|
||
}
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
}
|
||
//(ssyy) В интерфейсах аттрибуты недопустимы
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER");
|
||
}
|
||
|
||
common_function_node ccfn = context.top_function;
|
||
if (ccfn.semantic_node_type != semantic_node_type.common_method_node)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "STATIC_KEYWORD_ALLOWED_ONLY_WITH_METHOD");
|
||
}
|
||
common_method_node cmn = ccfn as common_method_node;
|
||
if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD");
|
||
}
|
||
if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CANNOT_BE_ABSTRACT_STATIC_METHOD");
|
||
}
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_static;
|
||
break;
|
||
}
|
||
case SyntaxTree.proc_attribute.attr_abstract:
|
||
{
|
||
if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER");
|
||
}
|
||
common_function_node ccfn = context.top_function;
|
||
common_method_node cmn = ccfn as common_method_node;
|
||
if (cmn.is_constructor)
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name);
|
||
if (ccfn.semantic_node_type != semantic_node_type.common_method_node)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name);
|
||
}
|
||
if (context.converted_type != null && context.converted_type.is_value)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ABSTRACT_METHOD_IN_RECORD");
|
||
}
|
||
if (ccfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CANNOT_BE_ABSTRACT_STATIC_METHOD");
|
||
}
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract;
|
||
if (context.converted_type.IsSealed)
|
||
AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ABSTRACT_METHOD_IN_SEALED_CLASS");
|
||
context.converted_type.SetIsAbstract(true);
|
||
break;
|
||
}
|
||
case proc_attribute.attr_extension:
|
||
{
|
||
if (is_forward)
|
||
AddError(get_location(_procedure_attributes_list), "EXTENSIONMETHOD_KEYWORD_NOT_ALLOWED");
|
||
if (context.converted_compiled_type != null)
|
||
AddError(get_location(_procedure_attributes_list), "EXTENSIONMETHOD_KEYWORD_NOT_ALLOWED");
|
||
if (in_interface_part)
|
||
AddError(get_location(_procedure_attributes_list), "EXTENSION_METHODS_IN_INTERFACE_PART_NOT_ALLOWED");
|
||
if (!(context.top_function is common_namespace_function_node))
|
||
AddError(get_location(_procedure_attributes_list), "EXTENSION_ATTRIBUTE_ONLY_FOR_NAMESPACE_FUNCTIONS_ALLOWED");
|
||
if (context.top_function.parameters.Count == 0)
|
||
AddError(context.top_function.loc, "EXTENSION_METHODS_MUST_HAVE_LEAST_ONE_PARAMETER");
|
||
if (!context.top_function.IsOperator && context.top_function.parameters[0].parameter_type != SemanticTree.parameter_type.value)
|
||
AddError(context.top_function.loc, "FIRST_PARAMETER_SHOULDBE_ONLY_VALUE_PARAMETER");
|
||
if (!context.top_function.IsOperator && context.top_function.parameters[0].name.ToLower() != compiler_string_consts.self_word)
|
||
AddError(context.top_function.loc,"FIRST_PARAMETER_MUST_HAVE_NAME_SELF");
|
||
common_namespace_function_node top_function = context.top_function as common_namespace_function_node;
|
||
top_function.ConnectedToType = context.top_function.parameters[0].type;
|
||
if (top_function.ConnectedToType.Scope == null && top_function.ConnectedToType is compiled_type_node)
|
||
{
|
||
(top_function.ConnectedToType as compiled_type_node).init_scope();
|
||
}
|
||
if (top_function.ConnectedToType.Scope == null)
|
||
AddError(context.top_function.loc, "EXTENSION_METHODS_FOR_CONSTRUCTED_TYPES_NOT_ALLOWED");
|
||
top_function.ConnectedToType.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
if (top_function.ConnectedToType.type_special_kind == SemanticTree.type_special_kind.array_kind && top_function.ConnectedToType.element_type.is_generic_parameter)
|
||
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
else if (top_function.ConnectedToType.is_generic_parameter)
|
||
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
else if (top_function.ConnectedToType is compiled_generic_instance_type_node && top_function.ConnectedToType.original_generic.Scope != null)
|
||
top_function.ConnectedToType.original_generic.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
else if (top_function.ConnectedToType.IsDelegate && top_function.ConnectedToType.base_type.IsDelegate)
|
||
compiled_type_node.get_type_node(typeof(Delegate)).Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
else if (top_function.ConnectedToType.type_special_kind == SemanticTree.type_special_kind.typed_file && top_function.ConnectedToType.element_type.is_generic_parameter && SystemLibrary.SystemLibInitializer.TypedFileType.sym_info != null)
|
||
(SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node).Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||
if (top_function.ConnectedToType.IsDelegate && context.top_function.IsOperator && (context.top_function.name == "+" || context.top_function.name == "-" || context.top_function.name == "+=" || context.top_function.name == "-="))
|
||
AddError(get_location(_procedure_attributes_list), "CANNOT_EXTEND_STANDARD_OPERATORS_FOR_DELEGATE");
|
||
if (context.top_function.IsOperator && (context.top_function.name == compiler_string_consts.implicit_operator_name || context.top_function.name == compiler_string_consts.explicit_operator_name) && context.top_function.parameters.Count == 1 && context.top_function.return_value_type != null)
|
||
{
|
||
if (!(context.top_function.return_value_type is compiled_type_node) && !(context.top_function.return_value_type is compiled_generic_instance_type_node) || !(context.top_function.parameters[0].type is compiled_type_node) && !(context.top_function.parameters[0].type is compiled_generic_instance_type_node))
|
||
AddError(get_location(_procedure_attributes_list), "IMPLICIT_EXPLICIT_OPERATOR_EXTENSION_ONLY_FOR_COMPILED_CLASSES_ALLOWED");
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
throw new NotSupportedError(get_location(_procedure_attributes_list.proc_attributes[i]));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool first_param=false;
|
||
public override void visit(SyntaxTree.formal_parameters _formal_parametres)
|
||
{
|
||
bool default_value_met = false;
|
||
bool params_met = false;
|
||
first_param = true;
|
||
foreach (SyntaxTree.typed_parameters tp in _formal_parametres.params_list)
|
||
{
|
||
if (params_met)
|
||
{
|
||
AddError(get_location(tp), "ONLY_LAST_PARAMETER_CAN_BE_PARAMS");
|
||
}
|
||
if (tp.param_kind == PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr)
|
||
{
|
||
params_met = true;
|
||
if (default_value_met)
|
||
{
|
||
AddError(get_location(tp), "FUNCTION_WITH_PARAMS_PARAMETER_CAN_NOT_HAVE_DEFAULT_PARAMETERS");
|
||
}
|
||
}
|
||
hard_node_test_and_visit(tp);
|
||
first_param = false;
|
||
if ((default_value_met) && (tp.inital_value == null))
|
||
{
|
||
AddError(new NeedDefaultValueForParameter(get_location(tp)));
|
||
}
|
||
|
||
if (tp.inital_value != null)
|
||
{
|
||
default_value_met = true;
|
||
}
|
||
}
|
||
first_param = false;
|
||
common_method_node cnode = context.top_function as common_method_node;
|
||
if (cnode != null && cnode.IsOperator)
|
||
{
|
||
parameter_list pars = context.top_function.parameters;
|
||
if (cnode.name != compiler_string_consts.implicit_operator_name && cnode.name != compiler_string_consts.explicit_operator_name)
|
||
{
|
||
bool all_types_mismatch = true;
|
||
foreach (parameter par in pars)
|
||
{
|
||
//if (par.type == cnode.comperehensive_type)
|
||
if (convertion_data_and_alghoritms.eq_type_nodes(par.type, cnode.comperehensive_type as type_node))
|
||
{
|
||
all_types_mismatch = false;
|
||
break;
|
||
}
|
||
}
|
||
if (all_types_mismatch)
|
||
{
|
||
AddError(cnode.loc, "TYPE_OF_ONE_OR_MORE_OPERATOR_PARAMETERS_MUST_BE_{0}", ((type_node)(cnode.comperehensive_type)).PrintableName);
|
||
}
|
||
}
|
||
if (pars.Count > 0 && pars[pars.Count - 1].is_params)
|
||
{
|
||
AddError(convertion_data_and_alghoritms.get_location(pars[pars.Count - 1]), "PARAMS_IN_OPERATOR");
|
||
}
|
||
int pcount = name_reflector.get_params_count(cnode.name);
|
||
if (pcount != pars.Count)
|
||
{
|
||
if (cnode.name != compiler_string_consts.minus_name && cnode.name != compiler_string_consts.plus_name)
|
||
AddError(cnode.loc, "OPERATOR_{0}_PARAMETERS_COUNT_MUST_EQUAL_{1}", cnode.name, pcount);
|
||
else
|
||
if (pars.Count != 1 && pars.Count != 2)
|
||
AddError(cnode.loc, "OPERATOR_{0}_PARAMETERS_COUNT_MUST_EQUAL_{1}", cnode.name, pcount);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void check_parameter_on_complex_type(SyntaxTree.type_definition type)
|
||
{
|
||
SyntaxTree.array_type arr = type as SyntaxTree.array_type;
|
||
if (type is SyntaxTree.class_definition || /*type is SyntaxTree.enum_type_definition ||*/
|
||
(arr != null && arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null))
|
||
{
|
||
AddError(get_location(type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM");
|
||
}
|
||
if (context.top_function is common_method_node && (context.converted_type.IsInterface || context.top_function.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract )
|
||
&& (type is function_header || type is procedure_header))
|
||
AddError(get_location(type), "ANONYMOUS_DELEGATE_IN_INTERFACE_NOT_ALLOWED");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.typed_parameters _typed_parametres)
|
||
{
|
||
SemanticTree.parameter_type par_type = SemanticTree.parameter_type.value;
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
bool is_params = false;
|
||
switch (_typed_parametres.param_kind)
|
||
{
|
||
case SyntaxTree.parametr_kind.const_parametr:
|
||
{
|
||
par_type = SemanticTree.parameter_type.value;
|
||
cpt = concrete_parameter_type.cpt_const;
|
||
break;
|
||
}
|
||
case SyntaxTree.parametr_kind.none:
|
||
{
|
||
par_type = SemanticTree.parameter_type.value;
|
||
cpt = concrete_parameter_type.cpt_none;
|
||
break;
|
||
}
|
||
case SyntaxTree.parametr_kind.out_parametr:
|
||
{
|
||
par_type = SemanticTree.parameter_type.var;
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
break;
|
||
}
|
||
case SyntaxTree.parametr_kind.var_parametr:
|
||
{
|
||
par_type = SemanticTree.parameter_type.var;
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
break;
|
||
}
|
||
case PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr:
|
||
{
|
||
is_params = true;
|
||
break;
|
||
}
|
||
}
|
||
common_parameter com_par = null;
|
||
if (is_params)
|
||
{
|
||
if (_typed_parametres.idents.idents.Count != 1)
|
||
{
|
||
AddError(get_location(_typed_parametres.idents.idents[1]), "ONLY_ONE_PARAMS_PARAMETER_ALLOWED");
|
||
}
|
||
}
|
||
foreach (SyntaxTree.ident id in _typed_parametres.idents.idents)
|
||
{
|
||
com_par = context.add_parameter(id.name, par_type, cpt, get_location(id));
|
||
if (_typed_parametres.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_typed_parametres, com_par);
|
||
}
|
||
if (is_params)
|
||
{
|
||
com_par.intrenal_is_params = true;
|
||
}
|
||
}
|
||
|
||
if (_typed_parametres.vars_type == null)
|
||
throw new NotSupportedError(get_location(_typed_parametres));
|
||
|
||
check_parameter_on_complex_type(_typed_parametres.vars_type);
|
||
type_node tn = convert_strong(_typed_parametres.vars_type);
|
||
if (_typed_parametres.vars_type is function_header || _typed_parametres.vars_type is procedure_header)
|
||
{
|
||
check_delegate_on_generic_parameters(tn as common_type_node, get_location(_typed_parametres.vars_type));
|
||
}
|
||
check_for_type_allowed(tn,get_location(_typed_parametres.vars_type));
|
||
if (is_params)
|
||
{
|
||
internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(get_location(_typed_parametres.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED");
|
||
}
|
||
}
|
||
com_par.type = tn;
|
||
context.in_parameters_block = true;
|
||
//TODO: Доделать параметры со значениями по умолчанию.
|
||
if (_typed_parametres.inital_value != null)
|
||
{
|
||
if (_typed_parametres.idents.idents.Count != 1)
|
||
{
|
||
AddError(new OnlyOneParameterNameWithDefaultValueAllowed(get_location(_typed_parametres)));
|
||
}
|
||
if (cpt == concrete_parameter_type.cpt_var)
|
||
{
|
||
AddError(new VarParametersCanNotHaveDefaultValue(get_location(_typed_parametres)));
|
||
}
|
||
if (cpt == concrete_parameter_type.cpt_const)
|
||
{
|
||
AddError(get_location(_typed_parametres), "CONST_PARAMETERS_CANNOT_HAVE_DEFAULT_VALUE");
|
||
}
|
||
context.top_function.num_of_default_variables = context.top_function.num_of_default_variables + 1;
|
||
expression_node def_val_expr = convert_strong_to_constant_node(_typed_parametres.inital_value);
|
||
com_par.default_value = convertion_data_and_alghoritms.convert_type(def_val_expr, tn);
|
||
}
|
||
context.in_parameters_block = false;
|
||
context.close_var_definition_list(tn, null);
|
||
}
|
||
|
||
private void check_delegate_on_generic_parameters(common_type_node ctn, location loc)
|
||
{
|
||
if (ctn == null)
|
||
return;
|
||
foreach (common_method_node cmn in ctn.methods)
|
||
{
|
||
if (cmn.name == "Invoke")
|
||
{
|
||
foreach (common_parameter prm in cmn.parameters)
|
||
{
|
||
if (is_instance_of_generic_parameter(prm.type))
|
||
AddError(loc, "ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS");
|
||
}
|
||
if (cmn.return_value_type != null && is_instance_of_generic_parameter(cmn.return_value_type))
|
||
AddError(loc, "ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS");
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool is_instance_of_generic_parameter(type_node tn)
|
||
{
|
||
if (tn.is_generic_parameter)
|
||
return true;
|
||
else if (tn.is_generic_type_instance)
|
||
{
|
||
foreach (type_node inst_tn in tn.instance_params)
|
||
if (is_instance_of_generic_parameter(inst_tn))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.procedure_attribute _procedure_attribute)
|
||
{
|
||
throw new NotSupportedError(get_location(_procedure_attribute));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.label_definitions _label_definitions)
|
||
{
|
||
/*if (context.converting_block() == block_type.type_block &&
|
||
context.converted_type.IsInterface)
|
||
{
|
||
throw new InvalidInterfaceMember(get_location(_label_definitions));
|
||
}*/
|
||
foreach (SyntaxTree.ident id in _label_definitions.labels.idents)
|
||
{
|
||
context.add_label_declaration(id.name, get_location(id));
|
||
}
|
||
}
|
||
|
||
private bool depended_from_generic_parameter(type_node tn)
|
||
{
|
||
//Ivan 1.09.08 added
|
||
if (tn == null)
|
||
return false;
|
||
if (tn.is_generic_parameter)
|
||
return true;
|
||
if (tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type)
|
||
{
|
||
return depended_from_generic_parameter(tn.element_type);
|
||
}
|
||
if (tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_kind)
|
||
{
|
||
return depended_from_generic_parameter(tn.element_type);
|
||
}
|
||
ref_type_node rtn = tn as ref_type_node;
|
||
if (rtn != null)
|
||
{
|
||
return depended_from_generic_parameter(rtn.pointed_type);
|
||
}
|
||
generic_instance_type_node gitn = tn as generic_instance_type_node;
|
||
if (gitn == null)
|
||
return false;
|
||
foreach (type_node param in gitn.generic_parameters)
|
||
{
|
||
if (depended_from_generic_parameter(param))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private bool is_unsized_array(SyntaxTree.indexers_types indexes, out int rank)
|
||
{
|
||
rank = 1;
|
||
if (indexes == null)
|
||
return true;
|
||
bool wait_empty = false;
|
||
for (int i=0; i<indexes.indexers.Count; i++)
|
||
{
|
||
if (i == 0)
|
||
{
|
||
if (indexes.indexers[0] == null)
|
||
{
|
||
if (indexes.indexers.Count == 1)
|
||
AddError(get_location(indexes), "INVALID_ARRAY_REPRESENTATION");
|
||
wait_empty=true;
|
||
}
|
||
}
|
||
else
|
||
if (indexes.indexers[i] == null && !wait_empty || indexes.indexers[i] != null && wait_empty)
|
||
AddError(get_location(indexes), "INVALID_ARRAY_REPRESENTATION");
|
||
else
|
||
rank++;
|
||
}
|
||
return wait_empty;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.array_type _array_type)
|
||
{
|
||
int rank = 1;
|
||
if (is_unsized_array(_array_type.indexers, out rank))
|
||
{
|
||
type_node ret = null;
|
||
type_node et = convert_strong(_array_type.elements_type);
|
||
//if (et == SystemLibrary.SystemLibrary.void_type)
|
||
//AddError(new VoidNotValid(get_location(_array_type.elemets_types)));
|
||
check_for_type_allowed(et,get_location(_array_type.elements_type));
|
||
ret = convertion_data_and_alghoritms.type_constructor.create_unsized_array(et,
|
||
context.converted_namespace, rank, get_location(_array_type));
|
||
return_value(ret);
|
||
return;
|
||
}
|
||
type_node_list ind_types = new type_node_list();
|
||
foreach (SyntaxTree.type_definition td in _array_type.indexers.indexers)
|
||
{
|
||
type_node tn = convert_strong(td);
|
||
internal_interface ii = tn.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(new OrdinalTypeExpected(get_location(td)));
|
||
}
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
if (tn.base_type == SystemLibrary.SystemLibrary.uint_type || tn.base_type == SystemLibrary.SystemLibrary.int64_type ||
|
||
tn.base_type == SystemLibrary.SystemLibrary.uint64_type)
|
||
//ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
AddError(get_location(td), "RANGE_TOO_LARGE");
|
||
}
|
||
else if (tn == SystemLibrary.SystemLibrary.uint_type || tn == SystemLibrary.SystemLibrary.int64_type ||
|
||
tn == SystemLibrary.SystemLibrary.uint64_type)
|
||
AddError(get_location(td), "RANGE_TOO_LARGE");
|
||
ind_types.AddElement(tn);
|
||
}
|
||
type_node elem_type = convert_strong(_array_type.elements_type);
|
||
//TODO: Сделать и массивы, связанные с generics!
|
||
if (depended_from_generic_parameter(elem_type))
|
||
{
|
||
throw new NotSupportedError(get_location(_array_type.elements_type));
|
||
}
|
||
check_for_type_allowed(elem_type,get_location(_array_type.elements_type));
|
||
for (int i = ind_types.Count - 1; i >= 0; i--)
|
||
{
|
||
internal_interface ii = ind_types[i].get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
ordinal_type_interface oti_ind = (ordinal_type_interface)ii;
|
||
elem_type = convertion_data_and_alghoritms.type_constructor.get_array_type(oti_ind, elem_type,
|
||
context.converted_namespace, get_location(_array_type));
|
||
}
|
||
return_value(elem_type);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.indexers_types _indexers_types)
|
||
{
|
||
throw new NotSupportedError(get_location(_indexers_types));
|
||
}
|
||
|
||
private constant_node convert_strong_to_constant_node(SyntaxTree.expression expr)
|
||
{
|
||
expression_node exp = convert_strong(expr);
|
||
return convert_strong_to_constant_node(exp, exp.type);
|
||
}
|
||
|
||
public expression_node convert_strong_to_constant_or_function_call_for_varinit(expression_node exp)
|
||
{
|
||
return convert_strong_to_constant_or_function_call_for_varinit(exp, exp.type);
|
||
}
|
||
|
||
private expression_node convert_strong_to_constant_or_function_call_for_varinit(expression_node exp, type_node tn)
|
||
{
|
||
if (exp is constant_node)
|
||
return convert_strong_to_constant_node(exp, tn);
|
||
if (exp is array_initializer)
|
||
{
|
||
//if (tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
//exp.type = DeduceType(exp.type,exp.location);
|
||
exp = ConvertArrayInitializer(tn, exp as array_initializer);
|
||
return exp;
|
||
//return convertion_data_and_alghoritms.convert_type(exp,tn);
|
||
}
|
||
// else
|
||
// {
|
||
// exp.type = tn;
|
||
// return exp;
|
||
// }
|
||
}
|
||
else if (exp is compiled_static_method_call && (exp.type.type_special_kind == SemanticTree.type_special_kind.set_type || exp.type.type_special_kind == SemanticTree.type_special_kind.base_set_type))
|
||
{
|
||
if (!(tn == exp.type) && !type_table.is_derived(tn, exp.type) && !(convertion_data_and_alghoritms.can_convert_type(exp, tn)))
|
||
{
|
||
AddError(new CanNotConvertTypes(exp, exp.type, tn, exp.location));
|
||
}
|
||
if (tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
compiled_static_method_call cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(exp);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
return new compiled_static_method_call_as_constant(cmc, null);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
compiled_static_method_call cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(exp);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null));
|
||
cmc.ret_type = tn;
|
||
return new compiled_static_method_call_as_constant(cmc, null);
|
||
}
|
||
}
|
||
return new compiled_static_method_call_as_constant(exp as compiled_static_method_call, null);
|
||
}
|
||
else if (exp is common_namespace_function_call && (exp.type.type_special_kind == SemanticTree.type_special_kind.set_type || exp.type.type_special_kind == SemanticTree.type_special_kind.base_set_type))
|
||
{
|
||
if (!(tn == exp.type) && !type_table.is_derived(tn, exp.type) && !(convertion_data_and_alghoritms.can_convert_type(exp, tn)))
|
||
{
|
||
AddError(new CanNotConvertTypes(exp, exp.type, tn, exp.location));
|
||
}
|
||
if (tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null);
|
||
cmc.parameters.AddElement(exp);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
return new common_namespace_function_call_as_constant(cmc, null);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null);
|
||
cmc.parameters.AddElement(exp);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null));
|
||
cmc.ret_type = tn;
|
||
return new common_namespace_function_call_as_constant(cmc, null);
|
||
}
|
||
}
|
||
return new common_namespace_function_call_as_constant(exp as common_namespace_function_call, null);
|
||
}
|
||
else if (exp is record_initializer)
|
||
{
|
||
if (tn is common_type_node)
|
||
exp = ConvertRecordInitializer(tn as common_type_node, exp as record_initializer);
|
||
else if (tn is compiled_type_node)
|
||
throw new NotSupportedError(exp.location);
|
||
return exp;
|
||
}
|
||
switch (SemanticRules.VariableInitializationParams)
|
||
{
|
||
case VariableInitializationParams.ConstructorCall:
|
||
if ((exp is common_constructor_call) || (exp is compiled_constructor_call))
|
||
return convertion_data_and_alghoritms.convert_type(exp, tn);
|
||
break;
|
||
case VariableInitializationParams.Expression:
|
||
if (exp.type != null)
|
||
return convertion_data_and_alghoritms.convert_type(exp, tn);
|
||
break;
|
||
}
|
||
return convert_strong_to_constant_node(exp, tn);
|
||
}
|
||
|
||
private constant_node convert_strong_to_constant_node(SyntaxTree.expression expr, type_node tn)
|
||
{
|
||
return convert_strong_to_constant_node(convert_strong(expr), tn);
|
||
}
|
||
|
||
private void check_set_for_constant(common_namespace_function_call cnfc)
|
||
{
|
||
expressions_list exprs = null;
|
||
if (cnfc.function_node == SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node)
|
||
exprs = get_set_initializer(cnfc);
|
||
else exprs = cnfc.parameters;
|
||
foreach (expression_node en in exprs)
|
||
if (en is common_namespace_function_call)
|
||
{
|
||
cnfc = en as common_namespace_function_call;
|
||
if (cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetUnionProcedure.sym_info as common_namespace_function_node
|
||
|| cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetSubtractProcedure.sym_info as common_namespace_function_node
|
||
|| cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node
|
||
|| cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetIntersectProcedure.sym_info as common_namespace_function_node
|
||
|| cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as common_namespace_function_node
|
||
|| cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as common_namespace_function_node)
|
||
check_set_for_constant(en as common_namespace_function_call);
|
||
else AddError(en.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
}
|
||
else
|
||
if (!(en is constant_node /*|| en is statements_expression_node*/)) AddError(en.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
}
|
||
|
||
private constant_node convert_strong_to_constant_node(expression_node expr, type_node tn)
|
||
{
|
||
location loc = expr.location;
|
||
constant_node constant = null;
|
||
try_convert_typed_expression_to_function_call(ref expr);
|
||
if (expr is null_const_node)
|
||
{
|
||
if (!(tn is null_type_node) && !type_table.is_with_nil_allowed(tn))
|
||
AddError(loc, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
|
||
return null_const_node.get_const_node_with_type(tn, expr as null_const_node);
|
||
}
|
||
if (expr is compiled_static_method_call)
|
||
{
|
||
compiled_static_method_call csmc = expr as compiled_static_method_call;
|
||
|
||
if (/*csmc.parameters.Count == 0 &&*/ csmc.type != null && csmc.type != SystemLibrary.SystemLibrary.void_type)
|
||
constant = new compiled_static_method_call_as_constant(csmc, expr.location);
|
||
}
|
||
else if (expr is common_namespace_function_call && SystemLibrary.SystemLibInitializer.CreateSetProcedure != null && (expr as common_namespace_function_call).function_node == SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = expr as common_namespace_function_call;
|
||
expressions_list exprs = get_set_initializer(cnfc);
|
||
check_set_for_constant(cnfc);
|
||
foreach (expression_node en in exprs)
|
||
{
|
||
if (en is common_namespace_function_call)
|
||
{
|
||
common_namespace_function_call cnfc2 = en as common_namespace_function_call;
|
||
check_set_for_constant(cnfc2);
|
||
}
|
||
else
|
||
if (!(en is constant_node)) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED");
|
||
}
|
||
constant = new common_namespace_function_call_as_constant(cnfc, loc);
|
||
}
|
||
else if (expr is common_namespace_function_call)
|
||
{
|
||
common_namespace_function_call cnfc=expr as common_namespace_function_call;
|
||
//if (cnfc.function_node.namespace_node == context.converted_namespace)
|
||
// throw new ConstantExpressionExpected(loc);
|
||
constant = new common_namespace_function_call_as_constant(expr as common_namespace_function_call, loc);
|
||
}
|
||
else if (expr is basic_function_call)
|
||
{
|
||
basic_function_call cnfc=expr as basic_function_call;
|
||
//if (cnfc.function_node.namespace_node == context.converted_namespace)
|
||
// throw new ConstantExpressionExpected(loc);
|
||
foreach (expression_node el in cnfc.parameters)
|
||
convert_strong_to_constant_node(el, el.type);
|
||
constant = new basic_function_call_as_constant(expr as basic_function_call, loc);
|
||
}
|
||
else if (expr is typed_expression)
|
||
{
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, tn);
|
||
if (expr is common_constructor_call)
|
||
{
|
||
constant = new common_constructor_call_as_constant(expr as common_constructor_call, null);
|
||
}
|
||
else
|
||
if (expr is typed_expression)
|
||
{
|
||
if (const_def_type != null)
|
||
{
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, const_def_type);
|
||
tn = const_def_type;
|
||
constant = new common_constructor_call_as_constant(expr as common_constructor_call, null);
|
||
}
|
||
else
|
||
{
|
||
base_function_call bfc = ((expr as typed_expression).type as delegated_methods).proper_methods[0];
|
||
common_type_node del =
|
||
convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null);
|
||
context.converted_namespace.types.AddElement(del);
|
||
tn = del;
|
||
expr = convertion_data_and_alghoritms.explicit_convert_type(expr, del);
|
||
expr.type = tn;
|
||
constant = new common_constructor_call_as_constant(expr as common_constructor_call, loc);
|
||
}
|
||
}
|
||
}
|
||
|
||
else if (expr is namespace_constant_reference)
|
||
{
|
||
constant = (expr as namespace_constant_reference).constant.const_value;
|
||
convertion_data_and_alghoritms.check_convert_type(constant,tn,expr.location);
|
||
if ((tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.base_set_type) && tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
constant = new common_namespace_function_call_as_constant(cmc,null);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length,null));
|
||
cmc.ret_type = tn;
|
||
constant = new common_namespace_function_call_as_constant(cmc,null);
|
||
}
|
||
}
|
||
else
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
/*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/
|
||
expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(expr,SystemLibrary.SystemLibrary.string_type),new int_const_node((tn as short_string_type_node).Length,null));
|
||
constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call,null);
|
||
}
|
||
/*expression_node e = convertion_data_and_alghoritms.convert_type(constant.get_constant_copy(expr.location), tn);
|
||
switch (e.semantic_node_type)
|
||
{
|
||
case semantic_node_type.compiled_constructor_call:
|
||
constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc);
|
||
break;
|
||
default:
|
||
constant = e as constant_node;
|
||
break;
|
||
}*/
|
||
/*if (constant.get_object_value() != null)
|
||
{
|
||
//if (const_def_type != null)
|
||
{
|
||
expression_node e = convertion_data_and_alghoritms.convert_type(constant.get_constant_copy(expr.location), tn);
|
||
switch (e.semantic_node_type)
|
||
{
|
||
case semantic_node_type.compiled_constructor_call:
|
||
constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc);
|
||
break;
|
||
default:
|
||
constant = e as constant_node;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//if (const_def_type != null)
|
||
{
|
||
expression_node e = convertion_data_and_alghoritms.convert_type(expr, tn);
|
||
switch (e.semantic_node_type)
|
||
{
|
||
case semantic_node_type.compiled_constructor_call:
|
||
constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc);
|
||
break;
|
||
default:
|
||
constant = e as constant_node;
|
||
break;
|
||
}
|
||
}
|
||
}*/
|
||
return constant;
|
||
}
|
||
else if (expr is function_constant_reference)
|
||
{
|
||
constant = (expr as function_constant_reference).constant.const_value;
|
||
convertion_data_and_alghoritms.check_convert_type(constant,tn,expr.location);
|
||
if ((tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.base_set_type) && tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
constant = new common_namespace_function_call_as_constant(cmc,null);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length,null));
|
||
cmc.ret_type = tn;
|
||
constant = new common_namespace_function_call_as_constant(cmc,null);
|
||
}
|
||
}
|
||
else
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
/*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/
|
||
expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(expr,SystemLibrary.SystemLibrary.string_type),new int_const_node((tn as short_string_type_node).Length,null));
|
||
constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call,null);
|
||
}
|
||
return constant;
|
||
}
|
||
else if (expr is static_compiled_variable_reference && !(expr as static_compiled_variable_reference).var.IsLiteral)
|
||
{
|
||
constant = new compiled_static_field_reference_as_constant(expr as static_compiled_variable_reference, null);
|
||
return constant;
|
||
}
|
||
else
|
||
{
|
||
constant = expr as constant_node;
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
/*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/
|
||
expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.string_type), new int_const_node((tn as short_string_type_node).Length, null));
|
||
if (cmc is common_namespace_function_call)
|
||
constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null);
|
||
else
|
||
constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null);
|
||
}
|
||
//else
|
||
//constant = convertion_data_and_alghoritms.convert_type(constant, tn) as constant_node;
|
||
if (expr is static_compiled_variable_reference)
|
||
{
|
||
compiled_class_constant_definition cccd = NetHelper.NetHelper.ConvertToConstant(((static_compiled_variable_reference)expr).var);
|
||
if (cccd != null)
|
||
constant = cccd.const_value;
|
||
else
|
||
constant = new compiled_static_field_reference_as_constant(expr as static_compiled_variable_reference, null);
|
||
}
|
||
|
||
}
|
||
if (constant == null)
|
||
AddError(loc, "CONSTANT_EXPRESSION_EXPECTED");
|
||
if (IsBoundedArray(tn) || IsUnsizedArray(tn))
|
||
{
|
||
if (!(constant is array_const))
|
||
AddError(loc, "ARRAY_CONST_EXPECTED");
|
||
constant = ConvertArrayConst(tn, constant as array_const);
|
||
}
|
||
else
|
||
if (tn is common_type_node)
|
||
{
|
||
if (tn.type_special_kind != SemanticTree.type_special_kind.set_type && tn.type_special_kind != SemanticTree.type_special_kind.base_set_type && tn.type_special_kind != SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
if (!tn.is_value)
|
||
{
|
||
if (expr is common_constructor_call)
|
||
return constant;
|
||
if (expr is common_constructor_call_as_constant)
|
||
return expr as common_constructor_call_as_constant;
|
||
convertion_data_and_alghoritms.check_convert_type(expr,tn,expr.location);
|
||
//AddError(new CanNotConvertTypes(expr,expr.type,tn,expr.location));
|
||
//throw new NotSupportedError(loc);
|
||
}
|
||
if ((tn as common_type_node).IsEnum)
|
||
{
|
||
convertion_data_and_alghoritms.check_convert_type(expr,tn,expr.location);
|
||
enum_const_node ecn = expr as enum_const_node;
|
||
if (ecn == null) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
return ecn;
|
||
}
|
||
if (!(constant is record_constant))
|
||
AddError(loc, "RECORD_CONST_EXPECTED");
|
||
constant = ConvertRecordConst(tn as common_type_node, constant as record_constant);
|
||
}
|
||
else if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type)
|
||
{
|
||
constant = expr as constant_node;
|
||
if (constant == null)
|
||
AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
//constant = (expr as namespace_constant_reference).constant.const_value;
|
||
convertion_data_and_alghoritms.check_convert_type(constant,tn,expr.location);
|
||
ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
bool success = false;
|
||
int val = convertion_data_and_alghoritms.convert_type_to_int_constant(constant, out success);
|
||
if (success)
|
||
{
|
||
int left = convertion_data_and_alghoritms.convert_type_to_int_constant(oti.lower_value, out success);
|
||
if (success)
|
||
{
|
||
int right = convertion_data_and_alghoritms.convert_type_to_int_constant(oti.upper_value, out success);
|
||
if (success)
|
||
if (val < left || val > right)
|
||
AddError(loc, "OUT_OF_RANGE");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//obrezka konstantnogo mnozhestva
|
||
if (!(tn == expr.type) && !type_table.is_derived(tn,expr.type))
|
||
{
|
||
AddError(new CanNotConvertTypes(expr,expr.type,tn,expr.location));
|
||
}
|
||
if (tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipFunction.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
if (cmc is common_namespace_function_call)
|
||
constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null);
|
||
else
|
||
constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null);
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length,null));
|
||
cmc.ret_type = tn;
|
||
if (cmc is common_namespace_function_call)
|
||
constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null);
|
||
else
|
||
constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
expression_node exprc = convertion_data_and_alghoritms.convert_type(constant, tn);
|
||
switch (exprc.semantic_node_type)
|
||
{
|
||
case semantic_node_type.compiled_constructor_call:
|
||
constant = new compiled_constructor_call_as_constant(exprc as compiled_constructor_call, loc);
|
||
break;
|
||
case semantic_node_type.compiled_static_method_call:
|
||
constant = new compiled_static_method_call_as_constant(exprc as compiled_static_method_call, loc);
|
||
break;
|
||
case semantic_node_type.basic_function_call:
|
||
constant = new basic_function_call_as_constant(exprc as basic_function_call, loc);
|
||
break;
|
||
default:
|
||
constant = exprc as constant_node;
|
||
break;
|
||
}
|
||
}
|
||
return constant;
|
||
}
|
||
|
||
internal common_type_node CreateDelegate(function_node fn)
|
||
{
|
||
common_type_node del =
|
||
convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), fn.return_value_type, fn.parameters, context.converted_namespace, null);
|
||
context.converted_namespace.types.AddElement(del);
|
||
return del;
|
||
}
|
||
|
||
internal expression_node CreateDelegateCall(base_function_call fn_call)
|
||
{
|
||
common_type_node del = CreateDelegate(fn_call.simple_function_node);
|
||
common_constructor_call deleg_costructor_call = new common_constructor_call(del.methods[0], fn_call.location);
|
||
deleg_costructor_call.parameters.AddElement((base_function_call)fn_call);
|
||
return deleg_costructor_call;
|
||
}
|
||
|
||
private record_initializer ConvertRecordInitializer(common_type_node ctn, record_initializer constant)
|
||
{
|
||
location loc = constant.location;
|
||
if (!ctn.is_value_type)
|
||
AddError(loc, "RECORD_CONST_NOT_ALLOWED_{0}", ctn.name);
|
||
if (ctn.fields.Count != constant.record_const_definition_list.Count)
|
||
AddError(loc, "INVALID_RECORD_CONST_FIELD_COUNT");
|
||
constant.type = ctn;
|
||
constant.field_values.Clear();
|
||
for (int i = 0; i < ctn.fields.Count; i++)
|
||
{
|
||
class_field cf = ctn.fields[i];
|
||
if (cf.name.ToLower() != constant.record_const_definition_list[i].name.name.ToLower())
|
||
AddError(get_location(constant.record_const_definition_list[i].name), "FIELD_NAME_SHOULD_BE_EQUAL_RECORD_FIELD_NAME", cf.name);
|
||
expression_node en = convert_strong_to_constant_or_function_call_for_varinit(convert_strong(constant.record_const_definition_list[i].val),cf.type);
|
||
en.type = cf.type;
|
||
constant.field_values.Add(en);
|
||
}
|
||
return constant;
|
||
}
|
||
|
||
private array_initializer ConvertNDimArrayInitializer(type_node tn, int cur_rank, type_node element_type, array_initializer constant)
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
int rank = aii.rank;
|
||
for (int i=0; i<constant.element_values.Count; i++)
|
||
{
|
||
expression_node e = constant.element_values[i];
|
||
if (e is array_initializer)
|
||
{
|
||
if (cur_rank>=rank)
|
||
constant.element_values[i] = ConvertArrayInitializer(tn.element_type,e as array_initializer);
|
||
//AddError(new CanNotConvertTypes(e,e.type,tn.element_type,e.location));
|
||
else
|
||
constant.element_values[i] = ConvertNDimArrayInitializer(tn,cur_rank+1,element_type,e as array_initializer);
|
||
}
|
||
else if (e is record_initializer)
|
||
{
|
||
if (element_type is common_type_node)
|
||
constant.element_values[i] = ConvertRecordInitializer(element_type as common_type_node, e as record_initializer);
|
||
else throw new NotSupportedError(constant.element_values[i].location);
|
||
}
|
||
else
|
||
{
|
||
if (cur_rank != rank)
|
||
AddError(constant.location, "RANK_MISMATCH_IN_INITILIALIZER");
|
||
constant.element_values[i] = convertion_data_and_alghoritms.convert_type(constant.element_values[i], element_type);
|
||
}
|
||
}
|
||
constant.type = tn;
|
||
return constant;
|
||
}
|
||
|
||
private expression_node ConvertArrayInitializer(type_node tn, array_initializer constant)
|
||
{
|
||
type_node element_type = null;
|
||
if (IsBoundedArray(tn))
|
||
{
|
||
bounded_array_interface bai = tn.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface;
|
||
element_type = bai.element_type;
|
||
ordinal_type_interface oti_indexer = bai.ordinal_type_interface;
|
||
int arr_length = oti_indexer.ordinal_type_to_int(oti_indexer.upper_value) - oti_indexer.ordinal_type_to_int(oti_indexer.lower_value) + 1;
|
||
if (arr_length != constant.element_values.Count)
|
||
AddError(constant.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", arr_length);
|
||
}
|
||
else
|
||
if (IsUnsizedArray(tn))
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
element_type = aii.element_type;
|
||
if (aii.rank > 1)
|
||
{
|
||
array_initializer cnst = ConvertNDimArrayInitializer(tn,1,element_type,constant);
|
||
cnst.type = tn;
|
||
return cnst;
|
||
}
|
||
}
|
||
else if (tn == SystemLibrary.SystemLibrary.complex_type && constant.element_values.Count == 2)
|
||
{
|
||
compiled_constructor_call cccall = new compiled_constructor_call(SystemLibrary.SystemLibrary.complex_type_constructor, null);
|
||
cccall.parameters.AddElement(convertion_data_and_alghoritms.convert_type(constant.element_values[0], SystemLibrary.SystemLibrary.double_type));
|
||
cccall.parameters.AddElement(convertion_data_and_alghoritms.convert_type(constant.element_values[1], SystemLibrary.SystemLibrary.double_type));
|
||
compiled_constructor_call_as_constant cccall_cnst = new compiled_constructor_call_as_constant(cccall, null);
|
||
return cccall_cnst;
|
||
}
|
||
else
|
||
AddError(new CanNotConvertTypes(constant,constant.type,tn,constant.location));//CompilerInternalError("Unexpected array type");
|
||
for (int i = 0; i < constant.element_values.Count; i++)
|
||
if (constant.element_values[i] is array_initializer)
|
||
constant.element_values[i] = ConvertArrayInitializer(element_type, constant.element_values[i] as array_initializer);
|
||
else if (constant.element_values[i] is record_initializer)
|
||
{
|
||
if (element_type is common_type_node)
|
||
constant.element_values[i] = ConvertRecordInitializer(element_type as common_type_node, constant.element_values[i] as record_initializer);
|
||
else throw new NotSupportedError(constant.element_values[i].location);
|
||
}
|
||
else
|
||
{
|
||
constant.element_values[i] = convertion_data_and_alghoritms.convert_type(constant.element_values[i], element_type);
|
||
}
|
||
constant.type = tn;
|
||
return constant;
|
||
}
|
||
|
||
private array_const ConvertNDimArrayConst(type_node tn, int cur_rank, type_node element_type, array_const constant)
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
int rank = aii.rank;
|
||
for (int i=0; i<constant.element_values.Count; i++)
|
||
{
|
||
expression_node e = constant.element_values[i];
|
||
if (e is array_const)
|
||
{
|
||
if (cur_rank>=rank)
|
||
constant.element_values[i] = ConvertArrayConst(tn.element_type,e as array_const);
|
||
//AddError(new CanNotConvertTypes(e,e.type,tn.element_type,e.location));
|
||
else
|
||
constant.element_values[i] = ConvertNDimArrayConst(tn,cur_rank+1,element_type,e as array_const);
|
||
}
|
||
else if (e is record_constant)
|
||
{
|
||
if (element_type is common_type_node)
|
||
constant.element_values[i] = ConvertRecordConst(element_type as common_type_node, e as record_constant);
|
||
else AddError(new NotSupportedError(constant.element_values[i].location));
|
||
}
|
||
else
|
||
{
|
||
if (cur_rank != rank)
|
||
AddError(constant.location, "RANK_MISMATCH_IN_INITILIALIZER");
|
||
constant.element_values[i] = convert_strong_to_constant_node(constant.element_values[i], element_type);
|
||
}
|
||
}
|
||
constant.SetType(tn);
|
||
return constant;
|
||
}
|
||
|
||
private array_const ConvertArrayConst(type_node tn, array_const constant)
|
||
{
|
||
type_node element_type = null;
|
||
if (IsBoundedArray(tn))
|
||
{
|
||
bounded_array_interface bai = tn.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface;
|
||
element_type = bai.element_type;
|
||
ordinal_type_interface oti_indexer = bai.ordinal_type_interface;
|
||
int arr_length = oti_indexer.ordinal_type_to_int(oti_indexer.upper_value) - oti_indexer.ordinal_type_to_int(oti_indexer.lower_value) + 1;
|
||
if (arr_length != constant.element_values.Count)
|
||
AddError(constant.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", arr_length);
|
||
}
|
||
else
|
||
if (IsUnsizedArray(tn))
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
element_type = aii.element_type;
|
||
if (aii.rank > 1)
|
||
{
|
||
array_const cnst = ConvertNDimArrayConst(tn,1,element_type,constant);
|
||
cnst.SetType(tn);
|
||
return cnst;
|
||
}
|
||
}
|
||
else
|
||
throw new CompilerInternalError("Unexpected array type");
|
||
for (int i = 0; i < constant.element_values.Count; i++)
|
||
constant.element_values[i] = convert_strong_to_constant_node(constant.element_values[i], element_type);
|
||
constant.SetType(tn);
|
||
return constant;
|
||
}
|
||
|
||
private record_constant ConvertRecordConst(common_type_node ctn, record_constant constant)
|
||
{
|
||
location loc = constant.location;
|
||
if (!ctn.is_value_type)
|
||
AddError(loc, "RECORD_CONST_NOT_ALLOWED_{0}", ctn.name);
|
||
if (ctn.fields.Count != constant.record_const_definition_list.Count)
|
||
AddError(loc, "INVALID_RECORD_CONST_FIELD_COUNT");
|
||
constant.SetType(ctn);
|
||
constant.field_values.Clear();
|
||
bool tmp = this.is_typed_const_def;
|
||
this.is_typed_const_def = true;
|
||
for (int i = 0; i < ctn.fields.Count; i++)
|
||
{
|
||
class_field cf = ctn.fields[i];
|
||
if (cf.name.ToLower() != constant.record_const_definition_list[i].name.name.ToLower())
|
||
AddError(get_location(constant.record_const_definition_list[i].name), "FIELD_NAME_SHOULD_BE_EQUAL_RECORD_FIELD_NAME", cf.name);
|
||
constant.field_values.Add(convert_strong_to_constant_node(constant.record_const_definition_list[i].val, cf.type));
|
||
}
|
||
this.is_typed_const_def = tmp;
|
||
return constant;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.diapason _diapason)
|
||
{
|
||
constant_node cnleft = convert_strong_to_constant_node(_diapason.left);
|
||
constant_node cnright = convert_strong_to_constant_node(_diapason.right);
|
||
type_node tn = convertion_data_and_alghoritms.type_constructor.get_pascal_diap(cnleft, cnright, get_location(_diapason.left),
|
||
context.converted_namespace, get_location(_diapason.right));
|
||
return_value(tn);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.ref_type _ref_type)
|
||
{
|
||
if (_ref_type.pointed_to is SyntaxTree.named_type_reference &&
|
||
((_ref_type.pointed_to as SyntaxTree.named_type_reference).names.Count == 1) &&
|
||
context.CurrentScope.Find((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name) == null)
|
||
{
|
||
//это указатель на тип который еще не описан
|
||
if (!is_direct_type_decl)
|
||
AddError(new UndefinedNameReference((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name,get_location(_ref_type.pointed_to)));
|
||
return_value(GetWaitedRefType((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name, get_location(_ref_type.pointed_to)));
|
||
}
|
||
else
|
||
{
|
||
type_node tn = convert_strong(_ref_type.pointed_to);
|
||
if (tn.is_generic_parameter)
|
||
{
|
||
if (SemanticRules.AllowPointersForGenericParameters)
|
||
{
|
||
get_type_abilities(tn).useful_for_pointers = true;
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_ref_type), "POINTERS_OF_GENERIC_PARAMETERS_NOT_ALLOWED");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!tn.is_value /*&& tn.type_special_kind != SemanticTree.type_special_kind.array_kind && tn.type_special_kind != SemanticTree.type_special_kind.set_type && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper && tn.type_special_kind != SemanticTree.type_special_kind.binary_file
|
||
&& tn.type_special_kind != SemanticTree.type_special_kind.binary_file*/ && !(tn is ref_type_node) && tn != SystemLibrary.SystemLibrary.pointer_type && tn.type_special_kind != SemanticTree.type_special_kind.short_string && tn.type_special_kind != SemanticTree.type_special_kind.diap_type && !tn.IsEnum &&
|
||
!(tn.semantic_node_type == semantic_node_type.indefinite_type))
|
||
AddError(get_location(_ref_type), "POINTERS_OF_REF_TYPES_NOT_ALLOWED");
|
||
}
|
||
ref_type_node rtn = tn.ref_type;
|
||
if (rtn != null)
|
||
{
|
||
rtn.loc = get_location(_ref_type);
|
||
if (SemanticRules.StrongPointersTypeCheckForDotNet)
|
||
//CheckPointersTypeForDotNetFramework(tn, get_location(_ref_type.pointed_to));
|
||
RefTypesForCheckPointersTypeForDotNetFramework.Add(rtn);
|
||
return_value(rtn);
|
||
}
|
||
else
|
||
{
|
||
return_value(SystemLibrary.SystemLibrary.pointer_type);
|
||
}
|
||
}
|
||
}
|
||
|
||
internal bool CheckPointersTypeForDotNetFramework(type_node tn, location loc)
|
||
{
|
||
type_node ttn = FindBadTypeNodeForPointersInDotNetFramework(tn);
|
||
__findBadTypeNodeForPointersPreparedTypes.Clear();
|
||
if (ttn != null)
|
||
{
|
||
AddErrorCheckPointersTypeForDotNetFramework(tn, ttn, loc);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public void AddErrorCheckPointersTypeForDotNetFramework(type_node tn, type_node ttn, location loc)
|
||
{
|
||
if (tn == ttn)
|
||
AddError(loc, "CANNOT_DECLARED_POINTER_TO_REFERENCE_TYPE");
|
||
else
|
||
AddError(loc, "CANNOT_DECLARED_POINTER_TO_RECORD_CONTAINS_REFERENCE_FIELDS");
|
||
}
|
||
private List<type_node> __findBadTypeNodeForPointersPreparedTypes = new List<type_node>();
|
||
private type_node FindBadTypeNodeForPointersInDotNetFramework(type_node tn)
|
||
{
|
||
if (__findBadTypeNodeForPointersPreparedTypes.Contains(tn))
|
||
return null;
|
||
__findBadTypeNodeForPointersPreparedTypes.Add(tn);
|
||
if (tn.semantic_node_type == semantic_node_type.indefinite_type)
|
||
{
|
||
return null;
|
||
}
|
||
if (tn.is_generic_parameter)
|
||
{
|
||
if (SemanticRules.AllowPointersForGenericParameters)
|
||
{
|
||
get_type_abilities(tn).useful_for_pointers = true;
|
||
return null;
|
||
}
|
||
else
|
||
{
|
||
return tn;
|
||
}
|
||
}
|
||
type_node btn = null;
|
||
if (tn is ref_type_node)
|
||
return FindBadTypeNodeForPointersInDotNetFramework((tn as ref_type_node).pointed_type);
|
||
if (tn == SystemLibrary.SystemLibrary.pointer_type || tn == SystemLibrary.SystemLibrary.void_type)
|
||
return null;
|
||
if (tn.is_value)
|
||
{
|
||
generic_instance_type_node gitn = tn as generic_instance_type_node;
|
||
if (gitn != null)
|
||
{
|
||
List<type_node> ftypes = gitn.all_field_types;
|
||
foreach (type_node ftype in ftypes)
|
||
{
|
||
if ((btn = FindBadTypeNodeForPointersInDotNetFramework(ftype)) != null)
|
||
return btn;
|
||
}
|
||
return null;
|
||
}
|
||
if (tn is common_type_node)
|
||
{
|
||
if (tn.IsEnum || tn.type_special_kind == SemanticTree.type_special_kind.diap_type) return null;
|
||
common_type_node ctn = tn as common_type_node;
|
||
foreach (class_field cf in ctn.fields)
|
||
if ((btn = FindBadTypeNodeForPointersInDotNetFramework(cf.type)) != null)
|
||
return btn;
|
||
return null;
|
||
}
|
||
if (tn is compiled_type_node)
|
||
{
|
||
compiled_type_node ctn = tn as compiled_type_node;
|
||
if (ctn.IsPrimitive)
|
||
return null;
|
||
System.Reflection.FieldInfo[] fields = ctn.compiled_type.GetFields();
|
||
foreach (System.Reflection.FieldInfo fi in fields)
|
||
if (!fi.IsStatic)
|
||
if ((btn = FindBadTypeNodeForPointersInDotNetFramework(compiled_type_node.get_type_node(fi.FieldType))) != null)
|
||
return btn;
|
||
return null;
|
||
}
|
||
}
|
||
/*if (IsBoudedArray(el_type))
|
||
{
|
||
//это обычный массив
|
||
bounded_array_interface bai = (bounded_array_interface)el_type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
return CanUseThisTypeForTypedFiles(bai.element_type);
|
||
}*/
|
||
if (tn == SystemLibrary.SystemLibrary.string_type || tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.short_string || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.array_kind) return null;
|
||
return tn;
|
||
}
|
||
|
||
|
||
/*private void ConvertStatement(SyntaxTree.statement stmt)
|
||
{
|
||
while (stmt != null)
|
||
{
|
||
if (stmt is SyntaxTree.if_node)
|
||
{
|
||
SyntaxTree.if_node _if_node = stmt as SyntaxTree.if_node;
|
||
|
||
expression_node condition = convert_strong(_if_node.condition);
|
||
condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type);
|
||
|
||
statements_list sl = new statements_list(get_location(_if_node.then_body));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node then_st = convert_strong(_if_node.then_body);
|
||
context.leave_code_block();
|
||
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (sl.statements.Count > 0)
|
||
{
|
||
sl.statements.AddElement(then_st);
|
||
then_st = sl;
|
||
}
|
||
|
||
if (_if_node.else_body != null)
|
||
{
|
||
sl = new statements_list(get_location(_if_node.else_body));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
}
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node else_st = convert_weak(_if_node.else_body);
|
||
context.leave_code_block();
|
||
|
||
if (_if_node.else_body != null)
|
||
{
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (sl.statements.Count > 0)
|
||
{
|
||
sl.statements.AddElement(else_st);
|
||
else_st = sl;
|
||
}
|
||
}
|
||
|
||
if_node if_node = new if_node(condition, then_st, else_st, get_location(_if_node));
|
||
return_value(if_node);
|
||
return;
|
||
}
|
||
visit(stmt);
|
||
}
|
||
}*/
|
||
|
||
void CheckToEmbeddedStatementCannotBeADeclaration(SyntaxTree.statement st)
|
||
{
|
||
if (st != null && st is SyntaxTree.var_statement)
|
||
AddError(get_location(st), "EMBEDDED_SATATEMENT_CANNOT_BE_A_DECLARATION");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.if_node _if_node)
|
||
{
|
||
expression_node condition = convert_strong(_if_node.condition);
|
||
condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type);
|
||
|
||
// SSM 29/08/16
|
||
var cc = condition as bool_const_node;
|
||
if (cc != null && cc.constant_value == false && _if_node.else_body == null)
|
||
{
|
||
// недостижимый код - ничего не генерировать
|
||
return_value(new empty_statement(get_location(_if_node)));
|
||
return;
|
||
}
|
||
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_if_node.then_body);
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_if_node.else_body);
|
||
|
||
statements_list sl = new statements_list(get_location(_if_node.then_body));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node then_st = convert_strong(_if_node.then_body);
|
||
context.leave_code_block();
|
||
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
|
||
{
|
||
sl.statements.AddElement(then_st);
|
||
then_st = sl;
|
||
}
|
||
|
||
if (_if_node.else_body != null)
|
||
{
|
||
sl = new statements_list(get_location(_if_node.else_body));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
}
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node else_st = convert_weak(_if_node.else_body);
|
||
context.leave_code_block();
|
||
|
||
if (_if_node.else_body != null)
|
||
{
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
|
||
{
|
||
sl.statements.AddElement(else_st);
|
||
else_st = sl;
|
||
}
|
||
}
|
||
|
||
if_node if_node = new if_node(condition, then_st, else_st, get_location(_if_node));
|
||
return_value(if_node);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.while_node _while_node)
|
||
{
|
||
expression_node expr = convert_strong(_while_node.expr);
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.bool_type);
|
||
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_while_node.statements);
|
||
|
||
while_node wn = new while_node(expr, get_location(_while_node));
|
||
context.cycle_stack.push(wn);
|
||
|
||
statements_list sl = new statements_list(get_location(_while_node.statements));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node st = convert_strong(_while_node.statements);
|
||
context.leave_code_block();
|
||
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
|
||
{
|
||
sl.statements.AddElement(st);
|
||
st = sl;
|
||
}
|
||
|
||
wn.body = st;
|
||
context.cycle_stack.pop();
|
||
return_value(wn);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.repeat_node _repeat_node)
|
||
{
|
||
repeat_node rep = new repeat_node(get_location(_repeat_node));
|
||
context.cycle_stack.push(rep);
|
||
|
||
statements_list sl = new statements_list(get_location(_repeat_node.statements));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_repeat_node.statements);
|
||
|
||
statement_node st = convert_strong(_repeat_node.statements);
|
||
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
//if (!(st is statements_list))
|
||
if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
|
||
{
|
||
sl.statements.AddElement(st);
|
||
st = sl;
|
||
}
|
||
|
||
rep.body = st;
|
||
expression_node expr = convert_strong(_repeat_node.expr);
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.bool_type);
|
||
rep.condition = expr;
|
||
context.cycle_stack.pop();
|
||
return_value(rep);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.for_node _for_node)
|
||
{
|
||
#region MikhailoMMX, обработка omp parallel for
|
||
bool isGenerateParallel = false;
|
||
bool isGenerateSequential = true;
|
||
if (OpenMP.ForsFound)
|
||
{
|
||
OpenMP.LoopVariables.Push(_for_node.loop_variable.name.ToLower());
|
||
//если в программе есть хоть одна директива parallel for - проверяем:
|
||
if (DirectivesToNodesLinks.ContainsKey(_for_node) && OpenMP.IsParallelForDirective(DirectivesToNodesLinks[_for_node]))
|
||
{
|
||
//перед этим узлом есть директива parallel for
|
||
if (CurrentParallelPosition == ParallelPosition.Outside) //входим в самый внешний параллельный for
|
||
{
|
||
if (_for_node.create_loop_variable || (_for_node.type_name != null))
|
||
{
|
||
//сгенерировать сначала последовательную ветку, затем параллельную
|
||
//устанавливаем флаг и продолжаем конвертирование, считая, что конвертируем последовательную ветку
|
||
isGenerateParallel = true;
|
||
CurrentParallelPosition = ParallelPosition.InsideSequential;
|
||
//в конце за счет флага вернем состояние обратно и сгенерируем и параллельную ветку тоже
|
||
}
|
||
else
|
||
WarningsList.Add(new OMP_BuildigError(new Exception("Переменная параллельного цикла должна быть определена в заголовке цикла"), new location(_for_node.source_context.begin_position.line_num, _for_node.source_context.begin_position.column_num, _for_node.source_context.end_position.line_num, _for_node.source_context.end_position.column_num, new document(_for_node.source_context.FileName))));
|
||
}
|
||
else //уже генерируем одну из веток
|
||
//если это параллельная ветка - последовательную генерировать не будем
|
||
if (CurrentParallelPosition == ParallelPosition.InsideParallel)
|
||
{
|
||
isGenerateParallel = true;
|
||
isGenerateSequential = false;
|
||
}
|
||
//else
|
||
//а если последовательная - то флаг isGenerateParallel не установлен, сгенерируется только последовательная
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
|
||
location loc1 = get_location(_for_node.loop_variable);
|
||
var_definition_node vdn = null;
|
||
expression_node left, right, res;
|
||
expression_node initv = convert_strong(_for_node.initial_value);
|
||
expression_node tmp = initv;
|
||
if (initv is typed_expression) initv = convert_typed_expression_to_function_call(initv as typed_expression);
|
||
if (initv.type == null)
|
||
initv = tmp;
|
||
statements_list head_stmts = new statements_list(loc1);
|
||
convertion_data_and_alghoritms.statement_list_stack_push(head_stmts);
|
||
if (_for_node.type_name == null && !_for_node.create_loop_variable)
|
||
{
|
||
definition_node dn = context.check_name_node_type(_for_node.loop_variable.name, loc1,
|
||
general_node_type.variable_node);
|
||
vdn = (var_definition_node)dn;
|
||
if (context.is_loop_variable(vdn))
|
||
AddError(get_location(_for_node.loop_variable), "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
if (!check_name_in_current_scope(_for_node.loop_variable.name))
|
||
AddError(new ForLoopControlMustBeSimpleLocalVariable(loc1));
|
||
}
|
||
else
|
||
{
|
||
//В разработке DS
|
||
//throw new NotSupportedError(get_location(_for_node.type_name));
|
||
type_node tn;
|
||
if (_for_node.type_name != null)
|
||
tn = convert_strong(_for_node.type_name);
|
||
else
|
||
tn = initv.type;
|
||
//if (tn == SystemLibrary.SystemLibrary.void_type && _for_node.type_name != null)
|
||
// AddError(new VoidNotValid(get_location(_for_node.type_name)))
|
||
if (_for_node.type_name != null)
|
||
check_for_type_allowed(tn,get_location(_for_node.type_name));
|
||
vdn = context.add_var_definition(_for_node.loop_variable.name, get_location(_for_node.loop_variable), tn, SemanticTree.polymorphic_state.ps_common);
|
||
}
|
||
internal_interface ii = vdn.type.get_internal_interface(internal_interface_kind.ordinal_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(new OrdinalTypeExpected(loc1));
|
||
}
|
||
ordinal_type_interface oti = (ordinal_type_interface)ii;
|
||
|
||
|
||
location loc2 = get_location(_for_node.finish_value);
|
||
var_definition_node vdn_finish = context.create_for_temp_variable(vdn.type, loc2);
|
||
//Это должно стаять первее!
|
||
left = create_variable_reference(vdn_finish, loc1);
|
||
expression_node finishValue = convert_strong(_for_node.finish_value);
|
||
right = finishValue;
|
||
if (right is typed_expression) right = convert_typed_expression_to_function_call(right as typed_expression);
|
||
res = find_operator(compiler_string_consts.assign_name, left, right, loc2);
|
||
head_stmts.statements.AddElement(res);
|
||
|
||
left = create_variable_reference(vdn, loc1);
|
||
right = initv;
|
||
res = find_operator(compiler_string_consts.assign_name, left, right, loc1);
|
||
head_stmts.statements.AddElement(res);
|
||
|
||
|
||
//for_node fn=new for_node(sl,;
|
||
//fn.initialization_statement=sl;
|
||
|
||
location loc3 = get_location(_for_node.initial_value);
|
||
|
||
statement_node sn_inc = null;
|
||
expression_node sn_while = null;
|
||
expression_node sn_init_while = null;
|
||
left = create_variable_reference(vdn, loc3);
|
||
right = create_variable_reference(vdn, loc2);
|
||
expression_node right_border = create_variable_reference(vdn_finish, loc2);
|
||
switch (_for_node.cycle_type)
|
||
{
|
||
case SyntaxTree.for_cycle_type.to:
|
||
{
|
||
sn_inc = convertion_data_and_alghoritms.create_simple_function_call(oti.inc_method, loc1, left);
|
||
//if (vdn.type != SystemLibrary.SystemLibrary.bool_type)
|
||
sn_while = convertion_data_and_alghoritms.create_simple_function_call(oti.lower_method, loc2, right, right_border);
|
||
sn_init_while = convertion_data_and_alghoritms.create_simple_function_call(oti.lower_eq_method, loc2, right, right_border);
|
||
// else
|
||
// sn_while = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.bool_noteq, loc2, right, right_border);
|
||
break;
|
||
}
|
||
case SyntaxTree.for_cycle_type.downto:
|
||
{
|
||
sn_inc = convertion_data_and_alghoritms.create_simple_function_call(oti.dec_method, loc1, left);
|
||
//if (vdn.type != SystemLibrary.SystemLibrary.bool_type)
|
||
sn_while = convertion_data_and_alghoritms.create_simple_function_call(oti.greater_method, loc2, right, right_border);
|
||
sn_init_while = convertion_data_and_alghoritms.create_simple_function_call(oti.greater_eq_method, loc2, right, right_border);
|
||
// else
|
||
// sn_while = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.bool_noteq, loc2, right, right_border);
|
||
break;
|
||
}
|
||
}
|
||
//fn.increment_statement=sn_inc;
|
||
//fn.while_expr=sn_while;
|
||
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_for_node.statements);
|
||
|
||
//DarkStar Modifed
|
||
//исправил ошибку: не работали break в циклах
|
||
for_node fn = new for_node(null, sn_while, sn_init_while, sn_inc, null, get_location(_for_node));
|
||
if (vdn.type == SystemLibrary.SystemLibrary.bool_type)
|
||
fn.bool_cycle = true;
|
||
context.cycle_stack.push(fn);
|
||
context.loop_var_stack.Push(vdn);
|
||
statements_list slst = new statements_list(get_location(_for_node.statements));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(slst);
|
||
|
||
context.enter_code_block_with_bind();
|
||
fn.body = convert_strong(_for_node.statements);
|
||
context.leave_code_block();
|
||
|
||
slst = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (slst.statements.Count > 0 || slst.local_variables.Count > 0)
|
||
{
|
||
slst.statements.AddElement(fn.body);
|
||
fn.body = slst;
|
||
}
|
||
|
||
context.cycle_stack.pop();
|
||
context.loop_var_stack.Pop();
|
||
head_stmts = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
head_stmts.statements.AddElement(fn);
|
||
|
||
#region MikhailoMMX, обработка omp parallel for
|
||
//флаг был установлен только если это самый внешний parallel for и нужно сгенерировать обе ветки
|
||
//или если это вложенный parallel for, нужно сгенерировать обе ветки, но без проверки на OMP_Available
|
||
//Последовательная ветка только что сгенерирована, теперь меняем состояние и генерируем параллельную
|
||
if (isGenerateParallel)
|
||
{
|
||
CurrentParallelPosition = ParallelPosition.InsideParallel;
|
||
statements_list stl = OpenMP.TryConvertFor(head_stmts, _for_node, fn, vdn, initv, finishValue, this);
|
||
CurrentParallelPosition = ParallelPosition.Outside;
|
||
if (stl != null)
|
||
{
|
||
OpenMP.LoopVariables.Pop();
|
||
return_value(stl);
|
||
return;
|
||
}
|
||
}
|
||
if (OpenMP.ForsFound)
|
||
{
|
||
OpenMP.LoopVariables.Pop();
|
||
}
|
||
#endregion
|
||
|
||
return_value(head_stmts);
|
||
}
|
||
|
||
|
||
private expression_node additional_indexer_convertion(expression_node ind_expr, type_node array_type)
|
||
{
|
||
return convertion_data_and_alghoritms.convert_type(ind_expr, SystemLibrary.SystemLibrary.integer_type);
|
||
}
|
||
|
||
private void indexer_as_expression_index(expression_node expr, SyntaxTree.expression_list parameters,
|
||
motivation mot, location loc)
|
||
{
|
||
try_convert_typed_expression_to_function_call(ref expr);
|
||
|
||
// SSM 10.01.16 Tuple t[i]
|
||
var ent = expr.type as compiled_type_node;
|
||
|
||
if (ent== null)
|
||
{
|
||
var eeee = expr.type as compiled_generic_instance_type_node;
|
||
if (eeee!= null)
|
||
ent = eeee.original_generic as compiled_type_node;
|
||
}
|
||
|
||
if (ent != null)
|
||
{
|
||
var t = ent.compiled_type;
|
||
if (t != null && !t.IsArray && t.FullName.StartsWith("System.Tuple"))
|
||
{
|
||
expression eee = parameters.expressions[0];
|
||
|
||
if (parameters.expressions.Count > 1)
|
||
AddError(get_location(eee), "TUPLE_CAN_HAVE_ONLY_ONE_INDEX");
|
||
|
||
var cn = convert_strong_to_constant_node(eee);
|
||
|
||
var v = cn as int_const_node;
|
||
|
||
if (v != null)
|
||
{
|
||
if (v.constant_value<0 || v.constant_value >= t.GetGenericArguments().Count())
|
||
AddError(cn.location, "TUPLE_INDEX_OUT_OF_RANGE_{0}", t.GetGenericArguments().Count()-1);
|
||
var dn = new dot_node(new semantic_addr_value(expr), new ident("Item" + (v.constant_value + 1).ToString(), eee.source_context),new SourceContext(loc.begin_line_num,loc.begin_column_num,loc.end_line_num,loc.end_column_num));
|
||
visit(dn);
|
||
return;
|
||
}
|
||
else AddError(cn.location, "TUPLE_INDEX_MUST_BE_INTEGER_CONSTANT");
|
||
}
|
||
}
|
||
// end SSM 09.01.16 Tuple t[i]
|
||
|
||
if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
||
{
|
||
internal_interface ii = expr.type.get_internal_interface(internal_interface_kind.unsized_array_interface);
|
||
array_internal_interface aii = (array_internal_interface)ii;
|
||
int rank = aii.rank;
|
||
//TODO: Многомерные массивы.
|
||
expression_node ind_expr = convert_strong(parameters.expressions[0]);
|
||
ind_expr = additional_indexer_convertion(ind_expr, expr.type);
|
||
simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, aii.element_type, loc);
|
||
if (rank == 1)
|
||
for (int i = 1; i < parameters.expressions.Count; i++)
|
||
{
|
||
ii = sai.type.get_internal_interface(internal_interface_kind.unsized_array_interface);
|
||
location lloc = get_location(parameters.expressions[i]);
|
||
if (ii == null)
|
||
{
|
||
AddError(lloc, "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", i, i+1);
|
||
}
|
||
aii = (array_internal_interface)ii;
|
||
ind_expr = convert_strong(parameters.expressions[i]);
|
||
ind_expr = additional_indexer_convertion(ind_expr, sai.type);
|
||
sai = new simple_array_indexing(sai, ind_expr, aii.element_type, lloc);
|
||
}
|
||
else
|
||
{
|
||
if (rank != parameters.expressions.Count)
|
||
AddError(get_location(parameters), "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", rank, rank + 1);
|
||
List<expression_node> lst = new List<expression_node>();
|
||
for (int i = 0; i < parameters.expressions.Count; i++)
|
||
{
|
||
location lloc = get_location(parameters.expressions[i]);
|
||
ind_expr = convert_strong(parameters.expressions[i]);
|
||
ind_expr = additional_indexer_convertion(ind_expr, sai.type);
|
||
lst.Add(ind_expr);
|
||
}
|
||
sai = new simple_array_indexing(expr, lst[0], aii.element_type, get_location(parameters));
|
||
sai.expr_indices = lst.ToArray();
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(sai);
|
||
break;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(sai);
|
||
break;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(sai);
|
||
break;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
else if (expr.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
if (parameters.expressions.Count != 1)
|
||
AddError(loc, "INVALID_PARAMETER_COUNT_IN_INDEXER");
|
||
expression_node ind_expr = convert_strong(parameters.expressions[0]);
|
||
ind_expr = additional_indexer_convertion(ind_expr, expr.type);
|
||
//expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null));
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, SystemLibrary.SystemLibrary.char_type, loc);
|
||
return_addressed_value(sai);
|
||
//return_addressed_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr) as common_namespace_function_call);
|
||
break;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null)));
|
||
break;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null)));
|
||
break;
|
||
}
|
||
}
|
||
return;
|
||
|
||
}
|
||
/*else if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
internal_interface ii = expr.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
array_internal_interface aii = (array_internal_interface)ii;
|
||
//TODO: Многомерные массивы.
|
||
expression_node ind_expr = convert_strong(parameters.expressions[0]);
|
||
ind_expr = additional_indexer_convertion(ind_expr, expr.type);
|
||
simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, aii.element_type, loc);
|
||
for (int i = 1; i < parameters.expressions.Count; i++)
|
||
{
|
||
ii = sai.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
location lloc = get_location(parameters.expressions[i]);
|
||
if (ii == null)
|
||
{
|
||
throw new NDimensionalArrayCanNotHaveNPlusOneIndexer(lloc, expr, i);
|
||
}
|
||
aii = (array_internal_interface)ii;
|
||
ind_expr = convert_strong(parameters.expressions[i]);
|
||
ind_expr = create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, ind_expr,
|
||
new int_const_node(ii.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),cmc.location));
|
||
ind_expr = additional_indexer_convertion(ind_expr, sai.type);
|
||
sai = new simple_array_indexing(sai, ind_expr, aii.element_type, lloc);
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(sai);
|
||
break;
|
||
}
|
||
case motivation.expression_evaluation:
|
||
{
|
||
return_value(sai);
|
||
break;
|
||
}
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
return_semantic_value(sai);
|
||
break;
|
||
}
|
||
}
|
||
return;
|
||
|
||
if (factparams[i].semantic_node_type == semantic_node_type.common_method_call)
|
||
{
|
||
common_method_call cmc = (common_method_call)factparams[i];
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),cmc.location));
|
||
factparams[i] = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
}
|
||
}*/
|
||
if (expr.type.default_property_node == null)
|
||
{
|
||
if (expr.type.semantic_node_type != semantic_node_type.delegated_method)
|
||
{
|
||
AddError(loc, "NO_DEFAULT_PROPERTY_TO_TYPE_{0}", expr.type.PrintableName);
|
||
}
|
||
else
|
||
{
|
||
AddError(loc, "NO_DEFAULT_PROPERTY_TO_FUNCTION_TYPE");
|
||
}
|
||
}
|
||
|
||
if (expr.type.default_property_node.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToStaticPropertyWithExpression(expr.type.default_property_node, loc, expr.type));
|
||
}
|
||
non_static_property_reference nspr = new non_static_property_reference(expr.type.default_property_node, expr, loc);
|
||
indexer_as_property_indexes(nspr, parameters, mot, loc);
|
||
//eto vrode rabotaet normalno. no imet v vidu
|
||
if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
{
|
||
expression_node en = ret.get_expression();
|
||
if (en is non_static_property_reference)
|
||
{
|
||
non_static_property_reference cmc = (non_static_property_reference)en;
|
||
internal_interface ii = cmc.expression.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
//if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.expression, cmc.location);
|
||
expression_node right = cmc.fact_parametres[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
en = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
//is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
common_method_call cmc = (common_method_call)en;
|
||
internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
//if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name)
|
||
{
|
||
bounded_array_interface bai = (bounded_array_interface)ii;
|
||
class_field cf = bai.int_array;
|
||
expression_node left = new class_field_reference(cf, cmc.obj, cmc.location);
|
||
expression_node right = cmc.parameters[0];
|
||
//right = convert_type(right, SystemLibrary.SystemLibrary.integer_type);
|
||
right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type);
|
||
right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right,
|
||
new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location));
|
||
en = new simple_array_indexing(left, right, cmc.type, cmc.location);
|
||
//is_pascal_array_ref = true;
|
||
}
|
||
}
|
||
}
|
||
return_value(en);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
private void indexer_as_type_indexes(type_node type, SyntaxTree.expression_list parameters, motivation mot,
|
||
location loc)
|
||
{
|
||
if (type.default_property_node == null)
|
||
{
|
||
if (type.semantic_node_type != semantic_node_type.delegated_method)
|
||
{
|
||
AddError(loc, "NO_DEFAULT_PROPERTY_TO_TYPE_{0}", type.PrintableName);
|
||
}
|
||
else
|
||
{
|
||
AddError(loc, "NO_DEFAULT_PROPERTY_TO_FUNCTION_TYPE");
|
||
}
|
||
}
|
||
if (type.default_property_node.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToNonStaticPropertyWithType(type.default_property_node, loc, type));
|
||
}
|
||
static_property_reference spr = new static_property_reference(type.default_property_node, loc);
|
||
indexer_as_property_indexes(spr, parameters, mot, loc);
|
||
return;
|
||
}
|
||
|
||
private void indexer_as_property_indexes(static_property_reference spr, SyntaxTree.expression_list parameters,
|
||
motivation mot, location loc)
|
||
{
|
||
/*if (spr.property.parameters.Count==0)
|
||
{
|
||
switch(mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
function_node fn=spr.property.get_function;
|
||
base_function_call_with_method bfc=convertion_data_and_alghoritms.create_simple_function_call(fn,loc,new expression_node[0]);
|
||
return_value(bfc);
|
||
return;
|
||
}
|
||
case motivation.address_reciving:
|
||
{
|
||
return_addressed_value(spr);
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Unsupported motivation");
|
||
}*/
|
||
if (spr.property.parameters.Count != 0)
|
||
{
|
||
if (parameters.expressions.Count != spr.property.parameters.Count)
|
||
{
|
||
AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", spr.property.name);
|
||
}
|
||
for (int i = 0; i < parameters.expressions.Count; i++)
|
||
{
|
||
expression_node exp = convert_strong(parameters.expressions[i]);
|
||
exp = convertion_data_and_alghoritms.convert_type(exp, spr.property.parameters[i].type);
|
||
spr.fact_parametres.AddElement(exp);
|
||
}
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
function_node fn = spr.property.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(spr.property, loc));
|
||
}
|
||
//expression_node bfc=convertion_data_and_alghoritms.create_simple_function_call(fn,loc,spr.fact_params.ToArray());
|
||
base_function_call bfc = create_static_method_call(fn, loc, spr.property.comprehensive_type, false);
|
||
bfc.parameters.AddRange(spr.fact_parametres);
|
||
if (spr.property.parameters.Count != 0)
|
||
{
|
||
return_value(bfc);
|
||
return;
|
||
}
|
||
indexer_as_expression_index(bfc, parameters, mot, loc);
|
||
return;
|
||
}
|
||
case motivation.address_reciving:
|
||
{
|
||
if (spr.property.parameters.Count != 0)
|
||
{
|
||
return_addressed_value(spr);
|
||
return;
|
||
}
|
||
function_node fn = spr.property.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(spr.property, loc));
|
||
}
|
||
base_function_call bfc = create_static_method_call(fn, loc, spr.property.comprehensive_type, false);
|
||
bfc.parameters.AddRange(spr.fact_parametres);
|
||
indexer_as_expression_index(bfc, parameters, mot, loc);
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Unsupported motivation");
|
||
}
|
||
|
||
private void indexer_as_property_indexes(non_static_property_reference nspr, SyntaxTree.expression_list parameters,
|
||
motivation mot, location loc)
|
||
{
|
||
if (nspr.property.parameters.Count != 0)
|
||
{
|
||
if (parameters.expressions.Count != nspr.property.parameters.Count)
|
||
{
|
||
internal_interface ii = nspr.property.comprehensive_type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii != null)
|
||
{
|
||
//bounded_array_interface dii = (bounded_array_interface)ii;
|
||
|
||
expression_node exp = convert_strong(parameters.expressions[0]);
|
||
exp = convertion_data_and_alghoritms.convert_type(exp, nspr.property.parameters[0].type);
|
||
nspr.fact_parametres.AddElement(exp);
|
||
|
||
base_function_call bfc = null;
|
||
|
||
for (int i = 1; i < parameters.expressions.Count; i++)
|
||
{
|
||
bfc = create_not_static_method_call(nspr.property.get_function, nspr.expression, exp.location, false);
|
||
bfc.parameters.AddRange(nspr.fact_parametres);
|
||
|
||
location lloc = get_location(parameters.expressions[i]);
|
||
ii = bfc.type.get_internal_interface(internal_interface_kind.bounded_array_interface);
|
||
if (ii == null)
|
||
{
|
||
AddError(lloc, "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", i, i+1);
|
||
}
|
||
bounded_array_interface bii = (bounded_array_interface)ii;
|
||
exp = convert_strong(parameters.expressions[i]);
|
||
exp = convertion_data_and_alghoritms.convert_type(exp, bii.index_type);
|
||
nspr = new non_static_property_reference(bii.index_property, bfc, lloc);
|
||
nspr.fact_parametres.AddElement(exp);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", nspr.property.name);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//String 1 based
|
||
if (parameters.expressions.Count == 1 &&
|
||
nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type &&
|
||
!SemanticRules.NullBasedStrings)
|
||
{
|
||
nspr.fact_parametres.AddElement(
|
||
ConstructDecExpr(
|
||
convertion_data_and_alghoritms.convert_type(
|
||
convert_strong(parameters.expressions[0]), nspr.property.parameters[0].type), null));
|
||
}
|
||
else
|
||
for (int i = 0; i < parameters.expressions.Count; i++)
|
||
{
|
||
expression_node exp = convert_strong(parameters.expressions[i]);
|
||
exp = convertion_data_and_alghoritms.convert_type(exp, nspr.property.parameters[i].type);
|
||
nspr.fact_parametres.AddElement(exp);
|
||
}
|
||
}
|
||
}
|
||
switch (mot)
|
||
{
|
||
case motivation.expression_evaluation:
|
||
case motivation.semantic_node_reciving:
|
||
{
|
||
function_node fn = nspr.property.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(nspr.property, loc));
|
||
}
|
||
base_function_call bfc = create_not_static_method_call(fn, nspr.expression, loc, false);
|
||
bfc.parameters.AddRange(nspr.fact_parametres);
|
||
if (nspr.property.parameters.Count != 0)
|
||
{
|
||
return_value(bfc);
|
||
return;
|
||
}
|
||
indexer_as_expression_index(bfc, parameters, mot, loc);
|
||
return;
|
||
}
|
||
case motivation.address_reciving:
|
||
{
|
||
if (nspr.property.parameters.Count != 0)
|
||
{
|
||
return_addressed_value(nspr);
|
||
return;
|
||
}
|
||
function_node fn = nspr.property.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(nspr.property, loc));
|
||
}
|
||
base_function_call bfc = create_not_static_method_call(fn, nspr.expression, loc, false);
|
||
bfc.parameters.AddRange(nspr.fact_parametres);
|
||
indexer_as_expression_index(bfc, parameters, mot, loc);
|
||
return;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Unsupported motivation");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.indexer _indexer)
|
||
{
|
||
//SSM 11/02/16 - нет, это глупость
|
||
/*if (_indexer.dereferencing_value is SyntaxTree.question_colon_expression) // то разбросать индекс по компонентам
|
||
{
|
||
var q = _indexer.dereferencing_value as SyntaxTree.question_colon_expression;
|
||
var nodeToVisit = new SyntaxTree.question_colon_expression(q.condition, new indexer(q.ret_if_true as addressed_value, _indexer.indexes, _indexer.source_context),
|
||
new indexer(q.ret_if_false as addressed_value, _indexer.indexes, _indexer.source_context), _indexer.source_context);
|
||
visit(nodeToVisit);
|
||
return;
|
||
}*/
|
||
//end SSM 11/02/16
|
||
|
||
// SSM 18.08.16 - пробуем обработать захват enn[i] в yieldах где enn - поле класса и нуждается в переименовании
|
||
// Так же ниже делает lroman
|
||
if (_indexer.dereferencing_value is yield_unknown_ident)
|
||
{
|
||
var yui = (yield_unknown_ident)_indexer.dereferencing_value;
|
||
var av = ProcessUnknownIdent(yui);
|
||
var nodeToVisit = new indexer(av,_indexer.indexes);
|
||
visit(nodeToVisit);
|
||
return;
|
||
}
|
||
|
||
//lroman
|
||
if (_indexer.dereferencing_value is closure_substituting_node)
|
||
{
|
||
var nodeToVisit = new indexer(((closure_substituting_node) _indexer.dereferencing_value).substitution,
|
||
_indexer.indexes);
|
||
visit(nodeToVisit);
|
||
return;
|
||
}
|
||
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
SyntaxTree.ident idi = _indexer.dereferencing_value as SyntaxTree.ident;
|
||
if (idi != null)
|
||
{
|
||
SymbolInfo si = context.find(idi.name);
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(idi.name, get_location(idi)));
|
||
}
|
||
if (si.sym_info.general_node_type == general_node_type.type_node)
|
||
{
|
||
indexer_as_type_indexes((type_node)si.sym_info, _indexer.indexes, mot, get_location(idi));
|
||
return;
|
||
}
|
||
if (si.sym_info.general_node_type == general_node_type.property_node)
|
||
{
|
||
property_node pn = (property_node)si.sym_info;
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
static_property_reference spr = new static_property_reference(pn, get_location(idi));
|
||
indexer_as_property_indexes(spr, _indexer.indexes, mot, get_location(idi));
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
this_node thisnode = new this_node(pn.comprehensive_type, get_location(_indexer));
|
||
location loc111 = get_location(idi);
|
||
non_static_property_reference nspr = new non_static_property_reference(pn, thisnode, loc111);
|
||
indexer_as_property_indexes(nspr, _indexer.indexes, mot, loc111);
|
||
return;
|
||
}
|
||
}
|
||
expression_node en = ident_value_reciving(si, idi);
|
||
|
||
indexer_as_expression_index(en, _indexer.indexes, mot, get_location(idi));
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
SyntaxTree.dot_node dotnd = _indexer.dereferencing_value as SyntaxTree.dot_node;
|
||
if (dotnd != null)
|
||
{
|
||
SyntaxTree.ident id = dotnd.right as SyntaxTree.ident;
|
||
semantic_node sn = convert_semantic_strong(dotnd.left);
|
||
switch (sn.general_node_type)
|
||
{
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node ttp = (type_node)sn;
|
||
SymbolInfo si = ttp.find_in_type(id.name, context.CurrentScope);
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id.name, get_location(id)));
|
||
}
|
||
if (si.sym_info.general_node_type == general_node_type.property_node)
|
||
{
|
||
property_node pn = (property_node)si.sym_info;
|
||
static_property_reference spr = new static_property_reference(pn, get_location(id));
|
||
indexer_as_property_indexes(spr, _indexer.indexes, mot, get_location(dotnd));
|
||
return;
|
||
}
|
||
expression_node exp1 = create_static_expression(ttp, id, si);
|
||
indexer_as_expression_index(exp1, _indexer.indexes, mot, get_location(id));
|
||
return;
|
||
}
|
||
case general_node_type.namespace_node:
|
||
case general_node_type.unit_node:
|
||
{
|
||
SymbolInfo si = null;
|
||
if (sn is namespace_node)
|
||
si = ((namespace_node)sn).find(id.name);
|
||
else
|
||
si = ((unit_node)sn).find_only_in_namespace(id.name);
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id.name, get_location(id)));
|
||
}
|
||
location lloc = get_location(id);
|
||
if (si.sym_info.general_node_type == general_node_type.type_node)
|
||
{
|
||
type_node tn = (type_node)si.sym_info;
|
||
indexer_as_type_indexes(tn, _indexer.indexes, mot, lloc);
|
||
return;
|
||
}
|
||
expression_node exp2 = ident_value_reciving(si, id);
|
||
indexer_as_expression_index(exp2, _indexer.indexes, mot, get_location(id));
|
||
return;
|
||
}
|
||
case general_node_type.expression:
|
||
{
|
||
expression_node ex = (expression_node)sn;
|
||
SymbolInfo si = ex.type.find_in_type(id.name, context.CurrentScope);
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(id.name, get_location(id)));
|
||
}
|
||
if (si.sym_info.general_node_type == general_node_type.property_node)
|
||
{
|
||
property_node pn = (property_node)si.sym_info;
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(dotnd), ex.type));
|
||
}
|
||
location lloc11 = get_location(dotnd);
|
||
try_convert_typed_expression_to_function_call(ref ex);
|
||
non_static_property_reference nspr = new non_static_property_reference(pn, ex, lloc11);
|
||
indexer_as_property_indexes(nspr, _indexer.indexes, mot, lloc11);
|
||
return;
|
||
}
|
||
expression_node en2 = expression_value_reciving(id, si, ex, false);
|
||
indexer_as_expression_index(en2, _indexer.indexes, mot, get_location(id));
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
expression_node expr = convert_strong(_indexer.dereferencing_value);
|
||
indexer_as_expression_index(expr, _indexer.indexes, mot, get_location(_indexer.dereferencing_value));
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.roof_dereference _roof_dereference)
|
||
{
|
||
expression_node exp = null;
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
|
||
exp = convert_strong(_roof_dereference.dereferencing_value);
|
||
if (exp is typed_expression) exp = convert_typed_expression_to_function_call(exp as typed_expression);
|
||
//Check this expression
|
||
ref_type_node rtn = exp.type as ref_type_node;
|
||
//TODO: Сделать нормальное сообщение об ошибке.
|
||
if (rtn == null)
|
||
{
|
||
AddError(get_location(_roof_dereference.dereferencing_value), "CANNOT_DEREFER_THIS_EXPR_OF_NON_POINTER_TYPE");
|
||
}
|
||
if (rtn.pointed_type == null)
|
||
AddError(get_location(_roof_dereference.dereferencing_value), "TYPE_{0}_IS_NOT_DETERMINED_COMPLETELY", rtn.PointedTypeName);
|
||
dereference_node res = new dereference_node(exp, get_location(_roof_dereference));
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: return_addressed_value(res); break;
|
||
case motivation.expression_evaluation: return_value(res); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(res); break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.dereference _dereference)
|
||
{
|
||
throw new NotSupportedError(get_location(_dereference));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.expression_list _expression_list)
|
||
{
|
||
//throw new NotSupportedError(get_location(_expression_list));
|
||
int count = _expression_list.expressions.Count;
|
||
statement_node_list snl = new statement_node_list();
|
||
for (int i = 0; i < count - 1; i++)
|
||
{
|
||
statement_node sn = ret.visit(_expression_list.expressions[i]);
|
||
snl.AddElement(sn);
|
||
}
|
||
expression_node ex = ret.visit(_expression_list.expressions[count - 1]);
|
||
statements_expression_node sen = new statements_expression_node(
|
||
snl, ex, get_location(_expression_list));
|
||
return_value(sen);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.string_const _string_const)
|
||
{
|
||
expression_node en = null;
|
||
if (_string_const.Value.Length != 1)
|
||
{
|
||
en = new string_const_node(_string_const.Value, get_location(_string_const));
|
||
if (SemanticRules.GenerateNativeCode && SemanticRules.StringType != null)
|
||
en.type = SemanticRules.StringType;
|
||
}
|
||
else
|
||
en = new char_const_node(Convert.ToChar(_string_const.Value), get_location(_string_const));
|
||
|
||
|
||
return_value(en);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.program_name _program_name)
|
||
{
|
||
throw new NotSupportedError(get_location(_program_name));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.program_tree _program_tree)
|
||
{
|
||
_program_tree.compilation_units[0].visit(this);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.declarations _subprogram_definitions)
|
||
{
|
||
if (SemanticRules.OrderIndependedTypeNames)
|
||
{
|
||
foreach (SyntaxTree.declaration sd in _subprogram_definitions.defs)
|
||
{
|
||
if (sd is SyntaxTree.type_declaration)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(sd);
|
||
sd.visit(this);
|
||
}
|
||
}
|
||
}
|
||
foreach (SyntaxTree.declaration sd in _subprogram_definitions.defs)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(sd);
|
||
sd.visit(this);
|
||
}
|
||
if (SemanticRules.OrderIndependedFunctionNames)
|
||
{
|
||
visit_function_realizations(_subprogram_definitions);
|
||
context.clear_member_bindings();
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.declaration _subprogram_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_subprogram_definition));
|
||
}
|
||
|
||
private SyntaxTree.expression get_possible_array_const(SyntaxTree.expression expr, type_node tn, int rank)
|
||
{
|
||
try
|
||
{
|
||
if (tn == null)
|
||
return expr;
|
||
if (rank == 0)
|
||
return get_possible_array_const(expr, tn.element_type);
|
||
if (expr is SyntaxTree.bracket_expr)
|
||
{
|
||
SyntaxTree.array_const arr = new SyntaxTree.array_const();
|
||
arr.source_context = expr.source_context;
|
||
arr.elements = new SyntaxTree.expression_list();
|
||
arr.elements.expressions.Add(get_possible_array_const((expr as SyntaxTree.bracket_expr).expr, tn.element_type, rank - 1));
|
||
return arr;
|
||
}
|
||
else if (expr is SyntaxTree.array_const)
|
||
{
|
||
SyntaxTree.array_const arr = expr as SyntaxTree.array_const;
|
||
if (arr.elements != null)
|
||
for (int i = 0; i < arr.elements.expressions.Count; i++)
|
||
arr.elements.expressions[i] = get_possible_array_const(arr.elements.expressions[i], tn.element_type, rank - 1);
|
||
return arr;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
return expr;
|
||
}
|
||
|
||
private SyntaxTree.expression get_possible_array_const(SyntaxTree.expression expr, type_node tn)
|
||
{
|
||
try
|
||
{
|
||
if (tn == null)
|
||
return expr;
|
||
if (expr is SyntaxTree.bracket_expr && (tn.type_special_kind == SemanticTree.type_special_kind.array_kind || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper))
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
if (aii != null && aii.rank > 1)
|
||
return get_possible_array_const(expr, tn, aii.rank);
|
||
SyntaxTree.array_const arr = new SyntaxTree.array_const();
|
||
arr.source_context = expr.source_context;
|
||
arr.elements = new SyntaxTree.expression_list();
|
||
arr.elements.expressions.Add(get_possible_array_const((expr as SyntaxTree.bracket_expr).expr, tn.element_type));
|
||
return arr;
|
||
}
|
||
else if (expr is SyntaxTree.array_const && (tn.type_special_kind == SemanticTree.type_special_kind.array_kind || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper))
|
||
{
|
||
array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||
if (aii != null && aii.rank > 1)
|
||
return get_possible_array_const(expr, tn, aii.rank);
|
||
SyntaxTree.array_const arr = expr as SyntaxTree.array_const;
|
||
if (arr.elements != null)
|
||
for (int i = 0; i < arr.elements.expressions.Count; i++)
|
||
arr.elements.expressions[i] = get_possible_array_const(arr.elements.expressions[i], tn.element_type);
|
||
return arr;
|
||
}
|
||
else if (expr is SyntaxTree.record_const && tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
SyntaxTree.record_const rec = expr as SyntaxTree.record_const;
|
||
for (int i = 0; i < rec.rec_consts.Count; i++)
|
||
{
|
||
if (i < ctn.fields.Count)
|
||
rec.rec_consts[i].val = get_possible_array_const(rec.rec_consts[i].val, ctn.fields[i].type);
|
||
}
|
||
return rec;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
return expr;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.var_def_statement _var_def_statement)
|
||
{
|
||
if (_var_def_statement.vars_type == null && _var_def_statement.inital_value is SyntaxTree.function_lambda_definition)
|
||
AddError(get_location(_var_def_statement.inital_value), "IMPOSSIBLE_TO_INFER_TYPES_IN_LAMBDA"); //lroman//
|
||
|
||
bool is_event = _var_def_statement.is_event;
|
||
|
||
if (context.converting_block() == block_type.type_block &&
|
||
context.converted_type.IsInterface && !is_event)
|
||
{
|
||
AddError(get_location(_var_def_statement), "INVALID_INTERFACE_MEMBER");
|
||
}
|
||
|
||
if (is_event && context.converting_block() == block_type.type_block && context.converted_type.IsInterface && (_var_def_statement.vars_type is function_header || _var_def_statement.vars_type is procedure_header))
|
||
AddError(get_location(_var_def_statement.vars_type), "ANONYMOUS_DELEGATE_IN_INTERFACE_NOT_ALLOWED");
|
||
|
||
type_node tn = null;
|
||
expression_node inital_value = null;
|
||
if (_var_def_statement.vars_type != null)
|
||
{
|
||
tn = convert_strong(_var_def_statement.vars_type);
|
||
//LambdaHelper.InferTypesFromVarStmt(tn, _var_def_statement.inital_value as SyntaxTree.function_lambda_definition, this); //lroman//
|
||
|
||
var fld1 = _var_def_statement.inital_value as SyntaxTree.function_lambda_definition;
|
||
if (fld1 != null)
|
||
{
|
||
MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(fld1);
|
||
LambdaHelper.InferTypesFromVarStmt(tn, fld1, this); //lroman//
|
||
}
|
||
|
||
ref_type_node rt = tn as ref_type_node;
|
||
if (rt != null)
|
||
{
|
||
if (type_section_converting)
|
||
{
|
||
RefTypesForCheckPointersTypeForDotNetFramework.Add(rt);
|
||
}
|
||
else
|
||
{
|
||
CheckPointersTypeForDotNetFramework(rt.pointed_type, get_location(_var_def_statement.vars_type));
|
||
}
|
||
}
|
||
if (is_event && !tn.IsDelegate)
|
||
AddError(get_location(_var_def_statement.vars_type), "EVENT_TYPE_MUST_BE_DELEGATE");
|
||
check_for_type_allowed(tn,get_location(_var_def_statement.vars_type));
|
||
if (_var_def_statement.vars_type is function_header || _var_def_statement.vars_type is procedure_header)
|
||
check_delegate_on_generic_parameters(tn as common_type_node, get_location(_var_def_statement.vars_type));
|
||
if (context.converting_block() == block_type.type_block && context.converted_type.is_value_type)
|
||
CheckForCircuralInRecord(tn, get_location(_var_def_statement.vars_type));
|
||
if (_var_def_statement.inital_value != null)
|
||
if (is_event) AddError(new NotSupportedError(get_location(_var_def_statement.inital_value)));
|
||
else
|
||
{
|
||
_var_def_statement.inital_value = get_possible_array_const(_var_def_statement.inital_value,tn);
|
||
inital_value = convert_strong_to_constant_or_function_call_for_varinit(convert_strong(_var_def_statement.inital_value), tn);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (is_event)
|
||
AddError(get_location(_var_def_statement), "EVENT_MUST_HAVE_TYPE");
|
||
expression_node cn = convert_strong_to_constant_or_function_call_for_varinit(convert_strong(_var_def_statement.inital_value));
|
||
if (cn is constant_node)
|
||
(cn as constant_node).SetType(DeduceType(cn.type, get_location(_var_def_statement.inital_value)));
|
||
inital_value = cn;
|
||
tn = inital_value.type;
|
||
if (tn is null_type_node)
|
||
AddError(cn.location, "CAN_NOT_DEDUCE_TYPE_{0}", tn.name);
|
||
}
|
||
if (inital_value != null && inital_value is typed_expression)
|
||
{
|
||
inital_value = convert_typed_expression_to_function_call(inital_value as typed_expression);
|
||
tn = inital_value.type;
|
||
if (inital_value is typed_expression)
|
||
{
|
||
base_function_call bfc = ((inital_value as typed_expression).type as delegated_methods).proper_methods[0];
|
||
if (bfc.function.is_generic_function && _var_def_statement.vars_type == null)
|
||
{
|
||
AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null);
|
||
}
|
||
foreach (parameter p in bfc.simple_function_node.parameters)
|
||
{
|
||
if (p.type.is_generic_parameter)
|
||
AddError(inital_value.location, "USE_ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS");
|
||
}
|
||
common_type_node del =
|
||
convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null);
|
||
context.converted_namespace.types.AddElement(del);
|
||
tn = del;
|
||
inital_value = convertion_data_and_alghoritms.explicit_convert_type(inital_value, del);
|
||
inital_value.type = tn;
|
||
}
|
||
else if (inital_value is base_function_call)
|
||
{
|
||
base_function_call bfc = inital_value as base_function_call;
|
||
if (bfc.function.is_generic_function && _var_def_statement.vars_type == null)
|
||
{
|
||
AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null);
|
||
}
|
||
}
|
||
}
|
||
foreach (SyntaxTree.ident id in _var_def_statement.vars.idents)
|
||
{
|
||
location lid = get_location(id);
|
||
SemanticTree.polymorphic_state ps = SemanticTree.polymorphic_state.ps_common;
|
||
if (_var_def_statement.var_attr == SyntaxTree.definition_attribute.Static)
|
||
ps = SemanticTree.polymorphic_state.ps_static;
|
||
if (!is_event)
|
||
{
|
||
var_definition_node vdn = context.add_var_definition(id.name, lid, ps);
|
||
assign_doc_info(vdn,_var_def_statement);
|
||
if (_var_def_statement.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_var_def_statement, vdn);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
event_node ce = null;
|
||
if (context.converted_type != null && context.converted_type.IsInterface)
|
||
ps = SemanticTree.polymorphic_state.ps_virtual_abstract;
|
||
if (context.converted_type != null)
|
||
ce = context.add_event_definition(id.name, lid, tn, ps, context.converted_type.IsInterface);
|
||
else if (context.top_function == null)
|
||
ce = context.add_namespace_event(id.name, lid, tn);
|
||
else
|
||
AddError(lid, "EVENT_MUST_BE_IN_CLASS_OR_NAMESPACE");
|
||
assign_doc_info(ce,_var_def_statement);
|
||
if (_var_def_statement.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_var_def_statement, ce);
|
||
}
|
||
}
|
||
}
|
||
if (is_event) return;
|
||
context.save_var_definitions();
|
||
|
||
context.restore_var_definitions();
|
||
context.close_var_definition_list(tn, inital_value);
|
||
if (!SemanticRules.ManyVariablesOneInitializator && _var_def_statement.inital_value != null && _var_def_statement.vars.idents.Count > 1)
|
||
AddError(get_location(_var_def_statement.inital_value), "ONE_VARIABLE_ONE_INITIALIZATOR");
|
||
}
|
||
|
||
private void CheckForCircularityInPointers(ref_type_node left, type_node right, location loc)
|
||
{
|
||
if (left == null || right == null)
|
||
return;
|
||
if (left == right)
|
||
// #ErrorRefactoringProblem
|
||
// AddError(loc, "CIRCULARITY_IN_POINTER"); // Если заменить этой строкой следующую, то при запуске bin\TestRunner.exe это приложение зацикливается, что сопровождается утечкой памяти
|
||
AddError(new CircuralityInPointer(loc));
|
||
if (right is ref_type_node)
|
||
CheckForCircularityInPointers(left, (right as ref_type_node).pointed_type, loc);
|
||
else if (right.type_special_kind == SemanticTree.type_special_kind.array_kind || right.type_special_kind == SemanticTree.type_special_kind.array_wrapper)
|
||
CheckForCircularityInPointers(left,right.element_type,loc);
|
||
}
|
||
|
||
private void CheckForCircuralInRecord(type_node tn, location loc)
|
||
{
|
||
if (tn == context.converted_type || tn.original_generic == context.converted_type)
|
||
{
|
||
AddError(loc, "CIRCULARITY_IN_RECORD");
|
||
}
|
||
if (tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
if (ctn.is_value_type)
|
||
{
|
||
foreach (class_field fld in ctn.fields)
|
||
CheckForCircuralInRecord(fld.type, loc);
|
||
}
|
||
else
|
||
{
|
||
foreach (class_field fld in ctn.fields)
|
||
if (fld.type is simple_array) CheckForCircuralInRecord((fld.type as simple_array).element_type, loc);
|
||
}
|
||
}
|
||
}
|
||
|
||
//Пытается вывести тип
|
||
private type_node DeduceType(type_node tn, location loc)
|
||
{
|
||
if (tn is undefined_type || tn is null_type_node)
|
||
{
|
||
if (tn is ArrayConstType)
|
||
return convertion_data_and_alghoritms.type_constructor.create_unsized_array((tn as ArrayConstType).element_type, context.converted_namespace, 1, loc);
|
||
AddError(loc, "CAN_NOT_DEDUCE_TYPE_{0}", tn.name);
|
||
}
|
||
return tn;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.ident_list _ident_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_ident_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.variable_definitions _variable_definitions)
|
||
{
|
||
bool is_event = false;
|
||
foreach (SyntaxTree.var_def_statement vds in _variable_definitions.var_definitions)
|
||
{
|
||
convertion_data_and_alghoritms.check_node_parser_error(vds);
|
||
if (vds.is_event && !is_event)
|
||
is_event = true;
|
||
else if (is_event)
|
||
vds.is_event = true;
|
||
vds.visit(this);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.named_type_reference _named_type_reference)
|
||
{
|
||
type_node tn = find_type(_named_type_reference, get_location(_named_type_reference));
|
||
return_value(tn);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.type_definition _type_definition)
|
||
{
|
||
throw new NotSupportedError(get_location(_type_definition));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.addressed_value _addressed_value)
|
||
{
|
||
throw new NotSupportedError(get_location(_addressed_value));
|
||
}
|
||
|
||
private addressed_expression ident_address_reciving(SymbolInfo si, SyntaxTree.ident _ident)
|
||
{
|
||
location lloc = get_location(_ident);
|
||
definition_node dn = null;
|
||
if (!internal_is_assign)
|
||
dn = context.check_name_node_type(_ident.name, si, lloc,
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node);
|
||
else
|
||
dn = context.check_name_node_type(_ident.name, si, lloc,
|
||
general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node, general_node_type.constant_definition);
|
||
if (dn.general_node_type == general_node_type.constant_definition)
|
||
AddError(get_location(_ident), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT");
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.variable_node:
|
||
{
|
||
local_variable lv = dn as local_variable;
|
||
if (lv != null && (lv.function is common_method_node))
|
||
{
|
||
//self variable
|
||
if ((lv.function as common_method_node).self_variable == lv)
|
||
AddError(lloc, "VARIABLE_{0}_READONLY", lv.name);
|
||
}
|
||
return create_variable_reference(dn, lloc);
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
static_property_reference spr = new static_property_reference(pn, lloc);
|
||
return spr;
|
||
}
|
||
//this_node thisnode=new this_node(context.converted_type,lloc);
|
||
if (pn.comprehensive_type.Scope == null && pn is compiled_property_node)
|
||
(pn.comprehensive_type as compiled_type_node).init_scope();
|
||
non_static_property_reference nspr = new non_static_property_reference(pn, GetCurrentObjectReference(pn.comprehensive_type.Scope, pn, lloc), lloc);
|
||
return nspr;
|
||
}
|
||
case general_node_type.event_node:
|
||
{
|
||
if (dn.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
compiled_event ce = (compiled_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
static_event_reference ser = new static_event_reference(ce, get_location(_ident));
|
||
return ser;
|
||
}
|
||
nonstatic_event_reference nser = new nonstatic_event_reference(
|
||
GetCurrentObjectReference(ce.comprehensive_type.Scope, ce, lloc), ce, lloc);
|
||
return nser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
common_event ce = (common_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
static_event_reference ser = new static_event_reference(ce, get_location(_ident));
|
||
return ser;
|
||
}
|
||
nonstatic_event_reference nser = new nonstatic_event_reference(
|
||
GetCurrentObjectReference(ce.comprehensive_type.Scope, ce, lloc), ce, lloc);
|
||
return nser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_namespace_event)
|
||
{
|
||
common_namespace_event cne = (common_namespace_event)dn;
|
||
static_event_reference ser = new static_event_reference(cne, get_location(_ident));
|
||
return ser;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private expression_node ident_value_reciving(SymbolInfo si, SyntaxTree.ident _ident)
|
||
{
|
||
//SymbolInfo si=blocks.find(_ident.name);
|
||
location lloc = get_location(_ident);
|
||
definition_node dn = context.check_name_node_type(_ident.name, si, get_location(_ident), general_node_type.variable_node,
|
||
general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition,
|
||
general_node_type.event_node);
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.constant_definition:
|
||
{
|
||
constant_definition_node cdn = (constant_definition_node)dn;
|
||
if (cdn.const_value is array_const || cdn.const_value is record_constant || cdn.const_value is common_namespace_function_call_as_constant)
|
||
{
|
||
return create_constant_reference(cdn,lloc);
|
||
}
|
||
if (cdn.const_value == null)
|
||
AddError(new UndefinedNameReference(cdn.name,get_location(_ident)));
|
||
constant_node cn = cdn.const_value.get_constant_copy(get_location(_ident));
|
||
if (cn != null) return cn;
|
||
return cdn.const_value;
|
||
}
|
||
case general_node_type.variable_node:
|
||
{
|
||
local_variable lv = dn as local_variable;
|
||
if (lv != null && (lv.function is common_method_node))
|
||
{
|
||
//self variable
|
||
if ((lv.function as common_method_node).self_variable == lv)
|
||
//return new this_node((lv.function as common_method_node).cont_type, lloc);
|
||
return new this_node(lv.type, lloc);
|
||
//return GetCurrentObjectReference((lv.function as common_method_node).cont_type.Scope, lloc);
|
||
}
|
||
return create_variable_reference(dn, lloc);
|
||
}
|
||
case general_node_type.function_node:
|
||
{
|
||
//return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(),
|
||
// si,lloc,blocks.converted_type,blocks.top_function,false);
|
||
|
||
if (si.sym_info == SystemLibrary.SystemLibInitializer.NewProcedure.sym_info)
|
||
{
|
||
AddError(lloc, "EXPECTED_TYPE_AFTER_NEW");
|
||
}
|
||
if (si.sym_info is common_method_node && (si.sym_info as common_method_node).is_constructor)
|
||
return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(),
|
||
si, lloc, context.converted_type, context.top_function, false);
|
||
if (!(si.sym_info is common_in_function_function_node))
|
||
return make_delegate_wrapper(null, si, lloc, ((si.sym_info is common_method_node) && ((common_method_node)si.sym_info).IsStatic));
|
||
return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(),
|
||
si,lloc,context.converted_type,context.top_function,false);
|
||
}
|
||
case general_node_type.property_node:
|
||
{
|
||
property_node pn = (property_node)dn;
|
||
function_node fn = pn.get_function;
|
||
if (fn == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeReaded(pn, lloc));
|
||
}
|
||
if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
return create_static_method_call(fn, lloc, pn.comprehensive_type, false);
|
||
}
|
||
check_property_no_params(pn, lloc);
|
||
//this_node thisnode = new this_node(context.converted_type, lloc);
|
||
if (pn.comprehensive_type.Scope == null && pn is compiled_property_node)
|
||
(pn.comprehensive_type as compiled_type_node).init_scope();
|
||
return create_not_static_method_call(fn, GetCurrentObjectReference(pn.comprehensive_type.Scope, fn, lloc), lloc, false);
|
||
}
|
||
case general_node_type.event_node:
|
||
{
|
||
if (dn.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
compiled_event ce = (compiled_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
static_event_reference ser = new static_event_reference(ce, get_location(_ident));
|
||
return ser;
|
||
}
|
||
nonstatic_event_reference nser = new nonstatic_event_reference(
|
||
new this_node(context.converted_type, lloc), ce, lloc);
|
||
return nser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
common_event ce = (common_event)dn;
|
||
if (ce.is_static)
|
||
{
|
||
static_event_reference ser = new static_event_reference(ce, get_location(_ident));
|
||
return ser;
|
||
}
|
||
nonstatic_event_reference nser = new nonstatic_event_reference(
|
||
new this_node(context.converted_type, lloc), ce, lloc);
|
||
return nser;
|
||
}
|
||
else if (dn.semantic_node_type == semantic_node_type.common_namespace_event)
|
||
{
|
||
common_namespace_event cne = (common_namespace_event)dn;
|
||
if (_compiled_unit.namespaces.IndexOf(cne.namespace_node) != -1)
|
||
{
|
||
static_event_reference ser = new static_event_reference(cne, get_location(_ident));
|
||
return ser;
|
||
}
|
||
else
|
||
AddError(get_location(_ident), "EVENT_{0}_MUST_BE_IN_LEFT_PART", cne.name);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private expression_node create_constant_reference(constant_definition_node cdn, location loc)
|
||
{
|
||
if (cdn is namespace_constant_definition)
|
||
return new namespace_constant_reference(cdn as namespace_constant_definition,loc);
|
||
else if (cdn is function_constant_definition)
|
||
return new function_constant_reference(cdn as function_constant_definition,loc);
|
||
else
|
||
return cdn.const_value;
|
||
}
|
||
|
||
private SymbolInfo find_in_base(SyntaxTree.inherited_message ident)
|
||
{
|
||
if (context.converted_type == null)
|
||
{
|
||
AddError(get_location(ident), "INHERITED_EXPECTED_IN_CLASS");
|
||
}
|
||
if (context.converted_type.base_type == null)
|
||
{
|
||
AddError(get_location(ident), "NO_BASE_CLASS_DEFINED_BUT_INHERITED_MEET");
|
||
}
|
||
common_method_node cmn = context.converted_func_stack.first() as common_method_node;
|
||
if (cmn == null)
|
||
{
|
||
AddError(get_location(ident), "NAME_IN_BASE_CLASS_MUST_BE_METHOD");
|
||
}
|
||
|
||
SymbolInfo si = null;
|
||
if (cmn.is_constructor)
|
||
si = context.converted_type.base_type.find_in_type(compiler_string_consts.default_constructor_name, context.CurrentScope);
|
||
else
|
||
si = context.converted_type.base_type.find_in_type(cmn.name, context.CurrentScope);
|
||
while (si != null)
|
||
{
|
||
if (!cmn.is_constructor)
|
||
{
|
||
if (si.sym_info is function_node && convertion_data_and_alghoritms.function_eq_params_and_result(si.sym_info as function_node,cmn))
|
||
return si;
|
||
}
|
||
else
|
||
{
|
||
if (si.sym_info is function_node && convertion_data_and_alghoritms.function_eq_params(si.sym_info as function_node,cmn))
|
||
return si;
|
||
}
|
||
si = si.Next;
|
||
}
|
||
if (cmn.is_constructor)
|
||
AddError(get_location(ident), "NO_CONSTRUCTOR_IN_BASE_CLASS_WITH_SAME_PARAMETERS");
|
||
else
|
||
AddError(get_location(ident), "NAME_IN_BASE_CLASS_MUST_BE_METHOD");
|
||
return si;
|
||
/*if (si == null)
|
||
{
|
||
throw new UndefinedNameReference(name, get_location(ident));
|
||
}
|
||
if (!(si.sym_info is common_method_node) && !(si.sym_info is compiled_function_node))
|
||
{
|
||
throw new NameInBaseClassMustBeMethod(name, get_location(ident));
|
||
}
|
||
common_function_node cfn = si.sym_info as common_function_node;*/
|
||
}
|
||
|
||
private SymbolInfo find_in_base(SyntaxTree.inherited_ident ident)
|
||
{
|
||
if (context.converted_type == null)
|
||
{
|
||
AddError(get_location(ident), "INHERITED_EXPECTED_IN_CLASS");
|
||
}
|
||
if (context.converted_type.base_type == null)
|
||
{
|
||
AddError(get_location(ident), "NO_BASE_CLASS_DEFINED_BUT_INHERITED_MEET");
|
||
}
|
||
SymbolInfo si = context.converted_type.base_type.find_in_type(ident.name, context.CurrentScope);
|
||
if (si == null)
|
||
{
|
||
si = context.converted_namespace.find(ident.name);
|
||
if (si != null)
|
||
AddError(get_location(ident), "CLASS_MEMBER_{0}_EXPECTED", ident.name);
|
||
else
|
||
AddError(new UndefinedNameReference(ident.name, get_location(ident)));
|
||
}
|
||
return si;
|
||
}
|
||
|
||
private addressed_expression inherited_ident_address_reciving(SyntaxTree.inherited_ident _ident)
|
||
{
|
||
SymbolInfo si = find_in_base(_ident);
|
||
return ident_address_reciving(si, _ident);
|
||
}
|
||
|
||
private addressed_expression ident_address_reciving(SyntaxTree.ident _ident)
|
||
{
|
||
if ((context.converting_block() == block_type.function_block) && (context.top_function.return_variable != null))
|
||
{
|
||
SymbolInfo si = context.top_function.scope.FindOnlyInScope(_ident.name);//context.find_only_in_namespace(_ident.name);
|
||
if (si == null)
|
||
{
|
||
int comp = SystemLibrary.SystemLibrary.string_comparer.Compare(_ident.name, context.top_function.name);
|
||
if (comp == 0)
|
||
{
|
||
local_variable lv = context.top_function.return_variable;
|
||
return new local_variable_reference(lv, 0, get_location(_ident));
|
||
}
|
||
}
|
||
}
|
||
SymbolInfo idsi = context.find(_ident.name);
|
||
|
||
return ident_address_reciving(idsi, _ident);
|
||
}
|
||
|
||
internal addressed_expression create_variable_reference(definition_node dn, location lloc)
|
||
{
|
||
switch (dn.semantic_node_type)
|
||
{
|
||
case semantic_node_type.local_variable:
|
||
{
|
||
local_variable lv = (local_variable)dn;
|
||
if (context.converting_block() == block_type.function_block)
|
||
{
|
||
return new local_variable_reference(lv,
|
||
convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(lv.function.scope, context.top_function.scope), lloc);
|
||
}
|
||
else if (context.converting_block() == block_type.namespace_block)
|
||
{
|
||
return new local_variable_reference(lv, 0, lloc);
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Invalid block type");
|
||
}
|
||
}
|
||
case semantic_node_type.namespace_variable:
|
||
{
|
||
namespace_variable nv = (namespace_variable)dn;
|
||
return new namespace_variable_reference(nv, lloc);
|
||
}
|
||
case semantic_node_type.class_field:
|
||
{
|
||
class_field cf = (class_field)dn;
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
return new static_class_field_reference(cf, lloc);
|
||
}
|
||
expression_node obj = GetCurrentObjectReference(cf.cont_type.Scope,cf, lloc); //new this_node(context.converted_type, lloc);
|
||
return new class_field_reference(cf, obj, lloc);
|
||
}
|
||
case semantic_node_type.common_parameter:
|
||
{
|
||
if (context.in_parameters_block)
|
||
AddError(new ParameterReferenceInDefaultParameterNotAllowed(lloc));
|
||
common_parameter cpar = (common_parameter)dn;
|
||
return new common_parameter_reference(cpar,
|
||
convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(cpar.common_function.scope, context.top_function.scope), lloc);
|
||
}
|
||
case semantic_node_type.local_block_variable:
|
||
{
|
||
return new local_block_variable_reference((local_block_variable)dn, lloc);
|
||
}
|
||
case semantic_node_type.compiled_variable_definition:
|
||
{
|
||
return new static_compiled_variable_reference((compiled_variable_definition)dn,lloc);
|
||
}
|
||
default: throw new NotSupportedError(lloc);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private expression_node ident_value_reciving(SyntaxTree.ident _ident)
|
||
{
|
||
SymbolInfo si = context.find(_ident.name);
|
||
return ident_value_reciving(si, _ident);
|
||
}
|
||
|
||
private expression_node inherited_message_value_reciving(SyntaxTree.inherited_message _ident)
|
||
{
|
||
SymbolInfo si = find_in_base(_ident);
|
||
bool constr = false;
|
||
if (si != null)
|
||
if (si.sym_info is common_method_node)
|
||
{
|
||
if ((si.sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
constr = (si.sym_info as common_method_node).is_constructor;
|
||
}
|
||
else
|
||
if (si.sym_info is compiled_function_node)
|
||
{
|
||
if ((si.sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
}
|
||
else if (si.sym_info is compiled_constructor_node)
|
||
{
|
||
constr = true;
|
||
}
|
||
location loc = get_location(_ident);
|
||
function_node fn = si.sym_info as function_node;
|
||
base_function_call bfc = null;
|
||
common_function_node cfn = context.converted_func_stack.first();
|
||
int depth = context.converted_func_stack.size-1;
|
||
if (!constr)
|
||
{
|
||
if (fn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
bfc = create_not_static_method_call(fn,new this_node(context.converted_type,loc),loc,true);
|
||
if (bfc is common_method_call)
|
||
(bfc as common_method_call).virtual_call = false;
|
||
else
|
||
(bfc as compiled_function_call).virtual_call = false;
|
||
}
|
||
else if (fn is common_method_node)
|
||
bfc = create_static_method_call(fn,loc,(fn as common_method_node).cont_type,true);
|
||
else if (fn is compiled_function_node)
|
||
bfc = create_static_method_call(fn,loc,(fn as compiled_function_node).cont_type,true);
|
||
else
|
||
throw new NotSupportedError(loc);
|
||
}
|
||
else
|
||
{
|
||
if (!context.allow_inherited_ctor_call)
|
||
AddError(loc, "INHERITED_CONSTRUCTOR_CALL_MUST_BE_FIRST");
|
||
expressions_list exprs = new expressions_list();
|
||
foreach (common_parameter cp in cfn.parameters)
|
||
{
|
||
exprs.AddElement(new common_parameter_reference(cp,depth,loc));
|
||
}
|
||
if (fn is common_method_node)
|
||
{
|
||
common_constructor_call ccc = create_constructor_call((fn as common_method_node).cont_type,exprs,loc) as common_constructor_call;
|
||
ccc._new_obj_awaited = false;
|
||
return ccc;
|
||
}
|
||
else if (fn is compiled_constructor_node)
|
||
{
|
||
compiled_constructor_call ccc = create_constructor_call((fn as compiled_constructor_node).compiled_type,exprs,loc) as compiled_constructor_call;
|
||
ccc._new_obj_awaited = false;
|
||
return ccc;
|
||
}
|
||
else
|
||
throw new NotSupportedError(loc);
|
||
}
|
||
|
||
foreach (common_parameter cp in cfn.parameters)
|
||
{
|
||
bfc.parameters.AddElement(new common_parameter_reference(cp,depth,loc));
|
||
}
|
||
return bfc;
|
||
}
|
||
|
||
private expression_node inherited_ident_value_reciving(SyntaxTree.inherited_ident _ident)
|
||
{
|
||
SymbolInfo si = find_in_base(_ident);
|
||
if (si != null)
|
||
if (si.sym_info is common_method_node)
|
||
{
|
||
if ((si.sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
}
|
||
else
|
||
if (si.sym_info is compiled_function_node)
|
||
{
|
||
if ((si.sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD");
|
||
}
|
||
return ident_value_reciving(si, _ident);
|
||
}
|
||
|
||
|
||
private semantic_node ident_semantic_reciving(SyntaxTree.ident _ident)
|
||
{
|
||
SymbolInfo si_left = context.find(_ident.name);
|
||
return ident_semantic_reciving(si_left, _ident);
|
||
}
|
||
|
||
private semantic_node inherited_ident_semantic_reciving(SyntaxTree.inherited_ident _ident)
|
||
{
|
||
SymbolInfo si = find_in_base(_ident);
|
||
return ident_semantic_reciving(si, _ident);
|
||
}
|
||
|
||
private semantic_node ident_semantic_reciving(SymbolInfo si_left, SyntaxTree.ident _ident)
|
||
{
|
||
//SymbolInfo si_left=blocks.find(_ident.name);
|
||
location lloc = get_location(_ident);
|
||
if (si_left == null)
|
||
{
|
||
AddError(new UndefinedNameReference(_ident.name, lloc));
|
||
}
|
||
definition_node dn = context.check_name_node_type(_ident.name, si_left, get_location(_ident),
|
||
general_node_type.constant_definition, general_node_type.function_node,
|
||
general_node_type.namespace_node, general_node_type.property_node,
|
||
general_node_type.type_node, general_node_type.variable_node,
|
||
general_node_type.unit_node);
|
||
switch (dn.general_node_type)
|
||
{
|
||
case general_node_type.constant_definition:
|
||
case general_node_type.function_node:
|
||
case general_node_type.property_node:
|
||
case general_node_type.variable_node:
|
||
{
|
||
return ident_value_reciving(si_left, _ident);
|
||
}
|
||
case general_node_type.namespace_node:
|
||
{
|
||
//throw new CompilerInternalError("Unsupported now.");
|
||
return dn;
|
||
}
|
||
case general_node_type.type_node:
|
||
{
|
||
type_node tn = dn as type_node;
|
||
//dot_node_as_type_ident(tn,id_right,mot);
|
||
return tn;
|
||
}
|
||
case general_node_type.unit_node:
|
||
{
|
||
//throw new CompilerInternalError("Unsupproted now.");
|
||
//throw new NotSupportedError(get_location(_ident));
|
||
return dn;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.ident _ident)
|
||
{
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: return_addressed_value(ident_address_reciving(_ident)); break;
|
||
case motivation.expression_evaluation: return_value(ident_value_reciving(_ident)); break;
|
||
//case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(ident_semantic_reciving(_ident)); break;
|
||
default: throw new NotSupportedError(get_location(_ident));
|
||
}
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.subprogram_body _subprogram_body)
|
||
{
|
||
throw new NotSupportedError(get_location(_subprogram_body));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.statement _statement)
|
||
{
|
||
throw new NotSupportedError(get_location(_statement));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.double_const _double_const)
|
||
{
|
||
expression_node en = new double_const_node(_double_const.val, get_location(_double_const));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: throw new CompilerInternalError("Addres reciving from constant"); break;
|
||
case motivation.expression_evaluation: return_value(en); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(en); break;
|
||
}
|
||
//return_value(en);
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.int32_const int32)
|
||
{
|
||
|
||
//таблица целых констант на уровне синтаксиса
|
||
// - 0 +
|
||
// 32--------16----8----|----8----16--------32----------------64(bits)
|
||
// [ int64 )[ int32 ]( int64 ]( uint64 ]
|
||
|
||
//таблица целых констант на уровне семантики(???)
|
||
// - 0 +
|
||
// 32--------16----8----|----8----16--------32----------------64(bits)
|
||
// [ long )[ int )[byte](int]( long ]( ulong ]
|
||
|
||
//Отлюченно временно (из-за ошибок временно алгоритмах выбора оперетора?)
|
||
/*if(int32.val>=byte.MinValue && int32.val<=byte.MaxValue)
|
||
return_value(new byte_const_node((byte)int32.val, get_location(int32)));
|
||
else*/
|
||
expression_node en = null;
|
||
/*
|
||
if ((int32.val >= byte.MinValue) && (int32.val <= byte.MaxValue))
|
||
{
|
||
en = new byte_const_node((byte)int32.val, get_location(int32));
|
||
}
|
||
else
|
||
{
|
||
en = new int_const_node(int32.val, get_location(int32));
|
||
}
|
||
*/
|
||
en = SystemLibrary.static_executors.make_int_const(int32.val, get_location(int32));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: throw new CompilerInternalError("Addres reciving from constant"); break;
|
||
case motivation.expression_evaluation: return_value(en); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(en); break;
|
||
}
|
||
//return_value(en);
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.int64_const int64)
|
||
{
|
||
expression_node en = new long_const_node(int64.val, get_location(int64));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: throw new CompilerInternalError("Addres reciving from constant"); break;
|
||
case motivation.expression_evaluation: return_value(en); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(en); break;
|
||
}
|
||
//return_value(en);
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.uint64_const uint64)
|
||
{
|
||
//TODO добавить обработку
|
||
// :-)
|
||
//throw new CompilerInternalError("Числа UInt64 доступны только в PascalABC.NET Professional Edition");
|
||
expression_node en = new ulong_const_node(uint64.val, get_location(uint64));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: throw new CompilerInternalError("Addres reciving from constant"); break;
|
||
case motivation.expression_evaluation: return_value(en); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(en); break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
public override void visit(SyntaxTree.bool_const _bool_const)
|
||
{
|
||
expression_node en = new bool_const_node(_bool_const.val, get_location(_bool_const));
|
||
var mot = motivation_keeper.motivation;
|
||
motivation_keeper.reset();
|
||
switch (mot)
|
||
{
|
||
case motivation.address_reciving: throw new CompilerInternalError("Address reciving from constant");
|
||
case motivation.expression_evaluation: return_value(en); break;
|
||
case motivation.semantic_node_reciving: return_semantic_value(en); break;
|
||
}
|
||
//return_value(en);
|
||
return;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.const_node _const_node)
|
||
{
|
||
throw new NotSupportedError(get_location(_const_node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.un_expr _un_expr)
|
||
{
|
||
expression_node exp = convert_strong(_un_expr.subnode);
|
||
expression_node res = find_operator(_un_expr.operation_type, exp, get_location(_un_expr));
|
||
return_value(res);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.bin_expr _bin_expr)
|
||
{
|
||
expression_node left = convert_strong(_bin_expr.left);
|
||
expression_node right = convert_strong(_bin_expr.right);
|
||
expression_node res = find_operator(_bin_expr.operation_type, left, right, get_location(_bin_expr));
|
||
if (res.type.type_special_kind == SemanticTree.type_special_kind.base_set_type)
|
||
{
|
||
if (left.type.element_type == right.type.element_type)
|
||
res.type = left.type;
|
||
else if (type_table.compare_types(left.type, right.type) == type_compare.greater_type)
|
||
res.type = left.type;
|
||
else if (type_table.compare_types(left.type, right.type) == type_compare.less_type)
|
||
res.type = right.type;
|
||
else if (type_table.compare_types(left.type, right.type) == type_compare.non_comparable_type)
|
||
res.type = context.create_set_type(SystemLibrary.SystemLibrary.object_type, get_location(_bin_expr));
|
||
}
|
||
//ssyy, 15.05.2009
|
||
switch (_bin_expr.operation_type)
|
||
{
|
||
case PascalABCCompiler.SyntaxTree.Operators.Equal:
|
||
case PascalABCCompiler.SyntaxTree.Operators.NotEqual:
|
||
if (left.type.is_generic_parameter && right.type.is_generic_parameter)
|
||
{
|
||
compiled_static_method_call cfc = new compiled_static_method_call(
|
||
SystemLibrary.SystemLibrary.object_equals_method, get_location(_bin_expr));
|
||
cfc.parameters.AddElement(left);
|
||
cfc.parameters.AddElement(right);
|
||
if (_bin_expr.operation_type == PascalABCCompiler.SyntaxTree.Operators.NotEqual)
|
||
{
|
||
res = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node, get_location(_bin_expr), cfc);
|
||
}
|
||
else
|
||
{
|
||
res = cfc;
|
||
}
|
||
}
|
||
else if (left is static_event_reference)
|
||
{
|
||
if ((left as static_event_reference).en is compiled_event)
|
||
AddError(left.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (left as static_event_reference).en.name);
|
||
if (context.converted_type != null && context.converted_type != ((left as static_event_reference).en as common_event).cont_type)
|
||
AddError(left.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (left as static_event_reference).en.name);
|
||
}
|
||
else if (right is static_event_reference)
|
||
{
|
||
if ((right as static_event_reference).en is compiled_event)
|
||
AddError(right.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (right as static_event_reference).en.name);
|
||
if (context.converted_type != null && context.converted_type != ((right as static_event_reference).en as common_event).cont_type)
|
||
AddError(right.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (right as static_event_reference).en.name);
|
||
}
|
||
break;
|
||
}
|
||
return_value(res);
|
||
}
|
||
|
||
private void check_property_no_params(property_node pn, location loc)
|
||
{
|
||
if (pn.parameters.Count != 0)
|
||
{
|
||
AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pn.name);
|
||
}
|
||
}
|
||
|
||
private void check_property_params(static_property_reference pr, location loc)
|
||
{
|
||
if (pr.property.parameters.Count != pr.fact_parametres.Count)
|
||
{
|
||
AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pr.property.name);
|
||
}
|
||
}
|
||
|
||
private void check_property_params(non_static_property_reference pr, location loc)
|
||
{
|
||
if (pr.property.parameters.Count != pr.fact_parametres.Count)
|
||
{
|
||
AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pr.property.name);
|
||
}
|
||
}
|
||
|
||
private SyntaxTree.procedure_call ConvertEventOperationToProcedureCall(SyntaxTree.assign _assign)
|
||
{
|
||
SyntaxTree.ident event_name = _assign.to as SyntaxTree.ident;
|
||
SyntaxTree.dot_node dot = _assign.to as SyntaxTree.dot_node;
|
||
if (dot != null)
|
||
event_name = dot.right as SyntaxTree.ident;
|
||
if (event_name == null)
|
||
AddError(new EventNameExpected(get_location(_assign.to)));
|
||
string format;
|
||
if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction)
|
||
format = compiler_string_consts.event_remove_method_nameformat;
|
||
else
|
||
format = compiler_string_consts.event_add_method_nameformat;
|
||
SyntaxTree.ident add_name = new SyntaxTree.ident(string.Format(format, event_name.name));
|
||
add_name.source_context = event_name.source_context;
|
||
if (dot != null)
|
||
dot.right = add_name;
|
||
SyntaxTree.expression_list exprlist = new SyntaxTree.expression_list();
|
||
exprlist.expressions.Add(_assign.from);
|
||
exprlist.source_context = _assign.to.source_context;
|
||
SyntaxTree.method_call add_methcall = new SyntaxTree.method_call(exprlist);
|
||
if (dot != null)
|
||
add_methcall.dereferencing_value = dot;
|
||
else
|
||
add_methcall.dereferencing_value = add_name;
|
||
add_methcall.source_context = _assign.source_context;
|
||
SyntaxTree.procedure_call add_proccall = new SyntaxTree.procedure_call(add_methcall);
|
||
add_proccall.source_context = _assign.source_context;
|
||
return add_proccall;
|
||
}
|
||
private SyntaxTree.procedure_call ConvertOperatorToProcedureCall(SyntaxTree.assign _assign)
|
||
{
|
||
SyntaxTree.ident operator_name = new PascalABCCompiler.SyntaxTree.ident(name_reflector.get_name(_assign.operator_type));
|
||
operator_name.source_context = _assign.to.source_context;
|
||
SyntaxTree.dot_node dot = new PascalABCCompiler.SyntaxTree.dot_node(_assign.to, operator_name);
|
||
dot.source_context = _assign.to.source_context;
|
||
SyntaxTree.expression_list exprlist = new SyntaxTree.expression_list();
|
||
exprlist.expressions.Add(_assign.from);
|
||
exprlist.source_context = _assign.to.source_context;
|
||
SyntaxTree.method_call add_methcall = new SyntaxTree.method_call(exprlist);
|
||
add_methcall.dereferencing_value = dot;
|
||
add_methcall.source_context = _assign.source_context;
|
||
SyntaxTree.procedure_call add_proccall = new SyntaxTree.procedure_call(add_methcall);
|
||
add_proccall.source_context = _assign.source_context;
|
||
return add_proccall;
|
||
}
|
||
|
||
private expression_node ConstructDecExpr(expression_node en, location loc)
|
||
{
|
||
int_const_node one = new int_const_node(1, loc);
|
||
return find_operator(SyntaxTree.Operators.Minus, en, one, loc);
|
||
}
|
||
|
||
private void check_field_reference_for_assign(class_field_reference expr, location loc)
|
||
{
|
||
if (expr.obj is namespace_constant_reference || expr.obj is function_constant_reference)
|
||
AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
||
else if (expr.obj is class_field_reference) check_field_reference_for_assign(expr.obj as class_field_reference,loc);
|
||
else if (expr.obj is simple_array_indexing) check_expression_for_assign((expr.obj as simple_array_indexing).simple_arr_expr,loc);
|
||
}
|
||
|
||
private void check_expression_for_assign(expression_node expr, location loc)
|
||
{
|
||
if (expr is namespace_constant_reference || expr is function_constant_reference)
|
||
AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
||
else if (expr is class_field_reference) check_field_reference_for_assign(expr as class_field_reference,loc);
|
||
else if (expr is simple_array_indexing) check_expression_for_assign((expr as simple_array_indexing).simple_arr_expr,loc);
|
||
}
|
||
|
||
public bool internal_is_assign = false;
|
||
|
||
public override void visit(SyntaxTree.assign _assign)
|
||
{
|
||
internal_is_assign = true;
|
||
addressed_expression to = convert_address_strong(_assign.to);
|
||
internal_is_assign = false;
|
||
if (to == null)
|
||
AddError(get_location(_assign.to), "CAN_NOT_ASSIGN_TO_LEFT_PART");
|
||
|
||
|
||
#region Вывод параметров лямбда-выражения
|
||
var fld1 = _assign.from as SyntaxTree.function_lambda_definition;
|
||
if (fld1 != null)
|
||
{
|
||
//MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(fld1); - вроде бы это делается внутри InferTypesFromVarStmt
|
||
LambdaHelper.InferTypesFromVarStmt(to.type, fld1, this); //lroman//
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
//(ssyy) Вставляю проверки прямо сюда, т.к. запарился вылавливать другие случаи.
|
||
bool flag=false;
|
||
general_node_type node_type = general_node_type.constant_definition;
|
||
if (convertion_data_and_alghoritms.check_for_constant_or_readonly(to, out flag, out node_type))
|
||
{
|
||
if (flag)
|
||
AddError(to.location, "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT");
|
||
else
|
||
AddError(new CanNotAssignToReadOnlyElement(to.location,node_type));
|
||
}
|
||
|
||
//expression_node from = convert_strong(_assign.from);
|
||
/// SSM исправление Саушкина 10.03.16
|
||
expression_node from;
|
||
var fromAsLambda = _assign.from as function_lambda_definition;
|
||
if (fromAsLambda != null)
|
||
{
|
||
var lambdaVisitMode = fromAsLambda.lambda_visit_mode;
|
||
fromAsLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
from = convert_strong(_assign.from);
|
||
fromAsLambda.lambda_visit_mode = lambdaVisitMode;
|
||
}
|
||
else
|
||
{
|
||
from = convert_strong(_assign.from);
|
||
// SSM 26.06.16 - правка в связи с автовыведением типов в yieldах
|
||
if (to.type is auto_type)
|
||
{
|
||
if (to is class_field_reference)
|
||
{
|
||
var cfr = to as class_field_reference;
|
||
cfr.field.type = from.type;
|
||
cfr.type = from.type;
|
||
}
|
||
else if (to is local_block_variable_reference)
|
||
{
|
||
var lvr = to as local_block_variable_reference;
|
||
lvr.var.type = from.type;
|
||
lvr.type = from.type;
|
||
}
|
||
else AddError(to.location, "Не могу вывести тип при наличии yield: "+ to.type.full_name);
|
||
//to.type = from.type; // и без всякого real_type!
|
||
}
|
||
else if (to.type is compiled_generic_instance_type_node && (to.type as compiled_generic_instance_type_node).instance_params[0] is ienumerable_auto_type)
|
||
{
|
||
var tt = to.type;
|
||
type_node elem_type = null;
|
||
var b = FindIEnumerableElementType(from.type, ref elem_type);
|
||
if (!b)
|
||
AddError(null, "FindIEnumerableElementType returns false");
|
||
|
||
var IEnumType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new semantic_type_node(elem_type)));
|
||
if (to is class_field_reference)
|
||
{
|
||
var cfr = to as class_field_reference;
|
||
|
||
cfr.field.type = convert_strong(IEnumType);
|
||
cfr.type = cfr.field.type;
|
||
}
|
||
else if (to is local_block_variable_reference)
|
||
{
|
||
var lvr = to as local_block_variable_reference;
|
||
|
||
lvr.var.type = convert_strong(IEnumType); // замена типа у описания переменной
|
||
lvr.type = lvr.var.type; // замена типа у переменной
|
||
}
|
||
}
|
||
}
|
||
/// end
|
||
|
||
//SSM 4.04.16
|
||
if (to.type is undefined_type)
|
||
to.type = from.type;
|
||
|
||
if (stflambda.Count>0) // мы находимся внутри лямбды - возможно, вложенной
|
||
{
|
||
var fld = stflambda.Peek();
|
||
if (_assign.to is ident && (_assign.to as ident).name.ToLower()=="result" && fld.RealSemTypeOfResExpr == null) // если это - первое присваивание Result
|
||
{
|
||
fld.RealSemTypeOfResExpr = from.type;
|
||
fld.RealSemTypeOfResult = to.type;
|
||
}
|
||
|
||
}
|
||
|
||
location loc = get_location(_assign);
|
||
bool oper_ass_in_prop = false;
|
||
|
||
//проверка на обращение к полю записи возвращенной из функции с целью присваивания
|
||
//нужно чтобы пользователь не мог менять временный обьект
|
||
if (to.semantic_node_type == semantic_node_type.static_property_reference ||
|
||
to.semantic_node_type == semantic_node_type.non_static_property_reference)
|
||
{
|
||
property_node pn = null;
|
||
base_function_call prop_expr = null;
|
||
if (to.semantic_node_type == semantic_node_type.static_property_reference)
|
||
pn = (to as static_property_reference).property;
|
||
else
|
||
pn = (to as non_static_property_reference).property;
|
||
|
||
PascalABCCompiler.SyntaxTree.Operators ot = PascalABCCompiler.SyntaxTree.Operators.Undefined;
|
||
switch (_assign.operator_type)
|
||
{
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentAddition:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.Plus;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseAND:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseAND;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseLeftShift:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseLeftShift;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseOR:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseOR;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseRightShift:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseRightShift;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseXOR:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseXOR;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentDivision:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.Division;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentModulus:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.ModulusRemainder;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentMultiplication:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.Multiplication;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction:
|
||
ot = PascalABCCompiler.SyntaxTree.Operators.Minus;
|
||
oper_ass_in_prop = true;
|
||
break;
|
||
}
|
||
if (oper_ass_in_prop)
|
||
{
|
||
if (pn.get_function == null)
|
||
AddError(new ThisPropertyCanNotBeReaded(pn,loc));
|
||
if (to.semantic_node_type == semantic_node_type.non_static_property_reference)
|
||
{
|
||
prop_expr = create_not_static_method_call(pn.get_function,(to as non_static_property_reference).expression,loc,false);
|
||
prop_expr.parameters.AddRange((to as non_static_property_reference).fact_parametres);
|
||
}
|
||
else
|
||
{
|
||
prop_expr = create_static_method_call(pn.get_function,loc,pn.comprehensive_type,false);
|
||
prop_expr.parameters.AddRange((to as static_property_reference).fact_parametres);
|
||
}
|
||
from = find_operator(ot,prop_expr,from,loc);
|
||
}
|
||
}
|
||
else
|
||
if (to is class_field_reference)
|
||
{
|
||
if ((to as class_field_reference).obj.type.type_special_kind == SemanticTree.type_special_kind.record &&
|
||
(to as class_field_reference).obj is base_function_call)
|
||
{
|
||
//исключим ситуацию обращения к массиву
|
||
if (!(((to as class_field_reference).obj is common_method_call) &&
|
||
((to as class_field_reference).obj as common_method_call).obj.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper))
|
||
AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
||
}
|
||
//else check_field_reference_for_assign(to as class_field_reference,loc);
|
||
}
|
||
else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.namespace_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((to as namespace_variable_reference).var))
|
||
AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.local_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((to as local_variable_reference).var))
|
||
AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.local_block_variable_reference)
|
||
{
|
||
if (context.is_loop_variable((to as local_block_variable_reference).var))
|
||
AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE");
|
||
}
|
||
else if (to is simple_array_indexing)
|
||
if ((to as simple_array_indexing).simple_arr_expr is class_field_reference && ((to as simple_array_indexing).simple_arr_expr as class_field_reference).obj != null &&
|
||
((to as simple_array_indexing).simple_arr_expr as class_field_reference).obj is constant_node)
|
||
AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO");
|
||
if ((to.semantic_node_type == semantic_node_type.static_event_reference)
|
||
|| (to.semantic_node_type == semantic_node_type.nonstatic_event_reference))
|
||
{
|
||
statement_node event_assign = null;
|
||
if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.Assignment)
|
||
{
|
||
//throw new CanNotAssignToEvent();
|
||
}
|
||
static_event_reference ser = (static_event_reference)to;
|
||
expression_node right_del = convertion_data_and_alghoritms.convert_type(from, ser.en.delegate_type);
|
||
switch (_assign.operator_type)
|
||
{
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentAddition:
|
||
{
|
||
if (to.semantic_node_type == semantic_node_type.static_event_reference)
|
||
{
|
||
event_assign = convertion_data_and_alghoritms.create_simple_function_call(
|
||
ser.en.add_method, loc, right_del);
|
||
}
|
||
else
|
||
{
|
||
if (ser.en.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
nonstatic_event_reference nser = (nonstatic_event_reference)ser;
|
||
compiled_function_node cfn = (compiled_function_node)ser.en.add_method;
|
||
compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc);
|
||
tmp_event_assign.parameters.AddElement(right_del);
|
||
event_assign = tmp_event_assign;
|
||
}
|
||
else if (ser.en.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
nonstatic_event_reference nser = (nonstatic_event_reference)ser;
|
||
common_method_node cfn = (common_method_node)ser.en.add_method;
|
||
common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc);
|
||
tmp_event_assign.parameters.AddElement(right_del);
|
||
event_assign = tmp_event_assign;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction:
|
||
{
|
||
if (to.semantic_node_type == semantic_node_type.static_event_reference)
|
||
{
|
||
event_assign = convertion_data_and_alghoritms.create_simple_function_call(
|
||
ser.en.remove_method, loc, right_del);
|
||
}
|
||
else
|
||
{
|
||
if (ser.en.semantic_node_type == semantic_node_type.compiled_event)
|
||
{
|
||
nonstatic_event_reference nser = (nonstatic_event_reference)ser;
|
||
compiled_function_node cfn = (compiled_function_node)ser.en.remove_method;
|
||
compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc);
|
||
tmp_event_assign.parameters.AddElement(right_del);
|
||
event_assign = tmp_event_assign;
|
||
}
|
||
else if (ser.en.semantic_node_type == semantic_node_type.common_event)
|
||
{
|
||
nonstatic_event_reference nser = (nonstatic_event_reference)ser;
|
||
common_method_node cfn = (common_method_node)ser.en.remove_method;
|
||
common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc);
|
||
tmp_event_assign.parameters.AddElement(right_del);
|
||
event_assign = tmp_event_assign;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
AddError(loc, "ASSIGN_TO_EVENT");
|
||
//throw new CanNotApplyThisOperationToEvent
|
||
|
||
break;
|
||
}
|
||
}
|
||
return_value(event_assign);
|
||
return;
|
||
}
|
||
|
||
if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.Assignment || oper_ass_in_prop)
|
||
{
|
||
if (to.semantic_node_type == semantic_node_type.static_property_reference)
|
||
{
|
||
static_property_reference spr = (static_property_reference)to;
|
||
if (spr.property.set_function == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeWrited(spr.property, loc));
|
||
}
|
||
check_property_params(spr, loc);
|
||
function_node set_func = spr.property.set_function;
|
||
from = convertion_data_and_alghoritms.convert_type(from, spr.property.property_type);
|
||
spr.fact_parametres.AddElement(from);
|
||
base_function_call bfc = create_static_method_call(set_func, loc, spr.property.comprehensive_type,
|
||
true);
|
||
bfc.parameters.AddRange(spr.fact_parametres);
|
||
return_value((statement_node)bfc);
|
||
return;
|
||
}
|
||
else if (to.semantic_node_type == semantic_node_type.non_static_property_reference)
|
||
{
|
||
non_static_property_reference nspr = (non_static_property_reference)to;
|
||
check_property_params(nspr, loc);
|
||
from = convertion_data_and_alghoritms.convert_type(from, nspr.property.property_type);
|
||
nspr.fact_parametres.AddElement(from);
|
||
|
||
//Обработка s[i]:='c'
|
||
if (SystemUnitAssigned)
|
||
if (nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type)
|
||
{
|
||
if (nspr.property == SystemLibrary.SystemLibrary.string_type.default_property_node)
|
||
{
|
||
if (SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure != null)
|
||
{
|
||
expressions_list exl = new expressions_list();
|
||
exl.AddElement(nspr.expression);
|
||
exl.AddElement(nspr.fact_parametres[0]);
|
||
exl.AddElement(from);
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc);
|
||
expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray());
|
||
return_value((statement_node)ret);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (nspr.property.set_function == null)
|
||
{
|
||
AddError(new ThisPropertyCanNotBeWrited(nspr.property, loc));
|
||
}
|
||
function_node set_func = nspr.property.set_function;
|
||
base_function_call bfc = create_not_static_method_call(set_func, nspr.expression, loc,
|
||
true);
|
||
bfc.parameters.AddRange(nspr.fact_parametres);
|
||
return_value((statement_node)bfc);
|
||
return;
|
||
}
|
||
else if (to is simple_array_indexing && (to as simple_array_indexing).simple_arr_expr.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node expr = (to as simple_array_indexing).simple_arr_expr;
|
||
expression_node ind_expr = (to as simple_array_indexing).ind_expr;
|
||
from = convertion_data_and_alghoritms.convert_type(from,SystemLibrary.SystemLibrary.char_type);
|
||
ind_expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null),from);
|
||
return_value(find_operator(compiler_string_consts.assign_name, expr, ind_expr, get_location(_assign)));
|
||
return;
|
||
}
|
||
else if (to.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
if (from.type is null_type_node)
|
||
AddError(get_location(_assign), "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
|
||
expression_node clip_expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, loc, convertion_data_and_alghoritms.convert_type(from, SystemLibrary.SystemLibrary.string_type), new int_const_node((to.type as short_string_type_node).Length, null));
|
||
statement_node en = find_operator(compiler_string_consts.assign_name, to, clip_expr, get_location(_assign));
|
||
return_value(en);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
|
||
assign_is_converting = true;
|
||
statement_node en = find_operator(compiler_string_consts.assign_name, to, from, get_location(_assign));
|
||
assign_is_converting = false;
|
||
return_value(en);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
assign_is_converting = true;
|
||
statement_node en = find_operator(_assign.operator_type, to, from, get_location(_assign));
|
||
assign_is_converting = false;
|
||
return_value(en);
|
||
return;
|
||
}
|
||
//throw new CompilerInternalError("Undefined assign to type");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.expression _expression)
|
||
{
|
||
throw new NotSupportedError(get_location(_expression));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.statement_list _statement_list)
|
||
{
|
||
#region MikhailoMMX, обработка omp parallel section
|
||
bool isGenerateParallel = false;
|
||
bool isGenerateSequential = true;
|
||
if (OpenMP.SectionsFound) //если в программе есть хоть одна директива parallel sections - проверяем:
|
||
if (DirectivesToNodesLinks.ContainsKey(_statement_list) && OpenMP.IsParallelSectionsDirective(DirectivesToNodesLinks[_statement_list]))
|
||
{
|
||
//перед этим узлом есть директива parallel sections
|
||
if (CurrentParallelPosition == ParallelPosition.Outside) //входим в самый внешний параллельный sections
|
||
{
|
||
//сгенерировать сначала последовательную ветку, затем параллельную
|
||
//устанавливаем флаг и продолжаем конвертирование, считая, что конвертируем последовательную ветку
|
||
isGenerateParallel = true;
|
||
CurrentParallelPosition = ParallelPosition.InsideSequential;
|
||
//в конце за счет флага вернем состояние обратно и сгенерируем и параллельную ветку тоже
|
||
}
|
||
else //уже генерируем одну из веток
|
||
if (CurrentParallelPosition == ParallelPosition.InsideParallel)
|
||
{
|
||
isGenerateParallel = true;
|
||
isGenerateSequential = false;
|
||
}
|
||
//else
|
||
//флаг isGenerateParallel не установлен, параллельная ветка не сгенерируется
|
||
}
|
||
#endregion
|
||
|
||
|
||
statements_list stl = new statements_list(get_location(_statement_list), get_location_with_check(_statement_list.left_logical_bracket), get_location_with_check(_statement_list.right_logical_bracket));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(stl);
|
||
|
||
for (var i=0; i< _statement_list.subnodes.Count; i++) // SSM 13.10.16 - поменял т.к. собираюсь менять узлы в процессе обхода
|
||
//foreach (statement syntax_statement in _statement_list.subnodes)
|
||
{
|
||
statement syntax_statement = _statement_list.subnodes[i];
|
||
try
|
||
{
|
||
// SSM выкинул эти три строки - теперь внутриблочные описания обрабатываются как обычные операторы.
|
||
// При этом в конце visit(var_statement) стоит вызов ret.reset(), который возвращает нулевой semantic_statement - и всё работает эквивалентно
|
||
//if (syntax_statement is SyntaxTree.var_statement)
|
||
// visit(syntax_statement as SyntaxTree.var_statement); // Добавление в текущий statements_list происходит опосредованно !!
|
||
//else if (MustVisitBody) // MustVisitBody - всегда True!!!
|
||
//{
|
||
//(ssyy) TODO Сделать по-другому!!!
|
||
statement_node semantic_statement = convert_strong(syntax_statement);
|
||
//(ssyy) Проверка для C
|
||
if (semantic_statement != null)
|
||
{
|
||
//Обработать по другому - комментарий не мой - SSM
|
||
//if (context.CurrentScope.AddStatementsToFront)
|
||
// stl.statements.AddElementFirst(semantic_statement);
|
||
//else
|
||
stl.statements.AddElement(semantic_statement);
|
||
}
|
||
|
||
context.allow_inherited_ctor_call = false;
|
||
//}
|
||
}
|
||
catch (Errors.Error ex)
|
||
{
|
||
if (ThrowCompilationError)
|
||
throw ex;
|
||
else
|
||
ErrorsList.Add(ex);
|
||
}
|
||
}
|
||
convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
|
||
#region MikhailoMMX, обработка omp parallel sections
|
||
//флаг был установлен только если это самый внешний parallel sections и нужно сгенерировать обе ветки
|
||
//или если это вложенный parallel sections, нужно сгенерировать обе ветки, но без проверки на OMP_Available
|
||
//Последовательная ветка только что сгенерирована, теперь меняем состояние и генерируем параллельную
|
||
if (isGenerateParallel)
|
||
{
|
||
CurrentParallelPosition = ParallelPosition.InsideParallel;
|
||
statements_list omp_stl = OpenMP.TryConvertSections(stl, _statement_list, this);
|
||
CurrentParallelPosition = ParallelPosition.Outside;
|
||
if (omp_stl != null)
|
||
{
|
||
return_value(omp_stl);
|
||
return;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
return_value(stl);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.syntax_tree_node _tree_node)
|
||
{
|
||
throw new NotSupportedError(get_location(_tree_node));
|
||
}
|
||
|
||
private bool has_dll_import_attribute(common_function_node cfn)
|
||
{
|
||
foreach (attribute_node attr in cfn.attributes)
|
||
{
|
||
if (attr.attribute_type == SystemLibrary.SystemLibrary.dllimport_type)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private bool is_pinvoke(SyntaxTree.proc_block bl)
|
||
{
|
||
if (bl is SyntaxTree.external_directive)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private attribute_node get_dll_import_attribute(common_function_node cfn)
|
||
{
|
||
foreach (attribute_node attr in cfn.attributes)
|
||
{
|
||
if (attr.attribute_type == SystemLibrary.SystemLibrary.dllimport_type)
|
||
return attr;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.external_directive _external_directive)
|
||
{
|
||
string module_name = "";
|
||
string name = "";
|
||
if (_external_directive.modulename == null)
|
||
{
|
||
if (!has_dll_import_attribute(context.top_function))
|
||
{
|
||
AddError(context.top_function.loc, "FUNCTION_MUST_HAVE_DLLIMPORT_ATTRIBUTE");
|
||
}
|
||
else
|
||
{
|
||
location loc2 = get_location(_external_directive);
|
||
pinvoke_statement pinv_stmt = new pinvoke_statement(loc2);
|
||
//statement_node_list sal = new statement_node_list(loc);
|
||
//sal.AddElement(ext_stmt);
|
||
statements_list sl2 = new statements_list(loc2);
|
||
sl2.statements.AddElement(pinv_stmt);
|
||
//return_value(sl);
|
||
context.code = sl2;
|
||
return;
|
||
}
|
||
}
|
||
if (has_dll_import_attribute(context.top_function))
|
||
{
|
||
AddError(get_location(_external_directive.modulename), "FUNCTION_MUST_HAVE_ONLY_EXTERNAL_STATEMENT");
|
||
}
|
||
if (_external_directive.modulename is SyntaxTree.string_const)
|
||
{
|
||
module_name = ((SyntaxTree.string_const)_external_directive.modulename).Value;
|
||
}
|
||
else if (_external_directive.modulename is SyntaxTree.ident)
|
||
{
|
||
//throw new CompilerInternalError("Unsupported now");
|
||
//throw new NotSupportedError(get_location(_external_directive));
|
||
expression_node en = convert_strong(_external_directive.modulename as SyntaxTree.ident);
|
||
if (en is string_const_node)
|
||
module_name = (en as string_const_node).constant_value;
|
||
else
|
||
AddError(get_location(_external_directive.modulename), "STRING_CONSTANT_EXPECTED");
|
||
}
|
||
else
|
||
AddError(get_location(_external_directive.modulename), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED");
|
||
if (_external_directive.name == null)
|
||
{
|
||
name = context.converted_func_stack.top().name;
|
||
}
|
||
else
|
||
if (_external_directive.name is SyntaxTree.string_const)
|
||
{
|
||
name = ((SyntaxTree.string_const)_external_directive.name).Value;
|
||
}
|
||
else if (_external_directive.name is SyntaxTree.ident)
|
||
{
|
||
expression_node en = convert_strong(_external_directive.name as SyntaxTree.ident);
|
||
if (en is string_const_node)
|
||
name = (en as string_const_node).constant_value;
|
||
else
|
||
AddError(get_location(_external_directive.name), "STRING_CONSTANT_EXPECTED");
|
||
}
|
||
else
|
||
{
|
||
//throw new CompilerInternalError("Unsupported now");
|
||
AddError(get_location(_external_directive.name), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED");
|
||
}
|
||
location loc = get_location(_external_directive);
|
||
external_statement ext_stmt = new external_statement(module_name, name, loc);
|
||
//statement_node_list sal = new statement_node_list(loc);
|
||
//sal.AddElement(ext_stmt);
|
||
statements_list sl = new statements_list(loc);
|
||
sl.statements.AddElement(ext_stmt);
|
||
//return_value(sl);
|
||
context.code = sl;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.unit_or_namespace _name_space)
|
||
{
|
||
throw new NotSupportedError(get_location(_name_space));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.using_list _using_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_using_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.jump_stmt _return_stmt)
|
||
{
|
||
if (_return_stmt.JumpType != PascalABCCompiler.SyntaxTree.JumpStmtType.Return)
|
||
{
|
||
throw new NotSupportedError(get_location(_return_stmt));
|
||
}
|
||
if (_return_stmt.expr == null)
|
||
{
|
||
if (context.top_function.return_value_type != null && context.top_function.return_value_type != SystemLibrary.SystemLibrary.void_type)
|
||
{
|
||
AddError(get_location(_return_stmt), "FUNCTION_SHOULD_RETURN_VALUE");
|
||
ret.return_value(new empty_statement(null));
|
||
return;
|
||
}
|
||
ret.return_value(new return_node(null, null));
|
||
}
|
||
else
|
||
{
|
||
type_node rettype = context.top_function.return_value_type;
|
||
if (rettype == null || rettype == SystemLibrary.SystemLibrary.void_type)
|
||
{
|
||
AddError(get_location(_return_stmt.expr), "FUNCTION_SHOULD_NOT_RETURN_VALUE");
|
||
ret.return_value(new empty_statement(null));
|
||
return;
|
||
}
|
||
expression_node en = convert_strong(_return_stmt.expr);
|
||
en = convertion_data_and_alghoritms.convert_type(en, rettype);
|
||
ret.return_value(new return_node(en, get_location(_return_stmt.expr)));
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.loop_stmt _loop_stmt)
|
||
{
|
||
throw new NotSupportedError(get_location(_loop_stmt));
|
||
}
|
||
|
||
private bool IsGetEnumerator(type_node tn, ref type_node elem_type)
|
||
{
|
||
if (tn == null || tn is null_type_node || tn.ImplementingInterfaces == null) return false;
|
||
compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(compiler_string_consts.IEnumerableInterfaceName));
|
||
if (tn == ctn)
|
||
return true;
|
||
foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces)
|
||
{
|
||
if (itn == ctn)
|
||
{
|
||
elem_type = tn.element_type;
|
||
if (elem_type != null) return true;
|
||
function_node get_enumerator_func = null;
|
||
SymbolInfo si = ctn.find_in_type(compiler_string_consts.GetEnumeratorMethodName);
|
||
while (get_enumerator_func == null && si != null)
|
||
{
|
||
get_enumerator_func = si.sym_info as function_node;
|
||
if (get_enumerator_func.parameters.Count == 0)
|
||
break;
|
||
get_enumerator_func = null;
|
||
si = si.Next;
|
||
}
|
||
elem_type = (get_enumerator_func.return_value_type.find_in_type(compiler_string_consts.CurrentPropertyName).sym_info as property_node).get_function.return_value_type;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public bool FindIEnumerableElementType(/*SyntaxTree.foreach_stmt _foreach_stmt, */type_node tn, ref type_node elem_type)
|
||
{
|
||
var IEnstring = "System.Collections.IEnumerable";
|
||
compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(IEnstring));
|
||
if (tn is compiled_type_node || tn is compiled_generic_instance_type_node) // Если этот тип зашит в .NET
|
||
// IEnumerable<integer>, Range(1,10), Dictionary<string,integer>: tn = compiled_type_node
|
||
// IEnumerable<T>: tn = compiled_generic_instance_type_node
|
||
// FibGen = class(IEnumerable,IEnumerator): tn = common_type_node, en = compiled_type_node
|
||
// array of Person: tn = common_type_node
|
||
{
|
||
compiled_type_node orig;
|
||
|
||
if (tn is compiled_type_node)
|
||
orig = tn as compiled_type_node;
|
||
else orig = (tn as compiled_generic_instance_type_node).original_generic as compiled_type_node;
|
||
//var pars = tn.instance_params;
|
||
System.Type ct = orig.compiled_type;
|
||
|
||
Type r;
|
||
var IEnTstring = "System.Collections.Generic.IEnumerable`1";
|
||
if (ct.ToString().StartsWith(IEnTstring))
|
||
r = ct;
|
||
else
|
||
r = ct.GetInterface(IEnTstring);
|
||
if (r != null)
|
||
{
|
||
Type arg1 = r.GetGenericArguments().First(); // тип параметра IEnumerable
|
||
var str = arg1.GetGenericArguments().Count();
|
||
if (tn is compiled_type_node)
|
||
{
|
||
elem_type = compiled_type_node.get_type_node(arg1);
|
||
}
|
||
else
|
||
{
|
||
if (arg1.GetGenericArguments().Count()>0)
|
||
{
|
||
elem_type = compiled_type_node.get_type_node(arg1.GetGenericTypeDefinition());
|
||
elem_type = elem_type.get_instance(tn.instance_params); // SSM 19/07/15 - работает!!!
|
||
}
|
||
else
|
||
{
|
||
var ip = tn.instance_params;
|
||
//var Tname = ip[0].name;
|
||
//elem_type = convert_strong(new SyntaxTree.named_type_reference(Tname, _foreach_stmt.in_what.source_context));
|
||
elem_type = ip[0];
|
||
}
|
||
|
||
//elem_type.instance_params = tn.instance_params;
|
||
//var ip = tn.instance_params;
|
||
//var Tname = new string(tn.name.SkipWhile(c => c != '<').Skip(1).TakeWhile(c => c != ',' && c != '>').ToArray());
|
||
//var Tname = ip[0].name;
|
||
//var Tname = "System.Collections.Generic.KeyValuePair'2"; // <integer,TClass>
|
||
//elem_type = convert_strong(new SyntaxTree.named_type_reference(Tname, _foreach_stmt.in_what.source_context));
|
||
}
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
if (tn.element_type != null) // значит, это массив любой размерности - 02.02.16 SSM - еще может быть множество set of T - 22.02.16 SSM
|
||
{
|
||
elem_type = tn.element_type;
|
||
return true;
|
||
}
|
||
|
||
var ttt = tn.ImplementingInterfaces;
|
||
foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces)
|
||
{
|
||
if (itn == ctn)
|
||
{
|
||
elem_type = SystemLibrary.SystemLibrary.object_type;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/*else if (tn is compiled_generic_instance_type_node)
|
||
{
|
||
var g = tn as compiled_generic_instance_type_node;
|
||
var og = g.original_generic;
|
||
var tt = og.ImplementingInterfaces;
|
||
if (_foreach_stmt.type_name != null && _foreach_stmt.type_name.GetType()!=typeof(SyntaxTree.no_type_foreach))
|
||
elem_type = convert_strong(_foreach_stmt.type_name);
|
||
else
|
||
{
|
||
var fn = tn.full_name;
|
||
}
|
||
return true;
|
||
} */
|
||
else // если мы самостоятельно определяем этот тип - можно реализовать в PascalABC.NET только IEnumerable. // Сейчас уже можно!!!!!
|
||
// Попытка реализовать IEnumerable<T> натыкается на необходимость определять GetEnumerator, возвращающий IEnumerator и IEnumerator<T>
|
||
{
|
||
if (tn == null || tn is null_type_node || tn.ImplementingInterfaces == null)
|
||
return false;
|
||
|
||
if (tn.element_type != null) // еще может быть множество set of T - 22.02.16 SSM
|
||
{
|
||
elem_type = tn.element_type;
|
||
return true;
|
||
}
|
||
|
||
foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) // Ищем интерфейс IEnumerable<T> и возвращаем T в качестве elem_type
|
||
{
|
||
if (itn is compiled_generic_instance_type_node)
|
||
{
|
||
var itnc = (itn as compiled_generic_instance_type_node);
|
||
var tt = (itnc.original_generic as compiled_type_node).compiled_type;
|
||
if (tt == typeof(System.Collections.Generic.IEnumerable<>))
|
||
{
|
||
elem_type = itnc.generic_parameters[0] as common_type_node;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) // если не нашли - ищем интерфейс IEnumerable и возвращаем object в качестве elem_type
|
||
{
|
||
if (itn is compiled_type_node)
|
||
{
|
||
/*var itnc = (itn as compiled_type_node).compiled_type;
|
||
if (itnc.IsGenericType)
|
||
{
|
||
var my = itnc.GetGenericTypeDefinition();// = typeof(System.Collections.Generic.IEnumerable<>)
|
||
if (my == typeof(System.Collections.Generic.IEnumerable<>))
|
||
{
|
||
var aarg1 = itnc.GetGenericArguments().First();
|
||
elem_type = compiled_type_node.get_type_node(aarg1);
|
||
return true;
|
||
}
|
||
}
|
||
else */
|
||
if (itn == ctn)
|
||
{
|
||
elem_type = SystemLibrary.SystemLibrary.object_type;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private int GenIdNum = 0;
|
||
public ident GenIdentName()
|
||
{
|
||
GenIdNum++;
|
||
return new ident("$GenId" + GenIdNum.ToString());
|
||
}
|
||
|
||
public override void visit(SyntaxTree.foreach_stmt _foreach_stmt)
|
||
{
|
||
var lambdaSearcher = new LambdaSearcher(_foreach_stmt.in_what);
|
||
if (lambdaSearcher.CheckIfContainsLambdas())
|
||
{
|
||
AddError(new LambdasNotAllowedInForeachInWhatSatetement(get_location(lambdaSearcher.FoundLambda)));
|
||
}
|
||
|
||
expression_node in_what = convert_strong(_foreach_stmt.in_what);
|
||
|
||
// SSM 29.07.16 - если in_what - одномерный массив, то заменить код foreach на for
|
||
var is1dimdynarr = false;
|
||
var comptn = in_what.type as compiled_type_node;
|
||
if (comptn != null && comptn.type_special_kind == SemanticTree.type_special_kind.array_kind && comptn.rank == 1)
|
||
{
|
||
is1dimdynarr = true;
|
||
}
|
||
if (!is1dimdynarr)
|
||
{
|
||
var comtn = in_what.type as common_type_node;
|
||
if (comtn != null && comtn.internal_type_special_kind == SemanticTree.type_special_kind.array_kind && comtn.rank == 1)
|
||
{
|
||
is1dimdynarr = true;
|
||
}
|
||
}
|
||
|
||
|
||
// SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура
|
||
|
||
if (is1dimdynarr) // Замена foreach на for для массива
|
||
{
|
||
// сгенерировать код для for и вызвать соответствующий visit
|
||
var arrid = GenIdentName();
|
||
//var vdarr = new var_statement(arrid, new semantic_addr_value(in_what)); // semantic_addr_value - перевод в синтаксис для мгновенного вычисления семантического выражения, которое уже вычислено в in_what
|
||
var vdarr = new var_statement(arrid, _foreach_stmt.in_what);
|
||
|
||
var i = GenIdentName();
|
||
var x = _foreach_stmt.identifier;
|
||
|
||
// Возможны 3 случая:
|
||
// 1. _foreach_stmt.type_name = null - значит, переменная определена в другом месте
|
||
// 2. _foreach_stmt.type_name = no_type_foreach - значит, это for var x in a
|
||
// 3. _foreach_stmt.type_name = T - значит, это for var x: T in a
|
||
|
||
statement vd;
|
||
if (_foreach_stmt.type_name == null) // 1.
|
||
vd = new assign(x, arrid.indexer(i));
|
||
else if (_foreach_stmt.type_name is no_type_foreach) // 2.
|
||
vd = new var_statement(x, arrid.indexer(i));
|
||
else // 3.
|
||
vd = new var_statement(x,_foreach_stmt.type_name, arrid.indexer(i));
|
||
|
||
// Превратить старое тело в statement_list и добавить к нему в начало x := a[i] или var x := a[i]
|
||
var newbody = _foreach_stmt.stmt.ToStatementList();
|
||
newbody.AddFirst(vd);
|
||
|
||
var high = arrid.dot_node("Length").Minus(1);
|
||
|
||
var fornode = new SyntaxTree.for_node(i, 0, high, newbody, for_cycle_type.to, null, null, true);
|
||
|
||
var stl = new SyntaxTree.statement_list(vdarr, fornode);
|
||
// Замена 1 оператора на 1 оператор. Всё хорошо даже если оператор помечен меткой
|
||
ReplaceUsingParent(_foreach_stmt, stl);
|
||
|
||
visit(stl);
|
||
//visit(vdarr);
|
||
//visit(fornode);
|
||
|
||
return;
|
||
}
|
||
/// SSM 29.07.16
|
||
|
||
//throw new NotSupportedError(get_location(_foreach_stmt));
|
||
definition_node dn = null;
|
||
var_definition_node vdn = null;
|
||
statements_list sl2 = new statements_list(get_location(_foreach_stmt));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl2);
|
||
|
||
expression_node tmp = in_what;
|
||
if (in_what is typed_expression) in_what = convert_typed_expression_to_function_call(in_what as typed_expression);
|
||
type_node elem_type = null;
|
||
if (in_what.type == null)
|
||
in_what = tmp;
|
||
//if (in_what.type.find_in_type("GetEnumerator") == null)
|
||
|
||
//(in_what.type as common_type_node).internal_type_special_kind == SemanticTree.type_special_kind.array_kind
|
||
//in_what.type as compiled_type_node
|
||
|
||
if (!FindIEnumerableElementType(/*_foreach_stmt, */in_what.type, ref elem_type))
|
||
//if (!IsGetEnumerator(in_what.type, ref elem_type))
|
||
AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name);
|
||
|
||
if (_foreach_stmt.type_name == null)
|
||
{
|
||
location loc1 = get_location(_foreach_stmt.identifier);
|
||
dn = context.check_name_node_type(_foreach_stmt.identifier.name, loc1,
|
||
general_node_type.variable_node);
|
||
vdn = (var_definition_node)dn;
|
||
if (!check_name_in_current_scope(_foreach_stmt.identifier.name))
|
||
AddError(loc1, "FOREACH_LOOP_CONTROL_MUST_BE_SIMPLE_LOCAL_VARIABLE");
|
||
}
|
||
else
|
||
{
|
||
//AddError(new NotSupportedError(get_location(_foreach_stmt.type_name)));
|
||
vdn = context.add_var_definition(_foreach_stmt.identifier.name, get_location(_foreach_stmt.identifier));
|
||
|
||
type_node tn;
|
||
if (_foreach_stmt.type_name is SyntaxTree.no_type_foreach)
|
||
{
|
||
tn = elem_type;
|
||
}
|
||
else
|
||
{
|
||
tn = convert_strong(_foreach_stmt.type_name);
|
||
//if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
// AddError(new VoidNotValid(get_location(_foreach_stmt.type_name)));
|
||
check_for_type_allowed(tn, get_location(_foreach_stmt.type_name));
|
||
}
|
||
|
||
context.close_var_definition_list(tn, null);
|
||
}
|
||
|
||
//elem_type = vdn.type;
|
||
if (!(vdn.type is compiled_generic_instance_type_node))
|
||
convertion_data_and_alghoritms.check_convert_type_with_inheritance(vdn.type, elem_type, get_location(_foreach_stmt.identifier));
|
||
|
||
//if (!convertion_data_and_alghoritms.eq_type_nodes(elem_type, vdn.type))
|
||
//AddError(new TypesOfVarAndElementsInForeachMustBeEqual(vdn.type.name,elem_type.name,get_location(_foreach_stmt.identifier)));
|
||
//AddError(new SimpleSemanticError("Тип элемента контейнера: " + elem_type.ToString() + " Тип переменной foreach: " + vdn.type.ToString(), get_location(_foreach_stmt.identifier)));
|
||
|
||
//convertion_data_and_alghoritms.check_convert_type_with_inheritance(vdn.type, elem_type, get_location(_foreach_stmt.identifier));
|
||
//if (in_what.type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
/*{
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(elem_type, vdn.type))
|
||
{
|
||
possible_type_convertions ptc = type_table.get_convertions(vdn.type,elem_type);
|
||
if (ptc.first == null || ptc.first.is_explicit)
|
||
if (vdn.node_location_kind == SemanticTree.node_location_kind.in_namespace_location)
|
||
throw new CanNotConvertTypes(new namespace_variable_reference(vdn as namespace_variable, get_location(_foreach_stmt.identifier)), vdn.type, elem_type, get_location(_foreach_stmt.identifier));
|
||
else if (vdn.node_location_kind == SemanticTree.node_location_kind.in_function_location) throw new CanNotConvertTypes(new local_variable_reference(vdn as local_variable, 0, get_location(_foreach_stmt.identifier)), vdn.type, elem_type, get_location(_foreach_stmt.identifier));
|
||
else if (vdn.node_location_kind == SemanticTree.node_location_kind.in_block_location) throw new CanNotConvertTypes(new local_block_variable_reference(vdn as local_block_variable,get_location(_foreach_stmt.identifier)),vdn.type,elem_type, get_location(_foreach_stmt.identifier));
|
||
else throw new ForeachLoopControlMustBeSimpleLocalVariable(get_location(_foreach_stmt.identifier));
|
||
|
||
}
|
||
}*/
|
||
statements_list sl = new statements_list(get_location(_foreach_stmt.stmt));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(sl);
|
||
CheckToEmbeddedStatementCannotBeADeclaration(_foreach_stmt.stmt);
|
||
foreach_node fn = new foreach_node(vdn, in_what, null, get_location(_foreach_stmt));
|
||
context.cycle_stack.push(fn);
|
||
context.loop_var_stack.Push(vdn);
|
||
context.enter_code_block_with_bind();
|
||
statement_node body = convert_strong(_foreach_stmt.stmt);
|
||
context.leave_code_block();
|
||
context.loop_var_stack.Pop();
|
||
sl = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
//if (!(st is statements_list))
|
||
if (sl.statements.Count > 0 || sl.local_variables.Count > 0)
|
||
{
|
||
sl.statements.AddElement(body);
|
||
body = sl;
|
||
}
|
||
//CheckToEmbeddedStatementCannotBeADeclaration(_foreach_stmt.stmt);
|
||
//statement_node body = convert_strong(_foreach_stmt.stmt);
|
||
//foreach_node fn = new foreach_node(vdn, in_what, body, get_location(_foreach_stmt));
|
||
fn.what_do = body;
|
||
//statements_list sl2 = new statements_list(get_location(_foreach_stmt));
|
||
convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
sl2.statements.AddElement(fn);
|
||
context.cycle_stack.pop();
|
||
//if (_foreach_stmt.type_name != null)
|
||
//sl2.local_variables.Add(vdn as local_block_variable);
|
||
return_value(sl2);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.addressed_value_funcname _addressed_value_funcname)
|
||
{
|
||
throw new NotSupportedError(get_location(_addressed_value_funcname));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.named_type_reference_list _named_type_reference_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_named_type_reference_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.template_param_list _template_param_list)
|
||
{
|
||
throw new NotSupportedError(get_location(_template_param_list));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.question_colon_expression node)
|
||
{
|
||
expression_node condition = convert_strong(node.condition);
|
||
condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type);
|
||
expression_node left = convert_strong(node.ret_if_true);
|
||
expression_node right = convert_strong(node.ret_if_false);
|
||
|
||
/*var typeComparisonResult = type_table.compare_types(left.type, right.type);
|
||
if (typeComparisonResult == type_compare.greater_type)
|
||
right = convertion_data_and_alghoritms.convert_type(right, left.type);
|
||
else left = convertion_data_and_alghoritms.convert_type(left, right.type);*/
|
||
if (left is null_const_node)
|
||
left = convertion_data_and_alghoritms.convert_type(left, right.type);
|
||
else
|
||
{
|
||
delegated_methods del_left = left.type as delegated_methods;
|
||
delegated_methods del_right = right.type as delegated_methods;
|
||
if (del_left != null && del_right != null && del_left.empty_param_method == null && del_right.empty_param_method == null)
|
||
{
|
||
base_function_call bfc = del_left.proper_methods[0];
|
||
common_type_node del =
|
||
convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null);
|
||
context.converted_namespace.types.AddElement(del);
|
||
right = convertion_data_and_alghoritms.explicit_convert_type(right, del);
|
||
left = convertion_data_and_alghoritms.explicit_convert_type(left, del);
|
||
}
|
||
else
|
||
right = convertion_data_and_alghoritms.convert_type(right, left.type);
|
||
}
|
||
|
||
|
||
//right = convertion_data_and_alghoritms.convert_type(right, left.type);
|
||
return_value(new question_colon_expression(condition, left, right, get_location(node)));
|
||
}
|
||
|
||
public List<type_node> visit_type_list(List<SyntaxTree.type_definition> types)
|
||
{
|
||
List<type_node> tparams = new List<type_node>();
|
||
foreach (SyntaxTree.type_definition id in types)
|
||
{
|
||
type_node tn = ret.visit(id);
|
||
if (tn == null)
|
||
{
|
||
AddError(get_location(id), "TYPE_NAME_EXPECTED");
|
||
}
|
||
tparams.Add(tn);
|
||
}
|
||
return tparams;
|
||
}
|
||
|
||
public List<type_node> visit_type_list_with_check(List<SyntaxTree.type_definition> types, List<generic_parameter_eliminations> gpe_list, bool where_checking)
|
||
{
|
||
List<type_node> tparams = new List<type_node>();
|
||
foreach (SyntaxTree.type_definition id in types)
|
||
{
|
||
type_node tn = ret.visit(id);
|
||
CompilationErrorWithLocation not_useful = generic_parameter_eliminations.check_type_generic_useful(tn, get_location(id));
|
||
if (not_useful != null)
|
||
{
|
||
AddError(not_useful);
|
||
}
|
||
tparams.Add(tn);
|
||
}
|
||
//Проверяем типы на соответствие ограничениям
|
||
int i;
|
||
if (where_checking)
|
||
{
|
||
CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(tparams, gpe_list, false, out i);
|
||
if (err != null)
|
||
{
|
||
err.loc = get_location(types[i]);
|
||
AddError(err);
|
||
}
|
||
}
|
||
return tparams;
|
||
}
|
||
|
||
public type_node get_generic_instance(SymbolInfo si, List<SyntaxTree.type_definition> type_pars)
|
||
{
|
||
type_node node = si.sym_info as type_node;
|
||
compiled_type_node comp_node = node as compiled_type_node;
|
||
List<generic_parameter_eliminations> lgpe = null;
|
||
if (!context.skip_check_where_sections)
|
||
{
|
||
lgpe = (comp_node == null) ?
|
||
(node as common_type_node).parameters_eliminations :
|
||
comp_node.parameters_eliminations;
|
||
}
|
||
List<type_node> tparams = visit_type_list_with_check(type_pars, lgpe, !context.skip_check_where_sections);
|
||
return node.get_instance(tparams);
|
||
}
|
||
|
||
public SymbolInfo ConvertTypeToInstance(SymbolInfo si, List<SyntaxTree.type_definition> type_pars, location loc)
|
||
{
|
||
if (si == null)
|
||
return null;
|
||
template_class tclass = si.sym_info as template_class;
|
||
if (tclass == null)
|
||
{
|
||
generic_indicator gi = si.sym_info as generic_indicator;
|
||
if (gi != null)
|
||
{
|
||
AddError(loc, "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", gi.generic.name, gi.generic.generic_params.Count);
|
||
}
|
||
return null;
|
||
}
|
||
//Формируем список параметров инстанцирования
|
||
List<type_node> tparams = visit_type_list(type_pars);
|
||
|
||
type_node t = instance_any(tclass, tparams, loc);
|
||
return new SymbolInfo(t);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.template_type_reference _template_type_reference)
|
||
{
|
||
int last_num = _template_type_reference.name.names.Count;
|
||
string typename = _template_type_reference.name.names[last_num - 1].name;
|
||
location loc = get_location(_template_type_reference);
|
||
SymbolInfo si;
|
||
List<type_node> tparams;
|
||
|
||
//Обрабатываем generic-типы
|
||
int tcount = _template_type_reference.params_list.params_list.Count;
|
||
string temp_name = _template_type_reference.name.names[last_num - 1].name;
|
||
if (!_template_type_reference.name.names[last_num - 1].name.Contains(compiler_string_consts.generic_params_infix)) // SSM 26.03.14
|
||
_template_type_reference.name.names[last_num - 1].name += compiler_string_consts.generic_params_infix + tcount;
|
||
si = context.find_definition_node(_template_type_reference.name, loc);
|
||
if (si != null)
|
||
{
|
||
type_node rez_type = get_generic_instance(si, _template_type_reference.params_list.params_list);
|
||
if (context.skip_check_where_sections)
|
||
{
|
||
generic_instance_type_node gitn = rez_type as generic_instance_type_node;
|
||
if (gitn != null)
|
||
{
|
||
context.possible_incorrect_instances.Add(
|
||
new type_instance_and_location(gitn, loc));
|
||
}
|
||
}
|
||
return_value(rez_type);
|
||
return;
|
||
}
|
||
_template_type_reference.name.names[last_num - 1].name = temp_name;
|
||
si = context.find_definition_node(_template_type_reference.name, loc);
|
||
if (si == null)
|
||
{
|
||
check_possible_generic_names(_template_type_reference.name, loc);
|
||
AddError(new UndefinedNameReference(typename, loc));
|
||
}
|
||
template_class tclass = si.sym_info as template_class;
|
||
if (tclass == null)
|
||
{
|
||
generic_indicator gi = si.sym_info as generic_indicator;
|
||
if (gi != null)
|
||
{
|
||
AddError(get_location(_template_type_reference), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", typename, gi.generic.generic_params.Count);
|
||
}
|
||
AddError(get_location(_template_type_reference), "{0}_IS_NOT_TEMPLATE_CLASS", typename);
|
||
}
|
||
|
||
//Формируем список параметров инстанцирования
|
||
tparams = visit_type_list(_template_type_reference.params_list.params_list);
|
||
|
||
type_node t = instance_any(tclass, tparams, get_location(_template_type_reference));
|
||
return_value(t);
|
||
}
|
||
|
||
public type_node instance_any(template_class tc, List<type_node> template_params, location loc)
|
||
{
|
||
common_type_node t = instance(tc, template_params, loc);
|
||
if (tc.is_synonym)
|
||
{
|
||
return t.fields[0].type;
|
||
}
|
||
return t;
|
||
}
|
||
|
||
public common_type_node instance(template_class tc, List<type_node> template_params, location loc)
|
||
{
|
||
//Проверяем, что попытка инстанцирования корректна
|
||
SyntaxTree.class_definition cl_def = tc.type_dec.type_def as SyntaxTree.class_definition;
|
||
SyntaxTree.template_type_name ttn = tc.type_dec.type_name as SyntaxTree.template_type_name;
|
||
#if (DEBUG)
|
||
if (!tc.is_synonym)
|
||
{
|
||
if (cl_def == null)
|
||
{
|
||
throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No body definition in template class.");
|
||
}
|
||
if (cl_def.template_args == null || cl_def.template_args.idents == null)
|
||
{
|
||
throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No template arguments in syntax tree.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (ttn == null)
|
||
{
|
||
throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No template name.");
|
||
}
|
||
}
|
||
#endif
|
||
List<SyntaxTree.ident> template_formals = (tc.is_synonym) ?
|
||
ttn.template_args.idents : cl_def.template_args.idents;
|
||
if (template_formals.Count != ttn.template_args.idents.Count)
|
||
{
|
||
AddError(loc, "TEMPLATE_ARGUMENTS_COUNT_MISMATCH");
|
||
}
|
||
|
||
if (!tc.is_synonym)
|
||
{
|
||
foreach (type_node tnode in template_params)
|
||
{
|
||
if (depended_from_generic_parameter(tnode))
|
||
{
|
||
AddError(loc, "TEMPLATES_AND_GENERICS_ARE_INCOMPATIBLE");
|
||
}
|
||
}
|
||
}
|
||
|
||
//А вдруг такая инстанция уже есть - вернём её
|
||
string inst_name = tc.CreateTemplateInstance(template_params, loc);
|
||
SymbolInfo si = tc.cnn.scope.FindOnlyInScope(inst_name);
|
||
if (si != null)
|
||
{
|
||
return (common_type_node)si.sym_info;
|
||
}
|
||
|
||
//Переходим в место описания шаблона
|
||
common_namespace_node current_namespace = context.converted_namespace;
|
||
context.converted_namespace = tc.cnn;
|
||
common_type_node current_type = context.converted_type;
|
||
context.converted_type = null;
|
||
template_class current_template = context.converted_template_type;
|
||
context.converted_template_type = null;
|
||
compiled_type_node current_compiled_type = context.converted_compiled_type;
|
||
context.converted_compiled_type = null;
|
||
common_function_node_stack current_funk_stack = context.converted_func_stack;
|
||
context.converted_func_stack = new common_function_node_stack(); //Думаю, это будет работать
|
||
|
||
//DarkStar
|
||
statement_list_stack statement_list_stack = convertion_data_and_alghoritms.statement_list_stack;
|
||
convertion_data_and_alghoritms.statement_list_stack = new statement_list_stack();
|
||
|
||
bool current_cur_meth_not_in_class = current_converted_method_not_in_class_defined;
|
||
current_converted_method_not_in_class_defined = false;
|
||
SymbolInfo current_last_created_function = context.last_created_function;
|
||
context.last_created_function = null;
|
||
bool current_record_created = _record_created;
|
||
_record_created = false;
|
||
SemanticTree.field_access_level current_fal = context.get_field_access_level();
|
||
document current_doc = current_document;
|
||
current_document = tc.cur_document;
|
||
bool current_body_exists = body_exists;
|
||
body_exists = false;
|
||
bool current_allow_inherited_ctor_call = context.allow_inherited_ctor_call;
|
||
bool current_is_direct_type_decl = is_direct_type_decl;
|
||
is_direct_type_decl = false;
|
||
context.allow_inherited_ctor_call = false;
|
||
bool current_type_section_converting = type_section_converting;
|
||
type_section_converting = true;
|
||
SemanticTree.field_access_level curr_fal = context.get_field_access_level();
|
||
List<var_definition_node> current_var_defs = context.var_defs;
|
||
context.var_defs = new List<var_definition_node>();
|
||
Hashtable current_member_decls = context.member_decls;
|
||
context.member_decls = new Hashtable();
|
||
//подменяем using-список
|
||
using_namespace_list current_using_list = new using_namespace_list();
|
||
foreach (using_namespace un in using_list)
|
||
{
|
||
current_using_list.AddElement(un);
|
||
}
|
||
using_list.clear();
|
||
foreach (using_namespace un in tc.using_list)
|
||
{
|
||
using_list.AddElement(un);
|
||
}
|
||
context.converted_type = null;
|
||
context.enter_code_block_without_bind();
|
||
|
||
common_type_node ctn;
|
||
|
||
bool interface_creating = false;
|
||
|
||
//Создаём инстанцию шаблона
|
||
if (tc.is_synonym)
|
||
{
|
||
ctn = context.create_type(inst_name, get_location(ttn));
|
||
}
|
||
else
|
||
{
|
||
if (cl_def.keyword == SyntaxTree.class_keyword.Record)
|
||
{
|
||
ctn = context.create_record_type(get_location(tc.type_dec.type_name), inst_name);
|
||
}
|
||
else
|
||
{
|
||
interface_creating = (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface);
|
||
ctn = context.advanced_create_type(inst_name, get_location(tc.type_dec.type_name), interface_creating);
|
||
}
|
||
}
|
||
ctn.original_template = tc;
|
||
bool indefinite = false;
|
||
foreach (type_node tn in template_params)
|
||
{
|
||
indefinite = indefinite || tn.depended_from_indefinite;
|
||
}
|
||
ctn.SetDependedFromIndefinite(indefinite);
|
||
tc.instance_params.Add(ctn, template_params);
|
||
|
||
//Ставим в соответствие формальным параметрам шаблона фактические
|
||
for (int i = 0; i < template_params.Count; i++)
|
||
{
|
||
ctn.Scope.AddSymbol(template_formals[i].name, new SymbolInfo(template_params[i]));
|
||
}
|
||
|
||
//Разбор тела класса
|
||
if (tc.is_synonym)
|
||
{
|
||
type_node synonym_value = convert_strong(tc.type_dec.type_def);
|
||
ctn.fields.AddElement(new class_field(compiler_string_consts.synonym_value_name,
|
||
synonym_value, ctn, PascalABCCompiler.SemanticTree.polymorphic_state.ps_static,
|
||
PascalABCCompiler.SemanticTree.field_access_level.fal_public, null));
|
||
}
|
||
else
|
||
{
|
||
if (cl_def.keyword == SyntaxTree.class_keyword.Record)
|
||
{
|
||
_record_created = true;
|
||
}
|
||
|
||
bool tmp_direct = is_direct_type_decl;
|
||
is_direct_type_decl = true;
|
||
hard_node_test_and_visit(cl_def);
|
||
is_direct_type_decl = tmp_direct;
|
||
|
||
//Разбор методов, описанных вне класса
|
||
if (!interface_creating)
|
||
{
|
||
type_section_converting = false;
|
||
foreach (procedure_definition_info pdi in tc.external_methods)
|
||
{
|
||
if (context.converted_namespace != pdi.nspace)
|
||
{
|
||
context.converted_namespace = pdi.nspace;
|
||
using_namespace_list ulist =
|
||
(pdi.nspace == tc.cnn) ? tc.using_list : tc.using_list2;
|
||
using_list.clear();
|
||
foreach (using_namespace un in ulist)
|
||
{
|
||
using_list.AddElement(un);
|
||
}
|
||
template_class.AddUsingListToScope(context.converted_namespace.scope, ulist);
|
||
}
|
||
|
||
//Заменяем в дереве метода имя шаблонного класса на имя инстанции
|
||
string tmp_name = pdi.proc.proc_header.name.class_name.name;
|
||
pdi.proc.proc_header.name.class_name.name = inst_name;
|
||
|
||
hard_node_test_and_visit(pdi.proc);
|
||
|
||
//Обратная замена
|
||
pdi.proc.proc_header.name.class_name.name = tmp_name;
|
||
}
|
||
|
||
foreach (common_method_node cmn in ctn.methods)
|
||
{
|
||
if (cmn.function_code == null)
|
||
{
|
||
AddError(cmn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//Прыжок обратно
|
||
context.leave_code_block();
|
||
context.converted_namespace = current_namespace;
|
||
context.converted_type = current_type;
|
||
context.converted_template_type = current_template;
|
||
context.set_field_access_level(current_fal);
|
||
context.converted_func_stack = current_funk_stack;
|
||
context.converted_compiled_type = current_compiled_type;
|
||
convertion_data_and_alghoritms.statement_list_stack = statement_list_stack;
|
||
current_document = current_doc;
|
||
body_exists = current_body_exists;
|
||
_record_created = current_record_created;
|
||
context.last_created_function = current_last_created_function;
|
||
is_direct_type_decl = current_is_direct_type_decl;
|
||
context.allow_inherited_ctor_call = current_allow_inherited_ctor_call;
|
||
current_converted_method_not_in_class_defined = current_cur_meth_not_in_class;
|
||
context.set_field_access_level(curr_fal);
|
||
type_section_converting = current_type_section_converting;
|
||
context.member_decls = current_member_decls;
|
||
context.var_defs = current_var_defs;
|
||
using_list.clear();
|
||
foreach (using_namespace un in current_using_list)
|
||
{
|
||
using_list.AddElement(un);
|
||
}
|
||
|
||
return ctn;
|
||
}
|
||
|
||
private SyntaxTree.addressed_value convert_named_type_reference_to_addressed_value(SyntaxTree.named_type_reference ntr)
|
||
{
|
||
SyntaxTree.addressed_value adrv = ntr.names[0];
|
||
for (int i = 1; i < ntr.names.Count; i++)
|
||
adrv = new SyntaxTree.dot_node(adrv, ntr.names[i]);
|
||
return adrv;
|
||
}
|
||
|
||
private base_function_call create_constructor_call(type_node tn, expressions_list exprs, location loc, Tuple<bool, List<SyntaxTree.expression>> lambdas_info = null)
|
||
{
|
||
if (tn.IsInterface)
|
||
{
|
||
AddError(loc, "INTERFACE_{0}_CONSTRUCTOR_CALL", tn.name);
|
||
}
|
||
if (tn.IsAbstract)
|
||
{
|
||
AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", tn.name);
|
||
}
|
||
SymbolInfo si = tn.find_in_type(TreeConverter.compiler_string_consts.default_constructor_name, context.CurrentScope); //tn.Scope);
|
||
delete_inherited_constructors(ref si, tn);
|
||
if (si == null)
|
||
AddError(loc, "CONSTRUCTOR_NOT_FOUND");
|
||
function_node fnn = null;
|
||
try
|
||
{
|
||
#region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим
|
||
//lroman//
|
||
if (lambdas_info != null && lambdas_info.Item1)
|
||
{
|
||
LambdaHelper.processingLambdaParametersForTypeInference++;
|
||
var syntax_nodes_parameters = lambdas_info.Item2;
|
||
|
||
// SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями
|
||
function_node_list spf = null;
|
||
try
|
||
{
|
||
function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, loc,
|
||
syntax_nodes_parameters);
|
||
int exprCounter = 0;
|
||
foreach (SyntaxTree.expression en in syntax_nodes_parameters)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var enLambda = (SyntaxTree.function_lambda_definition)en;
|
||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
exprs[exprCounter] = convert_strong(en);
|
||
enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
exprCounter++;
|
||
}
|
||
}
|
||
}
|
||
catch (SeveralFunctionsCanBeCalled sf)
|
||
{
|
||
spf = sf.set_of_possible_functions;
|
||
// Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна
|
||
}
|
||
|
||
Exception lastmultex = null;
|
||
if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try
|
||
{
|
||
// exprs - глобальная, поэтому надо копировать
|
||
int spfnum = -1; // spfnum - первый номер правильно инстанцированной. Пока -1. Если потом встретился второй, то тоже ошибка
|
||
int GoodVersionsCount = 0;
|
||
int GoodVersionsCountWithSameResType = 0;
|
||
for (int i = 0; i < spf.Count; i++)
|
||
{
|
||
function_node fn = spf[i];
|
||
try
|
||
{
|
||
int exprCounter = 0;
|
||
expressions_list exprs1 = new expressions_list();
|
||
exprs1.AddRange(exprs); // сделали копию
|
||
|
||
foreach (SyntaxTree.expression en in syntax_nodes_parameters)
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
exprCounter++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
var fld = en as SyntaxTree.function_lambda_definition;
|
||
|
||
var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо
|
||
var fl = fld.lambda_visit_mode;
|
||
|
||
// запомнили типы параметров лямбды - SSM
|
||
object[] realparamstype = new object[fld.formal_parameters.params_list.Count];
|
||
// здесь хранятся выведенные типы лямбд или null если типы явно заданы
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK =
|
||
fld.formal_parameters.params_list[k].vars_type as
|
||
SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK == null)
|
||
realparamstype[k] = null;
|
||
else realparamstype[k] = laminftypeK.real_type;
|
||
}
|
||
|
||
// запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим
|
||
var restype = fld.return_type as SyntaxTree.lambda_inferred_type;
|
||
object realrestype = null;
|
||
if (restype != null)
|
||
realrestype = restype.real_type;
|
||
|
||
LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this);
|
||
fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
|
||
//lroman
|
||
fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName);
|
||
// поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ!
|
||
|
||
//contextChanger.SaveContextAndUpToNearestDefSect();
|
||
try
|
||
{
|
||
exprs1[exprCounter] = convert_strong(en);
|
||
|
||
type_node resexprtype = fld.RealSemTypeOfResExpr as type_node;
|
||
type_node resformaltype = fld.RealSemTypeOfResult as type_node;
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
|
||
/*var tt = fn.parameters[exprCounter].type as compiled_type_node;
|
||
if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func"))
|
||
{
|
||
resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения
|
||
var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность
|
||
if (bbb)
|
||
{
|
||
GoodVersionsCountWithSameResType += 1;
|
||
spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет.
|
||
}
|
||
}*/
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition);
|
||
// восстанавливаем сохраненный тип возвращаемого значения
|
||
if (restype != null)
|
||
restype.real_type = realrestype;
|
||
// восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно
|
||
for (var k = 0; k < fld.formal_parameters.params_list.Count; k++)
|
||
{
|
||
var laminftypeK =
|
||
fld.formal_parameters.params_list[k].vars_type as
|
||
SyntaxTree.lambda_inferred_type;
|
||
if (laminftypeK != null)
|
||
laminftypeK.real_type = realparamstype[k];
|
||
}
|
||
|
||
fld.lambda_name = lambdaName; //lroman Восстанавливаем имена
|
||
fld.lambda_visit_mode = fl;
|
||
}
|
||
|
||
//contextChanger.RestoreCurrentContext();
|
||
exprCounter++;
|
||
}
|
||
}
|
||
/*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так
|
||
{
|
||
spfnum = -2;
|
||
break;
|
||
}*/
|
||
|
||
if (GoodVersionsCountWithSameResType == 0)
|
||
spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения
|
||
GoodVersionsCount += 1;
|
||
for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо
|
||
exprs[j] = exprs1[j];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать
|
||
//contextChanger.RestoreCurrentContext();
|
||
lastmultex = e;
|
||
}
|
||
}
|
||
if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения
|
||
throw new SeveralFunctionsCanBeCalled(loc, spf);
|
||
if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд
|
||
{
|
||
throw lastmultex;
|
||
//throw new NoFunctionWithSameArguments(subloc2, false);
|
||
}
|
||
|
||
var kk = 0;
|
||
foreach (SyntaxTree.expression en in syntax_nodes_parameters)
|
||
//lroman окончательно подставить типы в лямбды
|
||
{
|
||
if (!(en is SyntaxTree.function_lambda_definition))
|
||
{
|
||
kk++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type,
|
||
en as SyntaxTree.function_lambda_definition, this);
|
||
exprs[kk] = convert_strong(en);
|
||
kk++;
|
||
}
|
||
}
|
||
}
|
||
// SSM 21.05.14 end
|
||
LambdaHelper.processingLambdaParametersForTypeInference--;
|
||
|
||
fnn = convertion_data_and_alghoritms.select_function(exprs, si, loc);
|
||
}
|
||
//lroman//
|
||
#endregion
|
||
|
||
else
|
||
{
|
||
fnn = convertion_data_and_alghoritms.select_function(exprs, si, loc);
|
||
}
|
||
}
|
||
catch (NoFunctionWithSameParametresNum e)
|
||
{
|
||
e.is_constructor = true;
|
||
throw;
|
||
}
|
||
return create_static_method_call_with_params(fnn, loc, tn, false, exprs);
|
||
}
|
||
|
||
private expression_node clip_expression_if_need(expression_node expr, type_node tn)
|
||
{
|
||
if (!(tn is short_string_type_node) && tn.type_special_kind != SemanticTree.type_special_kind.set_type)
|
||
return expr;
|
||
if (tn is short_string_type_node)
|
||
{
|
||
return convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(expr,SystemLibrary.SystemLibrary.string_type),new int_const_node((tn as short_string_type_node).Length,null));
|
||
}
|
||
else if (tn.type_special_kind == SemanticTree.type_special_kind.set_type && tn.element_type != null)
|
||
{
|
||
ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface;
|
||
if (oti != null)
|
||
{
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipFunction.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null));
|
||
cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null));
|
||
cmc.ret_type = tn;
|
||
return cmc;
|
||
}
|
||
else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
base_function_call cmc = null;
|
||
if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info is common_namespace_function_node)
|
||
cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null);
|
||
else
|
||
cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null);
|
||
cmc.parameters.AddElement(expr);
|
||
cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null));
|
||
cmc.ret_type = tn;
|
||
return cmc;
|
||
}
|
||
}
|
||
return expr;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.new_expr _new_expr)
|
||
{
|
||
type_node tn = ret.visit(_new_expr.type);
|
||
//if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
// AddError(new VoidNotValid(get_location(_new_expr.type)));
|
||
check_for_type_allowed(tn,get_location(_new_expr.type));
|
||
location loc = get_location(_new_expr);
|
||
expressions_list exprs = null;
|
||
var lambdas_are_in_parameters = false;
|
||
var syntax_nodes_parameters = _new_expr.params_list == null
|
||
? new List<expression>()
|
||
: _new_expr.params_list.expressions;
|
||
|
||
if (_new_expr.params_list != null)
|
||
{
|
||
exprs = new expressions_list();
|
||
foreach (SyntaxTree.expression en in _new_expr.params_list.expressions)
|
||
{
|
||
if (en is SyntaxTree.function_lambda_definition)
|
||
{
|
||
lambdas_are_in_parameters = true;
|
||
((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing;
|
||
}
|
||
exprs.AddElement(convert_strong(en));
|
||
}
|
||
}
|
||
else
|
||
exprs = new expressions_list();
|
||
if (_new_expr.new_array)
|
||
{
|
||
//if (exprs.Count == 1)
|
||
{
|
||
//new typename[size]
|
||
type_node atn = convertion_data_and_alghoritms.type_constructor.create_unsized_array(tn, context.converted_namespace, exprs.Count, loc);
|
||
//тип элементов
|
||
typeof_operator to = new typeof_operator(tn, loc);
|
||
List<expression_node> lst = new List<expression_node>();
|
||
//размер
|
||
for (int i=0; i<exprs.Count; i++)
|
||
{
|
||
expression_node expr = exprs[i];
|
||
expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.integer_type);
|
||
if (expr is int_const_node && (expr as int_const_node).constant_value < 0)
|
||
AddError(expr.location, "NEGATIVE_ARRAY_LENGTH_({0})_NOT_ALLOWED", (expr as int_const_node).constant_value);
|
||
lst.Add(expr);
|
||
}
|
||
//это вызов спецфункции
|
||
expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(exprs.Count,loc));
|
||
base_function_call cnfc = retv as base_function_call;
|
||
foreach (expression_node e in lst)
|
||
cnfc.parameters.AddElement(e);
|
||
if (_new_expr.array_init_expr != null)
|
||
{
|
||
if (exprs.Count > 1)
|
||
{
|
||
foreach (expression_node expr in lst)
|
||
if (!(expr is int_const_node))
|
||
AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
if (_new_expr.array_init_expr.elements == null)
|
||
AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_EXPECTED");
|
||
_new_expr.array_init_expr = get_possible_array_const(_new_expr.array_init_expr,atn) as SyntaxTree.array_const;
|
||
expression_node e = convert_strong(_new_expr.array_init_expr);
|
||
if (e is array_initializer)
|
||
{
|
||
array_initializer tmp = e as array_initializer;
|
||
for (int i=0; i<exprs.Count; i++)
|
||
{
|
||
int len = (exprs[i] as int_const_node).constant_value;
|
||
if (!(e is array_initializer) || (e as array_initializer).element_values.Count != len)
|
||
AddError(e.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len);
|
||
e = (e as array_initializer).element_values[0];
|
||
}
|
||
cnfc.parameters.AddElement(ConvertArrayInitializer(atn,tmp));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
expression_node expr = lst[0];
|
||
if (!(expr is int_const_node))
|
||
AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED");
|
||
int len = (expr as int_const_node).constant_value;
|
||
if (_new_expr.array_init_expr.elements == null)
|
||
{
|
||
if (len != 0)
|
||
AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len);
|
||
}
|
||
else if (_new_expr.array_init_expr.elements.expressions.Count != len)
|
||
AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len);
|
||
_new_expr.array_init_expr = get_possible_array_const(_new_expr.array_init_expr,atn) as SyntaxTree.array_const;
|
||
if (_new_expr.array_init_expr.elements != null)
|
||
foreach (SyntaxTree.expression e in _new_expr.array_init_expr.elements.expressions)
|
||
cnfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(clip_expression_if_need(convert_strong(e),tn),tn));
|
||
}
|
||
}
|
||
//явное преобразования для того чтобы тип задать
|
||
function_node fn = convertion_data_and_alghoritms.get_empty_conversion(retv.type, atn, false);
|
||
retv = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, retv);
|
||
return_value(retv);
|
||
return;
|
||
}
|
||
|
||
}
|
||
return_value(create_constructor_call(tn, exprs, get_location(_new_expr.type), new Tuple<bool, List<expression>>(lambdas_are_in_parameters, syntax_nodes_parameters)));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.where_type_specificator_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.where_definition node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.where_definition_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
|
||
private bool can_evaluate_size(type_node tn)
|
||
{
|
||
if (tn is compiled_type_node)
|
||
{
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper || tn.type_special_kind == SemanticTree.type_special_kind.set_type
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.short_string || tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
||
return true;
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.type_special_kind == SemanticTree.type_special_kind.enum_kind)
|
||
return true;
|
||
if (tn.IsPointer)
|
||
return true;
|
||
if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance)
|
||
return false;
|
||
}
|
||
if (tn is common_type_node)
|
||
{
|
||
common_type_node ctn = tn as common_type_node;
|
||
|
||
if (ctn.type_special_kind == SemanticTree.type_special_kind.diap_type || ctn.type_special_kind == SemanticTree.type_special_kind.enum_kind)
|
||
return true;
|
||
if (tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper || tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.short_string
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file
|
||
|| tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
||
return true;
|
||
if (tn.IsPointer)
|
||
return true;
|
||
|
||
if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance)
|
||
return false;
|
||
foreach (class_field cf in ctn.fields)
|
||
if (!cf.IsStatic)
|
||
if (!can_evaluate_size(cf.type)) return false;
|
||
|
||
}
|
||
return true;
|
||
}
|
||
|
||
private expression_node make_sizeof_operator(type_node tn, location loc)
|
||
{
|
||
return new sizeof_operator(tn,loc);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.sizeof_operator node)
|
||
{
|
||
if (node.type_def != null && node.type_def is SyntaxTree.named_type_reference)
|
||
{
|
||
SyntaxTree.named_type_reference ntr = node.type_def as SyntaxTree.named_type_reference;
|
||
type_node tn = find_type(ntr, get_location(ntr));
|
||
switch (tn.type_special_kind)
|
||
{
|
||
case SemanticTree.type_special_kind.enum_kind:
|
||
return_value(new int_const_node(sizeof(int),get_location(ntr))); break;
|
||
default:
|
||
if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance)
|
||
{
|
||
AddError(get_location(ntr), "OPERATOR_SIZEOF_CAN_NOT_BE_USED_WITH_GENERIC_TYPE");
|
||
}
|
||
if (!can_evaluate_size(tn))
|
||
AddError(get_location(ntr), "CANNOT_EVALUATE_SIZE", tn.name);
|
||
return_value(make_sizeof_operator(tn, get_location(node)));
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
throw new NotSupportedError(get_location(node));
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.typeof_operator node)
|
||
{
|
||
return_value(new typeof_operator(find_type(node.type_name, get_location(node.type_name)), get_location(node)));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.compiler_directive node)
|
||
{
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_faststrings)
|
||
{
|
||
SemanticRules.FastStrings = true;
|
||
return;
|
||
}
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_nullbasedstrings)
|
||
{
|
||
SemanticRules.NullBasedStrings = node.Directive.text.ToLower() == compiler_string_consts.true_const_name;
|
||
return;
|
||
}
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_nullbasedstrings_ON)
|
||
{
|
||
SemanticRules.NullBasedStrings = true;
|
||
return;
|
||
}
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_nullbasedstrings_OFF)
|
||
{
|
||
SemanticRules.NullBasedStrings = false;
|
||
return;
|
||
}
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_initstring_as_empty_ON)
|
||
{
|
||
SemanticRules.InitStringAsEmptyString = true;
|
||
return;
|
||
}
|
||
if (node.Name.text.ToLower() == compiler_string_consts.compiler_directive_initstring_as_empty_OFF)
|
||
{
|
||
SemanticRules.InitStringAsEmptyString = false;
|
||
return;
|
||
}
|
||
if (node.Name.text == "platform" && node.Directive.text.ToLower() == "native")
|
||
{
|
||
SemanticRules.GenerateNativeCode = true;
|
||
|
||
|
||
return;
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.operator_name_ident node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.var_statement node)
|
||
{
|
||
visit(node.var_def);
|
||
ret.reset(); // SSM 19.01.17 не возвращать семантическое значение т.к. ничего не нужно добавлять в текущий список операторов!!
|
||
}
|
||
|
||
public override void visit(SyntaxTree.expression_as_statement node)
|
||
{
|
||
return_value((statement_node)convert_strong(node.expr));
|
||
}
|
||
|
||
//ssyy
|
||
public void generate_inherit_constructors()
|
||
{
|
||
common_type_node _ctn = context.converted_type;
|
||
if (_ctn == null)
|
||
{
|
||
throw new CompilerInternalError("Can generate inherited constructors only in class.");
|
||
}
|
||
if (_ctn.has_user_defined_constructor)
|
||
{
|
||
//Пользователь определил хотя бы один конструктор, никакие конструкторы не наследуем.
|
||
return;
|
||
}
|
||
//Получили список процедур предка, имеющих имя Create
|
||
SymbolInfo si = _ctn.base_type.find_in_type(compiler_string_consts.default_constructor_name, _ctn.base_type.Scope);
|
||
delete_inherited_constructors(ref si, _ctn.base_type);
|
||
while (si != null)
|
||
{
|
||
function_node fn = si.sym_info as function_node;
|
||
compiled_constructor_node pconstr = fn as compiled_constructor_node;
|
||
common_method_node mconstr = fn as common_method_node;
|
||
//Если это конструктор...
|
||
if (pconstr != null ||
|
||
mconstr != null && mconstr.is_constructor)
|
||
{
|
||
//Генерируем унаследованный конструктор
|
||
location loc = null;
|
||
SemanticTree.polymorphic_state ps;
|
||
if (mconstr != null)
|
||
{
|
||
loc = mconstr.loc;
|
||
ps = mconstr.polymorphic_state;
|
||
}
|
||
else //значит (pconstr != null)
|
||
{
|
||
ps = pconstr.polymorphic_state;
|
||
}
|
||
if (pconstr != null)
|
||
context.set_field_access_level(pconstr.field_access_level);
|
||
else
|
||
context.set_field_access_level(mconstr.field_access_level);
|
||
common_method_node gen_constr = context.create_function(compiler_string_consts.default_constructor_name, loc) as common_method_node;
|
||
gen_constr.polymorphic_state = ps;
|
||
gen_constr.is_overload = true;
|
||
gen_constr.is_constructor = true;
|
||
gen_constr.field_access_level = fn.field_access_level;
|
||
gen_constr.return_value_type = _ctn;
|
||
|
||
foreach (parameter par in fn.parameters)
|
||
{
|
||
//(ssyy) Интересно, зачем это.
|
||
concrete_parameter_type cpt =
|
||
(par.parameter_type == SemanticTree.parameter_type.var) ?
|
||
concrete_parameter_type.cpt_var :
|
||
concrete_parameter_type.cpt_none;
|
||
common_parameter c_p = new common_parameter(par.name,
|
||
par.parameter_type, gen_constr, cpt, null);
|
||
c_p.type = par.type;
|
||
c_p.set_param_is_params(par.is_params);
|
||
c_p.inital_value = par.inital_value;
|
||
gen_constr.parameters.AddElement(c_p);
|
||
c_p.default_value = par.default_value;
|
||
}
|
||
|
||
base_function_call bfc;
|
||
|
||
if (mconstr != null)
|
||
{
|
||
common_constructor_call c1 = new common_constructor_call(mconstr, null);
|
||
c1._new_obj_awaited = false;
|
||
bfc = c1;
|
||
}
|
||
else
|
||
{
|
||
compiled_constructor_call c2 = new compiled_constructor_call(pconstr, null);
|
||
c2._new_obj_awaited = false;
|
||
bfc = c2;
|
||
}
|
||
foreach (parameter p in gen_constr.parameters)
|
||
{
|
||
bfc.parameters.AddElement(
|
||
create_variable_reference(p, null));
|
||
}
|
||
statements_list snlist = new statements_list(null);
|
||
snlist.statements.AddElement(bfc);
|
||
snlist.statements.AddElement(new empty_statement(null));
|
||
gen_constr.function_code = snlist;
|
||
context.leave_block();
|
||
if (fn.parameters.Count == 0 || fn.parameters[0].default_value != null)
|
||
{
|
||
_ctn.has_default_constructor = true;
|
||
}
|
||
}
|
||
si = si.Next;
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
//ssyy
|
||
public void generate_inherited_from_base_and_interface_function(common_type_node ctype, function_node func)
|
||
{
|
||
common_method_node gen_func = context.create_function(func.name, null) as common_method_node;
|
||
gen_func.polymorphic_state = SemanticTree.polymorphic_state.ps_common;
|
||
gen_func.newslot_awaited = true;
|
||
gen_func.is_final = true;
|
||
gen_func.is_overload = true;
|
||
gen_func.field_access_level = SemanticTree.field_access_level.fal_public;
|
||
gen_func.return_value_type = func.return_value_type;
|
||
//gen_func.return_variable = func.retu
|
||
|
||
foreach (parameter par in func.parameters)
|
||
{
|
||
concrete_parameter_type cpt =
|
||
(par.parameter_type == SemanticTree.parameter_type.value) ?
|
||
concrete_parameter_type.cpt_const :
|
||
concrete_parameter_type.cpt_var;
|
||
common_parameter c_p = new common_parameter(par.name,
|
||
par.parameter_type, gen_func, cpt, null);
|
||
c_p.type = par.type;
|
||
c_p.set_param_is_params(par.is_params);
|
||
c_p.inital_value = par.inital_value;
|
||
gen_func.parameters.AddElement(c_p);
|
||
}
|
||
|
||
local_variable lv = new local_variable(compiler_string_consts.self_word, gen_func.cont_type, gen_func, null);
|
||
gen_func.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(lv));
|
||
gen_func.self_variable = lv;
|
||
|
||
base_function_call bfc;
|
||
this_node tn = null;
|
||
|
||
common_method_node commn = func as common_method_node;
|
||
if (commn != null)
|
||
{
|
||
tn = new this_node(commn.comperehensive_type as type_node, null);
|
||
bfc = new common_method_call(commn, tn, null);
|
||
}
|
||
else
|
||
{
|
||
compiled_function_node compn = func as compiled_function_node;
|
||
tn = new this_node(compn.comperehensive_type as type_node, null);
|
||
bfc = new compiled_function_call(compn, tn, null);
|
||
}
|
||
|
||
foreach (parameter p in gen_func.parameters)
|
||
{
|
||
bfc.parameters.AddElement(
|
||
create_variable_reference(p, null));
|
||
}
|
||
|
||
//Это запретит чистку стека
|
||
bfc.last_result_function_call = true;
|
||
|
||
statements_list snlist = new statements_list(null);
|
||
snlist.statements.AddElement(bfc);
|
||
snlist.statements.AddElement(new empty_statement(null));
|
||
gen_func.function_code = snlist;
|
||
context.pop_top_function();
|
||
//context.leave_block();
|
||
}
|
||
//\ssyy
|
||
|
||
private Dictionary<string, ref_type_node> WaitedRefTypes = new Dictionary<string, ref_type_node>();
|
||
internal ref_type_node GetWaitedRefType(string name, location loc)
|
||
{
|
||
ref_type_node rtn = null;
|
||
if (WaitedRefTypes.TryGetValue(name, out rtn))
|
||
return rtn;
|
||
rtn = new ref_type_node(null);
|
||
rtn.PointedTypeName = name;
|
||
rtn.loc = loc;
|
||
WaitedRefTypes.Add(name, rtn);
|
||
return rtn;
|
||
}
|
||
|
||
internal List<ref_type_node> RefTypesForCheckPointersTypeForDotNetFramework = new List<ref_type_node>();
|
||
void ProcessRefTypesForCheckPointersTypeForDotNetFramework()
|
||
{
|
||
foreach (ref_type_node rtn in RefTypesForCheckPointersTypeForDotNetFramework)
|
||
if (SemanticRules.StrongPointersTypeCheckForDotNet)
|
||
CheckPointersTypeForDotNetFramework(rtn.pointed_type, rtn.loc);
|
||
RefTypesForCheckPointersTypeForDotNetFramework.Clear();
|
||
}
|
||
internal void CheckWaitedRefTypes(type_node tn)
|
||
{
|
||
ref_type_node rtn = null;
|
||
if (WaitedRefTypes.TryGetValue(tn.name, out rtn))
|
||
{
|
||
if (SemanticRules.StrongPointersTypeCheckForDotNet)
|
||
RefTypesForCheckPointersTypeForDotNetFramework.Add(rtn);
|
||
rtn.SetPointedType(tn);
|
||
WaitedRefTypes.Remove(tn.name);
|
||
}
|
||
}
|
||
|
||
internal void EnterTypeDeclarationsSection()
|
||
{
|
||
type_section_converting = true;
|
||
}
|
||
|
||
internal void LeaveTypeDeclarationsSection()
|
||
{
|
||
type_section_converting = false;
|
||
if (context.types_predefined.Count > 0)
|
||
{
|
||
AddError(context.types_predefined[0].loc, "NO_TYPE_{0}_DEFINITION", context.types_predefined[0].name);
|
||
}
|
||
foreach (string Name in WaitedRefTypes.Keys)
|
||
WaitedRefTypes[Name].SetPointedType(find_type(Name, WaitedRefTypes[Name].loc));
|
||
foreach (ref_type_node rtn in WaitedRefTypes.Values)
|
||
CheckForCircularityInPointers(rtn, rtn.pointed_type,rtn.loc);
|
||
ProcessRefTypesForCheckPointersTypeForDotNetFramework();
|
||
WaitedRefTypes.Clear();
|
||
}
|
||
|
||
internal void ProcessCheckPointersInRecord()
|
||
{
|
||
ProcessRefTypesForCheckPointersTypeForDotNetFramework();
|
||
}
|
||
|
||
public override void visit(SyntaxTree.c_scalar_type node)
|
||
{
|
||
Type t = null;
|
||
switch (node.scalar_name)
|
||
{
|
||
case SyntaxTree.c_scalar_type_name.tn_void:
|
||
t = typeof(void);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_char:
|
||
t = typeof(char);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_double:
|
||
t = typeof(double);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_float:
|
||
t = typeof(float);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_int:
|
||
t = (node.sign == SyntaxTree.c_scalar_sign.unsigned) ?
|
||
typeof(UInt32) :
|
||
typeof(Int32);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_long:
|
||
case SyntaxTree.c_scalar_type_name.tn_long_int:
|
||
t = (node.sign == SyntaxTree.c_scalar_sign.unsigned) ?
|
||
typeof(UInt64) :
|
||
typeof(Int64);
|
||
break;
|
||
case SyntaxTree.c_scalar_type_name.tn_short:
|
||
case SyntaxTree.c_scalar_type_name.tn_short_int:
|
||
t = typeof(Int16);
|
||
break;
|
||
}
|
||
ret.return_value(compiled_type_node.get_type_node(t));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.c_module node)
|
||
{
|
||
string namespace_name = "";
|
||
location loc = null;
|
||
// if (_program_module.program_name != null)
|
||
// {
|
||
// namespace_name = _program_module.program_name.prog_name.name;
|
||
// loc = get_location(_program_module.program_name.prog_name);
|
||
// if (namespace_name.ToLower() != System.IO.Path.GetFileNameWithoutExtension(_program_module.file_name).ToLower())
|
||
// throw new ProgramNameMustBeEqualProgramFileName(loc);
|
||
// }
|
||
|
||
|
||
_compiled_unit = new common_unit_node();
|
||
|
||
_compiled_unit.compiler_directives = ConvertDirectives(node);
|
||
//PrepareDirectives(_compiled_unit.compiler_directives);
|
||
|
||
//using_list.AddRange(interface_using_list);
|
||
//weak_node_test_and_visit(_program_module.using_namespaces);
|
||
//weak_node_test_and_visit(node.used_units);
|
||
|
||
//compiled_main_unit=new unit_node();
|
||
//SymbolTable.Scope[] used_units=new SymbolTable.Scope[used_assemblyes.Count+1];
|
||
|
||
SymbolTable.Scope[] used_units = build_referenced_units(referenced_units,true);
|
||
|
||
_compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units);
|
||
|
||
common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc);
|
||
cnsn.is_main = true;
|
||
//compiled_program=new program_node();
|
||
//compiled_program.units.Add(compiled_main_unit);
|
||
|
||
reset_for_interface();
|
||
|
||
UpdateUnitDefinitionItemForUnit(_compiled_unit);
|
||
|
||
//_program_module.program_block.visit(this);
|
||
//hard_node_test_and_visit(_program_module.program_block);
|
||
//context.check_labels(context.converted_namespace.labels);
|
||
|
||
//TODO: Доделать.
|
||
//common_namespace_function_node main_function = new common_namespace_function_node(compiler_string_consts.temp_main_function_name,
|
||
// null, null, cnsn, null);
|
||
//main_function.function_code = context.code;
|
||
//cnsn.functions.AddElement(main_function);
|
||
|
||
weak_node_test_and_visit(node.defs);
|
||
|
||
bool main_not_found = true;
|
||
foreach (function_node fn in cnsn.functions)
|
||
{
|
||
if (fn.name == compiler_string_consts.c_main_function_name)
|
||
{
|
||
_compiled_unit.main_function = fn as common_namespace_function_node;
|
||
//context.apply_special_local_vars(_compiled_unit.main_function);
|
||
main_not_found = false;
|
||
break;
|
||
}
|
||
}
|
||
if (main_not_found)
|
||
{
|
||
AddError(get_location(node), "NO_MAIN_FUNCTION");
|
||
}
|
||
|
||
context.leave_block();
|
||
|
||
//_compiled_unit.main_function = main_function;
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.declarations_as_statement node)
|
||
{
|
||
//throw new NotSupportedError(get_location(node));
|
||
node.defs.visit(this);
|
||
return_value(new empty_statement(null));
|
||
}
|
||
public override void visit(SyntaxTree.array_size node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.enumerator node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.enumerator_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.c_for_cycle node)
|
||
{
|
||
//throw new NotSupportedError(get_location(node));
|
||
location loc1 = get_location(node.expr1);
|
||
statements_list head_stmts = new statements_list(loc1);
|
||
convertion_data_and_alghoritms.statement_list_stack_push(head_stmts);
|
||
//statement_node sn_init = convert_weak((SyntaxTree.statement)node.expr1); // SSM 12/06/15 - всё равно c-узлы никому не нужны
|
||
statement_node sn_init = convert_weak(node.expr1); // SSM 12/06/15
|
||
expression_node sn_cond = convert_weak(node.expr2);
|
||
//statement_node sn_next = convert_weak((SyntaxTree.statement)node.expr3); // SSM 12/06/15
|
||
statement_node sn_next = convert_weak(node.expr3); // SSM 12/06/15
|
||
|
||
CheckToEmbeddedStatementCannotBeADeclaration(node.stmt);
|
||
|
||
for_node fn = new for_node(sn_init, sn_cond, null, sn_next, null, get_location(node));
|
||
context.cycle_stack.push(fn);
|
||
|
||
statements_list slst = new statements_list(get_location(node.stmt));
|
||
convertion_data_and_alghoritms.statement_list_stack_push(slst);
|
||
|
||
context.enter_code_block_with_bind();
|
||
fn.body = convert_strong(node.stmt);
|
||
context.leave_code_block();
|
||
|
||
slst = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (slst.statements.Count > 0 || slst.local_variables.Count > 0)
|
||
{
|
||
slst.statements.AddElement(fn.body);
|
||
fn.body = slst;
|
||
}
|
||
|
||
context.cycle_stack.pop();
|
||
|
||
head_stmts = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
head_stmts.statements.AddElement(fn);
|
||
return_value(head_stmts);
|
||
|
||
/*slst = convertion_data_and_alghoritms.statement_list_stack.pop();
|
||
if (slst.statements.Count > 0 || slst.local_variables.Count > 0)
|
||
{
|
||
slst.statements.AddElement(fn.body);
|
||
fn.body = slst;
|
||
}
|
||
|
||
context.cycle_stack.pop();*/
|
||
//ret.return_value(slst);
|
||
}
|
||
public override void visit(SyntaxTree.switch_stmt node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.type_definition_attr node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.type_definition_attr_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.lock_stmt node)
|
||
{
|
||
expression_node lock_object = convert_strong(node.lock_object);
|
||
//Нужно ли это???
|
||
if (lock_object.type.semantic_node_type == semantic_node_type.delegated_method)
|
||
try_convert_typed_expression_to_function_call(ref lock_object);
|
||
if (lock_object.type == null || lock_object.type.is_value_type)
|
||
AddError(get_location(node.lock_object), "EXPRESSION_IN_LOCK_STATEMENT_RETURNED_NOT_A_REFERENCE_TYPE", lock_object.type);
|
||
CheckToEmbeddedStatementCannotBeADeclaration(node.stmt);
|
||
statement_node stmt = convert_strong(node.stmt);
|
||
return_value(new lock_statement(lock_object, stmt, get_location(node)));
|
||
}
|
||
public override void visit(SyntaxTree.compiler_directive_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.compiler_directive_if node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.documentation_comment_list node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.documentation_comment_section node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.documentation_comment_tag node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.documentation_comment_tag_param node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.token_taginfo node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
public override void visit(SyntaxTree.declaration_specificator node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.ident_with_templateparams _ident_with_templateparams)
|
||
{
|
||
SyntaxTree.expression ex = _ident_with_templateparams.name;
|
||
SyntaxTree.ident id_ex = _ident_with_templateparams.name as SyntaxTree.ident;
|
||
dot_node dn = _ident_with_templateparams.name as dot_node;
|
||
int par_count = _ident_with_templateparams.template_params.params_list.Count;
|
||
if (id_ex != null)
|
||
{
|
||
SymbolInfo type_si = context.find(id_ex.name + compiler_string_consts.generic_params_infix + par_count.ToString());
|
||
if (type_si != null)
|
||
{
|
||
return_value(get_generic_instance(type_si, _ident_with_templateparams.template_params.params_list));
|
||
return;
|
||
}
|
||
type_si = context.find(id_ex.name);
|
||
if (type_si != null && type_si.sym_info.general_node_type == general_node_type.template_type)
|
||
{
|
||
template_class tc = type_si.sym_info as template_class;
|
||
List<type_node> tpars = visit_type_list(_ident_with_templateparams.template_params.params_list);
|
||
return_value(instance_any(tc, tpars, get_location(_ident_with_templateparams)));
|
||
return;
|
||
}
|
||
}
|
||
else if (dn != null && dn.right is ident)
|
||
{
|
||
semantic_node sn = convert_semantic_strong(dn.left);
|
||
id_ex = dn.right as SyntaxTree.ident;
|
||
type_node tn = null;
|
||
namespace_node nn = null;
|
||
unit_node un = null;
|
||
switch (sn.general_node_type)
|
||
{
|
||
case general_node_type.expression: tn = (sn as expression_node).type; break;
|
||
case general_node_type.type_node: tn = sn as type_node; break;
|
||
case general_node_type.namespace_node: nn = sn as namespace_node; break;
|
||
case general_node_type.unit_node: un = sn as unit_node; break;
|
||
default:
|
||
AddError(get_location(dn.left), "EXPECTED_ANOTHER_KIND_OF_OBJECT"); break;
|
||
}
|
||
SymbolInfo type_si = null;
|
||
if (tn != null)
|
||
type_si = tn.find_in_type(id_ex.name + compiler_string_consts.generic_params_infix + par_count.ToString());
|
||
else if (nn != null)
|
||
type_si = nn.find(id_ex.name + compiler_string_consts.generic_params_infix + par_count.ToString());
|
||
else if (un != null)
|
||
type_si = un.find_only_in_namespace(id_ex.name + compiler_string_consts.generic_params_infix + par_count.ToString());
|
||
if (type_si != null)
|
||
{
|
||
return_value(get_generic_instance(type_si, _ident_with_templateparams.template_params.params_list));
|
||
return;
|
||
}
|
||
if (tn != null)
|
||
type_si = tn.find_in_type(id_ex.name);
|
||
else if (nn != null)
|
||
type_si = nn.find(id_ex.name);
|
||
else if (un != null)
|
||
type_si = un.find_only_in_namespace(id_ex.name);
|
||
if (type_si != null && type_si.sym_info.general_node_type == general_node_type.template_type)
|
||
{
|
||
template_class tc = type_si.sym_info as template_class;
|
||
List<type_node> tpars = visit_type_list(_ident_with_templateparams.template_params.params_list);
|
||
return_value(instance_any(tc, tpars, get_location(_ident_with_templateparams)));
|
||
return;
|
||
}
|
||
dot_node dn2 = new dot_node(dn.left, new ident_with_templateparams(dn.right, _ident_with_templateparams.template_params, dn.right.source_context), dn.source_context);
|
||
ex = dn2;
|
||
}
|
||
|
||
expression_node adr = ret.visit(ex);
|
||
typed_expression te = adr as typed_expression;
|
||
if (te != null)
|
||
{
|
||
delegated_methods dm = te.type as delegated_methods;
|
||
if (dm != null)
|
||
{
|
||
List<type_node> ptypes = visit_type_list(_ident_with_templateparams.template_params.params_list);
|
||
base_function_call_list bfcl = new base_function_call_list();
|
||
common_method_node cnode;
|
||
compiled_function_node comp_node;
|
||
function_node fnode;
|
||
int generic_count = 0;
|
||
foreach (base_function_call bfc in dm.proper_methods)
|
||
{
|
||
if (bfc.simple_function_node.is_generic_function)
|
||
{
|
||
generic_count++;
|
||
}
|
||
}
|
||
bool one_function = false;
|
||
switch (generic_count)
|
||
{
|
||
case 0:
|
||
AddError(get_location(_ident_with_templateparams), "TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS"); break;
|
||
case 1:
|
||
one_function = true;
|
||
break;
|
||
default:
|
||
one_function = false;
|
||
break;
|
||
}
|
||
foreach (base_function_call bfc in dm.proper_methods)
|
||
{
|
||
if (!bfc.simple_function_node.is_generic_function)
|
||
{
|
||
continue;
|
||
}
|
||
switch (bfc.semantic_node_type)
|
||
{
|
||
case semantic_node_type.common_namespace_function_call:
|
||
common_namespace_function_node cnfn = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)) as common_namespace_function_node;
|
||
if (cnfn != null)
|
||
{
|
||
bfcl.AddElement(new common_namespace_function_call(cnfn, bfc.location));
|
||
}
|
||
break;
|
||
case semantic_node_type.common_method_call:
|
||
cnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)) as common_method_node;
|
||
if (cnode != null)
|
||
{
|
||
bfcl.AddElement(new common_method_call(cnode, (bfc as common_method_call).obj, bfc.location));
|
||
}
|
||
break;
|
||
case semantic_node_type.compiled_function_call:
|
||
fnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams));
|
||
cnode = fnode as common_method_node;
|
||
if (cnode != null)
|
||
{
|
||
bfcl.AddElement(new common_method_call(cnode, (bfc as compiled_function_call).obj, bfc.location));
|
||
}
|
||
else
|
||
{
|
||
comp_node = fnode as compiled_function_node;
|
||
if (comp_node != null)
|
||
{
|
||
bfcl.AddElement(new compiled_function_call(comp_node, (bfc as compiled_function_call).obj, bfc.location));
|
||
}
|
||
}
|
||
break;
|
||
case semantic_node_type.common_static_method_call:
|
||
case semantic_node_type.compiled_static_method_call:
|
||
fnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams));
|
||
cnode = fnode as common_method_node;
|
||
if (cnode != null)
|
||
{
|
||
bfcl.AddElement(new common_static_method_call(cnode, bfc.location));
|
||
}
|
||
else
|
||
{
|
||
comp_node = fnode as compiled_function_node;
|
||
if (comp_node != null)
|
||
{
|
||
bfcl.AddElement(new compiled_static_method_call(comp_node, bfc.location));
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (bfcl.Count == 0)
|
||
{
|
||
AddError(get_location(_ident_with_templateparams.template_params), "NO_FUNCTIONS_{0}_CAN_BE_USED_WITH_THIS_SPECIFICATION", dm.proper_methods[0].function.name);
|
||
}
|
||
delegated_methods dm1 = new delegated_methods();
|
||
dm1.proper_methods.AddRange(bfcl);
|
||
typed_expression te1 = new typed_expression(dm1, te.location);
|
||
return_value(te1);
|
||
return;
|
||
}
|
||
}
|
||
if (!(adr is compiled_static_method_call) && !(adr is common_static_method_call))
|
||
AddError(get_location(_ident_with_templateparams.name), "TRIANGLE_BRACKETS_NOT_AWAITED");
|
||
}
|
||
|
||
public override void visit(SyntaxTree.template_type_name node)
|
||
{
|
||
throw new NotSupportedError(get_location(node));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.default_operator _default_operator)
|
||
{
|
||
type_node tn = ret.visit(_default_operator.type_name);
|
||
if (tn == null)
|
||
{
|
||
AddError(get_location(_default_operator), "TYPE_REFERENCE_EXPECTED");
|
||
}
|
||
if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
{
|
||
AddError(get_location(_default_operator.type_name), "INAVLID_TYPE");
|
||
}
|
||
return_value(new default_operator_node(tn, get_location(_default_operator)));
|
||
//throw new NotSupportedError(get_location(_default_operator));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.bracket_expr _bracket_expr)
|
||
{
|
||
_bracket_expr.expr.visit(this);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.attribute _attribute)
|
||
{
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.attribute_list _attribute_list)
|
||
{
|
||
|
||
}
|
||
|
||
public override void visit(SyntaxTree.simple_attribute_list _simple_attribute_list)
|
||
{
|
||
|
||
}
|
||
|
||
public override void visit(closure_substituting_node _closure_substituting_node)
|
||
{
|
||
visit(_closure_substituting_node.substitution);
|
||
}
|
||
|
||
public void MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(function_lambda_definition _function_lambda_definition)
|
||
{
|
||
// SSM 23/07/16 - вроде сделал лучше в LambdaHelper.InferTypesFromVarStmt, но пока везде удалять вызов этой функции не решаюсь - лень тестировать
|
||
// SSM 18/04/16 попытка разрешить x->Print(x)
|
||
var stl = _function_lambda_definition.proc_body as SyntaxTree.statement_list;
|
||
if (_function_lambda_definition.return_type is lambda_inferred_type && stl != null && stl.list.Count == 1 && _function_lambda_definition.usedkeyword == 0)
|
||
{
|
||
var ass = stl.list[0] as assign;
|
||
if (ass != null && ass.to is ident && (ass.to as ident).name.ToLower() == "result")
|
||
{
|
||
var f = ass.from;
|
||
if (f is method_call)
|
||
{
|
||
var ff = f as method_call;
|
||
// Надо посмотреть, как это делается для преобразования типов T(x). А пока так
|
||
expression_node qq = null;
|
||
delegated_methods dm = null;
|
||
try
|
||
{
|
||
qq = convert_strong(ff.dereferencing_value);
|
||
dm = qq.type as delegated_methods;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// Погасить все исключения. Значит, не вывелось, и в правой части лямбды - не вызов процедуры, а скорее всего приведение типа T(x)
|
||
// К сожалению, сюда попадает случай a->a.Print() где a до более позднего этапа не определяется
|
||
// Плохо, но лучше пока не получается
|
||
}
|
||
if (dm != null && dm.proper_methods != null && dm.proper_methods.Count > 0)
|
||
{
|
||
if (dm.proper_methods[0].ret_type == null && stl.expr_lambda_body)
|
||
{
|
||
// Очищаем от Result :=
|
||
stl.list[0] = new procedure_call(ff, ff.source_context); // заменить result := Print(x) на Print(x)
|
||
_function_lambda_definition.return_type = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else // значит, первый и единственный оператор - не присваивание и это лямбда - процедура!
|
||
{
|
||
_function_lambda_definition.return_type = null;
|
||
}
|
||
}
|
||
else if (_function_lambda_definition.return_type is lambda_inferred_type && stl != null && stl.list.Count > 1 && _function_lambda_definition.usedkeyword == 0)
|
||
{
|
||
var rns = new LambdaHelper.ResultNodesSearcher(_function_lambda_definition.proc_body);
|
||
if (rns.exprList.Count == 0) // Значит, это процедура, т.к. в блоке begin-end нет ни одного result := ...
|
||
{
|
||
_function_lambda_definition.return_type = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.function_lambda_definition _function_lambda_definition)
|
||
{
|
||
MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(_function_lambda_definition);
|
||
|
||
_function_lambda_definition.RealSemTypeOfResExpr = null; // После первого присваивания Result она будет содержать тип type_node в правой части Result
|
||
_function_lambda_definition.RealSemTypeOfResult = null;
|
||
try
|
||
{
|
||
stflambda.Push(_function_lambda_definition);
|
||
if (_function_lambda_definition.substituting_node != null)
|
||
{
|
||
if (_function_lambda_definition.substituting_node is dot_node)
|
||
{
|
||
visit((dot_node)_function_lambda_definition.substituting_node);
|
||
}
|
||
else
|
||
{
|
||
if (_function_lambda_definition.substituting_node is ident)
|
||
{
|
||
visit((ident)_function_lambda_definition.substituting_node);
|
||
}
|
||
else
|
||
{
|
||
if (_function_lambda_definition.substituting_node is ident_with_templateparams)
|
||
{
|
||
visit((ident_with_templateparams)_function_lambda_definition.substituting_node);
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
Func<function_lambda_definition, ident_list, where_definition_list, expression> makeProcedureForLambdaAndVisit =
|
||
(lambdaDefinition, tempParsList, whereSection) =>
|
||
{
|
||
var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition);
|
||
|
||
if (tempParsList != null)
|
||
{
|
||
procDecl.proc_header.template_args = tempParsList;
|
||
}
|
||
|
||
if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0)
|
||
{
|
||
procDecl.proc_header.where_defs = whereSection;
|
||
}
|
||
|
||
if (!context.func_stack.Empty && context.func_stack.top().polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
procDecl.proc_header.class_keyword = true;
|
||
if (procDecl.proc_header.proc_attributes == null)
|
||
procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list();
|
||
procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static));
|
||
}
|
||
|
||
try
|
||
{
|
||
visit(procDecl);
|
||
}
|
||
catch
|
||
{
|
||
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true);
|
||
throw;
|
||
}
|
||
|
||
context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false);
|
||
|
||
return tempParsList == null ?
|
||
(expression)procDecl.proc_header.name.meth_name :
|
||
(expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList()));
|
||
};
|
||
|
||
|
||
switch (lambdaProcessingState)
|
||
{
|
||
case LambdaProcessingState.FinishPhase:
|
||
{
|
||
if (context.top_function != null && context.top_function.generic_params != null)
|
||
{
|
||
var pars = context.top_function.generic_params.Select(par => new ident(par.name)).ToList();
|
||
|
||
var whereSection =
|
||
CapturedVariablesSubstitutor.GetWhereSection(
|
||
generic_parameter_eliminations.make_eliminations_common(
|
||
context.top_function.generic_params), pars);
|
||
|
||
if (_function_lambda_definition.formal_parameters != null && _function_lambda_definition.formal_parameters.params_list.Count > 0)
|
||
{
|
||
for (var j = 0; j < _function_lambda_definition.formal_parameters.params_list.Count; j++)
|
||
{
|
||
if (_function_lambda_definition.formal_parameters.params_list[j].vars_type is lambda_inferred_type)
|
||
{
|
||
if ((_function_lambda_definition.formal_parameters.params_list[j].vars_type as lambda_inferred_type).real_type is type_node)
|
||
{
|
||
_function_lambda_definition.formal_parameters.params_list[j].vars_type =
|
||
LambdaHelper.ConvertSemanticTypeToSyntaxType((type_node)(_function_lambda_definition.formal_parameters.params_list[j].vars_type as lambda_inferred_type).real_type);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (_function_lambda_definition.return_type is lambda_inferred_type)
|
||
{
|
||
if ((_function_lambda_definition.return_type as lambda_inferred_type).real_type is type_node)
|
||
{
|
||
_function_lambda_definition.return_type = LambdaHelper.ConvertSemanticTypeToSyntaxType((type_node)(_function_lambda_definition.return_type as lambda_inferred_type).real_type);
|
||
}
|
||
}
|
||
|
||
var methodNameToVisit = (ident_with_templateparams)makeProcedureForLambdaAndVisit(_function_lambda_definition, new ident_list(pars), whereSection);
|
||
_function_lambda_definition.substituting_node = methodNameToVisit;
|
||
visit(methodNameToVisit);
|
||
}
|
||
else
|
||
{
|
||
var methodNameToVisit = (ident)makeProcedureForLambdaAndVisit(_function_lambda_definition, null, null);
|
||
_function_lambda_definition.substituting_node = methodNameToVisit;
|
||
visit(methodNameToVisit);
|
||
}
|
||
break;
|
||
}
|
||
case LambdaProcessingState.TypeInferencePhase:
|
||
{
|
||
if (_function_lambda_definition.lambda_visit_mode ==
|
||
LambdaVisitMode.VisitForAdvancedMethodCallProcessing)
|
||
{
|
||
makeProcedureForLambdaAndVisit(_function_lambda_definition, null, null);
|
||
if (!LambdaHelper.IsAuxiliaryLambdaName(_function_lambda_definition.lambda_name))
|
||
{
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, _function_lambda_definition);
|
||
}
|
||
}
|
||
|
||
ret.return_value((semantic_node)LambdaHelper.GetTempFunctionNodeForTypeInference(_function_lambda_definition, this));
|
||
|
||
break;
|
||
}
|
||
case LambdaProcessingState.ClosuresProcessingPhase:
|
||
{
|
||
makeProcedureForLambdaAndVisit(_function_lambda_definition, null, null);
|
||
LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, _function_lambda_definition);
|
||
ret.return_value((semantic_node)LambdaHelper.GetTempFunctionNodeForTypeInference(_function_lambda_definition, this));
|
||
break;
|
||
}
|
||
case LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase:
|
||
{
|
||
makeProcedureForLambdaAndVisit(_function_lambda_definition, null, null);
|
||
break;
|
||
}
|
||
case LambdaProcessingState.None:
|
||
{
|
||
if (context.converting_block() == block_type.namespace_block)
|
||
{
|
||
var methodNameToVisit = (ident)makeProcedureForLambdaAndVisit(_function_lambda_definition, null, null);
|
||
_function_lambda_definition.substituting_node = methodNameToVisit;
|
||
visit(methodNameToVisit);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
stflambda.Pop();
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.function_lambda_call _function_lambda_call)
|
||
{
|
||
SyntaxTree.op_type_node _op_type_node = new SyntaxTree.op_type_node(SyntaxTree.Operators.Assignment);
|
||
for (int i = 0; i < _function_lambda_call.parameters.expressions.Count; i++)
|
||
{
|
||
SyntaxTree.assign _assign = new SyntaxTree.assign(_function_lambda_call.f_lambda_def.parameters.expressions[i] as SyntaxTree.addressed_value, _function_lambda_call.parameters.expressions[i] as SyntaxTree.expression, _op_type_node.type);
|
||
((SyntaxTree.statement_list)_function_lambda_call.f_lambda_def.proc_body).subnodes.Insert(0, _assign);
|
||
_assign.source_context = _function_lambda_call.source_context;
|
||
}
|
||
SyntaxTree.expression_list el = new SyntaxTree.expression_list();
|
||
for (int i = 0; i < _function_lambda_call.f_lambda_def.formal_parameters.params_list.Count; i++)
|
||
if (i < _function_lambda_call.parameters.expressions.Count)
|
||
el.expressions.Add(_function_lambda_call.parameters.expressions[i]);
|
||
else
|
||
{
|
||
el.expressions.Add(new SyntaxTree.ident(_function_lambda_call.f_lambda_def.formal_parameters.params_list[i].idents.idents[0].name, _function_lambda_call.source_context));
|
||
}
|
||
SyntaxTree.method_call _method_call = new SyntaxTree.method_call(el);
|
||
_method_call.source_context = _function_lambda_call.source_context;
|
||
if (_method_call is SyntaxTree.dereference)
|
||
{
|
||
((SyntaxTree.dereference)_method_call).dereferencing_value = (SyntaxTree.addressed_value)(new SyntaxTree.ident(_function_lambda_call.f_lambda_def.lambda_name, _function_lambda_call.source_context));
|
||
}
|
||
_method_call.visit(this);
|
||
}
|
||
|
||
public void lambda_header_visit(SymbolInfo si, SyntaxTree.function_header _function_header, type_node tn1)
|
||
{
|
||
type_node tn = null;
|
||
if (_function_header.return_type == null)
|
||
{
|
||
if (context.top_function.IsOperator)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
}
|
||
if (_function_header.return_type != null)
|
||
{
|
||
check_parameter_on_complex_type(_function_header.return_type);
|
||
if (tn1 != null)
|
||
tn = tn1;
|
||
else
|
||
tn = convert_strong(_function_header.return_type);
|
||
//if (tn == SystemLibrary.SystemLibrary.void_type)
|
||
// AddError(new VoidNotValid(get_location(_function_header.return_type)));
|
||
check_for_type_allowed(tn, get_location(_function_header.return_type));
|
||
}
|
||
//(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения
|
||
context.top_function.return_value_type = tn;
|
||
assign_doc_info(context.top_function, _function_header);
|
||
if (_function_header.attributes != null)
|
||
{
|
||
make_attributes_for_declaration(_function_header, context.top_function);
|
||
}
|
||
if (context.converted_type != null && has_dll_import_attribute(context.top_function))
|
||
AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD");
|
||
if (_function_header.name.class_name != null)
|
||
with_class_name = true;
|
||
if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes))
|
||
{
|
||
SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static);
|
||
pa.source_context = _function_header.source_context;
|
||
_function_header.proc_attributes.proc_attributes.Add(pa);
|
||
}
|
||
weak_node_test_and_visit(_function_header.proc_attributes);
|
||
if (context.top_function.IsOperator)
|
||
{
|
||
common_method_node cmmn = context.top_function as common_method_node;
|
||
//if (cmmn == null)
|
||
//{
|
||
// throw new OverloadOperatorMustBeStaticFunction(get_location(_function_header), context.top_function);
|
||
//}
|
||
if (cmmn != null && cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
|
||
{
|
||
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||
}
|
||
if (cmmn != null && (cmmn.name == compiler_string_consts.implicit_operator_name || cmmn.name == compiler_string_consts.explicit_operator_name))
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName);
|
||
}
|
||
else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.parameters[0].type))
|
||
{
|
||
AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION");
|
||
}
|
||
}
|
||
with_class_name = false;
|
||
if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator)
|
||
{
|
||
concrete_parameter_type cpt = concrete_parameter_type.cpt_none;
|
||
SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value;
|
||
if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type)
|
||
{
|
||
cpt = concrete_parameter_type.cpt_var;
|
||
pt = PascalABCCompiler.SemanticTree.parameter_type.var;
|
||
}
|
||
common_parameter cp = new common_parameter(compiler_string_consts.self_word, (context.top_function as common_namespace_function_node).ConnectedToType, pt,
|
||
context.top_function, cpt, null, null);
|
||
context.top_function.parameters.AddElementFirst(cp);
|
||
context.top_function.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(cp));
|
||
}
|
||
CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header));
|
||
|
||
bool unique = context.close_function_params(body_exists);
|
||
if (context.top_function.return_value_type == null)
|
||
AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE");
|
||
if (_function_header.where_defs != null)
|
||
{
|
||
if (unique)
|
||
{
|
||
visit_where_list(_function_header.where_defs);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION");
|
||
}
|
||
}
|
||
convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si);
|
||
|
||
/*if (_function_header.name != null && context.converted_compiled_type != null && context.top_function is common_namespace_function_node)
|
||
{
|
||
if (context.FindMethodToOverride(context.top_function as common_namespace_function_node) != null)
|
||
AddError(new CanNotDeclareExtensionMethodAsOverrided(get_location(_function_header)));
|
||
}*/
|
||
//TODO: Разобрать подробнее.
|
||
if (!body_exists)
|
||
{
|
||
if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node)
|
||
|| ((context.func_stack_size_is_one()) && (_is_interface_part)))
|
||
{
|
||
context.leave_block();
|
||
}
|
||
}
|
||
body_exists = false;
|
||
}
|
||
public void lambda_body_visit(SyntaxTree.block _block)
|
||
{
|
||
//weak_node_test_and_visit(_block.defs);
|
||
|
||
//ssyy добавил генерацию вызова конструктора предка без параметров
|
||
if (context.converting_block() == block_type.function_block)
|
||
{
|
||
common_method_node cmn = context.top_function as common_method_node;
|
||
if (cmn != null && cmn.is_constructor && !(cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static))
|
||
{
|
||
context.allow_inherited_ctor_call = true;
|
||
if (_block.program_code != null && _block.program_code.subnodes != null)
|
||
{
|
||
//(ssyy) Для записей конструктор предка не вызываем.
|
||
bool should_ctor_add = context.converted_type.is_class;
|
||
if (should_ctor_add)
|
||
{
|
||
if (_block.program_code.subnodes.Count > 0)
|
||
{
|
||
SyntaxTree.procedure_call pc = _block.program_code.subnodes[0] as SyntaxTree.procedure_call;
|
||
if (pc != null || _block.program_code.subnodes[0] is SyntaxTree.inherited_message)
|
||
{
|
||
//SyntaxTree.inherited_ident ii = pc.func_name as SyntaxTree.inherited_ident;
|
||
//SyntaxTree.method_call mc = pc.func_name as SyntaxTree.method_call;
|
||
//SyntaxTree.ident id = pc.func_name as SyntaxTree.ident;
|
||
//if (/*ii != null*/id != null || mc != null /*&& mc.dereferencing_value is SyntaxTree.inherited_ident*/)
|
||
{
|
||
//(ssyy) Не уверен, что следующий оператор необходим.
|
||
convertion_data_and_alghoritms.check_node_parser_error(_block.program_code);
|
||
|
||
statement_node inh = convert_strong(_block.program_code.subnodes[0]);
|
||
|
||
compiled_constructor_call c1 = inh as compiled_constructor_call;
|
||
if (c1 != null && !c1._new_obj_awaited)
|
||
{
|
||
should_ctor_add = false;
|
||
}
|
||
else
|
||
{
|
||
common_constructor_call c2 = inh as common_constructor_call;
|
||
if (c2 != null && !c2._new_obj_awaited)
|
||
{
|
||
should_ctor_add = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (should_ctor_add)
|
||
{
|
||
//Пытаемся добавить вызов .ctor() предка...
|
||
//Для начала проверим, есть ли у предка таковой.
|
||
bool not_found = true;
|
||
SymbolInfo sym = context.converted_type.base_type.find_in_type(compiler_string_consts.default_constructor_name, context.CurrentScope);
|
||
while (not_found && sym != null)
|
||
{
|
||
compiled_constructor_node ccn = sym.sym_info as compiled_constructor_node;
|
||
if (ccn != null && ccn.parameters.Count == 0)
|
||
{
|
||
not_found = false;
|
||
}
|
||
else
|
||
{
|
||
common_method_node cnode = sym.sym_info as common_method_node;
|
||
if (cnode != null && cnode.is_constructor && (cnode.parameters.Count == 0 || cnode.parameters[0].default_value != null))
|
||
{
|
||
not_found = false;
|
||
}
|
||
}
|
||
sym = sym.Next;
|
||
}
|
||
if (not_found)
|
||
{
|
||
//У предка нет конструктора по умолчанию
|
||
AddError(get_location(_block.program_code), "INHERITED_CONSTRUCTOR_CALL_EXPECTED");
|
||
}
|
||
else
|
||
{
|
||
//Генерируем вызов .ctor() предка
|
||
SyntaxTree.inherited_ident ii = new SyntaxTree.inherited_ident();
|
||
ii.name = compiler_string_consts.default_constructor_name;
|
||
_block.program_code.subnodes.Insert(0, new SyntaxTree.procedure_call(ii));
|
||
//context.allow_inherited_ctor_call = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
//ssyy
|
||
if (context.converting_block() == block_type.namespace_block)
|
||
{
|
||
context.check_predefinition_defined();
|
||
}
|
||
|
||
context.enter_code_block_with_bind();
|
||
statement_node sn = convert_strong(_block.program_code);
|
||
context.leave_code_block();
|
||
|
||
context.code = sn;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.lambda_inferred_type lit) //lroman//
|
||
{
|
||
return_value(lit.real_type as type_node);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.semantic_check sem)
|
||
{
|
||
if (sem == null)
|
||
return;
|
||
switch (sem.CheckName)
|
||
{
|
||
case "ExprIsInteger":
|
||
var ex = (SyntaxTree.expression)sem.param[0];
|
||
expression_node en = convert_strong(ex);
|
||
en.location = get_location(ex);
|
||
if (en.type != SystemLibrary.SystemLibrary.integer_type)
|
||
AddError(get_location(ex), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED");
|
||
break;
|
||
case " ":
|
||
break;
|
||
case " ":
|
||
break;
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.same_type_node st) // SSM 22/06/13
|
||
{
|
||
expression_node en = convert_strong(st.ex);
|
||
if (en == null)
|
||
AddError(get_location(st.ex),"CANNOT_EVALUATE_FUNCTION_TYPE");
|
||
return_value(en.type);
|
||
}
|
||
|
||
public type_node try_calc_expr_type(SyntaxTree.expression ex) // SSM 10.07.13
|
||
{
|
||
try
|
||
{
|
||
expression_node en = convert_strong(ex);
|
||
return en.type;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
return new undefined_type("#UndefType", null);
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.semantic_type_node stn)
|
||
{
|
||
return_value(stn.type as type_node);
|
||
}
|
||
|
||
// SSM 10.01.16 впервые для реализации Tuple - t[0]
|
||
public override void visit(SyntaxTree.semantic_addr_value sav)
|
||
{
|
||
return_value(sav.expr as expression_node);
|
||
}
|
||
|
||
public bool SameTypeAutoClasses(List<string> names, List<type_node> types, common_type_node t)
|
||
{
|
||
if (t.properties.Count() != names.Count())
|
||
return false;
|
||
|
||
var tnames = t.properties.Select(tt => tt.name);
|
||
|
||
return types.SequenceEqual(t.fields.Select(tt => tt.type)) && names.SequenceEqual(tnames, StringComparer.OrdinalIgnoreCase);
|
||
//return true;
|
||
}
|
||
|
||
public override void visit(SyntaxTree.unnamed_type_object unn) // SSM 27.06.13
|
||
{
|
||
var l = unn.ne_list;
|
||
var names = l.name_expr.Select(x=>x.name).ToList();
|
||
var strnames = names.Select(id=>id.name).ToList(); // преобразование idents в строки
|
||
var semantic_types = l.name_expr.Select(x => convert_strong(x.expr).type).ToList();
|
||
var types = semantic_types.Select(x => SyntaxTreeBuilder.BuildSemanticType(x)).ToList();
|
||
|
||
contextChanger.SaveContextAndUpToGlobalLevel();
|
||
|
||
var tt = context._cmn.types.Where(t => t.name.StartsWith("AnonymousType#")); // найти все анонимные типы, полученные в текущей компиляции
|
||
|
||
var typ = tt.FirstOrDefault(t => SameTypeAutoClasses(strnames, semantic_types, t)); // найти структурно совпадающий уже существующий анонимный тип
|
||
|
||
// Генерация глобальных описаний - перенесена с синтаксического уровня
|
||
if (typ != null)
|
||
unn.set_name(typ.name); // если нашли, то просто меняем имя на имя этого класса
|
||
else
|
||
{
|
||
var td = SyntaxTreeBuilder.BuildAutoClass(unn.name(), names, types, unn.is_class);
|
||
visit(td);
|
||
}
|
||
|
||
contextChanger.RestoreCurrentContext();
|
||
|
||
// Сахарный узел. Переадресация дальнейшей генерации узлу new_ex
|
||
visit(unn.new_ex);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.short_func_definition def) // SSM 20.07.13
|
||
{
|
||
// Сахарный узел. Переадресация дальнейшей генерации узлу procedure_definition
|
||
visit(def.procdef);
|
||
}
|
||
|
||
public override void visit(matching_expression _matching_expression)
|
||
{
|
||
throw new NotSupportedError(get_location(_matching_expression));
|
||
}
|
||
|
||
public override void visit(SyntaxTree.sequence_type _sequence_type) // сахарный узел
|
||
{
|
||
// SSM 11/05/15 sugared node
|
||
var l = new List<ident>();
|
||
l.Add(new ident("?System"));
|
||
l.Add(new ident("Collections"));
|
||
l.Add(new ident("Generic"));
|
||
l.Add(new ident("IEnumerable"));
|
||
var tr = new template_type_reference(new named_type_reference(l),
|
||
new template_param_list(_sequence_type.elements_type, _sequence_type.elements_type.source_context),
|
||
_sequence_type.source_context);
|
||
visit(tr);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.modern_proc_type _modern_proc_type) // сахарный узел
|
||
{
|
||
if (_modern_proc_type.res != null)
|
||
{
|
||
var l = new List<ident>();
|
||
l.Add(new ident("?System"));
|
||
l.Add(new ident("Func"));
|
||
var t = new template_param_list();
|
||
if (_modern_proc_type.aloneparam != null)
|
||
t.Add(_modern_proc_type.aloneparam);
|
||
if (_modern_proc_type.el != null)
|
||
{
|
||
var en = _modern_proc_type.el;
|
||
if (en.enumerators.Count == 1)
|
||
AddError(get_location(en.enumerators[0].name), "ONE_TYPE_PARAMETER_MUSTBE_WITHOUT_PARENTHESES");
|
||
for (int i = 0; i < en.enumerators.Count; i++)
|
||
{
|
||
if (en.enumerators[i].value != null)
|
||
AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER");
|
||
|
||
if (!(en.enumerators[i].name is named_type_reference))
|
||
AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER");
|
||
|
||
t.Add(en.enumerators[i].name); // ???????????????
|
||
}
|
||
}
|
||
t.Add(_modern_proc_type.res, _modern_proc_type.res.source_context);
|
||
t.source_context = _modern_proc_type.source_context;
|
||
var ttr = new template_type_reference(new named_type_reference(l), t, _modern_proc_type.source_context);
|
||
visit(ttr);
|
||
}
|
||
else if (_modern_proc_type.aloneparam != null || _modern_proc_type.el != null)
|
||
{
|
||
var l = new List<ident>();
|
||
l.Add(new ident("?System"));
|
||
l.Add(new ident("Action"));
|
||
var t = new template_param_list();
|
||
if (_modern_proc_type.aloneparam != null)
|
||
t.Add(_modern_proc_type.aloneparam);
|
||
if (_modern_proc_type.el != null)
|
||
{
|
||
var en = _modern_proc_type.el;
|
||
if (en.enumerators.Count == 1)
|
||
AddError(get_location(en.enumerators[0].name), "ONE_TYPE_PARAMETER_MUSTBE_WITHOUT_PARENTHESES");
|
||
for (int i = 0; i < en.enumerators.Count; i++)
|
||
{
|
||
|
||
if (en.enumerators[i].value != null)
|
||
AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER");
|
||
|
||
if (!(en.enumerators[i].name is named_type_reference))
|
||
AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER");
|
||
|
||
t.Add(en.enumerators[i].name);
|
||
}
|
||
}
|
||
t.source_context = _modern_proc_type.source_context;
|
||
var ttr = new template_type_reference(new named_type_reference(l), t, _modern_proc_type.source_context);
|
||
visit(ttr);
|
||
}
|
||
else
|
||
{
|
||
var l = new List<ident>();
|
||
l.Add(new ident("?System"));
|
||
l.Add(new ident("Action"));
|
||
var ntr = new named_type_reference(l);
|
||
visit(ntr);
|
||
}
|
||
}
|
||
|
||
// Это в куче мест надо. Потому что либо compiled_type_node, либо compiled_generic_instance_type_node
|
||
// compiled_type_node если в записи A<T> все типы NETовские
|
||
// compiled_generic_instance_type_node если в записи A<T> хоть один тип - паскалевский
|
||
public Type ConvertSemanticTypeNodeToNETType(type_node tn)
|
||
{
|
||
if (tn is compiled_generic_instance_type_node)
|
||
{
|
||
var tnc = (tn as compiled_generic_instance_type_node);
|
||
var itnc = tnc.original_generic as compiled_type_node;
|
||
var tt = itnc.compiled_type;
|
||
if (tt.IsGenericType)
|
||
tt = tt.GetGenericTypeDefinition();
|
||
return tt;
|
||
}
|
||
else if (tn is compiled_type_node)
|
||
{
|
||
var itnc = (tn as compiled_type_node);
|
||
var tt = itnc.compiled_type;
|
||
if (tt.IsGenericType)
|
||
tt = tt.GetGenericTypeDefinition();
|
||
return tt;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/*expression_list construct_expression_list_for_slice_expr(SyntaxTree.slice_expr sl)
|
||
{
|
||
// situation = 0 - ничего не пропущено
|
||
// situation = 1 - пропущен from
|
||
// situation = 2 - пропущен to
|
||
// situation = 3 - пропущены from и to
|
||
// Пропущенность кодируется тем, что в соответствующем поле - int.MaxValue
|
||
// step может просто отсутствовать - это параметр по умолчанию в SystemSlice
|
||
|
||
int situation = 0;
|
||
|
||
if ((sl.from is int32_const) && (sl.from as int32_const).val == int.MaxValue)
|
||
situation += 1;
|
||
if ((sl.to is int32_const) && (sl.to as int32_const).val == int.MaxValue)
|
||
situation += 2;
|
||
|
||
var el = new SyntaxTree.expression_list();
|
||
el.Add(new int32_const(situation));
|
||
el.Add(sl.from); // Это плохо - считается 2 раза. Надо делать semantic_expr_node !!!? Нет!!!
|
||
// Если там будет лямбда, то не будет работать - известно, что semantic_expr_node не работает с лямбдами
|
||
// т.к. они несколько раз обходят код.
|
||
el.Add(sl.to);
|
||
if (sl.step != null)
|
||
el.Add(sl.step);
|
||
|
||
return el;
|
||
}*/
|
||
|
||
// frninja 04/03/16 - для yield
|
||
|
||
// frninja 06/06/16 - фикс для видимости private методов и полей с классов в том же модуле
|
||
private unit_node GetUnknownIdentUnit(definition_node dn)
|
||
{
|
||
if (dn is class_field)
|
||
{
|
||
return ((dn as class_field).cont_type.comprehensive_namespace != null)
|
||
? (dn as class_field).cont_type.comprehensive_namespace.cont_unit
|
||
: null;
|
||
}
|
||
else if (dn is common_method_node)
|
||
{
|
||
return ((dn as common_method_node).cont_type.comprehensive_namespace != null)
|
||
? (dn as common_method_node).cont_type.comprehensive_namespace.cont_unit
|
||
: null;
|
||
}
|
||
else if (dn is common_property_node)
|
||
{
|
||
return ((dn as common_property_node).common_comprehensive_type.comprehensive_namespace != null)
|
||
? (dn as common_property_node).common_comprehensive_type.comprehensive_namespace.cont_unit
|
||
: null;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
// end frninja 06/06/16
|
||
|
||
private bool CheckIsStaticName(definition_node dn)
|
||
{
|
||
if (dn is class_field && (dn as class_field).polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
return true;
|
||
|
||
if (dn is common_method_node && (dn as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
return true;
|
||
|
||
if (dn is common_property_node && (dn as common_property_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
return true;
|
||
|
||
if (dn is compiled_function_node && (dn as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
return true;
|
||
|
||
if (dn is compiled_property_node && (dn as compiled_property_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
private bool CheckUnknownIdentNeedsClassCapture(SyntaxTree.yield_unknown_ident _unk, out bool isStaticIdent)
|
||
{
|
||
|
||
string Consts__Self = YieldHelpers.YieldConsts.Self;
|
||
|
||
// Find semantic class containing iterator (yield-method) with unknown ident
|
||
var iteratorContainingClass = context._ctn.fields.Where(f => f.name == Consts__Self).First().type;
|
||
//var iteratorContainingClass = context._cmn.types.Where(t => t.name == _unk.ClassName.name).First();
|
||
|
||
isStaticIdent = false;
|
||
|
||
if (iteratorContainingClass != null)
|
||
{
|
||
// Search for unknown ident in class
|
||
var found = iteratorContainingClass.find(_unk.UnknownID.name);
|
||
if ((object)found != null)
|
||
{
|
||
// class_field - поле класса
|
||
// common_method_node - метод класса
|
||
// common_property_node - свойство класса
|
||
|
||
// че там с .NET как базовым?
|
||
// compiled_function_node - метод базового .NET класса
|
||
// compiled_property_node - свойство базового .NET класса
|
||
|
||
// че с классом из другого модуля?
|
||
// то же что и с классом из этого же
|
||
|
||
isStaticIdent = CheckIsStaticName(found.sym_info);
|
||
|
||
if (found.sym_info is class_field
|
||
|| found.sym_info is common_method_node
|
||
|| found.sym_info is common_property_node
|
||
|| found.sym_info is compiled_function_node
|
||
|| found.sym_info is compiled_property_node)
|
||
{
|
||
if (!isStaticIdent && _unk.IsYieldInStaticMethod)
|
||
return false;
|
||
|
||
// frninja 06/06/16 - фиксим private того же модуля
|
||
if ((iteratorContainingClass is common_type_node)
|
||
&& this.GetUnknownIdentUnit(found.sym_info) ==
|
||
(((iteratorContainingClass as common_type_node).comprehensive_namespace != null)
|
||
? (iteratorContainingClass as common_type_node).comprehensive_namespace.cont_unit
|
||
: null))
|
||
{
|
||
return true;
|
||
}
|
||
else if (found.access_level != access_level.al_private)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// common_namespace_function_node - глобальный метод
|
||
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private dot_node CaptureUnknownIdent(yield_unknown_ident unk, bool isStaticIdent = false)
|
||
{
|
||
if (isStaticIdent)
|
||
{
|
||
return new dot_node(unk.ClassName, unk.UnknownID);
|
||
}
|
||
string Consts__Self = YieldHelpers.YieldConsts.Self;
|
||
|
||
return new dot_node(new dot_node(new ident("self"), new ident(Consts__Self)), unk.UnknownID);
|
||
}
|
||
|
||
private SyntaxTree.addressed_value_funcname ProcessUnknownIdent(yield_unknown_ident unk)
|
||
{
|
||
bool isStaticIdent;
|
||
if (CheckUnknownIdentNeedsClassCapture(unk, out isStaticIdent))
|
||
{
|
||
var uid = CaptureUnknownIdent(unk, isStaticIdent);
|
||
return uid;
|
||
}
|
||
else
|
||
{
|
||
return unk.UnknownID;
|
||
}
|
||
}
|
||
|
||
public override void visit(SyntaxTree.yield_node yn)
|
||
{
|
||
// надо что то сгенерировать, иначе выдается ложное предупреждение о недостижимом коде и проч.
|
||
/*var ass = new assign("Result", new nil_const());
|
||
visit(ass);
|
||
var pc = new procedure_call("exit");
|
||
visit(pc);*/
|
||
}
|
||
|
||
// frninja - захват полей класса для yield
|
||
public override void visit(SyntaxTree.yield_unknown_ident _unk)
|
||
{
|
||
ProcessUnknownIdent(_unk).visit(this);
|
||
}
|
||
|
||
public override void visit(SyntaxTree.yield_unknown_expression_type _unk_expr)
|
||
{
|
||
// Отвечает за типизацию всех переменных с автовыведением типа
|
||
// Пробую сделать по-другому: перевести в auto_type и потом на присваивании перехватить
|
||
var t = new semantic_type_node(new auto_type(get_location(_unk_expr)));
|
||
t.visit(this);
|
||
}
|
||
|
||
// frninja 29/05/16 - выявляем тип перемнной в foreach
|
||
public override void visit(SyntaxTree.yield_unknown_foreach_type _unk)
|
||
{
|
||
var t = new semantic_type_node(new ienumerable_auto_type(get_location(_unk)));
|
||
t.visit(this);
|
||
}
|
||
|
||
/*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn)
|
||
{
|
||
// Неверно работает. Пока не используется. Доделать
|
||
addressed_value left = dqn.left;
|
||
addressed_value right = dqn.right;
|
||
var eq = new bin_expr(left, new nil_const(), Operators.Equal, left.source_context);
|
||
var dn = new dot_node(left, right, dqn.source_context);
|
||
var q = new SyntaxTree.question_colon_expression(eq, new nil_const(), dn, dqn.source_context);
|
||
return q;
|
||
}
|
||
public override void visit(SyntaxTree.dot_question_node dqn)
|
||
{
|
||
// a?.b
|
||
var q = ConvertToQCE(dqn);
|
||
visit(q);
|
||
}*/
|
||
|
||
public override void visit(SyntaxTree.semantic_check_sugared_statement_node st)
|
||
{
|
||
if (st.stat is SyntaxTree.assign_tuple)
|
||
{
|
||
semantic_check_assign_tuple(st.stat as SyntaxTree.assign_tuple);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(st), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", st.GetType().Name);
|
||
}
|
||
ret.reset(); // обязательно очистить - этот узел в семантику ничего не должен приносить!
|
||
}
|
||
|
||
public override void visit(SyntaxTree.sugared_expression ex)
|
||
{
|
||
/*if (ex.sugared_expr is SyntaxTree.tuple_node)
|
||
{
|
||
semantic_check_tuple(ex.sugared_expr as SyntaxTree.tuple_node);
|
||
}
|
||
else*/
|
||
{
|
||
AddError(get_location(ex), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", ex.sugared_expr.GetType().Name);
|
||
}
|
||
|
||
ProcessNode(ex.new_expr); // обойти десахарное выражение - обязательно ProcessNode - visit нельзя!
|
||
}
|
||
|
||
public override void visit(SyntaxTree.sugared_addressed_value av)
|
||
{
|
||
if (av.sugared_expr is SyntaxTree.slice_expr) // и slice_expr_question
|
||
{
|
||
semantic_check_method_call_as_slice_expr(av.new_addr_value as SyntaxTree.method_call);
|
||
}
|
||
else
|
||
{
|
||
AddError(get_location(av), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", av.sugared_expr.GetType().Name);
|
||
}
|
||
|
||
ProcessNode(av.new_addr_value); // обойти десахарное
|
||
}
|
||
|
||
public override void visit(SyntaxTree.assign_tuple asstup) // сахарный узел
|
||
{
|
||
AddError(get_location(asstup), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", asstup.GetType().Name);
|
||
|
||
/*semantic_check_assign_tuple(asstup);
|
||
|
||
var tname = "#temp_var" + UniqueNumStr();
|
||
|
||
//var tt = new var_statement(new ident(tname), new semantic_addr_value(expr)); // тут semantic_addr_value хранит на самом деле expr - просто неудачное название
|
||
var tt = new var_statement(new ident(tname), asstup.expr); // тут semantic_addr_value хранит на самом деле expr - просто неудачное название
|
||
var st = new statement_list(tt);
|
||
|
||
var n = asstup.vars.variables.Count();
|
||
for (var i = 0; i < n; i++)
|
||
{
|
||
var a = new assign(asstup.vars.variables[i], new dot_node(new ident(tname),
|
||
new ident("Item" + (i + 1).ToString())), Operators.Assignment,
|
||
asstup.vars.variables[i].source_context);
|
||
st.Add(a);
|
||
}
|
||
visit(st);
|
||
// Замена 1 оператор на 1 оператор - всё OK
|
||
ReplaceUsingParent(asstup, st);*/
|
||
}
|
||
|
||
public override void visit(SyntaxTree.assign_var_tuple assvartup) // сахарный узел
|
||
{
|
||
AddError(get_location(assvartup), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", assvartup.GetType().Name);
|
||
|
||
/*check_sugared(assvartup);
|
||
|
||
var tname = "#temp_var" + UniqueNumStr();
|
||
|
||
var tt = new var_statement(new ident(tname), assvartup.expr); // тут для assvartup.expr внутри повторно вызывается convert_strong, это плохо, но если там лямбда, то иначе - с semantic_addr_value - не работает!!!
|
||
//var tt = new var_statement(new ident(tname), new semantic_addr_value(expr)); // тут semantic_addr_value хранит на самом деле expr - просто неудачное название
|
||
visit(tt); // обходится первый элемент - вместо asstup
|
||
|
||
var sl = new List<statement>();
|
||
sl.Add(tt); // он же помещается в новое синтаксическое дерево
|
||
|
||
var n = assvartup.vars.variables.Count();
|
||
for (var i = 0; i < n; i++)
|
||
{
|
||
var rr = assvartup.vars.variables[i] as ident;
|
||
var a = new var_statement(rr,
|
||
new dot_node(new ident(tname),new ident("Item" + (i + 1).ToString())),
|
||
assvartup.vars.variables[i].source_context
|
||
);
|
||
// Остальные элементы обходить не надо (!!!уже надо!) - они обходятся на следующих итерациях при обходе внешнего statement_list
|
||
//visit(a);
|
||
sl.Add(a);
|
||
}
|
||
ReplaceStatementUsingParent(assvartup, sl);*/
|
||
}
|
||
|
||
public override void visit(SyntaxTree.slice_expr sl) // сахарный узел
|
||
{
|
||
AddError(get_location(sl), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", sl.GetType().Name);
|
||
|
||
/*
|
||
// Преобразуется в вызов a.SystemSlice(situation,from,to,step)
|
||
// Тип a должен быть array of T, List<T> или string
|
||
semcheck(sl);
|
||
|
||
// Действия уровня синтаксиса. Можно вынести на синтаксический уровень как desugaring для сахарного узла
|
||
var el = construct_expression_list_for_slice_expr(sl);
|
||
var mc = new method_call(new dot_node(sl.v, new ident("SystemSlice", sl.v.source_context), sl.v.source_context), el, sl.source_context);
|
||
|
||
visit(mc);*/
|
||
}
|
||
|
||
public override void visit(SyntaxTree.slice_expr_question sl) // сахарный узел
|
||
{
|
||
AddError(get_location(sl), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", sl.GetType().Name);
|
||
/*
|
||
// Преобразуется в вызов a.SystemSlice(situation,from,to,step)
|
||
// Тип a должен быть array of T, List<T> или string
|
||
semcheck(sl);
|
||
|
||
var el = construct_expression_list_for_slice_expr(sl);
|
||
var mc = new method_call(new dot_node(sl.v, new ident("SystemSliceQuestion", sl.v.source_context), sl.v.source_context), el, sl.source_context);
|
||
|
||
visit(mc);*/
|
||
}
|
||
}
|
||
}
|