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:
parent
5ece315769
commit
1fe7bceade
@ -7,6 +7,10 @@
|
||||
<Inherits>
|
||||
<Type>System.Object</Type>
|
||||
</Inherits>
|
||||
<Iterable>
|
||||
<ReturnType>System.Char</ReturnType>
|
||||
<Java>${expr}.toCharArray()</Java>
|
||||
</Iterable>
|
||||
<Methods>
|
||||
<Method>
|
||||
<Imports>
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -61,6 +61,7 @@ tokens {
|
||||
THROW = 'throw';
|
||||
ELSE = 'else';
|
||||
BREAK = 'break';
|
||||
OBJECT = 'object';
|
||||
|
||||
OPEN_BRACKET='[';
|
||||
CLOSE_BRACKET=']';
|
||||
|
Loading…
x
Reference in New Issue
Block a user