bool BuilderFileInfo::StoreManifest()
{
	ConfigFile file;
	file.SetOrAddValue("Manifest", "Hash", CastToString(Hash));

	for (BuilderDependencyInfo& dependency : Dependencies)
	{
		file.SetOrAddValue("Dependencies", CastToString(dependency.Hash), dependency.SourcePath.ToString());
	}

	return file.Serialize(ManifestPath);
}
Element ExpectEqBuiltinImplementation::Interpret_( Environment& /*environment*/
                                                 , std::vector<Element> const& parms
                                                 , Element const& /*addParms*/ )
{
    typedef std::vector<Element>::const_iterator Iterator;
    Iterator iter = parms.begin();
    Iterator end = parms.end();

    bool success = true;

    String title = CastToString(*iter, success);
    ++iter;

    std::string first = iter->ToString();

    for(; iter != end; ++iter)
    {
        success = success && (first == iter->ToString());
    }

    if (success)
    {
        Tests::Instance().Success(title.Value());
        return True();        
    }
    else
    {
        std::stringstream ss;
        ss << title.Value() << ": " << parms[1].ToString() << " != " << parms[2].ToString();
        Tests::Instance().Failure(ss.str());
        return False(); 
    }
}
Element LanguageBuiltinImplementation::Interpret_( Environment& environment
                                                 , std::vector<Element> const& parmsIn
                                                 , Element const& // additional_parameters
                                                 )
{
    Element out;

    if (false == parmsIn.empty())
    {
        Element parm1 = parmsIn[0];
        std::vector<Element> parms(parmsIn.begin() + 1, parmsIn.end());
        
        bool isSuperString = false;
        SuperString SS = CastToSuperString(parm1, isSuperString);

        bool isString = false;
        String S = CastToString(parm1, isString);
        
        std::string id;
        if (isSuperString)
        {
            id = SS.Value();
        }

        if (isString)
        { 
            id = S.Value();
        }

        Translator& translator = this->translators.Get(id);
        out = Translate_(environment, parms, translator);
    }

    return out;
}
        int SizeOf_(Element const& element)
        {
            bool isA = false;
            int out = 0;
            switch(element.Type())
            {
                case Types::STRING: 
                {
                    String in  = CastToString(element, isA);
                    out = static_cast<int>(in.Value().size());
                    break;
                }

                case Types::SUPERSTRING: 
                {
                    SuperString in  = CastToSuperString(element, isA);
                    out = static_cast<int>(in.Value().size());
                    break;
                }

                case Types::CONTAINER:
                {
                    Container in = CastToContainer(element, isA);
                    out = in.NumberOfElements();
                    break;
                }
            };
            return out;  
        }
Element LanguageSetBuiltinImplementation::Translate_( Environment& //environment
                                                    , std::vector<Element> const& parms 
                                                    , Translator& translator
                                                    )
{
    Element out;
    if (2 == parms.size())  
    {
        bool idIsString = false;
        String idString = CastToString(parms[0], idIsString);

        bool valueIsString = false;
        String valueString = CastToString(parms[1], valueIsString);

        if (idIsString && valueIsString)
        {
            translator.SetProperty(idString.Value(), valueString.Value());
            out = valueString; 
        }
    }
    return out;
}
Element FileAttributesBuiltinImplementation::Interpret_( Environment&
        , std::vector<strine::Element> const& parms
        , Element const& )
{
    Container out;
    QString filename;
    if (1 >= parms.size())
    {
        bool success = false;
        String s = CastToString(parms[0], success);
        if (success)
        {
            filename = QString::fromStdString(s.Value());
        }
    }

    QFileInfo fileInfo(filename);
    if (fileInfo.isReadable())
    {
        out.Add(String("read"));
    }

    if (fileInfo.isWritable())
    {
        out.Add(String("write"));
    }

    if (fileInfo.isExecutable())
    {
        out.Add(String("execute"));
    }

    if (fileInfo.isDir())
    {
        out.Add(String("directory"));
    }

    if (fileInfo.isHidden())
    {
        out.Add(String("hidden"));
    }

    if (fileInfo.isSymLink())
    {
        out.Add(String("link"));
    }

    out.Add(String(fileInfo.owner().toStdString()));

    return out;
}
        Element Interpret_( Environment& 
                          , std::vector<Element> const& elements 
                          , Element const&)
        {
            Element out;

            bool hasError = true;
            std::stringstream errorStream;

            if (1 == elements.size())
            {
                bool isAContainer = false;    
                bool isAString = false;    
                bool isASuperString = false;    

                Container container = CastToContainer(elements[0], isAContainer);
                if (isAContainer)
                {
                    out = InterpretContainer_(container);
                    hasError = false;
                }

                String str = CastToString(elements[0], isAString);
                if (isAString)
                {
                    out = InterpretString_(str);
                    hasError = false;
                }

                SuperString sstr = CastToSuperString(elements[0], isASuperString);
                if (isASuperString)
                {
                    out = InterpretSuperString_(sstr);
                    hasError = false;
                }
            }

            if (hasError)
            {
                std::stringstream ss;
                ss << FunctionName_()
                   << " expects only 1 argument that is a container/string.";
                out = Error(ss.str());
            }
            

            return out;
        }
        Element Interpret_( Environment& 
                          , std::vector<Element> const& parms 
                          , Element const& )
        {
            if (parms.size() != 2)
            {
                std::stringstream ss; 
                ss << "at requires 2 parameters, received " << parms.size();
                return Error(ss.str());
            }

            bool castedToNumber = false;
            Number number = CastToNumber(parms[1], castedToNumber);

            bool castedToContainer = false;
            Container container = CastToContainer(parms[0], castedToContainer);
 
            bool castedToString = false;
            String str = CastToString(parms[0], castedToString);

            bool castedToSuperString = false;
            SuperString sstr = CastToSuperString(parms[0], castedToSuperString);

            if ((castedToContainer || castedToString || castedToSuperString) && castedToNumber)
            {
                if (castedToContainer)
                {
                     return InterpretContainer_( container, number );
                }
                if (castedToString)
                {
                     return InterpretString_( str, number );
                }      
                if (castedToSuperString)
                {
                     return InterpretSuperString_(sstr, number);
                }
                return Error("severe error");
            }
            else
            {
                std::stringstream ss;
                ss << "at requires a container/string and a number.";
                return Error(ss.str());
            }
        }
bool MSBuild_ProjectFile::Generate(
	DatabaseFile& databaseFile,
	WorkspaceFile& workspaceFile,
	ProjectFile& projectFile,
	IdeHelper::BuildProjectMatrix& buildMatrix
)
{
	Platform::Path solutionDirectory =
		workspaceFile.Get_Workspace_Location();

	Platform::Path projectDirectory =
		projectFile.Get_Project_Location();

	Platform::Path projectLocation =
		projectDirectory.AppendFragment(
			projectFile.Get_Project_Name() + ".vcxproj", true);

	std::vector<std::string> configurations =
		workspaceFile.Get_Configurations_Configuration();

	std::vector<EPlatform> platforms =
		workspaceFile.Get_Platforms_Platform();

	std::string projectGuid = Strings::Guid({
		workspaceFile.Get_Workspace_Name(),
		projectFile.Get_Project_Name() });

	// Files.
	std::vector<std::string> allFiles;

	std::vector<Platform::Path> baseFiles = projectFile.Get_Files_File();
	for (Platform::Path& path : baseFiles)
	{
		std::string relativePath = "$(SolutionDir)" +
			solutionDirectory.RelativeTo(path).ToString();

		allFiles.push_back(relativePath);
	}

	XmlNode root;

	// Header
	root.Node("?xml")
		.Attribute("version", "1.0")
		.Attribute("encoding", "utf-8");

	XmlNode& project =
		root.Node("Project")
		.Attribute("DefaultTargets", "Build")
		.Attribute("ToolsVersion", "")
		.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");

	// Build Matrix
	XmlNode& projectConfig =
		project.Node("ItemGroup")
		.Attribute("Label", "ProjectConfiguration");

	for (auto matrix : buildMatrix)
	{
		std::string platformId = MSBuild::GetPlatformID(matrix.platform);

		XmlNode& buildConfig =
			projectConfig.Node("ProjectConfiguration")
			.Attribute("Include", "%s|%s", matrix.config.c_str(), platformId.c_str());

		buildConfig.Node("Configuration").Value("%s", matrix.config.c_str());
		buildConfig.Node("Platform").Value("%s", platformId.c_str());
	}

	// Globals.
	XmlNode& globals =
		project.Node("PropertyGroup")
		.Attribute("Label", "Globals");

	globals.Node("ProjectGuid").Value("%s", projectGuid.c_str());
	globals.Node("Keyword").Value("MakeFileProj");

	// Undocumented hackery going on here:
	// As we have our own custom platforms, and we are building them through makefiles we are just
	// going to silence the "platform not found" warnings visual studio gives. It seems preferable
	// to creating a bunch of unneccessary project property files and tampering with visual studio.
	globals.Node("PlatformTargetsFound").Value("True");
	globals.Node("PlatformPropsFound").Value("True");	 
	globals.Node("ToolsetTargetsFound").Value("True");
		
	// Imports
	project.Node("Import")
		.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");

	// Property Grid
	for (auto matrix : buildMatrix)
	{
		std::string platformId = MSBuild::GetPlatformID(matrix.platform);

		XmlNode& propertyGroup =
			project.Node("PropertyGroup")
			.Attribute("Condition", "'$(Configuration)|$(Platform)'=='%s|%s'", matrix.config.c_str(), platformId.c_str())
			.Attribute("Label", "Configuration");

		propertyGroup.Node("ConfigurationType").Value("Makefile");

		// Debug libraries.
		if (matrix.projectFile.Get_Build_OptimizationLevel() == EOptimizationLevel::None ||
			matrix.projectFile.Get_Build_OptimizationLevel() == EOptimizationLevel::Debug)
		{
			propertyGroup.Node("UseDebugLibraries").Value("true");
		}
		else
		{
			propertyGroup.Node("UseDebugLibraries").Value("false");
		}

		// Platform tooltype.
		switch (matrix.projectFile.Get_Build_PlatformToolset())
		{
		case EPlatformToolset::Default:
			propertyGroup.Node("PlatformToolset").Value("%s", CastToString(m_defaultToolset).c_str());
			break;
		case EPlatformToolset::MSBuild_v140:
			propertyGroup.Node("PlatformToolset").Value("v140");
			break;
		case EPlatformToolset::MSBuild_v141:
			propertyGroup.Node("PlatformToolset").Value("v141");
			break;
		default:
			// Anny others will be dealt with on a per-platform basis, eg, AnyCPU etc.
			break;
		}
	}

	// Imports
	project.Node("Import")
		.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");

	// Extension settings
	project.Node("ImportGroup")
		.Attribute("Label", "ExtensionSettings");

	// Shared settings
	project.Node("ImportGroup")
		.Attribute("Label", "Shared");

	// Property sheets
	XmlNode& propSheetsNode = 
		project.Node("ImportGroup")
		.Attribute("Label", "PropertySheets");

	propSheetsNode.Node("Import")
		.Attribute("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")
		.Attribute("Label", "LocalAppDataPlatform")
		.Attribute("Condition", "Exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')");
	
	propSheetsNode.Node("Import")
		.Attribute("Project", "$(UserRootDir)\\Microsoft.Cpp.Win32.user.props")
		.Attribute("Label", "LocalAppDataPlatform")
		.Attribute("Condition", "!Exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')");
	
	// Macros
	project.Node("ImportGroup")
		.Attribute("Label", "UserMacros");

	// NMake property groups.
	for (auto matrix : buildMatrix)
	{
		std::string platformId = MSBuild::GetPlatformID(matrix.platform);

		Platform::Path outDir = matrix.projectFile.Get_Project_OutputDirectory();
		Platform::Path intDir = matrix.projectFile.Get_Project_IntermediateDirectory();

		Platform::Path outDirRelative = solutionDirectory.RelativeTo(outDir);
		Platform::Path intDirRelative = solutionDirectory.RelativeTo(intDir);

		std::vector<std::string> forcedIncludes;
		std::vector<std::string> includePaths;

		std::vector<std::string> defines = matrix.projectFile.Get_Defines_Define();

		XmlNode& propertyGroup =
			project.Node("PropertyGroup")
			.Attribute("Condition", "'$(Configuration)|$(Platform)'=='%s|%s'", matrix.config.c_str(), platformId.c_str());

		for (Platform::Path& path : matrix.projectFile.Get_ForcedIncludes_ForcedInclude())
		{
			forcedIncludes.push_back("$(SolutionDir)\\" + solutionDirectory.RelativeTo(path).ToString());
		}

		for (Platform::Path& path : matrix.projectFile.Get_SearchPaths_IncludeDirectory())
		{
			Platform::Path relativePath = solutionDirectory.RelativeTo(path).ToString();
			if (relativePath.IsRelative())
			{
				includePaths.push_back("$(SolutionDir)\\" + relativePath.ToString() + "\\");
			}
			else
			{
				includePaths.push_back(relativePath.ToString());
			}
		}

		Platform::Path relativeMicroBuildPath = solutionDirectory.RelativeTo(Platform::Path::GetExecutablePath());

		propertyGroup.Node("NMakeBuildCommandLine").Value("%s Build %s %s -c=%s -p=%s --silent", 
			Strings::Quoted("$(SolutionDir)\\" + relativeMicroBuildPath.ToString()).c_str(), 
			Strings::Quoted(workspaceFile.Get_Workspace_File().ToString()).c_str(),
			projectFile.Get_Project_Name().c_str(),
			matrix.config.c_str(),
			CastToString(matrix.platform).c_str()
		);
		propertyGroup.Node("NMakeOutput").Value("$(SolutionDir)%s\\%s%s", outDirRelative.ToString().c_str(), matrix.projectFile.Get_Project_OutputName().c_str(), matrix.projectFile.Get_Project_OutputExtension().c_str());
		propertyGroup.Node("NMakeCleanCommandLine").Value("%s Clean %s %s -c=%s -p=%s --silent",
			Strings::Quoted("$(SolutionDir)\\" + relativeMicroBuildPath.ToString()).c_str(), 
			Strings::Quoted(workspaceFile.Get_Workspace_File().ToString()).c_str(),
			projectFile.Get_Project_Name().c_str(),
			matrix.config.c_str(),
			CastToString(matrix.platform).c_str()
		);
		propertyGroup.Node("NMakeReBuildCommandLine").Value("%s Build %s %s -c=%s -p=%s -r --silent",
			Strings::Quoted("$(SolutionDir)\\" + relativeMicroBuildPath.ToString()).c_str(), 
			Strings::Quoted(workspaceFile.Get_Workspace_File().ToString()).c_str(),
			projectFile.Get_Project_Name().c_str(),
			matrix.config.c_str(),
			CastToString(matrix.platform).c_str()
		);
		propertyGroup.Node("NMakePreprocessorDefinitions").Value("%s;$(NMakePreprocessorDefinitions)", Strings::Join(defines, ";").c_str());
		propertyGroup.Node("NMakeIncludeSearchPath").Value("%s;$(NMakeIncludeSearchPath)", Strings::Join(includePaths, ";").c_str());
		propertyGroup.Node("NMakeForcedIncludes").Value("%s;$(NMakeForcedIncludes)", Strings::Join(forcedIncludes, ";").c_str());
	}

	// Empty item group (nmake project seems to generate this by default?).
	project.Node("ItemDefinitionGroup");

	// Create list of files.
	XmlNode& groupNode = 
		project.Node("ItemGroup");

	for (auto file : allFiles)
	{
		groupNode.Node("None")
			.Attribute("Include", "%s", file.c_str());
	}
		
	// We store which groups each file goes into so we can easily
	// generate a filters file.
	std::vector<MSBuildFileGroup> fileGroupList;

	MSBuildFileGroup group;
	for (auto file : allFiles)
	{
		MSBuildFile groupFile;
		groupFile.TypeId = "None";
		groupFile.Path = file;
		group.Files.push_back(groupFile);
	}
	fileGroupList.push_back(group);

	// Imports
	project.Node("Import")
		.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");

	// Extension settings
	project.Node("ImportGroup")
		.Attribute("Label", "ExtensionSettings");

	// Generate result.
	if (!databaseFile.StoreFile(
		workspaceFile,
		projectLocation,
		root.ToString().c_str()))
	{
		return false;
	}

	// Generate the filters file.
	MSBuild_VcxFiltersFile filtersFile(m_defaultToolsetString);

	if (!filtersFile.Generate(
		databaseFile,
		workspaceFile,
		projectFile,
		buildMatrix,
		fileGroupList
	))
	{
		return false;
	}

	return true;
}
        Element Interpret_( Environment& 
                          , std::vector<Element> const& parms
                          , Element const&)
        {
            if (parms.size() != 3)
            {
                std::stringstream ss;
                ss << "subseq requires 3 arguments, a container/string and start/end values";
                return Error(ss.str());
            }             

            bool gotANumber1 = false;
            bool gotANumber2 = false;
            bool gotAContainer = false;
            bool gotAString = false;
            bool gotASuperString = false;

            Number N1 = CastToNumber(parms[1], gotANumber1);
            Number N2 = CastToNumber(parms[2], gotANumber2);
            Container C = CastToContainer(parms[0], gotAContainer);
            String S = CastToString(parms[0], gotAString);
            SuperString SS = CastToSuperString(parms[0], gotASuperString);
             
            if (gotANumber1 && gotANumber2 && (gotAContainer || gotAString || gotASuperString))
            {
                int index1 = N1.IntValue();
                int index2 = N2.IntValue();
 
                if (index1 < 0 || index2 < 0)
                {
                    std::stringstream ss;
                    ss << "subseq requires a positive range, received: " << index1 << " and " << index2;
                    return Error(ss.str());
                }

                if (gotAContainer)
                {
                    if (C.NumberOfElements() <= index1 && C.NumberOfElements() <= index2)
                    {
                         return Container();
                    }

                    std::vector<Element> elements;
                    C.RetrieveVector(elements);
                    elements.assign(elements.begin() + N1.IntValue(), elements.begin() + N2.IntValue());
                    Container out;
                    out.SetVector(elements);
                    return out;
                }
                if (gotAString)
                {
                    std::string value = S.Value();
                    if (index1 >= static_cast<int>(value.size()))
                    {
                         return String("");
                    }

                    value = value.substr(N1.IntValue(), N2.IntValue());
                    return String(value);
                }

                if (gotASuperString)
                {
                    StringHolder temp = SS.GetStringHolder();
                    return SuperString(StringHolder(temp, N1.IntValue(), N2.IntValue()));
                }

                return Error("Something unexpected happened in subseq");
            }
            else
            {
                std::stringstream ss;
                ss << "subseq requires 3 arguments, a container/string and start/end numeric values.\n"
                   << "Received: " << parms[0].ToString() << ", " << parms[1].ToString() << ", " << parms[2].ToString();
                return Error(ss.str());
            }
        }
Example #11
0
void Visitor::Visit(Element const& element)
{
    bool isElement = false;
    switch(element.Type())
    {
        // Constant Tokens
        case Types::NIL: VisitNil(); break;
        case Types::TRUE_: VisitTrue(); break; 
        case Types::FALSE_: VisitFalse(); break; 
        case Types::STRING:
        {
            String S = CastToString(element, isElement);
            VisitString(S);
        }
            break;
        case Types::SUPERSTRING:
        {
            SuperString S = CastToSuperString(element, isElement);
            VisitSuperString(S);
        }
            break;
        case Types::NUMBER:
        {
            Number N = CastToNumber(element, isElement);
            VisitNumber(N);
        }
            break;
        case Types::CONTAINER:
        {
            Container C = CastToContainer(element, isElement);
            VisitContainer(C);
        }
            break;
        case Types::BUILTIN:
        {
            Builtin B = CastToBuiltin(element, isElement);
            VisitBuiltin(B);
        }
            break;
        case Types::CALL:
        {
            Funcall F = CastToFuncall(element, isElement);
            VisitCall(F);
        }
            break;
        case Types::FUNCTION:
        {
            Function F = CastToFunction(element, isElement);
            VisitFunction(F);
        }
            break;
        case Types::IF:
        {
            If F = CastToIf(element, isElement);
            VisitIf(F);
        }
            break;
        case Types::SET:
        {
            Set F = CastToSet(element, isElement);
            VisitSet(F);
        }
            break;
        case Types::IMPERATIVE:
        {
            Imperative F = CastToImperative(element, isElement);
            VisitImperative(F);
        }
        case Types::CASE:
        {
            Case C = CastToCase(element, isElement);
            VisitCase(C);
        }
            break;
    };
}