Skip to content

Commit

Permalink
Test new metadata system
Browse files Browse the repository at this point in the history
  • Loading branch information
Delaunay committed Aug 15, 2024
1 parent bb235b7 commit f38c2a9
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 108 deletions.
4 changes: 4 additions & 0 deletions lython/header/custom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@


#
#
124 changes: 102 additions & 22 deletions lython/header.py → lython/header/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@



class Project:
class Preprocessor:
def __init__(self, folder, file=None) -> None:
self.index = clang.cindex.Index.create()
self.tu = []
Expand Down Expand Up @@ -60,6 +60,16 @@ def parse_files(self, folder, file=None):
self.tu.append(tu)
self.check_for_errors(tu)


def reflect_type(self, struct) -> bool:
return struct["members"] and struct["ann"]

def reflect_property(self, attr) -> bool:
return attr.get("ann")

def reflect_method(self, method) -> bool:
return method.get("ann")

def check_for_errors(self, tu):
# Check for parsing errors
for diag in tu.diagnostics:
Expand All @@ -83,25 +93,45 @@ def generate_data(self):

print("namespace lython {", file=fp)
for name, struct in self.structs.items():
#
if struct["members"] and struct["ann"]:
typename = struct['name']

print(f"template <>", file=fp)
print(f"struct meta::ReflectionTrait<{typename}> {{", file=fp)
print(f" static int register_members() {{", file=fp)
if self.reflect_type(struct):
self.struct_begin(struct, fp)

for attr in struct["members"]:
if attr.get("ann"):
attrname = attr["name"]
print(f" meta::register_property<&{typename}::{attrname}>(\"{attrname}\");", file=fp)

print(f" return 1;", file=fp)
print(f" }}", file=fp)
print(f"}};", file=fp)
if self.reflect_property(attr):
self.generate_proprety(struct, attr, fp)

for attr in struct["methods"]:
if self.reflect_method(attr):
self.generate_method(struct, attr, fp)

self.struct_end(struct, fp)


print("}", file=fp)


def struct_begin(self, struct, fp):
typename = struct['name']

print(f"template <>", file=fp)
print(f"struct meta::ReflectionTrait<{typename}> {{", file=fp)
print(f" static int register_members() {{", file=fp)

def struct_end(self, struct, fp):
print(f" return 1;", file=fp)
print(f" }}", file=fp)
print(f"}};", file=fp)

def generate_proprety(self, struct, attr, fp):
attrname = attr["name"]
typename = struct['name']
print(f" meta::register_member<&{typename}::{attrname}>(\"{attrname}\");", file=fp)

def generate_method(self, struct, attr, fp):
attrname = attr["name"]
typename = struct['name']
print(f" meta::register_member<&{typename}::{attrname}>(\"{attrname}\");", file=fp)

def parse_annotation(self, ann):
return ann

Expand All @@ -113,13 +143,16 @@ def add_field(self, members, node, gather_members, field_ann):
break

if ann or gather_members:
members.append({
data = {
"id": len(members),
"name": node.spelling,
"type": node.type.spelling,
"ann": ann,
"custom": field_ann,
})
"ann": ann,
"cindex": node
}

members.append(data)

def has_meta_info(self, node):
if node.location.file and str(node.location.file).endswith(self.file):
Expand All @@ -136,10 +169,11 @@ def process_struct(self, node, depth):
struct = {
"name": namespace,
"spelling": node.spelling,
"members": members,
"ann": ann,
"custom": custom,
"members": members,
"methods": methods
"methods": methods,
"cindex": node,
}

# fields = [f.spelling for f in node.get_definition().get_fields()]
Expand Down Expand Up @@ -187,14 +221,60 @@ def find_class_struct_members(self, node, depth):



class KiwiPreprocessor(Preprocessor):
def __init__(self, folder, file=None) -> None:
self.options = {
"exhaustive": 1, # Reflect all properties by default even if not annotated
"reflected": 1, # Annotated properties are reflected by default
}
super().__init__(folder, file)

def parse_annotation(self, ann):
args = [arg.strip() for arg in ann.split(",")]

annotation_kind = "unknown"
if len(args) > 0:
annotation_kind = args[0]

annotation = {
"kind": annotation_kind
}

for value in args[1:]:
splits = value.split("=", maxsplit=1)
if len(splits) == 2:
annotation[splits[0]] = splits[1]
else:
annotation[value] = 1

return annotation

def flag(self, ann, key, type=int):
return type(ann.get(key, self.options.get(key)))

def reflected(self, ann):
if ann is None:
return self.options["exhaustive"]
return self.flag(ann, "reflected", int)

def reflect_property(self, attr) -> bool:
return self.reflected(attr["ann"])

def reflect_method(self, method) -> bool:
return self.reflected(method["ann"])

def reflect_type(self, struct) -> bool:
return self.reflected(struct["ann"])


if __name__ == "__main__":
import platform

if platform.uname().system != "Linux":
folder = "K:/lython/src"
file = "K:/lython/src/ast/nodes.h"
file = "K:/lython/lython/meta.h"
else:
folder = "/home/newton/work/lython/src"
file = "/home/newton/work/lython/lython/meta.h"

Project(folder, file)
KiwiPreprocessor(folder, file)
42 changes: 42 additions & 0 deletions lython/jsonrpc/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from dataclasses import dataclass
from typing import Any, Optional
from enum import Enum


class ErrorCode(Enum):
# -32768 to -32000 are reserved for pre-defined errors
ParseError = -32700
InvalidRequest = -32600
MethodNotFound = -32601
InvalidParams = -32602
InternalError = -32603
# -32000 to -32099


@dataclass
class Request:
id: Optional[int | str] # if it is not included it is assumed to be a notification
method: str # "rpc.(.*)" names a reserved
params: Optional[Any]
jsonrpc: str = "2.0"


@dataclass
class Error:
code: int
message: str
data: Optional[Any]


@dataclass
class Response:
id: int
result: Optional[Any]
error: Optional[Error]
jsonrpc: str = "2.0"



# protobuf
# json
# msgpack
19 changes: 14 additions & 5 deletions lython/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,31 @@ struct MyStruct {


#if KMETA_PROCESSING
#define KMETA2(...) __attribute__((annotate(#__VA_ARGS__)))
#define KMETA(...) __attribute__((annotate(#__VA_ARGS__)))
#else
#define KMETA2(...)
#define KMETA(...)
#endif

struct KMETA2(a, b, c) MyStruct1 {
#define KCLASS(...) KMETA(class, __VA_ARGS__)
#define KSTRUCT(...) KMETA(struct, __VA_ARGS__)
#define KPROPERTY(...) KMETA(proprety, __VA_ARGS__)
#define KFUNCTION(...) KMETA(function, __VA_ARGS__)
#define KIGNORE(...) KMETA(__VA_ARGS__, reflected=0)

int a;
struct KSTRUCT(a, b, c) MyStruct1 {

int a;

KMETA2(1, 2, 3)
KPROPERTY(FirstFlag, SomeValue=Elaborate, SecondFlag)
int b;

KPROPERTY(reflected=0, SomeValue=Elaborate, SecondFlag)
int d;

int c;

KFUNCTION()
void fun() {}
};


Expand Down
57 changes: 44 additions & 13 deletions src/ast/meta.generated.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,44 @@
#include "dtypes.h"
#include "ast/nodes.h"
#include "utilities/names.h"

namespace lython {
template <>
struct meta::ReflectionTrait<MyStruct1> {
static int register_members() {
meta::register_property<&MyStruct1::b>("b");
return 1;
}
};
}
#include "ast/nodes.h"
#include "dtypes.h"
#include "utilities/names.h"

#if KMETA_PROCESSING
#define KMETA(...) __attribute__((annotate(#__VA_ARGS__)))
#else
#define KMETA(...)
#endif

#define KCLASS(...) KMETA(class, __VA_ARGS__)
#define KSTRUCT(...) KMETA(struct, __VA_ARGS__)
#define KPROPERTY(...) KMETA(proprety, __VA_ARGS__)
#define KFUNCTION(...) KMETA(function, __VA_ARGS__)
#define KIGNORE(...) KMETA(__VA_ARGS__, reflected = 0)

struct KSTRUCT(a, b, c) MyStruct1 {

int a;

KPROPERTY(FirstFlag, SomeValue = Elaborate, SecondFlag)
int b;

KPROPERTY(reflected = 0, SomeValue = Elaborate, SecondFlag)
int d;

int c;

KFUNCTION()
void fun() {}
};

namespace lython {
template <>
struct meta::ReflectionTrait<MyStruct1> {
static int register_members() {
meta::register_member<&MyStruct1::a>("a");
meta::register_member<&MyStruct1::b>("b");
meta::register_member<&MyStruct1::c>("c");
meta::register_member<&MyStruct1::fun>("fun");
return 1;
}
};
} // namespace lython
Loading

0 comments on commit f38c2a9

Please sign in to comment.