Skip to content

Commit

Permalink
Merge #84
Browse files Browse the repository at this point in the history
84: Codegen support for builtin types r=Bromeon a=Bromeon

Provides the Godot API of _built-in types_ such as `Array`, `Color`, `PackedInt64Array`, `Dictionary`, `NodePath` and so on.
For now, they are designed as "inner" types being accessible from manually written, user-facing types.

bors r+

Co-authored-by: Jan Haller <bromeon@gmail.com>
  • Loading branch information
bors[bot] and Bromeon authored Jan 24, 2023
2 parents c078127 + 785dd81 commit 9907d1c
Show file tree
Hide file tree
Showing 15 changed files with 680 additions and 305 deletions.
124 changes: 72 additions & 52 deletions godot-codegen/src/api_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct ExtensionApi {
pub builtin_class_sizes: Vec<ClassSizes>,
pub builtin_classes: Vec<BuiltinClass>,
pub classes: Vec<Class>,
pub global_enums: Vec<GlobalEnum>,
pub global_enums: Vec<Enum>,
pub utility_functions: Vec<UtilityFunction>,
pub singletons: Vec<Singleton>,
}
Expand All @@ -40,16 +40,15 @@ pub struct ClassSize {
#[derive(DeJson)]
pub struct BuiltinClass {
pub name: String,
pub indexing_return_type: Option<String>,
pub is_keyed: bool,
pub members: Option<Vec<Member>>,
pub constants: Option<Vec<Constant>>,
pub enums: Option<Vec<BuiltinClassEnum>>, // no bitfield
pub operators: Vec<Operator>,
pub methods: Option<Vec<BuiltinClassMethod>>,
pub constructors: Vec<Constructor>,
pub has_destructor: bool,
pub operators: Vec<Operator>,
}

#[derive(DeJson)]
pub struct Operator {
pub name: String,
pub right_type: Option<String>, // null if unary
pub return_type: String,
}

#[derive(DeJson)]
Expand All @@ -60,8 +59,8 @@ pub struct Class {
pub inherits: Option<String>,
// pub api_type: String,
// pub constants: Option<Vec<Constant>>,
pub enums: Option<Vec<ClassEnum>>,
pub methods: Option<Vec<Method>>,
pub enums: Option<Vec<Enum>>,
pub methods: Option<Vec<ClassMethod>>,
// pub properties: Option<Vec<Property>>,
// pub signals: Option<Vec<Signal>>,
}
Expand All @@ -75,23 +74,54 @@ pub struct Singleton {
}

#[derive(DeJson)]
pub struct ClassEnum {
pub struct Enum {
pub name: String,
pub is_bitfield: bool,
pub values: Vec<Constant>,
pub values: Vec<EnumConstant>,
}

// Same as above, but no bitfield
#[derive(DeJson)]
pub struct GlobalEnum {
pub struct BuiltinClassEnum {
pub name: String,
pub values: Vec<EnumConstant>,
}

impl BuiltinClassEnum {
pub(crate) fn to_enum(&self) -> Enum {
Enum {
name: self.name.clone(),
is_bitfield: false,
values: self.values.clone(),
}
}
}

#[derive(DeJson, Clone)]
pub struct EnumConstant {
pub name: String,
pub values: Vec<Constant>,
pub value: i32,
}

#[derive(DeJson)]
pub struct Constant {
pub name: String,
pub value: i32,
#[nserde(rename = "type")]
pub type_: String,
pub value: String,
}

#[derive(DeJson)]
pub struct Operator {
pub name: String,
pub right_type: Option<String>, // null if unary
pub return_type: String,
}

#[derive(DeJson)]
pub struct Member {
pub name: String,
#[nserde(rename = "type")]
pub type_: String,
}

#[derive(DeJson)]
Expand Down Expand Up @@ -127,18 +157,29 @@ pub struct UtilityFunction {
}

#[derive(DeJson)]
pub struct Method {
pub struct BuiltinClassMethod {
pub name: String,
pub return_type: Option<String>,
pub is_vararg: bool,
pub is_const: bool,
pub is_static: bool,
pub hash: Option<i64>,
pub arguments: Option<Vec<MethodArg>>,
}

#[derive(DeJson)]
pub struct ClassMethod {
pub name: String,
pub is_const: bool,
pub is_vararg: bool,
//pub is_static: bool,
pub is_virtual: bool,
pub hash: Option<i64>,
pub arguments: Option<Vec<MethodArg>>,
pub return_value: Option<MethodReturn>,
pub arguments: Option<Vec<MethodArg>>,
}

impl Method {
impl ClassMethod {
pub fn map_args<R>(&self, f: impl FnOnce(&Vec<MethodArg>) -> R) -> R {
match self.arguments.as_ref() {
Some(args) => f(args),
Expand All @@ -147,51 +188,30 @@ impl Method {
}
}

// Example: set_point_weight_scale ->
// [ {name: "id", type: "int", meta: "int64"},
// {name: "weight_scale", type: "float", meta: "float"},
#[derive(DeJson, Clone)]
pub struct MethodArg {
pub name: String,
#[nserde(rename = "type")]
pub type_: String,
// pub meta: Option<String>,
}

// Example: get_available_point_id -> {type: "int", meta: "int64"}
#[derive(DeJson)]
pub struct MethodReturn {
#[nserde(rename = "type")]
pub type_: String,
// pub meta: Option<String>,
}

pub trait Enum {
fn name(&self) -> &str;
fn values(&self) -> &Vec<Constant>;
fn is_bitfield(&self) -> bool;
}

impl Enum for ClassEnum {
fn name(&self) -> &str {
&self.name
}

fn values(&self) -> &Vec<Constant> {
&self.values
}

fn is_bitfield(&self) -> bool {
self.is_bitfield
}
}

impl Enum for GlobalEnum {
fn name(&self) -> &str {
&self.name
}

fn values(&self) -> &Vec<Constant> {
&self.values
}

fn is_bitfield(&self) -> bool {
// Hack until this is exported in the JSON
self.name.contains("Flag")
impl MethodReturn {
pub fn from_type(type_: &str) -> Self {
Self {
type_: type_.to_owned(),
}
}
}

Expand Down
37 changes: 19 additions & 18 deletions godot-codegen/src/central_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,30 @@ struct CentralItems {
global_enum_defs: Vec<TokenStream>,
}

struct TypeNames {
pub(crate) struct TypeNames {
/// "int" or "PackedVector2Array"
pascal_case: String,
pub pascal_case: String,

/// "packed_vector2_array"
snake_case: String,
pub snake_case: String,

/// "PACKED_VECTOR2_ARRAY"
//shout_case: String,
//pub shout_case: String,

/// GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY
sys_variant_type: Ident,
pub sys_variant_type: Ident,
}

/// Allows collecting all builtin TypeNames before generating methods
struct BuiltinTypeInfo<'a> {
value: i32,
type_names: TypeNames,
pub(crate) struct BuiltinTypeInfo<'a> {
pub value: i32,
pub type_names: TypeNames,

/// If `variant_get_ptr_destructor` returns a non-null function pointer for this type.
/// List is directly sourced from extension_api.json (information would also be in variant_destruct.cpp).
has_destructor: bool,
constructors: Option<&'a Vec<Constructor>>,
operators: Option<&'a Vec<Operator>>,
pub has_destructor: bool,
pub constructors: Option<&'a Vec<Constructor>>,
pub operators: Option<&'a Vec<Operator>>,
}

pub(crate) fn generate_sys_central_file(
Expand Down Expand Up @@ -103,12 +103,14 @@ pub(crate) fn generate_core_mod_file(

pub mod class_macros {}
}
pub mod builtin_classes {}
pub mod utilities {}
}
} else {
quote! {
pub mod central;
pub mod classes;
pub mod builtin_classes;
pub mod utilities;
}
};
Expand Down Expand Up @@ -304,8 +306,7 @@ fn make_central_items(api: &ExtensionApi, build_config: &str, ctx: &mut Context)
}
}

let class_map = collect_builtin_classes(api);
let builtin_types_map = collect_builtin_types(api, &class_map);
let builtin_types_map = collect_builtin_types(api);
let variant_operators = collect_variant_operators(api);

// Generate builtin methods, now with info for all types available.
Expand Down Expand Up @@ -389,10 +390,10 @@ fn collect_builtin_classes(api: &ExtensionApi) -> HashMap<String, &BuiltinClass>
class_map
}

fn collect_builtin_types<'a>(
api: &'a ExtensionApi,
class_map: &HashMap<String, &'a BuiltinClass>,
) -> HashMap<String, BuiltinTypeInfo<'a>> {
/// Returns map from "PackedStringArray" to all the info
pub(crate) fn collect_builtin_types(api: &ExtensionApi) -> HashMap<String, BuiltinTypeInfo<'_>> {
let class_map = collect_builtin_classes(api);

let variant_type_enum = api
.global_enums
.iter()
Expand Down Expand Up @@ -456,7 +457,7 @@ fn collect_builtin_types<'a>(
builtin_types_map
}

fn collect_variant_operators(api: &ExtensionApi) -> Vec<&Constant> {
fn collect_variant_operators(api: &ExtensionApi) -> Vec<&EnumConstant> {
let variant_operator_enum = api
.global_enums
.iter()
Expand Down
Loading

0 comments on commit 9907d1c

Please sign in to comment.