示例#1
0
        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)));
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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))
                    )
                );
        }
示例#4
0
        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));
        }
示例#5
0
        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));
        }
示例#6
0
        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())));
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }