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

add support for iterables

This commit is contained in:
Kevin Glynn 2011-01-26 11:47:15 +01:00
parent 5ece315769
commit 1fe7bceade
5 changed files with 204 additions and 8 deletions

View File

@ -7,6 +7,10 @@
<Inherits>
<Type>System.Object</Type>
</Inherits>
<Iterable>
<ReturnType>System.Char</ReturnType>
<Java>${expr}.toCharArray()</Java>
</Iterable>
<Methods>
<Method>
<Imports>

View File

@ -373,6 +373,77 @@ namespace RusticiSoftware.Translator.CLR
}
public class IterableRepTemplate : TranslationBase, IEquatable<IterableRepTemplate>
{
public String ReturnType {
get; set;
}
public override string mkJava() {
return "${expr}";
}
public IterableRepTemplate () : base()
{
}
public IterableRepTemplate (String ty) : base()
{
ReturnType = ty;
}
public IterableRepTemplate (String ty, string[] imps, string javaRep) : base(imps, javaRep)
{
ReturnType = ty;
}
public override void Apply(Dictionary<string,TypeRepTemplate> args)
{
if (ReturnType != null)
{
TemplateUtilities.SubstituteInType(ReturnType, args);
}
base.Apply(args);
}
#region Equality
public bool Equals (IterableRepTemplate other)
{
if (other == null)
return false;
return ReturnType == other.ReturnType && base.Equals(other);
}
public override bool Equals (object obj)
{
IterableRepTemplate temp = obj as IterableRepTemplate;
if (!Object.ReferenceEquals (temp, null))
return this.Equals (temp);
return false;
}
public static bool operator == (IterableRepTemplate a1, IterableRepTemplate a2)
{
return Object.Equals (a1, a2);
}
public static bool operator != (IterableRepTemplate a1, IterableRepTemplate a2)
{
return !(a1 == a2);
}
public override int GetHashCode ()
{
return base.GetHashCode () ^ ReturnType.GetHashCode();
}
#endregion
}
public class ConstructorRepTemplate : TranslationBase, IEquatable<ConstructorRepTemplate>
{
@ -1412,6 +1483,24 @@ namespace RusticiSoftware.Translator.CLR
return null;
}
public virtual ResolveResult ResolveIterable(DirectoryHT<TypeRepTemplate> AppEnv)
{
if (Inherits != null)
{
foreach (String b in Inherits)
{
TypeRepTemplate baseType = BuildType(b, AppEnv);
if (baseType != null)
{
ResolveResult ret = baseType.ResolveIterable(AppEnv);
if (ret != null)
return ret;
}
}
}
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)
@ -1898,7 +1987,6 @@ namespace RusticiSoftware.Translator.CLR
}
}
[XmlIgnore]
private List<IndexerRepTemplate> _indexers = null;
[XmlArrayItem("Indexer")]
public List<IndexerRepTemplate> Indexers {
@ -1909,6 +1997,16 @@ namespace RusticiSoftware.Translator.CLR
}
}
private IterableRepTemplate _iterable = null;
public IterableRepTemplate Iterable {
get {
return _iterable;
}
set {
_iterable = value;
}
}
public InterfaceRepTemplate () : base()
{
Inherits = null;
@ -2088,6 +2186,19 @@ namespace RusticiSoftware.Translator.CLR
return base.ResolveIndexer(args, AppEnv);
}
public override ResolveResult ResolveIterable(DirectoryHT<TypeRepTemplate> AppEnv)
{
if (Iterable != null)
{
ResolveResult res = new ResolveResult();
res.Result = Iterable;
res.ResultType = BuildType(Iterable.ReturnType, AppEnv);
return res;
}
return base.ResolveIterable(AppEnv);
}
#region Equality
public bool Equals (InterfaceRepTemplate other)
{

View File

@ -218,15 +218,15 @@ options {
public string cleanTemplate(string template) {
// Are there any markers in the template? Mostly, the answer will be no and we can return tout-de-suite
String ret = template;
if (Regex.IsMatch(ret, "\\$\\{.*\\}")) {
if (Regex.IsMatch(ret, "\\$\\{\\w+\\}")) {
// ${this}.fred -> fred
ret = Regex.Replace(ret, "\\$\\{.*\\}\\.", String.Empty);
ret = Regex.Replace(ret, "\\$\\{\\w+?\\}\\.", String.Empty);
// (a,${var},b) -> (a,b)
ret = Regex.Replace(ret, "\\$\\{.*\\},", String.Empty);
ret = Regex.Replace(ret, "\\$\\{\\w+?\\},", String.Empty);
// (a,${var}) -> (a)
ret = Regex.Replace(ret, ",\\$\\{.*\\}", String.Empty);
ret = Regex.Replace(ret, ",\\$\\{\\w+?\\}", String.Empty);
// (${var}) -> ()
ret = Regex.Replace(ret, "\\$\\{.*\\}", String.Empty);
ret = Regex.Replace(ret, "\\$\\{\\w+?\\}", String.Empty);
}
return ret;
}

View File

@ -208,8 +208,9 @@ scope SymTab {
}
// counter to ensure that the catch vars we introduce are unique
// counter to ensure that the vars we introduce are unique
protected int dummyScrutVarCtr = 0;
protected int dummyForeachVarCtr = 0;
protected CommonTree convertSectionsToITE(List sections) {
CommonTree ret = null;
@ -256,6 +257,33 @@ scope SymTab {
return ret;
}
// embeddedStatement is either ";", "{ .... }", or a single statement
protected CommonTree prefixCast(CommonTree ty, CommonTree id, CommonTree foreachVar, CommonTree embeddedStatement, IToken tok) {
CommonTree root = embeddedStatement;
if (!embeddedStatement.IsNil && adaptor.GetType(embeddedStatement) == SEMI) {
// Do nothing, id is unused
}
else {
// Make cast statement
CommonTree kast = (CommonTree)adaptor.Nil;
kast = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(CAST_EXPR, tok, "CAST"), kast);
adaptor.AddChild(kast, (CommonTree)adaptor.DupTree(ty));
adaptor.AddChild(kast, (CommonTree)adaptor.DupTree(foreachVar));
CommonTree vardec = (CommonTree)adaptor.Nil;
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(ty));
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(id));
adaptor.AddChild(vardec, (CommonTree)adaptor.Create(ASSIGN, tok, "="));
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(kast));
root = (CommonTree)adaptor.Nil;
// Make a { <cast> statement }
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
adaptor.AddChild(root, vardec);
// todo: strip "{ }"
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(embeddedStatement));
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
}
return (CommonTree)adaptor.RulePostProcessing(root);
}
}
compilation_unit
@ -1459,11 +1487,54 @@ iteration_statement
scope SymTab;
@init {
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
CommonTree ret = null;
CommonTree newType = null;
CommonTree newIdentifier = null;
CommonTree newExpression = null;
CommonTree newEmbeddedStatement = null;
}
@after {
if (ret != null)
$iteration_statement.tree = ret;
}:
^('while' boolean_expression SEP embedded_statement)
| do_statement
| ^('for' for_initializer? SEP for_condition? SEP for_iterator? SEP embedded_statement)
| ^('foreach' local_variable_type identifier expression SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement);
| ^(f='foreach' local_variable_type identifier expression s=SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement)
magicObjectType[$f.token] magicForeachVar[$f.token]
{
newType = $local_variable_type.tree;
newIdentifier = $identifier.tree;
newExpression = $expression.tree;
newEmbeddedStatement = $embedded_statement.tree;
TypeRepTemplate exprType = $expression.dotNetType;
TypeRepTemplate elType = null;
// translate expression, if available
if (exprType != null) {
ResolveResult iterable = exprType.ResolveIterable(AppEnv);
if (iterable != null) {
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
myMap["expr"] = wrapExpression($expression.tree, $expression.tree.Token);
newExpression = mkJavaWrapper(iterable.Result.Java, myMap, $expression.tree.Token);
Imports.Add(iterable.Result.Imports);
elType = iterable.ResultType;
}
}
bool needCast = true;
if (elType != null && $local_variable_type.dotNetType != null) {
if (elType.IsA($local_variable_type.dotNetType, AppEnv)) {
needCast = false;
}
}
// Construct new foreach using newExpression and needCast
if (needCast) {
newType = $magicObjectType.tree;
newIdentifier = $magicForeachVar.tree;
newEmbeddedStatement = prefixCast($local_variable_type.tree, $identifier.tree, newIdentifier, $embedded_statement.tree, $embedded_statement.tree.Token);
}
}
-> ^($f { newType } { newIdentifier } { newExpression } $s { newEmbeddedStatement })
;
do_statement:
'do' embedded_statement 'while' '(' boolean_expression ')' ';' ;
for_initializer:
@ -1577,6 +1648,15 @@ magicScrutineeVar [IToken tok] returns [String thetext]
}:
-> IDENTIFIER[tok,$thetext];
magicForeachVar [IToken tok] returns [String thetext]
@init {
$thetext = "__dummyForeachVar" + dummyForeachVarCtr++;
}:
-> IDENTIFIER[tok,$thetext];
magicObjectType [IToken tok]:
-> ^(TYPE[tok, "TYPE"] OBJECT[tok, "System.Object"]);
magicCastOperator[CommonTree mods, String methodName, CommonTree header, CommonTree body]
@init {
IToken tok = ((CommonTree)$header.Children[0]).Token;

View File

@ -61,6 +61,7 @@ tokens {
THROW = 'throw';
ELSE = 'else';
BREAK = 'break';
OBJECT = 'object';
OPEN_BRACKET='[';
CLOSE_BRACKET=']';