예제 #1
0
            public void AddDeclaredFunctions(FunctionSyntax function)
            {
                if (_declaredFunctions == null)
                    _declaredFunctions = new List<FunctionSyntax>();

                _declaredFunctions.Add(function);
            }
예제 #2
0
        private static bool ValidateEntryPoint(FunctionSyntax syntax, IDiagnosticSink diagnosticSink,
                                               TypeDefinition returnType, ImmutableList <TypeDefinition> parameterTypes)
        {
            // The method must return int32 and take no parameters
            if (returnType.Equals(SimpleType.Int32) && parameterTypes.Count == 0)
            {
                return(true);
            }

            diagnosticSink.Add(DiagnosticCode.EntryPointMustBeDeclaredCorrectly, syntax.Position);
            return(false);
        }
예제 #3
0
        /// <summary>
        /// Performs semantic analysis on the given method syntax tree and returns the compiled method if successful.
        /// Returns null if the compilation fails, in which case diagnostics are also emitted.
        /// </summary>
        /// <param name="syntaxTree">The syntax tree for the method.</param>
        /// <param name="declaration">The method declaration.</param>
        /// <param name="definingNamespace">The namespace where the method is defined.</param>
        /// <param name="sourceFilename">The name of the file where the method is defined.</param>
        public CompiledMethod?CompileBody(
            FunctionSyntax syntaxTree,
            MethodDeclaration declaration,
            string definingNamespace,
            string sourceFilename)
        {
            // Reset most per-method fields
            _syntaxTree        = syntaxTree;
            _declaration       = declaration;
            _definingNamespace = definingNamespace;
            _sourceFilename    = sourceFilename;
            _variableMap.Reset();

            return(InternalCompile());
        }
예제 #4
0
        public void Render(FunctionSyntax function)
        {
            if (function.ConstantKeywordToken != null)
            {
                Render(function.ConstantKeywordToken);
                WriteSpace();
            }

            Render(function.FunctionKeywordToken);
            WriteSpace();
            Render(function.FunctionDeclarationNode);
            Render(function.DeclarationLineDelimiterNode, true);
            Render(function.LocalVariableListNode);
            Render(function.StatementListNode);
            Outdent();
            Render(function.EndfunctionKeywordToken);
            Render(function.LastLineDelimiterNode);
        }
예제 #5
0
 public BoundFunction(string name, FunctionSyntax syntax)
     : base(syntax)
 {
     Name = name;
 }
예제 #6
0
        /// <summary>
        /// 解析模板语法。
        /// </summary>
        /// <param name="reader">当前读取实例。</param>
        /// <param name="syntax">当前语法节点。</param>
        protected virtual void Parse(CodeReader reader, Syntax syntax)
        {
            var declares = reader.ReadDeclarings();

            //读取代码
            while (reader.MoveNext())
            {
                if (reader.Current == '@')
                {
                    var name = reader.ReadName();
                    switch (name.ToLower())
                    {
                    case "@":
                    {
                        reader.MoveNext();
                        if (reader.Current == '{' || reader.Current == '(')
                        {        //代码块@{}/@()
                            var current = new SourceCodeSyntax();
                            current.Name = name;
                            if (reader.Current == '(')
                            {
                                current.Source = reader.ReadBlock('(', ')');
                            }
                            else
                            {
                                current.Source = reader.ReadBlock('{', '}');
                            }
                            current.Declarings.AddRange(declares);
                            syntax.Append(current);
                        }
                    }
                        continue;

                    case "@if":
                    {
                        ReadIf(reader, syntax);
                    }
                        continue;

                    default:
                    {
                        if (reader.IsNextNonWhiteSpace(';') || !reader.IsNextNonWhiteSpace('(', false))
                        {        //@属性
                            var property = new CodeSyntax();
                            property.Name = name;
                            property.Declarings.AddRange(declares);
                            syntax.Append(property);
                        }
                        else
                        {
                            var current = new FunctionSyntax();
                            current.Name = name;
                            //读取参数
                            if (!reader.IsNextNonWhiteSpace(')'))
                            {
                                current.Parameters = reader.ReadParameters();
                            }
                            current.Declarings.AddRange(declares);
                            syntax.Append(current);
                            //函数结束
                            ParseChildren(reader, current);
                        }
                        continue;
                    }
                    }
                }

                if (reader.Current == '}')
                {
                    reader.Skip();
                    break;
                }

                if (reader.Current == ';')
                {
                    reader.Skip();
                }
                else
                {
                    var name = reader.ReadName();
                    switch (name.ToLower())
                    {
                    case "script":
                    case "style":
                    {
                        var current = new CodeHtmlSyntax();
                        current.Name       = name;
                        current.Attributes = reader.ReadAttributes();
                        current.Declarings.AddRange(declares);
                        current.Code = reader.ReadBlock('{', '}').Trim('{', '}', ' ');
                        syntax.Append(current);
                    }
                        continue;

                    default:
                    {
                        var current = new HtmlSyntax();
                        current.Name       = name;
                        current.Attributes = reader.ReadAttributes();
                        current.Declarings.AddRange(declares);
                        syntax.Append(current);
                        //函数结束
                        ParseChildren(reader, current);
                    }
                        continue;
                    }
                }
            }
        }
예제 #7
0
        private JsFunction CompileFunction(string sourceCode, ReadOnlyArray<string> parameters)
        {
            BodySyntax newBody;

            if (sourceCode == String.Empty)
                newBody = new BodySyntax(BodyType.Function, ReadOnlyArray<SyntaxNode>.Empty, ReadOnlyArray<IIdentifier>.Empty, false, null);
            else
                newBody = ParseBlockStatement(sourceCode, parameters);

            var function = new FunctionSyntax(null, parameters, newBody, null);

            var scriptBuilder = TypeSystem.CreateScriptBuilder(null);
            var bindingVisitor = new BindingVisitor(scriptBuilder);

            var boundFunction = bindingVisitor.DeclareFunction(function);

            DefiniteAssignmentPhase.Perform(boundFunction);
            TypeMarkerPhase.Perform(boundFunction);

            boundFunction = SquelchPhase.Perform(boundFunction);

            return (JsFunction)Delegate.CreateDelegate(
                typeof(JsFunction),
                new CodeGenerator(Global, scriptBuilder).BuildFunction(boundFunction, sourceCode)
            );
        }
 public Function(FunctionSyntax syntax, Namespace containingNamespace, Accessibility declaredAccessibility, string name)
     : base(syntax, containingNamespace, declaredAccessibility, name)
 {
 }
예제 #9
0
 public virtual void Visit(FunctionSyntax functionSyntax)
 {
     foreach (var parameterSyntax in functionSyntax.Parameter)
     {
         Visit(parameterSyntax);
     }
     Visit(functionSyntax.Statements);
 }
예제 #10
0
        /// <summary>
        /// Verifies and creates type information for the method.
        /// Returns null if this fails, in which case diagnostics are also emitted.
        /// The name is not checked for duplication in this method.
        /// </summary>
        /// <param name="syntax">The syntax tree for the method.</param>
        /// <param name="definingNamespace">The name of the namespace this method is in.</param>
        /// <param name="definingFilename">The name of the file that contains the method.</param>
        /// <param name="methodBodyIndex">The index associated with the compiled method body.</param>
        /// <param name="declarationProvider">The type provider to use for resolving custom types.</param>
        /// <param name="diagnosticSink">The receiver for any semantic errors or warnings.</param>
        public static MethodDeclaration?Compile(
            FunctionSyntax syntax,
            string definingNamespace,
            string definingFilename,
            int methodBodyIndex,
            IDeclarationProvider declarationProvider,
            IDiagnosticSink diagnosticSink)
        {
            // Resolve the return type
            if (!TypeResolver.TryResolve(syntax.ReturnType, diagnosticSink, out var returnType))
            {
                return(null);
            }
            Debug.Assert(returnType != null);

            // Resolve parameter types
            // The parameter names are checked in InternalCompile()
            var parameterTypes = ImmutableList <TypeDefinition> .Empty;

            foreach (var param in syntax.Parameters)
            {
                if (!TypeResolver.TryResolve(param.Type, diagnosticSink, out var paramType))
                {
                    return(null);
                }
                Debug.Assert(paramType != null);
                if (paramType.Equals(SimpleType.Void))
                {
                    diagnosticSink.Add(DiagnosticCode.VoidIsNotValidType, param.Position, param.Name);
                    return(null);
                }
                parameterTypes = parameterTypes.Add(paramType);
            }

            // Apply the attributes
            // Each attribute can be validated independently, so don't stop on first failure
            var isEntryPoint = false;
            var isValid      = true;

            byte[]? importName    = null;
            byte[]? importLibrary = null;
            foreach (var attribute in syntax.Attributes)
            {
                switch (attribute.Name)
                {
                case "EntryPoint":
                    isValid     &= ValidateEntryPoint(syntax, diagnosticSink, returnType, parameterTypes);
                    isEntryPoint = true;
                    break;

                case "Import":
                    isValid &= TryParseImportAttribute(attribute, diagnosticSink, out importName, out importLibrary);
                    break;

                default:
                    diagnosticSink.Add(DiagnosticCode.UnknownAttribute, attribute.Position, attribute.Name);
                    isValid = false;
                    break;
                }
            }

            if (!isValid)
            {
                return(null);
            }

            // Some attributes may not be applied to the same method
            if (isEntryPoint && importName != null)
            {
                diagnosticSink.Add(DiagnosticCode.EntryPointAndImportNotCompatible, syntax.Position);
                return(null);
            }

            // Return a suitable subtype of the MethodDeclaration class
            if (importName != null)
            {
                Debug.Assert(importLibrary != null);

                return(new ImportedMethodDeclaration(methodBodyIndex, returnType, parameterTypes, syntax.Visibility,
                                                     definingNamespace + "::" + syntax.Name, definingFilename, syntax.Position, importName, importLibrary));
            }
            else
            {
                return(new NativeMethodDeclaration(methodBodyIndex, returnType, parameterTypes, syntax.Visibility,
                                                   definingNamespace + "::" + syntax.Name, definingFilename, syntax.Position, isEntryPoint));
            }
        }
예제 #11
0
 public void AddDeclaredFunction(FunctionSyntax function)
 {
     _scope.AddDeclaredFunctions(function);
 }
예제 #12
0
파일: Binder.cs 프로젝트: lawl-dev/Kiwi
        private void BindFunction(BoundFunction boundFunction, FunctionSyntax syntax)
        {
            _contextService.EnterScope();

            var boundParameters = syntax.Parameter.Select(BindParameter).ToList();
            boundFunction.Parameter = boundParameters;

            if (syntax.ReturnType != null)
            {
                boundFunction.ReturnType = BindType(syntax.ReturnType);
            }
            else if(syntax.Statements is ReturnStatementSyntax)
            {
                boundFunction.ReturnType = BindExpression(((ReturnStatementSyntax)syntax.Statements).Expression).Type;
            }
            boundFunction.Type = new FunctionCompilerGeneratedType(boundParameters.Select(x => x.Type).ToList(), boundFunction.ReturnType);
            boundFunction.IsInfixFunction = syntax is InfixFunctionSyntax;
            if (boundFunction.IsInfixFunction)
            {
                var parameter = string.Join(",", boundFunction.Parameter.Select(x=>x.Type));
                Ensure(
                    () => boundParameters.Count == 2,
                    $"infix' modifier is inapplicable on {boundFunction.Name}({parameter}) -> {boundFunction.ReturnType}. Parameter count != 2");
            }

            if (!_bindSignatures)
            {
                boundFunction.Statements = BindStatement(syntax.Statements);
            }
            _contextService.ExitScope();
        }