Пример #1
0
        public void Can_import_into_global_symbols()
        {
            var SExprs = Lisp.Parse("(fib 10)");

            var lispCtx = Lisp.CreateInterpreter();

            try
            {
                lispCtx.Eval(SExprs);
                Assert.Fail("should throw");
            }
            catch (LispEvalException e) {}

            Lisp.Import(@"
(defun fib (n)
  (if (< n 2)
      1
    (+ (fib (- n 1))
       (fib (- n 2)) )
  ))
");
            lispCtx = Lisp.CreateInterpreter();

            Assert.That(lispCtx.Eval(SExprs), Is.EqualTo(89));

            Lisp.Reset();

            lispCtx = Lisp.CreateInterpreter();
            try
            {
                lispCtx.Eval(SExprs);
                Assert.Fail("should throw");
            }
            catch (LispEvalException e) {}
        }
Пример #2
0
        public void Can_eval_fib_lisp()
        {
            var lisp = @"
(defun fib (n)
  (if (< n 2)
      1
    (+ (fib (- n 1))
       (fib (- n 2)) )
  ))
";

            try
            {
                var lispCtx = Lisp.CreateInterpreter();

                var sExpressions = Lisp.Parse(lisp);
                var x            = lispCtx.Eval(sExpressions);
                $"{x}".Print();

                sExpressions = Lisp.Parse("(fib 15)");
                x            = lispCtx.Eval(sExpressions);

                $"{x}".Print();
                Assert.That((int)x, Is.EqualTo(987));
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
Пример #3
0
        public void Can_min_max_int_long_double_values()
        {
            var lispCtx = Lisp.CreateInterpreter();

            Assert.That((int)lispCtx.Eval(Lisp.Parse("(min 1 2)")), Is.EqualTo(1));
            Assert.That((int)lispCtx.Eval(Lisp.Parse("(max 1 2)")), Is.EqualTo(2));

            Assert.That((double)lispCtx.Eval(Lisp.Parse("(min 1.0 2.0)")), Is.EqualTo(1.0));
            Assert.That((double)lispCtx.Eval(Lisp.Parse("(max 1.0 2.0)")), Is.EqualTo(2.0));

            Assert.That((long)lispCtx.Eval(Lisp.Parse($"(min {int.MaxValue + 1L} {int.MaxValue + 2L})")), Is.EqualTo(int.MaxValue + 1L));
            Assert.That((long)lispCtx.Eval(Lisp.Parse($"(max {int.MaxValue + 1L} {int.MaxValue + 2L})")), Is.EqualTo(int.MaxValue + 2L));
        }
Пример #4
0
        private void HandleConnection(TcpClient client, int id, string remoteIp)
        {
            try
            {
                using (client)
                {
                    var interp = Lisp.CreateInterpreter();

                    var CMD_CLEAR     = "\u001B[2J";
                    var sb            = new StringBuilder();
                    var networkStream = client.GetStream();
                    var remoteUrl     = $"tcp://{remoteIp}";
                    void write(string msg) => MemoryProvider.Instance.Write(networkStream, msg.AsMemory());

                    using (var reader = new StreamReader(networkStream, Encoding.UTF8))
                    {
                        string line;
                        if (RequireAuthSecret)
                        {
                            MemoryProvider.Instance.Write(networkStream,
                                                          $"Authentication required:\n> ".AsMemory());

                            line = reader.ReadLine();
                            var authSuccess = !string.IsNullOrEmpty(line) && line == HostContext.Config.AdminAuthSecret;
                            if (!authSuccess)
                            {
                                write($"Authentication failed.\n\n");
                                client.Close();
                                return;
                            }

                            write(CMD_CLEAR);
                        }

                        MemoryProvider.Instance.Write(networkStream,
                                                      $"\nWelcome to #Script Lisp! The Server time is: {DateTime.Now.ToShortTimeString()}, type ? for help.\n\n".AsMemory());

                        while (true)
                        {
                            if (listener == null)
                            {
                                return;
                            }
prompt:
                            write("> ");

                            sb.Clear();

                            while ((line = reader.ReadLine()) != null)
                            {
                                if (line == "quit" || line == "exit")
                                {
                                    write($"Goodbye.\n\n");
                                    client.Close();
                                    return;
                                }
                                if (line == "verbose")
                                {
                                    var toggle = interp.GetSymbolValue("verbose") is bool v && v
                                        ? null
                                        : Lisp.TRUE;

                                    interp.SetSymbolValue("verbose", toggle);
                                    var mode = toggle != null ? "on" : "off";
                                    write($"verbose mode {mode}\n\n");
                                    goto prompt;
                                }
                                if (line == "mode")
                                {
                                    var toggle = interp.GetSymbolValue("multi-line") is bool v && v
                                        ? null
                                        : Lisp.TRUE;

                                    interp.SetSymbolValue("multi-line", toggle);
                                    var mode = toggle != null ? "off" : "on";
                                    write($"single-line mode {mode}\n\n");
                                    goto prompt;
                                }
                                if (line == "clear")
                                {
                                    write(CMD_CLEAR);
                                    goto prompt;
                                }
                                if (line == "?")
                                {
                                    var usage = @"
 ; verbose - toggle output to indent complex responses
 ; mode    - toggle between single and multi-line modes 
 ; clear   - clear screen
 ; quit    - exit session

Learn more about #Script Lisp at: https://sharpscript.net/lisp

";
                                    write(usage);
                                    goto prompt;
                                }

                                sb.AppendLine(line);

                                var multiLine = interp.GetSymbolValue("multi-line");
                                if (multiLine == null || multiLine is bool b && !b)
                                {
                                    break;
                                }

                                if (line == "") // evaluate on empty new line
                                {
                                    break;
                                }
                            }

                            var lisp = sb.ToString();
                            if (lisp.Trim().Length == 0)
                            {
                                continue;
                            }

                            string output = null;
                            try
                            {
                                var requestArgs = CreateBasicRequest(remoteUrl);
                                output = interp.ReplEval(ScriptContext, networkStream, lisp, requestArgs);
                            }
                            catch (Exception e)
                            {
                                var str = (e.InnerException ?? e) + "\n";
                                MemoryProvider.Instance.Write(networkStream, str.AsMemory());
                            }

                            if (!string.IsNullOrEmpty(output))
                            {
                                MemoryProvider.Instance.Write(networkStream, output.AsMemory());
                                MemoryProvider.Instance.Write(networkStream, "\n\n".AsMemory());
                                networkStream.Flush();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"{remoteIp} connection was disconnected. " + ex.Message);
                }
            }
        }
Пример #5
0
        public void Can_eval_lisp_in_lisp()
        {
            var lisp = @"
;;; A circular Lisp interpreter in Common/Emacs/Nukata Lisp
;;;    by SUZUKI Hisao on H28.8/10, H29.3/13
;;;    cf. Zick Standard Lisp (https://github.com/zick/ZickStandardLisp)

(progn
  ;; Expr: (EXPR environment (symbol...) expression...)
  ;; Subr: (SUBR . function)
  ;; Environment: ((symbol . value)...)
  ;; N.B. Expr has its own environment since this Lisp is lexically scoped.

  ;; Language-specific Hacks
  (setq funcall (lambda (f x) (f x)))  ; for Nukata Lisp and this Lisp
  (setq max-lisp-eval-depth 10000)     ; for Emacs Lisp
  (setq max-specpdl-size 7000)         ; for Emacs Lisp

  ;; The global environment of this Lisp
  (setq global-env
        (list '(*version* . (1.2 ""Lisp"" ""circlisp""))
              (cons 'car
                    (cons 'SUBR (lambda (x) (car (car x)))))
              (cons 'cdr
                    (cons 'SUBR (lambda (x) (cdr (car x)))))
              (cons 'cons
                    (cons 'SUBR (lambda (x) (cons (car x) (cadr% x)))))
              (cons 'eq
                    (cons 'SUBR (lambda (x) (eq (car x) (cadr% x)))))
              (cons 'atom
                    (cons 'SUBR (lambda (x) (atom (car x)))))
              (cons 'rplaca
                    (cons 'SUBR (lambda (x) (rplaca (car x) (cadr% x)))))
              (cons 'rplacd
                    (cons 'SUBR (lambda (x) (rplacd (car x) (cadr% x)))))
              (cons 'list
                    (cons 'SUBR (lambda (x) x)))
              (cons '+
                    (cons 'SUBR (lambda (x) (+ (car x) (cadr% x)))))
              (cons '*
                    (cons 'SUBR (lambda (x) (* (car x) (cadr% x)))))
              (cons '-
                    (cons 'SUBR (lambda (x) (- (car x) (cadr% x)))))
              (cons 'truncate
                    (cons 'SUBR (lambda (x) (truncate (car x) (cadr% x)))))
              (cons 'mod
                    (cons 'SUBR (lambda (x) (mod (car x) (cadr% x)))))
              (cons '=
                    (cons 'SUBR (lambda (x) (= (car x) (cadr% x)))))
              (cons '<
                    (cons 'SUBR (lambda (x) (< (car x) (cadr% x)))))
              (cons 'print
                    (cons 'SUBR (lambda (x) (print (car x)))))
              (cons 'apply
                    (cons 'SUBR (lambda (x) (apply% (car x) (cadr% x)))))
              (cons 'eval
                    (cons 'SUBR (lambda (x) (eval% (car x) global-env))))))

  (defun caar% (x) (car (car x)))
  (defun cadr% (x) (car (cdr x)))
  (defun cddr% (x) (cdr (cdr x)))
  (defun caddr% (x) (car (cdr (cdr x))))
  (defun cdddr% (x) (cdr (cdr (cdr x))))
  (defun cadddr% (x) (car (cdr (cdr (cdr x)))))

  (defun assq% (key alist)              ; cf. Emacs/Nukata Lisp
    (if alist
        (if (eq key (caar% alist))
            (car alist)
          (assq% key (cdr alist)))
      nil))

  (defun pairlis% (keys data alist)     ; cf. Common Lisp
    (if keys
        (cons (cons (car keys) (car data))
              (pairlis% (cdr keys) (cdr data) alist))
      alist))

  ;; Define symbol as value in the global environment.
  (defun global-def (sym val)
    (rplacd global-env
            (cons (car global-env)
                  (cdr global-env)))
    (rplaca global-env
            (cons sym val)))

  (defun eval% (e env)
    (if (atom e)
        ((lambda (var)
           (if var
               (cdr var)
             e))
         (assq% e env))
      (if (eq (car e) 'quote)           ; (quote e)
          (cadr% e)
        (if (eq (car e) 'if)            ; (if e e e)
            (if (eval% (cadr% e) env)
                (eval% (caddr% e) env)
              (eval% (cadddr% e) env))
          (if (eq (car e) 'progn)       ; (progn e...)
              (eval-progn (cdr e) env nil)
            (if (eq (car e) 'lambda)    ; (lambda (v...) e...)
                (make-closure env (cdr e))
              (if (eq (car e) 'defun)   ; (defun f (v...) e...)
                  (global-def (cadr% e)
                              (make-closure env (cddr% e)))
                (if (eq (car e) 'setq)  ; (setq v e)
                    ((lambda (var value)
                       (if var
                           (rplacd var value)
                         (global-def (cadr% e) value))
                       value)
                     (assq% (cadr% e) env)
                     (eval% (caddr% e) env))
                  (apply% (eval% (car e) env) ; (f e...)
                          (evlis (cdr e) env))))))))))

  ;; (make-closure env '((v...) e...)) => (EXPR env (v...) e...)
  (defun make-closure (env ve)
    (cons 'EXPR
          (cons env ve)))

  ;; (eval-progn '((+ 1 2) 3 (+ 4 5)) global-env nil) => 9
  (defun eval-progn (x env result)
    (if x
        (if (cdr x)
            (eval-progn (cdr x)
                        env
                        (eval% (car x) env))
          (eval% (car x) env))
      result))

  ;; (evlis '((+ 1 2) 3 (+ 4 5)) global-env) => (3 3 9)
  (defun evlis (x env)
    (if x
        (cons (eval% (car x) env)
              (evlis (cdr x) env))
      nil))

  (defun apply% (fun arg)
    (if (eq (car fun) 'EXPR)            ; (EXPR env (v...) e...)
        (eval-progn (cdddr% fun)
                    (pairlis% (caddr% fun)
                              arg
                              (cadr% fun))
                    nil)
      (if (eq (car fun) 'SUBR)          ; (SUBR . f)
          (funcall (cdr fun) arg)
        fun)))

  (defun global-eval (e)
    (eval% e global-env))

  (global-eval (quote

;; -- WRITE YOUR EXPRESSION HERE --
(progn
  (defun fib (n)
    (if (< n 2)
        1
      (+ (fib (- n 1))
         (fib (- n 2)))))
  (print (fib 10)))
;; --------------------------------
)))
";

            try
            {
                var lispCtx = Lisp.CreateInterpreter();

                var sExpressions = Lisp.Parse(lisp);
                var x            = lispCtx.Eval(sExpressions);
                Assert.That((int)x, Is.EqualTo(89));
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }