mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
3433 lines
161 KiB
Plaintext
3433 lines
161 KiB
Plaintext
/*
|
|
Copyright 2010,2011 Kevin Glynn (kevin.glynn@twigletsoftware.com)
|
|
*/
|
|
|
|
tree grammar NetMaker;
|
|
|
|
options {
|
|
tokenVocab=cs;
|
|
ASTLabelType=CommonTree;
|
|
output=AST;
|
|
language=CSharp2;
|
|
superClass='Twiglet.CS2J.Translator.Transform.NetFragments';
|
|
}
|
|
|
|
// A scope to keep track of the namespace search path available at any point in the program
|
|
scope NSContext {
|
|
|
|
string currentNS;
|
|
|
|
// all namespaces in scope
|
|
List<string> namespaces;
|
|
// all namespaces in all scopes
|
|
List<string> globalNamespaces;
|
|
|
|
// all typevariables in scope
|
|
List<string> typeVariables;
|
|
// all typevariables in all scopes
|
|
List<string> globalTypeVariables;
|
|
|
|
// Does this type implement ICollection?
|
|
bool IsGenericICollection;
|
|
string GenericICollectionTyVar;
|
|
bool IsICollection;
|
|
}
|
|
|
|
// A scope to keep track of the mapping from variables to types
|
|
scope SymTab {
|
|
Dictionary<string,TypeRepTemplate> symtab;
|
|
}
|
|
|
|
// When this scope is true, then generate equivalent Object types instead of primitive types
|
|
scope PrimitiveRep {
|
|
bool primitiveTypeAsObject;
|
|
}
|
|
|
|
// When this scope is true, then strip generic arguments from types
|
|
// (In Java the runtime doesn't know the generic types so e.g. instanceof Set<T>
|
|
// must be just instanceof Set).
|
|
scope MkNonGeneric {
|
|
bool scrubGenericArgs;
|
|
}
|
|
|
|
@namespace { Twiglet.CS2J.Translator.Transform }
|
|
|
|
@header
|
|
{
|
|
using System;
|
|
using System.Text;
|
|
using Twiglet.CS2J.Translator.Utils;
|
|
using Twiglet.CS2J.Translator.TypeRep;
|
|
using Twiglet.CS2J.Translator;
|
|
}
|
|
|
|
@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 <type>.member_name
|
|
private bool in_member_name = false;
|
|
|
|
private string CompUnitName = null;
|
|
|
|
// Initial namespace search path gathered in JavaMaker
|
|
public List<string> SearchPath { get; set; }
|
|
public List<string> AliasKeys { get; set; }
|
|
public List<string> AliasNamespaces { get; set; }
|
|
|
|
protected CommonTree mkImports() {
|
|
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
|
|
if (Imports != null) {
|
|
string[] sortedImports = Imports.AsArray();
|
|
Array.Sort(sortedImports);
|
|
foreach (string imp in sortedImports) {
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(IMPORT, "import"));
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(PAYLOAD, imp));
|
|
}
|
|
}
|
|
return root;
|
|
|
|
}
|
|
|
|
public override void AddToImports(string imp) {
|
|
// Don't add import if its namespace is within our type
|
|
// if (!imp.StartsWith($NSContext::currentNS+".")) {
|
|
if (imp != null && imp.Contains(".") && (CompUnitName == null || CompUnitName.Length == 0 || !imp.StartsWith(NSPrefix(CompUnitName)))) {
|
|
Imports.Add(imp);
|
|
}
|
|
// }
|
|
}
|
|
|
|
protected string ParentNameSpace {
|
|
get {
|
|
return ((NSContext_scope)$NSContext.ToArray()[1]).currentNS;
|
|
}
|
|
}
|
|
|
|
protected TypeRepTemplate findType(TypeRepRef name) {
|
|
return findType(name.Type);
|
|
}
|
|
|
|
protected TypeRepTemplate findType(string name) {
|
|
if ($NSContext::globalTypeVariables.Contains(name)) {
|
|
return new TypeVarRepTemplate(name);
|
|
}
|
|
return AppEnv.Search($NSContext::globalNamespaces, name, new UnknownRepTemplate(name));
|
|
}
|
|
|
|
protected TypeRepTemplate findType(string name, ICollection<TypeRepTemplate> args) {
|
|
if (args == null || args.Count == 0) {
|
|
return findType(name);
|
|
}
|
|
StringBuilder argNames = new StringBuilder();
|
|
bool first = true;
|
|
if (args != null && args.Count > 0) {
|
|
argNames.Append("<");
|
|
foreach (TypeRepTemplate sub in args) {
|
|
if (!first) {
|
|
argNames.Append(", ");
|
|
first = false;
|
|
}
|
|
argNames.Append(sub.TypeName);
|
|
}
|
|
argNames.Append(">");
|
|
}
|
|
|
|
TypeRepTemplate tyRep = AppEnv.Search($NSContext::globalNamespaces, mkGenericTypeAlias(name, args != null ? args.Count : 0), new UnknownRepTemplate(name + argNames.ToString()));
|
|
return (args != null && args.Count > 0 ? tyRep.Instantiate(args) : tyRep);
|
|
}
|
|
|
|
private ClassRepTemplate objectType = null;
|
|
|
|
protected ClassRepTemplate ObjectType {
|
|
get {
|
|
if (objectType == null) {
|
|
objectType = (ClassRepTemplate)AppEnv.Search("System.Object", new UnknownRepTemplate("System.Object"));
|
|
}
|
|
return objectType;
|
|
}
|
|
}
|
|
|
|
private ClassRepTemplate boolType = null;
|
|
|
|
protected ClassRepTemplate BoolType {
|
|
get {
|
|
if (boolType == null) {
|
|
boolType = (ClassRepTemplate)AppEnv.Search("System.Boolean", new UnknownRepTemplate("System.Boolean"));
|
|
}
|
|
return boolType;
|
|
}
|
|
}
|
|
|
|
private ClassRepTemplate voidType = null;
|
|
|
|
protected ClassRepTemplate VoidType {
|
|
get {
|
|
if (voidType == null) {
|
|
voidType = (ClassRepTemplate)AppEnv.Search("System.Void", new UnknownRepTemplate("System.Void"));
|
|
}
|
|
return voidType;
|
|
}
|
|
}
|
|
|
|
private ClassRepTemplate stringType = null;
|
|
|
|
protected ClassRepTemplate StringType {
|
|
get {
|
|
if (stringType == null) {
|
|
stringType = (ClassRepTemplate)AppEnv.Search("System.String", new UnknownRepTemplate("System.String"));
|
|
}
|
|
return stringType;
|
|
}
|
|
}
|
|
|
|
private ClassRepTemplate dateType = null;
|
|
protected ClassRepTemplate DateType {
|
|
get {
|
|
if (dateType == null) {
|
|
dateType = (ClassRepTemplate)AppEnv.Search("System.DateTime", new UnknownRepTemplate("System.DateTime"));
|
|
}
|
|
return dateType;
|
|
}
|
|
}
|
|
|
|
private InterfaceRepTemplate iCollectionType = null;
|
|
protected InterfaceRepTemplate ICollectionType {
|
|
get {
|
|
if (iCollectionType == null) {
|
|
iCollectionType = (InterfaceRepTemplate)findType("System.Collections.ICollection");
|
|
}
|
|
return iCollectionType;
|
|
}
|
|
}
|
|
|
|
private InterfaceRepTemplate genericICollectionType = null;
|
|
protected InterfaceRepTemplate GenericICollectionType {
|
|
get {
|
|
if (genericICollectionType == null) {
|
|
genericICollectionType = (InterfaceRepTemplate)findType("System.Collections.Generic.ICollection", new TypeRepTemplate[] {ObjectType});
|
|
}
|
|
return genericICollectionType;
|
|
}
|
|
}
|
|
|
|
protected TypeRepTemplate SymTabLookup(string name) {
|
|
return SymTabLookup(name, null);
|
|
}
|
|
|
|
protected TypeRepTemplate SymTabLookup(string name, TypeRepTemplate def) {
|
|
object[] stabs = $SymTab.ToArray();
|
|
foreach(SymTab_scope stabScope in stabs) {
|
|
if (stabScope.symtab.ContainsKey(name)) {
|
|
return stabScope.symtab[name];
|
|
}
|
|
}
|
|
return def;
|
|
}
|
|
|
|
protected CommonTree mkJavaWrapper(string template, Dictionary<string,CommonTree> varMap, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPER, tok, "JAVAWRAPPER"), root);
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, template));
|
|
|
|
if (varMap != null) {
|
|
foreach (string var in varMap.Keys) {
|
|
if (varMap[var] != null) {
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, var));
|
|
adaptor.AddChild(root, dupTree(varMap[var]));
|
|
}
|
|
}
|
|
}
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
protected CommonTree wrapExpression(CommonTree e, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPEREXPRESSION, tok, "JAVAWRAPPEREXPRESSION"), root);
|
|
adaptor.AddChild(root, dupTree(e));
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
protected CommonTree wrapArgument(CommonTree e, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPERARGUMENT, tok, "JAVAWRAPPERARGUMENT"), root);
|
|
adaptor.AddChild(root, dupTree(e));
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
protected CommonTree wrapArgumentList(CommonTree e, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPERARGUMENTLIST, tok, "JAVAWRAPPERARGUMENTLIST"), root);
|
|
adaptor.AddChild(root, dupTree(e));
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
protected CommonTree mkArgumentList(CommonTree e1, IToken tok) {
|
|
if (adaptor.IsNil(e1))
|
|
return e1;
|
|
|
|
CommonTree argList = (CommonTree)adaptor.Nil;
|
|
argList = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), argList);
|
|
adaptor.AddChild(argList, dupTree(e1));
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(argList);
|
|
}
|
|
|
|
protected CommonTree mkArgumentList(CommonTree e1, CommonTree e2, IToken tok) {
|
|
CommonTree argList = (CommonTree)adaptor.Nil;
|
|
argList = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), argList);
|
|
adaptor.AddChild(argList, dupTree(e1));
|
|
adaptor.AddChild(argList, dupTree(e2));
|
|
|
|
return (CommonTree)adaptor.RulePostProcessing(argList);
|
|
}
|
|
|
|
protected CommonTree mkArgumentList(IToken tok, params CommonTree[] es) {
|
|
CommonTree argList = (CommonTree)adaptor.Nil;
|
|
if (es == null || es.Length == 0)
|
|
return argList;
|
|
|
|
argList = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), argList);
|
|
if (es != null) {
|
|
foreach (CommonTree e in es) {
|
|
adaptor.AddChild(argList, dupTree(e));
|
|
}
|
|
}
|
|
return (CommonTree)adaptor.RulePostProcessing(argList);
|
|
}
|
|
|
|
protected CommonTree mkArgumentList(IToken tok, IList<CommonTree> es) {
|
|
CommonTree argList = (CommonTree)adaptor.Nil;
|
|
if (es == null || es.Count == 0)
|
|
return argList;
|
|
|
|
argList = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), argList);
|
|
if (es != null) {
|
|
foreach (CommonTree e in es) {
|
|
adaptor.AddChild(argList, dupTree(e));
|
|
}
|
|
}
|
|
return (CommonTree)adaptor.RulePostProcessing(argList);
|
|
}
|
|
|
|
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);
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, t.Java));
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populates the param Map that gives values for tokens in a Java template
|
|
/// </summary>
|
|
/// <param name="pMap">
|
|
/// A <see cref="Dictionary<System.String, CommonTree>"/>. The map to populate.
|
|
/// </param>
|
|
/// <param name="ps">
|
|
/// A <see cref="IList<ParamRepTemplate>"/>. The parameters.
|
|
/// </param>
|
|
/// <param name="argTrees">
|
|
/// A <see cref="IList<CommonTree>"/>. The expressions for each parameter.
|
|
/// </param>
|
|
/// <param name="argTreeTypeofTypes">
|
|
/// A <see cref="IList<TypeRepTemplate>"/>. (May be null). The type of each argument.
|
|
/// </param>
|
|
/// <param name="argListTree">
|
|
/// A <see cref="CommonTree"/>. (May be null). A Tree with the list of arguments. If needed and not provided then we build it from argTrees.
|
|
/// </param>
|
|
/// <param name="incStar">
|
|
/// A <see cref="System.Boolean"/>. If true then substitute for arglist parameters ("${*]n}") using argListTree.
|
|
/// </param>
|
|
/// <param name="tok">
|
|
/// A <see cref="IToken"/> Mark created trees with this token's posiition.
|
|
/// </param>
|
|
protected void populateParamMap(Dictionary<string,CommonTree> pMap, IList<ParamRepTemplate> ps,
|
|
IList<CommonTree> argTrees, IList<TypeRepTemplate> argTreeTypeofTypes, CommonTree argListTree,
|
|
bool incStar, IToken tok) {
|
|
populateParamMap(pMap, ps, argTrees, argTreeTypeofTypes, argListTree, incStar, null, null, tok);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populates the param Map that gives values for tokens in a Java template
|
|
/// </summary>
|
|
/// <param name="pMap">
|
|
/// A <see cref="Dictionary<System.String, CommonTree>"/>. The map to populate.
|
|
/// </param>
|
|
/// <param name="ps">
|
|
/// A <see cref="IList<ParamRepTemplate>"/>. The parameters.
|
|
/// </param>
|
|
/// <param name="argTrees">
|
|
/// A <see cref="IList<CommonTree>"/>. The expressions for each parameter.
|
|
/// </param>
|
|
/// <param name="argTreeTypeofTypes">
|
|
/// A <see cref="IList<TypeRepTemplate>"/>. (May be null). The type of each argument.
|
|
/// </param>
|
|
/// <param name="argListTree">
|
|
/// A <see cref="CommonTree"/>. (May be null). A Tree with the list of arguments. If needed and not provided then we build it from argTrees.
|
|
/// </param>
|
|
/// <param name="incStar">
|
|
/// A <see cref="System.Boolean"/>. If true then substitute for arglist parameters ("${*]n}") using argListTree.
|
|
/// </param>
|
|
/// <param name="typeParams">
|
|
/// A <see cref="String[]"/>. (May be null). Array of Type Parameter Names.
|
|
/// </param>
|
|
/// <param name="typeTrees">
|
|
/// A <see cref="IList<CommonTree>"/> (May be null). Types to substitute for typeParams.
|
|
/// </param>
|
|
/// <param name="tok">
|
|
/// A <see cref="IToken"/> Mark created trees with this token's posiition.
|
|
/// </param>
|
|
protected void populateParamMap(Dictionary<string,CommonTree> pMap, IList<ParamRepTemplate> ps,
|
|
IList<CommonTree> argTrees, IList<TypeRepTemplate> argTreeTypeofTypes, CommonTree argListTree,
|
|
bool incStar, String[] typeParams, IList<CommonTree> typeTrees,
|
|
IToken tok) {
|
|
for (int idx = 0; idx < ps.Count; idx++) {
|
|
pMap[ps[idx].Name] = wrapArgument(argTrees[idx], tok);
|
|
if (ps[idx].Name.StartsWith("TYPEOF") && argTreeTypeofTypes != null && argTreeTypeofTypes[idx] != null) {
|
|
// if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
|
|
pMap[ps[idx].Name + "_TYPE"] = wrapTypeOfType(argTreeTypeofTypes[idx], tok);
|
|
}
|
|
}
|
|
if (incStar)
|
|
{
|
|
pMap["*"] = wrapArgumentList(argListTree != null ? argListTree : mkArgumentList(tok, argTrees), tok);
|
|
}
|
|
if (typeTrees != null && typeTrees.Count == typeParams.Length) {
|
|
int idx = 0;
|
|
foreach (CommonTree ty in typeTrees)
|
|
{
|
|
pMap[typeParams[idx]] = wrapType(ty, tok);
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected bool wantsStar(String template) {
|
|
return template.Contains("${*") || template.Contains("${,*");
|
|
}
|
|
|
|
protected CommonTree mkArray(CommonTree t, IToken tok) {
|
|
if (!t.IsNil) {
|
|
adaptor.AddChild(t, (CommonTree)adaptor.Create(OPEN_BRACKET, tok, "["));
|
|
adaptor.AddChild(t, (CommonTree)adaptor.Create(CLOSE_BRACKET, tok, "]"));
|
|
}
|
|
return t;
|
|
}
|
|
|
|
protected CommonTree castToBoxedType(TypeRepTemplate ty, CommonTree exp, IToken tok) {
|
|
if (!String.IsNullOrEmpty(ty.BoxExpressionTemplate)) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["expr"] = wrapExpression(exp, tok);
|
|
return mkJavaWrapper(ty.BoxExpressionTemplate, myMap, tok);
|
|
}
|
|
else {
|
|
return dupTree(exp);
|
|
}
|
|
}
|
|
|
|
protected CommonTree dupTree(CommonTree t) {
|
|
return (CommonTree)adaptor.DupTree(t);
|
|
}
|
|
|
|
protected static readonly string[] ScruTypeStrs = new string[] { "System.Int32",
|
|
"System.Int64",
|
|
"System.Char",
|
|
"System.Enum",
|
|
};
|
|
|
|
protected bool typeIsInvalidForScrutinee(TypeRepTemplate sType) {
|
|
bool ret = true;
|
|
|
|
foreach (string t in ScruTypeStrs)
|
|
{
|
|
if (sType.IsA(AppEnv.Search(t), AppEnv))
|
|
{
|
|
ret = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
// counter to ensure that the vars we introduce are unique
|
|
protected int dummyScrutVarCtr = 0;
|
|
protected int dummyForeachVarCtr = 0;
|
|
protected int dummyStaticConstructorCatchVarCtr = 0;
|
|
protected int dummyTyVarCtr = 0;
|
|
protected int dummyRefVarCtr = 0;
|
|
protected int dummyVarCtr = 0;
|
|
|
|
// It turns out that 'default:' doesn't have to be last in the switch statement, so
|
|
// we need some jiggery pokery when converting to if-then-else.
|
|
// If there was a default section then 'defaultTree' will be non-null and 'sections'
|
|
// will have a null entry (the hole where the default section appeared).
|
|
protected CommonTree convertSectionsToITE(List sections, CommonTree defaultTree) {
|
|
CommonTree ret = null;
|
|
if ((sections == null || sections.Count == 1) && defaultTree != null) {
|
|
// We just had a default section, so emit it.
|
|
ret = dupTree(defaultTree);
|
|
}
|
|
else if (sections != null) {
|
|
int startidx = sections.Count - 2;
|
|
if (defaultTree != null) {
|
|
// must have at least if .. then .. else
|
|
// wrap default in else { }
|
|
IToken tok = defaultTree.Token;
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(ELSE, tok, "else"));
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
adaptor.AddChild(root, dupTree(defaultTree));
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
ret = root;
|
|
startidx = sections.Count - 1;
|
|
}
|
|
else {
|
|
ret = dupTree((CommonTree)sections[sections.Count - 1]);
|
|
}
|
|
for(int i = startidx; i >= 0; i--) {
|
|
if (sections[i] != null) {
|
|
CommonTree section = dupTree((CommonTree)sections[i]);
|
|
// section is either ^(IF ...) or "else ^(IF ....)" we need to insert ret into the IF
|
|
if (section.IsNil) {
|
|
section.Children[section.Children.Count-1].AddChild(ret);
|
|
}
|
|
else {
|
|
section.AddChild(ret);
|
|
}
|
|
ret = section;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// In switch sections we want to remove final break statements if we have converted to if-then-else
|
|
protected CommonTree stripFinalBreak(CommonTree stats) {
|
|
|
|
CommonTree ret = stats;
|
|
if (stats.IsNil) {
|
|
// A list of statements
|
|
// look for an ending of "break [;]"
|
|
int len = stats.Children.Count;
|
|
int breakPos = len - 1;
|
|
if ( len > 1 && stats.Children[len-1].Type == SEMI ) {
|
|
breakPos = len -2;
|
|
}
|
|
if (stats.Children[breakPos].Type != BREAK) {
|
|
// not found
|
|
breakPos = -1;
|
|
}
|
|
if (breakPos >= 0) {
|
|
// delete from break to end
|
|
for (int i = len-1; i >= breakPos; i--) {
|
|
stats.DeleteChild(i);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// if slist is a list of statements surrounded by braces, then strip them out.
|
|
protected CommonTree stripPossibleBraces(CommonTree slist) {
|
|
CommonTree ret = slist;
|
|
if (ret.IsNil && adaptor.GetChildCount(ret) >= 2) {
|
|
if (adaptor.GetType(adaptor.GetChild(ret,0)) == OPEN_BRACE &&
|
|
adaptor.GetType(adaptor.GetChild(ret,adaptor.GetChildCount(ret)-1)) == CLOSE_BRACE) {
|
|
adaptor.DeleteChild(ret,adaptor.GetChildCount(ret)-1);
|
|
adaptor.DeleteChild(ret,0);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// embeddedStatement is either ";", "{ .... }", or a single statement
|
|
protected CommonTree prefixCast(CommonTree targetTy, CommonTree id, CommonTree castTy, 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(castTy));
|
|
adaptor.AddChild(kast, (CommonTree)adaptor.DupTree(foreachVar));
|
|
CommonTree vardec = (CommonTree)adaptor.Nil;
|
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(targetTy));
|
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(id));
|
|
adaptor.AddChild(vardec, (CommonTree)adaptor.Create(ASSIGN, tok, "="));
|
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(kast));
|
|
adaptor.AddChild(vardec, (CommonTree)adaptor.Create(SEMI, tok, ";"));
|
|
root = (CommonTree)adaptor.Nil;
|
|
// Make a { <cast> statement }
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
adaptor.AddChild(root, vardec);
|
|
|
|
adaptor.AddChild(root, stripPossibleBraces((CommonTree)adaptor.DupTree(embeddedStatement)));
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
}
|
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
|
|
private Dictionary<int,string> _boxTypeMap = null;
|
|
protected Dictionary<int,string> BoxTypeMap {
|
|
get {
|
|
if (_boxTypeMap == null) {
|
|
_boxTypeMap = new Dictionary<int,string>();
|
|
// Initialize boxTypeMap (see JLS, ed 3 sec 5.1.7)
|
|
_boxTypeMap[BOOL] = "Boolean";
|
|
_boxTypeMap[BYTE] = "Byte";
|
|
_boxTypeMap[CHAR] = "Character";
|
|
_boxTypeMap[SHORT] = "Short";
|
|
_boxTypeMap[INT] = "Integer";
|
|
_boxTypeMap[LONG] = "Long";
|
|
_boxTypeMap[FLOAT] = "Float";
|
|
_boxTypeMap[DOUBLE] = "Double";
|
|
}
|
|
return _boxTypeMap;
|
|
}
|
|
}
|
|
|
|
protected CommonTree mkBoxedType(CommonTree ty, IToken tok) {
|
|
CommonTree ret = ty;
|
|
// Make sure its just plain old predefined type
|
|
if (!ty.IsNil && adaptor.GetType(ty) == TYPE && adaptor.GetChildCount(ty) == 1 &&
|
|
BoxTypeMap.ContainsKey(adaptor.GetType(((CommonTree)adaptor.GetChild(ty,0)))) ) {
|
|
ret = (CommonTree)adaptor.Nil;
|
|
ret = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), ret);
|
|
adaptor.AddChild(ret, (CommonTree)adaptor.Create(IDENTIFIER, tok, BoxTypeMap[adaptor.GetType((CommonTree)adaptor.GetChild(ty,0))]));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
private Dictionary<int,int> _assOpMap = null;
|
|
protected Dictionary<int,int> AssOpMap {
|
|
get {
|
|
if (_assOpMap == null) {
|
|
_assOpMap = new Dictionary<int,int>();
|
|
// Initialize boxTypeMap (see JLS, ed 3 sec 5.1.7)
|
|
_assOpMap[PLUS_ASSIGN] = PLUS;
|
|
_assOpMap[MINUS_ASSIGN] = MINUS;
|
|
_assOpMap[STAR_ASSIGN] = STAR;
|
|
_assOpMap[DIV_ASSIGN] = DIV;
|
|
_assOpMap[MOD_ASSIGN] = MOD;
|
|
_assOpMap[BIT_AND_ASSIGN] = BIT_AND;
|
|
_assOpMap[BIT_OR_ASSIGN] = BIT_OR;
|
|
_assOpMap[BIT_XOR_ASSIGN] = BIT_XOR;
|
|
_assOpMap[LEFT_SHIFT_ASSIGN] = LEFT_SHIFT;
|
|
_assOpMap[RIGHT_SHIFT_ASSIGN] = RIGHT_SHIFT;
|
|
}
|
|
return _assOpMap;
|
|
}
|
|
}
|
|
|
|
protected CommonTree mkOpExp(CommonTree assTree) {
|
|
CommonTree ret = assTree;
|
|
if (AssOpMap.ContainsKey(assTree.Token.Type)) {
|
|
ret = (CommonTree)adaptor.Create(AssOpMap[assTree.Token.Type], assTree.Token, assTree.Token.Text != null && assTree.Token.Text.EndsWith("=") ? assTree.Token.Text.Substring(0, assTree.Token.Text.Length - 1) : assTree.Token.Text);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// make ^(op lhs rhs)
|
|
protected CommonTree mkOpExp(CommonTree opTree, CommonTree lhs, CommonTree rhs) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.DupTree(opTree), root);
|
|
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(lhs));
|
|
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(rhs));
|
|
return root;
|
|
}
|
|
|
|
protected CommonTree mkJavaRep(IToken tok, TypeRepTemplate ty) {
|
|
if (ty.InstantiatedTypes == null || ty.InstantiatedTypes.Length == 0) {
|
|
return (CommonTree)adaptor.Create(IDENTIFIER, tok, ty.Java);
|
|
}
|
|
else {
|
|
Dictionary<string,CommonTree> tyMap = new Dictionary<string,CommonTree>();
|
|
int i = 0;
|
|
foreach (TypeRepTemplate tyArg in ty.InstantiatedTypes) {
|
|
CommonTree typeRoot = (CommonTree)adaptor.Nil;
|
|
typeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), typeRoot);
|
|
adaptor.AddChild(typeRoot, mkJavaRep(tok, tyArg));
|
|
tyMap[ty.TypeParams[i]] = wrapType(typeRoot, tok);
|
|
i++;
|
|
}
|
|
return mkJavaWrapper(ty.Java, tyMap, tok);
|
|
}
|
|
}
|
|
|
|
// either ^(PARAMS (type identifier)*) or ^(ARGS identifier*) depending on value of formal
|
|
protected CommonTree mkParams(TypeRepTemplate tyRep, List<ParamRepTemplate> inParams, bool formal, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(formal ? PARAMS : ARGS, tok, formal ? "PARAMS" : "ARGS"), root);
|
|
foreach (ParamRepTemplate p in inParams) {
|
|
if (formal) {
|
|
TypeRepTemplate ty = tyRep.BuildType(p.Type, AppEnv, new UnknownRepTemplate(p.Type));
|
|
CommonTree typeRoot = (CommonTree)adaptor.Nil;
|
|
typeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), typeRoot);
|
|
adaptor.AddChild(typeRoot, mkJavaRep(tok, ty));
|
|
adaptor.AddChild(root, typeRoot);
|
|
AddToImports(ty.Imports);
|
|
}
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, p.Name));
|
|
}
|
|
return root;
|
|
}
|
|
|
|
// make ^(PARAMS (type identifier)*) from a List<ParamRepTemplate (for the types) and List<IDENTIFIER> for the names
|
|
protected CommonTree mkTypedParams(List<ParamRepTemplate> inParams, List<CommonTree> ids, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(PARAMS, tok, "PARAMS"), root);
|
|
CommonTree[] idsArray = ids.ToArray();
|
|
int i = 0;
|
|
foreach (ParamRepTemplate p in inParams) {
|
|
TypeRepTemplate ty = findType(p.Type);
|
|
CommonTree typeRoot = (CommonTree)adaptor.Nil;
|
|
typeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), typeRoot);
|
|
adaptor.AddChild(typeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, ty.Java));
|
|
adaptor.AddChild(root, typeRoot);
|
|
AddToImports(ty.Imports);
|
|
adaptor.AddChild(root, dupTree(idsArray[i]));
|
|
i++;
|
|
}
|
|
return root;
|
|
}
|
|
|
|
// public List<delegate_type> GetInvocationList() throws Exception {
|
|
// List<delegate_type> ret = new ArrayList<delegate_type>();
|
|
// ret.add(this);
|
|
// return ret;
|
|
// }
|
|
protected CommonTree mkDelegateGetInvocationList(CommonTree delTree, TypeRepTemplate delType, IToken tok) {
|
|
|
|
// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
|
|
CommonTree method = (CommonTree)adaptor.Nil;
|
|
method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
|
|
|
|
CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
|
|
retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
|
|
adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, "List"));
|
|
AddToImports("java.util.List");
|
|
adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
|
|
CommonTree delTypeRoot = (CommonTree)adaptor.Nil;
|
|
if (delTree != null) {
|
|
delTypeRoot = dupTree(delTree);
|
|
}
|
|
else {
|
|
delTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTypeRoot);
|
|
adaptor.AddChild(delTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, delType.mkFormattedTypeName(false, "<",">")));
|
|
AddToImports(delType.Imports);
|
|
}
|
|
adaptor.AddChild(retTypeRoot, delTypeRoot);
|
|
|
|
adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(GT, tok, ">"));
|
|
|
|
adaptor.AddChild(method, retTypeRoot);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "GetInvocationList"));
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
|
|
|
|
CommonTree body = (CommonTree)adaptor.Nil;
|
|
|
|
// List<delegate_type> ret = new ArrayList<delegate_type>();
|
|
CommonTree retdecl = (CommonTree)adaptor.Nil;
|
|
|
|
adaptor.AddChild(retdecl, dupTree(retTypeRoot));
|
|
adaptor.AddChild(retdecl, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
|
|
adaptor.AddChild(retdecl, (CommonTree)adaptor.Create(ASSIGN, tok, "="));
|
|
|
|
CommonTree newA = (CommonTree)adaptor.Nil;
|
|
newA = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW, tok, "new"), newA);
|
|
|
|
CommonTree alTypeRoot = (CommonTree)adaptor.Nil;
|
|
alTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), alTypeRoot);
|
|
adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ArrayList"));
|
|
AddToImports("java.util.ArrayList");
|
|
adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
|
|
|
|
adaptor.AddChild(alTypeRoot, dupTree(delTypeRoot));
|
|
|
|
adaptor.AddChild(alTypeRoot, (CommonTree)adaptor.Create(GT, tok, ">"));
|
|
|
|
adaptor.AddChild(newA, alTypeRoot);
|
|
adaptor.AddChild(retdecl, newA);
|
|
adaptor.AddChild(body, retdecl);
|
|
adaptor.AddChild(body, (CommonTree)adaptor.Create(SEMI, tok, ";"));
|
|
|
|
// ret.add(this)
|
|
CommonTree retaddcall = (CommonTree)adaptor.Nil;
|
|
retaddcall = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(APPLY, tok, "APPLY"), retaddcall);
|
|
|
|
CommonTree retadd = (CommonTree)adaptor.Nil;
|
|
retadd = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(DOT, tok, "."), retadd);
|
|
adaptor.AddChild(retadd, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
|
|
adaptor.AddChild(retadd, (CommonTree)adaptor.Create(IDENTIFIER, tok, "add"));
|
|
|
|
adaptor.AddChild(retaddcall, retadd);
|
|
|
|
CommonTree arg = (CommonTree)adaptor.Nil;
|
|
arg = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(ARGS, tok, "ARGS"), arg);
|
|
|
|
adaptor.AddChild(arg, (CommonTree)adaptor.Create(THIS, tok, "this"));
|
|
adaptor.AddChild(retaddcall, arg);
|
|
adaptor.AddChild(body,retaddcall);
|
|
adaptor.AddChild(body, (CommonTree)adaptor.Create(SEMI, tok, ";"));
|
|
|
|
// return ret;
|
|
CommonTree ret = (CommonTree)adaptor.Nil;
|
|
ret = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(RETURN, tok, "return"), ret);
|
|
adaptor.AddChild(ret, (CommonTree)adaptor.Create(IDENTIFIER, tok, "ret"));
|
|
adaptor.AddChild(body,ret);
|
|
|
|
adaptor.AddChild(method, body);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
|
|
|
|
return method;
|
|
}
|
|
|
|
// new <delegate_type>() { public void Invoke(<formal args>) throws Exception { [return] arg[0](<args>); }
|
|
// public List<delegate_type> GetInvocationList() throws Exception { ... }}
|
|
protected CommonTree mkDelegateObject(CommonTree delTree, CommonTree methTree, DelegateRepTemplate delg, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW_DELEGATE, tok, "NEW_DELEGATE"), root);
|
|
if (delTree != null) {
|
|
adaptor.AddChild(root, dupTree(delTree));
|
|
}
|
|
else {
|
|
CommonTree delTyTree = (CommonTree)adaptor.Nil;
|
|
delTyTree = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTyTree);
|
|
adaptor.AddChild(delTyTree, (CommonTree)adaptor.Create(IDENTIFIER, tok, delg.mkFormattedTypeName(false, "<",">")));
|
|
AddToImports(delg.Imports);
|
|
adaptor.AddChild(root, delTyTree);
|
|
}
|
|
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
|
|
// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
|
|
CommonTree method = (CommonTree)adaptor.Nil;
|
|
method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
|
|
|
|
TypeRepTemplate returnType = findType(delg.Invoke.Return);
|
|
AddToImports(returnType.Imports);
|
|
CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
|
|
retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
|
|
adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, returnType.Java));
|
|
adaptor.AddChild(method, retTypeRoot);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "Invoke"));
|
|
if (delg.Invoke.Params.Count > 0) {
|
|
adaptor.AddChild(method, mkParams(delg, delg.Invoke.Params, true, tok));
|
|
}
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
|
|
CommonTree ret = (CommonTree)adaptor.Nil;
|
|
ret = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(RETURN, tok, "return"), ret);
|
|
|
|
CommonTree call = (CommonTree)adaptor.Nil;
|
|
call = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(APPLY, tok, "APPLY"), call);
|
|
adaptor.AddChild(call, dupTree(methTree));
|
|
if (delg.Invoke.Params.Count > 0) {
|
|
adaptor.AddChild(call, mkParams(delg, delg.Invoke.Params, false, tok));
|
|
}
|
|
if (returnType.IsA(VoidType, AppEnv)) {
|
|
adaptor.AddChild(ret, call);
|
|
adaptor.AddChild(method, ret);
|
|
}
|
|
else {
|
|
adaptor.AddChild(method, call);
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(SEMI, tok, ";"));
|
|
}
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
|
|
adaptor.AddChild(root, method);
|
|
adaptor.AddChild(root, mkDelegateGetInvocationList(delTree, delg, tok));
|
|
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
|
|
return root;
|
|
}
|
|
|
|
// new <delegate_type>() { public void Invoke(<formal args>) throw exception <body> }
|
|
protected CommonTree mkDelegateObject(CommonTree delTree, CommonTree argsTree, CommonTree bodyTree, DelegateRepTemplate delg, IToken tok) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(NEW_DELEGATE, tok, "NEW_DELEGATE"), root);
|
|
if (delTree != null) {
|
|
adaptor.AddChild(root, dupTree(delTree));
|
|
}
|
|
else {
|
|
CommonTree delTyTree = (CommonTree)adaptor.Nil;
|
|
delTyTree = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), delTyTree);
|
|
adaptor.AddChild(delTyTree, (CommonTree)adaptor.Create(IDENTIFIER, tok, delg.mkFormattedTypeName(false, "<",">")));
|
|
AddToImports(delg.Imports);
|
|
adaptor.AddChild(root, delTyTree);
|
|
}
|
|
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
|
|
|
// | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? method_body exception*)
|
|
CommonTree method = (CommonTree)adaptor.Nil;
|
|
method = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(METHOD, tok, "METHOD"), method);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(PUBLIC, tok, "public"));
|
|
|
|
TypeRepTemplate returnType = findType(delg.Invoke.Return);
|
|
AddToImports(returnType.Imports);
|
|
CommonTree retTypeRoot = (CommonTree)adaptor.Nil;
|
|
retTypeRoot = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), retTypeRoot);
|
|
adaptor.AddChild(retTypeRoot, (CommonTree)adaptor.Create(IDENTIFIER, tok, returnType.Java));
|
|
adaptor.AddChild(method, retTypeRoot);
|
|
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(IDENTIFIER, tok, "Invoke"));
|
|
adaptor.AddChild(method, dupTree(argsTree));
|
|
adaptor.AddChild(method, dupTree(bodyTree));
|
|
adaptor.AddChild(method, (CommonTree)adaptor.Create(EXCEPTION, tok, "Exception"));
|
|
adaptor.AddChild(root, method);
|
|
adaptor.AddChild(root, mkDelegateGetInvocationList(delTree, delg, tok));
|
|
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(CLOSE_BRACE, tok, "}"));
|
|
|
|
return root;
|
|
}
|
|
|
|
}
|
|
|
|
public compilation_unit
|
|
scope NSContext, PrimitiveRep, MkNonGeneric;
|
|
@init {
|
|
|
|
$PrimitiveRep::primitiveTypeAsObject = false;
|
|
$MkNonGeneric::scrubGenericArgs = false;
|
|
|
|
// TODO: Do we need to ensure we have access to System? If so, can add it here.
|
|
$NSContext::namespaces = SearchPath ?? new List<string>();
|
|
$NSContext::globalNamespaces = SearchPath ?? new List<string>();
|
|
|
|
$NSContext::typeVariables = new List<string>();
|
|
$NSContext::globalTypeVariables = new List<string>();
|
|
|
|
$NSContext::IsGenericICollection = false;
|
|
$NSContext::GenericICollectionTyVar = "";
|
|
$NSContext::IsICollection = false;
|
|
|
|
}:
|
|
^(pkg=PACKAGE ns=PAYLOAD { $NSContext::currentNS = $ns.text; } dec=type_declaration )
|
|
-> ^($pkg $ns { mkImports() } $dec);
|
|
|
|
type_declaration:
|
|
class_declaration
|
|
| interface_declaration
|
|
| enum_declaration
|
|
;
|
|
// Identifiers
|
|
qualified_identifier:
|
|
identifier ('.' identifier)*;
|
|
|
|
modifiers returns [List<string> modList]
|
|
@init {
|
|
$modList = new List<string>();
|
|
}:
|
|
(modifier { $modList.Add($modifier.tree.Text); } )+ ;
|
|
modifier:
|
|
'new' | 'public' | 'protected' | 'private' | 'abstract' | 'sealed' | 'static'
|
|
| 'readonly' | 'volatile' | 'extern' | 'virtual' | 'override' | FINAL ;
|
|
|
|
class_member_declaration:
|
|
^(CONST attributes? modifiers? type constant_declarators[$type.dotNetType])
|
|
| ^(EVENT attributes? modifiers? event_declaration)
|
|
| ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list[null,null]? method_body exception*)
|
|
| interface_declaration
|
|
| class_declaration
|
|
| ^(FIELD attributes? modifiers? type field_declaration[$type.tree, $type.dotNetType])
|
|
| ^(OPERATOR attributes? modifiers? type operator_declaration)
|
|
| enum_declaration
|
|
| ^(CONVERSION_OPERATOR attributes? modifiers? conversion_operator_declaration[$attributes.tree, $modifiers.tree]) -> conversion_operator_declaration
|
|
| constructor_declaration
|
|
;
|
|
|
|
exception:
|
|
EXCEPTION;
|
|
|
|
constructor_declaration
|
|
@init {
|
|
bool isStatic = false;
|
|
}:
|
|
^(c=CONSTRUCTOR attributes? (modifiers { isStatic = $modifiers.modList.Contains("static"); })? identifier formal_parameter_list[null,null]? block exception* sb=magicSmotherExceptionsThrow[$block.tree, "ExceptionInInitializerError"])
|
|
-> { isStatic }? ^(STATIC_CONSTRUCTOR[$c.token, "CONSTRUCTOR"] attributes? modifiers? $sb)
|
|
-> ^($c attributes? modifiers? identifier formal_parameter_list? block exception*)
|
|
;
|
|
|
|
|
|
|
|
// rmId is the rightmost ID in an expression like fdfd.dfdsf.returnme, otherwise it is null
|
|
// used in switch labels to strip down qualified types, which Java doesn't grok
|
|
// thedottedtext is the text read so far that *might* be part of a qualified type
|
|
primary_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
|
|
scope {
|
|
bool parentIsApply;
|
|
}
|
|
@init {
|
|
$primary_expression::parentIsApply = false;
|
|
CommonTree ret = null;
|
|
TypeRepTemplate expType = SymTabLookup("this");
|
|
bool implicitThis = true;
|
|
$thedottedtext = null;
|
|
string popstr = null;
|
|
CommonTree e1Tree = null;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$primary_expression.tree = ret;
|
|
}:
|
|
^(index=INDEX ie=expression[ObjectType] expression_list?)
|
|
{
|
|
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<TypeRepTemplate>(), AppEnv);
|
|
if (indexerResult != null) {
|
|
if (!String.IsNullOrEmpty(indexerResult.Result.Warning)) Warning($index.line, indexerResult.Result.Warning);
|
|
IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
|
|
if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
|
|
populateParamMap(myMap, indexerRep.Params, $expression_list.expTrees, $expression_list.expTreeTypeofTypes, null, wantsStar(indexerResult.Result.Java), $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 against " + expType.TypeName);
|
|
}
|
|
}
|
|
| (^(APPLY (^('.' expression[ObjectType] identifier generic_argument_list?)|(identifier generic_argument_list?)) argument_list?)) =>
|
|
^(APPLY (^(d0='.' e2=expression[ObjectType] {expType = $e2.dotNetType; implicitThis = false;} i2=identifier generic_argument_list?)|(i2=identifier generic_argument_list?)) argument_list?)
|
|
{
|
|
if (implicitThis && SymTabLookup($i2.thetext) != null) {
|
|
// we have a local var with a delegate reference (I hope ...)?
|
|
DelegateRepTemplate idType = SymTabLookup($i2.thetext) as DelegateRepTemplate;
|
|
if (idType != null) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($i2.tree, $i2.tree.Token);
|
|
populateParamMap(myMap, idType.Invoke.Params, $argument_list.argTrees, $argument_list.argTreeTypeofTypes, $argument_list.tree, wantsStar(idType.Invoke.Java), $i2.tree.Token);
|
|
ret = mkJavaWrapper(idType.Invoke.Java, myMap, $i2.tree.Token);
|
|
AddToImports(idType.Invoke.Imports);
|
|
$dotNetType = AppEnv.Search(idType.Invoke.Return.Type);
|
|
}
|
|
}
|
|
else {
|
|
|
|
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 calleeResult = expType.Resolve($i2.thetext, $argument_list.argTypes ?? new List<TypeRepTemplate>(), AppEnv);
|
|
if (calleeResult != null) {
|
|
if (!String.IsNullOrEmpty(calleeResult.Result.Warning)) Warning($d0.line, calleeResult.Result.Warning);
|
|
DebugDetail($i2.tree.Token.Line + ": Found '" + $i2.thetext + "'");
|
|
|
|
// We are calling a method or a delegate on an expression. If it has a primitive type then cast it to
|
|
// the appropriate Object type.
|
|
CommonTree e2InBox = expType.IsUnboxedType && Cfg.ExperimentalTransforms ? castToBoxedType(expType, $e2.tree, $d0.token) : $e2.tree;
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
MethodRepTemplate calleeMethod = null;
|
|
|
|
if (calleeResult is DelegateResolveResult) {
|
|
// We have a field/property that is pointing at a delegate, first extract the delegate ...
|
|
Dictionary<string,CommonTree> delMap = new Dictionary<string,CommonTree>();
|
|
if (!implicitThis) {
|
|
delMap["this"] = wrapExpression(e2InBox, $i2.tree.Token);
|
|
}
|
|
myMap["this"] = mkJavaWrapper(calleeResult.Result.Java, delMap, $i2.tree.Token);
|
|
AddToImports(calleeResult.Result.Imports);
|
|
calleeMethod = ((DelegateRepTemplate)((DelegateResolveResult)calleeResult).DelegateResult.Result).Invoke;
|
|
}
|
|
else {
|
|
if (!implicitThis) {
|
|
myMap["this"] = wrapExpression(e2InBox, $i2.tree.Token);
|
|
}
|
|
calleeMethod = calleeResult.Result as MethodRepTemplate;
|
|
}
|
|
populateParamMap(myMap, calleeMethod.Params, $argument_list.argTrees, $argument_list.argTreeTypeofTypes, $argument_list.tree, wantsStar(calleeMethod.Java), $i2.tree.Token);
|
|
ret = mkJavaWrapper(calleeMethod.Java, myMap, $i2.tree.Token);
|
|
AddToImports(calleeMethod.Imports);
|
|
$dotNetType = calleeResult.ResultType;
|
|
}
|
|
else {
|
|
WarningFailedResolve($i2.tree.Token.Line, "Could not resolve method application of " + $i2.thetext + " against " + expType.TypeName);
|
|
}
|
|
}
|
|
}
|
|
| ^(APPLY {$primary_expression::parentIsApply = true; } expression[ObjectType] {$primary_expression::parentIsApply = false; } argument_list?)
|
|
| (^((POSTINC|POSTDEC) (^('.' expression[objectType] identifier) | identifier))) =>
|
|
(^(POSTINC {popstr = "+";} (^('.' pse=expression[ObjectType] pi=identifier {implicitThis = false;}) | pi=identifier))
|
|
| ^(POSTDEC {popstr = "-";} (^('.' pse=expression[ObjectType] pi=identifier {implicitThis = false;}) | pi=identifier)))
|
|
{
|
|
if (implicitThis && SymTabLookup($pi.thetext) != null) {
|
|
// Is this a wrapped parameter?
|
|
TypeRepTemplate idType = SymTabLookup($pi.thetext);
|
|
if (idType.IsWrapped) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($pi.tree, $pi.tree.Token);
|
|
AddToImports("CS2JNet.JavaSupport.language.ReturnPreOrPostValue");
|
|
ret = mkJavaWrapper("${this}.setValue(${this}.getValue() " + popstr + " 1, ReturnPreOrPostValue.POST)", myMap, $pi.tree.Token);
|
|
}
|
|
$dotNetType = idType;
|
|
// a simple variable
|
|
}
|
|
else {
|
|
TypeRepTemplate seType = (implicitThis ? SymTabLookup("this") : $pse.dotNetType);
|
|
if (seType == null) {
|
|
seType = new UnknownRepTemplate("FIELD.BASE");
|
|
}
|
|
if (seType.IsUnknownType) {
|
|
WarningFailedResolve($pi.tree.Token.Line, "Could not find type of expression for field /property access");
|
|
}
|
|
ResolveResult fieldResult = seType.Resolve($pi.thetext, true, AppEnv);
|
|
if (fieldResult != null) {
|
|
if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($pi.tree.Token.Line, fieldResult.Result.Warning);
|
|
if (fieldResult.Result is PropRepTemplate) {
|
|
PropRepTemplate propRep = fieldResult.Result as PropRepTemplate;
|
|
if (!String.IsNullOrEmpty(propRep.JavaSet)) {
|
|
// only translate if we also have JavaGet
|
|
|
|
// We have to resolve property reads and writes separately, because they may come from
|
|
// different parent classes
|
|
ResolveResult readFieldResult = seType.Resolve($pi.thetext, false, AppEnv);
|
|
if (readFieldResult.Result is PropRepTemplate) {
|
|
if (!String.IsNullOrEmpty(readFieldResult.Result.Warning)) Warning($pi.tree.Token.Line, readFieldResult.Result.Warning);
|
|
PropRepTemplate readPropRep = readFieldResult.Result as PropRepTemplate;
|
|
|
|
if (!String.IsNullOrEmpty(readPropRep.JavaGet)) {
|
|
// we have prop (++/--)
|
|
// need to translate to setProp(getProp (+/-) 1)
|
|
Dictionary<string,CommonTree> rhsMap = new Dictionary<string,CommonTree>();
|
|
if (!implicitThis)
|
|
rhsMap["this"] = wrapExpression($pse.tree, $pi.tree.Token);
|
|
CommonTree rhsPropTree = mkJavaWrapper(readPropRep.JavaGet, rhsMap, $pi.tree.Token);
|
|
CommonTree newRhsExp = (CommonTree)adaptor.Nil;
|
|
newRhsExp = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(popstr == "+" ? PLUS : MINUS, $pi.tree.Token, popstr), newRhsExp);
|
|
adaptor.AddChild(newRhsExp, (CommonTree)adaptor.DupTree(rhsPropTree));
|
|
adaptor.AddChild(newRhsExp, (CommonTree)adaptor.Create(NUMBER,$pi.tree.Token, "1"));
|
|
|
|
Dictionary<string,CommonTree> valMap = new Dictionary<string,CommonTree>();
|
|
if (!implicitThis)
|
|
valMap["this"] = wrapExpression($pse.tree, $pi.tree.Token);
|
|
valMap["value"] = wrapExpression(newRhsExp, $pi.tree.Token);
|
|
ret = mkJavaWrapper(propRep.JavaSet, valMap, $pi.tree.Token);
|
|
AddToImports(propRep.Imports);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
WarningFailedResolve($pi.tree.Token.Line, "Could not resolve field or property expression against " + seType.ToString());
|
|
}
|
|
}
|
|
}
|
|
| ^(POSTINC expression[ObjectType]) { $dotNetType = $expression.dotNetType; }
|
|
| ^(POSTDEC expression[ObjectType]) { $dotNetType = $expression.dotNetType; }
|
|
| ^('->' expression[ObjectType] identifier generic_argument_list?)
|
|
| predefined_type { $dotNetType = $predefined_type.dotNetType; }
|
|
| 'this' { $dotNetType = SymTabLookup("this"); }
|
|
| SUPER { $dotNetType = SymTabLookup("super"); }
|
|
| (^(d1='.' e1=expression[ObjectType] {expType = $e1.dotNetType; implicitThis = false; e1Tree = dupTree($e1.tree); /* keving: yuk, shouldn't be necessary but $e1.tree was also capturing i=identifier */} i=identifier dgal=generic_argument_list?)
|
|
|(i=identifier dgal=generic_argument_list?)) magicInputPeId[$d1.tree,$i.tree,$dgal.tree]
|
|
{
|
|
// TODO: generic_argument_list is ignored ....
|
|
|
|
// Possibilities:
|
|
// - a variable in scope.
|
|
// - a property/field of some object
|
|
// - a type name
|
|
// - a method name if we are in a delegate type context then create a delegate (in C# it is an implicit cast)
|
|
// - part of a type name
|
|
bool found = false;
|
|
if (implicitThis) {
|
|
// single identifier, might be a variable
|
|
TypeRepTemplate idType = SymTabLookup($i.thetext);
|
|
if (idType != null) {
|
|
// Is this a wrapped parameter?
|
|
if (idType.IsWrapped) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
|
|
ret = mkJavaWrapper("${this}.getValue()", myMap, $i.tree.Token);
|
|
}
|
|
$dotNetType = idType;
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
// Not a variable, expType is the type of 'expression', or 'this'.
|
|
|
|
// Is it a property read? Ensure we are not being applied to arguments or about to be assigned
|
|
if (expType != null && !expType.IsUnknownType &&
|
|
($primary_expression.Count == 1 || !((primary_expression_scope)($primary_expression.ToArray()[1])).parentIsApply)) {
|
|
|
|
DebugDetail($i.tree.Token.Line + ": '" + $i.thetext + "' might be a property");
|
|
ResolveResult fieldResult = expType.Resolve($i.thetext, false, AppEnv);
|
|
if (fieldResult != null) {
|
|
if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($i.tree.Token.Line, fieldResult.Result.Warning);
|
|
DebugDetail($i.tree.Token.Line + ": Found '" + $i.thetext + "'");
|
|
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
if (!implicitThis) {
|
|
// We are accessing a field / property on an expression. If it has a primitive type then cast it to
|
|
// the appropriate Object type.
|
|
CommonTree e1InBox = expType.IsUnboxedType && Cfg.ExperimentalTransforms ? castToBoxedType(expType, e1Tree, $d1.token) : e1Tree;
|
|
myMap["this"] = wrapExpression(e1InBox, $i.tree.Token);
|
|
}
|
|
ret = mkJavaWrapper(fieldResult.Result.Java, myMap, $i.tree.Token);
|
|
AddToImports(fieldResult.Result.Imports);
|
|
$dotNetType = fieldResult.ResultType;
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
if (!found && (implicitThis || $e1.thedottedtext != null)) {
|
|
String textSoFar = (implicitThis ? "" : $e1.thedottedtext + ".") + $i.thetext;
|
|
// Not a variable, not a property read, is it a type name?
|
|
TypeRepTemplate staticType = findType(textSoFar);
|
|
if (!staticType.IsUnknownType) {
|
|
ret = mkJavaWrapper(staticType.Java, new Dictionary<string,CommonTree>(), $i.tree.Token);
|
|
AddToImports(staticType.Imports);
|
|
$dotNetType = staticType;
|
|
$thedottedtext = (implicitThis || String.IsNullOrEmpty($e1.thedottedtext) ? "" : $e1.thedottedtext + ".") + $i.thetext;
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
// Could be a reference to a method group. If we are in a Delegate Type context then create a delegate object.
|
|
if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate) {
|
|
// Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
|
|
// use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
|
|
// new <delegate_name>() { public void Invoke(<formal args>) throw exception { [return] arg[0](<args>); } }
|
|
DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
|
|
ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $magicInputPeId.tree, delType, $i.tree.Token);
|
|
$dotNetType = $typeCtxt;
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
// Not a variable, not a property read, not a type, is it part of a type name?
|
|
$dotNetType = new UnknownRepTemplate($i.thetext);
|
|
$thedottedtext = (implicitThis || String.IsNullOrEmpty($e1.thedottedtext) ? "" : $e1.thedottedtext + ".") + $i.thetext;
|
|
}
|
|
$rmId = $i.thetext;
|
|
if (ret == null)
|
|
ret = $magicInputPeId.tree;
|
|
}
|
|
| primary_expression_start { $dotNetType = $primary_expression_start.dotNetType; }
|
|
| literal { $dotNetType = $literal.dotNetType; }
|
|
// ('this' brackets) => 'this' brackets primary_expression_part*
|
|
// | ('base' brackets) => 'this' brackets primary_expression_part*
|
|
// | primary_expression_start primary_expression_part*
|
|
| ^(n=NEW type argument_list? object_or_collection_initializer?)
|
|
{
|
|
// look for delegate creation
|
|
if ($type.dotNetType is DelegateRepTemplate && $argument_list.argTypes != null && $argument_list.argTypes.Count > 0) {
|
|
|
|
// argument_list should consist of just a single expression, either a method group or a value of a delegate type.
|
|
// If its a delegate type, then that is the result of this expression otherwise we create a delegte object.
|
|
if ($argument_list.argTypes[0] is DelegateRepTemplate) {
|
|
ret = dupTree((CommonTree)adaptor.GetChild($argument_list.tree, 0));
|
|
$dotNetType = $argument_list.argTypes[0];
|
|
}
|
|
else {
|
|
// Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
|
|
// use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
|
|
// new <delegate_name>() { public void Invoke(<formal args>) throw exception { [return] arg[0](<args>); } }
|
|
DelegateRepTemplate delType = $type.dotNetType as DelegateRepTemplate;
|
|
ret = mkDelegateObject($type.tree, (CommonTree)adaptor.GetChild($argument_list.tree, 0), delType, $n.token);
|
|
$dotNetType = $type.dotNetType;
|
|
}
|
|
}
|
|
else {
|
|
// assume object constructor
|
|
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) {
|
|
if (!String.IsNullOrEmpty(conResult.Result.Warning)) Warning($n.line, conResult.Result.Warning);
|
|
ConstructorRepTemplate conRep = conResult.Result as ConstructorRepTemplate;
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
populateParamMap(myMap, conRep.Params, $argument_list.argTrees, $argument_list.argTreeTypeofTypes,
|
|
$argument_list.tree, wantsStar(conResult.Result.Java),
|
|
$type.dotNetType == null ? null : $type.dotNetType.TypeParams, $type.argTrees,
|
|
$n.token);
|
|
ret = mkJavaWrapper(conResult.Result.Java, myMap, $n.token);
|
|
AddToImports(conResult.Result.Imports);
|
|
$dotNetType = conResult.ResultType;
|
|
}
|
|
else if ($argument_list.argTypes != null && $argument_list.argTypes.Count > 0) { // assume we have a zero-arg constructor, so don't print warning
|
|
WarningFailedResolve($n.token.Line, "Could not resolve constructor against " + conType.TypeName);
|
|
}
|
|
}
|
|
}
|
|
| ^(NEW_ANON_OBJECT anonymous_object_creation_expression) // new {int X, string Y}
|
|
| sizeof_expression // sizeof (struct)
|
|
| checked_expression // checked (...
|
|
| unchecked_expression // unchecked {...}
|
|
| default_value_expression // default
|
|
| ^(d='delegate'
|
|
formal_parameter_list[$typeCtxt != null && $typeCtxt is DelegateRepTemplate ? ((DelegateRepTemplate)$typeCtxt).Invoke.Params : null,
|
|
$typeCtxt != null && $typeCtxt is DelegateRepTemplate ? ((DelegateRepTemplate)$typeCtxt).Invoke.ParamArray : null]?
|
|
block)
|
|
{
|
|
if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate) {
|
|
// Since 'type' is a delegate then we assume that argument_list[0] will be a method group name.
|
|
// use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
|
|
// new <delegate_name>() { public void Invoke(<formal args>) throw exception { [return] arg[0](<args>); } }
|
|
DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
|
|
ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $formal_parameter_list.tree, $block.tree, delType, $d.token);
|
|
$dotNetType = $typeCtxt;
|
|
}
|
|
}
|
|
| typeof_expression { $dotNetType = $typeof_expression.dotNetType; $typeofType = $typeof_expression.typeofType; } // typeof(Foo).Name
|
|
;
|
|
|
|
primary_expression_start returns [TypeRepTemplate dotNetType]:
|
|
^('::' identifier identifier)
|
|
;
|
|
|
|
// primary_expression_part:
|
|
// access_identifier
|
|
// | brackets_or_arguments
|
|
// | '++'
|
|
// | '--' ;
|
|
access_identifier:
|
|
access_operator type_or_generic[""] ;
|
|
access_operator:
|
|
'.' | '->' ;
|
|
brackets_or_arguments:
|
|
brackets | arguments ;
|
|
brackets:
|
|
'[' expression_list? ']' ;
|
|
paren_expression[TypeRepTemplate typeCtxt]:
|
|
'(' expression[$typeCtxt] ')' ;
|
|
arguments:
|
|
'(' argument_list? ')' ;
|
|
argument_list returns [List<TypeRepTemplate> argTypes, List<CommonTree> argTrees, List<TypeRepTemplate> argTreeTypeofTypes]
|
|
@init {
|
|
$argTypes = new List<TypeRepTemplate>();
|
|
$argTrees = new List<CommonTree>();
|
|
$argTreeTypeofTypes = new List<TypeRepTemplate>();
|
|
}:
|
|
^(ARGS (argument { $argTypes.Add($argument.dotNetType); $argTrees.Add(dupTree($argument.tree)); $argTreeTypeofTypes.Add($argument.typeofType); })+);
|
|
// 4.0
|
|
argument returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]:
|
|
argument_name argument_value { $dotNetType = $argument_value.dotNetType; $typeofType = $argument_value.typeofType; }
|
|
| argument_value { $dotNetType = $argument_value.dotNetType; $typeofType = $argument_value.typeofType; }
|
|
;
|
|
argument_name:
|
|
identifier ':';
|
|
argument_value returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]
|
|
@init {
|
|
string refVar = null;
|
|
}:
|
|
expression[ObjectType] { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; }
|
|
| ref_variable_reference { $dotNetType = $ref_variable_reference.dotNetType; $typeofType = $ref_variable_reference.typeofType; }
|
|
| o='out' variable_reference { refVar = "refVar___" + dummyRefVarCtr++; }
|
|
magicCreateOutVar[$o.token, refVar, ($variable_reference.dotNetType != null ? (CommonTree)$variable_reference.dotNetType.Tree : null)]
|
|
magicUpdateFromRefVar[$o.token, refVar, $variable_reference.tree, $variable_reference.dotNetType != null && $variable_reference.dotNetType.IsWrapped]
|
|
{ $dotNetType = $variable_reference.dotNetType;
|
|
$typeofType = $variable_reference.typeofType;
|
|
AddToImports("CS2JNet.JavaSupport.language.RefSupport");
|
|
adaptor.AddChild($statement::preStatements, $magicCreateOutVar.tree);
|
|
adaptor.AddChild($statement::postStatements, $magicUpdateFromRefVar.tree);
|
|
}
|
|
-> IDENTIFIER[$o.token, refVar]
|
|
;
|
|
ref_variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]
|
|
@init {
|
|
string refVar = null;
|
|
}:
|
|
r='ref'
|
|
(('(' type ')') => '(' type ')' (ref_variable_reference | variable_reference) { $dotNetType = $type.dotNetType; } // SomeFunc(ref (int) ref foo)
|
|
// SomeFunc(ref (int) foo)
|
|
| v1=variable_reference // SomeFunc(ref foo)
|
|
{ refVar = "refVar___" + dummyRefVarCtr++; }
|
|
magicCreateRefVar[$r.token, refVar, ($v1.dotNetType != null ? (CommonTree)$v1.dotNetType.Tree : null), $v1.tree]
|
|
magicUpdateFromRefVar[$r.token, refVar, $v1.tree, $v1.dotNetType != null && $v1.dotNetType.IsWrapped]
|
|
{
|
|
$dotNetType = $v1.dotNetType; $typeofType = $v1.typeofType;
|
|
AddToImports("CS2JNet.JavaSupport.language.RefSupport");
|
|
adaptor.AddChild($statement::preStatements, $magicCreateRefVar.tree);
|
|
adaptor.AddChild($statement::postStatements, $magicUpdateFromRefVar.tree);
|
|
}
|
|
-> IDENTIFIER[$r.token, refVar])
|
|
;
|
|
// lvalue
|
|
variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]:
|
|
expression[ObjectType] { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; };
|
|
rank_specifiers[TypeRepTemplate inTy] returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
TypeRepTemplate ty = $inTy;
|
|
}:
|
|
(rank_specifier[ty] { ty = $rank_specifier.dotNetType;} )+ { $dotNetType = ty; };
|
|
rank_specifier[TypeRepTemplate inTy] returns [TypeRepTemplate dotNetType]:
|
|
'[' /*dim_separators?*/ ']' { if ($inTy != null) { $dotNetType = findType("System.Array", new TypeRepTemplate[] {$inTy}); } } ;
|
|
// keving
|
|
// dim_separators:
|
|
// ','+ ;
|
|
|
|
delegate_creation_expression:
|
|
// 'new'
|
|
type_name '(' type_name ')' ;
|
|
anonymous_object_creation_expression:
|
|
// 'new'
|
|
anonymous_object_initializer ;
|
|
anonymous_object_initializer:
|
|
'{' (member_declarator_list ','?)? '}';
|
|
member_declarator_list:
|
|
member_declarator (',' member_declarator)* ;
|
|
member_declarator:
|
|
qid ('=' expression[ObjectType])? ;
|
|
primary_or_array_creation_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]:
|
|
(array_creation_expression) => array_creation_expression { $dotNetType = $array_creation_expression.dotNetType; $thedottedtext = null; }
|
|
| primary_expression[$typeCtxt] { $dotNetType = $primary_expression.dotNetType; $rmId = $primary_expression.rmId; $typeofType = $primary_expression.typeofType; $thedottedtext = $primary_expression.thedottedtext; }
|
|
;
|
|
// new Type[2] { }
|
|
array_creation_expression returns [TypeRepTemplate dotNetType]:
|
|
^(NEW_ARRAY
|
|
(type ('[' expression_list ']' rank_specifiers[$type.dotNetType]? array_initializer? // new int[4]
|
|
| array_initializer { $dotNetType = $type.dotNetType; }
|
|
)
|
|
| rank_specifier[null] array_initializer // var a = new[] { 1, 10, 100, 1000 }; // int[]
|
|
)
|
|
) ;
|
|
array_initializer:
|
|
'{' variable_initializer_list? ','? '}' ;
|
|
variable_initializer_list:
|
|
variable_initializer[ObjectType] (',' variable_initializer[ObjectType])* ;
|
|
variable_initializer[TypeRepTemplate typeCtxt]:
|
|
expression[$typeCtxt] | array_initializer ;
|
|
sizeof_expression:
|
|
^('sizeof' unmanaged_type );
|
|
checked_expression:
|
|
^('checked' expression[ObjectType] ) ;
|
|
unchecked_expression:
|
|
^('unchecked' expression[ObjectType] ) ;
|
|
default_value_expression:
|
|
^('default' type ) ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
object_creation_expression:
|
|
// 'new'
|
|
type
|
|
( '(' argument_list? ')' object_or_collection_initializer?
|
|
| object_or_collection_initializer )
|
|
;
|
|
object_or_collection_initializer:
|
|
'{' (object_initializer
|
|
| collection_initializer) ;
|
|
collection_initializer:
|
|
element_initializer_list ','? '}' ;
|
|
element_initializer_list:
|
|
element_initializer (',' element_initializer)* ;
|
|
element_initializer:
|
|
non_assignment_expression[ObjectType]
|
|
| '{' expression_list '}' ;
|
|
// object-initializer eg's
|
|
// Rectangle r = new Rectangle {
|
|
// P1 = new Point { X = 0, Y = 1 },
|
|
// P2 = new Point { X = 2, Y = 3 }
|
|
// };
|
|
// TODO: comma should only follow a member_initializer_list
|
|
object_initializer:
|
|
member_initializer_list? ','? '}' ;
|
|
member_initializer_list:
|
|
member_initializer (',' member_initializer)* ;
|
|
member_initializer:
|
|
identifier '=' initializer_value ;
|
|
initializer_value:
|
|
expression[ObjectType]
|
|
| object_or_collection_initializer ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
typeof_expression returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]:
|
|
^('typeof' (unbound_type_name | type { $typeofType = $type.dotNetType; } | 'void' { $typeofType = AppEnv.Search("System.Void"); }) ) { $dotNetType = AppEnv.Search("System.Type"); };
|
|
// unbound type examples
|
|
//foo<bar<X<>>>
|
|
//bar::foo<>
|
|
//foo1::foo2.foo3<,,>
|
|
unbound_type_name: // qualified_identifier v2
|
|
// unbound_type_name_start unbound_type_name_part* ;
|
|
unbound_type_name_start
|
|
(((generic_dimension_specifier '.') => generic_dimension_specifier unbound_type_name_part)
|
|
| unbound_type_name_part)*
|
|
generic_dimension_specifier
|
|
;
|
|
|
|
unbound_type_name_start:
|
|
identifier ('::' identifier)?;
|
|
unbound_type_name_part:
|
|
'.' identifier;
|
|
generic_dimension_specifier:
|
|
'<' commas? '>' ;
|
|
commas:
|
|
','+ ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Type Section
|
|
///////////////////////////////////////////////////////
|
|
|
|
// i.e not a predefined type.
|
|
type_name returns [TypeRepTemplate dotNetType, List<CommonTree> argTrees, bool hasTyArgs]
|
|
@init {
|
|
$hasTyArgs = false;
|
|
Dictionary<string,CommonTree> tyMap = new Dictionary<string,CommonTree>();
|
|
}
|
|
@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 > 0 && $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[String prefix] returns [TypeRepTemplate dotNetType, List<CommonTree> argTrees, bool hasTyArgs]
|
|
@init {
|
|
$hasTyArgs = false;
|
|
$argTrees = new List<CommonTree>();
|
|
Dictionary<string,CommonTree> tyMap = new Dictionary<string,CommonTree>();
|
|
}
|
|
@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 (!$MkNonGeneric::scrubGenericArgs && $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[""])
|
|
| qid_start
|
|
;
|
|
qid_start:
|
|
predefined_type
|
|
| (identifier generic_argument_list) => identifier generic_argument_list
|
|
// | 'this'
|
|
// | 'base'
|
|
| identifier ('::' identifier)?
|
|
| literal
|
|
; // 0.ToString() is legal
|
|
|
|
|
|
qid_part:
|
|
access_identifier;
|
|
|
|
generic_argument_list returns [List<TypeRepTemplate> argTypes, List<CommonTree> argTrees]:
|
|
'<' type_arguments '>' { $argTypes = $type_arguments.tyTypes; $argTrees = $type_arguments.argTrees; };
|
|
type_arguments returns [List<TypeRepTemplate> tyTypes, List<CommonTree> argTrees]
|
|
scope PrimitiveRep;
|
|
@init {
|
|
$PrimitiveRep::primitiveTypeAsObject = true;
|
|
$tyTypes = new List<TypeRepTemplate>();
|
|
$argTrees = new List<CommonTree>();
|
|
}:
|
|
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, List<CommonTree> argTrees]
|
|
@ init {
|
|
bool hasRank = false;
|
|
bool isPredefined = false;
|
|
CommonTree pTree = null;
|
|
}
|
|
@after {
|
|
if ($dotNetType.Tree == null) {
|
|
$dotNetType.Tree = $type.tree;
|
|
}
|
|
}
|
|
:
|
|
^(t=TYPE (p=predefined_type { isPredefined = true; $dotNetType = $predefined_type.dotNetType; pTree = $p.tree; }
|
|
| type_name { $dotNetType = $type_name.dotNetType; $argTrees = $type_name.argTrees; }
|
|
| 'void' { $dotNetType = VoidType; } )
|
|
(rank_specifiers[$dotNetType] { isPredefined = false; $dotNetType = $rank_specifiers.dotNetType; $argTrees = null; hasRank = true; })? '*'* '?'?)
|
|
magicBoxedType[isPredefined && $dotNetType != null && !String.IsNullOrEmpty($dotNetType.BoxedJava), $t.token, $dotNetType == null ? "" : $dotNetType.BoxedJava]
|
|
{ if (isPredefined) $dotNetType.Tree = ($magicBoxedType.tree != null ? dupTree($magicBoxedType.tree) : null); }
|
|
-> { $PrimitiveRep::primitiveTypeAsObject && !hasRank && !String.IsNullOrEmpty($dotNetType.BoxedJava) }? ^(TYPE[$t.token, "TYPE"] IDENTIFIER[$t.token,$dotNetType.BoxedJava] '*'* '?'?)
|
|
-> ^(TYPE[$t.token, "TYPE"] predefined_type? type_name? 'void'? rank_specifiers? '*'* '?'?)
|
|
;
|
|
|
|
non_nullable_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
non_array_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
array_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
unmanaged_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
class_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
pointer_type returns [TypeRepTemplate dotNetType]:
|
|
type { $dotNetType = $type.dotNetType; } ;
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Statement Section
|
|
///////////////////////////////////////////////////////
|
|
block
|
|
scope SymTab;
|
|
@init {
|
|
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
|
}:
|
|
';'
|
|
| '{' statement_list? '}';
|
|
statement_list:
|
|
statement[/* isStatementListCtxt */ true]+ ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Expression Section
|
|
///////////////////////////////////////////////////////
|
|
expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
|
|
:
|
|
(unary_expression[ObjectType] assignment_operator) => assignment { $dotNetType = VoidType; $thedottedtext = null;}
|
|
| non_assignment_expression[$typeCtxt] { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; $typeofType = $non_assignment_expression.typeofType; $thedottedtext = $non_assignment_expression.thedottedtext; }
|
|
;
|
|
expression_list returns [List<TypeRepTemplate> expTypes, List<CommonTree> expTrees, List<TypeRepTemplate> expTreeTypeofTypes]
|
|
@init {
|
|
$expTypes = new List<TypeRepTemplate>();
|
|
$expTrees = new List<CommonTree>();
|
|
$expTreeTypeofTypes = new List<TypeRepTemplate>();
|
|
}:
|
|
e1=expression[ObjectType] { $expTypes.Add($e1.dotNetType); $expTrees.Add(dupTree($e1.tree)); $expTreeTypeofTypes.Add($e1.typeofType); }
|
|
(',' en=expression[ObjectType] { $expTypes.Add($en.dotNetType); $expTrees.Add(dupTree($en.tree)); $expTreeTypeofTypes.Add($en.typeofType); })* ;
|
|
|
|
assignment
|
|
@init {
|
|
CommonTree ret = null;
|
|
bool isThis = false;
|
|
bool isLocalVar = false;
|
|
TypeRepTemplate expType = null;
|
|
TypeRepTemplate lhsType = ObjectType;
|
|
|
|
ResolveResult fieldResult = null;
|
|
ResolveResult indexerResult = null;
|
|
|
|
CommonTree lhsTree = null;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$assignment.tree = ret;
|
|
}:
|
|
((^('.' expression[ObjectType] identifier generic_argument_list?) | identifier) assignment_operator) =>
|
|
(^(d0='.' se=expression[ObjectType] i=identifier generic_argument_list?) {lhsTree = dupTree($d0.tree); }
|
|
| i=identifier { isThis = true; lhsTree = dupTree($i.tree); })
|
|
{
|
|
TypeRepTemplate varType = SymTabLookup($i.thetext);
|
|
if (isThis && varType != null) {
|
|
isLocalVar = true;
|
|
lhsType = varType;
|
|
}
|
|
else {
|
|
expType = (isThis ? SymTabLookup("this") : $se.dotNetType);
|
|
if (expType == null) {
|
|
expType = new UnknownRepTemplate("FIELD.BASE");
|
|
}
|
|
if (expType.IsUnknownType) {
|
|
WarningFailedResolve($i.tree.Token.Line, "Could not find type of expression for field /property access");
|
|
}
|
|
fieldResult = expType.Resolve($i.thetext, true, AppEnv);
|
|
if (fieldResult != null) {
|
|
lhsType = fieldResult.ResultType ?? lhsType;
|
|
}
|
|
}
|
|
}
|
|
a=assignment_operator rhs=expression[lhsType]
|
|
{
|
|
CommonTree assignmentOp = $a.tree;
|
|
CommonTree rhsTree = $rhs.tree;
|
|
TypeRepTemplate rhsType = $rhs.dotNetType ?? ObjectType;
|
|
// Is lhs a delegate and assignment one of += -=?
|
|
if (lhsType is DelegateRepTemplate && (assignmentOp.Token.Type == PLUS_ASSIGN || assignmentOp.Token.Type == MINUS_ASSIGN)) {
|
|
// rewrite to lhs = <op>(lhs,rhs)
|
|
// First calculate new rhs
|
|
CommonTree lhsGetter = lhsTree;
|
|
// Do we have a getter for lhs
|
|
if (isLocalVar && lhsType.IsWrapped) {
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
|
|
lhsGetter = mkJavaWrapper("${this}.getValue()", myMap, $i.tree.Token);
|
|
}
|
|
else if (expType != null) {
|
|
// Is lhs a property?
|
|
ResolveResult readFieldResult = expType.Resolve($i.thetext, false, AppEnv);
|
|
if (readFieldResult.Result is PropRepTemplate) {
|
|
if (!String.IsNullOrEmpty(readFieldResult.Result.Warning)) Warning($i.tree.Token.Line, readFieldResult.Result.Warning);
|
|
PropRepTemplate readPropRep = readFieldResult.Result as PropRepTemplate;
|
|
|
|
if (!String.IsNullOrEmpty(readPropRep.JavaGet)) {
|
|
// need to translate to setProp(getProp <op> rhs)
|
|
Dictionary<string,CommonTree> rhsMap = new Dictionary<string,CommonTree>();
|
|
if (!isThis)
|
|
rhsMap["this"] = wrapExpression($se.tree, $i.tree.Token);
|
|
lhsGetter = mkJavaWrapper(readPropRep.JavaGet, rhsMap, assignmentOp.Token);
|
|
lhsType = readFieldResult.ResultType;
|
|
}
|
|
}
|
|
}
|
|
// OK, lhsGetter is good for use.
|
|
List<TypeRepTemplate> args = new List<TypeRepTemplate>();
|
|
args.Add(lhsType);
|
|
args.Add(rhsType == null ? lhsType : rhsType);
|
|
ResolveResult calleeResult = lhsType.Resolve(assignmentOp.Token.Type == PLUS_ASSIGN ? "Combine" : "Remove", args, AppEnv);
|
|
if (calleeResult != null) {
|
|
if (!String.IsNullOrEmpty(calleeResult.Result.Warning)) Warning(assignmentOp.Token.Line, calleeResult.Result.Warning);
|
|
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
MethodRepTemplate calleeMethod = calleeResult.Result as MethodRepTemplate;
|
|
myMap[calleeMethod.Params[0].Name] = wrapArgument(lhsGetter, assignmentOp.token);
|
|
myMap[calleeMethod.Params[1].Name] = wrapArgument(rhsTree, assignmentOp.token);
|
|
rhsTree = mkJavaWrapper(calleeMethod.Java, myMap, assignmentOp.token);
|
|
AddToImports(calleeMethod.Imports);
|
|
rhsType = calleeResult.ResultType;
|
|
assignmentOp = (CommonTree)adaptor.Create(ASSIGN, assignmentOp.Token, "=");
|
|
|
|
// set up a default ret
|
|
ret = (CommonTree)adaptor.Nil;
|
|
adaptor.AddChild(ret, dupTree(lhsTree));
|
|
adaptor.AddChild(ret, dupTree(assignmentOp));
|
|
adaptor.AddChild(ret, dupTree(rhsTree));
|
|
}
|
|
else {
|
|
WarningFailedResolve(assignmentOp.Token.Line, "Could not resolve method application of " + (assignmentOp.Token.Type == PLUS_ASSIGN ? "Combine" : "Remove") + " against " + lhsType.TypeName);
|
|
}
|
|
}
|
|
if (isLocalVar) {
|
|
// Is this a wrapped parameter?
|
|
if (lhsType.IsWrapped) {
|
|
CommonTree newRhsExp = rhsTree;
|
|
if (assignmentOp.Token.Type != ASSIGN) {
|
|
Dictionary<string,CommonTree> rhsMap = new Dictionary<string,CommonTree>();
|
|
rhsMap["this"] = wrapExpression($i.tree, $i.tree.Token);
|
|
CommonTree rhsPropTree = mkJavaWrapper("${this}.getValue()", rhsMap, assignmentOp.Token);
|
|
newRhsExp = mkOpExp(mkOpExp(assignmentOp), rhsPropTree, rhsTree);
|
|
}
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($i.tree, $i.tree.Token);
|
|
myMap["value"] = wrapExpression(newRhsExp, rhsTree.Token);
|
|
ret = mkJavaWrapper("${this}.setValue(${value})", myMap, $i.tree.Token);
|
|
}
|
|
// a simple variable assignment
|
|
}
|
|
else {
|
|
if (fieldResult != null) {
|
|
if (!String.IsNullOrEmpty(fieldResult.Result.Warning)) Warning($i.tree.Token.Line, fieldResult.Result.Warning);
|
|
if (fieldResult.Result is PropRepTemplate) {
|
|
PropRepTemplate propRep = fieldResult.Result as PropRepTemplate;
|
|
if (!String.IsNullOrEmpty(propRep.JavaSet)) {
|
|
CommonTree newRhsExp = rhsTree;
|
|
// if assignment operator is a short cut operator then only translate if we also have JavaGet
|
|
bool goodTx = true;
|
|
if (assignmentOp.Token.Type != ASSIGN) {
|
|
// We have to resolve property reads and writes separately, because they may come from
|
|
// different parent classes
|
|
ResolveResult readFieldResult = expType.Resolve($i.thetext, false, AppEnv);
|
|
if (readFieldResult.Result is PropRepTemplate) {
|
|
if (!String.IsNullOrEmpty(readFieldResult.Result.Warning)) Warning($i.tree.Token.Line, readFieldResult.Result.Warning);
|
|
PropRepTemplate readPropRep = readFieldResult.Result as PropRepTemplate;
|
|
|
|
if (!String.IsNullOrEmpty(readPropRep.JavaGet)) {
|
|
// we have prop <op>= rhs
|
|
// need to translate to setProp(getProp <op> rhs)
|
|
Dictionary<string,CommonTree> rhsMap = new Dictionary<string,CommonTree>();
|
|
if (!isThis)
|
|
rhsMap["this"] = wrapExpression($se.tree, $i.tree.Token);
|
|
CommonTree rhsPropTree = mkJavaWrapper(readPropRep.JavaGet, rhsMap, assignmentOp.Token);
|
|
newRhsExp = mkOpExp(mkOpExp(assignmentOp), rhsPropTree, rhsTree);
|
|
}
|
|
else {
|
|
goodTx = false;
|
|
}
|
|
}
|
|
}
|
|
Dictionary<string,CommonTree> valMap = new Dictionary<string,CommonTree>();
|
|
if (!isThis)
|
|
valMap["this"] = wrapExpression($se.tree, $i.tree.Token);
|
|
valMap["value"] = wrapExpression(newRhsExp, $i.tree.Token);
|
|
if (goodTx) {
|
|
ret = mkJavaWrapper(propRep.JavaSet, valMap, assignmentOp.Token);
|
|
AddToImports(propRep.Imports);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
WarningFailedResolve($i.tree.Token.Line, "Could not resolve field or property expression against " + expType.ToString());
|
|
}
|
|
}
|
|
}
|
|
| (^(INDEX expression[ObjectType] expression_list?) assignment_operator) =>
|
|
^(INDEX ie=expression[ObjectType] expression_list?)
|
|
{
|
|
expType = $ie.dotNetType ?? (new UnknownRepTemplate("INDEXER.BASE"));
|
|
if (expType.IsUnknownType) {
|
|
WarningFailedResolve($ie.tree.Token.Line, "Could not find type of expression for Indexer");
|
|
}
|
|
indexerResult = expType.ResolveIndexer($expression_list.expTypes ?? new List<TypeRepTemplate>(), AppEnv);
|
|
if (indexerResult != null) {
|
|
lhsType = indexerResult.ResultType ?? lhsType;
|
|
}
|
|
}
|
|
ia=assignment_operator irhs=expression[lhsType]
|
|
{
|
|
if (indexerResult != null) {
|
|
if (!String.IsNullOrEmpty(indexerResult.Result.Warning)) Warning($ia.tree.Token.Line, indexerResult.Result.Warning);
|
|
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] <op>= rhs
|
|
// need to translate to set___idx(args, get___idx(args) <op> rhs)
|
|
Dictionary<string,CommonTree> rhsMap = new Dictionary<string,CommonTree>();
|
|
rhsMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
|
|
populateParamMap(rhsMap, indexerRep.Params, $expression_list.expTrees, $expression_list.expTreeTypeofTypes, null, wantsStar(indexerRep.JavaGet), $ie.tree.Token);
|
|
CommonTree rhsIdxTree = mkJavaWrapper(indexerRep.JavaGet, rhsMap, $ia.tree.Token);
|
|
newRhsExp = mkOpExp(mkOpExp($ia.tree), rhsIdxTree, $irhs.tree);
|
|
}
|
|
else {
|
|
goodTx = false;
|
|
}
|
|
}
|
|
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
|
|
myMap["value"] = wrapExpression(newRhsExp, newRhsExp.Token);
|
|
populateParamMap(myMap, indexerRep.Params, $expression_list.expTrees, $expression_list.expTreeTypeofTypes, null, wantsStar(indexerRep.JavaSet), $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 against " + expType.ToString());
|
|
}
|
|
}
|
|
| unary_expression[ObjectType] assignment_operator expression[ObjectType] ;
|
|
|
|
|
|
unary_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
|
|
@init {
|
|
$thedottedtext = null;
|
|
}:
|
|
//('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression
|
|
|
|
cast_expression { $dotNetType = $cast_expression.dotNetType; }
|
|
| primary_or_array_creation_expression[$typeCtxt] { $dotNetType = $primary_or_array_creation_expression.dotNetType; $rmId = $primary_or_array_creation_expression.rmId; $typeofType = $primary_or_array_creation_expression.typeofType; $thedottedtext = $primary_or_array_creation_expression.thedottedtext; }
|
|
| ^(MONOPLUS u1=unary_expression[ObjectType]) { $dotNetType = $u1.dotNetType; }
|
|
| ^(MONOMINUS u2=unary_expression[ObjectType]) { $dotNetType = $u2.dotNetType; }
|
|
| ^(MONONOT u3=unary_expression[ObjectType]) { $dotNetType = $u3.dotNetType; }
|
|
| ^(MONOTWIDDLE u4=unary_expression[ObjectType]) { $dotNetType = $u4.dotNetType; }
|
|
| ^(PREINC u5=unary_expression[ObjectType]) { $dotNetType = $u5.dotNetType; }
|
|
| ^(PREDEC u6=unary_expression[ObjectType]) { $dotNetType = $u6.dotNetType; }
|
|
| ^(MONOSTAR unary_expression[ObjectType]) { $dotNetType = ObjectType; }
|
|
| ^(ADDRESSOF unary_expression[ObjectType]) { $dotNetType = ObjectType; }
|
|
| ^(PARENS expression[$typeCtxt]) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; $typeofType = $expression.typeofType; }
|
|
;
|
|
|
|
cast_expression returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
CommonTree ret = null;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$cast_expression.tree = ret;
|
|
}:
|
|
^(c=CAST_EXPR type expression[$type.dotNetType ?? ObjectType])
|
|
{
|
|
$dotNetType = $type.dotNetType;
|
|
if ($type.dotNetType != null && $expression.dotNetType != null) {
|
|
// see if expression's type has a cast to type
|
|
ResolveResult kaster = $expression.dotNetType.ResolveCastTo($type.dotNetType, AppEnv);
|
|
if (kaster == null) {
|
|
// see if type has a cast from expression's type
|
|
kaster = $type.dotNetType.ResolveCastFrom($expression.dotNetType, AppEnv);
|
|
}
|
|
if (kaster != null) {
|
|
if (!String.IsNullOrEmpty(kaster.Result.Warning)) Warning($c.line, kaster.Result.Warning);
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
myMap["expr"] = wrapExpression($expression.tree, $c.token);
|
|
myMap["TYPEOF_totype"] = wrapTypeOfType($type.dotNetType, $c.token);
|
|
myMap["TYPEOF_expr"] = wrapTypeOfType($expression.dotNetType, $c.token);
|
|
ret = mkJavaWrapper(kaster.Result.Java, myMap, $c.token);
|
|
AddToImports(kaster.Result.Imports);
|
|
}
|
|
}
|
|
}
|
|
-> ^($c { ($expression.dotNetType != null && $expression.dotNetType.TypeName == "System.Object" ? mkBoxedType($type.tree, $type.tree.Token) : $type.tree) } expression)
|
|
// -> ^($c { ($type.dotNetType.IsUnboxedType && !$unary_expression.dotNetType.IsUnboxedType ? mkBoxedType($type.tree, $type.tree.Token) : $type.tree) } unary_expression)
|
|
;
|
|
assignment_operator:
|
|
'=' | shortcut_assignment_operator ;
|
|
shortcut_assignment_operator: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | RIGHT_SHIFT_ASSIGN ;
|
|
//pre_increment_expression:
|
|
// '++' unary_expression ;
|
|
//pre_decrement_expression:
|
|
// '--' unary_expression ;
|
|
//pointer_indirection_expression:
|
|
// '*' unary_expression ;
|
|
//addressof_expression:
|
|
// '&' unary_expression ;
|
|
|
|
non_assignment_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType, string rmId, TypeRepTemplate typeofType, string thedottedtext]
|
|
scope MkNonGeneric, PrimitiveRep;
|
|
@init {
|
|
$MkNonGeneric::scrubGenericArgs = false;
|
|
$PrimitiveRep::primitiveTypeAsObject = false;
|
|
bool nullArg = false;
|
|
bool stringArgs = false;
|
|
bool dateArgs = false;
|
|
$thedottedtext = null;
|
|
CommonTree ret = null;
|
|
}
|
|
@after{
|
|
if (ret != null)
|
|
$non_assignment_expression.tree = ret;
|
|
}:
|
|
//'non ASSIGNment'
|
|
(anonymous_function_signature[null]? '=>') => lambda_expression[$typeCtxt] { $dotNetType = $lambda_expression.dotNetType; }
|
|
| (query_expression) => query_expression
|
|
| ^(COND_EXPR non_assignment_expression[ObjectType] e1=expression[ObjectType] e2=expression[ObjectType]) {$dotNetType = $e1.dotNetType; }
|
|
| ^('??' n1=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n1.dotNetType; }
|
|
| ^('||' n2=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n2.dotNetType; }
|
|
| ^('&&' n3=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n3.dotNetType; }
|
|
| ^('|' n4=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n4.dotNetType; }
|
|
| ^('^' n5=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n5.dotNetType; }
|
|
| ^('&' n6=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n6.dotNetType; }
|
|
| ^(eq='==' ne1=non_assignment_expression[ObjectType] ne2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $ne1.dotNetType != null && $ne2.dotNetType != null && ($ne1.dotNetType.IsExplicitNull || $ne2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
stringArgs = !nullArg && (($ne1.dotNetType != null && !$ne1.dotNetType.IsExplicitNull && $ne1.dotNetType.IsA(StringType,AppEnv)) ||
|
|
($ne2.dotNetType != null && !$ne2.dotNetType.IsExplicitNull && $ne2.dotNetType.IsA(StringType,AppEnv)));
|
|
if (stringArgs) {
|
|
this.AddToImports("CS2JNet.System.StringSupport");
|
|
}
|
|
dateArgs = !nullArg && (($ne1.dotNetType != null && !$ne1.dotNetType.IsExplicitNull && $ne1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($ne2.dotNetType != null && !$ne2.dotNetType.IsExplicitNull && $ne2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
opse=magicSupportOp[stringArgs, "StringSupport", "equals", $ne1.tree, $ne2.tree, $eq.token]
|
|
opde=magicSupportOp[dateArgs, "DateTimeSupport", "equals", $ne1.tree, $ne2.tree, $eq.token])
|
|
-> {stringArgs}?
|
|
$opse
|
|
-> {dateArgs}?
|
|
$opde
|
|
->^($eq $ne1 $ne2)
|
|
| ^(neq='!=' neqo1=non_assignment_expression[ObjectType] neqo2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $neqo1.dotNetType != null && $neqo2.dotNetType != null && ($neqo1.dotNetType.IsExplicitNull || $neqo2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
stringArgs = !nullArg && (($neqo1.dotNetType != null && !$neqo1.dotNetType.IsExplicitNull && $neqo1.dotNetType.IsA(StringType,AppEnv)) ||
|
|
($neqo2.dotNetType != null && !$neqo2.dotNetType.IsExplicitNull && $neqo2.dotNetType.IsA(StringType,AppEnv)));
|
|
if (stringArgs) {
|
|
this.AddToImports("CS2JNet.System.StringSupport");
|
|
}
|
|
dateArgs = !nullArg && (($neqo1.dotNetType != null && !$neqo1.dotNetType.IsExplicitNull && $neqo1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($neqo2.dotNetType != null && !$neqo2.dotNetType.IsExplicitNull && $neqo2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
opse1=magicSupportOp[stringArgs, "StringSupport", "equals", $neqo1.tree, $neqo2.tree, $neq.token]
|
|
opsne=magicNegate[stringArgs, $opse1.tree, $neq.token]
|
|
opde1=magicSupportOp[dateArgs, "DateTimeSupport", "equals", $neqo1.tree, $neqo2.tree, $neq.token]
|
|
opdne=magicNegate[dateArgs, $opde1.tree, $neq.token])
|
|
-> {stringArgs}?
|
|
$opsne
|
|
-> {dateArgs}?
|
|
$opdne
|
|
->^($neq $neqo1 $neqo2)
|
|
| ^(gt='>' gt1=non_assignment_expression[ObjectType] gt2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $gt1.dotNetType != null && $gt2.dotNetType != null && ($gt1.dotNetType.IsExplicitNull || $gt2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
dateArgs = !nullArg && (($gt1.dotNetType != null && !$gt1.dotNetType.IsExplicitNull && $gt1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($gt2.dotNetType != null && !$gt2.dotNetType.IsExplicitNull && $gt2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
opgt=magicSupportOp[dateArgs, "DateTimeSupport", "lessthan", $gt2.tree, $gt1.tree, $gt.token])
|
|
-> {dateArgs}?
|
|
$opgt
|
|
->^($gt $gt1 $gt2)
|
|
| ^(lt='<' lt1=non_assignment_expression[ObjectType] lt2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $lt1.dotNetType != null && $lt2.dotNetType != null && ($lt1.dotNetType.IsExplicitNull || $lt2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
dateArgs = !nullArg && (($lt1.dotNetType != null && !$lt1.dotNetType.IsExplicitNull && $lt1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($lt2.dotNetType != null && !$lt2.dotNetType.IsExplicitNull && $lt2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
oplt=magicSupportOp[dateArgs, "DateTimeSupport", "lessthan", $lt1.tree, $lt2.tree, $lt.token])
|
|
-> {dateArgs}?
|
|
$oplt
|
|
->^($lt $lt1 $lt2)
|
|
| ^(ge='>=' ge1=non_assignment_expression[ObjectType] ge2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $ge1.dotNetType != null && $ge2.dotNetType != null && ($ge1.dotNetType.IsExplicitNull || $ge2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
dateArgs = !nullArg && (($ge1.dotNetType != null && !$ge1.dotNetType.IsExplicitNull && $ge1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($ge2.dotNetType != null && !$ge2.dotNetType.IsExplicitNull && $ge2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
opge=magicSupportOp[dateArgs, "DateTimeSupport", "lessthanorequal", $ge2.tree, $ge1.tree, $ge.token])
|
|
-> {dateArgs}?
|
|
$opge
|
|
->^($ge $ge1 $ge2)
|
|
| ^(le='<=' le1=non_assignment_expression[ObjectType] le2=non_assignment_expression[ObjectType]
|
|
{
|
|
// if One arg is null then leave original operator
|
|
nullArg = $le1.dotNetType != null && $le2.dotNetType != null && ($le1.dotNetType.IsExplicitNull || $le2.dotNetType.IsExplicitNull);
|
|
// need to exclude null because that has every type
|
|
dateArgs = !nullArg && (($le1.dotNetType != null && !$le1.dotNetType.IsExplicitNull && $le1.dotNetType.IsA(DateType,AppEnv)) ||
|
|
($le2.dotNetType != null && !$le2.dotNetType.IsExplicitNull && $le2.dotNetType.IsA(DateType,AppEnv)));
|
|
if (dateArgs) {
|
|
this.AddToImports("CS2JNet.System.DateTimeSupport");
|
|
}
|
|
$dotNetType = BoolType;
|
|
}
|
|
ople=magicSupportOp[dateArgs, "DateTimeSupport", "lessthanorequal", $le1.tree, $le2.tree, $le.token])
|
|
-> {dateArgs}?
|
|
$ople
|
|
->^($le $le1 $le2)
|
|
| ^(INSTANCEOF non_assignment_expression[ObjectType] { $MkNonGeneric::scrubGenericArgs = true; $PrimitiveRep::primitiveTypeAsObject = true; } non_nullable_type) {$dotNetType = BoolType; }
|
|
| ^('<<' n7=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n7.dotNetType; }
|
|
| ^(RIGHT_SHIFT n8=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n8.dotNetType; }
|
|
// TODO: need to munge these numeric types
|
|
| ^(pl='+' n9=non_assignment_expression[ObjectType] n92=non_assignment_expression[ObjectType])
|
|
{
|
|
// Are we adding two delegates?
|
|
if ($n9.dotNetType != null && $n9.dotNetType is DelegateRepTemplate) {
|
|
List<TypeRepTemplate> args = new List<TypeRepTemplate>();
|
|
args.Add($n9.dotNetType);
|
|
args.Add($n92.dotNetType == null ? $n9.dotNetType : $n92.dotNetType);
|
|
ResolveResult calleeResult = $n9.dotNetType.Resolve("Combine", args, AppEnv);
|
|
if (calleeResult != null) {
|
|
if (!String.IsNullOrEmpty(calleeResult.Result.Warning)) Warning($pl.line, calleeResult.Result.Warning);
|
|
IList<CommonTree> argTrees = new List<CommonTree>();
|
|
argTrees.Add($n9.tree);
|
|
argTrees.Add($n92.tree);
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
MethodRepTemplate calleeMethod = calleeResult.Result as MethodRepTemplate;
|
|
populateParamMap(myMap, calleeMethod.Params, argTrees, null, null, wantsStar(calleeMethod.Java), $pl.token);
|
|
ret = mkJavaWrapper(calleeMethod.Java, myMap, $pl.token);
|
|
AddToImports(calleeMethod.Imports);
|
|
$dotNetType = calleeResult.ResultType;
|
|
}
|
|
else {
|
|
WarningFailedResolve($pl.line, "Could not resolve method application of Combine against " + $n9.dotNetType.TypeName);
|
|
}
|
|
}
|
|
$dotNetType = $n9.dotNetType;
|
|
}
|
|
| ^(ne='-' n10=non_assignment_expression[ObjectType] n102=non_assignment_expression[ObjectType]) {$dotNetType = $n10.dotNetType; }
|
|
{
|
|
// Are we adding two delegates?
|
|
if ($n10.dotNetType != null && $n10.dotNetType is DelegateRepTemplate) {
|
|
List<TypeRepTemplate> args = new List<TypeRepTemplate>();
|
|
args.Add($n10.dotNetType);
|
|
args.Add($n102.dotNetType == null ? $n10.dotNetType : $n102.dotNetType);
|
|
ResolveResult calleeResult = $n10.dotNetType.Resolve("Remove", args, AppEnv);
|
|
if (calleeResult != null) {
|
|
if (!String.IsNullOrEmpty(calleeResult.Result.Warning)) Warning($ne.line, calleeResult.Result.Warning);
|
|
|
|
IList<CommonTree> argTrees = new List<CommonTree>();
|
|
argTrees.Add($n10.tree);
|
|
argTrees.Add($n102.tree);
|
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
|
MethodRepTemplate calleeMethod = calleeResult.Result as MethodRepTemplate;
|
|
populateParamMap(myMap, calleeMethod.Params, argTrees, null, null, wantsStar(calleeMethod.Java), $ne.token);
|
|
ret = mkJavaWrapper(calleeMethod.Java, myMap, $ne.token);
|
|
AddToImports(calleeMethod.Imports);
|
|
$dotNetType = calleeResult.ResultType;
|
|
}
|
|
else {
|
|
WarningFailedResolve($ne.line, "Could not resolve method application of Remove against " + $n10.dotNetType.TypeName);
|
|
}
|
|
}
|
|
$dotNetType = $n10.dotNetType;
|
|
}
|
|
| ^('*' n11=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n11.dotNetType; }
|
|
| ^('/' n12=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n12.dotNetType; }
|
|
| ^('%' n13=non_assignment_expression[ObjectType] non_assignment_expression[ObjectType]) {$dotNetType = $n13.dotNetType; }
|
|
// | ^(UNARY_EXPRESSION unary_expression)
|
|
| unary_expression[$typeCtxt]
|
|
{
|
|
$dotNetType = $unary_expression.dotNetType;
|
|
$rmId = $unary_expression.rmId;
|
|
$typeofType = $unary_expression.typeofType;
|
|
$thedottedtext = $unary_expression.thedottedtext;
|
|
}
|
|
;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// lambda Section
|
|
///////////////////////////////////////////////////////
|
|
lambda_expression[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
CommonTree ret = null;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$lambda_expression.tree = ret;
|
|
}:
|
|
anonymous_function_signature[$typeCtxt]? d='=>' anonymous_function_body
|
|
{
|
|
if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate && $anonymous_function_signature.isTypedParams) {
|
|
// use an anonymous inner class to generate a delegate object (object wih an Invoke with appropriate arguments)
|
|
// new <delegate_name>() { public void Invoke(<formal args>) throw exception <block> }
|
|
DelegateRepTemplate delType = $typeCtxt as DelegateRepTemplate;
|
|
ret = mkDelegateObject((CommonTree)$typeCtxt.Tree, $anonymous_function_signature.tree, $anonymous_function_body.tree, delType, $d.token);
|
|
$dotNetType = $typeCtxt;
|
|
}
|
|
}
|
|
;
|
|
anonymous_function_signature[TypeRepTemplate typeCtxt] returns [bool isTypedParams]
|
|
@init {
|
|
$isTypedParams = true;
|
|
CommonTree ret = null;
|
|
List<CommonTree> ids = new List<CommonTree>();
|
|
int idx = 0;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$anonymous_function_signature.tree = ret;
|
|
}:
|
|
^(PARAMS fixed_parameter[$typeCtxt != null && $typeCtxt is DelegateRepTemplate && idx < ((DelegateRepTemplate)$typeCtxt).Invoke.Params.Count ? ((DelegateRepTemplate)$typeCtxt).Invoke.Params[idx++\] : null]+)
|
|
| ^(p=PARAMS_TYPELESS (identifier { ids.Add($identifier.tree); })+)
|
|
{
|
|
if ($typeCtxt != null && $typeCtxt is DelegateRepTemplate && ids.Count == ((DelegateRepTemplate)$typeCtxt).Invoke.Params.Count) {
|
|
ret = mkTypedParams(((DelegateRepTemplate)$typeCtxt).Invoke.Params, ids, $p.token);
|
|
}
|
|
else {
|
|
$isTypedParams = false;
|
|
}
|
|
}
|
|
;
|
|
anonymous_function_body:
|
|
expression[ObjectType]
|
|
-> {$expression.dotNetType != null && $expression.dotNetType.IsA(VoidType, AppEnv)}? OPEN_BRACE[$expression.tree.Token, "{"] expression SEMI[$expression.tree.Token, ";"] CLOSE_BRACE[$expression.tree.Token, "}"]
|
|
-> OPEN_BRACE[$expression.tree.Token, "{"] ^(RETURN[$expression.tree.Token, "return"] expression) CLOSE_BRACE[$expression.tree.Token, "}"]
|
|
| block ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// LINQ Section
|
|
///////////////////////////////////////////////////////
|
|
query_expression:
|
|
from_clause query_body ;
|
|
query_body:
|
|
// match 'into' to closest query_body
|
|
query_body_clauses? select_or_group_clause (('into') => query_continuation)? ;
|
|
query_continuation:
|
|
'into' identifier query_body;
|
|
query_body_clauses:
|
|
query_body_clause+ ;
|
|
query_body_clause:
|
|
from_clause
|
|
| let_clause
|
|
| where_clause
|
|
| join_clause
|
|
| orderby_clause;
|
|
from_clause:
|
|
'from' type? identifier 'in' expression[ObjectType] ;
|
|
join_clause:
|
|
'join' type? identifier 'in' expression[ObjectType] 'on' expression[ObjectType] 'equals' expression[ObjectType] ('into' identifier)? ;
|
|
let_clause:
|
|
'let' identifier '=' expression[ObjectType];
|
|
orderby_clause:
|
|
'orderby' ordering_list ;
|
|
ordering_list:
|
|
ordering (',' ordering)* ;
|
|
ordering:
|
|
expression[ObjectType] ordering_direction
|
|
;
|
|
ordering_direction:
|
|
'ascending'
|
|
| 'descending' ;
|
|
select_or_group_clause:
|
|
select_clause
|
|
| group_clause ;
|
|
select_clause:
|
|
'select' expression[ObjectType] ;
|
|
group_clause:
|
|
'group' expression[ObjectType] 'by' expression[ObjectType] ;
|
|
where_clause:
|
|
'where' boolean_expression ;
|
|
boolean_expression:
|
|
expression[ObjectType];
|
|
|
|
///////////////////////////////////////////////////////
|
|
// B.2.13 Attributes
|
|
///////////////////////////////////////////////////////
|
|
global_attributes:
|
|
global_attribute+ ;
|
|
global_attribute:
|
|
^(GLOBAL_ATTRIBUTE global_attribute_target_specifier attribute_list);
|
|
global_attribute_target_specifier:
|
|
global_attribute_target ':' ;
|
|
global_attribute_target:
|
|
'assembly' | 'module' ;
|
|
attributes:
|
|
attribute_sections ;
|
|
attribute_sections:
|
|
attribute_section+ ;
|
|
attribute_section:
|
|
^(ATTRIBUTE attribute_target_specifier? attribute_list) ;
|
|
attribute_target_specifier:
|
|
attribute_target ':' ;
|
|
attribute_target:
|
|
'field' | 'event' | 'method' | 'param' | 'property' | 'return' | 'type' ;
|
|
attribute_list:
|
|
attribute (',' attribute)* ;
|
|
attribute:
|
|
type_name attribute_arguments? ;
|
|
// TODO: allows a mix of named/positional arguments in any order
|
|
attribute_arguments:
|
|
'(' (')' // empty
|
|
| (positional_argument ((',' identifier '=') => named_argument
|
|
|',' positional_argument)*
|
|
) ')'
|
|
) ;
|
|
positional_argument_list:
|
|
^(ARGS positional_argument+) ;
|
|
positional_argument:
|
|
attribute_argument_expression ;
|
|
named_argument_list:
|
|
^(ARGS named_argument+) ;
|
|
named_argument:
|
|
identifier '=' attribute_argument_expression ;
|
|
attribute_argument_expression:
|
|
expression[ObjectType] ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Class Section
|
|
///////////////////////////////////////////////////////
|
|
|
|
class_declaration
|
|
scope NSContext,SymTab;
|
|
@init {
|
|
$NSContext::namespaces = new List<string>();
|
|
$NSContext::globalNamespaces = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalNamespaces);
|
|
$NSContext::typeVariables = new List<string>();
|
|
$NSContext::globalTypeVariables = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalTypeVariables);
|
|
|
|
$NSContext::IsGenericICollection = false;
|
|
$NSContext::GenericICollectionTyVar = "";
|
|
$NSContext::IsICollection = false;
|
|
|
|
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
|
|
}
|
|
:
|
|
^(c=CLASS 'partial'? PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses?
|
|
type_parameter_list?
|
|
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
|
class_implements?
|
|
{
|
|
$NSContext::namespaces.Add($NSContext::currentNS);
|
|
$NSContext::globalNamespaces.Add($NSContext::currentNS);
|
|
if ($type_parameter_list.tyParams != null) {
|
|
$NSContext::typeVariables.AddRange($type_parameter_list.tyParams);
|
|
$NSContext::globalTypeVariables.AddRange($type_parameter_list.tyParams);
|
|
}
|
|
ClassRepTemplate classTypeRep = (ClassRepTemplate)AppEnv.Search($NSContext::currentNS);
|
|
if (classTypeRep == null) {
|
|
Error($c.line, "Could not find class " + $NSContext::currentNS + " in the type environment");
|
|
}
|
|
else {
|
|
$SymTab::symtab["this"] = classTypeRep;
|
|
ClassRepTemplate baseType = ObjectType;
|
|
if (classTypeRep.Inherits != null && classTypeRep.Inherits.Length > 0) {
|
|
// if Inherits[0] Take first class as super
|
|
foreach (String super in classTypeRep.Inherits) {
|
|
ClassRepTemplate parent = AppEnv.Search(classTypeRep.Uses, super, null) as ClassRepTemplate;
|
|
if (parent != null) {
|
|
baseType = parent;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
$SymTab::symtab["super"] = baseType;
|
|
}
|
|
if ($NSContext::IsICollection) {
|
|
Debug(10, $NSContext::currentNS + " is a Collection");
|
|
}
|
|
if ($NSContext::IsGenericICollection) {
|
|
Debug(10, $NSContext::currentNS + " is a Generic Collection");
|
|
}
|
|
}
|
|
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
|
|
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
|
|
-> ^($c 'partial'? PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list? class_implements? class_body);
|
|
|
|
type_parameter_list returns [List<string> tyParams]
|
|
@init {
|
|
$tyParams = new List<string>();
|
|
}:
|
|
(attributes? type_parameter { $tyParams.Add($type_parameter.thetext); })+ ;
|
|
|
|
type_parameter returns [string thetext]:
|
|
identifier { $thetext = $identifier.thetext; };
|
|
|
|
class_extends:
|
|
class_extend+ ;
|
|
class_extend:
|
|
^(EXTENDS type);
|
|
|
|
// If first implements type is a class then convert to extends
|
|
class_implements returns [bool hasExtends, TypeRepTemplate extendDotNetType]
|
|
@init {
|
|
CommonTree extends = null;
|
|
}:
|
|
(class_implement_or_extend[extends == null] { if ($class_implement_or_extend.extends != null) {
|
|
extends = $class_implement_or_extend.extends;
|
|
$hasExtends = true;
|
|
$extendDotNetType = $class_implement_or_extend.extendDotNetType;
|
|
}})+
|
|
-> { extends } class_implement_or_extend*;
|
|
|
|
class_implement_or_extend[bool lookingForBase] returns [CommonTree extends, TypeRepTemplate extendDotNetType]
|
|
@init {
|
|
$extends = null;
|
|
}:
|
|
^(i=IMPLEMENTS t=type magicExtends[$lookingForBase && $t.dotNetType is ClassRepTemplate, $i.token, $t.tree]
|
|
{ if ($lookingForBase && $t.dotNetType is ClassRepTemplate) {
|
|
$extends = $magicExtends.tree;
|
|
$extendDotNetType = $t.dotNetType;
|
|
}
|
|
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
|
|
if($t.dotNetType.IsA(GenericICollectionType,AppEnv) && $t.dotNetType.TypeParams.Length > 0) {
|
|
$NSContext::IsGenericICollection = true;
|
|
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
|
|
}
|
|
} )
|
|
-> { $lookingForBase && $t.dotNetType is ClassRepTemplate }?
|
|
-> ^($i $t);
|
|
|
|
class_body
|
|
@init {
|
|
CommonTree collectorNodes = null;
|
|
if ($NSContext::IsGenericICollection) {
|
|
collectorNodes = this.parseString("class_member_declarations", Fragments.GenericCollectorMethods($NSContext::GenericICollectionTyVar, $NSContext::GenericICollectionTyVar + "__" + dummyTyVarCtr++));
|
|
AddToImports("java.util.Iterator");
|
|
AddToImports("java.util.Collection");
|
|
AddToImports("java.util.ArrayList");
|
|
}
|
|
}:
|
|
'{' class_member_declarations? '}' -> '{' class_member_declarations? { dupTree(collectorNodes) } '}' ;
|
|
class_member_declarations:
|
|
class_member_declaration+ ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
constant_declaration:
|
|
'const' type constant_declarators[$type.dotNetType] ';' ;
|
|
constant_declarators[TypeRepTemplate ty]:
|
|
constant_declarator[$ty] (',' constant_declarator[$ty])* ;
|
|
constant_declarator[TypeRepTemplate ty]:
|
|
identifier { $SymTab::symtab[$identifier.thetext] = $ty; } ('=' constant_expression[$ty])? ;
|
|
constant_expression[TypeRepTemplate tyCtxt] returns [string rmId]:
|
|
expression[$tyCtxt] {$rmId = $expression.rmId; };
|
|
|
|
///////////////////////////////////////////////////////
|
|
field_declaration[CommonTree tyTree, TypeRepTemplate ty]:
|
|
variable_declarators[$tyTree, $ty] ;
|
|
variable_declarators[CommonTree tyTree, TypeRepTemplate ty]:
|
|
variable_declarator[$tyTree, $ty] (',' variable_declarator[$tyTree, $ty])* ;
|
|
variable_declarator[CommonTree tyTree, TypeRepTemplate ty]
|
|
@init {
|
|
bool hasInit = false;
|
|
bool constructStruct = $ty != null && $ty is StructRepTemplate ;
|
|
EnumRepTemplate enumRep = $ty as EnumRepTemplate;
|
|
bool constructEnum = enumRep != null && enumRep.Members.Count > 0;
|
|
string zeroEnum = "WhoopsEnum";
|
|
if (constructEnum)
|
|
{
|
|
zeroEnum = enumRep.Members[0].Name;
|
|
}
|
|
}:
|
|
identifier
|
|
(e='=' variable_initializer[$ty] { hasInit = true; constructStruct = false; constructEnum = false; } )?
|
|
magicConstructStruct[constructStruct, $tyTree, $identifier.tree != null ? $identifier.tree.Token : null]
|
|
magicConstructDefaultEnum[constructEnum, $ty, zeroEnum, $identifier.tree != null ? $identifier.tree.Token : null]
|
|
// eg. event EventHandler IInterface.VariableName = Foo;
|
|
-> {hasInit}? identifier $e variable_initializer
|
|
-> {constructStruct}? identifier ASSIGN[$identifier.tree.Token, "="] magicConstructStruct
|
|
-> {constructEnum}? identifier ASSIGN[$identifier.tree.Token, "="] magicConstructDefaultEnum
|
|
-> identifier
|
|
;
|
|
///////////////////////////////////////////////////////
|
|
method_declaration
|
|
scope SymTab;
|
|
@init {
|
|
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
|
}:
|
|
method_header method_body ;
|
|
method_header:
|
|
^(METHOD_HEADER attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list[null,null]?);
|
|
method_body:
|
|
block ;
|
|
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
|
|
;
|
|
// keving: missing interface_type.identifier
|
|
//identifier ; // IInterface<int>.Method logic added.
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
event_declaration:
|
|
type member_name '{' event_accessor_declarations '}'
|
|
;
|
|
event_modifiers:
|
|
modifier+ ;
|
|
event_accessor_declarations:
|
|
attributes? ((add_accessor_declaration attributes? remove_accessor_declaration)
|
|
| (remove_accessor_declaration attributes? add_accessor_declaration)) ;
|
|
add_accessor_declaration:
|
|
'add' block ;
|
|
remove_accessor_declaration:
|
|
'remove' block ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// enum declaration
|
|
///////////////////////////////////////////////////////
|
|
enum_declaration:
|
|
^(ENUM attributes? modifiers? identifier enum_base? enum_body );
|
|
enum_base:
|
|
type ;
|
|
enum_body:
|
|
^(ENUM_BODY enum_member_declarations?) ;
|
|
enum_member_declarations:
|
|
enum_member_declaration+ ;
|
|
enum_member_declaration:
|
|
attributes? identifier ;
|
|
//enum_modifiers:
|
|
// enum_modifier+ ;
|
|
//enum_modifier:
|
|
// 'new' | 'public' | 'protected' | 'internal' | 'private' ;
|
|
integral_type:
|
|
'sbyte' | 'byte' | 'short' | 'ushort' | 'int' | 'uint' | 'long' | 'ulong' | 'char' ;
|
|
|
|
// 4.0
|
|
variant_generic_parameter_list returns [List<string> tyParams]
|
|
@init {
|
|
$tyParams = new List<string>();
|
|
}:
|
|
(variant_type_variable_name {$tyParams.Add($variant_type_variable_name.thetext); })+ ;
|
|
variant_type_variable_name returns [string thetext]:
|
|
attributes? variance_annotation? type_variable_name { $thetext = $type_variable_name.thetext; };
|
|
variance_annotation:
|
|
IN | OUT ;
|
|
|
|
type_parameter_constraints_clauses:
|
|
type_parameter_constraints_clause+ -> type_parameter_constraints_clause*;
|
|
type_parameter_constraints_clause:
|
|
// If there are no type constraints on this variable then drop this constraint
|
|
^(TYPE_PARAM_CONSTRAINT type_variable_name) ->
|
|
| ^(TYPE_PARAM_CONSTRAINT type_variable_name type_name+) ;
|
|
type_variable_name returns [string thetext]:
|
|
identifier { $thetext = $identifier.thetext; };
|
|
constructor_constraint:
|
|
'new' '(' ')' ;
|
|
return_type:
|
|
type ;
|
|
formal_parameter_list[IList<ParamRepTemplate> pInfos, ParamArrayRepTemplate paInfo]
|
|
@init {
|
|
int idx = 0;
|
|
}:
|
|
^(PARAMS formal_parameter[$pInfos != null && idx < $pInfos.Count ? $pInfos[idx++\] : null, $paInfo]+) ;
|
|
|
|
formal_parameter[ParamRepTemplate pInfo, ParamArrayRepTemplate paInfo]
|
|
:
|
|
attributes? (fixed_parameter[$pInfo] | parameter_array[$paInfo])
|
|
| '__arglist'; // __arglist is undocumented, see google
|
|
//fixed_parameters:
|
|
// fixed_parameter (',' fixed_parameter)* ;
|
|
// 4.0
|
|
fixed_parameter[ParamRepTemplate pInfo]
|
|
scope PrimitiveRep;
|
|
@init {
|
|
$PrimitiveRep::primitiveTypeAsObject = $pInfo != null ? $pInfo.Type.ForceBoxed : false;
|
|
bool isRefOut = false;
|
|
}:
|
|
(parameter_modifier { isRefOut = $parameter_modifier.isRefOut; if (isRefOut) { $PrimitiveRep::primitiveTypeAsObject = true; AddToImports("CS2JNet.JavaSupport.language.RefSupport");} })?
|
|
type identifier { $type.dotNetType.IsWrapped = isRefOut; $SymTab::symtab[$identifier.thetext] = $type.dotNetType; } default_argument? magicRef[isRefOut, $type.tree != null ? $type.tree.Token : null, $type.tree]
|
|
-> {isRefOut}? magicRef identifier default_argument?
|
|
-> parameter_modifier? type identifier default_argument?
|
|
;
|
|
// 4.0
|
|
default_argument:
|
|
'=' expression[ObjectType];
|
|
parameter_modifier returns [bool isRefOut]
|
|
@init {
|
|
$isRefOut = true;
|
|
}:
|
|
'ref' -> | 'out' -> | 'this' { $isRefOut = false;};
|
|
parameter_array[ParamArrayRepTemplate paInfo]
|
|
scope PrimitiveRep;
|
|
@init {
|
|
$PrimitiveRep::primitiveTypeAsObject = $paInfo != null ? $paInfo.Type.ForceBoxed : false;
|
|
}:
|
|
^(p='params' type identifier { $SymTab::symtab[$identifier.thetext] = findType("System.Array", new TypeRepTemplate[] {$type.dotNetType}); }) ;
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
interface_declaration:
|
|
^(INTERFACE 'partial'? attributes? modifiers? identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
|
class_extends? interface_body ) ;
|
|
interface_modifiers:
|
|
modifier+ ;
|
|
interface_body:
|
|
'{' interface_member_declarations? '}' ;
|
|
interface_member_declarations:
|
|
interface_member_declaration+ ;
|
|
interface_member_declaration
|
|
scope SymTab;
|
|
@init {
|
|
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
|
}:
|
|
^(e=EVENT attributes? modifiers? t=type i=identifier magicEventCollectionType[$t.tree.Token, $t.tree] )
|
|
{ AddToImports("CS2JNet.JavaSupport.language.IEventCollection"); }
|
|
-> ^(METHOD[$e.token, "METHOD"] attributes? modifiers? magicEventCollectionType identifier EXCEPTION[$i.tree.Token, "Exception"])
|
|
| ^(METHOD attributes? modifiers? type identifier type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list[null,null]? exception*)
|
|
;
|
|
|
|
///////////////////////////////////////////////////////
|
|
operator_declaration:
|
|
operator_declarator operator_body ;
|
|
operator_declarator:
|
|
'operator'
|
|
(('+' | '-') '(' type identifier (binary_operator_declarator | unary_operator_declarator)
|
|
| overloadable_unary_operator '(' type identifier unary_operator_declarator
|
|
| overloadable_binary_operator '(' type identifier binary_operator_declarator) ;
|
|
unary_operator_declarator:
|
|
')' ;
|
|
overloadable_unary_operator:
|
|
/*'+' | '-' | */ '!' | '~' | '++' | '--' | 'true' | 'false' ;
|
|
binary_operator_declarator:
|
|
',' type identifier ')' ;
|
|
// >> check needed
|
|
overloadable_binary_operator:
|
|
/*'+' | '-' | */ '*' | '/' | '%' | '&' | '|' | '^' | '<<' | '>' '>' | '==' | '!=' | '>' | '<' | '>=' | '<=' ;
|
|
|
|
// rewrite to a method
|
|
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;
|
|
// 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 ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
invocation_expression:
|
|
invocation_start (((arguments ('['|'.'|'->')) => arguments invocation_part)
|
|
| invocation_part)* arguments ;
|
|
invocation_start returns [TypeRepTemplate dotNetType]:
|
|
predefined_type { $dotNetType = $predefined_type.dotNetType; }
|
|
| (identifier generic_argument_list) => identifier generic_argument_list
|
|
| 'this'
|
|
| SUPER
|
|
| identifier ('::' identifier)?
|
|
| typeof_expression // typeof(Foo).Name
|
|
;
|
|
invocation_part:
|
|
access_identifier
|
|
| brackets ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// keving: split statement into two parts, there seems to be a problem with the state
|
|
// machine if we combine statement and statement_plus. (It fails to recognise dataHelper.Add();)
|
|
statement[bool isStatementListCtxt]
|
|
scope {
|
|
CommonTree preStatements;
|
|
CommonTree postStatements;
|
|
}
|
|
@init {
|
|
$statement::preStatements = (CommonTree)adaptor.Nil;
|
|
$statement::postStatements = (CommonTree)adaptor.Nil;
|
|
bool hasPreOrPost = false;
|
|
CommonTree statTree = null;
|
|
}:
|
|
((declaration_statement) => declaration_statement { statTree = dupTree($declaration_statement.tree); }
|
|
| statement_plus[isStatementListCtxt] { statTree = dupTree($statement_plus.tree); })
|
|
{ hasPreOrPost = adaptor.GetChildCount($statement::preStatements) > 0 || adaptor.GetChildCount($statement::postStatements) > 0; }
|
|
-> {isStatementListCtxt || !hasPreOrPost }? { $statement::preStatements } { statTree } { $statement::postStatements }
|
|
-> OPEN_BRACE[statTree.Token, "{"] { $statement::preStatements } { statTree } { $statement::postStatements } CLOSE_BRACE[statTree.Token, "}"]
|
|
;
|
|
statement_plus[bool isStatementListCtxt]:
|
|
labeled_statement[isStatementListCtxt]
|
|
| embedded_statement[isStatementListCtxt]
|
|
;
|
|
embedded_statement[bool isStatementListCtxt]
|
|
@init{
|
|
string idName = null;
|
|
bool emitPrePost = false;
|
|
bool jumpStatementHasExpression = false;
|
|
}
|
|
@after{
|
|
if(emitPrePost) {
|
|
// reset (just in case) they have already been emitted
|
|
$statement::preStatements = (CommonTree)adaptor.Nil;
|
|
$statement::postStatements = (CommonTree)adaptor.Nil;
|
|
}
|
|
}
|
|
:
|
|
block
|
|
| ^(ift=IF boolean_expression
|
|
{ emitPrePost = adaptor.GetChildCount($statement::preStatements) > 0 || adaptor.GetChildCount($statement::postStatements) > 0;
|
|
if (emitPrePost) {
|
|
idName = "boolVar___" + dummyVarCtr++;
|
|
}
|
|
}
|
|
SEP embedded_statement[/* isStatementListCtxt */ false] else_statement?)
|
|
magicType[emitPrePost, $ift.token, "boolean", null]
|
|
magicAssignment[emitPrePost, $ift.token, $magicType.tree, idName, $boolean_expression.tree]
|
|
-> {!emitPrePost }? ^($ift boolean_expression SEP embedded_statement else_statement?)
|
|
-> {isStatementListCtxt}?
|
|
{ $statement::preStatements } magicAssignment { $statement::postStatements } ^($ift IDENTIFIER[$ift.token, idName] SEP embedded_statement else_statement?)
|
|
-> OPEN_BRACE[$ift.token, "{"] { $statement::preStatements } magicAssignment { $statement::postStatements } ^($ift IDENTIFIER[$ift.token, idName] SEP embedded_statement else_statement?) CLOSE_BRACE[$ift.token, "}"]
|
|
| switch_statement[isStatementListCtxt]
|
|
| iteration_statement // while, do, for, foreach
|
|
| jump_statement
|
|
| (^(('return' | 'throw') expression[ObjectType]?)) => (^(jt='return' (je=expression[ObjectType] {jumpStatementHasExpression = true;})?) | ^(jt='throw' (je=expression[ObjectType]{ jumpStatementHasExpression = true; })?))
|
|
{ emitPrePost = adaptor.GetChildCount($statement::preStatements) > 0 || adaptor.GetChildCount($statement::postStatements) > 0;
|
|
if (emitPrePost) {
|
|
idName = "resVar___" + dummyVarCtr++;
|
|
}
|
|
}
|
|
magicAssignment[emitPrePost, $jt.token, jumpStatementHasExpression ? ($je.dotNetType != null ? (CommonTree)$je.dotNetType.Tree : null) : null, idName, $je.tree]
|
|
// jump_statement transfers control, so we ignore any poststatements
|
|
-> {!emitPrePost }? ^($jt $je?)
|
|
-> {isStatementListCtxt}? { $statement::preStatements } magicAssignment { $statement::postStatements } ^($jt IDENTIFIER[$jt.token, idName])
|
|
-> OPEN_BRACE[$jt.token, "{"] { $statement::preStatements } magicAssignment { $statement::postStatements } ^($jt IDENTIFIER[$jt.token, idName]) CLOSE_BRACE[$jt.token, "}"]
|
|
|
|
// break, continue, goto, return, throw
|
|
| ^('try' block catch_clauses? finally_clause?)
|
|
| checked_statement
|
|
| unchecked_statement
|
|
| synchronized_statement // Java: synchronized(obj) {}
|
|
| lock_statement
|
|
| yield_statement
|
|
| ^('unsafe' block)
|
|
| fixed_statement
|
|
| expression_statement { emitPrePost = adaptor.GetChildCount($statement::preStatements) > 0 || adaptor.GetChildCount($statement::postStatements) > 0; }
|
|
-> {!emitPrePost }? expression_statement
|
|
-> {isStatementListCtxt}? { $statement::preStatements } expression_statement { $statement::postStatements }
|
|
-> OPEN_BRACE[$expression_statement.tree.Token, "{"] { $statement::preStatements } expression_statement { $statement::postStatements } CLOSE_BRACE[$expression_statement.tree.Token, "}"]
|
|
// expression!
|
|
;
|
|
switch_statement[ bool isStatementListCtxt]
|
|
scope {
|
|
bool isEnum;
|
|
bool convertToIfThenElse;
|
|
string scrutVar;
|
|
bool isFirstCase;
|
|
CommonTree defaultTree;
|
|
}
|
|
@init {
|
|
$switch_statement::isEnum = false;
|
|
$switch_statement::convertToIfThenElse = false;
|
|
$switch_statement::scrutVar = "WHOOPS";
|
|
$switch_statement::isFirstCase = true;
|
|
$switch_statement::defaultTree = null;
|
|
}:
|
|
^(s='switch' se=expression[ObjectType] sv=magicScrutineeVar[$s.token]
|
|
{
|
|
if ($expression.dotNetType != null) {
|
|
$switch_statement::isEnum = $expression.dotNetType.IsA(AppEnv.Search("System.Enum"), AppEnv);
|
|
$switch_statement::convertToIfThenElse = typeIsInvalidForScrutinee($expression.dotNetType);
|
|
$switch_statement::scrutVar = $sv.thetext;
|
|
}
|
|
}
|
|
ss+=switch_section*)
|
|
-> { $switch_statement::convertToIfThenElse && isStatementListCtxt }?
|
|
// TYPE{ String } ret ;
|
|
^(TYPE[$s.token, "TYPE"] IDENTIFIER[$s.token,$expression.dotNetType.Java]) $sv ASSIGN[$s.token, "="] { dupTree($se.tree) } SEMI[$s.token, ";"]
|
|
{ convertSectionsToITE($ss, $switch_statement::defaultTree) }
|
|
-> { $switch_statement::convertToIfThenElse }?
|
|
// TYPE{ String } ret ;
|
|
OPEN_BRACE[$s.token, "{"]
|
|
^(TYPE[$s.token, "TYPE"] IDENTIFIER[$s.token,$expression.dotNetType.Java]) $sv ASSIGN[$s.token, "="] { dupTree($se.tree) } SEMI[$s.token, ";"]
|
|
{ convertSectionsToITE($ss, $switch_statement::defaultTree) }
|
|
CLOSE_BRACE[$s.token, "}"]
|
|
-> ^($s expression $ss*)
|
|
;
|
|
fixed_statement:
|
|
'fixed' '(' pointer_type fixed_pointer_declarators ')' embedded_statement[ /* isStatementListCtxt */ false] ;
|
|
fixed_pointer_declarators:
|
|
fixed_pointer_declarator (',' fixed_pointer_declarator)* ;
|
|
fixed_pointer_declarator:
|
|
identifier '=' fixed_pointer_initializer ;
|
|
fixed_pointer_initializer:
|
|
//'&' variable_reference // unary_expression covers this
|
|
expression[ObjectType];
|
|
labeled_statement[bool isStatementListCtxt]:
|
|
identifier ':' statement[isStatementListCtxt] ;
|
|
declaration_statement:
|
|
(local_variable_declaration
|
|
| local_constant_declaration) ';' ;
|
|
local_variable_declaration:
|
|
local_variable_type local_variable_declarators[$local_variable_type.tree, $local_variable_type.dotNetType, $local_variable_type.isVar]
|
|
{
|
|
if ($local_variable_type.isVar && $local_variable_declarators.bestTy != null && !$local_variable_declarators.bestTy.IsUnknownType) {
|
|
foreach (string id in $local_variable_declarators.identifiers) {
|
|
$SymTab::symtab[id] = $local_variable_declarators.bestTy;
|
|
}
|
|
}
|
|
}
|
|
-> {$local_variable_type.isVar && $local_variable_declarators.bestTy != null && !$local_variable_declarators.bestTy.IsUnknownType}?
|
|
^(TYPE[$local_variable_type.tree.Token, "TYPE"] IDENTIFIER[$local_variable_type.tree.Token, $local_variable_declarators.bestTy.mkFormattedTypeName(false, "<",">")]) local_variable_declarators
|
|
-> local_variable_type local_variable_declarators
|
|
;
|
|
local_variable_type returns [bool isTypeNode, bool isVar, TypeRepTemplate dotNetType]
|
|
@init {
|
|
$isTypeNode = false;
|
|
$isVar = false;
|
|
}:
|
|
TYPE_VAR { $dotNetType = new UnknownRepTemplate("System.Object"); $isVar = true;}
|
|
| TYPE_DYNAMIC { $dotNetType = new UnknownRepTemplate("System.Object"); }
|
|
| type { $dotNetType = $type.dotNetType; $isTypeNode = true; };
|
|
local_variable_declarators[CommonTree tyTree, TypeRepTemplate ty, bool isVar] returns [TypeRepTemplate bestTy, List<String> identifiers]
|
|
@init {
|
|
$identifiers = new List<String>();
|
|
}:
|
|
d1=local_variable_declarator[$tyTree, $ty] { $identifiers.Add($d1.identifier); if ($isVar) $bestTy = $d1.dotNetType; }
|
|
(',' dn=local_variable_declarator[$tyTree, $ty]
|
|
{
|
|
$identifiers.Add($d1.identifier);
|
|
if ($isVar) {
|
|
if (!$dn.dotNetType.IsUnknownType && $bestTy.IsA($dn.dotNetType, AppEnv)) {
|
|
$bestTy = $dn.dotNetType;
|
|
}
|
|
}
|
|
}
|
|
)* ;
|
|
local_variable_declarator[CommonTree tyTree, TypeRepTemplate ty] returns [TypeRepTemplate dotNetType, String identifier]
|
|
@init {
|
|
bool hasInit = false;
|
|
bool constructStruct = $ty != null && $ty is StructRepTemplate ;
|
|
EnumRepTemplate enumRep = $ty as EnumRepTemplate;
|
|
bool constructEnum = enumRep != null && enumRep.Members.Count > 0;
|
|
string zeroEnum = "WhoopsEnum";
|
|
if (constructEnum)
|
|
{
|
|
zeroEnum = enumRep.Members[0].Name;
|
|
}
|
|
}:
|
|
i=identifier { $identifier = $i.thetext; $SymTab::symtab[$i.thetext] = $ty; }
|
|
(e='=' local_variable_initializer[$ty ?? ObjectType] { hasInit = true; constructStruct = false; constructEnum = false; $dotNetType = $local_variable_initializer.dotNetType; } )?
|
|
magicConstructStruct[constructStruct, $tyTree, ($i.tree != null ? $i.tree.Token : null)]
|
|
magicConstructDefaultEnum[constructEnum, $ty, zeroEnum, $identifier.tree != null ? $identifier.tree.Token : null]
|
|
// eg. event EventHandler IInterface.VariableName = Foo;
|
|
-> {hasInit}? $i $e local_variable_initializer
|
|
-> {constructStruct}? $i ASSIGN[$i.tree.Token, "="] magicConstructStruct
|
|
-> {constructEnum}? $i ASSIGN[$i.tree.Token, "="] magicConstructDefaultEnum
|
|
-> $i
|
|
;
|
|
local_variable_initializer[TypeRepTemplate typeCtxt] returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
$dotNetType = ObjectType;
|
|
}:
|
|
expression[$typeCtxt] { $dotNetType = $expression.dotNetType; }
|
|
| array_initializer
|
|
| stackalloc_initializer;
|
|
stackalloc_initializer:
|
|
'stackalloc' unmanaged_type '[' expression[ObjectType] ']' ;
|
|
local_constant_declaration:
|
|
'const' type constant_declarators[$type.dotNetType] ;
|
|
expression_statement:
|
|
expression[ObjectType] ';' ;
|
|
|
|
// TODO: should be assignment, call, increment, decrement, and new object expressions
|
|
statement_expression:
|
|
expression[ObjectType]
|
|
;
|
|
else_statement:
|
|
'else' embedded_statement[/* isStatementListCtxt */ false] ;
|
|
switch_section
|
|
@init {
|
|
bool defaultSection = false;
|
|
bool isFirstCase = $switch_statement::isFirstCase;
|
|
}
|
|
:
|
|
^(s=SWITCH_SECTION ({$switch_statement::convertToIfThenElse}? ite_switch_labels | switch_labels) sl=statement_list
|
|
{ if ($switch_statement::convertToIfThenElse && $ite_switch_labels.isDefault) {
|
|
$switch_statement::defaultTree = stripFinalBreak($sl.tree);
|
|
} else {
|
|
$switch_statement::isFirstCase = false;
|
|
}
|
|
}
|
|
)
|
|
|
|
-> {$switch_statement::convertToIfThenElse && $ite_switch_labels.isDefault}?
|
|
// -> {$switch_statement::convertToIfThenElse && $ite_switch_labels.isDefault}? ELSE[$s.token, "else"] OPEN_BRACE[$s.token, "{"] { stripFinalBreak($sl.tree) } CLOSE_BRACE[$s.token, "}"]
|
|
-> {$switch_statement::convertToIfThenElse && isFirstCase}? ^(IF[$s.token, "if"] ite_switch_labels SEP OPEN_BRACE[$s.token, "{"] { stripFinalBreak($sl.tree) } CLOSE_BRACE[$s.token, "}"])
|
|
-> {$switch_statement::convertToIfThenElse}? ELSE[$s.token, "else"] ^(IF[$s.token, "if"] ite_switch_labels SEP OPEN_BRACE[$s.token, "{"] { stripFinalBreak($sl.tree) } CLOSE_BRACE[$s.token, "}"])
|
|
-> ^($s switch_labels statement_list)
|
|
;
|
|
|
|
ite_switch_labels returns [bool isDefault]
|
|
@init {
|
|
$isDefault = false;
|
|
}:
|
|
(l1=switch_label { if($l1.isDefault) $isDefault = true; } -> $l1)
|
|
(ln=switch_label { if($ln.isDefault) $isDefault = true; } -> ^(LOG_OR[$ln.tree.Token, "||"] { dupTree($ite_switch_labels.tree) } { dupTree($ln.tree) }) )*
|
|
;
|
|
switch_labels returns [bool isDefault]
|
|
@init {
|
|
$isDefault = false;
|
|
}:
|
|
switch_label+
|
|
;
|
|
|
|
switch_label returns [bool isDefault]
|
|
@init {
|
|
$isDefault = false;
|
|
}:
|
|
^(c='case' ce=constant_expression[ObjectType] )
|
|
-> { $switch_statement::convertToIfThenElse }?
|
|
// scrutVar.equals(ce)
|
|
^(APPLY[$c.token, "APPLY"] ^(DOT[$c.token, "."] IDENTIFIER[$c.token, $switch_statement::scrutVar] IDENTIFIER[$c.token, "equals"]) ^(ARGS[$c.token, "ARGS"] $ce))
|
|
-> { $switch_statement::isEnum && $constant_expression.rmId != null}? ^($c IDENTIFIER[$c.token, $constant_expression.rmId])
|
|
-> ^($c $ce)
|
|
| 'default' { $isDefault = true; };
|
|
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;
|
|
|
|
TypeRepTemplate exprType = null;
|
|
TypeRepTemplate elType = null;
|
|
}
|
|
@after {
|
|
if (ret != null)
|
|
$iteration_statement.tree = ret;
|
|
}:
|
|
^('while' boolean_expression SEP embedded_statement[/* isStatementListCtxt */ false])
|
|
| do_statement
|
|
| ^('for' for_initializer? SEP for_condition? SEP for_iterator? SEP embedded_statement[/* isStatementListCtxt */ false])
|
|
| ^(f='foreach' local_variable_type identifier expression[ObjectType] s=SEP
|
|
{
|
|
newExpression = $expression.tree;
|
|
exprType = $expression.dotNetType;
|
|
if (exprType != null) {
|
|
ResolveResult iterable = exprType.ResolveIterable(AppEnv);
|
|
if (iterable != null) {
|
|
if (!String.IsNullOrEmpty(iterable.Result.Warning)) Warning($expression.tree.Token.Line, iterable.Result.Warning);
|
|
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);
|
|
AddToImports(iterable.Result.Imports);
|
|
elType = iterable.ResultType;
|
|
}
|
|
}
|
|
// Set identifier type in symbol table
|
|
if ($local_variable_type.isVar && elType != null) {
|
|
$SymTab::symtab[$identifier.thetext] = elType;
|
|
}
|
|
else {
|
|
$SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType;
|
|
}
|
|
}
|
|
embedded_statement[/* isStatementListCtxt */ false])
|
|
magicTypeFromTemplate[$local_variable_type.isVar && elType != null, $f.token, elType] magicObjectType[$f.token] magicForeachVar[$f.token]
|
|
{
|
|
newType = $local_variable_type.tree;
|
|
newIdentifier = $identifier.tree;
|
|
newEmbeddedStatement = $embedded_statement.tree;
|
|
|
|
bool needCast = true;
|
|
if ($local_variable_type.isVar) {
|
|
// If local_type is dynamic then just leave it there,
|
|
if (elType != null) {
|
|
newType = $magicTypeFromTemplate.tree;
|
|
}
|
|
needCast = false;
|
|
}
|
|
else {
|
|
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, mkBoxedType($local_variable_type.tree, $local_variable_type.tree.Token), newIdentifier, $embedded_statement.tree, $embedded_statement.tree.Token);
|
|
}
|
|
}
|
|
-> ^($f { newType } { newIdentifier } { newExpression } $s { newEmbeddedStatement })
|
|
;
|
|
do_statement:
|
|
'do' embedded_statement[/* isStatementListCtxt */ false] 'while' '(' boolean_expression ')' ';' ;
|
|
for_initializer:
|
|
(local_variable_declaration) => local_variable_declaration
|
|
| statement_expression_list
|
|
;
|
|
for_condition:
|
|
boolean_expression ;
|
|
for_iterator:
|
|
statement_expression_list ;
|
|
statement_expression_list:
|
|
statement_expression (',' statement_expression)* ;
|
|
jump_statement:
|
|
break_statement
|
|
| continue_statement
|
|
| goto_statement
|
|
;
|
|
break_statement:
|
|
'break' ';' ;
|
|
continue_statement:
|
|
'continue' ';' ;
|
|
goto_statement:
|
|
'goto' ( identifier
|
|
| 'case' constant_expression[ObjectType]
|
|
| 'default') ';' ;
|
|
catch_clauses:
|
|
catch_clause+ ;
|
|
catch_clause
|
|
scope SymTab;
|
|
@init {
|
|
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
|
}:
|
|
^('catch' class_type identifier { $SymTab::symtab[$identifier.thetext] = $class_type.dotNetType; } block) ;
|
|
finally_clause:
|
|
^('finally' block) ;
|
|
checked_statement:
|
|
'checked' block ;
|
|
unchecked_statement:
|
|
^(UNCHECKED block) ;
|
|
|
|
synchronized_statement:
|
|
^(SYNCHRONIZED expression[ObjectType] '{' statement_list '}') ;
|
|
|
|
lock_statement:
|
|
'lock' '(' expression[ObjectType] ')' embedded_statement[/* isStatementListCtxt */ false] ;
|
|
|
|
yield_statement:
|
|
^(YIELD_RETURN expression[ObjectType])
|
|
| YIELD_BREAK ;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Lexar Section
|
|
///////////////////////////////////////////////////////
|
|
|
|
predefined_type returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
string ns = "";
|
|
}
|
|
@after {
|
|
$dotNetType = new ClassRepTemplate((ClassRepTemplate)AppEnv.Search(ns, new UnknownRepTemplate(ns)));
|
|
$dotNetType.IsUnboxedType = true;
|
|
string newText = null;
|
|
}:
|
|
'bool' { ns = "System.Boolean"; }
|
|
| 'byte' { ns = Cfg.UnsignedNumbersToSigned ? "System.SByte" : "System.Byte"; }
|
|
| 'char' { ns = "System.Char"; }
|
|
| 'decimal' { ns = "System.Decimal"; }
|
|
| 'double' { ns = "System.Double"; }
|
|
| 'float' { ns = "System.Single"; }
|
|
| 'int' { ns = "System.Int32"; }
|
|
| 'long' { ns = "System.Int64"; }
|
|
| 'object' { ns = "System.Object"; }
|
|
| 'sbyte' { ns = "System.Byte"; }
|
|
| 'short' { ns = "System.Int16"; }
|
|
| 'string' { ns = "System.String"; }
|
|
| 'uint' { ns = Cfg.UnsignedNumbersToSigned ? "System.Int32" : "System.UInt32"; }
|
|
| 'ulong' { ns = Cfg.UnsignedNumbersToSigned ? "System.Int64" : "System.UInt64"; }
|
|
| 'ushort' { ns = Cfg.UnsignedNumbersToSigned ? "System.Int16" : "System.UInt16"; }
|
|
;
|
|
|
|
// Don't trust identifier.text in tree grammars: Doesn't work for our magic additions because the text function goes back to the
|
|
// original token stream to make up the text for a tree node
|
|
identifier returns [string thetext]:
|
|
IDENTIFIER { $thetext = $IDENTIFIER.text; } | also_keyword { $thetext = $also_keyword.text; }; // might need to return text from also_keyword too if we start manufacturing those
|
|
|
|
keyword:
|
|
'abstract' | 'as' | 'base' | 'bool' | 'break' | 'byte' | 'case' | 'catch' | 'char' | 'checked' | 'class' | 'const' | 'continue' | 'decimal' | 'default' | 'delegate' | 'do' | 'double' | 'else' | 'enum' | 'event' | 'explicit' | 'extern' | 'false' | 'finally' | 'fixed' | 'float' | 'for' | 'foreach' | 'goto' | 'if' | 'implicit' | 'in' | 'int' | 'interface' | 'internal' | 'is' | 'lock' | 'long' | 'namespace' | 'new' | 'null' | 'object' | 'operator' | 'out' | 'override' | 'params' | 'private' | 'protected' | 'public' | 'readonly' | 'ref' | 'return' | 'sbyte' | 'sealed' | 'short' | 'sizeof' | 'stackalloc' | 'static' | 'string' | 'struct' | 'switch' | 'this' | 'throw' | 'true' | 'try' | 'typeof' | 'uint' | 'ulong' | 'unchecked' | 'unsafe' | 'ushort' | 'using' | 'virtual' | 'void' | 'volatile' ;
|
|
|
|
also_keyword:
|
|
'add' | 'alias' | 'assembly' | 'module' | 'field' | 'method' | 'param' | 'property' | 'type' | 'yield'
|
|
| 'from' | 'into' | 'join' | 'on' | 'where' | 'orderby' | 'group' | 'by' | 'ascending' | 'descending'
|
|
| 'equals' | 'select' | 'pragma' | 'let' | 'remove' | 'get' | 'set' | 'var' | '__arglist' | 'dynamic' | 'elif'
|
|
| 'endif' | 'define' | 'undef' | 'extends';
|
|
|
|
literal returns [TypeRepTemplate dotNetType]
|
|
@init {
|
|
string ns = "System.Object";
|
|
bool isNull = false;
|
|
}
|
|
@after {
|
|
TypeRepTemplate retTy = AppEnv.Search(ns);
|
|
if (isNull) {
|
|
retTy = new ClassRepTemplate((ClassRepTemplate)retTy);
|
|
retTy.IsExplicitNull = true;
|
|
}
|
|
$dotNetType = retTy;
|
|
}:
|
|
Real_literal { ns = "System.Double"; }
|
|
| NUMBER { ns = "System.Int32"; }
|
|
| LONGNUMBER { ns = "System.Int64"; }
|
|
| Hex_number { ns = "System.Int32"; }
|
|
| Character_literal { ns = "System.Char"; }
|
|
| STRINGLITERAL { ns = "System.String"; }
|
|
| Verbatim_string_literal { ns = "System.String"; }
|
|
| TRUE { ns = "System.Boolean"; }
|
|
| FALSE { ns = "System.Boolean"; }
|
|
| NULL { ns = "System.Object"; isNull = true; }
|
|
;
|
|
|
|
magicScrutineeVar [IToken tok] returns [string thetext]
|
|
@init {
|
|
$thetext = "__dummyScrutVar" + dummyScrutVarCtr++;
|
|
}:
|
|
-> IDENTIFIER[tok,$thetext];
|
|
|
|
magicForeachVar [IToken tok] returns [string thetext]
|
|
@init {
|
|
$thetext = "__dummyForeachVar" + dummyForeachVarCtr++;
|
|
}:
|
|
-> IDENTIFIER[tok,$thetext];
|
|
|
|
magicObjectType [IToken tok]:
|
|
-> ^(TYPE[tok, "TYPE"] OBJECT[tok, "Object"]);
|
|
|
|
magicCastOperator[CommonTree mods, string methodName, CommonTree header, CommonTree body]
|
|
@init {
|
|
IToken tok = ((CommonTree)$header.Children[0]).Token;
|
|
CommonTree toType = dupTree((CommonTree)$header.Children[1]);
|
|
CommonTree fromType = dupTree((CommonTree)$header.Children[2]);
|
|
CommonTree paramName = dupTree((CommonTree)$header.Children[3]);
|
|
}:
|
|
-> ^(METHOD[tok, "METHOD"]
|
|
{ dupTree($mods) }
|
|
{ toType } IDENTIFIER[tok, $methodName] ^(PARAMS[tok, "PARAMS"] { fromType } { paramName})
|
|
{ dupTree(body) }
|
|
EXCEPTION[tok, Cfg.TranslatorExceptionIsThrowable ? "Throwable" : "Exception"])
|
|
;
|
|
|
|
magicAnnotation [CommonTree mods, CommonTree name, CommonTree body, IToken tok]:
|
|
-> ^(ANNOTATION[tok, "ANNOTATION"] { dupTree($mods) } { dupTree($name) } { dupTree(body) });
|
|
|
|
magicSupportOp[bool isOn, string supportlib, string op, CommonTree e1, CommonTree e2, IToken tok]:
|
|
-> { isOn }?
|
|
^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,supportlib] IDENTIFIER[tok,op]) ^(ARGS[tok, "ARGS"] { dupTree($e1) } { dupTree($e2) } ) )
|
|
->
|
|
;
|
|
|
|
magicNegate[bool isOn, CommonTree e, IToken tok]:
|
|
-> { isOn }?
|
|
^(MONONOT[tok, "!"] { dupTree($e) })
|
|
->
|
|
;
|
|
|
|
magicConstructStruct[bool isOn, CommonTree ty, IToken tok]:
|
|
-> { isOn }? ^(NEW[tok, "NEW"] { dupTree(ty) } )
|
|
->
|
|
;
|
|
magicConstructDefaultEnum[bool isOn, TypeRepTemplate ty, string zero, IToken tok]:
|
|
-> { isOn }? ^(DOT[tok, "."] IDENTIFIER[tok, ty.Java] IDENTIFIER[tok, zero])
|
|
->
|
|
;
|
|
|
|
magicSmotherExceptionsThrow[CommonTree body, string exception]:
|
|
v=magicCatchVar magicThrowableType[true, body.Token]
|
|
-> OPEN_BRACE["{"]
|
|
^(TRY["try"]
|
|
{ dupTree(body) }
|
|
^(CATCH["catch"] magicThrowableType { dupTree($v.tree) }
|
|
OPEN_BRACE["{"] ^(THROW["throw"] ^(NEW["new"] ^(TYPE["TYPE"] IDENTIFIER[exception]) ^(ARGS["ARGS"] { dupTree($v.tree) }))) CLOSE_BRACE["}"]))
|
|
CLOSE_BRACE["}"]
|
|
;
|
|
|
|
magicCatchVar:
|
|
-> IDENTIFIER["__dummyStaticConstructorCatchVar" + dummyStaticConstructorCatchVarCtr++];
|
|
|
|
magicThrowableType[bool isOn, IToken tok]:
|
|
-> {isOn}? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, Cfg.TranslatorExceptionIsThrowable ? "Throwable" : "Exception"])
|
|
->
|
|
;
|
|
|
|
magicEventCollectionType[IToken tok, CommonTree type]:
|
|
-> ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "IEventCollection"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"] )
|
|
;
|
|
|
|
// METHOD{ public TYPE{ Iterator < TYPE{ JAVAWRAPPER{ T } } > } kiterator { TYPE{ Iterator < TYPE{ JAVAWRAPPER{ T } } > } ret = null ; try{ { ret = APPLY{ .{ JAVAWRAPPER{ ${this:16}.GetEnumerator() this EXPRESSION{ this } } iterator } } ; } catch{ TYPE{ JAVAWRAPPER{ Exception } } e { APPLY{ .{ e printStackTrace } } ; } } } return{ ret } } Exception }
|
|
//
|
|
|
|
magicXXGenericIterator[bool isOn, IToken tok, String tyVar]
|
|
@init {
|
|
if (isOn) AddToImports("java.util.Iterator");
|
|
}
|
|
:
|
|
-> {isOn}? ^(METHOD[tok, "METHOD"]
|
|
PUBLIC[tok, "public"]
|
|
^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"] LTHAN[tok, "<"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, tyVar]) GT[tok, ">"])
|
|
IDENTIFIER[tok, "iterator"]
|
|
OPEN_BRACE[tok, "{"]
|
|
// Iterator<T> ret = null;
|
|
^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"] LTHAN[tok, "<"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, tyVar]) GT[tok, ">"]) IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] NULL[tok,"null"] SEMI[tok, ";"]
|
|
// try { ret = this.GetEnumerator().iterator(); } catch (Exception e) { e.printstackTrace(); }}
|
|
^(TRY[tok, "try"]
|
|
OPEN_BRACE[tok, "{"]
|
|
IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
|
|
CLOSE_BRACE[tok, "}"]
|
|
^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
|
|
OPEN_BRACE[tok, "{"]
|
|
^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
|
|
CLOSE_BRACE[tok, "}"]
|
|
)
|
|
)
|
|
// return ret;
|
|
^(RETURN[tok, "return"] IDENTIFIER[tok, "ret"])
|
|
CLOSE_BRACE[tok, "}"]
|
|
)
|
|
|
|
->
|
|
;
|
|
|
|
// IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
|
|
|
|
magicGenericIterator[bool isOn, IToken tok, String tyVar]
|
|
@init {
|
|
if (isOn) AddToImports("java.util.Iterator");
|
|
}
|
|
:
|
|
magicType[isOn, tok, "Iterator", new string[\] {tyVar}]
|
|
n=magicToken[isOn, tok, NULL, "null"]
|
|
magicAssignment[isOn, tok, $magicType.tree, "ret", $n.tree]
|
|
|
|
thisT=magicToken[isOn, tok, THIS, "this"]
|
|
thisEnum=magicDot[isOn, tok, $thisT.tree, "GetEnumerator"]
|
|
mkIter=magicDot[isOn, tok, $thisEnum.tree, "iterator"]
|
|
tryBody=magicApply[isOn, tok, $mkIter.tree, null]
|
|
|
|
magicTryCatch[isOn, tok, $tryBody.tree]
|
|
|
|
magicMethod[isOn, tok, "iterator", $magicType.tree, null, $magicTryCatch.tree]
|
|
|
|
-> {isOn}? magicMethod
|
|
->
|
|
;
|
|
|
|
magicIterator[bool isOn, IToken tok]
|
|
@init {
|
|
if (isOn) AddToImports("java.util.Iterator");
|
|
}
|
|
:
|
|
magicType[isOn, tok, "Iterator", null]
|
|
n=magicToken[isOn, tok, NULL, "null"]
|
|
magicAssignment[isOn, tok, $magicType.tree, "ret", $n.tree]
|
|
// magicSmotherExceptions[isOn, tok, ]
|
|
magicMethod[isOn, tok, "iterator", $magicType.tree, null, $magicAssignment.tree]
|
|
-> {isOn}? magicMethod
|
|
// ^(METHOD[tok, "METHOD"]
|
|
// PUBLIC[tok, "public"]
|
|
// ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"])
|
|
// IDENTIFIER[tok, "iterator"]
|
|
// OPEN_BRACE[tok, "{"]
|
|
// // Iterator ret = null;
|
|
// ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"]) IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] NULL[tok,"null"] SEMI[tok, ";"]
|
|
// // try { ret = this.GetEnumerator().iterator(); } catch (Exception e) { e.printstackTrace(); }}
|
|
// ^(TRY[tok, "try"]
|
|
// OPEN_BRACE[tok, "{"]
|
|
// IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
|
|
// CLOSE_BRACE[tok, "}"]
|
|
// ^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
|
|
// OPEN_BRACE[tok, "{"]
|
|
// ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
|
|
// CLOSE_BRACE[tok, "}"]
|
|
// )
|
|
// )
|
|
// // return ret;
|
|
// ^(RETURN[tok, "return"] IDENTIFIER[tok, "ret"])
|
|
// CLOSE_BRACE[tok, "}"]
|
|
// )
|
|
//
|
|
->
|
|
;
|
|
|
|
magicToken[bool isOn, IToken tok, int tokenType, string text]
|
|
@init {
|
|
CommonTree ret = null;
|
|
if (isOn)
|
|
ret = (CommonTree)adaptor.Create(tokenType, tok, text);
|
|
}:
|
|
-> {isOn}? { ret }
|
|
->
|
|
;
|
|
|
|
// public <retType> <name> <args> { <body> }
|
|
magicMethod[bool isOn, IToken tok, string name, CommonTree retType, CommonTree args, CommonTree body]:
|
|
-> {isOn}?
|
|
^(METHOD[tok, "METHOD"]
|
|
PUBLIC[tok, "public"]
|
|
{ dupTree(retType) }
|
|
IDENTIFIER[tok, name]
|
|
{ dupTree(args) }
|
|
OPEN_BRACE[tok, "{"]
|
|
{ dupTree(body) }
|
|
CLOSE_BRACE[tok, "}"]
|
|
)
|
|
->
|
|
;
|
|
|
|
magicType[bool isOn, IToken tok, string name, string[\] args]
|
|
@init {
|
|
CommonTree argsTree = null;
|
|
if (args != null && args.Length > 0) {
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
|
|
foreach (string a in args) {
|
|
CommonTree root0 = (CommonTree)adaptor.Nil;
|
|
root0 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), root0);
|
|
adaptor.AddChild(root0, (CommonTree)adaptor.Create(IDENTIFIER, tok, a));
|
|
adaptor.AddChild(root, root0);
|
|
}
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(GT, tok, ">"));
|
|
argsTree = (CommonTree)adaptor.RulePostProcessing(root);
|
|
}
|
|
}
|
|
:
|
|
-> {isOn}?
|
|
^(TYPE[tok, "TYPE"]
|
|
IDENTIFIER[tok, name]
|
|
{ dupTree(argsTree) }
|
|
)
|
|
->
|
|
;
|
|
|
|
// <type>? <name> = exp ;
|
|
magicAssignment[bool isOn, IToken tok, CommonTree type, string name, CommonTree exp]:
|
|
-> {isOn}?
|
|
{ dupTree(type) }
|
|
IDENTIFIER[tok, name]
|
|
ASSIGN[tok, "="]
|
|
{ dupTree(exp) }
|
|
SEMI[tok, ";"]
|
|
->
|
|
;
|
|
|
|
magicTryCatch[bool isOn, IToken tok, CommonTree body]:
|
|
-> {isOn}?
|
|
^(TRY[tok, "try"]
|
|
OPEN_BRACE[tok, "{"]
|
|
{ dupTree(body) }
|
|
CLOSE_BRACE[tok, "}"]
|
|
^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
|
|
OPEN_BRACE[tok, "{"]
|
|
^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
|
|
CLOSE_BRACE[tok, "}"]
|
|
)
|
|
)
|
|
->
|
|
;
|
|
|
|
magicDot[bool isOn, IToken tok, CommonTree lhs, string rhs]:
|
|
-> {isOn}? ^(DOT[tok, "."] { dupTree(lhs) } IDENTIFIER[tok, rhs])
|
|
->
|
|
;
|
|
|
|
magicApply[bool isOn, IToken tok, CommonTree methodExp, CommonTree args]:
|
|
-> {isOn}? ^(APPLY[tok, "APPLY"] { dupTree(methodExp) } { dupTree(args) })
|
|
->
|
|
;
|
|
|
|
magicRef[bool isOn, IToken tok, CommonTree ty]:
|
|
-> {isOn}? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"] LTHAN[tok, "<"] { dupTree(ty) } GT[tok, ">"])
|
|
->
|
|
;
|
|
|
|
magicCreateRefVar[IToken tok, String id, CommonTree type, CommonTree value]:
|
|
-> { type == null }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"]) IDENTIFIER[tok, id] ASSIGN[tok, "="]
|
|
^(NEW[tok, "new"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"]) ^(ARGS[tok, "ARGS"] { dupTree(value) }))
|
|
SEMI[tok,";"]
|
|
-> ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"]) IDENTIFIER[tok, id] ASSIGN[tok, "="]
|
|
^(NEW[tok, "new"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"]) ^(ARGS[tok, "ARGS"] { dupTree(value) }))
|
|
SEMI[tok,";"]
|
|
;
|
|
|
|
magicCreateOutVar[IToken tok, String id, CommonTree type]:
|
|
-> {type == null}? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"]) IDENTIFIER[tok, id] ASSIGN[tok, "="]
|
|
^(NEW[tok, "new"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"]))
|
|
SEMI[tok,";"]
|
|
-> ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"]) IDENTIFIER[tok, id] ASSIGN[tok, "="]
|
|
^(NEW[tok, "new"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "RefSupport"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"]))
|
|
SEMI[tok,";"]
|
|
;
|
|
|
|
magicUpdateFromRefVar[IToken tok, String id, CommonTree variable_ref, bool isWrapped]:
|
|
-> {isWrapped}? ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] { dupTree((CommonTree)adaptor.GetChild((CommonTree)adaptor.GetChild(variable_ref, 2),0)) } IDENTIFIER[tok, "setValue"]) ^(ARGS[tok, "ARGS"] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, id] IDENTIFIER[tok, "getValue"]) ))) SEMI[tok,";"]
|
|
-> { dupTree(variable_ref) } ASSIGN[tok, "="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, id] IDENTIFIER[tok, "getValue"])) SEMI[tok,";"]
|
|
;
|
|
|
|
magicBoxedType[bool isOn, IToken tok, String boxedName]:
|
|
-> { isOn }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, boxedName])
|
|
->
|
|
;
|
|
|
|
magicInputPeId[CommonTree dotTree, CommonTree idTree, CommonTree galTree]:
|
|
-> { dotTree != null}? {dupTree(dotTree)}
|
|
-> {dupTree(idTree)} { dupTree(galTree) }
|
|
;
|
|
|
|
magicTypeFromTemplate[bool isOn, IToken tok, TypeRepTemplate dotNetType]:
|
|
-> { $isOn && $dotNetType.Tree != null}? { dupTree((CommonTree)$dotNetType.Tree) }
|
|
-> { $isOn }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, $dotNetType.mkFormattedTypeName(false, "<",">")])
|
|
->
|
|
;
|
|
|
|
magicExtends[bool isOn, IToken tok, CommonTree type]:
|
|
-> { $isOn }? ^(EXTENDS[tok, "extends"] { dupTree($type) })
|
|
->
|
|
;
|