Slopjective-C is an Objective-C 3.0 draft specification and native compiler project.
This repository contains two things that matter:
- a working draft of the Objective-C 3.0 language and runtime model,
- an in-tree native implementation under
native/objc3c/.
The project is no longer just a grammar sketch.
Today it has:
- a real native
objc3ccompiler, - real LLVM IR and native object emission,
- a runnable subset of
.objc3, - emitted runtime metadata for the object-model surface,
- ongoing work to finish full runtime realization of classes, protocols, categories, properties, blocks, and ARC.
What is still incomplete:
- full live Objective-C 3.0 object-model runtime behavior,
- full property/ivar/runtime reflection closure,
- full blocks and ARC automation,
- advanced error, concurrency, metaprogramming, and broader interop features.
The current runnable subset is real, but it is still a subset.
What you can compile and run today:
moduledeclarations,- global and local
letbindings, fn,pure fn, and external function declarations,- integer and boolean values,
- baseline alias surfaces such as
BOOL,NSInteger, andNSUInteger, - Objective-C-flavored signature aliases such as
id,Class,SEL,Protocol, andinstancetype, - control flow:
if/elsewhiledo whileforswitchbreakcontinuereturn
- arithmetic, comparison, logical, bitwise, shift, ternary, and grouping expressions,
- bracket message-send syntax through the current runtime dispatch path,
- deterministic selector/string pool and metadata-bearing object emission,
- ownership-baseline runtime behavior for supported retainable object storage.
What is not fully runnable yet:
- full class/protocol/category/property runtime realization,
- full property synthesis and reflective runtime consumption,
- full escaping block/byref runtime behavior,
- full ARC automation,
- advanced language features such as
throws, async/await, tasks, actors, macros, and broader interop closure.
- Public overview: https://doublemover.github.io/Slopjective-C/
- Draft overview section: Introduction
- Current implementation / module-boundary status: Module Metadata and ABI Surface
- Compiler implementation:
native/objc3c/ - Detailed spec source:
spec/
If you only want the high-level picture, read the published site first. If you want the exact language rules, use the files under spec/. If you want the implementation, start in native/objc3c/.
spec/- the detailed draft specification
- language parts, ABI notes, compatibility rules, conformance material, and planning packets
native/objc3c/- the native compiler, runtime-facing lowering, and toolchain integration work
site/- the generated public overview page
scripts/- build, validation, and documentation tooling
tests/- tooling, conformance, and runtime-oriented test coverage
This repository is currently easiest to use on Windows with PowerShell 7.
Minimum practical setup:
- PowerShell 7 (
pwsh) - Node.js and
npm - Python 3 with
pip - LLVM installed either at
C:\Program Files\LLVMor pointed to byLLVM_ROOT
What the native build script actually expects from LLVM:
clang++.exellvm-lib.exelibclang.liborclang.lib- LLVM headers under
include/
What the fuller native compile-and-run path also expects:
llc.exe
Useful optional LLVM tools for inspection and debugging:
llvm-readobj.exellvm-objdump.exe
Python packages:
- there is no repo-wide
requirements.txtat the moment - for normal local validation, install at least:
pytestjsonschema
Notes:
npmscripts in this repo run through PowerShell 7 because.npmrcsetsscript-shell=pwsh.- If LLVM is not installed in
C:\Program Files\LLVM, setLLVM_ROOTbefore building. - The build script does not install LLVM for you.
From a fresh clone on this machine:
git clone https://github.com/doublemover/Slopjective-C.git
cd .\Slopjective-C
npm ci
python -m pip install --upgrade pytest jsonschemaIf LLVM is installed somewhere other than C:\Program Files\LLVM, set:
$env:LLVM_ROOT = 'D:\path\to\LLVM'Build the native compiler and runtime archive:
npm run build:objc3c-nativeExpected artifacts:
artifacts/bin/objc3c-native.exeartifacts/bin/objc3c-frontend-c-api-runner.exeartifacts/lib/objc3_runtime.lib
Current truthful state:
npm run build:objc3c-nativeis now a PowerShell wrapper over a persistent CMake/Ninja build tree undertmp/build-objc3c-native.- That command reuses the configured build tree across invocations, publishes
the native binaries and runtime archive into
artifacts/, and then regenerates the current frontend packet family.
Frozen future command surface (M276-A001):
npm run build:objc3c-native- eventual fast local binary-build default after parity proof lands
npm run build:objc3c-native:contracts- reserved contracts and packet-generation path
npm run build:objc3c-native:full- reserved full-build path for closeout and CI
npm run build:objc3c-native:reconfigure- reserved fingerprint refresh / self-healing configure path
Planned policy boundary:
- local issue work should eventually use the fast default path
- packet generation should be callable independently where dependency shape permits it
- milestone closeout and CI should retain a truthful full-build path
- persistent local build trees will live under
tmp/ - published binaries and libraries will remain under
artifacts/
The command split is fully implemented now.
Parity freeze (M276-A002):
- the current PowerShell build and the current
CMakeLists.txtalready cover the same in-tree native source set - the remaining parity gaps are tool discovery,
libclanglinkage, compile-definition shape, compile-database policy, and finalartifacts/publication behavior - the frozen compile-database target path is
tmp/build-objc3c-native/compile_commands.json - the authoritative toolchain root remains
LLVM_ROOT, with the wrapper responsible for carrying that into any future configure step
M276-C001 is now the first landed implementation step after that parity freeze:
- native binary builds route through CMake/Ninja
tmp/build-objc3c-native/compile_commands.jsonis emitted on configure- warm invocations reuse the persistent build tree
- canonical binaries still publish to
artifacts/binandartifacts/lib
M276-C003 now decomposes the generated frontend packet family by dependency
shape inside that wrapper:
source-derivedfrontend_modular_scaffold.json
binary-derivedfrontend_invocation_lock.jsonfrontend_core_feature_expansion.json
closeout-derivedfrontend_edge_compat.jsonfrontend_edge_robustness.jsonfrontend_diagnostics_hardening.jsonfrontend_recovery_determinism_hardening.jsonfrontend_conformance_matrix.jsonfrontend_conformance_corpus.jsonfrontend_integration_closeout.json
Current truthful boundary after M276-C002:
npm run build:objc3c-native- fast public binary-build path
- uses
binaries-only
npm run build:objc3c-native:contracts- public source-derived plus binary-derived packet path
- uses
packets-binary
npm run build:objc3c-native:full- public full binary-plus-packet path
- uses
full
npm run build:objc3c-native:reconfigure- public forced-configure binary-build path
- uses
binaries-onlyplus-ForceReconfigure
M276-D002 now adds the shared native build helper:
scripts/ensure_objc3c_native_build.py--mode fast--mode contracts--mode full--force-reconfigure
- active readiness runners can now ask for a usable native build without hard-coding raw npm build semantics
- forced reconfigure now routes through the wrapper without deleting the persistent build tree
M276-D001 now migrates the active M262/M263 issue-work range onto the
shared helper.
- active lane
AthroughDreadiness runners now acquire binaries with:python scripts/ensure_objc3c_native_build.py --mode fast
- those runners now emit deterministic helper summaries under:
tmp/reports/<milestone>/<issue>/ensure_objc3c_native_build_summary.json
- lane
Eaggregators remain orchestration layers over the migrated lane runners instead of reacquiring native builds themselves - the truthful boundary after
M276-D001is:- fast helper mode for active issue work
- full builds reserved for closeout, CI, and deliberately cross-cutting proof paths
M276-D003 preserves compatibility for older raw-build callers during the
transition.
- historical raw-build callers remain supported through the public default build
command:
npm run build:objc3c-native
- that compatibility path is truthful but narrow:
- canonical native binaries are refreshed at
artifacts/ - packet generation is not implied
- downstream historical checkers remain responsible for their own proof work
- canonical native binaries are refreshed at
- representative coexistence proof now uses:
- active helper runner:
scripts/run_m262_a001_lane_a_readiness.py - historical raw-build runner:
scripts/run_m257_a001_lane_a_readiness.py
- active helper runner:
| Command | Use when | Result |
|---|---|---|
npm run build:objc3c-native |
ordinary local native compiler work | refreshes native binaries through the persistent CMake/Ninja tree |
npm run build:objc3c-native:contracts |
packet/checker work that needs the public contract packet surface | refreshes the source-derived plus binary-derived packet surface |
npm run build:objc3c-native:full |
milestone closeout or deliberately broad validation | refreshes native binaries and the full packet family |
npm run build:objc3c-native:reconfigure |
toolchain drift, path drift, or stale fingerprint mismatch | forces a fresh configure against tmp/build-objc3c-native, then rebuilds binaries |
Build-tree facts:
- persistent build tree:
tmp/build-objc3c-native
- compile database:
tmp/build-objc3c-native/compile_commands.json
- fingerprint:
tmp/build-objc3c-native/native_build_backend_fingerprint.json
Fingerprint inputs:
generatorcmakeninjaclangxxllvm_rootllvm_include_dirlibclangbuild_dirsource_dirruntime_output_dirlibrary_output_dir- direct-object-emission and warning-parity flags
Supported stale-tree recovery:
- use
npm run build:objc3c-native:reconfigure - do not delete the build tree
CI and closeout semantics:
- local issue work benefits from the persistent tree under
tmp/build-objc3c-native - CI runners start from clean workspaces, so
fast,contracts, andfulldescribe proof scope rather than cache expectations - the active Windows core workflow proves
build:objc3c-nativeplusbuild:objc3c-native:contracts - the manual compiler closeout workflow proves
build:objc3c-native:full - milestone closeout evidence for this build-surface tranche lives under
tmp/reports/m276/M276-E002/
Build the public site overview:
python scripts/build_site_index.pyCheck that the generated site is up to date:
python scripts/build_site_index.py --checkBuild the native compiler:
npm run build:objc3c-nativeCompile the basic native hello-world fixture:
npm run compile:objc3c -- tests/tooling/fixtures/native/hello.objc3 --out-dir tmp/artifacts/compilation/objc3c-native/readme-hello --emit-prefix moduleRun the native execution smoke suite:
$env:OBJC3C_NATIVE_EXECUTION_LLC_PATH = 'C:\Program Files\LLVM\bin\llc.exe'
pwsh -NoProfile -ExecutionPolicy Bypass -File .\scripts\check_objc3c_native_execution_smoke.ps1If llc.exe is already on PATH, you can omit OBJC3C_NATIVE_EXECUTION_LLC_PATH.
Rebuild the generated site output with the standard package script:
npm run build:specThe spec is organized as a small set of cross-cutting reference documents plus the numbered language parts.
Start here:
- Spec root
- Table of contents
- Introduction
- Syntax catalog
- Lowering and runtime contracts
- Module metadata and ABI tables
- Conformance profile checklist
Language parts:
| Part | Focus |
|---|---|
| Part 0 | Baseline rules, terminology, and normative references |
| Part 1 | Versioning, compatibility, and conformance claims |
| Part 2 | Modules, namespacing, and public API surfaces |
| Part 3 | Types, nullability, optionals, generics, and key paths |
| Part 4 | Ownership, retainable objects, and lifetime rules |
| Part 5 | Control flow, safety constructs, and execution behavior |
| Part 6 | Errors, Result, and throws |
| Part 7 | Async/await, actors, and concurrency rules |
| Part 8 | System programming extensions and low-level features |
| Part 9 | Performance controls and runtime dynamism boundaries |
| Part 10 | Metaprogramming, derives, macros, and property behaviors |
| Part 11 | Interoperability with C, C++, and Swift-facing surfaces |
| Part 12 | Diagnostics, tooling, and conformance testing |
No repository-wide license file is currently present. Add one before treating this as a redistributable public package.