366
366
data.IsArray = true;
367
367
r+=" .field public valuetype _" + ILIdentifier(data.Name) + "[] " + ILIdentifier(data.Name) + "\n";
369
r+=" .field public " + ILType(data.Type) + " " + ILIdentifier(data.Name) + "\n";
369
r+=" .field public " + ILType(data.Type) + " " + ILIdentifier(data.Name) + "\n";
371
//This is a group, so it needs a boolean flag to indicate if its empty
372
r+=" .field public bool _hasData_" + ILIdentifier(data.Name) + "\n";
875
879
//TODO: Implement"corresponding"
876
//TODO: Implement "MOVE SPACES..."
877
if (move.From.IsSpaces)
879
//TODO: Type checking
880
//TODO: Line number in exception
881
//TODO: Look variable up in definitions and get size, then move n spaces into it.
882
foreach (Identifier toIdentifier in move.To)
880
//TODO: Implement "MOVE SPACES..."
881
if (move.From.GetType() == typeof(FigurativeConstant))
883
FigurativeConstant constant = move.From as FigurativeConstant;
884
if (constant.Type == FigurativeConstantType.Spaces)
884
int size = toIdentifier.Definition.Size;
885
//Console.WriteLine("MOVE SPACES TO variable of size "+size);
887
r += ILAddress(1) + "ldarg.0"; //Hidden pointer to 'this'
889
Literal literal = new Literal();
890
literal.Type = VariableType.String;
892
for (int i = 0; i < size; i++)
886
//TODO: Type checking
887
//TODO: Line number in exception
888
//TODO: Look variable up in definitions and get size, then move n spaces into it.
889
foreach (Identifier toIdentifier in move.To)
894
literal.Value += " ";
896
r += EmitLiteral(literal);
897
r += EmitStore(toIdentifier); //TODO: This needs changed for subscripts
891
int size = toIdentifier.Definition.Size;
892
//Console.WriteLine("MOVE SPACES TO variable of size "+size);
894
r += ILAddress(1) + "ldarg.0"; //Hidden pointer to 'this'
896
Literal literal = new Literal();
897
literal.Type = VariableType.String;
899
for (int i = 0; i < size; i++)
901
literal.Value += " ";
903
r += EmitLiteral(literal);
904
r += EmitStore(toIdentifier); //TODO: This needs changed for subscripts
905
if (IsGroup(toIdentifier))
907
r += " " + ILAddress(1) + "ldarg.0\n"; //Hidden pointer to 'this'
908
r += " " + ILAddress(1) + "ldc.i4.0\n"; //Zero, used for 'false'
909
r += " " + ILAddress(5) + "stfld bool __CobolProgram::_hasData_"+toIdentifier.Definition.Name+"\n";
913
Console.WriteLine("TODO: Other figurative constants not supported yet");
1073
1089
else if(identifier.Definition.IsHighValues)
1075
1091
//Set value of entire record and set this to true/false?
1076
Console.WriteLine("Warning: SET with HIGH-VALUES isn't fully implemented yet");
1092
//TODO: I've commented this warning out. Can't remember why it was there.
1093
//Console.WriteLine("Warning: SET with HIGH-VALUES isn't fully implemented yet");
1077
1094
r += " " + ILAddress(5);
1078
1095
if (className==null)
1079
1096
className = "__CobolProgram";
1156
//Load length of string
1157
//if p>=length, skip this
1158
r += " " + ILAddress(5);
1159
r += "ldc.i4 "+p+"\n";
1160
r += " " + ILAddress(1);
1162
r += " " + ILAddress(5);
1163
r += "callvirt instance int32 string::get_Length()\n";
1164
r += " " + ILAddress(5);
1165
r += "bge "; //Address will be added here later
1169
//Set boolean flag to indicat group is not empty here
1170
r2 += " " + ILAddress(1) + "ldarg.0\n"; //Hidden pointer to 'this'
1171
r2 += " " + ILAddress(1) + "ldc.i4.1\n"; //Zero, used for 'false'
1172
r2 += " " + ILAddress(5) + "stfld bool __CobolProgram::_hasData_"+identifier.Definition.Name+"\n";
1138
1174
//Pointer to this...
1139
r += " " + ILAddress(1);
1175
r2 += " " + ILAddress(1);
1142
1178
//Load the string...
1143
r += " " + ILAddress(1);
1179
r2 += " " + ILAddress(1);
1146
1182
//Take a substring out of it (based on DDE's size)...
1148
r+= " " + ILAddress(5);
1149
r+= "ldc.i4 "+p+"\n";
1184
r2+= " " + ILAddress(5);
1185
r2+= "ldc.i4 "+p+"\n";
1151
r+= " " + ILAddress(5);
1187
r2+= " " + ILAddress(5);
1153
1189
if (dd.Size==0)
1157
1193
//or skip to next element of the group
1160
r+= "ldc.i4 "+dd.Size+"\n";
1196
r2+= "ldc.i4 "+dd.Size+"\n";
1161
1197
// callvirt instance string string::Substring(int32, int32)
1162
r+= " " + ILAddress(5);
1163
r+= "callvirt instance string string::Substring(int32, int32)\n";
1198
r2+= " " + ILAddress(5);
1199
r2+= "callvirt instance string string::Substring(int32, int32)\n";
1168
1204
// e.g. Integer
1169
1205
if (dd.Type == DataType.Integer)
1171
r+= " " + ILAddress(5);
1172
r+="call int32 int32::Parse(string)\n";
1207
r2+= " " + ILAddress(5);
1208
r2+="call int32 int32::Parse(string)\n";
1175
1211
//Save the substring to an element...
1176
1212
Identifier elem = new Identifier();
1177
1213
elem.Definition = dd;
1178
1214
elem.Name = dd.Name;
1179
r+=EmitStore(elem,null);
1215
r2+=EmitStore(elem,null);
1217
//Skips to here if p>=length of string
1218
r+=ILAddress()+" //<-------- \n";
1181
1221
Identifier elem = new Identifier();
1182
1222
elem.Definition = dd;
1280
1320
//Call substring:
1281
1321
// IL_0011: callvirt instance string string::Substring(int32, int32)
1282
r += " " + ILAddress(5) + "callvirt instance string string::Substring(int32, int32)\n";
1322
r += " " + ILAddress(5) + "callvirt instance string string::Substring(int32, int32)\n";
1284
1324
//Store result:
1285
1325
// IL_0016: stfld string WorkingStorageTest.Program::bb1
1389
// if (id.Definition.IsGroup)
1391
// Console.WriteLine("EmitLoadField Groups/Records not supported yet");
1429
if (id.Definition.IsGroup && !id.Definition.IsAnonymous)
1431
//TODO: Make this work
1432
//Console.WriteLine("EmitLoadField Groups/Records not supported yet");
1434
r += " " + ILAddress(1) + "pop\n";
1436
//Build the format string...
1437
List<DataDescription> ddes = ListElements(id.Definition);
1440
foreach (DataDescription dd in ddes)
1442
fmt += "{" + obj + ",-" + dd.Size + "}";
1445
//Load the format string...
1446
r += " " + ILAddress(5);
1447
r += "ldstr \"" + fmt + "\"\n";
1448
Console.WriteLine("fmt = "+fmt);
1451
r += " " + ILAddress(5);
1452
r += "ldc.i4 " + ddes.Count + "\n";
1453
r += " " + ILAddress(5);
1454
r += "newarr [mscorlib]System.Object\n";
1456
//Load elements into array
1458
foreach (DataDescription dd in ddes)
1460
Identifier tmp = new Identifier();
1462
tmp.Definition = dd;
1463
r += " " + ILAddress(1) + "dup\n";
1464
r += " " + ILAddress(5) + "ldc.i4 "+obj+"\n";
1465
r += EmitLoadSource(tmp as Source, false, true);
1466
r += " " + ILAddress(1) + "stelem.ref\n";
1469
r += " " + ILAddress(5) + "call string string::Format(string,object[])\n";
1393
1471
string typ = null;
1395
1473
if (id.Definition.IsClass)
1826
private string EmitLoopStringComparisonCondition(RelationCondition condition, string startAddress)
1830
Source left = condition.LeftExpression.TimesDiv.Power.Basis.Source;
1831
Source right = condition.RightExpression.TimesDiv.Power.Basis.Source;
1833
if (left.GetType() == typeof(FigurativeConstant) ||
1834
right.GetType() == typeof(FigurativeConstant))
1836
//Work out which side is the figurative constant...
1838
FigurativeConstant constant;
1839
if (left.GetType() == typeof(FigurativeConstant)){
1840
constant = left as FigurativeConstant;
1843
constant = right as FigurativeConstant;
1847
if (constant.Type == FigurativeConstantType.Spaces)
1849
Identifier id = other as Identifier;
1851
Console.WriteLine("Identifier expected when comparing to figurative constant");
1853
r += " " + ILAddress(1) + "ldarg.0\n"; //Hidden pointer to 'this'
1854
r += " " + ILAddress(5) + "ldfld bool __CobolProgram::_hasData_"+id.Definition.Name+"\n";
1855
r += " " + ILAddress(5) + "brtrue " + startAddress + "\n";
1857
Console.WriteLine("Other figurative constants not supported yet");
1862
r += EmitLoadSource(left, false, false);
1863
r += EmitLoadSource(right, false, false);
1864
if (condition.RelationalOperator.Relation == RelationType.EqualTo)
1866
//Stop looping when left = right
1867
r += " " + ILAddress(2);
1869
r += " " + ILAddress(1);
1871
r += " " + ILAddress(2);
1873
r += " " + ILAddress(1);
1875
r += " " + ILAddress(1);
1877
r += " " + ILAddress(5);
1878
r += "brtrue " + startAddress + "\n";
1880
Console.WriteLine("Other relation types not supported yet");
1748
1886
private string EmitLoopRelationCondition(RelationCondition condition, string startAddress)
1803
1941
private string EmitLoopCondition(PerformVerb perform, string startAddress)
1805
1943
//TODO: Replace most of this with a call to EmitCondition
1807
1945
if (perform.Varying!=null)
1809
1947
if (perform.Varying.Condition.GetType() == typeof(RelationCondition))
1811
RelationCondition condition = perform.Varying.Condition as RelationCondition;
1812
r+=EmitLoopRelationCondition(condition, startAddress);
1949
RelationCondition condition = perform.Varying.Condition as RelationCondition;
1951
r+=EmitLoopRelationCondition(condition, startAddress);
1953
catch(BasisException be)
1955
r+=EmitLoopStringComparisonCondition(condition, startAddress);
1828
RelationCondition condition = perform.Until as RelationCondition;
1829
r+=EmitLoopRelationCondition(condition, startAddress);
1972
RelationCondition condition = perform.Until as RelationCondition;
1974
r+=EmitLoopRelationCondition(condition, startAddress);
1976
catch(BasisException be)
1978
r+=EmitLoopStringComparisonCondition(condition, startAddress);
1901
2051
private string EmitLiteral(Literal literal)
1903
2053
return EmitLiteral(literal,false);
1906
2056
private string EmitBasis(Basis basis)
1908
2058
//TODO: Variable Types
1909
2059
//( identifier | literal | "(" arithmetic-expression ")" ) .
1911
2061
if (basis.Source != null)
1913
2063
if (basis.Source.GetType() == typeof(Literal))
1915
2065
Literal literal = basis.Source as Literal;
1918
2068
else if (basis.Source.GetType() == typeof(Identifier))
1920
Identifier id = basis.Source as Identifier;
2070
Identifier id = basis.Source as Identifier;
2071
if (id.Definition.Type == DataType.String)
2073
throw new BasisException();
1921
2075
r += EmitIdentifier(id);