#generation #generator #code-generation #code

code_generator

A code generator (Currently only targets C)

16 releases

new 0.1.16 Oct 15, 2024
0.1.15 Aug 12, 2024
0.1.7 Jul 30, 2024

#540 in Data structures

MIT license

55KB
1K SLoC

Code Generator

  • This project is not stabilized. There will be many breaking changes before it is stabilized.
  • The goal of this project is to be able to generate code, and be able to easily change the formatting of the generated code as needed.
  • This library makes it easier to reuse code generation code since it is context aware.
  • This library currently only supports C, but I would like to support multiple target languages.

TODO:

  • Support more types of code generation (switch, do/while, etc.)
  • Support more languages. Currently the language is fairly hard coded. Not sure if that can be abstracted.
  • Unit tests
  • Documentation

Limitations

  • I don't believe it would be possible to work backwards with the existing architecture of the project. This library could not parse code, and do anything with it without a major rework.

lib.rs:

This generator is designed to allow easy reuse of code generation

Example

This example shows how the same structure can be generated into two different formats.

#
let code = CodeSet::new(vec![
    Box::new(String::from("#include \"test.h\"")),
    Box::new(String::from("")),
    Box::new(String::from("")),
    Box::new(Function::new(FunctionSignature::new(
            Name::new("MyReturnTypeOne"),
            Name::new("MyFunctionNameOne"),
            vec![
                (Name::new("ParamTypeOne"), Name::new("ParamNameOne")),
                (Name::new("ParamTypeTwo"), Name::new("ParamNameTwo")),
                (Name::new("ParamTypeThree"), Name::new("ParamNameThree")),
            ]
        ),
        CodeSet::new(vec![
            Box::new(IfStatement::new(
                    Name::new_with_type("ParamNameThree", NameType::Member),
                CodeBody::new(vec![
                    Box::new(ForLoop::new(
                        String::from("ParamTypeTwo i = 0"),
                        String::from("i < param_name_two"),
                        String::from("i++"),
                        vec![
                            Box::new(String::from("printf(\"ParamOne: {}\\n\", param_name_one);"))
                        ]
                    ))
                ])
            ))
        ])
    )),
    Box::new(String::from("")),
]);

let mut info = CodeGenerationInfo::from_style(CodeStyle::KnR);
info.set_new_line_type(NewLineType::Nl);
assert_eq!(
"#include \"test.h\"


MyReturnTypeOne my_function_name_one(ParamTypeOne param_name_one, ParamTypeTwo param_name_two, ParamTypeThree param_name_three) {
    if (param_name_three) {
        for (ParamTypeTwo i = 0; i < param_name_two; i++) {
            printf(\"ParamOne: {}\\n\", param_name_one);
        }
    }
}
", format!("{}", code.display(info)));

let mut info = CodeGenerationInfo::from_style(CodeStyle::Allman);
info.set_new_line_type(NewLineType::Nl);
assert_eq!(
"#include \"test.h\"


MyReturnTypeOne my_function_name_one(ParamTypeOne param_name_one, ParamTypeTwo param_name_two, ParamTypeThree param_name_three)
{
    if (param_name_three)
    {
        for (ParamTypeTwo i = 0; i < param_name_two; i++)
        {
            printf(\"ParamOne: {}\\n\", param_name_one);
        }
    }
}
", format!("{}", code.display(info)));



Because the output format is not dependent on the input data structure, it is very easy to make code generation modular. Any pieces of generated code that share structure, can share a generator.

No runtime deps