diff --git a/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs b/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs index 248ab79..4a9937b 100644 --- a/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs +++ b/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs @@ -579,7 +579,17 @@ namespace RusticiSoftware.Translator.CLR } else { if (!String.IsNullOrEmpty(SurroundingTypeName)) { - return SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1) + ".__castto_" + To.Replace('.','_') + "(${expr})"; + String myType = SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1); + String toType = To.Substring(To.LastIndexOf('.') + 1); + if (myType == toType) + { + // just overload various casts to my type + return myType + ".__cast(${expr})"; + } + else + { + return myType + ".__cast${TYPEOF_totype}(${expr})"; + } } else { @@ -906,6 +916,16 @@ namespace RusticiSoftware.Translator.CLR [XmlArrayItem("Alias")] public AliasRepTemplate[] Aliases { get; set; } + protected List _casts = null; + [XmlArrayItem("Cast")] + public virtual List Casts { + get { + if (_casts == null) + _casts = new List (); + return _casts; + } + } + public TypeRepTemplate () : base() { TypeName = null; @@ -966,6 +986,7 @@ namespace RusticiSoftware.Translator.CLR } } + // Resolve a method call (name and arg types) public virtual ResolveResult Resolve(String name, List args, DirectoryHT AppEnv) { if (Inherits != null) @@ -984,6 +1005,7 @@ namespace RusticiSoftware.Translator.CLR return null; } + // Resolve a field or property access public virtual ResolveResult Resolve(String name, DirectoryHT AppEnv) { if (Inherits != null) @@ -1002,6 +1024,85 @@ namespace RusticiSoftware.Translator.CLR return null; } + // Resolve a cast from this type to castTo + public virtual ResolveResult ResolveCastTo(TypeRepTemplate castTo, DirectoryHT AppEnv) + { + if (Casts != null) + { + foreach (CastRepTemplate c in Casts) + { + if (c.To != null) + { + // Is this a cast from us? + TypeRepTemplate fromTy = null; + if (c.From != null) + { + fromTy = AppEnv.Search(Uses, c.From); + } + if (c.From == null || (fromTy != null && fromTy.TypeName == TypeName)) + { + // cast from us + TypeRepTemplate toTy = AppEnv.Search(Uses, c.To); + if (toTy.IsA(castTo, AppEnv)) + { + ResolveResult res = new ResolveResult(); + res.Result = c; + res.ResultType = toTy; + return res; + } + } + } + } + } + if (Inherits != null) + { + foreach (String b in Inherits) + { + TypeRepTemplate baseType = AppEnv.Search(Uses, b); + if (baseType != null) + { + ResolveResult ret = baseType.ResolveCastTo(castTo,AppEnv); + if (ret != null) + return ret; + } + } + } + return null; + } + + // Resolve a cast to this type from castFrom + public virtual ResolveResult ResolveCastFrom(TypeRepTemplate castFrom, DirectoryHT AppEnv) + { + if (Casts != null) + { + foreach (CastRepTemplate c in Casts) + { + if (c.From != null) + { + // Is this a cast to us? + TypeRepTemplate toTy = null; + if (c.To != null) + { + toTy = AppEnv.Search(Uses, c.To); + } + if (c.To == null || (toTy != null && toTy.TypeName == TypeName)) + { + // cast to us + TypeRepTemplate fromTy = AppEnv.Search(Uses, c.From); + if (castFrom.IsA(fromTy, AppEnv)) + { + ResolveResult res = new ResolveResult(); + res.Result = c; + res.ResultType = toTy; + return res; + } + } + } + } + } + return null; + } + // Returns true if other is a subclass, or implements our interface public virtual bool IsA (TypeRepTemplate other, DirectoryHT AppEnv) { if (other.TypeName == this.TypeName) @@ -1122,6 +1223,15 @@ namespace RusticiSoftware.Translator.CLR } } + if (Casts != other.Casts) { + if (Casts == null || other.Casts == null || Casts.Count != other.Casts.Count) + return false; + for (int i = 0; i < Casts.Count; i++) { + if (Casts[i] != other.Casts[i]) + return false; + } + } + return TypeName == other.TypeName && base.Equals(other); } @@ -1163,6 +1273,12 @@ namespace RusticiSoftware.Translator.CLR hashCode ^= e.GetHashCode(); } } + if (Casts != null) { + foreach (CastRepTemplate e in Casts) { + hashCode ^= e.GetHashCode(); + } + } + return (Java ?? String.Empty).GetHashCode () ^ hashCode; } #endregion @@ -1186,6 +1302,38 @@ namespace RusticiSoftware.Translator.CLR } } + private List _enumCasts = null; + private List EnumCasts { + get { + if (_enumCasts == null) + { + _enumCasts = new List (); + CastRepTemplate kast = new CastRepTemplate(); + kast.From = "System.Int32"; + kast.Java = "${TYPEOF_totype}.values()[${expr}]"; + _enumCasts.Add(kast); + kast = new CastRepTemplate(); + kast.To = "System.Int32"; + kast.Java = "((Enum)${expr}).ordinal()"; + _enumCasts.Add(kast); + } + return _enumCasts; + } + } + + public override List Casts { + get { + if (_casts == null) + { + return EnumCasts; + } + else + { + return _casts; + } + } + } + public EnumRepTemplate () : base() { Inherits = new string[] { "System.Enum" }; @@ -1632,16 +1780,6 @@ namespace RusticiSoftware.Translator.CLR } } - private List _casts = null; - [XmlArrayItem("Cast")] - public List Casts { - get { - if (_casts == null) - _casts = new List (); - return _casts; - } - } - private List _unaryOps = null; [XmlArrayItem("UnaryOp")] public List UnaryOps { @@ -1752,7 +1890,6 @@ namespace RusticiSoftware.Translator.CLR return null; } - #region Equality public bool Equals (ClassRepTemplate other) { @@ -1777,15 +1914,6 @@ namespace RusticiSoftware.Translator.CLR } } - if (Casts != other.Casts) { - if (Casts == null || other.Casts == null || Casts.Count != other.Casts.Count) - return false; - for (int i = 0; i < Casts.Count; i++) { - if (Casts[i] != other.Casts[i]) - return false; - } - } - if (UnaryOps != other.UnaryOps) { if (UnaryOps == null || other.UnaryOps == null || UnaryOps.Count != other.UnaryOps.Count) return false; @@ -1841,11 +1969,6 @@ namespace RusticiSoftware.Translator.CLR hashCode ^= e.GetHashCode(); } } - if (Casts != null) { - foreach (CastRepTemplate e in Casts) { - hashCode ^= e.GetHashCode(); - } - } return hashCode; } diff --git a/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g b/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g index 8ba7d58..a60f904 100644 --- a/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g +++ b/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g @@ -751,8 +751,7 @@ assignment unary_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType]: //('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression - //(cast_expression) => cast_expression - ^(CAST_EXPR type unary_expression) { $dotNetType = $type.dotNetType; } + 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; } | ^(MONOPLUS u1=unary_expression) { $dotNetType = $u1.dotNetType; } | ^(MONOMINUS u2=unary_expression) { $dotNetType = $u2.dotNetType; } @@ -764,8 +763,36 @@ unary_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTempla | ^(ADDRESSOF unary_expression) { $dotNetType = ObjectType; } | ^(PARENS expression) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; $typeofType = $expression.typeofType; } ; -//cast_expression: -// '(' type ')' non_assignment_expression ; + +cast_expression returns [TypeRepTemplate dotNetType] +@init { + CommonTree ret = null; +} +@after { + if (ret != null) + $cast_expression.tree = ret; +}: + ^(c=CAST_EXPR type unary_expression) + { + $dotNetType = $type.dotNetType; + if ($type.dotNetType != null && $unary_expression.dotNetType != null) { + // see if expression's type has a cast to type + ResolveResult kaster = $unary_expression.dotNetType.ResolveCastTo($type.dotNetType, AppEnv); + if (kaster == null) { + // see if type has a cast from expression's type + kaster = $type.dotNetType.ResolveCastFrom($unary_expression.dotNetType, AppEnv); + } + if (kaster != null) { + Dictionary myMap = new Dictionary(); + myMap["expr"] = wrapExpression($unary_expression.tree, $c.token); + myMap["TYPEOF_totype"] = wrapTypeOfType($type.dotNetType, $c.token); + myMap["TYPEOF_expr"] = wrapTypeOfType($unary_expression.dotNetType, $c.token); + ret = mkJavaWrapper(kaster.Result.Java, myMap, $c.token); + Imports.Add(kaster.Result.Imports); + } + } + } +; assignment_operator: '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>' '>=' ; //pre_increment_expression: @@ -1195,10 +1222,22 @@ conversion_operator_declaration[CommonTree atts, CommonTree mods] scope SymTab; @init { $SymTab::symtab = new Dictionary(); + String methodName = "__cast"; }: - h=conversion_operator_declarator { $SymTab::symtab[$h.var] = $h.varTy; } b=operator_body meth=magicCastOperator[$mods, $h.tree, $b.tree] -> $meth; -conversion_operator_declarator returns [ String var, TypeRepTemplate varTy ] : - ('implicit' | 'explicit') o='operator' t=type '(' f=type n=identifier ')' { $var = $n.thetext; $varTy = $f.dotNetType; } -> $o $t $f $n; + h=conversion_operator_declarator + { + $SymTab::symtab[$h.var] = $h.varTy; + // if varTy is same as this class then need to include toType in methodname + if ($NSContext::currentNS == $h.varTy.TypeName) + { + methodName += $h.toTy.Java; + } + } + b=operator_body meth=magicCastOperator[$mods, methodName, $h.tree, $b.tree] -> $meth; +conversion_operator_declarator returns [ String var, TypeRepTemplate varTy, TypeRepTemplate toTy ] : + ('implicit' | 'explicit') o='operator' t=type '(' f=type n=identifier ')' + { $var = $n.thetext; $varTy = $f.dotNetType; $toTy = $t.dotNetType; } + -> $o $t $f $n; operator_body: block ; @@ -1479,7 +1518,7 @@ magicScrutineeVar [IToken tok] returns [String thetext] }: -> IDENTIFIER[tok,$thetext]; -magicCastOperator[CommonTree mods, CommonTree header, CommonTree body] +magicCastOperator[CommonTree mods, String methodName, CommonTree header, CommonTree body] @init { IToken tok = ((CommonTree)$header.Children[0]).Token; CommonTree toType = dupTree((CommonTree)$header.Children[1]); @@ -1488,7 +1527,7 @@ magicCastOperator[CommonTree mods, CommonTree header, CommonTree body] }: -> ^(METHOD[tok, "METHOD"] { dupTree($mods) } - { toType } IDENTIFIER[tok, "__cast"] ^(PARAMS[tok, "PARAMS"] { fromType } { paramName}) + { toType } IDENTIFIER[tok, $methodName] ^(PARAMS[tok, "PARAMS"] { fromType } { paramName}) { dupTree(body) } EXCEPTION[tok, "Throwable"]) ;