From f03cc0a6101dff4f8b72c80c64b6fb5739fcd2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=BD=D0=B4=D0=B0=D1=80=D0=B5=D0=B2=20=D0=98?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD?= Date: Sun, 8 Nov 2015 13:39:39 +0100 Subject: [PATCH] enum type as array indexer --- Optimizer/Optimizer.cs | 112 +++++++++++++++++- Optimizer/Warnings.cs | 45 ++++++- TestSuite/arrays8.pas | 36 +----- .../TreeConversion/syntax_tree_visitor.cs | 2 +- VisualPascalABCNET/IB/Debugger/Debugger.cs | 6 +- 5 files changed, 164 insertions(+), 37 deletions(-) diff --git a/Optimizer/Optimizer.cs b/Optimizer/Optimizer.cs index c39cc8630..292996e13 100644 --- a/Optimizer/Optimizer.cs +++ b/Optimizer/Optimizer.cs @@ -13,6 +13,7 @@ namespace PascalABCCompiler { private List warns = new List(); private OptimizerHelper helper = new OptimizerHelper(); + private bool extended_mode = false; public Optimizer() { @@ -44,6 +45,16 @@ namespace PascalABCCompiler } } + private void AddWarning(string message, location loc) + { + warns.Add(new GenericWarning(message, loc)); + } + + private void AddHint(string message, location loc) + { + warns.Add(new GenericHint(message, loc)); + } + private void VisitCommonNamespaceHeader(common_namespace_node cnn) { if (!cnn.from_pcu) @@ -108,6 +119,8 @@ namespace PascalABCCompiler private void VisitMethod(common_method_node cmn) { + if (extended_mode) + VisitVariables(cmn.var_definition_nodes_list); foreach (var_definition_node vdn in cmn.var_definition_nodes_list) helper.AddVariable(vdn); foreach (common_parameter prm in cmn.parameters) @@ -171,8 +184,34 @@ namespace PascalABCCompiler private common_function_node cur_func=null; + private void CheckType(type_node type, expression_node initial_value, location loc) + { + if (type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) + { + AddHint("DO_NOT_USE_STATIC_ARRAYS", loc); + } + else if (type.IsPointer && type.element_type.is_value_type && type.element_type is common_type_node) + { + AddHint("DO_NOT_USE_POINTERS_TO_RECORDS", loc); + } + else if (type.type_special_kind == SemanticTree.type_special_kind.short_string) + { + AddHint("DO_NOT_USE_SHORT_STRINGS", loc); + } + } + + private void VisitVariables(local_variable_list var_list) + { + foreach (local_variable lv in var_list) + { + CheckType(lv.type, lv.inital_value, lv.loc); + } + } + private void VisitCommonNamespaceFunctionNode(common_namespace_function_node cnfn) { + if (extended_mode) + VisitVariables(cnfn.var_definition_nodes_list); foreach (var_definition_node vdn in cnfn.var_definition_nodes_list) helper.AddVariable(vdn); foreach (common_parameter prm in cnfn.parameters) @@ -220,6 +259,8 @@ namespace PascalABCCompiler private void VisitNestedFunction(common_in_function_function_node cnfn) { + if (extended_mode) + VisitVariables(cnfn.var_definition_nodes_list); foreach (var_definition_node vdn in cnfn.var_definition_nodes_list) helper.AddVariable(vdn); foreach (common_parameter prm in cnfn.parameters) @@ -364,6 +405,22 @@ namespace PascalABCCompiler private void VisitFor(for_node stmt) { + if (extended_mode) + { + if (stmt.init_while_expr is basic_function_call) + { + basic_function_call bfc = stmt.init_while_expr as basic_function_call; + if (!(bfc.real_parameters[0] is local_block_variable_reference)) + AddHint("USE_LOCAL_BLOCK_VARIABLES_FOR_CYCLE_COUNTER", stmt.location); + else + { + local_block_variable lbv = (bfc.real_parameters[0] as local_block_variable_reference).var; + if (lbv.loc.begin_line_num < stmt.location.begin_line_num || lbv.loc.begin_column_num < stmt.location.end_column_num) + AddHint("USE_LOCAL_BLOCK_VARIABLES_CYCLE_COUNTER", stmt.location); + } + } + } + VisitStatement(stmt.init_while_expr); VisitStatement(stmt.initialization_statement); VisitStatement(stmt.increment_statement); VisitExpression(stmt.while_expr); @@ -462,7 +519,8 @@ namespace PascalABCCompiler private void VisitGoto(goto_statement stmt) { - + if (extended_mode) + AddHint("DO_NOT_USE_GOTO", stmt.location); } private void IncreaseNumUseVar(var_definition_node lvr) @@ -840,6 +898,58 @@ namespace PascalABCCompiler private void VisitCommonNamespaceFunctionCall(common_namespace_function_call en) { + if (extended_mode) + { + string func_name = en.function_node.name.ToLower(); + if ((func_name == "readln" || func_name == "read") && en.function_node.namespace_node.namespace_name == "PABCSystem") + { + if (en.parameters.Count == 1) + { + if (func_name == "readln") + func_name = "Readln"; + else + func_name = "Read"; + compiled_type_node ctn = en.parameters[0].type as compiled_type_node; + if (ctn != null) + { + if (ctn == SystemLibrary.SystemLibrary.integer_type) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", func_name + "Integer"), en.location); + } + else if (ctn == SystemLibrary.SystemLibrary.double_type) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", func_name + "Real"), en.location); + } + else if (ctn == SystemLibrary.SystemLibrary.char_type) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", func_name + "Char"), en.location); + } + else if (ctn == SystemLibrary.SystemLibrary.string_type) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", func_name + "String"), en.location); + } + else if (ctn == SystemLibrary.SystemLibrary.bool_type) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", func_name + "Boolean"), en.location); + } + } + } + } + else if (func_name == "writeln") + { + if (en.parameters.Count >= 3) + { + foreach (expression_node prm in en.parameters) + { + if (prm is string_const_node || prm is char_const_node) + { + AddHint(string.Format("USE_FUNCTION_{0}_INSTEAD", "WritelnFormat"), en.location); + break; + } + } + } + } + } for (int i = 0; i < en.parameters.Count; i++) VisitExpression(en.parameters[i]); } diff --git a/Optimizer/Warnings.cs b/Optimizer/Warnings.cs index 0f2f6f019..a0ccfc9f9 100644 --- a/Optimizer/Warnings.cs +++ b/Optimizer/Warnings.cs @@ -23,6 +23,19 @@ namespace PascalABCCompiler } } + public class HintStringResources + { + public static string Get(string key) + { + return PascalABCCompiler.StringResources.Get("HINT_" + key); + } + + public static string Get(string key, params object[] values) + { + return (string.Format(Get(key), values)); + } + } + public class CompilerWarningWithLocation : CompilerWarning { protected location loc; @@ -43,7 +56,37 @@ namespace PascalABCCompiler } } - + public class GenericWarning : CompilerWarningWithLocation + { + protected string message; + + public GenericWarning(string message, location loc) + { + this.message = message; + this.loc = loc; + } + + public override string ToString() + { + //return ("Possible two type convertions\n"+_en.location.ToString()); + return WarningStringResources.Get(message); + } + } + + public class GenericHint : GenericWarning + { + public GenericHint(string message, location loc):base(message, loc) + { + + } + + public override string ToString() + { + //return ("Possible two type convertions\n"+_en.location.ToString()); + return WarningStringResources.Get(message); + } + } + public class UnreachableCodeDetected : CompilerWarningWithLocation { public UnreachableCodeDetected(location loc) diff --git a/TestSuite/arrays8.pas b/TestSuite/arrays8.pas index 8cd3e2997..04469a952 100644 --- a/TestSuite/arrays8.pas +++ b/TestSuite/arrays8.pas @@ -1,32 +1,6 @@ -type TArr = array[1..3] of integer; - -type TRec = record -a : integer; -b : real; -c : TArr; -d : string; -e : string[4]; -f : set of char; - -end; - -var rec1, rec2 : TRec; - arr1 : TArr := (1,2,3); - arr2 : TArr := (1,2,3); - arr3 : TArr := (1,2,4); - +type TEnum = (one, two, three); +var arr: array[TEnum] of integer; begin -rec1.a := 2; rec1.b := 2.3; rec1.d := 'abc'; rec1.e := 'abc'; -rec1.c := arr1; -rec1.f := ['e','d']; -rec2.a := 2; rec2.b := 2.3; rec2.d := 'abc'; rec2.e := 'abc'; -rec2.c := arr2; -rec2.f := ['e','d']; -assert(rec1=rec2); -rec1.b := 6.3; -assert(rec1<>rec2); -rec1.c[2] := 8; -assert(rec1 <> rec2); -assert(arr1=arr2); -assert(arr3<>arr1); -end. + arr[three] := 12; + assert(arr[three] = 12); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 24a847d7a..43df7fe73 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -12131,7 +12131,7 @@ namespace PascalABCCompiler.TreeConverter { type_node tn = convert_strong(td); internal_interface ii = tn.get_internal_interface(internal_interface_kind.ordinal_interface); - if (ii == null || ((tn is common_type_node) && (tn as common_type_node).IsEnum)) + if (ii == null /*|| ((tn is common_type_node) && (tn as common_type_node).IsEnum)*/) { AddError(new OrdinalTypeExpected(get_location(td))); } diff --git a/VisualPascalABCNET/IB/Debugger/Debugger.cs b/VisualPascalABCNET/IB/Debugger/Debugger.cs index 22096eb8c..e3b92f256 100644 --- a/VisualPascalABCNET/IB/Debugger/Debugger.cs +++ b/VisualPascalABCNET/IB/Debugger/Debugger.cs @@ -289,7 +289,7 @@ namespace VisualPascalABC } foreach (Breakpoint bp in dbg.Breakpoints) { - if (bp.SourcecodeSegment.SourceFilename == fileName && bp.SourcecodeSegment.StartLine == line) + if (bp.SourcecodeSegment.SourceFullFilename == fileName && bp.SourcecodeSegment.StartLine == line) { added = true; br = bp; @@ -869,8 +869,8 @@ namespace VisualPascalABC { curILOffset = nextStatement.ILOffset; CurrentLine = nextStatement.StartLine; - //MustDebug = false; - MustDebug = ((nextStatement.ILOffset + 1) == nextStatement.ILEnd); + MustDebug = false; + //MustDebug = ((nextStatement.ILOffset + 1) == nextStatement.ILEnd); } //MustDebug = false; //if (remove_breakpoints)