Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c19e523
remove global pch
YasInvolved Jul 12, 2026
78ecfd0
allow having additional primitives in the codegen definitions
YasInvolved Jul 12, 2026
3ecae84
allow adding headers to include in the codegen
YasInvolved Jul 12, 2026
f191f08
redefine some types to allow adding other emitters in the future
YasInvolved Jul 12, 2026
30659f7
type registry and schema decoder
YasInvolved Jul 12, 2026
bf8e633
emitter selection for each structure and schema
YasInvolved Jul 12, 2026
4a04ba9
fix circular dependencies
YasInvolved Jul 12, 2026
e12507f
enum emitter
YasInvolved Jul 12, 2026
224b858
group enums and structures in separate groups
YasInvolved Jul 12, 2026
7162dbf
write a notice at the top of the file
YasInvolved Jul 12, 2026
1c8189d
use absolute path to the header
YasInvolved Jul 12, 2026
480124d
namespace support
YasInvolved Jul 12, 2026
8537d51
aos emitter
YasInvolved Jul 12, 2026
89c04b6
soa emitter and some type safety
YasInvolved Jul 12, 2026
ee223dd
basic view emitter
YasInvolved Jul 12, 2026
1000893
rename AoS emitter to default
YasInvolved Jul 12, 2026
af98f5a
better INVALID value assignment
YasInvolved Jul 13, 2026
1b01c29
structurize the generator more for flexibility
YasInvolved Jul 13, 2026
4c5d08d
remove old type registry
YasInvolved Jul 13, 2026
a9e6d1f
adjust main.py to the new api
YasInvolved Jul 13, 2026
dc15ce2
adjust file generator
YasInvolved Jul 13, 2026
fa569ea
fix circular dependencies
YasInvolved Jul 13, 2026
5927339
exclude python virtual environment and .vscode
YasInvolved Jul 13, 2026
1e250f6
factory functions
YasInvolved Jul 14, 2026
0273285
safety exclusions
YasInvolved Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
.vs
.vscode
build
out
venv
__pycache__

CodeGen/*.json
CodeGen/*.h
10 changes: 10 additions & 0 deletions CodeGen/components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from dataclasses import dataclass, field
from interfaces.component import IComponent

@dataclass
class EnumComponent(IComponent):
underlying_type: str = "u32"
values: list[str] = field(default_factory=dict)

def calculate_bytes(self, registry):
return registry.get_byte_size(self.underlying_type)
30 changes: 0 additions & 30 deletions CodeGen/emitters/buffer.py

This file was deleted.

28 changes: 28 additions & 0 deletions CodeGen/emitters/code_buffer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class CodeBuffer:
def __init__(self, indent_char: str = " "):
self._lines: list[str] = []
self._indent_level: int = 0
self._indent_char: str = indent_char

def write_line(self, text: str = "") -> None:
if text.strip() == "":
self._lines.append("")
else:
indent = self._indent_char * self._indent_level
self._lines.append(f"{indent}{text}")

def open_block(self, prefix_text: str = "") -> None:
if prefix_text:
self.write_line(prefix_text)
self.write_line("{")
self._indent_level += 1

def close_block(self, suffix_text: str = "") -> None:
self._indent_level = max(0, self._indent_level - 1)
self.write_line(f"}}{suffix_text}")

def comment(self, text: str) -> None:
self.write_line(f"// {text}")

def get_content(self) -> str:
return "\n".join(self._lines)
10 changes: 10 additions & 0 deletions CodeGen/emitters/default_emitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .structure_emitter import BaseStructureEmitter

class DefaultEmitter(BaseStructureEmitter):
def _emit_structure(self, buffer, struct):
buffer.open_block(f"struct {struct.name}")
for name, type in struct.fields.items():
buffer.write_line(f"{type} {name};")

buffer.close_block(";")
buffer.write_line()
124 changes: 0 additions & 124 deletions CodeGen/emitters/engine_emitters.py

This file was deleted.

28 changes: 28 additions & 0 deletions CodeGen/emitters/enum_emitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import components
from .emitter import ICodeEmitter

class EnumEmitter(ICodeEmitter):
def emit_component(self, buffer, component):
if not isinstance(component, components.EnumComponent):
raise TypeError("EnumEmitter cannot process components other than enum!")

enum: components.EnumComponent = component
buffer.open_block(f"enum class {enum.name} : {enum.underlying_type}") # open enum

for idx, val in enumerate(enum.values):
buffer.write_line(f"{val:<24} = {idx},")

buffer.write_line(f"{'INVALID':<24} = std::numeric_limits<{enum.underlying_type}>::max()")
buffer.close_block(";\n") # close enum

buffer.open_block(f"[[nodiscard]] inline constexpr const char* ToString({enum.name} value) noexcept") # open function
buffer.open_block("switch (value)") # open switch

for val in enum.values:
buffer.write_line(f"case {enum.name}::{val}: return \"{val}\";")
buffer.write_line(f"case {enum.name}::INVALID: return \"INVALID\"")
buffer.write_line("default: return \"UNKNOWN\";")

buffer.close_block() # close switch
buffer.close_block() # close function
buffer.write_line()
10 changes: 10 additions & 0 deletions CodeGen/emitters/soa_emitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .structure_emitter import BaseStructureEmitter

class SoAEmitter(BaseStructureEmitter):
def _emit_structure(self, buffer, struct):
buffer.open_block(f"struct {struct.name}SoA")
for name, type in struct.fields.items():
buffer.write_line(f"{type}* {name};")

buffer.close_block(";")
buffer.write_line()
15 changes: 15 additions & 0 deletions CodeGen/emitters/structure_emitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from components import StructureComponent
from .emitter import ICodeEmitter
from .code_buffer import CodeBuffer
from abc import abstractmethod

class BaseStructureEmitter(ICodeEmitter):
def emit_component(self, buffer, component):
if not isinstance(component, StructureComponent):
raise TypeError("AosEmitter cannot emit components other than structures")

self._emit_structure(buffer, component)

@abstractmethod
def _emit_structure(self, buffer: CodeBuffer, struct: StructureComponent):
pass
16 changes: 16 additions & 0 deletions CodeGen/emitters/view_emitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .structure_emitter import BaseStructureEmitter

class ViewEmitter(BaseStructureEmitter):
def _emit_structure(self, buffer, struct):
struct_type_name = f"{struct.name}View"

buffer.open_block(f"struct {struct_type_name}")
buffer.comment("delete default constructor")
buffer.write_line(f"{struct_type_name}() = delete;")
buffer.write_line()

for name, type in struct.fields.items():
buffer.write_line(f"{type}& {name};")

buffer.close_block(";")
buffer.write_line()
40 changes: 40 additions & 0 deletions CodeGen/generators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from interfaces.file_generator import IFileGenerator
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from schema import Schema

class CppFileGenerator(IFileGenerator):
def write_comment(self, text) -> None:
self.write_line(f"// {text}")

def open_block(self, prefix: str = "") -> None:
if prefix:
self.write_line(prefix)

self.write_line("{")
self._indent_level += 1

def close_block(self, suffix = ""):
self._indent_level = max(0, self._indent_level - 1)
self.write_line(f"}}{suffix}")

def generate(self, schema_data, registry):
self.write_comment("="*100)
self.write_comment("FILE GENERATED BY DELTA CODEGEN UTILITY".center(100))
self.write_comment("="*100)
self.write_line()

self.write_line("#pragma once")
self.write_line("#include <cstdint>")
self.write_line("#include <cstddef>")
self.write_line()

# TODO: Namespace, structures, enums and anything else

def select_generator(schema: "Schema", outfile: str) -> IFileGenerator:
type = schema.generator_type.lower()
if type == "cpp":
return CppFileGenerator(outfile)
else:
raise RuntimeError(f"Unrecognized generator type: '{schema.generator_type}'")
20 changes: 20 additions & 0 deletions CodeGen/interfaces/component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Dict, Any, TYPE_CHECKING

if TYPE_CHECKING:
from type_registries import ITypeRegistry

@dataclass
class IComponent(ABC):
_name: str
metadata: Dict[str, Any] = field(default_factory=dict)

@property
def name(self) -> str:
return self._name

@abstractmethod
def calculate_bytes(self, registry: "ITypeRegistry") -> int:
"""Calculates the byte footprint of the component."""
pass
Loading