読者です 読者をやめる 読者になる 読者になる

言語のしくみを読む

パーサで解析されたスクリプトは構造体のリンクで表現されたノードで返される。
state.lvalにつながれたリンク。

node(node_value)
type:NODE_STMTS
void** data

node(node_op)
type:NODE_OP
op:strm_string
len:1
ptr:“|”
lhs:
node(node_values)
type:NODE_ARRAY
data
node(node_value)
value:
t:NODE_VALUE_STRING
v.s->ptr:“Hello world
v.s->len:11
rhs:
node(node_value)
type:NODE_IDENT
v.s->ptr:“STDOUT”
v.s->len:6
ノードをかたち作るのはnode構造体でその末端に納められているデータなどはnode_valueに収められている
共用体でint,long,double,void:,strm_string(const char *ではない)
main関数のnode_run関数呼ぶ

exe_expr(ctx,(node)p->lval,&v)関数に構造体のリンクを投入する
リンクを辿りながらnodeのtypeごとに処理をしている。
最初はtype:NODE_STMTS
data[i]にリンクしてある次のノードを引数にexe_expr関数を再帰呼び出しをする。 リンクしてあるのはNODE_OPタイプのノードになる。
ノードのメンバーであるlhsにリンクされている次のノードを引数にexe_expr関数を呼ぶ
リンクされているのはNODE_ARRAY(node_values)タイプである。
ここであらかじめstrm_arrayの構造体を用意しておく。
ノード内のdataをexe_expr関数に渡して呼び出すとようやく末端データ構造体の
NODE_VALUE(NODE_VALUE_STRING)にたどり着く。
ノード構造体に入っているデータ(string型)をstrm_ptr_value関数を使って
strm_value構造体にタイプ型と一緒にコピーしている。
ノードのデータをstrm_value構造体にコピーする関数はvalue.cにまとめて入っている。
bool値(NODE_VALUE):
 strm_bool_value関数
nil値(NODE_VALUE_NIL):
 strm_nil_value関数
string,IDENT値:
 strm_ptr_value関数
double値:
 strm_flt_value関数
int値
 strm_int_value関数
これら関数を使ってノードに登録しておいたデータ(ここでは"Hello World")を
val(strm_value
)変数に格納しておく。

次にNODE_OPに戻ってきたらrhsを引数にexe_expr関数を呼ぶ。
rhs(右辺)にリンクされているのはNODE_IDENT(node_value)タイプで
strm_var_get関数を呼ぶ、このとき引数には右辺の"STDOUTが渡されている。
このstreemに設定してある識別子を探しているようだ。
見つけた識別子はstrm_value配列(args[2])保管しておき、exec_call関数に引数として渡す。
今回はSTRM_VALUE_CFUNCのexec_bar関数を呼び出す。
exec_bar関数内でlhsがARRAYタイプを探して行き
strm_alloc_stream関数を呼び実際にコールする関数をstart_funcに登録する
strm_task構造体
  id:-1
  mode:strm_task_prod
  start_func:arr_exec関数
  close_func:arr_finish関数
  data:
  dst:NULL
  nextd:NULL
  flags:0
続いて右辺の処理
rhs:ioを選択しstrm_value_io関数を呼び
strm_io構造体に値を設定する
  type:STRM_OBJ_IO
  fd:1
  mode:2
  read_task = 0x0
  write_task:0x0
これをstrm_io_open関数に渡す。
modeがSTRM_IO_WRITEなのでstrm_task構造体に設定して返してくる。
strm_task構造体
  id:-1
  mode:strm_task_cons
  start_func:write_cb関数
  close_func:write_close関数
  data:
  dst:NULL
  nextd:NULL
  flags:0
/task x task/
strem_connect関数を呼ぶ
task_init関数を呼び、task_loop関数をマルチスレッドで待機させておく
strem_connect関数に戻ってきたらstrm_tasak_push関数でtaskをキューに
押し込んでおく。
strem_queue_task構造体に設定する内容
strm:strm_task構造体で左辺のtask
func:arr_exec
data
next:NULL

ここでexec_bar関数に戻り、exec_call関数に戻り、exec_expr関数に戻る。
再帰で呼ばれていたexec_expr関数に次々に戻っていく。
node_run関数まで戻ったらmain関数のstrm_loop関数を呼ぶ
キューにタスクが詰められていたらstrm_queue_exec関数を呼び
実行させる。
このときに関数はwrite_cb関数で"Hello World"を標準出力に表示させた。