言語仕様

Lambda C は組み込みスクリプティング向けに設計された C89 のサブセットです。本ページは、コンパイラ(lcvmc)が受理する言語表面と対象ランタイム — サポートする型・演算子・制御フロー・組込みライブラリ、そして意図的な非対応事項と実装上限 — を定義します。

言語がどのようにコンパイル・実行されるかは アーキテクチャ を、API と機能のカタログは 機能 を参照してください。


データ型

サイズ備考
char1 B符号付き
unsigned char1 B
short2 B
unsigned short2 B
int4 B
unsigned int4 B
long4 B / 8 Bターゲット依存(LP64 対応)
unsigned long4 B / 8 B
float4 B
double8 B
void関数の戻り値 / void *
ポインタ4 B / 8 Bint *char ** …(ターゲット依存)

型の幅はビルド時のターゲット設定(common.hLCVM_TARGET_*_SIZE)で固定されます。64 ビットホストでは long とポインタは 8 バイト、32 ビット MCU では 4 バイトです。long long_Bool、および C99 の固定幅型は非対応です。


演算子

分類演算子
算術+ - * / %
比較== != < <= > >=
論理&& || !
ビット& | ^ ~ << >>
代入= += -= *= /= %= &= |= ^= <<= >>=
インクリメント / デクリメント++ --(前置・後置)
単項&(アドレス取得)、*(間接参照)、-+!~
メンバアクセス. -> []
その他sizeof? :(三項)、,(カンマ)、(type) キャスト

制御フロー

if (cond) { ... } else { ... }
while (cond) { ... }
do { ... } while (cond);
for (init; cond; step) { ... }
switch (expr) { case N: ... break; default: ... }
break;
continue;
return expr;
goto label;

宣言と定義

/* グローバル変数・静的変数 */
int  global_var;
static int static_var;
char *string_ptr = "hello";

/* 関数: 定義とプロトタイプ。
   パラメータ数に固定上限はなく、スタック容量のみで制限される。 */
int func(int a, int b) { return a + b; }
int external_func(int x);

/* 配列(多次元配列も最大6次元までサポート) */
int  array[100];
char buffer[256];
int  matrix[10][10];
int  cube[4][4][4];

/* ポインタ(関数ポインタを含む) */
int  *ptr;
char **argv;
int  (*callback)(int);

/* 構造体と共用体 */
struct Point { int x; int y; };
struct Point  p;
struct Point *pp;

union IntBytes { int value; char bytes[4]; };

/* enum: 明示的な値と無名 enum */
enum Color     { RED, GREEN, BLUE };
enum ErrorCode { OK = 0, ERR = -1, ERR_IO = -2 };
enum           { FLAG_A = 1, FLAG_B = 2 };

/* typedef */
typedef int INT32;
typedef struct Point Point_t;

/* const / volatile は認識されるが無視される(通常の型として扱う) */
const int LIMIT = 100;
volatile int flag;

型キャスト

整数・浮動小数点・ポインタの間のキャストがサポートされます:

char   c = (char)i;       /* int  -> char(切り捨て)   */
double d = (double)i;     /* int  -> double             */
int   *p = (int *)ptr;    /* ポインタの再解釈            */
char  *b = (char *)&v;    /* int のバイト表現ビュー       */

注意点が一つあります。式の途中での intdouble 拡張キャストは適用されません。浮動小数点オペランドで演算を行うか、いったん double 変数に代入してください。


プリプロセッサ

レキサが小さなインラインプリプロセッサを処理します。フル機能の C プリプロセッサではありません — スクリプトの合成とターゲットコードのゲーティングのために存在し、メタプログラミングを目的としていません。

サポート:

#include "header.h"
#include <stdio.h>        /* 組込みヘッダー(標準ライブラリ参照) */

#define MACRO 100         /* オブジェクト形式マクロ: 数値 / 文字 / 文字列 */

#ifdef MACRO
#endif

#ifndef MACRO
#else
#endif

非サポート: #if / #elif#undef#pragma#error / #warning##(トークン連結)および #(文字列化)演算子、defined()、引数を取る関数形式マクロ。単純な数値・文字・文字列定数でない #define 本体は拒否されます。


標準ライブラリ

スクリプトは include/lcvm/ 配下のヘッダーで公開される組込み関数を通じてランタイムにアクセスします。以下の関数は VM イントリンシックとして実装されており、対応するヘッダーを #include するとプロトタイプが可視になります。

stdio.h printfsprintffprintfscanfsscanffscanfgetcharputchargetcputcfopenfclosefgetcfputcfgetsfputs

stdlib.h mallocfreeatoiqsortexitabort。 管理ヒープはバンプ/リージョンアロケータです — malloc は確保しますが、個別ブロックの free は no-op です。一括回収は heap_mark / heap_release 拡張(後述)で行います。realloc は提供されません。

string.h strlenstrcpystrcatstrncatstrcmpstrncmpmemcpymemset

math.h(すべて double を扱う) sincostanasinacosatanatan2sinhcoshtanhexploglog10powsqrtceilfloorfabsfmod

time.h clocktimedifftimemktimegmtimelocaltimeasctimectimestrftime

search.h / glob.h / regex.h bf_searchbf_re_searchbm_searchbm_re_search(総当たり / Boyer–Moore による文字列・正規表現検索)、amatch(glob マッチャ)、rx_search(正規表現検索)。

Lambda C 拡張

C ライブラリに加え、ランタイムは組み込みオーケストレーション向けのイントリンシックを公開します:

関数用途
heap_mark()現在のヒープ位置(ウォーターマーク)を記録
heap_release(mark)mark 以降に確保した全領域を一括解放
millis()経過ミリ秒(単調タイマー)
lcvm_reset(vm)VM の自己リセットを要求
vm_reload(reason)スクリプトのホットリロードを要求
vm_interrupt(flag)協調的割り込みフラグを設定

関数を持たないヘッダー

limits.hfloat.h は定数(INT_MAXDBL_DIG …)のみを提供します。ctype.hassert.hstdarg.hsetjmp.hsignal.h はスタブとして存在し、動作する関数は提供しません — setjmp / longjmp はホスト側にのみ存在します。<stddef.h><stdint.h><stdbool.h><errno.h><locale.h> は存在しません。NULL には 0bool には int、固定幅整数には明示的な typedef を使ってください。


静的型モード(-Os

-Os はモジュールを静的型モードでコンパイルし、値ごとの実行時型タグと型スタックを除去します(バイトコードに LCVM_LCBC_FLAG_STATIC_TYPES フラグが付く)。実行時型情報と引き換えに、スループットがおよそ倍増し、スタック使用量が減ります。

このモードは整数とポインタの制御コードを対象とします。浮動小数点(float / double)はこのモードが除去する型情報に依存するため、-Os モジュールは整数とポインタに限定すべきです。printf などの組込み関数は通常(非 -Os)モードで動作し続けます。

lcvmc -Os -oc output.lcbc source.c   # 静的型モードでコンパイル
lcvmc -rcn output.lcbc               # コンパクトバイトコードを実行

ベンチマークと技術的背景は アーキテクチャ を参照してください。


実装上限

項目上限設定箇所
スタックサイズ100 KBSTACKSIZE
グローバル領域100 KBGLOBALSIZE
管理ヒープ256 KBLCVM_HEAP_MAX
VM 再入 / ネスト深度8LCVM_MAX_VM_DEPTH
登録 FFI 関数64LCVM_FFI_MAX_FUNCTIONS
VM レジスタ13REGSIZE
識別子長30IDSIZE
文字列 / トークンバッファ2000STRSIZE
配列次元数6ARR_MAX
関数パラメータ無制限スタック制限

ローダーはさらに、構造的な上限を超えるバイトコードを拒否します: 命令 65536、定数 4096、文字列テーブルとグローバル領域それぞれ 256 KB。


個別機能に関する注記

集約初期化

スカラと文字列の初期化は動作します。構造体・配列の初期化子リストは部分的にしかサポートされません。フィールドごとの代入を推奨し、配列初期化子リストはグローバルに限定してください。

struct Point p; p.x = 10; p.y = 20;   /* 推奨 */
char str[] = "hello";                 /* OK */
int  arr[] = { 1, 2, 3 };             /* グローバルスコープで OK */

文字列リテラル

隣接する文字列リテラルは連結されます:

char *s = "hello" "world";            /* "helloworld" */

可変長配列

VLA は非対応です。配列サイズはコンパイル時定数でなければなりません。


非対応の言語機能

機能理由
ビットフィールド(struct { int x:4; }未実装
ユーザー定義の可変長引数関数(...printf 等は組込みイントリンシック
複合リテラル((int[]){1,2,3}未実装
指示付き初期化子(.x = 1未実装
_Boolinlinerestrictlong longC99
フル C プリプロセッサ(#if、関数マクロ …)プリプロセッサ参照

カバレッジ

Lambda C は C89 のおよそ 80% を実装します — 組み込み制御・オーケストレーションスクリプトに十分な範囲 — そして残りは意図的に省きます: クロージャなし、GC なし、動的型付けなし、例外なし。その「なさ」こそが、ランタイムを ROM 配備に十分小さく、ハードリアルタイム制御ループに十分予測可能に保ちます。

関連ページ