diff --git a/CS2JLibrary/NetFramework/System/Collections/Generic/List'1.xml b/CS2JLibrary/NetFramework/System/Collections/Generic/List'1.xml
new file mode 100644
index 0000000..ceb917c
--- /dev/null
+++ b/CS2JLibrary/NetFramework/System/Collections/Generic/List'1.xml
@@ -0,0 +1,205 @@
+
+
+
+
+ java.util.ArrayList
+
+ ArrayList*[${T}]*
+ System.Collections.Generic.List
+
+ T
+
+
+
+
+
+
+
+
+ ${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
+
+
+
+
+
+
+
+
+
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
index f9c6157..d87343a 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTemplate/TranslationTemplate.cs
@@ -35,7 +35,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
return ret;
}
-
+
public static string SubstituteInType(String type, Dictionary argMap)
{
if (String.IsNullOrEmpty(type))
@@ -88,7 +88,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string Type {
get { return _type; }
set {
- _type=value.Replace('<','[').Replace('>',']');
+ _type=value.Replace("<","*[").Replace(">","]*");
}
}
public string Name { get; set; }
@@ -281,7 +281,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string SurroundingTypeName {
get { return _surroundingTypeName; }
set {
- _surroundingTypeName=value.Replace('<','[').Replace('>',']');
+ _surroundingTypeName=value.Replace("<","*[").Replace(">","]*");
}
}
public virtual string[] mkImports() {
@@ -632,15 +632,41 @@ namespace Twiglet.CS2J.Translator.TypeRep
// Method name
public string Name { get; set; }
+ private string[] _typeParams = null;
[XmlArrayItem("Name")]
- public string[] TypeParams { get; set; }
+ public string[] TypeParams {
+ get
+ {
+ if (_typeParams == null)
+ {
+ TypeParams = new string[0];
+ }
+ return _typeParams;
+ }
+ set
+ {
+ // First time that TypeParams is set then create InstantiatedTypes as corresponding list of TypeVars
+ if (value != null && InstantiatedTypes == null)
+ {
+ InstantiatedTypes = new TypeRepTemplate[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ {
+ InstantiatedTypes[i] = new TypeVarRepTemplate(value[i]);
+ }
+ }
+ _typeParams = value;
+ }
+ }
+
+ [XmlIgnore]
+ public TypeRepTemplate[] InstantiatedTypes { get; set; }
// Return type
private string _return;
public string Return {
get { return _return; }
set {
- _return=value.Replace('<','[').Replace('>',']');
+ _return=value.Replace("<","*[").Replace(">","]*");
}
}
@@ -670,6 +696,15 @@ namespace Twiglet.CS2J.Translator.TypeRep
TypeParams[i] = copyFrom.TypeParams[i];
}
}
+ if (copyFrom.InstantiatedTypes != null)
+ {
+ len = copyFrom.InstantiatedTypes.Length;
+ InstantiatedTypes = new TypeRepTemplate[len];
+ for (int i = 0; i < len; i++)
+ {
+ InstantiatedTypes[i] = copyFrom.InstantiatedTypes[i].Instantiate(null);
+ }
+ }
if (!String.IsNullOrEmpty(copyFrom.Return))
{
Return = copyFrom.Return;
@@ -749,6 +784,14 @@ namespace Twiglet.CS2J.Translator.TypeRep
return false;
}
}
+ if (InstantiatedTypes != other.InstantiatedTypes) {
+ if (InstantiatedTypes == null || other.InstantiatedTypes == null || InstantiatedTypes.Length != other.InstantiatedTypes.Length)
+ return false;
+ for (int i = 0; i < InstantiatedTypes.Length; i++) {
+ if (InstantiatedTypes[i] != other.InstantiatedTypes[i])
+ return false;
+ }
+ }
return Return == other.Return && Name == other.Name && IsStatic == other.IsStatic && base.Equals(other);
}
@@ -781,6 +824,11 @@ namespace Twiglet.CS2J.Translator.TypeRep
hashCode = hashCode ^ o.GetHashCode() ;
}
}
+ if (InstantiatedTypes != null) {
+ foreach (TypeRepTemplate o in InstantiatedTypes) {
+ hashCode = hashCode ^ o.GetHashCode() ;
+ }
+ }
return hashCode ^ (Return ?? String.Empty).GetHashCode () ^ (Name ?? String.Empty).GetHashCode () ^ IsStatic.GetHashCode() ^ base.GetHashCode();
}
@@ -796,7 +844,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string From {
get { return _from; }
set {
- _from=value.Replace('<','[').Replace('>',']');
+ _from=value.Replace("<","*[").Replace(">","]*");
}
}
@@ -804,7 +852,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string To {
get { return _to; }
set {
- _to=value.Replace('<','[').Replace('>',']');
+ _to=value.Replace("<","*[").Replace(">","]*");
}
}
@@ -930,7 +978,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string Type {
get { return _type; }
set {
- _type=value.Replace('<','[').Replace('>',']');
+ _type=value.Replace("<","*[").Replace(">","]*");
}
}
public string Name { get; set; }
@@ -1414,8 +1462,48 @@ namespace Twiglet.CS2J.Translator.TypeRep
[XmlElementAttribute("Name")]
public string TypeName { get; set; }
+ private string[] _typeParams = null;
[XmlArrayItem("Name")]
- public string[] TypeParams { get; set; }
+ public string[] TypeParams {
+ get
+ {
+ if (_typeParams == null)
+ {
+ TypeParams = new string[0];
+ }
+ return _typeParams;
+ }
+ set
+ {
+ // First time that TypeParams is set then create InstantiatedTypes as corresponding list of TypeVars
+ if (value != null && InstantiatedTypes == null)
+ {
+ InstantiatedTypes = new TypeRepTemplate[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ {
+ InstantiatedTypes[i] = new TypeVarRepTemplate(value[i]);
+ }
+ }
+ _typeParams = value;
+ }
+ }
+
+ [XmlIgnore]
+ public TypeRepTemplate[] InstantiatedTypes { get; set; }
+
+ [XmlIgnore]
+ public Dictionary TyVarMap
+ { get
+ {
+ Dictionary ret = new Dictionary(TypeParams.Length);
+ for (int i = 0; i < TypeParams.Length; i++)
+ {
+ ret[TypeParams[i]] = InstantiatedTypes[i];
+ }
+ return ret;
+ }
+
+ }
// Path to use when resolving types
[XmlArrayItem("Use")]
@@ -1449,7 +1537,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
if (value != null) {
_inherits= new string[value.Length];
for (int i = 0; i < value.Length; i++) {
- _inherits[i] = (value[i] != null ? value[i].Replace('<','[').Replace('>',']') : null);
+ _inherits[i] = (value[i] != null ? value[i].Replace("<","*[").Replace(">","]*") : null);
}
}
else {
@@ -1490,36 +1578,20 @@ namespace Twiglet.CS2J.Translator.TypeRep
// Equivalent to "this is TypeVarRepTemplate"
[XmlIgnore]
- public bool IsTypeVar
+ public virtual bool IsTypeVar
{
get
{
return (this is TypeVarRepTemplate);
}
}
-
- // Type Arguments that this (generic) type has been instantiated with
- private TypeRepTemplate[] _instantiatedTypes = null;
+ // Equivalent to "this is UnknownRepTemplate"
[XmlIgnore]
- public TypeRepTemplate[] InstantiatedTypes
+ public virtual bool IsUnknownType
{
get
{
- if (_instantiatedTypes == null)
- {
- // Create from the TypeParams
- int numParams = TypeParams == null ? 0 : TypeParams.Length;
- _instantiatedTypes = new TypeRepTemplate[numParams];
- for (int i = 0; i < numParams; i++)
- {
- _instantiatedTypes[i] = new TypeVarRepTemplate(TypeParams[i]);
- }
- }
- return _instantiatedTypes;
- }
- set
- {
- _instantiatedTypes = value;
+ return (this is UnknownRepTemplate);
}
}
@@ -1556,6 +1628,16 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
}
+ if (copyFrom.InstantiatedTypes != null)
+ {
+ len = copyFrom.InstantiatedTypes.Length;
+ InstantiatedTypes = new TypeRepTemplate[len];
+ for (int i = 0; i < len; i++)
+ {
+ InstantiatedTypes[i] = copyFrom.InstantiatedTypes[i].Instantiate(null);
+ }
+ }
+
if (copyFrom.Uses != null)
{
len = copyFrom.Uses.Length;
@@ -1623,20 +1705,16 @@ namespace Twiglet.CS2J.Translator.TypeRep
// IMPORTANT: Call this on the fresh copy because it has the side effect of updating this type's TypeParams.
protected Dictionary mkTypeMap(ICollection args) {
Dictionary ret = new Dictionary();
- if (args.Count == TypeParams.Length)
+ if (args != null && args.Count == TypeParams.Length)
{
- List remTypeParams = new List();
+ InstantiatedTypes = new TypeRepTemplate[args.Count];
int i = 0;
foreach (TypeRepTemplate sub in args)
{
- if (sub.IsTypeVar)
- {
- remTypeParams.Add(sub.TypeName);
- }
ret[TypeParams[i]] = sub;
+ InstantiatedTypes[i] = sub;
i++;
}
- TypeParams = remTypeParams.ToArray();
}
else
{
@@ -1666,16 +1744,6 @@ namespace Twiglet.CS2J.Translator.TypeRep
Inherits[i] = TemplateUtilities.SubstituteInType(Inherits[i],args);
}
}
- if (InstantiatedTypes != null)
- {
- for(int i = 0; i < InstantiatedTypes.Length; i++)
- {
- if (InstantiatedTypes[i].IsTypeVar && args.ContainsKey(InstantiatedTypes[i].TypeName))
- {
- InstantiatedTypes[i] = args[InstantiatedTypes[i].TypeName];
- }
- }
- }
base.Apply(args);
}
@@ -2077,9 +2145,9 @@ namespace Twiglet.CS2J.Translator.TypeRep
}
if (InstantiatedTypes != null)
{
- foreach (TypeRepTemplate t in InstantiatedTypes)
+ foreach (TypeRepTemplate ty in InstantiatedTypes)
{
- hashCode ^= t.GetHashCode();
+ hashCode ^= ty.GetHashCode();
}
}
@@ -2102,7 +2170,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
else
{
fmt.Append(TypeName.Substring(incNameSpace ? 0 : TypeName.LastIndexOf('.')+1));
- if (InstantiatedTypes.Length > 0)
+ if (InstantiatedTypes != null && InstantiatedTypes.Length > 0)
{
bool isFirst = true;
fmt.Append("<");
@@ -2291,7 +2359,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
public string Return {
get { return _return; }
set {
- _return=value.Replace('<','[').Replace('>',']');
+ _return=value.Replace("<","*[").Replace(">","]*");
}
}
@@ -2974,7 +3042,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
{
ResolveResult res = new ResolveResult();
res.Result = c;
- res.ResultType = BuildType(TypeName, AppEnv);
+ res.ResultType = this;
return res;
}
}
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
index 57f1cbe..22b5450 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/JavaPrettyPrint.g
@@ -273,6 +273,8 @@ options {
public string fillTemplate(string template, Dictionary templateMap) {
string ret = template;
+ // *[ -> < and ]* -> >
+ ret = ret.Replace("*[","<").Replace("]*",">");
foreach (string v in templateMap.Keys) {
MatchEvaluator myEvaluator = new MatchEvaluator(templateMap[v].replace);
ret = Regex.Replace(ret, Regex.Escape("${" + v) + "(?::(?\\d+))?}", myEvaluator);
@@ -481,6 +483,7 @@ rank_specifier:
wrapped returns [int precedence]:
^(JAVAWRAPPEREXPRESSION expression) { $precedence = $expression.precedence; } -> { $expression.st }
| ^(JAVAWRAPPERARGUMENT argument_value) { $precedence = $argument_value.precedence; } -> { $argument_value.st }
+ | ^(JAVAWRAPPERTYPE type) { $precedence = int.MaxValue; } -> { $type.st }
;
delegate_creation_expression:
@@ -627,8 +630,18 @@ commas:
// Type Section
///////////////////////////////////////////////////////
-type_name:
- namespace_or_type_name -> { $namespace_or_type_name.st };
+type_name
+@init {
+ Dictionary templateMap = new Dictionary();
+}:
+ namespace_or_type_name -> { $namespace_or_type_name.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)})
+ ;
namespace_or_type_name:
t1=type_or_generic -> { $t1.st }
// keving: external aliases not supported
@@ -670,8 +683,13 @@ type
StringTemplate nm = null;
List stars = new List();
string opt = null;
+ Dictionary templateMap = new Dictionary();
}:
- ^(TYPE (tp=predefined_type {nm=$tp.st;} | tn=type_name {nm=$tn.st;} | tv='void' { nm=%void();}) rank_specifiers? ('*' { stars.Add("*");})* ('?' { opt = "?";} )?) -> type(name={ nm }, stars={ stars }, rs={ $rank_specifiers.st }, opt={ opt })
+ ^(TYPE (
+ tp=predefined_type {nm=$tp.st;}
+ | tn=type_name {nm=$tn.st;}
+ | tv='void' { nm=%void();}
+ ) rank_specifiers? ('*' { stars.Add("*");})* ('?' { opt = "?";} )?) -> type(name={ nm }, stars={ stars }, rs={ $rank_specifiers.st }, opt={ opt })
;
non_nullable_type:
type -> { $type.st } ;
diff --git a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
index 4772406..4eac289 100644
--- a/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
+++ b/CSharpTranslator/antlr3/src/CS2JTranslator/CS2JTransform/NetMaker.g
@@ -46,6 +46,10 @@ scope SymTab {
@members
{
+ // in_member_name is set while we are processing member_name. It stops type_or_generic from
+ // treating its input as a type (and translating it).
+ // TODO: Decide what should really be done here with .member_name
+ private bool in_member_name = false;
private string CompUnitName = null;
@@ -180,7 +184,7 @@ scope SymTab {
}
protected TypeRepTemplate SymTabLookup(string name) {
- return SymTabLookup(name, new UnknownRepTemplate("TYPE OF " + name));
+ return SymTabLookup(name, null);
}
protected TypeRepTemplate SymTabLookup(string name, TypeRepTemplate def) {
@@ -226,6 +230,13 @@ scope SymTab {
return (CommonTree)adaptor.RulePostProcessing(root);
}
+ protected CommonTree wrapType(CommonTree t, IToken tok) {
+ CommonTree root = (CommonTree)adaptor.Nil;
+ root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPERTYPE, tok, "TYPE"), root);
+ adaptor.AddChild(root, dupTree(t));
+
+ return (CommonTree)adaptor.RulePostProcessing(root);
+ }
protected CommonTree wrapTypeOfType(TypeRepTemplate t, IToken tok) {
CommonTree root = (CommonTree)adaptor.Nil;
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPEREXPRESSION, tok, "EXPRESSION"), root);
@@ -455,8 +466,6 @@ type_declaration:
// Identifiers
qualified_identifier:
identifier ('.' identifier)*;
-namespace_name
- : namespace_or_type_name ;
modifiers:
modifier+ ;
@@ -500,64 +509,64 @@ scope {
}:
^(index=INDEX ie=expression expression_list?)
{
- if ($ie.dotNetType != null && !$ie.dotNetType.IsUnknownType) {
- $dotNetType = new UnknownRepTemplate($ie.dotNetType.TypeName+".INDEXER");
- ResolveResult indexerResult = $ie.dotNetType.ResolveIndexer($expression_list.expTypes ?? new List(), AppEnv);
- if (indexerResult != null) {
- IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
- if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
- Dictionary myMap = new Dictionary();
- myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
- for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
- myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
- if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
- // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
- myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
- }
- }
- ret = mkJavaWrapper(indexerResult.Result.Java, myMap, $ie.tree.Token);
- AddToImports(indexerResult.Result.Imports);
- $dotNetType = indexerResult.ResultType;
- }
- }
- else {
- WarningFailedResolve($index.token.Line, "Could not resolve index expression");
- }
+ expType = $ie.dotNetType ?? (new UnknownRepTemplate("INDEXER.BASE"));
+ if (expType.IsUnknownType) {
+ WarningFailedResolve($index.token.Line, "Could not find type of indexed expression");
+ }
+ $dotNetType = new UnknownRepTemplate(expType.TypeName+".INDEXER");
+ ResolveResult indexerResult = expType.ResolveIndexer($expression_list.expTypes ?? new List(), AppEnv);
+ if (indexerResult != null) {
+ IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
+ if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
+ Dictionary myMap = new Dictionary();
+ myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
+ for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
+ myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
+ if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
+ // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
+ myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
+ }
+ }
+ ret = mkJavaWrapper(indexerResult.Result.Java, myMap, $ie.tree.Token);
+ AddToImports(indexerResult.Result.Imports);
+ $dotNetType = indexerResult.ResultType;
+ }
}
else {
- WarningFailedResolve($index.token.Line, "Could not find type of indexed expression");
+ WarningFailedResolve($index.token.Line, "Could not resolve index expression against " + expType.TypeName);
}
}
| (^(APPLY (^('.' expression identifier)|identifier) argument_list?)) =>
^(APPLY (^('.' e2=expression {expType = $e2.dotNetType; implicitThis = false;} i2=identifier)|i2=identifier) argument_list?)
{
- if (expType != null && !expType.IsUnknownType) {
- $dotNetType = new UnknownRepTemplate(expType.TypeName+".APPLY");
- ResolveResult methodResult = expType.Resolve($i2.thetext, $argument_list.argTypes ?? new List(), AppEnv);
- if (methodResult != null) {
- Debug($i2.tree.Token.Line + ": Found '" + $i2.thetext + "'");
- MethodRepTemplate methodRep = methodResult.Result as MethodRepTemplate;
- Dictionary myMap = new Dictionary();
- if (!implicitThis) {
- myMap["this"] = wrapExpression($e2.tree, $i2.tree.Token);
- }
- 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) {
- // 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);
- }
- }
- ret = mkJavaWrapper(methodResult.Result.Java, myMap, $i2.tree.Token);
- AddToImports(methodResult.Result.Imports);
- $dotNetType = methodResult.ResultType;
- }
- else {
- WarningFailedResolve($i2.tree.Token.Line, "Could not resolve method application");
- }
+ if (expType == null) {
+ expType = new UnknownRepTemplate("APPLY.BASE");
+ }
+ if (expType.IsUnknownType) {
+ 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) {
+ Debug($i2.tree.Token.Line + ": Found '" + $i2.thetext + "'");
+ MethodRepTemplate methodRep = methodResult.Result as MethodRepTemplate;
+ Dictionary myMap = new Dictionary();
+ if (!implicitThis) {
+ myMap["this"] = wrapExpression($e2.tree, $i2.tree.Token);
+ }
+ 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) {
+ // 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);
+ }
+ }
+ ret = mkJavaWrapper(methodResult.Result.Java, myMap, $i2.tree.Token);
+ AddToImports(methodResult.Result.Imports);
+ $dotNetType = methodResult.ResultType;
}
else {
- WarningFailedResolve($i2.tree.Token.Line, "Could not find type needed to resolve method application");
+ WarningFailedResolve($i2.tree.Token.Line, "Could not resolve method application against " + expType.TypeName);
}
}
| ^(APPLY {$primary_expression::parentIsApply = true; } expression {$primary_expression::parentIsApply = false; } argument_list?)
@@ -565,6 +574,8 @@ scope {
| ^(POSTDEC expression) { $dotNetType = $expression.dotNetType; }
| ^(d1='.' e1=expression i1=identifier generic_argument_list?)
{
+ // TODO: generic_argument_list is ignored ....
+
// Possibilities:
// - accessing a property/field of some object
// - a qualified type name
@@ -612,7 +623,7 @@ scope {
// - part of a type name
bool found = false;
TypeRepTemplate idType = SymTabLookup($identifier.thetext);
- if (idType != null && !idType.IsUnknownType) {
+ if (idType != null) {
$dotNetType = idType;
found = true;
}
@@ -658,6 +669,9 @@ scope {
{
ClassRepTemplate conType = $type.dotNetType as ClassRepTemplate;
$dotNetType = $type.dotNetType;
+ if (conType == null) {
+ conType = new UnknownRepTemplate("CONSTRUCTOR");
+ }
ResolveResult conResult = conType.Resolve($argument_list.argTypes, AppEnv);
if (conResult != null) {
ConstructorRepTemplate conRep = conResult.Result as ConstructorRepTemplate;
@@ -665,12 +679,20 @@ scope {
for (int idx = 0; idx < conRep.Params.Count; idx++) {
myMap[conRep.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $n.token);
}
+ if ($type.argTrees != null && $type.argTrees.Count == $type.dotNetType.TypeParams.Length) {
+ int idx = 0;
+ foreach (CommonTree ty in $type.argTrees)
+ {
+ myMap[$type.dotNetType.TypeParams[idx]] = wrapType(ty, $n.token);
+ idx++;
+ }
+ }
ret = mkJavaWrapper(conResult.Result.Java, myMap, $n.token);
AddToImports(conResult.Result.Imports);
$dotNetType = conResult.ResultType;
}
else {
- WarningFailedResolve($n.token.Line, "Could not resolve constructor");
+ WarningFailedResolve($n.token.Line, "Could not resolve constructor against " + conType.TypeName);
}
}
| 'new' (
@@ -697,7 +719,7 @@ primary_expression_part:
| '++'
| '--' ;
access_identifier:
- access_operator type_or_generic ;
+ access_operator type_or_generic[""] ;
access_operator:
'.' | '->' ;
brackets_or_arguments:
@@ -864,37 +886,94 @@ commas:
// Type Section
///////////////////////////////////////////////////////
-type_name returns [string name, TypeRepTemplate dotNetType]:
- namespace_or_type_name { $name = $namespace_or_type_name.name; $dotNetType = findType($namespace_or_type_name.name, $namespace_or_type_name.tyargs); } ;
-namespace_or_type_name returns [string name, List tyargs]
+// i.e not a predefined type.
+type_name returns [TypeRepTemplate dotNetType, List argTrees, bool hasTyArgs]
@init {
- TypeRepTemplate tyRep = null;
-}:
- type_or_generic { $name = $type_or_generic.name; $tyargs = $type_or_generic.tyargs; }
- | ^('::' namespace_or_type_name type_or_generic) { $name = "System.Object"; } // give up, we don't support these
- | ^(d='.' n1=namespace_or_type_name tg1=type_or_generic) { WarningAssert($n1.tyargs == null, $d.token.Line, "Didn't expect type arguments in prefix of type name"); $name = $n1.name + "." + $type_or_generic.name; $tyargs = $type_or_generic.tyargs; tyRep = findType($name, $tyargs); if (tyRep != null) AddToImports(tyRep.Imports); }
- -> { tyRep != null }? IDENTIFIER[$d.token, tyRep.Java]
- -> ^($d $n1 $tg1)
+ $hasTyArgs = false;
+ Dictionary tyMap = new Dictionary();
+}
+@after {
+ AddToImports($dotNetType.Imports);
+}
+:
+ tg=type_or_generic[""] { $dotNetType = $tg.dotNetType; $argTrees = $tg.argTrees; $hasTyArgs = $tg.hasTyArgs; }
+ | ^('::' ct=type_name ctg=type_or_generic[$ct.dotNetType == null ? "::" : $ct.dotNetType.TypeName+"::"])
+ {
+ // give up, we don't support these, pretty printer will wrap in a comment
+ $dotNetType = $ctg.dotNetType;
+ $hasTyArgs = $ctg.hasTyArgs;
+ $argTrees = $ctg.argTrees;
+ }
+ | ^(d='.' dt=type_name dtg=type_or_generic[$dt.dotNetType == null ? "." : $dt.dotNetType.TypeName+"."])
+ {
+ WarningAssert(!$dt.hasTyArgs, $d.token.Line, "Didn't expect type arguments in prefix of type name");
+
+ $dotNetType = $dtg.dotNetType;
+ if (!$dotNetType.IsUnknownType) {
+ if ($dotNetType.TypeParams.Length == $dtg.argTrees.Count) {
+ int i = 0;
+ foreach (CommonTree ty in $dtg.argTrees) {
+ tyMap[$dotNetType.TypeParams[i]] = wrapType(ty, $dt.tree.Token);
+ i++;
+ }
+ $hasTyArgs = true;
+ $argTrees = $dtg.argTrees;
+ }
+ }
+ }
+ -> {!$dotNetType.IsUnknownType}? { mkJavaWrapper($dotNetType.Java, tyMap, $dt.tree.Token) }
+ -> ^($d $dt $dtg)
;
-type_or_generic returns [string name, List tyargs]
-:
- (identifier_type generic_argument_list) => t=identifier_type { $name = $identifier_type.thetext; } generic_argument_list { $tyargs = $generic_argument_list.argTypes; }
- | t=identifier_type { $name = $identifier_type.thetext; } ;
-
-identifier_type returns [string thetext]
+type_or_generic[String prefix] returns [TypeRepTemplate dotNetType, List argTrees, bool hasTyArgs]
@init {
- TypeRepTemplate tyRep = null;
+ $hasTyArgs = false;
+ $argTrees = new List();
+ Dictionary tyMap = new Dictionary();
}
-@after{
- $thetext = $t.thetext;
-}:
- t=identifier { tyRep = findType($t.thetext); if (tyRep != null) AddToImports(tyRep.Imports); }
- -> { tyRep != null }? IDENTIFIER[$t.tree.Token, tyRep.Java]
- -> $t;
-
+@after {
+ AddToImports($dotNetType.Imports);
+}
+:
+// (identifier generic_argument_list) => t=identifier ga=generic_argument_list
+ t=identifier (ga=generic_argument_list {$hasTyArgs = true;})?
+ {
+ $dotNetType = findType(prefix+$t.thetext, $ga.argTypes);
+ if (!$dotNetType.IsUnknownType) {
+ if ($hasTyArgs && $dotNetType.TypeParams.Length == $ga.argTrees.Count) {
+ int i = 0;
+ foreach (CommonTree ty in $ga.argTrees) {
+ tyMap[$dotNetType.TypeParams[i]] = wrapType(ty, $t.tree.Token);
+ i++;
+ }
+ $argTrees = $ga.argTrees;
+ }
+ }
+ }
+ -> {!this.in_member_name && !$dotNetType.IsUnknownType}? { mkJavaWrapper($dotNetType.Java, tyMap, $t.tree.Token) }
+ -> $t $ga?
+ ;
+// | ity=identifier_type[prefix]
+// { $dotNetType = $ity.dotNetType);
+// }
+// -> {!$dotNetType.IsUnknownType}? { mkJavaWrapper($dotNetType.Java, null, $ity.tree.Token) }
+// -> $ity
+// ;
+//
+// identifier_type[string prefix] returns [string thetext]
+// @init {
+// TypeRepTemplate tyRep = null;
+// }
+// @after{
+// $thetext = $t.thetext;
+// AddToImports($dotNetType.Imports);
+// }:
+// t=identifier { tyRep = findType(prefix+$t.thetext); }
+// -> { mkJavaWrapper(tyRep.Java, null, $t.tree.Token) }
+// ;
+//
qid: // qualified_identifier v2
- ^(access_operator qid type_or_generic)
+ ^(access_operator qid type_or_generic[""])
| qid_start
;
qid_start:
@@ -910,21 +989,22 @@ qid_start:
qid_part:
access_identifier;
-generic_argument_list returns [List argTypes]:
- '<' type_arguments '>' { $argTypes = $type_arguments.tyTypes; };
-type_arguments returns [List tyTypes]
+generic_argument_list returns [List argTypes, List argTrees]:
+ '<' type_arguments '>' { $argTypes = $type_arguments.tyTypes; $argTrees = $type_arguments.argTrees; };
+type_arguments returns [List tyTypes, List argTrees]
@init {
$tyTypes = new List();
+ $argTrees = new List();
}:
- t1=type { $tyTypes.Add($t1.dotNetType); } (',' tn=type { $tyTypes.Add($tn.dotNetType); })* ;
+ t1=type { $tyTypes.Add($t1.dotNetType); $argTrees.Add(dupTree($t1.tree)); } (',' tn=type { $tyTypes.Add($tn.dotNetType); $argTrees.Add(dupTree($tn.tree)); })* ;
// keving: TODO: Look for type vars
-type returns [TypeRepTemplate dotNetType]
+type returns [TypeRepTemplate dotNetType, List argTrees]
:
^(TYPE (predefined_type { $dotNetType = $predefined_type.dotNetType; }
- | type_name { $dotNetType = $type_name.dotNetType; }
+ | type_name { $dotNetType = $type_name.dotNetType; $argTrees = $type_name.argTrees; }
| 'void' { $dotNetType = AppEnv["System.Void"]; } )
- (rank_specifiers[$dotNetType] { $dotNetType = $rank_specifiers.dotNetType; })? '*'* '?'?);
+ (rank_specifiers[$dotNetType] { $dotNetType = $rank_specifiers.dotNetType; $argTrees = null; })? '*'* '?'?);
non_nullable_type returns [TypeRepTemplate dotNetType]:
type { $dotNetType = $type.dotNetType; } ;
@@ -973,6 +1053,7 @@ assignment
@init {
CommonTree ret = null;
bool isThis = false;
+ TypeRepTemplate expType = null;
}
@after {
if (ret != null)
@@ -982,103 +1063,105 @@ assignment
(^('.' se=expression i=identifier generic_argument_list?) | i=identifier { isThis = true;}) a=assignment_operator rhs=expression
{
TypeRepTemplate seType = (isThis ? SymTabLookup("this") : $se.dotNetType);
- if (seType != null && !seType.IsUnknownType) {
- ResolveResult fieldResult = seType.Resolve($i.thetext, AppEnv);
- if (fieldResult != null && fieldResult.Result is PropRepTemplate) {
- PropRepTemplate propRep = fieldResult.Result as PropRepTemplate;
- if (!String.IsNullOrEmpty(propRep.JavaSet)) {
- CommonTree newRhsExp = $rhs.tree;
- // if assignment operator is a short cut operator then only translate if we also have JavaGet
- bool goodTx = true;
- if ($a.tree.Token.Type != ASSIGN) {
- if (!String.IsNullOrEmpty(propRep.JavaGet)) {
- // we have prop = rhs
- // need to translate to setProp(getProp rhs)
- Dictionary rhsMap = new Dictionary();
- if (!isThis)
- rhsMap["this"] = wrapExpression($se.tree, $i.tree.Token);
- CommonTree rhsPropTree = mkJavaWrapper(propRep.JavaGet, rhsMap, $a.tree.Token);
- newRhsExp = mkOpExp(mkOpExp($a.tree), rhsPropTree, $rhs.tree);
- }
- else {
- goodTx = false;
- }
+ 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, AppEnv);
+ if (fieldResult != null) {
+ if (fieldResult.Result is PropRepTemplate) {
+ PropRepTemplate propRep = fieldResult.Result as PropRepTemplate;
+ if (!String.IsNullOrEmpty(propRep.JavaSet)) {
+ CommonTree newRhsExp = $rhs.tree;
+ // if assignment operator is a short cut operator then only translate if we also have JavaGet
+ bool goodTx = true;
+ if ($a.tree.Token.Type != ASSIGN) {
+ if (!String.IsNullOrEmpty(propRep.JavaGet)) {
+ // we have prop = rhs
+ // need to translate to setProp(getProp rhs)
+ Dictionary rhsMap = new Dictionary();
+ if (!isThis)
+ rhsMap["this"] = wrapExpression($se.tree, $i.tree.Token);
+ CommonTree rhsPropTree = mkJavaWrapper(propRep.JavaGet, rhsMap, $a.tree.Token);
+ newRhsExp = mkOpExp(mkOpExp($a.tree), rhsPropTree, $rhs.tree);
}
- Dictionary valMap = new Dictionary();
- if (!isThis)
- valMap["this"] = wrapExpression($se.tree, $i.tree.Token);
- valMap["value"] = wrapExpression(newRhsExp, $i.tree.Token);
- if (goodTx) {
- ret = mkJavaWrapper(propRep.JavaSet, valMap, $a.tree.Token);
- AddToImports(propRep.Imports);
+ else {
+ goodTx = false;
}
- }
- }
- else {
- WarningFailedResolve($i.tree.Token.Line, "Could not resolve field or property expression");
- }
+ }
+ Dictionary valMap = new Dictionary();
+ if (!isThis)
+ valMap["this"] = wrapExpression($se.tree, $i.tree.Token);
+ valMap["value"] = wrapExpression(newRhsExp, $i.tree.Token);
+ if (goodTx) {
+ ret = mkJavaWrapper(propRep.JavaSet, valMap, $a.tree.Token);
+ AddToImports(propRep.Imports);
+ }
+ }
+ }
}
else {
- WarningFailedResolve($i.tree.Token.Line, "Could not find type of expression for field /property access");
+ WarningFailedResolve($i.tree.Token.Line, "Could not resolve field or property expression against " + seType.ToString());
}
}
| (^(INDEX expression expression_list?) assignment_operator) =>
^(INDEX ie=expression expression_list?) ia=assignment_operator irhs=expression
{
- if ($ie.dotNetType != null && !$ie.dotNetType.IsUnknownType) {
- ResolveResult indexerResult = $ie.dotNetType.ResolveIndexer($expression_list.expTypes ?? new List(), AppEnv);
- if (indexerResult != null) {
- IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
- if (!String.IsNullOrEmpty(indexerRep.JavaSet)) {
- CommonTree newRhsExp = $irhs.tree;
- // if assignment operator is a short cut operator then only translate if we also have JavaGet
- bool goodTx = true;
- if ($ia.tree.Token.Type != ASSIGN) {
- if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
- // we have indexable[args] = rhs
- // need to translate to set___idx(args, get___idx(args) rhs)
- Dictionary rhsMap = new Dictionary();
- rhsMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
- for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
- rhsMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
- if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
- // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
- rhsMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
- }
- }
-
- CommonTree rhsIdxTree = mkJavaWrapper(indexerRep.JavaGet, rhsMap, $ia.tree.Token);
- newRhsExp = mkOpExp(mkOpExp($ia.tree), rhsIdxTree, $irhs.tree);
- }
- else {
- goodTx = false;
- }
- }
-
- Dictionary myMap = new Dictionary();
- myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
- myMap["value"] = wrapExpression(newRhsExp, newRhsExp.Token);
+ 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);
+ if (indexerResult != null) {
+ IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
+ if (!String.IsNullOrEmpty(indexerRep.JavaSet)) {
+ CommonTree newRhsExp = $irhs.tree;
+ // if assignment operator is a short cut operator then only translate if we also have JavaGet
+ bool goodTx = true;
+ if ($ia.tree.Token.Type != ASSIGN) {
+ if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
+ // we have indexable[args] = rhs
+ // need to translate to set___idx(args, get___idx(args) rhs)
+ Dictionary rhsMap = new Dictionary();
+ rhsMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
- myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
- if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
- // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
- myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
- }
+ rhsMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
+ if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
+ // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
+ rhsMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
+ }
}
- if (goodTx) {
- ret = mkJavaWrapper(indexerRep.JavaSet, myMap, $ie.tree.Token);
- AddToImports(indexerRep.Imports);
- }
- }
- }
- else {
- WarningFailedResolve($ie.tree.Token.Line, "Could not resolve index expression");
- }
+
+ CommonTree rhsIdxTree = mkJavaWrapper(indexerRep.JavaGet, rhsMap, $ia.tree.Token);
+ newRhsExp = mkOpExp(mkOpExp($ia.tree), rhsIdxTree, $irhs.tree);
+ }
+ else {
+ goodTx = false;
+ }
+ }
+
+ Dictionary myMap = new Dictionary();
+ myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
+ myMap["value"] = wrapExpression(newRhsExp, newRhsExp.Token);
+ for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
+ myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
+ if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
+ // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
+ myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
+ }
+ }
+ if (goodTx) {
+ ret = mkJavaWrapper(indexerRep.JavaSet, myMap, $ie.tree.Token);
+ AddToImports(indexerRep.Imports);
+ }
+ }
}
else {
- WarningFailedResolve($ie.tree.Token.Line, "Could not find type of expression for index access");
+ WarningFailedResolve($ie.tree.Token.Line, "Could not resolve index expression against " + expType.ToString());
}
- }
+ }
| unary_expression assignment_operator expression ;
@@ -1562,8 +1645,17 @@ method_header:
^(METHOD_HEADER attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list?);
method_body:
block ;
-member_name:
- type_or_generic ('.' type_or_generic)*
+member_name
+@init {
+ // in_member_name is used by type_or-generic so that we don't treat the member name as a type.
+ string preTy = null;
+ bool save_in_member_name = this.in_member_name;
+ this.in_member_name = true;
+}
+@after{
+ this.in_member_name = save_in_member_name;
+}:
+ t1=type_or_generic[""] { preTy = ($t1.dotNetType == null ? "" : $t1.dotNetType.TypeName); }('.' tn=type_or_generic[preTy+"."] { preTy = ($tn.dotNetType == null ? "" : $tn.dotNetType.TypeName); })*
//(type '.') => type '.' identifier
//| identifier
;
diff --git a/CSharpTranslator/antlr3/src/CSharpParser/cs.g b/CSharpTranslator/antlr3/src/CSharpParser/cs.g
index 35d5ff2..7bdac70 100644
--- a/CSharpTranslator/antlr3/src/CSharpParser/cs.g
+++ b/CSharpTranslator/antlr3/src/CSharpParser/cs.g
@@ -134,6 +134,7 @@ tokens {
JAVAWRAPPER;
JAVAWRAPPEREXPRESSION;
JAVAWRAPPERARGUMENT;
+ JAVAWRAPPERTYPE;
SEP;
KGHOLE;