Example #1
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;
            }
        }
Example #2
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));
        }
Example #3
0
        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();
        }
Example #4
0
        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();
        }
Example #5
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);
        }