1
0
mirror of https://github.com/twiglet/cs2j.git synced 2025-01-18 13:15:17 +01:00

support explicit casts

This commit is contained in:
Kevin Glynn 2011-01-23 17:13:59 +01:00
parent d27c25c2c8
commit c536686bf6
2 changed files with 197 additions and 35 deletions

View File

@ -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<CastRepTemplate> _casts = null;
[XmlArrayItem("Cast")]
public virtual List<CastRepTemplate> Casts {
get {
if (_casts == null)
_casts = new List<CastRepTemplate> ();
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<TypeRepTemplate> args, DirectoryHT<TypeRepTemplate> 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<TypeRepTemplate> 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<TypeRepTemplate> 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<TypeRepTemplate> 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<TypeRepTemplate> 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<CastRepTemplate> _enumCasts = null;
private List<CastRepTemplate> EnumCasts {
get {
if (_enumCasts == null)
{
_enumCasts = new List<CastRepTemplate> ();
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<CastRepTemplate> 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<CastRepTemplate> _casts = null;
[XmlArrayItem("Cast")]
public List<CastRepTemplate> Casts {
get {
if (_casts == null)
_casts = new List<CastRepTemplate> ();
return _casts;
}
}
private List<MethodRepTemplate> _unaryOps = null;
[XmlArrayItem("UnaryOp")]
public List<MethodRepTemplate> 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;
}

View File

@ -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<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
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,TypeRepTemplate>();
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"])
;