public AstPrinterNode Visit(UserFunctionCall node) { var printer = new AstPrinterNode(node.ToString()); // printer.AddChild(node.FuncIdent.Accept(this)); foreach (var param in node.ParamList) { printer.AddChild(param.Accept(this)); } return(printer); }
public bool Visit(UserFunctionCall node) { if (!_symStack.IsFuncExist(node.Ident.ToString())) { throw new Exception(string.Format( "({0}, {1}) semantic error: function '{2}' is not found", node.Ident.Token.Line, node.Ident.Token.Column, node.Ident.ToString())); } var paramTypes = new List <Tuple <bool, SymType> >(); foreach (var param in node.ParamList) { if (!WritableNodes.Contains(param.NodeType)) { throw new Exception(string.Format( "({0}, {1}) semantic error: expression '{2}' is not writable", param.Token.Line, param.Token.Column, param.ToString())); } param.Accept(this); // paramTypes.Add(new Tuple<bool, SymType>(param.IsLValue, param.SymType)); paramTypes.Add(new Tuple <bool, SymType>(param.IsLValue, (param.SymType as SymAliasType)?.GetBase() ?? param.SymType)); } var paramTypesString = paramTypes[0].Item2.ToString(); for (var i = 1; i < paramTypes.Count; ++i) { paramTypesString = string.Concat(paramTypesString, ", ", paramTypes[i].Item2.ToString()); } var possibleCallables = _symStack.FindFunc(node.Ident.ToString()); if (possibleCallables == null) { throw new Exception(string.Format( "({0}, {1}) semantic error: function '{2}({3})' is not found", node.Ident.Token.Line, node.Ident.Token.Column, node.Ident.ToString(), paramTypesString)); } CallableSymbol calledCallable = null; foreach (var callable in possibleCallables) { if (callable == null || paramTypes.Count != callable.ParametersTypes.Count) { throw new Exception(string.Format( "({0}, {1}) semantic error: function '{2}({3})' is not found", node.Ident.Token.Line, node.Ident.Token.Column, node.Ident.ToString(), paramTypesString)); } var callableFound = true; for (var i = 0; i < paramTypes.Count; ++i) { if (!((callable.ParametersTypes[i].Item2 as SymAliasType)?.GetBase() ?? callable.ParametersTypes[i].Item2).IsEquivalent(paramTypes[i].Item2)) { callableFound = false; } else //if got parameter is not lvalue, but it has 'var' modifier if (callable.ParametersTypes[i].Item1 == "var" && !paramTypes[i].Item1) { throw new Exception(string.Format( "({0}, {1}) semantic error: parameter '{2}' is not lvalue", node.ParamList[i].Token.Line, node.ParamList[i].Token.Column, node.ParamList[i].ToString())); } } if (callableFound) { calledCallable = callable; break; } } if (calledCallable == null) { throw new Exception(string.Format( "({0}, {1}) semantic error: function '{2}({3})' is not found", node.Ident.Token.Line, node.Ident.Token.Column, node.Ident.ToString(), paramTypesString)); } node.CallableSymbol = calledCallable; node.SymType = calledCallable.ReturnSymType; node.IsLValue = false; return(true); }