enum type as array indexer

This commit is contained in:
Бондарев Иван 2015-11-08 13:39:39 +01:00
parent faad7cdd52
commit f03cc0a610
5 changed files with 164 additions and 37 deletions

View file

@ -13,6 +13,7 @@ namespace PascalABCCompiler
{ {
private List<Errors.CompilerWarning> warns = new List<Errors.CompilerWarning>(); private List<Errors.CompilerWarning> warns = new List<Errors.CompilerWarning>();
private OptimizerHelper helper = new OptimizerHelper(); private OptimizerHelper helper = new OptimizerHelper();
private bool extended_mode = false;
public Optimizer() 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) private void VisitCommonNamespaceHeader(common_namespace_node cnn)
{ {
if (!cnn.from_pcu) if (!cnn.from_pcu)
@ -108,6 +119,8 @@ namespace PascalABCCompiler
private void VisitMethod(common_method_node cmn) 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) foreach (var_definition_node vdn in cmn.var_definition_nodes_list)
helper.AddVariable(vdn); helper.AddVariable(vdn);
foreach (common_parameter prm in cmn.parameters) foreach (common_parameter prm in cmn.parameters)
@ -171,8 +184,34 @@ namespace PascalABCCompiler
private common_function_node cur_func=null; 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) 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) foreach (var_definition_node vdn in cnfn.var_definition_nodes_list)
helper.AddVariable(vdn); helper.AddVariable(vdn);
foreach (common_parameter prm in cnfn.parameters) foreach (common_parameter prm in cnfn.parameters)
@ -220,6 +259,8 @@ namespace PascalABCCompiler
private void VisitNestedFunction(common_in_function_function_node cnfn) 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) foreach (var_definition_node vdn in cnfn.var_definition_nodes_list)
helper.AddVariable(vdn); helper.AddVariable(vdn);
foreach (common_parameter prm in cnfn.parameters) foreach (common_parameter prm in cnfn.parameters)
@ -364,6 +405,22 @@ namespace PascalABCCompiler
private void VisitFor(for_node stmt) 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.initialization_statement);
VisitStatement(stmt.increment_statement); VisitStatement(stmt.increment_statement);
VisitExpression(stmt.while_expr); VisitExpression(stmt.while_expr);
@ -462,7 +519,8 @@ namespace PascalABCCompiler
private void VisitGoto(goto_statement stmt) private void VisitGoto(goto_statement stmt)
{ {
if (extended_mode)
AddHint("DO_NOT_USE_GOTO", stmt.location);
} }
private void IncreaseNumUseVar(var_definition_node lvr) private void IncreaseNumUseVar(var_definition_node lvr)
@ -840,6 +898,58 @@ namespace PascalABCCompiler
private void VisitCommonNamespaceFunctionCall(common_namespace_function_call en) 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++) for (int i = 0; i < en.parameters.Count; i++)
VisitExpression(en.parameters[i]); VisitExpression(en.parameters[i]);
} }

View file

@ -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 public class CompilerWarningWithLocation : CompilerWarning
{ {
protected location loc; 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 class UnreachableCodeDetected : CompilerWarningWithLocation
{ {
public UnreachableCodeDetected(location loc) public UnreachableCodeDetected(location loc)

View file

@ -1,32 +1,6 @@
type TArr = array[1..3] of integer; type TEnum = (one, two, three);
var arr: array[TEnum] 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);
begin begin
rec1.a := 2; rec1.b := 2.3; rec1.d := 'abc'; rec1.e := 'abc'; arr[three] := 12;
rec1.c := arr1; assert(arr[three] = 12);
rec1.f := ['e','d']; end.
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.

View file

@ -12131,7 +12131,7 @@ namespace PascalABCCompiler.TreeConverter
{ {
type_node tn = convert_strong(td); type_node tn = convert_strong(td);
internal_interface ii = tn.get_internal_interface(internal_interface_kind.ordinal_interface); 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))); AddError(new OrdinalTypeExpected(get_location(td)));
} }

View file

@ -289,7 +289,7 @@ namespace VisualPascalABC
} }
foreach (Breakpoint bp in dbg.Breakpoints) 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; added = true;
br = bp; br = bp;
@ -869,8 +869,8 @@ namespace VisualPascalABC
{ {
curILOffset = nextStatement.ILOffset; curILOffset = nextStatement.ILOffset;
CurrentLine = nextStatement.StartLine; CurrentLine = nextStatement.StartLine;
//MustDebug = false; MustDebug = false;
MustDebug = ((nextStatement.ILOffset + 1) == nextStatement.ILEnd); //MustDebug = ((nextStatement.ILOffset + 1) == nextStatement.ILEnd);
} }
//MustDebug = false; //MustDebug = false;
//if (remove_breakpoints) //if (remove_breakpoints)