diff --git a/CS2JLibrary/NetFramework/System/Collections/Generic/IList'1.xml b/CS2JLibrary/NetFramework/System/Collections/Generic/IList'1.xml
new file mode 100644
index 0000000..b03e750
--- /dev/null
+++ b/CS2JLibrary/NetFramework/System/Collections/Generic/IList'1.xml
@@ -0,0 +1,209 @@
+
+
+
+
+ java.util.List
+
+ List*[${T}]*
+ System.Collections.Generic.IList
+
+ T
+
+
+
+
+
+
+ T
+ ${expr}
+
+
+
+
+ ${this:16}.add(${arg})
+
+
+ T
+ arg
+
+
+ Add
+
+ System.Int32
+
+
+
+ java.util.Arrays
+
+ ${this:16}.addAll(Arrays.asList(${arg}))
+
+
+ T[]
+ arg
+
+
+ AddRange
+ System.Void
+
+
+
+ ${this:16}.addAll(${arg})
+
+
+ System.Collections.Generic.IEnumerable*[T]*
+ arg
+
+
+ AddRange
+ System.Void
+
+
+
+ ${this:16}.clear()
+
+ Clear
+ System.Void
+
+
+
+ ${this:16}.contains(${key})
+
+
+ T
+ key
+
+
+ Contains
+ System.Boolean
+
+
+
+ ${this:16}.add(${index}, ${value})
+
+
+ System.Int32
+ index
+
+
+ T
+ value
+
+
+ Insert
+ System.Void
+
+
+
+ ${this:16}.remove(${value})
+
+
+ T
+ value
+
+
+ Remove
+ System.Boolean
+
+
+
+ ${this:16}.remove((int)${value})
+
+
+ System.Int32
+ index
+
+
+ RemoveAt
+ System.Void
+
+
+ ${this:16}.toArray(new ${T}[${this}.size()])
+
+
+ ToArray
+ T[]
+
+
+
+ java.util.Collections
+
+ Collections.sort(${this})
+
+ Sort
+ System.Void
+
+
+
+
+
+ ${this:16}.size()
+ System.Int32
+ Count
+ ${this:16}.size()
+ ${this:16}.setCount(${value})
+
+
+
+
+
+
+
+
+ System.Int32
+ i
+
+
+ T
+ ${this:16}.get(${i})
+ ${this:16}.add(${i}, ${value})
+
+
+
+
+
+ new ArrayList*[${T}]*()
+
+
+
+
+ new ArrayList*[${T}]*(${length})
+
+
+ System.Int32
+ length
+
+
+
+
+ new ArrayList*[${T}]*(Arrays.asList(${collection}))
+
+
+ T[]
+ collection
+
+
+
+
+
+ new ArrayList*[${T}]*(${collection})
+
+
+ System.IEnumerable[T]
+ collection
+
+
+
+
+
+
+
+
+rUong3D9EauJhCA+cIiWlGuXn08=esb0vH9iEN6TefBNnLiampoglnuOe2oggi0NVh+r9eoUKf6vzAQCfNGubdlKaf8IausdKZ3wS212MtQtXkJ8TFKPjK+gOpmoVhFKd/6rPnT5xt89+N7s5cByTPW8epjPNnAH7pEiRbzk5+JpH/xKeNCCoGoADV4L/E0TIsZRCH4=
diff --git a/CS2JLibrary/src/CS2JNet/JavaSupport/util/ListSupport.java b/CS2JLibrary/src/CS2JNet/JavaSupport/util/ListSupport.java
new file mode 100644
index 0000000..8be9c43
--- /dev/null
+++ b/CS2JLibrary/src/CS2JNet/JavaSupport/util/ListSupport.java
@@ -0,0 +1,93 @@
+/*
+ Copyright 2010,2011 Kevin Glynn (kevin.glynn@twigletsoftware.com)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author(s):
+
+ Kevin Glynn (kevin.glynn@twigletsoftware.com)
+*/
+
+package CS2JNet.JavaSupport.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author keving
+ *
+ */
+public class ListSupport {
+
+ // If the sequence of elements in stretch appears in l, then returns a new list, a copy of l without
+ // the final such sequence. Otherwise returns l.
+ public static List removeFinalStretch(List l, List stretch) {
+ List ret = l;
+ boolean found = true;
+ int endIdx = l.size() - 1;
+ while (endIdx >= stretch.size() - 1) {
+ // is this the start of a sequence of stretch?
+ found = true;
+ for (int j = 0; j < stretch.size(); j++) {
+ if (l.get(endIdx - j) != stretch.get(stretch.size() - j - 1)) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ endIdx--;
+ }
+ if (found) {
+ // stretch starts at l(endIdx - stretch.size())
+ // don't use subList, create a totally new list.
+ ret = new ArrayList(l.size() - stretch.size());
+ for (int i = 0; i <= endIdx - stretch.size(); i++){
+ ret.add(l.get(i));
+ }
+ for (int i = endIdx+1; i < l.size(); i++){
+ ret.add(l.get(i));
+ }
+ }
+
+ return ret;
+ }
+
+ public static void main(String[] args) {
+ List master = Arrays.asList(new Integer[] {0,1,2,3,4,5,1,2,3,4,5});
+ List find0 = Arrays.asList(new Integer[] {0});
+ List find1 = Arrays.asList(new Integer[] {2,3,4});
+ List find2 = Arrays.asList(new Integer[] {2,4});
+ List find3 = Arrays.asList(new Integer[] {4,5});
+
+ for (int i : removeFinalStretch(master,find0)) {
+ System.out.printf("%1d ",i);
+ }
+ System.out.println();
+ for (int i : removeFinalStretch(master,find1)) {
+ System.out.printf("%1d ",i);
+ }
+ System.out.println();
+ for (int i : removeFinalStretch(master,find2)) {
+ System.out.printf("%1d ",i);
+ }
+ System.out.println();
+ for (int i : removeFinalStretch(master,find3)) {
+ System.out.printf("%1d ",i);
+ }
+ System.out.println();
+ }
+
+}
diff --git a/CSharpTranslator/antlr3/src/CS2JTemplateGenerator/Main.cs b/CSharpTranslator/antlr3/src/CS2JTemplateGenerator/Main.cs
index 1ad92f8..6e49007 100755
--- a/CSharpTranslator/antlr3/src/CS2JTemplateGenerator/Main.cs
+++ b/CSharpTranslator/antlr3/src/CS2JTemplateGenerator/Main.cs
@@ -224,8 +224,9 @@ namespace Twiglet.CS2J.Utility
MethodInfo invoker = t.GetMethod("Invoke");
if (invoker == null)
throw new Exception("Unexpected: class " + t.FullName + " inherits from System.Delegate but doesn't have an Invoke method");
- buildParameters(d.Params, invoker);
- d.Return = TypeHelper.buildTypeName(invoker.ReturnType);
+ List pars = new List();
+ buildParameters(pars, invoker);
+ d.Invoke = new InvokeRepTemplate(TypeHelper.buildTypeName(invoker.ReturnType), "Invoke", null, pars);
}
private IList mkTemplates(string typeName)
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Fragments.cs b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Fragments.cs
index ad19829..c5eb9ef 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Fragments.cs
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Fragments.cs
@@ -11,6 +11,15 @@ namespace Twiglet.CS2J.Translator
public class Fragments
{
+ public static string DelegateObject(String delName, String args, String body)
+ {
+ return delegateObject.Replace("${D}",delName).Replace("${A}",args).Replace("${B}",body);
+ }
+
+ private static string delegateObject = @"
+ new ${D}() { public void Invoke(${A}) { ${B}; } }
+";
+
public static string GenericCollectorMethods(string T, string S)
{
return genericCollectorMethodsStr.Replace("${T}", T).Replace("${S}", S);
@@ -153,6 +162,39 @@ namespace Twiglet.CS2J.Translator
}
";
+ public static string MultiDelegateMethods(string Del, string DelClass, string TyArgs)
+ {
+ return multiDelegateMethodsStr.Replace("${Del}", Del).Replace("${DelClass}", DelClass).Replace("${TyArgs}", TyArgs);
+ }
+
+ private static string multiDelegateMethodsStr = @"
+ private System.Collections.Generic.IList<${Del}> _invocationList = new ArrayList<${Del}>();
+
+ public static ${Del} Combine ${TyArgs} (${Del} a, ${Del} b) throws Exception {
+ ${DelClass} ret = new ${DelClass}();
+ ret._invocationList = a.GetInvocationList();
+ ret._invocationList.addAll(b.GetInvocationList());
+ return ret;
+ }
+
+ public static ${Del} Remove ${TyArgs} (${Del} a, ${Del} b) throws Exception {
+ System.Collections.Generic.IList<${Del}> aInvList = a.GetInvocationList();
+ System.Collections.Generic.IList<${Del}> newInvList = ListSupport.removeFinalStretch(aInvList, b.GetInvocationList());
+ if (aInvList == newInvList) {
+ return a;
+ }
+ else {
+ ${DelClass} ret = new ${DelClass}();
+ ret._invocationList = newInvList;
+ return ret;
+ }
+ }
+
+ public System.Collections.Generic.IList<${Del}> GetInvocationList() throws Exception {
+ return _invocationList;
+ }
+";
+
public static string GenIterator = @"
public Iterator<${T}> iterator() {
Iterator<${T}> ret = null;
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Templates.cs b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Templates.cs
index 63ca763..04b521d 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Templates.cs
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JMain/Templates.cs
@@ -279,7 +279,16 @@ braceblock(statements) ::= <<
cast_expr(type, exp) ::= ""()""
construct(type, args, inits) ::= ""new () /* [UNIMPLEMENTED] */""
-array_construct(type, args, inits) ::= ""new []""
+delegate(type, args, body) ::= <<
+new ()
+ {
+
+ }
+>>
+lambda(args, body) ::= <<
+() =>
+>>
+array_construct(type, args, inits) ::= ""new []""
array_initializer(init) ::= ""{ }""
application(func, funcparens, args) ::= ""()""
index(func, funcparens, args) ::= ""[]""
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
index a48045e..2f0d774 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
@@ -897,6 +897,22 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
+ public class InvokeRepTemplate : MethodRepTemplate
+ {
+ public InvokeRepTemplate()
+ {
+
+ }
+ public InvokeRepTemplate (string retType, string methodName, string[] tParams, List pars) : base(retType, methodName, tParams, pars)
+ {
+ }
+
+ public override string mkJava()
+ {
+ return "${this:16}.Invoke" + mkJavaParams(this.Params);
+ }
+ }
+
// A user-defined cast from one type to another
public class CastRepTemplate : TranslationBase, IEquatable
{
@@ -2540,41 +2556,16 @@ namespace Twiglet.CS2J.Translator.TypeRep
[XmlType("Delegate")]
public class DelegateRepTemplate : TypeRepTemplate, IEquatable
{
- private List _params = null;
- [XmlArrayItem("Param")]
- public List Params {
+ private InvokeRepTemplate _invoke = null;
+ public InvokeRepTemplate Invoke {
get {
- if (_params == null)
- _params = new List ();
- return _params;
+ return _invoke;
}
set {
- _params = value;
+ _invoke = value;
}
}
- private string _return;
- public string Return {
- get { return _return; }
- set {
- _return=value.Replace("<","*[").Replace(">","]*");
- }
- }
-
- protected string _javaInvoke = null;
- [XmlElementAttribute("Invoke")]
- public virtual string JavaInvoke {
- get {
- if (_javaInvoke == null) {
- return "${this:16}.Invoke" + mkJavaParams(Params);
- }
- else {
- return _javaInvoke;
- }
- }
- set { _javaInvoke = value; }
- }
-
public DelegateRepTemplate()
: base()
{
@@ -2583,41 +2574,15 @@ namespace Twiglet.CS2J.Translator.TypeRep
public DelegateRepTemplate(DelegateRepTemplate copyFrom)
: base(copyFrom)
{
- foreach (ParamRepTemplate p in copyFrom.Params)
+ if (copyFrom.Invoke != null)
{
- Params.Add(new ParamRepTemplate(p));
+ Invoke = copyFrom.Invoke;
}
-
- if (!String.IsNullOrEmpty(copyFrom.Return))
- {
- Return = copyFrom.Return;
- }
- if (!String.IsNullOrEmpty(copyFrom.JavaInvoke))
- {
- JavaInvoke = copyFrom.JavaInvoke;
- }
- }
-
- public DelegateRepTemplate(string retType, List args)
- : base()
- {
- Return = retType;
- _params = args;
}
public override void Apply(Dictionary args)
{
- if (Params != null)
- {
- foreach(ParamRepTemplate p in Params)
- {
- p.Apply(args);
- }
- }
- if (Return != null)
- {
- Return = TemplateUtilities.SubstituteInType(Return, args);
- }
+ Invoke.Apply(args);
base.Apply(args);
}
public override TypeRepTemplate Instantiate(ICollection args)
@@ -2633,16 +2598,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
if (other == null)
return false;
- if (Params != other.Params) {
- if (Params == null || other.Params == null || Params.Count != other.Params.Count)
- return false;
- for (int i = 0; i < Params.Count; i++) {
- if (Params[i] != other.Params[i])
- return false;
- }
- }
-
- return Return == other.Return && JavaInvoke == other.JavaInvoke && base.Equals(other);
+ return Invoke == other.Invoke && base.Equals(other);
}
public override bool Equals (object obj)
@@ -2668,12 +2624,8 @@ namespace Twiglet.CS2J.Translator.TypeRep
public override int GetHashCode ()
{
int hashCode = base.GetHashCode ();
- if (Params != null) {
- foreach (ParamRepTemplate e in Params) {
- hashCode ^= e.GetHashCode();
- }
- }
- return (Return ?? String.Empty).GetHashCode() ^ (JavaInvoke ?? String.Empty).GetHashCode() ^ hashCode;
+
+ return (Invoke ?? new InvokeRepTemplate()).GetHashCode() ^ hashCode;
}
#endregion
}
@@ -2897,6 +2849,56 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
}
}
+ // Look for a property which holds a delegate with the right type
+ if (Properties != null)
+ {
+ foreach (PropRepTemplate p in Properties)
+ {
+ if (p.Name == name)
+ {
+ // Is p's type a delegate?
+ DelegateRepTemplate del = BuildType(p.Type, AppEnv, null) as DelegateRepTemplate;
+ if (del != null)
+ {
+ bool matchingArgs = true;
+ if (del.Invoke.Params == null || args == null)
+ {
+ // Are they both zero length?
+ matchingArgs = (del.Invoke.Params == null || del.Invoke.Params.Count == 0) && (args == null || args.Count == 0);
+ }
+ else
+ {
+ // Are num args the same?
+ if (del.Invoke.Params.Count != args.Count)
+ {
+ matchingArgs = false;
+ }
+ else
+ {
+ // check that for each argument in the caller its type 'IsA' the type of the formal argument
+ for (int idx = 0; idx < del.Invoke.Params.Count; idx++) {
+ if (args[idx] == null || !args[idx].IsA(BuildType(del.Invoke.Params[idx].Type, AppEnv, new UnknownRepTemplate(del.Invoke.Params[idx].Type)),AppEnv))
+ {
+ matchingArgs = false;
+ break;
+ }
+ }
+ }
+ }
+ if (matchingArgs)
+ {
+ ResolveResult delRes = new ResolveResult();
+ delRes.Result = del;
+ delRes.ResultType = BuildType(del.Invoke.Return, AppEnv);
+ DelegateResolveResult res = new DelegateResolveResult();
+ res.Result = p;
+ res.ResultType = BuildType(p.Type, AppEnv);
+ res.DelegateResult = delRes;
+ return res; }
+ }
+ }
+ }
+ }
return base.Resolve(name, args, AppEnv);
}
@@ -3202,6 +3204,63 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
+ public override ResolveResult Resolve(String name, List args, DirectoryHT AppEnv)
+ {
+
+ // Look for a property which holds a delegate with the right type
+ if (Fields != null)
+ {
+ foreach (FieldRepTemplate f in Fields)
+ {
+ if (f.Name == name)
+ {
+ // Is f's type a delegate?
+ DelegateRepTemplate del = BuildType(f.Type, AppEnv, null) as DelegateRepTemplate;
+ if (del != null)
+ {
+ bool matchingArgs = true;
+ if (del.Invoke.Params == null || args == null)
+ {
+ // Are they both zero length?
+ matchingArgs = (del.Invoke.Params == null || del.Invoke.Params.Count == 0) && (args == null || args.Count == 0);
+ }
+ else
+ {
+ // Are num args the same?
+ if (del.Invoke.Params.Count != args.Count)
+ {
+ matchingArgs = false;
+ }
+ else
+ {
+ // check that for each argument in the caller its type 'IsA' the type of the formal argument
+ for (int idx = 0; idx < del.Invoke.Params.Count; idx++) {
+ if (args[idx] == null || !args[idx].IsA(BuildType(del.Invoke.Params[idx].Type, AppEnv, new UnknownRepTemplate(del.Invoke.Params[idx].Type)),AppEnv))
+ {
+ matchingArgs = false;
+ break;
+ }
+ }
+ }
+ }
+ if (matchingArgs)
+ {
+ ResolveResult delRes = new ResolveResult();
+ delRes.Result = del;
+ delRes.ResultType = BuildType(del.Invoke.Return, AppEnv);
+ DelegateResolveResult res = new DelegateResolveResult();
+ res.Result = f;
+ res.ResultType = BuildType(f.Type, AppEnv);
+ res.DelegateResult = delRes;
+ return res;
+ }
+ }
+ }
+ }
+ }
+ return base.Resolve(name, args, AppEnv);
+ }
+
public override ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv)
{
@@ -3585,6 +3644,13 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
-
+ // Used when the result of resolving the callee of an APPLY node is a pointer to a delegate
+ public class DelegateResolveResult : ResolveResult
+ {
+ public ResolveResult DelegateResult
+ {
+ get; set;
+ }
+ }
}
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaMaker.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaMaker.g
index 7291be6..cfe5996 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaMaker.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaMaker.g
@@ -190,6 +190,99 @@ scope TypeContext {
return root;
}
+ protected CommonTree mkGenericArgs(IToken tok, List tyVars) {
+ if (tyVars == null || tyVars.Count == 0) {
+ return null;
+ }
+
+ CommonTree root = (CommonTree)adaptor.Nil;
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
+ bool isFirst = true;
+ foreach (string v in tyVars) {
+ if (!isFirst) {
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(COMMA, tok, ","));
+ }
+ isFirst = false;
+ CommonTree ty = (CommonTree)adaptor.Nil;
+ ty = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), ty);
+ adaptor.AddChild(ty, (CommonTree)adaptor.Create(IDENTIFIER, tok, v));
+ adaptor.AddChild(root, ty);
+ }
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(GT, tok, ">"));
+ return root;
+
+ }
+
+ protected CommonTree mkPackage(IToken tok, CommonTree tree, String nameSpace) {
+
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(PACKAGE, tok, "package"), root);
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(PAYLOAD, tok, nameSpace));
+ adaptor.AddChild(root, dupTree(tree));
+ return root;
+ }
+
+ protected CommonTree mkFlattenDictionary(IToken tok, Dictionary treeDict) {
+
+ CommonTree root = (CommonTree)adaptor.Nil;
+ foreach (CommonTree tree in treeDict.Values) {
+ if (tree != null) {
+ adaptor.AddChild(root, dupTree(tree));
+ }
+ }
+ root = (CommonTree)adaptor.RulePostProcessing(root);
+ return root;
+ }
+
+ protected CommonTree mkArgsFromParams(IToken tok, CommonTree pars) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), root);
+
+ // take every second child
+ for (int i = 1; i < adaptor.GetChildCount(pars); i+=2) {
+ adaptor.AddChild(root, dupTree((CommonTree)adaptor.GetChild(pars, i)));
+ }
+ root = (CommonTree)adaptor.RulePostProcessing(root);
+ return root;
+ }
+
+ protected CommonTree mkType(IToken tok, CommonTree id, List tyVars) {
+
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), root);
+ adaptor.AddChild(root, dupTree(id));
+
+ if (tyVars != null && tyVars.Count > 0) {
+ adaptor.AddChild(root, mkGenericArgs(tok, tyVars));
+ }
+
+ return root;
+ }
+
+ protected string mkTypeString(string tyName, List tyargs) {
+ StringBuilder ty = new StringBuilder();
+ ty.Append(tyName);
+ ty.Append(mkTypeArgString(tyargs));
+ return ty.ToString();
+ }
+
+ protected string mkTypeArgString(List tyargs) {
+ StringBuilder ty = new StringBuilder();
+ if (tyargs != null && tyargs.Count > 0) {
+ ty.Append("<");
+ bool isFirst = true;
+ foreach (String v in tyargs) {
+ if (!isFirst) {
+ ty.Append(",");
+ }
+ isFirst = false;
+ ty.Append(v);
+ }
+ ty.Append(">");
+ }
+ return ty.ToString();
+ }
+
// for ["conn", "conn1", "conn2"] generate:
//
// if (conn != null)
@@ -384,31 +477,38 @@ namespace_member_declaration
}
@after {
if (isCompUnit) {
- if (CUKeys.Contains(ns+"."+$ty.name)) {
- { Warning($ty.start.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + ns+"."+$ty.name); }
- }
- else {
- CUMap.Add(ns+"."+$ty.name, new CUnit($namespace_member_declaration.tree,CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces));
- CUKeys.Add(ns+"."+$ty.name);
- }
- };
-}
-:
+ foreach (KeyValuePair treeEntry in $ty.compUnits) {
+ if (treeEntry.Value != null) {
+ if (CUKeys.Contains(ns+"."+treeEntry.Key)) {
+ { Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + ns+"."+treeEntry.Key); }
+ }
+ else {
+ CUMap.Add(ns+"."+treeEntry.Key, new CUnit(mkPackage(treeEntry.Value.Token, treeEntry.Value, ns),CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces));
+ CUKeys.Add(ns+"."+treeEntry.Key);
+ }
+ }
+ };
+ }
+}:
namespace_declaration
- | attributes? modifiers? ty=type_declaration[$attributes.tree, mangleModifiersForType($modifiers.tree)] { isCompUnit = true; } -> ^(PACKAGE[$ty.start.Token, "package"] PAYLOAD[ns] $ty);
+ | attributes? modifiers? ty=type_declaration[$attributes.tree, mangleModifiersForType($modifiers.tree)] { isCompUnit = true; }
+ ;
// type_declaration is only called at the top level, so each of the types declared
// here will become a Java compilation unit (and go to its own file)
-type_declaration[CommonTree atts, CommonTree mods] returns [string name]
+type_declaration[CommonTree atts, CommonTree mods] returns [Dictionary compUnits]
+@init {
+ $compUnits = new Dictionary();
+}
:
('partial') => p='partial'! { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); }
- (pc=class_declaration[$atts, $mods, true /* toplevel */] { $name=$pc.name; }
- | ps=struct_declaration[$atts, $mods, true /* toplevel */] { $name=$ps.name; }
- | pi=interface_declaration[$atts, $mods] { $name=$pi.name; })
- | c=class_declaration[$atts, $mods, true /* toplevel */] { $name=$c.name; }
- | s=struct_declaration[$atts, $mods, true /* toplevel */] { $name=$s.name; }
- | i=interface_declaration[$atts, $mods] { $name=$i.name; }
- | e=enum_declaration[$atts, $mods] { $name=$e.name; }
- | d=delegate_declaration[$atts, $mods] { $name=$d.name; }
+ (pc=class_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($pc.name, $pc.tree); }
+ | ps=struct_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($ps.name, $ps.tree); }
+ | pi=interface_declaration[$atts, $mods] { $compUnits.Add($pi.name, $pi.tree); } )
+ | c=class_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($c.name, $c.tree); }
+ | s=struct_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($s.name, $s.tree); }
+ | i=interface_declaration[$atts, $mods] { $compUnits.Add($i.name, $i.tree); }
+ | e=enum_declaration[$atts, $mods] { $compUnits.Add($e.name, $e.tree); }
+ | d=delegate_declaration[$atts, $mods] { $compUnits = $d.compUnits; }
;
// Identifiers
qualified_identifier returns [string thetext]:
@@ -448,7 +548,7 @@ class_member_declaration:
| cd=class_declaration[$a.tree, $m.tree, false /* toplevel */] -> $cd
| sd=struct_declaration[$a.tree, $m.tree, false /* toplevel */] -> $sd
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
- | dd=delegate_declaration[$a.tree, $m.tree] -> $dd
+ | dd=delegate_declaration[$a.tree, $m.tree] -> { mkFlattenDictionary($dd.tree.Token,$dd.compUnits) }
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
| con3=constructor_declaration[$a.tree, $m.tree, $m.modList] -> $con3
| de3=destructor_declaration -> $de3
@@ -462,12 +562,8 @@ primary_expression:
// keving:TODO fixup
| 'new' ( (object_creation_expression ('.'|'->'|'[')) =>
(oc1=object_creation_expression -> $oc1) (pp4=primary_expression_part[ $primary_expression.tree ] -> $pp4 )+ // new Foo(arg, arg).Member
- // try the simple one first, this has no argS and no expressions
- // symantically could be object creation
- // keving: No, try object_creation_expression first, it could be new type ( xx ) {}
- // can also match delegate_creation, will have to distinguish in NetMaker.g
| (object_creation_expression) => oc2=object_creation_expression -> $oc2
- | delegate_creation_expression -> delegate_creation_expression // new FooDelegate (MyFunction)
+ // | delegate_creation_expression -> delegate_creation_expression // new FooDelegate (MyFunction)
| anonymous_object_creation_expression -> anonymous_object_creation_expression) // new {int X, string Y}
| sizeof_expression // sizeof (struct)
| checked_expression // checked (...
@@ -617,9 +713,9 @@ unchecked_expression:
default_value_expression:
'default'^ '('! type ')'! ;
anonymous_method_expression:
- 'delegate'^ explicit_anonymous_function_signature? block;
+ 'delegate'^ explicit_anonymous_function_signature? block;
explicit_anonymous_function_signature:
- '(' explicit_anonymous_function_parameter_list? ')' ;
+ '(' explicit_anonymous_function_parameter_list? ')' -> ^(PARAMS explicit_anonymous_function_parameter_list?);
explicit_anonymous_function_parameter_list:
explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)* ;
explicit_anonymous_function_parameter:
@@ -875,16 +971,16 @@ conditional_expression:
lambda_expression:
anonymous_function_signature '=>' anonymous_function_body;
anonymous_function_signature:
- '(' (explicit_anonymous_function_parameter_list
- | implicit_anonymous_function_parameter_list)? ')'
- | implicit_anonymous_function_parameter_list
+ '(' (explicit_anonymous_function_parameter_list -> ^(PARAMS explicit_anonymous_function_parameter_list)
+ | implicit_anonymous_function_parameter_list -> ^(PARAMS_TYPELESS implicit_anonymous_function_parameter_list))? ')'
+ | implicit_anonymous_function_parameter_list -> ^(PARAMS_TYPELESS implicit_anonymous_function_parameter_list)
;
implicit_anonymous_function_parameter_list:
implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)* ;
implicit_anonymous_function_parameter:
identifier;
anonymous_function_body:
- expression
+ expression -> OPEN_BRACE[$expression.tree.Token, "{"] expression CLOSE_BRACE[$expression.tree.Token, "}"]
| block ;
///////////////////////////////////////////////////////
@@ -1107,8 +1203,13 @@ method_body [bool smotherExceptions] returns [CommonTree exceptionList]:
;
throw_exceptions:
- {IsJavaish}?=> 'throws'! t1=identifier { $t1.tree.Type = EXCEPTION; } (','! tn=identifier { $tn.tree.Type = EXCEPTION; } )*
+ {IsJavaish}?=> 'throws'! javaException (','! javaException)*
;
+
+javaException:
+ identifier -> EXCEPTION[$identifier.tree.Token, $identifier.tree.Token.Text]
+;
+
member_name returns [string rawId, string full_name]
@init {
$full_name = "";
@@ -1234,14 +1335,39 @@ integral_type:
'sbyte' | 'byte' | 'short' | 'ushort' | 'int' | 'uint' | 'long' | 'ulong' | 'char' ;
// B.2.12 Delegates
-delegate_declaration[CommonTree atts, CommonTree mods] returns [string name]
+delegate_declaration[CommonTree atts, CommonTree mods] returns [Dictionary compUnits]
scope TypeContext;
+@init {
+ $compUnits = new Dictionary();
+ CommonTree delClassMemberNodes = null;
+ CommonTree ifTree = null;
+ String delName = "";
+ String multiDelName = "";
+}
+@after {
+ $compUnits.Add(delName, dupTree($delegate_declaration.tree));
+}
:
- d='delegate' return_type identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list?
- '(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';' magicInvoker[$d.token, $return_type.tree, $identifier.tree, $formal_parameter_list.tree] ->
+ d='delegate' return_type identifier { delName = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list? {ifTree = mkType($d.token, $identifier.tree, $variant_generic_parameter_list.tyargs); }
+ '(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';'
+ magicDelegateInterface[$d.token, $return_type.tree, $identifier.tree, $formal_parameter_list.tree, $variant_generic_parameter_list.tyargs]
+ magicMultiInvokerMethod[$d.token, $return_type.tree, $return_type.thetext == "Void" || $return_type.thetext == "System.Void", ifTree, $formal_parameter_list.tree, mkArgsFromParams($d.token, $formal_parameter_list.tree), $variant_generic_parameter_list.tyargs]
+ {
+ multiDelName = "__Multi" + delName;
+ delClassMemberNodes = this.parseString("class_member_declarations", Fragments.MultiDelegateMethods(mkTypeString(delName, $variant_generic_parameter_list.tyargs), mkTypeString(multiDelName, $variant_generic_parameter_list.tyargs),mkTypeArgString($variant_generic_parameter_list.tyargs)));
+ AddToImports("java.util.List");
+ AddToImports("java.util.ArrayList");
+ AddToImports("CS2JNet.JavaSupport.util.ListSupport");
+ }
+ magicMultiDelClass[$d.token, $atts, $mods, multiDelName, ifTree, $type_parameter_constraints_clauses.tree, $variant_generic_parameter_list.tree, $magicMultiInvokerMethod.tree, delClassMemberNodes]
+ {
+ $compUnits.Add(multiDelName, $magicMultiDelClass.tree);
+ }
+ ->
// ^(DELEGATE[$d.token, "DELEGATE"] { dupTree($atts) } { dupTree($mods) } return_type identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
// '(' formal_parameter_list? ')' );
- ^(INTERFACE[$d.token, "interface"] { dupTree($atts) } { dupTree($mods) } identifier type_parameter_constraints_clauses? variant_generic_parameter_list? magicInvoker);
+ ^(INTERFACE[$d.token, "interface"] { dupTree($atts) } { dupTree($mods) } identifier { dupTree($type_parameter_constraints_clauses.tree) } { dupTree($variant_generic_parameter_list.tree) } magicDelegateInterface)
+ ;
delegate_modifiers:
modifier+ ;
// 4.0
@@ -1279,9 +1405,9 @@ type_variable_name:
// keving: TOTEST we drop new constraints, but what will happen in Java for this case?
constructor_constraint:
'new' '(' ')' ;
-return_type:
- type
- | void_type ;
+return_type returns [string thetext]:
+ type {$thetext = $type.thetext; }
+ | void_type {$thetext = "System.Void"; };
formal_parameter_list returns [int numArgs]
@init {
$numArgs = 0;
@@ -1917,9 +2043,59 @@ magicThrowsException[bool isOn, IToken tok]:
->
;
-magicInvoker[IToken tok, CommonTree return_type, CommonTree identifier, CommonTree formal_parameter_list]:
- magicThrowsException[true, tok]
--> OPEN_BRACE[tok, "{"]
- ^(METHOD[tok, "METHOD"] { dupTree(return_type) } IDENTIFIER[tok,"Invoke"] { dupTree(formal_parameter_list) } magicThrowsException)
+magicDelegateInterface[IToken tok, CommonTree return_type, CommonTree identifier, CommonTree formal_parameter_list, List tyArgs]
+@init {
+ AddToImports("java.util.List");
+}:
+ e1=magicThrowsException[true, tok]
+ e2=magicThrowsException[true, tok]
+-> OPEN_BRACE[tok, "{"] // System.Collections.Generic.IList
+ ^(METHOD[tok, "METHOD"] { dupTree(return_type) } IDENTIFIER[tok,"Invoke"] { dupTree(formal_parameter_list) } $e1)
+ ^(METHOD[tok, "METHOD"] ^(TYPE ^(DOT[tok, "."] ^(DOT[tok, "."] ^(DOT[tok, "."] IDENTIFIER[tok, "System"] IDENTIFIER[tok, "Collections"]) IDENTIFIER[tok, "Generic"]) IDENTIFIER[tok, "IList"] LTHAN[tok,"<"] ^(TYPE { dupTree( identifier) } { mkGenericArgs(tok, tyArgs) }) GT[tok,">"])) IDENTIFIER[tok,"GetInvocationList"] $e2)
CLOSE_BRACE[tok, "}"]
;
+
+// First execute all but the last one, then execute the last one and (if non-void) return its result.
+magicMultiInvokerMethod[IToken tok, CommonTree return_type, bool retIsVoid, CommonTree type, CommonTree formal_parameter_list, CommonTree argument_list, List tyArgs]
+:
+ e1=magicThrowsException[true, tok]
+-> {retIsVoid}?
+ ^(METHOD[tok, "METHOD"] PUBLIC[tok, "public"] { dupTree($return_type) } IDENTIFIER[tok,"Invoke"] { dupTree($formal_parameter_list) }
+ OPEN_BRACE[tok, "{"]
+ ^(FOREACH[tok, "foreach"]
+ { $type } IDENTIFIER[tok, "d"] ^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] THIS[tok,"this"] IDENTIFIER[tok,"GetInvocationList"]))
+ SEP[tok, "SEP"]
+ OPEN_BRACE[tok, "{"]
+ ^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,"d"] IDENTIFIER[tok,"Invoke"]) { $argument_list }) SEMI[tok, ";"]
+ CLOSE_BRACE[tok, "}"]
+ )
+ CLOSE_BRACE[tok, "}"]
+ magicThrowsException
+ )
+-> ^(METHOD[tok, "METHOD"] PUBLIC[tok, "public"] { dupTree($return_type) } IDENTIFIER[tok,"Invoke"] { dupTree($formal_parameter_list) }
+ OPEN_BRACE[tok, "{"]
+ { $type } IDENTIFIER[tok, "prev"] ASSIGN[tok, "="] NULL[tok, "null"] SEMI[tok,";"]
+ ^(FOREACH[tok, "foreach"]
+ { $type } IDENTIFIER[tok, "d"] ^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] THIS[tok,"this"] IDENTIFIER[tok,"GetInvocationList"]))
+ SEP[tok, "SEP"]
+ OPEN_BRACE[tok, "{"]
+ ^(IF[tok, "if"] ^(NOT_EQUAL[tok, "!="] IDENTIFIER[tok,"prev"] NULL[tok, "null"]) SEP ^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,"prev"] IDENTIFIER[tok,"Invoke"]) { $argument_list }) SEMI[tok, ";"])
+ IDENTIFIER[tok, "prev"] ASSIGN[tok, "="] IDENTIFIER[tok, "d"] SEMI[tok,";"]
+ CLOSE_BRACE[tok, "}"]
+ )
+ ^(RETURN[tok, "return"] ^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,"prev"] IDENTIFIER[tok,"Invoke"]) { $argument_list }))
+ CLOSE_BRACE[tok, "}"]
+ magicThrowsException
+ )
+;
+
+magicPackage[IToken tok, CommonTree cu, String ns]:
+-> { $cu != null }? ^(PACKAGE[tok, "package"] PAYLOAD[tok, ns] { dupTree(cu) })
+->
+;
+
+magicMultiDelClass[IToken tok, CommonTree atts, CommonTree mods, string className, CommonTree delIface, CommonTree paramConstraints, CommonTree tyParamList, CommonTree invokeMethod, CommonTree members]:
+-> ^(CLASS[tok, "class"] { dupTree($atts) } { dupTree($mods) } IDENTIFIER[tok, className] { dupTree(paramConstraints) } { dupTree(tyParamList) } ^(IMPLEMENTS[tok, "implements"] { dupTree(delIface) })
+ OPEN_BRACE[tok, "{"] {dupTree(invokeMethod)} { dupTree(members) } CLOSE_BRACE[tok, "}"])
+;
+
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
index 50949db..7eb699b 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
@@ -156,6 +156,7 @@ options {
precedence[i] = int.MaxValue;
}
precedence[ASSIGN] = 1;
+ precedence[LAMBDA] = 1;
precedence[PLUS_ASSIGN] = 1;
precedence[MINUS_ASSIGN] = 1;
precedence[STAR_ASSIGN] = 1;
@@ -378,7 +379,7 @@ primary_expression returns [int precedence]
// | ('base' brackets) => 'this' brackets primary_expression_part*
// | primary_expression_start primary_expression_part*
| ^(NEW type argument_list? object_or_collection_initializer?) { $precedence = precedence[NEW]; }-> construct(type = {$type.st}, args = {$argument_list.st}, inits = {$object_or_collection_initializer.st})
- | ^(NEW_DELEGATE delegate_creation_expression) // new FooDelegate (MyFunction)
+ | ^(NEW_DELEGATE type argument_list? class_body) -> delegate(type = {$type.st}, args = {$argument_list.st}, body={$class_body.st})
| ^(NEW_ANON_OBJECT anonymous_object_creation_expression) // new {int X, string Y}
| sizeof_expression // sizeof (struct)
| checked_expression -> { $checked_expression.st } // checked (...
@@ -430,7 +431,7 @@ primary_expression_part:
access_identifier:
access_operator type_or_generic ;
access_operator returns [int precedence]:
- (op='.' | op='->') { $precedence = precedence[$op.token.Type]; } -> string(payload = { $op.token.Text }) ;
+ (op=DOT | op='->') { $precedence = precedence[$op.token.Type]; } -> string(payload = { $op.token.Text }) ;
brackets_or_arguments:
brackets | arguments ;
brackets:
@@ -479,15 +480,25 @@ rank_specifier:
// dim_separators:
// ','+ ;
-wrapped returns [int precedence]:
+wrapped returns [int precedence]
+@init {
+ $precedence = int.MaxValue;
+ Dictionary templateMap = new Dictionary();
+}:
^(JAVAWRAPPEREXPRESSION expression) { $precedence = $expression.precedence; } -> { $expression.st }
| ^(JAVAWRAPPERARGUMENT argument_value) { $precedence = $argument_value.precedence; } -> { $argument_value.st }
- | ^(JAVAWRAPPERTYPE type) { $precedence = int.MaxValue; } -> { $type.st }
+ | ^(JAVAWRAPPERTYPE type) -> { $type.st }
+ | ^(JAVAWRAPPER t=identifier
+ (k=identifier v=wrapped
+ {
+ templateMap[$k.st.ToString()] = new ReplacementDescriptor($v.st != null ? $v.st.ToString() : "", $v.precedence);
+ }
+ )*) -> string(payload = {fillTemplate($t.st.ToString(), templateMap)})
;
-delegate_creation_expression:
+//delegate_creation_expression:
// 'new'
- type_name '(' type_name ')' ;
+// type_name '(' type_name ')' ;
anonymous_object_creation_expression:
// 'new'
anonymous_object_initializer ;
@@ -504,7 +515,7 @@ primary_or_array_creation_expression returns [int precedence]:
// new Type[2] { }
array_creation_expression returns [int precedence]:
^(NEW_ARRAY
- (type ('[' expression_list ']' rank_specifiers? ai1=array_initializer? -> array_construct(type = { $type.st }, args = { $expression_list.st }, inits = { $ai1.st }) // new int[4]
+ (type ('[' expression_list? ']' rank_specifiers? ai1=array_initializer? -> array_construct(type = { $type.st }, args = { $expression_list.st }, inits = { $ai1.st }) // new int[4]
| ai2=array_initializer -> array_construct(type = { $type.st }, inits = { $ai2.st })
)
| rank_specifier array_initializer // var a = new[] { 1, 10, 100, 1000 }; // int[]
@@ -552,16 +563,7 @@ default_value_expression
} -> unsupported(reason = {"default expressions are not yet supported"}, text = { someText } )
;
anonymous_method_expression:
- ^('delegate' explicit_anonymous_function_signature? block);
-explicit_anonymous_function_signature:
- '(' explicit_anonymous_function_parameter_list? ')' ;
-explicit_anonymous_function_parameter_list:
- explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)* ;
-explicit_anonymous_function_parameter:
- anonymous_function_parameter_modifier? type identifier;
-anonymous_function_parameter_modifier:
- 'ref' | 'out';
-
+ ^('delegate' formal_parameter_list? block);
///////////////////////////////////////////////////////
object_creation_expression:
@@ -785,7 +787,7 @@ non_assignment_expression returns [int precedence]
$precedence = int.MaxValue;
}:
//'non ASSIGNment'
- (anonymous_function_signature '=>') => lambda_expression
+ (anonymous_function_signature '=>') => lambda_expression { $precedence = precedence[LAMBDA]; } -> { $lambda_expression.st; }
| (query_expression) => query_expression
| ^(cop=COND_EXPR ce1=non_assignment_expression ce2=expression ce3=expression) { $precedence = precedence[$cop.token.Type]; }
-> cond( condexp = { $ce1.st }, thenexp = { $ce2.st }, elseexp = { $ce3.st },
@@ -809,19 +811,20 @@ non_assignment_expression returns [int precedence]
// lambda Section
///////////////////////////////////////////////////////
lambda_expression:
- anonymous_function_signature '=>' anonymous_function_body;
+ anonymous_function_signature? '=>' block
+ {
+ StringTemplate lambdaText = %lambda();
+ %{lambdaText}.args = $anonymous_function_signature.st;
+ %{lambdaText}.body = $block.st;
+ $st = %unsupported();
+ %{$st}.reason = "to translate lambda expressions we need an explicit delegate type, try adding a cast";
+ %{$st}.text = lambdaText;
+ }
+ ;
anonymous_function_signature:
- '(' (explicit_anonymous_function_parameter_list
- | implicit_anonymous_function_parameter_list)? ')'
- | implicit_anonymous_function_parameter_list
+ ^(PARAMS fps+=formal_parameter+) -> list(items= {$fps}, sep={", "})
+ | ^(PARAMS_TYPELESS ids+=identifier+) -> list(items= {$ids}, sep={", "})
;
-implicit_anonymous_function_parameter_list:
- implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)* ;
-implicit_anonymous_function_parameter:
- identifier;
-anonymous_function_body:
- expression
- | block ;
///////////////////////////////////////////////////////
// LINQ Section
@@ -1286,9 +1289,9 @@ jump_statement:
| ^('return' expression?) -> return(exp = { $expression.st })
| ^('throw' expression?) -> throw(exp = { $expression.st });
goto_statement:
- 'goto' ( identifier
- | 'case' constant_expression
- | 'default') ';' ;
+ 'goto' ( identifier -> op(op={"goto"}, post={$identifier.st})
+ | 'case' constant_expression -> op(op={"goto case"}, post={$constant_expression.st})
+ | 'default' -> string(payload={"goto default"}) ) ';' ;
catch_clauses:
c+=catch_clause+ -> seplist(items={ $c }, sep = { "\n" }) ;
catch_clause:
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
index 23718fe..142de08 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
@@ -517,6 +517,249 @@ scope MkNonGeneric {
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(rhs));
return root;
}
+
+ // either ^(PARAMS (type identifier)*) or ^(ARGS identifier*) depending on value of formal
+ protected CommonTree mkParams(List inParams, bool formal, IToken tok) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(formal ? PARAMS : ARGS, tok, formal ? "PARAMS" : "ARGS"), root);
+ foreach (ParamRepTemplate p in inParams) {
+ if (formal) {
+ TypeRepTemplate ty = findType(p.Type);
+ CommonTree typeRoot = (CommonTree)adaptor.Nil;
+ typeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), typeRoot);
+ adaptor.AddChild(typeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, ty.Java));
+ adaptor.AddChild(root, typeRoot);
+ AddToImports(ty.Imports);
+ }
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, p.Name));
+ }
+ return root;
+ }
+
+ // make ^(PARAMS (type identifier)*) from a List for the names
+ protected CommonTree mkTypedParams(List inParams, List ids, IToken tok) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(PARAMS, tok, "PARAMS"), root);
+ CommonTree[] idsArray = ids.ToArray();
+ int i = 0;
+ foreach (ParamRepTemplate p in inParams) {
+ TypeRepTemplate ty = findType(p.Type);
+ CommonTree typeRoot = (CommonTree)adaptor.Nil;
+ typeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), typeRoot);
+ adaptor.AddChild(typeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, ty.Java));
+ adaptor.AddChild(root, typeRoot);
+ AddToImports(ty.Imports);
+ adaptor.AddChild(root, dupTree(idsArray[i]));
+ i++;
+ }
+ return root;
+ }
+
+ // public List GetInvocationList() throws Exception {
+ // List ret = new ArrayList();
+ // ret.add(this);
+ // return ret;
+ // }
+ protected CommonTree mkDelegateGetInvocationList(CommonTree delTree, TypeRepTemplate delType, IToken tok) {
+
+// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
+ CommonTree method = (CommonTree)adaptor.Nil;
+ method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
+
+ CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
+ retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
+ adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, "List"));
+ AddToImports("java.util.List");
+ adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
+ CommonTree delTypeRoot = (CommonTree)adaptor.Nil;
+ if (delTree != null) {
+ delTypeRoot = dupTree(delTree);
+ }
+ else {
+ delTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTypeRoot);
+ adaptor.AddChild(delTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, delType.Java));
+ AddToImports(delType.Imports);
+ }
+ adaptor.AddChild(retTypeRoot, delTypeRoot);
+
+ adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(GT, tok, ">"));
+
+ adaptor.AddChild(method, retTypeRoot);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "GetInvocationList"));
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
+
+
+ CommonTree body = (CommonTree)adaptor.Nil;
+
+ // List ret = new ArrayList();
+ CommonTree retdecl = (CommonTree)adaptor.Nil;
+
+ adaptor.AddChild(retdecl, dupTree(retTypeRoot));
+ adaptor.AddChild(retdecl, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
+ adaptor.AddChild(retdecl, (CommonTree)adaptor.Create(ASSIGN, tok, "="));
+
+ CommonTree newA = (CommonTree)adaptor.Nil;
+ newA = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW, tok, "new"), newA);
+
+ CommonTree alTypeRoot = (CommonTree)adaptor.Nil;
+ alTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), alTypeRoot);
+ adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ArrayList"));
+ AddToImports("java.util.ArrayList");
+ adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
+
+ adaptor.AddChild(alTypeRoot, dupTree(delTypeRoot));
+
+ adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(GT, tok, ">"));
+
+ adaptor.AddChild(newA, alTypeRoot);
+ adaptor.AddChild(retdecl, newA);
+ adaptor.AddChild(body, retdecl);
+ adaptor.AddChild(body, (CommonTree)adaptor.Create(SEMI, tok, ";"));
+
+ // ret.add(this)
+ CommonTree retaddcall = (CommonTree)adaptor.Nil;
+ retaddcall = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(APPLY, tok, "APPLY"), retaddcall);
+
+ CommonTree retadd = (CommonTree)adaptor.Nil;
+ retadd = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(DOT, tok, "."), retadd);
+ adaptor.AddChild(retadd, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
+ adaptor.AddChild(retadd, (CommonTree)adaptor.Create(IDENTIFIER, tok, "add"));
+
+ adaptor.AddChild(retaddcall, retadd);
+
+ CommonTree arg = (CommonTree)adaptor.Nil;
+ arg = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), arg);
+
+ adaptor.AddChild(arg, (CommonTree)adaptor.Create(THIS, tok, "this"));
+ adaptor.AddChild(retaddcall, arg);
+ adaptor.AddChild(body,retaddcall);
+ adaptor.AddChild(body, (CommonTree)adaptor.Create(SEMI, tok, ";"));
+
+ // return ret;
+ CommonTree ret = (CommonTree)adaptor.Nil;
+ ret = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(RETURN, tok, "return"), ret);
+ adaptor.AddChild(ret, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
+ adaptor.AddChild(body,ret);
+
+ adaptor.AddChild(method, body);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
+
+ return method;
+ }
+
+ // new () { public void Invoke() throws Exception { [return] arg[0](); }
+ // public List GetInvocationList() throws Exception { ... }}
+ protected CommonTree mkDelegateObject(CommonTree delTree, CommonTree methTree, DelegateRepTemplate delg, IToken tok) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW_DELEGATE, tok, "NEW_DELEGATE"), root);
+ if (delTree != null) {
+ adaptor.AddChild(root, dupTree(delTree));
+ }
+ else {
+ CommonTree delTyTree = (CommonTree)adaptor.Nil;
+ delTyTree = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTyTree);
+ adaptor.AddChild(delTyTree, (CommonTree)adaptor.Create(IDENTIFIER, tok, delg.Java));
+ AddToImports(delg.Imports);
+ adaptor.AddChild(root, delTyTree);
+ }
+
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
+
+// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
+ CommonTree method = (CommonTree)adaptor.Nil;
+ method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
+
+ TypeRepTemplate returnType = findType(delg.Invoke.Return);
+ AddToImports(returnType.Imports);
+ CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
+ retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
+ adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, returnType.Java));
+ adaptor.AddChild(method, retTypeRoot);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "Invoke"));
+ if (delg.Invoke.Params.Count > 0) {
+ adaptor.AddChild(method, mkParams(delg.Invoke.Params, true, tok));
+ }
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
+
+ CommonTree ret = (CommonTree)adaptor.Nil;
+ ret = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(RETURN, tok, "return"), ret);
+
+ CommonTree call = (CommonTree)adaptor.Nil;
+ call = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(APPLY, tok, "APPLY"), call);
+ adaptor.AddChild(call, dupTree(methTree));
+ if (delg.Invoke.Params.Count > 0) {
+ adaptor.AddChild(call, mkParams(delg.Invoke.Params, false, tok));
+ }
+ if (returnType.IsA(voidType, AppEnv)) {
+ adaptor.AddChild(ret, call);
+ adaptor.AddChild(method, ret);
+ }
+ else {
+ adaptor.AddChild(method, call);
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(SEMI, tok, ";"));
+ }
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
+ adaptor.AddChild(root, method);
+ adaptor.AddChild(root, mkDelegateGetInvocationList(delTree, delg, tok));
+
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
+
+ return root;
+ }
+
+ // new () { public void Invoke() throw exception }
+ protected CommonTree mkDelegateObject(CommonTree delTree, CommonTree argsTree, CommonTree bodyTree, DelegateRepTemplate delg, IToken tok) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW_DELEGATE, tok, "NEW_DELEGATE"), root);
+ if (delTree != null) {
+ adaptor.AddChild(root, dupTree(delTree));
+ }
+ else {
+ CommonTree delTyTree = (CommonTree)adaptor.Nil;
+ delTyTree = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTyTree);
+ adaptor.AddChild(delTyTree, (CommonTree)adaptor.Create(IDENTIFIER, tok, delg.Java));
+ AddToImports(delg.Imports);
+ adaptor.AddChild(root, delTyTree);
+ }
+
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
+
+// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
+ CommonTree method = (CommonTree)adaptor.Nil;
+ method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
+
+ TypeRepTemplate returnType = findType(delg.Invoke.Return);
+ AddToImports(returnType.Imports);
+ CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
+ retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
+ adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, returnType.Java));
+ adaptor.AddChild(method, retTypeRoot);
+
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "Invoke"));
+ adaptor.AddChild(method, dupTree(argsTree));
+ adaptor.AddChild(method, dupTree(bodyTree));
+ adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
+ adaptor.AddChild(root, method);
+ adaptor.AddChild(root, mkDelegateGetInvocationList(delTree, delg, tok));
+
+ adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
+
+ return root;
+ }
+
}
public compilation_unit
@@ -589,7 +832,7 @@ constructor_declaration
// rmId is the rightmost ID in an expression like fdfd.dfdsf.returnme, otherwise it is null
// used in switch labels to strip down qualified types, which Java doesn't grok
// thedottedtext is the text read so far that *might* be part of a qualified type
-primary_expression returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
+primary_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
scope {
bool parentIsApply;
}
@@ -605,7 +848,7 @@ scope {
if (ret != null)
$primary_expression.tree = ret;
}:
- ^(index=INDEX ie=expression expression_list?)
+ ^(index=INDEX ie=expression[ObjectType] expression_list?)
{
expType = $ie.dotNetType ?? (new UnknownRepTemplate("INDEXER.BASE"));
if (expType.IsUnknownType) {
@@ -635,26 +878,26 @@ scope {
WarningFailedResolve($index.token.Line, "Could not resolve index expression against " + expType.TypeName);
}
}
- | (^(APPLY (^('.' expression identifier)|identifier) argument_list?)) =>
- ^(APPLY (^(d0='.' e2=expression {expType = $e2.dotNetType; implicitThis = false;} i2=identifier)|i2=identifier) argument_list?)
+ | (^(APPLY (^('.' expression[ObjectType] identifier generic_argument_list?)|(identifier generic_argument_list?)) argument_list?)) =>
+ ^(APPLY (^(d0='.' e2=expression[ObjectType] {expType = $e2.dotNetType; implicitThis = false;} i2=identifier generic_argument_list?)|(i2=identifier generic_argument_list?)) argument_list?)
{
if (implicitThis && SymTabLookup($i2.thetext) != null) {
- // we have a delegate reference (I hope ...)?
+ // we have a local var with a delegate reference (I hope ...)?
DelegateRepTemplate idType = SymTabLookup($i2.thetext) as DelegateRepTemplate;
if (idType != null) {
Dictionary myMap = new Dictionary();
myMap["this"] = wrapExpression($i2.tree, $i2.tree.Token);
- for (int idx = 0; idx < idType.Params.Count; idx++) {
- myMap[idType.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $i2.tree.Token);
- if (idType.Params[idx].Name.StartsWith("TYPEOF") && $argument_list.argTreeTypeofTypes[idx] != null) {
+ for (int idx = 0; idx < idType.Invoke.Params.Count; idx++) {
+ myMap[idType.Invoke.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $i2.tree.Token);
+ if (idType.Invoke.Params[idx].Name.StartsWith("TYPEOF") && $argument_list.argTreeTypeofTypes[idx] != null) {
// if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
- myMap[idType.Params[idx].Name + "_TYPE"] = wrapTypeOfType($argument_list.argTreeTypeofTypes[idx], $i2.tree.Token);
+ myMap[idType.Invoke.Params[idx].Name + "_TYPE"] = wrapTypeOfType($argument_list.argTreeTypeofTypes[idx], $i2.tree.Token);
}
}
- AddToImports(idType.Imports);
- ret = mkJavaWrapper(idType.JavaInvoke, myMap, $i2.tree.Token);
- $dotNetType = AppEnv.Search(idType.Return);
- }
+ AddToImports(idType.Invoke.Imports);
+ ret = mkJavaWrapper(idType.Invoke.Java, myMap, $i2.tree.Token);
+ $dotNetType = AppEnv.Search(idType.Invoke.Return);
+ }
}
else {
@@ -665,40 +908,54 @@ scope {
WarningFailedResolve($i2.tree.Token.Line, "Could not find type needed to resolve method application");
}
$dotNetType = new UnknownRepTemplate(expType.TypeName+".APPLY");
- ResolveResult methodResult = expType.Resolve($i2.thetext, $argument_list.argTypes ?? new List(), AppEnv);
- if (methodResult != null) {
- if (!String.IsNullOrEmpty(methodResult.Result.Warning)) Warning($d0.line, methodResult.Result.Warning);
+ ResolveResult calleeResult = expType.Resolve($i2.thetext, $argument_list.argTypes ?? new List(), AppEnv);
+ if (calleeResult != null) {
+ if (!String.IsNullOrEmpty(calleeResult.Result.Warning)) Warning($d0.line, calleeResult.Result.Warning);
DebugDetail($i2.tree.Token.Line + ": Found '" + $i2.thetext + "'");
-
- // We are calling a method on an expression. If it has a primitive type then cast it to
+
+ // We are calling a method or a delegate on an expression. If it has a primitive type then cast it to
// the appropriate Object type.
CommonTree e2InBox = expType.IsUnboxedType && Cfg.ExperimentalTransforms ? castToBoxedType(expType, $e2.tree, $d0.token) : $e2.tree;
-
- MethodRepTemplate methodRep = methodResult.Result as MethodRepTemplate;
Dictionary myMap = new Dictionary();
- if (!implicitThis) {
- myMap["this"] = wrapExpression(e2InBox, $i2.tree.Token);
+ MethodRepTemplate calleeMethod = null;
+
+ if (calleeResult is DelegateResolveResult) {
+ // We have a field/property that is pointing at a delegate, first extract the delegate ...
+ Dictionary delMap = new Dictionary();
+ if (!implicitThis) {
+ delMap["this"] = wrapExpression(e2InBox, $i2.tree.Token);
+ }
+ myMap["this"] = mkJavaWrapper(calleeResult.Result.Java, delMap, $i2.tree.Token);
+ AddToImports(calleeResult.Result.Imports);
+ calleeMethod = ((DelegateRepTemplate)((DelegateResolveResult)calleeResult).DelegateResult.Result).Invoke;
}
- for (int idx = 0; idx < methodRep.Params.Count; idx++) {
- myMap[methodRep.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $i2.tree.Token);
- if (methodRep.Params[idx].Name.StartsWith("TYPEOF") && $argument_list.argTreeTypeofTypes[idx] != null) {
+ else {
+ if (!implicitThis) {
+ myMap["this"] = wrapExpression(e2InBox, $i2.tree.Token);
+ }
+ calleeMethod = calleeResult.Result as MethodRepTemplate;
+ }
+
+ for (int idx = 0; idx < calleeMethod.Params.Count; idx++) {
+ myMap[calleeMethod.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $i2.tree.Token);
+ if (calleeMethod.Params[idx].Name.StartsWith("TYPEOF") && $argument_list.argTreeTypeofTypes[idx] != null) {
// if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
- myMap[methodRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($argument_list.argTreeTypeofTypes[idx], $i2.tree.Token);
+ myMap[calleeMethod.Params[idx].Name + "_TYPE"] = wrapTypeOfType($argument_list.argTreeTypeofTypes[idx], $i2.tree.Token);
}
}
- ret = mkJavaWrapper(methodResult.Result.Java, myMap, $i2.tree.Token);
- AddToImports(methodResult.Result.Imports);
- $dotNetType = methodResult.ResultType;
+ ret = mkJavaWrapper(calleeMethod.Java, myMap, $i2.tree.Token);
+ AddToImports(calleeMethod.Imports);
+ $dotNetType = calleeResult.ResultType;
}
else {
WarningFailedResolve($i2.tree.Token.Line, "Could not resolve method application of " + $i2.thetext + " against " + expType.TypeName);
}
}
}
- | ^(APPLY {$primary_expression::parentIsApply = true; } expression {$primary_expression::parentIsApply = false; } argument_list?)
- | (^((POSTINC|POSTDEC) (^('.' expression identifier) | identifier))) =>
- (^(POSTINC {popstr = "+";} (^('.' pse=expression pi=identifier {implicitThis = false;}) | pi=identifier))
- | ^(POSTDEC {popstr = "-";} (^('.' pse=expression pi=identifier {implicitThis = false;}) | pi=identifier)))
+ | ^(APPLY {$primary_expression::parentIsApply = true; } expression[ObjectType] {$primary_expression::parentIsApply = false; } argument_list?)
+ | (^((POSTINC|POSTDEC) (^('.' expression[objectType] identifier) | identifier))) =>
+ (^(POSTINC {popstr = "+";} (^('.' pse=expression[ObjectType] pi=identifier {implicitThis = false;}) | pi=identifier))
+ | ^(POSTDEC {popstr = "-";} (^('.' pse=expression[ObjectType] pi=identifier {implicitThis = false;}) | pi=identifier)))
{
if (implicitThis && SymTabLookup($pi.thetext) != null) {
// Is this a wrapped parameter?
@@ -762,108 +1019,69 @@ scope {
WarningFailedResolve($pi.tree.Token.Line, "Could not resolve field or property expression against " + seType.ToString());
}
}
- }
-
- | ^(POSTINC expression) { $dotNetType = $expression.dotNetType; }
- | ^(POSTDEC expression) { $dotNetType = $expression.dotNetType; }
- | ^(d1='.' e1=expression i1=identifier generic_argument_list?)
+ }
+ | ^(POSTINC expression[ObjectType]) { $dotNetType = $expression.dotNetType; }
+ | ^(POSTDEC expression[ObjectType]) { $dotNetType = $expression.dotNetType; }
+ | ^('->' expression[ObjectType] identifier generic_argument_list?)
+ | predefined_type { $dotNetType = $predefined_type.dotNetType; }
+ | 'this' { $dotNetType = SymTabLookup("this"); }
+ | SUPER { $dotNetType = SymTabLookup("super"); }
+ | (^(d1='.' e1=expression[ObjectType] {expType = $e1.dotNetType; implicitThis = false;} i=identifier)|i=identifier) generic_argument_list? magicInputPeId[$d1.tree,$i.tree,$generic_argument_list.tree]
{
// TODO: generic_argument_list is ignored ....
- // Possibilities:
- // - accessing a property/field of some object
- // - a qualified type name
- // - part of a qualified type name
- expType = $e1.dotNetType;
-
- // Is it a property read? Ensure we are not being applied to arguments or about to be assigned
- if (expType != null &&
- ($primary_expression.Count == 1 || !((primary_expression_scope)($primary_expression.ToArray()[1])).parentIsApply)) {
-
- DebugDetail($d1.token.Line + ": '" + $i1.thetext + "' might be a property");
-
- $dotNetType = new UnknownRepTemplate(expType.TypeName+".DOTACCESS."+ $i1.thetext);
-
- ResolveResult fieldResult = expType.Resolve($i1.thetext, false, AppEnv);
- if (fieldResult != null) {
- if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($d1.line, fieldResult.Result.Warning);
-
- // We are calling a method on an expression. If it has a primitive type then cast it to
- // the appropriate Object type.
- CommonTree e1InBox = $e1.dotNetType.IsUnboxedType && Cfg.ExperimentalTransforms ? castToBoxedType($e1.dotNetType, $e1.tree, $d1.token) : $e1.tree;
-
- Dictionary myMap = new Dictionary();
- myMap["this"] = wrapExpression(e1InBox, $i1.tree.Token);
- ret = mkJavaWrapper(fieldResult.Result.Java, myMap, $i1.tree.Token);
- AddToImports(fieldResult.Result.Imports);
- $dotNetType = fieldResult.ResultType;
- }
- else if ($e1.thedottedtext != null) {
- string staticType = $e1.thedottedtext + "." + $i1.thetext;
- $dotNetType = findType(staticType);
- if (!$dotNetType.IsUnknownType) {
- AddToImports($dotNetType.Imports);
- }
- else {
- // remember text so far
- $thedottedtext = staticType;
- }
- }
- else {
- // Could not find identifier in e1's type and we aren't building up a static type reference, so emit warning
- WarningFailedResolve($i1.tree.Token.Line, "Could not resolve identifier " + $i1.thetext + " against " + expType.TypeName);
- }
-
- }
- $rmId = $identifier.thetext;
- }
- | ^('->' expression identifier generic_argument_list?)
- | predefined_type { $dotNetType = $predefined_type.dotNetType; }
- | 'this' { $dotNetType = SymTabLookup("this"); }
- | SUPER { $dotNetType = SymTabLookup("super"); }
- | (identifier generic_argument_list) => identifier generic_argument_list
- | i=identifier
- {
// Possibilities:
// - a variable in scope.
- // - a property/field of current object
+ // - a property/field of some object
// - a type name
+ // - a method name if we are in a delegate type context then create a delegate (in C# it is an implicit cast)
// - part of a type name
bool found = false;
- TypeRepTemplate idType = SymTabLookup($identifier.thetext);
- if (idType != null) {
- // Is this a wrapped parameter?
- if (idType.IsWrapped) {
- Dictionary myMap = new Dictionary();
- myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
- ret = mkJavaWrapper("${this}.getValue()", myMap, $i.tree.Token);
- }
- $dotNetType = idType;
- found = true;
+ if (implicitThis) {
+ // single identifier, might be a variable
+ TypeRepTemplate idType = SymTabLookup($i.thetext);
+ if (idType != null) {
+ // Is this a wrapped parameter?
+ if (idType.IsWrapped) {
+ Dictionary myMap = new Dictionary();
+ myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
+ ret = mkJavaWrapper("${this}.getValue()", myMap, $i.tree.Token);
+ }
+ $dotNetType = idType;
+ found = true;
+ }
}
if (!found) {
- // Not a variable, is it a property?
- TypeRepTemplate thisType = SymTabLookup("this");
+ // Not a variable, expType is the type of 'expression', or 'this'.
// Is it a property read? Ensure we are not being applied to arguments or about to be assigned
- if (thisType != null && !thisType.IsUnknownType &&
+ if (expType != null && !expType.IsUnknownType &&
($primary_expression.Count == 1 || !((primary_expression_scope)($primary_expression.ToArray()[1])).parentIsApply)) {
- DebugDetail($identifier.tree.Token.Line + ": '" + $identifier.thetext + "' might be a property");
- ResolveResult fieldResult = thisType.Resolve($identifier.thetext, false, AppEnv);
+ DebugDetail($i.tree.Token.Line + ": '" + $i.thetext + "' might be a property");
+ ResolveResult fieldResult = expType.Resolve($i.thetext, false, AppEnv);
if (fieldResult != null) {
if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($i.tree.Token.Line, fieldResult.Result.Warning);
- DebugDetail($identifier.tree.Token.Line + ": Found '" + $identifier.thetext + "'");
- ret = mkJavaWrapper(fieldResult.Result.Java, null, $i.tree.Token);
+ DebugDetail($i.tree.Token.Line + ": Found '" + $i.thetext + "'");
+
+ Dictionary myMap = new Dictionary();
+ if (!implicitThis) {
+ // We are accessing a field / property on an expression. If it has a primitive type then cast it to
+ // the appropriate Object type.
+ CommonTree e1InBox = expType.IsUnboxedType && Cfg.ExperimentalTransforms ? castToBoxedType(expType, $e1.tree, $d1.token) : $e1.tree;
+ myMap["this"] = wrapExpression(e1InBox, $i.tree.Token);
+ }
+ ret = mkJavaWrapper(fieldResult.Result.Java, myMap, $i.tree.Token);
AddToImports(fieldResult.Result.Imports);
$dotNetType = fieldResult.ResultType;
found = true;
}
}
}
- if (!found) {
+ if (!found && (implicitThis || $e1.thedottedtext != null)) {
+ String textSoFar = (implicitThis ? "" : $e1.thedottedtext + ".") + $i.thetext;
// Not a variable, not a property read, is it a type name?
- TypeRepTemplate staticType = findType($i.thetext);
+ TypeRepTemplate staticType = findType(textSoFar);
if (!staticType.IsUnknownType) {
AddToImports(staticType.Imports);
$dotNetType = staticType;
@@ -871,10 +1089,25 @@ scope {
}
}
if (!found) {
- // Not a variable, not a property read, not a type, is it part of a type name?
- $dotNetType = new UnknownRepTemplate($identifier.thetext);
- $thedottedtext = $identifier.thetext;
+ // Could be a reference to a method group. If we are in a Delegate Type context then create a delegate object.
+ if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate) {
+ // Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
+ // use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
+ // new () { public void Invoke() throw exception { [return] arg[0](); } }
+ DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
+ ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $magicInputPeId.tree, delType, $i.tree.Token);
+ $dotNetType = $typeCtxt;
+ found = true;
+ }
}
+ if (!found) {
+ // Not a variable, not a property read, not a type, is it part of a type name?
+ $dotNetType = new UnknownRepTemplate($i.thetext);
+ $thedottedtext = (implicitThis || String.IsNullOrEmpty($e1.thedottedtext) ? "" : $e1.thedottedtext + ".") + $i.thetext;
+ }
+ $rmId = $i.thetext;
+ if (ret == null)
+ ret = $magicInputPeId.tree;
}
| primary_expression_start { $dotNetType = $primary_expression_start.dotNetType; }
| literal { $dotNetType = $literal.dotNetType; }
@@ -883,6 +1116,26 @@ scope {
// | primary_expression_start primary_expression_part*
| ^(n=NEW type argument_list? object_or_collection_initializer?)
{
+ // look for delegate creation
+ if ($type.dotNetType is DelegateRepTemplate && $argument_list.argTypes != null && $argument_list.argTypes.Count > 0) {
+
+ // argument_list should consist of just a single expression, either a method group or a value of a delegate type.
+ // If its a delegate type, then that is the result of this expression otherwise we create a delegte object.
+ if ($argument_list.argTypes[0] is DelegateRepTemplate) {
+ ret = dupTree((CommonTree)adaptor.GetChild($argument_list.tree, 0));
+ $dotNetType = $argument_list.argTypes[0];
+ }
+ else {
+ // Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
+ // use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
+ // new () { public void Invoke() throw exception { [return] arg[0](); } }
+ DelegateRepTemplate delType = $type.dotNetType as DelegateRepTemplate;
+ ret = mkDelegateObject($type.tree, (CommonTree)adaptor.GetChild($argument_list.tree, 0), delType, $n.token);
+ $dotNetType = $type.dotNetType;
+ }
+ }
+ else {
+ // assume object constructor
ClassRepTemplate conType = $type.dotNetType as ClassRepTemplate;
$dotNetType = $type.dotNetType;
if (conType == null) {
@@ -911,14 +1164,24 @@ scope {
else if ($argument_list.argTypes != null && $argument_list.argTypes.Count > 0) { // assume we have a zero-arg constructor, so don't print warning
WarningFailedResolve($n.token.Line, "Could not resolve constructor against " + conType.TypeName);
}
+ }
}
- | ^(NEW_DELEGATE delegate_creation_expression) // new FooDelegate (MyFunction)
| ^(NEW_ANON_OBJECT anonymous_object_creation_expression) // new {int X, string Y}
| sizeof_expression // sizeof (struct)
| checked_expression // checked (...
| unchecked_expression // unchecked {...}
| default_value_expression // default
- | anonymous_method_expression // delegate (int foo) {}
+ | ^(d='delegate' formal_parameter_list? block)
+ {
+ if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate) {
+ // Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
+ // use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
+ // new () { public void Invoke() throw exception { [return] arg[0](); } }
+ DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
+ ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $formal_parameter_list.tree, $block.tree, delType, $d.token);
+ $dotNetType = $typeCtxt;
+ }
+ }
| typeof_expression { $dotNetType = $typeof_expression.dotNetType; $typeofType = $typeof_expression.typeofType; } // typeof(Foo).Name
;
@@ -939,8 +1202,8 @@ brackets_or_arguments:
brackets | arguments ;
brackets:
'[' expression_list? ']' ;
-paren_expression:
- '(' expression ')' ;
+paren_expression[TypeRepTemplate typeCtxt]:
+ '(' expression[$typeCtxt] ')' ;
arguments:
'(' argument_list? ')' ;
argument_list returns [List argTypes, List argTrees, List argTreeTypeofTypes]
@@ -961,7 +1224,7 @@ argument_value returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]
@init {
string refVar = null;
}:
- expression { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; }
+ expression[ObjectType] { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; }
| ref_variable_reference { $dotNetType = $ref_variable_reference.dotNetType; $typeofType = $ref_variable_reference.typeofType; }
| o='out' variable_reference { refVar = "refVar___" + dummyRefVarCtr++; }
magicCreateOutVar[$o.token, refVar, ($variable_reference.dotNetType != null ? (CommonTree)$variable_reference.dotNetType.Tree : null)]
@@ -995,7 +1258,7 @@ ref_variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate type
;
// lvalue
variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]:
- expression { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; };
+ expression[ObjectType] { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; };
rank_specifiers[TypeRepTemplate inTy] returns [TypeRepTemplate dotNetType]
@init {
TypeRepTemplate ty = $inTy;
@@ -1018,10 +1281,10 @@ anonymous_object_initializer:
member_declarator_list:
member_declarator (',' member_declarator)* ;
member_declarator:
- qid ('=' expression)? ;
-primary_or_array_creation_expression returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]:
+ qid ('=' expression[ObjectType])? ;
+primary_or_array_creation_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]:
(array_creation_expression) => array_creation_expression { $dotNetType = $array_creation_expression.dotNetType; $thedottedtext = null; }
- | primary_expression { $dotNetType = $primary_expression.dotNetType; $rmId = $primary_expression.rmId; $typeofType = $primary_expression.typeofType; $thedottedtext = $primary_expression.thedottedtext; }
+ | primary_expression[$typeCtxt] { $dotNetType = $primary_expression.dotNetType; $rmId = $primary_expression.rmId; $typeofType = $primary_expression.typeofType; $thedottedtext = $primary_expression.thedottedtext; }
;
// new Type[2] { }
array_creation_expression returns [TypeRepTemplate dotNetType]:
@@ -1037,26 +1300,15 @@ array_initializer:
variable_initializer_list:
variable_initializer (',' variable_initializer)* ;
variable_initializer:
- expression | array_initializer ;
+ expression[ObjectType] | array_initializer ;
sizeof_expression:
^('sizeof' unmanaged_type );
checked_expression:
- ^('checked' expression ) ;
+ ^('checked' expression[ObjectType] ) ;
unchecked_expression:
- ^('unchecked' expression ) ;
+ ^('unchecked' expression[ObjectType] ) ;
default_value_expression:
^('default' type ) ;
-anonymous_method_expression:
- ^('delegate' explicit_anonymous_function_signature? block);
-explicit_anonymous_function_signature:
- '(' explicit_anonymous_function_parameter_list? ')' ;
-explicit_anonymous_function_parameter_list:
- explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)* ;
-explicit_anonymous_function_parameter:
- anonymous_function_parameter_modifier? type identifier;
-anonymous_function_parameter_modifier:
- 'ref' | 'out';
-
///////////////////////////////////////////////////////
object_creation_expression:
@@ -1073,7 +1325,7 @@ collection_initializer:
element_initializer_list:
element_initializer (',' element_initializer)* ;
element_initializer:
- non_assignment_expression
+ non_assignment_expression[ObjectType]
| '{' expression_list '}' ;
// object-initializer eg's
// Rectangle r = new Rectangle {
@@ -1088,7 +1340,7 @@ member_initializer_list:
member_initializer:
identifier '=' initializer_value ;
initializer_value:
- expression
+ expression[ObjectType]
| object_or_collection_initializer ;
///////////////////////////////////////////////////////
@@ -1288,10 +1540,10 @@ statement_list:
///////////////////////////////////////////////////////
// Expression Section
///////////////////////////////////////////////////////
-expression returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
+expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
:
- (unary_expression assignment_operator) => assignment { $dotNetType = VoidType; $thedottedtext = null;}
- | non_assignment_expression { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; $typeofType = $non_assignment_expression.typeofType; $thedottedtext = $non_assignment_expression.thedottedtext; }
+ (unary_expression[ObjectType] assignment_operator) => assignment { $dotNetType = VoidType; $thedottedtext = null;}
+ | non_assignment_expression[$typeCtxt] { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; $typeofType = $non_assignment_expression.typeofType; $thedottedtext = $non_assignment_expression.thedottedtext; }
;
expression_list returns [List expTypes, List expTrees, List expTreeTypeofTypes]
@init {
@@ -1299,26 +1551,52 @@ expression_list returns [List expTypes, List expTre
$expTrees = new List();
$expTreeTypeofTypes = new List();
}:
- e1=expression { $expTypes.Add($e1.dotNetType); $expTrees.Add(dupTree($e1.tree)); $expTreeTypeofTypes.Add($e1.typeofType); }
- (',' en=expression { $expTypes.Add($en.dotNetType); $expTrees.Add(dupTree($en.tree)); $expTreeTypeofTypes.Add($en.typeofType); })* ;
+ e1=expression[ObjectType] { $expTypes.Add($e1.dotNetType); $expTrees.Add(dupTree($e1.tree)); $expTreeTypeofTypes.Add($e1.typeofType); }
+ (',' en=expression[ObjectType] { $expTypes.Add($en.dotNetType); $expTrees.Add(dupTree($en.tree)); $expTreeTypeofTypes.Add($en.typeofType); })* ;
assignment
@init {
CommonTree ret = null;
bool isThis = false;
+ bool isLocalVar = false;
TypeRepTemplate expType = null;
+ TypeRepTemplate lhsType = ObjectType;
+
+ ResolveResult fieldResult = null;
+ ResolveResult indexerResult = null;
}
@after {
if (ret != null)
$assignment.tree = ret;
}:
- ((^('.' expression identifier generic_argument_list?) | identifier) assignment_operator) =>
- (^('.' se=expression i=identifier generic_argument_list?) | i=identifier { isThis = true;}) a=assignment_operator rhs=expression
+ ((^('.' expression[ObjectType] identifier generic_argument_list?) | identifier) assignment_operator) =>
+ (^('.' se=expression[ObjectType] i=identifier generic_argument_list?)
+ | i=identifier { isThis = true; })
+ {
+ TypeRepTemplate varType = SymTabLookup($i.thetext);
+ if (isThis && varType != null) {
+ isLocalVar = true;
+ lhsType = varType;
+ }
+ else {
+ expType = (isThis ? SymTabLookup("this") : $se.dotNetType);
+ if (expType == null) {
+ expType = new UnknownRepTemplate("FIELD.BASE");
+ }
+ if (expType.IsUnknownType) {
+ WarningFailedResolve($i.tree.Token.Line, "Could not find type of expression for field /property access");
+ }
+ fieldResult = expType.Resolve($i.thetext, true, AppEnv);
+ if (fieldResult != null) {
+ lhsType = fieldResult.ResultType ?? lhsType;
+ }
+ }
+ }
+ a=assignment_operator rhs=expression[lhsType]
{
- if (isThis && SymTabLookup($i.thetext) != null) {
+ if (isLocalVar) {
// Is this a wrapped parameter?
- TypeRepTemplate idType = SymTabLookup($i.thetext);
- if (idType.IsWrapped) {
+ if (lhsType.IsWrapped) {
Dictionary myMap = new Dictionary();
myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
myMap["value"] = wrapExpression($rhs.tree, $rhs.tree.Token);
@@ -1327,14 +1605,6 @@ assignment
// a simple variable assignment
}
else {
- TypeRepTemplate seType = (isThis ? SymTabLookup("this") : $se.dotNetType);
- if (seType == null) {
- seType = new UnknownRepTemplate("FIELD.BASE");
- }
- if (seType.IsUnknownType) {
- WarningFailedResolve($i.tree.Token.Line, "Could not find type of expression for field /property access");
- }
- ResolveResult fieldResult = seType.Resolve($i.thetext, true, AppEnv);
if (fieldResult != null) {
if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($i.tree.Token.Line, fieldResult.Result.Warning);
if (fieldResult.Result is PropRepTemplate) {
@@ -1346,7 +1616,7 @@ assignment
if ($a.tree.Token.Type != ASSIGN) {
// We have to resolve property reads and writes separately, because they may come from
// different parent classes
- ResolveResult readFieldResult = seType.Resolve($i.thetext, false, AppEnv);
+ ResolveResult readFieldResult = expType.Resolve($i.thetext, false, AppEnv);
if (readFieldResult.Result is PropRepTemplate) {
if (!String.IsNullOrEmpty(readFieldResult.Result.Warning)) Warning($i.tree.Token.Line, readFieldResult.Result.Warning);
PropRepTemplate readPropRep = readFieldResult.Result as PropRepTemplate;
@@ -1377,18 +1647,24 @@ assignment
}
}
else {
- WarningFailedResolve($i.tree.Token.Line, "Could not resolve field or property expression against " + seType.ToString());
+ WarningFailedResolve($i.tree.Token.Line, "Could not resolve field or property expression against " + expType.ToString());
}
}
}
- | (^(INDEX expression expression_list?) assignment_operator) =>
- ^(INDEX ie=expression expression_list?) ia=assignment_operator irhs=expression
- {
+ | (^(INDEX expression[ObjectType] expression_list?) assignment_operator) =>
+ ^(INDEX ie=expression[ObjectType] expression_list?)
+ {
expType = $ie.dotNetType ?? (new UnknownRepTemplate("INDEXER.BASE"));
if (expType.IsUnknownType) {
WarningFailedResolve($ie.tree.Token.Line, "Could not find type of expression for Indexer");
}
- ResolveResult indexerResult = expType.ResolveIndexer($expression_list.expTypes ?? new List(), AppEnv);
+ indexerResult = expType.ResolveIndexer($expression_list.expTypes ?? new List(), AppEnv);
+ if (indexerResult != null) {
+ lhsType = indexerResult.ResultType ?? lhsType;
+ }
+ }
+ ia=assignment_operator irhs=expression[lhsType]
+ {
if (indexerResult != null) {
if (!String.IsNullOrEmpty(indexerResult.Result.Warning)) Warning($ia.tree.Token.Line, indexerResult.Result.Warning);
IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
@@ -1438,26 +1714,26 @@ assignment
WarningFailedResolve($ie.tree.Token.Line, "Could not resolve index expression against " + expType.ToString());
}
}
- | unary_expression assignment_operator expression ;
+ | unary_expression[ObjectType] assignment_operator expression[ObjectType] ;
-unary_expression returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
+unary_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
@init {
$thedottedtext = null;
}:
//('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression
cast_expression { $dotNetType = $cast_expression.dotNetType; }
- | primary_or_array_creation_expression { $dotNetType = $primary_or_array_creation_expression.dotNetType; $rmId = $primary_or_array_creation_expression.rmId; $typeofType = $primary_or_array_creation_expression.typeofType; $thedottedtext = $primary_or_array_creation_expression.thedottedtext; }
- | ^(MONOPLUS u1=unary_expression) { $dotNetType = $u1.dotNetType; }
- | ^(MONOMINUS u2=unary_expression) { $dotNetType = $u2.dotNetType; }
- | ^(MONONOT u3=unary_expression) { $dotNetType = $u3.dotNetType; }
- | ^(MONOTWIDDLE u4=unary_expression) { $dotNetType = $u4.dotNetType; }
- | ^(PREINC u5=unary_expression) { $dotNetType = $u5.dotNetType; }
- | ^(PREDEC u6=unary_expression) { $dotNetType = $u6.dotNetType; }
- | ^(MONOSTAR unary_expression) { $dotNetType = ObjectType; }
- | ^(ADDRESSOF unary_expression) { $dotNetType = ObjectType; }
- | ^(PARENS expression) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; $typeofType = $expression.typeofType; }
+ | primary_or_array_creation_expression[$typeCtxt] { $dotNetType = $primary_or_array_creation_expression.dotNetType; $rmId = $primary_or_array_creation_expression.rmId; $typeofType = $primary_or_array_creation_expression.typeofType; $thedottedtext = $primary_or_array_creation_expression.thedottedtext; }
+ | ^(MONOPLUS u1=unary_expression[ObjectType]) { $dotNetType = $u1.dotNetType; }
+ | ^(MONOMINUS u2=unary_expression[ObjectType]) { $dotNetType = $u2.dotNetType; }
+ | ^(MONONOT u3=unary_expression[ObjectType]) { $dotNetType = $u3.dotNetType; }
+ | ^(MONOTWIDDLE u4=unary_expression[ObjectType]) { $dotNetType = $u4.dotNetType; }
+ | ^(PREINC u5=unary_expression[ObjectType]) { $dotNetType = $u5.dotNetType; }
+ | ^(PREDEC u6=unary_expression[ObjectType]) { $dotNetType = $u6.dotNetType; }
+ | ^(MONOSTAR unary_expression[ObjectType]) { $dotNetType = ObjectType; }
+ | ^(ADDRESSOF unary_expression[ObjectType]) { $dotNetType = ObjectType; }
+ | ^(PARENS expression[$typeCtxt]) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; $typeofType = $expression.typeofType; }
;
cast_expression returns [TypeRepTemplate dotNetType]
@@ -1468,7 +1744,7 @@ cast_expression returns [TypeRepTemplate dotNetType]
if (ret != null)
$cast_expression.tree = ret;
}:
- ^(c=CAST_EXPR type expression)
+ ^(c=CAST_EXPR type expression[$type.dotNetType ?? ObjectType])
{
$dotNetType = $type.dotNetType;
if ($type.dotNetType != null && $expression.dotNetType != null) {
@@ -1504,7 +1780,7 @@ shortcut_assignment_operator: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '
//addressof_expression:
// '&' unary_expression ;
-non_assignment_expression returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
+non_assignment_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
scope MkNonGeneric, PrimitiveRep;
@init {
$MkNonGeneric::scrubGenericArgs = false;
@@ -1515,16 +1791,16 @@ scope MkNonGeneric, PrimitiveRep;
$thedottedtext = null;
}:
//'non ASSIGNment'
- (anonymous_function_signature '=>') => lambda_expression
+ (anonymous_function_signature[null]? '=>') => lambda_expression[$typeCtxt] { $dotNetType = $lambda_expression.dotNetType; }
| (query_expression) => query_expression
- | ^(COND_EXPR non_assignment_expression e1=expression e2=expression) {$dotNetType = $e1.dotNetType; }
- | ^('??' n1=non_assignment_expression non_assignment_expression) {$dotNetType = $n1.dotNetType; }
- | ^('||' n2=non_assignment_expression non_assignment_expression) {$dotNetType = $n2.dotNetType; }
- | ^('&&' n3=non_assignment_expression non_assignment_expression) {$dotNetType = $n3.dotNetType; }
- | ^('|' n4=non_assignment_expression non_assignment_expression) {$dotNetType = $n4.dotNetType; }
- | ^('^' n5=non_assignment_expression non_assignment_expression) {$dotNetType = $n5.dotNetType; }
- | ^('&' n6=non_assignment_expression non_assignment_expression) {$dotNetType = $n6.dotNetType; }
- | ^(eq='==' ne1=non_assignment_expression ne2=non_assignment_expression
+ | ^(COND_EXPR non_assignment_expression[ObjectType] e1=expression[ObjectType] e2=expression[ObjectType]) {$dotNetType = $e1.dotNetType; }
+ | ^('??' n1=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n1.dotNetType; }
+ | ^('||' n2=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n2.dotNetType; }
+ | ^('&&' n3=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n3.dotNetType; }
+ | ^('|' n4=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n4.dotNetType; }
+ | ^('^' n5=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n5.dotNetType; }
+ | ^('&' n6=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n6.dotNetType; }
+ | ^(eq='==' ne1=non_assignment_expression[ObjectType] ne2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $ne1.dotNetType != null && $ne2.dotNetType != null && ($ne1.dotNetType.IsExplicitNull || $ne2.dotNetType.IsExplicitNull);
@@ -1548,7 +1824,7 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$opde
->^($eq $ne1 $ne2)
- | ^(neq='!=' neqo1=non_assignment_expression neqo2=non_assignment_expression
+ | ^(neq='!=' neqo1=non_assignment_expression[ObjectType] neqo2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $neqo1.dotNetType != null && $neqo2.dotNetType != null && ($neqo1.dotNetType.IsExplicitNull || $neqo2.dotNetType.IsExplicitNull);
@@ -1574,7 +1850,7 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$opdne
->^($neq $neqo1 $neqo2)
- | ^(gt='>' gt1=non_assignment_expression gt2=non_assignment_expression
+ | ^(gt='>' gt1=non_assignment_expression[ObjectType] gt2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $gt1.dotNetType != null && $gt2.dotNetType != null && ($gt1.dotNetType.IsExplicitNull || $gt2.dotNetType.IsExplicitNull);
@@ -1590,7 +1866,7 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$opgt
->^($gt $gt1 $gt2)
- | ^(lt='<' lt1=non_assignment_expression lt2=non_assignment_expression
+ | ^(lt='<' lt1=non_assignment_expression[ObjectType] lt2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $lt1.dotNetType != null && $lt2.dotNetType != null && ($lt1.dotNetType.IsExplicitNull || $lt2.dotNetType.IsExplicitNull);
@@ -1606,7 +1882,7 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$oplt
->^($lt $lt1 $lt2)
- | ^(ge='>=' ge1=non_assignment_expression ge2=non_assignment_expression
+ | ^(ge='>=' ge1=non_assignment_expression[ObjectType] ge2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $ge1.dotNetType != null && $ge2.dotNetType != null && ($ge1.dotNetType.IsExplicitNull || $ge2.dotNetType.IsExplicitNull);
@@ -1622,7 +1898,7 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$opge
->^($ge $ge1 $ge2)
- | ^(le='<=' le1=non_assignment_expression le2=non_assignment_expression
+ | ^(le='<=' le1=non_assignment_expression[ObjectType] le2=non_assignment_expression[ObjectType]
{
// if One arg is null then leave original operator
nullArg = $le1.dotNetType != null && $le2.dotNetType != null && ($le1.dotNetType.IsExplicitNull || $le2.dotNetType.IsExplicitNull);
@@ -1638,72 +1914,68 @@ scope MkNonGeneric, PrimitiveRep;
-> {dateArgs}?
$ople
->^($le $le1 $le2)
- | ^(INSTANCEOF non_assignment_expression { $MkNonGeneric::scrubGenericArgs = true; $PrimitiveRep::primitiveTypeAsObject = true; } non_nullable_type) {$dotNetType = BoolType; }
- | ^('<<' n7=non_assignment_expression non_assignment_expression) {$dotNetType = $n7.dotNetType; }
- | ^(RIGHT_SHIFT n8=non_assignment_expression non_assignment_expression) {$dotNetType = $n8.dotNetType; }
+ | ^(INSTANCEOF non_assignment_expression[ObjectType] { $MkNonGeneric::scrubGenericArgs = true; $PrimitiveRep::primitiveTypeAsObject = true; } non_nullable_type) {$dotNetType = BoolType; }
+ | ^('<<' n7=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n7.dotNetType; }
+ | ^(RIGHT_SHIFT n8=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n8.dotNetType; }
// TODO: need to munge these numeric types
- | ^('+' n9=non_assignment_expression non_assignment_expression) {$dotNetType = $n9.dotNetType; }
- | ^('-' n10=non_assignment_expression non_assignment_expression) {$dotNetType = $n10.dotNetType; }
- | ^('*' n11=non_assignment_expression non_assignment_expression) {$dotNetType = $n11.dotNetType; }
- | ^('/' n12=non_assignment_expression non_assignment_expression) {$dotNetType = $n12.dotNetType; }
- | ^('%' n13=non_assignment_expression non_assignment_expression) {$dotNetType = $n13.dotNetType; }
+ | ^('+' n9=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n9.dotNetType; }
+ | ^('-' n10=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n10.dotNetType; }
+ | ^('*' n11=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n11.dotNetType; }
+ | ^('/' n12=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n12.dotNetType; }
+ | ^('%' n13=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n13.dotNetType; }
// | ^(UNARY_EXPRESSION unary_expression)
- | unary_expression {$dotNetType = $unary_expression.dotNetType; $rmId = $unary_expression.rmId; $typeofType = $unary_expression.typeofType; $thedottedtext = $unary_expression.thedottedtext; }
+ | unary_expression[$typeCtxt]
+ {
+ $dotNetType = $unary_expression.dotNetType;
+ $rmId = $unary_expression.rmId;
+ $typeofType = $unary_expression.typeofType;
+ $thedottedtext = $unary_expression.thedottedtext;
+ }
;
-// ///////////////////////////////////////////////////////
-// // Conditional Expression Section
-// ///////////////////////////////////////////////////////
-//
-// multiplicative_expression:
-// unary_expression ( ('*'|'/'|'%') unary_expression)* ;
-// additive_expression:
-// multiplicative_expression (('+'|'-') multiplicative_expression)* ;
-// // >> check needed (no whitespace)
-// shift_expression:
-// additive_expression (('<<'|'>' '>') additive_expression)* ;
-// relational_expression:
-// shift_expression
-// ( (('<'|'>'|'>='|'<=') shift_expression)
-// | (('is'|'as') non_nullable_type)
-// )* ;
-// equality_expression:
-// relational_expression
-// (('=='|'!=') relational_expression)* ;
-// and_expression:
-// equality_expression ('&' equality_expression)* ;
-// exclusive_or_expression:
-// and_expression ('^' and_expression)* ;
-// inclusive_or_expression:
-// exclusive_or_expression ('|' exclusive_or_expression)* ;
-// conditional_and_expression:
-// inclusive_or_expression ('&&' inclusive_or_expression)* ;
-// conditional_or_expression:
-// conditional_and_expression ('||' conditional_and_expression)* ;
-//
-// null_coalescing_expression:
-// conditional_or_expression ('??' conditional_or_expression)* ;
-// conditional_expression:
-// null_coalescing_expression ('?' expression ':' expression)? ;
-//
-
///////////////////////////////////////////////////////
// lambda Section
///////////////////////////////////////////////////////
-lambda_expression:
- anonymous_function_signature '=>' anonymous_function_body;
-anonymous_function_signature:
- '(' (explicit_anonymous_function_parameter_list
- | implicit_anonymous_function_parameter_list)? ')'
- | implicit_anonymous_function_parameter_list
+lambda_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType]
+@init {
+ CommonTree ret = null;
+}
+@after {
+ if (ret != null)
+ $lambda_expression.tree = ret;
+}:
+ anonymous_function_signature[$typeCtxt]? d='=>' block
+ {
+ if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate && $anonymous_function_signature.isTypedParams) {
+ // use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
+ // new () { public void Invoke() throw exception }
+ DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
+ ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $anonymous_function_signature.tree, $block.tree, delType, $d.token);
+ $dotNetType = $typeCtxt;
+ }
+ }
+ ;
+anonymous_function_signature[TypeRepTemplate typeCtxt] returns [bool isTypedParams]
+@init {
+ $isTypedParams = true;
+ CommonTree ret = null;
+ List ids = new List();
+}
+@after {
+ if (ret != null)
+ $anonymous_function_signature.tree = ret;
+}:
+ ^(PARAMS (parameter_modifier? type identifier)+)
+ | ^(p=PARAMS_TYPELESS (identifier { ids.Add($identifier.tree); })+)
+ {
+ if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate && ids.Count == ((DelegateRepTemplate)$typeCtxt).Invoke.Params.Count) {
+ ret = mkTypedParams(((DelegateRepTemplate)$typeCtxt).Invoke.Params, ids, $p.token);
+ }
+ else {
+ $isTypedParams = false;
+ }
+ }
;
-implicit_anonymous_function_parameter_list:
- implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)* ;
-implicit_anonymous_function_parameter:
- identifier;
-anonymous_function_body:
- expression
- | block ;
///////////////////////////////////////////////////////
// LINQ Section
@@ -1724,17 +1996,17 @@ query_body_clause:
| join_clause
| orderby_clause;
from_clause:
- 'from' type? identifier 'in' expression ;
+ 'from' type? identifier 'in' expression[ObjectType] ;
join_clause:
- 'join' type? identifier 'in' expression 'on' expression 'equals' expression ('into' identifier)? ;
+ 'join' type? identifier 'in' expression[ObjectType] 'on' expression[ObjectType] 'equals' expression[ObjectType] ('into' identifier)? ;
let_clause:
- 'let' identifier '=' expression;
+ 'let' identifier '=' expression[ObjectType];
orderby_clause:
'orderby' ordering_list ;
ordering_list:
ordering (',' ordering)* ;
ordering:
- expression ordering_direction
+ expression[ObjectType] ordering_direction
;
ordering_direction:
'ascending'
@@ -1743,13 +2015,13 @@ select_or_group_clause:
select_clause
| group_clause ;
select_clause:
- 'select' expression ;
+ 'select' expression[ObjectType] ;
group_clause:
- 'group' expression 'by' expression ;
+ 'group' expression[ObjectType] 'by' expression[ObjectType] ;
where_clause:
'where' boolean_expression ;
boolean_expression:
- expression;
+ expression[ObjectType];
///////////////////////////////////////////////////////
// B.2.13 Attributes
@@ -1792,7 +2064,7 @@ named_argument_list:
named_argument:
identifier '=' attribute_argument_expression ;
attribute_argument_expression:
- expression ;
+ expression[ObjectType] ;
///////////////////////////////////////////////////////
// Class Section
@@ -1919,7 +2191,7 @@ constant_declarators[TypeRepTemplate ty]:
constant_declarator[TypeRepTemplate ty]:
identifier { $SymTab::symtab[$identifier.thetext] = $ty; } ('=' constant_expression)? ;
constant_expression returns [string rmId]:
- expression {$rmId = $expression.rmId; };
+ expression[ObjectType] {$rmId = $expression.rmId; };
///////////////////////////////////////////////////////
field_declaration[CommonTree tyTree, TypeRepTemplate ty]:
@@ -2051,13 +2323,13 @@ scope PrimitiveRep;
bool isRefOut = false;
}:
(parameter_modifier { isRefOut = $parameter_modifier.isRefOut; if (isRefOut) { $PrimitiveRep::primitiveTypeAsObject = true; AddToImports("CS2JNet.JavaSupport.language.RefSupport");} })?
- type identifier { $type.dotNetType.IsWrapped = isRefOut; $SymTab::symtab[$identifier.thetext] = $type.dotNetType; } default_argument? magicRef[isRefOut, $type.tree.Token, $type.tree]
+ type identifier { $type.dotNetType.IsWrapped = isRefOut; $SymTab::symtab[$identifier.thetext] = $type.dotNetType; } default_argument? magicRef[isRefOut, $type.tree != null ? $type.tree.Token : null, $type.tree]
-> {isRefOut}? magicRef identifier default_argument?
-> parameter_modifier? type identifier default_argument?
;
// 4.0
default_argument:
- '=' expression;
+ '=' expression[ObjectType];
parameter_modifier returns [bool isRefOut]
@init {
$isRefOut = true;
@@ -2202,7 +2474,7 @@ embedded_statement[bool isStatementListCtxt]
| switch_statement[isStatementListCtxt]
| iteration_statement // while, do, for, foreach
| jump_statement
- | (^(('return' | 'throw') expression?)) => (^(jt='return' (je=expression {jumpStatementHasExpression = true;})?) | ^(jt='throw' (je=expression{ jumpStatementHasExpression = true; })?))
+ | (^(('return' | 'throw') expression[ObjectType]?)) => (^(jt='return' (je=expression[ObjectType] {jumpStatementHasExpression = true;})?) | ^(jt='throw' (je=expression[ObjectType]{ jumpStatementHasExpression = true; })?))
{ emitPrePost = adaptor.GetChildCount($statement::preStatements) > 0 || adaptor.GetChildCount($statement::postStatements) > 0;
if (emitPrePost) {
idName = "resVar___" + dummyVarCtr++;
@@ -2243,7 +2515,7 @@ scope {
$switch_statement::isFirstCase = true;
$switch_statement::defaultTree = null;
}:
- ^(s='switch' se=expression sv=magicScrutineeVar[$s.token]
+ ^(s='switch' se=expression[ObjectType] sv=magicScrutineeVar[$s.token]
{
if ($expression.dotNetType != null) {
$switch_statement::isEnum = $expression.dotNetType.IsA(AppEnv.Search("System.Enum"), AppEnv);
@@ -2272,7 +2544,7 @@ fixed_pointer_declarator:
identifier '=' fixed_pointer_initializer ;
fixed_pointer_initializer:
//'&' variable_reference // unary_expression covers this
- expression;
+ expression[ObjectType];
labeled_statement[bool isStatementListCtxt]:
^(':' identifier statement[isStatementListCtxt]) ;
declaration_statement:
@@ -2302,7 +2574,7 @@ local_variable_declarator[CommonTree tyTree, TypeRepTemplate ty]
}
}:
i=identifier { $SymTab::symtab[$i.thetext] = $ty; }
- (e='=' local_variable_initializer { hasInit = true; constructStruct = false; constructEnum = false; } )?
+ (e='=' local_variable_initializer[$ty ?? ObjectType] { hasInit = true; constructStruct = false; constructEnum = false; } )?
magicConstructStruct[constructStruct, $tyTree, ($i.tree != null ? $i.tree.Token : null)]
magicConstructDefaultEnum[constructEnum, $ty, zeroEnum, $identifier.tree != null ? $identifier.tree.Token : null]
// eg. event EventHandler IInterface.VariableName = Foo;
@@ -2311,20 +2583,20 @@ local_variable_declarator[CommonTree tyTree, TypeRepTemplate ty]
-> {constructEnum}? $i ASSIGN[$i.tree.Token, "="] magicConstructDefaultEnum
-> $i
;
-local_variable_initializer:
- expression
+local_variable_initializer[TypeRepTemplate typeCtxt]:
+ expression[$typeCtxt]
| array_initializer
| stackalloc_initializer;
stackalloc_initializer:
- 'stackalloc' unmanaged_type '[' expression ']' ;
+ 'stackalloc' unmanaged_type '[' expression[ObjectType] ']' ;
local_constant_declaration:
'const' type constant_declarators[$type.dotNetType] ;
expression_statement:
- expression ';' ;
+ expression[ObjectType] ';' ;
// TODO: should be assignment, call, increment, decrement, and new object expressions
statement_expression:
- expression
+ expression[ObjectType]
;
else_statement:
'else' embedded_statement[/* isStatementListCtxt */ false] ;
@@ -2392,7 +2664,7 @@ scope SymTab;
^('while' boolean_expression SEP embedded_statement[/* isStatementListCtxt */ false])
| do_statement
| ^('for' for_initializer? SEP for_condition? SEP for_iterator? SEP embedded_statement[/* isStatementListCtxt */ false])
- | ^(f='foreach' local_variable_type identifier expression s=SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement[/* isStatementListCtxt */ false])
+ | ^(f='foreach' local_variable_type identifier expression[ObjectType] s=SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement[/* isStatementListCtxt */ false])
magicObjectType[$f.token] magicForeachVar[$f.token]
{
newType = $local_variable_type.tree;
@@ -2475,9 +2747,9 @@ checked_statement:
unchecked_statement:
'unchecked' block ;
lock_statement:
- 'lock' '(' expression ')' embedded_statement[/* isStatementListCtxt */ false] ;
+ 'lock' '(' expression[ObjectType] ')' embedded_statement[/* isStatementListCtxt */ false] ;
yield_statement:
- 'yield' ('return' expression ';'
+ 'yield' ('return' expression[ObjectType] ';'
| 'break' ';') ;
///////////////////////////////////////////////////////
@@ -2840,3 +3112,8 @@ magicBoxedType[bool isOn, IToken tok, String boxedName]:
-> { isOn }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, boxedName])
->
;
+
+magicInputPeId[CommonTree dotTree, CommonTree idTree, CommonTree galTree]:
+ -> { dotTree != null}? {dupTree(dotTree)} { dupTree(galTree) }
+ -> {dupTree(idTree)} { dupTree(galTree) }
+;
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/TemplateExtracter.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/TemplateExtracter.g
index 445180f..1436678 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/TemplateExtracter.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/TemplateExtracter.g
@@ -867,6 +867,7 @@ scope NSContext;
$NSContext::searchpath = new List();
$NSContext::aliases = new List();
DelegateRepTemplate dlegate = new DelegateRepTemplate();
+ ClassRepTemplate multiDelegateClass = new ClassRepTemplate();
}
:
'delegate' return_type identifier variant_generic_parameter_list?
@@ -878,12 +879,26 @@ scope NSContext;
if ($variant_generic_parameter_list.tyargs != null && $variant_generic_parameter_list.tyargs.Count > 0) {
dlegate.TypeParams = $variant_generic_parameter_list.tyargs.ToArray();
}
- dlegate.Return=$return_type.thetext;
- dlegate.Params=$formal_parameter_list.paramlist;
+ dlegate.Invoke = new InvokeRepTemplate($return_type.thetext, "Invoke", null, $formal_parameter_list.paramlist);
AppEnv[genericNameSpace] = dlegate;
dlegate.Uses = this.CollectUses;
dlegate.Aliases = this.CollectAliases;
dlegate.Imports = new string[] {dlegate.TypeName};
+
+ // now add a class for the MultiDelegateClass that we will be generating
+ genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias("__Multi"+$identifier.text, $variant_generic_parameter_list.tyargs);
+ multiDelegateClass.TypeName = NSPrefix(ParentNameSpace) + "__Multi" + $identifier.text;
+ multiDelegateClass.Inherits = new String[] { dlegate.TypeName };
+ if ($variant_generic_parameter_list.tyargs != null && $variant_generic_parameter_list.tyargs.Count > 0) {
+ multiDelegateClass.TypeParams = $variant_generic_parameter_list.tyargs.ToArray();
+ }
+ multiDelegateClass.Methods.Add(new MethodRepTemplate($return_type.thetext, "Invoke", null, $formal_parameter_list.paramlist));
+ multiDelegateClass.Methods.Add(new MethodRepTemplate("System.Collections.Generic.List*[" + dlegate.TypeName + "]*", "GetInvocationList", null, null));
+ AppEnv[genericNameSpace] = multiDelegateClass;
+ multiDelegateClass.Uses = this.CollectUses;
+ multiDelegateClass.Aliases = this.CollectAliases;
+ multiDelegateClass.Imports = new string[] {multiDelegateClass.TypeName};
+
}
;
delegate_modifiers:
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTranslator.csproj b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTranslator.csproj
index c83425b..dba655a 100755
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTranslator.csproj
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTranslator.csproj
@@ -24,7 +24,7 @@
DEBUG;TRACE
prompt
4
- -translator-timestamp-files=false -translator-keep-parens=false -netdir=/Users/keving/gitrepos/cs2j/CS2JLibrary/NetFramework/ -dumpxmls -xmldir=/Users/keving/tmp/xml/se -odir=/Users/keving/tmp/java/se/src -appdir=/Users/keving/svnrepos/ScormEngineNet/src/app/ScormEngine.Core /Users/keving/svnrepos/ScormEngineNet/src/app/ScormEngine.Core/Logic/Integration/IntegrationInterface.cs
+ --debug 5 -experimental-transforms=true -translator-timestamp-files=false -translator-keep-parens=false -netdir=/Users/keving/gitrepos/cs2j/CS2JLibrary/NetFramework/ -dumpxmls -xmldir=/Users/keving/tmp/xml/libomv -odir=/Users/keving/tmp/java/libomv/src -csdir=/Users/keving/Projects/libomv-0.8.3-source/Programs/VisualParamGenerator/ -excsdir=/Users/keving/Projects/libomv-0.8.3-source/Programs/VisualParamGenerator/template.cs
x86
diff --git a/CSharpTranslator/antlr3/src/CSharpParser/cs.g b/CSharpTranslator/antlr3/src/CSharpParser/cs.g
index e5e43c4..f32469b 100644
--- a/CSharpTranslator/antlr3/src/CSharpParser/cs.g
+++ b/CSharpTranslator/antlr3/src/CSharpParser/cs.g
@@ -30,6 +30,7 @@ tokens {
DESTRUCTOR;
METHOD_HEADER;
PARAMS;
+ PARAMS_TYPELESS;
SWITCH_SECTION;
MONOPLUS;
@@ -126,6 +127,9 @@ tokens {
MOD = '%';
STAR = '*';
+ LAMBDA = '=>';
+ COMMA = ',';
+
TYPE;
TYPE_VAR;
TYPE_DYNAMIC;
@@ -271,6 +275,9 @@ public class_member_declaration:
)
;
+public java_delegate_creation_expression:
+ 'new' type '(' ')' '{' class_member_declaration '}';
+
public primary_expression:
('this' brackets) => 'this' brackets primary_expression_part*
| ('base' brackets) => 'base' brackets primary_expression_part*
@@ -771,12 +778,19 @@ public variable_declarator:
public method_declaration:
method_header method_body ;
public method_header:
- member_name '(' formal_parameter_list? ')' type_parameter_constraints_clauses? ;
+ member_name '(' formal_parameter_list? ')' type_parameter_constraints_clauses?
+ // Only have throw Exceptions if IsJavaish
+ throw_exceptions?
+;
public method_body:
block ;
public member_name:
qid ; // IInterface.Method logic added.
+throw_exceptions:
+ {IsJavaish}?=> 'throws' identifier (',' identifier)*
+ ;
+
///////////////////////////////////////////////////////
public property_declaration:
member_name '{' accessor_declarations '}' ;