public void AddDeclaredFunctions(FunctionSyntax function) { if (_declaredFunctions == null) _declaredFunctions = new List<FunctionSyntax>(); _declaredFunctions.Add(function); }
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); }
/// <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()); }
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); }
public BoundFunction(string name, FunctionSyntax syntax) : base(syntax) { Name = name; }
/// <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; } } } }
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) { }
public virtual void Visit(FunctionSyntax functionSyntax) { foreach (var parameterSyntax in functionSyntax.Parameter) { Visit(parameterSyntax); } Visit(functionSyntax.Statements); }
/// <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)); } }
public void AddDeclaredFunction(FunctionSyntax function) { _scope.AddDeclaredFunctions(function); }
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(); }