/snippets/VS2010/Nemerle.Compiler.Utils/CodeDom/NemerleCodeParserBase.n

http://github.com/xxVisorxx/nemerle · Unknown · 786 lines · 647 code · 139 blank · 0 comment · 0 complexity · c75049fc43cb2906f678050d06b8b7a2 MD5 · raw file

  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.CodeDom;
  6. using System.CodeDom.Compiler;
  7. using System.ComponentModel.Design.Serialization;
  8. using System.Diagnostics;
  9. using System.Drawing;
  10. using System.Reflection;
  11. using Nemerle.Assertions;
  12. using Nemerle.Collections;
  13. using Nemerle.Compiler;
  14. using Nemerle.Compiler.Parsetree;
  15. using Nemerle.Compiler.Typedtree;
  16. using Nemerle.Completion2;
  17. using Nemerle.Imperative;
  18. using Nemerle.Text;
  19. using Nemerle.Utility;
  20. using System.CodeDom.CodeBinaryOperatorType;
  21. namespace Nemerle.Compiler.Utils
  22. {
  23. public class NemerleCodeParserBase
  24. {
  25. // now needed only for AsObject
  26. protected mutable _manager : ManagerClass;
  27. protected virtual ToCodeNamespace(ns : NamespaceTree.Node) : CodeNamespace
  28. {
  29. CodeNamespace(ns.GetDisplayName());
  30. }
  31. protected virtual ToCodeTypeDelegate(del : TopDeclaration.Delegate) : CodeTypeDelegate
  32. {
  33. def ty = CodeTypeDelegate(del.Name);
  34. ty.ReturnType = ToCodeTypeReference(del.header.ParsedReturnType);
  35. ty.Parameters.AddRange(del.header.ParsedParameters.Map(ToCodeParameterDeclarationExpression).NToArray());
  36. ty;
  37. }
  38. protected virtual ToCodeTypeDeclaration(vrt : TopDeclaration.Variant) : CodeTypeDeclaration
  39. {
  40. def ty = CodeTypeDeclaration(vrt.Name);
  41. ty.IsClass = true;
  42. ty.IsInterface = false;
  43. ty.BaseTypes.AddRange(vrt.t_extends.Map(ToCodeTypeReference).NToArray());
  44. ty.TypeParameters.AddRange(ToCodeTypeParameters(vrt.typarms).NToArray());
  45. ty.Members.AddRange(vrt.decls.Map(ToCodeTypeMember).NToArray());
  46. ty.UserData["Nemerle.TopDeclaration"] = "Variant";
  47. ty;
  48. }
  49. protected virtual ToCodeTypeDeclaration(vrto : TopDeclaration.VariantOption) : CodeTypeDeclaration
  50. {
  51. def ty = CodeTypeDeclaration(vrto.Name);
  52. ty.IsClass = true;
  53. ty.IsInterface = false;
  54. //ty.BaseTypes.AddRange(vrto.t_extends.Map(ToCodeTypeReference).NToArray());
  55. //ty.TypeParameters.AddRange(ToCodeTypeParameters(vrto.typarms).NToArray());
  56. ty.Members.AddRange(vrto.decls.Map(ToCodeTypeMember).NToArray());
  57. ty.UserData["Nemerle.TopDeclaration"] = "VariantOption";
  58. ty;
  59. }
  60. protected virtual ToCodeTypeDeclaration(enm : TopDeclaration.Enum) : CodeTypeDeclaration
  61. {
  62. def ty = CodeTypeDeclaration(enm.Name);
  63. ty.IsClass = false;
  64. ty.IsEnum = true;
  65. ty.BaseTypes.AddRange(enm.t_extends.Map(ToCodeTypeReference).NToArray());
  66. ty.TypeParameters.AddRange(ToCodeTypeParameters(enm.typarms).NToArray());
  67. ty.Members.AddRange(enm.decls.Map(ToCodeTypeMember).NToArray());
  68. ty;
  69. }
  70. protected virtual ToCodeTypeDeclaration(ifs : TopDeclaration.Interface) : CodeTypeDeclaration
  71. {
  72. def ty = CodeTypeDeclaration(ifs.Name);
  73. ty.IsClass = false;
  74. ty.IsInterface = true;
  75. ty.BaseTypes.AddRange(ifs.t_extends.Map(ToCodeTypeReference).NToArray());
  76. ty.TypeParameters.AddRange(ToCodeTypeParameters(ifs.typarms).NToArray());
  77. ty.Members.AddRange(ifs.methods.Map(ToCodeTypeMember).NToArray());
  78. ty;
  79. }
  80. protected virtual ToCodeTypeDeclaration(cls : TopDeclaration.Class) : CodeTypeDeclaration
  81. {
  82. def ty = CodeTypeDeclaration(cls.Name);
  83. when(cls.Attributes %&& NemerleAttributes.Struct)
  84. {
  85. ty.IsClass = false;
  86. ty.IsStruct = true;
  87. }
  88. ty.BaseTypes.AddRange(cls.t_extends.Map(ToCodeTypeReference).NToArray());
  89. ty.TypeParameters.AddRange(ToCodeTypeParameters(cls.typarms).NToArray());
  90. ty.Members.AddRange(cls.decls.Map(ToCodeTypeMember).NToArray());
  91. ty;
  92. }
  93. private ToCodeTypeReference(typeName : string) : CodeTypeReference
  94. {
  95. CodeTypeReference(typeName);
  96. }
  97. protected virtual ToCodeTypeReference(expr : PExpr) : CodeTypeReference
  98. {
  99. ToCodeTypeReference(expr.ToString());
  100. }
  101. protected virtual ToCodeTypeParameter(tyvar : Splicable) : CodeTypeParameter
  102. {
  103. CodeTypeParameter(tyvar.GetName().Id);
  104. }
  105. protected virtual ToCodeTypeParameters(typarms : Typarms) : list [CodeTypeParameter]
  106. {
  107. def toCodeTypeParameter(tyvar : Splicable) : CodeTypeParameter
  108. {
  109. def tyParm = ToCodeTypeParameter(tyvar);
  110. typarms.constraints
  111. .Filter(c => c.tyvar.Equals(tyvar))
  112. .Iter (c => _ = tyParm.Constraints.Add(ToCodeTypeReference(c.ty)));
  113. tyParm;
  114. }
  115. typarms.tyvars.Map(toCodeTypeParameter);
  116. }
  117. protected virtual ToMemberAttributes(attrs : NemerleAttributes) : MemberAttributes
  118. {
  119. mutable memberAttrs: MemberAttributes;
  120. when(attrs %&& NemerleAttributes.Static) memberAttrs |= MemberAttributes.Static;
  121. when(attrs %&& NemerleAttributes.Public) memberAttrs |= MemberAttributes.Public;
  122. when(attrs %&& NemerleAttributes.Private) memberAttrs |= MemberAttributes.Private;
  123. if(attrs %&& NemerleAttributes.Internal && attrs %&& NemerleAttributes.Protected)
  124. memberAttrs |= MemberAttributes.FamilyOrAssembly
  125. else
  126. {
  127. when(attrs %&& NemerleAttributes.Internal) memberAttrs |= MemberAttributes.Assembly;
  128. when(attrs %&& NemerleAttributes.Protected) memberAttrs |= MemberAttributes.Family;
  129. }
  130. when(attrs %&& NemerleAttributes.New) memberAttrs |= MemberAttributes.New;
  131. when(attrs %&& NemerleAttributes.Override) memberAttrs |= MemberAttributes.Override;
  132. when(attrs %&& NemerleAttributes.Sealed) memberAttrs |= MemberAttributes.Final;
  133. memberAttrs;
  134. }
  135. protected virtual ToCodeEnumOption(opt : ClassMember.EnumOption) : CodeMemberField
  136. {
  137. def ext = (opt.DefinedIn :> TopDeclaration.Enum).t_extends;
  138. def typeRef =
  139. if(ext.Length>0)
  140. ToCodeTypeReference(ext.Head);
  141. else
  142. ToCodeTypeReference("int");
  143. CodeMemberField(typeRef, opt.Name);
  144. }
  145. protected virtual ToCodeMemberField(field : ClassMember.Field) : CodeMemberField
  146. {
  147. CodeMemberField (ToCodeTypeReference (field.ty), field.Name);
  148. }
  149. protected virtual ToCodeMemberMethod(func : ClassMember.Function) : CodeMemberMethod
  150. {
  151. def codeMethod =
  152. match(func.Name)
  153. {
  154. | ".ctor" => CodeConstructor()
  155. | ".cctor" => CodeTypeConstructor()
  156. | "Main" when func.Attributes %&& NemerleAttributes.Static
  157. => CodeEntryPointMethod()
  158. | _ => CodeMemberMethod()
  159. };
  160. codeMethod.Name = func.Name;
  161. codeMethod.ReturnType = ToCodeTypeReference(func.header.ReturnType);
  162. //TODO: codeMethod.ReturnTypeCustomAttributes.AddRange(???.NToArray());
  163. codeMethod.Parameters.AddRange(func.header.Parameters.Map(ToCodeParameterDeclarationExpression).NToArray());
  164. codeMethod.ImplementationTypes.AddRange(func.implemented.Map(ToCodeTypeReference).NToArray());
  165. //TODO: codeMethod.PrivateImplementationType = ???
  166. codeMethod.TypeParameters.AddRange(ToCodeTypeParameters(func.header.TypeParameters).NToArray());
  167. codeMethod.Statements.AddRange(ToStatements(func.Body).NToArray());
  168. codeMethod;
  169. }
  170. protected virtual ToCodeParameterDeclarationExpression(parm : Parsetree.PParameter) : CodeParameterDeclarationExpression
  171. {
  172. def codeParam = CodeParameterDeclarationExpression(ToCodeTypeReference(parm.Type), parm.Name);
  173. codeParam.CustomAttributes.AddRange(parm.modifiers.GetCustomAttributes().Map(ToCodeAttributeDeclaration).NToArray());
  174. //codeParam.Direction = ???
  175. codeParam;
  176. }
  177. protected virtual ToCodeMemberProperty(prop : ClassMember.Property) : CodeMemberProperty
  178. {
  179. def codeProperty = CodeMemberProperty();
  180. codeProperty.Name = prop.Name;
  181. //TODO: codeProperty.ImplementationTypes.AddRange(???(ToCodeTypeReference).NToArray());
  182. //TODO: codeProperty.PrivateImplementationType = ???
  183. //TODO: codeProperty.Parameters = ???
  184. match (prop.getter)
  185. {
  186. | Some (m) => codeProperty.GetStatements.AddRange(ToStatements(m.Body).NToArray());
  187. | None => ()
  188. }
  189. match (prop.setter)
  190. {
  191. | Some (m) => codeProperty.SetStatements.AddRange(ToStatements(m.Body).NToArray());
  192. | None => ()
  193. }
  194. codeProperty;
  195. }
  196. protected virtual ToCodeMemberEvent(evt : ClassMember.Event) : CodeMemberEvent
  197. {
  198. def codeEvent = CodeMemberEvent();
  199. codeEvent.Name = evt.Name;
  200. codeEvent.Type = ToCodeTypeReference(evt.ty);
  201. //TODO: codeProperty.ImplementationTypes.AddRange(???(ToCodeTypeReference).NToArray());
  202. //TODO: codeProperty.PrivateImplementationType = ???
  203. codeEvent;
  204. }
  205. protected virtual ToCodeTypeMember(member : ClassMember) : CodeTypeMember
  206. {
  207. def codeMember =
  208. match (member)
  209. {
  210. | ClassMember.TypeDeclaration as tyDecl
  211. when tyDecl.td is TopDeclaration.Class => ToCodeTypeDeclaration(tyDecl.td :> TopDeclaration.Class);
  212. | ClassMember.TypeDeclaration as tyDecl
  213. when tyDecl.td is TopDeclaration.Variant => ToCodeTypeDeclaration(tyDecl.td :> TopDeclaration.Variant);
  214. | ClassMember.TypeDeclaration as tyDecl
  215. when tyDecl.td is TopDeclaration.VariantOption => ToCodeTypeDeclaration(tyDecl.td :> TopDeclaration.VariantOption);
  216. | ClassMember.TypeDeclaration as tyDecl
  217. when tyDecl.td is TopDeclaration.Delegate => ToCodeTypeDelegate(tyDecl.td :> TopDeclaration.Delegate);
  218. | ClassMember.Field as field => ToCodeMemberField(field);
  219. | ClassMember.Function as func => ToCodeMemberMethod(func);
  220. | ClassMember.Property as prop => ToCodeMemberProperty(prop);
  221. | ClassMember.Event as evt => ToCodeMemberEvent(evt);
  222. | ClassMember.EnumOption as enm => ToCodeEnumOption(enm);
  223. | _ => throw NotSupportedException($"$member not supported");
  224. }
  225. when(member.modifiers != null)
  226. {//member.modifiers == null for TopDeclaration.Variant
  227. codeMember.Attributes = ToMemberAttributes (member.Attributes);
  228. codeMember.CustomAttributes.AddRange(member.modifiers.GetCustomAttributes().Map(ToCodeAttributeDeclaration).NToArray());
  229. }
  230. codeMember.UserData["Member"] = member;
  231. codeMember;
  232. }
  233. protected virtual ToCodeAttributeDeclaration(attr : PExpr) : CodeAttributeDeclaration
  234. {
  235. CodeAttributeDeclaration(ToCodeTypeReference(attr));
  236. }
  237. protected ProcessTypeDeclaration(typeDecl : TopDeclaration) : CodeTypeDeclaration
  238. {
  239. match(typeDecl)
  240. {
  241. | TopDeclaration.Class as typeDecl => CreateClass(typeDecl)
  242. | _ =>
  243. throw NotImplementedException("Non class top declarations aren't supported yet")
  244. }
  245. }
  246. protected CreateClass(cls : TopDeclaration.Class) : CodeTypeDeclaration
  247. {
  248. // creates class declaration
  249. def classDecl = CodeTypeDeclaration(cls.Name);
  250. classDecl.Attributes = CodeDomHelper.GetMemberAttributes(cls.Attributes);
  251. classDecl.TypeAttributes = CodeDomHelper.GetTypeAttributes(cls.Attributes);
  252. def typeBuilder = cls.TypeBuilder;
  253. assert(typeBuilder != null);
  254. foreach (baseType in typeBuilder.GetDirectSuperTypes())
  255. _ = classDecl.BaseTypes.Add(ToTypeRef(baseType));
  256. classDecl.IsClass = true;
  257. // sets class access mofifiers
  258. classDecl.IsPartial = CodeDomHelper.IsPartial(cls.Attributes);
  259. // Set type parameters. will it work?
  260. //VladD2: ?????, ??? ???? ??? ?? ??? ?? ?????.
  261. //foreach (t in cls.typarms.tyvars)
  262. // _ = classDecl.TypeParameters.Add(CodeTypeParameter(t.ToString()));
  263. foreach (part is TopDeclaration.Class in typeBuilder.AstParts)
  264. ProcessClassPart(classDecl, part);
  265. classDecl.UserData["Name"] = cls.Name;
  266. classDecl.UserData["Member"] = cls;
  267. classDecl
  268. }
  269. protected virtual ProcessClassPart(classDecl : CodeTypeDeclaration, part : TopDeclaration.Class) : void
  270. {
  271. // TODO: Seems like comments went away
  272. //classDecl.Comments = CodeCommentStatement();
  273. // TODO: Figure out how to parse CustomAttributes
  274. //classDecl.CustomAttributes = cls.GetModifiers().GetCustomAttributes();
  275. ProcessClassMembers(part.GetMembers(), classDecl);
  276. //TODO: adds usings directives
  277. //AddToCodeNamespace(cls, codeClass);
  278. //TODO: Add Location ?
  279. }
  280. // needed cause we may want to override it in derived classes
  281. protected virtual ProcessClassMembers(members : list[ClassMember], classDecl : CodeTypeDeclaration) : void
  282. {
  283. foreach (m in members)
  284. {
  285. def codeTypeMember : CodeTypeMember =
  286. match (m : ClassMember)
  287. {
  288. | TypeDeclaration(td) => ProcessTypeDeclaration(td)
  289. | Field as field => CreateField(field)
  290. | Property as prop => CreateProperty(prop)
  291. | Event as vnt => CreateEvent(vnt)
  292. | Function as func => CreateMethod(func)
  293. | EnumOption => assert(false, "ClassMember.EnumOption not supported yet");
  294. };
  295. // TODO: Seems like comments went away
  296. //memberDecl.Comments = CodeCommentStatement();
  297. // TODO: Figure out how to parse CustomAttributes
  298. //memberDecl.CustomAttributes = member.GetModifiers().GetCustomAttributes();
  299. //// Add Location
  300. //memberDecl.UserData.Add(typeof(Location), member.Location);
  301. def loc = m.BodyOpenTokenLocation;
  302. codeTypeMember.UserData[typeof(Point)] = Point(loc.EndColumn, loc.EndLine);
  303. codeTypeMember.UserData["Name"] = m.Name;
  304. codeTypeMember.UserData["Member"] = m;
  305. codeTypeMember.Name = m.Name;
  306. _ = classDecl.Members.Add(codeTypeMember);
  307. }
  308. }
  309. protected virtual CreateField(field : ClassMember.Field) : CodeMemberField
  310. {
  311. // GetFieldInfo() doesn't work
  312. //def fieldDecl = CodeMemberField(field.GetFieldInfo().FieldType, field.Name);
  313. Debug.Print($"CreateField: from field $field");
  314. // TODO: VladD2: Using of GetSystemType() is bad idea!
  315. def fieldDecl = CodeMemberField(ToTypeRef(field.ty), field.Name);
  316. fieldDecl.Attributes = CodeDomHelper.GetMemberAttributes(field.Attributes, true);
  317. when (field.Initializer != null)
  318. fieldDecl.InitExpression = ToExpression(field.Initializer);
  319. fieldDecl
  320. }
  321. protected virtual CreateProperty(prop : ClassMember.Property) : CodeMemberProperty
  322. {
  323. Debug.Print($"CreateProperty: from $prop");
  324. def result = CodeMemberProperty();
  325. result.Attributes = CodeDomHelper.GetMemberAttributes(prop.Attributes);
  326. result.Name = prop.Name;
  327. when(prop.getter is Some(get))
  328. {
  329. result.HasGet = true;
  330. result.Type = ToTypeRef(get.header.ReturnType);
  331. _ = result.GetStatements.AddRange(ToStatements(get.Body).NToArray())
  332. }
  333. when(prop.setter is Some(set))
  334. {
  335. result.HasSet = true;
  336. result.Type = ToTypeRef(set.header.ReturnType);
  337. _ = result.SetStatements.AddRange(ToStatements(set.Body).NToArray())
  338. }
  339. result
  340. }
  341. protected virtual CreateEvent(evt : ClassMember.Event) : CodeMemberEvent
  342. {
  343. def eventDecl = CodeMemberEvent();
  344. eventDecl.Attributes = CodeDomHelper.GetMemberAttributes(evt.Attributes);
  345. eventDecl.Name = evt.Name;
  346. eventDecl.Type = ToTypeRef(evt.ty);
  347. eventDecl
  348. }
  349. protected virtual CreateMethod(method : ClassMember.Function) : CodeMemberMethod
  350. {
  351. Debug.Print($"CreateMethod : from $method");
  352. def methodDecl : CodeMemberMethod =
  353. match(method.Name)
  354. {
  355. | ".ctor" when method.Attributes %&& NemerleAttributes.Static => CodeTypeConstructor()
  356. | ".ctor" => CodeConstructor()
  357. | "Main" when method.Attributes %&& NemerleAttributes.Static => CodeEntryPointMethod()
  358. | _ => CodeMemberMethod()
  359. };
  360. methodDecl.Attributes = CodeDomHelper.GetMemberAttributes(method.Attributes, false);
  361. //TODO: methodDecl.ImplementationTypes - how to get that
  362. //methodDecl.Parameters
  363. foreach (p in method.header.Parameters)
  364. _ = methodDecl.Parameters.Add(CodeParameterDeclarationExpression(ToTypeRef(p.Type), p.Name));
  365. //TODO: methodDecl.PrivateImplementationType ?
  366. methodDecl.ReturnType = ToTypeRef(method.header.ReturnType);
  367. // methodDecl.TypeParameters , TODO: check if it actually works
  368. foreach (tp in method.header.TypeParameters.tyvars)
  369. _ = methodDecl.TypeParameters.Add(CodeTypeParameter(tp.ToString()));
  370. //_currentMethod = method;
  371. method.Builder.EnsureCompiled(); // we need PExpr & TExpr
  372. try
  373. {
  374. methodDecl.Statements.AddRange(ToStatements(method.Builder.BodyParsed).NToArray());
  375. }
  376. catch { | _ => () }
  377. //Debug.Print($" method.BodyTyped.Location (col = $(method.BodyTyped.Location.Column), line = $(method.BodyTyped.Location.Line))");
  378. methodDecl
  379. }
  380. ToTypeRefExpression(typeInfo : Nemerle.Compiler.TypeInfo, typeParaams : list[TypeVar]) : CodeTypeReferenceExpression
  381. {
  382. CodeTypeReferenceExpression(ToTypeRef(typeInfo, typeParaams))
  383. }
  384. ToTypeRefExpression(tyVar : TypeVar) : CodeTypeReferenceExpression
  385. {
  386. CodeTypeReferenceExpression(ToTypeRef(tyVar))
  387. }
  388. ToTypeRef(tyVar : PExpr) : CodeTypeReference
  389. {
  390. def cnvToCsTy(t : object)
  391. {
  392. t.ToString().Replace(".[", "<").Replace("[", "<").Replace("]", ">")
  393. }
  394. match (tyVar.TypedObject)
  395. {
  396. | t is TypeVar => ToTypeRef(t)
  397. | null => CodeTypeReference(cnvToCsTy(tyVar))
  398. | t => CodeTypeReference(cnvToCsTy(t))
  399. }
  400. }
  401. ToTypeRef(tyVar : TypeVar) : CodeTypeReference
  402. {
  403. _manager.Solver.PushState();
  404. try
  405. {
  406. def ty = tyVar.Fix();
  407. if (ty.IsFixed)
  408. {
  409. def makeTypeArgs(args) { args.MapToArray(ToTypeRef) }
  410. match (ty)
  411. {
  412. | Class(tycon, args) => ToTypeRef(tycon, args)
  413. | StaticTypeVarRef(tyvar) => CodeTypeReference(tyvar.Name)
  414. | Fun(_from, _to) => CodeTypeReference(typeof(object)) // HACK: Not supported by C#
  415. | Tuple(args) =>
  416. CodeTypeReference("Nemerle.Builtins.Tuple", makeTypeArgs(args))
  417. | Array(tyVar, rank) => CodeTypeReference(ToTypeRef(tyVar), rank)
  418. | Void => CodeTypeReference(typeof(void))
  419. | Ref(_tyVar)
  420. | Out(_tyVar) => throw ApplicationException("Ref/Out not supported")
  421. | Intersection(_types) => CodeTypeReference(typeof(object))
  422. }
  423. }
  424. else CodeTypeReference(typeof(object))
  425. }
  426. finally { _manager.Solver.PopState(); }
  427. }
  428. ToTypeRef(typeInfo : Nemerle.Compiler.TypeInfo, typeParams : list[TypeVar]) : CodeTypeReference
  429. {
  430. //Debug.Assert(typeInfo.TyparmsCount == 0, "typeInfo.TyparmsCount == 0, value is $(typeInfo.TyparmsCount)"); // TODO: Add support for type parameters!
  431. //Debug.Assert(typeParams.IsEmpty, $"typeParams.IsEmpty, value is $(typeParams.ToString())");
  432. if (typeInfo.SystemType != null)
  433. CodeTypeReference(typeInfo.SystemType.FullName, typeParams.Map(ToTypeRef).NToArray());
  434. else
  435. CodeTypeReference(typeInfo.FullName, typeParams.Map(ToTypeRef).NToArray());
  436. }
  437. protected virtual ToExpression(expr : PExpr) : CodeExpression
  438. {
  439. match (expr)
  440. {
  441. | <[ $expr1 && $expr2 ]> with op = BooleanAnd
  442. | <[ $expr1 || $expr2 ]> with op = BooleanOr
  443. | <[ $expr1 != $expr2 ]> with op = IdentityInequality
  444. | <[ $expr1 == $expr2 ]> with op = IdentityEquality
  445. | <[ $expr1 & $expr2 ]> with op = BitwiseAnd
  446. | <[ $expr1 | $expr2 ]> with op = BitwiseOr
  447. | <[ $expr1 + $expr2 ]> with op = Add
  448. | <[ $expr1 - $expr2 ]> with op = Subtract
  449. | <[ $expr1 / $expr2 ]> with op = Divide
  450. | <[ $expr1 * $expr2 ]> with op = Multiply =>
  451. CodeBinaryOperatorExpression(ToExpression(expr1), op, ToExpression(expr2))
  452. | <[ array[..$parms] ]> as ary =>
  453. def tExpr = ary.TypedObject :> TExpr;
  454. match (tExpr)
  455. {
  456. | TExpr.Array(_args, dimensions) =>
  457. Debug.Assert(dimensions is [_]);
  458. CodeArrayCreateExpression(
  459. ToTypeRef(tExpr.FixedType()), parms.MapToArray(ToExpression))
  460. | _ => NotSupportedExpression(ary)
  461. }
  462. | <[ $obj.$func(..$parms) ]> as call =>
  463. match (call.func.TypedObject)
  464. {
  465. | TExpr.StaticRef(from, mem, type_parms) when mem.MemberKind == MemberTypes.Constructor =>
  466. def codeParams = parms.MapToArray(ToExpression);
  467. CodeObjectCreateExpression(ToTypeRef(from.tycon, type_parms), codeParams);
  468. | te =>
  469. _ = te;
  470. CodeMethodInvokeExpression(
  471. CodeMethodReferenceExpression(ToExpression(obj),
  472. func.ToString()),
  473. parms.MapToArray(ToExpression));
  474. }
  475. | <[ + $expr ]> => ToExpression(expr)
  476. | <[ - $expr ]> =>
  477. def result = ToExpression(expr);
  478. match (result)
  479. {
  480. | cde is CodePrimitiveExpression =>
  481. match (cde.Value)
  482. {
  483. | val is int => CodePrimitiveExpression(-val)
  484. | val is long => CodePrimitiveExpression(-val)
  485. | val is short => CodePrimitiveExpression(-val)
  486. | val is decimal => CodePrimitiveExpression(-val)
  487. | val is double => CodePrimitiveExpression(-val)
  488. | val is float => CodePrimitiveExpression(-val)
  489. | _ => CodeBinaryOperatorExpression(CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, cde)
  490. }
  491. | _ => CodeBinaryOperatorExpression(CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, result)
  492. }
  493. | PExpr.Literal(literal) =>
  494. match (literal)
  495. {
  496. | Void => CodeTypeReferenceExpression("void")
  497. | Null with val = null : object | String(val) | Float (val) | Double (val)
  498. | Decimal (val) | Char (val) | Bool (val) => CodePrimitiveExpression(val)
  499. | Integer(val, is_negative, _treat_as) =>
  500. def val = val :> long;
  501. def val = if (is_negative) -val else val;
  502. def it = _manager.InternalType;
  503. def res = if (_treat_as.Equals(it.Int32)) CodePrimitiveExpression(val :> int)
  504. else if (_treat_as.Equals(it.UInt32)) CodePrimitiveExpression(val :> uint)
  505. else if (_treat_as.Equals(it.Int16)) CodePrimitiveExpression(val :> short)
  506. else if (_treat_as.Equals(it.UInt16)) CodePrimitiveExpression(val :> ushort)
  507. else if (_treat_as.Equals(it.SByte)) CodePrimitiveExpression(val :> sbyte)
  508. else if (_treat_as.Equals(it.Byte)) CodePrimitiveExpression(val :> byte)
  509. else CodePrimitiveExpression(val);
  510. res
  511. | Enum (_val : Literal.Integer, ty : TypeInfo, field : IField) =>
  512. CodeFieldReferenceExpression(CodeTypeReferenceExpression(ty.FullName), field.Name)
  513. }
  514. | <[ $func(..$parms) ]> => // TODO: Add support of ctor's
  515. match (func.TypedObject)
  516. {
  517. | TExpr.StaticRef(from, mem, tParms) when mem.MemberKind == MemberTypes.Constructor =>
  518. def codeParams = parms.MapToArray(ToExpression);
  519. CodeObjectCreateExpression(ToTypeRef(from.tycon, tParms), codeParams)
  520. | TExpr.MethodRef(obj = TExpr.This) with codeObj = CodeThisReferenceExpression()
  521. | TExpr.MethodRef(obj = TExpr.Base) with codeObj = CodeBaseReferenceExpression() =>
  522. CodeMethodInvokeExpression(
  523. CodeMethodReferenceExpression(codeObj,
  524. func.ToString()),
  525. parms.MapToArray(ToExpression));
  526. | te =>
  527. _ = te;
  528. CodeMethodInvokeExpression(
  529. CodeMethodReferenceExpression(null,
  530. func.ToString()),
  531. parms.MapToArray(ToExpression));
  532. }
  533. | <[ $obj.$field ]> when field.TypedObject is IField =>
  534. CodeFieldReferenceExpression(ToExpression(obj), field.TypedObject.Name);
  535. | <[ $obj.$prop ]> when prop.TypedObject is IProperty =>
  536. CodePropertyReferenceExpression(ToExpression(obj), prop.TypedObject.Name);
  537. | <[ $obj.$_ ]> as mem when mem.TypedObject is TExpr =>
  538. match (mem.TypedObject)
  539. {
  540. | TExpr.StaticRef(_from, mem, type_parms) when mem.IsStatic =>
  541. CodeFieldReferenceExpression(
  542. ToTypeRefExpression(mem.DeclaringType, type_parms), mem.Name)
  543. | TExpr.MethodRef(_tObj, meth, typeParms, _notvirtual) =>
  544. CodeMethodReferenceExpression(ToExpression(obj), meth.Name,
  545. typeParms.MapToArray(param => ToTypeRef(param)))
  546. | TExpr.StaticPropertyRef(from, prop) =>
  547. CodeFieldReferenceExpression(ToTypeRefExpression(from), prop.Name)
  548. | xxx => //TExpr.StaticPropertyRef
  549. _ = xxx;
  550. NotSupportedExpression(expr)
  551. }
  552. | PExpr.Ref(name) => CodeVariableReferenceExpression(name.ToString())
  553. | <[ $sourceExpr :> $_ ]> =>
  554. def tExpr = expr.TypedObject :> TExpr.TypeConversion;
  555. CodeCastExpression(ToTypeRef(tExpr.FixedType()), ToExpression(sourceExpr))
  556. | <[ base ]> => CodeBaseReferenceExpression()
  557. | <[ this ]> => CodeThisReferenceExpression()
  558. | <[ typeof($typeExpr) ]> => CodeTypeOfExpression(typeExpr.ToString()) // TODO: Test it
  559. | null => CodeSnippetExpression("");
  560. | PExpr.Member(_, _) => // (obj, member)
  561. //TODO: VladD2: ?????-?? ????. ???? ??? ??????????...
  562. // sample: obj = System.Drawing, member = Color
  563. match(_manager.CoreEnv.LookupType(expr.ToString().Split('.').NToList()))
  564. {
  565. | Some(ti) => CodeTypeReferenceExpression(ti.FullName);
  566. | _ => NotSupportedExpression(expr);
  567. }
  568. | _ => NotSupportedExpression(expr)
  569. }
  570. }
  571. NotSupportedExpression(expr : PExpr) : CodeExpression
  572. {
  573. def msg = $"[Form Designer]: Not suported expression: '$expr' ($(expr.GetType().Name)). Please, report about this bug.";
  574. Debug.WriteLine(msg);
  575. Message.Warning(expr.Location, msg);
  576. CodeSnippetExpression(expr.ToString())
  577. }
  578. GetInferredType(expr : PExpr) : CodeTypeReference
  579. {
  580. match (expr.TypedObject)
  581. {
  582. | tExpr is TExpr => ToTypeRef(tExpr.Type)
  583. | val is LocalValue => ToTypeRef(val.Type)
  584. | ty is TypeVar => ToTypeRef(ty)
  585. | _ => throw NotSupportedException($"can't inferr type for '$expr' expression")
  586. }
  587. }
  588. protected ToStatements(expr : PExpr) : IEnumerable[CodeStatement]
  589. {
  590. match (expr)
  591. {
  592. | PExpr.Sequence(exprs) =>
  593. foreach (expr in exprs)
  594. foreach (codeStatement in ToStatements(expr))
  595. yield codeStatement;
  596. | <[ $expr1 += $expr2 ]> =>
  597. match (expr1)
  598. {
  599. | <[ $obj.$member ]> when member.TypedObject is IEvent =>
  600. yield CodeAttachEventStatement(ToExpression(obj),
  601. member.TypedObject.Name, ToExpression(expr2))
  602. | _ =>
  603. yield CodeAssignStatement(ToExpression(expr1), ToExpression(<[ $expr1 + $expr2 ]>))
  604. }
  605. | <[ $expr1 -= $expr2 ]> =>
  606. match (expr1)
  607. {
  608. | <[ $obj.$member ]> when member.TypedObject is IEvent =>
  609. yield CodeRemoveEventStatement(ToExpression(obj),
  610. member.TypedObject.Name, ToExpression(expr2))
  611. | _ =>
  612. yield CodeAssignStatement(ToExpression(expr1), ToExpression(<[ $expr1 - $expr2 ]>))
  613. }
  614. | <[ $target = $source ]> =>
  615. yield CodeAssignStatement(ToExpression(target), ToExpression(source))
  616. | <[ mutable $expr = $val ]> with isMutable = true
  617. | <[ def $expr = $val ]> with isMutable = false =>
  618. def (expr, tyRef) =
  619. match (expr)
  620. {
  621. | PExpr.TypeEnforcement(expr, ty) => (expr, GetInferredType(ty))
  622. | _ => (expr, GetInferredType(expr));
  623. };
  624. def name =
  625. match (expr)
  626. {
  627. | PExpr.Ref(name) => name.Id;
  628. | _ => throw NotSupportedException($"$expr not supported");
  629. };
  630. def statement =
  631. match (val)
  632. {
  633. | null => CodeVariableDeclarationStatement(tyRef, name);
  634. | _ => CodeVariableDeclarationStatement(tyRef, name, ToExpression(val))
  635. };
  636. statement.UserData["mutable"] = isMutable;
  637. yield statement;
  638. | <[ when ($cond) $expr ]> =>
  639. yield CodeConditionStatement(ToExpression(cond), ToStatements(expr).NToArray())
  640. | <[ if ($cond) $trueExpr else $falseExpr ]> =>
  641. yield CodeConditionStatement(ToExpression(cond),
  642. ToStatements(trueExpr).NToArray(), ToStatements(falseExpr).NToArray())
  643. | _ => yield CodeExpressionStatement(ToExpression(expr))
  644. }
  645. }
  646. }
  647. }