+2008-01-14 Marek Safar <marek.safar@gmail.com>
+
+ * typemanager.cs, lambda.cs, parameter.cs, ecore.cs, class.cs, delegate.cs,
+ iterators.cs, convert.cs, assign.cs, anonymous.cs, expression.cs,
+ statement.cs: The first expression tree implementation drop, mostly
+ infrastructure work.
+
2008-01-14 Marek Safar <marek.safar@gmail.com>
* ecore.cs (IsNestedChild): Refactored.
public bool CreateAnonymousHelpers ()
{
+ // FIXME: this polutes expression trees implementation
+
Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
this, Host, container, loc);
}
}
- protected Expression CompatibleChecks (EmitContext ec, Type delegate_type)
+ protected Type CompatibleChecks (EmitContext ec, Type delegate_type)
{
if (!ec.IsAnonymousMethodAllowed) {
Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
return null;
}
- if (!TypeManager.IsDelegateType (delegate_type)){
- Report.Error (1660, loc,
- "Cannot convert `{0}' to type " +
- "`{1}' because it is not a delegate type",
- GetSignatureForError (), TypeManager.CSharpName (delegate_type));
+ if (TypeManager.IsDelegateType (delegate_type))
+ return delegate_type;
+
+#if GMCS_SOURCE
+ if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) {
+ delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
+ if (TypeManager.IsDelegateType (delegate_type))
+ return delegate_type;
+
+ Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
+ GetSignatureForError (), TypeManager.CSharpName (delegate_type));
return null;
}
- return this;
+#endif
+
+ Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
+ GetSignatureForError (), TypeManager.CSharpName (delegate_type));
+ return null;
}
protected bool VerifyExplicitParameters (Type delegate_type, ParameterData parameters, bool ignore_error)
// Returns AnonymousMethod container if this anonymous method
// expression can be implicitly converted to the delegate type `delegate_type'
//
- public AnonymousMethod Compatible (EmitContext ec, Type delegate_type)
+ public Expression Compatible (EmitContext ec, Type type)
{
- if (CompatibleChecks (ec, delegate_type) == null)
+ Type delegate_type = CompatibleChecks (ec, type);
+ if (delegate_type == null)
return null;
//
TypeManager.IsGenericType (delegate_type), loc);
try {
- return CompatibleMethod (ec, null, return_type, delegate_type);
+ AnonymousMethod am = CompatibleMethod (ec, null, return_type, delegate_type);
+ if (am != null && delegate_type != type)
+ return CreateExpressionTree (ec, delegate_type);
+
+ return am;
} catch (Exception e) {
throw new InternalErrorException (e, loc);
}
}
+ protected virtual Expression CreateExpressionTree (EmitContext ec, Type delegate_type)
+ {
+ Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree");
+ return null;
+ }
+
protected virtual Parameters ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegate_type)
{
ParameterData delegate_parameters = TypeManager.GetDelegateParameters (delegate_type);
}
}
- public abstract class AnonymousContainer : IAnonymousContainer
+ public abstract class AnonymousContainer : Expression, IAnonymousContainer
{
- public readonly Location Location;
-
public Parameters Parameters;
//
this.generic = generic;
this.Parameters = parameters;
this.Block = block;
- this.Location = loc;
+ this.loc = loc;
block.AnonymousContainer = this;
}
get;
}
- public abstract string GetSignatureForError ();
-
public bool Compatible (EmitContext ec)
{
// REFACTOR: The method should be refactor, many of the
return res;
}
- public abstract Expression Resolve (EmitContext ec);
-
public virtual bool Define (EmitContext ec)
{
Report.Debug (64, "DEFINE ANONYMOUS METHOD #3", this, ec, aec, Block);
protected abstract Method DoCreateMethodHost (EmitContext ec);
+ public override void Emit (EmitContext ec)
+ {
+ throw new NotSupportedException ();
+ }
+
public Block Container {
get { return container; }
}
scope == null ? Modifiers.PRIVATE : Modifiers.INTERNAL, member_name, Parameters);
}
- public override Expression Resolve (EmitContext ec)
+ public override Expression DoResolve (EmitContext ec)
{
if (!Define (ec))
return null;
{
this.is_embedded = true;
}
+
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ Report.Error (832, loc, "An expression tree cannot contain an assignment operator");
+ return null;
+ }
protected virtual Assign GetEmbeddedAssign (Location loc)
{
{
base.Emit ();
+#if GMCS_SOURCE
if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
TypeBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
+#endif
}
public override TypeExpr[] GetClassBases (out TypeExpr base_class)
MethodData.Emit (Parent);
base.Emit ();
+#if GMCS_SOURCE
if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
MethodBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
-
+#endif
+
Block = null;
MethodData = null;
} catch {
if (expr_type == TypeManager.anonymous_method_type){
AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
-
- AnonymousMethod am = ame.Compatible (ec, target_type);
+ Expression am = ame.Compatible (ec, target_type);
if (am != null)
- return am.Resolve (ec);
+ return am.DoResolve (ec);
}
return null;
Expression e = a.Expr;
if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1) {
- AnonymousMethod am = ((AnonymousMethodExpression) e).Compatible (ec, type);
- if (am == null)
+ e = ((AnonymousMethodExpression) e).Compatible (ec, type);
+ if (e == null)
return null;
- return am.Resolve (ec);
+ return e.Resolve (ec);
}
method_group = e as MethodGroupExpr;
return cloned;
}
+
+ public virtual Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotImplementedException (
+ "Expression tree conversion not implemented for " + GetType ());
+ }
}
/// <summary>
return Name == pr.Name && referenced == pr.referenced;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ return Parameter.ExpressionTreeVariableReference ();
+ }
+
//
// Notice that for ref/out parameters, the type exposed is not the
// same type exposed externally.
Parameters.EmptyReadOnlyParameters);
}
- public override Expression Resolve (EmitContext ec)
+ public override Expression DoResolve (EmitContext ec)
{
throw new NotSupportedException ();
}
explicit_parameters = !(parameters.FixedParameters [0] is ImplicitLambdaParameter);
}
+ public static Expression System_Linq_Expressions;
+ public static Expression System_Linq_Expressions_Expression;
+
+ protected override Expression CreateExpressionTree (EmitContext ec, Type delegate_type)
+ {
+ System_Linq_Expressions = new MemberAccess (
+ new MemberAccess (new SimpleName ("System", loc), "Linq", loc), "Expressions", loc);
+
+ System_Linq_Expressions_Expression = new MemberAccess (
+ System_Linq_Expressions, "Expression", loc);
+
+ MemberAccess lambda = new MemberAccess (System_Linq_Expressions_Expression, "Lambda",
+ new TypeArguments (loc, new TypeExpression (delegate_type, loc)), loc);
+
+ Expression args = Parameters.CreateExpressionTree (ec, loc);
+ Expression expr = Block.CreateExpressionTree (ec);
+ if (expr == null)
+ return null;
+
+ ArrayList arguments = new ArrayList (2);
+ arguments.Add (new Argument (expr));
+ arguments.Add (new Argument (args));
+ Expression invocation = new Invocation (lambda, arguments);
+
+ return invocation;
+ }
+
public override bool HasExplicitParameters {
get {
return explicit_parameters;
{
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ return Expr.CreateExpressionTree (ec);
+ }
+
public override void Emit (EmitContext ec)
{
if (statement_return) {
public readonly Location Location;
IResolveContext resolve_context;
+ LocalVariableReference expr_tree_variable;
+ static TypeExpr parameter_expr_tree_type;
Variable var;
public Variable Variable {
return p;
}
+
+ public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
+ {
+ if ((modFlags & Modifier.ISBYREF) != 0)
+ Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
+
+ LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
+ ResolveParameterExpressionType (ec, Location), Location);
+ variable.Resolve (ec);
+
+ expr_tree_variable = new LocalVariableReference (
+ ec.CurrentBlock, variable.Name, Location, variable, false);
+
+ ArrayList arguments = new ArrayList (2);
+ arguments.Add (new Argument (new TypeOf (
+ new TypeExpression (parameter_type, Location), Location)));
+ arguments.Add (new Argument (new StringConstant (Name, Location)));
+ return new Assign (ExpressionTreeVariableReference (),
+ new Invocation (
+ new MemberAccess (LambdaExpression.System_Linq_Expressions_Expression, "Parameter", Location),
+ arguments));
+ }
+
+ public Expression ExpressionTreeVariableReference ()
+ {
+ return expr_tree_variable;
+ }
+
+ //
+ // System.Linq.Expressions.ParameterExpression type
+ //
+ public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location)
+ {
+ if (parameter_expr_tree_type != null)
+ return parameter_expr_tree_type;
+
+ MemberAccess ma = new MemberAccess (
+ LambdaExpression.System_Linq_Expressions, "ParameterExpression", location);
+ parameter_expr_tree_type = ma.ResolveAsTypeTerminal (ec, false);
+ return parameter_expr_tree_type;
+ }
}
/// <summary>
return this [pos].ModFlags;
}
+ public Expression CreateExpressionTree (EmitContext ec, Location loc)
+ {
+ ArrayList initializers = new ArrayList (count);
+ foreach (Parameter p in FixedParameters) {
+ //
+ // Each parameter expression is stored to local variable
+ // to save some memory when referenced later.
+ //
+ StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
+ if (se.Resolve (ec))
+ ec.CurrentBlock.AddScopeStatement (se);
+
+ initializers.Add (p.ExpressionTreeVariableReference ());
+ }
+
+ return new ArrayCreation (
+ Parameter.ResolveParameterExpressionType (ec, loc),
+ "[]", initializers, loc);
+ }
+
public Parameters Clone ()
{
Parameter [] parameters_copy = new Parameter [FixedParameters.Length];
return s;
}
+ public virtual Expression CreateExpressionTree (EmitContext ec)
+ {
+ Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
+ return null;
+ }
+
public Statement PerformClone ()
{
CloneContext clonectx = new CloneContext ();
//
Block switch_block;
+ // TODO: merge with scope_initializers
ExpressionStatement scope_init;
+ ArrayList scope_initializers;
ArrayList anonymous_children;
}
return null;
}
+
+ //
+ // It should be used by expressions which require to
+ // register a statement during resolve process.
+ //
+ public void AddScopeStatement (StatementExpression s)
+ {
+ if (scope_initializers == null)
+ scope_initializers = new ArrayList ();
+
+ scope_initializers.Add (s);
+ }
public void AddStatement (Statement s)
{
ec.Mark (StartLocation, true);
if (scope_init != null)
scope_init.EmitStatement (ec);
+ if (scope_initializers != null) {
+ foreach (StatementExpression s in scope_initializers)
+ s.Emit (ec);
+ }
+
DoEmit (ec);
ec.Mark (EndLocation, true);
return root_scope;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ return ((Statement) statements [0]).CreateExpressionTree (ec);
+ }
+
public void CreateIteratorHost (RootScopeInfo root)
{
Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope);
static public Type coclass_attr_type;
static public Type comimport_attr_type;
- ///
- /// .NET 2.0
- ///
-#if NET_2_0
+#if GMCS_SOURCE
+ //
+ // C# 2.0
+ //
static internal Type runtime_compatibility_attr_type;
static internal Type compiler_generated_attr_type;
static internal Type fixed_buffer_attr_type;
static internal Type default_charset_type;
static internal Type internals_visible_attr_type;
static internal Type type_forwarder_attr_type;
+
+ //
+ // C# 3.0
+ //
+ static internal Type expression_type;
#endif
//
static internal ConstructorInfo struct_layout_attribute_ctor;
static public ConstructorInfo field_offset_attribute_ctor;
-#if NET_2_0
- /// C# 2.0
+#if GMCS_SOURCE
+ // C# 2.0
static internal CustomAttributeBuilder compiler_generated_attr;
static internal ConstructorInfo fixed_buffer_attr_ctor;
-#endif
- /// C# 3.0
+ // C# 3.0
static internal CustomAttributeBuilder extension_attribute_attr;
+#endif
static PtrHashtable builder_to_declspace;
// C# 3.0
//
extension_attribute_type = CoreLookupType("System.Runtime.CompilerServices", "ExtensionAttribute", true);
+ expression_type = CoreLookupType ("System.Linq.Expressions", "Expression`1", true);
#endif
//