Exemple d'implémentation d'un système de traitement LISP simple (version Ruby)

[Lien de l'article vers une autre version linguistique] Exemple d'implémentation d'un système de traitement LISP simple [Résumé de chaque version linguistique]

Cet article est un exemple d'implémentation d'un système de traitement LISP simple ("McCarthy's Original Lisp") qui utilise un extrait et une modification de la version Ruby de mon article suivant. C'est un résumé.

Dans le cas de la mise en œuvre du système de traitement LISP avec les fonctions minimales, il est très facile de mettre en œuvre l'évaluateur (eval), qui est le corps principal. Il est résumé pour ceux qui ont beaucoup de mal pour chaque langue et c'est un seuil.

Vue d'ensemble du système de traitement

L'exemple d'exécution est le suivant. Confirmé avec Ruby 2.5.5.

$ irb --simple-prompt
>> load "jmclisp.rb"
=> true
>> s_rep("(car (cdr '(10 20 30)))")
=> "20"
>> s_rep(gets.chomp)
((lambda (x) (car (cdr x))) '(abc def ghi))
=> "def"
>> s_rep("((lambda (f x y) (f x (f y '()))) 'cons '10 '20)")
=> "(10 20)"
>> s_rep("((lambda (f x y) (f x (f y '())))
          '(lambda (x y) (cons x (cons y '())))
          '10 '20)")
=> "(10 (20 ()))"
>> s_rep("((lambda (assoc k v) (assoc k v))
          '(lambda (k v)
             (cond ((eq v '()) nil)
                   ((eq (car (car v)) k)
                    (car v))
                   ('t (assoc k (cdr v)))))
          'Orange
          '((Apple . 120) (Orange . 210) (Lemmon . 180)))")
=> "(Orange . 210)"

Le contenu de la mise en œuvre est le suivant.

Pour plus de détails sur «McCarthy's Original Lisp», reportez-vous à Résumé de l'article. Puisqu'il s'agit d'une portée dynamique, l'expression lambda est utilisée à la place de letrec (Scheme) et labels (Common Lisp) dans l'exemple d'exécution.

Exemple d'implémentation

Code source complet

jmclisp.rb


####
#### JMC Lisp: defined in McCarthy's 1960 paper,
#### with S-expression input/output and basic list processing
####


#### basic list processing: cons, car, cdr, eq, atom
def cons(x, y) [x, y].freeze end
def car(s) s[0] end
def cdr(s) s[1] end
def eq(s1, s2) s1 == s2 end
def atom(s) s.is_a?(String) || eq(s, nil) || eq(s, true) || eq(s, false) end


#### S-expression input: s_read

def s_lex(s)
  for p in ['(',')','\''] do
    s = s.gsub(p, " #{p} ")
  end
  s.split
end

def s_syn(s)
  def quote(x, s)
    if s.length != 0 && s[-1] == '\'' then
      s.delete_at(-1)
      cons("quote", cons(x, nil))
    else x
    end
  end
  t = s.delete_at(-1)
  if t == ')' then
    r = nil
    while s[-1] != '(' do
      if s[-1] == '.' then
        s.delete_at(-1)
        r = cons(s_syn(s), car(r))
      else
        r = cons(s_syn(s), r)
      end
    end
    s.delete_at(-1)
    quote(r, s)
  else
    quote(t, s)
  end
end

def s_read(s) s_syn(s_lex(s)) end


#### S-expression output: s_string

def s_strcons(s)
  sa_r = s_string(car(s))
  sd = cdr(s)
  if eq(sd, nil) then sa_r
  elsif atom(sd) then "#{sa_r} . #{sd}"
  else "#{sa_r} #{s_strcons(sd)}"
  end
end

def s_string(s)
  if    eq(s, nil)   then "()"
  elsif eq(s, true)  then "t"
  elsif eq(s, false) then "nil"
  elsif atom(s) then s
  else "(#{s_strcons(s)})"
  end
end


#### JMC Lisp evaluator: s_eval

def caar(x) car(car(x)) end
def cadr(x) car(cdr(x)) end
def cadar(x) car(cdr(car(x))) end
def caddr(x) car(cdr(cdr(x))) end
def caddar(x) car(cdr(cdr(car(x)))) end

def s_null(x) eq(x, nil) end

def s_append(x, y)
  if s_null(x) then y
  else cons(car(x), s_append(cdr(x), y))
  end
end

def s_list(x, y) cons(x, cons(y, nil)) end

def s_pair(x, y)
  if s_null(x) and s_null(y) then nil
  elsif (not atom(x)) and (not atom(y))
    cons(s_list(car(x), car(y)), s_pair(cdr(x), cdr(y)))
  else nil
  end
end

def s_assoc(x, y)
  if eq(caar(y), x) then cadar(y)
  else s_assoc(x, cdr(y))
  end
end

def s_eval(e, a)
  if    eq(e, "t")   then true
  elsif eq(e, "nil") then false
  elsif atom(e) then s_assoc(e, a)
  elsif atom(car(e))
    if    eq(car(e), "quote") then cadr(e)
    elsif eq(car(e), "atom")  then atom(s_eval(cadr(e), a))
    elsif eq(car(e), "eq")    then eq(  s_eval(cadr(e), a), s_eval(caddr(e), a))
    elsif eq(car(e), "car")   then car( s_eval(cadr(e), a))
    elsif eq(car(e), "cdr")   then cdr( s_eval(cadr(e), a))
    elsif eq(car(e), "cons")  then cons(s_eval(cadr(e), a), s_eval(caddr(e), a))
    elsif eq(car(e), "cond")  then evcon(cdr(e), a)
    else s_eval(cons(s_assoc(car(e), a), cdr(e)), a)
    end
  elsif eq(caar(e), "lambda")
    s_eval(caddar(e), s_append(s_pair(cadar(e), evlis(cdr(e), a)), a))
  else print("Error")
  end
end

def evcon(c, a)
  if s_eval(caar(c), a) then s_eval(cadar(c), a)
  else evcon(cdr(c), a)
  end
end

def evlis(m, a)
  if s_null(m) then nil
  else cons(s_eval(car(m), a), evlis(cdr(m), a))
  end
end


#### REP (no Loop): s_rep
def s_rep(e) s_string(s_eval(s_read(e), s_read("()"))) end

Commentaire

Remarques

Informations complémentaires sur l'article

Journal des modifications

Recommended Posts

Exemple d'implémentation d'un système de traitement LISP simple (version Ruby)
Exemple d'implémentation d'un système de traitement LISP simple [Résumé de chaque version linguistique]
Implémentation du traitement asynchrone dans Tomcat
[Kotlin] Un exemple de traitement utilisant Enum
Liste de gemmes pour chaque version Ruby 2.5.x
Implémentation du traitement asynchrone compatible multi-tenant dans Tomcat
[Ruby on rails] Implémentation d'une fonction similaire
Un exemple simple du modèle MVC
Un exemple simple de servlet qui affiche le japonais
Implémentation de la fonction de connexion Ruby on Rails (Session)
Gérez la version de Ruby elle-même avec rbenv
Comment écrire un exemple d'implémentation F04 ruby et C99 en temps réel hors ligne
Comment écrire un exemple d'implémentation du problème dans E05 (ruby, C11) en temps réel hors ligne