function parameter-passing convertion

这里先对一些需要的helper函数做定义。这里对于环境(environment)和闭包(closure)的定义在于,使得解释器的实现与数据结构无关。(我现在用的函数表示,当然完全可以用list代替)

(define (empty-env)
  (lambda (y) (error 'value-of "unbound variable ~s" y)))

(define (apply-env env x)
  (env x))

(define (extend-env x val env)
  (lambda (y)
    (if (eqv? x y)
        val
        (apply-env env y))))

(define (make-closure x body env interp)
  (lambda (var) (interp body (extend-env x var env))))

(define (apply-closure e1 e2)
  (e1 e2))

这里给出call-by-value解释器的定义,对于函数((lambda (x) body) exp),在解释body的时候,我们把x和exp bind在一起放在环境中。这个时候,exp是已经evaluate过的。也就是说每次在对函数进行evaluate的时候,参数在bind以前就已经evaluate。

同时,可以看到对于exp解释的时候,在环境中找到exp的box,通过unbox取出值,然后再box生成一个新的box structure。这样在对函数进行解释的时候,传入的value是之前环境中value的一个复制(copy)。

(define val-of-cbv
  (lambda (exp env)
    (match exp
      [`,b #:when (boolean? b) b]
      [`,n #:when (number? n)  n]
      [`,y #:when (symbol? y) (unbox (apply-env env y))]
      [`(zero? ,n) (zero? (val-of-cbv n env))]
      [`(sub1 ,n) (sub1 (val-of-cbv n env))]
      [`(* ,n1 ,n2) (* (val-of-cbv n1 env) (val-of-cbv n2 env))]
      [`(if ,test ,conseq ,alt) (if (val-of-cbv test env)
                                  (val-of-cbv conseq env)
                                  (val-of-cbv alt env))]
      [`(begin2 ,e1 ,e2) (begin (val-of-cbv e1 env) (val-of-cbv e2 env))]
      [`(set! ,x ,v) (set-box! (apply-env env x) (val-of-cbv v env))]
      [`(random ,n) (random (val-of-cbv n env))]
      [`(lambda (,x) ,body) (make-closure x body env val-of-cbv)]
      [`(,rator ,rand) (apply-closure (val-of-cbv rator env)
                                      (box (val-of-cbv rand env)))])))

第二种解释器,是基于call-by-reference,函数的参数在进行bind的时候,传进去的是数据的引用,而不是数据的value。

我们对

(,rator ,sym) #:when (symbol? sym)

pass的是symbol的情况做特殊处理:在环境中找到sym所对应的box,直接把box和函数的参数进行bind。这样,如果box的内容被修改,相应的,环境中sym所对应的值都会改变。

(define val-of-cbr
  (lambda (exp env)
    (match exp
      [`,b #:when (boolean? b) b]
      [`,n #:when (number? n)  n]
      [`,y #:when (symbol? y) (unbox (apply-env env y))]
      [`(zero? ,n) (zero? (val-of-cbr n env))]
      [`(sub1 ,n) (sub1 (val-of-cbr n env))]
      [`(* ,n1 ,n2) (* (val-of-cbr n1 env) (val-of-cbr n2 env))]
      [`(if ,test ,conseq ,alt) (if (val-of-cbr test env)
                                  (val-of-cbr conseq env)
                                  (val-of-cbr alt env))]
      [`(begin2 ,e1 ,e2) (begin (val-of-cbr e1 env) (val-of-cbr e2 env))]
      [`(set! ,x ,v) (set-box! (apply-env env x) (val-of-cbr v env))]
      [`(random ,n) (random (val-of-cbr n env))]
      [`(lambda (,x) ,body) (make-closure x body env val-of-cbr)]
      [`(,rator ,sym) #:when (symbol? sym) (apply-closure (val-of-cbr rator env)
                                                              (apply-env env sym))]
      [`(,rator ,rand) (apply-closure (val-of-cbr rator env)
                                      (box (val-of-cbr rand env)))])))

第三种解释器,是call-by-name,这里用到了一个解释器通用的trick --thunk。也就是说((lambda(x) exp),在bind的时候,exp并没有被解释,直到exp被调用的时候。

(lambda() (val-of-cbname rand env))

我们并没有直接evaluate rand的值,而是把它做成一个没有参数的函数和rator的参数bind,直到这个参数被调用的时候,才对rand进行evaluate。

(define val-of-cbname
  (lambda (exp env)
    (match exp
      [`,b #:when (boolean? b) b]
      [`,n #:when (number? n)  n]
      [`,y #:when (symbol? y) ((unbox (apply-env env y)))]
      [`(zero? ,n) (zero? (val-of-cbname n env))]
      [`(sub1 ,n) (sub1 (val-of-cbname n env))]
      [`(* ,n1 ,n2) (* (val-of-cbname n1 env) (val-of-cbname n2 env))]
      [`(if ,test ,conseq ,alt) (if (val-of-cbname test env)
                                  (val-of-cbname conseq env)
                                  (val-of-cbname alt env))]
      [`(random ,n) (random (val-of-cbname n env))]
      [`(lambda (,x) ,body) (make-closure x body env val-of-cbname)]
      [`(,rator ,rand) (apply-closure (val-of-cbname rator env)
                                      (box (lambda () (val-of-cbname rand env))))])))

最后一种方法是call-by-need, 也叫做lazy evaluation。对于call-by-name,每次evaluate参数的时候,他的值都会重新被evaluate一次。但是call-by-need的做法,就是第一次进行evaluate,再把evaluate的结果存在环境中。这样就可以只进行一次evaluation。

(define (unbox/init-set box-case)
  (let ([val ((unbox box-case))])
    (begin (set-box! box-case (lambda() val)) val)))

(define val-of-cbneed
  (lambda (exp env)
    (match exp
      [`,b #:when (boolean? b) b]
      [`,n #:when (number? n)  n]
      [`,y #:when (symbol? y) (unbox/init-set (apply-env env y))]
      [`(zero? ,n) (zero? (val-of-cbneed n env))]
      [`(sub1 ,n) (sub1 (val-of-cbneed n env))]
      [`(* ,n1 ,n2) (* (val-of-cbneed n1 env) (val-of-cbneed n2 env))]
      [`(if ,test ,conseq ,alt) (if (val-of-cbneed test env)
                                  (val-of-cbneed conseq env)
                                  (val-of-cbneed alt env))]
      [`(random ,n) (random (val-of-cbneed n env))]
      [`(lambda (,x) ,body) (make-closure x body env val-of-cbneed)]
      [`(,rator ,rand) (apply-closure (val-of-cbneed rator env)
                                      (box (lambda () (val-of-cbneed rand env))))])))

C++ virtual function

#include<iostream>
using namespace std;
class A
{

};
class B
{
    int i;
};

class C
{
    void foo();
};
class D
{
    virtual void foo();
};

class E
{
    int i ;
    virtual void foo();
};
class F
{
    int i;
    void foo();
};
class G
{
    void foo();
    int i;
    void foo1();
};

class H
{
    int i ;
    virtual void foo();
    virtual void foo1();
};
int main()
{
    cout <<"sizeof(class A) : " << sizeof(A) << endl ;
    cout <<"sizeof(class B) adding the member int i : " << sizeof(B) << endl ;
    cout <<"sizeof(class C) adding the member void foo() : " << sizeof(C) << endl ;
    cout <<"sizeof(class D) after making foo virtual : " << sizeof(D) << endl ;
    cout <<"sizeof(class E) after adding foo virtual , int : " << sizeof(E) << endl ;
    cout <<"sizeof(class F) after adding foo  , int : " << sizeof(F) << endl ;
    cout <<"sizeof(class G) after adding foo  , int : " << sizeof(G) << endl ;
    G g;
    cout <<"sizeof(class G) after adding foo  , int : " << sizeof(g) << endl ;
    cout <<"sizeof(class H) after adding int 2 virtual " << sizeof(H) << endl ;
    return 0;
}

Output result:
sizeof(class A) : 1
sizeof(class B) adding the member int i : 4
sizeof(class C) adding the member void foo() : 1
sizeof(class D) after making foo virtual : 8
sizeof(class E) after adding foo virtual , int : 16
sizeof(class F) after adding foo , int : 4
sizeof(class G) after adding foo , int : 4
sizeof(class G) after adding foo , int : 4
sizeof(class H) after adding int 2 virtual 16

sizeof(class A) == sizeof(class C), since class is empty and non-virtual function doesn’t take any space.

 

How to build gcc cross-compile toolchain

This post tells almost everything you need to know about building gcc cross-compile toolchain.

One thing needs to be noticed, when build binutils in 2nd step, you have to specify sysroot with –with-sysroot=path/to/sys/root/. Otherwise some cross-compile tools (i.e. ld) will not properly configured.

Hello world!

Welcome to WordPress.com. After you read this, you should delete and write your own post, with a new title above. Or hit Add New on the left (of the admin dashboard) to start a fresh post.

Here are some suggestions for your first post.

  1. You can find new ideas for what to blog about by reading the Daily Post.
  2. Add PressThis to your browser. It creates a new blog post for you about any interesting  page you read on the web.
  3. Make some changes to this page, and then hit preview on the right. You can always preview any post or edit it before you share it to the world.
Design a site like this with WordPress.com
Get started