Example #1
0
        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);
        }