2026.09.13 21:40

culebraで遊ぶ(mini_culebra/mini_lua)


・というところで、Culebraによる他言語の実行をやってみる。
・とりあえずCulebra自身のmini_culebraをお試し。とりあえずサンプルをうごかしてみるかと

culebra mini_culebra.cul samples/adder.cul

なんてやってみたらエラーになってしまった。他のミニ言語も同じようにエラー。
・なんで?ということで、困った時のChatGPTしてみたら、「ソースコードアップしてみて」という。300kbyte超えるんだけど大丈夫?と思ったけど、まぁやってみるかとやった後、言われるままREPLで少し試しただけで原因判明。
・どうやら
 CodeGen.Resolver()をCodeGen.Resolver.new()
 CodeGen.Module()をCodeGen.Module.new()
 として.new()を明示的に呼ばないといけないらしい。コンストラクタとしてnew()が自動的に呼ばれるようになっていたのが変更になってしまったのかな?
・おまえ、Culebraの言語仕様をそこまで把握できているのか?感あるけど。
・とりあえず修正して動かしてみたら元気に動き出した。
・お試しに
culebra build mini_culebra.cul -o mini_culebra
 として実行ファイルを作ってやるのもあり。
・mini_Luaも同じように修正したら無事動作。よしよし。

2026.09.12 12:14

ノートPC修理に旅立つ


・画面がお亡くなりになったF社さんのノートPCを修理に出す。生きている予備機も欲しいというのもあるけど、Xilinxな有償環境がこのPCで登録してしまっているので、なるべく温存したいというのも大きな理由。
・電器店に出すことも考えたけど、オンラインで申し込んで直接引き取りに来てくれるということなので、お試ししてみたのだった。
・時間していどおり日通さんがきて、ご指定のダンボールに載せて・・・封はその場でやらないのね。大丈夫かいな?という感じだけど、とりあえず持っていった。
・さて、いくらかかるのやら。まぁこのところメモリの暴騰でPCの価格も結構な上昇らしいし、メモリ32Gbyte+ストレージ2Tというのは温存しておいて損はないかな。

2026.09.12 12:07

culebraで遊ぶ(Version0.5.0で他言語も動く?)


・culebraが0.4.0から0.5.0にバージョンアップされていたのでアップデート
・とはいっても、実行ファイルを一つ/usr/local/binにコピーしておくだけ。ついでにgit cloneしてローカルのplaygroundも立ち上げ直しておく。
・リリースノートを見るとちょっと面白い記述がある。
----------
CodeGen namespace: a new stdlib namespace that exposes cpp-vmlib's compact IR and its bytecode compiler/executor to Culebra programs. Paired with the existing PEG parser namespace, a program can parse a source language, walk the resulting tree to build a CodeGen.Module, and run()/compile() it — with CodeGen.Resolver handling closure capture analysis. Six example front-ends ship under examples/languages/, built this way: mini-js (an ES6 subset), mini-culebra (a subset of Culebra itself), mini-csharp, mini-lua, mini-go, and a second, CodeGen-based implementation of PL/0.
ーーーーー
CodeGen 名前空間: 新しい標準ライブラリの名前空間で、cpp-vmlib のコンパクトな IR と、そのバイトコードコンパイラ/実行系を Culebra プログラムから利用できるようにします。r

既存の PEG パーサー名前空間と組み合わせることで、プログラムはあるソース言語を解析し、得られた構文木を走査して CodeGen.Module を構築し、それを run() / compile() で実行・コンパイルできるようになります。このとき、クロージャによる変数キャプチャの解析は CodeGen.Resolver が担当します。

この仕組みを使って実装された6つのサンプル・フロントエンドが examples/languages/ に収録されています。

mini-js — ES6 のサブセット
mini-culebra — Culebra 自身のサブセット
mini-csharp
mini-lua
mini-go
PL/0 — CodeGen を使って実装した、もう1つの PL/0 実装

----------

・つまり、Culebra の中から 「別のプログラミング言語を解析 → 構文木を IR に変換 → バイトコードへコンパイル → 実行」 という一連の処理を行えるようになったということかな?
・言語処理系サンプルを見ると、文法と、それぞれの言語向けな処理をひたすら書いているだけっていう感じ。これで
・LLVMみたいな環境がCulebra上に構築されたということだけど、実行がCulebra上なので、インタプリタやJIT上でも別の言語が動くっていうことになるのかな。
・他にも結構メジャーなアップデートがあるみたいだけど、それはまたいずれ。

2026.09.11 21:54

プログラミング言語culebraで遊ぶ(集合)


・というところで本日はsets。日本語版ドキュメントでは「集合」と名付けられている。
1)集合は型を問わず何でも飲み込む
2)重複したものは一つにまとめられる
3)比較は「要素の有無」の比較になるので登録順は問わない
4)演算は演算子ではなく、メソッドを使う(ラムダ式の"|"と区別できなくなるからだとか)
5)要素が1個以下の時は”,”を付ける(オブジェクトと区別できなくなるので)
というあたりかな。

----------
let s0 = {1, 2, 3}
let s1 = {3, 2, 1, 2, 3}
let one = {3.14,} # trailing comma forces a 1-element Set
let mixed = {1, 'two', 3.14, true}
let mixed2 = {1, 'two', 3.15, true}
let mixed_array = mixed.to_array() # 配列に変換

println("s0={s0} s1={s1} (s0==s1)=>{s0==s1}") # 重複要素は消え、順番が違っていても一致
println("one = {one}")
println("mixed = {mixed}")
println("mixed2 = {mixed2}")
println("mixed_array = {mixed_array}")
println(".....")
println("Size of one = {one.size()}") # 要素数
println("mixed one = {mixed.diff(one)}") # oneに無いもの
println("mixed mixed2 = {mixed.diff(mixed2)}") # mixed2に無いもの
println("mixed < or > mixed2 = {mixed.union(mixed2)}") # 少なくともどちらか一方にあるもの
println("mixed mixed2 = {mixed.intersect(mixed2)}") # 両方に含まれるもの
println("mixed mixed2 = {mixed.sym_diff(mixed2)}") # どちらか一方にだけ含まれるもの
println("mixed_array[1] = {mixed_array[1]}") # 配列に変換すればインデックスが使える
# println("mixed[1] = {mixed[1]}") # これはだめ
-----
実行結果:
s0={1, 2, 3} s1={3, 2, 1} (s0==s1)=>true
one = {3.14}
mixed = {1, 'two', 3.14, true}
mixed2 = {1, 'two', 3.15, true}
mixed_array = [1, 'two', 3.14, true]
.....
Size of one = 1
mixed one = {1, 'two', true}
mixed mixed2 = {3.14}
mixed < or > mixed2 = {1, 'two', 3.14, true, 3.15}
mixed mixed2 = {1, 'two', true}
mixed mixed2 = {3.14, 3.15}
mixed_array[1] = two
----------

2026.09.11 13:54

電子証明書の更新


・「ボチボチ電子証明書の有効期限が切れるから更新してね」というメッセージ。了解です。やっておこう・・・と思ったら時間外。
・そうなんだよね。法人口座はセキュリティ面から個人口座より色々厳しいのだ。
・昨日都心方面に行って結構歩いたよなぁ、帰りも最寄り駅から自宅まで徒歩だったし・・・と思ってヘルスケアデータを見たら8300歩程度。意外と歩数はいかないものだな。
・というところで、実験用の電源を検討していたのだけど、USBのPPS機能でできちゃうのだな。まぁ、CH224Aとかいう中華チップを使うのが定番みたいだけど、ちょっと探すとPPSの仕様書はあるわけで、1から手作りしてみる手もあるのかな。

2026.09.10 09:28

中革連の債務残高が10億?


・ということで、いろいろ物議を醸し出しているけど、ちょっと気になるのはそんなことを今までやっていたの?ということ。
・選挙の時に業者などへの支払いを猶予してもらって政党交付金で支払うなんていうやり方を立憲民主党やら公明党時代にやっていたのだろうか。
・代表者の説明だと20億円くらい使って、まだ残債が10億円くらいあるというけど、ちょっと眺めた範囲でも昨年度からの繰越金が40億円もあるという話で、支払えないという額ではない。
・議員数が減ったからこの先不安だとか言ってもそれはちょっと変な気がする。
・もう一つ気になるのは、そもそもその10億とも20億とも言われる負債(未払金?買掛金?)は一体誰の名義なのかということかな。
・選挙にあたって候補者のポスターの制作費などを党として負担したのかな?そして、落選した議員の分は?などといろいろ考えてしまう。
・そんな中で都心方面へ。電車に乗るのはいつぶりだろう。
・で、やっぱりやってしまった。帰りの電車の混雑の中で晴雨兼用傘を紛失してしまった。
・まだ新しいものだったんだけどな。がっくし。



2026.09.09 20:45

culebraで遊ぶ(例外)

・culebraでは例外の扱いもお気楽なようだ。
・もう、投げたくなったらthrowすれば良い。
・シンプルにメッセージを送るなら”ERROR!"なんて具合に文字列を投げても良いし、この例みたいにthrowの右に{}で囲んでタグと値のセットを投げても良い。これはpythonで言うところの辞書型だけど、culebraでは「Object型」と呼ぶらしい。(println("{type_of(e)}")として表示させるとObjectとなるので)
・ということで、ここから先インスタンスをオブジェクトと呼ぶのはやめよう。
----------
fn divide(a, b) {
if (b == 0) {
throw { // ユーザ独自の例外を投げてみる
kind: "operator",
type: "divide",
msg: "division by zero",
left: a,
right:b
}
}
if (b == 1) {
throw "divide : {a}/{b}"
}
a / b
}
try {
x = divide(10, 2) // これは正常終了
inspect(x)
x = divide(10, 0) // これで例外発生させてみる
inspect(x) // ここには来ない
}
catch e {
inspect("error: {e}")
println("kind={e.kind}")
println("type={e.type}")
}
ーーーーー
実行結果:
5
'error: {kind: 'operator', type: 'divide', msg: 'division by zero', left: 10, right: 0}'
kind=operator
type=divide
-----
x = divide(10,1)としたときは
5
'error: divide : 10/1'
kind=nil
type=nil
----------

・このあたりの記述もC++やPythonよりシンプルなんじゃないかな。

2026.09.08 18:55

culebraで遊ぶ(演算子のオーバーロード)

・というところで、本日は軽く演算子のオーバーロード。もちろんCulebraも対応している。
・C++だと結構煩雑でこんな感じになる。
----------
class Vector {
public:
int x;
int y;
Vector(int x, int y) : x(x), y(y) {}
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
};
----------

視認性が著しく悪いし、煩雑で書いていても面倒くさい。
pythonだと
----------
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x,
self.y + other.y)
---------

こんな感じになる。じゃあ、clebraは?っていうと
----------
class Vect2 {
x:Float
y:Float
new(x:Long|Float, y:Long|Float) {
self.x = to_float(x)
self.y = to_float(y)
}
__add__(dat) { // 加算
Vect2.new(self.x + dat.x, self.y + dat.y)
}
__mul__(dat) { // 加算
self.x * dat.x + self.y * dat.y
}
}

a = Vect2(1,2)
b = Vect2(2,3)

println("a=[{a}]")
println("b=[{b}]")
println("a+b=[{a+b}]")
println("a*b=[{a*b}]")
----------

てな塩梅。Pythonより更に簡素。せっかくなので、サンプルにしたがってLongとFloat型を受け入れられるようにしてみた。
実行すると
-----
a=[Vect2 {mut x: 1.0, mut y: 2.0}]
b=[Vect2 {mut x: 2.0, mut y: 3.0}]
a+b=[Vect2 {mut x: 3.0, mut y: 5.0}]
a*b=[8.0]
-----

なんていう具合。Pythonにあった引数のselfだのdefなんて省略だし、returnは付けても良いけど、省略してもかまわない。
・要するにClebraの基本思想は「わかりきったことをいちいち書かせるな!」なんだろうな。


2026.09.07 07:39

culebraで遊ぶ(デコレータ:その3:classのデコレータ)


・というところで、classに対するデコレータ。
・基本的には関数に対するそれと同じで、
 @XXXXなんていうのをclassの定義の前に付けてあると、起動時にXXXX()という関数が自動的に呼ばれてこの関数が戻したclassによって元のclassが上書きされたようになる(すり替えが行われる)ということ。
・例によってGeminiくんが生成したサンプルにあれこれ手を加えてみたのがこれ。
----------
// 元のクラスを受け取って、「改造版の新しいクラス」を返すデコレータ
let log_instantiation = fn (OriginalClass) {
println("log_instantiation")
// 元のクラスを包み込む(ラップする)新しいクラスを定義する
class WrappedClass {
new(x, y) {
println("Wrapped Class x={x}, y={y}")
// 元クラス(OriginalClass)からオブジェクト(インスタンス)生成
self.inner = OriginalClass.new(x+1,y+1)
}
get_x() {
println("代替元のxを読み出します")
return self.inner.x
}
}
// 代替クラスを返す
return WrappedClass
}
@log_instantiation
class Point {
new(x, y) {
println("Point x={x},y={y}")
self.x = x
self.y = y
}
}
println("Start")
let p = Point(10, 20)
println(p.get_x())
-----
実行結果:
log_instantiation // ユーザコード実行前にデコレータが呼ばれる
Start // ここからユーザコード
Wrapped Class x=10, y=20 // 代替したWrappedClassのコンストラクタ
Point x=11,y=21 // WrappedClassからPointインスタンス(オブジェクト)生成
代替元のxを読み出します
11
----------


・というところで、functionのデコレータと大差はない。ただ、公式ドキュメント側の方ではこんな感じ。
----------
let mark = fn (cls) {
cls.marked = true
cls
}
@mark
class Point {
new(x, y) {
self.x = x
self.y = y
}
}
j = Point(4,5)
println("{j.class}")
println("{j.class.marked}")
println("{(j.class).marked}")
println("{Point.marked}") # true
-----
実行結果:
true
----------

・こちらのサンプルのcls.markedって何だ?っていう話になる。
引数として渡されたのはPointクラス。これにmarkedとやらを何やら付加している。これはclassのメンバの追加?それをprintlnで・・・と思ったけど、これは単にmark関数が返したcls・・・これは代替元クラスそのもので、インタンス化されていないので、メンバなんてアクセスできるわけもない。
・ということで、しばし悩んだけど例によってGeminiくんとあれこれやってやっと納得したのは、これは金型の刻印みたいなものということ。
・鯛焼きを作る金型みたいなものを想像する。この金型がclassで金型を使ってパッコン!と作られる鯛焼きがインスタンスやらオブジェクトやらと言われるもの。
・で、このサンプルの.markedとか言って追加しているものは、この金型の外側につけられた金型メーカーの刻印みたいなものということ。
・なので、Point.markedはこの刻印を読んでいる。
・あくまでも”金型の外側の刻印”なので、このクラス(mark()が返したクラス:cls)から生成されたオブジェクトには.markedなんてメンバはない。
・この刻印のことはGeminiによるとメタデータと呼ぶらしい。
・ちょっと不思議なのは

 j = Point(2,3)
println("{j.class}")
println("{j.class.marked}")

 とすると、j.classは"Point"だと言うけど、”j.class.marked"はnilになってしまうこと。
・さて、これはどう解釈すると良いのかな。とりあえずの対処としては

class Point {
new(x, y) {
self.myclass = Point // 明示的にクラスオブジェクトを保持しておく
・・・・・・

なんて具合にクラスそのものをバックアップしておいて

j = Point(4, 5)
println("{j.myclass.marked}") // これなら true が取れる!

とすればtrueとなる。でも美しくないな。これはいずれ変更・修正されるのかな?

2026.09.06 16:51

culebraで遊ぶ(デコレータ:その2:多重デコレータ)


・というところで、今度は公式ドキュメント側のデコレータのセクションを読むと、
-----
@a
@b
fn foo() { ... }
-----

なんて具合にダブルで使うこともOKらしい。この場合、実行はfoo = a(b())という具合になると書いてある。後で確認しよう。
・で、ドキュメントにあるサンプルコードを元にしてあちこち書き足してみたのはこんな感じだ。公式では最後のところが単にgreet()になって何も表示されなかったので、println("{greet()}")に書き換えた
-----
let tag = fn (f) {
println("tag")
mut x=3
fn () {
println("x={x}")
x+=1
"[{f()} world!]"

}
}
@tag
fn greet() {
"hello"
}
@tag
fn greet2() {
"んちゃ!"
}
println("{greet()}") # "[hello world!]"
println("{greet()}") # "[hello world!]"
println("{greet2()}") # "[hello world!]"
---
実行結果
tag
tag
x=3
[hello world!]
x=4
[hello world!]
x=3
[んちゃ! world!]
-----
]
・どちらかというと、こんな風にlet tag = fn (f) {...}と書くほうが統一感があって良いかもしれないな。
・ってことで、最初に示した@a @bパターンも試してみる
-----
let tag = fn (f) {
fn () {
"[tag:{f()}]"
}
}
let tag2 = fn (f) {
fn () {
"[Tag2:{f()}]"
}
}

@tag
@tag2
fn greet() {
"hello"
}
println("{greet()}")
ーーー
実行結果
[tag:[Tag2:hello]]
-----

ちなみに
@tag2
@tag
と入れ替えると
[Tag2:[tag:hello]]
になる。
・ちょっとややこしいようだけど、記述の下から順番に関数オブジェクトがスタックに積まれている感じなんだろう。この例で言えばまさに
 tag()
 tag2()
 greet()
という感じでスタッキングされている感じ。
 1)tag2()オブジェクトを引数にしているtag()オブジェクト
 2)greet()を引数にしているtag2()オブジェクト
が重なって、結果的に
 ”greet()を引数にしているtag2()オブジェクト”を引数にしているtag2オブジェクト
 が生成されるという感じ。

・で、デコレータはclassにも適用できるということだけど、ちょっと長くなってきたのと公式サンプルでちょっと頭をひねってしまったので今日はこのへんで一休さん。