Add comprehensive Zig syntax test coverage
- Add support for error sets and error union types - Implement for loops with index and payload syntax - Add defer, break, continue, and switch statements - Support unary expressions and array indexing - Add unreachable expression and test declarations - Extend AST with new type expressions (array, error union) - Update formatter to handle all new syntax elements - Fix formatting for switch prongs, payloads, and blocks
This commit is contained in:
@@ -92,6 +92,217 @@ fn main() void {
|
||||
runZigASTTest(t, expected, root)
|
||||
}
|
||||
|
||||
func TestCompoundFeatures(t *testing.T) {
|
||||
expected := `const ProcessError = error{
|
||||
InvalidInput,
|
||||
OutOfBounds,
|
||||
};
|
||||
|
||||
fn processData(values: [5]?i32) ProcessError!i32 {
|
||||
var result: i32 = 0;
|
||||
defer std.debug.print("Cleanup\n", .{});
|
||||
for (values, 0..) |opt_val, idx| {
|
||||
if (opt_val) |val| {
|
||||
switch (val) {
|
||||
-10...-1 => result += -val,
|
||||
0 => continue,
|
||||
1...10 => {
|
||||
if (idx > 3) break;
|
||||
result += val;
|
||||
},
|
||||
else => return ProcessError.InvalidInput,
|
||||
}
|
||||
} else {
|
||||
if (idx == 0) return ProcessError.InvalidInput;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (values[0] == null) {
|
||||
unreachable;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
test "processData" {
|
||||
const data = .{ 5, -3, 0, null, 10 };
|
||||
const result = try processData(data);
|
||||
try std.testing.expectEqual(@as(i32, 8), result);
|
||||
}
|
||||
`
|
||||
|
||||
root := &zig.Root{
|
||||
ContainerMembers: []*zig.ContainerMember{
|
||||
{
|
||||
Decl: zig.DeclareGlobalVar("ProcessError",
|
||||
zig.ErrorSet("InvalidInput", "OutOfBounds"),
|
||||
zig.GlobalVarConst,
|
||||
),
|
||||
},
|
||||
{
|
||||
Decl: zig.DeclareFn(
|
||||
"processData",
|
||||
zig.ErrorUnionType(zig.Id("ProcessError"), zig.Id("i32")),
|
||||
zig.NewBlock(
|
||||
// var result: i32 = 0;
|
||||
zig.DeclareVarStmt(false, []string{"result"}, zig.Id("i32"), zig.Lit("int", "0")),
|
||||
// defer std.debug.print("Cleanup\n", .{});
|
||||
zig.Defer(
|
||||
zig.NewExprStmt(
|
||||
zig.Call(
|
||||
zig.FieldAccess(
|
||||
zig.FieldAccess(zig.Id("std"), "debug"),
|
||||
"print",
|
||||
),
|
||||
zig.Lit("string", `Cleanup\n`),
|
||||
zig.InitList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
// for (values, 0..) |opt_val, idx| { ... }
|
||||
zig.ForLoop(
|
||||
[]zig.ForArg{
|
||||
zig.ForArgExpr(zig.Id("values")),
|
||||
{Expr: zig.Lit("int", "0"), From: zig.Lit("", "")},
|
||||
},
|
||||
zig.PayloadNames([]string{"opt_val", "idx"}, []bool{false, false}),
|
||||
zig.NewBlockStmt(
|
||||
// if (opt_val) |val| { ... } else { ... }
|
||||
zig.IfWithPayload(
|
||||
zig.Id("opt_val"),
|
||||
zig.PayloadNames([]string{"val"}, []bool{false}),
|
||||
zig.NewBlockStmt(
|
||||
// switch (val) { ... }
|
||||
zig.Switch(
|
||||
zig.Id("val"),
|
||||
// -10...-1 => result += -val,
|
||||
zig.Prong(
|
||||
[]*zig.SwitchCase{
|
||||
zig.Case(
|
||||
zig.Unary("-", zig.Lit("int", "10")),
|
||||
zig.Unary("-", zig.Lit("int", "1")),
|
||||
),
|
||||
},
|
||||
nil,
|
||||
zig.NewExprStmt(
|
||||
zig.Binary("+=",
|
||||
zig.Id("result"),
|
||||
zig.Unary("-", zig.Id("val")),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 0 => continue,
|
||||
zig.Prong(
|
||||
[]*zig.SwitchCase{
|
||||
zig.Case(zig.Lit("int", "0"), nil),
|
||||
},
|
||||
nil,
|
||||
zig.Continue(""),
|
||||
),
|
||||
// 1...10 => { ... }
|
||||
zig.Prong(
|
||||
[]*zig.SwitchCase{
|
||||
zig.Case(zig.Lit("int", "1"), zig.Lit("int", "10")),
|
||||
},
|
||||
nil,
|
||||
zig.NewBlockStmt(
|
||||
zig.If(
|
||||
zig.Binary(">", zig.Id("idx"), zig.Lit("int", "3")),
|
||||
zig.Break("", nil),
|
||||
nil,
|
||||
),
|
||||
zig.NewExprStmt(
|
||||
zig.Binary("+=", zig.Id("result"), zig.Id("val")),
|
||||
),
|
||||
),
|
||||
),
|
||||
// else => return ProcessError.InvalidInput,
|
||||
zig.Prong(
|
||||
[]*zig.SwitchCase{zig.ElseCase()},
|
||||
nil,
|
||||
zig.Return(
|
||||
zig.FieldAccess(zig.Id("ProcessError"), "InvalidInput"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// else block
|
||||
zig.NewBlockStmt(
|
||||
zig.If(
|
||||
zig.Binary("==", zig.Id("idx"), zig.Lit("int", "0")),
|
||||
zig.Return(zig.FieldAccess(zig.Id("ProcessError"), "InvalidInput")),
|
||||
nil,
|
||||
),
|
||||
zig.Break("", nil),
|
||||
),
|
||||
),
|
||||
),
|
||||
nil,
|
||||
),
|
||||
// if (values[0] == null) { unreachable; }
|
||||
zig.If(
|
||||
zig.Binary("==",
|
||||
zig.Index(zig.Id("values"), zig.Lit("int", "0")),
|
||||
zig.Id("null"),
|
||||
),
|
||||
zig.NewBlockStmt(
|
||||
zig.NewExprStmt(zig.Unreachable()),
|
||||
),
|
||||
nil,
|
||||
),
|
||||
// return result;
|
||||
zig.Return(zig.Id("result")),
|
||||
),
|
||||
[]*zig.ParamDecl{
|
||||
zig.Param("values", zig.ArrayType(zig.Lit("int", "5"), zig.OptionalType(zig.Id("i32")))),
|
||||
},
|
||||
0,
|
||||
),
|
||||
},
|
||||
{
|
||||
Decl: zig.Test("processData",
|
||||
zig.NewBlock(
|
||||
// const data = [_]?i32{ 5, -3, 0, null, 10 };
|
||||
zig.DeclareVarStmt(true, []string{"data"}, nil,
|
||||
&zig.InitListExpr{
|
||||
Values: []zig.Expr{
|
||||
zig.Lit("int", "5"),
|
||||
zig.Unary("-", zig.Lit("int", "3")),
|
||||
zig.Lit("int", "0"),
|
||||
zig.Id("null"),
|
||||
zig.Lit("int", "10"),
|
||||
},
|
||||
},
|
||||
),
|
||||
// const result = try processData(data);
|
||||
zig.DeclareVarStmt(true, []string{"result"}, nil,
|
||||
zig.Try(zig.Call(zig.Id("processData"), zig.Id("data"))),
|
||||
),
|
||||
// try std.testing.expectEqual(@as(i32, 8), result);
|
||||
zig.NewExprStmt(
|
||||
zig.Try(
|
||||
zig.Call(
|
||||
zig.FieldAccess(
|
||||
zig.FieldAccess(zig.Id("std"), "testing"),
|
||||
"expectEqual",
|
||||
),
|
||||
zig.Call(
|
||||
zig.Id("@as"),
|
||||
zig.Id("i32"),
|
||||
zig.Lit("int", "8"),
|
||||
),
|
||||
zig.Id("result"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runZigASTTest(t, expected, root)
|
||||
}
|
||||
|
||||
func TestEvenOdd(t *testing.T) {
|
||||
expected := `//! Abc
|
||||
|
||||
|
Reference in New Issue
Block a user