---
# System prepended metadata

title: C言語風KSPトランスパイル草案
tags: [ksp]

---

# C言語風KSPトランスパイル草案

###### tags: `ksp`

[toc]

## NI_Types.h

~~~c
typedef int polyphonic
typedef int UIButton
typedef int UILabel
typedef int UIKnob
typedef int[] UITable
:
:
// 後で追加出来るようにtypedef
// Cコンパイルがサポートするのは
// int
// float
// string （char*相当）
// callback (コールバック登録用。関数ポインタほど厳密に扱わない。)
// function (ユーザー定義関数)
~~~

## NI_Commands.h

~~~c
construct UIKnob NI_CreateUIKnob( int min, int max, int ratio ); 
register void RegisterCallback( int variable, callback func );

NICommand void NI_SetText( int variable, string label );
:
:
:
~~~

## NI.h

~~~c
#include <NI_Types.h>
#include <NI_Commands.h>
~~~

## Main.c

~~~c
#include <NI.h>

//
// C言語「風」なだけで
// - C標準関数は使用できない
// - ポインタは使用できない（KSPに落とし込むのに、逆に複雑になる）
//
// KSP変数宣言は全てグローバル。ローカル変数は不可
// ローカル変数をやるなら、ローカルスタック用のワークエリアを
// 確保し厳密にトラバースする（※プリミティブ型のみ）
int count;
UIButton button;

callback init()
{
    int i = 1;
    NI_SetText( button, "Label" );
    RegisterCallback( button, OnButtonEvent_1 );
    // C言語のポインタ渡しで書くと RegisterCallback の宣言は
    // void RegisterCallback( int, callback (func*)(int) );
    
    count = i;
}

// ボタンクリックイベント on ui_control( $button ) 相当
callback OnButtonEvent_1( UIButton button )
{
    NI_Message( "Clicked" );
}
~~~

## To KSP

~~~
on init
    { transpile internal }
    declare %__transpile__stack__[ 4096 ]
    declare $__transpile__sp__ := 0
    declare $__transpile__fp__ := 0

    { initialize of local stack }
    $__transpile__fp__ := $__transpile__sp__

    { Local : int i = 1; }
    %__transpile__stack__[ $__transpile__sp__ ] := 1 { i = 1; }
    inc( $__transpile__sp__ )

    { Global }
    declare $count
    declare ui_button $button

    set_text( $button, "Label" )

    $count := %__transpile__stack__[ $__transpile__fp__ + 0 ]

    { pop a local stack }
    $__transpile__sp__ := $__transpile__fp__
end on

on ui_control( $button )
    message( "Clicked" )
end on
~~~

## メモ：プリプロセス→構文解析→...

Cコンパイラのイメージ（？）的なもの。
1passでやろうとしても無理があるので最低2passは必要。

https://www.anarres.org/projects/jcpp/
https://github.com/shevek/jcpp

- 一旦プリプロセスフェーズでマクロ展開
    - #include ディレクティブ検出の時点で行数カウントを行い、展開前との行オフセットを控えておく

- 構文解析フェーズ
    - エラー、警告出力時は控えておいた行番号オフセットを元に再計算
    - 展開前のソースコードのエラー発生行を示すことができるはず…？

- 意味解析
- バックパッチ (ここでは動的なASTノード生成)
- KSPの構文へテキスト出力
