public dynamic Visit(FuncImplementation impl) { impl.CodeGenMethod = _currentMethod; foreach (var param in impl.Parameters) { _currentMethod.Parameter(param.Value.CodeGenType(), param.Key); } foreach (var param in impl.Parameters) { impl.Namespace.Symbols .SingleOrDefault(x => x.Name == param.Key) .CodeGenField = _codeGen.Arg(param.Key); } if (impl.ReturnExpression != null) { _codeGen.Return(Visit((dynamic)impl.ReturnExpression)); } if (impl.Code != null) { foreach (var statement in impl.Code.Statements) { Visit((dynamic)statement); } } return(null); }
public dynamic Visit(FuncImplementation impl) { var node = new TreeNode($"{impl.Name} Implementation") { Tag = impl.Node }; var argNode = new TreeNode("Arguments"); argNode.Nodes.AddRange(impl.ArgumentsTypes.Select(x => new TreeNode(x.ToString())).ToArray()); node.Nodes.Add(argNode); if (impl.ReturnExpression != null) { node.Nodes.Add(new TreeNode("ReturnExpr") { Nodes = { Visit(impl.ReturnExpression) } }); } if (impl.Code != null) { node.Nodes.Add(new TreeNode("Code") { Nodes = { Visit(impl.Code) } }); } node.Nodes.Add(new TreeNode("ReturnType") { Nodes = { new TreeNode(impl.ReturnType.ToString()) } }); return(node); }
public dynamic Visit(FuncImplementation impl) { impl.Code?.Optimize(); //if (impl.Code != null && !(impl.Code.Statements.LastOrDefault() is ReturnStm)) //{ // var retType = impl.ReturnType; // impl.Code.Statements.Add(new ReturnStm // { // Namespace = impl.Namespace, // ReturnExpression = new LiteralExpr // { // Namespace = impl.Namespace, // Value = retType.CodeGenType() == typeof(void)? null: GetDefault(retType.CodeGenType()) ?? "", // SymbolType = retType // } // }); //} impl.ReturnExpression?.Optimize(); return(null); }
public dynamic Visit(FuncImplementation impl) { Visit(impl.Code); return(null); }
/// <summary> /// Rule: Variable -> IDENTIFIER ((Array | Call))? ; /// </summary> protected override object EvalVariable(ParseTree tree, params object[] paramlist) { var identNode = GetNode(TokenType.IDENTIFIER); var name = identNode.Token.Text; var isLeftSide = paramlist != null && paramlist.Any() && (bool)paramlist.First(); if (GetNode(TokenType.Array) == null && GetNode(TokenType.Call) == null) { if (isLeftSide) { return(new LeftSideExprVariable { Name = name, Type = LeftSideExprType.Variable, Node = this }); } var existingSymbol = Namespaces.Current.Symbols.SingleOrDefault(x => x.Name == name); if (existingSymbol != null && existingSymbol.Type == SymbolType.Array) { throw new ParseException($"Использование массива {name} без индексатора", identNode); } if (existingSymbol != null && existingSymbol.Type == SymbolType.Function) { throw new ParseException($"Использование функции {name} без скобок", identNode); } if (existingSymbol != null && existingSymbol.Type != SymbolType.Unknown) { existingSymbol.UsagesCount++; return(new GetVariableExpr { Type = existingSymbol.Type, Node = this, Name = name }); } throw new ParseException($"Использование непроинициализированной переменной {name}", identNode); } if (GetNode(TokenType.Array) != null) { var expr = (ExpressionBase)GetNode(TokenType.Array).Eval(tree); var exprType = expr.GetExprType(); if (isLeftSide) { return(new LeftSideExprArray { ArrayKeyType = exprType, Index = expr, Node = this, Type = LeftSideExprType.Array, Name = name }); } var existingSymbol = Namespaces.Current.Symbols.SingleOrDefault(x => x.Name == name && x.Type == SymbolType.Array && x.ArrayKeyType == exprType); if (existingSymbol != null) { existingSymbol.UsagesCount++; return(new GetArrayExpr { ValuesType = existingSymbol.ArrayValueType, Node = this, Name = name, Index = expr, KeysType = existingSymbol.ArrayKeyType }); } if (Namespaces.Current.Symbols.Any(x => x.Name == name && x.Type == SymbolType.Array)) { throw new ParseException("Невозможно изменить тип ключа у массива", identNode); } throw new ParseException($"Использование непроинициализированного массива {name}", identNode); } if (GetNode(TokenType.Call) != null) { var arguments = ((Arguments)GetNode(TokenType.Call).Eval(tree)); var funcDeclaration = AstCreator.FuncDeclarations.SingleOrDefault(x => x.Name == name && x.Arguments.Count == arguments.Values.Count); if (funcDeclaration == null) { throw new ParseException($"Попытка использовать необъявленную функцию {name}", identNode); } var argumentsTypes = arguments.Values.Select(av => av.GetExprType()).ToList(); if (AstCreator.FuncImplementation.Count > 0) { if (AstCreator.FuncImplementation.Any(x => x.Name == name && x.ArgumentsTypes.SequenceEqual(argumentsTypes))) { throw new ParseException("Рекурсия не поддерживается", identNode); } } var funcImplementation = AstCreator.FuncImplementations.SingleOrDefault(x => x.Name == name && x.ArgumentsTypes.SequenceEqual(argumentsTypes)); if (funcImplementation == null) { funcImplementation = new FuncImplementation { Name = name, Node = this, ArgumentsTypes = argumentsTypes, Declaration = funcDeclaration }; AstCreator.FuncImplementation.Push(funcImplementation); var currentNamespace = Namespaces.Current; Namespaces.Current = Namespaces.Root; Namespaces.LevelDown(new Namespace($"{name}({string.Join(", ", argumentsTypes)})")); for (var index = 0; index < arguments.Values.Count; index++) { var symbolType = argumentsTypes[index]; var symbol = new Symbol(symbolType, funcDeclaration.Arguments[index]); Namespaces.Current.AddSymbol(symbol, identNode); } funcDeclaration.Node.Eval(tree, true, this); funcImplementation.Namespace = Namespaces.Current; Namespaces.Current = currentNamespace; AstCreator.FuncImplementations.Add(AstCreator.FuncImplementation.Pop()); } var callFuncExpr = new CallFuncExpr { Node = this, Function = funcImplementation, Arguments = arguments }; if (isLeftSide) { return(new LeftSideExprCall { Name = name, Type = LeftSideExprType.Call, Node = this, CallFunc = callFuncExpr }); } if (funcImplementation.ReturnType == SymbolType.Void || funcImplementation.ReturnType == SymbolType.Unknown) { throw new ParseException("Невозможно использовать функции, возвращающие void в выражениях", this); } return(callFuncExpr); } return(null); }
/// <summary> /// Rule: Function -> IDENTIFIER (BROPEN Parameters BRCLOSE )? (ARROW Expr | Statements) ; /// </summary> protected override object EvalFunction(ParseTree tree, params object[] paramlist) { var functionName = GetNode(TokenType.IDENTIFIER).Token.Text; var parameters = (List <string>)GetNode(TokenType.Parameters)?.Eval(tree) ?? new List <string>(); bool isCalled = false; ParseNode callPlace = null; if (paramlist != null && paramlist.Any()) { isCalled = (bool)paramlist[0]; callPlace = (ParseNode)paramlist[1]; } if (functionName == "main") { if (isCalled) { throw new ParseException("Нельзя вызвать main", callPlace ?? GetNode(TokenType.IDENTIFIER)); } if (parameters.Count > 0) { throw new ParseException("Main не может иметь аргументов", GetNode(TokenType.IDENTIFIER)); } if (AstCreator.FuncImplementations.Any(x => x.Name == "main")) { throw new ParseException("Повторное обявление main", GetNode(TokenType.IDENTIFIER)); } var implementation = new FuncImplementation { Node = this, Name = "main", Declaration = AstCreator.FuncDeclarations.SingleOrDefault(x => x.Name == "main") }; AstCreator.FuncImplementation.Push(implementation); Namespaces.LevelDown(new Namespace("main()")); var codeblockNode = GetNode(TokenType.Statements); if (codeblockNode == null) { throw new ParseException("Main должен иметь тело", GetNode(TokenType.IDENTIFIER)); } var stms = (CodeBlock)codeblockNode.Eval(tree); implementation.Code = stms; implementation.Namespace = Namespaces.Current; Namespaces.LevelUp(); AstCreator.FuncImplementations.Add(AstCreator.FuncImplementation.Pop()); } else { if (isCalled) { var exprNode = GetNode(TokenType.Expr); var funcImpl = AstCreator.FuncImplementation.Peek(); funcImpl.Node = this; if (exprNode != null) { var expr = (ExpressionBase)exprNode.Eval(tree); funcImpl.ReturnExpression = expr; funcImpl.ReturnType = expr.GetExprType(); } else { var stms = (CodeBlock)GetNode(TokenType.Statements).Eval(tree); funcImpl.Code = stms; } } else { if (AstCreator.FuncDeclarations.Any(f => f.Name == functionName && f.Arguments.Count == parameters.Count)) { throw new ParseException($"Повтороное объявление функции {functionName}", GetNode(TokenType.IDENTIFIER)); } AstCreator.FuncDeclarations.Add( new FuncDeclaration { Name = functionName, Node = this, Arguments = parameters }); Namespaces.Current.AddSymbol( new Symbol(SymbolType.Function, functionName), GetNode(TokenType.IDENTIFIER)); } } return(null); }