/// <summary> /// Updates function information in symbols or add new function /// </summary> /// <param name="function"></param> public void UpdateFunction(LanguageFunction function) { m_userFunctions.RemoveAll(func => func.Name == function.Name && func.Arguments.CompareTo(function.Arguments, (arg1, arg2) => arg1.TypeInfo.Name == arg2.TypeInfo.Name)); UpdateFunctionBuildName(function); m_userFunctions.Add(function); }
/// <summary> /// Returns function build name by name and arguments /// </summary> /// <param name="function"></param> /// <returns></returns> public string GetFunctionBuildName(LanguageFunction function) { string argsStr = "null"; if (function.Arguments.Count != 0) { argsStr = function.Arguments.Select(arg => arg.TypeInfo.Name) .Aggregate((id1, id2) => id1 + "@" + id2); } return(string.Format("{0}_@{1}", function.Name, argsStr)); }
/// <summary> /// Adds new function or returns false if it exists /// </summary> /// <param name="function"></param> /// <returns>True if function is added, otherwise false</returns> public bool AddUserFunction(LanguageFunction function) { if (IsFunctionExist(function.Name, function.Arguments)) { return(false); } UpdateFunctionBuildName(function); m_userFunctions.Add(function); return(true); }
private static FunctionElement CreateMain() { var symbols = LanguageSymbols.Instance; LanguageFunction functionInfo = new LanguageFunction(); functionInfo.Name = "!_Main"; functionInfo.Arguments = new List <LanguageFunction.FunctionArg>(); functionInfo.ReturnTypes = new List <LanguageType>(); symbols.AddUserFunction(functionInfo); FunctionElement funcElement = new FunctionElement(); funcElement.Info = functionInfo; StatementListElement statements = new StatementListElement(); funcElement.AddChild(statements); FunctionCallElement callElement = new FunctionCallElement(); LanguageFunction mainFuncInfo = null; try { mainFuncInfo = symbols.GetFunction("Main", new List <string>()); } catch (CompilationException) { Compilation.WriteError("Main() wasn't found. Did you forget it?", -1); } callElement.FunctionInfo = mainFuncInfo; callElement.CallArguments = new List <ValueElement>(); statements.AddChild(callElement); SingleGenOpElement exitElement = new SingleGenOpElement(); exitElement.Operation = new GenOp { Code = GenCodes.Exit, ArgCount = 0 }; statements.AddChild(exitElement); return(funcElement); }
/// <summary> /// Updates function build name by name and arguments /// </summary> /// <param name="function"></param> public void UpdateFunctionBuildName(LanguageFunction function) { function.BuildName = GetFunctionBuildName(function); }
/// <summary> /// Parse function declaration and save it. (Function body is parsed at second pass) /// </summary> /// <param name="module"></param> /// <param name="pos"></param> /// <returns>Position of a next lexeme</returns> private int ParseFunctionDeclaration(LexemeModule module, int pos) { ++pos; //skip "function" Compilation.Assert(module.Lexemes[pos].Code == Lexeme.CodeType.Name, "Invalid function name: '" + module.Lexemes[pos].Source + "'.", module.Lexemes[pos].Line); var functionName = module.Lexemes[pos].Source; ++pos; Compilation.Assert(module.Lexemes[pos].Source == "(", "Did you forget the '(' ?", module.Lexemes[pos].Line); ++pos; var args = new List <LanguageFunction.FunctionArg>(); var argsInitLexemes = new List <Lexemes>(); if (module.Lexemes[pos].Source != ")") { while (true) { string typeName; string varName; Lexemes initElements; pos = ParseFuncVarDeclaration(module, pos, false, out typeName, out varName, out initElements); args.Add(new LanguageFunction.FunctionArg { TypeInfo = m_symbols.GetTypeByName(typeName), ArgName = varName, DefaultVal = null /*Will be set in the 2nd pass*/ }); argsInitLexemes.Add(initElements); if (module.Lexemes[pos].Source == ")") { break; } else if (module.Lexemes[pos].Source == ",") { ++pos; } else { Compilation.WriteError("Expected ',' or ')', but found '" + module.Lexemes[pos].Source + "'.", module.Lexemes[pos].Line); } } } ++pos; //skip ")" Compilation.Assert(module.Lexemes[pos].Source == "->", "Did you forget the '->' ?", module.Lexemes[pos].Line); ++pos; bool hasOneReturnVar = true; if (module.Lexemes[pos].Source == "(") { hasOneReturnVar = false; ++pos; } List <string> returnVars = new List <string>(); do { Compilation.Assert(module.Lexemes[pos].Code == Lexeme.CodeType.Reserved || module.Lexemes[pos].Code == Lexeme.CodeType.Name, "'" + module.Lexemes[pos].Source + "' can't be a type", module.Lexemes[pos].Line); returnVars.Add(module.Lexemes[pos].Source); ++pos; if (hasOneReturnVar) { break; } if (module.Lexemes[pos].Source == ")") { ++pos; break; } if (module.Lexemes[pos].Source != ",") { Compilation.WriteError("Expected ',', but found '" + module.Lexemes[pos].Source + "'.", module.Lexemes[pos].Line); } ++pos; } while (true); var funcInfo = new LanguageFunction { Name = functionName, Arguments = args, ReturnTypes = returnVars.Select(typeName => m_symbols.GetTypeByName(typeName)) .ToList() }; bool ok = m_symbols.AddUserFunction(funcInfo); if (!ok) { Compilation.WriteError("Function " + funcInfo.Name + "' with arguments [" + funcInfo.Arguments.Select(arg => arg.TypeInfo.Name) .Aggregate((arg1, arg2) => arg1 + ", " + arg2) + "] already exists", module.Lexemes[pos].Line); } Lexemes funcLexemes; pos = ExtractBlock(module, pos, out funcLexemes); m_foundedFunctions.Add(new Parser1To2Pass.FunctionInfo { Info = funcInfo, FuncLexemes = funcLexemes, ArgInitLexemes = argsInitLexemes, ModuleName = module.FileName }); return(pos); }