dev/studio-packer-rgba8888-asset-pipeline #11
@ -1,6 +1,25 @@
|
||||
final_id_hex,final_id_dec,canonical_name,canonical_version,owner,name,arg_slots,ret_slots,arg_layout,ret_layout,deterministic,may_allocate
|
||||
0x1000,4096,vec2.dot,1,vec2,dot,4,1,float|float|float|float,float,true,false
|
||||
0x1001,4097,vec2.length,1,vec2,length,2,1,float|float,float,true,false
|
||||
0x1100,4352,color.from_raw,1,color,from_raw,1,1,int,builtin:color,true,false
|
||||
0x1101,4353,color.rgb,1,color,rgb,3,1,int|int|int,builtin:color,true,false
|
||||
0x1102,4354,color.rgba,1,color,rgba,4,1,int|int|int|int,builtin:color,true,false
|
||||
0x1103,4355,color.html_rgba,1,color,html_rgba,1,1,str,builtin:color,true,false
|
||||
0x1104,4356,color.gray_scale,1,color,gray_scale,1,1,int,builtin:color,true,false
|
||||
0x1105,4357,color.hex,1,color,hex,1,1,builtin:color,int,true,false
|
||||
0x1106,4358,color.alpha,1,color,alpha,1,1,builtin:color,int,true,false
|
||||
0x1120,4384,color.black,1,color,black,0,1,,builtin:color,true,false
|
||||
0x1121,4385,color.white,1,color,white,0,1,,builtin:color,true,false
|
||||
0x1122,4386,color.red,1,color,red,0,1,,builtin:color,true,false
|
||||
0x1123,4387,color.green,1,color,green,0,1,,builtin:color,true,false
|
||||
0x1124,4388,color.blue,1,color,blue,0,1,,builtin:color,true,false
|
||||
0x1125,4389,color.yellow,1,color,yellow,0,1,,builtin:color,true,false
|
||||
0x1126,4390,color.orange,1,color,orange,0,1,,builtin:color,true,false
|
||||
0x1127,4391,color.indigo,1,color,indigo,0,1,,builtin:color,true,false
|
||||
0x1128,4392,color.gray,1,color,gray,0,1,,builtin:color,true,false
|
||||
0x1129,4393,color.cyan,1,color,cyan,0,1,,builtin:color,true,false
|
||||
0x112A,4394,color.magenta,1,color,magenta,0,1,,builtin:color,true,false
|
||||
0x112B,4395,color.transparent,1,color,transparent,0,1,,builtin:color,true,false
|
||||
0x2000,8192,input.pad,1,input,pad,0,1,,builtin:input.pad,true,false
|
||||
0x2001,8193,input.touch,1,input,touch,0,1,,builtin:input.touch,true,false
|
||||
0x2010,8208,input.pad.up,1,input.pad,up,1,1,builtin:input.pad,builtin:input.button,true,false
|
||||
|
||||
|
@ -574,7 +574,30 @@ final class PbsExecutableBodyLowerer {
|
||||
final var constDecl = context.resolveConstDecl(identifierExpr.name());
|
||||
if (constDecl != null && constDecl.initializer() != null) {
|
||||
lowerConstExpression(constDecl.initializer(), context);
|
||||
return;
|
||||
}
|
||||
final var builtinConst = context.builtinConstByNameId().get(context.nameTable().register(identifierExpr.name()));
|
||||
if (builtinConst != null) {
|
||||
emitBuiltinConstFetch(builtinConst, identifierExpr.span(), context);
|
||||
}
|
||||
}
|
||||
|
||||
private void emitBuiltinConstFetch(
|
||||
final p.studio.compiler.models.IRReservedMetadata.BuiltinConstSurface builtinConst,
|
||||
final p.studio.compiler.source.Span span,
|
||||
final PbsExecutableLoweringContext context) {
|
||||
final var canonicalName = builtinConst.canonicalTarget() + "." + builtinConst.canonicalName();
|
||||
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.CALL_INTRINSIC,
|
||||
"",
|
||||
null,
|
||||
new IRBackendExecutableFunction.IntrinsicCallMetadata(
|
||||
canonicalName,
|
||||
builtinConst.canonicalVersion(),
|
||||
context.intrinsicIdTable().register(canonicalName, builtinConst.canonicalVersion())),
|
||||
0,
|
||||
1,
|
||||
span));
|
||||
}
|
||||
|
||||
private String flattenAssetReference(final PbsAst.Expression expression) {
|
||||
|
||||
@ -326,6 +326,10 @@ final class PbsExecutableCallsiteEmitter {
|
||||
if (!localOwner.isBlank()) {
|
||||
return localOwner;
|
||||
}
|
||||
final var builtinOwner = context.builtinCanonicalBySourceType().getOrDefault(identifier, "");
|
||||
if (!builtinOwner.isBlank()) {
|
||||
return builtinOwner;
|
||||
}
|
||||
return context.builtinConstOwnerByNameId().getOrDefault(context.nameTable().register(identifier), "");
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +60,10 @@ final class PbsExecutableLoweringContext {
|
||||
return metadataIndex.builtinConstOwnerByNameId();
|
||||
}
|
||||
|
||||
Map<NameId, p.studio.compiler.models.IRReservedMetadata.BuiltinConstSurface> builtinConstByNameId() {
|
||||
return metadataIndex.builtinConstByNameId();
|
||||
}
|
||||
|
||||
Map<NameId, Integer> globalSlotByNameId() {
|
||||
return metadataIndex.globalSlotByNameId();
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ public class PbsExecutableLoweringModels {
|
||||
Map<NameId, List<IRReservedMetadata.HostMethodBinding>> hostByMethodName,
|
||||
Map<String, String> builtinCanonicalBySourceType,
|
||||
Map<NameId, String> builtinConstOwnerByNameId,
|
||||
Map<NameId, IRReservedMetadata.BuiltinConstSurface> builtinConstByNameId,
|
||||
Map<NameId, Integer> globalSlotByNameId,
|
||||
Map<NameId, PbsAst.ConstDecl> constDeclByNameId,
|
||||
Map<String, Addressable> addressableByAddress,
|
||||
|
||||
@ -30,6 +30,7 @@ final class PbsExecutableMetadataIndexFactory {
|
||||
final var hostByMethodName = indexHostBindingsByMethodName(reservedMetadata, nameTable);
|
||||
final var builtinCanonicalBySourceType = indexBuiltinCanonicalBySourceType(reservedMetadata);
|
||||
final var builtinConstOwnerByNameId = indexBuiltinConstOwners(reservedMetadata, nameTable);
|
||||
final var builtinConstByNameId = indexBuiltinConstSurfaces(reservedMetadata, nameTable);
|
||||
final var globalSlotByNameId = indexGlobalSlots(ast, nameTable);
|
||||
final var constDeclByNameId = indexConstDecls(ast, nameTable);
|
||||
final var addressableByAddress = indexAddressables(feSurfaceContext);
|
||||
@ -50,6 +51,7 @@ final class PbsExecutableMetadataIndexFactory {
|
||||
hostByMethodName,
|
||||
builtinCanonicalBySourceType,
|
||||
builtinConstOwnerByNameId,
|
||||
builtinConstByNameId,
|
||||
globalSlotByNameId,
|
||||
constDeclByNameId,
|
||||
addressableByAddress,
|
||||
@ -90,6 +92,19 @@ final class PbsExecutableMetadataIndexFactory {
|
||||
return builtinConstOwnerByNameId;
|
||||
}
|
||||
|
||||
private Map<NameId, IRReservedMetadata.BuiltinConstSurface> indexBuiltinConstSurfaces(
|
||||
final IRReservedMetadata reservedMetadata,
|
||||
final NameTable nameTable) {
|
||||
final var builtinConstByNameId = new HashMap<NameId, IRReservedMetadata.BuiltinConstSurface>();
|
||||
for (final var builtinConst : reservedMetadata.builtinConstSurfaces()) {
|
||||
if (builtinConst.sourceConstName().isBlank() || builtinConst.canonicalTarget().isBlank()) {
|
||||
continue;
|
||||
}
|
||||
builtinConstByNameId.put(nameTable.register(builtinConst.sourceConstName()), builtinConst);
|
||||
}
|
||||
return builtinConstByNameId;
|
||||
}
|
||||
|
||||
private Map<NameId, Integer> indexGlobalSlots(
|
||||
final PbsAst.File ast,
|
||||
final NameTable nameTable) {
|
||||
|
||||
@ -86,6 +86,22 @@ final class PbsFlowCallableResolutionAnalyzer {
|
||||
if (enumCases != null && enumCases.contains(memberExpr.memberName())) {
|
||||
return ExprResult.type(TypeView.enumType(receiver.name()));
|
||||
}
|
||||
if (model.knownBuiltinTypeNames.contains(receiver.name())) {
|
||||
final var builtin = model.structs.get(receiver.name());
|
||||
if (builtin != null) {
|
||||
final var methods = builtin.methods().get(memberExpr.memberName());
|
||||
if (methods != null && !methods.isEmpty()) {
|
||||
if (use == ExprUse.VALUE) {
|
||||
Diagnostics.error(diagnostics,
|
||||
PbsSemanticsErrors.E_SEM_BARE_METHOD_EXTRACTION.name(),
|
||||
"Bare method extraction is not allowed in PBS core",
|
||||
memberExpr.span());
|
||||
return ExprResult.type(TypeView.unknown());
|
||||
}
|
||||
return ExprResult.callables(methods, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Diagnostics.error(diagnostics,
|
||||
PbsSemanticsErrors.E_SEM_INVALID_MEMBER_ACCESS.name(),
|
||||
"Invalid type member access",
|
||||
|
||||
@ -191,6 +191,7 @@ final class PbsFlowSemanticSupport {
|
||||
final Map<String, TypeView> constTypes = new HashMap<>();
|
||||
final Map<String, TypeView> globalTypes = new HashMap<>();
|
||||
final Map<String, TypeView> serviceSingletons = new HashMap<>();
|
||||
final Set<String> knownBuiltinTypeNames = new HashSet<>();
|
||||
final Set<String> knownStructNames = new HashSet<>();
|
||||
final Set<String> knownServiceNames = new HashSet<>();
|
||||
final Set<String> knownContractNames = new HashSet<>();
|
||||
@ -232,6 +233,7 @@ final class PbsFlowSemanticSupport {
|
||||
return;
|
||||
}
|
||||
if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) {
|
||||
knownBuiltinTypeNames.add(builtinTypeDecl.name());
|
||||
knownStructNames.add(builtinTypeDecl.name());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -108,6 +108,10 @@ final class PbsFlowStructuralExpressionAnalyzer {
|
||||
return ExprResult.type(TypeView.typeRef(identifierExpr.name()));
|
||||
}
|
||||
|
||||
if (model.knownBuiltinTypeNames.contains(identifierExpr.name())) {
|
||||
return ExprResult.type(TypeView.typeRef(identifierExpr.name()));
|
||||
}
|
||||
|
||||
return ExprResult.type(TypeView.unknown());
|
||||
}
|
||||
if (expression instanceof PbsAst.GroupExpr groupExpr) {
|
||||
|
||||
@ -1,5 +1,61 @@
|
||||
[BuiltinType(name = "Color", version = 1)]
|
||||
[BuiltinType(name = "color", version = 1)]
|
||||
declare builtin type Color(
|
||||
pub raw: int
|
||||
) {
|
||||
[IntrinsicCall(name = "from_raw", version = 1)]
|
||||
fn from_raw(raw: int) -> Color;
|
||||
|
||||
[IntrinsicCall(name = "rgb", version = 1)]
|
||||
fn rgb(r: int, g: int, b: int) -> Color;
|
||||
|
||||
[IntrinsicCall(name = "rgba", version = 1)]
|
||||
fn rgba(r: int, g: int, b: int, a: int) -> Color;
|
||||
|
||||
[IntrinsicCall(name = "html_rgba", version = 1)]
|
||||
fn html_rgba(value: str) -> Color;
|
||||
|
||||
[IntrinsicCall(name = "gray_scale", version = 1)]
|
||||
fn gray_scale(value: int) -> Color;
|
||||
|
||||
[IntrinsicCall(name = "hex", version = 1)]
|
||||
fn hex() -> int;
|
||||
|
||||
[IntrinsicCall(name = "alpha", version = 1)]
|
||||
fn alpha() -> int;
|
||||
}
|
||||
|
||||
[BuiltinConst(target = "color", name = "black", version = 1)]
|
||||
declare const BLACK: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "white", version = 1)]
|
||||
declare const WHITE: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "red", version = 1)]
|
||||
declare const RED: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "green", version = 1)]
|
||||
declare const GREEN: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "blue", version = 1)]
|
||||
declare const BLUE: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "yellow", version = 1)]
|
||||
declare const YELLOW: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "orange", version = 1)]
|
||||
declare const ORANGE: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "indigo", version = 1)]
|
||||
declare const INDIGO: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "gray", version = 1)]
|
||||
declare const GRAY: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "cyan", version = 1)]
|
||||
declare const CYAN: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "magenta", version = 1)]
|
||||
declare const MAGENTA: Color;
|
||||
|
||||
[BuiltinConst(target = "color", name = "transparent", version = 1)]
|
||||
declare const TRANSPARENT: Color;
|
||||
|
||||
@ -1 +1,13 @@
|
||||
pub struct Color;
|
||||
pub const BLACK;
|
||||
pub const WHITE;
|
||||
pub const RED;
|
||||
pub const GREEN;
|
||||
pub const BLUE;
|
||||
pub const YELLOW;
|
||||
pub const ORANGE;
|
||||
pub const INDIGO;
|
||||
pub const GRAY;
|
||||
pub const CYAN;
|
||||
pub const MAGENTA;
|
||||
pub const TRANSPARENT;
|
||||
|
||||
@ -1019,6 +1019,74 @@ class PBSFrontendPhaseServiceTest {
|
||||
assertTrue(irBackend.getExecutableFunctions().stream().anyMatch(function -> "frame".equals(function.callableName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLowerCoreColorConstructorsAndConstantsFromBootstrapStdlib() throws IOException {
|
||||
final var projectRoot = tempDir.resolve("project-bootstrap-core-color-rgba");
|
||||
final var sourceRoot = projectRoot.resolve("src");
|
||||
final var modulePath = sourceRoot.resolve("app");
|
||||
Files.createDirectories(modulePath);
|
||||
|
||||
final var sourceFile = modulePath.resolve("source.pbs");
|
||||
final var modBarrel = modulePath.resolve("mod.barrel");
|
||||
Files.writeString(sourceFile, """
|
||||
import { Color, RED, TRANSPARENT } from @core:color;
|
||||
import { Gfx } from @sdk:gfx;
|
||||
|
||||
[Frame]
|
||||
fn frame() -> void
|
||||
{
|
||||
let tint: Color = Color.rgba(1, 2, 3, 128);
|
||||
let web: Color = Color.html_rgba("#11223344");
|
||||
Gfx.clear(RED);
|
||||
Gfx.fill_rect(0, 0, 1, 1, tint);
|
||||
Gfx.fill_rect(1, 0, 1, 1, web);
|
||||
Gfx.fill_rect(2, 0, 1, 1, TRANSPARENT);
|
||||
}
|
||||
""");
|
||||
Files.writeString(modBarrel, "pub fn frame() -> void;");
|
||||
|
||||
final var projectTable = new ProjectTable();
|
||||
final var fileTable = new FileTable(1);
|
||||
final var projectId = projectTable.register(ProjectDescriptor.builder()
|
||||
.rootPath(projectRoot)
|
||||
.name("app")
|
||||
.version("1.0.0")
|
||||
.sourceRoots(ReadOnlyList.wrap(List.of(sourceRoot)))
|
||||
.build());
|
||||
|
||||
registerFile(projectId, projectRoot, sourceFile, fileTable);
|
||||
registerFile(projectId, projectRoot, modBarrel, fileTable);
|
||||
|
||||
final var ctx = new FrontendPhaseContext(
|
||||
projectTable,
|
||||
fileTable,
|
||||
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
|
||||
1,
|
||||
AppMode.Game);
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
|
||||
final var irBackend = new PBSFrontendPhaseService().compile(
|
||||
ctx,
|
||||
diagnostics,
|
||||
LogAggregator.empty(),
|
||||
BuildingIssueSink.empty());
|
||||
|
||||
assertFalse(diagnostics.hasErrors(),
|
||||
"diagnostics=" + diagnostics.stream().map(d -> d.getCode() + ":" + d.getMessage()).toList());
|
||||
assertTrue(diagnostics.stream().noneMatch(d ->
|
||||
d.getCode().equals(PbsSemanticsErrors.E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE.name())),
|
||||
"diagnostics=" + diagnostics.stream().map(d -> d.getCode() + ":" + d.getMessage()).toList());
|
||||
final var intrinsicNames = irBackend.getExecutableFunctions().stream()
|
||||
.flatMap(function -> function.instructions().stream())
|
||||
.filter(instruction -> instruction.kind() == IRBackendExecutableFunction.InstructionKind.CALL_INTRINSIC)
|
||||
.map(instruction -> instruction.intrinsicCall().canonicalName())
|
||||
.toList();
|
||||
assertTrue(intrinsicNames.contains("color.rgba"), "intrinsics=" + intrinsicNames);
|
||||
assertTrue(intrinsicNames.contains("color.html_rgba"), "intrinsics=" + intrinsicNames);
|
||||
assertTrue(intrinsicNames.contains("color.red"), "intrinsics=" + intrinsicNames);
|
||||
assertTrue(intrinsicNames.contains("color.transparent"), "intrinsics=" + intrinsicNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLowerSdkComposerEmitSpriteFacadeUsingCanonicalComposerContract() throws IOException {
|
||||
final var projectRoot = tempDir.resolve("project-bootstrap-sdk-composer-emit-sprite");
|
||||
|
||||
@ -5,6 +5,25 @@ import java.util.Objects;
|
||||
enum IRVMIntrinsicDefinition {
|
||||
VEC2_DOT("vec2.dot", 1, 0x1000, "vec2", "dot", 4, 1, "float|float|float|float", "float", true, false),
|
||||
VEC2_LENGTH("vec2.length", 1, 0x1001, "vec2", "length", 2, 1, "float|float", "float", true, false),
|
||||
COLOR_FROM_RAW("color.from_raw", 1, 0x1100, "color", "from_raw", 1, 1, "int", "builtin:color", true, false),
|
||||
COLOR_RGB("color.rgb", 1, 0x1101, "color", "rgb", 3, 1, "int|int|int", "builtin:color", true, false),
|
||||
COLOR_RGBA("color.rgba", 1, 0x1102, "color", "rgba", 4, 1, "int|int|int|int", "builtin:color", true, false),
|
||||
COLOR_HTML_RGBA("color.html_rgba", 1, 0x1103, "color", "html_rgba", 1, 1, "str", "builtin:color", true, false),
|
||||
COLOR_GRAY_SCALE("color.gray_scale", 1, 0x1104, "color", "gray_scale", 1, 1, "int", "builtin:color", true, false),
|
||||
COLOR_HEX("color.hex", 1, 0x1105, "color", "hex", 1, 1, "builtin:color", "int", true, false),
|
||||
COLOR_ALPHA("color.alpha", 1, 0x1106, "color", "alpha", 1, 1, "builtin:color", "int", true, false),
|
||||
COLOR_BLACK("color.black", 1, 0x1120, "color", "black", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_WHITE("color.white", 1, 0x1121, "color", "white", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_RED("color.red", 1, 0x1122, "color", "red", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_GREEN("color.green", 1, 0x1123, "color", "green", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_BLUE("color.blue", 1, 0x1124, "color", "blue", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_YELLOW("color.yellow", 1, 0x1125, "color", "yellow", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_ORANGE("color.orange", 1, 0x1126, "color", "orange", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_INDIGO("color.indigo", 1, 0x1127, "color", "indigo", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_GRAY("color.gray", 1, 0x1128, "color", "gray", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_CYAN("color.cyan", 1, 0x1129, "color", "cyan", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_MAGENTA("color.magenta", 1, 0x112A, "color", "magenta", 0, 1, "", "builtin:color", true, false),
|
||||
COLOR_TRANSPARENT("color.transparent", 1, 0x112B, "color", "transparent", 0, 1, "", "builtin:color", true, false),
|
||||
INPUT_PAD("input.pad", 1, 0x2000, "input", "pad", 0, 1, "", "builtin:input.pad", true, false),
|
||||
INPUT_TOUCH("input.touch", 1, 0x2001, "input", "touch", 0, 1, "", "builtin:input.touch", true, false),
|
||||
INPUT_PAD_UP("input.pad.up", 1, 0x2010, "input.pad", "up", 1, 1, "builtin:input.pad", "builtin:input.button", true, false),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user