Skip to content

feat: Improve support for function call #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ jobs:
pr_sha: ${{ github.event.pull_request.head.sha }}

tests:
needs: check-branch
timeout-minutes: 10
strategy:
matrix:
Expand Down
1 change: 1 addition & 0 deletions conda/dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ dependencies:
# fix issues with distlib
- paginate
- pyrepl
- msgpack-python
1 change: 1 addition & 0 deletions conda/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ dependencies:
# fix issues with distlib
- paginate
- pyrepl
- msgpack-python
135 changes: 131 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ include = ["src/irx/py.typed"]
[tool.poetry.dependencies]
python = ">=3.8.1,<4"
atpublic = ">=4.0"
astx = "0.12.2"
astx = "0.15.0"
typing-extensions = { version = "^4", python = "<3.9" }
llvmlite = ">=0.41.1"
plum-dispatch = ">=2.2.2"
Expand Down
101 changes: 98 additions & 3 deletions src/irx/builders/llvmliteir.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def create_entry_block_alloca(
@dispatch.abstract
def visit(self, expr: astx.AST) -> None:
"""Translate an ASTx expression."""
raise Exception("Not implemented yet.")
raise Exception("astx.AST doesn't have a direct translation.")

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.BinaryOp) -> None:
Expand Down Expand Up @@ -272,12 +272,13 @@ def visit(self, expr: astx.BinaryOp) -> None:
elif expr.op_code == "<":
# note: it should be according the datatype,
# e.g. for float it should be fcmp
cmp_result = self._llvm.ir_builder.cmp_unordered(
cmp_result = self._llvm.ir_builder.icmp_signed(
"<", llvm_lhs, llvm_rhs, "lttmp"
)
result = self._llvm.ir_builder.uitofp(
result = self._llvm.ir_builder.zext(
cmp_result, self._llvm.INT32_TYPE, "booltmp"
)

self.result_stack.append(result)
return
elif expr.op_code == ">":
Expand Down Expand Up @@ -592,6 +593,73 @@ def visit(self, expr: astx.ForRangeLoop) -> None:
result = ir.Constant(self._llvm.INT32_TYPE, 0)
self.result_stack.append(result)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.While) -> None:
"""Translate ASTx While Loop to LLVM-IR."""
# Create blocks for the condition check, the loop body,
# and the block after the loop.
cond_bb = self._llvm.ir_builder.function.append_basic_block(
"whilecond"
)
body_bb = self._llvm.ir_builder.function.append_basic_block(
"whilebody"
)
after_bb = self._llvm.ir_builder.function.append_basic_block(
"afterwhile"
)

# Branch to the condition check block.
self._llvm.ir_builder.branch(cond_bb)

# Start inserting into the condition check block.
self._llvm.ir_builder.position_at_start(cond_bb)

# Emit the condition.
self.visit(expr.condition)
cond_val = self.result_stack.pop()
if not cond_val:
raise Exception("codegen: Invalid condition expression.")

# Convert condition to a bool by comparing non-equal to 0.
if isinstance(cond_val.type, (ir.FloatType, ir.DoubleType)):
cmp_instruction = self._llvm.ir_builder.fcmp_ordered
zero_val = ir.Constant(cond_val.type, 0.0)
else:
cmp_instruction = self._llvm.ir_builder.icmp_signed
zero_val = ir.Constant(cond_val.type, 0)

cond_val = cmp_instruction(
"!=",
cond_val,
zero_val,
"whilecond",
)

# Conditional branch based on the condition.
self._llvm.ir_builder.cbranch(cond_val, body_bb, after_bb)

# Start inserting into the loop body block.
self._llvm.ir_builder.position_at_start(body_bb)

# Emit the body of the loop. This, like any other expr, can change
# the current basic_block. Note that we ignore the value computed by
# the body, but don't allow an error.
self.visit(expr.body)
body_val = self.result_stack.pop()

if not body_val:
return

# Branch back to the condition check.
self._llvm.ir_builder.branch(cond_bb)

# Start inserting into the block after the loop.
self._llvm.ir_builder.position_at_start(after_bb)

# While loop always returns 0.
result = ir.Constant(self._llvm.INT32_TYPE, 0)
self.result_stack.append(result)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.Module) -> None:
"""Translate ASTx Module to LLVM-IR."""
Expand Down Expand Up @@ -718,6 +786,33 @@ def visit(self, expr: astx.Variable) -> None:
result = self._llvm.ir_builder.load(expr_var, expr.name)
self.result_stack.append(result)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.VariableAssignment) -> None:
"""Translate variable assignment expression."""
# Get the name of the variable to assign to
var_name = expr.name

# Codegen the value expression on the right-hand side
self.visit(expr.value)
llvm_value = safe_pop(self.result_stack)

if not llvm_value:
raise Exception("codegen: Invalid value in VariableAssignment.")

# Look up the variable in the named values
llvm_var = self.named_values.get(var_name)

if not llvm_var:
raise Exception(
f"Variable '{var_name}' not found in the named values."
)

# Store the value in the variable
self._llvm.ir_builder.store(llvm_value, llvm_var)

# Optionally, you can push the result onto the result stack if needed
self.result_stack.append(llvm_value)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.VariableDeclaration) -> None:
"""Translate ASTx Variable to LLVM-IR."""
Expand Down
1 change: 1 addition & 0 deletions tests/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests with real examples."""
Loading
Loading