broken
This commit is contained in:
11284
examples/basic/generated0005.ngr
Normal file
11284
examples/basic/generated0005.ngr
Normal file
File diff suppressed because it is too large
Load Diff
@@ -180,9 +180,9 @@ pub struct ProgramTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProgramTree {
|
impl ProgramTree {
|
||||||
fn new(mut rng: TestRng) -> Self {
|
fn new(_rng: TestRng) -> Self {
|
||||||
// let mut items = vec![];
|
// let mut items = vec![];
|
||||||
let program_length = PROGRAM_LENGTH_DISTRIBUTION.sample(&mut rng);
|
//let program_length = PROGRAM_LENGTH_DISTRIBUTION.sample(&mut rng);
|
||||||
// let mut env = ScopedMap::new();
|
// let mut env = ScopedMap::new();
|
||||||
|
|
||||||
// for _ in 0..program_length {
|
// for _ in 0..program_length {
|
||||||
@@ -216,10 +216,10 @@ impl ProgramTree {
|
|||||||
let current = Program {
|
let current = Program {
|
||||||
functions: HashMap::new(),
|
functions: HashMap::new(),
|
||||||
type_definitions: HashMap::new(),
|
type_definitions: HashMap::new(),
|
||||||
body: unimplemented!(),
|
body: Expression::Block(Location::manufactured(), Type::void(), vec![]),
|
||||||
};
|
};
|
||||||
|
|
||||||
ProgramTree { _rng: rng, current }
|
ProgramTree { _rng, current }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,8 +459,8 @@ fn generate_random_name(rng: &mut TestRng) -> Name {
|
|||||||
Name::gensym(start)
|
Name::gensym(start)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_random_argument_type(rng: &mut TestRng) -> Type {
|
//fn generate_random_argument_type(rng: &mut TestRng) -> Type {
|
||||||
ARGUMENT_TYPE_FREQUENCIES[ARGUMENT_TYPE_DISTRIBUTION.sample(rng)]
|
// ARGUMENT_TYPE_FREQUENCIES[ARGUMENT_TYPE_DISTRIBUTION.sample(rng)]
|
||||||
.0
|
// .0
|
||||||
.clone()
|
// .clone()
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -322,17 +322,38 @@ fn order_of_operations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proptest::proptest! {
|
proptest::proptest! {
|
||||||
#[test]
|
#[test]
|
||||||
fn random_syntaxes_validate(program in self::arbitrary::ProgramGenerator::default()) {
|
fn syntax_asts_roundtrip(program in self::arbitrary::ProgramGenerator::default()) {
|
||||||
let result = Program::validate(program);
|
use crate::util::pretty::Allocator;
|
||||||
proptest::prop_assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
let allocator = Allocator::new();
|
||||||
fn generated_run_or_overflow(program in self::arbitrary::ProgramGenerator::default()) {
|
let mut outbytes = Vec::new();
|
||||||
use crate::eval::{EvalError, PrimOpError};
|
|
||||||
let validated = Program::validate(program);
|
for top_level in program.iter() {
|
||||||
let actual_program = validated.into_result().expect("got a valid result");
|
let docbuilder = top_level.pretty(&allocator);
|
||||||
proptest::prop_assert!(matches!(actual_program.eval(), Ok(_) | Err(EvalError::PrimOp(PrimOpError::MathFailure(_)))));
|
docbuilder.render(78, &mut outbytes).expect("can write program text");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let outstr = std::str::from_utf8(&outbytes).expect("generated utf8");
|
||||||
|
println!("---------------- GENERATED TEXT -------------------");
|
||||||
|
println!("{}", outstr);
|
||||||
|
println!("---------------------------------------------------");
|
||||||
|
|
||||||
|
let syntax = crate::syntax::parse_string(0, &outstr).expect("generated text parses");
|
||||||
|
assert_eq!(program, syntax);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn random_syntaxes_validate(program in self::arbitrary::ProgramGenerator::default()) {
|
||||||
|
let result = Program::validate(program);
|
||||||
|
proptest::prop_assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generated_run_or_overflow(program in self::arbitrary::ProgramGenerator::default()) {
|
||||||
|
use crate::eval::{EvalError, PrimOpError};
|
||||||
|
let validated = Program::validate(program);
|
||||||
|
let actual_program = validated.into_result().expect("got a valid result");
|
||||||
|
proptest::prop_assert!(matches!(actual_program.eval(), Ok(_) | Err(EvalError::PrimOp(PrimOpError::MathFailure(_)))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,21 +18,22 @@ const MAX_COMPLEX_DEPTH: usize = 4;
|
|||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref BASE_PROGRAM_LENGTH: WeightedIndex<usize> = WeightedIndex::new([
|
static ref BASE_PROGRAM_LENGTH: WeightedIndex<usize> = WeightedIndex::new([
|
||||||
0, // weight for 0
|
0, // weight for 0
|
||||||
1, // weight for 1
|
9,
|
||||||
1, // weight for 2
|
// 1, // weight for 1
|
||||||
1, // weight for 3
|
// 1, // weight for 2
|
||||||
3, // triple weight for 4
|
// 1, // weight for 3
|
||||||
3, // triple weight for 5
|
// 3, // triple weight for 4
|
||||||
3, // triple weight for 6
|
// 3, // triple weight for 5
|
||||||
3, // triple weight for 7
|
// 3, // triple weight for 6
|
||||||
3, // triple weight for 8
|
// 3, // triple weight for 7
|
||||||
3, // triple weight for 9
|
// 3, // triple weight for 8
|
||||||
3, // triple weight for 10
|
// 3, // triple weight for 9
|
||||||
3, // double weight for 11
|
// 3, // triple weight for 10
|
||||||
3, // double weight for 12
|
// 3, // double weight for 11
|
||||||
3, // double weight for 13
|
// 3, // double weight for 12
|
||||||
1, // weight for 14
|
// 3, // double weight for 13
|
||||||
1, // weight for 15
|
// 1, // weight for 14
|
||||||
|
// 1, // weight for 15
|
||||||
]).unwrap();
|
]).unwrap();
|
||||||
|
|
||||||
static ref KEEP_FIELD_TYPE_ANNOTATION: WeightedMap<bool> = WeightedMap::new(&[
|
static ref KEEP_FIELD_TYPE_ANNOTATION: WeightedMap<bool> = WeightedMap::new(&[
|
||||||
@@ -151,7 +152,7 @@ impl Strategy for ProgramGenerator {
|
|||||||
|
|
||||||
pub struct ProgramTree {
|
pub struct ProgramTree {
|
||||||
_rng: TestRng,
|
_rng: TestRng,
|
||||||
current: VecDeque<TopLevel>,
|
current: Vec<TopLevel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Requirement {
|
pub enum Requirement {
|
||||||
@@ -167,14 +168,15 @@ impl ProgramTree {
|
|||||||
let mut rng = runner.new_rng();
|
let mut rng = runner.new_rng();
|
||||||
let base_program_length = BASE_PROGRAM_LENGTH.sample(&mut rng);
|
let base_program_length = BASE_PROGRAM_LENGTH.sample(&mut rng);
|
||||||
let mut env = ScopedMap::new();
|
let mut env = ScopedMap::new();
|
||||||
let mut current = VecDeque::new();
|
let mut current = Vec::new();
|
||||||
let mut established_structs = HashMap::new();
|
let mut established_structs = HashMap::new();
|
||||||
|
|
||||||
while current.len() < base_program_length {
|
while current.len() < base_program_length {
|
||||||
let (expression, mut requirements) =
|
let (expression, mut requirements) =
|
||||||
generate_expr(0, &mut rng, &mut established_structs, &mut env, None);
|
generate_expr(0, &mut rng, &mut established_structs, &mut env, None);
|
||||||
|
let mut new_entries = VecDeque::new();
|
||||||
|
|
||||||
current.push_front(TopLevel::Expression(expression));
|
new_entries.push_back(TopLevel::Expression(expression));
|
||||||
while let Some(requirement) = requirements.pop() {
|
while let Some(requirement) = requirements.pop() {
|
||||||
match requirement {
|
match requirement {
|
||||||
Requirement::Function(name, args, result) => {
|
Requirement::Function(name, args, result) => {
|
||||||
@@ -187,7 +189,7 @@ impl ProgramTree {
|
|||||||
args,
|
args,
|
||||||
result,
|
result,
|
||||||
);
|
);
|
||||||
current.push_front(TopLevel::Expression(expression));
|
new_entries.push_front(TopLevel::Expression(expression));
|
||||||
requirements.extend(newreqs.into_iter());
|
requirements.extend(newreqs.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +204,7 @@ impl ProgramTree {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
current.push_front(TopLevel::Structure(
|
new_entries.push_front(TopLevel::Structure(
|
||||||
Location::manufactured(),
|
Location::manufactured(),
|
||||||
name,
|
name,
|
||||||
fields,
|
fields,
|
||||||
@@ -219,17 +221,16 @@ impl ProgramTree {
|
|||||||
);
|
);
|
||||||
let binding =
|
let binding =
|
||||||
Expression::Binding(Location::manufactured(), name, Box::new(newexpr));
|
Expression::Binding(Location::manufactured(), name, Box::new(newexpr));
|
||||||
current.push_front(TopLevel::Expression(binding));
|
new_entries.push_front(TopLevel::Expression(binding));
|
||||||
requirements.extend(newreqs.into_iter());
|
requirements.extend(newreqs.into_iter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current.extend(new_entries.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramTree {
|
ProgramTree { _rng: rng, current }
|
||||||
_rng: rng,
|
|
||||||
current: current.into_iter().collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +288,7 @@ fn generate_expr(
|
|||||||
let mut valid_types =
|
let mut valid_types =
|
||||||
find_structs_with_field_type(established_struct_types, &target_type);
|
find_structs_with_field_type(established_struct_types, &target_type);
|
||||||
if valid_types.is_empty() {
|
if valid_types.is_empty() {
|
||||||
let name = generate_name(rng);
|
let struct_name = generate_type_name(rng);
|
||||||
let mut fields = generate_structure_fields(rng, established_struct_types);
|
let mut fields = generate_structure_fields(rng, established_struct_types);
|
||||||
valid_types = fields
|
valid_types = fields
|
||||||
.iter()
|
.iter()
|
||||||
@@ -298,10 +299,11 @@ fn generate_expr(
|
|||||||
if valid_types.is_empty() {
|
if valid_types.is_empty() {
|
||||||
let field_name = generate_name(rng);
|
let field_name = generate_name(rng);
|
||||||
fields.insert(field_name.clone(), target_type.clone());
|
fields.insert(field_name.clone(), target_type.clone());
|
||||||
valid_types = vec![(Type::Named(name.clone()), field_name)];
|
valid_types = vec![(Type::Named(struct_name.clone()), field_name)];
|
||||||
}
|
}
|
||||||
|
|
||||||
requirements.push(Requirement::Structure(name.clone(), fields));
|
established_struct_types.insert(struct_name.clone(), fields.clone());
|
||||||
|
requirements.push(Requirement::Structure(struct_name.clone(), fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_target_type_idx = rng.gen_range(0..valid_types.len());
|
let new_target_type_idx = rng.gen_range(0..valid_types.len());
|
||||||
@@ -366,7 +368,7 @@ fn generate_expr(
|
|||||||
Type::Struct(fields) => match find_struct_for_fields(&fields, established_struct_types)
|
Type::Struct(fields) => match find_struct_for_fields(&fields, established_struct_types)
|
||||||
{
|
{
|
||||||
None => {
|
None => {
|
||||||
let name = generate_name(rng);
|
let struct_name = generate_type_name(rng);
|
||||||
let mut new_fields = HashMap::new();
|
let mut new_fields = HashMap::new();
|
||||||
|
|
||||||
for (field_name, maybe_type) in fields.into_iter() {
|
for (field_name, maybe_type) in fields.into_iter() {
|
||||||
@@ -375,20 +377,20 @@ fn generate_expr(
|
|||||||
new_fields.insert(field_name, field_type);
|
new_fields.insert(field_name, field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
established_struct_types.insert(name.clone(), new_fields.clone());
|
established_struct_types.insert(struct_name.clone(), new_fields.clone());
|
||||||
let (subexpr, mut reqs) = generate_expr(
|
let (subexpr, mut reqs) = generate_expr(
|
||||||
depth + 1,
|
depth + 1,
|
||||||
rng,
|
rng,
|
||||||
established_struct_types,
|
established_struct_types,
|
||||||
env,
|
env,
|
||||||
Some(Type::Named(name.clone())),
|
Some(Type::Named(struct_name.clone())),
|
||||||
);
|
);
|
||||||
let result = Expression::Cast(
|
let result = Expression::Cast(
|
||||||
Location::manufactured(),
|
Location::manufactured(),
|
||||||
name.current_name().to_string(),
|
struct_name.current_name().to_string(),
|
||||||
Box::new(subexpr),
|
Box::new(subexpr),
|
||||||
);
|
);
|
||||||
reqs.push(Requirement::Structure(name, new_fields));
|
reqs.push(Requirement::Structure(struct_name, new_fields));
|
||||||
(result, reqs)
|
(result, reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,6 +468,7 @@ fn generate_expr(
|
|||||||
let mut block = VecDeque::new();
|
let mut block = VecDeque::new();
|
||||||
let mut prereqs = vec![];
|
let mut prereqs = vec![];
|
||||||
|
|
||||||
|
env.new_scope();
|
||||||
while block.len() < target_block_size_minus_one {
|
while block.len() < target_block_size_minus_one {
|
||||||
let inner_type = if INNER_BLOCK_TYPE_SHOULD_BE_VOID.sample(rng) {
|
let inner_type = if INNER_BLOCK_TYPE_SHOULD_BE_VOID.sample(rng) {
|
||||||
Some(Type::Named(Name::new("void", Location::manufactured())))
|
Some(Type::Named(Name::new("void", Location::manufactured())))
|
||||||
@@ -501,6 +504,7 @@ fn generate_expr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
env.release_scope();
|
||||||
|
|
||||||
let retval = Expression::Block(Location::manufactured(), block.into_iter().collect());
|
let retval = Expression::Block(Location::manufactured(), block.into_iter().collect());
|
||||||
(retval, prereqs)
|
(retval, prereqs)
|
||||||
@@ -705,19 +709,34 @@ fn find_struct_for_fields(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_name(rng: &mut TestRng) -> Name {
|
fn internal_generate_name(rng: &mut TestRng, is_type_name: bool) -> Name {
|
||||||
static COUNTER: AtomicU64 = AtomicU64::new(0);
|
static COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
let idx = rng.gen_range(0..names::NOUNS.len());
|
let idx = rng.gen_range(0..names::NOUNS.len());
|
||||||
|
let mut noun = names::NOUNS[idx].to_string();
|
||||||
|
|
||||||
|
if is_type_name {
|
||||||
|
let first_char = noun.get_mut(0..1).expect("has first character");
|
||||||
|
first_char.make_ascii_uppercase();
|
||||||
|
}
|
||||||
|
|
||||||
let name = format!(
|
let name = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
names::NOUNS[idx],
|
noun,
|
||||||
COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
|
COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
|
||||||
);
|
);
|
||||||
|
|
||||||
Name::new(name, Location::manufactured())
|
Name::new(name, Location::manufactured())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_name(rng: &mut TestRng) -> Name {
|
||||||
|
internal_generate_name(rng, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_type_name(rng: &mut TestRng) -> Name {
|
||||||
|
internal_generate_name(rng, true)
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_type(rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap) -> Type {
|
fn generate_type(rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap) -> Type {
|
||||||
let possible_result = TYPE_FREQUENCIES.sample(rng);
|
let possible_result = TYPE_FREQUENCIES.sample(rng);
|
||||||
|
|
||||||
|
|||||||
@@ -218,6 +218,8 @@ UnaryExpression: Expression = {
|
|||||||
Expression::primitive(Location::new(file_idx, l..le), "negate", vec![e]),
|
Expression::primitive(Location::new(file_idx, l..le), "negate", vec![e]),
|
||||||
<l: @L> "<" <v:"<var>"> ">" <e:UnaryExpression> <le: @L> =>
|
<l: @L> "<" <v:"<var>"> ">" <e:UnaryExpression> <le: @L> =>
|
||||||
Expression::Cast(Location::new(file_idx, l..le), v.to_string(), Box::new(e)),
|
Expression::Cast(Location::new(file_idx, l..le), v.to_string(), Box::new(e)),
|
||||||
|
<l: @L> "<" <v:"<type>"> ">" <e:UnaryExpression> <le: @L> =>
|
||||||
|
Expression::Cast(Location::new(file_idx, l..le), v.to_string(), Box::new(e)),
|
||||||
CallExpression,
|
CallExpression,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ impl Program {
|
|||||||
|
|
||||||
interior = interior.indent(9);
|
interior = interior.indent(9);
|
||||||
|
|
||||||
let start = allocator.text("struct")
|
let start = allocator
|
||||||
|
.text("struct")
|
||||||
.append(allocator.space())
|
.append(allocator.space())
|
||||||
.append(allocator.text(definition.name.original_name().to_string()))
|
.append(allocator.text(definition.name.original_name().to_string()))
|
||||||
.append(allocator.space())
|
.append(allocator.space())
|
||||||
.append(allocator.text("{"));
|
.append(allocator.text("{"));
|
||||||
|
|
||||||
let conclusion = allocator.text("}")
|
let conclusion = allocator.text("}").append(allocator.hardline());
|
||||||
.append(allocator.hardline());
|
|
||||||
|
|
||||||
result = result.append(start.append(interior).append(conclusion));
|
result = result.append(start.append(interior).append(conclusion));
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,8 @@ impl TopLevel {
|
|||||||
.append(type_bit)
|
.append(type_bit)
|
||||||
.append(allocator.text(";"))
|
.append(allocator.text(";"))
|
||||||
.append(allocator.hardline())
|
.append(allocator.hardline())
|
||||||
})).indent(2)
|
}))
|
||||||
|
.indent(2),
|
||||||
)
|
)
|
||||||
.append(allocator.text("}"))
|
.append(allocator.text("}"))
|
||||||
.append(allocator.hardline()),
|
.append(allocator.hardline()),
|
||||||
@@ -141,7 +142,7 @@ impl Expression {
|
|||||||
.append(allocator.text(";"))
|
.append(allocator.text(";"))
|
||||||
.append(allocator.hardline())
|
.append(allocator.hardline())
|
||||||
}))
|
}))
|
||||||
.indent(2)
|
.indent(2),
|
||||||
)
|
)
|
||||||
.append(allocator.text("}")),
|
.append(allocator.text("}")),
|
||||||
Expression::Reference(var) => allocator.text(var.to_string()),
|
Expression::Reference(var) => allocator.text(var.to_string()),
|
||||||
@@ -158,7 +159,10 @@ impl Expression {
|
|||||||
let mut args = args.iter().map(|x| x.pretty(allocator)).collect::<Vec<_>>();
|
let mut args = args.iter().map(|x| x.pretty(allocator)).collect::<Vec<_>>();
|
||||||
|
|
||||||
match fun.as_ref() {
|
match fun.as_ref() {
|
||||||
Expression::Primitive(_, name) if ["/", "*", "+", "-"].contains(&name.current_name()) && args.len() == 2 => {
|
Expression::Primitive(_, name)
|
||||||
|
if ["/", "*", "+", "-"].contains(&name.current_name())
|
||||||
|
&& args.len() == 2 =>
|
||||||
|
{
|
||||||
let second = args.pop().unwrap();
|
let second = args.pop().unwrap();
|
||||||
args.pop()
|
args.pop()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -169,13 +173,20 @@ impl Expression {
|
|||||||
.parens()
|
.parens()
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression::Primitive(_, name) if ["negate"].contains(&name.current_name()) && args.len() == 1 =>
|
Expression::Primitive(_, name)
|
||||||
allocator.text("-").append(args.pop().unwrap()),
|
if ["negate"].contains(&name.current_name()) && args.len() == 1 =>
|
||||||
|
{
|
||||||
|
allocator.text("-").append(args.pop().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
Expression::Primitive(_, name) if ["print"].contains(&&name.current_name()) && args.len() == 1 =>
|
Expression::Primitive(_, name)
|
||||||
allocator.text("print")
|
if ["print"].contains(&&name.current_name()) && args.len() == 1 =>
|
||||||
.append(allocator.space())
|
{
|
||||||
.append(args.pop().unwrap()),
|
allocator
|
||||||
|
.text("print")
|
||||||
|
.append(allocator.space())
|
||||||
|
.append(args.pop().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let comma_sepped_args = allocator.intersperse(args, allocator.text(","));
|
let comma_sepped_args = allocator.intersperse(args, allocator.text(","));
|
||||||
@@ -273,7 +284,7 @@ impl Value {
|
|||||||
allocator.text(value_str)
|
allocator.text(value_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Void => allocator.text("<void>"),
|
Value::Void => allocator.text("void()"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +292,7 @@ impl Value {
|
|||||||
fn type_suffix(x: &Option<ConstantType>) -> &'static str {
|
fn type_suffix(x: &Option<ConstantType>) -> &'static str {
|
||||||
match x {
|
match x {
|
||||||
None => "",
|
None => "",
|
||||||
Some(ConstantType::Void) => "<void>",
|
Some(ConstantType::Void) => panic!("Should never get a void type suffix."),
|
||||||
Some(ConstantType::I8) => "i8",
|
Some(ConstantType::I8) => "i8",
|
||||||
Some(ConstantType::I16) => "i16",
|
Some(ConstantType::I16) => "i16",
|
||||||
Some(ConstantType::I32) => "i32",
|
Some(ConstantType::I32) => "i32",
|
||||||
@@ -314,8 +325,7 @@ impl Type {
|
|||||||
.append(allocator.text(";"))
|
.append(allocator.text(";"))
|
||||||
}),
|
}),
|
||||||
allocator.hardline(),
|
allocator.hardline(),
|
||||||
))
|
).braces())
|
||||||
.braces(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user