<commit_before>// \file standard.cpp
// Implementation of some standard lisp operations
//
#include "yacas/yacasprivate.h"
#include "yacas/standard.h"
#include "yacas/lispatom.h"
#include "yacas/lisperror.h"
#include "yacas/lispenvironment.h"

#include "yacas/lispio.h"
#include "yacas/platfileio.h"
#include "yacas/lispenvironment.h"
#include "yacas/tokenizer.h"
#include "yacas/infixparser.h"
#include "yacas/lispeval.h"
#include "yacas/stringio.h"
#include "yacas/numbers.h"

bool InternalIsList(const LispPtr& aPtr)
{
    if (!aPtr)
        return false;
    if (!aPtr->SubList())
        return false;
    if (!(*aPtr->SubList()))
        return false;
    // The following happens with IsList(UnList({foo(x), a, b}))
    if ((*aPtr->SubList())->String()->c_str() == nullptr)
        return false;
    //TODO this StrEqual is far from perfect. We could pass in a LispEnvironment object...
    if (std::strcmp((*aPtr->SubList())->String()->c_str(), "List"))
        return false;
    return true;
}


bool InternalIsString(LispString * aOriginal)
{
    if (aOriginal)
        if ((*aOriginal)[0] == '\"')
            if ((*aOriginal)[aOriginal->size()-1] == '\"')
                return true;
    return false;
}


/* TODO: in documenting the choices made in the C++ engine, perhaps document why I pass objects that should contain the
   result by reference. Result string passed in by reference to avoid copy-constructors etcetera (allowing
   the code to share the same LispString in different places).
 */
void InternalUnstringify(LispString& aResult, const LispString * aOriginal)
{
  /*TODO: should these not be checked also higher up, and should this not be an assert at this level?
   * ideally this function should be as efficient as possible (allowing for a code generator to generate
   * compiled code that calls this function immediately. The compiler could prove that the input is valid,
   * so the checks would not be needed here in a non-debug run).
   *
   * Also do not forget to make the change in the Java version then, and find the other places where this is relevant.
   */
    if (!aOriginal || (*aOriginal)[0] != '\"')
        throw LispErrInvalidArg();

  LispInt nrc = aOriginal->size()-1;

  if (!aOriginal || (*aOriginal)[nrc] != '\"')
      throw LispErrInvalidArg();

  aResult.resize(nrc);
  for (LispInt i = 1; i < nrc; i++)
    aResult[i-1] = (*aOriginal)[i];
}

void InternalStringify(LispString& aResult, const LispString* aOriginal)
{
    if (!aOriginal)
        throw LispErrInvalidArg();

    LispInt nrc=aOriginal->size()-1;
    aResult.resize(nrc+3);
    LispInt i;
    aResult[0] = '\"';
    for (i=0;i<nrc;i++)
        aResult[i+1] = (*aOriginal)[i];
    aResult[nrc+1] = '\"';
    aResult[nrc+2] = '\0';
}

void InternalIntToAscii(LispChar * aTrg,LispInt aInt)
{<commit_msg>adjustments to correct string semantics<commit_after>// \file standard.cpp
// Implementation of some standard lisp operations
//
#include "yacas/yacasprivate.h"
#include "yacas/standard.h"
#include "yacas/lispatom.h"
#include "yacas/lisperror.h"
#include "yacas/lispenvironment.h"

#include "yacas/lispio.h"
#include "yacas/platfileio.h"
#include "yacas/lispenvironment.h"
#include "yacas/tokenizer.h"
#include "yacas/infixparser.h"
#include "yacas/lispeval.h"
#include "yacas/stringio.h"
#include "yacas/numbers.h"

bool InternalIsList(const LispPtr& aPtr)
{
    if (!aPtr)
        return false;
    if (!aPtr->SubList())
        return false;
    if (!(*aPtr->SubList()))
        return false;
    // The following happens with IsList(UnList({foo(x), a, b}))
    if ((*aPtr->SubList())->String()->c_str() == nullptr)
        return false;
    //TODO this StrEqual is far from perfect. We could pass in a LispEnvironment object...
    if (std::strcmp((*aPtr->SubList())->String()->c_str(), "List"))
        return false;
    return true;
}


bool InternalIsString(LispString * aOriginal)
{
    if (aOriginal)
        if ((*aOriginal)[0] == '\"')
            if ((*aOriginal)[aOriginal->size()-1] == '\"')
                return true;
    return false;
}


/* TODO: in documenting the choices made in the C++ engine, perhaps document why I pass objects that should contain the
   result by reference. Result string passed in by reference to avoid copy-constructors etcetera (allowing
   the code to share the same LispString in different places).
 */
void InternalUnstringify(LispString& aResult, const LispString * aOriginal)
{
  /*TODO: should these not be checked also higher up, and should this not be an assert at this level?
   * ideally this function should be as efficient as possible (allowing for a code generator to generate
   * compiled code that calls this function immediately. The compiler could prove that the input is valid,
   * so the checks would not be needed here in a non-debug run).
   *
   * Also do not forget to make the change in the Java version then, and find the other places where this is relevant.
   */
    if (!aOriginal || aOriginal->size() < 2 || aOriginal->front() != '\"' || aOriginal->back() != '\"')
        throw LispErrInvalidArg();

    aResult.assign(aOriginal->c_str() + 1, aOriginal->size() - 2);
}

void InternalStringify(LispString& aResult, const LispString* aOriginal)
{
    if (!aOriginal)
        throw LispErrInvalidArg();

    LispInt nrc=aOriginal->size()-1;
    aResult.resize(nrc+3);
    LispInt i;
    aResult[0] = '\"';
    for (i=0;i<nrc;i++)
        aResult[i+1] = (*aOriginal)[i];
    aResult[nrc+1] = '\"';
    aResult[nrc+2] = '\0';
}

void InternalIntToAscii(LispChar * aTrg,LispInt aInt)
{
{'fraction_non_alphanumeric': 0.1367873789888849, 'fraction_numerical': 0.004840444603800645, 'mean_word_length': 3.459632294164668, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6565114', 'n_tokens_mistral': 1875, 'n_tokens_neox': 1834, 'n_words': 557}