private static string GetFunctionMarkdown(FunctionSymbol function, FunctionCallSyntax functionCall, SemanticModel model) { var buffer = new StringBuilder(); buffer.Append($"```bicep\nfunction "); buffer.Append(function.Name); buffer.Append('('); const string argumentSeparator = ", "; foreach (FunctionArgumentSyntax argumentSyntax in functionCall.Arguments) { var argumentType = model.GetTypeInfo(argumentSyntax); buffer.Append(argumentType); buffer.Append(argumentSeparator); } // remove trailing argument separator (if any) if (functionCall.Arguments.Length > 0) { buffer.Remove(buffer.Length - argumentSeparator.Length, argumentSeparator.Length); } buffer.Append("): "); buffer.Append(model.GetTypeInfo(functionCall)); buffer.Append("\n```"); return(buffer.ToString()); }
void ProcessCallExpression_throw_when_param_number_not_match() { var scope = new SymbolScope(); var name = new IdentifierToken("print", default); var funcSymbol = new FunctionSymbol(name.Value, DataType.Long, new DataType[] { DataType.Long }); scope.AddSymbol(funcSymbol); var param1 = new Mock <ExpressionAst>().Object; var param2 = new Mock <ExpressionAst>().Object; var callParamList = new CallParamListAst(new[] { param1, param2 }); var ast = new CallExpressionAst( name, new OperatorToken(Operator.LeftParen, default), callParamList, new OperatorToken(Operator.RightParen, default)); var generator = ConfigureGenerator(scope, mock => { mock.Setup(p => p.ProcessExpression(param1)).Returns(DataType.Long); mock.Setup(p => p.ProcessExpression(param2)).Returns(DataType.Long); }); Assert.Throws <SemanticException>(() => generator.ProcessCallExpression(ast)); }
public FuncCallExpression(FunctionSymbol symbol, Expression[] parameters) : base(symbol.ReturnType) { this.symbol = symbol; this.parameters = parameters; // TODO : Check parameter types against function signature. }
void ProcessCallExpression_returns_returnType_when_ok() { var scope = new SymbolScope(); var name = new IdentifierToken("print", default); var funcSymbol = new FunctionSymbol(name.Value, DataType.Long, // return new DataType[] { DataType.Double, DataType.Double }); // need scope.AddSymbol(funcSymbol); var param1 = new Mock <ExpressionAst>().Object; var param2 = new Mock <ExpressionAst>().Object; var callParamList = new CallParamListAst(new[] { param1, param2 }); var ast = new CallExpressionAst( name, new OperatorToken(Operator.LeftParen, default), callParamList, new OperatorToken(Operator.RightParen, default)); var generator = ConfigureGenerator(scope, mock => { mock.Setup(p => p.ProcessExpression(param1)).Returns(DataType.Double); // provide mock.Setup(p => p.ProcessExpression(param2)).Returns(DataType.Double); // provide }); Assert.Equal(DataType.Long, generator.ProcessCallExpression(ast)); }
public static BoundBlockStatement Flatten(FunctionSymbol function, BoundStatement node) { var builder = ImmutableArray.CreateBuilder <BoundStatement>(); var stack = new Stack <BoundStatement>(); stack.Push(node); while (stack.Count > 0) { var current = stack.Pop(); if (current is BoundBlockStatement block) { foreach (var s in block.Statements.Reverse()) { stack.Push(s); } } else { builder.Add(current); } } if (function.ReturnType == TypeSymbol.Void) { if (builder.Count == 0 || CanFallThrough(builder.Last())) { builder.Add(new BoundReturnStatement(null, true)); } } return(new BoundBlockStatement(builder.ToImmutable(), node.IsValid)); }
public static BoundBlockStatement Lower(FunctionSymbol function, BoundStatement body) { var lowerer = new Lowerer(); var res = lowerer.RewriteStatement(body); return(RemoveDeadCode(Flatten(function, res))); }
public BoundCallExpression(FunctionSymbol function, ImmutableArray <BoundExpression> arguments, string @namespace, ClassSymbol inClass = null) { Function = function; Arguments = arguments; Namespace = @namespace; InClass = inClass; }
public override bool Execute() { FunctionSymbol functionSymbol = GlobalSymbolTable.table.GetFunctionSymbol(_functionName); if (functionSymbol.Arguments.Count != _arguments.Count) { throw new Exception("Incorrect number of arguments passed to function: Expecting " + functionSymbol.Arguments.Count + " passed " + _arguments.Count); } //Checks that arguments passed to function are what the function is expecting for (int i = 0; i < _arguments.Count; i++) { //Incorrect type passed to the function if (_arguments[i].Value.Type != functionSymbol.Arguments[i].Value.Type) { throw new Exception("Incorrect type passed to function: Expecting " + functionSymbol.Arguments[i].Value.Type + " passed " + _arguments[i].Value.Type); } //Creates every argument as a variable for the function to use VariableDeclerationStatement variable = new VariableDeclerationStatement(_arguments[i].Value.Type, functionSymbol.Arguments[i].ArgumentName, _arguments[i].Value); variable.Execute(); } //Executes all function statements foreach (Statement statement in functionSymbol.Statements) { statement?.Execute(); } return(true); }
/// <summary> /// Inserts the given instruction at the given index. /// </summary> /// <param name="index">Index to insert instruction at.</param> /// <param name="insertInstruction">Instruction to insert.</param> private void InsertInstruction(int index, Instruction insertInstruction) { // Update the instruction index's of the instruction index operands. foreach (Instruction instruction in _instructionList) { for (int i = 0; i < instruction.OperandCount; i++) { Operand operand = instruction[i]; if (operand.OpType == OperandType.InstrIndex && operand.InstrIndex > index) { operand.InstrIndex++; } } } // Update the entry points of the functions. foreach (Symbol symbol in _symbolList) { if (symbol.Type == SymbolType.Function) { FunctionSymbol functionSymbol = (FunctionSymbol)symbol; if (functionSymbol.EntryPoint > index && functionSymbol.IsImport == false) { functionSymbol.EntryPoint++; } } } _instructionList.Insert(index, insertInstruction); _instructionIndex += 1; }
/** * 네이티브 라이브러리를 심볼 테이블에 로드한다. * * @param symbolTable */ public void load(SymbolTable symbolTable) { // 클래스 입력 foreach (int i in Enumerable.Range(0, classes.Count)) { symbolTable.classes.Add(new ClassSymbol(classes[i].className)); } // 함수 입력 foreach (int i in Enumerable.Range(0, functions.Count)) { List <VariableSymbol> parameters = new List <VariableSymbol>(); // 파라미터 처리 foreach (int j in Enumerable.Range(0, functions[i].parameters.Count)) { parameters.Add(new VariableSymbol("native_arg_" + j.ToString(), functions[i].parameters[j])); } // 함수 심볼 객체 생성 FunctionSymbol functn = new FunctionSymbol(functions[i].functionName, functions[i].returnType, parameters); functn.isNative = true; functn.nativeFunction = functions[i]; symbolTable.functions.Add(functn); } }
private FunctionSymbol MatchCompatibleOverload(ExpressionNode node, FunctionSymbol candidate, Expression[] arguments, out Expression[] convertedArguments) { var parameters = candidate.Parameters.ToArray(); if (arguments.Length != parameters.Length) { convertedArguments = null; return(null); } convertedArguments = new Expression[arguments.Length]; for (var i = 0; i < arguments.Length; i++) { var argument = arguments[i]; var parameter = parameters[i]; var conversionExpression = BindConversion(node, argument, parameter.Type, allowExplicit: false, noDiagnostics: true); if (conversionExpression is InvalidExpression) { return(null); } convertedArguments[i] = conversionExpression; } return(candidate); }
private FunctionSymbol BindFunctionDeclaration(FunctionDeclarationNode node) { var seenParameterNames = new HashSet <string>(); var parameters = new List <ParameterSymbol>(); foreach (var parameterNode in node.ParametersDeclaration.Parameters) { var parameterName = parameterNode.MainToken.Text; var parameterType = BindTypeClause(parameterNode.Type); if (seenParameterNames.Add(parameterName)) { var parameter = new ParameterSymbol(parameterName, parameterType); parameters.Add(parameter); } else { diagnostics.ReportParameterAlreadyDeclared(parameterNode.MainToken, parameterName); } } var type = BindTypeClause(node.ReturnType) ?? BuiltinTypes.Void; var function = new FunctionSymbol(node.FunctionName.Text, parameters, type, node); if (Scope.TryDeclareFunction(function)) { return(function); } diagnostics.ReportSymbolAlreadyDeclared(node.FunctionName, function.Name, "Function"); return(null); }
private static void WriteFunctionTo(FunctionSymbol symbol, TextWriter writer) { writer.WriteKeyword(SyntaxKind.FuncKeyword); writer.WriteSpace(); writer.WriteIdentifier(symbol.Name); writer.WritePunctuation(SyntaxKind.OpenParenToken); for (var i = 0; i < symbol.Parameters.Length; i++) { if (i > 0) { writer.WritePunctuation(SyntaxKind.CommaToken); } writer.WriteSpace(); symbol.Parameters[i].WriteTo(writer); writer.WriteSpace(); } writer.WritePunctuation(SyntaxKind.CloseParenToken); writer.WriteSpace(); writer.WritePunctuation(SyntaxKind.ColonToken); writer.WriteSpace(); symbol.ReturnType.WriteTo(writer); }
public static BoundBlockStatement Lower(FunctionSymbol function, BoundStatement statement) { var lowerer = new Lowerer(); var result = lowerer.RewriteStatement(statement); return(Flatten(function, result)); }
private void BuildParameter(ParameterDeclarationNode parameterDeclarationNode, bool buildArray = false) { if (parameterDeclarationNode.ParentNode is FunctionDefinitionNode functionDefinitionNode) { FunctionSymbol functionSymbol = (FunctionSymbol)functionDefinitionNode.Symbol; string parameterName = parameterDeclarationNode.NameNode.Value; string parameterTypeName = parameterDeclarationNode.TypeNameCapitalized; ParameterSymbol parameterSymbol; if (functionSymbol.IsExternal) { parameterSymbol = buildArray ? new ExternalParameterArraySymbol(functionSymbol, parameterTypeName, parameterName, parameterDeclarationNode) : new ExternalParameterSymbol(functionSymbol, parameterTypeName, parameterName, parameterDeclarationNode); } else { parameterSymbol = buildArray ? new ParameterArraySymbol(functionSymbol, parameterTypeName, parameterName, parameterDeclarationNode) : new ParameterSymbol(functionSymbol, parameterTypeName, parameterName, parameterDeclarationNode); } AddSymbol(parameterSymbol); } else { throw new Exception(); } }
private void OutputFunctionBody(FunctionSymbol symbol, BoundBlock body) { builder.AddFragment(new OutputFragment("Function ", StatementColour)); builder.AddFragment(new OutputFragment(symbol.Name, FunctionNameColour)); builder.AddFragment(new OutputFragment(DelimeterString, DefaultColour)); builder.AddFragment(new OutputFragment(symbol.ReturnType.Name, TypeColour)); builder.NewLine(); var paramCount = symbol.Parameters.Length; if (paramCount > 0) { builder.AddFragment(new OutputFragment("Parameters ", StatementColour)); for (int index = 0; index < paramCount - 1; index++) { builder.AddFragment(new OutputFragment(symbol.Parameters[index].Name, VariableColour)); builder.AddFragment(new OutputFragment(DelimeterString, DefaultColour)); builder.AddFragment(new OutputFragment(symbol.Parameters[index].ValueType.Name, TypeColour)); builder.AddFragment(new OutputFragment(", ", StatementColour)); } builder.AddFragment(new OutputFragment(symbol.Parameters[paramCount - 1].Name, VariableColour)); builder.AddFragment(new OutputFragment(DelimeterString, DefaultColour)); builder.AddFragment(new OutputFragment(symbol.Parameters[paramCount - 1].ValueType.Name, TypeColour)); builder.NewLine(); } OutputStatements(body.Statements, IndentString); }
private void PrintFunctionSymbol(FunctionSymbol symbol) { var parameters = new StringBuilder(); parameters.Append('('); foreach (var parameter in symbol.Syntax.Parameters) { parameters.Append(parameter.SpecifiedType?.FullName); parameters.Append(", "); } if (parameters.Length > 1) { parameters.Remove(parameters.Length - 2, 2); } parameters.Append(')'); PrintStart("Function: " + symbol.Syntax.FullName + parameters, ConsoleColor.Blue); if (symbol.AllChecked.Count > 1) { foreach (var checkedFunction in symbol.AllChecked) { PrintCheckedFunction(checkedFunction); } } _indentationLevel--; }
private void ParseFunctionDecl(SymTable symTable) { var c = Current; SymTable procSymTable = new SymTable { Parent = symTable }; var h = ParseFunctionHeading(procSymTable); Require(Semicolon); if (symTable.Contains(h.Name)) { throw new ParserException("Duplicate identifier {h.Name}", c.Line, c.Position); } var f = new FunctionSymbol { Name = h.Name, Parameters = h.Parameters, ReturnType = h.ReturnType }; symTable.Add(h.Name, f); var backup = CurrentReturnType; CurrentReturnType = f.ReturnType; var b = ParseBlock(procSymTable); CurrentReturnType = backup; Require(Semicolon); f.Block = b; }
private void BindFunctionDeclaration(FunctionDeclarationSyntax syntax) { var parameters = ImmutableArray.CreateBuilder <ParameterSymbol>(); var seenParameterNames = new HashSet <string>(); foreach (var parameterSyntax in syntax.Parameters) { var parameterName = parameterSyntax.Identifier.Text; var parameterType = BindTypeClause(parameterSyntax.Type); if (!seenParameterNames.Add(parameterName)) { _diagnostics.ReportParameterAlreadyDeclared(parameterSyntax.Span, parameterName); } else { var parameter = new ParameterSymbol(parameterName, parameterType); parameters.Add(parameter); } } var type = BindTypeClause(syntax.Type) ?? TypeSymbol.Void; if (type != TypeSymbol.Void) { _diagnostics.XXX_ReportFunctionsAreUnsupported(syntax.Type.Span); } var function = new FunctionSymbol(syntax.Identifier.Text, parameters.ToImmutable(), type, syntax); if (!_scope.TryDeclareFunction(function)) { _diagnostics.ReportSymbolAlreadyDeclared(syntax.Identifier.Span, function.Name); } }
private static void AppendFunctionSymbolInfo(this ICollection<SymbolMarkupToken> markup, FunctionSymbol symbol) { markup.AppendType(symbol.ValueType); markup.AppendSpace(); markup.AppendName(SymbolMarkupKind.FunctionName, symbol.Name); markup.AppendParameters(symbol.Parameters); }
private static BoundBlockStatement Flatten(FunctionSymbol function, BoundStatement statement) { var builder = ImmutableArray.CreateBuilder <BoundStatement>(); var stack = new Stack <BoundStatement>(); stack.Push(statement); while (stack.Count > 0) { var current = stack.Pop(); if (current is BoundBlockStatement block) { foreach (var syntax in block.Statements.Reverse()) { stack.Push(syntax); } } else { builder.Add(current); } } if (function.ReturnType == BuiltinTypes.Void) { if (builder.Count == 0 || CanFallThrough(builder.Last())) { builder.Add(new BoundReturnStatement(statement.Syntax, null)); } } return(new BoundBlockStatement(statement.Syntax, builder.ToImmutable())); }
public static bool AllPathsReturn(FunctionSymbol symbol, BoundBlockStatement body) { if (symbol.ReturnType == TypeSymbol.Void) { return(true); } if (!body.IsValid) { return(false); } var graph = Create(body); foreach (var toEnd in graph.End.Incoming) { if (!toEnd.From.Statements.Any()) { return(false); } if (toEnd.From.Statements.Last().Kind != BoundNodeKind.BoundReturnStatement) { return(false); } } return(true); }
void ExpressionStatement_generates_pop_if_expr_not_returning_void()// not correct!!! { // Arrange var scope = new SymbolScope(); var expr = new Mock <ExpressionAst>().Object; var generator = ConfigureGenerator(scope, mock => { mock.Setup(p => p.ProcessExpression(expr)).Returns(DataType.Long); }); var ast = new ExpressionStatementAst(expr, new OperatorToken(Operator.Semicolon, default)); var function = new FunctionSymbol("p", DataType.Void, new DataType[0]); generator.GlobalBuilder.RegisterFunction(function); generator.EnterFunctionDefination(function); // Act generator.ProcessExpressionStatement(ast); // Assert var instructions = generator.CurrentFunction.Builder.Bucket.Pop(); Assert.Single(instructions); Assert.Equal("pop", instructions[0].Parts.Single()); }
public static ControlFlowGraph CreateGraph(BoundBlock block, FunctionSymbol function = null) { var blockBuilder = new BasicBlockBuilder(); var edgeBuilder = new GraphBuilder(function); var blocks = blockBuilder.Build(block); return(edgeBuilder.Build(blocks)); }
public BoundFunctionPointer(FunctionSymbol function) { Function = function; var paramTypes = function.Parameters.Select(param => param.ValueType).ToImmutableArray(); ValueType = new FunctionTypeSymbol(paramTypes, function.ReturnType); }
public void EmitTree(FunctionSymbol function, TextWriter writer) { var tree = Program.Functions[function]; function.WriteTo(writer); writer.WriteLine(); tree.WriteTo(writer); }
public GraphBuilder(FunctionSymbol function) { blockFromStatement = new Dictionary <BoundStatement, BasicBlock>(); blockFromLabel = new Dictionary <LabelSymbol, BasicBlock>(); edges = new List <BasicBlockEdge>(); start = new BasicBlock(true, function); end = new BasicBlock(false, function); }
public static BoundBlockStatement Lower(FunctionSymbol function, BoundStatement statement) { var lowerer = new Lowerer(); var result = lowerer.RewriteStatement(statement); var flattenedResult = Flatten(function, result); var removedDeadCodeResult = RemoveDeadCode(flattenedResult); return(removedDeadCodeResult); }
public StandardLibraryDefinitionsStatement(SymbolTable table) { printInt = table.PutFunc(WordToken.PrintF.Lexeme, typeof(void), new[] { typeof(int) }); printFloat = table.PutFunc(WordToken.PrintF.Lexeme, typeof(void), new[] { typeof(float) }); printChar = table.PutFunc(WordToken.PrintF.Lexeme, typeof(void), new[] { typeof(char) }); printBool = table.PutFunc(WordToken.PrintF.Lexeme, typeof(void), new[] { typeof(bool) }); scanF = table.PutFunc(WordToken.ScanF.Lexeme, typeof(string), new Type[0]); }
private static IList <SymbolMarkupToken> GetMethodGroupPreambleParts(FunctionSymbol method) { var result = new List <SymbolMarkupToken>(); result.AddRange(method.ToMarkup(SymbolDisplayFormat.MinimallyQualifiedWithoutParameters).Tokens); result.Add(new SymbolMarkupToken(SymbolMarkupKind.Punctuation, "(")); return(result); }
public bool TryDeclareFunction(FunctionSymbol function) { if (functions.ContainsKey(function.Name)) { return(false); } functions.Add(function.Name, function); return(true); }
private static void AppendFunctionSymbolInfo(this ICollection<SymbolMarkupToken> markup, FunctionSymbol symbol) { markup.AppendType(symbol.ReturnType, false); markup.AppendSpace(); if (symbol.Parent is TypeSymbol) { markup.AppendTypeName((TypeSymbol) symbol.Parent); markup.AppendPunctuation("."); } if (symbol.IsNumericConstructor) markup.AppendKeyword(symbol.Name); else markup.AppendName(SymbolMarkupKind.FunctionName, symbol.Name); markup.AppendParameters(symbol.Parameters); }
FunctionSymbol CreateFunctionDef(BuiltIns.FuncShape fn) { IType returnType = ConvertTypeAndNullable(fn.ReturnType); List<IType> formalTypes = fn.FormalTypes.ConvertAll(desc => ConvertTypeAndNullable(desc)); // FunctionSymbol symFunctionDef = new FunctionSymbol(fn.Name, returnType, this.builtins); NadirAST nodeFunctionDef = new NadirAST(NadirParser.FunctionDef); NadirAST nodeReturnType = CreateBuiltinTypeNode(returnType); NadirAST nodeFormalParams = new NadirAST(NadirParser.FormalParams); NadirAST nodeOptions = new NadirAST(NadirParser.Options); // nodeFunctionDef.AddChild(CreateNameNode(fn.Name)); // 0 nodeFunctionDef.AddChild(nodeReturnType); // 1 nodeFunctionDef.AddChild(nodeFormalParams); // 2 nodeFunctionDef.AddChild(new NadirAST(NadirParser.Statements)); // 3 nodeFunctionDef.AddChild(nodeOptions); // 4 // for (int i = 0; i < fn.FormalNames.Count; i++) { NadirAST nodeFormalParam = new NadirAST(NadirParser.FormalParam); NadirAST nodeName = CreateNameNode(fn.FormalNames[i]); NadirAST nodeType = CreateBuiltinTypeNode(formalTypes[i]); NadirAST nodeFormalOptions = new NadirAST(NadirParser.Options); nodeFormalParam.AddChild(nodeName); nodeFormalParam.AddChild(nodeType); nodeFormalParam.AddChild(nodeFormalOptions); // if (fn.FormalTypes[i].IsRef) nodeFormalOptions.AddChild(new NadirAST(NadirParser.Ref)); if (fn.FormalTypes[i].IsOut) nodeFormalOptions.AddChild(new NadirAST(NadirParser.Out)); if (i==0 && fn.IsMethod) nodeFormalOptions.AddChild(new NadirAST(NadirParser.This)); // NadirASTDefineSymbols.LinkSymbolWithDefinition(nodeFormalParam, new VariableSymbol(fn.FormalNames[i], false, null)); NadirASTDefineTypes.SetResolvedTypeOfDefinition(nodeFormalParam, formalTypes[i]); // Debug.Assert(FormalParameter.FormalParamName(nodeFormalParam)==nodeName); Debug.Assert(FormalParameter.FormalParamType(nodeFormalParam)==nodeType); // nodeFormalParams.AddChild(nodeFormalParam); } // if (fn.IsVariadic) nodeOptions.AddChild(new NadirAST(NadirParser.Variadic)); if (fn.IsHoldFirst) nodeOptions.AddChild(new NadirAST(NadirParser.HoldFirst)); if (fn.IsHoldRest) nodeOptions.AddChild(new NadirAST(NadirParser.HoldRest)); if (fn.IsHoldAll) nodeOptions.AddChild(new NadirAST(NadirParser.HoldAll)); // NadirASTDefineSymbols.LinkSymbolWithDefinition(nodeFunctionDef, symFunctionDef); NadirASTDefineTypes.SetResolvedTypeOfDefinition(nodeFunctionDef, returnType); // symFunctionDef.NoteOptions(); // return symFunctionDef; }