Skip to content

Commit 0b4d27b

Browse files
Toposort data types in definitions file (#115)
Toposort data types
1 parent bbaa455 commit 0b4d27b

File tree

2 files changed

+159
-117
lines changed

2 files changed

+159
-117
lines changed

scripts/dumpRobloxTypes.py

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,10 @@
249249
declare function spawn<T...>(callback: (T...) -> ())
250250
declare function version(): string
251251
declare function printidentity(prefix: string?)
252+
"""
252253

254+
# Hardcoded types after data types have been defined
255+
POST_DATATYPES_BASE = """
253256
export type RBXScriptSignal<T... = ...any> = {
254257
Wait: (self: RBXScriptSignal<T...>) -> T...,
255258
Connect: (self: RBXScriptSignal<T...>, callback: (T...) -> ()) -> RBXScriptConnection,
@@ -603,14 +606,8 @@ def printClasses(dump: ApiDump):
603606
print()
604607

605608

606-
def printDataTypes(types: DataTypesDump):
607-
# Forward declare all the types
608-
for klass in types["DataTypes"]:
609-
if klass["Name"] in IGNORED_INSTANCES:
610-
continue
611-
print(f"type {klass['Name']} = any")
612-
613-
for klass in types["DataTypes"]:
609+
def printDataTypes(types: List[DataType]):
610+
for klass in types:
614611
if klass["Name"] in IGNORED_INSTANCES:
615612
continue
616613
name = klass["Name"]
@@ -770,6 +767,82 @@ def loadClassesIntoStructures(dump: ApiDump):
770767
CLASSES[klass["Name"]] = klass
771768

772769

770+
def topologicalSortDataTypes(dataTypes: List[DataType]) -> List[DataType]:
771+
# A child of node in graph indicates that the child references the node
772+
graph: defaultdict[str, set[str]] = defaultdict(set)
773+
774+
dataTypeNames = {klass["Name"] for klass in dataTypes}
775+
776+
def resolveClass(type: Union[ApiValueType, CorrectionsValueType]):
777+
name = type["Name"][:-1] if type["Name"][-1] == "?" else type["Name"]
778+
if name in dataTypeNames:
779+
return name
780+
781+
return None
782+
783+
def createReference(klassName: str, referenced: str | None):
784+
if referenced is not None:
785+
if klassName == referenced:
786+
return
787+
graph[referenced].add(klassName)
788+
789+
for klass in dataTypes:
790+
klassName = klass["Name"]
791+
792+
if klassName not in graph:
793+
graph[klassName] = set()
794+
795+
for member in klass["Members"]:
796+
if member["MemberType"] == "Property":
797+
createReference(klassName, resolveClass(member["ValueType"]))
798+
elif (
799+
member["MemberType"] == "Function" or member["MemberType"] == "Callback"
800+
):
801+
for param in member["Parameters"]:
802+
createReference(klassName, resolveClass(param["Type"]))
803+
if "TupleReturns" in member:
804+
for ret in member["TupleReturns"]:
805+
createReference(klassName, resolveClass(ret))
806+
else:
807+
createReference(klassName, resolveClass(member["ReturnType"]))
808+
elif member["MemberType"] == "Event":
809+
for param in member["Parameters"]:
810+
createReference(klassName, resolveClass(param["Type"]))
811+
812+
visited: set[str] = set()
813+
tempMark: set[str] = set()
814+
sort: List[DataType] = []
815+
816+
def visit(klass: DataType):
817+
n = klass["Name"]
818+
819+
if n in visited:
820+
return
821+
822+
if n in tempMark:
823+
raise RuntimeError()
824+
825+
tempMark.add(n)
826+
827+
for child in graph[n]:
828+
visit(next(filter(lambda d: d["Name"] == child, dataTypes)))
829+
830+
tempMark.remove(n)
831+
visited.add(n)
832+
sort.append(klass)
833+
834+
stack: List[DataType] = []
835+
for klass in dataTypes:
836+
stack.append(klass)
837+
838+
while stack:
839+
klass = stack.pop()
840+
if klass["Name"] not in visited:
841+
visit(klass)
842+
843+
return list(reversed(sort))
844+
845+
773846
# Print global types
774847
dataTypes: DataTypesDump = json.loads(requests.get(DATA_TYPES_URL).text)
775848
dump: ApiDump = json.loads(requests.get(API_DUMP_URL).text)
@@ -783,7 +856,8 @@ def loadClassesIntoStructures(dump: ApiDump):
783856

784857
print(START_BASE)
785858
printEnums(dump)
786-
printDataTypes(dataTypes)
859+
printDataTypes(topologicalSortDataTypes(dataTypes["DataTypes"]))
860+
print(POST_DATATYPES_BASE)
787861
printClasses(dump)
788862
printDataTypeConstructors(dataTypes)
789863
print(END_BASE)

scripts/globalTypes.d.lua

Lines changed: 76 additions & 108 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)