[svn] r7665: nemerle/trunk: macros/core.n
ncc/hierarchy/ClassMembers.n ncc/hierarchy/TypeBuilder.n ncc/par...
VladD2
svnadmin at nemerle.org
Thu May 10 16:48:20 CEST 2007
Log:
1. Fix error in autoproperty implementation.
2. Change fields and properties description generation (DescribeMember()). Fix corresponding error message and tests.
3. Add property 'Builder' which get reference to corresponding MemberBuilder from AST (ClassMember).
4. Add BeforeBodyTyping event which allow transform method body when it available.
Author: VladD2
Date: Thu May 10 16:48:09 2007
New Revision: 7665
Added:
nemerle/trunk/ncc/testsuite/positive/autoproperty.n
Modified:
nemerle/trunk/macros/core.n
nemerle/trunk/ncc/hierarchy/ClassMembers.n
nemerle/trunk/ncc/hierarchy/TypeBuilder.n
nemerle/trunk/ncc/parsing/ (props changed)
nemerle/trunk/ncc/parsing/MainParser.n
nemerle/trunk/ncc/parsing/ParseTree.n
nemerle/trunk/ncc/testsuite/negative/access1.n
nemerle/trunk/ncc/testsuite/negative/redef.n
nemerle/trunk/ncc/testsuite/negative/typer2.n
nemerle/trunk/ncc/testsuite/positive/boxing.n
nemerle/trunk/ncc/testsuite/positive/infer.n
nemerle/trunk/ncc/testsuite/positive/warn-unused-value.n
nemerle/trunk/ncc/typing/MType.n
nemerle/trunk/ncc/typing/Typer2.n
Modified: nemerle/trunk/macros/core.n
==============================================================================
--- nemerle/trunk/macros/core.n (original)
+++ nemerle/trunk/macros/core.n Thu May 10 16:48:09 2007
@@ -434,7 +434,9 @@
typer.DelayMacro (fun (fail_loudly) {
match (tcollection.Type.Hint) {
| Some (MType.Class (tc, args)) =>
- if (tc.SuperType (tc.InternalType.Nemerle_list_tc).IsSome) {
+ if (tc.InternalType.Nemerle_list_tc != null
+ && tc.SuperType (tc.InternalType.Nemerle_list_tc).IsSome)
+ {
def arg = List.Head (args);
def definition = build_definition (<[ x ]>);
Some (<[
Modified: nemerle/trunk/ncc/hierarchy/ClassMembers.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/ClassMembers.n (original)
+++ nemerle/trunk/ncc/hierarchy/ClassMembers.n Thu May 10 16:48:09 2007
@@ -27,10 +27,11 @@
*/
using System;
+using System.Diagnostics;
+using Nemerle.Assertions;
using Nemerle.Collections;
-using Nemerle.Utility;
using Nemerle.Compiler.Typedtree;
-using System.Diagnostics;
+using Nemerle.Utility;
using SCG = System.Collections.Generic;
using SR = System.Reflection;
@@ -79,6 +80,7 @@
{
declaring_type = par;
_ast = ast;
+ _ast._builder = this;
Env = ast.Env;
loc = ast.loc;
modifiers = ast.modifiers;
@@ -261,6 +263,17 @@
| MemberKinds.Event => "event"
| _ => "<unknown>"
};
+
+ def makeTypeName(ty) { ty.FullName.Replace('+', '.') }
+ def add(str, iaAdd) { if (iaAdd) str + " " else "" }
+ def mekeGetSet (canRead, canWrite)
+ {
+ | (false, false) => ""
+ | (true, false) => "get;"
+ | (false, true) => "set;"
+ | (true, true) => "get; set;"
+ }
+
match (m) {
| m is IMethod =>
def parms = List.Map (m.GetParameters (),
@@ -271,17 +284,36 @@
kind + " " + full_name + "(" + NString.Concat (", ", parms) + ") : " + ret_ty
| prop is PropertyBuilder =>
+ def getSet = mekeGetSet (prop.CanRead, prop.CanWrite);
match (prop.parms)
{
| _ :: _ =>
match (prop.ty)
{
- | MType.Fun(_, to) => $"$kind `$full_name$(prop.parms) : $to'"
+ | MType.Fun(_, to) => $"property: `$full_name$(prop.parms) : $to { $getSet }"
| _ => "<error>"
}
- | _ => $"$kind `$full_name : $(prop.ty)'"
+ | _ => $"property: $full_name : $(prop.ty) { $getSet }"
}
+ | p is IProperty =>
+ def pi = p.GetPropertyInfo ();
+ _=pi;
+ def getSet = mekeGetSet (pi.CanRead, pi.CanWrite);
+ def indexer = if (p.IsIndexer) "[...]" else "";
+ def typeName = makeTypeName(pi.PropertyType);
+
+ $"property: $(p.Name)$indexer : $typeName { $getSet }"
+
+ | fld is FieldBuilder =>
+ def modifs = add("static", fld.IsStatic) + add("mutable", fld.IsMutable);
+ $"field: $modifs$(fld.Name) : $(fld.ty);"
+
+ | fld is IField =>
+ def fi = fld.GetFieldInfo ();
+ def typeName = makeTypeName(fi.FieldType);
+ def modifs = add("static", fi.IsStatic) + add("mutable", !fi.IsInitOnly);
+ $"field: $modifs$(fld.Name) : $typeName;"
| _ => $ "$kind `$full_name'"
}
@@ -388,6 +420,12 @@
internal virtual Compile () : void {
_ast = null; // GC kill
}
+
+ public IsBodyless : bool
+ {
+ // only allow abstract and extern methods to have no bodies
+ get { attributes %&& (NemerleAttributes.Abstract | NemerleAttributes.Extern) }
+ }
}
public partial class FieldBuilder : MemberBuilder, IField
@@ -618,6 +656,23 @@
par.MonoBindType (parm.ty);
});
+ // Support autoproperty (see C# 3.0 specification).
+ when (!(propertyAst.Attributes %&& (NemerleAttributes.Abstract | NemerleAttributes.Extern))
+ && !IsIndexer && !par.IsInterface)
+ match (propertyAst.get, propertyAst.set)
+ {
+ | (Some(PT.ClassMember.Function(_, _, FunBody.Abstract) as getr),
+ Some(PT.ClassMember.Function(_, _, FunBody.Abstract) as setr)) =>
+
+ def field = Macros.NewSymbol ("field");
+ par.Define(<[ decl: mutable $(field : name) : $(propertyAst.ty); ]>);
+
+ getr.Body = <[ $(field : name) ]>;
+ setr.Body = <[ $(field : name) = value ]>;
+
+ | _ => ()
+ }
+
def process_accessor (_ : option [PT.ClassMember]) {
| Some (fn) =>
def fn = fn :> PT.ClassMember.Function;
@@ -628,6 +683,7 @@
method
| None => null
}
+
getter = process_accessor (propertyAst.get);
setter = process_accessor (propertyAst.set);
@@ -668,6 +724,9 @@
property_builder
}
+ public Getter : IMethod { get { GetGetter () } }
+ public CanRead : bool { get { Getter != null } }
+
public GetGetter () : IMethod
{
if (getter == null && parent_property != null)
@@ -676,6 +735,9 @@
getter
}
+ public Setter : IMethod { get { GetSetter () } }
+ public CanWrite : bool { get { Setter != null } }
+
public GetSetter () : IMethod
{
if (setter == null && parent_property != null)
@@ -822,23 +884,43 @@
}
}
+ type BeforeBodyTypingHandler = MethodBuilder * PT.PExpr -> PT.PExpr;
+
+ public BeforeBodyTyping : list[BeforeBodyTypingHandler]
+ {
+ mutable _beforeBodyTyping : list[BeforeBodyTypingHandler];
+
+ private set { _beforeBodyTyping = value; }
+ get { _beforeBodyTyping }
+ }
+
+ public AddBeforeBodyTypingHandler([NotNull] handler : BeforeBodyTypingHandler) : void
+ {
+ unless (Manager.IsIntelliSenseMode) // see also property BodyParsed in http://nemerle.org/svn/vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CompilerConcreteDefinitions/IntelliSenseModeMethodBuilder.n
+ Body = handler(this, Body);
+
+ if (BeforeBodyTyping == null) BeforeBodyTyping = [handler];
+ else BeforeBodyTyping ::= handler;
+ }
+
+ public ClearBeforeBodyTypingHandlers() : void { BeforeBodyTyping = null; }
//***********************************************************************
// This members available only under completion engine.
- public virtual EnsureCompiled() : void
+ ThrowNotSupported[T] () : T
{ throw System.NotSupportedException ("available on in code-completion use-case") }
- public virtual BodyMessages : SCG.List[CompilerMessage]
- { get { throw System.NotSupportedException ("available on in code-completion use-case") } }
+
+ public virtual EnsureCompiled() : void { ThrowNotSupported () }
+ public virtual BodyMessages : SCG.List[CompilerMessage] { get { ThrowNotSupported () } }
public virtual BodyTokens : Token.BracesGroup
- { get { throw System.NotSupportedException ("available on in code-completion use-case") }
- set { throw System.NotSupportedException ("available on in code-completion use-case " + value.ToString ()) } }
- public virtual BodyParsed : PT.PExpr
- { get { throw System.NotSupportedException ("available on in code-completion use-case") } }
- public virtual IsBodyCompilable : bool
- { get { throw System.NotSupportedException ("available on in code-completion use-case") } }
- public virtual BodyTyped : TExpr
- { get { throw System.NotSupportedException ("available on in code-completion use-case") } }
+ {
+ get { ThrowNotSupported() }
+ set { throw System.NotSupportedException ("available on in code-completion use-case " + value.ToString ()) }
+ }
+ public virtual BodyParsed : PT.PExpr { get { ThrowNotSupported () } }
+ public virtual IsBodyCompilable : bool { get { ThrowNotSupported () } }
+ public virtual BodyTyped : TExpr { get { ThrowNotSupported () } }
// End: This members available only under completion engine.
//***********************************************************************
@@ -1199,10 +1281,7 @@
Message.Error (loc, "interface method cannot implement anything");
}
- // only allow abstract and extern methods to have no bodies
- def bodyless = attributes %&& (NemerleAttributes.Abstract | NemerleAttributes.Extern);
-
- when (HasAbstractBody && !bodyless)
+ when (HasAbstractBody && !IsBodyless)
Message.Error (loc, "missing body of a non-abstract and non-extern method in " +
ToString ());
Modified: nemerle/trunk/ncc/hierarchy/TypeBuilder.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/TypeBuilder.n (original)
+++ nemerle/trunk/ncc/hierarchy/TypeBuilder.n Thu May 10 16:48:09 2007
@@ -1687,6 +1687,7 @@
default_indexer = "Item";
modifiers.AddCustomAttribute (<[ System.Reflection.DefaultMemberAttribute ("Item") ]>);
}
+
AddMember (r);
r
@@ -2501,7 +2502,7 @@
if (f.HasBeenUsed)
when (!f.IsLiteral && (f.IsPrivate || IsSealed || IsInternal))
Message.Warning (649, member.Location,
- $"$f is never assigned to, and will always have its default value")
+ $"field `$(f.Name)' is never assigned to, and will always have its default value")
else
Message.Warning (10003, member.Location,
$"$member is not externally visible and has never been referenced")
Modified: nemerle/trunk/ncc/parsing/MainParser.n
==============================================================================
--- nemerle/trunk/ncc/parsing/MainParser.n (original)
+++ nemerle/trunk/ncc/parsing/MainParser.n Thu May 10 16:48:09 2007
@@ -1070,26 +1070,6 @@
pop_stream ("property member");
}
- // Support autoproperty (see C# 3.0 specification).
- /*
- when (!(mods.Attributes %&& (NemerleAttributes.Abstract | NemerleAttributes.Extern)) && parms.IsEmpty)
- match (getter, setter)
- {
- | (Some(ClassMember.Function(_, _, FunBody.Abstract) as getr),
- Some(ClassMember.Function(_, _, FunBody.Abstract) as setr)) =>
-
- def embed = PExpr.Quoted (SyntaxElement.ClassMember (
- <[ decl: mutable field : $ret_type; ]>));
- mods.AddCustomAttribute (<[ $(mkname ("Nemerle") : name).InternalMacros.PropertyEmbeddedField ($embed) ]>);
-
- getr.Body = <[ field ]>;
- setr.Body = <[ field = value ]>;
-
- | _ => ()
- }
- */
-
-
def prop = ClassMember.Property (loc + group.Location, id, mods,
ret_type, prop_ty, parms, getter, setter);
Modified: nemerle/trunk/ncc/parsing/ParseTree.n
==============================================================================
--- nemerle/trunk/ncc/parsing/ParseTree.n (original)
+++ nemerle/trunk/ncc/parsing/ParseTree.n Thu May 10 16:48:09 2007
@@ -91,15 +91,19 @@
}
}
- [Record (Exclude = [_env, _tokens, _bodyLocation, _definedIn])]
+ [Record (Exclude = [_env, _tokens, _bodyLocation, _definedIn, _builder, _userData])]
public variant ClassMember : DeclarationBase
{
| TypeDeclaration { td : TopDeclaration; }
- | Field { mutable ty : PExpr; }
+ | Field {
+ mutable ty : PExpr;
+ public new Builder : FieldBuilder { get { _builder :> FieldBuilder } }
+ }
| Function {
header : Fun_header;
mutable implemented : list [PExpr];
mutable body : FunBody;
+ public new Builder : MethodBuilder { get { _builder :> MethodBuilder } }
}
| Property {
ty : PExpr;
@@ -107,12 +111,14 @@
dims : list [Fun_parm]; // parameters of indexer property
get : option [ClassMember];
set : option [ClassMember];
+ public new Builder : PropertyBuilder { get { _builder :> PropertyBuilder } }
}
| Event {
ty : PExpr;
field : ClassMember.Field;
add : ClassMember.Function;
remove : ClassMember.Function;
+ public new Builder : EventBuilder { get { _builder :> EventBuilder } }
}
| EnumOption { value : option [PExpr]; }
@@ -123,6 +129,10 @@
[Accessor] internal mutable _bodyLocation : Location;
/// This property contain referens to TopDeclaration where defined this member.
[Accessor] internal mutable _definedIn : TopDeclaration;
+ /// This field set to MemberBuilder where it will be created. (null for EnumOption & TypeDeclaration)
+ [Accessor] internal mutable _builder : MemberBuilder;
+ [Accessor(flags = WantSetter)]
+ mutable _userData : object;
/** accessible only for ClassMember.Function, when its FunBody is not typed or compiled */
public Body : PExpr
Modified: nemerle/trunk/ncc/testsuite/negative/access1.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/access1.n (original)
+++ nemerle/trunk/ncc/testsuite/negative/access1.n Thu May 10 16:48:09 2007
@@ -3,11 +3,11 @@
class X { }
- public class Y : X { // E: DerivingAccess.Y is more accessible than `DerivingAccess.X'
+ public class Y : X { // E: Type `Y' is more accessible than `DerivingAccess.X'
}
interface IFoo { }
- public interface IBar : IFoo { } // E: DerivingAccess.IBar is more accessible than `DerivingAccess.IFoo'
+ public interface IBar : IFoo { } // E: Type `IBar' is more accessible than `DerivingAccess.IFoo'
}
namespace UninitializedSubtyping {
Modified: nemerle/trunk/ncc/testsuite/negative/redef.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/redef.n (original)
+++ nemerle/trunk/ncc/testsuite/negative/redef.n Thu May 10 16:48:09 2007
@@ -63,11 +63,11 @@
}
public class EE {
- public meth (_ : A) : void {} // E: method EE.meth\(_.* : A\) : void is more accessible than `A'
+ public meth (_ : A) : void {} // E: Method `meth' is more accessible than `A'
meth2 (_ : A) : void {} // OK
foo : A; // OK
- public bar : A; // E: field `EE.bar' is more accessible than `A'
- protected Bar : A { get { A() } } // E: property `EE.Bar : A' is more accessible than `A'
+ public bar : A; // E: Field `bar' is more accessible than `A'
+ protected Bar : A { get { A() } } // E: Property `Bar' is more accessible than `A'
}
public class HH { // E: first defined
Modified: nemerle/trunk/ncc/testsuite/negative/typer2.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/typer2.n (original)
+++ nemerle/trunk/ncc/testsuite/negative/typer2.n Thu May 10 16:48:09 2007
@@ -38,7 +38,7 @@
static Main () : void {
def x = System.Text.StringBuilder ();
- def _ = x.Chars; // E: property `System.Text.StringBuilder.Chars' was used as a first class value
+ def _ = x.Chars; // E: Property `Chars' was used as a first class value
3; // W: ignored computed value of type int
Added: nemerle/trunk/ncc/testsuite/positive/autoproperty.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/autoproperty.n Thu May 10 16:48:09 2007
@@ -0,0 +1,29 @@
+using System.Console;
+
+public interface ITest
+{
+ Prop : int { get; set; }
+}
+
+public class A
+{
+ public this(i : int) { Prop1 = i; }
+ public Prop1 : int { get; private set; }
+ public Prop2 : string { get; set; }
+}
+
+module Program
+{
+ Main() : void
+ {
+ def a = A(123);
+ a.Prop2 = "<789>";
+ WriteLine($"a.Prop1=$(a.Prop1); a.Prop2=$(a.Prop2);");
+ }
+}
+
+/*
+BEGIN-OUTPUT
+a.Prop1=123; a.Prop2=<789>;
+END-OUTPUT
+*/
Modified: nemerle/trunk/ncc/testsuite/positive/boxing.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/boxing.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/boxing.n Thu May 10 16:48:09 2007
@@ -66,7 +66,7 @@
f ()
}
- xx : long; // W: field `M.xx' is never assigned to
+ xx : long; // W: field `xx' is never assigned to, and will always have its default value
apply (x:object,y:object):object { x :> int + y :> int }
PassCB (ini : int) : int
Modified: nemerle/trunk/ncc/testsuite/positive/infer.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/infer.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/infer.n Thu May 10 16:48:09 2007
@@ -4,7 +4,7 @@
f1 (_ : object) : void {}
class X ['a] {
- a : 'a; // W: field `M.X.a' is never assigned to
+ a : 'a; // W: field `a' is never assigned to, and will always have its default value
m () : void { f1 (a) }
}
Modified: nemerle/trunk/ncc/testsuite/positive/warn-unused-value.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/warn-unused-value.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/warn-unused-value.n Thu May 10 16:48:09 2007
@@ -44,7 +44,7 @@
{
foo ();
}
- public a: list [int]; // W: field .* is never assigned to, and will always have its default value
+ public a: list [int]; // W: field `a' is never assigned to, and will always have its default value
foo () : void {
_ = a;
Modified: nemerle/trunk/ncc/typing/MType.n
==============================================================================
--- nemerle/trunk/ncc/typing/MType.n (original)
+++ nemerle/trunk/ncc/typing/MType.n Thu May 10 16:48:09 2007
@@ -714,7 +714,10 @@
if (AccessibilityIntersect (tc.Accessibility, access) != access &&
(maybe_me == null || !maybe_me.Equals (tc)))
- Message.Error ($ "$what is more accessible than `$(tc)'")
+ {
+ def kind = what.MemberKind.ToString().Replace("Info", "");
+ Message.Error ($ "$kind `$(what.Name)' is more accessible than `$tc'")
+ }
else
foreach (t in parms)
t.Fix ().CheckAccessibility (what, access)
Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n (original)
+++ nemerle/trunk/ncc/typing/Typer2.n Thu May 10 16:48:09 2007
@@ -805,7 +805,7 @@
| TExpr.LocalRef (decl) =>
when (decl.ValKind is LocalValue.Kind.BlockReturn) {
ReportError (messenger,
- $ "$decl was used as a first class value, "
+ $ "Block $(decl.Name) was used as a first class value, "
"this is not supported");
decl.Register ();
}
@@ -917,7 +917,7 @@
else prop.GetGetter ();
when (meth == null) {
assert (!(ctx %&& Context.NeedLValue), "should be rejected by Typer");
- ReportError (messenger, $ "the get accessor is unavailable for $prop");
+ ReportError (messenger, $ "the get accessor is unavailable for property $(prop.Name)");
}
unless (meth.CanAccess (current_type))
@@ -935,7 +935,7 @@
if (ctx %&& Context.IsIndexerRef)
the_ref
else if (prop.IsIndexer) {
- ReportError (messenger, $ "$prop was used as a first class value");
+ ReportError (messenger, $ "Property `$(prop.Name)' was used as a first class value");
the_ref
} else
TExpr.Call (the_ref, [], false)
@@ -951,7 +951,7 @@
if (ctx %&& Context.IsIndexerRef)
the_ref
else if (prop.IsIndexer) {
- ReportError (messenger, $ "$prop was used as a first class value");
+ ReportError (messenger, $ "Property `$(prop.Name)' was used as a first class value");
the_ref
} else
TExpr.Call (the_ref, [], false)
More information about the svn
mailing list