summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-10-06 17:07:22 -0400
committerGitHub <noreply@github.com>2020-10-06 14:07:22 -0700
commit4ad2e52662a00f7d8b25be6d451bba33ba62947f (patch)
treeabd70777a73037c44e40d182e332c7a19c60e779
parent8a70e20df6f47678c146eb29f89655aa734f97c7 (diff)
Use Reflection for (Serial)RefObject Serialization (#1567)
* First pass at generalizing serializer. * Split out ReflectClassInfo * Use the general ReflectClassInfo * Fix some typos in debug generalized serialization. * Add calculation of classIds. Make distinct addCopy/add on SerialClasses. * Write up of more generalized serialization * WIP to transition from ASTSerialReader/Writer etc to generalized SerialReader/Writer and associated types. * Improvements to SerialExtraObjects. Keep RefObjects in scope in factory * Compiles with Serial refactor - doesn't quite work yet. * First pass serialization appears to work with refector. * Split out type info for general slang types. * Split out slang-serialize-misc-type-info.h * DebugSerialData -> SerialSourecLocData DebugSerialReader -> SerialSourceLocReader DebugSerialWriter -> SerialSourceLocWriter * Remove unused template that only compiles on VS. * Fix warning around unused function on non-VS. * Improve output of type names that are in scopes in C++ extractor. Update premake5.lua to run generation for RefObject derived types. * C++ extractor working on RefObject type. * Split out serialization functionality that spans different types into slang-serialization-factory.cpp/.h Put AST type info into header. Removed RefObjectSerialSubType - use RefObjectType Add filtering for RefObject derived types Remove construction and filteringhacks. * Set up field serialization for SerialRefObject derived types. * Fix template problem compiling on Clang/Gcc * Work in progress to make Value types work. * Added slang-value-reflect.cpp
-rw-r--r--premake5.lua99
-rw-r--r--source/slang/run-generators.vcxproj29
-rw-r--r--source/slang/run-generators.vcxproj.filters3
-rw-r--r--source/slang/slang-ast-base.h3
-rw-r--r--source/slang/slang-ast-reflect.h13
-rw-r--r--source/slang/slang-ast-support-types.h176
-rw-r--r--source/slang/slang-ref-object-reflect.cpp85
-rw-r--r--source/slang/slang-ref-object-reflect.h69
-rw-r--r--source/slang/slang-serialize-ast-type-info.h401
-rw-r--r--source/slang/slang-serialize-ast.cpp558
-rw-r--r--source/slang/slang-serialize-ast.h31
-rw-r--r--source/slang/slang-serialize-container.cpp5
-rw-r--r--source/slang/slang-serialize-factory.cpp133
-rw-r--r--source/slang/slang-serialize-factory.h48
-rw-r--r--source/slang/slang-serialize-misc-type-info.h5
-rw-r--r--source/slang/slang-serialize-reflection.h16
-rw-r--r--source/slang/slang-serialize-type-info.h5
-rw-r--r--source/slang/slang-serialize.cpp41
-rw-r--r--source/slang/slang-serialize.h48
-rw-r--r--source/slang/slang-value-reflect.cpp8
-rw-r--r--source/slang/slang-value-reflect.h6
-rw-r--r--source/slang/slang.vcxproj11
-rw-r--r--source/slang/slang.vcxproj.filters33
-rw-r--r--tools/slang-cpp-extractor/slang-cpp-extractor-diagnostic-defs.h5
-rw-r--r--tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp358
25 files changed, 1292 insertions, 897 deletions
diff --git a/premake5.lua b/premake5.lua
index 3dcb5dd2e..0d3887986 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -269,7 +269,12 @@ function dumpTable(o)
return s .. '} '
end
-
+function getExecutableSuffix()
+ if(os.target() == "windows") then
+ return ".exe"
+ end
+ return ""
+end
--
-- We are now going to start defining the projects, where
-- each project builds some binary artifact (an executable,
@@ -768,6 +773,40 @@ tool "gfx"
-- might be able to do pic(true)
buildoptions{"-fPIC"}
+
+function runCPPExtractor(sourcePath, name, inputFiles, stripPrefix, typeName, markSuffix)
+
+ local generatedName = "slang-" .. name .. "-generated.h"
+ local generatedMacroName = "slang-" .. name .. "-generated-macro.h"
+
+ local options = { "-strip-prefix", stripPrefix, "-reflect-type", typeName, " ", "-o", "slang-" .. name .. "-generated", "-output-fields", "-mark-suffix", markSuffix}
+
+ -- Specify the actual command to run for this action.
+ --
+ -- Note that we use a single-quoted Lua string and wrap the path
+ -- to the `slang-cpp-extractor` command in double quotes to avoid
+ -- confusing the Windows shell. It seems that Premake outputs that
+ -- path with forward slashes, which confused the shell if we don't
+ -- quote the executable path.
+
+ local buildcmd = '"%{cfg.targetdir}/slang-cpp-extractor" -d ' .. sourcePath .. " " .. table.concat(inputFiles, " ") .. " " .. table.concat(options, " ")
+
+ buildcommands { buildcmd }
+
+ -- Specify the files output by the extactor - so custom action will run when these files are needed.
+ --
+ buildoutputs { sourcePath .. generatedName, sourcePath .. generatedMacroName}
+
+ -- Make it depend on the extractor tool itself
+ local buildInputTable = { "%{cfg.targetdir}/slang-cpp-extractor" .. getExecutableSuffix() }
+ for key, inputFile in ipairs(inputFiles) do
+ table.insert(buildInputTable, sourcePath .. "/" .. inputFile)
+ end
+
+ --
+ buildinputs(buildInputTable)
+end
+
--
-- The `slangc` command-line application is just a very thin wrapper
-- around the Slang dynamic library, so its build is extermely simple.
@@ -781,7 +820,6 @@ standardProject "slangc"
kind "ConsoleApp"
links { "core", "slang" }
-
generatorProject("run-generators", "source/slang/")
-- We make 'source/slang' the location of the source, to make paths to source
@@ -792,9 +830,10 @@ generatorProject("run-generators", "source/slang/")
files
{
- "source/slang/*.meta.slang", -- The stdlib files
- "source/slang/slang-ast-reflect.h", -- The C++ reflection
- "prelude/*.h", -- The prelude files
+ "source/slang/*.meta.slang", -- The stdlib files
+ "source/slang/slang-ast-reflect.h", -- C++ reflection
+ "source/slang/slang-ref-object-reflect.h", -- More C++ reflection
+ "prelude/*.h", -- The prelude files
--
-- To build we need to have some source! It has to be a source file that
@@ -811,46 +850,28 @@ generatorProject("run-generators", "source/slang/")
--
dependson { "slang-cpp-extractor", "slang-generate", "slang-embed" }
- local executableSuffix = "";
- if(os.target() == "windows") then
- executableSuffix = ".exe";
- end
-
+ local executableSuffix = getExecutableSuffix()
+
-- We need to run the C++ extractor to generate some include files
if executeBinary then
- filter "files:**/slang-ast-reflect.h"
- buildmessage "slang-cpp-extractor AST %{file.relpath}"
-
- -- Where the input files are located
- local sourcePath = "%{file.directory}/"
-
- -- Specify the files that will be used for the generation
- local inputFiles = { "slang-ast-base.h", "slang-ast-decl.h", "slang-ast-expr.h", "slang-ast-modifier.h", "slang-ast-stmt.h", "slang-ast-type.h", "slang-ast-val.h" }
-
- -- Specify the actual command to run for this action.
- --
- -- Note that we use a single-quoted Lua string and wrap the path
- -- to the `slang-cpp-extractor` command in double quotes to avoid
- -- confusing the Windows shell. It seems that Premake outputs that
- -- path with forward slashes, which confused the shell if we don't
- -- quote the executable path.
-
- local buildcmd = '"%{cfg.targetdir}/slang-cpp-extractor" -d ' .. sourcePath .. " " .. table.concat(inputFiles, " ") .. " -strip-prefix slang-ast- -o slang-ast-generated -output-fields"
+ local sourcePath = "%{file.directory}"
+
+ filter "files:**/slang-ast-reflect.h"
- buildcommands { buildcmd }
+ buildmessage "slang-cpp-extractor value%{file.relpath}"
+
+ runCPPExtractor(sourcePath, "value", { "slang-ast-support-types.h" }, "slang-", "Value", "_VALUE_CLASS")
- -- Specify the files output by the extactor - so custom action will run when these files are needed.
- --
- buildoutputs { sourcePath .. "slang-ast-generated.h", sourcePath .. "slang-ast-generated-macro.h"}
+ filter "files:**/slang-ast-reflect.h"
+ buildmessage "slang-cpp-extractor ref-object %{file.relpath}"
+
+ runCPPExtractor(sourcePath, "ref-object", { "slang-ast-support-types.h" }, "slang-", "RefObject", "_OBJ_CLASS")
- -- Make it depend on the extractor tool itself
- local buildInputTable = { "%{cfg.targetdir}/slang-cpp-extractor" .. executableSuffix }
- for key, inputFile in ipairs(inputFiles) do
- table.insert(buildInputTable, sourcePath .. inputFile)
+ filter "files:**/slang-ast-reflect.h"
+ do
+ local inputFiles = { "slang-ast-base.h", "slang-ast-decl.h", "slang-ast-expr.h", "slang-ast-modifier.h", "slang-ast-stmt.h", "slang-ast-type.h", "slang-ast-val.h" }
+ runCPPExtractor(sourcePath, "ast", inputFiles, "slang-ast", "ASTNode", "_CLASS")
end
-
- --
- buildinputs(buildInputTable)
end
-- Next, we want to add a custom build rule for each of the
diff --git a/source/slang/run-generators.vcxproj b/source/slang/run-generators.vcxproj
index 82b993466..56924b0d5 100644
--- a/source/slang/run-generators.vcxproj
+++ b/source/slang/run-generators.vcxproj
@@ -156,6 +156,7 @@
<ItemGroup>
<ClInclude Include="..\..\prelude\slang-cpp-scalar-intrinsics.h" />
<ClInclude Include="..\..\prelude\slang-cpp-types.h" />
+ <ClInclude Include="slang-ref-object-reflect.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\core\slang-string.cpp" />
@@ -228,16 +229,24 @@
</CustomBuild>
<CustomBuild Include="slang-ast-reflect.h">
<FileType>Document</FileType>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated -output-fields</Command>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated -output-fields</Command>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated -output-fields</Command>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated -output-fields</Command>
- <Outputs>slang-ast-generated.h;slang-ast-generated-macro.h</Outputs>
- <Message>slang-cpp-extractor AST %(Identity)</Message>
- <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
- <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
- <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../bin/windows-x86/release/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
- <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../bin/windows-x64/release/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type Value -o slang-value-generated -output-fields -mark-suffix _VALUE_CLASS
+"../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type RefObject -o slang-ref-object-generated -output-fields -mark-suffix _OBJ_CLASS
+"../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast -reflect-type ASTNode -o slang-ast-generated -output-fields -mark-suffix _CLASS</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type Value -o slang-value-generated -output-fields -mark-suffix _VALUE_CLASS
+"../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type RefObject -o slang-ref-object-generated -output-fields -mark-suffix _OBJ_CLASS
+"../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast -reflect-type ASTNode -o slang-ast-generated -output-fields -mark-suffix _CLASS</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type Value -o slang-value-generated -output-fields -mark-suffix _VALUE_CLASS
+"../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type RefObject -o slang-ref-object-generated -output-fields -mark-suffix _OBJ_CLASS
+"../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast -reflect-type ASTNode -o slang-ast-generated -output-fields -mark-suffix _CLASS</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type Value -o slang-value-generated -output-fields -mark-suffix _VALUE_CLASS
+"../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-support-types.h -strip-prefix slang- -reflect-type RefObject -o slang-ref-object-generated -output-fields -mark-suffix _OBJ_CLASS
+"../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory) slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast -reflect-type ASTNode -o slang-ast-generated -output-fields -mark-suffix _CLASS</Command>
+ <Outputs>../slangslang-value-generated.h;../slangslang-value-generated-macro.h;../slangslang-ref-object-generated.h;../slangslang-ref-object-generated-macro.h;../slangslang-ast-generated.h;../slangslang-ast-generated-macro.h</Outputs>
+ <Message>slang-cpp-extractor ref-object %(Identity)</Message>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">slang-ast-support-types.h;../../bin/windows-x86/debug/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">slang-ast-support-types.h;../../bin/windows-x64/debug/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">slang-ast-support-types.h;../../bin/windows-x86/release/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">slang-ast-support-types.h;../../bin/windows-x64/release/slang-cpp-extractor.exe;slang-ast-base.h;slang-ast-decl.h;slang-ast-expr.h;slang-ast-modifier.h;slang-ast-stmt.h;slang-ast-type.h;slang-ast-val.h</AdditionalInputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/source/slang/run-generators.vcxproj.filters b/source/slang/run-generators.vcxproj.filters
index e8ec8394a..9ec19c0d7 100644
--- a/source/slang/run-generators.vcxproj.filters
+++ b/source/slang/run-generators.vcxproj.filters
@@ -15,6 +15,9 @@
<ClInclude Include="..\..\prelude\slang-cpp-types.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ref-object-reflect.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\core\slang-string.cpp">
diff --git a/source/slang/slang-ast-base.h b/source/slang/slang-ast-base.h
index 275832342..66b7d7c9e 100644
--- a/source/slang/slang-ast-base.h
+++ b/source/slang/slang-ast-base.h
@@ -14,12 +14,11 @@
// basic `Decl`, `Stmt`, `Expr`, `type`, etc. definitions come from.
namespace Slang
-{
+{
class NodeBase
{
SLANG_ABSTRACT_CLASS(NodeBase)
- SLANG_CLASS_ROOT
// MUST be called before used. Called automatically via the ASTBuilder.
// Note that the astBuilder is not stored in the NodeBase derived types by default.
diff --git a/source/slang/slang-ast-reflect.h b/source/slang/slang-ast-reflect.h
index 3b055cc87..63bd889b8 100644
--- a/source/slang/slang-ast-reflect.h
+++ b/source/slang/slang-ast-reflect.h
@@ -3,11 +3,9 @@
#ifndef SLANG_AST_REFLECT_H
#define SLANG_AST_REFLECT_H
-#include "slang-ast-generated.h"
+#include "slang-serialize-reflection.h"
-#define SLANG_CLASS_REFLECT_SUPER_BASE(SUPER)
-#define SLANG_CLASS_REFLECT_SUPER_INNER(SUPER) typedef SUPER Super;
-#define SLANG_CLASS_REFLECT_SUPER_LEAF(SUPER) typedef SUPER Super;
+#include "slang-ast-generated.h"
// Implementation for SLANG_ABSTRACT_CLASS(x) using reflection from C++ extractor in slang-ast-generated.h
#define SLANG_CLASS_REFLECT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
@@ -28,13 +26,6 @@
#define SLANG_ABSTRACT_CLASS(NAME) SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_IMPL, _)
#define SLANG_CLASS(NAME) SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_IMPL, _)
-// Does nothing - just a mark to the C++ extractor
-#define SLANG_REFLECT_BASE_CLASS(NAME)
-#define SLANG_REFLECTED
-#define SLANG_UNREFLECTED
-
-#define SLANG_CLASS_ROOT
-
// Macros for simulating virtual methods without virtual methods
#define SLANG_AST_NODE_INVOKE(method, methodParams) _##method##Override methodParams
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
index ae2f6e6be..4cc76804c 100644
--- a/source/slang/slang-ast-support-types.h
+++ b/source/slang/slang-ast-support-types.h
@@ -9,12 +9,13 @@
#include "../core/slang-semantic-version.h"
-#include "slang-ast-generated.h"
-
-#include "slang-ast-reflect.h"
+#include "slang-ast-generated.h"
#include "slang-serialize-reflection.h"
+#include "slang-ast-reflect.h"
+#include "slang-ref-object-reflect.h"
+
#include "slang-name.h"
#include <assert.h>
@@ -444,6 +445,8 @@ namespace Slang
struct QualType
{
+ SLANG_VALUE_CLASS(QualType)
+
Type* type = nullptr;
bool isLeftValue;
@@ -1003,9 +1006,98 @@ namespace Slang
IgnoreBaseInterfaces = 1 << 0,
};
+ class SerialRefObject;
+ // Make sure C++ extractor can see the base class.
+ SLANG_PRE_DECLARE(_OBJ_CLASS, class SerialRefObject)
+
+ class LookupResultItem_Breadcrumb : public SerialRefObject
+ {
+ public:
+ SLANG_OBJ_CLASS(LookupResultItem_Breadcrumb)
+
+ enum class Kind : uint8_t
+ {
+ // The lookup process looked "through" an in-scope
+ // declaration to the fields inside of it, so that
+ // even if lookup started with a simple name `f`,
+ // it needs to result in a member expression `obj.f`.
+ Member,
+
+ // The lookup process took a pointer(-like) value, and then
+ // proceeded to derefence it and look at the thing(s)
+ // it points to instead, so that the final expression
+ // needs to have `(*obj)`
+ Deref,
+
+ // The lookup process saw a value `obj` of type `T` and
+ // took into account an in-scope constraint that says
+ // `T` is a subtype of some other type `U`, so that
+ // lookup was able to find a member through type `U`
+ // instead.
+ SuperType,
+
+ // The lookup process considered a member of an
+ // enclosing type as being in scope, so that any
+ // reference to that member needs to use a `this`
+ // expression as appropriate.
+ This,
+ };
+
+ // The kind of lookup step that was performed
+ Kind kind;
+
+ // For the `Kind::This` case, what does the implicit
+ // `this` or `This` parameter refer to?
+ //
+ enum class ThisParameterMode : uint8_t
+ {
+ ImmutableValue, // An immutable `this` value
+ MutableValue, // A mutable `this` value
+ Type, // A `This` type
+
+ Default = ImmutableValue,
+ };
+ ThisParameterMode thisParameterMode = ThisParameterMode::Default;
+
+ // As needed, a reference to the declaration that faciliated
+ // the lookup step.
+ //
+ // For a `Member` lookup step, this is the declaration whose
+ // members were implicitly pulled into scope.
+ //
+ // For a `Constraint` lookup step, this is the `ConstraintDecl`
+ // that serves to witness the subtype relationship.
+ //
+ DeclRef<Decl> declRef;
+
+ Val* val = nullptr;
+
+ // The next implicit step that the lookup process took to
+ // arrive at a final value.
+ RefPtr<LookupResultItem_Breadcrumb> next;
+
+ LookupResultItem_Breadcrumb(
+ Kind kind,
+ DeclRef<Decl> declRef,
+ Val* val,
+ RefPtr<LookupResultItem_Breadcrumb> next,
+ ThisParameterMode thisParameterMode = ThisParameterMode::Default)
+ : kind(kind)
+ , thisParameterMode(thisParameterMode)
+ , declRef(declRef)
+ , val(val)
+ , next(next)
+ {}
+ protected:
+ // Needed for serialization
+ LookupResultItem_Breadcrumb() = default;
+ };
+
// Represents one item found during lookup
struct LookupResultItem
{
+ typedef LookupResultItem_Breadcrumb Breadcrumb;
+
// Sometimes lookup finds an item, but there were additional
// "hops" taken to reach it. We need to remember these steps
// so that if/when we consturct a full expression we generate
@@ -1058,83 +1150,7 @@ namespace Slang
// the unique result (perhaps by overload resolution), then
// we can walk the list of breadcrumbs to create a full
// expression.
- class Breadcrumb : public RefObject
- {
- public:
- enum class Kind : uint8_t
- {
- // The lookup process looked "through" an in-scope
- // declaration to the fields inside of it, so that
- // even if lookup started with a simple name `f`,
- // it needs to result in a member expression `obj.f`.
- Member,
-
- // The lookup process took a pointer(-like) value, and then
- // proceeded to derefence it and look at the thing(s)
- // it points to instead, so that the final expression
- // needs to have `(*obj)`
- Deref,
-
- // The lookup process saw a value `obj` of type `T` and
- // took into account an in-scope constraint that says
- // `T` is a subtype of some other type `U`, so that
- // lookup was able to find a member through type `U`
- // instead.
- SuperType,
-
- // The lookup process considered a member of an
- // enclosing type as being in scope, so that any
- // reference to that member needs to use a `this`
- // expression as appropriate.
- This,
- };
-
- // The kind of lookup step that was performed
- Kind kind;
-
- // For the `Kind::This` case, what does the implicit
- // `this` or `This` parameter refer to?
- //
- enum class ThisParameterMode : uint8_t
- {
- ImmutableValue, // An immutable `this` value
- MutableValue, // A mutable `this` value
- Type, // A `This` type
-
- Default = ImmutableValue,
- };
- ThisParameterMode thisParameterMode = ThisParameterMode::Default;
-
- // As needed, a reference to the declaration that faciliated
- // the lookup step.
- //
- // For a `Member` lookup step, this is the declaration whose
- // members were implicitly pulled into scope.
- //
- // For a `Constraint` lookup step, this is the `ConstraintDecl`
- // that serves to witness the subtype relationship.
- //
- DeclRef<Decl> declRef;
-
- Val* val = nullptr;
-
- // The next implicit step that the lookup process took to
- // arrive at a final value.
- RefPtr<Breadcrumb> next;
-
- Breadcrumb(
- Kind kind,
- DeclRef<Decl> declRef,
- Val* val,
- RefPtr<Breadcrumb> next,
- ThisParameterMode thisParameterMode = ThisParameterMode::Default)
- : kind(kind)
- , thisParameterMode(thisParameterMode)
- , declRef(declRef)
- , val(val)
- , next(next)
- {}
- };
+
// A properly-specialized reference to the declaration that was found.
DeclRef<Decl> declRef;
diff --git a/source/slang/slang-ref-object-reflect.cpp b/source/slang/slang-ref-object-reflect.cpp
new file mode 100644
index 000000000..caf8eb6a3
--- /dev/null
+++ b/source/slang/slang-ref-object-reflect.cpp
@@ -0,0 +1,85 @@
+#include "../../slang.h"
+
+#include "slang-ref-object-reflect.h"
+
+#include "slang-ref-object-generated.h"
+#include "slang-ref-object-generated-macro.h"
+
+#include "slang-ast-support-types.h"
+
+//#include "slang-serialize.h"
+
+#include "slang-serialize-ast-type-info.h"
+
+namespace Slang
+{
+
+static const SerialClass* _addClass(SerialClasses* serialClasses, RefObjectType type, RefObjectType super, const List<SerialField>& fields)
+{
+ const SerialClass* superClass = serialClasses->getSerialClass(SerialTypeKind::RefObject, SerialSubType(super));
+ return serialClasses->add(SerialTypeKind::RefObject, SerialSubType(type), fields.getBuffer(), fields.getCount(), superClass);
+}
+
+#define SLANG_REF_OBJECT_ADD_SERIAL_FIELD(FIELD_NAME, TYPE, param) fields.add(SerialField::make(#FIELD_NAME, &obj->FIELD_NAME));
+
+// Note that the obj point is not nullptr, because some compilers notice this is 'indexing from null'
+// and warn/error. So we offset from 1.
+#define SLANG_REF_OBJECT_ADD_SERIAL_CLASS(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+{ \
+ NAME* obj = SerialField::getPtr<NAME>(); \
+ SLANG_UNUSED(obj); \
+ fields.clear(); \
+ SLANG_FIELDS_RefObject_##NAME(SLANG_REF_OBJECT_ADD_SERIAL_FIELD, param) \
+ _addClass(serialClasses, RefObjectType::NAME, RefObjectType::SUPER, fields); \
+}
+
+struct RefObjectAccess
+{
+ template <typename T>
+ static void* create(void* context)
+ {
+ SLANG_UNUSED(context)
+ return new T;
+ }
+
+ static void calcClasses(SerialClasses* serialClasses)
+ {
+ // Add SerialRefObject first, and specially handle so that we add a null super class
+ serialClasses->add(SerialTypeKind::RefObject, SerialSubType(RefObjectType::SerialRefObject), nullptr, 0, nullptr);
+
+ // Add the rest in order such that Super class is always added before its children
+ List<SerialField> fields;
+ SLANG_CHILDREN_RefObject_SerialRefObject(SLANG_REF_OBJECT_ADD_SERIAL_CLASS, _)
+ }
+};
+
+#define SLANG_GET_SUPER_BASE(SUPER) nullptr
+#define SLANG_GET_SUPER_INNER(SUPER) &SUPER::kReflectClassInfo
+#define SLANG_GET_SUPER_LEAF(SUPER) &SUPER::kReflectClassInfo
+
+#define SLANG_GET_CREATE_FUNC_NONE(NAME) nullptr
+#define SLANG_GET_CREATE_FUNC_OBJ_ABSTRACT(NAME) nullptr
+#define SLANG_GET_CREATE_FUNC_OBJ(NAME) &RefObjectAccess::create<NAME>
+
+#define SLANG_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ /* static */const ReflectClassInfo NAME::kReflectClassInfo = { uint32_t(RefObjectType::NAME), uint32_t(RefObjectType::LAST), SLANG_GET_SUPER_##TYPE(SUPER), #NAME, SLANG_GET_CREATE_FUNC_##MARKER(NAME), nullptr, uint32_t(sizeof(NAME)), uint8_t(SLANG_ALIGN_OF(NAME)) };
+
+SLANG_ALL_RefObject_SerialRefObject(SLANG_REFLECT_CLASS_INFO, _)
+
+/* static */const SerialRefObjects SerialRefObjects::g_singleton;
+
+// Macro to set all of the entries in m_infos for SerialRefObjects
+#define SLANG_GET_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) m_infos[Index(RefObjectType::NAME)] = &NAME::kReflectClassInfo;
+
+SerialRefObjects::SerialRefObjects()
+{
+ SLANG_ALL_RefObject_SerialRefObject(SLANG_GET_REFLECT_CLASS_INFO, _)
+}
+
+/* static */SlangResult SerialRefObjects::addSerialClasses(SerialClasses* serialClasses)
+{
+ RefObjectAccess::calcClasses(serialClasses);
+ return SLANG_OK;
+}
+
+} // namespace Slang
diff --git a/source/slang/slang-ref-object-reflect.h b/source/slang/slang-ref-object-reflect.h
new file mode 100644
index 000000000..cf50c010a
--- /dev/null
+++ b/source/slang/slang-ref-object-reflect.h
@@ -0,0 +1,69 @@
+// slang-ref-object-reflect.h
+
+#ifndef SLANG_REF_OBJECT_REFLECT_H
+#define SLANG_REF_OBJECT_REFLECT_H
+
+#include "slang-serialize-reflection.h"
+
+#include "slang-ref-object-generated.h"
+
+#include "../core/slang-smart-pointer.h"
+
+class SerialClasses;
+
+struct RefObjectAccess;
+
+#define SLANG_OBJ_CLASS_REFLECT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ public: \
+ typedef NAME This; \
+ static const ReflectClassInfo kReflectClassInfo; \
+ virtual const ReflectClassInfo* getClassInfo() const SLANG_OVERRIDE { return &kReflectClassInfo; } \
+ \
+ friend struct RefObjectAccess; \
+ \
+ SLANG_CLASS_REFLECT_SUPER_##TYPE(SUPER) \
+
+// Placed in any SerialRefObject derived class
+#define SLANG_ABSTRACT_OBJ_CLASS(NAME) SLANG_RefObject_##NAME(SLANG_OBJ_CLASS_REFLECT_IMPL, _)
+#define SLANG_OBJ_CLASS(NAME) SLANG_RefObject_##NAME(SLANG_OBJ_CLASS_REFLECT_IMPL, _)
+
+namespace Slang
+{
+
+class SerialClasses;
+
+// Is friended such that internally we have access to construct or get members
+struct RefObjectAccess;
+
+// Base class for Serialized RefObject derived classes. The main feature is that gives away to get ReflectClassInfo
+// via getClassInfo() method
+class SerialRefObject : public RefObject
+{
+public:
+ typedef RefObject Super;
+ typedef SerialRefObject This;
+
+ static const ReflectClassInfo kReflectClassInfo;
+
+ virtual const ReflectClassInfo* getClassInfo() const { return &kReflectClassInfo; }
+};
+
+// For turning RefObjectType back to ReflectClassInfo
+struct SerialRefObjects
+{
+ /// Add serialization classes
+ static SlangResult addSerialClasses(SerialClasses* serialClasses);
+
+ static const ReflectClassInfo* getClassInfo(RefObjectType type) { return g_singleton.m_infos[Index(type)]; }
+
+
+ static const SerialRefObjects g_singleton;
+
+protected:
+ SerialRefObjects();
+ const ReflectClassInfo* m_infos[Index(RefObjectType::CountOf)];
+};
+
+} // namespace Slang
+
+#endif // SLANG_REF_OBJECT_REFLECT_H
diff --git a/source/slang/slang-serialize-ast-type-info.h b/source/slang/slang-serialize-ast-type-info.h
new file mode 100644
index 000000000..03fe61fbb
--- /dev/null
+++ b/source/slang/slang-serialize-ast-type-info.h
@@ -0,0 +1,401 @@
+// slang-serialize-ast-type-info.h
+#ifndef SLANG_SERIALIZE_AST_TYPE_INFO_H
+#define SLANG_SERIALIZE_AST_TYPE_INFO_H
+
+#include "slang-ast-support-types.h"
+#include "slang-ast-all.h"
+
+#include "slang-serialize-type-info.h"
+#include "slang-serialize-misc-type-info.h"
+
+namespace Slang {
+
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AST types !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+// SyntaxClass<T>
+template <typename T>
+struct SerialTypeInfo<SyntaxClass<T>>
+{
+ typedef SyntaxClass<T> NativeType;
+ typedef uint16_t SerialType;
+
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ SLANG_UNUSED(writer);
+ auto& src = *(const NativeType*)native;
+ auto& dst = *(SerialType*)serial;
+ dst = SerialType(src.classInfo->m_classId);
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ SLANG_UNUSED(reader);
+ auto& src = *(const SerialType*)serial;
+ auto& dst = *(NativeType*)native;
+ dst.classInfo = ASTClassInfo::getInfo(ASTNodeType(src));
+ }
+};
+
+struct SerialDeclRefBaseTypeInfo
+{
+ typedef DeclRefBase NativeType;
+ struct SerialType
+ {
+ SerialIndex substitutions;
+ SerialIndex decl;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* inNative, void* outSerial)
+ {
+ SerialType& serial = *(SerialType*)outSerial;
+ const NativeType& native = *(const NativeType*)inNative;
+
+ serial.decl = writer->addPointer(native.decl);
+ serial.substitutions = writer->addPointer(native.substitutions.substitutions);
+ }
+ static void toNative(SerialReader* reader, const void* inSerial, void* outNative)
+ {
+ DeclRefBase& native = *(DeclRefBase*)(outNative);
+ const SerialType& serial = *(const SerialType*)inSerial;
+
+ native.decl = reader->getPointer(serial.decl).dynamicCast<Decl>();
+ native.substitutions.substitutions = reader->getPointer(serial.substitutions).dynamicCast<Substitutions>();
+ }
+ static const SerialFieldType* getFieldType()
+ {
+ static const SerialFieldType type = { sizeof(SerialType), uint8_t(SerialAlignment), &toSerial, &toNative };
+ return &type;
+ }
+};
+// Special case DeclRef, because it always uses the same type
+template <typename T>
+struct SerialGetFieldType<DeclRef<T>>
+{
+ static const SerialFieldType* getFieldType() { return SerialDeclRefBaseTypeInfo::getFieldType(); }
+};
+
+
+template <typename T>
+struct SerialTypeInfo<DeclRef<T>> : public SerialDeclRefBaseTypeInfo {};
+
+// MatrixCoord can just go as is
+template <>
+struct SerialTypeInfo<MatrixCoord> : SerialIdentityTypeInfo<MatrixCoord> {};
+
+
+// QualType
+
+template <>
+struct SerialTypeInfo<QualType>
+{
+ typedef QualType NativeType;
+ struct SerialType
+ {
+ SerialIndex type;
+ uint8_t isLeftValue;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto dst = (SerialType*)serial;
+ auto src = (const NativeType*)native;
+ dst->isLeftValue = src->isLeftValue ? 1 : 0;
+ dst->type = writer->addPointer(src->type);
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto src = (const SerialType*)serial;
+ auto dst = (NativeType*)native;
+ dst->type = reader->getPointer(src->type).dynamicCast<Type>();
+ dst->isLeftValue = src->isLeftValue != 0;
+ }
+};
+
+
+// LookupResult::Breadcrumb
+template <>
+struct SerialTypeInfo<LookupResultItem::Breadcrumb>
+{
+ typedef LookupResultItem::Breadcrumb NativeType;
+ struct SerialType
+ {
+ NativeType::Kind kind;
+ NativeType::ThisParameterMode thisParameterMode;
+ SerialTypeInfo<DeclRef<Decl>>::SerialType declRef;
+ SerialTypeInfo<RefPtr<NativeType>> next;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& src = *(const NativeType*)native;
+ auto& dst = *(SerialType*)serial;
+
+ dst.kind = src.kind;
+ dst.thisParameterMode = src.thisParameterMode;
+ toSerialValue(writer, src.declRef, dst.declRef);
+ toSerialValue(writer, src.next, dst.next);
+ }
+
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& dst = *(NativeType*)native;
+ auto& src = *(const SerialType*)serial;
+
+ dst.kind = src.kind;
+ dst.thisParameterMode = src.thisParameterMode;
+ toNativeValue(reader, src.declRef, dst.declRef);
+ toNativeValue(reader, src.next, dst.next);
+ }
+};
+
+// LookupResultItem
+template <>
+struct SerialTypeInfo<LookupResultItem>
+{
+ typedef LookupResultItem NativeType;
+ struct SerialType
+ {
+ SerialTypeInfo<DeclRef<Decl>>::SerialType declRef;
+ SerialTypeInfo<RefPtr<NativeType::Breadcrumb>> breadcrumbs;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& src = *(const NativeType*)native;
+ auto& dst = *(SerialType*)serial;
+
+ toSerialValue(writer, src.declRef, dst.declRef);
+ toSerialValue(writer, src.breadcrumbs, dst.breadcrumbs);
+ }
+
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& dst = *(NativeType*)native;
+ auto& src = *(const SerialType*)serial;
+
+ toNativeValue(reader, src.declRef, dst.declRef);
+ toNativeValue(reader, src.breadcrumbs, dst.breadcrumbs);
+ }
+};
+
+// LookupResult
+template <>
+struct SerialTypeInfo<LookupResult>
+{
+ typedef LookupResult NativeType;
+ typedef SerialIndex SerialType;
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& src = *(const NativeType*)native;
+ auto& dst = *(SerialType*)serial;
+
+ if (src.isOverloaded())
+ {
+ // Save off as an array
+ dst = writer->addArray(src.items.getBuffer(), src.items.getCount());
+ }
+ else if (src.item.declRef.getDecl())
+ {
+ dst = writer->addArray(&src.item, 1);
+ }
+ else
+ {
+ dst = SerialIndex(0);
+ }
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& dst = *(NativeType*)native;
+ auto& src = *(const SerialType*)serial;
+
+ // Initialize
+ dst = NativeType();
+
+ List<LookupResultItem> items;
+ reader->getArray(src, items);
+
+ if (items.getCount() == 1)
+ {
+ dst.item = items[0];
+ }
+ else
+ {
+ dst.items.swapWith(items);
+ // We have to set item such that it is valid/member of items, if items is non empty
+ dst.item = dst.items[0];
+ }
+ }
+};
+
+// GlobalGenericParamSubstitution::ConstraintArg
+template <>
+struct SerialTypeInfo<GlobalGenericParamSubstitution::ConstraintArg>
+{
+ typedef GlobalGenericParamSubstitution::ConstraintArg NativeType;
+ struct SerialType
+ {
+ SerialIndex decl;
+ SerialIndex val;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& dst = *(SerialType*)serial;
+ auto& src = *(const NativeType*)native;
+
+ dst.decl = writer->addPointer(src.decl);
+ dst.val = writer->addPointer(src.val);
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& src = *(const SerialType*)serial;
+ auto& dst = *(NativeType*)native;
+
+ dst.decl = reader->getPointer(src.decl).dynamicCast<Decl>();
+ dst.val = reader->getPointer(src.val).dynamicCast<Val>();
+ }
+};
+
+// ExpandedSpecializationArg
+template <>
+struct SerialTypeInfo<ExpandedSpecializationArg>
+{
+ typedef ExpandedSpecializationArg NativeType;
+ struct SerialType
+ {
+ SerialIndex val;
+ SerialIndex witness;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& dst = *(SerialType*)serial;
+ auto& src = *(const NativeType*)native;
+
+ dst.witness = writer->addPointer(src.witness);
+ dst.val = writer->addPointer(src.val);
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& src = *(const SerialType*)serial;
+ auto& dst = *(NativeType*)native;
+
+ dst.witness = reader->getPointer(src.witness).dynamicCast<Val>();
+ dst.val = reader->getPointer(src.val).dynamicCast<Val>();
+ }
+};
+
+// TypeExp
+template <>
+struct SerialTypeInfo<TypeExp>
+{
+ typedef TypeExp NativeType;
+ struct SerialType
+ {
+ SerialIndex type;
+ SerialIndex expr;
+ };
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ auto& dst = *(SerialType*)serial;
+ auto& src = *(const NativeType*)native;
+
+ dst.type = writer->addPointer(src.type);
+ dst.expr = writer->addPointer(src.exp);
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ auto& src = *(const SerialType*)serial;
+ auto& dst = *(NativeType*)native;
+
+ dst.type = reader->getPointer(src.type).dynamicCast<Type>();
+ dst.exp = reader->getPointer(src.expr).dynamicCast<Expr>();
+ }
+};
+
+// DeclCheckStateExt
+template <>
+struct SerialTypeInfo<DeclCheckStateExt>
+{
+ typedef DeclCheckStateExt NativeType;
+ typedef DeclCheckStateExt::RawType SerialType;
+
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ SLANG_UNUSED(writer);
+ *(SerialType*)serial = (*(const NativeType*)native).getRaw();
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ SLANG_UNUSED(reader);
+ (*(NativeType*)serial).setRaw(*(const SerialType*)native);
+ }
+};
+
+// Modifiers
+template <>
+struct SerialTypeInfo<Modifiers>
+{
+ typedef Modifiers NativeType;
+ typedef SerialIndex SerialType;
+
+ enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
+
+ static void toSerial(SerialWriter* writer, const void* native, void* serial)
+ {
+ // We need to make into an array
+ List<SerialIndex> modifierIndices;
+ for (Modifier* modifier : *(NativeType*)native)
+ {
+ modifierIndices.add(writer->addPointer(modifier));
+ }
+ *(SerialType*)serial = writer->addArray(modifierIndices.getBuffer(), modifierIndices.getCount());
+ }
+ static void toNative(SerialReader* reader, const void* serial, void* native)
+ {
+ List<Modifier*> modifiers;
+ reader->getArray(*(const SerialType*)serial, modifiers);
+
+ Modifier* prev = nullptr;
+ for (Modifier* modifier : modifiers)
+ {
+ if (prev)
+ {
+ prev->next = modifier;
+ }
+ }
+
+ NativeType& dst = *(NativeType*)native;
+ dst.first = modifiers.getCount() > 0 ? modifiers[0] : nullptr;
+ }
+};
+
+// ASTNodeType
+template <>
+struct SerialTypeInfo<ASTNodeType> : public SerialConvertTypeInfo<ASTNodeType, uint16_t> {};
+
+// LookupResultItem_Breadcrumb::ThisParameterMode
+template <>
+struct SerialTypeInfo<LookupResultItem_Breadcrumb::ThisParameterMode> : public SerialConvertTypeInfo<LookupResultItem_Breadcrumb::ThisParameterMode, uint8_t> {};
+
+// LookupResultItem_Breadcrumb::Kind
+template <>
+struct SerialTypeInfo<LookupResultItem_Breadcrumb::Kind> : public SerialConvertTypeInfo<LookupResultItem_Breadcrumb::Kind, uint8_t> {};
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-serialize-ast.cpp b/source/slang/slang-serialize-ast.cpp
index 65a5488a3..8310c155b 100644
--- a/source/slang/slang-serialize-ast.cpp
+++ b/source/slang/slang-serialize-ast.cpp
@@ -8,475 +8,27 @@
#include "slang-ast-support-types.h"
-// Needed for ModuleSerialFilter
-// Needed for 'findModuleForDecl'
-#include "slang-legalize-types.h"
-#include "slang-mangle.h"
+#include "slang-serialize-ast-type-info.h"
-#include "slang-serialize-type-info.h"
-#include "slang-serialize-misc-type-info.h"
+#include "slang-serialize-factory.h"
namespace Slang {
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ModuleSerialFilter !!!!!!!!!!!!!!!!!!!!!!!!
-
-SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBase* inPtr)
-{
- NodeBase* ptr = const_cast<NodeBase*>(inPtr);
- SLANG_ASSERT(ptr);
-
- if (Decl* decl = as<Decl>(ptr))
- {
- ModuleDecl* moduleDecl = findModuleForDecl(decl);
- SLANG_ASSERT(moduleDecl);
- if (moduleDecl && moduleDecl != m_moduleDecl)
- {
- ASTBuilder* astBuilder = m_moduleDecl->module->getASTBuilder();
-
- // It's a reference to a declaration in another module, so create an ImportExternalDecl.
-
- String mangledName = getMangledName(astBuilder, decl);
-
- ImportExternalDecl* importDecl = astBuilder->create<ImportExternalDecl>();
- importDecl->mangledName = mangledName;
- const SerialIndex index = writer->addPointer(importDecl);
-
- // Set as the index of this
- writer->setPointerIndex(ptr, index);
-
- return index;
- }
- else
- {
- // Okay... we can just write it out then
- return writer->writeObject(ptr);
- }
- }
-
- // TODO(JS): What we really want to do here is to ignore bodies functions.
- // It's not 100% clear if this is even right though - for example does type inference
- // imply the body is needed to say infer a return type?
- // Also not clear if statements in other scenarios (if there are others) might need to be kept.
- //
- // For now we just ignore all stmts
-
- if (Stmt* stmt = as<Stmt>(ptr))
- {
- //
- writer->setPointerIndex(stmt, SerialIndex(0));
- return SerialIndex(0);
- }
-
- // For now for everything else just write it
- return writer->writeObject(ptr);
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AST types !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-// SyntaxClass<T>
-template <typename T>
-struct SerialTypeInfo<SyntaxClass<T>>
-{
- typedef SyntaxClass<T> NativeType;
- typedef uint16_t SerialType;
-
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- SLANG_UNUSED(writer);
- auto& src = *(const NativeType*)native;
- auto& dst = *(SerialType*)serial;
- dst = SerialType(src.classInfo->m_classId);
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- SLANG_UNUSED(reader);
- auto& src = *(const SerialType*)serial;
- auto& dst = *(NativeType*)native;
- dst.classInfo = ASTClassInfo::getInfo(ASTNodeType(src));
- }
-};
-
-struct SerialDeclRefBaseTypeInfo
-{
- typedef DeclRefBase NativeType;
- struct SerialType
- {
- SerialIndex substitutions;
- SerialIndex decl;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* inNative, void* outSerial)
- {
- SerialType& serial = *(SerialType*)outSerial;
- const NativeType& native = *(const NativeType*)inNative;
-
- serial.decl = writer->addPointer(native.decl);
- serial.substitutions = writer->addPointer(native.substitutions.substitutions);
- }
- static void toNative(SerialReader* reader, const void* inSerial, void* outNative)
- {
- DeclRefBase& native = *(DeclRefBase*)(outNative);
- const SerialType& serial = *(const SerialType*)inSerial;
-
- native.decl = reader->getPointer(serial.decl).dynamicCast<Decl>();
- native.substitutions.substitutions = reader->getPointer(serial.substitutions).dynamicCast<Substitutions>();
- }
- static const SerialFieldType* getFieldType()
- {
- static const SerialFieldType type = { sizeof(SerialType), uint8_t(SerialAlignment), &toSerial, &toNative };
- return &type;
- }
-};
-// Special case DeclRef, because it always uses the same type
-template <typename T>
-struct SerialGetFieldType<DeclRef<T>>
-{
- static const SerialFieldType* getFieldType() { return SerialDeclRefBaseTypeInfo::getFieldType(); }
-};
-
-
-template <typename T>
-struct SerialTypeInfo<DeclRef<T>> : public SerialDeclRefBaseTypeInfo {};
-
-// MatrixCoord can just go as is
-template <>
-struct SerialTypeInfo<MatrixCoord> : SerialIdentityTypeInfo<MatrixCoord> {};
-
-
-// QualType
-
-template <>
-struct SerialTypeInfo<QualType>
-{
- typedef QualType NativeType;
- struct SerialType
- {
- SerialIndex type;
- uint8_t isLeftValue;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto dst = (SerialType*)serial;
- auto src = (const NativeType*)native;
- dst->isLeftValue = src->isLeftValue ? 1 : 0;
- dst->type = writer->addPointer(src->type);
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto src = (const SerialType*)serial;
- auto dst = (NativeType*)native;
- dst->type = reader->getPointer(src->type).dynamicCast<Type>();
- dst->isLeftValue = src->isLeftValue != 0;
- }
-};
-
-
-// LookupResult::Breadcrumb
-template <>
-struct SerialTypeInfo<LookupResultItem::Breadcrumb>
-{
- typedef LookupResultItem::Breadcrumb NativeType;
- struct SerialType
- {
- NativeType::Kind kind;
- NativeType::ThisParameterMode thisParameterMode;
- SerialTypeInfo<DeclRef<Decl>>::SerialType declRef;
- SerialTypeInfo<RefPtr<NativeType>> next;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& src = *(const NativeType*)native;
- auto& dst = *(SerialType*)serial;
-
- dst.kind = src.kind;
- dst.thisParameterMode = src.thisParameterMode;
- toSerialValue(writer, src.declRef, dst.declRef);
- toSerialValue(writer, src.next, dst.next);
- }
-
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& dst = *(NativeType*)native;
- auto& src = *(const SerialType*)serial;
-
- dst.kind = src.kind;
- dst.thisParameterMode = src.thisParameterMode;
- toNativeValue(reader, src.declRef, dst.declRef);
- toNativeValue(reader, src.next, dst.next);
- }
-};
-
-// LookupResultItem
-template <>
-struct SerialTypeInfo<LookupResultItem>
-{
- typedef LookupResultItem NativeType;
- struct SerialType
- {
- SerialTypeInfo<DeclRef<Decl>>::SerialType declRef;
- SerialTypeInfo<RefPtr<NativeType::Breadcrumb>> breadcrumbs;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& src = *(const NativeType*)native;
- auto& dst = *(SerialType*)serial;
-
- toSerialValue(writer, src.declRef, dst.declRef);
- toSerialValue(writer, src.breadcrumbs, dst.breadcrumbs);
- }
-
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& dst = *(NativeType*)native;
- auto& src = *(const SerialType*)serial;
-
- toNativeValue(reader, src.declRef, dst.declRef);
- toNativeValue(reader, src.breadcrumbs, dst.breadcrumbs);
- }
-};
-
-// LookupResult
-template <>
-struct SerialTypeInfo<LookupResult>
-{
- typedef LookupResult NativeType;
- typedef SerialIndex SerialType;
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& src = *(const NativeType*)native;
- auto& dst = *(SerialType*)serial;
-
- if (src.isOverloaded())
- {
- // Save off as an array
- dst = writer->addArray(src.items.getBuffer(), src.items.getCount());
- }
- else if (src.item.declRef.getDecl())
- {
- dst = writer->addArray(&src.item, 1);
- }
- else
- {
- dst = SerialIndex(0);
- }
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& dst = *(NativeType*)native;
- auto& src = *(const SerialType*)serial;
-
- // Initialize
- dst = NativeType();
-
- List<LookupResultItem> items;
- reader->getArray(src, items);
-
- if (items.getCount() == 1)
- {
- dst.item = items[0];
- }
- else
- {
- dst.items.swapWith(items);
- // We have to set item such that it is valid/member of items, if items is non empty
- dst.item = dst.items[0];
- }
- }
-};
-
-// GlobalGenericParamSubstitution::ConstraintArg
-template <>
-struct SerialTypeInfo<GlobalGenericParamSubstitution::ConstraintArg>
-{
- typedef GlobalGenericParamSubstitution::ConstraintArg NativeType;
- struct SerialType
- {
- SerialIndex decl;
- SerialIndex val;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& dst = *(SerialType*)serial;
- auto& src = *(const NativeType*)native;
-
- dst.decl = writer->addPointer(src.decl);
- dst.val = writer->addPointer(src.val);
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& src = *(const SerialType*)serial;
- auto& dst = *(NativeType*)native;
-
- dst.decl = reader->getPointer(src.decl).dynamicCast<Decl>();
- dst.val = reader->getPointer(src.val).dynamicCast<Val>();
- }
-};
-
-// ExpandedSpecializationArg
-template <>
-struct SerialTypeInfo<ExpandedSpecializationArg>
-{
- typedef ExpandedSpecializationArg NativeType;
- struct SerialType
- {
- SerialIndex val;
- SerialIndex witness;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& dst = *(SerialType*)serial;
- auto& src = *(const NativeType*)native;
-
- dst.witness = writer->addPointer(src.witness);
- dst.val = writer->addPointer(src.val);
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& src = *(const SerialType*)serial;
- auto& dst = *(NativeType*)native;
-
- dst.witness = reader->getPointer(src.witness).dynamicCast<Val>();
- dst.val = reader->getPointer(src.val).dynamicCast<Val>();
- }
-};
-
-// TypeExp
-template <>
-struct SerialTypeInfo<TypeExp>
-{
- typedef TypeExp NativeType;
- struct SerialType
- {
- SerialIndex type;
- SerialIndex expr;
- };
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialIndex) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- auto& dst = *(SerialType*)serial;
- auto& src = *(const NativeType*)native;
-
- dst.type = writer->addPointer(src.type);
- dst.expr = writer->addPointer(src.exp);
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- auto& src = *(const SerialType*)serial;
- auto& dst = *(NativeType*)native;
-
- dst.type = reader->getPointer(src.type).dynamicCast<Type>();
- dst.exp = reader->getPointer(src.expr).dynamicCast<Expr>();
- }
-};
-
-// DeclCheckStateExt
-template <>
-struct SerialTypeInfo<DeclCheckStateExt>
-{
- typedef DeclCheckStateExt NativeType;
- typedef DeclCheckStateExt::RawType SerialType;
-
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- SLANG_UNUSED(writer);
- *(SerialType*)serial = (*(const NativeType*)native).getRaw();
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- SLANG_UNUSED(reader);
- (*(NativeType*)serial).setRaw(*(const SerialType*)native);
- }
-};
-
-// Modifiers
-template <>
-struct SerialTypeInfo<Modifiers>
-{
- typedef Modifiers NativeType;
- typedef SerialIndex SerialType;
-
- enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) };
-
- static void toSerial(SerialWriter* writer, const void* native, void* serial)
- {
- // We need to make into an array
- List<SerialIndex> modifierIndices;
- for (Modifier* modifier : *(NativeType*)native)
- {
- modifierIndices.add(writer->addPointer(modifier));
- }
- *(SerialType*)serial = writer->addArray(modifierIndices.getBuffer(), modifierIndices.getCount());
- }
- static void toNative(SerialReader* reader, const void* serial, void* native)
- {
- List<Modifier*> modifiers;
- reader->getArray(*(const SerialType*)serial, modifiers);
-
- Modifier* prev = nullptr;
- for (Modifier* modifier : modifiers)
- {
- if (prev)
- {
- prev->next = modifier;
- }
- }
-
- NativeType& dst = *(NativeType*)native;
- dst.first = modifiers.getCount() > 0 ? modifiers[0] : nullptr;
- }
-};
-
-// ASTNodeType
-template <>
-struct SerialTypeInfo<ASTNodeType> : public SerialConvertTypeInfo<ASTNodeType, uint16_t> {};
-
// !!!!!!!!!!!!!!!!!!!!!! Generate fields for a type !!!!!!!!!!!!!!!!!!!!!!!!!!!
-template <typename T>
-SerialField _makeField(const char* name, T& in)
-{
- uint8_t* ptr = &reinterpret_cast<uint8_t&>(in);
-
- SerialField field;
- field.name = name;
- field.type = SerialGetFieldType<T>::getFieldType();
- // This only works because we in is an offset from 1
- field.nativeOffset = uint32_t(size_t(ptr) - 1);
- field.serialOffset = 0;
- return field;
-}
-
static const SerialClass* _addClass(SerialClasses* serialClasses, ASTNodeType type, ASTNodeType super, const List<SerialField>& fields)
{
const SerialClass* superClass = serialClasses->getSerialClass(SerialTypeKind::NodeBase, SerialSubType(super));
return serialClasses->add(SerialTypeKind::NodeBase, SerialSubType(type), fields.getBuffer(), fields.getCount(), superClass);
}
-#define SLANG_AST_ADD_SERIAL_FIELD(FIELD_NAME, TYPE, param) fields.add(_makeField(#FIELD_NAME, obj->FIELD_NAME));
+#define SLANG_AST_ADD_SERIAL_FIELD(FIELD_NAME, TYPE, param) fields.add(SerialField::make(#FIELD_NAME, &obj->FIELD_NAME));
// Note that the obj point is not nullptr, because some compilers notice this is 'indexing from null'
// and warn/error. So we offset from 1.
#define SLANG_AST_ADD_SERIAL_CLASS(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
{ \
- NAME* obj = (NAME*)1; \
+ NAME* obj = SerialField::getPtr<NAME>(); \
SLANG_UNUSED(obj); \
fields.clear(); \
SLANG_FIELDS_ASTNode_##NAME(SLANG_AST_ADD_SERIAL_FIELD, param) \
@@ -496,108 +48,18 @@ struct ASTFieldAccess
}
};
-void addASTTypes(SerialClasses* serialClasses)
-{
- {
- ASTFieldAccess::calcClasses(serialClasses);
- }
-
- {
- {
- // Let's hack Breadcrumbs...
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ASTSerialUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!
- typedef LookupResultItem::Breadcrumb Type;
- Type* obj = (Type*)1;
- SerialField field = _makeField("_", *obj);
- serialClasses->add(SerialTypeKind::RefObject, SerialSubType(RefObjectSerialSubType::LookupResultItem_Breadcrumb), &field, 1, nullptr);
- }
-
- // Set these types to not serialize
- serialClasses->addUnserialized(SerialTypeKind::RefObject, SerialSubType(RefObjectSerialSubType::Module));
- serialClasses->addUnserialized(SerialTypeKind::RefObject, SerialSubType(RefObjectSerialSubType::Scope));
- }
-}
-
-// A Hack for now to turn an RefObject* into a SubType for serialization
-extern RefObjectSerialSubType getRefObjectSubType(const RefObject* obj)
+/* static */void ASTSerialUtil::addSerialClasses(SerialClasses* serialClasses)
{
- if (as<LookupResultItem::Breadcrumb>(obj))
- {
- return RefObjectSerialSubType::LookupResultItem_Breadcrumb;
- }
- else if (as<Module>(obj))
- {
- return RefObjectSerialSubType::Module;
- }
- else if (as<Scope>(obj))
- {
- return RefObjectSerialSubType::Scope;
- }
- return RefObjectSerialSubType::Invalid;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!! DefaultSerialObjectFactory !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* DefaultSerialObjectFactory::create(SerialTypeKind typeKind, SerialSubType subType)
-{
- switch (typeKind)
- {
- case SerialTypeKind::NodeBase:
- {
- return m_astBuilder->createByNodeType(ASTNodeType(subType));
- }
- case SerialTypeKind::RefObject:
- {
- switch (RefObjectSerialSubType(subType))
- {
- case RefObjectSerialSubType::LookupResultItem_Breadcrumb:
- {
- typedef LookupResultItem::Breadcrumb Breadcrumb;
- return _add(new LookupResultItem::Breadcrumb(Breadcrumb::Kind::Member, DeclRef<Decl>(), nullptr, nullptr));
- }
- default: break;
- }
- }
- default: break;
- }
-
- return nullptr;
+ ASTFieldAccess::calcClasses(serialClasses);
}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ASTSerializeUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-/* static */SlangResult ASTSerialTestUtil::selfTest()
+
+/* static */SlangResult ASTSerialUtil::testSerialize(NodeBase* node, RootNamePool* rootNamePool, SharedASTBuilder* sharedASTBuilder, SourceManager* sourceManager)
{
RefPtr<SerialClasses> classes;
- SerialClasses::create(classes);
- {
- const SerialFieldType* type = SerialGetFieldType<Type*>::getFieldType();
- SLANG_UNUSED(type);
- }
-
- {
- const SerialFieldType* type = SerialGetFieldType<int[10]>::getFieldType();
- SLANG_UNUSED(type);
- }
-
- {
- const SerialFieldType* type = SerialGetFieldType<bool[3]>::getFieldType();
- SLANG_UNUSED(type);
- }
-
- {
- const SerialFieldType* type = SerialGetFieldType<Type*[3]>::getFieldType();
- SLANG_UNUSED(type);
- }
-
- return SLANG_OK;
-}
-
-/* static */SlangResult ASTSerialTestUtil::testSerialize(NodeBase* node, RootNamePool* rootNamePool, SharedASTBuilder* sharedASTBuilder, SourceManager* sourceManager)
-{
- RefPtr<SerialClasses> classes;
- SerialClasses::create(classes);
+ SerialClassesUtil::create(classes);
List<uint8_t> contents;
diff --git a/source/slang/slang-serialize-ast.h b/source/slang/slang-serialize-ast.h
index e2b9a956a..3aa790c86 100644
--- a/source/slang/slang-serialize-ast.h
+++ b/source/slang/slang-serialize-ast.h
@@ -30,6 +30,7 @@ class ModuleSerialFilter : public SerialFilter
public:
// SerialFilter impl
virtual SerialIndex writePointer(SerialWriter* writer, const NodeBase* ptr) SLANG_OVERRIDE;
+ virtual SerialIndex writePointer(SerialWriter* writer, const RefObject* ptr) SLANG_OVERRIDE;
ModuleSerialFilter(ModuleDecl* moduleDecl):
m_moduleDecl(moduleDecl)
@@ -39,34 +40,10 @@ public:
ModuleDecl* m_moduleDecl;
};
-class DefaultSerialObjectFactory : public SerialObjectFactory
+struct ASTSerialUtil
{
-public:
-
- virtual void* create(SerialTypeKind typeKind, SerialSubType subType) SLANG_OVERRIDE;
-
- DefaultSerialObjectFactory(ASTBuilder* astBuilder) :
- m_astBuilder(astBuilder)
- {
- }
-
-protected:
- RefObject* _add(RefObject* obj)
- {
- m_scope.add(obj);
- return obj;
- }
-
- // We keep RefObjects in scope
- List<RefPtr<RefObject>> m_scope;
- ASTBuilder* m_astBuilder;
-};
-
-/* None of the functions in this util should *not* be called from production code,
-they exist to test features of AST Serialization */
-struct ASTSerialTestUtil
-{
- static SlangResult selfTest();
+ /// Add the AST related classes
+ static void addSerialClasses(SerialClasses* classes);
/// Tries to serialize out, read back in and test the results are the same.
/// Will write dumped out node to files
diff --git a/source/slang/slang-serialize-container.cpp b/source/slang/slang-serialize-container.cpp
index 3d5b234ff..7dd2c15a1 100644
--- a/source/slang/slang-serialize-container.cpp
+++ b/source/slang/slang-serialize-container.cpp
@@ -10,6 +10,7 @@
#include "slang-serialize-ast.h"
#include "slang-serialize-ir.h"
#include "slang-serialize-source-loc.h"
+#include "slang-serialize-factory.h"
namespace Slang {
@@ -143,7 +144,7 @@ namespace Slang {
{
if (!serialClasses)
{
- SLANG_RETURN_ON_FAIL(SerialClasses::create(serialClasses));
+ SLANG_RETURN_ON_FAIL(SerialClassesUtil::create(serialClasses));
}
ModuleSerialFilter filter(moduleDecl);
@@ -295,7 +296,7 @@ namespace Slang {
{
if (!serialClasses)
{
- SLANG_RETURN_ON_FAIL(SerialClasses::create(serialClasses));
+ SLANG_RETURN_ON_FAIL(SerialClassesUtil::create(serialClasses));
}
// TODO(JS): We probably want to store off better information about each of the translation unit
diff --git a/source/slang/slang-serialize-factory.cpp b/source/slang/slang-serialize-factory.cpp
new file mode 100644
index 000000000..2bb7b047e
--- /dev/null
+++ b/source/slang/slang-serialize-factory.cpp
@@ -0,0 +1,133 @@
+// slang-serialize-factory.cpp
+#include "slang-serialize-factory.h"
+
+#include "../core/slang-math.h"
+
+#include "slang-ast-builder.h"
+
+#include "slang-ref-object-reflect.h"
+#include "slang-ast-reflect.h"
+
+#include "slang-serialize-ast.h"
+#include "slang-ref-object-reflect.h"
+
+// Needed for ModuleSerialFilter
+// Needed for 'findModuleForDecl'
+#include "slang-legalize-types.h"
+#include "slang-mangle.h"
+
+namespace Slang {
+
+/* !!!!!!!!!!!!!!!!!!!!!! DefaultSerialObjectFactory !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void* DefaultSerialObjectFactory::create(SerialTypeKind typeKind, SerialSubType subType)
+{
+ switch (typeKind)
+ {
+ case SerialTypeKind::NodeBase:
+ {
+ return m_astBuilder->createByNodeType(ASTNodeType(subType));
+ }
+ case SerialTypeKind::RefObject:
+ {
+ const ReflectClassInfo* info = SerialRefObjects::getClassInfo(RefObjectType(subType));
+
+ if (info && info->m_createFunc)
+ {
+ RefObject* obj = reinterpret_cast<RefObject*>(info->m_createFunc(nullptr));
+ return _add(obj);
+ }
+ return nullptr;
+ }
+ default: break;
+ }
+
+ return nullptr;
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ModuleSerialFilter !!!!!!!!!!!!!!!!!!!!!!!!
+
+SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const RefObject* inPtr)
+{
+ // We don't serialize Module or Scope
+ if (as<Module>(inPtr) || as<Scope>(inPtr))
+ {
+ writer->setPointerIndex(inPtr, SerialIndex(0));
+ return SerialIndex(0);
+ }
+
+ // For now for everything else just write it
+ return writer->writeObject(inPtr);
+}
+
+SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBase* inPtr)
+{
+ NodeBase* ptr = const_cast<NodeBase*>(inPtr);
+ SLANG_ASSERT(ptr);
+
+ if (Decl* decl = as<Decl>(ptr))
+ {
+ ModuleDecl* moduleDecl = findModuleForDecl(decl);
+ SLANG_ASSERT(moduleDecl);
+ if (moduleDecl && moduleDecl != m_moduleDecl)
+ {
+ ASTBuilder* astBuilder = m_moduleDecl->module->getASTBuilder();
+
+ // It's a reference to a declaration in another module, so create an ImportExternalDecl.
+
+ String mangledName = getMangledName(astBuilder, decl);
+
+ ImportExternalDecl* importDecl = astBuilder->create<ImportExternalDecl>();
+ importDecl->mangledName = mangledName;
+ const SerialIndex index = writer->addPointer(importDecl);
+
+ // Set as the index of this
+ writer->setPointerIndex(ptr, index);
+
+ return index;
+ }
+ else
+ {
+ // Okay... we can just write it out then
+ return writer->writeObject(ptr);
+ }
+ }
+
+ // TODO(JS): What we really want to do here is to ignore bodies functions.
+ // It's not 100% clear if this is even right though - for example does type inference
+ // imply the body is needed to say infer a return type?
+ // Also not clear if statements in other scenarios (if there are others) might need to be kept.
+ //
+ // For now we just ignore all stmts
+
+ if (Stmt* stmt = as<Stmt>(ptr))
+ {
+ //
+ writer->setPointerIndex(stmt, SerialIndex(0));
+ return SerialIndex(0);
+ }
+
+ // For now for everything else just write it
+ return writer->writeObject(ptr);
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SerialClassesUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+/* static */SlangResult SerialClassesUtil::addSerialClasses(SerialClasses* serialClasses)
+{
+ ASTSerialUtil::addSerialClasses(serialClasses);
+ SerialRefObjects::addSerialClasses(serialClasses);
+
+ return SLANG_OK;
+}
+
+/* static */SlangResult SerialClassesUtil::create(RefPtr<SerialClasses>& out)
+{
+ RefPtr<SerialClasses> classes(new SerialClasses);
+ SLANG_RETURN_ON_FAIL(addSerialClasses(classes));
+
+ out = classes;
+ return SLANG_OK;
+}
+
+} // namespace Slang
diff --git a/source/slang/slang-serialize-factory.h b/source/slang/slang-serialize-factory.h
new file mode 100644
index 000000000..7e51a840d
--- /dev/null
+++ b/source/slang/slang-serialize-factory.h
@@ -0,0 +1,48 @@
+// slang-serialize-factory.h
+#ifndef SLANG_SERIALIZE_FACTORY_H
+#define SLANG_SERIALIZE_FACTORY_H
+
+#include "slang-serialize.h"
+
+namespace Slang {
+
+// !!!!!!!!!!!!!!!!!!!!! DefaultSerialObjectFactory !!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+class ASTBuilder;
+
+class DefaultSerialObjectFactory : public SerialObjectFactory
+{
+public:
+
+ virtual void* create(SerialTypeKind typeKind, SerialSubType subType) SLANG_OVERRIDE;
+
+ DefaultSerialObjectFactory(ASTBuilder* astBuilder) :
+ m_astBuilder(astBuilder)
+ {
+ }
+
+protected:
+ RefObject* _add(RefObject* obj)
+ {
+ m_scope.add(obj);
+ return obj;
+ }
+
+ // We keep RefObjects in scope
+ List<RefPtr<RefObject>> m_scope;
+ ASTBuilder* m_astBuilder;
+};
+
+
+struct SerialClassesUtil
+{
+ /// Add all types to serialClasses
+ static SlangResult addSerialClasses(SerialClasses* serialClasses);
+ /// Create SerialClasses with all the types added
+ static SlangResult create(RefPtr<SerialClasses>& out);
+};
+
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-serialize-misc-type-info.h b/source/slang/slang-serialize-misc-type-info.h
index bdcbf2c98..08fd1269d 100644
--- a/source/slang/slang-serialize-misc-type-info.h
+++ b/source/slang/slang-serialize-misc-type-info.h
@@ -12,6 +12,11 @@ namespace Slang {
/* Conversion for serialization for some more misc Slang types
*/
+
+// Because is sized, we don't need to convert
+template <>
+struct SerialTypeInfo<FeedbackType::Kind> : public SerialIdentityTypeInfo<FeedbackType::Kind> {};
+
// SamplerStateFlavor
template <>
diff --git a/source/slang/slang-serialize-reflection.h b/source/slang/slang-serialize-reflection.h
index 045b7bf97..a6889f795 100644
--- a/source/slang/slang-serialize-reflection.h
+++ b/source/slang/slang-serialize-reflection.h
@@ -57,6 +57,22 @@ struct ReflectClassInfo
uint8_t m_alignment; ///< The required alignment of the type
};
+// Does nothing - just a mark to the C++ extractor
+#define SLANG_REFLECTED
+#define SLANG_UNREFLECTED
+
+#define SLANG_PRE_DECLARE(SUFFIX, DEF)
+
+// Use these macros to help define Super, and making the base definition NOT have a Super definition.
+// For example something like...
+
+#define SLANG_CLASS_REFLECT_SUPER_BASE(SUPER)
+#define SLANG_CLASS_REFLECT_SUPER_INNER(SUPER) typedef SUPER Super;
+#define SLANG_CLASS_REFLECT_SUPER_LEAF(SUPER) typedef SUPER Super;
+
+// Mark a value class
+#define SLANG_VALUE_CLASS(x)
+
} // namespace Slang
#endif
diff --git a/source/slang/slang-serialize-type-info.h b/source/slang/slang-serialize-type-info.h
index 5440fc201..89097fc32 100644
--- a/source/slang/slang-serialize-type-info.h
+++ b/source/slang/slang-serialize-type-info.h
@@ -62,11 +62,6 @@ struct SerialIdentityTypeInfo
template <>
struct SerialTypeInfo<SerialIndex> : public SerialIdentityTypeInfo<SerialIndex> {};
-
-// Because is sized, we don't need to convert
-template <>
-struct SerialTypeInfo<FeedbackType::Kind> : public SerialIdentityTypeInfo<FeedbackType::Kind> {};
-
// Implement for Basic Types
template <>
diff --git a/source/slang/slang-serialize.cpp b/source/slang/slang-serialize.cpp
index 06ddbdde0..46aae18b2 100644
--- a/source/slang/slang-serialize.cpp
+++ b/source/slang/slang-serialize.cpp
@@ -156,24 +156,6 @@ SerialClasses::SerialClasses():
{
}
-// For now just use an extern so we don't need to include AST serialize
-extern void addASTTypes(SerialClasses* serialClasses);
-extern RefObjectSerialSubType getRefObjectSubType(const RefObject* obj);
-
-/* static */SlangResult SerialClasses::create(RefPtr<SerialClasses>& out)
-{
- RefPtr<SerialClasses> classes(new SerialClasses);
- addASTTypes(classes);
-
- out = classes;
- return SLANG_OK;
-}
-
-/* static */RefObjectSerialSubType SerialClasses::getSubType(const RefObject* obj)
-{
- return getRefObjectSubType(obj);
-}
-
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SerialWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!
SerialWriter::SerialWriter(SerialClasses* classes, SerialFilter* filter) :
@@ -238,14 +220,17 @@ SerialIndex SerialWriter::writeObject(const NodeBase* node)
SerialIndex SerialWriter::writeObject(const RefObject* obj)
{
- const RefObjectSerialSubType subType = SerialClasses::getSubType(obj);
- if (subType == RefObjectSerialSubType::Invalid)
+ const SerialRefObject* serialObj = as<const SerialRefObject>(obj);
+ if (!serialObj)
{
SLANG_ASSERT(!"Unhandled type");
return SerialIndex(0);
}
- const SerialClass* serialClass = m_classes->getSerialClass(SerialTypeKind::RefObject, SerialSubType(subType));
+ const ReflectClassInfo* classInfo = serialObj->getClassInfo();
+ SLANG_ASSERT(classInfo);
+
+ const SerialClass* serialClass = m_classes->getSerialClass(SerialTypeKind::RefObject, SerialSubType(classInfo->m_classId));
return writeObject(serialClass, (const void*)obj);
}
@@ -254,6 +239,11 @@ void SerialWriter::setPointerIndex(const NodeBase* ptr, SerialIndex index)
m_ptrMap.Add(ptr, Index(index));
}
+void SerialWriter::setPointerIndex(const RefObject* ptr, SerialIndex index)
+{
+ m_ptrMap.Add(ptr, Index(index));
+}
+
SerialIndex SerialWriter::addPointer(const NodeBase* node)
{
// Null is always 0
@@ -307,7 +297,14 @@ SerialIndex SerialWriter::addPointer(const RefObject* obj)
return addName(name);
}
- return writeObject(obj);
+ if (m_filter)
+ {
+ return m_filter->writePointer(this, obj);
+ }
+ else
+ {
+ return writeObject(obj);
+ }
}
SerialIndex SerialWriter::addString(const UnownedStringSlice& slice)
diff --git a/source/slang/slang-serialize.h b/source/slang/slang-serialize.h
index d43bb7960..4c6a57b34 100644
--- a/source/slang/slang-serialize.h
+++ b/source/slang/slang-serialize.h
@@ -2,7 +2,7 @@
#ifndef SLANG_SERIALIZE_H
#define SLANG_SERIALIZE_H
-#include <type_traits>
+//#include <type_traits>
#include "../core/slang-riff.h"
#include "../core/slang-byte-encode-util.h"
@@ -283,22 +283,6 @@ enum class SerialTypeKind : uint8_t
};
typedef uint16_t SerialSubType;
-enum class RefObjectSerialSubType
-{
- Invalid, ///< Invalid (ie not a known RefObject type)
- LookupResultItem_Breadcrumb,
-
- // TODO(JS):
- // ! We don't want to serialize these types.
- // We could set a nullptr SerialClass in classes ?
- // Perhaps we need some special SerialClass that indicates we want to always write as 0?
-
- Scope,
- Module,
-
- CountOf,
-};
-
struct SerialInfo
{
enum
@@ -416,6 +400,7 @@ class SerialFilter
{
public:
virtual SerialIndex writePointer(SerialWriter* writer, const NodeBase* ptr) = 0;
+ virtual SerialIndex writePointer(SerialWriter* writer, const RefObject* ptr) = 0;
};
class SerialObjectFactory
@@ -556,6 +541,7 @@ public:
/// Set a the ptr associated with an index.
/// NOTE! That there cannot be a pre-existing setting.
void setPointerIndex(const NodeBase* ptr, SerialIndex index);
+ void setPointerIndex(const RefObject* ptr, SerialIndex index);
/// Get the entries table holding how each index maps to an entry
const List<SerialInfo::Entry*>& getEntries() const { return m_entries; }
@@ -641,6 +627,14 @@ struct SerialFieldType
/* Describes a field in a SerialClass. */
struct SerialField
{
+ /// Returns a suitable ptr for use in make.
+ /// NOTE! Sets to 1 so it's constant and not 0 (and so nullptr)
+ template <typename T>
+ static T* getPtr() { return (T*)1; }
+
+ template <typename T>
+ static SerialField make(const char* name, T* in);
+
const char* name; ///< The name of the field
const SerialFieldType* type; ///< The type of the field
uint32_t nativeOffset; ///< Offset to field from base of type
@@ -704,10 +698,6 @@ public:
/// Ctor
SerialClasses();
- static SlangResult create(RefPtr<SerialClasses>& out);
-
- static RefObjectSerialSubType getSubType(const RefObject* obj);
-
protected:
SerialClass* _createSerialClass(const SerialClass* cls);
@@ -730,6 +720,22 @@ struct SerialGetFieldType
}
};
+// !!!!!!!!!!!!!!!!!!!!! SerialGetFieldType<T> !!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+template <typename T>
+/* static */SerialField SerialField::make(const char* name, T* in)
+{
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(in);
+
+ SerialField field;
+ field.name = name;
+ field.type = SerialGetFieldType<T>::getFieldType();
+ // This only works because we in is an offset from 1
+ field.nativeOffset = uint32_t(size_t(ptr) - 1);
+ field.serialOffset = 0;
+ return field;
+}
+
// !!!!!!!!!!!!!!!!!!!!! Convenience functions !!!!!!!!!!!!!!!!!!!!!!!!!!!
template <typename NATIVE_TYPE, typename SERIAL_TYPE>
diff --git a/source/slang/slang-value-reflect.cpp b/source/slang/slang-value-reflect.cpp
new file mode 100644
index 000000000..9a7f1feb3
--- /dev/null
+++ b/source/slang/slang-value-reflect.cpp
@@ -0,0 +1,8 @@
+#include "../../slang.h"
+
+#include "slang-value-reflect.h"
+
+namespace Slang
+{
+
+} // namespace Slang
diff --git a/source/slang/slang-value-reflect.h b/source/slang/slang-value-reflect.h
new file mode 100644
index 000000000..4d6ec5582
--- /dev/null
+++ b/source/slang/slang-value-reflect.h
@@ -0,0 +1,6 @@
+// slang-value-reflect.h
+
+#ifndef SLANG_VALUE_REFLECT_H
+#define SLANG_VALUE_REFLECT_H
+
+#endif // SLANG_VALUE_REFLECT_H
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index 7dafd3823..ec3066778 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -281,10 +281,15 @@
<ClInclude Include="slang-preprocessor.h" />
<ClInclude Include="slang-profile-defs.h" />
<ClInclude Include="slang-profile.h" />
+ <ClInclude Include="slang-ref-object-generated-macro.h" />
+ <ClInclude Include="slang-ref-object-generated.h" />
+ <ClInclude Include="slang-ref-object-reflect.h" />
<ClInclude Include="slang-reflection.h" />
<ClInclude Include="slang-repro.h" />
+ <ClInclude Include="slang-serialize-ast-type-info.h" />
<ClInclude Include="slang-serialize-ast.h" />
<ClInclude Include="slang-serialize-container.h" />
+ <ClInclude Include="slang-serialize-factory.h" />
<ClInclude Include="slang-serialize-ir-types.h" />
<ClInclude Include="slang-serialize-ir.h" />
<ClInclude Include="slang-serialize-misc-type-info.h" />
@@ -299,6 +304,9 @@
<ClInclude Include="slang-token.h" />
<ClInclude Include="slang-type-layout.h" />
<ClInclude Include="slang-type-system-shared.h" />
+ <ClInclude Include="slang-value-generated-macro.h" />
+ <ClInclude Include="slang-value-generated.h" />
+ <ClInclude Include="slang-value-reflect.h" />
<ClInclude Include="slang-visitor.h" />
</ItemGroup>
<ItemGroup>
@@ -398,10 +406,12 @@
<ClCompile Include="slang-parser.cpp" />
<ClCompile Include="slang-preprocessor.cpp" />
<ClCompile Include="slang-profile.cpp" />
+ <ClCompile Include="slang-ref-object-reflect.cpp" />
<ClCompile Include="slang-reflection.cpp" />
<ClCompile Include="slang-repro.cpp" />
<ClCompile Include="slang-serialize-ast.cpp" />
<ClCompile Include="slang-serialize-container.cpp" />
+ <ClCompile Include="slang-serialize-factory.cpp" />
<ClCompile Include="slang-serialize-ir-types.cpp" />
<ClCompile Include="slang-serialize-ir.cpp" />
<ClCompile Include="slang-serialize-reflection.cpp" />
@@ -414,6 +424,7 @@
<ClCompile Include="slang-token.cpp" />
<ClCompile Include="slang-type-layout.cpp" />
<ClCompile Include="slang-type-system-shared.cpp" />
+ <ClCompile Include="slang-value-reflect.cpp" />
<ClCompile Include="slang.cpp" />
</ItemGroup>
<ItemGroup>
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index be81a48c2..d69ff3059 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -294,18 +294,33 @@
<ClInclude Include="slang-profile.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ref-object-generated-macro.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ref-object-generated.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ref-object-reflect.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-reflection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-repro.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-serialize-ast-type-info.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-serialize-ast.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-serialize-container.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-serialize-factory.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-serialize-ir-types.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -348,6 +363,15 @@
<ClInclude Include="slang-type-system-shared.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-value-generated-macro.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-value-generated.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-value-reflect.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-visitor.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -641,6 +665,9 @@
<ClCompile Include="slang-profile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-ref-object-reflect.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-reflection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -653,6 +680,9 @@
<ClCompile Include="slang-serialize-container.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-serialize-factory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-serialize-ir-types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -689,6 +719,9 @@
<ClCompile Include="slang-type-system-shared.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-value-reflect.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/tools/slang-cpp-extractor/slang-cpp-extractor-diagnostic-defs.h b/tools/slang-cpp-extractor/slang-cpp-extractor-diagnostic-defs.h
index 7ed2f0691..97bc8eea0 100644
--- a/tools/slang-cpp-extractor/slang-cpp-extractor-diagnostic-defs.h
+++ b/tools/slang-cpp-extractor/slang-cpp-extractor-diagnostic-defs.h
@@ -23,6 +23,9 @@ DIAGNOSTIC(-1, Note, seeOpen, "see open $0")
DIAGNOSTIC(1, Error, cannotOpenFile, "cannot open file '$0'.")
+DIAGNOSTIC(1, Error, extractorFailed, "C++ Extractor failed for '$0'")
+DIAGNOSTIC(1, Error, internalError, "Unknown internal error in C++ Extractor, aborted!")
+
// Parsing errors
DIAGNOSTIC(100000, Error, expectingToken, "Expecting token $0")
DIAGNOSTIC(100001, Error, typeAlreadyDeclared, "Type '$0' already declared")
@@ -35,6 +38,8 @@ DIAGNOSTIC(100007, Error, superTypeNotFound, "Super type not found for $0")
DIAGNOSTIC(100008, Error, superTypeNotAType, "Named super type is not a type $0")
DIAGNOSTIC(100009, Error, unexpectedUnbalancedToken, "Unexpected unbalanced token")
DIAGNOSTIC(100010, Error, unexpectedEndOfFile, "Unexpected end of file")
+DIAGNOSTIC(100011, Error, expectingTypeKeyword, "Expecting type keyword - struct or class, found $0")
+
// Command line errors 100100
diff --git a/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp b/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp
index d2f83f53e..fc5c3d1f9 100644
--- a/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp
+++ b/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp
@@ -22,6 +22,20 @@
#include "slang-cpp-extractor-diagnostics.h"
+/*
+Some command lines:
+
+For AST
+-d source/slang slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated -output-fields -mark-suffix _CLASS
+
+For RefObjects
+-d source/slang slang-ast-support-types.h -strip-prefix slang- -reflect-type RefObject -o slang-ref-object-generated -output-fields -mark-suffix _OBJ_CLASS
+
+For Values
+
+-d source/slang slang-ast-support-types.h -strip-prefix slang- -reflect-type Value -o slang-value-generated -output-fields -mark-suffix _VALUE_CLASS
+*/
+
namespace SlangExperimental
{
@@ -32,8 +46,8 @@ enum class IdentifierStyle
None, ///< It's not an identifier
Identifier, ///< Just an identifier
- Root,
- BaseClass, ///< Has the name of a base class defined elsewhere
+
+ PreDeclare, ///< Declare a type (not visible in C++ code)
TypeModifier, ///< const, volatile etc
Keyword, ///< A keyword C/C++ keyword that is not another type
@@ -63,9 +77,8 @@ struct IdentifierFlag
static const IdentifierFlags kIdentifierFlags[Index(IdentifierStyle::CountOf)] =
{
0, /// None
- 0, /// Identifier
- 0, /// Root
- 0, /// BaseClass
+ 0, /// Identifier
+ 0, /// Declare type
IdentifierFlag::Keyword, /// TypeModifier
IdentifierFlag::Keyword, /// Keyword
IdentifierFlag::Keyword | IdentifierFlag::StartScope | IdentifierFlag::ClassLike, /// Class
@@ -74,7 +87,6 @@ static const IdentifierFlags kIdentifierFlags[Index(IdentifierStyle::CountOf)] =
IdentifierFlag::Keyword, /// Access
IdentifierFlag::Reflection, /// Reflected
IdentifierFlag::Reflection, /// Unreflected
-
};
SLANG_FORCE_INLINE IdentifierFlags getFlags(IdentifierStyle style)
@@ -170,13 +182,6 @@ public:
ReflectionType reflectionType;
};
- enum class BaseType
- {
- None, ///< Neither a base or marked base
- Marked, ///< It's a marked base
- Unmarked, ///< It's a base, but it's not marked
- };
-
bool isClassLike() const { return m_type == Type::StructType || m_type == Type::ClassType; }
/// Add a child node to this nodes scope
@@ -197,6 +202,9 @@ public:
/// Calculate the absolute name for this namespace/type
void calcAbsoluteName(StringBuilder& outName) const;
+ /// Get the absolute name
+ String getAbsoluteName() const { StringBuilder buf; calcAbsoluteName(buf); return buf.ProduceString(); }
+
/// Do depth first traversal of nodes
void calcScopeDepthFirst(List<Node*>& outNodes);
@@ -226,7 +234,18 @@ public:
/// Stores in out any reflected derived types
void getReflectedDerivedTypes(List<Node*>& out) const;
- static void filterReflectedClassLike(List<Node*>& io);
+ typedef bool (*Filter)(Node* node);
+
+ static bool isClassLikeAndReflected(Node* node)
+ {
+ return node->isClassLike() && node->isReflected();
+ }
+ static bool isClassLike(Node* node)
+ {
+ return node->isClassLike();
+ }
+
+ static void filter(Filter filter, List<Node*>& io);
static void calcScopePath(Node* node, List<Node*>& outPath);
@@ -236,7 +255,6 @@ public:
m_reflectionType(ReflectionType::NotReflected),
m_reflectionOverride(ReflectionType::Reflected),
m_superNode(nullptr),
- m_baseType(BaseType::None),
m_origin(nullptr)
{
m_anonymousNamespace = nullptr;
@@ -269,9 +287,6 @@ public:
/// For child types, fields, how reflection is handled. If this type is not reflected
ReflectionType m_reflectionOverride;
- /// The base type of this
- BaseType m_baseType;
-
Token m_name; ///< The name of this scope/type
Token m_super; ///< Super class name
Token m_marker; ///< The marker associated with this scope (typically the marker is SLANG_CLASS etc, that is used to identify reflectedType)
@@ -340,7 +355,10 @@ public:
/// we allow files to be processed in any order, so we have to do the type lookup as a separate operation
SlangResult calcDerivedTypes();
- /// Only valid after calcDerivedTypes has been executed
+ /// Find the name starting in specified scope
+ Node* findNode(Node* scope, const UnownedStringSlice& name);
+
+ /// Only valid after calcDerivedTypes has been executed
const List<Node*>& getBaseTypes() const { return m_baseTypes; }
/// Get all of the parsed source origins
@@ -356,6 +374,8 @@ protected:
bool _isMarker(const UnownedStringSlice& name);
+ SlangResult _parsePreDeclare();
+
SlangResult _maybeParseNode(Node::Type type);
SlangResult _maybeParseField();
@@ -555,24 +575,26 @@ void Node::dump(int indentCount, StringBuilder& out)
void Node::calcAbsoluteName(StringBuilder& outName) const
{
- if (m_parentScope == nullptr)
+ List<Node*> path;
+ calcScopePath(const_cast<Node*>(this), path);
+
+ // 1 so we skip the global scope
+ for (Index i = 1; i < path.getCount(); ++i)
{
- if (!m_name.hasContent())
+ Node* node = path[i];
+
+ if (i > 1)
{
- return;
+ outName << "::";
}
- outName << m_name.getContent();
- }
- else
- {
- outName << "::";
- if (m_type == Type::AnonymousNamespace)
+
+ if (node->m_type == Type::AnonymousNamespace)
{
outName << "{Anonymous}";
}
else
{
- outName << m_name.getContent();
+ outName << node->m_name.getContent();
}
}
}
@@ -593,11 +615,6 @@ Index Node::calcDerivedDepth() const
Node* Node::findLastDerived()
{
- if (!isReflected())
- {
- return nullptr;
- }
-
for (Index i = m_derivedTypes.getCount() - 1; i >= 0; --i)
{
Node* derivedType = m_derivedTypes[i];
@@ -648,14 +665,15 @@ void Node::getReflectedDerivedTypes(List<Node*>& out) const
}
}
-/* static */void Node::filterReflectedClassLike(List<Node*>& ioNodes)
+/* static */void Node::filter(Filter inFilter, List<Node*>& ioNodes)
{
// Filter out all the unreflected nodes
Index count = ioNodes.getCount();
for (Index j = 0; j < count; )
{
Node* node = ioNodes[j];
- if (!node->isClassLike() || !node->isReflected())
+
+ if (!inFilter(node))
{
ioNodes.removeAt(j);
count--;
@@ -678,8 +696,8 @@ struct Options
Options()
{
- m_prefixMark = "SLANG_";
- m_postfixMark = "_CLASS";
+ m_markPrefix = "SLANG_";
+ m_markSuffix = "_CLASS";
}
bool m_defs = false; ///< If set will output a '-defs.h' file for each of the input files, that corresponds to previous defs files (although doesn't have fields/RAW)
@@ -692,8 +710,8 @@ struct Options
String m_outputPath; ///< The ouput path. Note that the extractor can generate multiple output files, and this will actually be the 'stem' of several files
String m_inputDirectory; ///< The input directory that is by default used for reading m_inputPaths from.
String m_reflectType; ///< The typename used for output
- String m_prefixMark; ///< The prefix of the 'marker' used to identify a reflected type
- String m_postfixMark; ///< The postfix of the 'marker' used to identify a reflected type
+ String m_markPrefix; ///< The prefix of the 'marker' used to identify a reflected type
+ String m_markSuffix; ///< The postfix of the 'marker' used to identify a reflected type
String m_stripFilePrefix; ///< Used for the 'origin' information, this is stripped from the source filename, and the remainder of the filename (without extension) is 'macroized'
};
@@ -704,6 +722,7 @@ struct OptionsParser
SlangResult _parseArgWithValue(const char* option, String& outValue);
SlangResult _parseArgReplaceValue(const char* option, String& outValue);
+ SlangResult _parseArgFlag(const char* option, bool& outFlag);
String m_reflectType;
@@ -713,6 +732,16 @@ struct OptionsParser
DiagnosticSink* m_sink;
};
+SlangResult OptionsParser::_parseArgFlag(const char* option, bool& outFlag)
+{
+ SLANG_ASSERT(UnownedStringSlice(m_args[m_index]) == option);
+ SLANG_ASSERT(m_index < m_argCount);
+
+ m_index ++;
+ outFlag = true;
+ return SLANG_OK;
+}
+
SlangResult OptionsParser::_parseArgWithValue(const char* option, String& ioValue)
{
SLANG_ASSERT(UnownedStringSlice(m_args[m_index]) == option);
@@ -789,25 +818,25 @@ SlangResult OptionsParser::parse(int argc, const char*const* argv, DiagnosticSin
SLANG_RETURN_ON_FAIL(_parseArgWithValue("-reflect-type", outOptions.m_reflectType));
continue;
}
- else if (arg == "-prefix-mark")
+ else if (arg == "-mark-prefix")
{
- SLANG_RETURN_ON_FAIL(_parseArgReplaceValue("-prefix-mark", outOptions.m_prefixMark));
+ SLANG_RETURN_ON_FAIL(_parseArgReplaceValue("-mark-prefix", outOptions.m_markPrefix));
continue;
}
- else if (arg == "-postfix-mark")
+ else if (arg == "-mark-suffix")
{
- SLANG_RETURN_ON_FAIL(_parseArgReplaceValue("-postfix-mark", outOptions.m_postfixMark));
+ SLANG_RETURN_ON_FAIL(_parseArgReplaceValue("-mark-suffix", outOptions.m_markSuffix));
continue;
}
else if (arg == "-defs")
{
- outOptions.m_defs = true;
+ SLANG_RETURN_ON_FAIL(_parseArgFlag("-defs", outOptions.m_defs));
continue;
}
else if (arg == "-output-fields")
{
- outOptions.m_outputFields = true;
- break;
+ SLANG_RETURN_ON_FAIL(_parseArgFlag("-output-fields", outOptions.m_outputFields));
+ continue;
}
else if (arg == "-strip-prefix")
{
@@ -855,7 +884,7 @@ CPPExtractor::CPPExtractor(StringSlicePool* typePool, NamePool* namePool, Diagno
bool CPPExtractor::_isMarker(const UnownedStringSlice& name)
{
- return name.startsWith(m_options->m_prefixMark.getUnownedSlice()) && name.endsWith(m_options->m_postfixMark.getUnownedSlice());
+ return name.startsWith(m_options->m_markPrefix.getUnownedSlice()) && name.endsWith(m_options->m_markSuffix.getUnownedSlice());
}
SlangResult CPPExtractor::expect(TokenType type, Token* outToken)
@@ -1587,6 +1616,84 @@ SlangResult CPPExtractor::_maybeParseField()
}
}
+static UnownedStringSlice _trimUnderscorePrefix(const UnownedStringSlice& slice)
+{
+ if (slice.getLength() && slice[0] == '_')
+ {
+ return UnownedStringSlice(slice.begin() + 1, slice.end());
+ }
+ else
+ {
+ return slice;
+ }
+}
+
+
+SlangResult CPPExtractor::_parsePreDeclare()
+{
+ // Skip the declare type token
+ m_reader.advanceToken();
+
+ SLANG_RETURN_ON_FAIL(expect(TokenType::LParent));
+
+ bool hasMatchingSuffix = false;
+
+ // Get the suffix
+ {
+ Token suffix;
+ SLANG_RETURN_ON_FAIL(expect(TokenType::Identifier, &suffix));
+
+ hasMatchingSuffix = _trimUnderscorePrefix(m_options->m_markSuffix.getUnownedSlice()) == _trimUnderscorePrefix(suffix.getContent());
+ }
+
+ SLANG_RETURN_ON_FAIL(expect(TokenType::Comma));
+
+ // Get the type of type
+ Node::Type nodeType;
+ {
+ Token typeToken;
+ SLANG_RETURN_ON_FAIL(expect(TokenType::Identifier, &typeToken));
+
+ const IdentifierStyle style = m_identifierLookup->get(typeToken.getContent());
+
+ if (style != IdentifierStyle::Struct && style != IdentifierStyle::Class)
+ {
+ m_sink->diagnose(typeToken, CPPDiagnostics::expectingTypeKeyword, typeToken.getContent());
+ return SLANG_FAIL;
+ }
+ nodeType = _toNodeType(style);
+ }
+
+ Token name;
+ Token super;
+
+ SLANG_RETURN_ON_FAIL(expect(TokenType::Identifier, &name));
+
+ if (advanceIfToken(TokenType::Colon))
+ {
+ SLANG_RETURN_ON_FAIL(expect(TokenType::Identifier, &super));
+ }
+
+ SLANG_RETURN_ON_FAIL(expect(TokenType::RParent));
+
+ if (hasMatchingSuffix)
+ {
+ RefPtr<Node> node(new Node(nodeType));
+
+ node->m_name = name;
+ node->m_super = super;
+
+ // Assume it is reflected
+ node->m_reflectionType = ReflectionType::Reflected;
+
+ SLANG_RETURN_ON_FAIL(pushNode(node));
+ // Pop out of it
+ popBrace();
+ }
+
+ return SLANG_OK;
+}
+
SlangResult CPPExtractor::parse(SourceFile* sourceFile, const Options* options)
{
SLANG_ASSERT(options);
@@ -1629,24 +1736,9 @@ SlangResult CPPExtractor::parse(SourceFile* sourceFile, const Options* options)
switch (style)
{
- case IdentifierStyle::BaseClass:
+ case IdentifierStyle::PreDeclare:
{
- m_reader.advanceToken();
-
- Token nameToken;
- SLANG_RETURN_ON_FAIL(expect(TokenType::LParent));
- SLANG_RETURN_ON_FAIL(expect(TokenType::Identifier, &nameToken));
- SLANG_RETURN_ON_FAIL(expect(TokenType::RParent));
-
- RefPtr<Node> node(new Node(Node::Type::ClassType));
- node->m_name = nameToken;
- node->m_baseType = Node::BaseType::Marked;
-
- // Classes defined this way are not reflected, as the mark means the type exists, but isn't visible
- node->m_reflectionType = ReflectionType::NotReflected;
-
- SLANG_RETURN_ON_FAIL(pushNode(node));
- popBrace();
+ SLANG_RETURN_ON_FAIL(_parsePreDeclare());
break;
}
case IdentifierStyle::Reflected:
@@ -1667,15 +1759,6 @@ SlangResult CPPExtractor::parse(SourceFile* sourceFile, const Options* options)
}
break;
}
- case IdentifierStyle::Root:
- {
- if (m_currentNode && m_currentNode->isClassLike())
- {
- m_currentNode->m_baseType = Node::BaseType::Marked;
- }
- m_reader.advanceToken();
- break;
- }
default:
{
IdentifierFlags flags = getFlags(style);
@@ -1752,9 +1835,32 @@ SlangResult CPPExtractor::parse(SourceFile* sourceFile, const Options* options)
}
}
+Node* CPPExtractor::findNode(Node* scope, const UnownedStringSlice& name)
+{
+ // TODO(JS): We may want to lookup based on the path.
+ // If the name is qualified, we give up for not
+ if (String(name).indexOf("::") >= 0)
+ {
+ return nullptr;
+ }
+
+ // Okay try in all scopes up to the root
+ while (scope)
+ {
+ if (Node* node = scope->findChild(name))
+ {
+ return node;
+ }
+
+ scope = scope->m_parentScope;
+ }
+
+ return nullptr;
+}
+
SlangResult CPPExtractor::_calcDerivedTypesRec(Node* node)
{
- if (node->isClassLike() && node->m_baseType == Node::BaseType::None)
+ if (node->isClassLike())
{
if (node->m_super.hasContent())
{
@@ -1765,12 +1871,13 @@ SlangResult CPPExtractor::_calcDerivedTypesRec(Node* node)
return SLANG_FAIL;
}
- Node* superType = parentScope->findChild(node->m_super.getContent());
+ Node* superType = findNode(parentScope, node->m_super.getContent());
+
if (!superType)
{
if (node->isReflected())
{
- m_sink->diagnose(node->m_name, CPPDiagnostics::superTypeNotFound, node->m_name.getContent());
+ m_sink->diagnose(node->m_name, CPPDiagnostics::superTypeNotFound, node->getAbsoluteName());
return SLANG_FAIL;
}
}
@@ -1778,7 +1885,7 @@ SlangResult CPPExtractor::_calcDerivedTypesRec(Node* node)
{
if (!superType->isClassLike())
{
- m_sink->diagnose(node->m_name, CPPDiagnostics::superTypeNotAType, node->m_name.getContent());
+ m_sink->diagnose(node->m_name, CPPDiagnostics::superTypeNotAType, node->getAbsoluteName());
return SLANG_FAIL;
}
@@ -1789,16 +1896,14 @@ SlangResult CPPExtractor::_calcDerivedTypesRec(Node* node)
}
else
{
- // If it has no super class defined, then we can just make it a root without being set
- node->m_baseType = Node::BaseType::Unmarked;
+ // Add the root nodes
+ if (node->isReflected())
+ {
+ m_baseTypes.add(node);
+ }
}
}
- if (node->m_baseType != Node::BaseType::None)
- {
- m_baseTypes.add(node);
- }
-
for (Node* child : node->m_children)
{
SLANG_RETURN_ON_FAIL(_calcDerivedTypesRec(child));
@@ -1877,6 +1982,8 @@ public:
SlangResult calcDef(CPPExtractor& extractor, SourceOrigin* origin, StringBuilder& out);
+ const Options& getOptions() const { return m_options; }
+
CPPExtractorApp(DiagnosticSink* sink, SourceManager* sourceManager, RootNamePool* rootNamePool):
m_sink(sink),
m_sourceManager(sourceManager),
@@ -1977,14 +2084,10 @@ SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringB
for (Index i = 0; i < baseTypes.getCount(); ++i)
{
Node* baseType = baseTypes[i];
- if (baseType->m_baseType != Node::BaseType::Marked)
- {
- continue;
- }
-
+
List<Node*> nodes;
baseType->calcDerivedDepthFirst(nodes);
- Node::filterReflectedClassLike(nodes);
+ Node::filter(Node::isClassLike, nodes);
List<Node*> derivedTypes;
@@ -1996,7 +2099,7 @@ SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringB
node->getReflectedDerivedTypes(derivedTypes);
// Define the derived types
- out << "#define " << m_options.m_prefixMark << "CHILDREN_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
+ out << "#define " << m_options.m_markPrefix << "CHILDREN_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
if (derivedTypes.getCount())
{
@@ -2005,7 +2108,7 @@ SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringB
{
Node* derivedType = derivedTypes[j];
_indent(1, out);
- out << m_options.m_prefixMark << "ALL_" << reflectTypeName << "_" << derivedType->m_name.getContent() << "(x, param)";
+ out << m_options.m_markPrefix << "ALL_" << reflectTypeName << "_" << derivedType->m_name.getContent() << "(x, param)";
if (j < derivedTypes.getCount() - 1)
{
out << "\\\n";
@@ -2020,16 +2123,16 @@ SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringB
for (Node* node : nodes)
{
// Define the derived types
- out << "#define " << m_options.m_prefixMark << "ALL_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param) \\\n";
+ out << "#define " << m_options.m_markPrefix << "ALL_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param) \\\n";
_indent(1, out);
- out << m_options.m_prefixMark << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
+ out << m_options.m_markPrefix << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
// If has derived types output them
if (node->hasReflectedDerivedType())
{
out << " \\\n";
_indent(1, out);
- out << m_options.m_prefixMark << "CHILDREN_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
+ out << m_options.m_markPrefix << "CHILDREN_" << reflectTypeName << "_" << node->m_name.getContent() << "(x, param)";
}
out << "\n\n";
}
@@ -2041,7 +2144,7 @@ SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringB
for (Node* node : nodes)
{
// Define the derived types
- out << "#define " << m_options.m_prefixMark << "FIELDS_" << reflectTypeName << "_" << node->m_name.getContent() << "(_x_, _param_)";
+ out << "#define " << m_options.m_markPrefix << "FIELDS_" << reflectTypeName << "_" << node->m_name.getContent() << "(_x_, _param_)";
if (node->m_fields.getCount() > 0)
{
@@ -2090,11 +2193,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
for (Index i = 0; i < baseTypes.getCount(); ++i)
{
Node* baseType = baseTypes[i];
- if (baseType->m_baseType != Node::BaseType::Marked)
- {
- continue;
- }
-
+
List<Node*> baseScopePath;
baseType->calcScopePath(baseScopePath);
@@ -2111,7 +2210,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
List<Node*> nodes;
baseType->calcDerivedDepthFirst(nodes);
- Node::filterReflectedClassLike(nodes);
+ Node::filter(Node::isClassLikeAndReflected, nodes);
// Write out the types
{
@@ -2158,6 +2257,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
out << "// Order is (NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \n";
out << "// NAME - is the class name\n";
out << "// SUPER - is the super class name (or NO_SUPER)\n";
+ out << "// ORIGIN - where the definition was found\n";
out << "// LAST - is the class name for the last in the range (or NO_LAST)\n";
out << "// MARKER - is the text inbetween in the prefix/postix (like ABSTRACT). If no inbetween text is is 'NONE'\n";
out << "// TYPE - Can be BASE, INNER or LEAF for the overall base class, an INNER class, or a LEAF class\n";
@@ -2166,7 +2266,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
// Output all of the definitions for each type
for (Node* node : nodes)
{
- out << "#define " << m_options.m_prefixMark << reflectTypeName << "_" << node->m_name.getContent() << "(x, param) ";
+ out << "#define " << m_options.m_markPrefix << reflectTypeName << "_" << node->m_name.getContent() << "(x, param) ";
// Output the X macro part
_indent(1, out);
@@ -2199,9 +2299,9 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
// Output any specifics of the markup
UnownedStringSlice marker = node->m_marker.getContent();
// Need to extract the name
- if (marker.getLength() > m_options.m_prefixMark.getLength() + m_options.m_postfixMark.getLength())
+ if (marker.getLength() > m_options.m_markPrefix.getLength() + m_options.m_markSuffix.getLength())
{
- marker = UnownedStringSlice(marker.begin() + m_options.m_prefixMark.getLength(), marker.end() - m_options.m_postfixMark.getLength());
+ marker = UnownedStringSlice(marker.begin() + m_options.m_markPrefix.getLength(), marker.end() - m_options.m_markSuffix.getLength());
}
else
{
@@ -2209,7 +2309,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
}
out << marker << ", ";
- if (node->m_baseType != Node::BaseType::None || node->m_superNode && node->m_superNode->isReflected() == false)
+ if (node->m_superNode == nullptr)
{
out << "BASE, ";
}
@@ -2240,7 +2340,7 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder&
for (SourceOrigin* origin : extractor.getSourceOrigins())
{
- out << "#define " << m_options.m_prefixMark << "ORIGIN_" << origin->m_macroOrigin << "_" << reflectTypeName << "(x, param) \\\n";
+ out << "#define " << m_options.m_markPrefix << "ORIGIN_" << origin->m_macroOrigin << "_" << reflectTypeName << "(x, param) \\\n";
for (Node* node : origin->m_nodes)
{
@@ -2355,29 +2455,24 @@ SlangResult CPPExtractorApp::writeOutput(CPPExtractor& extractor)
// Special markers
{
{
+ const char* names[] = { "const", "volatile" };
StringBuilder buf;
- buf << options.m_prefixMark;
- buf << "CLASS_ROOT";
-
- outLookup.set(buf.getUnownedSlice(), IdentifierStyle::Root);
+ buf << options.m_markPrefix;
+ buf << "PRE_DECLARE";
+
+ outLookup.set(buf.getUnownedSlice(), IdentifierStyle::PreDeclare);
}
- {
- StringBuilder buf;
- buf << options.m_prefixMark;
- buf << "REFLECT_BASE_CLASS";
- outLookup.set(buf.getUnownedSlice(), IdentifierStyle::BaseClass);
- }
{
StringBuilder buf;
- buf << options.m_prefixMark;
+ buf << options.m_markPrefix;
buf << "REFLECTED";
outLookup.set(buf.getUnownedSlice(), IdentifierStyle::Reflected);
}
{
StringBuilder buf;
- buf << options.m_prefixMark;
+ buf << options.m_markPrefix;
buf << "UNREFLECTED";
outLookup.set(buf.getUnownedSlice(), IdentifierStyle::Unreflected);
@@ -2489,30 +2584,33 @@ int main(int argc, const char*const* argv)
{
ComPtr<ISlangWriter> writer(new FileWriter(stderr, WriterFlag::AutoFlush));
- try
- {
- RootNamePool rootNamePool;
+ RootNamePool rootNamePool;
+
+ SourceManager sourceManager;
+ sourceManager.initialize(nullptr, nullptr);
- SourceManager sourceManager;
- sourceManager.initialize(nullptr, nullptr);
+ DiagnosticSink sink(&sourceManager);
+ sink.writer = writer;
- DiagnosticSink sink(&sourceManager);
- sink.writer = writer;
+ CPPExtractorApp app(&sink, &sourceManager, &rootNamePool);
- CPPExtractorApp app(&sink, &sourceManager, &rootNamePool);
+ try
+ {
if (SLANG_FAILED(app.executeWithArgs(argc - 1, argv + 1)))
{
+ sink.diagnose(SourceLoc(), CPPDiagnostics::extractorFailed, app.getOptions().m_reflectType);
return 1;
}
if (sink.getErrorCount())
{
+ sink.diagnose(SourceLoc(), CPPDiagnostics::extractorFailed, app.getOptions().m_reflectType);
return 1;
}
}
catch (...)
{
- WriterHelper helper(writer);
- helper.print("Unknown internal error in C++ extractor, aborted!\n");
+ sink.diagnose(SourceLoc(), CPPDiagnostics::internalError);
+ sink.diagnose(SourceLoc(), CPPDiagnostics::extractorFailed, app.getOptions().m_reflectType);
return 1;
}
}