Skip to content

Latest commit

 

History

History
1800 lines (1530 loc) · 69.3 KB

File metadata and controls

1800 lines (1530 loc) · 69.3 KB
title Semantic IR Reference
audience advanced users, developers
prerequisites parser references, native datatype model
related index.md
status maintained
publication draft

Semantic IR Reference

Datatype Mapping

Semantic Names

Semantic dtype NumPy equivalent Notes
Bool numpy.bool_ Boolean scalar.
Int8, Int16, Int32, Int64 numpy.int8, numpy.int16, numpy.int32, numpy.int64 Signed integers.
UInt8, UInt16, UInt32, UInt64 numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64 Unsigned integers.
Float32, Float64 numpy.float32, numpy.float64 Binary floating-point scalars.
Float128 numpy.longdouble Platform precision varies; numpy.float128 is not portable.
Complex64, Complex128 numpy.complex64, numpy.complex128 Complex scalars.
Complex256 numpy.clongdouble Platform precision varies.
String numpy.str_ or byte storage at ABI boundary Character policy depends on wrapper ABI.
SizeT numpy.uintp Target width is compiler-probed when available.
Any object Used for void pointer pointees and intentionally opaque values.

Fortran Intrinsics

Fortran spelling or kind Semantic dtype NumPy equivalent
Unqualified integer, real, complex Compiler-probed default storage Matching NumPy numeric dtype
Numeric kinds such as kind=4/8/16 and kind(...) expressions Compiler-probed kind storage Matching NumPy numeric dtype
integer(int8/int16/int32/int64) Int8 / Int16 / Int32 / Int64 Matching NumPy signed integer
real(real32/real64/real128) Float32 / Float64 / Float128 Matching NumPy real dtype
complex(real32/real64/real128) Complex64 / Complex128 / Complex256 Matching NumPy complex dtype
double precision, double complex Compiler-probed double-kind storage Matching NumPy real or complex dtype
Legacy numeric type*N, such as integer*8, real*8, complex*16, logical*1 Fixed N-byte total storage Matching NumPy dtype
Legacy character*N, character*(*) String; N/* is length, not kind numpy.str_ or ABI byte storage
procedure(...) Procedure Callback/interface policy

Compiler-backed Fortran semantic CLI stages measure the storage of every intrinsic type used by the source after resolving kind expressions. This is required because default and numeric kind mappings are processor-dependent and flags such as -fdefault-real-8 can change them. Results are cached by exact compiler identity, target flags, expressions, environment, and runner. Legacy numeric type*N extensions carry fixed total storage and therefore do not need a compiler probe. In particular, complex*8 is an 8-byte Complex64, while modern complex(kind=8) is a compiler kind that is Complex128 on the documented gfortran target. DOUBLE PRECISION and DOUBLE COMPLEX remain compiler-dependent and use the cached probe. Direct converter calls without compiler facts retain the current GitHub Actions gfortran profile as a fallback. Explicit iso_fortran_env kinds are preferred when a portable source contract needs a fixed precision.

Generated Linux x86_64 Mapping Example

The following mapping snapshots are generated from the same compiler-backed code paths used by prik. They target the linux-x86_64 profile used by GitHub Actions. The executable documentation test reruns the commands and compares their complete output, so a compiler fact or semantic mapping change must update these examples.

Semantic .pyi Contract Surface

Semantic .pyi is a Python-valid serialization and editing surface for semantic IR, not a second semantic model. The syntax, metadata names, projection notation, diagnostics, generated coverage, and editing workflow are owned by Semantic .pyi format.

This IR reference keeps only the relationship between that surface and the underlying semantic model:

  • source frontends populate SemanticModule, SemanticFunction, SemanticArgument, SemanticVariable, SemanticClass, and related storage contracts;
  • .pyi printing exposes the public wrapper contract plus the native-call metadata required to reconstruct the same semantic IR;
  • .pyi loading converts the documented contract subset back to semantic IR without reparsing native source; and
  • policy completion and lowering consume semantic IR, not raw .pyi syntax.

The shared semantic model separates value type, storage and calling contract, public array contract, ownership and transfer policy, and source-origin metadata. The .pyi surface exposes only the facts that are part of the public wrapper contract or required to reconstruct native-call topology. Native source-provenance details not emitted into the public contract are intentionally excluded from public contract equality.

Post-IR policy completion turns those facts into two explicit barrier actions before lowering:

  • the Python barrier action, which tells Python binding generation how to extract or validate the Python object; and
  • the native barrier action, which tells bridge generation how to hand the extracted value to native code.

The Python barrier distinguishes Python scalar values, rank-0 NumPy scalar storage, NumPy array storage, Python strings, raw address values, and generated wrapper instances. The native barrier distinguishes direct values, call-local addresses, caller/Python-backed storage addresses, raw addresses, packed array descriptors, and wrapper-owned native addresses. These decisions are semantic policy. Wrapper planning, binding/bridge lowering, and printers may create backend-local temporaries, but they must not infer or override a barrier action from datatype, source-declaration direction, array category, aliasing, or memory-storage checks.

Parser-model conversion and semantic/wrapper-model traversal use the shared prik.utilities.visitor.ClassVisitor dispatcher and one configured <prefix>_<ClassName> protocol. The default prefix is _visit; specialized visitors may choose clearer names such as _print or _parse while still using the same MRO dispatcher. Barrier/action dispatch tables are allowed only for completed policy actions; the primitive ABI map is the other deliberate table because it maps datatype classes to semantic dtypes rather than traversing model nodes. These tables are separate from model-node dispatch.

Round Trips And Provenance

prik.parsers.pyi parses the documented semantic .pyi subset into Python AST. convert_pyi_to_ir converts that AST into the same public storage contracts emitted by the source semantic pipelines; pyi_file_to_semantic_module combines file parsing and conversion. Focused round-trip tests cover:

Fortran parser model -> semantic IR -> .pyi -> semantic IR

Generated and edited stubs must not use hidden native-source parsing as a fallback. If the .pyi contract omits native facts required for policy completion or lowering, prik reports a contract or wrapper-planning error instead of guessing.

External Type References

External source-language types are modeled in semantic IR by owner-module type identity. Stub printing may emit owner-module dependency stubs, and pyi_paths_to_semantic_modules reconciles those imports back into semantic external_type_ref metadata. The concrete file syntax for those owner stubs is documented in Semantic .pyi format.