public override void ExitNativeMethodInvocationExpression(NativeMethodInvocationExpression nativeMethodInvocationExpression) { var arguments = nativeMethodInvocationExpression.Arguments.ToList(); var parameterTypes = nativeMethodInvocationExpression.ParameterTypes.ToList(); for (int i = 0; i < nativeMethodInvocationExpression.Arguments.Count(); i++) { var fromType = arguments[i].Type; var toType = parameterTypes[i]; if (!fromType.IsAssignableTo(toType)) { Errors.Add(new CompilationError(arguments[i].Context, $"Can not assign {fromType} to {toType}")); } } }
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(); }
public override INode VisitNativeMethodInvocationExpression(NativeMethodInvocationExpression nativeMethodInvocationExpression) { return(new NativeMethodInvocationExpression(nativeMethodInvocationExpression.Context, nativeMethodInvocationExpression.NativeMethodName, nativeMethodInvocationExpression.Type, nativeMethodInvocationExpression.ReadsState, nativeMethodInvocationExpression.ChangesState, nativeMethodInvocationExpression.ModifiesControlFlow, nativeMethodInvocationExpression.Children.Select(Visit))); }
public virtual void ExitNativeMethodInvocationExpression(NativeMethodInvocationExpression nativeMethodInvocationExpression) { }
public virtual T VisitNativeMethodInvocationExpression(NativeMethodInvocationExpression nativeMethodInvocationExpression) { return(VisitChildren(nativeMethodInvocationExpression)); }