@cocoatomo
Python との出会い: 仕事で Jython
C での OOP 言語の実装が学べる
CPython の特性が理解できる
CPython を改造して俺々 Python が作れる
俺々言語の実装の参考に
結局は自己満足です. はい.
gtags
$ gtags -v $ htags
gtags-mode
(setq gtags-mode-hook '(lambda () (local-set-key "\M-t" 'gtags-find-tag) (local-set-key "\M-r" 'gtags-find-rtag) (local-set-key "\M-s" 'gtags-find-symbol) (local-set-key "\C-t" 'gtags-pop-stack))) (add-to-list 'exec-path "/usr/local/bin") (setenv "PATH" (concat '"/usr/local/bin:" (getenv "PATH")))
run_command
RunModule
RunMainFromImporter
PyRun_InteractiveLoopFlags
run_pyc_file
int
main(int argc, char **argv)
{
/* 引数のコピー */
res = Py_Main(argc, argv_copy);
/* メモリとかの後処理 */
return res;
}
/* Main program */
int
Py_Main(int argc, wchar_t **argv)
{
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
/* option の処理 */
}
Py_Initialize();
/* Py_Main 続き */
if (command) { // -c で起動
sts = run_command(command, &cf);
free(command);
} else if (module) { // -m で起動
sts = RunModule(module, 1);
}
else {
/* REPL の起動. */
if (filename == NULL && stdin_is_interactive) {
Py_InspectFlag = 0; /* do exit on SystemExit */
/* Startup File を読み込む */
RunStartupFile(&cf);
}
/* XXX */
/* Py_Main 続き */
// -1 は「未実行」の意味
sts = -1; /* keep track of whether we've already run __main__ */
if (filename != NULL) {
// run_file との違いは??
sts = RunMainFromImporter(filename);
}
if (sts==-1 && filename!=NULL) {
fp = _Py_wfopen(filename, L"r");
/* エラー処理などなど */
}
/* Py_Main 続き */
// .py (.pyc, .pyo) ファイルの実行
if (sts == -1)
sts = run_file(fp, filename, &cf);
}
Py_Finalize();
}
static int
RunMainFromImporter(wchar_t *filename)
{
/* ... */
sts = RunModule(L"__main__", 0);
return sts != 0;
error:
/* ... */
}
static int RunModule(wchar_t *modname, int set_argv0)
{
/* ... */
result = PyObject_Call(runmodule, runargs, NULL);
if (result == NULL) {
return -1;
}
return 0;
}
static int
run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf)
{
/* ... */
run = PyRun_AnyFileExFlags(fp, filename_str, filename != NULL, p_cf);
return run != 0;
}
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
if (filename == NULL)
filename = "???";
if (Py_FdIsInteractive(fp, filename)) {
int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
if (closeit)
fclose(fp);
return err;
}
else
return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}
int
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
/* ... */
for (;;) { // REPL
ret = PyRun_InteractiveOneFlags(fp, filename, flags);
PRINT_TOTAL_REFS();
if (ret == E_EOF)
return 0;
}
}
int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
m = PyImport_AddModule("__main__");
/* __main__.__file__ の設定 */
len = strlen(filename);
ext = filename + len - (len > 4 ? 4 : 0);
/* PyRun_SimpleFileExFlags 続き */
if (maybe_pyc_file(fp, filename, ext, closeit)) {
/* Try to run a pyc file. First, re-open in binary */
/* Turn on optimization if a .pyo file is given */
v = run_pyc_file(fp, filename, d, d, flags);
} else {
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
closeit, flags);
}
/* ... */
}
PyObject *
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals, int closeit, PyCompilerFlags *flags)
{
PyObject *ret;
mod_ty mod;
PyArena *arena = PyArena_New(); /* メモリ領域確保 */
if (arena == NULL)
return NULL;
// parsing
mod = PyParser_ASTFromFile(fp, filename, NULL, start, 0, 0,
flags, NULL, arena);
Arena, Pool は Python のメモリプールの仕組み.
/* PyRun_FileExFlags 続き */
/* ... */
// executing ここは @mayahjp 担当
ret = run_mod(mod, filename, globals, locals, flags, arena);
PyArena_Free(arena);
return ret;
}
mod_ty
PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc,
int start, char *ps1,
char *ps2, PyCompilerFlags *flags, int *errcode,
PyArena *arena)
{
/* ... */
node *n = PyParser_ParseFileFlagsEx(fp, filename, enc,
&_PyParser_Grammar,
start, ps1, ps2, &err, &iflags);
/* ... */
/* PyParser_ASTFromFile 続き */
if (n) {
flags->cf_flags |= iflags & PyCF_MASK;
mod = PyAST_FromNode(n, flags, filename, arena);
PyNode_Free(n);
return mod;
}
/* ... */
}
node *
PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
const char *enc, grammar *g, int start,
char *ps1, char *ps2, perrdetail *err_ret, int *flags)
{
/* ... */
if ((tok = PyTokenizer_FromFile(fp, (char *)enc, ps1, ps2)) == NULL) {
err_ret->error = E_NOMEM;
return NULL;
}
tok->filename = filename;
return parsetok(tok, g, start, err_ret, flags);
}
mod_ty
PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
PyArena *arena)
{
/* ast_for_stmt を呼ぶ */
}
static stmt_ty
ast_for_stmt(struct compiling *c, const node *n)
{
/* 文の種類で switch-case */
/* それぞれの文に対応した ast_for_* を呼ぶ */
}
PEP 3107 で入った関数アノテーションがどう parsing されるか見てみよう.