From 4bd57de01f582c42906bd3e9ad4f4df218606740 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 24 Jul 2003 16:46:43 +0000 Subject: [PATCH] Initial import of the Generic MCS tree. 2003-07-20 Miguel de Icaza * cs-parser.jay (namespace_name): do not use namespace_or_type_name, use qualified_identifier, because namespace_or_type_name will soon return a composed expression instead of a string. (namespace_or_type_name): Instead of returning a string, now this production returns an expression. * codegen.cs (EmitContext): Setup IsGeneric property based on whether our DeclSpace is generic, our the method is generic. * modifier.cs (Modifiers.METHOD_GENERIC): New definition, use if the method is generic. * cs-parser.jay (type_arguments, opt_type_argument_list, type_parameters, type_parameter_list, opt_type_parameter_list, type_parameter,, opt_type_parameter_constraints_clauses, type_parameter_constraints_clauses, type_parameter_constraint_clause, type_parameter_constraint, interface_constraints): Add new production * decl.cs (DeclSpace): IsGeneric, flag to track whether this DeclSpace is generic or not. (DeclSpace.SetParameterInfo): New routine, used to set the parameter info for a type. (DeclSpace.LookupGeneric): Lookups a name, and if it is a generic, returns a GenericTypeExpr * ecore.cs (SimpleName.ResolveAsTypeStep): If our container is generic, lookup the generic argument. * attribute.cs: Do not allow TypeParameterExpressions in Attributes. * class.cs: Do not allow the Main method to be defined in a Generic container. * expression.cs (SizeOf): Do not allow generic types to be used as arguments to sizeof. * typemanager.cs (IsGeneric): Wrapper for Reflection when we have it: whether a type is generic or not. Only works for types we are currently building for now. 2003-01-21 Miguel de Icaza * generic.cs: New file, contains support code for generics. * cs-parser.jay: Remove OP_SHIFT_LEFT, OP_SHIFT_RIGHT, OP_SHIFT_LEFT_ASSIGN, OP_SHIFT_RIGHT_ASSIGN. Update parser for the above removals. * cs-tokenizer.cs: Do not handle <<= or >>= specially. This is now taken care of in the parser. svn path=/trunk/mcs/; revision=16612 --- mcs/gmcs/AssemblyInfo.cs | 2 +- mcs/gmcs/ChangeLog | 78 ++++++++++++++++- mcs/gmcs/Makefile | 2 +- mcs/gmcs/attribute.cs | 13 ++- mcs/gmcs/class.cs | 31 ++++++- mcs/gmcs/codegen.cs | 11 +++ mcs/gmcs/cs-parser.jay | 170 ++++++++++++++++++++++++++++++++++---- mcs/gmcs/cs-tokenizer.cs | 23 +----- mcs/gmcs/decl.cs | 71 +++++++++++++++- mcs/gmcs/driver.cs | 5 +- mcs/gmcs/ecore.cs | 9 +- mcs/gmcs/expression.cs | 11 ++- mcs/gmcs/generic.cs | 44 ++++++++++ mcs/gmcs/genericparser.cs | 2 - mcs/gmcs/modifiers.cs | 1 + mcs/gmcs/namespace.cs | 1 - mcs/gmcs/typemanager.cs | 10 +++ 17 files changed, 426 insertions(+), 58 deletions(-) diff --git a/mcs/gmcs/AssemblyInfo.cs b/mcs/gmcs/AssemblyInfo.cs index 26e3ce24915..60c2d35431d 100644 --- a/mcs/gmcs/AssemblyInfo.cs +++ b/mcs/gmcs/AssemblyInfo.cs @@ -3,6 +3,6 @@ using System.Runtime.CompilerServices; [assembly: AssemblyVersion("0.25.99")] [assembly: AssemblyTitle ("Mono C# Compiler")] -[assembly: AssemblyDescription ("Mono C# Compiler")] +[assembly: AssemblyDescription ("Mono C# Compiler with Generics")] [assembly: AssemblyCopyright ("2001, 2002, 2003 Ximian, Inc.")] [assembly: AssemblyCompany ("Ximian, Inc.")] diff --git a/mcs/gmcs/ChangeLog b/mcs/gmcs/ChangeLog index ec6d491e6db..921b4fbdcd1 100755 --- a/mcs/gmcs/ChangeLog +++ b/mcs/gmcs/ChangeLog @@ -58,9 +58,57 @@ * enum.cs (AddEnumMember): Report a CS0076 if name is `value__'. - * typemanager.cs (TypeManager.ChangeType): Catch exceptions; - makes cs0031.cs actually work. + * typemanager.cs (TypeManager.ChangeType): Catch exceptions; makes + cs0031.cs actually work. + 2003-07-20 Miguel de Icaza + + * cs-parser.jay (namespace_name): do not use + namespace_or_type_name, use qualified_identifier, because + namespace_or_type_name will soon return a composed expression + instead of a string. + + (namespace_or_type_name): Instead of returning a string, now this + production returns an expression. + + * codegen.cs (EmitContext): Setup IsGeneric property based on + whether our DeclSpace is generic, our the method is generic. + + * modifier.cs (Modifiers.METHOD_GENERIC): New definition, use if + the method is generic. + + * cs-parser.jay (type_arguments, opt_type_argument_list, + type_parameters, type_parameter_list, opt_type_parameter_list, + type_parameter,, opt_type_parameter_constraints_clauses, + type_parameter_constraints_clauses, + type_parameter_constraint_clause, type_parameter_constraint, + interface_constraints): Add new production + + * decl.cs (DeclSpace): IsGeneric, flag to track whether this + DeclSpace is generic or not. + + (DeclSpace.SetParameterInfo): New routine, used to set the + parameter info for a type. + + (DeclSpace.LookupGeneric): Lookups a name, and if it is a generic, + returns a GenericTypeExpr + + * ecore.cs (SimpleName.ResolveAsTypeStep): If our container is + generic, lookup the generic argument. + + * attribute.cs: Do not allow TypeParameterExpressions in + Attributes. + + * class.cs: Do not allow the Main method to be defined in a + Generic container. + + * expression.cs (SizeOf): Do not allow generic types to be used as + arguments to sizeof. + + * typemanager.cs (IsGeneric): Wrapper for Reflection when we have + it: whether a type is generic or not. Only works for types we are + currently building for now. + 2003-07-20 Martin Baulig * namespace.cs: Fixed that bug which caused a crash when compiling @@ -1160,7 +1208,31 @@ Tue Jun 3 11:11:08 CEST 2003 Paolo Molaro 2003-04-05 Martin Baulig - * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #40670. + * expression.cs (SizeOf.DoResolve): Use ResolveTypeExpr, so we can + probe if its a type parameter, and if so, flag an error. + + * decl.cs: Move here the SetParameterInfo code from class.cs. + Handle IsGeneric here. + + Handle a variety of errors in the parameter info definition. + + * ecore.cs (SimpleName.DoResolveType): Handle look ups for generic + type parameters here. + + * cs-parser.jay (class_declaration): report errors for parameters + here as well. + +2003-01-21 Miguel de Icaza + + * generic.cs: New file, contains support code for generics. + + * cs-parser.jay: Remove OP_SHIFT_LEFT, OP_SHIFT_RIGHT, + OP_SHIFT_LEFT_ASSIGN, OP_SHIFT_RIGHT_ASSIGN. + + Update parser for the above removals. + + * cs-tokenizer.cs: Do not handle <<= or >>= specially. This is + now taken care of in the parser. 2003-04-02 Miguel de Icaza diff --git a/mcs/gmcs/Makefile b/mcs/gmcs/Makefile index e922174e7aa..f4e8eddb4c4 100644 --- a/mcs/gmcs/Makefile +++ b/mcs/gmcs/Makefile @@ -20,7 +20,7 @@ COMPILER_SOURCES = \ enum.cs \ ecore.cs \ expression.cs \ - genericparser.cs \ + generic.cs \ interface.cs \ iterators.cs \ literal.cs \ diff --git a/mcs/gmcs/attribute.cs b/mcs/gmcs/attribute.cs index 8400748fe90..0b9bb7b0899 100644 --- a/mcs/gmcs/attribute.cs +++ b/mcs/gmcs/attribute.cs @@ -75,6 +75,12 @@ namespace Mono.CSharp { Report.Error (-6, loc, "Could not find a constructor for this argument list."); } + + static void Error_TypeParameterInAttribute (Location loc) + { + Report.Error ( + -202, loc, "Can not use a type parameter in an attribute"); + } private Type CheckAttributeType (EmitContext ec) { Type t; @@ -264,6 +270,11 @@ namespace Mono.CSharp { } e = a.Expr; + if (e is TypeParameterExpr){ + Error_TypeParameterInAttribute (Location); + return null; + } + if (member is PropertyExpr) { PropertyExpr pe = (PropertyExpr) member; PropertyInfo pi = pe.PropertyInfo; @@ -625,7 +636,7 @@ namespace Mono.CSharp { foreach (Attribute a in asec.Attributes){ if (a.ResolveType (ec) == null) return null; - + if (a.Type != TypeManager.indexer_name_type) continue; diff --git a/mcs/gmcs/class.cs b/mcs/gmcs/class.cs index 11e5b3010b2..06b7a731b81 100755 --- a/mcs/gmcs/class.cs +++ b/mcs/gmcs/class.cs @@ -128,7 +128,7 @@ namespace Mono.CSharp { // The parent member container and our member cache IMemberContainer parent_container; MemberCache member_cache; - + // // The indexer name for this class // @@ -142,11 +142,11 @@ namespace Mono.CSharp { if (parent == null) n = ""; - else + else n = parent.Name; base_class_name = null; - + //Console.WriteLine ("New class " + name + " inside " + n); } @@ -602,6 +602,13 @@ namespace Mono.CSharp { } } + void Error_TypeParameterAsBase (TypeParameterExpr e) + { + Report.Error ( + -213, e.Location, + String.Format ("Type parameter `{0}' can not be used t as a base class or interface", e.Name)); + } + /// /// The pending methods that need to be implemented (interfaces or abstract methods) /// @@ -663,6 +670,12 @@ namespace Mono.CSharp { return null; } + if (name is TypeParameterExpr){ + Error_TypeParameterAsBase ((TypeParameterExpr) name); + error = true; + return null; + } + Type first = name.Type; if (first.IsClass){ @@ -786,6 +799,12 @@ namespace Mono.CSharp { } } + if (IsGeneric && (parent == TypeManager.attribute_type || + parent.IsSubclassOf (TypeManager.attribute_type))){ + Report.Error (-214, Location, "Generic type can not derive from Attribute"); + return null; + } + if (!is_class && TypeManager.value_type == null) throw new Exception (); @@ -2065,7 +2084,6 @@ namespace Mono.CSharp { } } - } public class Class : TypeContainer { @@ -2551,6 +2569,11 @@ namespace Mono.CSharp { RootContext.MainClass == container.TypeBuilder.FullName)){ if (IsEntryPoint (MethodBuilder, ParameterInfo)) { if (RootContext.EntryPoint == null) { + if (container.IsGeneric){ + Report.Error (-201, Location, + "Entry point can not be defined in a generic class"); + } + RootContext.EntryPoint = MethodBuilder; RootContext.EntryPointLocation = Location; } else { diff --git a/mcs/gmcs/codegen.cs b/mcs/gmcs/codegen.cs index 43ac7def63d..be4c1746025 100755 --- a/mcs/gmcs/codegen.cs +++ b/mcs/gmcs/codegen.cs @@ -275,6 +275,12 @@ namespace Mono.CSharp { /// public bool InEnumContext; + /// + /// If our type container, or the method we are generating code + /// for is Generic + /// + public bool IsGeneric; + protected Stack FlowStack; public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig, @@ -309,6 +315,11 @@ namespace Mono.CSharp { if (ReturnType == TypeManager.void_type) ReturnType = null; + + // + // We should also set it if the method is generic + // + IsGeneric = ds.IsGeneric || ((Modifiers.METHOD_GENERIC) != 0); } public EmitContext (TypeContainer tc, Location l, ILGenerator ig, diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay index bf3e8357b8f..1dcae765a52 100755 --- a/mcs/gmcs/cs-parser.jay +++ b/mcs/gmcs/cs-parser.jay @@ -26,12 +26,11 @@ using System; namespace Mono.CSharp { using System.Collections; - using Mono.Languages; /// /// The C# Parser /// - public class CSharpParser : GenericParser { + public class CSharpParser { NamespaceEntry current_namespace; TypeContainer current_container; @@ -81,6 +80,11 @@ namespace Mono.CSharp // Stack switch_stack; + public bool yacc_verbose_flag; + + // Name of the file we are parsing + public string name; + // // The current file. // @@ -174,6 +178,7 @@ namespace Mono.CSharp %token VIRTUAL %token VOID %token VOLATILE +%token WHERE %token WHILE /* v2 tokens */ @@ -213,8 +218,6 @@ namespace Mono.CSharp /* C# multi-character operators. */ %token OP_INC "++" %token OP_DEC "--" -%token OP_SHIFT_LEFT "<<" -%token OP_SHIFT_RIGHT ">>" %token OP_LE "<=" %token OP_GE ">=" %token OP_EQ "==" @@ -226,8 +229,6 @@ namespace Mono.CSharp %token OP_MOD_ASSIGN "%=" %token OP_ADD_ASSIGN "+=" %token OP_SUB_ASSIGN "-=" -%token OP_SHIFT_LEFT_ASSIGN "<<=" -%token OP_SHIFT_RIGHT_ASSIGN ">>=" %token OP_AND_ASSIGN "&=" %token OP_XOR_ASSIGN "^=" %token OP_OR_ASSIGN "|=" @@ -252,7 +253,6 @@ namespace Mono.CSharp %left OP_AND %left BITWISE_OR %left BITWISE_AND -%left OP_SHIFT_LEFT OP_SHIFT_RIGHT %left PLUS MINUS %left STAR DIV PERCENT %right BANG CARRET UMINUS @@ -358,7 +358,7 @@ qualified_identifier namespace_name - : namespace_or_type_name + : qualified_identifier ; namespace_body @@ -1358,8 +1358,8 @@ overloadable_operator | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; } | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; } | CARRET { $$ = Operator.OpType.ExclusiveOr; } - | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; } - | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; } + | OP_LT OP_LT { $$ = Operator.OpType.LeftShift; } + | OP_GT OP_GT { $$ = Operator.OpType.RightShift; } | OP_EQ { $$ = Operator.OpType.Equality; } | OP_NE { $$ = Operator.OpType.Inequality; } | OP_GT { $$ = Operator.OpType.GreaterThan; } @@ -1824,9 +1824,52 @@ type_name ; namespace_or_type_name - : qualified_identifier + : IDENTIFIER opt_type_argument_list { + if ($2 == null) + $$ = new SimpleName ((string) $1, lexer.Location); + else + $$ = new ConstructedType (null, (string) $1, (TypeArguments) $2, lexer.Location); + } + | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list + { + Expression right; + + if ($4 == null) + right = new SimpleName ((string) $3, lexer.Location); + else + right = new ConstructedType ((Expression) $1, (string) $3, + (TypeArguments) $4, lexer.Location); + + // + // This is known to be broken, just to compile for now + // Right should be an expression, not a string + // + $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location); + } ; +// +// TODO: +// Figure out what to do with the list +// +opt_type_argument_list + : /* empty */ { $$ = null; } + | OP_LT type_arguments OP_GT { $$ = $2; } + ; + +type_arguments + : type { + TypeArguments type_args = new TypeArguments (); + type_args.Add ((Expression) $1); + $$ = type_args; + } + | type_arguments COMMA type { + TypeArguments type_args = (TypeArguments) $1; + type_args.Add ((Expression) $3); + $$ = type_args; + } + ; + /* * Before you think of adding a return_type, notice that we have been * using two rules in the places where it matters (one rule using type @@ -2489,12 +2532,12 @@ additive_expression shift_expression : additive_expression - | shift_expression OP_SHIFT_LEFT additive_expression + | shift_expression OP_LT OP_LT additive_expression { $$ = new Binary (Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, lexer.Location); } - | shift_expression OP_SHIFT_RIGHT additive_expression + | shift_expression OP_GT OP_GT additive_expression { $$ = new Binary (Binary.Operator.RightShift, (Expression) $1, (Expression) $3, lexer.Location); @@ -2640,14 +2683,14 @@ assignment_expression $$ = new CompoundAssign ( Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l); } - | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression + | prefixed_unary_expression OP_LT OP_LE expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, l); } - | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression + | prefixed_unary_expression OP_GT OP_GE expression { Location l = lexer.Location; @@ -2709,20 +2752,36 @@ class_declaration current_container.Namespace = current_namespace; RootContext.Tree.RecordDecl (name, new_class); } + opt_type_parameter_list opt_class_base + opt_type_parameter_constraints_clauses class_body opt_semicolon { Class new_class = (Class) current_container; - if ($6 != null) - new_class.Bases = (ArrayList) $6; + if ($8 != null && $6 == null) + Report.Error (-200, new_class.Location, + "Type parameter constraints only valid if there is a type parameter list"); + if ($6 != null) + CheckDef (new_class.SetParameterInfo ((ArrayList) $6, $8), new_class.Name, new_class.Location); + if ($7 != null) + new_class.Bases = (ArrayList) $7; current_container = current_container.Parent; CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location); $$ = new_class; } + | opt_attributes + opt_modifiers + CLASS IDENTIFIER + WHERE { + Report.Error (-200, lexer.Location, + "Type parameter constraints only valid if there is a type parameter list"); + yyErrorFlag = 0; + $$ = null; + } ; opt_modifiers @@ -2771,6 +2830,81 @@ class_base : COLON type_list { $$ = $2; } ; +opt_type_parameter_list + : /* empty */ { $$ = null; } + | type_parameter_list { $$ = $1; } + ; + +type_parameter_list + : OP_LT type_parameters OP_GT { $$ = $2; } + ; + +type_parameters + : type_parameter { + // + // Do some profiling to find the optimal size, for now we + // assume most people will be generic on one type (saves space + // + ArrayList type_parameters = new ArrayList (1); + type_parameters.Add ($1); + $$ = type_parameters; + } + | type_parameters COMMA type_parameter { + ArrayList type_parameters = (ArrayList) $1; + + type_parameters.Add ($3); + $$ = type_parameters; + } + ; + +type_parameter + : IDENTIFIER + ; + +opt_type_parameter_constraints_clauses + : /* empty */ { $$ = null; } + | type_parameter_constraints_clauses + { $$ = $1; } + ; + +type_parameter_constraints_clauses + : type_parameter_constraints_clause + | type_parameter_constraints_clauses type_parameter_constraints_clause + ; + +type_parameter_constraint_clause + : WHERE type_parameter COLON type_parameter_constraints { + $$ = new Constraints ((string) $2, (ArrayList) $4); + } + ; + +type_parameter_constraint + // + // we merge class and interface constraints, the tree resolution + // will split them apart. + // + | interface_constraints { $$ = $1; } + ; + +interface_constraints + : type { + ArrayList constraints = new ArrayList (1); + constraints.Add ($1); + $$ = constraints; + } + | NEW OPEN_PARENS CLOSE_PARENS { + ArrayList constraints = new ArrayList (1); + constraints.Add (true); + $$ = constraints; + } + | interface_constraints COMMA type { + ArrayList constraints = (ArrayList) $1; + + constraints.Add ($3); + $$ = constraints; + } + ; + // // Statements (8.2) // @@ -4083,7 +4217,7 @@ public CSharpParser (StreamReader reader, SourceFile file, ArrayList defines) lexer = new Tokenizer (reader, file, defines); } -public override void parse () +public void parse () { try { if (yacc_verbose_flag) diff --git a/mcs/gmcs/cs-tokenizer.cs b/mcs/gmcs/cs-tokenizer.cs index de90a126fba..8cc6e440851 100755 --- a/mcs/gmcs/cs-tokenizer.cs +++ b/mcs/gmcs/cs-tokenizer.cs @@ -279,6 +279,7 @@ namespace Mono.CSharp keywords.Add ("virtual", Token.VIRTUAL); keywords.Add ("void", Token.VOID); keywords.Add ("volatile", Token.VOLATILE); + keywords.Add ("where", Token.WHERE); keywords.Add ("while", Token.WHILE); if (RootContext.V2){ @@ -493,16 +494,7 @@ namespace Mono.CSharp } if (c == '<'){ - if (d == '<'){ - getChar (); - d = peekChar (); - - if (d == '='){ - doread = true; - return Token.OP_SHIFT_LEFT_ASSIGN; - } - return Token.OP_SHIFT_LEFT; - } else if (d == '='){ + if (d == '='){ doread = true; return Token.OP_LE; } @@ -510,16 +502,7 @@ namespace Mono.CSharp } if (c == '>'){ - if (d == '>'){ - getChar (); - d = peekChar (); - - if (d == '='){ - doread = true; - return Token.OP_SHIFT_RIGHT_ASSIGN; - } - return Token.OP_SHIFT_RIGHT; - } else if (d == '='){ + if (d == '='){ doread = true; return Token.OP_GE; } diff --git a/mcs/gmcs/decl.cs b/mcs/gmcs/decl.cs index 02316464f34..1a0e78f9bb7 100755 --- a/mcs/gmcs/decl.cs +++ b/mcs/gmcs/decl.cs @@ -296,7 +296,12 @@ namespace Mono.CSharp { /// protected Hashtable defined_names; - TypeContainer parent; + // + // Whether we are Generic + // + public bool IsGeneric; + + TypeContainer parent; public DeclSpace (TypeContainer parent, string name, Location l) : base (name, l) @@ -304,6 +309,12 @@ namespace Mono.CSharp { Basename = name.Substring (1 + name.LastIndexOf ('.')); defined_names = new Hashtable (); this.parent = parent; + + // + // We are generic if our parent is generic + // + if (parent != null) + IsGeneric = parent.IsGeneric; } /// @@ -762,6 +773,64 @@ namespace Mono.CSharp { public abstract MemberCache MemberCache { get; } + + // + // Extensions for generics + // + ArrayList type_parameter_list; + + /// + /// Called by the parser to configure the type_parameter_list for this + /// declaration space + /// + public AdditionResult SetParameterInfo (ArrayList type_parameter_list, object constraints) + { + this.type_parameter_list = type_parameter_list; + + // + // Mark this type as Generic + // + IsGeneric = true; + + // + // Register all the names + // + foreach (string type_parameter in type_parameter_list){ + AdditionResult res = IsValid (type_parameter, type_parameter); + + if (res != AdditionResult.Success) + return res; + + DefineName (type_parameter, GetGenericData ()); + } + + return AdditionResult.Success; + } + + // + // This is just something to flag the defined names for now + // + const int GENERIC_COOKIE = 20; + static object generic_flag = GENERIC_COOKIE; + + static object GetGenericData () + { + return generic_flag; + } + + /// + /// Returns a GenericTypeExpr if `name' refers to a type parameter + /// + public TypeParameterExpr LookupGeneric (string name, Location l) + { + foreach (string type_parameter in type_parameter_list){ + Console.WriteLine (" trying: " + type_parameter); + if (name == type_parameter) + return new TypeParameterExpr (name, l); + } + + return null; + } } /// diff --git a/mcs/gmcs/driver.cs b/mcs/gmcs/driver.cs index 7fa7e567c1f..85b16b0b0ad 100755 --- a/mcs/gmcs/driver.cs +++ b/mcs/gmcs/driver.cs @@ -17,7 +17,6 @@ namespace Mono.CSharp using System.IO; using System.Text; using System.Globalization; - using Mono.Languages; enum Target { Library, Exe, Module, WinExe @@ -175,7 +174,7 @@ namespace Mono.CSharp StreamReader reader = new StreamReader (input, encoding, using_default_encoder); parser = new CSharpParser (reader, file, defines); - parser.yacc_verbose = yacc_verbose; + parser.yacc_verbose_flag = yacc_verbose; try { parser.parse (); } catch (Exception ex) { @@ -1119,6 +1118,8 @@ namespace Mono.CSharp int i; bool parsing_options = true; + Console.WriteLine ("Mono C# Compiler {0} for Generics", + Assembly.GetExecutingAssembly ().GetName ().Version.ToString ()); try { encoding = Encoding.GetEncoding (28591); } catch { diff --git a/mcs/gmcs/ecore.cs b/mcs/gmcs/ecore.cs index 60f583b959f..0dc221c0c95 100755 --- a/mcs/gmcs/ecore.cs +++ b/mcs/gmcs/ecore.cs @@ -1989,6 +1989,13 @@ namespace Mono.CSharp { // we have alias value, but it isn't Type, so try if it's namespace return new SimpleName (alias_value, loc); } + + if (ec.IsGeneric){ + TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc); + + if (generic_type != null) + return generic_type; + } // // Stage 2: Lookup up if we are an alias to a type @@ -2097,7 +2104,7 @@ namespace Mono.CSharp { lookup_ds =lookup_ds.Parent; } while (lookup_ds != null); - + if (e == null && ec.ContainerType != null) e = MemberLookup (ec, ec.ContainerType, Name, loc); diff --git a/mcs/gmcs/expression.cs b/mcs/gmcs/expression.cs index 50f367fe34b..3c29a1d3157 100755 --- a/mcs/gmcs/expression.cs +++ b/mcs/gmcs/expression.cs @@ -6379,7 +6379,7 @@ namespace Mono.CSharp { /// Implements the sizeof expression /// public class SizeOf : Expression { - public readonly Expression QueriedType; + public Expression QueriedType; Type type_queried; public SizeOf (Expression queried_type, Location l) @@ -6397,10 +6397,15 @@ namespace Mono.CSharp { return null; } - type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc); - if (type_queried == null) + QueriedType = ec.DeclSpace.ResolveTypeExpr (QueriedType, false, loc); + if (QueriedType == null || QueriedType.Type == null) return null; + if (QueriedType is TypeParameterExpr){ + ((TypeParameterExpr)QueriedType).Error_CannotUseAsUnmanagedType (loc); + return null; + } + if (!TypeManager.IsUnmanagedType (type_queried)){ Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")"); return null; diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs index 4e66eb6cc66..c35134d2329 100644 --- a/mcs/gmcs/generic.cs +++ b/mcs/gmcs/generic.cs @@ -36,6 +36,12 @@ namespace Mono.CSharp { // public class TypeParameterExpr : TypeExpr { string type_parameter; + + public string Name { + get { + return type_parameter; + } + } public TypeParameterExpr (string type_parameter, Location l) : base (typeof (object), l) @@ -53,4 +59,42 @@ namespace Mono.CSharp { Report.Error (-203, loc, "Can not use type parameter as unamanged type"); } } + + public class TypeArguments { + ArrayList args; + + public TypeArguments () + { + args = new ArrayList (); + } + + public void Add (Expression type) + { + args.Add (type); + } + } + + public class ConstructedType : Expression { + Expression container_type; + string name; + TypeArguments args; + + public ConstructedType (Expression container_type, string name, TypeArguments args, Location l) + { + loc = l; + this.container_type = container_type; + this.name = name; + this.args = args; + } + + public override Expression DoResolve (EmitContext ec) + { + throw new Exception ("IMPLEMENT ME"); + } + + public override void Emit (EmitContext ec) + { + throw new Exception ("IMPLEMENT ME"); + } + } } diff --git a/mcs/gmcs/genericparser.cs b/mcs/gmcs/genericparser.cs index 522987d6f30..90fe7b45ed0 100644 --- a/mcs/gmcs/genericparser.cs +++ b/mcs/gmcs/genericparser.cs @@ -25,8 +25,6 @@ namespace Mono.Languages // Input stream to parse from. public System.IO.Stream input; - public abstract void parse (); - public virtual string[] extensions() { string [] list = { ".cs" }; diff --git a/mcs/gmcs/modifiers.cs b/mcs/gmcs/modifiers.cs index edbc6d17ce6..b6f8d42aef4 100755 --- a/mcs/gmcs/modifiers.cs +++ b/mcs/gmcs/modifiers.cs @@ -31,6 +31,7 @@ namespace Mono.CSharp { // We use this internally to flag that the method contains an iterator // public const int METHOD_YIELDS = 0x8000; + public const int METHOD_GENERIC = 0x10000; public const int Accessibility = PUBLIC | PROTECTED | INTERNAL | PRIVATE; diff --git a/mcs/gmcs/namespace.cs b/mcs/gmcs/namespace.cs index e517d621d06..231b5414b38 100755 --- a/mcs/gmcs/namespace.cs +++ b/mcs/gmcs/namespace.cs @@ -8,7 +8,6 @@ // using System; using System.Collections; -using Mono.Languages; namespace Mono.CSharp { diff --git a/mcs/gmcs/typemanager.cs b/mcs/gmcs/typemanager.cs index 326e22f66ea..bcc57cf04d1 100755 --- a/mcs/gmcs/typemanager.cs +++ b/mcs/gmcs/typemanager.cs @@ -1308,6 +1308,16 @@ public class TypeManager { return false; } + // + // Only a quick hack to get things moving, while real runtime support appears + // + public static bool IsGeneric (Type t) + { + DeclSpace ds = (DeclSpace) builder_to_declspace [t]; + + return ds.IsGeneric; + } + // // Whether a type is unmanaged. This is used by the unsafe code (25.2) // -- 2.25.1