From 0e6da1433b0bf842ba0dc24ea141b82871978fd9 Mon Sep 17 00:00:00 2001 From: bquarkz Date: Wed, 21 Jan 2026 10:55:47 +0000 Subject: [PATCH] dev/prometeuc-improvements (#5) Co-authored-by: Nilton Constantino Reviewed-on: https://git-local.bquarkz.net/Intrepid/prometeu-runtime/pulls/5 --- .gitignore | 2 + Cargo.lock | 296 +++---- Cargo.toml | 6 +- README.md | 2 +- build/program.disasm.txt | 17 + build/program.pbc | Bin 0 -> 82 bytes build/symbols.json | 74 ++ crates/prometeu-bytecode/Cargo.toml | 2 + crates/prometeu-bytecode/src/asm.rs | 20 +- crates/prometeu-compiler/Cargo.toml | 27 + .../src/cli.rs | 7 +- .../prometeu-compiler/src/codegen/ast_util.rs | 26 + .../prometeu-compiler/src/codegen/codegen.rs | 507 +++++++++++ .../src/codegen/mod.rs | 2 + .../src/codegen/validator.rs | 163 ++++ crates/prometeu-compiler/src/compiler.rs | 154 ++++ .../main.rs => prometeu-compiler/src/lib.rs} | 19 +- crates/prometeu-compiler/src/main.rs | 5 + .../src/syscall_map.rs | 2 +- crates/prometeu-core/Cargo.toml | 4 +- crates/prometeu-core/src/hardware/gfx.rs | 15 + crates/prometeu-core/src/model/color.rs | 10 + .../src/prometeu_os/prometeu_os.rs | 125 ++- .../prometeu-core/src/prometeu_os/syscalls.rs | 96 ++- crates/prometeu-runtime-desktop/Cargo.toml | 2 +- crates/prometeu-runtime-desktop/src/lib.rs | 84 ++ crates/prometeu-runtime-desktop/src/main.rs | 83 +- crates/prometeu/Cargo.toml | 25 +- crates/prometeu/README.md | 4 +- crates/prometeu/src/bin/prometeu-runtime.rs | 1 + crates/prometeu/src/bin/prometeuc.rs | 1 + crates/prometeu/src/main.rs | 12 +- crates/prometeuc/Cargo.toml | 16 - crates/prometeuc/src/codegen/codegen.rs | 324 ------- crates/prometeuc/src/compiler.rs | 72 -- .../debugger-protocol}/README.md | 4 +- .../examples/basic_session.jsonl | 0 .../examples/breakpoint_flow.jsonl | 0 .../examples/handshake.jsonl | 0 .../debugger-protocol}/protocol.json | 0 devtools/typescript-sdk/package.json | 6 + devtools/typescript-sdk/src/audio.ts | 2 + devtools/typescript-sdk/src/color.ts | 25 + devtools/typescript-sdk/src/fs.ts | 2 + devtools/typescript-sdk/src/gfx.ts | 1 + devtools/typescript-sdk/src/index.ts | 8 + devtools/typescript-sdk/src/input.ts | 4 + devtools/typescript-sdk/src/log.ts | 11 + devtools/typescript-sdk/src/system.ts | 2 + devtools/typescript-sdk/tsconfig.json | 4 + devtools/typescript-sdk/types/index.d.ts | 95 +++ dist-workspace.toml | 2 +- docs/README.md | 2 +- examples/colorsquare/src/main.ts | 6 +- scripts/clean-all.sh | 5 + scripts/gen-version.sh | 2 +- scripts/local-dist.sh | 26 +- symbols.json | 80 ++ temp_test_2.disasm.txt | 23 + .../color-square/build/program.disasm.txt | 158 ++++ .../color-square/build/program.pbc | Bin 0 -> 817 bytes .../color-square/build/symbols.json | 788 ++++++++++++++++++ .../{ => cartridge}/manifest.json | 0 .../color-square/cartridge/program.pbc | Bin 0 -> 817 bytes .../node_modules/.package-lock.json | 22 + .../color-square/node_modules/@prometeu/sdk | 1 + .../color-square/package-lock.json | 27 + test-cartridges/color-square/package.json | 5 + test-cartridges/color-square/program.pbc | Bin 491 -> 0 bytes test-cartridges/color-square/prometeu-sdk | 1 + test-cartridges/color-square/run.sh | 5 + test-cartridges/color-square/src/main.ts | 11 + test-cartridges/color-square/src/my_fs.ts | 9 + test-cartridges/color-square/src/my_gfx.ts | 13 + test-cartridges/color-square/src/my_input.ts | 15 + test-cartridges/color-square/tsconfig.json | 6 + 76 files changed, 2820 insertions(+), 756 deletions(-) create mode 100644 build/program.disasm.txt create mode 100644 build/program.pbc create mode 100644 build/symbols.json create mode 100644 crates/prometeu-compiler/Cargo.toml rename crates/{prometeuc => prometeu-compiler}/src/cli.rs (82%) create mode 100644 crates/prometeu-compiler/src/codegen/ast_util.rs create mode 100644 crates/prometeu-compiler/src/codegen/codegen.rs rename crates/{prometeuc => prometeu-compiler}/src/codegen/mod.rs (53%) create mode 100644 crates/prometeu-compiler/src/codegen/validator.rs create mode 100644 crates/prometeu-compiler/src/compiler.rs rename crates/{prometeuc/src/main.rs => prometeu-compiler/src/lib.rs} (63%) create mode 100644 crates/prometeu-compiler/src/main.rs rename crates/{prometeuc => prometeu-compiler}/src/syscall_map.rs (88%) create mode 100644 crates/prometeu-runtime-desktop/src/lib.rs create mode 100644 crates/prometeu/src/bin/prometeu-runtime.rs create mode 100644 crates/prometeu/src/bin/prometeuc.rs delete mode 100644 crates/prometeuc/Cargo.toml delete mode 100644 crates/prometeuc/src/codegen/codegen.rs delete mode 100644 crates/prometeuc/src/compiler.rs rename {devtools-protocol => devtools/debugger-protocol}/README.md (92%) rename {devtools-protocol => devtools/debugger-protocol}/examples/basic_session.jsonl (100%) rename {devtools-protocol => devtools/debugger-protocol}/examples/breakpoint_flow.jsonl (100%) rename {devtools-protocol => devtools/debugger-protocol}/examples/handshake.jsonl (100%) rename {devtools-protocol => devtools/debugger-protocol}/protocol.json (100%) create mode 100644 devtools/typescript-sdk/package.json create mode 100644 devtools/typescript-sdk/src/audio.ts create mode 100644 devtools/typescript-sdk/src/color.ts create mode 100644 devtools/typescript-sdk/src/fs.ts create mode 100644 devtools/typescript-sdk/src/gfx.ts create mode 100644 devtools/typescript-sdk/src/index.ts create mode 100644 devtools/typescript-sdk/src/input.ts create mode 100644 devtools/typescript-sdk/src/log.ts create mode 100644 devtools/typescript-sdk/src/system.ts create mode 100644 devtools/typescript-sdk/tsconfig.json create mode 100644 devtools/typescript-sdk/types/index.d.ts create mode 100755 scripts/clean-all.sh create mode 100644 symbols.json create mode 100644 temp_test_2.disasm.txt create mode 100644 test-cartridges/color-square/build/program.disasm.txt create mode 100644 test-cartridges/color-square/build/program.pbc create mode 100644 test-cartridges/color-square/build/symbols.json rename test-cartridges/color-square/{ => cartridge}/manifest.json (100%) create mode 100644 test-cartridges/color-square/cartridge/program.pbc create mode 100644 test-cartridges/color-square/node_modules/.package-lock.json create mode 120000 test-cartridges/color-square/node_modules/@prometeu/sdk create mode 100644 test-cartridges/color-square/package-lock.json create mode 100644 test-cartridges/color-square/package.json delete mode 100644 test-cartridges/color-square/program.pbc create mode 120000 test-cartridges/color-square/prometeu-sdk create mode 100755 test-cartridges/color-square/run.sh create mode 100644 test-cartridges/color-square/src/main.ts create mode 100644 test-cartridges/color-square/src/my_fs.ts create mode 100644 test-cartridges/color-square/src/my_gfx.ts create mode 100644 test-cartridges/color-square/src/my_input.ts create mode 100644 test-cartridges/color-square/tsconfig.json diff --git a/.gitignore b/.gitignore index 477afa04..02577a42 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ sdcard/** dist-staging dist-staging/** +temp +temp/** \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e61a0629..d0e0f3be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,7 +86,7 @@ dependencies = [ "ndk-context", "ndk-sys 0.6.0+11769913", "num_enum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -187,12 +187,6 @@ dependencies = [ "libloading 0.7.4", ] -[[package]] -name = "assert-unchecked" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7330592adf847ee2e3513587b4db2db410a0d751378654e7e993d9adcbe5c795" - [[package]] name = "atomic-waker" version = "1.1.2" @@ -270,9 +264,6 @@ name = "bumpalo" version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" -dependencies = [ - "allocator-api2", -] [[package]] name = "bytemuck" @@ -297,7 +288,7 @@ dependencies = [ "polling", "rustix 0.38.44", "slab", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -476,9 +467,9 @@ dependencies = [ [[package]] name = "compact_str" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" dependencies = [ "castaway", "cfg-if", @@ -642,6 +633,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "dragonbox_ecma" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5577f010d4e1bb3f3c4d6081e05718eb6992cf20119cab4d3abadff198b5ae" + [[package]] name = "either" version = "1.15.0" @@ -664,6 +661,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "find-msvc-tools" version = "0.1.7" @@ -784,7 +787,7 @@ checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" dependencies = [ "log", "presser", - "thiserror", + "thiserror 1.0.69", "winapi", "windows 0.52.0", ] @@ -819,20 +822,14 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "allocator-api2", -] - [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", +] [[package]] name = "hassle-rs" @@ -844,7 +841,7 @@ dependencies = [ "com", "libc", "libloading 0.8.9", - "thiserror", + "thiserror 1.0.69", "widestring", "winapi", ] @@ -909,7 +906,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -1091,7 +1088,7 @@ dependencies = [ "rustc-hash 1.1.0", "spirv", "termcolor", - "thiserror", + "thiserror 1.0.69", "unicode-xid", ] @@ -1106,7 +1103,7 @@ dependencies = [ "log", "ndk-sys 0.5.0+25.2.9519653", "num_enum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1121,7 +1118,7 @@ dependencies = [ "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1509,23 +1506,24 @@ checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" [[package]] name = "oxc-miette" -version = "1.0.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03e63fd113c068b82d07c9c614b0b146c08a3ac0a4dface3ea1d1a9d14d549e" +checksum = "60a7ba54c704edefead1f44e9ef09c43e5cfae666bdc33516b066011f0e6ebf7" dependencies = [ "cfg-if", "owo-colors", "oxc-miette-derive", "textwrap", - "thiserror", + "thiserror 2.0.18", + "unicode-segmentation", "unicode-width 0.2.2", ] [[package]] name = "oxc-miette-derive" -version = "1.0.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21f680e8c5f1900297d394627d495351b9e37761f7bbf90116bd5eeb6e80967" +checksum = "d4faecb54d0971f948fbc1918df69b26007e6f279a204793669542e1e8b75eb3" dependencies = [ "proc-macro2", "quote", @@ -1534,29 +1532,27 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17374a91329f2e362bc8be31cb3e171ef226777d0ea668e17a39620443693027" +checksum = "2174c7c8f77137b1bd1c653d7a5a531ae41f3b8fec1dd0251c801689784e7a2e" dependencies = [ "allocator-api2", - "bumpalo", - "hashbrown 0.15.5", + "hashbrown 0.16.1", + "oxc_data_structures", "rustc-hash 2.1.1", - "simdutf8", ] [[package]] name = "oxc_ast" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b38cfe954ee987354af015020f5cb2723df6fed6cd688eff24388437c7eb7e" +checksum = "62f1902f97a5cac8767b76a1d8a1b3124e9db80c176ebbc98f75143dcc124a15" dependencies = [ "bitflags 2.10.0", - "cow-utils", - "num-bigint", - "num-traits", "oxc_allocator", "oxc_ast_macros", + "oxc_data_structures", + "oxc_diagnostics", "oxc_estree", "oxc_regular_expression", "oxc_span", @@ -1565,57 +1561,83 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85f9e03eff90b041078edcc8aff09457eb4126fa5d62a383fdb082d3ae286274" +checksum = "c5a31bd55516a98a35b2d99fa5813a3d3a5b798bad3262c819dfe7344bc6f390" dependencies = [ + "phf", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] -name = "oxc_diagnostics" -version = "0.48.2" +name = "oxc_ast_visit" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24c41929c1910d83fb6f4c508190a8b2d1bad02e81c8cb3a9d3f474ca0ad2c1" +checksum = "e2c520a488c04ba5267223edd0bb245fb7f10e2358e8955802a5d962bb95b50a" dependencies = [ - "cow-utils", - "oxc-miette", -] - -[[package]] -name = "oxc_ecmascript" -version = "0.48.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30fba86c97b571671f941b818e6831ba821aac398b9f6f3b4e3367ca264b8324" -dependencies = [ - "num-bigint", - "num-traits", + "oxc_allocator", "oxc_ast", "oxc_span", "oxc_syntax", ] [[package]] -name = "oxc_estree" -version = "0.48.2" +name = "oxc_data_structures" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e587034bb5f108dd987e5419a4ad35a173550bd9439fc2b610d34e4ce41e8b23" +checksum = "a42840ce8d83a08a92823dda6189e4d97359feca24a4fa732f3256c4614bb5a4" + +[[package]] +name = "oxc_diagnostics" +version = "0.110.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f7b09c1563a67ede53af131f717b31ba89a992959ebad188b5158c21d4dc0a" +dependencies = [ + "cow-utils", + "oxc-miette", + "percent-encoding", +] + +[[package]] +name = "oxc_ecmascript" +version = "0.110.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4813b352bd5b0b05badf0c9e6c5ec7ea58a6a7ab49bec8d18ead262624c6ef8d" +dependencies = [ + "cow-utils", + "num-bigint", + "num-traits", + "oxc_allocator", + "oxc_ast", + "oxc_regular_expression", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_estree" +version = "0.110.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54fb3effe995e6538d68070bf0a450b5ffd11dd41b62f11a4d01efa1f40e278" [[package]] name = "oxc_index" -version = "2.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eca5d9726cd0a6e433debe003b7bc88b2ecad0bb6109f0cef7c55e692139a34" +checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b" +dependencies = [ + "nonmax", + "serde", +] [[package]] name = "oxc_parser" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc385aca3586877f8c918aed1141b885dedcfc1019d6ea5be4105f8e2a7965e" +checksum = "5592bf8b64743944eb46528f9eabdde2b2435c8293cd502f5c183f9dff644e16" dependencies = [ - "assert-unchecked", "bitflags 2.10.0", "cow-utils", "memchr", @@ -1623,6 +1645,7 @@ dependencies = [ "num-traits", "oxc_allocator", "oxc_ast", + "oxc_data_structures", "oxc_diagnostics", "oxc_ecmascript", "oxc_regular_expression", @@ -1634,14 +1657,14 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8d172402f6d542ab2837d35126cc42ad6989b9c2289b06bc5c8c89dceb60c48" +checksum = "09de7f7e0fb82f54750e3a95346a828fd354b9aeac00f131719008733e66a18d" dependencies = [ + "bitflags 2.10.0", "oxc_allocator", "oxc_ast_macros", "oxc_diagnostics", - "oxc_estree", "oxc_span", "phf", "rustc-hash 2.1.1", @@ -1650,9 +1673,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75881376dfdbb6a23f12a66794904f0d215629f208edcf7e156c0770e89e2101" +checksum = "2a42c0759b745eca0fe776890af46ce12e79e61796995e51a8eb9dcdf5516ab0" dependencies = [ "compact_str", "oxc-miette", @@ -1663,22 +1686,21 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.48.2" +version = "0.110.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d88037a5de07f66299ab523a65545cc48d550658cea8cadcea09b60596dd49" +checksum = "b63eac2e04a75a10c5714aeb753cdfa06b1abc66bbaa748b7994700f52c9b184" dependencies = [ - "assert-unchecked", "bitflags 2.10.0", "cow-utils", + "dragonbox_ecma", "nonmax", "oxc_allocator", "oxc_ast_macros", + "oxc_data_structures", "oxc_estree", "oxc_index", "oxc_span", "phf", - "rustc-hash 2.1.1", - "ryu-js", "unicode-id-start", ] @@ -1719,29 +1741,30 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_macros", "phf_shared", + "serde", ] [[package]] name = "phf_generator" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ + "fastrand", "phf_shared", - "rand", ] [[package]] name = "phf_macros" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ "phf_generator", "phf_shared", @@ -1752,9 +1775,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ "siphasher", ] @@ -1794,7 +1817,7 @@ dependencies = [ "bytemuck", "pollster", "raw-window-handle", - "thiserror", + "thiserror 1.0.69", "ultraviolet", "wgpu", ] @@ -1874,19 +1897,33 @@ checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" name = "prometeu" version = "0.1.0" dependencies = [ + "anyhow", "clap", - "cpal", - "pixels", - "prometeu-core", - "ringbuf", - "serde_json", - "winit", + "prometeu-compiler", + "prometeu-runtime-desktop", ] [[package]] name = "prometeu-bytecode" version = "0.1.0" +[[package]] +name = "prometeu-compiler" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_parser", + "oxc_span", + "prometeu-bytecode", + "prometeu-core", + "serde", + "serde_json", +] + [[package]] name = "prometeu-core" version = "0.1.0" @@ -1908,22 +1945,6 @@ dependencies = [ "winit", ] -[[package]] -name = "prometeuc" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "oxc_allocator", - "oxc_ast", - "oxc_parser", - "oxc_span", - "prometeu-bytecode", - "prometeu-core", - "serde", - "serde_json", -] - [[package]] name = "quick-xml" version = "0.38.4" @@ -1948,21 +1969,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - [[package]] name = "range-alloc" version = "0.1.4" @@ -2098,12 +2104,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" -[[package]] -name = "ryu-js" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" - [[package]] name = "safe_arch" version = "0.7.4" @@ -2202,12 +2202,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "siphasher" version = "1.0.1" @@ -2255,7 +2249,7 @@ dependencies = [ "log", "memmap2", "rustix 0.38.44", - "thiserror", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -2350,7 +2344,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] @@ -2364,6 +2367,17 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -2754,7 +2768,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.69", "web-sys", "wgpu-hal", "wgpu-types", @@ -2798,7 +2812,7 @@ dependencies = [ "renderdoc-sys", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", "web-sys", "wgpu-types", diff --git a/Cargo.toml b/Cargo.toml index a726ea0f..d282406c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = [ "crates/prometeu-runtime-desktop", "crates/prometeu", "crates/prometeu-bytecode", - "crates/prometeuc", + "crates/prometeu-compiler", ] resolver = "2" @@ -15,4 +15,6 @@ repository = "https://github.com/prometeu/runtime" # The profile that 'dist' will build with [profile.dist] inherits = "release" -lto = "thin" +lto = true +codegen-units = 1 +strip = "symbols" diff --git a/README.md b/README.md index a56e64cc..50c7b8ab 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ This repository is organized as a Rust workspace and contains several components - **[prometeu-core](./crates/prometeu-core)**: The logical core, VM, and internal OS. - **[prometeu-runtime-desktop](crates/prometeu-runtime-desktop)**: Host for execution on Desktop systems. - **[docs/](./docs)**: Technical documentation and system specifications. -- **[devtools-protocol/](./devtools-protocol)**: Definition of the communication protocol for development tools. +- **[devtools-protocol/](devtools)**: Definition of the communication protocol for development tools. - **[test-cartridges/](./test-cartridges)**: Cartridge examples and test suites. --- diff --git a/build/program.disasm.txt b/build/program.disasm.txt new file mode 100644 index 00000000..99dc1644 --- /dev/null +++ b/build/program.disasm.txt @@ -0,0 +1,17 @@ +00000000 Call U32(18) U32(0) +0000000A FrameSync +0000000C Jmp U32(0) +00000012 PushI32 U32(1) ; test_supported.ts:2 +00000018 SetLocal U32(0) ; test_supported.ts:2 +0000001E GetLocal U32(0) ; test_supported.ts:3 +00000024 PushI32 U32(10) ; test_supported.ts:3 +0000002A Lt ; test_supported.ts:3 +0000002C JmpIfFalse U32(80) ; test_supported.ts:3 +00000032 GetLocal U32(0) ; test_supported.ts:4 +00000038 PushI32 U32(1) ; test_supported.ts:4 +0000003E Add ; test_supported.ts:4 +00000040 Dup ; test_supported.ts:4 +00000042 SetLocal U32(0) ; test_supported.ts:4 +00000048 Pop ; test_supported.ts:4 +0000004A Jmp U32(80) +00000050 Ret diff --git a/build/program.pbc b/build/program.pbc new file mode 100644 index 0000000000000000000000000000000000000000..49db59a3734e6a160f1d665299b13ae9f3e0bf27 GIT binary patch literal 82 zcmWGw5MqFU1_mZDL!5yTNIQesPEZjpAZ^6J%n$&iVPYUv3P9Zum4ZOsAlX0$0F~?m As{jB1 literal 0 HcmV?d00001 diff --git a/build/symbols.json b/build/symbols.json new file mode 100644 index 00000000..9d066842 --- /dev/null +++ b/build/symbols.json @@ -0,0 +1,74 @@ +[ + { + "pc": 18, + "file": "test_supported.ts", + "line": 2, + "col": 13 + }, + { + "pc": 24, + "file": "test_supported.ts", + "line": 2, + "col": 9 + }, + { + "pc": 30, + "file": "test_supported.ts", + "line": 3, + "col": 9 + }, + { + "pc": 36, + "file": "test_supported.ts", + "line": 3, + "col": 13 + }, + { + "pc": 42, + "file": "test_supported.ts", + "line": 3, + "col": 9 + }, + { + "pc": 44, + "file": "test_supported.ts", + "line": 3, + "col": 5 + }, + { + "pc": 50, + "file": "test_supported.ts", + "line": 4, + "col": 13 + }, + { + "pc": 56, + "file": "test_supported.ts", + "line": 4, + "col": 17 + }, + { + "pc": 62, + "file": "test_supported.ts", + "line": 4, + "col": 13 + }, + { + "pc": 64, + "file": "test_supported.ts", + "line": 4, + "col": 9 + }, + { + "pc": 66, + "file": "test_supported.ts", + "line": 4, + "col": 9 + }, + { + "pc": 72, + "file": "test_supported.ts", + "line": 4, + "col": 9 + } +] \ No newline at end of file diff --git a/crates/prometeu-bytecode/Cargo.toml b/crates/prometeu-bytecode/Cargo.toml index 6d00aa1b..6bc5742d 100644 --- a/crates/prometeu-bytecode/Cargo.toml +++ b/crates/prometeu-bytecode/Cargo.toml @@ -2,6 +2,8 @@ name = "prometeu-bytecode" version = "0.1.0" edition = "2021" +license.workspace = true +repository.workspace = true [dependencies] # No dependencies for now diff --git a/crates/prometeu-bytecode/src/asm.rs b/crates/prometeu-bytecode/src/asm.rs index 8079997f..0f7d2b45 100644 --- a/crates/prometeu-bytecode/src/asm.rs +++ b/crates/prometeu-bytecode/src/asm.rs @@ -18,6 +18,18 @@ pub enum Asm { Label(String), } +pub fn update_pc_by_operand(initial_pc: u32, operands: &Vec) -> u32 { + let mut pcp: u32 = initial_pc; + for operand in operands { + match operand { + Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => pcp += 4, + Operand::I64(_) | Operand::F64(_) => pcp += 8, + Operand::Bool(_) => pcp += 1, + } + } + pcp +} + pub fn assemble(instructions: &[Asm]) -> Result, String> { let mut labels = HashMap::new(); let mut current_pc = 0u32; @@ -30,13 +42,7 @@ pub fn assemble(instructions: &[Asm]) -> Result, String> { } Asm::Op(_opcode, operands) => { current_pc += 2; // OpCode is u16 (2 bytes) - for operand in operands { - match operand { - Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => current_pc += 4, - Operand::I64(_) | Operand::F64(_) => current_pc += 8, - Operand::Bool(_) => current_pc += 1, - } - } + current_pc = update_pc_by_operand(current_pc, operands); } } } diff --git a/crates/prometeu-compiler/Cargo.toml b/crates/prometeu-compiler/Cargo.toml new file mode 100644 index 00000000..da67a39f --- /dev/null +++ b/crates/prometeu-compiler/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "prometeu-compiler" +version = "0.1.0" +edition = "2021" +license.workspace = true +repository.workspace = true + +[[bin]] +name = "prometeu-compiler" +path = "src/main.rs" + +[package.metadata.dist] +dist = true +include = ["../../VERSION.txt"] + +[dependencies] +prometeu-bytecode = { path = "../prometeu-bytecode" } +prometeu-core = { path = "../prometeu-core" } +oxc_parser = "0.110.0" +oxc_allocator = "0.110.0" +oxc_ast = "0.110.0" +oxc_ast_visit = "0.110.0" +oxc_span = "0.110.0" +clap = { version = "4.5.54", features = ["derive"] } +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.149" +anyhow = "1.0.100" diff --git a/crates/prometeuc/src/cli.rs b/crates/prometeu-compiler/src/cli.rs similarity index 82% rename from crates/prometeuc/src/cli.rs rename to crates/prometeu-compiler/src/cli.rs index 1f57b91c..68c6f2fb 100644 --- a/crates/prometeuc/src/cli.rs +++ b/crates/prometeu-compiler/src/cli.rs @@ -2,7 +2,7 @@ use clap::{Parser, Subcommand}; use std::path::PathBuf; #[derive(Parser)] -#[command(name = "prometeuc")] +#[command(name = "prometeu-compiler")] #[command(about = "Prometeu Compiler", long_about = None)] pub struct Cli { #[command(subcommand)] @@ -32,4 +32,9 @@ pub enum Commands { #[arg(long, default_value_t = true)] emit_symbols: bool, }, + /// Verifies a Prometeu project + Verify { + /// Project directory + project_dir: PathBuf, + }, } diff --git a/crates/prometeu-compiler/src/codegen/ast_util.rs b/crates/prometeu-compiler/src/codegen/ast_util.rs new file mode 100644 index 00000000..c2c13262 --- /dev/null +++ b/crates/prometeu-compiler/src/codegen/ast_util.rs @@ -0,0 +1,26 @@ +use oxc_ast::ast::*; +use anyhow::{Result, anyhow}; + +pub fn get_callee_name(expr: &Expression) -> Result { + get_member_expr_name(expr) +} + +pub fn get_member_expr_name(expr: &Expression) -> Result { + match expr { + Expression::Identifier(ident) => { + let name = ident.name.to_string(); + // Remove prefix 'P' if it's followed by an uppercase letter (e.g., PGfx -> Gfx) + if name.len() > 1 && name.starts_with('P') && name.chars().nth(1).unwrap().is_uppercase() { + Ok(name[1..].to_string()) + } else { + Ok(name) + } + } + Expression::StaticMemberExpression(member) => { + let obj = get_member_expr_name(&member.object)?; + let prop = member.property.name.to_string(); + Ok(format!("{}.{}", obj, prop)) + } + _ => Err(anyhow!("Unsupported expression")), + } +} diff --git a/crates/prometeu-compiler/src/codegen/codegen.rs b/crates/prometeu-compiler/src/codegen/codegen.rs new file mode 100644 index 00000000..08f0a77d --- /dev/null +++ b/crates/prometeu-compiler/src/codegen/codegen.rs @@ -0,0 +1,507 @@ +use anyhow::{Result, anyhow}; +use oxc_ast::ast::*; +use oxc_span::{Span, GetSpan}; +use prometeu_bytecode::opcode::OpCode; +use prometeu_bytecode::asm::{Asm, Operand, assemble}; +use prometeu_bytecode::pbc::{ConstantPoolEntry, PbcFile, write_pbc}; +use crate::compiler::Symbol; +use crate::syscall_map; +use crate::codegen::ast_util; +use prometeu_core::prometeu_os::Syscall; +use std::collections::HashMap; +use prometeu_bytecode::asm; +use prometeu_core::model::Color; + +pub struct Codegen { + file_name: String, + source_text: String, + pub symbols: Vec, + instructions: Vec<(Asm, bool)>, // (Asm, has_symbol) + locals: HashMap, + constant_pool: Vec, + next_local: u32, + label_count: u32, +} + +impl Codegen { + pub fn new(file_name: String, source_text: String) -> Self { + Self { + file_name, + source_text, + symbols: Vec::new(), + instructions: Vec::new(), + locals: HashMap::new(), + constant_pool: vec![ConstantPoolEntry::Null], // Index 0 is always Null + next_local: 0, + label_count: 0, + } + } + + fn add_constant(&mut self, entry: ConstantPoolEntry) -> u32 { + if let Some(pos) = self.constant_pool.iter().position(|e| e == &entry) { + pos as u32 + } else { + let pos = self.constant_pool.len(); + self.constant_pool.push(entry); + pos as u32 + } + } + + pub fn compile_program(&mut self, program: &Program) -> Result> { + self.compile_programs(vec![(self.file_name.clone(), self.source_text.clone(), program)]) + } + + pub fn compile_programs(&mut self, programs: Vec<(String, String, &Program)>) -> Result> { + // First pass: collect all functions and their indices + let mut all_functions = Vec::new(); + for (file, source, program) in &programs { + for item in &program.body { + match item { + Statement::FunctionDeclaration(f) => { + all_functions.push((file.clone(), source.clone(), f.as_ref())); + } + Statement::ExportNamedDeclaration(decl) => { + if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration { + all_functions.push((file.clone(), source.clone(), f.as_ref())); + } + } + _ => {} + } + } + } + + // Find tick function (should be in the first program, which is the entry) + let mut tick_fn_name = None; + if let Some((_, _, entry_program)) = programs.first() { + for item in &entry_program.body { + let f_opt = match item { + Statement::FunctionDeclaration(f) => Some(f.as_ref()), + Statement::ExportNamedDeclaration(decl) => { + if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration { + Some(f.as_ref()) + } else { + None + } + } + _ => None, + }; + + if let Some(f) = f_opt { + if let Some(ident) = &f.id { + if ident.name == "tick" { + tick_fn_name = Some(ident.name.to_string()); + break; + } + } + } + } + } + + let tick_fn_name = tick_fn_name.ok_or_else(|| anyhow!("export function tick() not found in entry file"))?; + + // Entry point: loop calling tick + self.emit_label("entry".to_string()); + self.emit_op(OpCode::Call, vec![Operand::Label(tick_fn_name), Operand::U32(0)], Span::default()); + self.emit_op(OpCode::Pop, vec![], Span::default()); + self.emit_op(OpCode::FrameSync, vec![], Span::default()); + self.emit_op(OpCode::Jmp, vec![Operand::Label("entry".to_string())], Span::default()); + + // Compile all functions + for (file, source, f) in all_functions { + self.file_name = file; + self.source_text = source; + if let Some(ident) = &f.id { + let name = ident.name.to_string(); + self.emit_label(name); + self.compile_function(f)?; + self.emit_op(OpCode::Ret, vec![], Span::default()); + } + } + + let asm_vec: Vec = self.instructions.iter().map(|(a, _)| a.clone()).collect(); + let bytecode = assemble(&asm_vec).map_err(|e| anyhow!("Assemble error: {}", e))?; + + // Finalize symbols (associate PC) + self.finalize_symbols(); + + let pbc = PbcFile { + cp: self.constant_pool.clone(), + rom: bytecode, + }; + + write_pbc(&pbc).map_err(|e| anyhow!("PBC Write error: {}", e)) + } + + fn compile_function(&mut self, f: &Function) -> Result<()> { + self.locals.clear(); + self.next_local = 0; + + // Start scope for parameters and local variables + self.emit_op(OpCode::PushScope, vec![], f.span); + + // Map parameters to locals + for param in &f.params.items { + if let BindingPattern::BindingIdentifier(ident) = ¶m.pattern { + let name = ident.name.to_string(); + let id = self.next_local; + self.locals.insert(name, id); + self.next_local += 1; + } + } + + if let Some(body) = &f.body { + for stmt in &body.statements { + self.compile_stmt(stmt)?; + } + } + + // ABI Rule: Every function MUST leave exactly one value on the stack before RET. + // If the function doesn't have a return statement, we push Null. + // For now, we always push Null at the end if it's not a return. + // In a more complex compiler, we would check if all paths return. + self.emit_op(OpCode::PopScope, vec![], Span::default()); + self.emit_op(OpCode::PushConst, vec![Operand::U32(0)], Span::default()); // Index 0 is Null in PBC + Ok(()) + } + + fn compile_stmt(&mut self, stmt: &Statement) -> Result<()> { + match stmt { + Statement::VariableDeclaration(var) => { + for decl in &var.declarations { + if let BindingPattern::BindingIdentifier(ident) = &decl.id { + let name = ident.name.to_string(); + if let Some(init) = &decl.init { + self.compile_expr(init)?; + } else { + self.emit_op(OpCode::PushI32, vec![Operand::I32(0)], decl.span); + } + let id = self.next_local; + self.locals.insert(name, id); + self.next_local += 1; + } + } + } + Statement::ExpressionStatement(expr_stmt) => { + self.compile_expr(&expr_stmt.expression)?; + self.emit_op(OpCode::Pop, vec![], expr_stmt.span); + } + Statement::IfStatement(if_stmt) => { + let else_label = self.new_label("else"); + let end_label = self.new_label("end_if"); + + self.compile_expr(&if_stmt.test)?; + self.emit_op(OpCode::JmpIfFalse, vec![Operand::Label(else_label.clone())], if_stmt.span); + + self.compile_stmt(&if_stmt.consequent)?; + self.emit_op(OpCode::Jmp, vec![Operand::Label(end_label.clone())], Span::default()); + + self.emit_label(else_label); + if let Some(alt) = &if_stmt.alternate { + self.compile_stmt(alt)?; + } + + self.emit_label(end_label); + } + Statement::BlockStatement(block) => { + self.emit_op(OpCode::PushScope, vec![], block.span); + for stmt in &block.body { + self.compile_stmt(stmt)?; + } + self.emit_op(OpCode::PopScope, vec![], block.span); + } + _ => return Err(anyhow!("Unsupported statement type at {:?}", stmt.span())), + } + Ok(()) + } + + fn compile_expr(&mut self, expr: &Expression) -> Result<()> { + match expr { + Expression::NumericLiteral(n) => { + let val = n.value; + if val.fract() == 0.0 && val >= i32::MIN as f64 && val <= i32::MAX as f64 { + self.emit_op(OpCode::PushI32, vec![Operand::I32(val as i32)], n.span); + } else { + self.emit_op(OpCode::PushI64, vec![Operand::I64(val as i64)], n.span); + } + } + Expression::BooleanLiteral(b) => { + self.emit_op(OpCode::PushBool, vec![Operand::Bool(b.value)], b.span); + } + Expression::StringLiteral(s) => { + let idx = self.add_constant(ConstantPoolEntry::String(s.value.to_string())); + self.emit_op(OpCode::PushConst, vec![Operand::U32(idx)], s.span); + } + Expression::NullLiteral(n) => { + self.emit_op(OpCode::PushConst, vec![Operand::U32(0)], n.span); + } + Expression::Identifier(ident) => { + let name = ident.name.to_string(); + if let Some(&id) = self.locals.get(&name) { + self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], ident.span); + } else { + return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span)); + } + } + Expression::AssignmentExpression(assign) => { + if let AssignmentTarget::AssignmentTargetIdentifier(ident) = &assign.left { + let name = ident.name.to_string(); + self.compile_expr(&assign.right)?; + if let Some(&id) = self.locals.get(&name) { + self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], assign.span); + self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], assign.span); + } else { + return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span)); + } + } else { + return Err(anyhow!("Unsupported assignment target at {:?}", assign.span)); + } + } + Expression::BinaryExpression(bin) => { + self.compile_expr(&bin.left)?; + self.compile_expr(&bin.right)?; + let op = match bin.operator { + BinaryOperator::Addition => OpCode::Add, + BinaryOperator::Subtraction => OpCode::Sub, + BinaryOperator::Multiplication => OpCode::Mul, + BinaryOperator::Division => OpCode::Div, + BinaryOperator::Equality => OpCode::Eq, + BinaryOperator::Inequality => OpCode::Neq, + BinaryOperator::LessThan => OpCode::Lt, + BinaryOperator::GreaterThan => OpCode::Gt, + BinaryOperator::LessEqualThan => OpCode::Lte, + BinaryOperator::GreaterEqualThan => OpCode::Gte, + _ => return Err(anyhow!("Unsupported binary operator {:?} at {:?}", bin.operator, bin.span)), + }; + self.emit_op(op, vec![], bin.span); + } + Expression::LogicalExpression(log) => { + self.compile_expr(&log.left)?; + self.compile_expr(&log.right)?; + let op = match log.operator { + LogicalOperator::And => OpCode::And, + LogicalOperator::Or => OpCode::Or, + _ => return Err(anyhow!("Unsupported logical operator {:?} at {:?}", log.operator, log.span)), + }; + self.emit_op(op, vec![], log.span); + } + Expression::UnaryExpression(unary) => { + self.compile_expr(&unary.argument)?; + let op = match unary.operator { + UnaryOperator::UnaryNegation => OpCode::Neg, + UnaryOperator::UnaryPlus => return Ok(()), + UnaryOperator::LogicalNot => OpCode::Not, + _ => return Err(anyhow!("Unsupported unary operator {:?} at {:?}", unary.operator, unary.span)), + }; + self.emit_op(op, vec![], unary.span); + } + Expression::CallExpression(call) => { + let name = ast_util::get_callee_name(&call.callee)?; + if let Some(syscall_id) = syscall_map::map_syscall(&name) { + if syscall_id == 0xFFFF_FFFF { + // Color.rgb(r, g, b) + if call.arguments.len() != 3 { + return Err(anyhow!("Color.rgb expects 3 arguments at {:?}", call.span)); + } + // We'll emit the bit manipulation logic here or just a special syscall if we had one. + // Since we have bitwise opcodes, let's use them! + // ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3) + + // Argument 0: r + if let Some(expr) = call.arguments[0].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + self.emit_op(OpCode::PushI32, vec![Operand::I32(11)], call.span); + self.emit_op(OpCode::Shl, vec![], call.span); + } + + // Argument 1: g + if let Some(expr) = call.arguments[1].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(2)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + self.emit_op(OpCode::PushI32, vec![Operand::I32(5)], call.span); + self.emit_op(OpCode::Shl, vec![], call.span); + } + + self.emit_op(OpCode::BitOr, vec![], call.span); + + // Argument 2: b + if let Some(expr) = call.arguments[2].as_expression() { + self.compile_expr(expr)?; + self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span); + self.emit_op(OpCode::Shr, vec![], call.span); + } + + self.emit_op(OpCode::BitOr, vec![], call.span); + + } else { + for arg in &call.arguments { + if let Some(expr) = arg.as_expression() { + self.compile_expr(expr)?; + } + } + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); + } + } else { + // Local function call + for arg in &call.arguments { + if let Some(expr) = arg.as_expression() { + self.compile_expr(expr)?; + } + } + self.emit_op(OpCode::Call, vec![Operand::Label(name), Operand::U32(call.arguments.len() as u32)], call.span); + } + } + Expression::StaticMemberExpression(member) => { + let full_name = ast_util::get_member_expr_name(expr)?; + + if full_name.to_lowercase().starts_with("color.") { + match full_name.to_lowercase().as_str() { + "color.black" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::BLACK.raw() as i32)], member.span), + "color.white" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::WHITE.raw() as i32)], member.span), + "color.red" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::RED.raw() as i32)], member.span), + "color.green" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::GREEN.raw() as i32)], member.span), + "color.blue" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::BLUE.raw() as i32)], member.span), + "color.yellow" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::YELLOW.raw() as i32)], member.span), + "color.cyan" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::CYAN.raw() as i32)], member.span), + "color.gray" | "color.grey" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::GRAY.raw() as i32)], member.span), + "color.orange" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::ORANGE.raw() as i32)], member.span), + "color.indigo" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::INDIGO.raw() as i32)], member.span), + "color.magenta" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::MAGENTA.raw() as i32)], member.span), + "color.colorKey" | "color.color_key" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::COLOR_KEY.raw() as i32)], member.span), + _ => return Err(anyhow!("Unsupported color constant: {} at {:?}", full_name, member.span)), + } + } else if full_name.to_lowercase().starts_with("pad.") { + let parts: Vec<&str> = full_name.split('.').collect(); + if parts.len() == 3 { + let btn_name = parts[1]; + let state_name = parts[2]; + let btn_id = self.map_btn_name(btn_name)?; + let syscall_id = match state_name { + "down" => Syscall::InputGetPad as u32, + "pressed" => Syscall::InputGetPadPressed as u32, + "released" => Syscall::InputGetPadReleased as u32, + "holdFrames" => Syscall::InputGetPadHold as u32, + _ => return Err(anyhow!("Unsupported button state: {} at {:?}", state_name, member.span)), + }; + self.emit_op(OpCode::PushI32, vec![Operand::I32(btn_id as i32)], member.span); + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span); + } else { + return Err(anyhow!("Partial Pad access not supported: {} at {:?}", full_name, member.span)); + } + } else if full_name.to_lowercase().starts_with("touch.") { + let parts: Vec<&str> = full_name.split('.').collect(); + match parts.len() { + 2 => { + let prop = parts[1]; + let syscall_id = match prop { + "x" => Syscall::TouchGetX as u32, + "y" => Syscall::TouchGetY as u32, + _ => return Err(anyhow!("Unsupported touch property: {} at {:?}", prop, member.span)), + }; + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span); + } + 3 if parts[1] == "button" => { + let state_name = parts[2]; + let syscall_id = match state_name { + "down" => Syscall::TouchIsDown as u32, + "pressed" => Syscall::TouchIsPressed as u32, + "released" => Syscall::TouchIsReleased as u32, + "holdFrames" => Syscall::TouchGetHold as u32, + _ => return Err(anyhow!("Unsupported touch button state: {} at {:?}", state_name, member.span)), + }; + self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span); + } + _ => return Err(anyhow!("Unsupported touch access: {} at {:?}", full_name, member.span)), + } + } else { + return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span)); + } + } + _ => return Err(anyhow!("Unsupported expression type at {:?}", expr.span())), + } + Ok(()) + } + + fn map_btn_name(&self, btn_name: &str) -> Result { + match btn_name.to_lowercase().as_str() { + "up" => Ok(syscall_map::BTN_UP), + "down" => Ok(syscall_map::BTN_DOWN), + "left" => Ok(syscall_map::BTN_LEFT), + "right" => Ok(syscall_map::BTN_RIGHT), + "a" => Ok(syscall_map::BTN_A), + "b" => Ok(syscall_map::BTN_B), + "x" => Ok(syscall_map::BTN_X), + "y" => Ok(syscall_map::BTN_Y), + "l" => Ok(syscall_map::BTN_L), + "r" => Ok(syscall_map::BTN_R), + "start" => Ok(syscall_map::BTN_START), + "select" => Ok(syscall_map::BTN_SELECT), + _ => Err(anyhow!("Unsupported button: {}", btn_name)), + } + } + + fn new_label(&mut self, prefix: &str) -> String { + let label = format!("{}_{}", prefix, self.label_count); + self.label_count += 1; + label + } + + fn emit_label(&mut self, name: String) { + self.instructions.push((Asm::Label(name), false)); + } + + fn emit_op(&mut self, opcode: OpCode, operands: Vec, span: Span) { + let has_symbol = if !span.is_unspanned() { + let (line, col) = self.lookup_pos(span.start); + self.symbols.push(Symbol { + pc: 0, + file: self.file_name.clone(), + line, + col, + }); + true + } else { + false + }; + self.instructions.push((Asm::Op(opcode, operands), has_symbol)); + } + + fn lookup_pos(&self, pos: u32) -> (usize, usize) { + let mut line = 1; + let mut col = 1; + for (i, c) in self.source_text.char_indices() { + if i as u32 == pos { + break; + } + if c == '\n' { + line += 1; + col = 1; + } else { + col += 1; + } + } + (line, col) + } + + fn finalize_symbols(&mut self) { + let mut current_pc = 0u32; + let mut symbol_ptr = 0; + + for (instr, has_symbol) in &self.instructions { + match instr { + Asm::Label(_) => {} + Asm::Op(_opcode, operands) => { + if *has_symbol && symbol_ptr < self.symbols.len() { + self.symbols[symbol_ptr].pc = current_pc; + symbol_ptr += 1; + } + + current_pc += 2; + current_pc = asm::update_pc_by_operand(current_pc, operands); + } + } + } + } +} diff --git a/crates/prometeuc/src/codegen/mod.rs b/crates/prometeu-compiler/src/codegen/mod.rs similarity index 53% rename from crates/prometeuc/src/codegen/mod.rs rename to crates/prometeu-compiler/src/codegen/mod.rs index 484803d5..3d883e34 100644 --- a/crates/prometeuc/src/codegen/mod.rs +++ b/crates/prometeu-compiler/src/codegen/mod.rs @@ -1,3 +1,5 @@ pub mod codegen; +pub mod validator; +pub mod ast_util; pub use codegen::Codegen; \ No newline at end of file diff --git a/crates/prometeu-compiler/src/codegen/validator.rs b/crates/prometeu-compiler/src/codegen/validator.rs new file mode 100644 index 00000000..81c1def7 --- /dev/null +++ b/crates/prometeu-compiler/src/codegen/validator.rs @@ -0,0 +1,163 @@ +use oxc_ast::ast::*; +use oxc_ast_visit::{Visit, walk}; +use oxc_span::GetSpan; +use anyhow::{Result, anyhow}; +use crate::syscall_map; +use crate::codegen::ast_util; + +pub struct Validator { + errors: Vec, + local_functions: std::collections::HashSet, +} + +impl Validator { + pub fn validate(program: &Program) -> Result<()> { + let mut validator = Self { + errors: Vec::new(), + local_functions: std::collections::HashSet::new(), + }; + + // 1. Collect all local function names + for item in &program.body { + match item { + Statement::FunctionDeclaration(f) => { + if let Some(ident) = &f.id { + validator.local_functions.insert(ident.name.to_string()); + } + } + Statement::ExportNamedDeclaration(decl) => { + if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration { + if let Some(ident) = &f.id { + validator.local_functions.insert(ident.name.to_string()); + } + } + } + Statement::ImportDeclaration(decl) => { + if let Some(specifiers) = &decl.specifiers { + for specifier in specifiers { + match specifier { + ImportDeclarationSpecifier::ImportSpecifier(s) => { + validator.local_functions.insert(s.local.name.to_string()); + } + ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => { + validator.local_functions.insert(s.local.name.to_string()); + } + ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => { + validator.local_functions.insert(s.local.name.to_string()); + } + } + } + } + } + _ => {} + } + } + + // 2. Recursive validation of the AST + validator.visit_program(program); + + if validator.errors.is_empty() { + Ok(()) + } else { + Err(anyhow!("Validation errors:\n{}", validator.errors.join("\n"))) + } + } +} + +impl<'a> Visit<'a> for Validator { + fn visit_statement(&mut self, stmt: &Statement<'a>) { + match stmt { + Statement::VariableDeclaration(_) | + Statement::ExpressionStatement(_) | + Statement::IfStatement(_) | + Statement::BlockStatement(_) | + Statement::ExportNamedDeclaration(_) | + Statement::ImportDeclaration(_) | + Statement::FunctionDeclaration(_) => { + // Supported + walk::walk_statement(self, stmt); + } + _ => { + self.errors.push(format!("Unsupported statement type at {:?}", stmt.span())); + } + } + } + + fn visit_expression(&mut self, expr: &Expression<'a>) { + match expr { + Expression::NumericLiteral(_) | + Expression::BooleanLiteral(_) | + Expression::StringLiteral(_) | + Expression::NullLiteral(_) | + Expression::Identifier(_) | + Expression::AssignmentExpression(_) | + Expression::BinaryExpression(_) | + Expression::LogicalExpression(_) | + Expression::UnaryExpression(_) | + Expression::CallExpression(_) | + Expression::StaticMemberExpression(_) => { + // Base types supported, detailed checks in specific visit methods if needed + walk::walk_expression(self, expr); + } + _ => { + self.errors.push(format!("Unsupported expression type at {:?}", expr.span())); + } + } + } + + fn visit_unary_expression(&mut self, expr: &UnaryExpression<'a>) { + match expr.operator { + UnaryOperator::UnaryNegation | + UnaryOperator::UnaryPlus | + UnaryOperator::LogicalNot => { + walk::walk_unary_expression(self, expr); + } + _ => { + self.errors.push(format!("Unsupported unary operator {:?} at {:?}", expr.operator, expr.span)); + } + } + } + + fn visit_binary_expression(&mut self, expr: &BinaryExpression<'a>) { + match expr.operator { + BinaryOperator::Addition | + BinaryOperator::Subtraction | + BinaryOperator::Multiplication | + BinaryOperator::Division | + BinaryOperator::Equality | + BinaryOperator::Inequality | + BinaryOperator::LessThan | + BinaryOperator::GreaterThan | + BinaryOperator::LessEqualThan | + BinaryOperator::GreaterEqualThan => { + walk::walk_binary_expression(self, expr); + } + _ => { + self.errors.push(format!("Unsupported binary operator {:?} at {:?}", expr.operator, expr.span)); + } + } + } + + fn visit_call_expression(&mut self, expr: &CallExpression<'a>) { + if let Ok(name) = ast_util::get_callee_name(&expr.callee) { + if syscall_map::map_syscall(&name).is_none() && !self.local_functions.contains(&name) { + self.errors.push(format!("Unsupported function call: {} at {:?}", name, expr.span)); + } + } else { + self.errors.push(format!("Unsupported callee expression at {:?}", expr.callee.span())); + } + walk::walk_call_expression(self, expr); + } + + fn visit_logical_expression(&mut self, expr: &LogicalExpression<'a>) { + match expr.operator { + LogicalOperator::And | + LogicalOperator::Or => { + walk::walk_logical_expression(self, expr); + } + _ => { + self.errors.push(format!("Unsupported logical operator {:?} at {:?}", expr.operator, expr.span)); + } + } + } +} diff --git a/crates/prometeu-compiler/src/compiler.rs b/crates/prometeu-compiler/src/compiler.rs new file mode 100644 index 00000000..4a0defc8 --- /dev/null +++ b/crates/prometeu-compiler/src/compiler.rs @@ -0,0 +1,154 @@ +use std::path::{Path, PathBuf}; +use anyhow::{Result, Context, anyhow}; +use oxc_allocator::Allocator; +use oxc_parser::Parser; +use oxc_span::SourceType; +use oxc_ast::ast::*; +use crate::codegen::Codegen; +use crate::codegen::validator::Validator; +use std::fs; +use std::collections::{HashMap, VecDeque}; +use prometeu_bytecode::disasm::disasm; +use serde::Serialize; + +#[derive(Serialize)] +pub struct Symbol { + pub pc: u32, + pub file: String, + pub line: usize, + pub col: usize, +} + +pub struct CompilationUnit { + pub rom: Vec, + pub symbols: Vec, +} + +impl CompilationUnit { + pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> { + fs::write(out, &self.rom).with_context(|| format!("Failed to write PBC to {:?}", out))?; + + if emit_symbols { + let symbols_path = out.with_file_name("symbols.json"); + let symbols_json = serde_json::to_string_pretty(&self.symbols)?; + fs::write(&symbols_path, symbols_json)?; + } + + if emit_disasm { + let disasm_path = out.with_extension("disasm.txt"); + + // Try to parse as PBC, if fails use raw + let rom_to_disasm = if let Ok(pbc) = prometeu_bytecode::pbc::parse_pbc(&self.rom) { + pbc.rom + } else { + self.rom.clone() + }; + + let instructions = disasm(&rom_to_disasm).map_err(|e| anyhow::anyhow!("Disassembly failed: {}", e))?; + + let mut disasm_text = String::new(); + for instr in instructions { + let symbol = self.symbols.iter().find(|s| s.pc == instr.pc); + let comment = if let Some(s) = symbol { + format!(" ; {}:{}", s.file, s.line) + } else { + "".to_string() + }; + + let operands_str = instr.operands.iter() + .map(|o| format!("{:?}", o)) + .collect::>() + .join(" "); + + disasm_text.push_str(&format!("{:08X} {:?} {}{}\n", instr.pc, instr.opcode, operands_str, comment)); + } + fs::write(disasm_path, disasm_text)?; + } + + Ok(()) + } +} + +fn resolve_import(base_path: &Path, import_str: &str) -> Result { + let mut path = base_path.parent().unwrap().join(import_str); + if !path.exists() { + if path.with_extension("ts").exists() { + path.set_extension("ts"); + } else if path.with_extension("js").exists() { + path.set_extension("js"); + } + } + if !path.exists() { + return Err(anyhow!("Cannot resolve import '{}' from {:?}", import_str, base_path)); + } + Ok(path.canonicalize()?) +} + +pub fn compile(entry: &Path) -> Result { + let allocator = Allocator::default(); + let mut modules = HashMap::new(); + let mut queue = VecDeque::new(); + + let entry_abs = entry.canonicalize() + .with_context(|| format!("Failed to canonicalize entry path: {:?}", entry))?; + queue.push_back(entry_abs.clone()); + + while let Some(path) = queue.pop_front() { + let path_str = path.to_string_lossy().to_string(); + if modules.contains_key(&path_str) { + continue; + } + + let source_text = fs::read_to_string(&path) + .with_context(|| format!("Failed to read file: {:?}", path))?; + + // Allocate source_text in the allocator to keep it alive + let source_text_ptr: &str = allocator.alloc_str(&source_text); + + let source_type = SourceType::from_path(&path).unwrap_or_default(); + let parser_ret = Parser::new(&allocator, source_text_ptr, source_type).parse(); + + if !parser_ret.errors.is_empty() { + for error in parser_ret.errors { + eprintln!("{:?}", error); + } + return Err(anyhow!("Failed to parse module: {:?}", path)); + } + + // Validate individual module + Validator::validate(&parser_ret.program)?; + + // Find imports to add to queue + for item in &parser_ret.program.body { + if let Statement::ImportDeclaration(decl) = item { + let import_path = decl.source.value.as_str(); + let resolved = resolve_import(&path, import_path)?; + queue.push_back(resolved); + } + } + + modules.insert(path_str, (source_text_ptr, parser_ret.program)); + } + + let entry_str = entry_abs.to_string_lossy().to_string(); + let mut program_list = Vec::new(); + + // Add entry program first + let entry_data = modules.get(&entry_str).ok_or_else(|| anyhow!("Entry module not found after loading"))?; + program_list.push((entry_str.clone(), entry_data.0.to_string(), &entry_data.1)); + + // Add all other programs + for (path, (source, program)) in &modules { + if path != &entry_str { + program_list.push((path.clone(), source.to_string(), program)); + } + } + + let mut codegen = Codegen::new(entry_str.clone(), entry_data.0.to_string()); + let rom = codegen.compile_programs(program_list)?; + + Ok(CompilationUnit { + rom, + symbols: codegen.symbols, + }) +} diff --git a/crates/prometeuc/src/main.rs b/crates/prometeu-compiler/src/lib.rs similarity index 63% rename from crates/prometeuc/src/main.rs rename to crates/prometeu-compiler/src/lib.rs index b91734e5..7916341d 100644 --- a/crates/prometeuc/src/main.rs +++ b/crates/prometeu-compiler/src/lib.rs @@ -1,12 +1,12 @@ -use clap::Parser; -use anyhow::Result; - pub mod cli; pub mod codegen; pub mod compiler; pub mod syscall_map; -fn main() -> Result<()> { +use clap::Parser; +use anyhow::Result; + +pub fn run() -> Result<()> { let cli = cli::Cli::parse(); match cli.command { @@ -29,7 +29,16 @@ fn main() -> Result<()> { println!("Entry: {:?}", entry); println!("Output: {:?}", out); - compiler::compile(&entry, &out, emit_disasm, emit_symbols)?; + let compilation_unit = compiler::compile(&entry)?; + compilation_unit.export(&out, emit_disasm, emit_symbols)?; + } + cli::Commands::Verify { project_dir } => { + let entry = project_dir.join("src/main.ts"); + println!("Verifying project at {:?}", project_dir); + println!("Entry: {:?}", entry); + + compiler::compile(&entry)?; + println!("Project is valid!"); } } diff --git a/crates/prometeu-compiler/src/main.rs b/crates/prometeu-compiler/src/main.rs new file mode 100644 index 00000000..6433df4a --- /dev/null +++ b/crates/prometeu-compiler/src/main.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +fn main() -> Result<()> { + prometeu_compiler::run() +} diff --git a/crates/prometeuc/src/syscall_map.rs b/crates/prometeu-compiler/src/syscall_map.rs similarity index 88% rename from crates/prometeuc/src/syscall_map.rs rename to crates/prometeu-compiler/src/syscall_map.rs index 50ffae92..df0779ee 100644 --- a/crates/prometeuc/src/syscall_map.rs +++ b/crates/prometeu-compiler/src/syscall_map.rs @@ -21,7 +21,7 @@ pub fn map_syscall(name: &str) -> Option { // Fallback para nomes especiais do compilador match name { - "input.btnA" | "input.btnB" => Some(Syscall::InputGetPad as u32), + "Color.rgb" | "color.rgb" => Some(0xFFFF_FFFF), // ID especial para Color.rgb (não é um syscall real) _ => None, } } diff --git a/crates/prometeu-core/Cargo.toml b/crates/prometeu-core/Cargo.toml index 94a0cc7d..7e4d77a5 100644 --- a/crates/prometeu-core/Cargo.toml +++ b/crates/prometeu-core/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" license.workspace = true [dependencies] -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.149" prometeu-bytecode = { path = "../prometeu-bytecode" } \ No newline at end of file diff --git a/crates/prometeu-core/src/hardware/gfx.rs b/crates/prometeu-core/src/hardware/gfx.rs index a2cf6831..61381e85 100644 --- a/crates/prometeu-core/src/hardware/gfx.rs +++ b/crates/prometeu-core/src/hardware/gfx.rs @@ -133,6 +133,8 @@ impl Gfx { color: Color, mode: BlendMode, ) { + if color == Color::COLOR_KEY { return; } + let fw = self.w as i32; let fh = self.h as i32; @@ -160,6 +162,7 @@ impl Gfx { /// Draws a single pixel. pub fn draw_pixel(&mut self, x: i32, y: i32, color: Color) { + if color == Color::COLOR_KEY { return; } if x >= 0 && x < self.w as i32 && y >= 0 && y < self.h as i32 { self.back[y as usize * self.w + x as usize] = color.0; } @@ -167,6 +170,8 @@ impl Gfx { /// Draws a line between two points using Bresenham's algorithm. pub fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + let dx = (x1 - x0).abs(); let sx = if x0 < x1 { 1 } else { -1 }; let dy = -(y1 - y0).abs(); @@ -193,6 +198,8 @@ impl Gfx { /// Draws a circle outline using Midpoint Circle Algorithm. pub fn draw_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + if r < 0 { return; } let mut x = 0; let mut y = r; @@ -223,6 +230,8 @@ impl Gfx { /// Draws a filled circle. pub fn fill_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + if r < 0 { return; } let mut x = 0; let mut y = r; @@ -255,6 +264,8 @@ impl Gfx { /// Draws a rectangle outline. pub fn draw_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + if w <= 0 || h <= 0 { return; } self.draw_horizontal_line(x, x + w - 1, y, color); self.draw_horizontal_line(x, x + w - 1, y + h - 1, color); @@ -269,6 +280,8 @@ impl Gfx { } fn draw_horizontal_line(&mut self, x0: i32, x1: i32, y: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + if y < 0 || y >= self.h as i32 { return; } let start = x0.max(0); let end = x1.min(self.w as i32 - 1); @@ -279,6 +292,8 @@ impl Gfx { } fn draw_vertical_line(&mut self, x: i32, y0: i32, y1: i32, color: Color) { + if color == Color::COLOR_KEY { return; } + if x < 0 || x >= self.w as i32 { return; } let start = y0.max(0); let end = y1.min(self.h as i32 - 1); diff --git a/crates/prometeu-core/src/model/color.rs b/crates/prometeu-core/src/model/color.rs index 3d211636..1cc09784 100644 --- a/crates/prometeu-core/src/model/color.rs +++ b/crates/prometeu-core/src/model/color.rs @@ -60,4 +60,14 @@ impl Color { pub const fn raw(self) -> u16 { self.0 } + + pub const fn hex(self) -> i32 { + let (r5, g6, b5) = Self::unpack_to_native(self.0); + let r8 = ((r5 as u32) << 3) | ((r5 as u32) >> 2); + let g8 = ((g6 as u32) << 2) | ((g6 as u32) >> 4); + let b8 = ((b5 as u32) << 3) | ((b5 as u32) >> 2); + let hex = r8 << 16 | g8 << 8 | b8; + hex as i32 + } + } diff --git a/crates/prometeu-core/src/prometeu_os/prometeu_os.rs b/crates/prometeu-core/src/prometeu_os/prometeu_os.rs index 831b7342..7680268c 100644 --- a/crates/prometeu-core/src/prometeu_os/prometeu_os.rs +++ b/crates/prometeu-core/src/prometeu_os/prometeu_os.rs @@ -325,26 +325,31 @@ impl PrometeuOS { Ok(100) } - pub fn get_color(&self, index: usize, hw: &mut dyn HardwareBridge) -> Color { - if let Some(bank) = hw.gfx().banks[0].as_ref() { - bank.palettes[0][index % 16] - } else { - match index % 16 { - 0 => Color::BLACK, - 1 => Color::WHITE, - 2 => Color::RED, - 3 => Color::GREEN, - 4 => Color::BLUE, - 5 => Color::YELLOW, - 6 => Color::CYAN, - 7 => Color::INDIGO, - 8 => Color::GRAY, - _ => Color::BLACK, - } - } + pub fn get_color(&self, value: i64) -> Color { + // Agora usamos o valor diretamente como RGB565. + Color::from_raw(value as u16) } // Helper para syscalls + pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a crate::model::Button> { + let pad = hw.pad(); + match id { + 0 => Some(&pad.up), + 1 => Some(&pad.down), + 2 => Some(&pad.left), + 3 => Some(&pad.right), + 4 => Some(&pad.a), + 5 => Some(&pad.b), + 6 => Some(&pad.x), + 7 => Some(&pad.y), + 8 => Some(&pad.l), + 9 => Some(&pad.r), + 10 => Some(&pad.start), + 11 => Some(&pad.select), + _ => None, + } + } + pub fn is_button_down(&self, id: u32, hw: &mut dyn HardwareBridge) -> bool { match id { 0 => hw.pad().up.down, @@ -464,6 +469,17 @@ mod tests { assert!(cycles_after_tick_2 > cycles_after_tick_1, "VM should have consumed more cycles because FrameSync reset the budget"); } + #[test] + fn test_get_color_logic() { + let os = PrometeuOS::new(None); + + // Deve retornar a cor raw diretamente + assert_eq!(os.get_color(0x07E0), Color::GREEN); + assert_eq!(os.get_color(0xF800), Color::RED); + assert_eq!(os.get_color(0x001F), Color::BLUE); + assert_eq!(os.get_color(3), Color::from_raw(3)); + } + #[test] fn test_syscall_log_write_and_rate_limit() { let mut os = PrometeuOS::new(None); @@ -575,70 +591,70 @@ impl NativeInterface for PrometeuOS { // gfx.clear(color_index) -> null Syscall::GfxClear => { - let color_idx = vm.pop_integer()? as usize; - let color = self.get_color(color_idx, hw); + let color_val = vm.pop_integer()?; + let color = self.get_color(color_val); hw.gfx_mut().clear(color); vm.push(Value::Null); Ok(100) } // gfx.draw_rect(x, y, w, h, color_index) -> null Syscall::GfxFillRect => { - let color_idx = vm.pop_integer()? as usize; + let color_val = vm.pop_integer()?; let h = vm.pop_integer()? as i32; let w = vm.pop_integer()? as i32; let y = vm.pop_integer()? as i32; let x = vm.pop_integer()? as i32; - let color = self.get_color(color_idx, hw); + let color = self.get_color(color_val); hw.gfx_mut().fill_rect(x, y, w, h, color); vm.push(Value::Null); Ok(200) } // gfx.draw_line(x1, y1, x2, y2, color_index) -> null Syscall::GfxDrawLine => { - let color_idx = vm.pop_integer()? as usize; + let color_val = vm.pop_integer()?; let y2 = vm.pop_integer()? as i32; let x2 = vm.pop_integer()? as i32; let y1 = vm.pop_integer()? as i32; let x1 = vm.pop_integer()? as i32; - let color = self.get_color(color_idx, hw); + let color = self.get_color(color_val); hw.gfx_mut().draw_line(x1, y1, x2, y2, color); vm.push(Value::Null); Ok(200) } // gfx.draw_circle(x, y, r, color_index) -> null Syscall::GfxDrawCircle => { - let color_idx = vm.pop_integer()? as usize; + let color_val = vm.pop_integer()?; let r = vm.pop_integer()? as i32; let y = vm.pop_integer()? as i32; let x = vm.pop_integer()? as i32; - let color = self.get_color(color_idx, hw); + let color = self.get_color(color_val); hw.gfx_mut().draw_circle(x, y, r, color); vm.push(Value::Null); Ok(200) } // gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null Syscall::GfxDrawDisc => { - let fill_color_idx = vm.pop_integer()? as usize; - let border_color_idx = vm.pop_integer()? as usize; + let fill_color_val = vm.pop_integer()?; + let border_color_val = vm.pop_integer()?; let r = vm.pop_integer()? as i32; let y = vm.pop_integer()? as i32; let x = vm.pop_integer()? as i32; - let fill_color = self.get_color(fill_color_idx, hw); - let border_color = self.get_color(border_color_idx, hw); + let fill_color = self.get_color(fill_color_val); + let border_color = self.get_color(border_color_val); hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color); vm.push(Value::Null); Ok(300) } // gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null Syscall::GfxDrawSquare => { - let fill_color_idx = vm.pop_integer()? as usize; - let border_color_idx = vm.pop_integer()? as usize; + let fill_color_val = vm.pop_integer()?; + let border_color_val = vm.pop_integer()?; let h = vm.pop_integer()? as i32; let w = vm.pop_integer()? as i32; let y = vm.pop_integer()? as i32; let x = vm.pop_integer()? as i32; - let fill_color = self.get_color(fill_color_idx, hw); - let border_color = self.get_color(border_color_idx, hw); + let fill_color = self.get_color(fill_color_val); + let border_color = self.get_color(border_color_val); hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color); vm.push(Value::Null); Ok(200) @@ -653,6 +669,49 @@ impl NativeInterface for PrometeuOS { vm.push(Value::Boolean(is_down)); Ok(50) } + Syscall::InputGetPadPressed => { + let button_id = vm.pop_integer()? as u32; + let val = self.get_button(button_id, hw).map(|b| b.pressed).unwrap_or(false); + vm.push(Value::Boolean(val)); + Ok(50) + } + Syscall::InputGetPadReleased => { + let button_id = vm.pop_integer()? as u32; + let val = self.get_button(button_id, hw).map(|b| b.released).unwrap_or(false); + vm.push(Value::Boolean(val)); + Ok(50) + } + Syscall::InputGetPadHold => { + let button_id = vm.pop_integer()? as u32; + let val = self.get_button(button_id, hw).map(|b| b.hold_frames).unwrap_or(0); + vm.push(Value::Int32(val as i32)); + Ok(50) + } + + Syscall::TouchGetX => { + vm.push(Value::Int32(hw.touch().x)); + Ok(50) + } + Syscall::TouchGetY => { + vm.push(Value::Int32(hw.touch().y)); + Ok(50) + } + Syscall::TouchIsDown => { + vm.push(Value::Boolean(hw.touch().f.down)); + Ok(50) + } + Syscall::TouchIsPressed => { + vm.push(Value::Boolean(hw.touch().f.pressed)); + Ok(50) + } + Syscall::TouchIsReleased => { + vm.push(Value::Boolean(hw.touch().f.released)); + Ok(50) + } + Syscall::TouchGetHold => { + vm.push(Value::Int32(hw.touch().f.hold_frames as i32)); + Ok(50) + } // --- Audio Syscalls --- diff --git a/crates/prometeu-core/src/prometeu_os/syscalls.rs b/crates/prometeu-core/src/prometeu_os/syscalls.rs index f2aef4be..f5be87c4 100644 --- a/crates/prometeu-core/src/prometeu_os/syscalls.rs +++ b/crates/prometeu-core/src/prometeu_os/syscalls.rs @@ -15,6 +15,16 @@ pub enum Syscall { // Input InputGetPad = 0x2001, + InputGetPadPressed = 0x2002, + InputGetPadReleased = 0x2003, + InputGetPadHold = 0x2004, + + TouchGetX = 0x2101, + TouchGetY = 0x2102, + TouchIsDown = 0x2103, + TouchIsPressed = 0x2104, + TouchIsReleased = 0x2105, + TouchGetHold = 0x2106, // Audio AudioPlaySample = 0x3001, @@ -45,6 +55,15 @@ impl Syscall { 0x1005 => Some(Self::GfxDrawDisc), 0x1006 => Some(Self::GfxDrawSquare), 0x2001 => Some(Self::InputGetPad), + 0x2002 => Some(Self::InputGetPadPressed), + 0x2003 => Some(Self::InputGetPadReleased), + 0x2004 => Some(Self::InputGetPadHold), + 0x2101 => Some(Self::TouchGetX), + 0x2102 => Some(Self::TouchGetY), + 0x2103 => Some(Self::TouchIsDown), + 0x2104 => Some(Self::TouchIsPressed), + 0x2105 => Some(Self::TouchIsReleased), + 0x2106 => Some(Self::TouchGetHold), 0x3001 => Some(Self::AudioPlaySample), 0x4001 => Some(Self::FsOpen), 0x4002 => Some(Self::FsRead), @@ -59,52 +78,71 @@ impl Syscall { } } - pub fn as_str(&self) -> &'static str { - match self { - Self::SystemHasCart => "system.has_cart", - Self::SystemRunCart => "system.run_cart", - Self::GfxClear => "gfx.clear", - Self::GfxFillRect => "gfx.fillRect", - Self::GfxDrawLine => "gfx.drawLine", - Self::GfxDrawCircle => "gfx.drawCircle", - Self::GfxDrawDisc => "gfx.drawDisc", - Self::GfxDrawSquare => "gfx.drawSquare", - Self::InputGetPad => "input.get_pad", - Self::AudioPlaySample => "audio.playSample", - Self::FsOpen => "fs.open", - Self::FsRead => "fs.read", - Self::FsWrite => "fs.write", - Self::FsClose => "fs.close", - Self::FsListDir => "fs.listDir", - Self::FsExists => "fs.exists", - Self::FsDelete => "fs.delete", - Self::LogWrite => "log.write", - Self::LogWriteTag => "log.writeTag", - } - } + // pub fn as_str(&self) -> &'static str { + // match self { + // Self::SystemHasCart => "system.has_cart", + // Self::SystemRunCart => "system.run_cart", + // Self::GfxClear => "gfx.clear", + // Self::GfxFillRect => "gfx.fillRect", + // Self::GfxDrawLine => "gfx.drawLine", + // Self::GfxDrawCircle => "gfx.drawCircle", + // Self::GfxDrawDisc => "gfx.drawDisc", + // Self::GfxDrawSquare => "gfx.drawSquare", + // Self::InputGetPad => "input.get_pad", + // Self::InputGetPadPressed => "input.get_pad_pressed", + // Self::InputGetPadReleased => "input.get_pad_released", + // Self::InputGetPadHold => "input.get_pad_hold", + // Self::TouchGetX => "touch.getX", + // Self::TouchGetY => "touch.getY", + // Self::TouchIsDown => "touch.isDown", + // Self::TouchIsPressed => "touch.isPressed", + // Self::TouchIsReleased => "touch.isReleased", + // Self::TouchGetHold => "touch.getHold", + // Self::AudioPlaySample => "audio.playSample", + // Self::FsOpen => "fs.open", + // Self::FsRead => "fs.read", + // Self::FsWrite => "fs.write", + // Self::FsClose => "fs.close", + // Self::FsListDir => "fs.listDir", + // Self::FsExists => "fs.exists", + // Self::FsDelete => "fs.delete", + // Self::LogWrite => "log.write", + // Self::LogWriteTag => "log.writeTag", + // } + // } pub fn from_name(name: &str) -> Option { match name { - "system.has_cart" => Some(Self::SystemHasCart), - "system.run_cart" => Some(Self::SystemRunCart), + "system.hasCart" | "system.has_cart" => Some(Self::SystemHasCart), "gfx.clear" => Some(Self::GfxClear), "gfx.fillRect" | "gfx.draw_rect" => Some(Self::GfxFillRect), "gfx.drawLine" | "gfx.draw_line" => Some(Self::GfxDrawLine), "gfx.drawCircle" | "gfx.draw_circle" => Some(Self::GfxDrawCircle), "gfx.drawDisc" | "gfx.draw_disc" => Some(Self::GfxDrawDisc), "gfx.drawSquare" | "gfx.draw_square" => Some(Self::GfxDrawSquare), - "input.get_pad" => Some(Self::InputGetPad), + "input.getPad" => Some(Self::InputGetPad), + "input.getPadPressed" | "input.get_pad_pressed" => Some(Self::InputGetPadPressed), + "input.getPadReleased" | "input.get_pad_released" => Some(Self::InputGetPadReleased), + "input.getPadHold" | "input.get_pad_hold" => Some(Self::InputGetPadHold), + "touch.getX" | "touch.get_x" => Some(Self::TouchGetX), + "touch.getY" | "touch.get_y" => Some(Self::TouchGetY), + "touch.isDown" | "touch.is_down" => Some(Self::TouchIsDown), + "touch.isPressed" | "touch.is_pressed" => Some(Self::TouchIsPressed), + "touch.isReleased" | "touch.is_released" => Some(Self::TouchIsReleased), + "touch.getHold" | "touch.get_hold" => Some(Self::TouchGetHold), "audio.playSample" | "audio.play_sample" => Some(Self::AudioPlaySample), "fs.open" => Some(Self::FsOpen), "fs.read" => Some(Self::FsRead), "fs.write" => Some(Self::FsWrite), "fs.close" => Some(Self::FsClose), - "fs.listDir" => Some(Self::FsListDir), + "fs.listDir" | "fs.list_dir" => Some(Self::FsListDir), "fs.exists" => Some(Self::FsExists), "fs.delete" => Some(Self::FsDelete), "log.write" => Some(Self::LogWrite), - "log.writeTag" => Some(Self::LogWriteTag), - _ => None, + "log.writeTag" | "log.write_tag" => Some(Self::LogWriteTag), + _ => { + None + } } } } diff --git a/crates/prometeu-runtime-desktop/Cargo.toml b/crates/prometeu-runtime-desktop/Cargo.toml index fe50420e..39d806b6 100644 --- a/crates/prometeu-runtime-desktop/Cargo.toml +++ b/crates/prometeu-runtime-desktop/Cargo.toml @@ -19,4 +19,4 @@ winit = "0.30.12" pixels = "0.15.0" cpal = "0.15.3" ringbuf = "0.4.7" -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0.149" \ No newline at end of file diff --git a/crates/prometeu-runtime-desktop/src/lib.rs b/crates/prometeu-runtime-desktop/src/lib.rs new file mode 100644 index 00000000..e8e58519 --- /dev/null +++ b/crates/prometeu-runtime-desktop/src/lib.rs @@ -0,0 +1,84 @@ +pub mod audio; +pub mod runner; +pub mod fs_backend; +pub mod log_sink; +pub mod debugger; +pub mod stats; +pub mod input; +pub mod cap; +pub mod utilities; + +use runner::HostRunner; +use cap::load_cap_config; +use winit::event_loop::EventLoop; +use prometeu_core::firmware::BootTarget; + +pub fn run() -> Result<(), Box> { + let args: Vec = std::env::args().collect(); + let mut fs_root = None; + let mut cap_config = None; + let mut cartridge_path = None; + let mut debug_mode = false; + let mut debug_port = 7777; + + let mut i = 1; // Skip the executable name + while i < args.len() { + match args[i].as_str() { + "--run" => { + if i + 1 < args.len() { + cartridge_path = Some(args[i + 1].clone()); + debug_mode = false; + i += 1; + } + } + "--debug" => { + if i + 1 < args.len() { + cartridge_path = Some(args[i + 1].clone()); + debug_mode = true; + i += 1; + } + } + "--port" => { + if i + 1 < args.len() { + if let Ok(port) = args[i + 1].parse::() { + debug_port = port; + } + i += 1; + } + } + "--fs-root" => { + if i + 1 < args.len() { + fs_root = Some(args[i + 1].clone()); + i += 1; + } + } + "--cap" => { + if i + 1 < args.len() { + cap_config = load_cap_config(&args[i + 1]); + i += 1; + } + } + _ => {} + } + i += 1; + } + + let boot_target = if let Some(path) = cartridge_path { + BootTarget::Cartridge { + path, + debug: debug_mode, + debug_port: if debug_mode { debug_port } else { 7777 }, + } + } else { + BootTarget::Hub + }; + + let event_loop = EventLoop::new()?; + + let mut runner = HostRunner::new(fs_root, cap_config); + runner.set_boot_target(boot_target); + + event_loop.run_app(&mut runner)?; + + Ok(()) +} diff --git a/crates/prometeu-runtime-desktop/src/main.rs b/crates/prometeu-runtime-desktop/src/main.rs index f57ebede..6219c316 100644 --- a/crates/prometeu-runtime-desktop/src/main.rs +++ b/crates/prometeu-runtime-desktop/src/main.rs @@ -1,84 +1,3 @@ -mod audio; -mod runner; -mod fs_backend; -mod log_sink; -mod debugger; -mod stats; -mod input; -mod cap; -mod utilities; - -use crate::runner::HostRunner; -use crate::cap::load_cap_config; -use winit::event_loop::EventLoop; -use prometeu_core::firmware::BootTarget; - fn main() -> Result<(), Box> { - let args: Vec = std::env::args().collect(); - let mut fs_root = None; - let mut cap_config = None; - let mut cartridge_path = None; - let mut debug_mode = false; - let mut debug_port = 7777; - - let mut i = 1; // Skip the executable name - while i < args.len() { - match args[i].as_str() { - "--run" => { - if i + 1 < args.len() { - cartridge_path = Some(args[i + 1].clone()); - debug_mode = false; - i += 1; - } - } - "--debug" => { - if i + 1 < args.len() { - cartridge_path = Some(args[i + 1].clone()); - debug_mode = true; - i += 1; - } - } - "--port" => { - if i + 1 < args.len() { - if let Ok(port) = args[i + 1].parse::() { - debug_port = port; - } - i += 1; - } - } - "--fs-root" => { - if i + 1 < args.len() { - fs_root = Some(args[i + 1].clone()); - i += 1; - } - } - "--cap" => { - if i + 1 < args.len() { - cap_config = load_cap_config(&args[i + 1]); - i += 1; - } - } - _ => {} - } - i += 1; - } - - let boot_target = if let Some(path) = cartridge_path { - BootTarget::Cartridge { - path, - debug: debug_mode, - debug_port: if debug_mode { debug_port } else { 7777 }, - } - } else { - BootTarget::Hub - }; - - let event_loop = EventLoop::new()?; - - let mut runner = HostRunner::new(fs_root, cap_config); - runner.set_boot_target(boot_target); - - event_loop.run_app(&mut runner)?; - - Ok(()) + prometeu_runtime_desktop::run() } \ No newline at end of file diff --git a/crates/prometeu/Cargo.toml b/crates/prometeu/Cargo.toml index 9401f9b5..ecb64279 100644 --- a/crates/prometeu/Cargo.toml +++ b/crates/prometeu/Cargo.toml @@ -11,29 +11,22 @@ path = "src/main.rs" [[bin]] name = "prometeu-runtime" -path = "../prometeu-runtime-desktop/src/main.rs" +path = "src/bin/prometeu-runtime.rs" -# Future binaries (commented) -# [[bin]] -# name = "prometeuc" -# path = "../prometeuc/src/main.rs" -# -# [[bin]] -# name = "prometeup" -# path = "../prometeup/src/main.rs" +[[bin]] +name = "prometeuc" +path = "src/bin/prometeuc.rs" [package.metadata.dist] dist = true include = [ "../../VERSION.txt", - "../../dist-staging/devtools-protocol" + "../../dist-staging/devtools/debugger-protocol", + "../../dist-staging/devtools/typescript-sdk" ] [dependencies] clap = { version = "4.5", features = ["derive"] } -prometeu-core = { path = "../prometeu-core" } -winit = "0.30.12" -pixels = "0.15.0" -cpal = "0.15.3" -ringbuf = "0.4.7" -serde_json = "1.0" +prometeu-runtime-desktop = { path = "../prometeu-runtime-desktop" } +prometeu-compiler = { path = "../prometeu-compiler" } +anyhow = "1.0.100" diff --git a/crates/prometeu/README.md b/crates/prometeu/README.md index 24ab405e..7dcfded6 100644 --- a/crates/prometeu/README.md +++ b/crates/prometeu/README.md @@ -6,8 +6,10 @@ The `prometeu` binary acts as the unified front-end for the ecosystem. It does n - `prometeu run `: Runs a cartridge using the available runtime. - `prometeu debug [--port

]`: Starts execution in debug mode. -- `prometeu build `: (Planned) Calls the `prometeuc` compiler. +- `prometeu build `: Calls the `prometeuc` compiler. +- `prometeu verify c `: Calls the `prometeuc` compiler. - `prometeu pack `: (Planned) Calls the `prometeup` packager. +- `prometeu verify p `: (Planned) Calls the `prometeup` packager. ## How it works diff --git a/crates/prometeu/src/bin/prometeu-runtime.rs b/crates/prometeu/src/bin/prometeu-runtime.rs new file mode 100644 index 00000000..d662a579 --- /dev/null +++ b/crates/prometeu/src/bin/prometeu-runtime.rs @@ -0,0 +1 @@ +fn main() -> Result<(), Box> { prometeu_runtime_desktop::run() } diff --git a/crates/prometeu/src/bin/prometeuc.rs b/crates/prometeu/src/bin/prometeuc.rs new file mode 100644 index 00000000..818d5c72 --- /dev/null +++ b/crates/prometeu/src/bin/prometeuc.rs @@ -0,0 +1 @@ +fn main() -> anyhow::Result<()> { prometeu_compiler::run() } diff --git a/crates/prometeu/src/main.rs b/crates/prometeu/src/main.rs index e6c44cda..0512f977 100644 --- a/crates/prometeu/src/main.rs +++ b/crates/prometeu/src/main.rs @@ -8,7 +8,7 @@ use std::process::Command; /// The main entry point for the user. This binary does not implement /// compilation or execution logic itself; instead, it acts as a smart /// front-end that locates and dispatches commands to specialized -/// components like `prometeu-runtime-desktop` or `prometeuc`. +/// components like `prometeu-runtime-desktop` or `prometeu-compiler`. #[derive(Parser)] #[command(name = "prometeu")] #[command(about = "Dispatcher for the Prometeu ecosystem", long_about = None)] @@ -86,14 +86,16 @@ fn main() { &["--debug", &cart, "--port", &port.to_string()], ); } - Some(Commands::Build { .. }) => { - not_implemented("build", "prometeuc"); + Some(Commands::Build { project_dir }) => { + dispatch(&exe_dir, "prometeuc", &["build", &project_dir]); } Some(Commands::Pack { .. }) => { not_implemented("pack", "prometeup"); } Some(Commands::Verify { target }) => match target { - VerifyCommands::C { .. } => not_implemented("verify c", "prometeuc"), + VerifyCommands::C { project_dir } => { + dispatch(&exe_dir, "prometeuc", &["verify", &project_dir]); + } VerifyCommands::P { .. } => not_implemented("verify p", "prometeup"), }, None => { @@ -119,7 +121,7 @@ fn dispatch(exe_dir: &Path, bin_name: &str, args: &[&str]) { eprintln!( "prometeu: command '{}' is not yet available in this distribution on {}", match bin_name { - "prometeu-runtime-desktop" => "run/debug", + "prometeu-runtime" => "run/debug", "prometeuc" => "build/verify c", "prometeup" => "pack/verify p", _ => bin_name, diff --git a/crates/prometeuc/Cargo.toml b/crates/prometeuc/Cargo.toml deleted file mode 100644 index 539e6e3f..00000000 --- a/crates/prometeuc/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "prometeuc" -version = "0.1.0" -edition = "2021" - -[dependencies] -prometeu-bytecode = { path = "../prometeu-bytecode" } -prometeu-core = { path = "../prometeu-core" } -oxc_parser = "0.48.0" -oxc_allocator = "0.48.0" -oxc_ast = "0.48.0" -oxc_span = "0.48.0" -clap = { version = "4.4", features = ["derive"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -anyhow = "1.0" diff --git a/crates/prometeuc/src/codegen/codegen.rs b/crates/prometeuc/src/codegen/codegen.rs deleted file mode 100644 index 1dddc283..00000000 --- a/crates/prometeuc/src/codegen/codegen.rs +++ /dev/null @@ -1,324 +0,0 @@ -use anyhow::{Result, anyhow}; -use oxc_ast::ast::*; -use oxc_span::{Span, GetSpan}; -use prometeu_bytecode::opcode::OpCode; -use prometeu_bytecode::asm::{Asm, Operand, assemble}; -use crate::compiler::Symbol; -use crate::syscall_map; -use std::collections::HashMap; - -pub struct Codegen { - file_name: String, - source_text: String, - pub symbols: Vec, - instructions: Vec<(Asm, bool)>, // (Asm, has_symbol) - locals: HashMap, - next_local: u32, - label_count: u32, -} - -impl Codegen { - pub fn new(file_name: String, source_text: String) -> Self { - Self { - file_name, - source_text, - symbols: Vec::new(), - instructions: Vec::new(), - locals: HashMap::new(), - next_local: 0, - label_count: 0, - } - } - - pub fn compile_program(&mut self, program: &Program) -> Result> { - // Find tick function - let mut tick_fn = None; - for item in &program.body { - if let Statement::ExportNamedDeclaration(decl) = item { - if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration { - if let Some(ident) = &f.id { - if ident.name == "tick" { - tick_fn = Some(f); - break; - } - } - } - } - } - - let tick_fn = tick_fn.ok_or_else(|| anyhow!("export function tick() not found"))?; - - // Entry point: loop calling tick - self.emit_label("entry".to_string()); - self.emit_op(OpCode::Call, vec![Operand::Label("tick".to_string()), Operand::U32(0)], Span::default()); - self.emit_op(OpCode::FrameSync, vec![], Span::default()); - self.emit_op(OpCode::Jmp, vec![Operand::Label("entry".to_string())], Span::default()); - - // Function tick - self.emit_label("tick".to_string()); - self.compile_function(tick_fn)?; - self.emit_op(OpCode::Ret, vec![], Span::default()); - - let asm_vec: Vec = self.instructions.iter().map(|(a, _)| a.clone()).collect(); - let rom = assemble(&asm_vec).map_err(|e| anyhow!("Assemble error: {}", e))?; - - // Finalize symbols (associate PC) - self.finalize_symbols(); - - Ok(rom) - } - - fn compile_function(&mut self, f: &Function) -> Result<()> { - self.locals.clear(); - self.next_local = 0; - - if let Some(body) = &f.body { - for stmt in &body.statements { - self.compile_stmt(stmt)?; - } - } - Ok(()) - } - - fn compile_stmt(&mut self, stmt: &Statement) -> Result<()> { - match stmt { - Statement::VariableDeclaration(var) => { - for decl in &var.declarations { - if let BindingPatternKind::BindingIdentifier(ident) = &decl.id.kind { - let name = ident.name.to_string(); - if let Some(init) = &decl.init { - self.compile_expr(init)?; - } else { - self.emit_op(OpCode::PushI32, vec![Operand::I32(0)], decl.span); - } - let id = self.next_local; - self.locals.insert(name, id); - self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], decl.span); - self.next_local += 1; - } - } - } - Statement::ExpressionStatement(expr_stmt) => { - self.compile_expr(&expr_stmt.expression)?; - self.emit_op(OpCode::Pop, vec![], expr_stmt.span); - } - Statement::IfStatement(if_stmt) => { - let else_label = self.new_label("else"); - let end_label = self.new_label("end_if"); - - self.compile_expr(&if_stmt.test)?; - self.emit_op(OpCode::JmpIfFalse, vec![Operand::Label(else_label.clone())], if_stmt.span); - - self.compile_stmt(&if_stmt.consequent)?; - self.emit_op(OpCode::Jmp, vec![Operand::Label(end_label.clone())], Span::default()); - - self.emit_label(else_label); - if let Some(alt) = &if_stmt.alternate { - self.compile_stmt(alt)?; - } - - self.emit_label(end_label); - } - Statement::BlockStatement(block) => { - for stmt in &block.body { - self.compile_stmt(stmt)?; - } - } - _ => return Err(anyhow!("Unsupported statement type at {:?}", stmt.span())), - } - Ok(()) - } - - fn compile_expr(&mut self, expr: &Expression) -> Result<()> { - match expr { - Expression::NumericLiteral(n) => { - let val = n.value; - if val.fract() == 0.0 && val >= i32::MIN as f64 && val <= i32::MAX as f64 { - self.emit_op(OpCode::PushI32, vec![Operand::I32(val as i32)], n.span); - } else { - self.emit_op(OpCode::PushI64, vec![Operand::I64(val as i64)], n.span); - } - } - Expression::BooleanLiteral(b) => { - self.emit_op(OpCode::PushBool, vec![Operand::Bool(b.value)], b.span); - } - Expression::Identifier(ident) => { - let name = ident.name.to_string(); - if let Some(&id) = self.locals.get(&name) { - self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], ident.span); - } else { - return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span)); - } - } - Expression::AssignmentExpression(assign) => { - if let AssignmentTarget::AssignmentTargetIdentifier(ident) = &assign.left { - let name = ident.name.to_string(); - self.compile_expr(&assign.right)?; - if let Some(&id) = self.locals.get(&name) { - self.emit_op(OpCode::Dup, vec![], assign.span); - self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], assign.span); - } else { - return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span)); - } - } else { - return Err(anyhow!("Unsupported assignment target at {:?}", assign.span)); - } - } - Expression::BinaryExpression(bin) => { - self.compile_expr(&bin.left)?; - self.compile_expr(&bin.right)?; - let op = match bin.operator { - BinaryOperator::Addition => OpCode::Add, - BinaryOperator::Subtraction => OpCode::Sub, - BinaryOperator::Multiplication => OpCode::Mul, - BinaryOperator::Division => OpCode::Div, - BinaryOperator::Equality => OpCode::Eq, - BinaryOperator::Inequality => OpCode::Neq, - BinaryOperator::LessThan => OpCode::Lt, - BinaryOperator::GreaterThan => OpCode::Gt, - BinaryOperator::LessEqualThan => OpCode::Lte, - BinaryOperator::GreaterEqualThan => OpCode::Gte, - _ => return Err(anyhow!("Unsupported binary operator {:?} at {:?}", bin.operator, bin.span)), - }; - self.emit_op(op, vec![], bin.span); - } - Expression::LogicalExpression(log) => { - self.compile_expr(&log.left)?; - self.compile_expr(&log.right)?; - let op = match log.operator { - LogicalOperator::And => OpCode::And, - LogicalOperator::Or => OpCode::Or, - _ => return Err(anyhow!("Unsupported logical operator {:?} at {:?}", log.operator, log.span)), - }; - self.emit_op(op, vec![], log.span); - } - Expression::UnaryExpression(unary) => { - self.compile_expr(&unary.argument)?; - let op = match unary.operator { - UnaryOperator::UnaryNegation => OpCode::Neg, - UnaryOperator::UnaryPlus => return Ok(()), - UnaryOperator::LogicalNot => OpCode::Not, - _ => return Err(anyhow!("Unsupported unary operator {:?} at {:?}", unary.operator, unary.span)), - }; - self.emit_op(op, vec![], unary.span); - } - Expression::CallExpression(call) => { - let name = self.get_callee_name(&call.callee)?; - if let Some(syscall_id) = syscall_map::map_syscall(&name) { - if name == "input.btnA" { - self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_A as i32)], call.span); - } else if name == "input.btnB" { - self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_B as i32)], call.span); - } else { - for arg in &call.arguments { - if let Some(expr) = arg.as_expression() { - self.compile_expr(expr)?; - } - } - } - self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span); - } else { - return Err(anyhow!("Unsupported function call: {} at {:?}", name, call.span)); - } - } - Expression::StaticMemberExpression(member) => { - let obj = self.get_callee_name_from_member_obj(&member.object)?; - let prop = member.property.name.to_string(); - let full_name = format!("{}.{}", obj, prop); - // If it's used as a value (GetGlobal/GetLocal?), but for now we only support it in calls - return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span)); - } - _ => return Err(anyhow!("Unsupported expression type at {:?}", expr.span())), - } - Ok(()) - } - - fn get_callee_name(&self, expr: &Expression) -> Result { - match expr { - Expression::Identifier(ident) => Ok(ident.name.to_string()), - Expression::StaticMemberExpression(member) => { - let obj = self.get_callee_name_from_member_obj(&member.object)?; - let prop = member.property.name.to_string(); - Ok(format!("{}.{}", obj, prop)) - } - _ => Err(anyhow!("Unsupported callee expression at {:?}", expr.span())), - } - } - - fn get_callee_name_from_member_obj(&self, expr: &Expression) -> Result { - if let Expression::Identifier(ident) = expr { - Ok(ident.name.to_string()) - } else { - Err(anyhow!("Unsupported member object expression")) - } - } - - fn new_label(&mut self, prefix: &str) -> String { - let label = format!("{}_{}", prefix, self.label_count); - self.label_count += 1; - label - } - - fn emit_label(&mut self, name: String) { - self.instructions.push((Asm::Label(name), false)); - } - - fn emit_op(&mut self, opcode: OpCode, operands: Vec, span: Span) { - let has_symbol = if !span.is_unspanned() { - let (line, col) = self.lookup_pos(span.start); - self.symbols.push(Symbol { - pc: 0, - file: self.file_name.clone(), - line, - col, - }); - true - } else { - false - }; - self.instructions.push((Asm::Op(opcode, operands), has_symbol)); - } - - fn lookup_pos(&self, pos: u32) -> (usize, usize) { - let mut line = 1; - let mut col = 1; - for (i, c) in self.source_text.char_indices() { - if i as u32 == pos { - break; - } - if c == '\n' { - line += 1; - col = 1; - } else { - col += 1; - } - } - (line, col) - } - - fn finalize_symbols(&mut self) { - let mut current_pc = 0u32; - let mut symbol_ptr = 0; - - for (instr, has_symbol) in &self.instructions { - match instr { - Asm::Label(_) => {} - Asm::Op(_opcode, operands) => { - if *has_symbol && symbol_ptr < self.symbols.len() { - self.symbols[symbol_ptr].pc = current_pc; - symbol_ptr += 1; - } - - current_pc += 2; - for operand in operands { - match operand { - Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => current_pc += 4, - Operand::I64(_) | Operand::F64(_) => current_pc += 8, - Operand::Bool(_) => current_pc += 1, - } - } - } - } - } - } -} diff --git a/crates/prometeuc/src/compiler.rs b/crates/prometeuc/src/compiler.rs deleted file mode 100644 index cda88df4..00000000 --- a/crates/prometeuc/src/compiler.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::path::Path; -use anyhow::{Result, Context}; -use oxc_allocator::Allocator; -use oxc_parser::Parser; -use oxc_span::SourceType; -use crate::codegen::Codegen; -use std::fs; -use prometeu_bytecode::disasm::disasm; -use serde::Serialize; - -#[derive(Serialize)] -pub struct Symbol { - pub pc: u32, - pub file: String, - pub line: usize, - pub col: usize, -} - -pub fn compile(entry: &Path, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> { - let source_text = fs::read_to_string(entry) - .with_context(|| format!("Failed to read entry file: {:?}", entry))?; - - let allocator = Allocator::default(); - let source_type = SourceType::from_path(entry).unwrap_or_default(); - - let mut codegen = Codegen::new(entry.to_string_lossy().to_string(), source_text.clone()); - let rom = { - let ret = Parser::new(&allocator, &source_text, source_type).parse(); - - if !ret.errors.is_empty() { - for error in ret.errors { - eprintln!("{:?}", error); - } - return Err(anyhow::anyhow!("Failed to parse module")); - } - - codegen.compile_program(&ret.program)? - }; - - fs::write(out, &rom).with_context(|| format!("Failed to write PBC to {:?}", out))?; - - if emit_symbols { - let symbols_path = out.with_file_name("symbols.json"); - let symbols_json = serde_json::to_string_pretty(&codegen.symbols)?; - fs::write(&symbols_path, symbols_json)?; - } - - if emit_disasm { - let disasm_path = out.with_extension("disasm.txt"); - let instructions = disasm(&rom).map_err(|e| anyhow::anyhow!("Disassembly failed: {}", e))?; - - let mut disasm_text = String::new(); - for instr in instructions { - let symbol = codegen.symbols.iter().find(|s| s.pc == instr.pc); - let comment = if let Some(s) = symbol { - format!(" ; {}:{}", s.file, s.line) - } else { - "".to_string() - }; - - let operands_str = instr.operands.iter() - .map(|o| format!("{:?}", o)) - .collect::>() - .join(" "); - - disasm_text.push_str(&format!("{:08X} {:?} {}{}\n", instr.pc, instr.opcode, operands_str, comment)); - } - fs::write(disasm_path, disasm_text)?; - } - - Ok(()) -} diff --git a/devtools-protocol/README.md b/devtools/debugger-protocol/README.md similarity index 92% rename from devtools-protocol/README.md rename to devtools/debugger-protocol/README.md index d4a2d064..b659d7b3 100644 --- a/devtools-protocol/README.md +++ b/devtools/debugger-protocol/README.md @@ -8,9 +8,9 @@ The protocol is based on JSON, sent via a transport connection (usually TCP). Ea ## Structure -- **[protocol.json](./protocol.json)**: Formal definition of the protocol in JSON format. +- **[protocol.json](protocol.json)**: Formal definition of the protocol in JSON format. - **[protocol.md](README.md)**: Human-readable documentation describing commands, events, and types. -- **[examples/](./examples)**: Examples of message flows (handshake, breakpoints, etc.) in JSONL format. +- **[examples/](examples)**: Examples of message flows (handshake, breakpoints, etc.) in JSONL format. ## Versioning diff --git a/devtools-protocol/examples/basic_session.jsonl b/devtools/debugger-protocol/examples/basic_session.jsonl similarity index 100% rename from devtools-protocol/examples/basic_session.jsonl rename to devtools/debugger-protocol/examples/basic_session.jsonl diff --git a/devtools-protocol/examples/breakpoint_flow.jsonl b/devtools/debugger-protocol/examples/breakpoint_flow.jsonl similarity index 100% rename from devtools-protocol/examples/breakpoint_flow.jsonl rename to devtools/debugger-protocol/examples/breakpoint_flow.jsonl diff --git a/devtools-protocol/examples/handshake.jsonl b/devtools/debugger-protocol/examples/handshake.jsonl similarity index 100% rename from devtools-protocol/examples/handshake.jsonl rename to devtools/debugger-protocol/examples/handshake.jsonl diff --git a/devtools-protocol/protocol.json b/devtools/debugger-protocol/protocol.json similarity index 100% rename from devtools-protocol/protocol.json rename to devtools/debugger-protocol/protocol.json diff --git a/devtools/typescript-sdk/package.json b/devtools/typescript-sdk/package.json new file mode 100644 index 00000000..7d382c93 --- /dev/null +++ b/devtools/typescript-sdk/package.json @@ -0,0 +1,6 @@ +{ + "name": "@prometeu/sdk", + "version": "0.1.0", + "main": "src/index.ts", + "types": "types/index.d.ts" +} diff --git a/devtools/typescript-sdk/src/audio.ts b/devtools/typescript-sdk/src/audio.ts new file mode 100644 index 00000000..f555e559 --- /dev/null +++ b/devtools/typescript-sdk/src/audio.ts @@ -0,0 +1,2 @@ +export const Audio = audio; +export type Audio = Prometeu.Audio; diff --git a/devtools/typescript-sdk/src/color.ts b/devtools/typescript-sdk/src/color.ts new file mode 100644 index 00000000..6269dbb0 --- /dev/null +++ b/devtools/typescript-sdk/src/color.ts @@ -0,0 +1,25 @@ +export type Color565 = Prometeu.Color565; + +function clamp8(n: number): number { + return n < 0 ? 0 : n > 255 ? 255 : n | 0; +} + +export const Color: Prometeu.Color = { + black: 0x0000 as Color565, + white: 0xffff as Color565, + red: 0xf800 as Color565, + green: 0x07e0 as Color565, + blue: 0x001f as Color565, + yellow: 0xffe0 as Color565, + cyan: 0x07ff as Color565, + magenta: 0xf81f as Color565, + indigo: 0x4810 as Color565, + + rgb(r: number, g: number, b: number): Color565 { + r = clamp8(r); g = clamp8(g); b = clamp8(b); + const r5 = (r >> 3) & 0x1f; + const g6 = (g >> 2) & 0x3f; + const b5 = (b >> 3) & 0x1f; + return ((r5 << 11) | (g6 << 5) | b5) as Color565; + }, +}; diff --git a/devtools/typescript-sdk/src/fs.ts b/devtools/typescript-sdk/src/fs.ts new file mode 100644 index 00000000..c9306b80 --- /dev/null +++ b/devtools/typescript-sdk/src/fs.ts @@ -0,0 +1,2 @@ +export const Fs = fs; +export type Fs = Prometeu.Fs; diff --git a/devtools/typescript-sdk/src/gfx.ts b/devtools/typescript-sdk/src/gfx.ts new file mode 100644 index 00000000..bdea5f4a --- /dev/null +++ b/devtools/typescript-sdk/src/gfx.ts @@ -0,0 +1 @@ +export type Gfx = Prometeu.Gfx; \ No newline at end of file diff --git a/devtools/typescript-sdk/src/index.ts b/devtools/typescript-sdk/src/index.ts new file mode 100644 index 00000000..3f6710fe --- /dev/null +++ b/devtools/typescript-sdk/src/index.ts @@ -0,0 +1,8 @@ +export { Color } from "./color"; +export { Pad, Touch } from "./input"; +export { Gfx } from "./gfx"; +export { System } from "./system"; +export { Audio } from "./audio"; +export { Fs } from "./fs"; +export { Log, LogLevel } from "./log"; +export type { Color565 } from "./color"; diff --git a/devtools/typescript-sdk/src/input.ts b/devtools/typescript-sdk/src/input.ts new file mode 100644 index 00000000..15b7419b --- /dev/null +++ b/devtools/typescript-sdk/src/input.ts @@ -0,0 +1,4 @@ + + +export const Pad: Prometeu.Pad = pad; +export const Touch: Prometeu.Touch = touch; diff --git a/devtools/typescript-sdk/src/log.ts b/devtools/typescript-sdk/src/log.ts new file mode 100644 index 00000000..fc65a17d --- /dev/null +++ b/devtools/typescript-sdk/src/log.ts @@ -0,0 +1,11 @@ +export const Log = log; +export type Log = Prometeu.Log; + +export enum LogLevel { + Trace = 0, + Debug = 1, + Info = 2, + Warn = 3, + Error = 4, + Fatal = 5, +} diff --git a/devtools/typescript-sdk/src/system.ts b/devtools/typescript-sdk/src/system.ts new file mode 100644 index 00000000..3be42c53 --- /dev/null +++ b/devtools/typescript-sdk/src/system.ts @@ -0,0 +1,2 @@ +export const System = system; +export type System = Prometeu.System; diff --git a/devtools/typescript-sdk/tsconfig.json b/devtools/typescript-sdk/tsconfig.json new file mode 100644 index 00000000..88ccffe7 --- /dev/null +++ b/devtools/typescript-sdk/tsconfig.json @@ -0,0 +1,4 @@ +{ + "compilerOptions": { + } +} diff --git a/devtools/typescript-sdk/types/index.d.ts b/devtools/typescript-sdk/types/index.d.ts new file mode 100644 index 00000000..7b1faa46 --- /dev/null +++ b/devtools/typescript-sdk/types/index.d.ts @@ -0,0 +1,95 @@ +export {}; // that is a module, should not include any other scope here + +declare global { + namespace Prometeu { + type Color565 = number & { readonly __brand: "Color565" }; + + interface Button { + readonly down: boolean; + readonly pressed: boolean; + readonly released: boolean; + readonly holdFrames: number; + } + + interface Pad { + readonly up: Button; + readonly down: Button; + readonly left: Button; + readonly right: Button; + readonly a: Button; + readonly b: Button; + readonly x: Button; + readonly y: Button; + readonly l: Button; + readonly r: Button; + readonly start: Button; + readonly select: Button; + } + + interface Touch { + readonly x: number; + readonly y: number; + readonly button: Button; + } + + interface Gfx { + fillRect(x: number, y: number, w: number, h: number, color: Color565): void; + drawLine(x1: number, y1: number, x2: number, y2: number, color: Color565): void; + drawCircle(x: number, y: number, r: number, color: Color565): void; + drawDisc(x: number, y: number, r: number, borderColor: Color565, fillColor: Color565): void; + drawSquare(x: number, y: number, w: number, h: number, borderColor: Color565, fillColor: Color565): void; + clear(color: Color565): void; + } + + interface Color { + readonly black: Color565; + readonly white: Color565; + readonly red: Color565; + readonly green: Color565; + readonly blue: Color565; + readonly yellow: Color565; + readonly cyan: Color565; + readonly magenta: Color565; + readonly indigo: Color565; + readonly color_key: Color565; + readonly orange: Color565; + readonly gray: Color565; + readonly grey: Color565; + rgb(r: number, g: number, b: number): Color565; + } + + interface System { + hasCart(): boolean; + } + + interface Audio { + playSample(sampleId: number, voiceId: number, volume: number, pan: number, pitch: number): void; + } + + interface Fs { + open(path: string): number; + read(handle: number): string | null; + write(handle: number, content: string): boolean; + close(handle: number): void; + listDir(path: string): string | null; + exists(path: string): boolean; + delete(path: string): boolean; + } + + interface Log { + write(level: number, msg: string): void; + writeTag(level: number, tag: number, msg: string): void; + } + } + + export const pad: Prometeu.Pad; + export const touch: Prometeu.Touch; + export const gfx: Prometeu.Gfx; + export const audio: Prometeu.Audio; + export const fs: Prometeu.Fs; + export const log: Prometeu.Log; + export const color: Prometeu.Color; + export const system: Prometeu.System; + +} + diff --git a/dist-workspace.toml b/dist-workspace.toml index a38529f9..2ee777fe 100644 --- a/dist-workspace.toml +++ b/dist-workspace.toml @@ -15,4 +15,4 @@ targets = ["aarch64-apple-darwin", "x86_64-apple-darwin"] unix-archive = ".zip" macos-universal-binaries = true [dist.hooks] -pre-build = ["./scripts/gen-version.sh"] +pre-build = ["./scripts/pre-dist.sh"] diff --git a/docs/README.md b/docs/README.md index c59c8dff..620cd2fe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,5 +11,5 @@ Detailed documentation on system architecture, cartridge format, VM instruction ### 🐞 [Debugger](./debugger) Documentation on debugging tools and how to integrate new tools into the ecosystem. -### 🔌 [DevTools Protocol](../devtools-protocol) +### 🔌 [DevTools Protocol](../devtools) Definition of the communication protocol used for real-time debugging and inspection. diff --git a/examples/colorsquare/src/main.ts b/examples/colorsquare/src/main.ts index c6ecbfec..bd01add1 100644 --- a/examples/colorsquare/src/main.ts +++ b/examples/colorsquare/src/main.ts @@ -1,8 +1,8 @@ export function tick(): void { let color = 0x07E0; // green - if (input.btnA()) color = 0xF800; // red - if (input.btnB()) color = 0x001F; // blue + if (PInput.btnA()) color = 0xF800; // red + if (PInput.btnB()) color = 0x001F; // blue - gfx.fillRect(60, 60, 40, 40, color); + Gfx.fillRect(60, 60, 40, 40, color); } diff --git a/scripts/clean-all.sh b/scripts/clean-all.sh new file mode 100755 index 00000000..71ce3a26 --- /dev/null +++ b/scripts/clean-all.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -euo pipefail + +cargo clean +rm -rf dist-staging \ No newline at end of file diff --git a/scripts/gen-version.sh b/scripts/gen-version.sh index 5ac5552a..c0fa86ee 100755 --- a/scripts/gen-version.sh +++ b/scripts/gen-version.sh @@ -1,5 +1,5 @@ #!/bin/bash # Get version from git tag or fallback to Cargo.toml version -VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/prometeu-runtime-desktop/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0") +VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/prometeu/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0") echo "$VERSION" > VERSION.txt echo "Generated VERSION.txt with version $VERSION" \ No newline at end of file diff --git a/scripts/local-dist.sh b/scripts/local-dist.sh index 1a7eac27..ed1574a3 100755 --- a/scripts/local-dist.sh +++ b/scripts/local-dist.sh @@ -1,25 +1,33 @@ #!/bin/bash +set -e +# Generate version ./scripts/gen-version.sh -VERSION=$(cat VERSION.txt) - # Prepare staging for SDK extra files echo "Preparing dist-staging..." -mkdir -p dist-staging/devtools-protocol -cp devtools-protocol/protocol.json dist-staging/devtools-protocol/ +rm -rf dist-staging/devtools/debugger-protocol +rm -rf dist-staging/devtools/typescript-sdk + +mkdir -p dist-staging/devtools/debugger-protocol +mkdir -p dist-staging/devtools/typescript-sdk + +cp devtools/debugger-protocol/protocol.json dist-staging/devtools/debugger-protocol/ +cp -R devtools/typescript-sdk dist-staging/devtools +cp VERSION.txt dist-staging/devtools/debugger-protocol/VERSION.txt +cp VERSION.txt dist-staging/devtools/typescript-sdk/VERSION.txt # Clean and prepare the version-specific directory -echo "Cleaning dist-staging/stable/$VERSION..." -rm -rf "dist-staging/stable/$VERSION" -mkdir -p "dist-staging/stable/$VERSION" +echo "Cleaning dist-staging/stable..." +mkdir -p "dist-staging/stable" +rm -rf "dist-staging/stable/*" # Build stable using cargo build dist build -echo "Copying target/distrib content to dist-staging/stable/$VERSION..." +echo "Copying target/distrib content to dist-staging/stable..." if [ -d "target/distrib" ] && [ "$(ls -A target/distrib)" ]; then - cp -r target/distrib/* "dist-staging/stable/$VERSION/" + cp -r target/distrib/* "dist-staging/stable/" else echo "Warning: target/dist directory not found or empty." fi \ No newline at end of file diff --git a/symbols.json b/symbols.json new file mode 100644 index 00000000..506ddeff --- /dev/null +++ b/symbols.json @@ -0,0 +1,80 @@ +[ + { + "pc": 20, + "file": "temp_test_2.ts", + "line": 1, + "col": 1 + }, + { + "pc": 22, + "file": "temp_test_2.ts", + "line": 2, + "col": 13 + }, + { + "pc": 28, + "file": "temp_test_2.ts", + "line": 2, + "col": 17 + }, + { + "pc": 34, + "file": "temp_test_2.ts", + "line": 2, + "col": 13 + }, + { + "pc": 46, + "file": "temp_test_2.ts", + "line": 5, + "col": 8 + }, + { + "pc": 48, + "file": "temp_test_2.ts", + "line": 6, + "col": 10 + }, + { + "pc": 54, + "file": "temp_test_2.ts", + "line": 6, + "col": 14 + }, + { + "pc": 60, + "file": "temp_test_2.ts", + "line": 6, + "col": 5 + }, + { + "pc": 70, + "file": "temp_test_2.ts", + "line": 6, + "col": 5 + }, + { + "pc": 72, + "file": "temp_test_2.ts", + "line": 7, + "col": 15 + }, + { + "pc": 78, + "file": "temp_test_2.ts", + "line": 7, + "col": 18 + }, + { + "pc": 84, + "file": "temp_test_2.ts", + "line": 7, + "col": 5 + }, + { + "pc": 90, + "file": "temp_test_2.ts", + "line": 7, + "col": 5 + } +] \ No newline at end of file diff --git a/temp_test_2.disasm.txt b/temp_test_2.disasm.txt new file mode 100644 index 00000000..5ccabf26 --- /dev/null +++ b/temp_test_2.disasm.txt @@ -0,0 +1,23 @@ +00000000 Call U32(46) U32(0) +0000000A Pop +0000000C FrameSync +0000000E Jmp U32(0) +00000014 PushScope ; temp_test_2.ts:1 +00000016 GetLocal U32(0) ; temp_test_2.ts:2 +0000001C GetLocal U32(1) ; temp_test_2.ts:2 +00000022 Add ; temp_test_2.ts:2 +00000024 PopScope +00000026 PushConst U32(0) +0000002C Ret +0000002E PushScope ; temp_test_2.ts:5 +00000030 PushI32 U32(10) ; temp_test_2.ts:6 +00000036 PushI32 U32(20) ; temp_test_2.ts:6 +0000003C Call U32(20) U32(2) ; temp_test_2.ts:6 +00000046 Pop ; temp_test_2.ts:6 +00000048 PushI32 U32(1) ; temp_test_2.ts:7 +0000004E PushConst U32(1) ; temp_test_2.ts:7 +00000054 Syscall U32(20481) ; temp_test_2.ts:7 +0000005A Pop ; temp_test_2.ts:7 +0000005C PopScope +0000005E PushConst U32(0) +00000064 Ret diff --git a/test-cartridges/color-square/build/program.disasm.txt b/test-cartridges/color-square/build/program.disasm.txt new file mode 100644 index 00000000..ec0dcac5 --- /dev/null +++ b/test-cartridges/color-square/build/program.disasm.txt @@ -0,0 +1,158 @@ +00000000 Call U32(20) U32(0) +0000000A Pop +0000000C FrameSync +0000000E Jmp U32(0) +00000014 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:5 +00000016 Call U32(428) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:6 +00000020 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:6 +00000022 Call U32(236) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:7 +0000002C Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:7 +0000002E Call U32(362) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:8 +00000038 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:8 +0000003A Call U32(92) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:9 +00000044 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:9 +00000046 Call U32(644) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:10 +00000050 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:10 +00000052 PopScope +00000054 PushConst U32(0) +0000005A Ret +0000005C PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:1 +0000005E PushConst U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:2 +00000064 Syscall U32(16385) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:2 +0000006A GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +00000070 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +00000076 Gte ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +00000078 JmpIfFalse U32(226) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +0000007E PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +00000080 GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4 +00000086 PushConst U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4 +0000008C Syscall U32(16387) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4 +00000092 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4 +00000094 GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:5 +0000009A Syscall U32(16386) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:5 +000000A0 GetLocal U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000A6 JmpIfFalse U32(204) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000AC PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000B2 PushI32 U32(101) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000B8 GetLocal U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000BE Syscall U32(20482) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000C4 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6 +000000C6 Jmp U32(204) +000000CC GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7 +000000D2 Syscall U32(16388) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7 +000000D8 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7 +000000DA PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3 +000000DC Jmp U32(226) +000000E2 PopScope +000000E4 PushConst U32(0) +000000EA Ret +000000EC PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:1 +000000EE PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2 +000000F4 Syscall U32(8193) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2 +000000FA JmpIfFalse U32(286) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2 +00000100 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2 +00000102 PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3 +00000108 PushConst U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3 +0000010E Syscall U32(20481) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3 +00000114 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3 +00000116 PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2 +00000118 Jmp U32(286) +0000011E PushI32 U32(4) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6 +00000124 Syscall U32(8194) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6 +0000012A JmpIfFalse U32(352) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6 +00000130 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6 +00000132 PushI32 U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +00000138 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +0000013E PushI32 U32(255) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +00000144 PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +0000014A PushI32 U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +00000150 Syscall U32(12289) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +00000156 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7 +00000158 PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6 +0000015A Jmp U32(352) +00000160 PopScope +00000162 PushConst U32(0) +00000168 Ret +0000016A PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:11 +0000016C Syscall U32(8451) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12 +00000172 JmpIfFalse U32(418) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12 +00000178 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12 +0000017A Syscall U32(8449) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +00000180 Syscall U32(8450) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +00000186 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +0000018C PushI32 U32(65535) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +00000192 Syscall U32(4100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +00000198 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13 +0000019A PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12 +0000019C Jmp U32(418) +000001A2 PopScope +000001A4 PushConst U32(0) +000001AA Ret +000001AC PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:1 +000001AE PushI32 U32(18448) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2 +000001B4 Syscall U32(4097) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2 +000001BA Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2 +000001BC PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001C2 PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001C8 PushI32 U32(50) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001CE PushI32 U32(50) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001D4 PushI32 U32(63488) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001DA Syscall U32(4098) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001E0 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3 +000001E2 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +000001E8 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +000001EE PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +000001F4 PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +000001FA PushI32 U32(65535) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +00000200 Syscall U32(4099) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +00000206 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4 +00000208 PushI32 U32(64) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +0000020E PushI32 U32(64) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +00000214 PushI32 U32(20) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +0000021A PushI32 U32(31) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +00000220 Syscall U32(4100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +00000226 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5 +00000228 PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +0000022E PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +00000234 PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +0000023A PushI32 U32(2016) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +00000240 PushI32 U32(65504) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +00000246 Syscall U32(4101) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +0000024C Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6 +0000024E PushI32 U32(20) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +00000254 PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +0000025A PushI32 U32(30) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +00000260 PushI32 U32(30) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +00000266 PushI32 U32(2047) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +0000026C PushI32 U32(63519) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +00000272 Syscall U32(4102) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +00000278 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7 +0000027A PopScope +0000027C PushConst U32(0) +00000282 Ret +00000284 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:10 +00000286 PushI32 U32(255) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +0000028C PushI32 U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +00000292 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +00000294 PushI32 U32(11) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +0000029A Shl ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +0000029C PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002A2 PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002A8 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002AA PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002B0 Shl ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002B2 BitOr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002B4 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002BA PushI32 U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002C0 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002C2 BitOr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11 +000002C4 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002CA PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002D0 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002D6 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002DC GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002E2 Syscall U32(4098) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002E8 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12 +000002EA PopScope +000002EC PushConst U32(0) +000002F2 Ret diff --git a/test-cartridges/color-square/build/program.pbc b/test-cartridges/color-square/build/program.pbc new file mode 100644 index 0000000000000000000000000000000000000000..c53077c1eebc1079a37d11097ac0f74bea19125b GIT binary patch literal 817 zcmZ8fJ5Iwu6r4B?ASiGor0w##076tK5mFSIlqQIdf+8+Jfmp-{$`qW0nxk-th?myP|y&q3!KRvL6 z4x5{nt_j!bRDO2Wb_48UnIiplsprHU8vz^PN@zU2kE(Rj*VFlZean3%KQ$#+^d<(h zND*NFv%+K5j`)^ysp7_Ozbn;_p4Kc?Bkefan+WIK S$A-1Fvwo9?)q9Bk<^2G{iAjmyP|y&q3!KRvL6 z4x5{nt_j!bRDO2Wb_48UnIiplsprHU8vz^PN@zU2kE(Rj*VFlZean3%KQ$#+^d<(h zND*NFv%+K5j`)^ysp7_Ozbn;_p4Kc?Bkefan+WIK S$A-1Fvwo9?)q9Bk<^2G{iAj43~HhcZ%QKofz}Or*rgkP>gm!jPpQD??gC)`n~h*&4F@BOWc??(n9Z z_*gX~%K4R_MccvSGO5&=(X7N%zgr5by#BImdCs;_$&oqhR`POR{C~-Nz= 0) { + fs.write(h, "Hello Prometeu!"); + let content = fs.read(h); + if (content) log.writeTag(2, 101, content); + fs.close(h); + } +} diff --git a/test-cartridges/color-square/src/my_gfx.ts b/test-cartridges/color-square/src/my_gfx.ts new file mode 100644 index 00000000..de97eb7b --- /dev/null +++ b/test-cartridges/color-square/src/my_gfx.ts @@ -0,0 +1,13 @@ +export function do_init_gfx(): void { + gfx.clear(color.indigo); + gfx.fillRect(10, 10, 50, 50, color.red); + gfx.drawLine(0, 0, 128, 128, color.white); + gfx.drawCircle(64, 64, 20, color.blue); + gfx.drawDisc(100, 100, 10, color.green, color.yellow); + gfx.drawSquare(20, 100, 30, 30, color.cyan, color.color_key); +} + +export function print_orange(): void { + let c = color.rgb(255, 128, 0); + gfx.fillRect(0, 0, 5, 5, c); +} \ No newline at end of file diff --git a/test-cartridges/color-square/src/my_input.ts b/test-cartridges/color-square/src/my_input.ts new file mode 100644 index 00000000..242df489 --- /dev/null +++ b/test-cartridges/color-square/src/my_input.ts @@ -0,0 +1,15 @@ +export function do_pad(): void { + if (pad.up.down) { + log.write(2, "Up is down"); + } + + if (pad.a.pressed) { + audio.playSample(1, 0, 255, 128, 1.0); + } +} + +export function do_touch(): void { + if (touch.button.down) { + gfx.drawCircle(touch.x, touch.y, 5, color.white); + } +} \ No newline at end of file diff --git a/test-cartridges/color-square/tsconfig.json b/test-cartridges/color-square/tsconfig.json new file mode 100644 index 00000000..150e9440 --- /dev/null +++ b/test-cartridges/color-square/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "typeRoots": [ + "./prometeu-sdk/types", "./node_modules/@types"] + } +} \ No newline at end of file