

/* This is the basic initialization file for Yacas. It gets loaded
 * each time Yacas is started. All the basic files are loaded.
 */

/* Set up drivers, configurable in the .yacasrc
 *   Set(MultiNomialDriver,"multivar.rep/sparsenomial.ys");
 *     or
 *   Set(MultiNomialDriver,"multivar.rep/partialdensenomial.ys");
 */

/* The truly required files (Yacas NEEDS to load). */
// syntax must be loaded first
Use("stdopers.ys");

/* Set of functions to define very simple functions. There are scripts that can
   be compiled to plugins. So Yacas either loads the plugin, or loads the
   scripts at this point. The functions in these plugins need to be defined with
   these "Defun" functions.
 */
DefMacroRuleBase("Defun",{func,args,body});
Rule("Defun",3,0,True)
[
  Local(nrargs);
  Set(nrargs,Length(@args));
  Retract(@func, `(@nrargs));
  RuleBase(@func,@args);
  Local(fn,bd);
  Set(fn,Hold(@func)); Set(bd,Hold(@body));
  `Rule(@fn, @nrargs, 0,True)(@bd);
];

//TODO remove? Use("base.rep/math.ys");

Use("patterns.rep/code.ys");
// at this point <-- can be used

Use("deffunc.rep/code.ys");

// at this point := and Function() can be used

Use("constants.rep/code.ys");
Use("standard.ys");
Use("stdarith.ys");

// at this point arithmetic can be used

/* Load the def files for the other modules. The def files contain lists
 * of functions defined in that file. So, in solve.def you can find the
 * functions defined in the file solve. Each time a function is invoked
 * for which the interpreter can not find a definition, the file is loaded.
 */

RuleBase(LoadPackages,{packages});
Rule(LoadPackages, 1, 1, True)
[
    If(Equals(packages,{}), True,
    [
        DefLoad(Head(packages));
        LoadPackages(Tail(packages));
    ]);
];

Use("packages.ys");
LoadPackages(DefFileList());

LocalSymbols(input, output) [
  input := {};
  output := {};

  RuleBase("Input'Append", {e});
  Rule("Input'Append", 1, 0, True) [
    DestructiveAppend(input, e);
  ];

  RuleBase("Input", {i});
  Rule("Input", 1, 0, IsInteger(i) And i > 0) [
    Check(i <= Length(input), "Input: wrong argument");
    input[i];
  ];

  Rule("Input", 1, 0, IsInteger(i) And i <= 0) [
    Echo(-i, Length(input), -i < Length(input));
    Check(-i < Length(input), "Input: wrong argument");
    input[Length(input) + i];
  ];

  RuleBase("Output'Append", {e});
  Rule("Output'Append", 1, 0, True) [
    DestructiveAppend(output, e);
  ];

  RuleBase("Output", {i});
  Rule("Output", 1, 0, IsInteger(i) And i > 0) [
    Check(i <= Length(output), "Output: wrong argument");
    output[i];
  ];

  Rule("Output", 1, 0, IsInteger(i) And i <= 0) [
    Echo(-i, Length(output), -i < Length(output));
    Check(-i < Length(output), "Output: wrong argument");
    output[Length(output) + i];
  ];
];

/* The read-eval-print loop */
RuleBase("REP",{});
LocalSymbols(input,stringOut,result,errorString)
Rule("REP",0,1,True)
[
  Local(input,stringOut,result,inprompt,outprompt);
  While(Not(IsExitRequested()))
  [
    inprompt := If (IsPromptShown(), "In> ", "");
    outprompt := If (IsPromptShown(), "Out> ", "");

    Set(errorString, "");
    If(And(IsString(PrettyReader'Get()),Not(PrettyReader'Get() = "")),
      TrapError(Set(input, FromString(ReadCmdLineString(inprompt))ApplyPure(PrettyReader'Get(),{})),Set(errorString,GetCoreError())),
      TrapError(Set(input, FromString(ConcatStrings(ReadCmdLineString(inprompt),";"))Read()),Set(errorString,GetCoreError())));
    If(Not(errorString = ""), WriteString(errorString));
    If (Not(IsExitRequested()) And errorString="",
    [
      Set(stringOut,"");
      Set(result,False);
      Set(stringOut,ToString()[TrapError(Set(result,Eval(input)),Set(errorString,GetCoreError()));]);
      If(Not(stringOut = ""), WriteString(stringOut));
      If(Not(errorString = ""), WriteString(errorString));
      UnProtect(%);
      SetGlobalLazyVariable(%,result);
      Protect(%);
      Input'Append(input);
      Output'Append(result);
      If(PrettyPrinter'Get()="",
      [
        Write(Atom(outprompt),result);
        NewLine();
      ],
      Apply(PrettyPrinter'Get(),{result}));
    ]);
  ];
];

