예제 #1
0
void LispLocalSymbols(LispEnvironment& aEnvironment, LispInt aStackTop)
{
    LispInt nrArguments = InternalListLength(ARGUMENT(0));

    LispInt nrSymbols = nrArguments-2;

    std::vector<const LispString*> names(nrSymbols);
    std::vector<const LispString*> localnames(nrSymbols);

    LispInt uniquenumber = aEnvironment.GetUniqueId();
    LispInt i;
    for (i=0;i<nrSymbols;i++)
    {
        const LispString* atomname = Argument(ARGUMENT(0), i+1)->String();
        CheckArg(atomname, i + 1, aEnvironment, aStackTop);
        names[i] = atomname;

        std::string newname = "$";
        newname.append(*atomname);
        newname.append(std::to_string(uniquenumber));
        localnames[i] = aEnvironment.HashTable().LookUp(newname);
    }

    LocalSymbolBehaviour behaviour(aEnvironment, std::move(names), std::move(localnames));
    LispPtr result;
    InternalSubstitute(result, Argument(ARGUMENT(0), nrArguments-1), behaviour);

    InternalEval(aEnvironment, RESULT, result);
}
예제 #2
0
bool MatchNumber::ArgumentMatches(LispEnvironment& aEnvironment,
                                       LispPtr& aExpression,
                                       LispPtr* arguments) const
{
    if (aExpression->Number(aEnvironment.Precision()))
        return iNumber->Equals(*aExpression->Number(aEnvironment.Precision()));

    return false;
}
예제 #3
0
void ParseExpression(LispPtr& aResult, const LispChar* aString,LispEnvironment& aEnvironment)
{
    LispString full(aString);
    full.push_back(';');
    StringInput input(full,aEnvironment.iInputStatus);
    aEnvironment.iInputStatus.SetTo("String");
    LispTokenizer &tok = *aEnvironment.iCurrentTokenizer;
    InfixParser parser(tok,
                       input,
                       aEnvironment,
                       aEnvironment.PreFix(),
                       aEnvironment.InFix(),
                       aEnvironment.PostFix(),
                       aEnvironment.Bodied());
    parser.Parse(aResult);
}
예제 #4
0
void InternalUse(LispEnvironment& aEnvironment, const std::string& aFileName)
{
    LispDefFile* def = aEnvironment.DefFiles().File(aFileName);
    if (!def->IsLoaded())
    {
        def->SetLoaded();

        for (const LispString* s: def->symbols)
            aEnvironment.UnProtect(s);

        InternalLoad(aEnvironment,aFileName);

        for (const LispString* s: def->symbols)
            aEnvironment.Protect(s);
    }
}
예제 #5
0
void YacasPatternPredicateBase::SetPatternVariables(LispEnvironment& aEnvironment,
                                                    LispPtr* arguments)
{
    const std::size_t n = iVariables.size();
    for (std::size_t i = 0; i < n; ++i)
        aEnvironment.NewLocal(iVariables[i],arguments[i]);
}
예제 #6
0
void PrintExpression(LispString& aResult,
                     LispPtr& aExpression,
                     LispEnvironment& aEnvironment,
                     std::size_t aMaxChars)
{
    std::ostringstream stream;
    InfixPrinter infixprinter(aEnvironment.PreFix(),
                              aEnvironment.InFix(),
                              aEnvironment.PostFix(),
                              aEnvironment.Bodied());
    infixprinter.Print(aExpression, stream, aEnvironment);
    aResult.assign(stream.str());
    if (aMaxChars > 0 && aResult.size()>aMaxChars)
    {
        aResult.resize(aMaxChars - 3);
        aResult += "...";
    }
}
예제 #7
0
void InternalEvalString(LispEnvironment& aEnvironment, LispPtr& aResult,
                        const LispChar* aString)
{
    LispString full(aString);
    full.push_back(';');
    StringInput input(full,aEnvironment.iInputStatus);
    LispPtr lispexpr;
    LispTokenizer &tok = *aEnvironment.iCurrentTokenizer;
    InfixParser parser(tok, input,
                       aEnvironment,
                       aEnvironment.PreFix(),
                       aEnvironment.InFix(),
                       aEnvironment.PostFix(),
                       aEnvironment.Bodied());
    parser.Parse(lispexpr);

    aEnvironment.iEvaluator->Eval(aEnvironment, aResult, lispexpr);
}
예제 #8
0
static void DoLoadDefFile(
    LispEnvironment& aEnvironment,
    LispInput* aInput,
    LispDefFile* def)
{
  LispLocalInput localInput(aEnvironment, aInput);

  const LispString* eof = aEnvironment.iEndOfFile->String();
  const LispString* end = aEnvironment.iListClose->String();

  bool endoffile = false;

  LispTokenizer tok;

  while (!endoffile)
  {
    // Read expression
    const LispString* token =
        tok.NextToken(*aEnvironment.CurrentInput(), aEnvironment.HashTable());

    // Check for end of file
    if (token == eof || token == end)
    {
      endoffile = true;
    }
    // Else evaluate
    else
    {
        LispMultiUserFunction* multiUser = aEnvironment.MultiUserFunction(token);

        if (multiUser->iFileToOpen != nullptr) {
            aEnvironment.CurrentOutput() << '[' << *token << "]\n";
            if (multiUser->iFileToOpen)
               throw LispErrDefFileAlreadyChosen();
        }

        multiUser->iFileToOpen = def;

        def->symbols.insert(token);

        aEnvironment.Protect(token);
    }
  }
}
예제 #9
0
void LispDebugFile(LispEnvironment& aEnvironment, LispInt aStackTop)
{
#ifndef YACAS_DEBUG
    throw LispErrGeneric("Cannot call DebugFile in non-debug version of Yacas");
#else
  const LispChar * file = ARGUMENT(1)->iFileName;
  if (!file) file = "";
  LispString * str = aEnvironment.HashTable().LookUpStringify(file);
  RESULT = LispAtom::New(aEnvironment, *str);
#endif
}
예제 #10
0
void InternalApplyPure(LispPtr& oper,LispPtr& args2,LispPtr& aResult,LispEnvironment& aEnvironment)
{
    LispPtr * chk1 = oper->SubList();

    if (!chk1)
        throw LispErrInvalidArg();

    LispPtr oper2((*chk1)->Nixed());

    if (!oper2)
        throw LispErrInvalidArg();

    LispPtr body(oper2->Nixed());

    if (!body)
        throw LispErrInvalidArg();

    LispPtr * chk2 = oper2->SubList();

    if (!chk2 || !*chk2)
        throw LispErrInvalidArg();

    oper2 = ((*chk2)->Nixed());

    LispLocalFrame frame(aEnvironment,false);

    while (!!oper2)  {
        if (!args2)
            throw LispErrInvalidArg();

        const LispString* var = oper2->String();

        if (!var)
            throw LispErrInvalidArg();

        LispPtr newly(args2->Copy());

        aEnvironment.NewLocal(var,newly);

        oper2 = (oper2->Nixed());

        args2 = (args2->Nixed());
    }

    if (args2)
        throw LispErrInvalidArg();

    aEnvironment.iEvaluator->Eval(aEnvironment, aResult, body);
}
예제 #11
0
void LoadDefFile(LispEnvironment& aEnvironment, const std::string& aFileName)
{
  const std::string flatfile = InternalUnstringify(aFileName) + ".def";
  LispDefFile* def = aEnvironment.DefFiles().File(aFileName);

  InputStatus oldstatus = aEnvironment.iInputStatus;
  aEnvironment.iInputStatus.SetTo(flatfile);

  LispLocalFile localFP(aEnvironment, flatfile, true,
                        aEnvironment.iInputDirectories);
  if (!localFP.stream.is_open())
    throw LispErrFileNotFound();

  StdFileInput newInput(localFP,aEnvironment.iInputStatus);
  DoLoadDefFile(aEnvironment, &newInput,def);

  aEnvironment.iInputStatus.RestoreFrom(oldstatus);
}
예제 #12
0
void DoInternalLoad(LispEnvironment& aEnvironment,LispInput* aInput)
{
    LispLocalInput localInput(aEnvironment, aInput);

    // TODO make "EndOfFile" a global thing
    // read-parse-eval to the end of file
    const LispString* eof = aEnvironment.HashTable().LookUp("EndOfFile");
    bool endoffile = false;

    LispTokenizer tok;
    InfixParser parser(tok,
                       *aEnvironment.CurrentInput(),
                       aEnvironment,
                       aEnvironment.PreFix(),
                       aEnvironment.InFix(),
                       aEnvironment.PostFix(),
                       aEnvironment.Bodied());

    while (!endoffile)
    {
        LispPtr readIn;
        // Read expression
        parser.Parse(readIn);

        if (!readIn)
            throw LispErrReadingFile();

        // Check for end of file
        if (readIn->String() == eof)
        {
            endoffile = true;
            }
        // Else evaluate
        else
        {
            LispPtr result;
            aEnvironment.iEvaluator->Eval(aEnvironment, result, readIn);
        }
    }
}
예제 #13
0
bool InternalEquals(const LispEnvironment& aEnvironment,
                    const LispPtr& aExpression1,
                    const LispPtr& aExpression2)
{
    // Handle pointers to same, or nullptr
    if (aExpression1.ptr() == aExpression2.ptr())  // compare pointers to LispObject
        return true;

    if (!aExpression1.ptr() || !aExpression2.ptr())
        return false;

/*TODO This code would be better, if BigNumber::Equals works*/

    BigNumber *n1 = aExpression1->Number(aEnvironment.Precision());
    BigNumber *n2 = aExpression2->Number(aEnvironment.Precision());
    if (!(!n1 && !n2) )
    {
        if (n1 == n2)
        {
            return true;
        }
        if (!n1) return false;
        if (!n2) return false;
        if (n1->Equals(*n2)) return true;
//this should be enabled
        return false;
    }


    //Pointers to strings should be the same
    if (aExpression1->String() != aExpression2->String())
    {
        return false;
    }

    // Handle same sublists, or nullptr
    if (aExpression1->SubList() == aExpression2->SubList())
    {
        return true;
    }

    // Now check the sublists
    if (aExpression1->SubList())
    {
        if (!aExpression2->SubList())
        {
            return false;
        }
        LispIterator iter1(*aExpression1->SubList());
        LispIterator iter2(*aExpression2->SubList());

        while (iter1.getObj() && iter2.getObj())
        {
            // compare two list elements
            if (!InternalEquals(aEnvironment, *iter1, *iter2))
            {
                return false;
            }

            // Step to next
            ++iter1;
            ++iter2;
        }
        // Lists don't have the same length
        if (iter1.getObj() != iter2.getObj())
            return false;

        // Same!
        return true;
    }

    // expressions sublists are not the same!
    return false;
}
예제 #14
0
bool InternalStrictTotalOrder(
    const LispEnvironment& env,
    const LispPtr& e1,
    const LispPtr& e2)
{
    if (e1.ptr() == e2.ptr())
        return false;

    if (!e1.ptr() && e2.ptr())
        return true;
    
    if (e1.ptr() && !e2.ptr())
        return false;
    
    BigNumber* n1 = e1->Number(env.Precision());
    BigNumber* n2 = e2->Number(env.Precision());
    
    if (n1 && !n2)
        return true;
    
    if (!n1 && n2)
        return false;
    
    if (n1 && n2) {
        if (n1->LessThan(*n2))
            return true;
        
        if (!n1->Equals(*n2))
            return false;
        
        return InternalStrictTotalOrder(env, e1->Nixed(), e2->Nixed());
    }
    
    const LispString* s1 = e1->String();
    const LispString* s2 = e2->String();
    
    if (s1 && !s2)
        return true;
    
    if (!s1 && s2)
        return false;
    
    if (s1 && s2) {
        const int c = s1->compare(*s2);

        if (c)
            return c < 0;
        
        return InternalStrictTotalOrder(env, e1->Nixed(), e2->Nixed());
    }
    
    LispPtr* l1 = e1->SubList();
    LispPtr* l2 = e2->SubList();
    
    if (!l1 && l2)
        return true;
    
    if (l1 && !l2)
        return false;

    if (l1 && l2) {
        LispIterator i1(*l1);
        LispIterator i2(*l2);
        
        while (i1.getObj() && i2.getObj()) {
            const LispPtr& p1 = *i1;
            const LispPtr& p2 = *i2;
            
            if (InternalEquals(env, p1, p2)) {
                ++i1;
                ++i2;
                
                continue;
            }
            
            return InternalStrictTotalOrder(env, p1, p2);
        }
        
        if (i1.getObj())
            return false;
        
        if (i2.getObj())
            return true;

        return false;
    }

    // FIXME: deal with generics
//    GenericClass* g1 = e1->Generic();
//    GenericClass* g2 = e2->Generic();
//
    return false;
}
예제 #15
0
void BranchingUserFunction::Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment,
                                     LispPtr& aArguments)
{
    const LispInt arity = Arity();
    LispInt i;

    if (Traced()) {
        LispPtr tr(LispSubList::New(aArguments));
        TraceShowEnter(aEnvironment, tr);
        tr = nullptr;
    }

    LispIterator iter(aArguments);
    ++iter;

    // unrollable arguments
    std::unique_ptr<LispPtr[]> arguments(arity == 0 ? nullptr : new LispPtr[arity]);

    // Walk over all arguments, evaluating them as necessary
    for (i = 0; i < arity; i++, ++iter) {
        if (!iter.getObj())
            throw LispErrWrongNumberOfArgs();

        if (iParameters[i].iHold) {
            arguments[i] = iter.getObj()->Copy();
        } else {
            //Check(iter.getObj(), KLispErrWrongNumberOfArgs);  // checked above
            InternalEval(aEnvironment, arguments[i], *iter);
        }
    }

    if (Traced()) {
        LispIterator iter(aArguments);
        for (i = 0; i < arity; i++)
            TraceShowArg(aEnvironment, *++iter, arguments[i]);
    }

    // declare a new local stack.
    LispLocalFrame frame(aEnvironment, Fenced());

    // define the local variables.
    for (i = 0; i < arity; i++) {
        const LispString* variable = iParameters[i].iParameter;
        // set the variable to the new value
        aEnvironment.NewLocal(variable, arguments[i]);
    }

    // walk the rules database, returning the evaluated result if the
    // predicate is true.
    const std::size_t nrRules = iRules.size();
    UserStackInformation &st = aEnvironment.iEvaluator->StackInformation();
    for (std::size_t i = 0; i < nrRules; i++) {
        BranchRuleBase* thisRule = iRules[i];
        assert(thisRule);

        st.iRulePrecedence = thisRule->Precedence();
        bool matches = thisRule->Matches(aEnvironment, arguments.get());
        if (matches) {
            st.iSide = 1;
            InternalEval(aEnvironment, aResult, thisRule->Body());
            goto FINISH;
        }

        // If rules got inserted, walk back
        while (thisRule != iRules[i] && i > 0)
            i--;
    }

    // No predicate was true: return a new expression with the evaluated
    // arguments.

    {
        LispPtr full(aArguments->Copy());
        if (arity == 0) {
            full->Nixed() = nullptr;
        } else {
            full->Nixed() = arguments[0];
            for (i = 0; i < arity - 1; i++)
                arguments[i]->Nixed() = arguments[i + 1];
        }
        aResult = LispSubList::New(full);
    }

FINISH:
    if (Traced()) {
        LispPtr tr(LispSubList::New(aArguments));
        TraceShowLeave(aEnvironment, aResult, tr);
        tr = nullptr;
    }
}