Added 2 tests and asthelpers.go
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package zig_test
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -9,13 +8,45 @@ import (
|
||||
"git.frop.prof/luke/go-zig-compiler/internal/zig"
|
||||
)
|
||||
|
||||
func Expect[T cmp.Ordered](expected, actual T) error {
|
||||
func Expect(expected, actual string) error {
|
||||
if expected != actual {
|
||||
return fmt.Errorf("\nExpected: %v\nActual: %v", expected, actual)
|
||||
message := fmt.Sprintf("\nExpected:\n%v\nActual:\n%v", expected, actual)
|
||||
message += fmt.Sprintf("\n%q", actual)
|
||||
|
||||
// Find the first difference (handle rune/byte mismatch)
|
||||
minLen := len(expected)
|
||||
if len(actual) < minLen {
|
||||
minLen = len(actual)
|
||||
}
|
||||
for i := 0; i < minLen; i++ {
|
||||
if expected[i] != actual[i] {
|
||||
message += fmt.Sprintf("\nDifference at index %d: expected '%c', got '%c'", i, expected[i], actual[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(expected) != len(actual) {
|
||||
message += fmt.Sprintf("\nLength mismatch: expected %d bytes, got %d bytes", len(expected), len(actual))
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s", message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// runZigASTTest is a helper to check if the Zig AST renders as expected.
|
||||
func runZigASTTest(t *testing.T, expected string, root *zig.Root) {
|
||||
t.Helper()
|
||||
sb := new(strings.Builder)
|
||||
err := zig.Write(sb, root)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
actual := sb.String()
|
||||
if err = Expect(expected, actual); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelloWorld(t *testing.T) {
|
||||
expected := `//! Hello, world!
|
||||
|
||||
@@ -30,52 +61,179 @@ fn main() void {
|
||||
ContainerDocComment: "Hello, world!",
|
||||
ContainerMembers: []*zig.ContainerMember{
|
||||
{
|
||||
Decl: &zig.GlobalVarDecl{
|
||||
Const: true,
|
||||
Name: "std",
|
||||
Value: &zig.CallExpr{
|
||||
Fun: &zig.Identifier{Name: "@import"},
|
||||
Args: []zig.Expr{
|
||||
&zig.Literal{Kind: "string", Value: "std"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Decl: zig.DeclareGlobalVar("std", zig.Call(
|
||||
zig.Id("@import"),
|
||||
zig.Lit("string", "std"),
|
||||
), zig.GlobalVarConst),
|
||||
},
|
||||
{
|
||||
Decl: &zig.FnDecl{
|
||||
Name: "main",
|
||||
ReturnType: &zig.Identifier{Name: "void"},
|
||||
Body: &zig.Block{
|
||||
Stmts: []zig.Stmt{
|
||||
&zig.ExprStmt{
|
||||
Expr: &zig.CallExpr{
|
||||
Fun: &zig.FieldAccessExpr{
|
||||
Receiver: &zig.FieldAccessExpr{
|
||||
Receiver: &zig.Identifier{Name: "std"},
|
||||
Field: "debug",
|
||||
},
|
||||
Field: "print",
|
||||
},
|
||||
Args: []zig.Expr{
|
||||
&zig.Literal{Kind: "string", Value: "Hello, world!\n"},
|
||||
&zig.InitListExpr{Empty: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Decl: zig.DeclareFn(
|
||||
"main",
|
||||
zig.Id("void"),
|
||||
zig.NewBlock(
|
||||
zig.NewExprStmt(
|
||||
zig.Call(
|
||||
zig.FieldAccess(
|
||||
zig.FieldAccess(zig.Id("std"), "debug"),
|
||||
"print",
|
||||
),
|
||||
zig.Lit("string", `Hello, world!\n`),
|
||||
zig.InitList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
nil, // params
|
||||
0, // flags
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
sb := new(strings.Builder)
|
||||
err := zig.Write(sb, root)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
actual := sb.String()
|
||||
|
||||
if err = Expect(expected, actual); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
runZigASTTest(t, expected, root)
|
||||
}
|
||||
|
||||
func TestEvenOdd(t *testing.T) {
|
||||
expected := `//! Abc
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() !void {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
var i: i32 = 1;
|
||||
while (i <= 5) : (i += 1) {
|
||||
if (i % 2 == 0) {
|
||||
try stdout.writeAll("even: {d}\n", .{i});
|
||||
} else {
|
||||
try stdout.writeAll("odd: {d}\n", .{i});
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
root := &zig.Root{
|
||||
ContainerDocComment: "Abc",
|
||||
ContainerMembers: []*zig.ContainerMember{
|
||||
{
|
||||
Decl: zig.DeclareGlobalVar("std",
|
||||
zig.Call(
|
||||
zig.Id("@import"),
|
||||
zig.Lit("string", "std"),
|
||||
),
|
||||
zig.GlobalVarConst,
|
||||
),
|
||||
},
|
||||
{
|
||||
Decl: zig.DeclareFn(
|
||||
"main",
|
||||
zig.Id("!void"),
|
||||
zig.NewBlock(
|
||||
// const stdout = std.io.getStdOut().writer();
|
||||
zig.DeclareVarStmt(true, []string{"stdout"}, nil,
|
||||
zig.Call(
|
||||
zig.FieldAccess(
|
||||
zig.Call(
|
||||
zig.FieldAccess(
|
||||
zig.FieldAccess(zig.Id("std"), "io"),
|
||||
"getStdOut",
|
||||
),
|
||||
),
|
||||
"writer",
|
||||
),
|
||||
),
|
||||
),
|
||||
// var i: i32 = 1;
|
||||
zig.DeclareVarStmt(false, []string{"i"}, zig.Id("i32"), zig.Lit("int", "1")),
|
||||
// while (i <= 5) : (i += 1) { ... }
|
||||
&zig.LoopStmt{
|
||||
Kind: "while",
|
||||
Prefix: &zig.WhilePrefix{
|
||||
Cond: zig.Binary("<=", zig.Id("i"), zig.Lit("int", "5")),
|
||||
Continue: zig.Binary("+=", zig.Id("i"), zig.Lit("int", "1")),
|
||||
},
|
||||
Body: zig.NewBlockStmt(
|
||||
&zig.IfStmt{
|
||||
Cond: zig.Binary("==",
|
||||
zig.Binary("%", zig.Id("i"), zig.Lit("int", "2")),
|
||||
zig.Lit("int", "0"),
|
||||
),
|
||||
Then: zig.NewBlockStmt(
|
||||
zig.NewExprStmt(
|
||||
zig.Try(
|
||||
zig.Call(
|
||||
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
||||
zig.Lit("string", `even: {d}\n`),
|
||||
zig.InitList(zig.Id("i")),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Else: zig.NewBlockStmt(
|
||||
zig.NewExprStmt(
|
||||
zig.Try(
|
||||
zig.Call(
|
||||
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
||||
zig.Lit("string", `odd: {d}\n`),
|
||||
zig.InitList(zig.Id("i")),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
nil,
|
||||
zig.FnExport,
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runZigASTTest(t, expected, root)
|
||||
}
|
||||
|
||||
func TestStructWithFieldsAndMethod(t *testing.T) {
|
||||
expected := `const MyStruct = struct {
|
||||
const Self = @This();
|
||||
data: ?*u8,
|
||||
count: u32,
|
||||
|
||||
pub fn reset(self: Self) void {
|
||||
self.count = 0;
|
||||
}
|
||||
};
|
||||
`
|
||||
|
||||
root := &zig.Root{
|
||||
ContainerMembers: []*zig.ContainerMember{
|
||||
{
|
||||
Decl: zig.DeclareGlobalVar("MyStruct",
|
||||
zig.StructDecl(
|
||||
zig.Field("Self", nil, nil, zig.Call(zig.Id("@This"))),
|
||||
zig.Field("data", zig.OptionalType(zig.PointerType(zig.Id("u8"))), nil, nil),
|
||||
zig.Field("count", zig.Id("u32"), nil, nil),
|
||||
zig.Method(zig.DeclareFn(
|
||||
"reset",
|
||||
zig.Id("void"),
|
||||
zig.NewBlock(
|
||||
zig.NewExprStmt(
|
||||
zig.Binary("=",
|
||||
zig.FieldAccess(zig.Id("self"), "count"),
|
||||
zig.Lit("int", "0"),
|
||||
),
|
||||
),
|
||||
),
|
||||
[]*zig.ParamDecl{
|
||||
zig.Param("self", zig.Id("Self")),
|
||||
},
|
||||
zig.FnExport,
|
||||
)),
|
||||
),
|
||||
zig.GlobalVarConst,
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runZigASTTest(t, expected, root)
|
||||
}
|
||||
|
Reference in New Issue
Block a user