使用对 AST 的运行时访问来编程 language/platform

Programming language/platform with runtime access to the AST

我希望为一个简短的演示实现一些概念验证演示,其中 运行 代码知道当前正在执行的代码块的散列 'value'。例如:

function BBB(a) {
  a = 2 * a;
  print me.hash;          --> "xxxxxxx" (value of BBB-syntax represenation)
  return a;                              
}

function AAA(a, b, c) {
  d = BBB(a);
  print me.hash;          --> "yyyyyyy" (value of AAA-Syntax representation, possibly dependant on value of BBB, but not necessary)
  return d;
}

我本能地转向了 LISPish 语言,但在 Scheme 上还没有成功。而且我已经很长时间没有接触 Common LISP,我怀疑它可能能够做到(感谢提示)。它不一定要很快,或者是一个流行的平台,可以是可用的最学术和最奇怪的平台。这只是一个演示。

有没有人知道 language/platform 几乎可以开箱即用或只需相对较少的修补就可以做到这一点?我更喜欢使用某种 parsed/treeish 东西,而不是实际的源代码。

不是散列,但对于唯一 ID,您可以使用 Python 对象标识。将每个函数放在自己的 class 中,然后使用 id()。例如,在 Python 3:

class cBBB(object):
    def do(a):
        a=2*a
        print(self.id())    # self.id() is the "hash"-like unique value
        return a;
BBB = cBBB()     # now you can call BBB.do(a)

class cAAA(object):
    def do(a,b,c):
        d = BBB.do(a)
        print(self.id())    # self.id() is the "hash"-like unique value
        return d;
AAA = cAAA()     # now you can call AAA.do(a,b,c)

这可以使用 __call__ 更干净地完成。有关 __call__.

的更多信息,请参阅 this question

你猜对了。 Common Lisp 可以很容易地做到这一点:

(defmacro reflective-defun (name args &body body)
  (let ((source-form `(reflective-defun ,name ,args ,@body)))
    `(let ((me ',source-form))
       (defun ,@(cdr source-form)))))

(reflective-defun bbb (a)
  (setf a (* 2 a))
  (print me)
  a)

(reflective-defun aaa (a b c)
  (let ((d (bbb a)))
    (print me)
    d))

(aaa 12 :x :y)

输出:

(REFLECTIVE-DEFUN BBB
    (A)
  (SETF A (* 2 A))
  (PRINT ME)
  A) 
(REFLECTIVE-DEFUN AAA
    (A B C)
  (LET ((D (BBB A)))
    (PRINT ME)
    D)) 
24

以下是编写自重定义函数的方法:

(defun recursive-replace (tree what with)
  "Walks down the TREE and replaces anything that is EQUALP to WHAT with WITH."
  (cond ((equalp tree what)
         with)
        ((listp tree)
         (loop for item in tree
              collect (recursive-replace item what with)))
        (t tree)))

(reflective-defun ccc (a b c)
  (let ((d (bbb a)))
    (print me)
    (if (eql b :use-me-from-now-on)
        (eval (recursive-replace me '(bbb a) '(bbb b))))
    d))

顺便说一句,Scheme(以及任何使用宏的语言)会竭尽全力阻止您创建一个名为 me 的标识符,该标识符可以被传递给宏的源代码引用。