Advertisement
szymski

Untitled

Jul 30th, 2019
314
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.57 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using LuaAdv.Compiler.Nodes;
  7. using LuaAdv.Compiler.Nodes.Expressions;
  8. using LuaAdv.Compiler.Nodes.Expressions.Assignment;
  9. using LuaAdv.Compiler.Nodes.Expressions.BasicTypes;
  10. using LuaAdv.Compiler.Nodes.Math;
  11. using LuaAdv.Compiler.Nodes.Statements;
  12. using LuaAdv.Compiler.SemanticAnalyzer1;
  13.  
  14. namespace LuaAdv.Compiler.SemanticAnalyzer
  15. {
  16. /// <summary>
  17. /// Does lowering (replaces complex nodes with simpler ones) and validates correctness.
  18. /// </summary>
  19. public class SemanticAnalyzer2 : TransparentVisitor
  20. {
  21. public string FileName { get; set; } = "";
  22.  
  23. public SemanticAnalyzer2(Node mainNode) : base(mainNode)
  24. {
  25. }
  26.  
  27. public override Node Visit(StatementLambdaFunctionDeclaration node)
  28. {
  29. Node newNode = new StatementFunctionDeclaration(node.local, node.funcToken, node.name, node.parameterList, new Sequence(node.expression.Token, new Node[] { new Return(node.expression.Token, new[] { (Expression)node.expression }) }));
  30. newNode = newNode.Accept(this);
  31. return newNode;
  32. }
  33.  
  34. public override Node Visit(StatementLambdaMethodDeclaration node)
  35. {
  36. Node newNode = new StatementMethodDeclaration(node.funcToken, node.tableName, node.name, node.parameterList, new Sequence(node.expression.Token, new Node[] { new Return(node.expression.Token, new[] { (Expression)node.expression }) }));
  37. newNode = newNode.Accept(this);
  38. return newNode;
  39. }
  40.  
  41. public override Node Visit(AnonymousLambdaFunction node)
  42. {
  43. Node newNode = new AnonymousFunction(node.funcToken, node.parameterList, new Sequence(null, new Node[] { new Return(null, new[] { node.expression }) }));
  44. newNode = newNode.Accept(this);
  45. return newNode;
  46. }
  47.  
  48. public override Node Visit(Class node)
  49. {
  50. var newFields = new List<Tuple<string, Expression, TokenDocumentationComment>>();
  51. foreach (var field in node.fields)
  52. newFields.Add(new Tuple<string, Expression, TokenDocumentationComment>(field.Item1, (Expression)field.Item2?.Accept(this), field.Item3));
  53.  
  54. node.fields = newFields.ToArray();
  55.  
  56. var newMethods = new List<Tuple<string, Tuple<Token, string, Expression>[], Node, TokenDocumentationComment>>();
  57. foreach (var method in node.methods)
  58. {
  59. var newParams = new List<Tuple<Token, string, Expression>>();
  60. foreach (var param in method.Item2)
  61. newParams.Add(new Tuple<Token, string, Expression>(param.Item1, param.Item2, param.Item3 != null ? (Expression)param.Item3.Accept(this) : null));
  62.  
  63. var prevScope = CurrentScope;
  64. var scope = new Scope(CurrentScope);
  65. CurrentScope = scope;
  66. CurrentScope.RawFunctionName = method.Item1;
  67. CurrentScope.FunctionName = $"{node.name}:{method.Item1}";
  68.  
  69. var newMethod = method.Item3.Accept(this);
  70.  
  71. CurrentScope = prevScope;
  72.  
  73. newMethods.Add(new Tuple<string, Tuple<Token, string, Expression>[], Node, TokenDocumentationComment>(method.Item1, newParams.ToArray(), new ScopeNode(newMethod, scope), method.Item4));
  74.  
  75. // TODO: Scopes for class methods should created be here, before visiting nodes.
  76. }
  77.  
  78. var sequenceNodes = new List<Node>();
  79. sequenceNodes.Add(node);
  80.  
  81. Tuple<string, Tuple<Token, string, Expression>[], Node, TokenDocumentationComment> constructorMethod = null;
  82.  
  83. foreach (var method in newMethods)
  84. {
  85. if (method.Item1 == "this")
  86. {
  87. constructorMethod = method;
  88. continue;
  89. }
  90.  
  91. var methodDeclaration =
  92. new StatementMethodDeclaration(node.Token /* TODO: This should be a function token */,
  93. new Variable(node.Token, $"C{node.name}"), method.Item1, method.Item2.ToList() /* TODO: This should be an array */, method.Item3);
  94. var methodNode = new ClassMethod(node, methodDeclaration);
  95.  
  96. sequenceNodes.Add(methodNode);
  97. }
  98.  
  99. // Construct a sequence of initializing variables
  100.  
  101. List<Node> initializerNodes = new List<Node>();
  102.  
  103. foreach (var field in node.fields.Where(f => f.Item2 != null))
  104. {
  105. var initializerNode = new StatementExpression(new ValueAssignmentOperator(new TableDotIndex(new This(null), null, field.Item1), null, field.Item2)); // TODO: Null tokens could be replaced with a special class.
  106. initializerNodes.Add(initializerNode);
  107. }
  108.  
  109. if (constructorMethod == null)
  110. {
  111. if (node.baseClass != null)
  112. initializerNodes.Insert(0, new StatementExpression(new SuperCall(null, new Expression[0])));
  113. constructorMethod = new Tuple<string, Tuple<Token, string, Expression>[], Node, TokenDocumentationComment>("__this", new Tuple<Token, string, Expression>[0], new Sequence(null, initializerNodes.ToArray()), null); // TODO: Create scope for implicit constructor
  114. }
  115. else
  116. {
  117. var sequence = initializerNodes.Concat(((constructorMethod.Item3 as ScopeNode).node as Sequence).nodes);
  118. constructorMethod = new Tuple<string, Tuple<Token, string, Expression>[], Node, TokenDocumentationComment>("__this", constructorMethod.Item2, new Sequence(null, sequence.ToArray()), constructorMethod.Item4);
  119. }
  120.  
  121. var constructorDeclaration =
  122. new StatementMethodDeclaration(node.Token /* TODO: This should be a function token */,
  123. new Variable(node.Token, $"C{node.name}"), constructorMethod.Item1, constructorMethod.Item2.ToList(), constructorMethod.Item3);
  124. var constructorNode = new ClassMethod(node, constructorDeclaration);
  125.  
  126. var constructorScope = new Scope(CurrentScope);
  127. constructorScope.RawFunctionName = constructorMethod.Item1;
  128. constructorScope.FunctionName = constructorMethod.Item1;
  129.  
  130. sequenceNodes.Add(new ScopeNode(constructorNode, constructorScope));
  131.  
  132. return new Sequence(null, sequenceNodes.ToArray());
  133. }
  134.  
  135. public override Node Visit(SpecialNode node)
  136. {
  137. switch (node.value)
  138. {
  139. case "__LINE__":
  140. return new Number(node.Token, node.Token.Line + 1);
  141. case "__FUNCTION__":
  142. return new StringType(node.Token, CurrentScope.FunctionName ?? "");
  143. case "__TIME__":
  144. return new StringType(node.Token, DateTime.Now.ToString("T"));
  145. case "__DATE__":
  146. return new StringType(node.Token, DateTime.Now.ToString("d"));
  147. case "__LONGDATE__":
  148. return new StringType(node.Token, DateTime.Now.ToString("D"));
  149. case "__DATETIME__":
  150. return new StringType(node.Token, DateTime.Now.ToString("G"));
  151. case "__LONGDATETIME__":
  152. return new StringType(node.Token, DateTime.Now.ToString("R"));
  153. case "__FILE__":
  154. return new StringType(node.Token, this.FileName);
  155. default:
  156. throw new Exception($"'{node.value}' special token analysis not implemented.");
  157. }
  158. }
  159.  
  160. public override Node Visit(Variable node)
  161. {
  162. var enumNode = CurrentScope.LookupSingleEnum(node.name);
  163. if (enumNode != null)
  164. return enumNode.value.Accept(this);
  165.  
  166. return node;
  167. }
  168.  
  169. public override Node Visit(TableDotIndex node)
  170. {
  171. node.table = (Expression)node.table.Accept(this);
  172.  
  173. if (node.table is Variable variable)
  174. {
  175. var name = variable.name;
  176.  
  177. var enumNode = CurrentScope.LookupMultiEnum(name);
  178. if (enumNode != null)
  179. {
  180. var key = node.index;
  181. var value = enumNode.values.FirstOrDefault(v => v.Item1 == key);
  182. if (value == null)
  183. throw new CompilerException($"There is no such key '{key}' in the enum '{name}'.", node.Token);
  184.  
  185. return value.Item2;
  186. }
  187. }
  188.  
  189. return node;
  190. }
  191.  
  192. public override Node Visit(SingleEnum node)
  193. {
  194. return new NullStatement(node.Token);
  195. }
  196.  
  197. public override Node Visit(MultiEnum node)
  198. {
  199. return new NullStatement(node.Token);
  200. }
  201.  
  202. public override Node Visit(StaticIf node)
  203. {
  204. for (int i = 0; i < node.ifs.Count; i++)
  205. {
  206. var ifChild = node.ifs[i];
  207.  
  208. // Else
  209. if (i == node.ifs.Count - 1 && ifChild.Item2 == null)
  210. return ifChild.Item3.Accept(this);
  211.  
  212. var condition = ifChild.Item2.Accept(this) as Expression;
  213.  
  214. bool isTrue = false;
  215.  
  216. if (condition is Bool)
  217. isTrue = ((Bool)condition).value;
  218. else if (condition is Number)
  219. isTrue = ((Number)condition).value > 0;
  220. else if (condition is Variable == false)
  221. throw new CompilerException("Only basic types are supported in static if statements.", ifChild.Item2.Token);
  222.  
  223. if (isTrue)
  224. return ifChild.Item3.Accept(this);
  225. }
  226.  
  227. return new NullStatement(null);
  228. }
  229.  
  230. public override Node Visit(Add node)
  231. {
  232. node.left = node.left.Accept(this);
  233. node.right = node.right.Accept(this);
  234.  
  235. if (node.left is Number left && node.right is Number right)
  236. return new Number(node.Token, left.value + right.value);
  237.  
  238. return node;
  239. }
  240.  
  241. public override Node Visit(Subtract node)
  242. {
  243. node.left = node.left.Accept(this);
  244. node.right = node.right.Accept(this);
  245.  
  246. if (node.left is Number left && node.right is Number right)
  247. return new Number(node.Token, left.value - right.value);
  248.  
  249. return node;
  250. }
  251.  
  252. public override Node Visit(Multiply node)
  253. {
  254. node.left = node.left.Accept(this);
  255. node.right = node.right.Accept(this);
  256.  
  257. if (node.left is Number left && node.right is Number right)
  258. return new Number(node.Token, left.value * right.value);
  259.  
  260. return node;
  261. }
  262.  
  263. public override Node Visit(Divide node)
  264. {
  265. node.left = node.left.Accept(this);
  266. node.right = node.right.Accept(this);
  267.  
  268. if (node.left is Number left && node.right is Number right)
  269. return new Number(node.Token, left.value / right.value);
  270.  
  271. return node;
  272. }
  273.  
  274. public override Node Visit(GroupedEquation node)
  275. {
  276. node.expression = node.expression.Accept(this);
  277.  
  278. if (node.expression is Number n)
  279. return new Number(node.Token, n.value);
  280.  
  281. return node;
  282. }
  283.  
  284. public override Node Visit(Decorator node)
  285. {
  286. node.function = node.function.Accept(this);
  287.  
  288. for (int i = 0; i < node.parameters.Length; i++)
  289. node.parameters[i] = node.parameters[i].Accept(this);
  290.  
  291. // TODO: Multiple decorators don't work
  292. node.decoratedNode = node.decoratedNode.Accept(this);
  293.  
  294. Node innerNode = node.decoratedNode;
  295. if (innerNode is ScopeNode scope)
  296. innerNode = scope.node;
  297.  
  298. //while (innerNode is Decorator innerDecorator)
  299. //{
  300. // innerNode = innerDecorator.decoratedNode;
  301. // node.function = innerDecorator =
  302. //}
  303.  
  304.  
  305. if (innerNode is StatementFunctionDeclaration func)
  306. {
  307. var decoratorConstructorCall = new FunctionCall((Expression)node.function, node.parameters);
  308. var anonymousFunc = new AnonymousFunction(func.Token, func.parameterList, func.sequence);
  309. var decoratorCall = new FunctionCall(decoratorConstructorCall, new Node[] { anonymousFunc });
  310. var newNode = new StatementExpression(new ValueAssignmentOperator(func.name, node.token, decoratorCall));
  311.  
  312. return newNode;
  313. }
  314. else if (innerNode is StatementExpression stmtExpr && stmtExpr.expression is ValueAssignmentOperator assignOp)
  315. {
  316. var decoratorConstructorCall = new FunctionCall((Expression)node.function, node.parameters);
  317. var decoratorCall = new FunctionCall(decoratorConstructorCall, new Node[] { assignOp.right });
  318. var newNode = new StatementExpression(new ValueAssignmentOperator((Expression)assignOp.left, assignOp.Token, decoratorCall));
  319.  
  320. return newNode;
  321. }
  322. else if (innerNode is Class cl)
  323. {
  324. throw new NotImplementedException();
  325. }
  326.  
  327. return node.decoratedNode;
  328. }
  329. }
  330. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement