Thread: [csdoc-patches] csdoc/src/mcs OTODO,NONE,1.1 README,NONE,1.1 compiler.csproj,NONE,1.1 mcs.exe.source
Status: Planning
Brought to you by:
mastergaurav
Update of /cvsroot/csdoc/csdoc/src/mcs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25921 Modified Files: .cvsignore AssemblyInfo.cs ChangeLog TODO assign.cs attribute.cs cfold.cs class.cs codegen.cs compiler.sln const.cs constant.cs convert.cs cs-parser.jay cs-tokenizer.cs decl.cs delegate.cs driver.cs ecore.cs enum.cs expression.cs flowanalysis.cs gen-treedump.cs iterators.cs literal.cs location.cs makefile mcs.exe.config modifiers.cs namespace.cs parameter.cs pending.cs report.cs rootcontext.cs statement.cs support.cs symbolwriter.cs tree.cs typemanager.cs Added Files: OTODO README compiler.csproj mcs.exe.sources Log Message: 2004-10-06 Gaurav Vaish <mastergaurav@> * Latest from Mono mcs --- NEW FILE: OTODO --- ---- This is a list of old tasks, just here for historical value ---- Open question: Create a toplevel block for anonymous methods? Anonymous Methods ----------------- Plan: * Resolve anonymous methods before. * Each time a Local matches, if the mode is `InAnonymous', flag the VariableInfo for `proxying'. * During Resolve track the depth required for local variables. * Before Emit, create proxy classes with proper depth. * Emit. Notes on memory allocation -------------------------- Outdated: A run of the AllocationProfile shows that the compiler allocates roughly 30 megabytes of strings. From those, 20 megabytes come from LookupType. See the notes on current_container problems below on memory usage. LookupTypeReflection: --------------------- With something like `System.Object', LookupTypeReflection will be called twice: once to find out that `System' is not a type and once for System.Object. This is required because System.Reflection requires that the type/nested types are not separated by a dot but by a plus sign. A nested class would be My+Class (My being the toplevel, Class the nested one). It is interesting to look at the most called lookups when bootstrapping MCS: 647 LTR: ArrayList 713 LTR: System.Globalization 822 LTR: System.Object+Expression 904 LTR: Mono.CSharp.ArrayList 976 LTR: System.Runtime.CompilerServices 999 LTR: Type 1118 LTR: System.Runtime 1208 LTR: Mono.CSharp.Type 1373 LTR: Mono.Languages 1599 LTR: System.Diagnostics 2036 LTR: System.Text 2302 LTR: System.Reflection.Emit 2515 LTR: System.Collections 4527 LTR: System.Reflection 22273 LTR: Mono.CSharp 24245 LTR: System 27005 LTR: Mono Analysis: The top 9 lookups are done for things which are not types. Mono.CSharp.Type happens to be a common lookup: the class Type used heavily in the compiler in the default namespace. RED FLAG: Then `Type' is looked up alone a lot of the time, this happens in parameter declarations and am not entirely sure that this is correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName, which for some reason is null!). This seems to be a problem with a lost piece of context during FindType. System.Object is also used a lot as a toplevel class, and we assume it will have children, we should just shortcut this. A cache: Adding a cache and adding a catch for `System.Object' to flag that it wont be the root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds. This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs. Memory consumption went down from 74 megs to 65 megs with this change. Major tasks: ------------ Pinned and volatile require type modifiers that can not be encoded with Reflection.Emit. * Revisit Primary-expression, as it has now been split into non-array-creation-expression and array-creation-expression. * Emit `pinned' for pinned local variables. Both `modreq' and pinned will require special hacks in the compiler. * Make sure that we are pinning the right variable * local_variable_declaration Not sure that this grammar is correct, we might have to resolve this during semantic analysis. * Optimizations In Indexers and Properties, probably support an EmitWithDup That emits the code to call Get and then leaves a this pointer in the stack, so that later a Store can be emitted using that this pointer (consider Property++ or Indexer++) * Use of local temporary in UnaryMutator We should get rid of the Localtemporary there for some cases This turns out to be very complex, at least for the post-version, because this case: a = i++ To produce optimal code, it is necessary for UnaryMutator to know that it is being assigned to a variable (the way the stack is laid out using dup requires the store to happen inside UnaryMutator). * Interface indexers I have not figured out why the Microsoft version puts an `instance' attribute, and I am not generating this `instance' attribute. Explanation: The reason for the `instance' attribute on indexers is that indexers only apply to instances * Check for Final when overriding, if the parent is Final, then we cant allow an override. Implement base indexer access. current_container/current_namespace and the DeclSpace ----------------------------------------------------- We are storing fully qualified names in the DeclSpace instead of the node, this is because `current_namespace' (Namepsace) is not a DeclSpace like `current_container'. The reason for storing the full names today is this: namespace X { class Y { } } namespace A { class Y { } } The problem is that we only use the namespace stack to track the "prefix" for typecontainers, but they are not typecontainers themselves, so we have to use fully qualified names, because both A.X and A.Y would be entered in the toplevel type container. If we use the short names, there would be a name clash. To fix this problem, we have to make namespaces DeclSpaces. The full size, contrasted with the size that could be stored is: corlib: Size of strings held: 368901 Size of strings short: 147863 System: Size of strings held: 212677 Size of strings short: 97521 System.XML: Size of strings held: 128055 Size of strings short: 35782 System.Data: Size of strings held: 117896 Size of strings short: 36153 System.Web: Size of strings held: 194527 Size of strings short: 58064 System.Windows.Forms: Size of strings held: 220495 Size of strings short: 64923 The use of DottedName --------------------- We could probably use a different system to represent names, like this: class Name { string simplename; Name parent; } So `System.ComponentModel' becomes: x: (System, null) y: (ComponentModel, x) The problem is that we would still need to construct the name to pass to GetType. This has been now implemented, its called "QualifiedIdentifier" TODO: 1. Create a "partial" emit context for each TypeContainer.. 2. EmitContext should be partially constructed. No IL Generator. interface_type review. parameter_array, line 952: `note: must be a single dimension array type'. Validate this Instance idea ------------- It would be nice to have things that can be "instances" to have an EmitInstance method (this would default to nothing). The idea is to be able to use efficiently the instance data on stack manipulations, as opposed to the current scheme, where we basically have a few special cases. * `yield' is no longer a keyword, it only has special meaning before a return or break keywords. * Study side effects with assign * Study TemporaryStorage/LocalStorage -> Merge/rename --- NEW FILE: README --- These are the sources to the Mono C# compiler --------------------------------------------- Read the mcs/docs/compiler.txt for an overview of the compiler. Testing the Compiler -------------------- You might want to use the `make btest' in this directory to have the compiler bootstrap itself, this is the basic regression test. Before commiting changes to MCS, make sure that all the tests in `mcs/tests' pass, and all the tests in 'mcs/errors' have the expected result, type: cd mcs # The top-level 'mcs' directory make compiler-tests If you want to test the installed compiler, you can run: cd mcs # The top-level 'mcs' directory make test-installed-compiler Full Bootstrap ============== To finally ensure the state of the compiler, it is ideal to do a full bootstrap, to do this, do: cd mcs make clean; make make install That installs the compiler and assemblies compiled by the new compiler. Then, repeat that step again: make clean make If things work, the compiler has not added a new regression while building the mscorlib and the compiler itself. Tests ===== When bugs are fixed, new tests must be added to the `mcs/tests' directory to excercise the problem and to guarantee that we keep the compiler in a good state. When an error is reported, it should be added to mcs/errors. We try to make the errors numbers be the same as the ones in Microsoft C#, if this is not possible, allocate a negative error number, and list it in mcs/errors/errors.txt --- NEW FILE: compiler.csproj --- <VisualStudioProject> <CSHARP ProjectType = "Local" ProductVersion = "7.10.3077" SchemaVersion = "2.0" ProjectGuid = "{896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}" > <Build> <Settings ApplicationIcon = "" AssemblyKeyContainerName = "" AssemblyName = "mcs" AssemblyOriginatorKeyFile = "" DefaultClientScript = "JScript" DefaultHTMLPageLayout = "Grid" DefaultTargetSchema = "IE50" DelaySign = "false" OutputType = "Exe" PreBuildEvent = "" PostBuildEvent = "" RootNamespace = "CIR" RunPostBuildEvent = "OnBuildSuccess" StartupObject = "" > <Config Name = "Debug" AllowUnsafeBlocks = "false" BaseAddress = "285212672" CheckForOverflowUnderflow = "false" ConfigurationOverrideFile = "" DefineConstants = "DEBUG;TRACE" DocumentationFile = "" DebugSymbols = "true" FileAlignment = "4096" IncrementalBuild = "false" NoStdLib = "false" NoWarn = "" Optimize = "false" OutputPath = ".\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "4" /> <Config Name = "Release" AllowUnsafeBlocks = "false" BaseAddress = "285212672" CheckForOverflowUnderflow = "false" ConfigurationOverrideFile = "" DefineConstants = "TRACE" DocumentationFile = "" DebugSymbols = "false" FileAlignment = "4096" IncrementalBuild = "true" NoStdLib = "false" NoWarn = "" Optimize = "true" OutputPath = "bin\Release\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "4" /> </Settings> <References> <Reference Name = "System" AssemblyName = "System" /> </References> </Build> <Files> <Include> <File RelPath = "anonymous.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "AssemblyInfo.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "assign.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "attribute.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "cfold.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "class.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "codegen.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "const.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "constant.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "convert.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CryptoConvert.cs" Link = "..\class\corlib\Mono.Security.Cryptography\CryptoConvert.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "cs-parser.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "cs-tokenizer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "decl.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "delegate.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "driver.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "ecore.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "enum.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "expression.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "flowanalysis.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "iterators.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "literal.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "location.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "modifiers.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "MonoSymbolFile.cs" Link = "..\class\Mono.CSharp.Debugger\MonoSymbolFile.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "MonoSymbolTable.cs" Link = "..\class\Mono.CSharp.Debugger\MonoSymbolTable.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "MonoSymbolWriter.cs" Link = "..\class\Mono.CSharp.Debugger\MonoSymbolWriter.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "namespace.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "parameter.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "pending.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "report.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "rootcontext.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "statement.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "support.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "symbolwriter.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "tree.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "typemanager.cs" SubType = "Code" BuildAction = "Compile" /> <Folder RelPath = "Web References\" WebReferences = "TRUE" /> </Include> </Files> </CSHARP> </VisualStudioProject> --- NEW FILE: mcs.exe.sources --- AssemblyInfo.cs anonymous.cs assign.cs attribute.cs driver.cs cs-tokenizer.cs cfold.cs class.cs codegen.cs const.cs constant.cs convert.cs decl.cs delegate.cs enum.cs ecore.cs expression.cs flowanalysis.cs iterators.cs literal.cs location.cs modifiers.cs namespace.cs parameter.cs pending.cs report.cs rootcontext.cs statement.cs support.cs typemanager.cs symbolwriter.cs tree.cs ../class/Mono.CSharp.Debugger/MonoSymbolFile.cs ../class/Mono.CSharp.Debugger/MonoSymbolTable.cs ../class/Mono.CSharp.Debugger/MonoSymbolWriter.cs ../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs Index: .cvsignore =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/.cvsignore,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** .cvsignore 16 Sep 2003 13:00:19 -0000 1.2 --- .cvsignore 6 Oct 2004 13:46:43 -0000 1.3 *************** *** 1,15 **** ! compiler.pdb ! compiler.exe ! compiler.suo ! compiler.csproj ! compiler.csproj.user ! cs-parser.cs ! y.output *.pdb - mcs.exe - mcsdoc.exe Web References - bin - obj Web References Web References --- 1,16 ---- ! *.mdb *.pdb Web References Web References Web References + bin + compiler.csproj + compiler.csproj.user + compiler.exe + compiler.pdb + compiler.suo + cs-parser.cs + mcs + obj + semantic.cache + y.output Index: AssemblyInfo.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/AssemblyInfo.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** AssemblyInfo.cs 16 Sep 2003 13:00:19 -0000 1.2 --- AssemblyInfo.cs 6 Oct 2004 13:46:43 -0000 1.3 *************** *** 2,6 **** using System.Runtime.CompilerServices; ! [assembly: AssemblyVersion("0.27")] [assembly: AssemblyTitle ("Mono C# Compiler")] [assembly: AssemblyDescription ("Mono C# Compiler")] --- 2,6 ---- using System.Runtime.CompilerServices; ! [assembly: AssemblyVersion("1.1.1")] [assembly: AssemblyTitle ("Mono C# Compiler")] [assembly: AssemblyDescription ("Mono C# Compiler")] Index: ChangeLog =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/ChangeLog,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ChangeLog 16 Sep 2003 13:00:20 -0000 1.2 --- ChangeLog 6 Oct 2004 13:46:43 -0000 1.3 *************** *** 1,2 **** --- 1,4158 ---- + 2004-10-04 Miguel de Icaza <mi...@xi...> + + * ecore.cs (Expression.Constantity): Add support for turning null + into a constant. + + * const.cs (Const.Define): Allow constants to be reference types + as long as the value is Null. + + 2004-10-04 Juraj Skripsky <js...@ho...> [...7025 lines suppressed...] --- 16561,16565 ---- enum_body or enum_member_declarations so we can handle trailing commas on enumeration members. Gets rid of a shift/reduce. ! (type_list): Need a COMMA in the middle. *************** *** 12418,12422 **** * cs-parser.jay: Add precendence rules for a number of operators ot reduce the number of shift/reduce conflicts in the grammar. ! 2001-07-17 Miguel de Icaza <mi...@xi...> --- 16574,16578 ---- * cs-parser.jay: Add precendence rules for a number of operators ot reduce the number of shift/reduce conflicts in the grammar. ! 2001-07-17 Miguel de Icaza <mi...@xi...> Index: TODO =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/TODO,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** TODO 16 Sep 2003 13:00:22 -0000 1.2 --- TODO 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 1,20 **** ! Iterators --------- ! * Fix simple case (foreach) ! * Study side effects with assign ! * Study TemporaryStorage/LocalStorage -> Merge/rename ! Big issues: try/finally in iterators. ! Instance idea ! ------------- ! It would be nice to have things that can be "instances" to have an ! EmitInstance method (this would default to nothing). ! The idea is to be able to use efficiently the instance data on stack ! manipulations, as opposed to the current scheme, where we basically have ! a few special cases. Optimization ideas --- 1,51 ---- ! NEW NOTES: ! ---------- ! ! ImplicitStandardConversionExists and ImplicitStandardConversion ! should always be the same, but there are a few diverging lines that ! must be studied: ! ! if (expr_type == target_type && !(expr is NullLiteral)) ! return expr; ! ! vs: ! ! if (expr_type == target_type) ! return true; ! ! ! Null Type --------- ! Need to introduce the NullType concept into the compiler, to address a ! few small buglets and remove the hardcoded values for NullLiteral. ! NullLiteral will be the only expression that has the NullType as its type. ! This is what must be used to test for Null literals, instead of `is NullLiteral', ! and this will introduce a couple of fixes to the rules. ! Revert Martin's patch to Conditional expression that worked around this bug: ! Reference r = xx ? null : null ! ! The right fix is to introduce NullType ! ! **************************************************************************************** ! * ! * The information on the rest of this file is mostly outdated, and its kept here for ! * historical reasons ! * ! **************************************************************************************** ! ! Error Reporting: ! ---------------- ! ! * Make yyerror show a nice syntax error, instead of the current mess. ! ! Iterators ! --------- ! ! * Reset should throw not implemented now. Optimization ideas *************** *** 43,66 **** - Anonymous Methods - ----------------- - - Plan: - - * Resolve anonymous methods before. - * Each time a Local matches, if the mode is `InAnonymous', flag - the VariableInfo for `proxying'. - * During Resolve track the depth required for local variables. - * Before Emit, create proxy classes with proper depth. - * Emit. - - Return Type: - During Resolve, track all the return types. - Allow for ec.ReturnType to be null, indicating `Pending Return Evaluation' - - - Open question: - Create a toplevel block for anonymous methods? - EmitContext.ResolveTypeTree --------------------------- --- 74,77 ---- *************** *** 101,170 **** that we could use for this. - Notes on memory allocation - -------------------------- - - A run of the AllocationProfile shows that the compiler allocates roughly - 30 megabytes of strings. From those, 20 megabytes come from - LookupType. - - See the notes on current_container problems below on memory usage. - - LookupTypeReflection: - --------------------- - - With something like `System.Object', LookupTypeReflection will be called - twice: once to find out that `System' is not a type and once - for System.Object. - - This is required because System.Reflection requires that the type/nested types are - not separated by a dot but by a plus sign. - - A nested class would be My+Class (My being the toplevel, Class the nested one). - - It is interesting to look at the most called lookups when bootstrapping MCS: - - 647 LTR: ArrayList - 713 LTR: System.Globalization - 822 LTR: System.Object+Expression - 904 LTR: Mono.CSharp.ArrayList - 976 LTR: System.Runtime.CompilerServices - 999 LTR: Type - 1118 LTR: System.Runtime - 1208 LTR: Mono.CSharp.Type - 1373 LTR: Mono.Languages - 1599 LTR: System.Diagnostics - 2036 LTR: System.Text - 2302 LTR: System.Reflection.Emit - 2515 LTR: System.Collections - 4527 LTR: System.Reflection - 22273 LTR: Mono.CSharp - 24245 LTR: System - 27005 LTR: Mono - - Analysis: - The top 9 lookups are done for things which are not types. - - Mono.CSharp.Type happens to be a common lookup: the class Type - used heavily in the compiler in the default namespace. - - RED FLAG: - - Then `Type' is looked up alone a lot of the time, this happens - in parameter declarations and am not entirely sure that this is - correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName, - which for some reason is null!). This seems to be a problem with a lost - piece of context during FindType. - - System.Object is also used a lot as a toplevel class, and we assume it will - have children, we should just shortcut this. - - A cache: - - Adding a cache and adding a catch for `System.Object' to flag that it wont be the - root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds. - - This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs. Memory consumption - went down from 74 megs to 65 megs with this change. - Ideas: ------ --- 112,115 ---- *************** *** 173,257 **** we should just make it simple for a probe to know that there is no need for it. - The use of DottedName - --------------------- - - We could probably use a different system to represent names, like this: - - class Name { - string simplename; - Name parent; - } - - So `System.ComponentModel' becomes: - - x: (System, null) - y: (ComponentModel, x) - - The problem is that we would still need to construct the name to pass to - GetType. - - current_container/current_namespace and the DeclSpace - ----------------------------------------------------- - - We are storing fully qualified names in the DeclSpace instead of the node, - this is because `current_namespace' (Namepsace) is not a DeclSpace like - `current_container'. - - The reason for storing the full names today is this: - - namespace X { - class Y { - } - } - - namespace A { - class Y { - } - } - - The problem is that we only use the namespace stack to track the "prefix" - for typecontainers, but they are not typecontainers themselves, so we have - to use fully qualified names, because both A.X and A.Y would be entered - in the toplevel type container. If we use the short names, there would be - a name clash. - - To fix this problem, we have to make namespaces DeclSpaces. - - The full size, contrasted with the size that could be stored is: - corlib: - Size of strings held: 368901 - Size of strings short: 147863 - - System: - Size of strings held: 212677 - Size of strings short: 97521 - - System.XML: - Size of strings held: 128055 - Size of strings short: 35782 - - System.Data: - Size of strings held: 117896 - Size of strings short: 36153 - - System.Web: - Size of strings held: 194527 - Size of strings short: 58064 - - System.Windows.Forms: - Size of strings held: 220495 - Size of strings short: 64923 - - - TODO: - - 1. Create a "partial" emit context for each TypeContainer.. - - 2. EmitContext should be partially constructed. No IL Generator. - - interface_type review. - - parameter_array, line 952: `note: must be a single dimension array type'. Validate this - Dead Code Elimination bugs: --------------------------- --- 118,121 ---- *************** *** 261,272 **** Major tasks: ------------ - - Pinned and volatile require type modifiers that can not be encoded - with Reflection.Emit. - Properties and 17.6.3: Finish it. - Implement base indexer access. - readonly variables and ref/out --- 125,130 ---- *************** *** 274,288 **** ---- - * Check for Final when overriding, if the parent is Final, then we cant - allow an override. - - * Interface indexers - - I have not figured out why the Microsoft version puts an - `instance' attribute, and I am not generating this `instance' attribute. - - Explanation: The reason for the `instance' attribute on - indexers is that indexers only apply to instances - * Break/Continue statements --- 132,135 ---- *************** *** 316,324 **** * Merge test 89 and test-34 - * Revisit - - Primary-expression, as it has now been split into - non-array-creation-expression and array-creation-expression. - * Code cleanup --- 163,166 ---- *************** *** 330,339 **** Handle modreq from public apis. - * Emit `pinned' for pinned local variables. - - Both `modreq' and pinned will require special hacks in the compiler. - - * Make sure that we are pinning the right variable - * Merge tree.cs, rootcontext.cs --- 172,175 ---- *************** *** 359,375 **** is on TypeContainer, and probably should go in DeclSpace. - * Use of local temporary in UnaryMutator - - We should get rid of the Localtemporary there for some cases - - This turns out to be very complex, at least for the post-version, - because this case: - - a = i++ - - To produce optimal code, it is necessary for UnaryMutator to know - that it is being assigned to a variable (the way the stack is laid - out using dup requires the store to happen inside UnaryMutator). - * Tests --- 195,198 ---- *************** *** 377,387 **** test for all the numeric conversions. - * Optimizations - - In Indexers and Properties, probably support an EmitWithDup - That emits the code to call Get and then leaves a this pointer - in the stack, so that later a Store can be emitted using that - this pointer (consider Property++ or Indexer++) - * Optimizations: variable allocation. --- 200,203 ---- *************** *** 422,428 **** { oob_stack.Push (lexer.Location) } takes a "slot" in the productions. - * local_variable_declaration - - Not sure that this grammar is correct, we might have to - resolve this during semantic analysis. --- 238,240 ---- Index: assign.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/assign.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** assign.cs 16 Sep 2003 13:00:22 -0000 1.2 --- assign.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 30,46 **** public interface IAssignMethod { // ! // This method will emit the code for the actual assignment ! // ! void EmitAssign (EmitContext ec, Expression source); ! // ! // This method is invoked before any code generation takes ! // place, and it is a mechanism to inform that the expression ! // will be invoked more than once, and that the method should ! // use temporary values to avoid having side effects // ! // Example: a [ g () ] ++ // ! void CacheTemporaries (EmitContext ec); } --- 30,152 ---- public interface IAssignMethod { // ! // This is an extra version of Emit. If leave_copy is `true' ! // A copy of the expression will be left on the stack at the ! // end of the code generated for EmitAssign // ! void Emit (EmitContext ec, bool leave_copy); ! // ! // This method does the assignment ! // `source' will be stored into the location specified by `this' ! // if `leave_copy' is true, a copy of `source' will be left on the stack ! // if `prepare_for_load' is true, when `source' is emitted, there will ! // be data on the stack that it can use to compuatate its value. This is ! // for expressions like a [f ()] ++, where you can't call `f ()' twice. // ! void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); ! ! /* ! For simple assignments, this interface is very simple, EmitAssign is called with source ! as the source expression and leave_copy and prepare_for_load false. ! ! For compound assignments it gets complicated. ! ! EmitAssign will be called as before, however, prepare_for_load will be ! true. The @source expression will contain an expression ! which calls Emit. So, the calls look like: ! ! this.EmitAssign (ec, source, false, true) -> ! source.Emit (ec); -> ! [...] -> ! this.Emit (ec, false); -> ! end this.Emit (ec, false); -> ! end [...] ! end source.Emit (ec); ! end this.EmitAssign (ec, source, false, true) ! ! ! When prepare_for_load is true, EmitAssign emits a `token' on the stack that ! Emit will use for its state. ! ! Let's take FieldExpr as an example. assume we are emitting f ().y += 1; ! ! Here is the call tree again. This time, each call is annotated with the IL ! it produces: ! ! this.EmitAssign (ec, source, false, true) ! call f ! dup ! ! Binary.Emit () ! this.Emit (ec, false); ! ldfld y ! end this.Emit (ec, false); ! ! IntConstant.Emit () ! ldc.i4.1 ! end IntConstant.Emit ! ! add ! end Binary.Emit () ! ! stfld ! end this.EmitAssign (ec, source, false, true) ! ! Observe two things: ! 1) EmitAssign left a token on the stack. It was the result of f (). ! 2) This token was used by Emit ! ! leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy ! of the expression at that point in evaluation. This is used for pre/post inc/dec ! and for a = x += y. Let's do the above example with leave_copy true in EmitAssign ! ! this.EmitAssign (ec, source, true, true) ! call f ! dup ! ! Binary.Emit () ! this.Emit (ec, false); ! ldfld y ! end this.Emit (ec, false); ! ! IntConstant.Emit () ! ldc.i4.1 ! end IntConstant.Emit ! ! add ! end Binary.Emit () ! ! dup ! stloc temp ! stfld ! ldloc temp ! end this.EmitAssign (ec, source, true, true) ! ! And with it true in Emit ! ! this.EmitAssign (ec, source, false, true) ! call f ! dup ! ! Binary.Emit () ! this.Emit (ec, true); ! ldfld y ! dup ! stloc temp ! end this.Emit (ec, true); ! ! IntConstant.Emit () ! ldc.i4.1 ! end IntConstant.Emit ! ! add ! end Binary.Emit () ! ! stfld ! ldloc temp ! end this.EmitAssign (ec, source, false, true) ! ! Note that these two examples are what happens for ++x and x++, respectively. ! */ } *************** *** 56,77 **** /// basically it creates a local variable, and its emit instruction generates /// code to access this value, return its address or save its value. /// </remarks> public class LocalTemporary : Expression, IMemoryLocation { LocalBuilder builder; ! public LocalTemporary (EmitContext ec, Type t) { type = t; eclass = ExprClass.Value; loc = Location.Null; ! builder = ec.GetTemporaryLocal (t); } - public void Release (EmitContext ec) - { - ec.FreeTemporaryLocal (builder, type); - builder = null; - } - public LocalTemporary (LocalBuilder b, Type t) { --- 162,193 ---- /// basically it creates a local variable, and its emit instruction generates /// code to access this value, return its address or save its value. + /// + /// If `is_address' is true, then the value that we store is the address to the + /// real value, and not the value itself. + /// + /// This is needed for a value type, because otherwise you just end up making a + /// copy of the value on the stack and modifying it. You really need a pointer + /// to the origional value so that you can modify it in that location. This + /// Does not happen with a class because a class is a pointer -- so you always + /// get the indirection. + /// + /// The `is_address' stuff is really just a hack. We need to come up with a better + /// way to handle it. /// </remarks> public class LocalTemporary : Expression, IMemoryLocation { LocalBuilder builder; + bool is_address; ! public LocalTemporary (EmitContext ec, Type t) : this (ec, t, false) {} ! ! public LocalTemporary (EmitContext ec, Type t, bool is_address) { type = t; eclass = ExprClass.Value; loc = Location.Null; ! builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (t): t); ! this.is_address = is_address; } public LocalTemporary (LocalBuilder b, Type t) { *************** *** 81,84 **** --- 197,206 ---- builder = b; } + + public void Release (EmitContext ec) + { + ec.FreeTemporaryLocal (builder, type); + builder = null; + } public override Expression DoResolve (EmitContext ec) *************** *** 89,103 **** public override void Emit (EmitContext ec) { ! ec.ig.Emit (OpCodes.Ldloc, builder); } public void Store (EmitContext ec) { ! ec.ig.Emit (OpCodes.Stloc, builder); } public void AddressOf (EmitContext ec, AddressOp mode) { ! ec.ig.Emit (OpCodes.Ldloca, builder); } } --- 211,247 ---- public override void Emit (EmitContext ec) { ! ILGenerator ig = ec.ig; ! ! ig.Emit (OpCodes.Ldloc, builder); ! // we need to copy from the pointer ! if (is_address) ! LoadFromPtr (ig, type); } + // NB: if you have `is_address' on the stack there must + // be a managed pointer. Otherwise, it is the type from + // the ctor. public void Store (EmitContext ec) { ! ILGenerator ig = ec.ig; ! ig.Emit (OpCodes.Stloc, builder); } public void AddressOf (EmitContext ec, AddressOp mode) { ! // if is_address, than this is just the address anyways, ! // so we just return this. ! ILGenerator ig = ec.ig; ! ! if (is_address) ! ig.Emit (OpCodes.Ldloc, builder); ! else ! ig.Emit (OpCodes.Ldloca, builder); ! } ! ! public bool PointsToAddress { ! get { ! return is_address; ! } } } *************** *** 261,271 **** if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) { ! source.Error_UnexpectedKind ("variable or value"); return null; ! } else if (source is MethodGroupExpr){ ((MethodGroupExpr) source).ReportUsageError (); return null; - } if (target_type == source_type) return this; --- 405,417 ---- if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) { ! source.Error_UnexpectedKind ("variable or value", loc); return null; ! } else if ((RootContext.Version == LanguageVersion.ISO_1) && ! (source is MethodGroupExpr)){ ((MethodGroupExpr) source).ReportUsageError (); return null; + } + if (target_type == source_type) return this; *************** *** 295,308 **** // // 2. and the original right side is implicitly convertible to ! // the type of target_type. // if (Convert.ImplicitStandardConversionExists (a.original_source, target_type)) return this; Convert.Error_CannotImplicitConversion (loc, a.original_source.Type, target_type); return null; } } ! source = Convert.ImplicitConversionRequired (ec, source, target_type, loc); if (source == null) --- 441,462 ---- // // 2. and the original right side is implicitly convertible to ! // the type of target // if (Convert.ImplicitStandardConversionExists (a.original_source, target_type)) return this; + // + // In the spec 2.4 they added: or if type of the target is int + // and the operator is a shift operator... + // + if (source_type == TypeManager.int32_type && + (b.Oper == Binary.Operator.LeftShift || b.Oper == Binary.Operator.RightShift)) + return this; + Convert.Error_CannotImplicitConversion (loc, a.original_source.Type, target_type); return null; } } ! source = Convert.ImplicitConversionRequired (ec, source, target_type, loc); if (source == null) *************** *** 348,352 **** Expression temp_source = (temp != null) ? temp : source; ! ((IAssignMethod) target).EmitAssign (ec, temp_source); return temp_source; } --- 502,506 ---- Expression temp_source = (temp != null) ? temp : source; ! ((IAssignMethod) target).EmitAssign (ec, temp_source, false, false); return temp_source; } *************** *** 370,389 **** return; } - - bool use_temporaries = false; - // - // FIXME! We need a way to "probe" if the process can - // just use `dup' to propagate the result - // IAssignMethod am = (IAssignMethod) target; - - if (this is CompoundAssign){ - am.CacheTemporaries (ec); - use_temporaries = true; - } - - if (!is_statement) - use_temporaries = true; Expression temp_source; --- 524,529 ---- *************** *** 398,422 **** } else temp_source = source; ! ! if (use_temporaries){ ! // ! // Doing this for every path is too expensive ! // I wonder if we can work around this and have a less ! // expensive path ! // ! LocalTemporary tempo; ! ! tempo = new LocalTemporary (ec, source.Type); ! ! temp_source.Emit (ec); ! tempo.Store (ec); ! am.EmitAssign (ec, tempo); ! if (!is_statement) ! tempo.Emit (ec); ! ! tempo.Release (ec); ! } else { ! am.EmitAssign (ec, temp_source); ! } if (embedded != null) { --- 538,543 ---- } else temp_source = source; ! ! am.EmitAssign (ec, temp_source, !is_statement, this is CompoundAssign); if (embedded != null) { Index: attribute.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/attribute.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** attribute.cs 16 Sep 2003 13:00:23 -0000 1.2 --- attribute.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 1,1146 **** ! // ! // attribute.cs: Attribute Handler ! // ! // Author: Ravi Pratap (ra...@xi...) ! // ! // Licensed under the terms of the GNU GPL ! // ! // (C) 2001 Ximian, Inc (http://www.ximian.com) ! // ! // [...2565 lines suppressed...] ! if (excluded != null) ! return excluded == TRUE ? true : false; ! ! ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[]; ! if (attrs.Length == 0) { ! analyzed_method_excluded.Add (mb, FALSE); ! return false; ! } ! ! foreach (ConditionalAttribute a in attrs) { ! if (RootContext.AllDefines.Contains (a.ConditionString)) { ! analyzed_method_excluded.Add (mb, FALSE); ! return false; ! } ! } ! analyzed_method_excluded.Add (mb, TRUE); ! return true; ! } ! } ! } Index: cfold.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/cfold.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** cfold.cs 16 Sep 2003 13:00:23 -0000 1.2 --- cfold.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 60,73 **** --- 60,79 ---- // operand is of type sbyte, short, int or long // + #if WRONG Constant match, other; + #endif if (left is ULongConstant){ + #if WRONG other = right; match = left; + #endif if (!(right is ULongConstant)) right = right.ToULong (loc); } else { + #if WRONG other = left; match = right; + #endif left = left.ToULong (loc); } *************** *** 99,110 **** // converted to type long. // ! Constant match, other; ! if (left is UIntConstant){ other = right; ! match = left; ! } else { other = left; - match = right; - } // Nothing to do. --- 105,113 ---- // converted to type long. // ! Constant other; ! if (left is UIntConstant) other = right; ! else other = left; // Nothing to do. *************** *** 112,119 **** return; ! if (other is SByteConstant || other is ShortConstant || ! other is IntConstant){ left = left.ToLong (loc); right = right.ToLong (loc); } --- 115,135 ---- return; ! IntConstant ic = other as IntConstant; ! if (ic != null){ ! if (ic.Value >= 0){ ! if (left == other) ! left = new UIntConstant ((uint) ic.Value); ! else ! right = new UIntConstant ((uint) ic.Value); ! return; ! } ! } ! ! if (other is SByteConstant || other is ShortConstant || ic != null){ left = left.ToLong (loc); right = right.ToLong (loc); + } else { + left = left.ToUInt (loc); + right = left.ToUInt (loc); } *************** *** 181,185 **** Type result_type = null; bool bool_res; ! // // Enumerator folding --- 197,201 ---- Type result_type = null; bool bool_res; ! // // Enumerator folding *************** *** 955,958 **** --- 971,987 ---- } + if (left is NullLiteral){ + if (right is NullLiteral) + return new BoolConstant (true); + else if (right is StringConstant) + return new BoolConstant ( + ((StringConstant) right).Value == null); + } else if (right is NullLiteral){ + if (left is NullLiteral) + return new BoolConstant (true); + else if (left is StringConstant) + return new BoolConstant ( + ((StringConstant) left).Value == null); + } if (left is StringConstant && right is StringConstant){ return new BoolConstant ( *************** *** 961,965 **** } ! DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); if (left == null || right == null) --- 990,994 ---- } ! DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); if (left == null || right == null) *************** *** 996,999 **** --- 1025,1041 ---- ((BoolConstant) right).Value); } + if (left is NullLiteral){ + if (right is NullLiteral) + return new BoolConstant (false); + else if (right is StringConstant) + return new BoolConstant ( + ((StringConstant) right).Value != null); + } else if (right is NullLiteral){ + if (left is NullLiteral) + return new BoolConstant (false); + else if (left is StringConstant) + return new BoolConstant ( + ((StringConstant) left).Value != null); + } if (left is StringConstant && right is StringConstant){ return new BoolConstant ( Index: class.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/class.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** class.cs 16 Sep 2003 13:00:24 -0000 1.2 --- class.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 4,7 **** --- 4,8 ---- // Authors: Miguel de Icaza (mi...@gn...) // Martin Baulig (ma...@gn...) + // Marek Safar (mar...@se...) // // Licensed under the terms of the GNU GPL *************** *** 35,89 **** using System.Reflection.Emit; using System.Runtime.CompilerServices; [...9884 lines suppressed...] - return false; - - if (!MemberSignatureCompare (m, filter_criteria)) - return false; - - // If only accessible to the defining assembly or - if (prot == MethodAttributes.FamANDAssem || - prot == MethodAttributes.Assembly){ - if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder) - return true; - else - return false; - } - - // Anything else (FamOrAssembly and Public) is fine - return true; - } } } --- 7107,7110 ---- Index: codegen.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/codegen.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** codegen.cs 16 Sep 2003 13:00:24 -0000 1.2 --- codegen.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 13,16 **** --- 13,20 ---- using System.Reflection; using System.Reflection.Emit; + using System.Runtime.InteropServices; + using System.Security.Cryptography; + + using Mono.Security.Cryptography; namespace Mono.CSharp { *************** [...1039 lines suppressed...] + ApplyAttributeBuilder (null, new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0])); + } + + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder) + { + if (a != null && a.Type == TypeManager.cls_compliant_attribute_type) { + Report.Warning (3012, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking"); + return; + } + + Builder.SetCustomAttribute (customBuilder); + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } } Index: compiler.sln =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/compiler.sln,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** compiler.sln 18 Feb 2003 07:36:40 -0000 1.1 --- compiler.sln 6 Oct 2004 13:46:44 -0000 1.2 *************** *** 1,21 **** ! Microsoft Visual Studio Solution File, Format Version 7.00 ! Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "compiler", "compiler.csproj", "{896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}" ! EndProject ! Global ! GlobalSection(SolutionConfiguration) = preSolution ! ConfigName.0 = Debug ! ConfigName.1 = Release ! EndGlobalSection ! GlobalSection(ProjectDependencies) = postSolution ! EndGlobalSection ! GlobalSection(ProjectConfiguration) = postSolution ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Debug.ActiveCfg = Debug|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Debug.Build.0 = Debug|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Release.ActiveCfg = Release|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Release.Build.0 = Release|.NET ! EndGlobalSection ! GlobalSection(ExtensibilityGlobals) = postSolution ! EndGlobalSection ! GlobalSection(ExtensibilityAddIns) = postSolution ! EndGlobalSection ! EndGlobal --- 1,21 ---- ! Microsoft Visual Studio Solution File, Format Version 8.00 ! Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "compiler", "compiler.csproj", "{896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}" ! ProjectSection(ProjectDependencies) = postProject ! EndProjectSection ! EndProject ! Global ! GlobalSection(SolutionConfiguration) = preSolution ! Debug = Debug ! Release = Release ! EndGlobalSection ! GlobalSection(ProjectConfiguration) = postSolution ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Debug.ActiveCfg = Debug|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Debug.Build.0 = Debug|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Release.ActiveCfg = Release|.NET ! {896D1461-B76B-41C0-ABE6-ACA2BB4F7B5A}.Release.Build.0 = Release|.NET ! EndGlobalSection ! GlobalSection(ExtensibilityGlobals) = postSolution ! EndGlobalSection ! GlobalSection(ExtensibilityAddIns) = postSolution ! EndGlobalSection ! EndGlobal Index: const.cs =================================================================== RCS file: /cvsroot/csdoc/csdoc/src/mcs/const.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** const.cs 16 Sep 2003 13:00:24 -0000 1.2 --- const.cs 6 Oct 2004 13:46:44 -0000 1.3 *************** *** 25,36 **** using System.Collections; ! public class Const : MemberBase { ! public Expression ConstantType; public Expression Expr; - public FieldBuilder FieldBuilder; EmitContext const_ec; object ConstantValue = null; - Type type; bool in_transit = false; --- 25,34 ---- using System.Collections; ! public class Const : FieldMember { public Expression Expr; EmitContext const_ec; + bool resolved = false; object ConstantValue = null; bool in_transit = false; *************** *** 43,53 **** Modifiers.PRIVATE; ! public Const (Expression constant_type, string name, Expression expr, int mod_flags, ! Attributes attrs, Location loc) ! : base (constant_type, mod_flags, AllowedModifiers, Modifiers.PRIVATE, name, attrs, loc) { - ConstantType = constant_type; - Name = name; Expr = expr; } --- 41,51 ---- Modifiers.PRIVATE; ! public Const (TypeContainer parent, Expression constant_type, string name, ! Expression expr, int mod_flags, Attributes attrs, Location loc) ! : base (parent, constant_type, mod_flags, AllowedModifiers, ! new MemberName (name), null, attrs, loc) { Expr = expr; + ModFlags |= Modifiers.STATIC; } *************** *** 74,88 **** /// Defines the constant in the @parent /// </summary> ! public override bool Define (TypeContainer parent) { ! type = parent.ResolveType (ConstantType, false, Location); ! ! if (type == null) return false; ! const_ec = new EmitContext (parent, Location, null, type, ModFlags); ! if (!TypeManager.IsBuiltinType (type) && ! (!type.IsSubclassOf (TypeManager.enum_type))) { Report.Error ( -3, Location, --- 72,87 ---- /// Defines the constant in the @parent /// </summary> ! public override bool Define () { ! if (!base.Define ()) return false; ! const_ec = new EmitContext (Parent, Location, null, MemberType, ModFlags); ! ! Type ttype = MemberType; ! while (ttype.IsArray) ! ttype = TypeManager.GetElementType (ttype); ! if (!TypeManager.IsBuiltinType (ttype) && (!ttype.IsSubclassOf (TypeManager.enum_type)) && !(Expr is NullLiteral)) { Report.Error ( -3, Location, *************** *** 91,109 **** } ! Type ptype = parent.TypeBuilder.BaseType; ! ! if (ptype != null) { ! MemberList list = TypeContainer.FindMembers ( ! ptype, MemberTypes.Field, BindingFlags.Public, ! System.Type.FilterName, Name); ! ! if (list.Count == 0) ! if ((ModFlags & Modifiers.NEW) != 0) ! WarningNotHiding (parent); ! ! } else if ((ModFlags & Modifiers.NEW) != 0) ! WarningNotHiding (parent); ! ! FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr); TypeManager.RegisterConstant (FieldBuilder, this); --- 90,94 ---- } ! FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, FieldAttr); TypeManager.RegisterConstant (FieldBuilder, this); *************** *** 112,123 **** } /// <summary> /// Looks up the value of a constant field. Defines it if it hasn't /// already been. Similar to LookupEnumValue in spirit. /// </summary> ! public object LookupConstantValue () { ! if (ConstantValue != null) ! return ConstantValue; if (in_transit) { --- 97,175 ---- } + // + // Changes the type of the constant expression `expr' to the Type `type' + // Returns null on failure. + // + public static Constant ChangeType (Location loc, Constant expr, Type type) + { + if (type == TypeManager.object_type) + return expr; + + bool fail; + + // from the null type to any reference-type. + if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type)) + return NullLiteral.Null; + + if (!Convert.ImplicitStandardConversionExists (expr, type)){ + Convert.Error_CannotImplicitConversion (loc, expr.Type, type); + return null; + } + + object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail); + if (fail){ + Convert.Error_CannotImplicitConversion (loc, expr.Type, type); + + // + // We should always catch the error before this is ever + // reached, by calling Convert.ImplicitStandardConversionExists + // + throw new Exception ( + String.Format ("LookupConstantValue: This should never be reached {0} {1}", expr.Type, type)); + } + + Constant retval; + if (type == TypeManager.int32_type) + retval = new IntConstant ((int) constant_value); + else if (type == TypeManager.uint32_type) + retval = new UIntConstant ((uint) constant_value); + else if (type == TypeManager.int64_type) + retval = new LongConstant ((long) constant_value); + else if (type == TypeManager.uint64_type) + retval = new ULongConstant ((ulong) constant_value); + else if (type == TypeManager.float_type) + retval = new FloatConstant ((float) constant_value); + else if (type == TypeManager.double_type) + retval = new DoubleConstant ((double) constant_value); + else if (type == TypeManager.string_type) + retval = new StringConstant ((string) constant_value); + else if (type == TypeManager.short_type) + retval = new ShortConstant ((short) constant_value); + else if (type == TypeManager.ushort_type) + retval = new UShortConstant ((ushort) constant_value); + else if (type == TypeManager.sbyte_type) + retval = new SByteConstant ((sbyte) constant_value); + else if (type == TypeManager.byte_type) + retval = new ByteConstant ((byte) constant_value); + else if (type == TypeManager.char_type) + retval = new CharConstant ((char) constant_value); + else if (type == TypeManager.bool_type) + retval = new BoolConstant ((bool) constant_value); + else + throw new Exception ("LookupConstantValue: Unhandled constant type: " + type); + + return retval; + } + /// <summary> /// Looks up the value of a constant field. Defines it if it hasn't /// already been. Similar to LookupEnumValue in spirit. /// </summary> ! public bool LookupConstantValue (out object value) { ! if (resolved) { ! value = ConstantValue; ! return true; ! } if (in_transit) { *************** *** 125,129 **** "The evaluation of the constant value for `" + Name + "' involves a circular definition."); ! return null; } --- 177,182 ---- "The evaluation of the constant value for `" + Name + "' involves a circular definition."); !... [truncated message content] |