x: initial generator

This commit is contained in:
Zack Buhman 2025-02-18 17:55:54 -06:00
parent 4e20ade922
commit d14c32eb01
6 changed files with 435 additions and 189 deletions

170
x/gen.py Normal file
View File

@ -0,0 +1,170 @@
import generate
from parse import parse_all, TokenReader
import templates
import dataclasses
from collections import Counter
from pprint import pprint
import sys
def obj_value(obj):
if type(obj) is tuple:
assert len(obj) == 2, obj
assert type(obj[0]) == bytes, obj
return obj[1]
else:
return obj
def obj_type(obj):
return type(obj_value(obj))
def visit_objects(func, obj):
print("vo", func)
yield func(obj)
for o in obj_value(obj).objects:
yield func(o)
def visit_self(func, obj):
print("vs", func)
yield func(obj)
visitors = {
templates.ColorRGBA : visit_self,
templates.ColorRGB : visit_self,
templates.Matrix4x4 : visit_self,
templates.Vector : visit_self,
templates.MeshFace : visit_self,
templates.Coords2D : visit_self,
templates.Reference : visit_self,
templates.FloatKeys : visit_self,
templates.TimedFloatKeys : visit_self,
templates.Header : visit_self,
templates.Material : visit_objects,
templates.TextureFilename : visit_self,
templates.Frame : visit_objects,
templates.FrameTransformMatrix : visit_self,
templates.Mesh : visit_objects,
templates.MeshMaterialList : visit_objects,
templates.MeshNormals : visit_self,
templates.MeshTextureCoords : visit_self,
templates.AnimationKey : visit_self,
templates.AnimationOptions : visit_self,
templates.Animation : visit_objects,
templates.AnimationSet : visit_objects,
}
type_map = {
templates.ColorRGBA : "vec4",
templates.ColorRGB : "vec3",
templates.Matrix4x4 : "mat4x4",
templates.Vector : "vec3",
templates.MeshFace : "mesh_face",
templates.Coords2D : "vec2",
#templates.Reference : None,
templates.FloatKeys : "float_keys",
templates.TimedFloatKeys : "time_float_keys",
templates.Header : "header",
templates.Material : "material",
templates.TextureFilename : "texture_filename",
templates.Frame : "frame",
templates.FrameTransformMatrix : "frame_transform_matrix",
templates.Mesh : "mesh",
templates.MeshMaterialList : "mesh_material_list",
templates.MeshNormals : "mesh_normals",
templates.MeshTextureCoords : "mesh_texture_coords",
templates.AnimationKey : "animation_key",
templates.AnimationOptions : "animation_options",
templates.Animation : "animation",
templates.AnimationSet : "animation_set",
}
type_counter = Counter()
def name_gen(obj):
global type_counter
assert type(obj) is not tuple
i = type_counter[type(obj)]
type_counter[type(obj)] += 1
return i
name_map = {}
def add_name_map(obj):
if type(obj) is not tuple:
return
name, obj = obj
assert name not in name_map, name
name_map[name] = obj
yield None
def type_declaration(obj):
type_name = type_map[obj_type(obj)]
if type(obj) is tuple:
name, _ = obj
string_name = name.decode('utf-8')
else:
string_name = name_gen(obj)
return f"const {type_name} {type_name}_{string_name}"
def generate_predeclaration(obj):
if type(obj) is not tuple:
return
yield f"{type_declaration(obj)};"
def generate_header(obj):
yield f"{type_declaration(obj)} {{"
yield "};"
def generate_definition(obj):
if obj_type(obj) is templates.Header:
yield from generate_header(obj)
elif obj_type(obj) is templates.Material:
yield from generate_material(obj)
elif obj_type(obj) is templates.TextureFilename:
yield from generate_texture_filename(obj)
elif obj_type(obj) is templates.Frame:
yield from generate_frame(obj)
elif obj_type(obj) is templates.FrameTransformMatrix:
yield from generate_frame_transform_matrix(obj)
elif obj_type(obj) is templates.Mesh:
yield from generate_mesh(obj)
elif obj_type(obj) is templates.MeshMaterialList:
yield from generate_mesh_material_list(obj)
elif obj_type(obj) is templates.MeshNormals:
yield from generate_mesh_normals(obj)
elif obj_type(obj) is templates.MeshTextureCoords:
yield from generate_mesh_texture_coords(obj)
elif obj_type(obj) is templates.AnimationKey:
yield from generate_animation_key(obj)
elif obj_type(obj) is templates.AnimationOptions:
yield from generate_animation_options(obj)
elif obj_type(obj) is templates.Animation:
yield from generate_animation(obj)
elif obj_type(obj) is templates.AnimationSet:
yield from generate_animation_set(obj)
else:
assert False, (type(obj), obj)
def visit(func, obj):
yield from visitors[obj_type(obj)](func, obj)
def visit_all(func, objects):
for obj in objects:
yield from visit(func, obj)
def gen(objects):
yield from visit_all(generate_predeclaration, objects)
yield from visit_all(generate_definition, objects)
with open(sys.argv[1], "rb") as f:
buf = f.read()
objects = list(parse_all(TokenReader(buf)))
_ = list(visit_all(add_name_map, objects))
render, out = generate.renderer()
for i in gen(objects):
print("line", i)
print(out.getvalue())

35
x/generate.py Normal file
View File

@ -0,0 +1,35 @@
import io
def should_autonewline(line):
return (
"static_assert" not in line
and "extern" not in line
and (len(line.split()) < 2 or line.split()[1] != '=') # hacky; meh
)
def _render(out, lines):
indent = " "
level = 0
for l in lines:
if l and (l[0] == "}" or l[0] == ")"):
level -= 2
assert level >= 0, out.getvalue()
if len(l) == 0:
out.write("\n")
else:
out.write(indent * level + l + "\n")
if l and (l[-1] == "{" or l[-1] == "("):
level += 2
if level == 0 and l and l[-1] == ";":
if should_autonewline(l):
out.write("\n")
return out
def renderer():
out = io.StringIO()
def render(lines):
return _render(out, lines)
return render, out

View File

@ -1,15 +1,9 @@
from pprint import pprint
import sys
import lex
import templates
with open(sys.argv[1], "rb") as f:
buf = f.read()
mem = memoryview(buf)
class TokenReader:
def __init__(self, mem):
def __init__(self, buf):
mem = memoryview(buf)
self.tokens = list(lex.lex_all(mem, 0))
self.ix = 0
@ -262,6 +256,18 @@ def parse_mesh_texture_coords(r):
textureCoords
)
def parse_animation(r):
r.consume(b"Animation")
name = r.consume_type(bytes)
r.consume(lex.TOKEN_LBRACKET)
objects = []
while not r.match(lex.TOKEN_RBRACKET):
objects.append(parse_one_ref(r, {b"AnimationKey", b"AnimationOptions"}))
return name, templates.Animation(
objects
)
def parse_animation_set(r):
r.consume(b"AnimationSet")
name = r.consume_type(bytes)
@ -274,16 +280,12 @@ def parse_animation_set(r):
objects
)
def parse_animation(r):
r.consume(b"Animation")
name = r.consume_type(bytes)
r.consume(lex.TOKEN_LBRACKET)
objects = []
while not r.match(lex.TOKEN_RBRACKET):
objects.append(parse_one_ref(r, {b"AnimationKey", b"AnimationOptions"}))
return name, templates.Animation(
objects
def parse_animation_options(r):
openClosed = parse_int(r)
positionQuality = parse_int(r)
return templates.AnimationOptions(
openClosed,
positionQuality
)
def parse_float_keys(r):
@ -341,12 +343,14 @@ def parse_one(r, peek_token=None):
return parse_mesh_normals(r)
elif token == b"MeshTextureCoords":
return parse_mesh_texture_coords(r)
elif token == b"AnimationSet":
return parse_animation_set(r)
elif token == b"Animation":
return parse_animation(r)
elif token == b"AnimationKey":
return parse_animation_key(r)
elif token == b"AnimationOptions":
return parse_animation_options(r)
elif token == b"Animation":
return parse_animation(r)
elif token == b"AnimationSet":
return parse_animation_set(r)
else:
assert False, token
@ -365,6 +369,13 @@ def parse_all(r):
while not r.eof():
yield parse_one_ref(r)
r = TokenReader(mem)
for i in parse_all(r):
pprint(i)
if __name__ == "__main__":
from pprint import pprint
import sys
with open(sys.argv[1], "rb") as f:
buf = f.read()
r = TokenReader(buf)
for i in parse_all(r):
pprint(i)

View File

@ -1,11 +1,7 @@
from typing import Any, Union
from dataclasses import dataclass
@dataclass
class Header:
major: int
minor: int
flags: int
# untagged objects
@dataclass
class ColorRGBA:
@ -24,23 +20,6 @@ class ColorRGB:
class Matrix4x4:
v: list[float]
@dataclass
class Material:
faceColor: ColorRGBA
power: float
specularColor: ColorRGB
emissiveColor: ColorRGB
objects: list[Any]
@dataclass
class Frame:
objects: list[Any]
@dataclass
class FrameTransformMatrix:
frameMatrix: Matrix4x4
@dataclass
class Vector:
x: float
@ -52,44 +31,11 @@ class MeshFace:
nFaceVertexIndices: int
faceVertexIndices: list[int]
@dataclass
class Mesh:
nVertices: int
vertices: list[Vector]
nFaces: int
faces: list[MeshFace]
objects: list[Any]
@dataclass
class MeshMaterialList:
nMaterials: int
nFaceIndices: int
faceIndices: list[int]
objects: list[Material]
@dataclass
class MeshNormals:
nNormals: int
normals: list[Vector]
nFaceNormals: int
faceNormals: list[MeshFace]
@dataclass
class Coords2D:
u: float
v: float
@dataclass
class MeshTextureCoords:
nTextureCoords: int
textureCoords: list[Coords2D]
@dataclass
class TextureFilename:
filename: str
@dataclass
class Reference:
name: bytes
@ -104,6 +50,62 @@ class TimedFloatKeys:
time: int
tfkeys: FloatKeys
# tagged objects
@dataclass
class Header:
major: int
minor: int
flags: int
@dataclass
class Material:
faceColor: ColorRGBA
power: float
specularColor: ColorRGB
emissiveColor: ColorRGB
objects: list[Any]
@dataclass
class TextureFilename:
filename: str
@dataclass
class Frame:
objects: list[Any]
@dataclass
class FrameTransformMatrix:
frameMatrix: Matrix4x4
@dataclass
class Mesh:
nVertices: int
vertices: list[Vector]
nFaces: int
faces: list[MeshFace]
objects: list[Any]
@dataclass
class MeshMaterialList:
nMaterials: int
nFaceIndices: int
faceIndices: list[int]
objects: list[Material]
@dataclass
class MeshNormals:
nNormals: int
normals: list[Vector]
nFaceNormals: int
faceNormals: list[MeshFace]
@dataclass
class MeshTextureCoords:
nTextureCoords: int
textureCoords: list[Coords2D]
@dataclass
class AnimationKey:
keyType: int

109
x/x.h
View File

@ -1,109 +0,0 @@
struct header {
int tag;
int major;
int minor;
int flags;
};
struct color_rgba {
float r;
float g;
float b;
float a;
};
struct color_rgb {
float r;
float g;
float b;
};
struct material {
int tag;
x_color_rgba facecolor;
float power;
x_color_rgb specularcolor;
x_color_rgb emissivecolor;
void * objects[];
};
struct frame {
int tag;
void * objects[];
};
struct frame_transform_matrix {
int tag;
mat4x4 framematrix;
};
struct mesh_face {
int nfacevertexindices;
int facevertexindices[];
};
struct mesh {
int nvertices;
vec3 * vertices;
int nfaces;
mesh_face * faces;
void * objects[];
};
struct mesh_material_list {
int n_materials;
int n_face_indices;
int * face_indices;
void * objects[];
};
struct mesh_normals {
int tag;
int n_normals;
vec3 * normals;
int n_face_normals;
mesh_face * face_normals;
};
struct mesh_texture_coords {
int tag;
int n_texture_coords;
vec2 texture_coords[];
};
struct texture_filename {
const char * filename;
};
struct float_keys {
int nvalues;
float values;
};
struct timed_float_keys {
int time;
float_keys tfkeys;
};
struct animation_key {
int tag;
int key_type;
int n_keys;
timed_float_keys keys[];
};
struct animation_options {
int tag;
int open_closed;
int position_quality;
};
struct animation {
int tag;
void * objects[];
};
struct animation_set {
int tag;
void * objects[];
}

137
x/x.hpp Normal file
View File

@ -0,0 +1,137 @@
/* primitives */
struct mesh_face {
int nfacevertexindices;
int facevertexindices[];
};
struct float_keys {
int nvalues;
float values;
};
struct timed_float_keys {
int time;
struct float_keys tfkeys;
};
/* data objects */
struct data_object;
enum struct tag : int {
header,
material,
texture_filename,
frame,
frame_transform_matrix,
mesh,
mesh_material_list,
mesh_normals,
mesh_texture_coords,
animation_key,
animation_options,
animation,
animation_set,
};
struct header {
enum tag tag;
int major;
int minor;
int flags;
};
struct material {
enum tag tag;
vec4 facecolor;
float power;
vec3 specularcolor;
vec3 emissivecolor;
struct data_object * objects[];
};
struct texture_filename {
enum tag tag;
const char * filename;
};
struct frame {
enum tag tag;
struct data_object * objects[];
};
struct frame_transform_matrix {
enum tag tag;
mat4x4 framematrix;
};
struct mesh {
enum tag tag;
int nvertices;
vec3 * vertices;
int nfaces;
struct mesh_face * faces;
struct data_object * objects[];
};
struct mesh_material_list {
enum tag tag;
int n_materials;
int n_face_indices;
int * face_indices;
struct data_object * objects[];
};
struct mesh_normals {
enum tag tag;
int n_normals;
vec3 * normals;
int n_face_normals;
struct mesh_face * face_normals;
};
struct mesh_texture_coords {
enum tag tag;
int n_texture_coords;
vec2 texture_coords[];
};
struct animation_key {
enum tag tag;
int key_type;
int n_keys;
struct timed_float_keys keys[];
};
struct animation_options {
enum tag tag;
int open_closed;
int position_quality;
};
struct animation {
enum tag tag;
struct data_object * objects[];
};
struct animation_set {
enum tag tag;
struct data_object * objects[];
};
struct data_object {
union {
enum tag tag;
struct header header;
struct material material;
struct texture_filename texture_filename;
struct frame frame;
struct frame_transform_matrix frame_transform_matrix;
struct mesh mesh;
struct mesh_material_list mesh_material_list;
struct mesh_normals mesh_normals;
struct mesh_texture_coords mesh_texture_coords;
struct animation_set animation_set;
struct animation animation;
struct animation_key animation_key;
};
};