/// <summary> /// Returns a ParametersParseNode object that represents the parameters defined /// for this external function using the values specified in the given control /// list dictionary. For parameters where no value is given, a default of 0 or /// NULL is substituted. /// </summary> /// <param name="cilist">A dictionary of control list values</param> /// <returns>A ParametersParseNode object.</returns> public ParametersParseNode ParametersNode(ControlList cilist) { if (cilist == null) { throw new ArgumentNullException("cilist"); } ParametersParseNode paramList = new ParametersParseNode(); foreach (FunctionDefinition def in _definitions) { if (def.Include) { ParseNode exprNode; if (!cilist.Has(def.Name)) { if (Symbol.IsNumberType(def.Symbol.Type)) { exprNode = new NumberParseNode(0); } else if (Symbol.IsLogicalType(def.Symbol.Type)) { exprNode = new NumberParseNode(new Variant(false)); } else { exprNode = new NullParseNode(); exprNode.Type = def.Symbol.Type; } } else { exprNode = cilist[def.Name]; } paramList.Add(exprNode, def.Symbol); } } return paramList; }
// Parse an intrinsic function call ParseNode IntrinsicOperand(string name, IdentifierParseNode node) { ExtCallParseNode tokenNode = new ExtCallParseNode("JComLib.Intrinsics,jcomlib", name); IntrDefinition intrDefinition = Intrinsics.IntrinsicDefinition(name); Debug.Assert(intrDefinition != null); SymType argType = SymType.NONE; int countOfParams = 0; bool isVarArg = (intrDefinition.Count == ArgCount.TwoOrMore); ParametersParseNode paramsNode = new ParametersParseNode(); VarArgParseNode argList = new VarArgParseNode(); // Parameters to inlined instrinsics are always passed by value. bool useByRef = !(_opts.Inline) || !tokenNode.CanInline(); if (!intrDefinition.IsPermittedInIntrinsic) { useByRef = false; } for (int c = 0; c < node.Indexes.Count; ++c) { ParseNode exprNode = node.Indexes[c]; if (c > 0 && !ValidateAssignmentTypes(exprNode.Type, argType)) { _messages.Error(MessageCode.TYPEMISMATCH, string.Format("All arguments to {0} must be of the same type", name)); } argType = exprNode.Type; if (!intrDefinition.IsValidArgType(argType)) { _messages.Error(MessageCode.TYPEMISMATCH, String.Format("Invalid argument type for {0}", name)); } if (intrDefinition.RequiredType != SymType.GENERIC) { exprNode.Type = intrDefinition.RequiredType; } if (isVarArg) { argList.Add(exprNode); } else { paramsNode.Add(exprNode, useByRef); } ++countOfParams; } if (isVarArg) { paramsNode.Add(argList, useByRef); } tokenNode.Parameters = paramsNode; // Make sure actual and expected arguments match bool match = false; switch (intrDefinition.Count) { case ArgCount.One: match = (countOfParams == 1); break; case ArgCount.OneOrTwo: match = (countOfParams == 1 || countOfParams == 2); break; case ArgCount.Two: match = (countOfParams == 2); break; case ArgCount.TwoOrMore: match = (countOfParams >= 2); break; default: Debug.Assert(false, "Unhandled ArgCount!"); break; } if (!match) { _messages.Error(MessageCode.WRONGNUMBEROFARGUMENTS, String.Format("Wrong number of arguments for {0}", name)); } // Set return type. GENERIC means use the type of the argument Debug.Assert(!(intrDefinition.ReturnType == SymType.GENERIC && argType == SymType.NONE), "argType cannot be null here!"); tokenNode.Type = (intrDefinition.ReturnType == SymType.GENERIC) ? argType : intrDefinition.ReturnType; tokenNode.Inline = _opts.Inline; return tokenNode; }