private void ConvertToPlayerVarsExpression(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <IStatement, IExpression>(methodInvocationExpression, 1, 1)) { return; } ReferenceType baseType = null; var genericType = methodInvocationExpression.GenericTypes.Single(); switch ((genericType as ReferenceType)?.Declaration) { case ClassDeclaration classDeclaration: baseType = classDeclaration.BaseType as ReferenceType; break; case GenericTypeDeclaration genericTypeDeclaration: baseType = genericTypeDeclaration.BaseType as ReferenceType; break; } if (!(baseType?.Declaration is ClassDeclaration baseClassDeclaration) || !(baseClassDeclaration.Parent is ModuleDeclaration baseClassModule) || baseClassModule.Parent != null || baseClassModule.Name != "Native" || baseClassDeclaration.Name != "PlayerVars") { Errors.Add(new CompilationError(context, "The generic type must extend Native.PlayerVars")); } methodInvocationExpression.ReplaceWith(new PlayerVarsExpression(context, genericType.Yield().Concat <INode>(methodInvocationExpression.Arguments))); }
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 ReplaceCallToNativeFunction(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; var memberExpression = (MemberExpression)methodInvocationExpression.Base; var matchGroups = nativeFunctionCallRegex.Match(memberExpression.Name).Groups; var numberOfArguments = int.Parse(matchGroups[1].Value); var hasReturnType = matchGroups[2].Value == "Function"; var expectedNumberOfGenericArguments = numberOfArguments + (hasReturnType ? 1 : 0); if (hasReturnType ? !ValidateSignature <IStatement, IExpression>(methodInvocationExpression, expectedNumberOfGenericArguments, numberOfArguments + 3, numberOfArguments + 4) : !ValidateSignature <ExpressionStatement>(methodInvocationExpression, expectedNumberOfGenericArguments, numberOfArguments + 3, numberOfArguments + 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(2)).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.")); } methodInvocationExpression.ReplaceWith( new NativeMethodInvocationExpression( context, nativeMethodName, hasReturnType ? methodInvocationExpression.GenericTypes.Last() : new VoidType(context), readsState, changesState, false, methodInvocationExpression.GenericTypes.Take(numberOfArguments) .Concat <INode>(methodInvocationExpression.Arguments.Skip(3).Take(numberOfArguments)) ) ); }
private void ConvertToStopChase(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <IStatement, IExpression>(methodInvocationExpression, 0, 1)) { return; } if (!(methodInvocationExpression.Arguments.First() is INameExpression)) { Errors.Add(new CompilationError(context, "The first argument must be a variable.")); return; } methodInvocationExpression.ReplaceWith(new StopChaseExpression(context, methodInvocationExpression.Arguments)); }
private void ConvertToChase(string name, MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <IStatement, IExpression>(methodInvocationExpression, 0, 3, 4)) { return; } if (!(methodInvocationExpression.Arguments.First() is INameExpression)) { Errors.Add(new CompilationError(context, "The first argument must be a variable.")); return; } var isChaseOverTime = name == "chaseOverTime"; var arguments = methodInvocationExpression.Arguments.ToList(); if (arguments.Count == 3) { var enumName = isChaseOverTime ? "ChaseTimeReevaluation" : "ChaseRateReevaluation"; var enumDeclaration = methodInvocationExpression .NearestAncestorOfType <Root>() .SourceFiles.SelectMany(x => x.EnumDeclarations) .Single(x => x.Name == enumName); var enumValue = enumDeclaration.Values.Single(x => x.Name == "None"); arguments.Add( new MemberExpression(context, "None", new[] { new SimpleNameExpression(context, enumName) { Declaration = enumDeclaration, Type = new StaticReference(enumDeclaration) }, }) { Declaration = enumValue, Type = new StaticReference(enumValue) }); } methodInvocationExpression.ReplaceWith(new ChaseExpression(context, isChaseOverTime, arguments)); }
private void ConvertToListLambda(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <IStatement, IExpression>(methodInvocationExpression, 3, 3)) { return; } if (!(methodInvocationExpression.Arguments.First() is StringLiteral name)) { Errors.Add(new CompilationError(context, "The first argument must be a string literal.")); return; } var returnType = methodInvocationExpression.GenericTypes.Last(); methodInvocationExpression.ReplaceWith(new ListLambdaExpression(context, name.UnquotedText, methodInvocationExpression.Arguments.Skip(1).Concat <INode>(returnType.Yield()))); }
private void ConvertToPlayerTrigger(MethodInvocationExpression methodInvocationExpression) { var context = methodInvocationExpression.Context; if (!ValidateSignature <IStatement, IExpression>(methodInvocationExpression, 0, 3)) { return; } if (!(methodInvocationExpression.Arguments.First() is StringLiteral nameExpression)) { Errors.Add(new CompilationError(context, "The argument must be a string literal.")); return; } var nativeMethodName = nameExpression.Text.Substring(1, nameExpression.Text.Length - 2); var trigger = new NativeTrigger(context, nativeMethodName, methodInvocationExpression.Arguments.Skip(1)); methodInvocationExpression.ReplaceWith(trigger); }
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); }