~sandy-dunlop/wildcatcobol/dev

« back to all changes in this revision

Viewing changes to src/Wildcat.Cobol.Compiler/ILGenerator/ILGenerator.cs

  • Committer: Sandy Dunlop
  • Date: 2007-10-14 16:14:53 UTC
  • mfrom: (7.1.5 filewrite)
  • Revision ID: sandy.dunlop@gmail.com-20071014161453-otgf2yviplpqbviq
Merging from filewrite branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
366
366
                                        data.IsArray = true;
367
367
                                        r+="    .field public valuetype _" + ILIdentifier(data.Name) + "[] " + ILIdentifier(data.Name) + "\n";
368
368
                                    }else{
369
 
                                        r+="    .field public " + ILType(data.Type) + " " + ILIdentifier(data.Name) + "\n";
 
369
                                        r+="    .field public " + ILType(data.Type) + " " + ILIdentifier(data.Name) + "\n";
 
370
                                        if (data.IsGroup){
 
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";
 
373
                                        }
370
374
                                    }
371
375
                                }
372
376
                                else
873
877
        {
874
878
            string r = "";
875
879
            //TODO: Implement"corresponding"
876
 
            //TODO: Implement "MOVE SPACES..."
877
 
            if (move.From.IsSpaces)
878
 
            {
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))
 
882
            {
 
883
                FigurativeConstant constant = move.From as FigurativeConstant;
 
884
                if (constant.Type == FigurativeConstantType.Spaces)
883
885
                {
884
 
                    int size = toIdentifier.Definition.Size;
885
 
                    //Console.WriteLine("MOVE SPACES TO variable of size "+size);
886
 
                    r += "        ";
887
 
                    r += ILAddress(1) + "ldarg.0"; //Hidden pointer to 'this'
888
 
                    r += "\n";
889
 
                    Literal literal = new Literal();
890
 
                    literal.Type = VariableType.String;
891
 
                    literal.Value = "";
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)
893
890
                    {
894
 
                        literal.Value += " ";
895
 
                    }
896
 
                    r += EmitLiteral(literal);
897
 
                    r += EmitStore(toIdentifier); //TODO: This needs changed for subscripts
898
 
                }
 
891
                        int size = toIdentifier.Definition.Size;
 
892
                        //Console.WriteLine("MOVE SPACES TO variable of size "+size);
 
893
                        r += "        ";
 
894
                        r += ILAddress(1) + "ldarg.0"; //Hidden pointer to 'this'
 
895
                        r += "\n";
 
896
                        Literal literal = new Literal();
 
897
                        literal.Type = VariableType.String;
 
898
                        literal.Value = "";
 
899
                        for (int i = 0; i < size; i++)
 
900
                        {
 
901
                            literal.Value += " ";
 
902
                        }
 
903
                        r += EmitLiteral(literal);
 
904
                        r += EmitStore(toIdentifier); //TODO: This needs changed for subscripts
 
905
                        if (IsGroup(toIdentifier))
 
906
                        {
 
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";
 
910
                        }
 
911
                    }
 
912
                }else{
 
913
                    Console.WriteLine("TODO: Other figurative constants not supported yet");
 
914
                }
899
915
            }
900
916
            else
901
917
            {
1073
1089
                else if(identifier.Definition.IsHighValues)
1074
1090
                {
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";
1135
1152
                                {
1136
1153
                                        r+="\n";
1137
1154
                                        
 
1155
                                        //Load p
 
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);
 
1161
                                    r += "ldloc.1\n";
 
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
 
1166
 
 
1167
                                        string r2="";
 
1168
                                        
 
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";
 
1173
                                        
1138
1174
                                        //Pointer to this...
1139
 
                                        r += "        " + ILAddress(1);
1140
 
                                    r += "ldarg.0\n";
 
1175
                                        r2 += "        " + ILAddress(1);
 
1176
                                    r2 += "ldarg.0\n";
1141
1177
                                                        
1142
1178
                                        //Load the string...
1143
 
                                        r += "        " + ILAddress(1);
1144
 
                                    r += "ldloc.1\n";
 
1179
                                        r2 += "        " + ILAddress(1);
 
1180
                                    r2 += "ldloc.1\n";
1145
1181
                                    
1146
1182
                                    //Take a substring out of it (based on DDE's size)...
1147
1183
                                    // ldc.i4.n
1148
 
                                    r+= "        " + ILAddress(5);
1149
 
                                    r+= "ldc.i4 "+p+"\n";
 
1184
                                    r2+= "        " + ILAddress(5);
 
1185
                                    r2+= "ldc.i4 "+p+"\n";
1150
1186
                                    // ldc.i4.n
1151
 
                                    r+= "        " + ILAddress(5);
 
1187
                                    r2+= "        " + ILAddress(5);
1152
1188
                                    
1153
1189
                                    if (dd.Size==0)
1154
1190
                                    {
1157
1193
                                        //or skip to next element of the group
1158
1194
                                    }
1159
1195
                                    
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";
1164
1200
                                    
1165
1201
                                    p+=dd.Size;
1166
1202
                                    
1168
1204
                                    //      e.g. Integer
1169
1205
                                    if (dd.Type == DataType.Integer)
1170
1206
                                    {
1171
 
                                            r+= "        " + ILAddress(5);
1172
 
                                        r+="call int32 int32::Parse(string)\n";
 
1207
                                            r2+= "        " + ILAddress(5);
 
1208
                                        r2+="call int32 int32::Parse(string)\n";
1173
1209
                                    }
1174
1210
                                    
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);
 
1216
                                    
 
1217
                                    //Skips to here if p>=length of string
 
1218
                                    r+=ILAddress()+" //<-------- \n";
 
1219
                                    r+=r2;
1180
1220
                                }else{
1181
1221
                                    Identifier elem = new Identifier();
1182
1222
                                    elem.Definition = dd;
1279
1319
 
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";
1283
1323
 
1284
1324
                        //Store result:
1285
1325
                        //  IL_0016:  stfld string WorkingStorageTest.Program::bb1
1386
1426
            {
1387
1427
                a = "a";
1388
1428
            }
1389
 
//            if (id.Definition.IsGroup)
1390
 
//            {
1391
 
//              Console.WriteLine("EmitLoadField Groups/Records not supported yet");
1392
 
//            }else{
 
1429
            if (id.Definition.IsGroup && !id.Definition.IsAnonymous)
 
1430
            {
 
1431
                //TODO: Make this work
 
1432
                //Console.WriteLine("EmitLoadField Groups/Records not supported yet");
 
1433
                        
 
1434
                r += "        " + ILAddress(1) + "pop\n";
 
1435
                
 
1436
                //Build the format string...
 
1437
                        List<DataDescription> ddes = ListElements(id.Definition);
 
1438
                        int obj = 0;
 
1439
                        string fmt = "";
 
1440
                        foreach (DataDescription dd in ddes)
 
1441
                        {
 
1442
                        fmt += "{" + obj + ",-" + dd.Size + "}";
 
1443
                            obj++;
 
1444
                        }
 
1445
                        //Load the format string...
 
1446
                r += "        " + ILAddress(5);
 
1447
                r += "ldstr \"" + fmt + "\"\n";
 
1448
                        Console.WriteLine("fmt = "+fmt);
 
1449
                
 
1450
                //Create an array
 
1451
                r += "        " + ILAddress(5);
 
1452
                r += "ldc.i4 " + ddes.Count + "\n";
 
1453
                r += "        " + ILAddress(5);
 
1454
                r += "newarr [mscorlib]System.Object\n";
 
1455
    
 
1456
                //Load elements into array
 
1457
                        obj = 0;
 
1458
                        foreach (DataDescription dd in ddes)
 
1459
                        {
 
1460
                                Identifier tmp = new Identifier();
 
1461
                                tmp.Name = dd.Name;
 
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";
 
1467
                    obj++;                          
 
1468
                        }
 
1469
                    r += "        " + ILAddress(5) + "call string string::Format(string,object[])\n";
 
1470
            }else{
1393
1471
                    string typ = null;
1394
1472
                    try{
1395
1473
                            if (id.Definition.IsClass)
1419
1497
                            r += "box [mscorlib]System.Int32\n";
1420
1498
                        }
1421
1499
                    }
1422
 
            //}
 
1500
            }
1423
1501
            return r;
1424
1502
        }
1425
1503
 
1744
1822
                        
1745
1823
                return r;
1746
1824
        }
1747
 
        
 
1825
        
 
1826
        private string EmitLoopStringComparisonCondition(RelationCondition condition, string startAddress)
 
1827
        {
 
1828
                string r = "";
 
1829
 
 
1830
            Source left = condition.LeftExpression.TimesDiv.Power.Basis.Source;
 
1831
            Source right = condition.RightExpression.TimesDiv.Power.Basis.Source;
 
1832
            
 
1833
            if (left.GetType() == typeof(FigurativeConstant) ||
 
1834
                right.GetType() == typeof(FigurativeConstant))
 
1835
            {
 
1836
                //Work out which side is the figurative constant...
 
1837
                Source other;
 
1838
                FigurativeConstant constant;
 
1839
                if (left.GetType() == typeof(FigurativeConstant)){
 
1840
                    constant = left as FigurativeConstant;
 
1841
                    other = right;
 
1842
                }else{
 
1843
                    constant = right as FigurativeConstant;
 
1844
                    other = left;
 
1845
                }
 
1846
                
 
1847
                if (constant.Type == FigurativeConstantType.Spaces)
 
1848
                {
 
1849
                    Identifier id = other as Identifier;
 
1850
                    if (id == null){
 
1851
                        Console.WriteLine("Identifier expected when comparing to figurative constant");
 
1852
                    }
 
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";
 
1856
                }else{
 
1857
                    Console.WriteLine("Other figurative constants not supported yet");
 
1858
                }
 
1859
            }
 
1860
            else
 
1861
            {
 
1862
                r += EmitLoadSource(left, false, false);
 
1863
                r += EmitLoadSource(right, false, false);
 
1864
                if (condition.RelationalOperator.Relation == RelationType.EqualTo)
 
1865
                {
 
1866
                    //Stop looping when left = right
 
1867
                    r += "        " + ILAddress(2);
 
1868
                    r += "ceq\n";
 
1869
                    r += "        " + ILAddress(1);
 
1870
                    r += "ldc.i4.0\n";
 
1871
                    r += "        " + ILAddress(2);
 
1872
                    r += "ceq\n";
 
1873
                    r += "        " + ILAddress(1);
 
1874
                    r += "stloc.0\n";
 
1875
                    r += "        " + ILAddress(1);
 
1876
                    r += "ldloc.0\n";
 
1877
                    r += "        " + ILAddress(5);
 
1878
                    r += "brtrue " + startAddress + "\n";
 
1879
                }else{
 
1880
                    Console.WriteLine("Other relation types not supported yet");
 
1881
                }
 
1882
            }
 
1883
            return r;
 
1884
        }
 
1885
        
1748
1886
        private string EmitLoopRelationCondition(RelationCondition condition, string startAddress)
1749
1887
        {
1750
1888
                string r = "";
1803
1941
        private string EmitLoopCondition(PerformVerb perform, string startAddress)
1804
1942
        {
1805
1943
            //TODO: Replace most of this with a call to EmitCondition
1806
 
            string r = "";
 
1944
            string r = "";
1807
1945
            if (perform.Varying!=null)
1808
1946
            {
1809
1947
                    if (perform.Varying.Condition.GetType() == typeof(RelationCondition))
1810
1948
                    {
1811
 
                        RelationCondition condition = perform.Varying.Condition as RelationCondition;
1812
 
                        r+=EmitLoopRelationCondition(condition, startAddress);
1813
 
                    }
 
1949
                        RelationCondition condition = perform.Varying.Condition as RelationCondition;
 
1950
                        try{
 
1951
                            r+=EmitLoopRelationCondition(condition, startAddress);
 
1952
                        }
 
1953
                        catch(BasisException be)
 
1954
                        {
 
1955
                            r+=EmitLoopStringComparisonCondition(condition, startAddress);
 
1956
                        }
 
1957
                    }
1814
1958
                    else
1815
1959
                    {
1816
1960
                        //TODO:
1825
1969
                        }
1826
1970
                        else
1827
1971
                        {
1828
 
                                RelationCondition condition = perform.Until as RelationCondition;
1829
 
                            r+=EmitLoopRelationCondition(condition, startAddress);
 
1972
                                RelationCondition condition = perform.Until as RelationCondition;
 
1973
                                try{
 
1974
                                r+=EmitLoopRelationCondition(condition, startAddress);
 
1975
                                }
 
1976
                                catch(BasisException be)
 
1977
                                {
 
1978
                        r+=EmitLoopStringComparisonCondition(condition, startAddress);
 
1979
                                }
1830
1980
                        }
1831
1981
                }
1832
1982
                else
1901
2051
        private string EmitLiteral(Literal literal)
1902
2052
        {
1903
2053
                return EmitLiteral(literal,false);
1904
 
        }
1905
 
 
 
2054
        }
 
2055
        
1906
2056
        private string EmitBasis(Basis basis)
1907
2057
        {
1908
2058
            //TODO: Variable Types
1909
2059
            //( identifier | literal | "(" arithmetic-expression ")" ) .
1910
2060
            string r = "";
1911
2061
            if (basis.Source != null)
1912
 
            {
 
2062
            {
1913
2063
                if (basis.Source.GetType() == typeof(Literal))
1914
2064
                {
1915
2065
                    Literal literal = basis.Source as Literal;
1917
2067
                }
1918
2068
                else if (basis.Source.GetType() == typeof(Identifier))
1919
2069
                {
1920
 
                    Identifier id = basis.Source as Identifier;
 
2070
                    Identifier id = basis.Source as Identifier;
 
2071
                    if (id.Definition.Type == DataType.String)
 
2072
                    {
 
2073
                        throw new BasisException();
 
2074
                    }
1921
2075
                    r += EmitIdentifier(id);
1922
2076
                }
1923
2077
                else