`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2009-07-04

xyzzyをVC2008でビルドする

xyzzyのソースは公開されてるから、VC2008で自分でプロジェクト作ってビルドしてみよう…とするとファイルがなかったりいろいろエラーが出る。

srcにコマンドラインでのMakefileが入ってる。長年コマンドラインからVCを使ったことないのであまり気が進まなかったのだけどno titleを見ればその通りできた。

手順:普通のDOSプロンプトからcl.exeを呼び出すと「mspdb80.dllが見つからない」というエラーが出る。これはスタートメニューのVC2008の「Visual Studio 2008 コマンドプロンプト」で開くコマンドラインから実行すると解決する。

no titlediff-v2.lzhのパッチを当てればビルドが通る。さすがNANRIさん!助かります。

パッチで行ってることは

  • cl.exe のコンパイルオプションに「-Zc:forScope-」を追加して、古いVCの for 文内で宣言した変数のスコープが漏れ出す仕様を有効にする
  • 「-Zc:wchar_t-」で文字コードの設定の変更?
  • あとは型の宣言に const をつけたり戻り値の型のintが省略されてるところを追加したり

ビルド時にいくつか実行ファイルが作られて、いくつかのファイルが自動生成されている

  • dpp.exe: .d ファイルのプリプロセッサ?
    • dpp.exe num-arith.h num-arith.d # 数値演算関連の型ごとの処理を記述
  • gen-syms.exe: ソース中で使われるシンボルの宣言を生成
    • .\gen-syms -vars > vars-decl.h
EXTERN lisp Qquote;
EXTERN lisp Qfunction;
...
      • 実体は、symtable.cc で「#define EXTERN /*empty*/」としてEXTERNを無効にした上で vars-decl.h をインクルードすることで定義している
    • .\gen-syms -proto > fns-decl.h
lisp Fquote (lisp, lex_env &);
lisp Ffunction (lisp, lex_env &);
...
    • .\gen-syms -symtable > symtable.cc
static const char SS[] = 
"quotefunctionprognletlet*ifsetqsetsymbol-valuespecial-form-pmacro-functi"
"onsymbol-functionset-defaultdefault-valueboundpfboundpconstantpblockretu"
...
lfns lsp_fns[] =
{
  {SS + 0, (lisp (__stdcall *)())(lisp (__stdcall *)(lisp, lex_env &))Fquote, &Qquote, 0, 5, 2, 0, 1, 0},
  {SS + 5, (lisp (__stdcall *)())(lisp (__stdcall *)(lisp, lex_env &))Ffunction, &Qfunction, 0, 8, 2, 0, 1, 0},
...
  • gen-msg.exe: msgdef.h からエラーメッセージの宣言と定義を生成
    • .\gen-msg -enum > msgcode.h # エラーメッセージのラベルの定義
enum message_code
{
  Eunexpected_eof,
  Eunterminated_comment,
...
    • .\gen-msg -c > msgdef.cc # エラーメッセージの文字列の定義
const char SSM[] =
  "予期しないEOFを検出しました\0"
  "コメントが終了していません\0"
...
static const char *const message_string[] =
{
  SSM + 0,
  SSM + 28,
...
  • gen-vinf.exe: リソース(.rc)用にバージョン情報を生成
    • .\gen-vinf > verinfo.h
  • gen-ctab.exe: 文字コードの属性を定義するテーブル生成。大文字、小文字、など…
  • gen-char-width.exe
  • gen-ibmext.exe
    • .\gen-ibmext > ibmext.h
  • gen-iso2022state.exe
    • .\gen-iso2022state > iso2022state.h
  • gen-jisx0212-hash.exe
    • .\gen-jisx0212-hash > jisx0212-hash.h
  • gen-ktab.exe
    • .\gen-ktab > kanjitab.h
  • gen-utf2sjis.exe
    • .\gen-utf2sjis > utf2sjis.h

自動生成してるソースはあるものの、Cygwinとか他のツールに頼らずにVCだけで実行ファイルができるのは組み込む側にとっては便利でいいですね。

さて、ここからCL処理系部分を抜き出して使いたい。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090704

2008-11-23

マクロ展開時の環境

マクロの中でフリーの変数の参照をした場合、グローバルの環境を見にいくはず:

; y がフリーのマクロ
(defmacro test (x) `(+ ,x ,y))

(setq y 100)
(test 10)
; => 110  ;グローバルの y を参照

(let ((y 1234)) (test 10))
; => 110  ;ローカル環境はマクロ展開時には影響しない

(let ((y 1234)) (macroexpand '(test 10)))
; => (+ 10 100)

xyzzy だと結果が違う:

(let ((y 1234)) (test 10))
; => 1244  ; 実行結果に影響を与えてしまっている

(let ((y 1234)) (macroexpand '(test 10)))
; => (+ 10 100)  ;展開は正しい

スペシャル変数だとどうなるかもテストする。

g000001g0000012008/11/23 19:36なんとなくですが、変数を意図的にキャプチャしたい場合は、
(defmacro test (x) `(+ ,x y))

(let ((x 1) (y 2))
(test x))
;=> 3
のようにクオートを解除しないでそのまま字面で記述しておくのが定番かなとも思います。これだと常にxyzzy風ですね。

mokehehemokehehe2008/11/24 09:07あ、今回確認したかったことは、マクロの展開時はローカル環境を見れないはず、ってことを確認したかったんですが、最初にxyzzyで試したら見れてしまったのでビックリした、という話でした(^^;; 紛らわしかったですね。

g000001g0000012008/11/24 14:53なるほど('-'*) CLの場合だと自由変数的になっているものを定義時に解決するみたいなんですが、xyzzyだとそのまま展開するのかもしれないですね。
ちなみにCLの動作については憶測で言ってますw

NANRINANRI2008/11/26 01:59マクロ展開がいつ起こるかは処理系依存なんですよね。
http://raido.sakura.ne.jp/southly/rn/index.rb?1204644339.txt
詳しくはCLtL2の8章を。

mokehehemokehehe2008/11/26 20:23マクロ展開は実行時に行われてもいいと思いますが、スコープがダイナミックになっちゃってますね。
CLtL2 を見てみました。8.1. Macro Definition
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node98.html
の [Macro] defmacro のあたりに
> The expander function is effectively defined in the global environment; lexically scoped entities established outside the defmacro form that would ordinarily be lexically apparent are not visible within the body of the expansion function.
と書いてあるので、実行時に展開したとしてもレキシカルスコープが正しいんじゃないでしょうか?まあ普通はマクロ展開は渡された引数しか見ないと思うので問題ないですが。

NANRINANRI2008/11/26 21:06言われてみると確かに
> 実行時に展開したとしてもレキシカルスコープ
が正しそうです。expander functionが作られないのでxyzzyのマクロ周りは微妙にCL仕様じゃないみたいですね。

g000001g0000012008/11/26 21:34おー、なるほど勉強になります。
(let ((y 'hello)) (defmacro foo (x) `'(,x ,y)))
;; CL
(foo 3) ;=> (3 HELLO)
;; Xyzzy ;y :変数が定義されてません。
って感じなんですねー。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20081123

2008-10-25

xyzzy でファイルを行ごとに読み込んでなんか処理

(defmacro awhile (expr &body body)
  `(do ((it ,expr ,expr))
       ((not it))
     ,@body))

(with-open-file (fp "test.txt" :direction :input)
  (awhile (read-line fp nil)
          (print it)))
トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20081025

2008-04-02

名前でバッファを検索

| 22:52

(find-buffer "*scratch*")

開いてるバッファを列挙

| 21:59

xyzzy 上で Lisp/xyzzy の使いかたを勉強する。

まず、開いてるバッファを列挙

(defun get-buffers ()
  (let ((acc '()))
    (enum-buffers #'(lambda (x)
                      (setq acc (cons x acc))
                      nil))
    (nreverse acc)))

佐野佐野2008/04/08 23:44buffer-list?

mokehehemokehehe2008/04/09 09:12お、そのような便利な関数があるんですね。
ありがとうございます。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080402