Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
36f449e
start work on adding new instructions
junikimm717 Nov 11, 2025
97b27a1
somewhat finish work on numba instructions
junikimm717 Nov 18, 2025
9f58e83
set up c buffer stuff
junikimm717 Nov 18, 2025
c276826
Merge branch 'main' into junikimm717/hashtable
junikimm717 Nov 18, 2025
c857b3f
at least things work a little
junikimm717 Nov 25, 2025
e48b278
some more errors fixed?
junikimm717 Nov 25, 2025
da93ec6
more fixes
junikimm717 Nov 25, 2025
a87c2f4
store tests actually work
junikimm717 Nov 25, 2025
d755f8a
trying to fix up numba
junikimm717 Nov 26, 2025
594600c
immutable tuples
junikimm717 Nov 27, 2025
072f6c9
ruff reasons
junikimm717 Nov 27, 2025
cdae8bb
Merge branch 'junikimm717/immutabletuple' into junikimm717/hashtable
junikimm717 Nov 27, 2025
2c443f6
load instruction completed
junikimm717 Nov 27, 2025
55dea61
c.py invocation and serialization errors fixed
junikimm717 Nov 27, 2025
7f8c2b0
need to work through numba stuff
junikimm717 Nov 27, 2025
4113469
c.py invocation and serialization errors fixed
junikimm717 Nov 27, 2025
7f1431e
ruff format
junikimm717 Nov 27, 2025
21f2815
numpy serialization also fixed
junikimm717 Nov 27, 2025
eb33bb2
Merge branch 'junikimm717/immutabletuple' into junikimm717/hashtable
junikimm717 Nov 27, 2025
23d4703
format and mypy errors
junikimm717 Nov 27, 2025
57e86b6
numba and assembly bugs fixed too
junikimm717 Nov 28, 2025
65040f2
generate tuplify and re-conversion code for numba
junikimm717 Nov 28, 2025
9fe02ef
All interface types fixed!!!
junikimm717 Nov 28, 2025
f2f09ac
docs update
junikimm717 Nov 28, 2025
94cd39a
tried some type fixing
junikimm717 Nov 29, 2025
570bad1
type checker tests too
junikimm717 Nov 30, 2025
f22c59b
node fix
junikimm717 Nov 30, 2025
ef84d94
turn all map -> dict
junikimm717 Dec 1, 2025
8cd031e
introduce immutable and mutable structs
junikimm717 Dec 2, 2025
1abae19
Remove `numba.typed` import
mtsokol Dec 2, 2025
3065ed0
remove STC
junikimm717 Dec 2, 2025
def082a
turn STC into a submodule
junikimm717 Dec 2, 2025
6efc28a
recursive submodules for checkout
junikimm717 Dec 2, 2025
7f70069
recursive submodules on the publish file too
junikimm717 Dec 2, 2025
69d89e1
simplify numpy serialization
junikimm717 Dec 2, 2025
27193c0
allow the c hashtable to accept arbitrary assembly structs as POD
junikimm717 Dec 2, 2025
ed10c5c
add additional test for c hash table definitions
junikimm717 Dec 2, 2025
8755bdf
Merge branch 'junikimm717/immutabletuple' into junikimm717/hashtable
junikimm717 Dec 2, 2025
e5653ec
fix the type checker test
junikimm717 Dec 2, 2025
e608efd
test floats valid
junikimm717 Dec 2, 2025
08caa87
mypy?
junikimm717 Dec 2, 2025
ec01d7d
ruff
junikimm717 Dec 3, 2025
21cc994
I can't believe I'm debugging in prod
junikimm717 Dec 3, 2025
37fe6cf
try to emit standard output
junikimm717 Dec 3, 2025
7a0878c
try clearing all macros
junikimm717 Dec 3, 2025
88732b4
we will try putting the int only struct first
junikimm717 Dec 3, 2025
a508a3c
try setidx_3
junikimm717 Dec 3, 2025
3df995d
just stick to homogeneous tuples for now
junikimm717 Dec 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
Expand All @@ -36,7 +38,7 @@ jobs:
poetry install --extras test
- name: Run tests
run: |
poetry run pytest --junit-xml=test-${{ matrix.os }}-Python-${{ matrix.python }}.xml
poetry run pytest -s --junit-xml=test-${{ matrix.os }}-Python-${{ matrix.python }}.xml
- uses: codecov/codecov-action@v5

on:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v2
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "src/finchlite/codegen/stc"]
path = src/finchlite/codegen/stc
url = https://github.com/stclib/stc
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ section-order = [

[tool.mypy]
ignore_missing_imports = true
exclude = ["tests/reference"]
exclude = ["tests/reference", "src/finchlite/codegen/stc"]
123 changes: 103 additions & 20 deletions src/finchlite/codegen/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import tempfile
from abc import ABC, abstractmethod
from collections import namedtuple
from collections.abc import Callable, Hashable
from functools import lru_cache
from pathlib import Path
from types import NoneType
Expand All @@ -15,7 +16,14 @@

from .. import finch_assembly as asm
from ..algebra import query_property, register_property
from ..finch_assembly import AssemblyStructFType, BufferFType, TupleFType
from ..finch_assembly import (
AssemblyStructFType,
BufferFType,
DictFType,
ImmutableStructFType,
MutableStructFType,
TupleFType,
)
from ..symbolic import Context, Namespace, ScopedDict, fisinstance, ftype
from ..util import config
from ..util.cache import file_cache
Expand Down Expand Up @@ -140,7 +148,7 @@ def construct_from_c(fmt, c_obj):
return fmt.construct_from_c(c_obj)
try:
return query_property(fmt, "construct_from_c", "__attr__", c_obj)
except NotImplementedError:
except AttributeError:
return fmt(c_obj)


Expand Down Expand Up @@ -204,12 +212,14 @@ def construct_from_c(fmt, c_obj):
register_property(t, "construct_from_c", "__attr__", lambda fmt, c_value: c_value)
register_property(t, "numba_type", "__attr__", lambda t: t)


register_property(
np.generic,
"serialize_to_c",
"__attr__",
lambda fmt, obj: np.ctypeslib.as_ctypes(obj),
lambda fmt, obj: np.ctypeslib.as_ctypes(np.array(obj)),
)

# pass by value -> no op
register_property(
np.generic,
Expand Down Expand Up @@ -254,11 +264,9 @@ def __call__(self, *args):
self.argtypes, args, serial_args, strict=False
):
deserialize_from_c(type_, arg, serial_arg)
if hasattr(self.ret_type, "construct_from_c"):
return construct_from_c(res.ftype, res)
if self.ret_type is type(None):
return None
return self.ret_type(res)
return construct_from_c(self.ret_type, res)


class CModule:
Expand Down Expand Up @@ -315,7 +323,6 @@ def __call__(self, prgm):
for func in prgm.funcs:
match func:
case asm.Function(asm.Variable(func_name, return_t), args, _):
return_t = c_type(return_t)
arg_ts = [arg.result_format for arg in args]
kern = CKernel(getattr(lib, func_name), return_t, arg_ts)
kernels[func_name] = kern
Expand Down Expand Up @@ -569,6 +576,9 @@ def __call__(self, prgm: asm.AssemblyNode):
class CContext(Context):
"""
A class to represent a C environment.

The context has functionality to track which datastructure definitions need
to get declared via the stc library.
"""

def __init__(
Expand Down Expand Up @@ -597,12 +607,24 @@ def __init__(
self.fptr = fptr
self.types = types
self.slots = slots
self.datastructures: dict[Hashable, Any] = {}

def add_header(self, header):
if header not in self._headerset:
self.headers.append(header)
self._headerset.add(header)

def add_datastructure(self, key: Hashable, handler: "Callable[[CContext], Any]"):
"""
Code to add a datastructure declaration.
This is the minimum required to prevent redundancy.
"""
if key in self.datastructures:
return
# at least mark something is there.
self.datastructures[key] = None
handler(self)

def emit_global(self):
"""
Emit the headers for the C code.
Expand Down Expand Up @@ -792,6 +814,15 @@ def __call__(self, prgm: asm.AssemblyNode):
case asm.Length(buf):
buf = self.resolve(buf)
return buf.result_format.c_length(self, buf)
case asm.LoadDict(map, idx):
map = self.resolve(map)
return map.result_format.c_loaddict(self, map, idx)
case asm.ExistsDict(map, idx):
map = self.resolve(map)
return map.result_format.c_existsdict(self, map, idx)
case asm.StoreDict(map, idx, val):
map = self.resolve(map)
return map.result_format.c_storedict(self, map, idx, val)
case asm.Block(bodies):
ctx_2 = self.block()
for body in bodies:
Expand Down Expand Up @@ -936,6 +967,34 @@ def construct_from_c(self, res):
"""


class CDictFType(DictFType, CArgumentFType, ABC):
"""
Abstract base class for the ftype of dictionaries. The ftype defines how
the data in a Map is organized and accessed.
"""

@abstractmethod
def c_existsdict(self, ctx, map, idx):
"""
Return C code which checks whether a given key exists in a map.
"""
...

@abstractmethod
def c_loaddict(self, ctx, map, idx):
"""
Return C code which gets a value corresponding to a certain key.
"""
...

@abstractmethod
def c_storedict(self, ctx, buffer, idx, value):
"""
Return C code which stores a certain value given a certain integer tuple key.
"""
...


class CBufferFType(BufferFType, CArgumentFType, ABC):
"""
Abstract base class for the ftype of datastructures. The ftype defines how
Expand Down Expand Up @@ -1035,36 +1094,55 @@ def struct_c_type(fmt: AssemblyStructFType):
return new_struct


"""
Note: When serializing any struct to C, it will get serialized to a struct with
no indirection.

When you pass a struct into a kernel that expects a struct pointer, ctypes can
intelligently infer whether we are working with a pointer arg type (pass by
reference) or a non-pointer type (in which case it will immediately apply
indirection)
"""

register_property(
AssemblyStructFType,
MutableStructFType,
"c_type",
"__attr__",
lambda fmt: ctypes.POINTER(struct_c_type(fmt)),
)

register_property(
ImmutableStructFType, "c_type", "__attr__", lambda fmt: struct_c_type(fmt)
)

def struct_c_getattr(fmt: AssemblyStructFType, ctx, obj, attr):
return f"{obj}->{attr}"

register_property(
MutableStructFType,
"c_getattr",
"__attr__",
lambda fmt, ctx, obj, attr: f"{obj}->{attr}",
)

register_property(
AssemblyStructFType,
ImmutableStructFType,
"c_getattr",
"__attr__",
struct_c_getattr,
lambda fmt, ctx, obj, attr: f"{obj}.{attr}",
)


def struct_c_setattr(fmt: AssemblyStructFType, ctx, obj, attr, val):
def struct_mutable_setattr(fmt: AssemblyStructFType, ctx, obj, attr, val):
ctx.emit(f"{ctx.feed}{obj}->{attr} = {val};")
return


# the equivalent for immutable is f"{ctx.feed}{obj}.{attr} = {val};"
# but we will not include that because it's bad.

register_property(
AssemblyStructFType,
MutableStructFType,
"c_setattr",
"__attr__",
struct_c_setattr,
struct_mutable_setattr,
)


Expand Down Expand Up @@ -1092,18 +1170,23 @@ def serialize_tuple_to_c(fmt, obj):
"__attr__",
serialize_tuple_to_c,
)


def tuple_construct_from_c(fmt: TupleFType, c_struct):
args = [getattr(c_struct, name) for name in fmt.struct_fieldnames]
return tuple(args)


register_property(
TupleFType,
"construct_from_c",
"__attr__",
lambda fmt, obj, c_tuple: tuple(c_tuple),
tuple_construct_from_c,
)

register_property(
TupleFType,
"c_type",
"__attr__",
lambda fmt: ctypes.POINTER(
struct_c_type(asm.NamedTupleFType("CTuple", fmt.struct_fields))
),
lambda fmt: struct_c_type(asm.NamedTupleFType("CTuple", fmt.struct_fields)),
)
Loading