private void CreateRuleDeclaration(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <SourceFile>(methodInvocationExpression, 0, 3, 4)) { return; } if (!(methodInvocationExpression.Arguments.First() is StringLiteral namExpression)) { Errors.Add(new CompilationError(context, "First argument must be a string literal.")); return; } var arguments = methodInvocationExpression.Arguments.Skip(1).ToList(); if (arguments.Count == 2) { arguments.Insert(1, new BooleanLiteral(context, true)); } methodInvocationExpression.Parent.AddChild( new RuleDeclaration( context, namExpression.Text.Substring(1, namExpression.Text.Length - 2), arguments ) ); methodInvocationExpression.Remove(); }
public override void EnterMethodInvocationExpression(MethodInvocationExpression methodInvocationExpression) { if (methodInvocationExpression.Base is MemberExpression memberExpression) { switch (memberExpression.Name) { case "toString": { if (methodInvocationExpression.GenericTypes.Any()) { Errors.Add(new CompilationError(memberExpression.Context, "Expected 0 generic type arguments")); } if (methodInvocationExpression.Arguments.Any()) { Errors.Add(new CompilationError(memberExpression.Context, "Expected 0 arguments")); } var replacement = memberExpression.Base; methodInvocationExpression.ReplaceWith(replacement); var parent = replacement.Parent; var index = parent.Children.IndexOf(replacement); Visit(replacement); if (replacement.Parent == null) { replacement = (IExpression)parent.Children.ElementAt(index); } replacement.Type = new StringType(methodInvocationExpression.Context); skipChildren = true; break; } } } if (methodInvocationExpression.isNativeRegisterReevaluation) { var nativeMethodName = ((StringLiteral)methodInvocationExpression.Arguments.ElementAt(0)).UnquotedText; var reevaluationEnumParameter = (int)((NumberLiteral)methodInvocationExpression.Arguments.ElementAt(1)).Value; Visit(methodInvocationExpression.Arguments.ElementAt(2)); var enumValue = (methodInvocationExpression.Arguments.ElementAt(2) as INameExpression)?.Declaration as EnumValue; var reevaluatedParameter = (int)((NumberLiteral)methodInvocationExpression.Arguments.ElementAt(3)).Value; if (enumValue == null) { Errors.Add(new CompilationError(methodInvocationExpression.Context, "The thrid argument must be an enum value")); } else { var root = methodInvocationExpression.NearestAncestorOfType <Root>(); root.ReevaluationRegistrations.Add(new ReevaluationRegistration(nativeMethodName, reevaluationEnumParameter, enumValue, reevaluatedParameter)); } methodInvocationExpression.Remove(); skipChildren = true; return; } }
private void RegisterString(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <SourceFile>(methodInvocationExpression, 0, 1)) { return; } if (!(methodInvocationExpression.Arguments.First() is StringLiteral nameExpression)) { Errors.Add(new CompilationError(context, "The argument must be a string literal.")); return; } var root = methodInvocationExpression.NearestAncestorOfType <Root>(); root.NativeStrings.Add(nameExpression.UnquotedText); methodInvocationExpression.Remove(); }
public override void ExitMethodInvocationExpression(MethodInvocationExpression methodInvocationExpression) { if (!(methodInvocationExpression.Base is MemberExpression memberExpression) || !(memberExpression.Base is SimpleNameExpression simpleNameExpression) || simpleNameExpression.Name != "Native") { return; } switch (memberExpression.Name) { case var name when nativeFunctionCallRegex.IsMatch(name): ReplaceCallToNativeFunction(methodInvocationExpression); break; case var name when nativeFunctionDefinitionRegex.IsMatch(name): RegisterNativeFunction(methodInvocationExpression); break; case "rule": CreateRuleDeclaration(methodInvocationExpression); break; case "debugExecute": methodInvocationExpression.Remove(); break; case "trigger": ConvertToNativeTrigger(methodInvocationExpression); break; case "playerTrigger": ConvertToPlayerTrigger(methodInvocationExpression); break; case "registerString": RegisterString(methodInvocationExpression); break; case "assert": ConvertToAssersion(methodInvocationExpression); break; case "listLambda": ConvertToListLambda(methodInvocationExpression); break; case "chaseOverTime": case "chaseAtRate": ConvertToChase(memberExpression.Name, methodInvocationExpression); break; case "stopChasing": ConvertToStopChase(methodInvocationExpression); break; case "playerVars": ConvertToPlayerVarsExpression(methodInvocationExpression); break; case "registerReevaluation": RegisterReevaluation(methodInvocationExpression); break; } }
private void RegisterNativeFunction(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; var memberExpression = (MemberExpression)methodInvocationExpression.Base; var matchGroups = nativeFunctionDefinitionRegex.Match(memberExpression.Name).Groups; var numberOfArguments = int.Parse(matchGroups[1].Value); var hasReturnType = matchGroups[2].Value == "Function"; var expectedNumberOfGenericArguments = numberOfArguments + (hasReturnType ? 1 : 0); if (!ValidateSignature <SourceFile>(methodInvocationExpression, expectedNumberOfGenericArguments, 4)) { return; } if (!(methodInvocationExpression.Arguments.First() is StringLiteral namExpression)) { Errors.Add(new CompilationError(context, "First argument must be a string literal.")); return; } if (methodInvocationExpression.Arguments.Skip(1).Take(2).Any(x => !(x is BooleanLiteral))) { Errors.Add(new CompilationError(context, "Second and third argument must be boolean literals.")); return; } var nativeMethodName = namExpression.Text.Substring(1, namExpression.Text.Length - 2); var readsState = ((BooleanLiteral)methodInvocationExpression.Arguments.AtIndex(1)).Value; var changesState = ((BooleanLiteral)methodInvocationExpression.Arguments.AtIndex(1)).Value; if (NativeMethods.ModifyingControlFlow.Contains(nativeMethodName)) { Errors.Add(new CompilationError(context, "Native methods that modify control flow are restricted. Use if/for/foreach/while to modify control flow.")); } var typescriptNames = new List <string>(); var typescriptNameExpression = methodInvocationExpression.Arguments.Skip(3).First(); while (true) { if (typescriptNameExpression is MemberExpression typescriptNameMemberExpression) { typescriptNames.Insert(0, typescriptNameMemberExpression.Name); typescriptNameExpression = typescriptNameMemberExpression.Base; } else if (typescriptNameExpression is SimpleNameExpression typescriptNameSimpleExpression) { typescriptNames.Insert(0, typescriptNameSimpleExpression.Name); break; } else { Errors.Add(new CompilationError(context, "Last argument can only consist of simple names. Ex. Math.abs")); break; } } var container = (INode)methodInvocationExpression.NearestAncestorOfType <Root>(); for (int i = 0; i < typescriptNames.Count - 1; i++) { var module = container.Children.OfType <ModuleDeclaration>().SingleOrDefault(x => x.Name == typescriptNames[i]); if (module == null) { module = new ModuleDeclaration(context, typescriptNames[i], new INode[0]); container.AddChild(module); } container = module; } var parameterTypes = methodInvocationExpression.GenericTypes.Take(numberOfArguments).ToList(); var returnType = hasReturnType ? methodInvocationExpression.GenericTypes.Last() : new VoidType(context); var nativeMethodInvocationExpression = new NativeMethodInvocationExpression( context, nativeMethodName, returnType, readsState, changesState, false, parameterTypes.SelectMany((x, i) => new INode[] { AstCloner.Clone(x), new SimpleNameExpression(context, "param" + i) }) ); var statement = hasReturnType ? (IStatement) new ReturnStatement(context, nativeMethodInvocationExpression.Yield()) : new ExpressionStatement(context, nativeMethodInvocationExpression); var methodDeclaration = new MethodDeclaration( context, typescriptNames.Last(), parameterTypes.Select((x, i) => new VariableDeclaration(context, "param" + i, AstCloner.Clone(x).Yield())) .Concat <INode>(returnType.Yield()) .Concat(new BlockStatement(context, statement.Yield()).Yield()) ); methodDeclaration.Modifiers.Add(MemberModifier.Static); container.AddChild( methodDeclaration ); methodInvocationExpression.Remove(); }
private void UnwrapMethodInvocation(MethodInvocationExpression invocation, MethodDeclaration declaration) { if (invocation.Parent == null) { return; } var context = invocation.Context; var parentStatement = invocation.NearestAncestorOfType <IStatement>(); var discardReturnValue = invocation.Parent is ExpressionStatement; var block = (BlockStatement)parentStatement.Parent; var addedStatements = new List <IStatement>(); VariableDeclaration returnValueVar = null; if (!discardReturnValue) { returnValueVar = new VariableDeclaration( context, declaration.Name + NumberWheel.Next(), new INode[] { AstCloner.Clone(declaration.ReturnType) }); var variableDeclarationStatement = new VariableDeclarationStatement(context, returnValueVar); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(returnValueVar); invocation.ReplaceWith(new SimpleNameExpression(context, returnValueVar.Name) { Type = returnValueVar.Type, Declaration = returnValueVar }); addedStatements.Add(variableDeclarationStatement); } else { invocation.Remove(); } var clonedDeclaration = AstCloner.Clone(declaration); var parameters = clonedDeclaration.Variables.ToList(); var arguments = invocation.Arguments.ToList(); for (int i = 0; i < parameters.Count; i++) { if (arguments.Count > i) { if (parameters[i].InitExpression != null) { parameters[i].InitExpression.ReplaceWith(arguments[i]); } else { parameters[i].AddChild(arguments[i]); } } parameters[i].Remove(); parameters[i].Name += NumberWheel.Next(); var variableDeclarationStatement = new VariableDeclarationStatement(parameters[i].Context, parameters[i]); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(parameters[i]); addedStatements.Add(variableDeclarationStatement); } foreach (var expression in clonedDeclaration.AllDescendantsAndSelf().OfType <SimpleNameExpression>()) { var index = parameters.IndexOf(expression.Declaration); if (index == -1) { continue; } expression.Name = parameters[index].Name; } var body = clonedDeclaration.Body; block.AddChildBefore(parentStatement, body); addedStatements.Add(body); var gotoTarget = new GotoTargetStatement(invocation.Context); block.AddChildBefore(parentStatement, gotoTarget); addedStatements.Add(gotoTarget); ReplaceReturnStatements(clonedDeclaration.Body, gotoTarget, returnValueVar); if (discardReturnValue) { parentStatement.Remove(); } foreach (var subInvocation in addedStatements.SelectMany(x => x.AllDescendantsAndSelf()).OfType <MethodInvocationExpression>().ToList()) { var subTarget = ((MethodReferenceType)subInvocation.Base.Type).Declaration; UnwrapMethodInvocation(subInvocation, subTarget); } BlockFlattener.FlattenAllSubBlocks(block); }