Skip to content

Commit bacc146

Browse files
committed
Albireo: Emit WAT
1 parent 1f5a1c3 commit bacc146

File tree

6 files changed

+72
-12
lines changed

6 files changed

+72
-12
lines changed

albireo/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ sources = \
1616
tokenize.lex.sml \
1717
parse.grm.sml \
1818
parse.sml \
19+
emit.sml \
1920
main.sml
2021

2122
albireo: albireo.mlb $(sources)

albireo/albireo.mlb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ in
99
tokenize.lex.sml
1010
parse.grm.sml
1111
parse.sml
12+
emit.sml
1213
main.sml
1314
end
1415
end

albireo/emit.sml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
(*
2+
* Copyright (c) 2025 ARATA Mizuki
3+
* This file is part of LunarML.
4+
*)
5+
structure AlbireoEmit :> sig
6+
val emit : AlbireoSyntax.dec list -> string
7+
end = struct
8+
structure S = AlbireoSyntax
9+
fun emitHeapTy S.HT_ANY = "any"
10+
| emitHeapTy S.HT_I31 = "i31"
11+
| emitHeapTy S.HT_EXTERN = "extern"
12+
fun emitTy S.I32 = "i32"
13+
| emitTy S.I64 = "i64"
14+
| emitTy S.F32 = "f32"
15+
| emitTy S.F64 = "f64"
16+
| emitTy S.V128 = "v128"
17+
| emitTy (S.REF { nullable, to }) =
18+
if nullable then
19+
"(ref null " ^ emitHeapTy to ^ ")"
20+
else
21+
"(ref " ^ emitHeapTy to ^ ")"
22+
fun compileExp (S.IntConstExp (i, SOME S.IT_64)) = ["i64.const " ^ CharVector.map (fn #"~" => #"-" | c => c) (Int.toString i)]
23+
| compileExp (S.IntConstExp (i, _)) = ["i32.const " ^ CharVector.map (fn #"~" => #"-" | c => c) (Int.toString i)]
24+
| compileExp (S.VarExp id) = ["local.get $" ^ id]
25+
| compileExp (S.BinExp (p, a, b)) =
26+
let val insn = case p of
27+
S.PlusOp => "i32.add"
28+
| S.MinusOp => "i32.sub"
29+
| S.TimesOp => "i32.mul"
30+
| S.DivOp => "i32.div_s"
31+
in compileExp a @ compileExp b @ [insn]
32+
end
33+
fun emitDec (S.FuncDec { name, params, results, body }) =
34+
let val name' = "(export \"" ^ name ^ "\")"
35+
val params' = List.map (fn (id, ty) => "(param $" ^ id ^ " " ^ emitTy ty ^ ")") params
36+
val results' = List.map (fn ty => "(result " ^ emitTy ty ^ ")") results
37+
val body' = case body of
38+
[S.ReturnStat exps] => List.concat (List.map compileExp exps) @ ["return"]
39+
| _ => raise Fail "unsupported function body"
40+
in "(func " ^ name' ^ "\n" ^ String.concatWith "\n" (params' @ results' @ body') ^ ")"
41+
end
42+
fun emit decs = "(module\n" ^ String.concatWith "\n" (List.map emitDec decs) ^ ")"
43+
end;

albireo/main.sml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
fun makeInputFromString s =
2-
let val r = ref s
3-
in fn _ => let val x = !r in r := ""; x end
1+
fun compile filename =
2+
let
3+
val strm = TextIO.openIn filename
4+
fun getInput n = TextIO.inputN (strm, n)
5+
val lexer = AlbireoParser.makeLexer getInput filename;
6+
fun onError (message, p1, p2) = raise Fail message;
7+
in
8+
let val (program, _) = AlbireoParser.parse ((* lookahead *) 0, lexer, onError, filename)
9+
in print (AlbireoEmit.emit program ^ "\n")
10+
end
11+
handle AlbireoParser.ParseError => ()
12+
| Fail s => print (s ^ "\n");
13+
TextIO.closeIn strm
414
end;
5-
val name = "<test input>";
6-
val lexer = AlbireoParser.makeLexer (makeInputFromString "func foo(x: i32) -> i32 { return x * x; }") name;
7-
fun onError (message, p1, p2) = raise Fail message;
8-
val () =
9-
let val (program, _) = AlbireoParser.parse ((* lookahead *) 0, lexer, onError, name)
10-
in print "OK.\n"
11-
end
12-
handle AlbireoParser.ParseError => ()
13-
| Fail s => print (s ^ "\n");
15+
fun main [filename] = compile filename
16+
| main _ = print "albireo <filename>";
17+
val () = main (CommandLine.arguments ());

albireo/runtest.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { readFileSync } from "node:fs";
2+
const wasmBuffer = readFileSync("test.wasm");
3+
const wasmModule = await WebAssembly.instantiate(wasmBuffer);
4+
const { foo } = wasmModule.instance.exports;
5+
console.log(foo(1));
6+
console.log(foo(2));
7+
console.log(foo(3));

albireo/test.albireo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
func foo(x: i32) -> i32
2+
{
3+
return x * x + 2 * x;
4+
}

0 commit comments

Comments
 (0)