mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
translate-c: more binaryoperator chagnes, blocks and unary type expressions
This commit is contained in:
parent
4c0c9b0755
commit
f5041caa2e
@ -68,16 +68,15 @@ const Scope = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents an in-progress ast.Node.Block. This struct is stack-allocated.
|
||||
/// When it is deinitialized, it produces an ast.Node.Block which is allocated
|
||||
/// Represents an in-progress Node.Block. This struct is stack-allocated.
|
||||
/// When it is deinitialized, it produces an Node.Block which is allocated
|
||||
/// into the main arena.
|
||||
const Block = struct {
|
||||
base: Scope,
|
||||
statements: std.ArrayList(*ast.Node),
|
||||
statements: std.ArrayList(Node),
|
||||
variables: AliasList,
|
||||
label: ?ast.TokenIndex,
|
||||
mangle_count: u32 = 0,
|
||||
lbrace: ast.TokenIndex,
|
||||
label: ?[]const u8 = null,
|
||||
|
||||
/// When the block corresponds to a function, keep track of the return type
|
||||
/// so that the return expression can be cast, if necessary
|
||||
@ -89,14 +88,11 @@ const Scope = struct {
|
||||
.id = .Block,
|
||||
.parent = parent,
|
||||
},
|
||||
.statements = std.ArrayList(*ast.Node).init(c.gpa),
|
||||
.statements = std.ArrayList(Node).init(c.gpa),
|
||||
.variables = AliasList.init(c.gpa),
|
||||
.label = null,
|
||||
.lbrace = try appendToken(c, .LBrace, "{"),
|
||||
};
|
||||
if (labeled) {
|
||||
blk.label = try appendIdentifier(c, try blk.makeMangledName(c, "blk"));
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
blk.label = try blk.makeMangledName(c, "blk");
|
||||
}
|
||||
return blk;
|
||||
}
|
||||
@ -107,31 +103,16 @@ const Scope = struct {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
fn complete(self: *Block, c: *Context) !*ast.Node {
|
||||
fn complete(self: *Block, c: *Context) !Node {
|
||||
// We reserve 1 extra statement if the parent is a Loop. This is in case of
|
||||
// do while, we want to put `if (cond) break;` at the end.
|
||||
const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);
|
||||
const rbrace = try appendToken(c, .RBrace, "}");
|
||||
if (self.label) |label| {
|
||||
const node = try ast.Node.LabeledBlock.alloc(c.arena, alloc_len);
|
||||
node.* = .{
|
||||
.statements_len = self.statements.items.len,
|
||||
.lbrace = self.lbrace,
|
||||
.rbrace = rbrace,
|
||||
.label = label,
|
||||
};
|
||||
mem.copy(*ast.Node, node.statements(), self.statements.items);
|
||||
return &node.base;
|
||||
} else {
|
||||
const node = try ast.Node.Block.alloc(c.arena, alloc_len);
|
||||
node.* = .{
|
||||
.statements_len = self.statements.items.len,
|
||||
.lbrace = self.lbrace,
|
||||
.rbrace = rbrace,
|
||||
};
|
||||
mem.copy(*ast.Node, node.statements(), self.statements.items);
|
||||
return &node.base;
|
||||
}
|
||||
const stmts = try c.arena.alloc(Node, alloc_len);
|
||||
mem.copy(Node, stmts, self.statements.items);
|
||||
return Node.block.create(c.arena, .{
|
||||
.lable = self.label,
|
||||
.stmts = stmts,
|
||||
});
|
||||
}
|
||||
|
||||
/// Given the desired name, return a name that does not shadow anything from outer scopes.
|
||||
@ -1390,7 +1371,7 @@ fn transBinaryOperator(
|
||||
// signed integer division uses @divTrunc
|
||||
const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
|
||||
const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
|
||||
const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs});
|
||||
const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||
return maybeSuppressResult(c, scope, result_used, div_trunc);
|
||||
}
|
||||
},
|
||||
@ -1399,7 +1380,7 @@ fn transBinaryOperator(
|
||||
// signed integer division uses @rem
|
||||
const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
|
||||
const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
|
||||
const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs});
|
||||
const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||
return maybeSuppressResult(c, scope, result_used, rem);
|
||||
}
|
||||
},
|
||||
@ -1411,6 +1392,12 @@ fn transBinaryOperator(
|
||||
const node = try transCreateNodeShiftOp(c, scope, stmt, .shr);
|
||||
return maybeSuppressResult(c, scope, result_used, node);
|
||||
},
|
||||
.LAnd => {
|
||||
return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used, true);
|
||||
},
|
||||
.LOr => {
|
||||
return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used, true);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
var op_id: Node.Tag = undefined;
|
||||
@ -1471,17 +1458,19 @@ fn transBinaryOperator(
|
||||
.Or => {
|
||||
op_id = .bit_or;
|
||||
},
|
||||
.LAnd => {
|
||||
op_id = .@"and";
|
||||
},
|
||||
.LOr => {
|
||||
op_id = .@"or";
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
|
||||
const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
|
||||
const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
|
||||
const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
|
||||
|
||||
const lhs = if (isBoolRes(lhs_uncasted))
|
||||
try Node.bool_to_int.create(c.arena, lhs_uncasted)
|
||||
else lhs_uncasted;
|
||||
|
||||
const rhs = if (isBoolRes(rhs_uncasted))
|
||||
try Node.bool_to_int.create(c.arena, rhs_uncasted)
|
||||
else rhs_uncasted;
|
||||
|
||||
const payload = try c.arena.create(ast.Payload.BinOp);
|
||||
payload.* = .{
|
||||
@ -1495,7 +1484,7 @@ fn transBinaryOperator(
|
||||
}
|
||||
|
||||
fn transCompoundStmtInline(
|
||||
rp: RestorePoint,
|
||||
c: *Context,
|
||||
parent_scope: *Scope,
|
||||
stmt: *const clang.CompoundStmt,
|
||||
block: *Scope.Block,
|
||||
@ -1503,16 +1492,16 @@ fn transCompoundStmtInline(
|
||||
var it = stmt.body_begin();
|
||||
const end_it = stmt.body_end();
|
||||
while (it != end_it) : (it += 1) {
|
||||
const result = try transStmt(rp, parent_scope, it[0], .unused, .r_value);
|
||||
const result = try transStmt(c, parent_scope, it[0], .unused, .r_value);
|
||||
try block.statements.append(result);
|
||||
}
|
||||
}
|
||||
|
||||
fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundStmt) TransError!*ast.Node {
|
||||
var block_scope = try Scope.Block.init(rp.c, scope, false);
|
||||
fn transCompoundStmt(c: *Context, scope: *Scope, stmt: *const clang.CompoundStmt) TransError!Node {
|
||||
var block_scope = try Scope.Block.init(c, scope, false);
|
||||
defer block_scope.deinit();
|
||||
try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
|
||||
return try block_scope.complete(rp.c);
|
||||
try transCompoundStmtInline(c, &block_scope.base, stmt, &block_scope);
|
||||
return try block_scope.complete(c);
|
||||
}
|
||||
|
||||
fn transCStyleCastExprClass(
|
||||
@ -3233,22 +3222,18 @@ fn qualTypeGetFnProto(qt: clang.QualType, is_ptr: *bool) ?ClangFunctionType {
|
||||
}
|
||||
|
||||
fn transUnaryExprOrTypeTraitExpr(
|
||||
rp: RestorePoint,
|
||||
c: *Context,
|
||||
scope: *Scope,
|
||||
stmt: *const clang.UnaryExprOrTypeTraitExpr,
|
||||
result_used: ResultUsed,
|
||||
) TransError!*ast.Node {
|
||||
) TransError!Node {
|
||||
const loc = stmt.getBeginLoc();
|
||||
const type_node = try transQualType(
|
||||
rp,
|
||||
stmt.getTypeOfArgument(),
|
||||
loc,
|
||||
);
|
||||
const type_node = try transQualType(rp, stmt.getTypeOfArgument(), loc);
|
||||
|
||||
const kind = stmt.getKind();
|
||||
const kind_str = switch (kind) {
|
||||
.SizeOf => "@sizeOf",
|
||||
.AlignOf => "@alignOf",
|
||||
switch (kind) {
|
||||
.SizeOf => return Node.sizeof.create(c.arena, type_node),
|
||||
.AlignOf => return Node.alignof.create(c.arena, type_node),
|
||||
.PreferredAlignOf,
|
||||
.VecStep,
|
||||
.OpenMPRequiredSimdAlign,
|
||||
@ -3259,12 +3244,7 @@ fn transUnaryExprOrTypeTraitExpr(
|
||||
"Unsupported type trait kind {}",
|
||||
.{kind},
|
||||
),
|
||||
};
|
||||
|
||||
const builtin_node = try rp.c.createBuiltinCall(kind_str, 1);
|
||||
builtin_node.params()[0] = type_node;
|
||||
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
return maybeSuppressResult(rp, scope, result_used, &builtin_node.base);
|
||||
}
|
||||
}
|
||||
|
||||
fn qualTypeHasWrappingOverflow(qt: clang.QualType) bool {
|
||||
@ -3967,8 +3947,8 @@ fn transQualTypeInitialized(
|
||||
return transQualType(rp, qt, source_loc);
|
||||
}
|
||||
|
||||
fn transQualType(rp: RestorePoint, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!*ast.Node {
|
||||
return transType(rp, qt.getTypePtr(), source_loc);
|
||||
fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node {
|
||||
return transType(c, qt.getTypePtr(), source_loc);
|
||||
}
|
||||
|
||||
/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.
|
||||
@ -4318,19 +4298,27 @@ fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []c
|
||||
return &field_access_node.base;
|
||||
}
|
||||
|
||||
fn transCreateNodeSimplePrefixOp(
|
||||
fn transCreateNodeBoolInfixOp(
|
||||
c: *Context,
|
||||
comptime tag: ast.Node.Tag,
|
||||
op_tok_id: std.zig.Token.Id,
|
||||
bytes: []const u8,
|
||||
) !*ast.Node.SimplePrefixOp {
|
||||
const node = try c.arena.create(ast.Node.SimplePrefixOp);
|
||||
node.* = .{
|
||||
.base = .{ .tag = tag },
|
||||
.op_token = try appendToken(c, op_tok_id, bytes),
|
||||
.rhs = undefined, // translate and set afterward
|
||||
scope: *Scope,
|
||||
stmt: *const clang.BinaryOperator,
|
||||
op: ast.Node.Tag,
|
||||
used: ResultUsed,
|
||||
) !Node {
|
||||
std.debug.assert(op == .bool_and or op == .bool_or);
|
||||
|
||||
const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value, true);
|
||||
const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value, true);
|
||||
|
||||
const payload = try c.arena.create(ast.Payload.BinOp);
|
||||
payload.* = .{
|
||||
.base = .{ .tag = op },
|
||||
.data = .{
|
||||
.lhs = lhs,
|
||||
.rhs = rhs,
|
||||
},
|
||||
};
|
||||
return node;
|
||||
return maybeSuppressResult(c, scope, used, &payload.base);
|
||||
}
|
||||
|
||||
fn transCreateNodePtrType(
|
||||
@ -4784,30 +4772,30 @@ fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAcces
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Type {
|
||||
fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
|
||||
switch (ty.getTypeClass()) {
|
||||
.Builtin => {
|
||||
const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
|
||||
return Type.initTag(switch (builtin_ty.getKind()) {
|
||||
.Void => .c_void,
|
||||
.Bool => .bool,
|
||||
.Char_U, .UChar, .Char_S, .Char8 => .u8,
|
||||
.SChar => .i8,
|
||||
.UShort => .c_ushort,
|
||||
.UInt => .c_uint,
|
||||
.ULong => .c_ulong,
|
||||
.ULongLong => .c_ulonglong,
|
||||
.Short => .c_short,
|
||||
.Int => .c_int,
|
||||
.Long => .c_long,
|
||||
.LongLong => .c_longlong,
|
||||
.UInt128 => .u128,
|
||||
.Int128 => .i128,
|
||||
.Float => .f32,
|
||||
.Double => .f64,
|
||||
.Float128 => .f128,
|
||||
.Float16 => .f16,
|
||||
.LongDouble => .c_longdouble,
|
||||
return Node.type.create(c.arena, switch (builtin_ty.getKind()) {
|
||||
.Void => "c_void",
|
||||
.Bool => "bool",
|
||||
.Char_U, .UChar, .Char_S, .Char8 => "u8",
|
||||
.SChar => "i8",
|
||||
.UShort => "c_ushort",
|
||||
.UInt => "c_uint",
|
||||
.ULong => "c_ulong",
|
||||
.ULongLong => "c_ulonglong",
|
||||
.Short => "c_short",
|
||||
.Int => "c_int",
|
||||
.Long => "c_long",
|
||||
.LongLong => "c_longlong",
|
||||
.UInt128 => "u128",
|
||||
.Int128 => "i128",
|
||||
.Float => "f32",
|
||||
.Double => "f64",
|
||||
.Float128 => "f128",
|
||||
.Float16 => "f16",
|
||||
.LongDouble => "c_longdouble",
|
||||
else => return fail(c, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
|
||||
});
|
||||
},
|
||||
@ -4826,61 +4814,25 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
|
||||
.Pointer => {
|
||||
const child_qt = ty.getPointeeType();
|
||||
if (qualTypeChildIsFnProto(child_qt)) {
|
||||
return Type.optional_single_mut_pointer.create(c.arena, try transQualType(c, child_qt, source_loc));
|
||||
return Node.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));
|
||||
}
|
||||
const is_const = child_qt.isConstQualified();
|
||||
const is_volatile = child_qt.isVolatileQualified();
|
||||
const elem_type = try transQualType(c, child_qt, source_loc);
|
||||
if (elem_type.zigTypeTag() == .Opaque) {
|
||||
if (!is_volatile) {
|
||||
if (is_const) {
|
||||
return Type.optional_single_const_pointer.create(c.arena, elem_type);
|
||||
} else {
|
||||
return Type.optional_single_mut_pointer.create(c.arena, elem_type);
|
||||
}
|
||||
}
|
||||
|
||||
return Type.pointer.create(c.arena, .{
|
||||
.pointee_type = elem_type,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = !is_const,
|
||||
.@"volatile" = true,
|
||||
.size = .Single,
|
||||
});
|
||||
if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(rp.c, child_qt)) {
|
||||
return Node.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
|
||||
}
|
||||
|
||||
if (!is_volatile) {
|
||||
if (is_const) {
|
||||
return Type.c_const_pointer.create(c.arena, elem_type);
|
||||
} else {
|
||||
return Type.c_mut_pointer.create(c.arena, elem_type);
|
||||
}
|
||||
}
|
||||
|
||||
return Type.pointer.create(c.arena, .{
|
||||
.pointee_type = elem_type,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = !is_const,
|
||||
.@"volatile" = true,
|
||||
.size = .C,
|
||||
});
|
||||
return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
|
||||
},
|
||||
.ConstantArray => {
|
||||
const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
|
||||
|
||||
const size_ap_int = const_arr_ty.getSize();
|
||||
const size = size_ap_int.getLimitedValue(math.maxInt(usize));
|
||||
const elem_type = try transType1(c, const_arr_ty.getElementType().getTypePtr(), source_loc);
|
||||
|
||||
return Type.array.create(c.arena, .{ .len = size, .elem_type = elem_type });
|
||||
const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);
|
||||
|
||||
return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
|
||||
},
|
||||
.IncompleteArray => {
|
||||
const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
|
||||
@ -4890,25 +4842,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
|
||||
const is_volatile = child_qt.isVolatileQualified();
|
||||
const elem_type = try transQualType(c, child_qt, source_loc);
|
||||
|
||||
if (!is_volatile) {
|
||||
if (is_const) {
|
||||
return Type.c_const_pointer.create(c.arena, elem_type);
|
||||
} else {
|
||||
return Type.c_mut_pointer.create(c.arena, elem_type);
|
||||
}
|
||||
}
|
||||
|
||||
return Type.pointer.create(c.arena, .{
|
||||
.pointee_type = elem_type,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = !is_const,
|
||||
.@"volatile" = true,
|
||||
.size = .C,
|
||||
});
|
||||
return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
|
||||
},
|
||||
.Typedef => {
|
||||
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
|
||||
@ -5233,25 +5167,14 @@ fn finishTransFnProto(
|
||||
return fn_proto;
|
||||
}
|
||||
|
||||
fn revertAndWarn(
|
||||
rp: RestorePoint,
|
||||
err: anytype,
|
||||
source_loc: clang.SourceLocation,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) (@TypeOf(err) || error{OutOfMemory}) {
|
||||
rp.activate();
|
||||
try emitWarning(rp.c, source_loc, format, args);
|
||||
return err;
|
||||
}
|
||||
|
||||
fn emitWarning(c: *Context, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
|
||||
fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
|
||||
const args_prefix = .{c.locStr(loc)};
|
||||
_ = try appendTokenFmt(c, .LineComment, "// {s}: warning: " ++ format, args_prefix ++ args);
|
||||
const value = std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);
|
||||
try scope.appendNode(c.gpa, try Node.warning.create(c.arena, value));
|
||||
}
|
||||
|
||||
fn fail(
|
||||
rp: RestorePoint,
|
||||
c: *Context,
|
||||
err: anytype,
|
||||
source_loc: clang.SourceLocation,
|
||||
comptime format: []const u8,
|
||||
|
||||
@ -107,6 +107,25 @@ pub const Node = extern union {
|
||||
rem,
|
||||
/// @divTrunc(lhs, rhs)
|
||||
div_trunc,
|
||||
/// @boolToInt(lhs, rhs)
|
||||
bool_to_int,
|
||||
|
||||
negate,
|
||||
negate_wrap,
|
||||
bit_not,
|
||||
not,
|
||||
|
||||
block,
|
||||
@"break",
|
||||
|
||||
sizeof,
|
||||
alignof,
|
||||
type,
|
||||
|
||||
optional_type,
|
||||
c_pointer,
|
||||
single_pointer,
|
||||
array_type,
|
||||
|
||||
pub const last_no_payload_tag = Tag.false_literal;
|
||||
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
|
||||
@ -127,6 +146,14 @@ pub const Node = extern union {
|
||||
.@"return",
|
||||
.discard,
|
||||
.std_math_Log2Int,
|
||||
.negate,
|
||||
.negate_wrap,
|
||||
.bit_not,
|
||||
.not,
|
||||
.optional_type,
|
||||
.c_pointer,
|
||||
.single_pointer,
|
||||
.array_type,
|
||||
=> Payload.UnOp,
|
||||
|
||||
.add,
|
||||
@ -180,6 +207,7 @@ pub const Node = extern union {
|
||||
.div_trunc,
|
||||
.rem,
|
||||
.int_cast,
|
||||
.bool_to_int,
|
||||
=> Payload.BinOp,
|
||||
|
||||
.int,
|
||||
@ -191,6 +219,9 @@ pub const Node = extern union {
|
||||
.field_access_arrow,
|
||||
.warning,
|
||||
.failed_decl,
|
||||
.sizeof,
|
||||
.alignof,
|
||||
.type,
|
||||
=> Payload.Value,
|
||||
.@"if" => Payload.If,
|
||||
.@"while" => Payload.While,
|
||||
@ -234,8 +265,8 @@ pub const Payload = struct {
|
||||
pub const Infix = struct {
|
||||
base: Node,
|
||||
data: struct {
|
||||
lhs: *Node,
|
||||
rhs: *Node,
|
||||
lhs: Node,
|
||||
rhs: Node,
|
||||
},
|
||||
};
|
||||
|
||||
@ -246,44 +277,44 @@ pub const Payload = struct {
|
||||
|
||||
pub const UnOp = struct {
|
||||
base: Node,
|
||||
data: *Node,
|
||||
data: Node,
|
||||
};
|
||||
|
||||
pub const BinOp = struct {
|
||||
base: Node,
|
||||
data: struct {
|
||||
lhs: *Node,
|
||||
rhs: *Node,
|
||||
lhs: Node,
|
||||
rhs: Node,
|
||||
},
|
||||
};
|
||||
|
||||
pub const If = struct {
|
||||
base: Node = .{ .tag = .@"if" },
|
||||
data: struct {
|
||||
cond: *Node,
|
||||
then: *Node,
|
||||
@"else": ?*Node,
|
||||
cond: Node,
|
||||
then: Node,
|
||||
@"else": ?Node,
|
||||
},
|
||||
};
|
||||
|
||||
pub const While = struct {
|
||||
base: Node = .{ .tag = .@"while" },
|
||||
data: struct {
|
||||
cond: *Node,
|
||||
body: *Node,
|
||||
cond: Node,
|
||||
body: Node,
|
||||
},
|
||||
};
|
||||
|
||||
pub const Switch = struct {
|
||||
base: Node = .{ .tag = .@"switch" },
|
||||
data: struct {
|
||||
cond: *Node,
|
||||
cond: Node,
|
||||
cases: []Prong,
|
||||
default: ?[]const u8,
|
||||
|
||||
pub const Prong = struct {
|
||||
lhs: *Node,
|
||||
rhs: ?*Node,
|
||||
lhs: Node,
|
||||
rhs: ?Node,
|
||||
label: []const u8,
|
||||
};
|
||||
},
|
||||
@ -293,15 +324,15 @@ pub const Payload = struct {
|
||||
base: Node = .{ .tag = .@"break" },
|
||||
data: struct {
|
||||
label: ?[]const u8,
|
||||
rhs: ?*Node,
|
||||
rhs: ?Node,
|
||||
},
|
||||
};
|
||||
|
||||
pub const Call = struct {
|
||||
base: Node = .{.call},
|
||||
data: struct {
|
||||
lhs: *Node,
|
||||
args: []*Node,
|
||||
lhs: Node,
|
||||
args: []Node,
|
||||
},
|
||||
};
|
||||
|
||||
@ -314,7 +345,7 @@ pub const Payload = struct {
|
||||
@"export": bool,
|
||||
name: []const u8,
|
||||
type: Type,
|
||||
init: *Node,
|
||||
init: Node,
|
||||
},
|
||||
};
|
||||
|
||||
@ -328,7 +359,7 @@ pub const Payload = struct {
|
||||
cc: std.builtin.CallingConvention,
|
||||
params: []Param,
|
||||
return_type: Type,
|
||||
body: ?*Node,
|
||||
body: ?Node,
|
||||
|
||||
pub const Param = struct {
|
||||
@"noalias": bool,
|
||||
@ -368,7 +399,7 @@ pub const Payload = struct {
|
||||
|
||||
pub const ArrayInit = struct {
|
||||
base: Node = .{ .tag = .array_init },
|
||||
data: []*Node,
|
||||
data: []Node,
|
||||
};
|
||||
|
||||
pub const ContainerInit = struct {
|
||||
@ -377,17 +408,22 @@ pub const Payload = struct {
|
||||
|
||||
pub const Initializer = struct {
|
||||
name: []const u8,
|
||||
value: *Node,
|
||||
value: Node,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Block = struct {
|
||||
base: Node = .{ .tag = .block },
|
||||
base: Node,
|
||||
data: struct {
|
||||
label: ?[]const u8,
|
||||
stmts: []*Node,
|
||||
stmts: []Node
|
||||
},
|
||||
};
|
||||
|
||||
pub const Break = struct {
|
||||
base: Node = .{ .tag = .@"break" },
|
||||
data: *Block
|
||||
};
|
||||
};
|
||||
|
||||
/// Converts the nodes into a Zig ast and then renders it.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user