mirror of
https://github.com/Z3Prover/z3
synced 2026-07-12 01:56:22 +00:00
Merge remote-tracking branch 'origin/master' into c3
This commit is contained in:
commit
706f62286e
199 changed files with 11004 additions and 4584 deletions
34
.github/agents/agentic-workflows.md
vendored
34
.github/agents/agentic-workflows.md
vendored
|
|
@ -35,7 +35,7 @@ Workflows may optionally include:
|
|||
- Workflow files: `.github/workflows/*.md` and `.github/workflows/**/*.md`
|
||||
- Workflow lock files: `.github/workflows/*.lock.yml`
|
||||
- Shared components: `.github/workflows/shared/*.md`
|
||||
- Configuration: `.github/aw/github-agentic-workflows.md`
|
||||
- Configuration: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/github-agentic-workflows.md`
|
||||
|
||||
## Problems This Solves
|
||||
|
||||
|
|
@ -54,10 +54,12 @@ When you interact with this agent, it will:
|
|||
|
||||
## Available Prompts
|
||||
|
||||
> **Note**: The prompt and reference files listed below are located in the [`github/gh-aw`](https://github.com/github/gh-aw) repository and are **not available locally** in this repository. Load them from their public URLs.
|
||||
|
||||
### Create New Workflow
|
||||
**Load when**: User wants to create a new workflow from scratch, add automation, or design a workflow that doesn't exist yet
|
||||
|
||||
**Prompt file**: `.github/aw/create-agentic-workflow.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/create-agentic-workflow.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Create a workflow that triages issues"
|
||||
|
|
@ -67,7 +69,7 @@ When you interact with this agent, it will:
|
|||
### Update Existing Workflow
|
||||
**Load when**: User wants to modify, improve, or refactor an existing workflow
|
||||
|
||||
**Prompt file**: `.github/aw/update-agentic-workflow.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/update-agentic-workflow.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Add web-fetch tool to the issue-classifier workflow"
|
||||
|
|
@ -77,7 +79,7 @@ When you interact with this agent, it will:
|
|||
### Debug Workflow
|
||||
**Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors
|
||||
|
||||
**Prompt file**: `.github/aw/debug-agentic-workflow.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/debug-agentic-workflow.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Why is this workflow failing?"
|
||||
|
|
@ -87,7 +89,7 @@ When you interact with this agent, it will:
|
|||
### Upgrade Agentic Workflows
|
||||
**Load when**: User wants to upgrade workflows to a new gh-aw version or fix deprecations
|
||||
|
||||
**Prompt file**: `.github/aw/upgrade-agentic-workflows.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/upgrade-agentic-workflows.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Upgrade all workflows to the latest version"
|
||||
|
|
@ -97,7 +99,7 @@ When you interact with this agent, it will:
|
|||
### Create a Report-Generating Workflow
|
||||
**Load when**: The workflow being created or updated produces reports — recurring status updates, audit summaries, analyses, or any structured output posted as a GitHub issue, discussion, or comment
|
||||
|
||||
**Prompt file**: `.github/aw/report.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/report.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Create a weekly CI health report"
|
||||
|
|
@ -107,7 +109,7 @@ When you interact with this agent, it will:
|
|||
### Create Shared Agentic Workflow
|
||||
**Load when**: User wants to create a reusable workflow component or wrap an MCP server
|
||||
|
||||
**Prompt file**: `.github/aw/create-shared-agentic-workflow.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/create-shared-agentic-workflow.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Create a shared component for Notion integration"
|
||||
|
|
@ -117,7 +119,7 @@ When you interact with this agent, it will:
|
|||
### Fix Dependabot PRs
|
||||
**Load when**: User needs to close or fix open Dependabot PRs that update dependencies in generated manifest files (`.github/workflows/package.json`, `.github/workflows/requirements.txt`, `.github/workflows/go.mod`)
|
||||
|
||||
**Prompt file**: `.github/aw/dependabot.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/dependabot.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Fix the open Dependabot PRs for npm dependencies"
|
||||
|
|
@ -127,7 +129,7 @@ When you interact with this agent, it will:
|
|||
### Analyze Test Coverage
|
||||
**Load when**: The workflow reads, analyzes, or reports test coverage — whether triggered by a PR, a schedule, or a slash command. Always consult this prompt before designing the coverage data strategy.
|
||||
|
||||
**Prompt file**: `.github/aw/test-coverage.md`
|
||||
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/test-coverage.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Create a workflow that comments coverage on PRs"
|
||||
|
|
@ -137,7 +139,7 @@ When you interact with this agent, it will:
|
|||
### CLI Commands Reference
|
||||
**Load when**: The user asks how to run, compile, debug, or manage workflows from the command line; needs the MCP tool equivalent of a `gh aw` command; or is in a restricted environment (e.g., Copilot Cloud) without direct CLI access.
|
||||
|
||||
**Reference file**: `.github/aw/cli-commands.md`
|
||||
**Reference file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/cli-commands.md`
|
||||
|
||||
**Use cases**:
|
||||
- "How do I trigger workflow X on the main branch?"
|
||||
|
|
@ -148,7 +150,7 @@ When you interact with this agent, it will:
|
|||
### Token Consumption Optimization
|
||||
**Load when**: The user asks how to reduce token usage, lower workflow costs, make a workflow faster or cheaper, or measure the impact of prompt or configuration changes.
|
||||
|
||||
**Reference file**: `.github/aw/token-optimization.md`
|
||||
**Reference file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/token-optimization.md`
|
||||
|
||||
**Use cases**:
|
||||
- "How do I reduce the token cost of this workflow?"
|
||||
|
|
@ -161,7 +163,7 @@ When you interact with this agent, it will:
|
|||
### Workflow Pattern Selection
|
||||
**Load when**: The user asks for architecture, strategy, operating model selection, or pattern recommendations for building agentic workflows.
|
||||
|
||||
**Reference file**: `.github/aw/patterns.md`
|
||||
**Reference file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/patterns.md`
|
||||
|
||||
**Use cases**:
|
||||
- "Which pattern should I use for multi-repo rollout?"
|
||||
|
|
@ -174,7 +176,7 @@ When you interact with this agent, it will:
|
|||
When a user interacts with you:
|
||||
|
||||
1. **Identify the task type** from the user's request
|
||||
2. **Load the appropriate prompt** from the repository paths listed above
|
||||
2. **Load the appropriate prompt** from the URLs listed above
|
||||
3. **Follow the loaded prompt's instructions** exactly
|
||||
4. **If uncertain**, ask clarifying questions to determine the right prompt
|
||||
|
||||
|
|
@ -213,12 +215,12 @@ gh aw compile --validate
|
|||
|
||||
## Important Notes
|
||||
|
||||
- Always reference the instructions file at `.github/aw/github-agentic-workflows.md` for complete documentation
|
||||
- Always reference the instructions file at `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/github-agentic-workflows.md` for complete documentation
|
||||
- Use the MCP tool `agentic-workflows` when running in GitHub Copilot Cloud
|
||||
- Workflows must be compiled to `.lock.yml` files before running in GitHub Actions
|
||||
- **Bash tools are enabled by default** - Don't restrict bash commands unnecessarily since workflows are sandboxed by the AWF
|
||||
- Follow security best practices: minimal permissions, explicit network access, no template injection
|
||||
- **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See `.github/aw/network.md` for the full list of valid ecosystem identifiers and domain patterns.
|
||||
- **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/network.md` for the full list of valid ecosystem identifiers and domain patterns.
|
||||
- **Single-file output**: When creating a workflow, produce exactly **one** workflow `.md` file. Do not create separate documentation files (architecture docs, runbooks, usage guides, etc.). If documentation is needed, add a brief `## Usage` section inside the workflow file itself.
|
||||
- **Triggering runs**: Always use `gh aw run <workflow-name>` to trigger a workflow on demand — not `gh workflow run <file>.lock.yml`. `gh aw run` handles workflow resolution by short name, input parsing and validation, and correct run-tracking for agentic workflows. Use `--ref <branch>` to run on a specific branch.
|
||||
- **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see `.github/aw/cli-commands.md`
|
||||
- **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/cli-commands.md`
|
||||
|
|
|
|||
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
|
|
@ -1,7 +1,8 @@
|
|||
updates:
|
||||
- directory: /
|
||||
ignore:
|
||||
- dependency-name: "github/gh-aw-actions/**" # Managed by gh aw compile. Version-locked to the gh-aw compiler; do not bump.
|
||||
- dependency-name: "github/gh-aw-actions/**"
|
||||
- dependency-name: "github/gh-aw-actions" # Managed by gh aw compile. Version-locked to the gh-aw compiler; do not bump.
|
||||
package-ecosystem: github-actions
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
|
|
|||
9
.github/mcp.json
vendored
9
.github/mcp.json
vendored
|
|
@ -1,10 +1,19 @@
|
|||
{
|
||||
"mcpServers": {
|
||||
"github-agentic-workflows": {
|
||||
"type": "local",
|
||||
"command": "gh",
|
||||
"args": [
|
||||
"aw",
|
||||
"mcp-server"
|
||||
],
|
||||
"tools": [
|
||||
"compile",
|
||||
"audit",
|
||||
"logs",
|
||||
"inspect",
|
||||
"status",
|
||||
"audit-diff"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
372
.github/skills/agentic-workflow-designer/SKILL.md
vendored
Normal file
372
.github/skills/agentic-workflow-designer/SKILL.md
vendored
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
---
|
||||
name: agentic-workflow-designer
|
||||
description: Conversational skill that interviews users to design new agentic workflows
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Workflow Designer
|
||||
|
||||
Use this skill to run a structured interview with users who know their goal but not the workflow syntax yet, then generate one complete workflow `.md` file.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this before `.github/aw/create-agentic-workflow.md` when requirements are unclear or incomplete.
|
||||
|
||||
- Use `skills/agentic-workflow-designer/SKILL.md` to discover and confirm requirements.
|
||||
- Use `.github/aw/create-agentic-workflow.md` once requirements are clear and ready for implementation.
|
||||
- Use `.github/aw/agentic-chat.md` when the user wants a specification/pseudo-code instead of a runnable workflow file.
|
||||
|
||||
## Interview Framework
|
||||
|
||||
Ask one question at a time. Move to the next phase only after the current phase is clear.
|
||||
|
||||
### Phase 1: Goal
|
||||
|
||||
Ask: **"What do you want to automate?"**
|
||||
|
||||
Capture:
|
||||
- Workflow name (kebab-case candidate)
|
||||
- Brief description
|
||||
- Optional emoji
|
||||
|
||||
### Phase 2: Trigger
|
||||
|
||||
Ask: **"When should this run?"**
|
||||
|
||||
Follow up only if needed:
|
||||
- Which event type(s)?
|
||||
- Any filters (labels, branches, commands)?
|
||||
- Scheduled cadence (daily/weekly/hourly)?
|
||||
|
||||
Map to the `on:` block.
|
||||
|
||||
### Phase 3: Scope (Read/Write)
|
||||
|
||||
Ask:
|
||||
- **"What should it read?"** (issues, PRs, code, discussions, CI data)
|
||||
- **"What should it create or update?"** (comments, issues, PRs, labels)
|
||||
|
||||
Map to:
|
||||
- `permissions:` (keep read-only for agent job)
|
||||
- `tools:`
|
||||
- `safe-outputs:`
|
||||
|
||||
### Phase 4: Data Strategy
|
||||
|
||||
Ask:
|
||||
- **"What data does the agent need to make decisions?"**
|
||||
- Follow up: **"Can we pre-fetch and aggregate that data with shell commands so the agent only reads compact JSON?"**
|
||||
|
||||
Capture:
|
||||
- Whether `steps:` should pre-fetch GitHub data with `gh` + `jq`
|
||||
- Output paths under `/tmp/gh-aw/data/`
|
||||
- Whether batch work should use sub-agents
|
||||
|
||||
Map to:
|
||||
- `steps:`
|
||||
- Prompt references to pre-computed file paths
|
||||
|
||||
### Phase 5: Guardrails
|
||||
|
||||
Ask: **"Should it block merging, just advise, or silently log?"**
|
||||
|
||||
Capture:
|
||||
- Visibility expectations (comment, issue, no visible output)
|
||||
- No-op behavior expectation
|
||||
|
||||
Guide toward safe output behavior and explicit `noop` instructions.
|
||||
|
||||
### Phase 6: Context & Network
|
||||
|
||||
Ask: **"Does it need external APIs, web access, package installs, or MCP servers?"**
|
||||
|
||||
Follow up:
|
||||
- **"Any third-party services or MCP servers to include (for example Slack, Jira, Datadog, custom internal MCP)?"**
|
||||
- **"Are you deploying on GitHub.com, GHEC with custom endpoints, or GHES?"**
|
||||
- For each integration, identify required auth from source docs and map it to GitHub Actions secrets + workflow env variables.
|
||||
- Ask for exact external domains (FQDN/wildcard).
|
||||
|
||||
Map to:
|
||||
- `network.allowed`
|
||||
- Optional MCP/GitHub tool usage in `tools:`
|
||||
- `secrets:` / `env:` wiring for integration tokens
|
||||
- GHES/GHEC settings such as `engine.api-target` and `aw.json` `ghes: true` (when applicable)
|
||||
|
||||
### Phase 7: Engine (optional)
|
||||
|
||||
Ask only if ambiguous: **"Any AI engine preference?"**
|
||||
|
||||
If no preference, suggest default:
|
||||
- "I'd suggest Copilot since you haven't mentioned a preference. Sound good?"
|
||||
|
||||
Map to `engine:` only when not default.
|
||||
|
||||
### Phase 8: Confirmation
|
||||
|
||||
Present a structured summary and ask for approval before generation.
|
||||
|
||||
## Decision Heuristics
|
||||
|
||||
### Trigger Mapping
|
||||
|
||||
| User says... | Maps to |
|
||||
|---|---|
|
||||
| "when someone opens a PR" | `on: pull_request:` with `types: [opened]` |
|
||||
| "when a PR is updated" | `on: pull_request:` with `types: [opened, synchronize]` |
|
||||
| "every morning", "daily" | fuzzy schedule shorthand `on: schedule: daily on weekdays` (compiler expands to cron) |
|
||||
| "every Monday", "weekly" | fuzzy schedule shorthand `on: schedule: weekly` (compiler expands to cron) |
|
||||
| "when I say /review" | `on: slash_command:` with `name: review` (or requested command) |
|
||||
| "when an issue is labeled bug" | `on: issues:` with `types: [labeled]` and label filter guidance |
|
||||
| "run when label ai-review is added" | `on: label_command:` with `name`/`names`, optional event scoping, and label-as-command semantics |
|
||||
| "run on PRs from forks" | `on: pull_request:` plus explicit `forks:` allowlist and fork security guardrails |
|
||||
| "sometimes automatic, sometimes manual" | semi-active pattern: combine `schedule`/event triggers with `workflow_dispatch` |
|
||||
| "manually", "on demand" | `on: workflow_dispatch:` |
|
||||
| "when a deployment fails" | `on: deployment_status:` |
|
||||
| "when another workflow finishes" | `on: workflow_run:` |
|
||||
|
||||
### Safe Output Mapping
|
||||
|
||||
| User says... | Maps to |
|
||||
|---|---|
|
||||
| "post a comment" | `add-comment` |
|
||||
| "create an issue" | `create-issue` |
|
||||
| "update issue title/body" | `update-issue` |
|
||||
| "close the issue" | `close-issue` |
|
||||
| "assign someone", "remove assignment" | `assign-to-user`, `unassign-from-user` |
|
||||
| "set issue type/field/milestone" | `set-issue-type`, `set-issue-field`, `assign-milestone` |
|
||||
| "open a PR", "submit changes" | `create-pull-request` |
|
||||
| "update PR description/title" | `update-pull-request` |
|
||||
| "close the PR", "merge the PR" | `close-pull-request`, `merge-pull-request` |
|
||||
| "mark PR ready", "sync PR branch" | `mark-pull-request-as-ready-for-review`, `update-branch` |
|
||||
| "commit a fix to the PR branch" | `push-to-pull-request-branch` |
|
||||
| "approve / request changes" | `submit-pull-request-review` |
|
||||
| "inline review comment", "reply to review thread" | `create-pull-request-review-comment`, `reply-to-pull-request-review-comment`, `resolve-pull-request-review-thread` |
|
||||
| "start or edit discussion", "close discussion" | `create-discussion`, `update-discussion`, `close-discussion` |
|
||||
| "request reviewer", "hide comment" | `add-reviewer`, `hide-comment` |
|
||||
| "create/update project", "project status update" | `create-project`, `update-project`, `create-project-status-update` |
|
||||
| "update release", "upload release asset" | `update-release`, `upload-asset` |
|
||||
| "create/auto-fix code scan alert" | `create-code-scanning-alert`, `autofix-code-scanning-alert` |
|
||||
| "start an agent session", "assign to an agent" | `create-agent-session`, `assign-to-agent` |
|
||||
| "store persistent memory comment" | `comment-memory` |
|
||||
| "link a sub-issue" | `link-sub-issue` |
|
||||
| "add labels", "remove labels" | `add-labels`, `remove-labels` |
|
||||
| "nothing visible", "just analyze" | no safe outputs required |
|
||||
|
||||
### Network Mapping
|
||||
|
||||
| User says... | Maps to |
|
||||
|---|---|
|
||||
| "calls an external API" | ask for exact FQDN/wildcard, then add to `network.allowed` |
|
||||
| "reads GitHub data / clones repos" | include `github` in `network.allowed` |
|
||||
| "uses GitHub Actions artifacts or cache" | include `github-actions` in `network.allowed` |
|
||||
| "installs npm packages" | include `node` in `network.allowed` |
|
||||
| "runs pip install" | include `python` in `network.allowed` |
|
||||
| "builds Go code" | include `go` in `network.allowed` |
|
||||
| "installs gems / uses Bundler" | include `ruby` in `network.allowed` |
|
||||
| "runs cargo build" | include `rust` in `network.allowed` |
|
||||
| "uses NuGet / .NET restore" | include `dotnet` in `network.allowed` |
|
||||
| "builds with Maven / Gradle" | include `java` in `network.allowed` |
|
||||
| "uses Docker / pulls container images / pushes to GHCR" | include `containers` in `network.allowed` |
|
||||
| "runs Playwright browser tests" | include `playwright` in `network.allowed` |
|
||||
| "runs apt install / yum / apk" | include `linux-distros` in `network.allowed` |
|
||||
| "uses Terraform / HashiCorp registry" | include `terraform` in `network.allowed` |
|
||||
| "connects to localhost / loopback / local services" | include `local` in `network.allowed` |
|
||||
| "uses Swift Package Manager" | include `swift` in `network.allowed` |
|
||||
| "uses Composer / PHP packages" | include `php` in `network.allowed` |
|
||||
| "uses pub.dev / Dart packages" | include `dart` in `network.allowed` |
|
||||
| "uses Hackage / Haskell packages" | include `haskell` in `network.allowed` |
|
||||
| "uses CPAN / Perl packages" | include `perl` in `network.allowed` |
|
||||
| "serves or loads web fonts" | include `fonts` in `network.allowed` |
|
||||
| "uses Deno or JSR packages" | include `deno` in `network.allowed` |
|
||||
| "uses Elixir / Hex packages" | include `elixir` in `network.allowed` |
|
||||
| "uses Bazel build" | include `bazel` in `network.allowed` |
|
||||
| "uses R / CRAN packages" | include `r` in `network.allowed` |
|
||||
| "no external access" | `network.allowed: [defaults]` (or `[]` if explicitly zero network) |
|
||||
|
||||
### Tool Mapping
|
||||
|
||||
| User says... | Maps to |
|
||||
|---|---|
|
||||
| "read GitHub issues/PRs/workflows" | `tools.github` with `mode: gh-proxy` and minimal `toolsets` |
|
||||
| "use full MCP server/tool definitions" | `tools.github` with `mode: local` |
|
||||
| "use other MCP servers but keep token cost down" | `tools.cli-proxy: true` (hybrid CLI-proxy mode) |
|
||||
| "edit files" | `edit` tool (default unless restricted) |
|
||||
| "run commands/tests" | `bash` tool (default unless restricted) |
|
||||
| "browse web pages/docs" | `web-fetch` and/or `web-search` |
|
||||
| "test UI flows" | `playwright` |
|
||||
|
||||
### Pattern Heuristics
|
||||
|
||||
| User says... | Recommended named pattern |
|
||||
|---|---|
|
||||
| "triage issues automatically" | `IssueOps` |
|
||||
| "run on /commands with human approval loops" | `ChatOps` |
|
||||
| "run every weekday and keep improving" | `DailyOps` |
|
||||
| "monitor workflow failures and trends" | `MonitorOps` |
|
||||
| "process a big backlog in chunks" | `BatchOps` |
|
||||
| "run manually with input parameters" | `DispatchOps` |
|
||||
| "apply a label-based workflow" | `LabelOps` |
|
||||
| "operate across multiple repositories" | `MultiRepoOps` |
|
||||
| "coordinate multiple sub-agents" | `Orchestration` |
|
||||
| "manage project board items" | `ProjectOps` |
|
||||
| "research, plan, and assign issues" | `ResearchPlanAssignOps` |
|
||||
| "self-correcting / retry on failure" | `CorrectionOps` |
|
||||
| "run in a side/fork repo" | `SideRepoOps` |
|
||||
| "write a spec before implementing" | `SpecOps` |
|
||||
| "A/B test workflow variants" | `TrialOps` |
|
||||
| "process items from a queue" | `WorkQueueOps` |
|
||||
| "deterministic, no LLM needed" | `DeterministicOps` |
|
||||
| "manage from a central repo" | `CentralRepoOps` |
|
||||
| "track work via GitHub Projects" | `Monitoring with Projects` |
|
||||
|
||||
### Integration Auth Mapping
|
||||
|
||||
When the user names a third-party service or MCP server:
|
||||
|
||||
1. Confirm whether native tool, MCP server, or safe-output job is the right integration path.
|
||||
2. Look up the integration's auth requirements and required scopes before finalizing the design.
|
||||
3. Provide a concrete setup checklist with:
|
||||
- required GitHub Actions secrets (names to create)
|
||||
- workflow env variables that consume those secrets
|
||||
- minimum token scopes/permissions needed
|
||||
|
||||
Output format to use:
|
||||
|
||||
```text
|
||||
Integration auth setup:
|
||||
- <service-or-mcp>: <purpose>
|
||||
- Secrets to create: <SECRET_NAME>, <SECRET_NAME>
|
||||
- Workflow env vars: <ENV_VAR>=${{ secrets.<SECRET_NAME> }}
|
||||
- Required scopes/permissions: <least-privilege scopes>
|
||||
```
|
||||
|
||||
Never suggest committing plaintext tokens.
|
||||
|
||||
### Data Strategy Mapping
|
||||
|
||||
| User says... | Maps to |
|
||||
|---|---|
|
||||
| "analyze PRs", "review issues", "check status" | add `steps:` that pre-fetch with `gh` + `jq` |
|
||||
| "read the diff", "look at changed files" | add `steps:` using `gh pr diff` or `gh pr view --json files` |
|
||||
| "search for patterns across repos" | add `steps:` using `gh search` + `jq` filters |
|
||||
| "just respond to a comment" | no pre-fetch needed (event payload is enough) |
|
||||
| "process each item individually" | suggest sub-agent pattern with `model: small` |
|
||||
|
||||
## Token Optimization Defaults
|
||||
|
||||
Apply these defaults unless the user explicitly asks otherwise:
|
||||
|
||||
1. Use DataOps by default for GitHub reads: pre-fetch/aggregate with `gh` + `jq` in `steps:`, store compact JSON in `/tmp/gh-aw/data/`, and point the prompt to those files (see `.github/aw/token-optimization.md` for details).
|
||||
2. Keep tool surface minimal: default to `tools.github.mode: gh-proxy`, include only required toolsets, and prefer `bash` + `gh` for simple reads.
|
||||
3. For batch workloads, split items into compact data and suggest sub-agent processing with `model: small`.
|
||||
4. Keep prompts compact: concise imperative instructions, explicit file paths, single-line `noop` guidance, and stable instructions before dynamic content.
|
||||
|
||||
## Progressive Disclosure Rules
|
||||
|
||||
1. Never dump all options at once; ask one targeted question at a time.
|
||||
2. Skip questions when answers are inferable from prior user statements.
|
||||
3. Offer smart defaults and request confirmation instead of over-questioning.
|
||||
4. Ask at most 5 questions before presenting a summary; then ask "anything else?" if needed.
|
||||
5. Detect done signals (`that's it`, `looks good`, `generate it`) and proceed to generation.
|
||||
|
||||
## Confirmation Format
|
||||
|
||||
Use this exact structure:
|
||||
|
||||
```text
|
||||
📋 Proposed workflow:
|
||||
- Name: <workflow-id>
|
||||
- Trigger: <event + key options>
|
||||
- Engine: <engine or default>
|
||||
- Tools: <tool summary>
|
||||
- Safe outputs: <list or none>
|
||||
- Network: <allowed summary>
|
||||
- Integrations/Auth: <service/mcp + required secrets/env vars>
|
||||
- Deployment: <GitHub.com or GHEC/GHES details>
|
||||
- Intent: <one-sentence task>
|
||||
```
|
||||
|
||||
Then ask: **"Ready to generate, or want to adjust anything?"**
|
||||
|
||||
## Generation Template
|
||||
|
||||
After confirmation, generate one workflow file using the same skeleton style as `.github/aw/create-agentic-workflow.md`.
|
||||
|
||||
```markdown
|
||||
---
|
||||
emoji: <emoji>
|
||||
description: <brief description>
|
||||
on:
|
||||
<trigger config>
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
tools:
|
||||
github:
|
||||
mode: gh-proxy
|
||||
toolsets: [default]
|
||||
steps:
|
||||
- name: <optional data prefetch>
|
||||
run: |
|
||||
mkdir -p /tmp/gh-aw/data
|
||||
<gh + jq commands that produce compact JSON>
|
||||
safe-outputs:
|
||||
<safe-output-types-if-needed>
|
||||
network:
|
||||
allowed:
|
||||
- defaults
|
||||
- <additional entries if needed>
|
||||
---
|
||||
|
||||
# <Workflow Name>
|
||||
|
||||
## Task
|
||||
|
||||
<clear instructions tied to trigger context>
|
||||
If `steps:` includes pre-fetch commands, read the resulting `/tmp/gh-aw/data/*.json` files instead of broad live re-fetches.
|
||||
|
||||
## Safe Outputs
|
||||
|
||||
- Use configured safe outputs for all visible write actions.
|
||||
- Call `noop` with a short reason when no action is needed.
|
||||
```
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before final output, run this internal self-check:
|
||||
|
||||
- [ ] Agent job permissions remain read-only (writes only via safe outputs)
|
||||
- [ ] `safe-outputs:` covers every write action mentioned in prompt/instructions
|
||||
- [ ] Network access is scoped; avoid blanket wildcard entries
|
||||
- [ ] Trigger matches the user's intended activation event
|
||||
- [ ] Prompt instructs agent to call `noop` when no action is needed
|
||||
- [ ] Unnecessary defaults are omitted (for example `engine: copilot`)
|
||||
- [ ] If reading GitHub data, `steps:` pre-fetches compact JSON (DataOps)
|
||||
- [ ] `tools.github.mode` is `gh-proxy` unless broader MCP toolsets are explicitly needed
|
||||
- [ ] Only required toolsets are listed (avoid blanket toolset lists)
|
||||
- [ ] Prompt references specific pre-computed file paths
|
||||
- [ ] For batch processing (>5 items), sub-agent pattern is suggested
|
||||
- [ ] For each third-party service/MCP integration, required secrets/env vars are listed
|
||||
- [ ] Auth guidance includes least-privilege token scope recommendations
|
||||
- [ ] For GHEC/GHES deployments, `engine.api-target` and GHES compatibility guidance are included when needed
|
||||
|
||||
## References (load only when needed)
|
||||
|
||||
In-repo references:
|
||||
- `.github/aw/syntax.md` (index → `.github/aw/syntax-core.md`, `.github/aw/syntax-agentic.md`, `.github/aw/syntax-tools-imports.md`)
|
||||
- `.github/aw/safe-outputs.md` (index → `.github/aw/safe-outputs-content.md`, `.github/aw/safe-outputs-management.md`, `.github/aw/safe-outputs-automation.md`, `.github/aw/safe-outputs-runtime.md`)
|
||||
- `.github/aw/network.md`
|
||||
- `.github/aw/patterns.md`
|
||||
- `.github/aw/subagents.md`
|
||||
- `.github/aw/token-optimization.md`
|
||||
- `.github/aw/triggers.md`
|
||||
- `.github/aw/create-agentic-workflow.md`
|
||||
|
||||
Portable HTTPS references:
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/syntax.md` (index → `.../syntax-core.md`, `.../syntax-agentic.md`, `.../syntax-tools-imports.md`)
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/safe-outputs.md` (index → `.../safe-outputs-content.md`, `.../safe-outputs-management.md`, `.../safe-outputs-automation.md`, `.../safe-outputs-runtime.md`)
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/network.md`
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/patterns.md`
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/triggers.md`
|
||||
- `https://github.com/github/gh-aw/blob/main/.github/aw/create-agentic-workflow.md`
|
||||
1
.github/skills/agentic-workflows/SKILL.md
vendored
1
.github/skills/agentic-workflows/SKILL.md
vendored
|
|
@ -32,6 +32,7 @@ Load these files from `github/gh-aw` (they are not available locally).
|
|||
- `.github/aw/memory.md`
|
||||
- `.github/aw/messages.md`
|
||||
- `.github/aw/network.md`
|
||||
- `.github/aw/optimize-agentic-workflow.md`
|
||||
- `.github/aw/patterns.md`
|
||||
- `.github/aw/pr-reviewer.md`
|
||||
- `.github/aw/report.md`
|
||||
|
|
|
|||
12
.github/workflows/Windows.yml
vendored
12
.github/workflows/Windows.yml
vendored
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
- run: |
|
||||
|
|
@ -37,9 +37,10 @@ jobs:
|
|||
${{ matrix.cmd1 }}
|
||||
${{ matrix.cmd2 }}
|
||||
${{ matrix.cmd3 }}
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }}
|
||||
cmake ${{ matrix.bindings }} -G "NMake Makefiles" ../
|
||||
nmake
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b 1
|
||||
cmake ${{ matrix.bindings }} -G "NMake Makefiles" ../ || exit /b 1
|
||||
nmake || exit /b 1
|
||||
cd ..
|
||||
shell: cmd
|
||||
- name: Run Regressions
|
||||
|
|
@ -52,7 +53,8 @@ jobs:
|
|||
if: ${{ matrix.test }}
|
||||
run: |
|
||||
pushd build
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }}
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b 1
|
||||
pushd build\python
|
||||
python z3test.py z3
|
||||
python z3test.py z3num
|
||||
|
|
|
|||
20
.github/workflows/a3-python.lock.yml
generated
vendored
20
.github/workflows/a3-python.lock.yml
generated
vendored
|
|
@ -31,13 +31,13 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -152,7 +152,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -377,7 +377,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -398,7 +398,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -999,7 +999,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1194,7 +1194,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1222,7 +1222,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1454,7 +1454,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
82
.github/workflows/academic-citation-tracker.lock.yml
generated
vendored
82
.github/workflows/academic-citation-tracker.lock.yml
generated
vendored
File diff suppressed because one or more lines are too long
87
.github/workflows/agentics-maintenance.yml
vendored
87
.github/workflows/agentics-maintenance.yml
vendored
|
|
@ -1,3 +1,5 @@
|
|||
# This file was automatically generated by pkg/workflow/maintenance_workflow.go (v0.80.9). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
|
||||
#
|
||||
# ___ _ _
|
||||
# / _ \ | | (_)
|
||||
# | |_| | __ _ ___ _ __ | |_ _ ___
|
||||
|
|
@ -12,7 +14,6 @@
|
|||
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
|
||||
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
|
||||
#
|
||||
# This file was automatically generated by pkg/workflow/maintenance_workflow.go (v0.79.6). DO NOT EDIT.
|
||||
#
|
||||
# To regenerate this workflow, run:
|
||||
# gh aw compile
|
||||
|
|
@ -20,15 +21,17 @@
|
|||
#
|
||||
# For more information: https://github.github.com/gh-aw/introduction/overview/
|
||||
#
|
||||
# Alternative regeneration methods:
|
||||
# make recompile
|
||||
# This file defines the generated agentic maintenance workflow for this repository.
|
||||
# It runs scheduled cleanup for expiring safe outputs and supports manual maintenance operations.
|
||||
#
|
||||
# Or use the gh-aw CLI directly:
|
||||
# ./gh-aw compile --validate --verbose
|
||||
# This workflow is generated automatically when workflows use expiring safe outputs
|
||||
# or when repository maintenance features are enabled in .github/workflows/aw.json.
|
||||
#
|
||||
# The workflow is generated when any workflow uses the 'expires' field
|
||||
# in create-discussions, create-issues, or create-pull-request safe-outputs configuration.
|
||||
# Schedule frequency is automatically determined by the shortest expiration time.
|
||||
# To disable maintenance workflow generation, set in .github/workflows/aw.json:
|
||||
# {"maintenance": false}
|
||||
#
|
||||
# Agentic maintenance docs:
|
||||
# https://github.github.com/gh-aw/reference/ephemerals/#manual-maintenance-operations
|
||||
#
|
||||
name: Agentic Maintenance
|
||||
|
||||
|
|
@ -93,7 +96,7 @@ jobs:
|
|||
pull-requests: write
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -131,7 +134,7 @@ jobs:
|
|||
actions: write
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -155,12 +158,12 @@ jobs:
|
|||
operation: ${{ steps.record.outputs.operation }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -175,9 +178,9 @@ jobs:
|
|||
await main();
|
||||
|
||||
- name: Install gh-aw
|
||||
uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup-cli@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
version: v0.79.6
|
||||
version: v0.80.9
|
||||
|
||||
- name: Run operation
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
|
|
@ -195,7 +198,9 @@ jobs:
|
|||
|
||||
- name: Record outputs
|
||||
id: record
|
||||
run: echo "operation=${{ inputs.operation }}" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_AW_OPERATION: ${{ inputs.operation }}
|
||||
run: echo "operation=$GH_AW_OPERATION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
update_pull_request_branches:
|
||||
if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'update_pull_request_branches' && (!(github.event.repository.fork)) }}
|
||||
|
|
@ -205,7 +210,7 @@ jobs:
|
|||
pull-requests: write
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -244,14 +249,14 @@ jobs:
|
|||
run_url: ${{ steps.record.outputs.run_url }}
|
||||
steps:
|
||||
- name: Checkout actions folder
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
sparse-checkout: |
|
||||
actions
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -280,7 +285,9 @@ jobs:
|
|||
|
||||
- name: Record outputs
|
||||
id: record
|
||||
run: echo "run_url=${{ inputs.run_url }}" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_AW_RUN_URL: ${{ inputs.run_url }}
|
||||
run: echo "run_url=$GH_AW_RUN_URL" >> "$GITHUB_OUTPUT"
|
||||
|
||||
create_labels:
|
||||
if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels' && (!(github.event.repository.fork)) }}
|
||||
|
|
@ -290,12 +297,12 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -310,9 +317,9 @@ jobs:
|
|||
await main();
|
||||
|
||||
- name: Install gh-aw
|
||||
uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup-cli@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
version: v0.79.6
|
||||
version: v0.80.9
|
||||
|
||||
- name: Create missing labels
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
|
|
@ -336,12 +343,12 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -356,13 +363,13 @@ jobs:
|
|||
await main();
|
||||
|
||||
- name: Install gh-aw
|
||||
uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup-cli@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
version: v0.79.6
|
||||
version: v0.80.9
|
||||
|
||||
- name: Restore activity report logs cache
|
||||
id: activity_report_logs_cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
path: ./.cache/gh-aw/activity-report-logs
|
||||
key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
|
|
@ -379,10 +386,10 @@ jobs:
|
|||
${GH_AW_CMD_PREFIX} logs \
|
||||
--repo "${{ github.repository }}" \
|
||||
--start-date -1w \
|
||||
--count 100 \
|
||||
--count 500 \
|
||||
--output ./.cache/gh-aw/activity-report-logs \
|
||||
--format markdown \
|
||||
> ./.cache/gh-aw/activity-report-logs/report.md
|
||||
--report-file ./.cache/gh-aw/activity-report-logs/report.md
|
||||
|
||||
- name: Save activity report logs cache
|
||||
if: ${{ always() }}
|
||||
|
|
@ -441,12 +448,12 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -461,13 +468,13 @@ jobs:
|
|||
await main();
|
||||
|
||||
- name: Install gh-aw
|
||||
uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup-cli@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
version: v0.79.6
|
||||
version: v0.80.9
|
||||
|
||||
- name: Restore forecast report logs cache
|
||||
id: forecast_report_logs_cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
path: ./.github/aw/logs
|
||||
key: ${{ runner.os }}-forecast-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
|
|
@ -538,7 +545,7 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -570,12 +577,12 @@ jobs:
|
|||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Scripts
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
|
||||
|
|
@ -590,9 +597,9 @@ jobs:
|
|||
await main();
|
||||
|
||||
- name: Install gh-aw
|
||||
uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup-cli@8c7d04ebf1ece56cd381446125da3e0f6896294a # v0.80.9
|
||||
with:
|
||||
version: v0.79.6
|
||||
version: v0.80.9
|
||||
|
||||
- name: Validate workflows and file issue on findings
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
|
|
|
|||
2
.github/workflows/android-build.yml
vendored
2
.github/workflows/android-build.yml
vendored
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Configure CMake and build
|
||||
run: |
|
||||
|
|
|
|||
84
.github/workflows/api-coherence-checker.lock.yml
generated
vendored
84
.github/workflows/api-coherence-checker.lock.yml
generated
vendored
File diff suppressed because one or more lines are too long
24
.github/workflows/build-warning-fixer.lock.yml
generated
vendored
24
.github/workflows/build-warning-fixer.lock.yml
generated
vendored
|
|
@ -32,13 +32,13 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -153,7 +153,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -376,7 +376,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -397,7 +397,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -1003,7 +1003,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1196,7 +1196,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1224,7 +1224,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1456,7 +1456,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1500,7 +1500,7 @@ jobs:
|
|||
await main();
|
||||
- name: Checkout repository (trusted default branch for comment events)
|
||||
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && (github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment')
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -1508,7 +1508,7 @@ jobs:
|
|||
fetch-depth: 1
|
||||
- name: Checkout repository
|
||||
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: ${{ steps.extract-base-branch.outputs.base-branch || github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }}
|
||||
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
4
.github/workflows/build-z3-cache.yml
vendored
4
.github/workflows/build-z3-cache.yml
vendored
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
|
||||
- name: Restore or create cache
|
||||
id: cache-z3
|
||||
uses: actions/cache@v5.0.5
|
||||
uses: actions/cache@v6.0.0
|
||||
with:
|
||||
path: |
|
||||
build/z3
|
||||
|
|
|
|||
34
.github/workflows/ci.yml
vendored
34
.github/workflows/ci.yml
vendored
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
runRegressions: false
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -81,7 +81,7 @@ jobs:
|
|||
container: "quay.io/pypa/manylinux_2_34_x86_64:latest"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Select Python
|
||||
run: |
|
||||
|
|
@ -121,7 +121,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download ARM toolchain
|
||||
run: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz'
|
||||
|
|
@ -165,7 +165,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup OCaml
|
||||
uses: ocaml/setup-ocaml@v3
|
||||
|
|
@ -220,7 +220,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup OCaml
|
||||
uses: ocaml/setup-ocaml@v3
|
||||
|
|
@ -248,7 +248,19 @@ jobs:
|
|||
cd ..
|
||||
|
||||
- name: Install Z3 OCaml package
|
||||
run: eval `opam config env`; ocamlfind install z3-static build/api/ml/* build/libz3-static.a
|
||||
run: |
|
||||
eval `opam config env`
|
||||
ocamlfind install z3-static build/api/ml/* build/libz3-static.a
|
||||
# Ensure the stublibs directory where dllz3ml-static.so was installed is
|
||||
# listed in ld.conf so the OCaml bytecode linker can find it. When no
|
||||
# explicit -dll flag is passed, ocamlfind installs dll* files to stublibs
|
||||
# but may not update ld.conf, causing "Fatal error: exception End_of_file"
|
||||
# in ocamlc when it cannot locate the stub shared library at link time.
|
||||
STUBLIBS="$(ocamlfind printconf destdir)/stublibs"
|
||||
LDCONF="$(ocamlfind printconf ldconf)"
|
||||
if [ -d "$STUBLIBS" ] && ! grep -qF "$STUBLIBS" "$LDCONF" 2>/dev/null; then
|
||||
echo "$STUBLIBS" >> "$LDCONF"
|
||||
fi
|
||||
|
||||
- name: Build and run OCaml examples
|
||||
run: |
|
||||
|
|
@ -314,7 +326,7 @@ jobs:
|
|||
runTests: false
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -404,7 +416,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -453,7 +465,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -494,7 +506,7 @@ jobs:
|
|||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -514,7 +526,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
|
|||
26
.github/workflows/code-conventions-analyzer.lock.yml
generated
vendored
26
.github/workflows/code-conventions-analyzer.lock.yml
generated
vendored
|
|
@ -31,15 +31,15 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -93,7 +93,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -154,7 +154,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -381,7 +381,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -402,7 +402,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -415,7 +415,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1087,7 +1087,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1281,7 +1281,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1309,7 +1309,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1541,7 +1541,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1617,7 +1617,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
26
.github/workflows/code-simplifier.lock.yml
generated
vendored
26
.github/workflows/code-simplifier.lock.yml
generated
vendored
|
|
@ -34,13 +34,13 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -97,7 +97,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -163,7 +163,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -393,7 +393,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -415,7 +415,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -1021,7 +1021,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1224,7 +1224,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1253,7 +1253,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1457,7 +1457,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1535,7 +1535,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1580,7 +1580,7 @@ jobs:
|
|||
await main();
|
||||
- name: Checkout repository (trusted default branch for comment events)
|
||||
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && (github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment')
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -1588,7 +1588,7 @@ jobs:
|
|||
fetch-depth: 1
|
||||
- name: Checkout repository
|
||||
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: ${{ steps.extract-base-branch.outputs.base-branch || github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }}
|
||||
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
20
.github/workflows/compare-stats-anomaly-reporter.lock.yml
generated
vendored
20
.github/workflows/compare-stats-anomaly-reporter.lock.yml
generated
vendored
|
|
@ -31,13 +31,13 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -90,7 +90,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -151,7 +151,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -377,7 +377,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -398,7 +398,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -990,7 +990,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1183,7 +1183,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1211,7 +1211,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1441,7 +1441,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
COV_DETAILS_PATH: ${{github.workspace}}/cov-details
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup
|
||||
run: |
|
||||
|
|
|
|||
2
.github/workflows/cross-build.yml
vendored
2
.github/workflows/cross-build.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Install cross build tools
|
||||
run: apt update && apt install -y ninja-build cmake python3 g++-13-${{ matrix.arch }}-linux-gnu
|
||||
|
|
|
|||
28
.github/workflows/csa-analysis.lock.yml
generated
vendored
28
.github/workflows/csa-analysis.lock.yml
generated
vendored
|
|
@ -31,16 +31,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -94,7 +94,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -155,7 +155,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -387,7 +387,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -414,7 +414,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1035,7 +1035,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1229,7 +1229,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1257,7 +1257,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1487,7 +1487,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1563,7 +1563,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
4
.github/workflows/docs.yml
vendored
4
.github/workflows/docs.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
needs: build-go-docs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v6
|
||||
|
|
|
|||
2
.github/workflows/fstar-master-build.yml
vendored
2
.github/workflows/fstar-master-build.yml
vendored
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
DISCUSSION_CATEGORY: ${{ github.event.inputs.discussion_category || 'Agentic Workflows' }}
|
||||
steps:
|
||||
- name: Checkout Z3
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
with:
|
||||
ref: ${{ env.Z3_REF }}
|
||||
fetch-depth: 1
|
||||
|
|
|
|||
82
.github/workflows/issue-backlog-processor.lock.yml
generated
vendored
82
.github/workflows/issue-backlog-processor.lock.yml
generated
vendored
File diff suppressed because one or more lines are too long
30
.github/workflows/memory-safety-report.lock.yml
generated
vendored
30
.github/workflows/memory-safety-report.lock.yml
generated
vendored
|
|
@ -34,16 +34,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -110,7 +110,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -173,7 +173,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -415,7 +415,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -442,7 +442,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1076,7 +1076,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1268,7 +1268,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1296,7 +1296,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1500,7 +1500,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1561,7 +1561,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1637,7 +1637,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
4
.github/workflows/memory-safety.yml
vendored
4
.github/workflows/memory-safety.yml
vendored
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
ASAN_OPTIONS: "detect_leaks=1:halt_on_error=0:print_stats=1:log_path=/tmp/asan"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -121,7 +121,7 @@ jobs:
|
|||
UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=0:log_path=/tmp/ubsan"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
BUILD_TYPE: Release
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
|
|||
2
.github/workflows/msvc-static-build.yml
vendored
2
.github/workflows/msvc-static-build.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
BUILD_TYPE: Release
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
|
|||
134
.github/workflows/nightly-validation.yml
vendored
134
.github/workflows/nightly-validation.yml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
|
|
@ -87,7 +87,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
|
|
@ -142,7 +142,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
|
|
@ -197,7 +197,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
|
|
@ -256,7 +256,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download Windows x64 build from release
|
||||
env:
|
||||
|
|
@ -292,7 +292,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download Windows x86 build from release
|
||||
env:
|
||||
|
|
@ -328,7 +328,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download Ubuntu x64 build from release
|
||||
env:
|
||||
|
|
@ -361,7 +361,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS x64 build from release
|
||||
env:
|
||||
|
|
@ -394,7 +394,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS ARM64 build from release
|
||||
env:
|
||||
|
|
@ -431,7 +431,7 @@ jobs:
|
|||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -470,7 +470,7 @@ jobs:
|
|||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -510,7 +510,7 @@ jobs:
|
|||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -553,7 +553,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -582,7 +582,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -611,7 +611,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -640,7 +640,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -672,7 +672,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -727,7 +727,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS x64 build from release
|
||||
env:
|
||||
|
|
@ -779,7 +779,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS ARM64 build from release
|
||||
env:
|
||||
|
|
@ -835,7 +835,7 @@ jobs:
|
|||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -844,3 +844,97 @@ jobs:
|
|||
|
||||
- name: Run build script unit tests
|
||||
run: python -m unittest discover -s scripts/tests -p "test_*.py" -v
|
||||
|
||||
# ============================================================================
|
||||
# DOTNET MANAGED WRAPPER ARCHITECTURE VALIDATION
|
||||
# ============================================================================
|
||||
|
||||
validate-dotnet-anycpu:
|
||||
name: "Validate Microsoft.Z3.dll is AnyCPU (issue #9863)"
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download NuGet package from release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.release_tag }}"
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="Nightly"
|
||||
fi
|
||||
gh release download $TAG --pattern "*.nupkg" --dir nuget-packages
|
||||
|
||||
- name: Extract managed DLL from NuGet package
|
||||
run: |
|
||||
# NuGet packages are ZIP archives; exclude the symbols package
|
||||
NUPKG=$(ls nuget-packages/*.nupkg | grep -v '\.symbols\.' | grep -v '\.snupkg' | head -n 1)
|
||||
echo "Checking package: $NUPKG"
|
||||
unzip -q "$NUPKG" "lib/netstandard2.0/Microsoft.Z3.dll" -d nupkg-extracted
|
||||
|
||||
- name: Check PE Machine field is AnyCPU (not architecture-specific)
|
||||
run: |
|
||||
python3 - <<'EOF'
|
||||
import struct
|
||||
import sys
|
||||
|
||||
dll_path = "nupkg-extracted/lib/netstandard2.0/Microsoft.Z3.dll"
|
||||
|
||||
with open(dll_path, 'rb') as f:
|
||||
# Verify MZ magic
|
||||
if f.read(2) != b'MZ':
|
||||
print("ERROR: Not a valid PE file (missing MZ header)")
|
||||
sys.exit(1)
|
||||
|
||||
# Read PE header offset stored at 0x3C in the DOS stub
|
||||
f.seek(0x3C)
|
||||
pe_offset = struct.unpack('<I', f.read(4))[0]
|
||||
|
||||
# Verify PE signature
|
||||
f.seek(pe_offset)
|
||||
if f.read(4) != b'PE\x00\x00':
|
||||
print("ERROR: Missing PE\\0\\0 signature")
|
||||
sys.exit(1)
|
||||
|
||||
# COFF Machine field is the 2 bytes immediately after the PE signature
|
||||
machine = struct.unpack('<H', f.read(2))[0]
|
||||
|
||||
machine_names = {
|
||||
0x0000: "Unknown/AnyCPU",
|
||||
0x014C: "i386 (AnyCPU for managed assemblies)",
|
||||
0x8664: "AMD64/x64",
|
||||
0xAA64: "ARM64",
|
||||
0x01C0: "ARM",
|
||||
0x01C4: "ARM Thumb-2",
|
||||
}
|
||||
machine_name = machine_names.get(machine, f"0x{machine:04X}")
|
||||
print(f"Machine field: 0x{machine:04X} = {machine_name}")
|
||||
|
||||
if machine == 0x8664:
|
||||
print()
|
||||
print("FAIL: Machine is AMD64 (0x8664).")
|
||||
print("This prevents loading on arm64 .NET hosts even though the assembly")
|
||||
print("contains only pure IL (CorFlags.ILONLY=True).")
|
||||
print("The DLL must be built as AnyCPU (Machine=0x014C) so the CLR loader")
|
||||
print("accepts it on every host architecture.")
|
||||
print("See issue #9863 for details.")
|
||||
sys.exit(1)
|
||||
elif machine == 0xAA64:
|
||||
print()
|
||||
print("FAIL: Machine is ARM64 (0xAA64).")
|
||||
print("This prevents loading on x64 .NET hosts.")
|
||||
print("The DLL must be built as AnyCPU (Machine=0x014C).")
|
||||
sys.exit(1)
|
||||
elif machine in (0x014C, 0x0000):
|
||||
print()
|
||||
print("PASS: Machine field indicates AnyCPU.")
|
||||
print("Microsoft.Z3.dll will load on any .NET host architecture.")
|
||||
else:
|
||||
print()
|
||||
print(f"FAIL: Unexpected Machine field 0x{machine:04X}.")
|
||||
print("Expected 0x014C (i386/AnyCPU) for a managed-only assembly.")
|
||||
sys.exit(1)
|
||||
EOF
|
||||
|
|
|
|||
104
.github/workflows/nightly.yml
vendored
104
.github/workflows/nightly.yml
vendored
|
|
@ -35,7 +35,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -71,7 +71,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -112,7 +112,7 @@ jobs:
|
|||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS x64 Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
@ -171,7 +171,7 @@ jobs:
|
|||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS ARM64 Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
@ -229,7 +229,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -258,7 +258,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -293,7 +293,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -349,7 +349,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Select Python
|
||||
run: |
|
||||
|
|
@ -387,7 +387,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download ARM toolchain
|
||||
run: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz'
|
||||
|
|
@ -435,7 +435,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download RISC-V toolchain
|
||||
run: curl -L -o /tmp/riscv-toolchain.tar.gz 'https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2024.09.03/riscv64-glibc-ubuntu-20.04-gcc-nightly-2024.09.03-nightly.tar.gz'
|
||||
|
|
@ -483,66 +483,13 @@ jobs:
|
|||
path: src/api/python/wheelhouse/*.whl
|
||||
retention-days: 2
|
||||
|
||||
pyodide-python:
|
||||
name: "Python bindings (Pyodide)"
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
|
||||
- name: Setup packages
|
||||
run: sudo apt-get update && sudo apt-get install -y python3-dev python3-pip python3-venv
|
||||
|
||||
- name: Create venv
|
||||
run: python3 -m venv ~/env
|
||||
|
||||
- name: Install pyodide
|
||||
run: ~/env/bin/pip install pyodide-build pyodide-cli
|
||||
|
||||
- name: Configure Emscripten
|
||||
run: |
|
||||
git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
|
||||
cd ~/emsdk
|
||||
PYODIDE_EMSCRIPTEN_VERSION=$(~/env/bin/pyodide config get emscripten_version)
|
||||
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
|
||||
- name: Build wheel
|
||||
run: |
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
cd src/api/python
|
||||
CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" CXXFLAGS="${CXXFLAGS}" ~/env/bin/pyodide build --exports whole_archive
|
||||
env:
|
||||
CFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0 -g2"
|
||||
LDFLAGS: "-fexceptions -s WASM_BIGINT"
|
||||
CXXFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0"
|
||||
|
||||
- name: Setup env-pyodide
|
||||
run: |
|
||||
source ~/env/bin/activate
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
pyodide venv ~/env-pyodide
|
||||
|
||||
- name: Test wheel
|
||||
run: |
|
||||
~/env-pyodide/bin/pip install src/api/python/dist/*.whl
|
||||
~/env-pyodide/bin/python src/api/python/z3test.py z3
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PyodidePythonBuild
|
||||
path: src/api/python/dist/*.whl
|
||||
retention-days: 2
|
||||
|
||||
windows-build-x64:
|
||||
name: "Windows x64 build"
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -552,7 +499,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -568,7 +516,7 @@ jobs:
|
|||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -578,7 +526,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x86 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x86-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -594,7 +543,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -604,7 +553,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 || exit /b 1
|
||||
python scripts\mk_win_dist_cmake.py --arm64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --assembly-version=${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.PATCH }} --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -624,7 +574,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -699,7 +649,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -740,11 +690,11 @@ jobs:
|
|||
|
||||
python-package:
|
||||
name: "Python packaging"
|
||||
needs: [mac-build-x64, mac-build-arm64, windows-build-x64, windows-build-x86, windows-build-arm64, manylinux-python-amd64, manylinux-python-arm64, manylinux-python-riscv64, pyodide-python]
|
||||
needs: [mac-build-x64, mac-build-arm64, windows-build-x64, windows-build-x86, windows-build-arm64, manylinux-python-amd64, manylinux-python-arm64, manylinux-python-riscv64]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -799,12 +749,6 @@ jobs:
|
|||
name: ManyLinuxPythonBuildRiscv64
|
||||
path: artifacts
|
||||
|
||||
- name: Download Pyodide Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
with:
|
||||
name: PyodidePythonBuild
|
||||
path: artifacts
|
||||
|
||||
- name: Extract builds
|
||||
run: |
|
||||
cd artifacts
|
||||
|
|
@ -865,7 +809,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
|
|||
25
.github/workflows/nuget-build.yml
vendored
25
.github/workflows/nuget-build.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -30,7 +30,8 @@ jobs:
|
|||
- name: Build Windows x64
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --assembly-version=${{ github.event.inputs.version || '4.17.0' }} --zip
|
||||
|
||||
- name: Upload Windows x64 artifact
|
||||
|
|
@ -44,7 +45,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -54,7 +55,8 @@ jobs:
|
|||
- name: Build Windows x86
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x86 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x86-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --assembly-version=${{ github.event.inputs.version || '4.17.0' }} --zip
|
||||
|
||||
- name: Upload Windows x86 artifact
|
||||
|
|
@ -68,7 +70,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -78,7 +80,8 @@ jobs:
|
|||
- name: Build Windows ARM64
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 || exit /b 1
|
||||
python scripts\mk_win_dist_cmake.py --arm64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --assembly-version=${{ github.event.inputs.version || '4.17.0' }} --zip
|
||||
|
||||
- name: Upload Windows ARM64 artifact
|
||||
|
|
@ -92,7 +95,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -113,7 +116,7 @@ jobs:
|
|||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -134,7 +137,7 @@ jobs:
|
|||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -157,7 +160,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -212,7 +215,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
|
|||
6
.github/workflows/ocaml.yaml
vendored
6
.github/workflows/ocaml.yaml
vendored
|
|
@ -17,11 +17,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
# Cache ccache (shared across runs)
|
||||
- name: Cache ccache
|
||||
uses: actions/cache@v5.0.5
|
||||
uses: actions/cache@v6.0.0
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{ runner.os }}-ccache-${{ github.sha }}
|
||||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
|
||||
# Cache opam (compiler + packages)
|
||||
- name: Cache opam
|
||||
uses: actions/cache@v5.0.5
|
||||
uses: actions/cache@v6.0.0
|
||||
with:
|
||||
path: ~/.opam
|
||||
key: ${{ runner.os }}-opam-${{ matrix.ocaml-version }}-${{ github.sha }}
|
||||
|
|
|
|||
22
.github/workflows/ostrich-benchmark.lock.yml
generated
vendored
22
.github/workflows/ostrich-benchmark.lock.yml
generated
vendored
|
|
@ -31,14 +31,14 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -152,7 +152,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -374,7 +374,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -401,7 +401,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout c3 branch
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
|
@ -990,7 +990,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1183,7 +1183,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1211,7 +1211,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1441,7 +1441,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
57
.github/workflows/pyodide-pypi.yml
vendored
Normal file
57
.github/workflows/pyodide-pypi.yml
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
name: Pyodide Wheel (PyPI)
|
||||
|
||||
# Builds a PEP 783 `pyemscripten_*_wasm32` wheel for z3-solver using cibuildwheel
|
||||
# and publishes it to PyPI on tag pushes. Unlike the legacy pyodide.yml (which
|
||||
# uses `pyodide build` and produces a Pyodide-version-locked emscripten_* wheel
|
||||
# uploaded only as a CI artifact), this wheel is installable at runtime with
|
||||
# micropip from PyPI. See src/api/python/pyproject.toml [tool.cibuildwheel].
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-pyodide:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Build Pyodide wheel
|
||||
uses: pypa/cibuildwheel@v4.1.0
|
||||
with:
|
||||
# The Python bindings live in a subdirectory of the repo.
|
||||
package-dir: src/api/python
|
||||
env:
|
||||
CIBW_PLATFORM: pyodide
|
||||
# Exception/longjmp/bigint flags are declared in
|
||||
# src/api/python/pyproject.toml ([tool.pyodide.build]) and combined
|
||||
# with Pyodide's -fwasm-exceptions defaults. Don't set CFLAGS/CXXFLAGS
|
||||
# here — a JS-EH -fexceptions value conflicts with the wasm-EH ABI.
|
||||
|
||||
- name: Store Pyodide wheel
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: pyodide-wheel
|
||||
path: wheelhouse/*.whl
|
||||
|
||||
publish:
|
||||
name: Publish to PyPI
|
||||
runs-on: ubuntu-24.04
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: [build-pyodide]
|
||||
environment: release
|
||||
permissions:
|
||||
id-token: write # trusted publishing (OIDC), no API token needed
|
||||
steps:
|
||||
- name: Download Pyodide wheel
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: pyodide-wheel
|
||||
path: dist/
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
68
.github/workflows/pyodide.yml
vendored
68
.github/workflows/pyodide.yml
vendored
|
|
@ -1,68 +0,0 @@
|
|||
name: Pyodide Build
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 */2 * *'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
|
||||
- name: Setup packages
|
||||
run: sudo apt-get update && sudo apt-get install -y python3-dev python3-pip python3-venv
|
||||
|
||||
- name: Create venv
|
||||
run: python3 -m venv ~/env
|
||||
|
||||
- name: Install pyodide
|
||||
run: ~/env/bin/pip install pyodide-build pyodide-cli
|
||||
|
||||
- name: Configure CMake and build
|
||||
run: |
|
||||
git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
|
||||
cd ~/emsdk && PYODIDE_EMSCRIPTEN_VERSION=$(~/env/bin/pyodide config get emscripten_version)
|
||||
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
|
||||
- name: Build Z3
|
||||
run: |
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
cd src/api/python
|
||||
CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" CXXFLAG="${CXXFLAGS}" ~/env/bin/pyodide build --exports whole_archive
|
||||
env:
|
||||
CFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0 -g2"
|
||||
LDFLAGS: "-fexceptions -s WASM_BIGINT"
|
||||
CXXFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0"
|
||||
|
||||
- name: Setup env-pyodide
|
||||
run: |
|
||||
source ~/env/bin/activate
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
pyodide venv ~/env-pyodide
|
||||
|
||||
- name: Setup z3 wheel
|
||||
run: |
|
||||
~/env-pyodide/bin/pip install src/api/python/dist/*.whl
|
||||
~/env-pyodide/bin/python - <src/api/python/z3test.py z3
|
||||
|
||||
- name: Package wheel
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: pyodide-wheel
|
||||
path: src/api/python/dist/*.whl
|
||||
retention-days: 1
|
||||
|
||||
22
.github/workflows/qf-s-benchmark.lock.yml
generated
vendored
22
.github/workflows/qf-s-benchmark.lock.yml
generated
vendored
|
|
@ -31,14 +31,14 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -152,7 +152,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -378,7 +378,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -405,7 +405,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout c3 branch
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
|
@ -994,7 +994,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1187,7 +1187,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1215,7 +1215,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1445,7 +1445,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
22
.github/workflows/release-notes-updater.lock.yml
generated
vendored
22
.github/workflows/release-notes-updater.lock.yml
generated
vendored
|
|
@ -31,14 +31,14 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -153,7 +153,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -378,7 +378,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -405,7 +405,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
|
@ -993,7 +993,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1185,7 +1185,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1213,7 +1213,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1443,7 +1443,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
106
.github/workflows/release.yml
vendored
106
.github/workflows/release.yml
vendored
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -78,7 +78,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -122,7 +122,7 @@ jobs:
|
|||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS x64 Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
@ -181,7 +181,7 @@ jobs:
|
|||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download macOS ARM64 Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
@ -239,7 +239,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -268,7 +268,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -303,7 +303,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -359,7 +359,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Select Python
|
||||
run: |
|
||||
|
|
@ -397,7 +397,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download ARM toolchain
|
||||
run: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz'
|
||||
|
|
@ -445,7 +445,7 @@ jobs:
|
|||
container: quay.io/pypa/manylinux_2_28_x86_64:latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download RISC-V toolchain
|
||||
run: curl -L -o /tmp/riscv-toolchain.tar.gz 'https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2024.09.03/riscv64-glibc-ubuntu-20.04-gcc-nightly-2024.09.03-nightly.tar.gz'
|
||||
|
|
@ -493,66 +493,13 @@ jobs:
|
|||
path: src/api/python/wheelhouse/*.whl
|
||||
retention-days: 7
|
||||
|
||||
pyodide-python:
|
||||
name: "Python bindings (Pyodide)"
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
|
||||
- name: Setup packages
|
||||
run: sudo apt-get update && sudo apt-get install -y python3-dev python3-pip python3-venv
|
||||
|
||||
- name: Create venv
|
||||
run: python3 -m venv ~/env
|
||||
|
||||
- name: Install pyodide
|
||||
run: ~/env/bin/pip install pyodide-build pyodide-cli
|
||||
|
||||
- name: Configure Emscripten
|
||||
run: |
|
||||
git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
|
||||
cd ~/emsdk
|
||||
PYODIDE_EMSCRIPTEN_VERSION=$(~/env/bin/pyodide config get emscripten_version)
|
||||
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
|
||||
|
||||
- name: Build wheel
|
||||
run: |
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
cd src/api/python
|
||||
CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" CXXFLAGS="${CXXFLAGS}" ~/env/bin/pyodide build --exports whole_archive
|
||||
env:
|
||||
CFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0 -g2"
|
||||
LDFLAGS: "-fexceptions -s WASM_BIGINT"
|
||||
CXXFLAGS: "-fexceptions -s DISABLE_EXCEPTION_CATCHING=0"
|
||||
|
||||
- name: Setup env-pyodide
|
||||
run: |
|
||||
source ~/env/bin/activate
|
||||
source ~/emsdk/emsdk_env.sh
|
||||
pyodide venv ~/env-pyodide
|
||||
|
||||
- name: Test wheel
|
||||
run: |
|
||||
~/env-pyodide/bin/pip install src/api/python/dist/*.whl
|
||||
~/env-pyodide/bin/python src/api/python/z3test.py z3
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PyodidePythonBuild
|
||||
path: src/api/python/dist/*.whl
|
||||
retention-days: 7
|
||||
|
||||
windows-build-x64:
|
||||
name: "Windows x64 build"
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -562,7 +509,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -578,7 +526,7 @@ jobs:
|
|||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -588,7 +536,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x86 || exit /b 1
|
||||
python scripts\mk_win_dist.py --x86-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -604,7 +553,7 @@ jobs:
|
|||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -614,7 +563,8 @@ jobs:
|
|||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||
for /f "usebackq delims=" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i"
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 || exit /b 1
|
||||
python scripts\mk_win_dist_cmake.py --arm64-only --dotnet-key=%GITHUB_WORKSPACE%\resources\z3.snk --assembly-version=${{ env.RELEASE_VERSION }} --zip
|
||||
|
||||
- name: Upload artifact
|
||||
|
|
@ -634,7 +584,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -709,7 +659,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -750,11 +700,11 @@ jobs:
|
|||
|
||||
python-package:
|
||||
name: "Python packaging"
|
||||
needs: [mac-build-x64, mac-build-arm64, windows-build-x64, windows-build-x86, windows-build-arm64, manylinux-python-amd64, manylinux-python-arm64, manylinux-python-riscv64, pyodide-python]
|
||||
needs: [mac-build-x64, mac-build-arm64, windows-build-x64, windows-build-x86, windows-build-arm64, manylinux-python-amd64, manylinux-python-arm64, manylinux-python-riscv64]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
|
|
@ -809,12 +759,6 @@ jobs:
|
|||
name: ManyLinuxPythonBuildRiscv64
|
||||
path: artifacts
|
||||
|
||||
- name: Download Pyodide Build
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
with:
|
||||
name: PyodidePythonBuild
|
||||
path: artifacts
|
||||
|
||||
- name: Extract builds
|
||||
run: |
|
||||
cd artifacts
|
||||
|
|
@ -873,7 +817,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
@ -929,7 +873,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Download NuGet packages
|
||||
uses: actions/download-artifact@v8.0.1
|
||||
|
|
|
|||
26
.github/workflows/smtlib-benchmark-finder.lock.yml
generated
vendored
26
.github/workflows/smtlib-benchmark-finder.lock.yml
generated
vendored
|
|
@ -31,15 +31,15 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -153,7 +153,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -385,7 +385,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -406,7 +406,7 @@ jobs:
|
|||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
|
|
@ -419,7 +419,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1036,7 +1036,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1230,7 +1230,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1258,7 +1258,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1488,7 +1488,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1564,7 +1564,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
28
.github/workflows/specbot-crash-analyzer.lock.yml
generated
vendored
28
.github/workflows/specbot-crash-analyzer.lock.yml
generated
vendored
|
|
@ -31,16 +31,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -152,7 +152,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -383,7 +383,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -410,7 +410,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout c3 branch
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: c3
|
||||
|
|
@ -460,7 +460,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1073,7 +1073,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1267,7 +1267,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1295,7 +1295,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1525,7 +1525,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1601,7 +1601,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
28
.github/workflows/tactic-to-simplifier.lock.yml
generated
vendored
28
.github/workflows/tactic-to-simplifier.lock.yml
generated
vendored
|
|
@ -31,16 +31,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -94,7 +94,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -155,7 +155,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -386,7 +386,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -413,7 +413,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
@ -421,7 +421,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1043,7 +1043,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1234,7 +1234,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1262,7 +1262,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1493,7 +1493,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1569,7 +1569,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
22
.github/workflows/tptp-benchmark.lock.yml
generated
vendored
22
.github/workflows/tptp-benchmark.lock.yml
generated
vendored
|
|
@ -31,14 +31,14 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -152,7 +152,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -379,7 +379,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -406,7 +406,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install build dependencies
|
||||
|
|
@ -999,7 +999,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1192,7 +1192,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1220,7 +1220,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1450,7 +1450,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
2
.github/workflows/wasm-release.yml
vendored
2
.github/workflows/wasm-release.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v6
|
||||
|
|
|
|||
2
.github/workflows/wasm.yml
vendored
2
.github/workflows/wasm.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.3
|
||||
uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v6
|
||||
|
|
|
|||
2
.github/workflows/wip.yml
vendored
2
.github/workflows/wip.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- uses: actions/checkout@v7.0.0
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
|
|
|||
28
.github/workflows/workflow-suggestion-agent.lock.yml
generated
vendored
28
.github/workflows/workflow-suggestion-agent.lock.yml
generated
vendored
|
|
@ -31,16 +31,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -94,7 +94,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -155,7 +155,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -387,7 +387,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -414,7 +414,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1035,7 +1035,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1228,7 +1228,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1256,7 +1256,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1486,7 +1486,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1562,7 +1562,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
28
.github/workflows/zipt-code-reviewer.lock.yml
generated
vendored
28
.github/workflows/zipt-code-reviewer.lock.yml
generated
vendored
|
|
@ -31,16 +31,16 @@
|
|||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/github-script@v9
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.80.4
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
|
|
@ -93,7 +93,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -154,7 +154,7 @@ jobs:
|
|||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
|
|
@ -383,7 +383,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -410,7 +410,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
@ -418,7 +418,7 @@ jobs:
|
|||
- name: Create cache-memory directory
|
||||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh"
|
||||
- name: Restore cache-memory file share data
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
|
||||
with:
|
||||
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
|
||||
path: /tmp/gh-aw/cache-memory
|
||||
|
|
@ -1063,7 +1063,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1255,7 +1255,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1283,7 +1283,7 @@ jobs:
|
|||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
|
|
@ -1514,7 +1514,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
@ -1590,7 +1590,7 @@ jobs:
|
|||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.80.4
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,9 +1,12 @@
|
|||
*~
|
||||
rebase.cmd
|
||||
reports/
|
||||
crashes/
|
||||
*.pyc
|
||||
*.pyo
|
||||
# Ignore callgrind files
|
||||
callgrind.out.*
|
||||
gmon.out
|
||||
# .hpp files are automatically generated
|
||||
*.hpp
|
||||
.env
|
||||
|
|
|
|||
17
BUILD.bazel
17
BUILD.bazel
|
|
@ -19,14 +19,23 @@ filegroup(
|
|||
cmake(
|
||||
name = "z3_dynamic",
|
||||
generate_args = [
|
||||
"-G Ninja",
|
||||
"-G Ninja",
|
||||
"-D Z3_EXPORTED_TARGETS=", # prevents installation, leaving symlinks between dylibs intact on copy
|
||||
],
|
||||
lib_source = ":all_files",
|
||||
out_binaries = ["z3"],
|
||||
out_shared_libs = select({
|
||||
"@platforms//os:linux": ["libz3.so"],
|
||||
# "@platforms//os:osx": ["libz3.dylib"], # FIXME: this is not working, libz3<version>.dylib is not copied
|
||||
# NOTE: These will need to be manually bumped along side the version in MODULE.bazel/VERSION.txt/CMake
|
||||
"@platforms//os:linux": [
|
||||
"libz3.so",
|
||||
"libz3.so.4.17",
|
||||
"libz3.so.4.17.0.0",
|
||||
],
|
||||
"@platforms//os:osx": [
|
||||
"libz3.dylib",
|
||||
"libz3.4.17.dylib",
|
||||
"libz3.4.17.0.0.dylib",
|
||||
],
|
||||
"@platforms//os:windows": ["libz3.dll"],
|
||||
"//conditions:default": ["@platforms//:incompatible"],
|
||||
}),
|
||||
|
|
@ -36,7 +45,7 @@ cmake(
|
|||
cmake(
|
||||
name = "z3_static",
|
||||
generate_args = [
|
||||
"-G Ninja",
|
||||
"-G Ninja",
|
||||
"-D BUILD_SHARED_LIBS=OFF",
|
||||
"-D Z3_BUILD_LIBZ3_SHARED=OFF",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -204,7 +204,12 @@ elseif (EMSCRIPTEN)
|
|||
"-Os"
|
||||
"-s ALLOW_MEMORY_GROWTH=1"
|
||||
"-s ASSERTIONS=0"
|
||||
"-s DISABLE_EXCEPTION_CATCHING=0"
|
||||
# Use native wasm exception handling + wasm longjmp to match the ABI of the
|
||||
# Pyodide / modern-emscripten main module. The legacy JS-based EH (which the
|
||||
# removed "-s DISABLE_EXCEPTION_CATCHING=0" selected) makes libz3 import
|
||||
# invoke_* trampolines the Pyodide runtime no longer provides.
|
||||
"-fwasm-exceptions"
|
||||
"-s SUPPORT_LONGJMP=wasm"
|
||||
"-s ERROR_ON_UNDEFINED_SYMBOLS=1"
|
||||
)
|
||||
endif()
|
||||
|
|
|
|||
29
README.md
29
README.md
|
|
@ -23,13 +23,13 @@ See the [release notes](RELEASE_NOTES.md) for notes on various stable releases o
|
|||
| [](https://github.com/Z3Prover/z3/actions/workflows/wasm.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/Windows.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/ci.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/ocaml.yaml) |
|
||||
|
||||
### Scheduled Workflows
|
||||
| Open Bugs | Android Build | Pyodide Build | Nightly Build | Cross Build |
|
||||
| Open Bugs | Android Build | Pyodide Wheel (PyPI) | Nightly Build | Cross Build |
|
||||
| -----------|---------------|---------------|---------------|-------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/wip.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/android-build.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/pyodide.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/nightly.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/cross-build.yml) |
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/wip.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/android-build.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/pyodide-pypi.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/nightly.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/cross-build.yml) |
|
||||
|
||||
| MSVC Static | MSVC Clang-CL | Build Z3 Cache | Code Coverage | Memory Safety | Mark PRs Ready |
|
||||
|-------------|---------------|----------------|---------------|---------------|----------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/msvc-static-build.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/msvc-static-build-clang-cl.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/build-z3-cache.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/coverage.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/memory-safety.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/mark-prs-ready-for-review.yml) |
|
||||
| MSVC Static | MSVC Clang-CL | Build Z3 Cache | Memory Safety | Mark PRs Ready |
|
||||
|-------------|---------------|----------------|---------------|----------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/msvc-static-build.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/msvc-static-build-clang-cl.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/build-z3-cache.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/memory-safety.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/mark-prs-ready-for-review.yml) |
|
||||
|
||||
### Manual & Release Workflows
|
||||
| Documentation | Release Build | WASM Release | NuGet Build |
|
||||
|
|
@ -42,17 +42,17 @@ See the [release notes](RELEASE_NOTES.md) for notes on various stable releases o
|
|||
| [](https://github.com/Z3Prover/z3/actions/workflows/nightly-validation.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/copilot-setup-steps.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/agentics-maintenance.yml) |
|
||||
|
||||
### Agentic Workflows
|
||||
| A3 Python | API Coherence | Code Simplifier | Release Notes | Workflow Suggestion |
|
||||
| ----------|---------------|-----------------|---------------|---------------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/a3-python.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/api-coherence-checker.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/code-simplifier.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/release-notes-updater.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/workflow-suggestion-agent.lock.yml) |
|
||||
| API Coherence | Code Simplifier | Release Notes | Workflow Suggestion | Academic Citation |
|
||||
| -------------|-----------------|---------------|---------------------|-------------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/api-coherence-checker.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/code-simplifier.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/release-notes-updater.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/workflow-suggestion-agent.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/academic-citation-tracker.lock.yml) |
|
||||
|
||||
| Academic Citation | Build Warning Fixer | Code Conventions | CSA Report | Issue Backlog |
|
||||
| ------------------|---------------------|------------------|------------|---------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/academic-citation-tracker.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/build-warning-fixer.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/code-conventions-analyzer.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/csa-analysis.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/issue-backlog-processor.lock.yml) |
|
||||
| Issue Backlog | Memory Safety Report | QF-S Benchmark | Specbot Crash Analyzer | SMTLIB Benchmark Finder |
|
||||
| --------------|----------------------|----------------|------------------------|-------------------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/issue-backlog-processor.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/memory-safety-report.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/qf-s-benchmark.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/specbot-crash-analyzer.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/smtlib-benchmark-finder.lock.yml) |
|
||||
|
||||
| Memory Safety Report | Ostrich Benchmark | QF-S Benchmark | Tactic-to-Simplifier | ZIPT Code Reviewer |
|
||||
| ---------------------|-------------------|----------------|----------------------|--------------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/memory-safety-report.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/ostrich-benchmark.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/qf-s-benchmark.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/tactic-to-simplifier.lock.yml) | [](https://github.com/Z3Prover/z3/actions/workflows/zipt-code-reviewer.lock.yml) |
|
||||
| TPTP Benchmark |
|
||||
|----------------|
|
||||
| [](https://github.com/Z3Prover/z3/actions/workflows/tptp-benchmark.lock.yml) |
|
||||
|
||||
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
||||
[2]: #building-z3-using-make-and-gccclang
|
||||
|
|
@ -299,4 +299,3 @@ to Z3's C API. For more information, see [MachineArithmetic/README.md](https://g
|
|||
## Power Tools
|
||||
* The [Axiom Profiler](https://github.com/viperproject/axiom-profiler-2) currently developed by ETH Zurich
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
if (EMSCRIPTEN OR Z3_SINGLE_THREADED)
|
||||
# Emscripten (Pyodide/WASM) and single-threaded builds do not use
|
||||
# libatomic; skip the check to avoid a spurious configure failure.
|
||||
message(STATUS "Skipping std::atomic link check (EMSCRIPTEN or Z3_SINGLE_THREADED)")
|
||||
else()
|
||||
set(ATOMIC_TEST_SOURCE "
|
||||
#include <atomic>
|
||||
std::atomic<int> x;
|
||||
|
|
@ -21,3 +26,4 @@ if (NOT BUILTIN_ATOMIC)
|
|||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ set(CLANG_ONLY_WARNINGS
|
|||
"-Wno-c++98-compat"
|
||||
"-Wno-c++98-compat-pedantic"
|
||||
"-Wno-zero-length-array"
|
||||
"-Wc99-extensions"
|
||||
"-Wsuggest-override"
|
||||
"-Winconsistent-missing-override"
|
||||
"-Wno-missing-field-initializers"
|
||||
"-Wcast-qual"
|
||||
)
|
||||
set(MSVC_WARNINGS "/W3")
|
||||
|
||||
|
|
|
|||
BIN
gmon.out
BIN
gmon.out
Binary file not shown.
|
|
@ -1804,6 +1804,7 @@ class DotNetDLLComponent(Component):
|
|||
<Description>Z3 is a satisfiability modulo theories solver from Microsoft Research.</Description>
|
||||
<Copyright>Copyright Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<PackageTags>smt constraint solver theorem prover</PackageTags>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
%s
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
double ackr_helper::calculate_lemma_bound(fun2terms_map const& occs1, sel2terms_map const& occs2) {
|
||||
double total = 0;
|
||||
for (auto const& kv : occs1) {
|
||||
total += n_choose_2_chk(kv.m_value->var_args.size());
|
||||
total += kv.m_value->const_args.size() * kv.m_value->var_args.size();
|
||||
for (auto const &[k, v] : occs1) {
|
||||
total += n_choose_2_chk(v->var_args.size());
|
||||
total += v->const_args.size() * v->var_args.size();
|
||||
}
|
||||
for (auto const& kv : occs2) {
|
||||
total += n_choose_2_chk(kv.m_value->var_args.size());
|
||||
total += kv.m_value->const_args.size() * kv.m_value->var_args.size();
|
||||
for (auto const &[k, v] : occs2) {
|
||||
total += n_choose_2_chk(v->var_args.size());
|
||||
total += v->const_args.size() * v->var_args.size();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,14 +52,26 @@ public:
|
|||
return m_autil.is_select(a) && is_uninterp_const(a->get_arg(0));
|
||||
}
|
||||
|
||||
void mark_non_select_rec(expr* t, expr_mark& visited, expr_mark& non_select) {
|
||||
if (visited.is_marked(t))
|
||||
return;
|
||||
visited.mark(t, true);
|
||||
non_select.mark(t, true);
|
||||
if (is_app(t)) {
|
||||
for (expr *arg : *to_app(t))
|
||||
mark_non_select_rec(arg, visited,non_select);
|
||||
}
|
||||
}
|
||||
|
||||
void mark_non_select(app* a, expr_mark& non_select) {
|
||||
if (m_autil.is_select(a)) {
|
||||
bool first = true;
|
||||
expr_mark visited;
|
||||
for (expr* arg : *a) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
non_select.mark(arg, true);
|
||||
mark_non_select_rec(arg, visited, non_select);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -70,10 +82,10 @@ public:
|
|||
|
||||
void prune_non_select(obj_map<app, app_set*> & sels, expr_mark& non_select) {
|
||||
ptr_vector<app> nons;
|
||||
for (auto& kv : sels) {
|
||||
if (non_select.is_marked(kv.m_key)) {
|
||||
nons.push_back(kv.m_key);
|
||||
dealloc(kv.m_value);
|
||||
for (auto &[k, v] : sels) {
|
||||
if (non_select.is_marked(k)) {
|
||||
nons.push_back(k);
|
||||
dealloc(v);
|
||||
}
|
||||
}
|
||||
for (app* s : nons) {
|
||||
|
|
|
|||
|
|
@ -149,9 +149,9 @@ void lackr::eager_enc() {
|
|||
checkpoint();
|
||||
ackr(v);
|
||||
}
|
||||
for (auto const& kv : m_sel2terms) {
|
||||
for (auto const &[k, v] : m_sel2terms) {
|
||||
checkpoint();
|
||||
ackr(kv.get_value());
|
||||
ackr(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,13 +190,13 @@ void lackr::abstract_fun(fun2terms_map const& apps) {
|
|||
}
|
||||
|
||||
void lackr::abstract_sel(sel2terms_map const& apps) {
|
||||
for (auto const& kv : apps) {
|
||||
func_decl * fd = kv.m_key->get_decl();
|
||||
for (app * t : kv.m_value->const_args) {
|
||||
for (auto const &[k, v] : apps) {
|
||||
func_decl * fd = k->get_decl();
|
||||
for (app * t : v->const_args) {
|
||||
app * fc = m.mk_fresh_const(fd->get_name(), t->get_sort());
|
||||
m_info->set_abstr(t, fc);
|
||||
}
|
||||
for (app * t : kv.m_value->var_args) {
|
||||
for (app * t : v->var_args) {
|
||||
app * fc = m.mk_fresh_const(fd->get_name(), t->get_sort());
|
||||
m_info->set_abstr(t, fc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
<Warn>4</Warn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<DocumentationFile>$(OutputPath)\Microsoft.Z3.xml</DocumentationFile>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Compilation items -->
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ go run basic_example.go
|
|||
|
||||
## Memory Management
|
||||
|
||||
The Go bindings use `runtime.SetFinalizer` to automatically manage Z3 reference counts. You don't need to manually call inc_ref/dec_ref. However, be aware that finalizers run during garbage collection, so resources may not be freed immediately.
|
||||
The Go bindings use `runtime.SetFinalizer` to automatically manage Z3 reference counts. You don't need to manually call inc_ref/dec_ref. However, be aware that finalizers run during garbage collection, so resources may not be freed immediately. The bindings enable `Z3_enable_concurrent_dec_ref` when creating contexts so finalizer-driven decref operations are safe with concurrent GC.
|
||||
|
||||
## Thread Safety
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ type Context struct {
|
|||
// NewContext creates a new Z3 context with default configuration.
|
||||
func NewContext() *Context {
|
||||
ctx := &Context{ptr: C.Z3_mk_context_rc(C.Z3_mk_config())}
|
||||
C.Z3_enable_concurrent_dec_ref(ctx.ptr)
|
||||
runtime.SetFinalizer(ctx, func(c *Context) {
|
||||
C.Z3_del_context(c.ptr)
|
||||
})
|
||||
|
|
@ -98,6 +99,7 @@ func NewContext() *Context {
|
|||
// NewContextWithConfig creates a new Z3 context with the given configuration.
|
||||
func NewContextWithConfig(cfg *Config) *Context {
|
||||
ctx := &Context{ptr: C.Z3_mk_context_rc(cfg.ptr)}
|
||||
C.Z3_enable_concurrent_dec_ref(ctx.ptr)
|
||||
runtime.SetFinalizer(ctx, func(c *Context) {
|
||||
C.Z3_del_context(c.ptr)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ static void decide_eh(void* _p, Z3_solver_callback cb, Z3_ast _val, unsigned bit
|
|||
info->jenv->CallVoidMethod(info->jobj, info->decide, (jlong)_val, bit, is_pos);
|
||||
}
|
||||
|
||||
static jboolean on_binding_eh(void* _p, Z3_solver_callback cb, Z3_ast _q, Z3_ast _inst) {
|
||||
[[maybe_unused]] static jboolean on_binding_eh(void* _p, Z3_solver_callback cb, Z3_ast _q, Z3_ast _inst) {
|
||||
JavaInfo *info = static_cast<JavaInfo*>(_p);
|
||||
ScopedCB scoped(info, cb);
|
||||
return info->jenv->CallBooleanMethod(info->jobj, info->on_binding, (jlong)_q, (jlong)_inst);
|
||||
|
|
|
|||
34
src/api/js/package-lock.json
generated
34
src/api/js/package-lock.json
generated
|
|
@ -5400,10 +5400,20 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/linkify-it": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz",
|
||||
"integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/puzrin"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/markdown-it"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uc.micro": "^2.0.0"
|
||||
|
|
@ -5501,15 +5511,25 @@
|
|||
}
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
|
||||
"integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/puzrin"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/markdown-it"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.0",
|
||||
"linkify-it": "^5.0.1",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,29 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=70"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
# --- Pyodide / WebAssembly (PEP 783) build configuration ---------------------
|
||||
# Consumed by pyodide-build (invoked directly or via `cibuildwheel --platform
|
||||
# pyodide`). These flags are forwarded to the emscripten toolchain that compiles
|
||||
# libz3 to wasm32. setup.py's IS_PYODIDE branch appends the same -fexceptions
|
||||
# flags defensively, but declaring them here is what cibuildwheel relies on.
|
||||
# Pyodide 314 / emscripten 5 builds its main module with *native wasm*
|
||||
# exception handling and wasm longjmp (see Pyodide's Makefile.envs). Side
|
||||
# modules like libz3.so MUST match that ABI: building with the legacy
|
||||
# `-fexceptions` (JS-based EH) makes libz3 import `invoke_*` trampolines that the
|
||||
# Pyodide runtime no longer provides -> "cannot resolve symbol invoke_vi" at the
|
||||
# first Z3 call. WASM_BIGINT is required because the Z3 C API passes 64-bit ints
|
||||
# across the ctypes/JS boundary.
|
||||
[tool.pyodide.build]
|
||||
cflags = "-fwasm-exceptions -sSUPPORT_LONGJMP=wasm"
|
||||
cxxflags = "-fwasm-exceptions -sSUPPORT_LONGJMP=wasm"
|
||||
ldflags = "-fwasm-exceptions -sSUPPORT_LONGJMP=wasm -sWASM_BIGINT -sSIDE_MODULE=1"
|
||||
|
||||
# --- cibuildwheel: produce a PyPI-publishable pyemscripten wheel -------------
|
||||
[tool.cibuildwheel]
|
||||
# Pyodide 314 ships CPython 3.14; match the single ABI it targets.
|
||||
build = "cp314-*"
|
||||
|
||||
[tool.cibuildwheel.pyodide]
|
||||
# z3test.py is the upstream smoke test; run it inside the Pyodide test venv.
|
||||
test-command = "python {project}/z3test.py z3"
|
||||
|
|
|
|||
|
|
@ -42,9 +42,16 @@ if RELEASE_DIR is None:
|
|||
BUILD_PLATFORM = "emscripten"
|
||||
BUILD_ARCH = "wasm32"
|
||||
BUILD_OS_VERSION = os.environ['_PYTHON_HOST_PLATFORM'].split('_')[1:-1]
|
||||
build_env['CFLAGS'] = build_env.get('CFLAGS', '') + " -fexceptions"
|
||||
build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + " -fexceptions"
|
||||
build_env['LDFLAGS'] = build_env.get('LDFLAGS', '') + " -fexceptions"
|
||||
# Match Pyodide's native-wasm exception/longjmp ABI (see Makefile.envs in
|
||||
# Pyodide). The legacy JS-based "-fexceptions" makes libz3.so import
|
||||
# invoke_* trampolines that the modern Pyodide runtime does not export,
|
||||
# which surfaces as "cannot resolve symbol invoke_vi" on the first Z3
|
||||
# call. These mirror [tool.pyodide.build] in pyproject.toml so direct
|
||||
# `pyodide build` invocations stay consistent with cibuildwheel.
|
||||
_wasm_eh = " -fwasm-exceptions -sSUPPORT_LONGJMP=wasm"
|
||||
build_env['CFLAGS'] = build_env.get('CFLAGS', '') + _wasm_eh
|
||||
build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + _wasm_eh
|
||||
build_env['LDFLAGS'] = build_env.get('LDFLAGS', '') + _wasm_eh + " -sWASM_BIGINT -sSIDE_MODULE=1"
|
||||
IS_SINGLE_THREADED = True
|
||||
ENABLE_LTO = False
|
||||
# build with pthread doesn't work. The WASM bindings are also single threaded.
|
||||
|
|
@ -305,6 +312,21 @@ class bdist_wheel(_bdist_wheel):
|
|||
|
||||
|
||||
def finalize_options(self):
|
||||
if BUILD_PLATFORM == "emscripten":
|
||||
# Under pyodide-build / `cibuildwheel --platform pyodide`, the
|
||||
# authoritative wheel platform tag is handed to us verbatim via
|
||||
# _PYTHON_HOST_PLATFORM. For PEP 783 (Pyodide >= 0.28 / "314") this
|
||||
# is e.g. "pyemscripten_2026_0_wasm32" -- a tag PyPI accepts. The
|
||||
# reconstruction below instead produced "emscripten_<ver>_wasm32",
|
||||
# which is locked to a Pyodide release and rejected by PyPI, so we
|
||||
# defer to pyodide-build's tag when it is available.
|
||||
host_platform = os.environ.get('_PYTHON_HOST_PLATFORM')
|
||||
if host_platform:
|
||||
self.plat_name = host_platform
|
||||
else:
|
||||
os_version_tag = '_'.join(BUILD_OS_VERSION) if BUILD_OS_VERSION else 'xxxxxx'
|
||||
self.plat_name = f"emscripten_{os_version_tag}_wasm32"
|
||||
return super().finalize_options()
|
||||
if BUILD_ARCH is not None and BUILD_PLATFORM is not None:
|
||||
os_version_tag = '_'.join(BUILD_OS_VERSION) if BUILD_OS_VERSION is not None else 'xxxxxx'
|
||||
os_version_tag = self.remove_build_machine_os_version(BUILD_PLATFORM, os_version_tag)
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ struct z3_replayer::imp {
|
|||
|
||||
Z3_symbol get_symbol(unsigned pos) const {
|
||||
check_arg(pos, SYMBOL);
|
||||
return (Z3_symbol)m_args[pos].m_sym;
|
||||
return (Z3_symbol)const_cast<void*>(m_args[pos].m_sym);
|
||||
}
|
||||
|
||||
void * get_obj(unsigned pos) const {
|
||||
|
|
|
|||
|
|
@ -2894,7 +2894,7 @@ proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs
|
|||
}
|
||||
});
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_eq(n1,n2));
|
||||
return mk_app(basic_family_id, PR_TRANSITIVITY_STAR, args.size(), args.data());
|
||||
}
|
||||
|
|
@ -2903,7 +2903,7 @@ proof * ast_manager::mk_monotonicity(func_decl * R, app * f1, app * f2, unsigned
|
|||
SASSERT(f1->get_num_args() == f2->get_num_args());
|
||||
SASSERT(f1->get_decl() == f2->get_decl());
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_app(R, f1, f2));
|
||||
proof* p = mk_app(basic_family_id, PR_MONOTONICITY, args.size(), args.data());
|
||||
return p;
|
||||
|
|
@ -2965,7 +2965,7 @@ proof * ast_manager::mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, pr
|
|||
if (proofs_disabled())
|
||||
return nullptr;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_eq(s, t));
|
||||
return mk_app(basic_family_id, PR_REWRITE_STAR, args.size(), args.data());
|
||||
}
|
||||
|
|
@ -3055,7 +3055,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
}
|
||||
|
||||
if (!found_complement) {
|
||||
args.append(num_proofs, (expr**)proofs);
|
||||
args.append(num_proofs, (expr* const *)proofs);
|
||||
CTRACE(mk_unit_resolution_bug, !is_or(f1), tout << mk_ll_pp(f1, *this) << "\n";
|
||||
for (unsigned i = 1; i < num_proofs; ++i)
|
||||
tout << mk_pp(proofs[i], *this) << "\n";
|
||||
|
|
@ -3125,7 +3125,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
tout << mk_pp(new_fact, *this) << "\n";);
|
||||
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(new_fact);
|
||||
#ifdef Z3DEBUG
|
||||
expr * f1 = get_fact(proofs[0]);
|
||||
|
|
@ -3191,7 +3191,7 @@ proof * ast_manager::mk_apply_defs(expr * n, expr * def, unsigned num_proofs, pr
|
|||
if (proofs_disabled())
|
||||
return nullptr;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_oeq(n, def));
|
||||
return mk_app(basic_family_id, PR_APPLY_DEF, args.size(), args.data());
|
||||
}
|
||||
|
|
@ -3225,7 +3225,7 @@ proof * ast_manager::mk_nnf_pos(expr * s, expr * t, unsigned num_proofs, proof *
|
|||
return nullptr;
|
||||
check_nnf_proof_parents(num_proofs, proofs);
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_oeq(s, t));
|
||||
return mk_app(basic_family_id, PR_NNF_POS, args.size(), args.data());
|
||||
}
|
||||
|
|
@ -3235,7 +3235,7 @@ proof * ast_manager::mk_nnf_neg(expr * s, expr * t, unsigned num_proofs, proof *
|
|||
return nullptr;
|
||||
check_nnf_proof_parents(num_proofs, proofs);
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(mk_oeq(mk_not(s), t));
|
||||
return mk_app(basic_family_id, PR_NNF_NEG, args.size(), args.data());
|
||||
}
|
||||
|
|
@ -3305,7 +3305,7 @@ proof * ast_manager::mk_redundant_del(expr* e) {
|
|||
|
||||
proof * ast_manager::mk_clause_trail(unsigned n, expr* const* ps) {
|
||||
ptr_buffer<expr> args;
|
||||
args.append(n, (expr**) ps);
|
||||
args.append(n, (expr* const *) ps);
|
||||
return mk_app(basic_family_id, PR_CLAUSE_TRAIL, 0, nullptr, args.size(), args.data());
|
||||
}
|
||||
|
||||
|
|
@ -3323,7 +3323,7 @@ proof * ast_manager::mk_th_lemma(
|
|||
for (unsigned i = 0; i < num_params; ++i)
|
||||
parameters.push_back(params[i]);
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
args.append(num_proofs, (expr* const *) proofs);
|
||||
args.push_back(fact);
|
||||
return mk_app(basic_family_id, PR_TH_LEMMA, parameters.size(), parameters.data(), args.size(), args.data());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ private:
|
|||
inline ast_manager & m() const { return m_manager; }
|
||||
|
||||
// label for an expression
|
||||
std::string label_of_expr(const expr * e) const {
|
||||
expr_ref er((expr*)e, m());
|
||||
std::string label_of_expr(const expr *e) const {
|
||||
expr_ref er(const_cast<expr *>(e), m());
|
||||
std::ostringstream out;
|
||||
out << er << std::flush;
|
||||
return escape_dot(out.str());
|
||||
|
|
|
|||
|
|
@ -39,11 +39,16 @@ z3_add_component(rewriter
|
|||
rewriter.cpp
|
||||
seq_axioms.cpp
|
||||
seq_eq_solver.cpp
|
||||
seq_derive.cpp
|
||||
seq_subset.cpp
|
||||
seq_split.cpp
|
||||
seq_derive.cpp
|
||||
seq_range_collapse.cpp
|
||||
seq_range_predicate.cpp
|
||||
seq_rewriter.cpp
|
||||
seq_regex_bisim.cpp
|
||||
seq_skolem.cpp
|
||||
term_enumeration.cpp
|
||||
th_rewriter.cpp
|
||||
value_sweep.cpp
|
||||
var_subst.cpp
|
||||
|
|
|
|||
|
|
@ -768,9 +768,10 @@ void bit_blaster_tpl<Cfg>::mk_smod(unsigned sz, expr * const * a_bits, expr * co
|
|||
template<typename Cfg>
|
||||
void bit_blaster_tpl<Cfg>::mk_eq(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out) {
|
||||
expr_ref_vector out_bits(m());
|
||||
out_bits.resize(sz);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
mk_iff(a_bits[i], b_bits[i], out);
|
||||
out_bits.push_back(out);
|
||||
out_bits[i] = out;
|
||||
}
|
||||
mk_and(out_bits.size(), out_bits.data(), out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1196,15 +1196,15 @@ bool bool_rewriter::decompose_ite(expr *r, expr_ref &c, expr_ref &th, expr_ref &
|
|||
}
|
||||
for (expr *e : subterms::ground(expr_ref(r, m()))) {
|
||||
if (m().is_ite(e, cond, r1, r2)) {
|
||||
expr_safe_replace rep1(m());
|
||||
expr_safe_replace rep2(m());
|
||||
rep1.insert(e, r1);
|
||||
rep2.insert(e, r2);
|
||||
m_rep1.reset();
|
||||
m_rep2.reset();
|
||||
m_rep1.insert(e, r1);
|
||||
m_rep2.insert(e, r2);
|
||||
c = cond;
|
||||
th = r;
|
||||
el = r;
|
||||
rep1(th);
|
||||
rep2(el);
|
||||
m_rep1(th);
|
||||
m_rep2(el);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1212,6 +1212,4 @@ bool bool_rewriter::decompose_ite(expr *r, expr_ref &c, expr_ref &th, expr_ref &
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template class rewriter_tpl<bool_rewriter_cfg>;
|
||||
template class rewriter_tpl<bool_rewriter_cfg>;
|
||||
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/rewriter/expr_safe_replace.h"
|
||||
#include "util/params.h"
|
||||
|
||||
/**
|
||||
|
|
@ -64,6 +65,7 @@ class bool_rewriter {
|
|||
ptr_vector<expr> m_todo1, m_todo2;
|
||||
unsigned_vector m_counts1, m_counts2;
|
||||
expr_mark m_marked;
|
||||
expr_safe_replace m_rep1, m_rep2;
|
||||
|
||||
br_status mk_flat_and_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_flat_or_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
|
@ -87,7 +89,7 @@ class bool_rewriter {
|
|||
expr_ref simplify_eq_ite(expr* value, expr* ite);
|
||||
|
||||
public:
|
||||
bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_local_ctx_cost(0) {
|
||||
bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_local_ctx_cost(0), m_rep1(m), m_rep2(m) {
|
||||
updt_params(p);
|
||||
}
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
|
@ -243,7 +245,9 @@ public:
|
|||
void mk_nor(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_ge2(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
|
||||
|
||||
// If r is, or contains, an if-then-else, decompose it into a top-level
|
||||
// ite by hoisting the (first) inner ite condition: returns c, th, el such
|
||||
// that r is equivalent to (ite c th el). Returns false if r has no ite.
|
||||
bool decompose_ite(expr *r, expr_ref &c, expr_ref &th, expr_ref &el);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -452,6 +452,8 @@ namespace seq {
|
|||
// |t| = 0 => |s| = 0 or indexof(t,s,offset) = -1
|
||||
// ~contains(t,s) => indexof(t,s,offset) = -1
|
||||
|
||||
add_clause(mk_ge(i, -1));
|
||||
|
||||
add_clause(cnt, i_eq_m1);
|
||||
add_clause(~t_eq_empty, s_eq_empty, i_eq_m1);
|
||||
|
||||
|
|
@ -638,8 +640,8 @@ namespace seq {
|
|||
add_clause(~i_ge_0, i_ge_len_s, mk_eq(i, len_x));
|
||||
}
|
||||
|
||||
add_clause(i_ge_0, mk_seq_eq(e, emp));
|
||||
add_clause(~i_ge_len_s, mk_seq_eq(e, emp));
|
||||
add_clause(i_ge_0, mk_eq(e, emp));
|
||||
add_clause(~i_ge_len_s, mk_eq(e, emp));
|
||||
add_clause(~i_ge_0, i_ge_len_s, mk_eq(one, len_e));
|
||||
add_clause(mk_le(len_e, 1));
|
||||
}
|
||||
|
|
@ -1066,7 +1068,7 @@ namespace seq {
|
|||
void axioms::replace_re_axiom(expr* e) {
|
||||
expr* s = nullptr, *r = nullptr, *t = nullptr;
|
||||
VERIFY(seq.str.is_replace_re(e, s, r, t));
|
||||
throw default_exception("replace-re is not supported");
|
||||
throw default_exception("no support for replace-re");
|
||||
}
|
||||
|
||||
// A basic strategy for supporting replace_all and other
|
||||
|
|
@ -1075,34 +1077,22 @@ namespace seq {
|
|||
// using iterative deepening can be re-used.
|
||||
//
|
||||
// create recursive relation 'ra' with properties:
|
||||
// ra(i, j, s, p, t, r) =
|
||||
// if len(s) = i && len(r) = j then
|
||||
// true
|
||||
// else if len(s) > i = 0 && p = "" && r = t + s then
|
||||
// true
|
||||
// else if len(s) > i && p != "" &&
|
||||
// s = extract(s, 0, i) + p + extract(s, i + len(p), len(s)) &&
|
||||
// r = extract(r, 0, i) + t + extract(r, i + len(p), len(r)) && ra(i + len(p), j + len(t), s, p, t, r)
|
||||
// else if ~prefix(p, extract(s, i, len(s)) && at(s,i) = at(r,j) then
|
||||
// ra(i + 1, j + 1, s, p, t, r)
|
||||
// else false
|
||||
// ra(i, j, s, p, t, r) <- len(s) = i && len(r) = j
|
||||
// ra(i, j, s, p, t, r) <- len(s) > i = 0 && p = "" && r = t + s
|
||||
// ra(i, j, s, p, t, r) <- len(s) > i && p != "" && s = extract(s, 0, i) + p + extract(s, i + len(p), len(s)) && r = extract(r, 0, i) + t + extract(r, i + len(p), len(r)) && ra(i + len(p), j + len(t), s, p, t, r)
|
||||
// ra(i, s, p, t, r) <- ~prefix(p, extract(s, i, len(s)) && at(s,i) = at(r,j) && ra(i + 1, j + 1, s, p, t, r)
|
||||
// which amounts to:
|
||||
//
|
||||
//
|
||||
// Then assert
|
||||
// ra(s, p, t, replace_all(s, p, t))
|
||||
//
|
||||
// ra(s, p, t, r) is a recursive predicate:
|
||||
// ra(s, p, t, r) iff replace_all(s, p, t) = r
|
||||
//
|
||||
// Base case, empty s or p: r = s
|
||||
// Match case, prefix(p, s): s = p ++ s', r = t ++ r', ra(s', p, t, r')
|
||||
// No-match case: r[0] = s[0], ra(s[1:], p, t, r[1:])
|
||||
//
|
||||
// Assert: ra(s, p, t, replace_all(s, p, t))
|
||||
//
|
||||
void axioms::replace_all_axiom(expr* r) {
|
||||
expr* s = nullptr, *p = nullptr, *t = nullptr;
|
||||
VERIFY(seq.str.is_replace_all(r, s, p, t));
|
||||
recfun::util rec(m);
|
||||
recfun::decl::plugin& plugin = rec.get_plugin();
|
||||
recfun_replace replace(m);
|
||||
sort* srt = s->get_sort();
|
||||
sort* domain[4] = { srt, srt, srt, srt };
|
||||
auto ra = rec.find_def_decl(symbol("ra"), 4, domain, m.mk_bool_sort(), true);
|
||||
|
|
@ -1146,7 +1136,7 @@ namespace seq {
|
|||
void axioms::replace_re_all_axiom(expr* e) {
|
||||
expr* s = nullptr, *p = nullptr, *t = nullptr;
|
||||
VERIFY(seq.str.is_replace_re_all(e, s, p, t));
|
||||
throw default_exception("replace_re_all is not supported");
|
||||
throw default_exception("no support for replace-re-all");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1345,7 +1335,7 @@ namespace seq {
|
|||
|
||||
/**
|
||||
* Consider the recursive definition of negated contains:
|
||||
~contains(a, b) =
|
||||
~contains(a, b) =
|
||||
if |b| > |a| then true
|
||||
else if |b| = |a| then a != b
|
||||
else ~prefix(b, a) and ~contains(a[1:], b)
|
||||
|
|
@ -1420,9 +1410,9 @@ namespace seq {
|
|||
return bound_tracker;
|
||||
}
|
||||
|
||||
// |u| != |v| OR
|
||||
// |u| != |v| OR
|
||||
// (u = w[a]u' AND v = w[b]v' AND a != b AND |u'| = |v'|)
|
||||
void axioms::diseq_axiom(expr *u, expr *v) {
|
||||
void axioms::diseq_axiom(expr *u, expr *v) {
|
||||
expr_ref u_len(mk_len(u), m);
|
||||
expr_ref v_len(mk_len(v), m);
|
||||
expr_ref len_eq(mk_eq(u_len, v_len), m);
|
||||
|
|
|
|||
1520
src/ast/rewriter/seq_derive.cpp
Normal file
1520
src/ast/rewriter/seq_derive.cpp
Normal file
File diff suppressed because it is too large
Load diff
266
src/ast/rewriter/seq_derive.h
Normal file
266
src/ast/rewriter/seq_derive.h
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_derive.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Symbolic derivative computation for regular expressions.
|
||||
Produces an ITE-tree (transition regex) representation where
|
||||
the free variable is de Bruijn index 0 representing the input character.
|
||||
|
||||
Based on the theory of symbolic derivatives and transition regexes:
|
||||
- Veanes et al., "On Symbolic Derivatives and Transition Regexes" (LPAR 2024)
|
||||
- Varatalu, Veanes, Ernits, "RE#" (POPL 2025)
|
||||
- Stanford, Veanes, Bjørner, "Symbolic Boolean Derivatives" (PLDI 2021)
|
||||
|
||||
Authors:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2025-06-03
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "util/obj_pair_hashtable.h"
|
||||
#include "util/obj_triple_hashtable.h"
|
||||
#include <functional>
|
||||
|
||||
class seq_rewriter;
|
||||
|
||||
namespace seq {
|
||||
|
||||
enum class derivative_kind { antimirov_t, brzozowski_t };
|
||||
/**
|
||||
* Symbolic derivative engine for regular expressions.
|
||||
*
|
||||
* Given a regex r, operator()(r) computes a symbolic derivative δ(r)
|
||||
* represented as an ITE-tree over character predicates (using de Bruijn
|
||||
* variable 0 for the character). Evaluating the ITE-tree for a concrete
|
||||
* character 'a' yields the classical Brzozowski derivative δ_a(r).
|
||||
*
|
||||
* The ITE-tree structure implicitly defines minterms (equivalence classes
|
||||
* of characters indistinguishable by the regex).
|
||||
*
|
||||
* Key properties:
|
||||
* - Results are memoized for termination on cyclic derivative graphs
|
||||
* - Union/intersection operands are sorted for ACI canonicalization
|
||||
* - Depth-bounded to prevent stack overflow
|
||||
*/
|
||||
class derive {
|
||||
ast_manager& m;
|
||||
seq_util m_util;
|
||||
arith_util m_autil;
|
||||
bool_rewriter m_br;
|
||||
seq_rewriter& m_re;
|
||||
|
||||
// Cache: maps (ele, regex) pair to its derivative
|
||||
obj_pair_map<expr, expr, expr*> m_acache, m_bcache;
|
||||
obj_pair_map<expr, expr, expr*> m_atop_cache, m_btop_cache; // post-simplify cache
|
||||
expr_ref_vector m_trail; // pin cached results
|
||||
|
||||
// Op cache for ITE-hoisting operations (union, inter, concat, complement)
|
||||
// Path-aware caches: key is (a, b, path_expr) for binary ops, (a, path_expr) for complement
|
||||
obj_triple_map<expr, expr, expr, expr *> m_aunion_cache, m_bunion_cache, m_ainter_cache, m_binter_cache, m_axor_cache, m_bxor_cache;
|
||||
obj_pair_map<expr, expr, expr*> m_aconcat_cache, m_bconcat_cache;
|
||||
obj_pair_map<expr, expr, expr*> m_acomplement_cache, m_bcomplement_cache;
|
||||
|
||||
// Depth limiting
|
||||
unsigned m_depth { 0 };
|
||||
static const unsigned m_max_depth = 512;
|
||||
|
||||
seq_util::rex& re() { return m_util.re; }
|
||||
seq_util& u() { return m_util; }
|
||||
|
||||
derivative_kind m_derivative_kind = derivative_kind::antimirov_t;
|
||||
|
||||
// The element (character) for the current derivative computation
|
||||
expr_ref m_ele;
|
||||
|
||||
// Path state for inline pruning during mk_inter/mk_union/mk_complement
|
||||
using intervals_t = svector<std::pair<unsigned, unsigned>>;
|
||||
|
||||
// Path: vector of signed atoms
|
||||
svector<std::pair<expr*, bool>> m_path;
|
||||
// Intervals: feasible character ranges under current path (append-only)
|
||||
intervals_t m_intervals;
|
||||
unsigned m_intervals_start { 0 };
|
||||
// Stack of saved states for push/pop
|
||||
struct path_save { unsigned path_sz; unsigned intervals_sz; unsigned intervals_start; expr* path_expr; };
|
||||
svector<path_save> m_path_stack;
|
||||
// Boolean expression encoding of current path (for cache keys)
|
||||
expr_ref m_path_expr;
|
||||
|
||||
// Path interface
|
||||
lbool push(expr* c, bool sign); // l_true: implied, l_undef: pushed (must pop), l_false: contradicts
|
||||
void pop(); // restore state to matching push
|
||||
expr* get_path_expr() { return m_path_expr; }
|
||||
|
||||
obj_pair_map<expr, expr, expr *> &cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_acache : m_bcache;
|
||||
}
|
||||
|
||||
obj_pair_map<expr, expr, expr *> &top_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_atop_cache : m_btop_cache;
|
||||
}
|
||||
|
||||
obj_triple_map<expr, expr, expr, expr *> &union_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_aunion_cache : m_bunion_cache;
|
||||
}
|
||||
|
||||
obj_triple_map<expr, expr, expr, expr *> &inter_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_ainter_cache : m_binter_cache;
|
||||
}
|
||||
|
||||
obj_triple_map<expr, expr, expr, expr *> &xor_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_axor_cache : m_bxor_cache;
|
||||
}
|
||||
|
||||
obj_pair_map<expr, expr, expr *> &concat_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_aconcat_cache : m_bconcat_cache;
|
||||
}
|
||||
|
||||
obj_pair_map<expr, expr, expr *> &complement_cache() {
|
||||
return m_derivative_kind == derivative_kind::antimirov_t ? m_acomplement_cache : m_bcomplement_cache;
|
||||
}
|
||||
|
||||
// Hoist ITE: apply_op through ite(c, t, e) with path pruning
|
||||
expr_ref apply_ite(expr* c, expr* t, expr* e, expr* r, std::function<expr_ref(expr*, expr*)> apply_op);
|
||||
expr_ref apply_ite(expr* c, expr* t1, expr* e1, expr* t2, expr* e2, std::function<expr_ref(expr*, expr*)> apply_op);
|
||||
expr_ref apply_ite(expr* c, expr* t, expr* e, std::function<expr_ref(expr*)> apply_op);
|
||||
// Common ITE dispatch for binary ops (union/inter)
|
||||
expr_ref hoist_ite(expr* a, expr* b, std::function<expr_ref(expr*, expr*)> apply_op);
|
||||
|
||||
// Evaluate a condition against the current path/intervals
|
||||
lbool eval_path_cond(expr* c);
|
||||
|
||||
// Internal helpers for push
|
||||
lbool push_path_atoms(expr* c, bool sign);
|
||||
lbool push_intervals_impl(expr* c, bool sign);
|
||||
|
||||
// Core derivative computation
|
||||
expr_ref derive_rec(expr* r);
|
||||
expr_ref derive_core(expr* r);
|
||||
|
||||
// Helpers for specific regex constructs
|
||||
expr_ref derive_to_re(expr* s, sort* seq_sort);
|
||||
expr_ref derive_range(expr* lo, expr* hi, sort* seq_sort);
|
||||
expr_ref derive_of_pred(expr* pred, sort* seq_sort);
|
||||
|
||||
// Nullable check: returns a Boolean expression
|
||||
expr_ref is_nullable(expr* r);
|
||||
expr_ref is_nullable_symbolic_regex(expr* r, sort* seq_sort);
|
||||
|
||||
// Smart constructors with path-aware simplification and ACI canonicalization
|
||||
expr_ref mk_union(expr* a, expr* b);
|
||||
bool are_complements(expr* a, expr* b);
|
||||
unsigned union_id(expr* e); // complement-aware ID for sorting
|
||||
bool is_subset(expr* a, expr* b);
|
||||
expr_ref mk_union_core(expr* a, expr* b);
|
||||
void add_union_elem(expr_ref_vector& set, expr* e);
|
||||
expr_ref mk_inter(expr* a, expr* b);
|
||||
expr_ref mk_inter_core(expr* a, expr* b);
|
||||
expr_ref mk_concat(expr* a, expr* b);
|
||||
expr_ref mk_complement(expr* a);
|
||||
expr_ref mk_complement_core(expr* a);
|
||||
expr_ref mk_xor(expr *a, expr *b);
|
||||
expr_ref mk_xor_core(expr *a, expr *b);
|
||||
expr_ref mk_core(decl_kind k, expr* a, expr* b);
|
||||
expr_ref mk_ite(expr* c, expr* t, expr* e);
|
||||
|
||||
// Distribute concatenation through ITE/union in derivative
|
||||
expr_ref mk_deriv_concat(expr* d, expr* tail);
|
||||
expr_ref mk_deriv_concat_core(expr* d, expr* tail);
|
||||
|
||||
// Extract head character and tail from a sequence expression
|
||||
bool get_head_tail(expr* s1, expr* s2, expr_ref& hd, expr_ref& tl);
|
||||
|
||||
// Predicate implication for character range conditions.
|
||||
bool pred_implies(bool sign_a, expr* a, bool sign_b, expr* b);
|
||||
bool pred_implies(expr* a, expr* b);
|
||||
|
||||
// Normalize reverse(r)
|
||||
expr_ref mk_regex_reverse(expr* r);
|
||||
|
||||
// Condition evaluation helpers
|
||||
lbool eval_cond(expr* cond);
|
||||
lbool eval_range_cond(expr* c);
|
||||
void intersect_intervals(unsigned lo, unsigned hi);
|
||||
void exclude_interval(unsigned lo, unsigned hi);
|
||||
|
||||
// Cofactor enumeration over a transition regex (ITE-tree).
|
||||
void get_cofactors_rec(expr* r, expr_ref_pair_vector& result);
|
||||
|
||||
// Re-apply union/intersection simplifications bottom-up to a cofactor
|
||||
// leaf. decompose_ite substitutes ITE branch values structurally
|
||||
// (no simplification), so leaves can contain un-normalized nodes such
|
||||
// as union(R, none) or inter(R, none); this rebuilds them through
|
||||
// mk_union/mk_inter so equal states share a canonical form.
|
||||
expr_ref clean_leaf(expr* r);
|
||||
|
||||
sort* re_sort(expr* r) { return r->get_sort(); }
|
||||
sort* seq_sort(expr* r) { sort* s = nullptr; m_util.is_re(r, s); return s; }
|
||||
sort* ele_sort(expr* r) { sort* s = seq_sort(r); sort* e = nullptr; m_util.is_seq(s, e); return e; }
|
||||
|
||||
void reset();
|
||||
void reset_op_caches();
|
||||
|
||||
public:
|
||||
derive(ast_manager& m, seq_rewriter& re);
|
||||
|
||||
/**
|
||||
* Compute the derivative of regex r with respect to element ele.
|
||||
* When ele is a de Bruijn variable, produces a symbolic ITE-tree.
|
||||
* When ele is a concrete character, produces the concrete derivative.
|
||||
*/
|
||||
expr_ref operator()(derivative_kind k, expr* ele, expr* r);
|
||||
|
||||
/**
|
||||
* Convenience: symbolic derivative using de Bruijn var 0.
|
||||
*/
|
||||
expr_ref operator()(derivative_kind k, expr* r);
|
||||
|
||||
/**
|
||||
* Nullable check: returns a Boolean expression that is true iff r accepts the empty string.
|
||||
*/
|
||||
expr_ref nullable(expr* r) { return is_nullable(r); }
|
||||
|
||||
/**
|
||||
* Enumerate the cofactors (min-terms) of a transition regex r taken with
|
||||
* respect to element ele. r is an ITE-tree over character predicates on
|
||||
* ele; for every feasible path through the tree this produces a pair
|
||||
* (path_condition, leaf_regex). Infeasible character-interval
|
||||
* combinations are pruned using the same path/interval context that the
|
||||
* derivative engine uses while hoisting ITEs.
|
||||
*/
|
||||
void get_cofactors(expr* ele, expr* r, expr_ref_pair_vector& result);
|
||||
|
||||
/**
|
||||
* Compute the symbolic derivative of r and enumerate its reachable
|
||||
* leaves in fully ITE-hoisted normal form.
|
||||
*
|
||||
* Concretely this returns, for every feasible minterm (character
|
||||
* class) of δ(r), a pair (path_condition, target_regex). Every
|
||||
* if-then-else over the input character (including ones that would
|
||||
* otherwise be buried under a concat/union) is hoisted to the top
|
||||
* via the same path/interval pruning used by the derivative engine,
|
||||
* so each target_regex is free of (:var 0) and its nullability is
|
||||
* always decidable. Unions are kept intact as single leaves (a
|
||||
* union leaf denotes a single bisimulation state). Infeasible
|
||||
* minterms are pruned, so all returned leaves are reachable.
|
||||
*
|
||||
* This is the entry point the regex_bisim equivalence procedure
|
||||
* uses: it consumes the target_regex of each pair and ignores the
|
||||
* (redundant) path condition.
|
||||
*/
|
||||
void derivative_cofactors(expr* r, expr_ref_pair_vector& result);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
160
src/ast/rewriter/seq_range_collapse.cpp
Normal file
160
src/ast/rewriter/seq_range_collapse.cpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_range_collapse.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of regex <-> range_predicate translation for the
|
||||
boolean-combination-of-ranges fragment. See header for the recognized
|
||||
grammar and the canonical regex AST emitted by materialization.
|
||||
|
||||
Authors:
|
||||
|
||||
Margus Veanes (veanes) 2026
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/rewriter/seq_range_collapse.h"
|
||||
|
||||
namespace seq {
|
||||
|
||||
bool regex_to_range_predicate(seq_util& u, expr* r, range_predicate& out) {
|
||||
// The range algebra only models sets of single characters over the
|
||||
// unsigned character domain [0, max_char]. Guard against any regex
|
||||
// whose element type is not a sequence of characters (e.g. a regex
|
||||
// over (Seq Int) or (Seq (Seq Char))): for such regexes the
|
||||
// re.range/re.union/... matchers below would silently fabricate a
|
||||
// character-class predicate and change semantics. Reject them up
|
||||
// front so callers fall back to the generic regex path.
|
||||
sort* seq_sort = nullptr;
|
||||
if (!u.is_re(r, seq_sort) || !u.is_string(seq_sort))
|
||||
return false;
|
||||
|
||||
unsigned const max_char = u.max_char();
|
||||
auto& re = u.re;
|
||||
|
||||
if (re.is_empty(r)) {
|
||||
out = range_predicate::empty(max_char);
|
||||
return true;
|
||||
}
|
||||
if (re.is_full_char(r)) {
|
||||
out = range_predicate::top(max_char);
|
||||
return true;
|
||||
}
|
||||
unsigned lo = 0, hi = 0;
|
||||
expr* lo_e = nullptr;
|
||||
expr* hi_e = nullptr;
|
||||
if (re.is_range(r, lo_e, hi_e)) {
|
||||
auto extract_char = [&](expr* e, unsigned& c) -> bool {
|
||||
if (u.is_const_char(e, c)) return true;
|
||||
expr* inner = nullptr;
|
||||
if (u.str.is_unit(e, inner) && u.is_const_char(inner, c)) return true;
|
||||
zstring s;
|
||||
if (u.str.is_string(e, s) && s.length() == 1) {
|
||||
c = s[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (!extract_char(lo_e, lo) || !extract_char(hi_e, hi))
|
||||
return false;
|
||||
// Empty/inverted range [lo > hi] is the empty regex.
|
||||
if (lo > hi) {
|
||||
out = range_predicate::empty(max_char);
|
||||
return true;
|
||||
}
|
||||
out = range_predicate::range(lo, hi, max_char);
|
||||
return true;
|
||||
}
|
||||
expr *a = nullptr, *b = nullptr, *c = nullptr;
|
||||
if (re.is_union(r, a, b)) {
|
||||
range_predicate pa(max_char), pb(max_char);
|
||||
if (!regex_to_range_predicate(u, a, pa)) return false;
|
||||
if (!regex_to_range_predicate(u, b, pb)) return false;
|
||||
out = pa | pb;
|
||||
return true;
|
||||
}
|
||||
auto mk_diff = [&](expr *a, expr *b) -> bool {
|
||||
range_predicate pa(max_char), pb(max_char);
|
||||
if (!regex_to_range_predicate(u, a, pa))
|
||||
return false;
|
||||
if (!regex_to_range_predicate(u, b, pb))
|
||||
return false;
|
||||
out = pa - pb;
|
||||
return true;
|
||||
};
|
||||
if (re.is_diff(r, a, b))
|
||||
return mk_diff(a, b);
|
||||
|
||||
if (re.is_intersection(r, a, b) && re.is_complement(b, c))
|
||||
return mk_diff(a, c);
|
||||
|
||||
if (re.is_intersection(r, a, b) && re.is_complement(a, c))
|
||||
return mk_diff(b, c);
|
||||
|
||||
if (re.is_intersection(r, a, b)) {
|
||||
range_predicate pa(max_char), pb(max_char);
|
||||
if (!regex_to_range_predicate(u, a, pa)) return false;
|
||||
if (!regex_to_range_predicate(u, b, pb)) return false;
|
||||
out = pa & pb;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: re.complement is intentionally NOT handled here.
|
||||
// re.complement is the SEQUENCE-level complement: its language
|
||||
// includes the empty string, strings of length >= 2, and any
|
||||
// length-1 string outside the operand. A character-class
|
||||
// range_predicate can only describe a set of length-1 strings,
|
||||
// so collapsing re.complement(R) to ~R (character-level
|
||||
// complement) would change semantics whenever R is wrapped in
|
||||
// any sequence-level context (e.g. re.diff at the top level,
|
||||
// or membership tests). De-Morgan equivalences and the
|
||||
// special cases re.complement(re.empty) / re.complement(re.full)
|
||||
// are already handled directly in seq_rewriter::mk_re_complement.
|
||||
return false;
|
||||
}
|
||||
|
||||
static expr_ref mk_unit_string_from_char(seq_util& u, unsigned c) {
|
||||
return expr_ref(u.str.mk_string(zstring(c)), u.get_manager());
|
||||
}
|
||||
|
||||
static expr_ref mk_single_range_regex(seq_util& u, unsigned lo, unsigned hi, sort* re_sort) {
|
||||
ast_manager& m = u.get_manager();
|
||||
return expr_ref(u.re.mk_range(re_sort, lo, hi), m);
|
||||
}
|
||||
|
||||
expr_ref range_predicate_to_regex(seq_util& u, range_predicate const& p, sort* seq_sort) {
|
||||
ast_manager& m = u.get_manager();
|
||||
sort* re_sort = u.re.mk_re(seq_sort);
|
||||
if (p.is_empty())
|
||||
return expr_ref(u.re.mk_empty(re_sort), m);
|
||||
unsigned const n = p.num_ranges();
|
||||
SASSERT(n > 0);
|
||||
if (n == 1) {
|
||||
auto [lo, hi] = p[0];
|
||||
return mk_single_range_regex(u, lo, hi, re_sort);
|
||||
}
|
||||
// Build single-range AST nodes first, then sort by expression id
|
||||
// so the resulting right-associated union matches the canonical
|
||||
// id-sorted shape that seq_rewriter::merge_regex_sets expects.
|
||||
// Without this the merge algorithm produces incorrect unions
|
||||
// when it has to combine our materialized output with another
|
||||
// (id-sorted) regex set.
|
||||
expr_ref_vector ranges(m);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
auto [lo, hi] = p[i];
|
||||
ranges.push_back(mk_single_range_regex(u, lo, hi, re_sort));
|
||||
}
|
||||
std::sort(ranges.data(), ranges.data() + ranges.size(),
|
||||
[](expr* a, expr* b) { return a->get_id() < b->get_id(); });
|
||||
expr_ref acc(ranges.get(n - 1), m);
|
||||
for (unsigned i = n - 1; i-- > 0; )
|
||||
acc = expr_ref(u.re.mk_union(ranges.get(i), acc), m);
|
||||
return acc;
|
||||
}
|
||||
|
||||
}
|
||||
71
src/ast/rewriter/seq_range_collapse.h
Normal file
71
src/ast/rewriter/seq_range_collapse.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_range_collapse.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Recognize regexes that are boolean combinations of character-class
|
||||
primitives (re.empty, re.full_char, re.range with concrete chars,
|
||||
and re.union/inter/comp/diff over translatable arguments), and
|
||||
materialize a seq::range_predicate back into a canonical regex AST.
|
||||
|
||||
Together with seq_rewriter integration, this lets any boolean
|
||||
combination of character-class regexes collapse to a canonical
|
||||
multi-range form, so that equivalent character classes share AST
|
||||
identity, and downstream consumers (derivative, OneStep, caching)
|
||||
can short-circuit them as pure range predicates.
|
||||
|
||||
Authors:
|
||||
|
||||
Margus Veanes (veanes) 2026
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/rewriter/seq_range_predicate.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
|
||||
namespace seq {
|
||||
|
||||
/**
|
||||
* If r is a boolean combination of character-class regex primitives
|
||||
* over the unsigned character domain [0, max_char], compute the
|
||||
* equivalent range_predicate and return true. Otherwise return false
|
||||
* with out untouched.
|
||||
*
|
||||
* Recognized fragment (all character-class-preserving operations):
|
||||
* re.empty -> empty
|
||||
* re.full_char_set -> top
|
||||
* re.range "c_lo" "c_hi" (concrete) -> [c_lo, c_hi]
|
||||
* re.union r1 r2 -> p1 | p2
|
||||
* re.intersection r1 r2 -> p1 & p2
|
||||
* re.diff r1 r2 -> p1 - p2
|
||||
*
|
||||
* Notably re.complement is NOT recognized: it is a SEQUENCE-level
|
||||
* complement (over all of Σ*), not a character-class complement, so
|
||||
* collapsing it would change semantics whenever the result is used
|
||||
* in any non-character-class context. Sequence-level rewrites for
|
||||
* re.complement (double-comp, deMorgan, etc.) are handled directly
|
||||
* in seq_rewriter::mk_re_complement.
|
||||
*/
|
||||
bool regex_to_range_predicate(seq_util& u, expr* r, range_predicate& out);
|
||||
|
||||
/**
|
||||
* Canonical materialization of p as a regex AST over the given
|
||||
* sequence sort. Two range_predicates with equal canonical
|
||||
* representations produce structurally identical regex ASTs:
|
||||
*
|
||||
* empty -> re.empty
|
||||
* top -> re.full_char_set
|
||||
* single range [lo, hi] -> re.range "lo" "hi"
|
||||
* multiple ranges -> right-associated re.union of single
|
||||
* ranges, in increasing order of lo
|
||||
* (matching the canonical range order
|
||||
* held by range_predicate).
|
||||
*/
|
||||
expr_ref range_predicate_to_regex(seq_util& u, range_predicate const& p, sort* seq_sort);
|
||||
|
||||
}
|
||||
292
src/ast/rewriter/seq_range_predicate.cpp
Normal file
292
src/ast/rewriter/seq_range_predicate.cpp
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_range_predicate.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of the specialized range-algebra used by symbolic
|
||||
derivative computation and regex rewriting. See seq_range_predicate.h
|
||||
for the algebraic specification.
|
||||
|
||||
All Boolean operations are implemented as single linear sweeps over
|
||||
the canonical sorted range vectors and produce canonical output
|
||||
(sorted, disjoint, non-adjacent).
|
||||
|
||||
Authors:
|
||||
|
||||
Margus Veanes (veanes) 2026
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/rewriter/seq_range_predicate.h"
|
||||
#include "util/debug.h"
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
|
||||
namespace seq {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Factories
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
range_predicate range_predicate::empty(unsigned max_char) {
|
||||
return range_predicate(max_char);
|
||||
}
|
||||
|
||||
range_predicate range_predicate::top(unsigned max_char) {
|
||||
range_predicate r(max_char);
|
||||
r.m_ranges.push_back({0u, max_char});
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::singleton(unsigned c, unsigned max_char) {
|
||||
SASSERT(c <= max_char);
|
||||
range_predicate r(max_char);
|
||||
r.m_ranges.push_back({c, c});
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::range(unsigned lo, unsigned hi, unsigned max_char) {
|
||||
range_predicate r(max_char);
|
||||
if (lo <= hi && lo <= max_char) {
|
||||
unsigned clipped_hi = hi <= max_char ? hi : max_char;
|
||||
r.m_ranges.push_back({lo, clipped_hi});
|
||||
}
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Invariants and observers
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
bool range_predicate::well_formed() const {
|
||||
for (unsigned i = 0; i < m_ranges.size(); ++i) {
|
||||
auto [lo, hi] = m_ranges[i];
|
||||
if (lo > hi) return false;
|
||||
if (hi > m_max_char) return false;
|
||||
if (i > 0) {
|
||||
unsigned prev_hi = m_ranges[i - 1].second;
|
||||
// Non-adjacent and sorted: prev_hi + 1 < lo, with care
|
||||
// around prev_hi == UINT_MAX which we never expect because
|
||||
// hi <= m_max_char.
|
||||
if (prev_hi + 1 >= lo) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool range_predicate::contains(unsigned c) const {
|
||||
// Binary search on first element of pairs.
|
||||
unsigned lo = 0, hi = m_ranges.size();
|
||||
while (lo < hi) {
|
||||
unsigned mid = lo + (hi - lo) / 2;
|
||||
auto [a, b] = m_ranges[mid];
|
||||
if (c < a) hi = mid;
|
||||
else if (c > b) lo = mid + 1;
|
||||
else return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t range_predicate::cardinality() const {
|
||||
uint64_t n = 0;
|
||||
for (auto [lo, hi] : m_ranges)
|
||||
n += static_cast<uint64_t>(hi) - static_cast<uint64_t>(lo) + 1u;
|
||||
return n;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Equality, ordering, hashing
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
bool range_predicate::equals(range_predicate const& o) const {
|
||||
if (m_max_char != o.m_max_char) return false;
|
||||
if (m_ranges.size() != o.m_ranges.size()) return false;
|
||||
for (unsigned i = 0; i < m_ranges.size(); ++i)
|
||||
if (m_ranges[i] != o.m_ranges[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool range_predicate::operator<(range_predicate const& o) const {
|
||||
if (m_max_char != o.m_max_char)
|
||||
return m_max_char < o.m_max_char;
|
||||
unsigned n = std::min(m_ranges.size(), o.m_ranges.size());
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
auto a = m_ranges[i];
|
||||
auto b = o.m_ranges[i];
|
||||
if (a.first != b.first) return a.first < b.first;
|
||||
if (a.second != b.second) return a.second < b.second;
|
||||
}
|
||||
return m_ranges.size() < o.m_ranges.size();
|
||||
}
|
||||
|
||||
unsigned range_predicate::hash() const {
|
||||
// FNV-1a 32-bit over (max_char, then each (lo, hi)).
|
||||
uint32_t h = 2166136261u;
|
||||
auto step = [&](uint32_t x) {
|
||||
h ^= x;
|
||||
h *= 16777619u;
|
||||
};
|
||||
step(m_max_char);
|
||||
for (auto [lo, hi] : m_ranges) {
|
||||
step(lo);
|
||||
step(hi);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Boolean operations
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
// Append (lo, hi) to result, merging with the previous range if
|
||||
// adjacent or overlapping. Maintains canonical form.
|
||||
inline void append_merged(svector<std::pair<unsigned, unsigned>>& result,
|
||||
unsigned lo, unsigned hi) {
|
||||
SASSERT(lo <= hi);
|
||||
if (!result.empty() && result.back().second + 1 >= lo) {
|
||||
if (result.back().second < hi)
|
||||
result.back().second = hi;
|
||||
} else {
|
||||
result.push_back({lo, hi});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
range_predicate range_predicate::operator|(range_predicate const& o) const {
|
||||
SASSERT(m_max_char == o.m_max_char);
|
||||
range_predicate r(m_max_char);
|
||||
unsigned i = 0, j = 0;
|
||||
const unsigned n = m_ranges.size();
|
||||
const unsigned m = o.m_ranges.size();
|
||||
while (i < n && j < m) {
|
||||
auto a = m_ranges[i];
|
||||
auto b = o.m_ranges[j];
|
||||
if (a.first <= b.first) {
|
||||
append_merged(r.m_ranges, a.first, a.second);
|
||||
++i;
|
||||
} else {
|
||||
append_merged(r.m_ranges, b.first, b.second);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
while (i < n) {
|
||||
auto a = m_ranges[i++];
|
||||
append_merged(r.m_ranges, a.first, a.second);
|
||||
}
|
||||
while (j < m) {
|
||||
auto b = o.m_ranges[j++];
|
||||
append_merged(r.m_ranges, b.first, b.second);
|
||||
}
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::operator&(range_predicate const& o) const {
|
||||
SASSERT(m_max_char == o.m_max_char);
|
||||
range_predicate r(m_max_char);
|
||||
unsigned i = 0, j = 0;
|
||||
const unsigned n = m_ranges.size();
|
||||
const unsigned m = o.m_ranges.size();
|
||||
while (i < n && j < m) {
|
||||
auto [a_lo, a_hi] = m_ranges[i];
|
||||
auto [b_lo, b_hi] = o.m_ranges[j];
|
||||
unsigned lo = std::max(a_lo, b_lo);
|
||||
unsigned hi = std::min(a_hi, b_hi);
|
||||
if (lo <= hi)
|
||||
r.m_ranges.push_back({lo, hi});
|
||||
// Advance the range that ends first.
|
||||
if (a_hi < b_hi) ++i;
|
||||
else if (b_hi < a_hi) ++j;
|
||||
else { ++i; ++j; }
|
||||
}
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::operator~() const {
|
||||
range_predicate r(m_max_char);
|
||||
unsigned cursor = 0;
|
||||
for (auto [lo, hi] : m_ranges) {
|
||||
if (cursor < lo)
|
||||
r.m_ranges.push_back({cursor, lo - 1});
|
||||
// Step past hi without overflow: hi <= m_max_char and we
|
||||
// only step when more characters remain.
|
||||
if (hi >= m_max_char) {
|
||||
cursor = m_max_char + 1; // sentinel: no more characters
|
||||
break;
|
||||
}
|
||||
cursor = hi + 1;
|
||||
}
|
||||
if (cursor <= m_max_char)
|
||||
r.m_ranges.push_back({cursor, m_max_char});
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::operator-(range_predicate const& o) const {
|
||||
SASSERT(m_max_char == o.m_max_char);
|
||||
// A - B by linear sweep: for each range of A, subtract overlapping
|
||||
// ranges of B. Both inputs are sorted so we advance j monotonically.
|
||||
range_predicate r(m_max_char);
|
||||
unsigned j = 0;
|
||||
const unsigned m = o.m_ranges.size();
|
||||
for (auto [a_lo, a_hi] : m_ranges) {
|
||||
unsigned cursor = a_lo;
|
||||
while (j < m && o.m_ranges[j].second < cursor)
|
||||
++j;
|
||||
unsigned k = j;
|
||||
while (k < m && o.m_ranges[k].first <= a_hi) {
|
||||
auto [b_lo, b_hi] = o.m_ranges[k];
|
||||
if (cursor < b_lo)
|
||||
r.m_ranges.push_back({cursor, std::min(a_hi, b_lo - 1)});
|
||||
if (b_hi >= a_hi) {
|
||||
cursor = a_hi + 1;
|
||||
break;
|
||||
}
|
||||
cursor = b_hi + 1;
|
||||
++k;
|
||||
}
|
||||
if (cursor <= a_hi)
|
||||
r.m_ranges.push_back({cursor, a_hi});
|
||||
}
|
||||
SASSERT(r.well_formed());
|
||||
return r;
|
||||
}
|
||||
|
||||
range_predicate range_predicate::operator^(range_predicate const& o) const {
|
||||
SASSERT(m_max_char == o.m_max_char);
|
||||
// (A | B) - (A & B), but implemented directly with one linear sweep
|
||||
// over the union of breakpoints.
|
||||
return (*this | o) - (*this & o);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Display
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
std::ostream& range_predicate::display(std::ostream& out) const {
|
||||
if (m_ranges.empty()) {
|
||||
return out << "[]";
|
||||
}
|
||||
out << "[";
|
||||
bool first = true;
|
||||
for (auto [lo, hi] : m_ranges) {
|
||||
if (!first) out << ",";
|
||||
first = false;
|
||||
if (lo == hi)
|
||||
out << lo;
|
||||
else
|
||||
out << lo << "-" << hi;
|
||||
}
|
||||
return out << "]";
|
||||
}
|
||||
|
||||
}
|
||||
127
src/ast/rewriter/seq_range_predicate.h
Normal file
127
src/ast/rewriter/seq_range_predicate.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_range_predicate.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Specialized range-algebra over an unsigned character domain [0, max_char].
|
||||
|
||||
A range_predicate represents a subset of the character domain as a
|
||||
sorted sequence of non-overlapping, non-adjacent, non-empty ranges:
|
||||
|
||||
[(lo_0, hi_0), (lo_1, hi_1), ...] with hi_i + 1 < lo_{i+1}.
|
||||
|
||||
The representation is canonical, so two range_predicates over the same
|
||||
domain are extensionally equivalent iff their internal vectors are
|
||||
elementwise equal.
|
||||
|
||||
All Boolean operations (union, intersection, complement, difference)
|
||||
are linear in the total number of ranges and produce the canonical
|
||||
representation.
|
||||
|
||||
Intended use:
|
||||
* path conditions for symbolic derivative computation,
|
||||
* OneStep predicates capturing length-1 acceptance,
|
||||
* smart-constructor side conditions for regex rewrites such as
|
||||
R & psi --> toregex(OneStep(R) & psi).
|
||||
|
||||
The type is a pure value: no ast_manager allocation occurs in its
|
||||
construction or its Boolean operations. Conversion to and from
|
||||
expr* is the responsibility of a separate translator (see callers
|
||||
in seq_derive / seq_rewriter).
|
||||
|
||||
Authors:
|
||||
|
||||
Margus Veanes (veanes) 2026
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "util/vector.h"
|
||||
#include <iosfwd>
|
||||
#include <utility>
|
||||
|
||||
namespace seq {
|
||||
|
||||
class range_predicate {
|
||||
using range_t = std::pair<unsigned, unsigned>;
|
||||
using ranges_t = svector<range_t>;
|
||||
|
||||
// Sorted by first; ranges are disjoint and non-adjacent;
|
||||
// every range satisfies lo <= hi <= m_max_char.
|
||||
ranges_t m_ranges;
|
||||
unsigned m_max_char { 0 };
|
||||
|
||||
// Invariant check used in debug builds.
|
||||
bool well_formed() const;
|
||||
|
||||
public:
|
||||
range_predicate() = default;
|
||||
explicit range_predicate(unsigned max_char) : m_max_char(max_char) {}
|
||||
|
||||
// ---------------- Factory functions ----------------
|
||||
|
||||
static range_predicate empty(unsigned max_char);
|
||||
static range_predicate top(unsigned max_char);
|
||||
static range_predicate singleton(unsigned c, unsigned max_char);
|
||||
static range_predicate range(unsigned lo, unsigned hi, unsigned max_char);
|
||||
|
||||
// ---------------- Observers ----------------
|
||||
|
||||
unsigned max_char() const { return m_max_char; }
|
||||
unsigned num_ranges() const { return m_ranges.size(); }
|
||||
range_t operator[](unsigned i) const { return m_ranges[i]; }
|
||||
ranges_t const& ranges() const { return m_ranges; }
|
||||
|
||||
bool is_empty() const { return m_ranges.empty(); }
|
||||
bool is_top() const {
|
||||
return m_ranges.size() == 1
|
||||
&& m_ranges[0].first == 0
|
||||
&& m_ranges[0].second == m_max_char;
|
||||
}
|
||||
bool is_singleton(unsigned& c) const {
|
||||
if (m_ranges.size() != 1) return false;
|
||||
if (m_ranges[0].first != m_ranges[0].second) return false;
|
||||
c = m_ranges[0].first;
|
||||
return true;
|
||||
}
|
||||
bool contains(unsigned c) const;
|
||||
|
||||
// Number of characters in the predicate (well-defined for any domain).
|
||||
uint64_t cardinality() const;
|
||||
|
||||
// ---------------- Equality, ordering, hashing ----------------
|
||||
|
||||
bool equals(range_predicate const& o) const;
|
||||
bool operator==(range_predicate const& o) const { return equals(o); }
|
||||
bool operator!=(range_predicate const& o) const { return !equals(o); }
|
||||
|
||||
// Total order: lexicographic on the canonical range sequence,
|
||||
// with shorter sequences ordered before longer prefixes.
|
||||
// Predicates over different domains compare by max_char first.
|
||||
bool operator<(range_predicate const& o) const;
|
||||
bool less_than(range_predicate const& o) const { return *this < o; }
|
||||
|
||||
unsigned hash() const;
|
||||
|
||||
// ---------------- Boolean operations ----------------
|
||||
|
||||
range_predicate operator|(range_predicate const& o) const; // union
|
||||
range_predicate operator&(range_predicate const& o) const; // intersection
|
||||
range_predicate operator-(range_predicate const& o) const; // difference
|
||||
range_predicate operator^(range_predicate const& o) const; // symmetric diff
|
||||
range_predicate operator~() const; // complement
|
||||
|
||||
// ---------------- Display ----------------
|
||||
|
||||
std::ostream& display(std::ostream& out) const;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, range_predicate const& p) {
|
||||
return p.display(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -85,41 +85,6 @@ namespace seq {
|
|||
return is_ground(r);
|
||||
}
|
||||
|
||||
/*
|
||||
Collect the leaves of a t-regex der (an ITE / antimirov union /
|
||||
union-tree with regex leaves) into the output vector. Empty
|
||||
(re.empty) leaves are dropped.
|
||||
|
||||
Returns false if we encountered an unexpected node (e.g. a free
|
||||
variable creeping in) — in that case the caller should bail out.
|
||||
*/
|
||||
bool regex_bisim::collect_leaves(expr* der, expr_ref_vector& leaves) {
|
||||
ptr_vector<expr> work;
|
||||
obj_hashtable<expr> seen;
|
||||
work.push_back(der);
|
||||
seen.insert(der);
|
||||
while (!work.empty()) {
|
||||
expr* e = work.back();
|
||||
work.pop_back();
|
||||
expr* c = nullptr, * t = nullptr, * f = nullptr;
|
||||
if (m.is_ite(e, c, t, f) ||
|
||||
m_util.re.is_union(e, t, f) ||
|
||||
m_util.re.is_antimirov_union(e, t, f)) {
|
||||
if (seen.insert_if_not_there(t))
|
||||
work.push_back(t);
|
||||
if (seen.insert_if_not_there(f))
|
||||
work.push_back(f);
|
||||
continue;
|
||||
}
|
||||
if (m_util.re.is_empty(e))
|
||||
continue;
|
||||
if (!m_util.is_re(e))
|
||||
return false;
|
||||
leaves.push_back(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Fast inequivalence check based on the get_info().classical flag.
|
||||
|
||||
|
|
@ -228,15 +193,19 @@ namespace seq {
|
|||
m_worklist.pop_back();
|
||||
|
||||
// Compute the symbolic derivative wrt the canonical variable
|
||||
// (:var 0). The result is a transition regex (ITE tree) whose
|
||||
// leaves are regex expressions. We use the classical Brzozowski
|
||||
// entry point so the derivative stays as a single TRegex and
|
||||
// does not lift unions to the top via antimirov nodes — this
|
||||
// preserves the XOR-pair invariant the bisimulation relies on.
|
||||
expr_ref d(m_rw.mk_brz_derivative(r), m);
|
||||
// (:var 0) and enumerate its reachable leaves in fully
|
||||
// ITE-hoisted normal form. Every if-then-else over the input
|
||||
// character — even one that would otherwise be buried under a
|
||||
// concat or union — is hoisted to the top and infeasible
|
||||
// minterms are pruned, so each leaf is a ground regex free of
|
||||
// (:var 0) whose nullability is always decidable. Unions are
|
||||
// kept intact as single leaves (a union leaf denotes a single
|
||||
// bisimulation state, never a split into separate states).
|
||||
expr_ref_pair_vector cofs(m);
|
||||
m_rw.brz_derivative_cofactors(r, cofs);
|
||||
expr_ref_vector leaves(m);
|
||||
if (!collect_leaves(d, leaves))
|
||||
return l_undef;
|
||||
for (auto const& p : cofs)
|
||||
leaves.push_back(p.second);
|
||||
|
||||
// First pass: check for any nullable leaf (definitive
|
||||
// distinguishing empty-continuation word) or any classically
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ namespace seq {
|
|||
|
||||
unsigned node_of(expr* r);
|
||||
bool merge_leaf(expr* xor_pair);
|
||||
bool collect_leaves(expr* der, expr_ref_vector& leaves);
|
||||
lbool nullability(expr* r);
|
||||
bool is_supported(expr* r);
|
||||
// Returns true if the leaf l proves that the original pair is
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,9 @@ Notes:
|
|||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "seq_split.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/rewriter/seq_derive.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/rewriter/rewriter_types.h"
|
||||
|
|
@ -129,16 +131,21 @@ class seq_rewriter {
|
|||
void insert(decl_kind op, expr* a, expr* b, expr* c, expr* r);
|
||||
};
|
||||
|
||||
friend class seq::derive;
|
||||
|
||||
seq_util m_util;
|
||||
seq_subset m_subset;
|
||||
seq_split m_split;
|
||||
arith_util m_autil;
|
||||
bool_rewriter m_br;
|
||||
seq::derive m_derive;
|
||||
// re2automaton m_re2aut;
|
||||
op_cache m_op_cache;
|
||||
expr_ref_vector m_es, m_lhs, m_rhs;
|
||||
bool m_coalesce_chars;
|
||||
bool m_in_bisim { false };
|
||||
bool m_coalesce_chars = true;
|
||||
bool m_in_bisim { false };
|
||||
unsigned m_re_deriv_depth { 0 };
|
||||
static const unsigned m_max_re_deriv_depth = 512;
|
||||
|
||||
enum length_comparison {
|
||||
shorter_c,
|
||||
|
|
@ -175,50 +182,22 @@ class seq_rewriter {
|
|||
//replace b in a by c into result
|
||||
void replace_all_subvectors(expr_ref_vector const& as, expr_ref_vector const& bs, expr* c, expr_ref_vector& result);
|
||||
|
||||
// Calculate derivative, memoized and enforcing a normal form
|
||||
expr_ref is_nullable_rec(expr* r);
|
||||
expr_ref mk_derivative_rec(expr* ele, expr* r);
|
||||
expr_ref mk_der_op(decl_kind k, expr* a, expr* b);
|
||||
expr_ref mk_der_op_rec(decl_kind k, expr* a, expr* b);
|
||||
expr_ref mk_der_concat(expr* a, expr* b);
|
||||
expr_ref mk_der_union(expr* a, expr* b);
|
||||
expr_ref mk_der_inter(expr* a, expr* b);
|
||||
expr_ref mk_der_xor(expr* a, expr* b);
|
||||
expr_ref mk_der_compl(expr* a);
|
||||
expr_ref mk_der_cond(expr* cond, expr* ele, sort* seq_sort);
|
||||
expr_ref mk_der_antimirov_union(expr* r1, expr* r2);
|
||||
bool ite_bdds_compatible(expr* a, expr* b);
|
||||
/* if r has the form deriv(en..deriv(e1,to_re(s))..) returns 's = [e1..en]' else returns '() in r'*/
|
||||
expr_ref is_nullable_symbolic_regex(expr* r, sort* seq_sort);
|
||||
#ifdef Z3DEBUG
|
||||
bool check_deriv_normal_form(expr* r, int level = 3);
|
||||
#endif
|
||||
// For replace_all(x, a, b) in R: transform R so that
|
||||
// - occurrences of b_ch are replaced by union(to_re(a_str), to_re(b_str))
|
||||
// - occurrences of a_ch are replaced by empty (replace_all never outputs a)
|
||||
expr_ref re_replace_char(expr *r, unsigned a_ch, unsigned b_ch, expr *a_str, expr *b_str);
|
||||
|
||||
void mk_antimirov_deriv_rec(expr* e, expr* r, expr* path, expr_ref& result);
|
||||
|
||||
expr_ref mk_antimirov_deriv(expr* e, expr* r, expr* path);
|
||||
expr_ref mk_in_antimirov_rec(expr* s, expr* d);
|
||||
expr_ref mk_in_antimirov(expr* s, expr* d);
|
||||
|
||||
expr_ref mk_antimirov_deriv_intersection(expr* elem, expr* d1, expr* d2, expr* path);
|
||||
expr_ref mk_antimirov_deriv_concat(expr* d, expr* r);
|
||||
expr_ref mk_antimirov_deriv_negate(expr* elem, expr* d);
|
||||
expr_ref mk_antimirov_deriv_union(expr* d1, expr* d2);
|
||||
expr_ref mk_antimirov_deriv_restrict(expr* elem, expr* d1, expr* cond);
|
||||
expr_ref mk_regex_reverse(expr* r);
|
||||
expr_ref mk_regex_concat(expr* r1, expr* r2);
|
||||
|
||||
expr_ref merge_regex_sets(expr* r1, expr* r2, expr* unit, std::function<bool(expr*, expr*&, expr*&)>& decompose, std::function<expr* (expr*, expr*)>& compose);
|
||||
|
||||
// elem is (:var 0) and path a condition that may have (:var 0) as a free variable
|
||||
// simplify path, e.g., (:var 0) = 'a' & (:var 0) = 'b' is simplified to false
|
||||
expr_ref simplify_path(expr* elem, expr* path);
|
||||
// expr_ref simplify_path(expr* elem, expr* path);
|
||||
|
||||
bool lt_char(expr* ch1, expr* ch2);
|
||||
bool eq_char(expr* ch1, expr* ch2);
|
||||
bool neq_char(expr* ch1, expr* ch2);
|
||||
bool le_char(expr* ch1, expr* ch2);
|
||||
bool pred_implies(expr* a, expr* b);
|
||||
bool are_complements(expr* r1, expr* r2) const;
|
||||
bool is_subset(expr* r1, expr* r2) const;
|
||||
|
||||
|
|
@ -264,6 +243,14 @@ class seq_rewriter {
|
|||
br_status mk_re_union0(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_re_inter0(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_re_complement(expr* a, expr_ref& result);
|
||||
// Range-set collapse helpers: if the operands form a boolean
|
||||
// combination of character-class regexes, materialize the result as a
|
||||
// canonical regex over a single range_predicate. See
|
||||
// ast/rewriter/seq_range_collapse.h for the recognized fragment.
|
||||
// NOTE: re.complement is intentionally not in this set because it
|
||||
// operates at the sequence level, not the character-class level.
|
||||
bool try_collapse_re_union(expr* a, expr* b, expr_ref& result);
|
||||
bool try_collapse_re_inter(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_re_star(expr* a, expr_ref& result);
|
||||
br_status mk_re_diff(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_re_xor(expr* a, expr* b, expr_ref& result);
|
||||
|
|
@ -347,10 +334,10 @@ class seq_rewriter {
|
|||
lbool some_string_in_re(expr_mark& visited, expr* r, unsigned_vector& str);
|
||||
|
||||
public:
|
||||
seq_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m), m_subset(m_util.re), m_split(*this), m_autil(m), m_br(m, p), // m_re2aut(m),
|
||||
seq_rewriter(ast_manager & m, params_ref const & p = params_ref()) :
|
||||
m_util(m), m_subset(m_util.re), m_split(*this), m_autil(m), m_br(m, p), m_derive(m, *this), // m_re2aut(m),
|
||||
m_op_cache(m), m_es(m),
|
||||
m_lhs(m), m_rhs(m), m_coalesce_chars(true) {
|
||||
m_lhs(m), m_rhs(m) {
|
||||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
|
@ -361,7 +348,7 @@ public:
|
|||
static void get_param_descrs(param_descrs & r);
|
||||
|
||||
|
||||
bool coalesce_chars() const { return m_coalesce_chars; }
|
||||
// bool coalesce_chars() const { return m_coalesce_chars; }
|
||||
|
||||
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
|
||||
|
|
@ -377,6 +364,34 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
expr_ref mk_xor0(expr *a, expr *b) {
|
||||
expr_ref result(m());
|
||||
if (mk_re_xor0(a, b, result) == BR_FAILED)
|
||||
result = re().mk_xor(a, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref mk_union(expr *a, expr *b) {
|
||||
expr_ref result(m());
|
||||
if (mk_re_union(a, b, result) == BR_FAILED)
|
||||
result = re().mk_union(a, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref mk_inter(expr *a, expr *b) {
|
||||
expr_ref result(m());
|
||||
if (mk_re_inter(a, b, result) == BR_FAILED)
|
||||
result = re().mk_inter(a, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref mk_complement(expr *a) {
|
||||
expr_ref result(m());
|
||||
if (mk_re_complement(a, result) == BR_FAILED)
|
||||
result = re().mk_complement(a);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* makes concat and simplifies
|
||||
*/
|
||||
|
|
@ -460,11 +475,35 @@ public:
|
|||
variable v0 = (:var 0). Unlike `mk_derivative` this entry point keeps
|
||||
the symbolic derivative as a single transition regex (TRegex): boolean
|
||||
operators are pushed into the ITE leaves rather than lifted to the top
|
||||
via _OP_RE_ANTIMIROV_UNION. Used by the regex_bisim equivalence
|
||||
as a union. Used by the regex_bisim equivalence
|
||||
procedure which relies on each leaf of D(p XOR q) being a coherent
|
||||
XOR pair (D_v p) XOR (D_v q).
|
||||
*/
|
||||
expr_ref mk_brz_derivative(expr* r);
|
||||
expr_ref mk_brz_derivative(expr *r) {
|
||||
return mk_derivative(r);
|
||||
}
|
||||
|
||||
/*
|
||||
Enumerate the cofactors (min-terms) of a transition regex r taken with
|
||||
respect to ele. Produces (path_condition, leaf_regex) pairs for every
|
||||
feasible path through the ITE-tree, pruning infeasible character ranges.
|
||||
Delegates to the derivative engine so the same path/interval context used
|
||||
while hoisting ITEs is reused for the leaf simplification.
|
||||
*/
|
||||
void get_cofactors(expr* ele, expr* r, expr_ref_pair_vector& result) {
|
||||
m_derive.get_cofactors(ele, r, result);
|
||||
}
|
||||
|
||||
/*
|
||||
Compute the symbolic derivative of r and enumerate its reachable leaves
|
||||
in fully ITE-hoisted normal form: a list of (path_condition, target)
|
||||
pairs where every target is free of (:var 0) (so nullability is always
|
||||
decidable) and unions are kept intact as single states. Used by
|
||||
regex_bisim, which consumes the targets and ignores the path conditions.
|
||||
*/
|
||||
void brz_derivative_cofactors(expr* r, expr_ref_pair_vector& result) {
|
||||
m_derive.derivative_cofactors(r, result);
|
||||
}
|
||||
|
||||
// heuristic elimination of element from condition that comes form a derivative.
|
||||
// special case optimization for conjunctions of equalities, disequalities and ranges.
|
||||
|
|
@ -475,15 +514,7 @@ public:
|
|||
/* Apply simplifications to the intersection to keep it normalized (r1 and r2 are not normalized)*/
|
||||
expr_ref mk_regex_inter_normalize(expr* r1, expr* r2);
|
||||
|
||||
/*
|
||||
* Extract some sequence that is a member of r.
|
||||
* result is set to a concrete sequence expression if l_true is returned.
|
||||
* For string-typed regexes, delegates to some_string_in_re.
|
||||
* For other sequence types, checks nullability and returns the empty
|
||||
* sequence if the regex accepts it; otherwise returns l_undef.
|
||||
* Returns l_false if the regex is known to be empty.
|
||||
*/
|
||||
lbool some_seq_in_re(expr* r, expr_ref& result);
|
||||
expr_ref mk_regex_concat(expr *r1, expr *r2);
|
||||
|
||||
/*
|
||||
* Extract some string that is a member of r.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Author:
|
|||
|
||||
bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
||||
while (true) {
|
||||
|
||||
|
||||
if (a == b)
|
||||
return true;
|
||||
if (m_re.is_empty(a))
|
||||
|
|
@ -30,7 +30,7 @@ bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
|||
return true;
|
||||
|
||||
if (depth >= m_max_depth)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
expr* a1 = nullptr, * a2 = nullptr, * b1 = nullptr, * b2 = nullptr;
|
||||
unsigned la, ua, lb, ub;
|
||||
|
|
@ -39,16 +39,12 @@ bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
|||
if (m_re.is_dot_plus(b) && m_re.get_info(a).nullable == l_false)
|
||||
return true;
|
||||
|
||||
// a ⊆ a*
|
||||
if (m_re.is_star(b, b1) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
||||
// e ⊆ a*
|
||||
if (m_re.is_epsilon(a) && m_re.is_star(b, b1))
|
||||
return true;
|
||||
|
||||
// R ⊆ R*
|
||||
if (m_re.is_star(b, b1) && is_subset_rec(a, b1, depth + 1))
|
||||
// a ⊆ a*: if b = b1* and a ⊆ b1, then a ⊆ b1*
|
||||
if (m_re.is_star(b, b1) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
||||
// R1* ⊆ R2* if R1 ⊆ R2
|
||||
|
|
@ -112,6 +108,12 @@ bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
|||
if (m_re.is_concat(b, b1, b2) && m_re.is_full_seq(b1) && is_subset_rec(a, b2, depth))
|
||||
return true;
|
||||
|
||||
// prefix absorption: P·R' ⊆ Σ*·R' for any prefix P (since P ⊆ Σ*).
|
||||
// Detect that a has R' (= b2) as a concatenation suffix, where b = Σ*·R'.
|
||||
// Covers contains-patterns, e.g. Σ*·a·Σ*·b·Σ* ⊆ Σ*·b·Σ*.
|
||||
if (m_re.is_concat(b, b1, b2) && m_re.is_full_seq(b1) && ends_with(a, b2))
|
||||
return true;
|
||||
|
||||
// R ⊆ R'·Σ* if R ⊆ R'
|
||||
if (m_re.is_concat(b, b1, b2) && m_re.is_full_seq(b2) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
|
@ -144,3 +146,30 @@ bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
|||
bool seq_subset::is_subset(expr* a, expr* b) const {
|
||||
return is_subset_rec(a, b, 0);
|
||||
}
|
||||
|
||||
bool seq_subset::ends_with(expr* a, expr* suf) const {
|
||||
if (a == suf)
|
||||
return true;
|
||||
// Flatten both regexes into their sequence of concatenation factors
|
||||
// (independent of left/right associativity) and test list-suffix equality.
|
||||
ptr_vector<expr> af, sf;
|
||||
flatten_concat(a, af);
|
||||
flatten_concat(suf, sf);
|
||||
if (sf.size() > af.size())
|
||||
return false;
|
||||
unsigned off = af.size() - sf.size();
|
||||
for (unsigned i = 0; i < sf.size(); ++i)
|
||||
if (af[off + i] != sf[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void seq_subset::flatten_concat(expr* a, ptr_vector<expr>& out) const {
|
||||
expr* a1 = nullptr, * a2 = nullptr;
|
||||
if (m_re.is_concat(a, a1, a2)) {
|
||||
flatten_concat(a1, out);
|
||||
flatten_concat(a2, out);
|
||||
}
|
||||
else
|
||||
out.push_back(a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ class seq_subset {
|
|||
|
||||
bool is_subset_rec(expr* a, expr* b, unsigned depth) const;
|
||||
|
||||
// true if regex a, viewed as a flattened concatenation, has suf as a
|
||||
// structural (concatenation) suffix.
|
||||
bool ends_with(expr* a, expr* suf) const;
|
||||
|
||||
void flatten_concat(expr* a, ptr_vector<expr>& out) const;
|
||||
|
||||
public:
|
||||
explicit seq_subset(seq_util::rex& re) : m_re(re) {}
|
||||
bool is_subset(expr* a, expr* b) const;
|
||||
|
|
|
|||
681
src/ast/rewriter/term_enumeration.cpp
Normal file
681
src/ast/rewriter/term_enumeration.cpp
Normal file
|
|
@ -0,0 +1,681 @@
|
|||
/**
|
||||
* term_enumeration.cpp - Bottom-up term enumeration module for Z3
|
||||
*
|
||||
* Inspired by the Probe synthesizer (Barke et al., "Just-in-Time Learning
|
||||
* for Bottom-Up Enumerative Synthesis"). Adapted to use Z3's internal APIs.
|
||||
*
|
||||
* Key ideas:
|
||||
* - Terms are enumerated bottom-up by "cost" (calculated by tree size).
|
||||
* - A grammar describes which function symbols (operators) and leaves
|
||||
* (constants, variables) are available for enumeration.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include "util/vector.h"
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "util/uint_set.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/term_enumeration.h"
|
||||
|
||||
|
||||
namespace term_enum {
|
||||
|
||||
// ============================================================================
|
||||
// grammar production rule
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* A production describes how to construct a term from child terms.
|
||||
* - domain: the sort required for each child
|
||||
* - range: the sort of the produced term
|
||||
* - builder: given a vector of child exprs, produce the result expr
|
||||
*/
|
||||
struct production {
|
||||
std::string name;
|
||||
sort_ref range;
|
||||
sort_ref_vector domain;
|
||||
std::function<expr_ref(expr_ref_vector const&)> builder;
|
||||
|
||||
bool is_leaf() const { return domain.empty(); }
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// grammar
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* A grammar groups productions into leaves (arity 0) and operators (arity > 0).
|
||||
*/
|
||||
class grammar {
|
||||
public:
|
||||
grammar(ast_manager& m) : m(m), m_pinned(m) {}
|
||||
|
||||
void add_production(production* p) {
|
||||
if (p->is_leaf())
|
||||
m_leaves.push_back(p);
|
||||
else
|
||||
m_operators.push_back(p);
|
||||
}
|
||||
|
||||
scoped_ptr_vector<production> const& leaves() const { return m_leaves; }
|
||||
scoped_ptr_vector<production> const& operators() const { return m_operators; }
|
||||
ast_manager& mgr() const { return m; }
|
||||
|
||||
void add_func_decl(func_decl *f) {
|
||||
if (m_seen.contains(f))
|
||||
return;
|
||||
m_pinned.push_back(f);
|
||||
m_seen.insert(f);
|
||||
sort_ref range(f->get_range(), m);
|
||||
sort_ref_vector dom(m);
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i)
|
||||
dom.push_back(sort_ref(f->get_domain(i), m));
|
||||
add_production(alloc(production, {f->get_name().str(), range, dom, [this, f](expr_ref_vector const &args) {
|
||||
return expr_ref(m.mk_app(f, args), m);
|
||||
}}));
|
||||
}
|
||||
|
||||
void add_expr(expr *e) {
|
||||
if (m_seen.contains(e))
|
||||
return;
|
||||
m_pinned.push_back(e);
|
||||
m_seen.insert(e);
|
||||
sort_ref range(e->get_sort(), m);
|
||||
sort_ref_vector dom(m);
|
||||
std::stringstream ss;
|
||||
ss << mk_bounded_pp(e, m);
|
||||
std::string name = ss.str();
|
||||
add_production(alloc(production, {name, range, dom, [this, e](expr_ref_vector const&) { return expr_ref(e, m); }}));
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
out << "Leaves:\n";
|
||||
for (auto const *p : m_leaves) {
|
||||
out << " " << p->name << " : " << mk_pp(p->range, m) << "\n";
|
||||
}
|
||||
out << "Operators:\n";
|
||||
for (auto const *p : m_operators) {
|
||||
out << " " << p->name << " : (";
|
||||
for (unsigned i = 0; i < p->domain.size(); ++i) {
|
||||
if (i > 0)
|
||||
out << ", ";
|
||||
out << mk_pp(p->domain[i], m);
|
||||
}
|
||||
out << ") -> " << mk_pp(p->range, m) << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
ast_manager& m;
|
||||
ast_ref_vector m_pinned;
|
||||
scoped_ptr_vector<production> m_leaves;
|
||||
scoped_ptr_vector<production> m_operators;
|
||||
obj_hashtable<ast> m_seen;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Term Bank - stores enumerated terms by cost and sort
|
||||
// ============================================================================
|
||||
|
||||
using cost_terms = vector<std::pair<expr*, unsigned>>;
|
||||
|
||||
class term_bank {
|
||||
using sort_term_map = obj_map<sort, ptr_vector<expr>>;
|
||||
public:
|
||||
term_bank(ast_manager& m) : m(m), m_pinned(m) {}
|
||||
|
||||
~term_bank() {
|
||||
for (auto s : m_terms)
|
||||
dealloc(s);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_pinned.reset();
|
||||
m_terms.clear();
|
||||
}
|
||||
|
||||
void add(expr* term, unsigned cost) {
|
||||
sort* s = term->get_sort();
|
||||
m_pinned.push_back(term);
|
||||
if (cost >= m_terms.size())
|
||||
m_terms.resize(cost + 1);
|
||||
if (!m_terms[cost])
|
||||
m_terms[cost] = alloc(sort_term_map);
|
||||
m_terms[cost]->insert_if_not_there(s, ptr_vector<expr>()).push_back(term);
|
||||
}
|
||||
|
||||
/** Get all terms of a given sort up to (and including) max_cost */
|
||||
cost_terms get_by_sort(sort* s, unsigned max_cost) const {
|
||||
cost_terms result;
|
||||
for (unsigned c = 0; c <= max_cost; ++c) {
|
||||
if (c >= m_terms.size())
|
||||
break;
|
||||
if (!m_terms[c]->contains(s))
|
||||
continue;
|
||||
for (auto t : m_terms[c]->find(s))
|
||||
result.push_back({t, c});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return true if there is at least one term at/above `cost` whose sort is
|
||||
// not in `sorts` (i.e., enumeration can still produce a new requested sort).
|
||||
bool is_productive(unsigned cost, uint_set const& sorts) {
|
||||
for (unsigned i = cost; i < m_terms.size(); ++i) {
|
||||
if (!m_terms[i])
|
||||
continue;
|
||||
for (auto const& entry : *m_terms[i]) {
|
||||
sort* term_sort = entry.m_key;
|
||||
if (!sorts.contains(term_sort->get_small_id()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr_vector<expr> null_ptr_vector;
|
||||
ptr_vector<expr> const &get_by_cost_and_sort(unsigned cost, sort *s) const {
|
||||
if (cost >= m_terms.size() || !m_terms[cost] || !m_terms[cost]->contains(s))
|
||||
return null_ptr_vector;
|
||||
return m_terms[cost]->find(s);
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
for (unsigned cost = 0; cost < m_terms.size(); ++cost) {
|
||||
if (!m_terms[cost])
|
||||
continue;
|
||||
out << "cost " << cost << ":\n";
|
||||
for (auto& [s, terms] : *m_terms[cost]) {
|
||||
out << " sort " << mk_pp(s, m) << ":\n";
|
||||
for (expr* e : terms) {
|
||||
out << " #" << e->get_id() << " ";
|
||||
if (cost == 0) {
|
||||
out << mk_bounded_pp(e, m);
|
||||
}
|
||||
else if (is_app(e)) {
|
||||
app* a = to_app(e);
|
||||
out << a->get_decl()->get_name() << "(";
|
||||
bool first = true;
|
||||
for (expr* arg : *a) {
|
||||
if (!first) out << ", ";
|
||||
first = false;
|
||||
out << "#" << arg->get_id();
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
ast_manager& m;
|
||||
expr_ref_vector m_pinned;
|
||||
// cost -> sort -> terms
|
||||
ptr_vector<sort_term_map> m_terms;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Children Iterator - generates all combinations of child terms
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Iterates over all tuples (c1, c2, ..., cn) where each ci has the required
|
||||
* sort, drawn from the term bank, with at least one child at the current
|
||||
* cost - 1 (to avoid regenerating previously seen terms).
|
||||
*/
|
||||
class children_iterator {
|
||||
public:
|
||||
children_iterator(ast_manager& m, production const& prod, term_bank const& bank, unsigned current_cost)
|
||||
: m(m), m_done(false)
|
||||
{
|
||||
m_arity = prod.domain.size();
|
||||
if (m_arity == 0) {
|
||||
m_done = true;
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < m_arity; ++i) {
|
||||
m_candidates.push_back(bank.get_by_sort(prod.domain[i], current_cost - 1));
|
||||
if (m_candidates.back().empty()) {
|
||||
m_done = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_indices.resize(m_arity, 0);
|
||||
}
|
||||
|
||||
bool has_next(unsigned cost) {
|
||||
while (!m_done) {
|
||||
if (m.limit().is_canceled())
|
||||
return false;
|
||||
if (has_child_at_cost(cost))
|
||||
return true;
|
||||
advance();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
expr_ref_vector next(unsigned& cost) {
|
||||
expr_ref_vector result(m);
|
||||
cost = 1;
|
||||
for (unsigned i = 0; i < m_arity; ++i) {
|
||||
auto [e, c] = m_candidates[i].get(m_indices[i]);
|
||||
cost += c;
|
||||
result.push_back(e);
|
||||
}
|
||||
advance();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
ast_manager& m;
|
||||
unsigned m_arity;
|
||||
bool m_done;
|
||||
vector<cost_terms> m_candidates;
|
||||
svector<unsigned> m_indices;
|
||||
|
||||
bool has_child_at_cost(unsigned cost) const {
|
||||
for (unsigned i = 0; i < m_arity; ++i) {
|
||||
auto [e, c] = m_candidates[i].get(m_indices[i]);
|
||||
if (c + 1 == cost)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void advance() {
|
||||
for (auto i = m_arity; i-- > 0;) {
|
||||
m_indices[i]++;
|
||||
if (m_indices[i] < m_candidates[i].size()) return;
|
||||
m_indices[i] = 0;
|
||||
}
|
||||
m_done = true;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// bottom_up_enumerator - the main bottom-up term enumeration engine
|
||||
// ============================================================================
|
||||
|
||||
|
||||
class bottom_up_enumerator {
|
||||
public:
|
||||
bottom_up_enumerator(grammar& grammar)
|
||||
: m_grammar(grammar), m(grammar.mgr()),
|
||||
m_bank(grammar.mgr()), m_pending(grammar.mgr()), m_rewriter(grammar.mgr())
|
||||
{}
|
||||
|
||||
void set_target_sort(sort *s) {
|
||||
m_target_sort = s;
|
||||
}
|
||||
bool has_next() {
|
||||
if (m_pending) return true;
|
||||
m_pending = find_next();
|
||||
return m_pending != nullptr;
|
||||
}
|
||||
|
||||
expr_ref next() {
|
||||
if (!m_pending)
|
||||
m_pending = find_next();
|
||||
expr_ref result(m_pending, m);
|
||||
m_pending = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
term_bank const& bank() const { return m_bank; }
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
m_grammar.display(out);
|
||||
return m_bank.display(out);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_cost = 0;
|
||||
m_leaf_idx = 0;
|
||||
m_op_idx = 0;
|
||||
m_state = State::Leaves;
|
||||
m_bank.reset();
|
||||
m_pending = nullptr;
|
||||
m_rewriter.reset();
|
||||
m_seen_terms.reset();
|
||||
m_children_iter.reset();
|
||||
}
|
||||
|
||||
expr* add_term(expr_ref const& term, unsigned cost) {
|
||||
expr_ref simplified(m);
|
||||
m_rewriter(term, simplified);
|
||||
if (m_seen_terms.contains(simplified))
|
||||
return nullptr;
|
||||
IF_VERBOSE(10, verbose_stream() << "add " << simplified << "\n");
|
||||
m_seen_terms.insert(simplified);
|
||||
m_bank.add(simplified, cost);
|
||||
return simplified;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class State { Leaves, Operators, Done };
|
||||
|
||||
grammar& m_grammar;
|
||||
ast_manager& m;
|
||||
term_bank m_bank;
|
||||
unsigned m_cost = 0;
|
||||
unsigned m_leaf_idx = 0;
|
||||
unsigned m_op_idx = 0;
|
||||
unsigned m_bank_idx = 0;
|
||||
unsigned m_bank_size = 0;
|
||||
bool m_made_progress = false;
|
||||
uint_set m_sorts_produced;
|
||||
State m_state = State::Leaves;
|
||||
expr_ref m_pending;
|
||||
th_rewriter m_rewriter;
|
||||
obj_hashtable<expr> m_seen_terms;
|
||||
std::unique_ptr<children_iterator> m_children_iter;
|
||||
sort *m_target_sort = nullptr;
|
||||
|
||||
bool sort_matches(expr* e) const {
|
||||
return !m_target_sort || e->get_sort() == m_target_sort;
|
||||
}
|
||||
|
||||
expr* find_next() {
|
||||
while (true) {
|
||||
if (m.limit().is_canceled()) {
|
||||
m_state = State::Done;
|
||||
return nullptr;
|
||||
}
|
||||
switch (m_state) {
|
||||
case State::Leaves:
|
||||
while (m_leaf_idx < m_grammar.leaves().size()) {
|
||||
production const &prod = *m_grammar.leaves()[m_leaf_idx];
|
||||
m_leaf_idx++;
|
||||
expr_ref_vector empty_args(m);
|
||||
expr_ref term = prod.builder(empty_args);
|
||||
expr* r = add_term(term, 0);
|
||||
if (r && sort_matches(r))
|
||||
return r;
|
||||
}
|
||||
m_state = State::Operators;
|
||||
m_cost = 1;
|
||||
m_op_idx = 0;
|
||||
m_bank_idx = 0;
|
||||
m_bank_size = get_bank_size();
|
||||
m_made_progress = false;
|
||||
m_sorts_produced.reset();
|
||||
m_children_iter.reset();
|
||||
break;
|
||||
|
||||
case State::Operators: {
|
||||
expr* result = enumerate_operators();
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
m_cost++;
|
||||
m_op_idx = 0;
|
||||
m_bank_idx = 0;
|
||||
m_bank_size = get_bank_size();
|
||||
m_children_iter.reset();
|
||||
if (!m_made_progress && !m_bank.is_productive(m_cost, m_sorts_produced)) {
|
||||
m_state = State::Done;
|
||||
return nullptr;
|
||||
}
|
||||
if (m_sorts_produced.contains(m_target_sort->get_small_id()))
|
||||
m_sorts_produced.reset();
|
||||
m_made_progress = false;
|
||||
break;
|
||||
}
|
||||
case State::Done:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_bank_size() const {
|
||||
auto const &terms = m_bank.get_by_cost_and_sort(m_cost, m_target_sort);
|
||||
return terms.size();
|
||||
}
|
||||
|
||||
expr *enumerate_operators() {
|
||||
auto const &ops = m_grammar.operators();
|
||||
while (true) {
|
||||
if (m.limit().is_canceled())
|
||||
return nullptr;
|
||||
|
||||
// first find terms at m_cost that were already created
|
||||
if (m_bank_idx < m_bank_size) {
|
||||
auto const &terms = m_bank.get_by_cost_and_sort(m_cost, m_target_sort);
|
||||
auto t = terms.get(m_bank_idx);
|
||||
m_bank_idx++;
|
||||
SASSERT(sort_matches(t));
|
||||
return t;
|
||||
}
|
||||
|
||||
// then create new terms using children at cost below current m_cost.
|
||||
if (m_children_iter && m_children_iter->has_next(m_cost)) {
|
||||
unsigned new_cost = 0;
|
||||
expr_ref_vector children = m_children_iter->next(new_cost);
|
||||
production const &prod = *ops[m_op_idx - 1];
|
||||
expr_ref term = prod.builder(children);
|
||||
// IF_VERBOSE(0, verbose_stream() << term << "\n");
|
||||
SASSERT(new_cost >= m_cost);
|
||||
expr* r = add_term(term, new_cost);
|
||||
if (!r)
|
||||
continue;
|
||||
unsigned sort_id = r->get_sort()->get_small_id();
|
||||
if (!m_sorts_produced.contains(sort_id))
|
||||
m_made_progress = true;
|
||||
m_sorts_produced.insert(sort_id);
|
||||
if (sort_matches(r) && new_cost == m_cost) {
|
||||
return r;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_op_idx >= ops.size())
|
||||
return nullptr;
|
||||
|
||||
production const &prod = *ops[m_op_idx];
|
||||
m_op_idx++;
|
||||
m_children_iter = std::make_unique<children_iterator>(m, prod, m_bank, m_cost);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace term_enum
|
||||
|
||||
// ============================================================================
|
||||
// term_enumeration public interface implementation
|
||||
// ============================================================================
|
||||
|
||||
struct term_enumeration::imp {
|
||||
ast_manager& m;
|
||||
term_enum::grammar m_grammar;
|
||||
term_enum::bottom_up_enumerator m_bottom_up_enumerator;
|
||||
std::function<unsigned(expr*)> m_cost;
|
||||
|
||||
imp(ast_manager& m) :
|
||||
m(m), m_grammar(m), m_bottom_up_enumerator(m_grammar) {}
|
||||
|
||||
void add_production(func_decl* f) {
|
||||
m_grammar.add_func_decl(f);
|
||||
}
|
||||
|
||||
void add_production(expr* e) {
|
||||
m_grammar.add_expr(e);
|
||||
}
|
||||
|
||||
void set_cost(std::function<unsigned(expr*)> const& cost) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
return m_bottom_up_enumerator.display(out);
|
||||
}
|
||||
};
|
||||
|
||||
// -- iterator implementation --
|
||||
|
||||
struct term_enumeration::iterator::iter_imp {
|
||||
imp& m_imp;
|
||||
ast_manager & m;
|
||||
sort* m_sort;
|
||||
unsigned m_cost = 0;
|
||||
unsigned m_idx = 0;
|
||||
vector<expr_ref_vector> m_levels;
|
||||
expr_ref m_current;
|
||||
bool m_end;
|
||||
vector<expr_ref_vector> m_vars;
|
||||
vector<ptr_vector<sort>> m_decls;
|
||||
vector<vector<symbol>> m_names;
|
||||
|
||||
iter_imp(imp& i, sort* s) : m_imp(i), m(i.m), m_sort(s), m_current(i.m), m_end(false) {
|
||||
m_imp.m_bottom_up_enumerator.reset();
|
||||
init_sort();
|
||||
advance();
|
||||
}
|
||||
|
||||
// Sentinel constructor
|
||||
iter_imp(imp& i) :
|
||||
m_imp(i), m(i.m), m_sort(nullptr), m_current(i.m), m_end(true) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void init_sort() {
|
||||
array_util autil(m);
|
||||
sort *range = m_sort;
|
||||
|
||||
while (autil.is_array(range)) {
|
||||
m_vars.push_back(expr_ref_vector(m));
|
||||
m_decls.push_back(ptr_vector<sort>());
|
||||
m_names.push_back(vector<symbol>());
|
||||
for (unsigned i = 0; i < get_array_arity(range); ++i) {
|
||||
m_decls.back().push_back(get_array_domain(range, i));
|
||||
m_vars.back().push_back(nullptr);
|
||||
m_names.back().push_back(symbol());
|
||||
}
|
||||
|
||||
expr_ref_vector args(m);
|
||||
args.push_back(m.mk_const("a", range));
|
||||
for (unsigned i = 0; i < m_decls.back().size(); ++i) {
|
||||
args.push_back(m.mk_var(i, m_decls.back().get(i)));
|
||||
}
|
||||
app_ref sel(autil.mk_select(args), m);
|
||||
m_imp.m_grammar.add_func_decl(sel->get_decl());
|
||||
|
||||
range = get_array_range(range);
|
||||
}
|
||||
unsigned n = 0;
|
||||
for (unsigned i = m_decls.size(); i-- > 0;) {
|
||||
for (unsigned j = m_decls[i].size(); j-- > 0;) {
|
||||
m_vars[i][j] = m.mk_var(n, m_decls[i][j]);
|
||||
m_names[i][j] = symbol(n);
|
||||
m_imp.add_production(m_vars[i].get(j));
|
||||
n++;
|
||||
}
|
||||
}
|
||||
m_sort = range;
|
||||
m_imp.m_bottom_up_enumerator.set_target_sort(range);
|
||||
}
|
||||
|
||||
void mk_lambda() {
|
||||
if (!m_current)
|
||||
return;
|
||||
for (unsigned i = m_decls.size(); i-- > 0;)
|
||||
m_current = m.mk_lambda(m_decls[i].size(), m_decls[i].data(), m_names[i].data(), m_current);
|
||||
}
|
||||
|
||||
void advance() {
|
||||
if (m_end)
|
||||
return;
|
||||
m_current = m_imp.m_bottom_up_enumerator.next();
|
||||
SASSERT(!m_current || m_current->get_sort() == m_sort);
|
||||
mk_lambda();
|
||||
if (!m_current)
|
||||
m_end = true;
|
||||
}
|
||||
};
|
||||
|
||||
term_enumeration::iterator::iterator(imp& i, sort* s) {
|
||||
m_imp = alloc(iter_imp, i, s);
|
||||
}
|
||||
|
||||
term_enumeration::iterator::iterator(std::nullptr_t) {
|
||||
m_imp = nullptr;
|
||||
}
|
||||
|
||||
term_enumeration::iterator::~iterator() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
expr* term_enumeration::iterator::operator*() {
|
||||
return m_imp ? m_imp->m_current.get() : nullptr;
|
||||
}
|
||||
|
||||
term_enumeration::iterator& term_enumeration::iterator::operator++() {
|
||||
if (m_imp) m_imp->advance();
|
||||
return *this;
|
||||
}
|
||||
|
||||
term_enumeration::iterator term_enumeration::iterator::operator++(int) {
|
||||
iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool term_enumeration::iterator::operator==(iterator const& other) const {
|
||||
if (!m_imp && !other.m_imp) return true;
|
||||
if (!m_imp) return other.m_imp->m_end;
|
||||
if (!other.m_imp) return m_imp->m_end;
|
||||
return m_imp->m_end == other.m_imp->m_end &&
|
||||
m_imp->m_current == other.m_imp->m_current;
|
||||
}
|
||||
|
||||
// -- terms implementation --
|
||||
|
||||
term_enumeration::terms::terms(imp* i, sort* s) : m_imp(i), m_sort(s) {}
|
||||
|
||||
term_enumeration::iterator term_enumeration::terms::begin() {
|
||||
return iterator(*m_imp, m_sort);
|
||||
}
|
||||
|
||||
term_enumeration::iterator term_enumeration::terms::end() {
|
||||
return iterator(nullptr);
|
||||
}
|
||||
|
||||
// -- term_enumeration implementation --
|
||||
|
||||
term_enumeration::term_enumeration(ast_manager& m) {
|
||||
m_imp = alloc(imp, m);
|
||||
}
|
||||
|
||||
term_enumeration::~term_enumeration() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void term_enumeration::add_production(func_decl* f) {
|
||||
m_imp->add_production(f);
|
||||
}
|
||||
|
||||
void term_enumeration::add_production(expr* e) {
|
||||
m_imp->add_production(e);
|
||||
}
|
||||
|
||||
void term_enumeration::set_cost(std::function<unsigned(expr*)> const& cost) {
|
||||
m_imp->set_cost(cost);
|
||||
}
|
||||
|
||||
term_enumeration::terms term_enumeration::enum_terms(sort* s) {
|
||||
return terms(m_imp, s);
|
||||
}
|
||||
|
||||
std::ostream& term_enumeration::display(std::ostream& out) const {
|
||||
return m_imp->display(out);
|
||||
}
|
||||
50
src/ast/rewriter/term_enumeration.h
Normal file
50
src/ast/rewriter/term_enumeration.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "ast/ast.h"
|
||||
#include <functional>
|
||||
|
||||
class term_enumeration {
|
||||
struct imp;
|
||||
imp* m_imp;
|
||||
public:
|
||||
term_enumeration(ast_manager& m);
|
||||
~term_enumeration();
|
||||
|
||||
void add_production(func_decl* f);
|
||||
void add_production(expr* e);
|
||||
// void add_production(sort *s, std::function<expr *()> g);
|
||||
|
||||
// cost function associated with expressions.
|
||||
// terms are enumerated with increasing cost.
|
||||
|
||||
void set_cost(std::function<unsigned(expr*)> const& cost);
|
||||
|
||||
class iterator {
|
||||
struct iter_imp;
|
||||
iter_imp* m_imp;
|
||||
public:
|
||||
iterator(imp& i, sort* s);
|
||||
iterator(std::nullptr_t);
|
||||
~iterator();
|
||||
expr* operator*();
|
||||
iterator operator++(int);
|
||||
iterator& operator++();
|
||||
bool operator!=(iterator const& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator==(iterator const &other) const;
|
||||
};
|
||||
|
||||
class terms {
|
||||
imp* m_imp;
|
||||
sort* m_sort;
|
||||
public:
|
||||
terms(imp* i, sort* s);
|
||||
iterator begin();
|
||||
iterator end();
|
||||
};
|
||||
|
||||
terms enum_terms(sort* s);
|
||||
|
||||
std::ostream& display(std::ostream& out) const;
|
||||
};
|
||||
|
|
@ -241,7 +241,6 @@ void seq_decl_plugin::init() {
|
|||
m_sigs[OP_RE_OF_PRED] = alloc(psig, m, "re.of.pred", 1, 1, &predA, reA);
|
||||
m_sigs[OP_RE_REVERSE] = alloc(psig, m, "re.reverse", 1, 1, &reA, reA);
|
||||
m_sigs[OP_RE_DERIVATIVE] = alloc(psig, m, "re.derivative", 1, 2, AreA, reA);
|
||||
m_sigs[_OP_RE_ANTIMIROV_UNION] = alloc(psig, m, "re.union", 1, 2, reAreA, reA);
|
||||
m_sigs[OP_SEQ_TO_RE] = alloc(psig, m, "seq.to.re", 1, 1, &seqA, reA);
|
||||
m_sigs[OP_SEQ_IN_RE] = alloc(psig, m, "seq.in.re", 1, 2, seqAreA, boolT);
|
||||
m_sigs[OP_SEQ_REPLACE_RE_ALL] = alloc(psig, m, "str.replace_re_all", 1, 3, seqAreAseqA, seqA);
|
||||
|
|
@ -413,7 +412,6 @@ func_decl* seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
case OP_RE_COMPLEMENT:
|
||||
case OP_RE_REVERSE:
|
||||
case OP_RE_DERIVATIVE:
|
||||
case _OP_RE_ANTIMIROV_UNION:
|
||||
m_has_re = true;
|
||||
Z3_fallthrough;
|
||||
case OP_SEQ_UNIT:
|
||||
|
|
@ -423,7 +421,7 @@ func_decl* seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
case OP_STRING_LE:
|
||||
case OP_STRING_IS_DIGIT:
|
||||
case OP_STRING_TO_CODE:
|
||||
case OP_STRING_FROM_CODE:
|
||||
case OP_STRING_FROM_CODE:
|
||||
match(*m_sigs[k], arity, domain, range, rng);
|
||||
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
|
||||
|
||||
|
|
@ -1213,6 +1211,17 @@ app* seq_util::rex::mk_of_pred(expr* p) {
|
|||
return m.mk_app(m_fid, OP_RE_OF_PRED, 0, nullptr, 1, &p);
|
||||
}
|
||||
|
||||
app* seq_util::rex::mk_range(sort* re_sort, unsigned lo, unsigned hi) {
|
||||
if (lo > hi)
|
||||
return mk_empty(re_sort);
|
||||
if (lo == 0 && hi == u.max_char())
|
||||
return mk_full_char(re_sort);
|
||||
app* lo_str = u.str.mk_string(zstring(lo));
|
||||
if (lo == hi)
|
||||
return mk_to_re(lo_str);
|
||||
return mk_range(lo_str, u.str.mk_string(zstring(hi)));
|
||||
}
|
||||
|
||||
bool seq_util::rex::is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi) const {
|
||||
if (is_loop(n)) {
|
||||
app const* a = to_app(n);
|
||||
|
|
@ -1441,7 +1450,7 @@ std::ostream& seq_util::rex::pp::print(std::ostream& out, expr* e) const {
|
|||
print(out, r1);
|
||||
print(out, r2);
|
||||
}
|
||||
else if (re.is_antimirov_union(e, r1, r2) || re.is_union(e, r1, r2)) {
|
||||
else if (re.is_union(e, r1, r2)) {
|
||||
out << "(";
|
||||
print(out, r1);
|
||||
out << (html_encode ? "⋃" : "|");
|
||||
|
|
@ -1674,11 +1683,19 @@ seq_util::rex::info seq_util::rex::mk_info_rec(app* e) const {
|
|||
case OP_RE_OPTION:
|
||||
i1 = get_info_rec(e->get_arg(0));
|
||||
return i1.opt();
|
||||
case OP_RE_RANGE:
|
||||
case OP_RE_RANGE: {
|
||||
// A concrete range [lo, hi] with lo <= hi is non-empty and classical.
|
||||
zstring slo, shi;
|
||||
if (u.str.is_string(e->get_arg(0), slo) && slo.length() == 1 &&
|
||||
u.str.is_string(e->get_arg(1), shi) && shi.length() == 1 &&
|
||||
slo[0] <= shi[0])
|
||||
return info(true, l_false, 1, true);
|
||||
// Symbolic or unknown: not classical
|
||||
return info(true, l_false, 1, false);
|
||||
}
|
||||
case OP_RE_FULL_CHAR_SET:
|
||||
case OP_RE_OF_PRED:
|
||||
//TBD: check if the character predicate contains uninterpreted symbols or is nonground or is unsat
|
||||
//TBD: check if the range is unsat
|
||||
return info(true, l_false, 1, false);
|
||||
case OP_RE_CONCAT:
|
||||
i1 = get_info_rec(e->get_arg(0));
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ enum seq_op_kind {
|
|||
_OP_REGEXP_EMPTY,
|
||||
_OP_REGEXP_FULL_CHAR,
|
||||
_OP_RE_IS_NULLABLE,
|
||||
_OP_RE_ANTIMIROV_UNION, // Lifted union for antimirov-style derivatives
|
||||
_OP_SEQ_SKOLEM,
|
||||
LAST_SEQ_OP
|
||||
};
|
||||
|
|
@ -525,6 +524,8 @@ public:
|
|||
app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); }
|
||||
app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); }
|
||||
app* mk_range(expr* s1, expr* s2) { return m.mk_app(m_fid, OP_RE_RANGE, s1, s2); }
|
||||
// Smart constructor: returns re.empty / str.to_re / re.range based on lo vs hi.
|
||||
app* mk_range(sort* re_sort, unsigned lo, unsigned hi);
|
||||
app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); }
|
||||
app* mk_union(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_UNION, r1, r2); }
|
||||
app* mk_inter(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_INTERSECT, r1, r2); }
|
||||
|
|
@ -546,7 +547,6 @@ public:
|
|||
app* mk_of_pred(expr* p);
|
||||
app* mk_reverse(expr* r) { return m.mk_app(m_fid, OP_RE_REVERSE, r); }
|
||||
app* mk_derivative(expr* ele, expr* r) { return m.mk_app(m_fid, OP_RE_DERIVATIVE, ele, r); }
|
||||
app* mk_antimirov_union(expr* r1, expr* r2) { return m.mk_app(m_fid, _OP_RE_ANTIMIROV_UNION, r1, r2); }
|
||||
|
||||
bool is_to_re(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_TO_RE); }
|
||||
bool is_concat(expr const* n) const { return is_app_of(n, m_fid, OP_RE_CONCAT); }
|
||||
|
|
@ -580,7 +580,6 @@ public:
|
|||
bool is_of_pred(expr const* n) const { return is_app_of(n, m_fid, OP_RE_OF_PRED); }
|
||||
bool is_reverse(expr const* n) const { return is_app_of(n, m_fid, OP_RE_REVERSE); }
|
||||
bool is_derivative(expr const* n) const { return is_app_of(n, m_fid, OP_RE_DERIVATIVE); }
|
||||
bool is_antimirov_union(expr const* n) const { return is_app_of(n, m_fid, _OP_RE_ANTIMIROV_UNION); }
|
||||
MATCH_UNARY(is_to_re);
|
||||
MATCH_BINARY(is_concat);
|
||||
MATCH_BINARY(is_union);
|
||||
|
|
@ -595,7 +594,6 @@ public:
|
|||
MATCH_UNARY(is_of_pred);
|
||||
MATCH_UNARY(is_reverse);
|
||||
MATCH_BINARY(is_derivative);
|
||||
MATCH_BINARY(is_antimirov_union);
|
||||
bool is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi) const;
|
||||
bool is_loop(expr const* n, expr*& body, unsigned& lo) const;
|
||||
bool is_loop(expr const* n, expr*& body, expr*& lo, expr*& hi) const;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Author:
|
|||
class dependent_expr_state {
|
||||
unsigned m_qhead = 0;
|
||||
bool m_suffix_frozen = false;
|
||||
unsigned m_num_recfun = 0, m_num_lambdas = 0;
|
||||
unsigned m_num_recfun = 0;
|
||||
lbool m_has_quantifiers = l_undef;
|
||||
ast_mark m_frozen;
|
||||
func_decl_ref_vector m_frozen_trail;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Abstract:
|
|||
All variables x, y, z, .. can eventually be eliminated, but the tactic requires a global
|
||||
analysis between each elimination. We address this by using reference counts and maintaining
|
||||
a heap of reference counts.
|
||||
- it does not accomodate side constraints. The more general invertibility reduction methods, such
|
||||
- it does not accommodate side constraints. The more general invertibility reduction methods, such
|
||||
as those introduced for bit-vectors use side constraints.
|
||||
- it is not modular: we detach the expression invertion routines to self-contained code.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ It traverses the same sub-terms many times.
|
|||
|
||||
Outline of a presumably better scheme:
|
||||
|
||||
1. maintain map FV: term -> bit-set where bitset reprsents set of free variables. Assume the number of variables is bounded.
|
||||
1. maintain map FV: term -> bit-set where bitset represents set of free variables. Assume the number of variables is bounded.
|
||||
FV is built from initial terms.
|
||||
2. maintain parent: term -> term-list of parent occurrences.
|
||||
3. repeat
|
||||
|
|
|
|||
|
|
@ -17,45 +17,51 @@ Notes:
|
|||
--*/
|
||||
#pragma once
|
||||
|
||||
#define ATOMIC_CMD(CLS_NAME, NAME, DESCR, ACTION) \
|
||||
#define ATOMIC_CMD(CLS_NAME, NAME, DESCR, ACTION) \
|
||||
class CLS_NAME : public cmd { \
|
||||
public: \
|
||||
CLS_NAME():cmd(NAME) {} \
|
||||
char const * get_usage() const override { return 0; } \
|
||||
char const * get_descr(cmd_context & ctx) const override { \
|
||||
return DESCR; \
|
||||
} \
|
||||
unsigned get_arity() const override { return 0; } \
|
||||
void execute(cmd_context & ctx) override { ACTION } \
|
||||
}
|
||||
|
||||
#define UNARY_CMD(CLS_NAME, NAME, USAGE, DESCR, ARG_KIND, ARG_TYPE, ACTION) \
|
||||
class CLS_NAME : public cmd { \
|
||||
public: \
|
||||
CLS_NAME():cmd(NAME) {} \
|
||||
virtual char const * get_usage() const { return 0; } \
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return DESCR; } \
|
||||
virtual unsigned get_arity() const { return 0; } \
|
||||
virtual void execute(cmd_context & ctx) { ACTION } \
|
||||
};
|
||||
|
||||
#define UNARY_CMD(CLS_NAME, NAME, USAGE, DESCR, ARG_KIND, ARG_TYPE, ACTION) \
|
||||
class CLS_NAME : public cmd { \
|
||||
public: \
|
||||
CLS_NAME():cmd(NAME) {} \
|
||||
virtual char const * get_usage() const { return USAGE; } \
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return DESCR; } \
|
||||
virtual unsigned get_arity() const { return 1; } \
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return ARG_KIND; } \
|
||||
virtual void set_next_arg(cmd_context & ctx, ARG_TYPE arg) { ACTION } \
|
||||
char const * get_usage() const override { return USAGE; } \
|
||||
char const * get_descr(cmd_context & ctx) const override { \
|
||||
return DESCR; \
|
||||
} \
|
||||
unsigned get_arity() const override { return 1; } \
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { \
|
||||
return ARG_KIND; \
|
||||
} \
|
||||
void set_next_arg(cmd_context & ctx, ARG_TYPE arg) override { ACTION } \
|
||||
}
|
||||
|
||||
// Macro for creating commands where the first argument is a symbol
|
||||
// The second argument cannot be a symbol
|
||||
#define BINARY_SYM_CMD(CLS_NAME, NAME, USAGE, DESCR, ARG_KIND, ARG_TYPE, ACTION) \
|
||||
class CLS_NAME : public cmd { \
|
||||
symbol m_sym; \
|
||||
symbol m_sym; \
|
||||
public: \
|
||||
CLS_NAME():cmd(NAME) {} \
|
||||
virtual char const * get_usage() const { return USAGE; } \
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return DESCR; } \
|
||||
virtual unsigned get_arity() const { return 2; } \
|
||||
virtual void prepare(cmd_context & ctx) { m_sym = symbol::null; } \
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { \
|
||||
return m_sym == symbol::null ? CPK_SYMBOL : ARG_KIND; \
|
||||
char const * get_usage() const override { return USAGE; } \
|
||||
char const * get_descr(cmd_context & ctx) const override { return DESCR; } \
|
||||
unsigned get_arity() const override { return 2; } \
|
||||
void prepare(cmd_context & ctx) override { m_sym = symbol::null; } \
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { \
|
||||
return m_sym == symbol::null ? CPK_SYMBOL : ARG_KIND; \
|
||||
} \
|
||||
virtual void set_next_arg(cmd_context & ctx, symbol const & s) { m_sym = s; } \
|
||||
virtual void set_next_arg(cmd_context & ctx, ARG_TYPE arg) { ACTION } \
|
||||
};
|
||||
|
||||
void set_next_arg(cmd_context & ctx, symbol const & s) override { m_sym = s; } \
|
||||
void set_next_arg(cmd_context & ctx, ARG_TYPE arg) override { ACTION } \
|
||||
}
|
||||
|
||||
|
||||
class ast;
|
||||
class expr;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
|
|
@ -65,7 +64,8 @@ enum class token_kind {
|
|||
slash_tok,
|
||||
minus_tok,
|
||||
at_tok,
|
||||
lambda_tok
|
||||
lambda_tok,
|
||||
modal_tok
|
||||
};
|
||||
|
||||
struct parse_error : public std::exception {
|
||||
|
|
@ -87,6 +87,7 @@ struct token {
|
|||
std::string text;
|
||||
unsigned line = 1;
|
||||
unsigned col = 1;
|
||||
bool dquote = false; // true for double-quoted strings ("..."): TPTP distinct objects
|
||||
};
|
||||
|
||||
class lexer {
|
||||
|
|
@ -163,6 +164,7 @@ public:
|
|||
if (peek() == '\'' || peek() == '"') {
|
||||
char q = get();
|
||||
t.kind = token_kind::str;
|
||||
t.dquote = (q == '"');
|
||||
while (!eof()) {
|
||||
char c = get();
|
||||
if (c == '\\' && !eof()) {
|
||||
|
|
@ -252,7 +254,7 @@ public:
|
|||
case '^': t.kind = token_kind::lambda_tok; return t;
|
||||
case '{':
|
||||
// Modal operators: {$box}, {$dia}, etc. — lex as identifier including braces
|
||||
t.kind = token_kind::id;
|
||||
t.kind = token_kind::modal_tok;
|
||||
t.text.push_back(c);
|
||||
while (!eof() && peek() != '}')
|
||||
t.text.push_back(get());
|
||||
|
|
@ -277,10 +279,10 @@ public:
|
|||
};
|
||||
|
||||
struct parsed_type {
|
||||
std::vector<sort*> domain;
|
||||
ptr_vector<sort> domain;
|
||||
sort* range = nullptr;
|
||||
parsed_type(sort* s): range(s) {}
|
||||
parsed_type(std::vector<sort*> const& d, sort* r): domain(d), range(r) {}
|
||||
parsed_type(ptr_vector<sort> const& d, sort* r): domain(d), range(r) {}
|
||||
};
|
||||
|
||||
class tptp_parser {
|
||||
|
|
@ -290,13 +292,20 @@ class tptp_parser {
|
|||
array_util m_array;
|
||||
sort* m_univ;
|
||||
bool m_has_conjecture = false;
|
||||
unsigned m_dropped_formulas = 0; // axioms/definitions skipped due to encoding errors
|
||||
bool m_last_name_quoted = false;
|
||||
bool m_last_name_dquoted = false; // last parsed name was a double-quoted distinct object
|
||||
// Distinct objects: TPTP double-quoted strings ("...") denote pairwise distinct
|
||||
// domain elements. Collected here (deduplicated by name) so a single global
|
||||
// (distinct ...) constraint can be asserted before solving.
|
||||
std::unordered_map<std::string, expr*> m_distinct_objects;
|
||||
std::string m_expected_status; // SZS status from the input annotation, if any
|
||||
std::unordered_map<std::string, sort*> m_sorts;
|
||||
sort_ref_vector m_pinned_sorts; // prevents cached sorts from being freed
|
||||
std::unordered_map<std::string, func_decl*> m_decls;
|
||||
func_decl_ref_vector m_pinned_decls; // prevents cached func_decls from being freed
|
||||
expr_ref_vector m_pinned_exprs; // prevents bound variable apps from being freed
|
||||
std::unordered_map<std::string, std::pair<std::vector<sort*>, sort*>> m_typed_decls;
|
||||
std::unordered_map<std::string, std::pair<ptr_vector<sort>, sort*>> m_typed_decls;
|
||||
std::vector<std::unordered_map<std::string, app*>> m_bound;
|
||||
bool m_in_at_arg = false; // true when parsing inside @ argument (lambda body stops consuming @)
|
||||
struct implicit_var_scope {
|
||||
|
|
@ -424,6 +433,7 @@ class tptp_parser {
|
|||
std::string parse_name() {
|
||||
if (is(token_kind::id) || is(token_kind::str)) {
|
||||
m_last_name_quoted = is(token_kind::str);
|
||||
m_last_name_dquoted = is(token_kind::str) && m_curr.dquote;
|
||||
std::string r = m_curr.text;
|
||||
next();
|
||||
return r;
|
||||
|
|
@ -449,7 +459,7 @@ class tptp_parser {
|
|||
// For higher-order types like ($i > $o), create an uninterpreted sort
|
||||
// Function type A > B is represented as Array(A, B).
|
||||
// Multi-argument A * B > C is represented as Array(A, Array(B, C)) (curried).
|
||||
sort* get_ho_sort(std::vector<sort*> const& domain, sort* range) {
|
||||
sort* get_ho_sort(ptr_vector<sort> const& domain, sort* range) {
|
||||
sort* s = range;
|
||||
for (int i = (int)domain.size() - 1; i >= 0; --i)
|
||||
s = m_array.mk_array_sort(domain[i], s);
|
||||
|
|
@ -513,7 +523,8 @@ class tptp_parser {
|
|||
if (itt != m_typed_decls.end()) {
|
||||
std::string typed_decl_key = mk_decl_key(name, arity, 'd');
|
||||
auto itd = m_decls.find(typed_decl_key);
|
||||
if (itd != m_decls.end()) return itd->second;
|
||||
if (itd != m_decls.end())
|
||||
return itd->second;
|
||||
auto const& sig = itt->second;
|
||||
func_decl* f = m.mk_func_decl(symbol(name), sig.first.size(), sig.first.data(), sig.second);
|
||||
m_pinned_decls.push_back(f);
|
||||
|
|
@ -525,7 +536,7 @@ class tptp_parser {
|
|||
auto itd = m_decls.find(key);
|
||||
if (itd != m_decls.end()) return itd->second;
|
||||
|
||||
std::vector<sort*> dom(arity, m_univ);
|
||||
ptr_vector<sort> dom(arity, m_univ);
|
||||
func_decl* f = m.mk_func_decl(symbol(name), arity, dom.data(), pred ? m.mk_bool_sort() : m_univ);
|
||||
m_pinned_decls.push_back(f);
|
||||
m_decls.emplace(key, f);
|
||||
|
|
@ -571,6 +582,14 @@ class tptp_parser {
|
|||
expr_ref coerce_arg(expr_ref const& e, sort* target) {
|
||||
sort* actual = e->get_sort();
|
||||
if (actual == target) return e;
|
||||
// Int <-> Real conversions must use the arithmetic semantics (to_real /
|
||||
// to_int), never an uninterpreted boxing function: an uninterpreted box
|
||||
// severs the numeric link between the two sides and lets the solver build
|
||||
// spurious models (e.g. it would make floor/ceiling identities sat).
|
||||
if (m_arith.is_int(actual) && m_arith.is_real(target))
|
||||
return expr_ref(m_arith.mk_to_real(e), m);
|
||||
if (m_arith.is_real(actual) && m_arith.is_int(target))
|
||||
return expr_ref(m_arith.mk_to_int(e), m);
|
||||
// Create a boxing function from actual sort to target sort
|
||||
std::string box_name = std::string("$box_") + actual->get_name().str() + "_to_" + target->get_name().str();
|
||||
std::string key = mk_decl_key(box_name, 1, 'f');
|
||||
|
|
@ -697,14 +716,14 @@ class tptp_parser {
|
|||
// <defined_type> ::= $oType | $o | $iType | $i | $tType | $real | $rat | $int
|
||||
parsed_type parse_type_atom() {
|
||||
if (accept(token_kind::lparen)) {
|
||||
std::vector<sort*> prod = parse_type_product_raw();
|
||||
ptr_vector<sort> prod = parse_type_product_raw();
|
||||
if (accept(token_kind::gt_tok)) {
|
||||
// Full function type inside parens: (A * B > C) or (A > B > C)
|
||||
parsed_type rhs = parse_type_expr();
|
||||
std::vector<sort*> full_domain = prod;
|
||||
ptr_vector<sort> full_domain = prod;
|
||||
if (!rhs.domain.empty()) {
|
||||
// Nested higher-order: (A > B > C) → flatten
|
||||
full_domain.insert(full_domain.end(), rhs.domain.begin(), rhs.domain.end());
|
||||
full_domain.append(rhs.domain);
|
||||
}
|
||||
expect(token_kind::rparen, "')'");
|
||||
// Return with domain/range preserved for proper flattening
|
||||
|
|
@ -743,15 +762,15 @@ class tptp_parser {
|
|||
// Grammar: <thf_xprod_type> ::= <thf_unitary_type> * <thf_unitary_type>
|
||||
// | <thf_xprod_type> * <thf_unitary_type>
|
||||
// Product types form the domain in mapping types: (A * B) > C
|
||||
std::vector<sort*> parse_type_product_raw() {
|
||||
ptr_vector<sort> parse_type_product_raw() {
|
||||
parsed_type first = parse_type_atom();
|
||||
if (!first.domain.empty() && first.range == nullptr) {
|
||||
// Already a parenthesized product from nested parens
|
||||
std::vector<sort*> args = first.domain;
|
||||
ptr_vector<sort> args = first.domain;
|
||||
while (accept(token_kind::star_tok)) {
|
||||
parsed_type t = parse_type_atom();
|
||||
if (!t.domain.empty()) {
|
||||
args.insert(args.end(), t.domain.begin(), t.domain.end());
|
||||
args.append(t.domain);
|
||||
} else {
|
||||
args.push_back(t.range);
|
||||
}
|
||||
|
|
@ -761,28 +780,28 @@ class tptp_parser {
|
|||
if (!first.domain.empty()) {
|
||||
// Function type as first element of product — use ho_sort
|
||||
sort* ho = get_ho_sort(first.domain, first.range);
|
||||
std::vector<sort*> args;
|
||||
ptr_vector<sort> args;
|
||||
args.push_back(ho);
|
||||
while (accept(token_kind::star_tok)) {
|
||||
parsed_type t = parse_type_atom();
|
||||
if (!t.domain.empty() && t.range != nullptr) {
|
||||
args.push_back(get_ho_sort(t.domain, t.range));
|
||||
} else if (!t.domain.empty()) {
|
||||
args.insert(args.end(), t.domain.begin(), t.domain.end());
|
||||
args.append(t.domain);
|
||||
} else {
|
||||
args.push_back(t.range);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
std::vector<sort*> args;
|
||||
ptr_vector<sort> args;
|
||||
args.push_back(first.range);
|
||||
while (accept(token_kind::star_tok)) {
|
||||
parsed_type t = parse_type_atom();
|
||||
if (!t.domain.empty() && t.range != nullptr) {
|
||||
args.push_back(get_ho_sort(t.domain, t.range));
|
||||
} else if (!t.domain.empty()) {
|
||||
args.insert(args.end(), t.domain.begin(), t.domain.end());
|
||||
args.append(t.domain);
|
||||
} else {
|
||||
args.push_back(t.range);
|
||||
}
|
||||
|
|
@ -801,7 +820,7 @@ class tptp_parser {
|
|||
return first;
|
||||
}
|
||||
// Build product vector
|
||||
std::vector<sort*> args;
|
||||
ptr_vector<sort> args;
|
||||
if (!first.domain.empty() && first.range != nullptr) {
|
||||
// Function type used as element in a product
|
||||
args.push_back(get_ho_sort(first.domain, first.range));
|
||||
|
|
@ -816,7 +835,7 @@ class tptp_parser {
|
|||
if (!t.domain.empty() && t.range != nullptr) {
|
||||
args.push_back(get_ho_sort(t.domain, t.range));
|
||||
} else if (!t.domain.empty()) {
|
||||
args.insert(args.end(), t.domain.begin(), t.domain.end());
|
||||
args.append(t.domain);
|
||||
} else {
|
||||
args.push_back(t.range);
|
||||
}
|
||||
|
|
@ -833,7 +852,7 @@ class tptp_parser {
|
|||
if (is(token_kind::type_forall_tok) || is(token_kind::type_exists_tok)) {
|
||||
next();
|
||||
expect(token_kind::lbrack, "'['");
|
||||
std::vector<sort*> type_params;
|
||||
ptr_vector<sort> type_params;
|
||||
if (!accept(token_kind::rbrack)) {
|
||||
do {
|
||||
std::string tv = parse_name();
|
||||
|
|
@ -848,8 +867,8 @@ class tptp_parser {
|
|||
parsed_type inner = parse_type_expr();
|
||||
// Prepend type params to domain
|
||||
if (!type_params.empty()) {
|
||||
std::vector<sort*> full_domain = type_params;
|
||||
full_domain.insert(full_domain.end(), inner.domain.begin(), inner.domain.end());
|
||||
ptr_vector<sort> full_domain = type_params;
|
||||
full_domain.append(inner.domain);
|
||||
return parsed_type(full_domain, inner.range);
|
||||
}
|
||||
return inner;
|
||||
|
|
@ -858,7 +877,7 @@ class tptp_parser {
|
|||
if (accept(token_kind::gt_tok)) {
|
||||
parsed_type rhs = parse_type_expr();
|
||||
// prod is either a product (domain non-empty, range==nullptr) or a single sort (domain empty)
|
||||
std::vector<sort*> domain;
|
||||
ptr_vector<sort> domain;
|
||||
if (!prod.domain.empty() && prod.range == nullptr) {
|
||||
domain = prod.domain;
|
||||
} else if (!prod.domain.empty() && prod.range != nullptr) {
|
||||
|
|
@ -869,7 +888,7 @@ class tptp_parser {
|
|||
}
|
||||
if (!rhs.domain.empty()) {
|
||||
// Higher-order result type: A > (B > C) flattened to (A, B) > C
|
||||
domain.insert(domain.end(), rhs.domain.begin(), rhs.domain.end());
|
||||
domain.append(rhs.domain);
|
||||
return parsed_type(domain, rhs.range);
|
||||
}
|
||||
return parsed_type(domain, rhs.range);
|
||||
|
|
@ -925,7 +944,7 @@ class tptp_parser {
|
|||
// Grammar: (same as parse_term, primary productions)
|
||||
expr_ref parse_term_primary() {
|
||||
if (accept(token_kind::lparen)) {
|
||||
expr_ref e = parse_formula();
|
||||
expr_ref e = parse_formula(false);
|
||||
expect(token_kind::rparen, "')'");
|
||||
return e;
|
||||
}
|
||||
|
|
@ -946,6 +965,7 @@ class tptp_parser {
|
|||
return parse_numeral_from_name(n);
|
||||
}
|
||||
|
||||
bool dq_name = m_last_name_dquoted;
|
||||
expr_ref b(m);
|
||||
// Check bound variables: uppercase (quantifier vars) AND lowercase (let-bound names)
|
||||
if (!m_last_name_quoted && find_bound(n, b)) {
|
||||
|
|
@ -971,11 +991,11 @@ class tptp_parser {
|
|||
// $ite needs special parsing: first arg is formula, rest are formulas (branches can be equalities)
|
||||
if (n == "$ite") {
|
||||
expect(token_kind::lparen, "'('");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(true));
|
||||
expect(token_kind::comma, "','");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(false));
|
||||
expect(token_kind::comma, "','");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(false));
|
||||
expect(token_kind::rparen, "')'");
|
||||
}
|
||||
else if (n == "$let") {
|
||||
|
|
@ -995,14 +1015,17 @@ class tptp_parser {
|
|||
}
|
||||
|
||||
func_decl* f = mk_decl_or_ho_const(n, args.size(), false);
|
||||
if (!args.empty()) coerce_args(f, args);
|
||||
return expr_ref(args.empty() ? m.mk_const(f) : m.mk_app(f, args.size(), args.data()), m);
|
||||
coerce_args(f, args);
|
||||
expr_ref term(args.empty() ? m.mk_const(f) : m.mk_app(f, args.size(), args.data()), m);
|
||||
if (dq_name && args.empty())
|
||||
register_distinct_object(n, term);
|
||||
return term;
|
||||
}
|
||||
|
||||
// Grammar: <tff_logic_formula> ::= <tff_unitary_formula> | <tff_binary_formula>
|
||||
// <thf_logic_formula> ::= <thf_unitary_formula> | <thf_binary_formula>
|
||||
// Entry point for formula parsing (wraps parse_expr with default precedence).
|
||||
expr_ref parse_formula();
|
||||
expr_ref parse_formula(bool is_boolean);
|
||||
|
||||
// Grammar: <thf_apply_formula> ::= <thf_unitary_formula> @ <thf_unitary_formula>
|
||||
// | <thf_apply_formula> @ <thf_unitary_formula>
|
||||
|
|
@ -1042,7 +1065,7 @@ class tptp_parser {
|
|||
return parse_lambda_expr();
|
||||
}
|
||||
if (accept(token_kind::lparen)) {
|
||||
expr_ref e = parse_formula();
|
||||
expr_ref e = parse_formula(false);
|
||||
expect(token_kind::rparen, "')'");
|
||||
// Do NOT call apply_at here — outer apply_at owns the remaining @ tokens
|
||||
return e;
|
||||
|
|
@ -1074,7 +1097,7 @@ class tptp_parser {
|
|||
// Quantifier body in @-arg should NOT consume @ — those belong to enclosing application
|
||||
bool save_in_at_arg = m_in_at_arg;
|
||||
m_in_at_arg = true;
|
||||
expr_ref body = parse_formula();
|
||||
expr_ref body = parse_formula(false);
|
||||
m_in_at_arg = save_in_at_arg;
|
||||
m_bound.pop_back();
|
||||
return mk_quantifier(is_forall, vars, body);
|
||||
|
|
@ -1092,7 +1115,7 @@ class tptp_parser {
|
|||
std::string key = mk_decl_key(name_str, 0, 'c') + "\x1f" + std::to_string(range->get_id());
|
||||
auto it = m_decls.find(key);
|
||||
if (it != m_decls.end()) return it->second;
|
||||
func_decl* f = m.mk_func_decl(name, 0, static_cast<sort**>(nullptr), range);
|
||||
func_decl* f = m.mk_const_decl(name, range);
|
||||
m_pinned_decls.push_back(f);
|
||||
m_decls.emplace(key, f);
|
||||
return f;
|
||||
|
|
@ -1121,31 +1144,29 @@ class tptp_parser {
|
|||
|
||||
// Coerce two expressions to have the same sort for equality.
|
||||
// In TPTP, = is term equality and m_univ is the default sort.
|
||||
// If one side has Bool sort (parsed as predicate), coerce it to m_univ.
|
||||
// If sorts already match and are not Bool, returns lhs unchanged.
|
||||
// If sorts already match, returns lhs unchanged; otherwise applies minimal
|
||||
// arithmetic/box coercions so both sides of an equality share a sort.
|
||||
expr_ref coerce_eq(expr_ref lhs, expr_ref& rhs) {
|
||||
// Coerce Bool-sorted operands to m_univ since = is term equality in TPTP
|
||||
if (m.is_bool(lhs->get_sort()) && is_app(lhs) && !m.is_true(lhs) && !m.is_false(lhs))
|
||||
lhs = coerce_to_univ(lhs);
|
||||
if (m.is_bool(rhs->get_sort()) && is_app(rhs) && !m.is_true(rhs) && !m.is_false(rhs))
|
||||
rhs = coerce_to_univ(rhs);
|
||||
|
||||
if (lhs->get_sort() == rhs->get_sort()) return lhs;
|
||||
|
||||
// No coercion is needed when both sides already share a sort. In particular
|
||||
// `=` between two Boolean ($o) operands is logical equivalence (iff): keep
|
||||
// them Boolean instead of forcing one into the term universe U.
|
||||
if (lhs->get_sort() == rhs->get_sort())
|
||||
return lhs;
|
||||
if (m_arith.is_int_real(lhs) && m_arith.is_int_real(rhs))
|
||||
return lhs;
|
||||
// Coerce 0-arity constants to match the other side's sort
|
||||
if (is_app(lhs) && to_app(lhs)->get_num_args() == 0 && lhs->get_sort() != rhs->get_sort()) {
|
||||
if (is_app(lhs) && to_app(lhs)->get_num_args() == 0) {
|
||||
return coerce_zero_arity(to_app(lhs), rhs->get_sort());
|
||||
}
|
||||
if (is_app(rhs) && to_app(rhs)->get_num_args() == 0 && lhs->get_sort() != rhs->get_sort()) {
|
||||
if (is_app(rhs) && to_app(rhs)->get_num_args() == 0) {
|
||||
rhs = coerce_zero_arity(to_app(rhs), lhs->get_sort());
|
||||
return lhs;
|
||||
}
|
||||
// Last resort: coerce both sides to have the same sort
|
||||
if (lhs->get_sort() != rhs->get_sort()) {
|
||||
// Prefer coercing to rhs sort, falling back to m_univ
|
||||
sort* target = rhs->get_sort();
|
||||
lhs = coerce_arg(lhs, target);
|
||||
}
|
||||
// Prefer coercing to rhs sort, falling back to m_univ
|
||||
sort* target = rhs->get_sort();
|
||||
lhs = coerce_arg(lhs, target);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
|
@ -1176,7 +1197,7 @@ class tptp_parser {
|
|||
// Bind parameter variables for parsing the RHS
|
||||
if (!param_scope.empty())
|
||||
m_bound.push_back(param_scope);
|
||||
expr_ref value = parse_formula();
|
||||
expr_ref value = parse_formula(false);
|
||||
if (!param_scope.empty())
|
||||
m_bound.pop_back();
|
||||
// For function-style definitions, wrap value in lambdas
|
||||
|
|
@ -1206,7 +1227,7 @@ class tptp_parser {
|
|||
|
||||
// --- Part 1: Parse type declarations ---
|
||||
std::vector<std::string> let_names;
|
||||
std::vector<sort*> let_sorts;
|
||||
ptr_vector<sort> let_sorts;
|
||||
|
||||
auto parse_one_typing = [&]() {
|
||||
std::string name = parse_name();
|
||||
|
|
@ -1264,7 +1285,7 @@ class tptp_parser {
|
|||
|
||||
// --- Part 3: Parse body with let-bound names in scope ---
|
||||
m_bound.push_back(scope);
|
||||
expr_ref body = parse_formula();
|
||||
expr_ref body = parse_formula(false);
|
||||
m_bound.pop_back();
|
||||
expect(token_kind::rparen, "')'");
|
||||
|
||||
|
|
@ -1288,7 +1309,7 @@ class tptp_parser {
|
|||
// <defined_pred> ::= $less | $lesseq | $greater | $greatereq | $is_int | $is_rat | ...
|
||||
// <defined_infix_pred> ::= = | !=
|
||||
// Also handles: let-bound name resolution, implicit variable creation.
|
||||
expr_ref parse_atomic_formula() {
|
||||
expr_ref parse_atomic_formula(bool is_boolean) {
|
||||
if (accept(token_kind::lparen)) {
|
||||
// Check for parenthesized connective used as higher-order term: (~), (&), (|), etc.
|
||||
if (is(token_kind::not_tok) || is(token_kind::and_tok) || is(token_kind::or_tok) ||
|
||||
|
|
@ -1307,31 +1328,50 @@ class tptp_parser {
|
|||
token saved = m_curr;
|
||||
next();
|
||||
if (accept(token_kind::rparen)) {
|
||||
// Parenthesized connective: treat as HO constant with array sort
|
||||
// A parenthesized connective used as a higher-order term, e.g.
|
||||
// "(~) @ p" or "(|) @ p @ q". Encode it as a genuine lambda over Bool
|
||||
// carrying the real logical semantics, so that application beta-reduces
|
||||
// to the actual connective (e.g. "(~) @ p" ==> "not p"). Encoding it as
|
||||
// an uninterpreted array constant instead would sever it from Boolean
|
||||
// logic and make valid higher-order theorems spuriously
|
||||
// CounterSatisfiable (the (~)/(|) applications would be unrelated to the
|
||||
// truth values of their operands).
|
||||
(void)op_text;
|
||||
sort* bool_sort = m.mk_bool_sort();
|
||||
sort* ho_sort;
|
||||
if (arity == 1)
|
||||
ho_sort = m_array.mk_array_sort(bool_sort, bool_sort);
|
||||
else
|
||||
ho_sort = m_array.mk_array_sort(bool_sort, m_array.mk_array_sort(bool_sort, bool_sort));
|
||||
std::string key = mk_decl_key(op_text, 0, 'h');
|
||||
auto it = m_decls.find(key);
|
||||
func_decl* f;
|
||||
if (it != m_decls.end()) {
|
||||
f = it->second;
|
||||
} else {
|
||||
f = m.mk_func_decl(symbol(op_text), 0, static_cast<sort**>(nullptr), ho_sort);
|
||||
m_pinned_decls.push_back(f);
|
||||
m_decls.emplace(key, f);
|
||||
symbol xn("X"), yn("Y");
|
||||
if (arity == 1) {
|
||||
// (~) ==> ^[X:$o] : ~X
|
||||
expr_ref body(m.mk_not(m.mk_var(0, bool_sort)), m);
|
||||
return expr_ref(m.mk_lambda(1, &bool_sort, &xn, body), m);
|
||||
}
|
||||
return expr_ref(m.mk_const(f), m);
|
||||
// binary connective ==> ^[X:$o] : ^[Y:$o] : (X <op> Y)
|
||||
// de Bruijn: X is var(1) (outer binder), Y is var(0) (inner binder).
|
||||
expr* vx = m.mk_var(1, bool_sort);
|
||||
expr* vy = m.mk_var(0, bool_sort);
|
||||
expr_ref opbody(m);
|
||||
switch (saved.kind) {
|
||||
case token_kind::and_tok: opbody = m.mk_and(vx, vy); break;
|
||||
case token_kind::or_tok: opbody = m.mk_or(vx, vy); break;
|
||||
case token_kind::implies_tok: opbody = m.mk_implies(vx, vy); break;
|
||||
case token_kind::iff_tok: opbody = m.mk_eq(vx, vy); break;
|
||||
case token_kind::xor_tok: opbody = m.mk_xor(vx, vy); break;
|
||||
default: opbody = m.mk_eq(vx, vy); break;
|
||||
}
|
||||
expr_ref inner(m.mk_lambda(1, &bool_sort, &yn, opbody), m);
|
||||
return expr_ref(m.mk_lambda(1, &bool_sort, &xn, inner), m);
|
||||
}
|
||||
// Not a parenthesized connective — lparen was consumed and connective was consumed
|
||||
// but ')' didn't follow. Parse as formula with the connective already consumed.
|
||||
expr_ref inner(m);
|
||||
if (saved.kind == token_kind::not_tok) {
|
||||
expr_ref e = parse_formula();
|
||||
inner = expr_ref(m.mk_not(e), m);
|
||||
// "( ~ <formula> )": the '~' is a unary connective binding only the
|
||||
// next unary unit; ordinary binary connectives then apply at their
|
||||
// own precedence (e.g. "( ~ p | q )" is "(~p) | q", NOT "~(p | q)").
|
||||
// We have already consumed '(' and '~', so negate the next unit and
|
||||
// resume precedence-climbing parsing from that negated left operand.
|
||||
expr_ref operand = parse_unary_formula(true);
|
||||
expr_ref neg(m.mk_not(ensure_bool(operand)), m);
|
||||
inner = parse_binary_rest(neg, PREC_IFF, true);
|
||||
} else {
|
||||
// Binary connective at start of parens — shouldn't happen in valid TPTP
|
||||
throw parse_error("unexpected connective after '(' at " + loc());
|
||||
|
|
@ -1342,12 +1382,15 @@ class tptp_parser {
|
|||
// Parentheses create a new scope for @ consumption
|
||||
bool save_in_at_arg = m_in_at_arg;
|
||||
m_in_at_arg = false;
|
||||
expr_ref e = parse_formula();
|
||||
expr_ref e = parse_formula(is_boolean);
|
||||
expect(token_kind::rparen, "')'");
|
||||
m_in_at_arg = save_in_at_arg;
|
||||
return e;
|
||||
}
|
||||
|
||||
if (accept(token_kind::modal_tok))
|
||||
throw parse_error("modal operators not supported in TPTP input at " + loc());
|
||||
|
||||
// Handle negative numerals in formula position: -2 = $uminus(2)
|
||||
if (accept(token_kind::minus_tok)) {
|
||||
expr_ref t = parse_term();
|
||||
|
|
@ -1358,9 +1401,9 @@ class tptp_parser {
|
|||
if (accept(token_kind::lbrack)) {
|
||||
if (accept(token_kind::rbrack))
|
||||
return expr_ref(m.mk_const(symbol("$nil"), m_univ), m);
|
||||
expr_ref first = parse_formula();
|
||||
expr_ref first = parse_formula(is_boolean);
|
||||
while (accept(token_kind::comma))
|
||||
parse_formula(); // consume remaining elements
|
||||
parse_formula(is_boolean); // consume remaining elements
|
||||
expect(token_kind::rbrack, "']'");
|
||||
return first;
|
||||
}
|
||||
|
|
@ -1373,6 +1416,7 @@ class tptp_parser {
|
|||
return parse_numeral_from_name(n);
|
||||
}
|
||||
|
||||
bool dq_name = m_last_name_dquoted;
|
||||
// Check if name is let-bound (works for both uppercase vars and lowercase let-bound names)
|
||||
{
|
||||
expr_ref b(m);
|
||||
|
|
@ -1417,7 +1461,7 @@ class tptp_parser {
|
|||
}
|
||||
expect(token_kind::colon, "':'");
|
||||
m_bound.push_back(scope);
|
||||
expr_ref body = parse_formula();
|
||||
expr_ref body = parse_formula(is_boolean);
|
||||
m_bound.pop_back();
|
||||
// Approximate choice as existential quantification
|
||||
return mk_quantifier(false, vars, body);
|
||||
|
|
@ -1427,11 +1471,11 @@ class tptp_parser {
|
|||
// $ite needs special parsing: first arg is formula, rest are formulas (branches can be equalities)
|
||||
if (n == "$ite") {
|
||||
expect(token_kind::lparen, "'('");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(true));
|
||||
expect(token_kind::comma, "','");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(is_boolean));
|
||||
expect(token_kind::comma, "','");
|
||||
args.push_back(parse_formula());
|
||||
args.push_back(parse_formula(is_boolean));
|
||||
expect(token_kind::rparen, "')'");
|
||||
}
|
||||
else if (n == "$let") {
|
||||
|
|
@ -1465,18 +1509,19 @@ class tptp_parser {
|
|||
auto typed = m_typed_decls.find(mk_typed_key(n, args.size()));
|
||||
if (typed != m_typed_decls.end()) {
|
||||
func_decl* f = args.empty() ? mk_decl_or_ho_const(n, 0, false) : mk_decl(n, args.size(), false);
|
||||
if (!args.empty()) coerce_args(f, args);
|
||||
return expr_ref(args.empty() ? m.mk_const(f) : m.mk_app(f, args.size(), args.data()), m);
|
||||
coerce_args(f, args);
|
||||
return expr_ref(m.mk_app(f, args.size(), args.data()), m);
|
||||
}
|
||||
|
||||
if (args.empty() && (is(token_kind::equal_tok) || is(token_kind::neq_tok))) {
|
||||
func_decl* f = mk_decl_or_ho_const(n, 0, false);
|
||||
return expr_ref(m.mk_const(f), m);
|
||||
}
|
||||
is_boolean = is_boolean && !is(token_kind::equal_tok) && !is(token_kind::neq_tok);
|
||||
|
||||
func_decl* pred = mk_decl_or_ho_const(n, args.size(), true);
|
||||
if (!args.empty()) coerce_args(pred, args);
|
||||
return expr_ref(args.empty() ? m.mk_const(pred) : m.mk_app(pred, args.size(), args.data()), m);
|
||||
|
||||
func_decl* pred = mk_decl_or_ho_const(n, args.size(), is_boolean);
|
||||
coerce_args(pred, args);
|
||||
expr_ref atom(m.mk_app(pred, args.size(), args.data()), m);
|
||||
if (dq_name && args.empty() && !m.is_bool(atom))
|
||||
register_distinct_object(n, atom);
|
||||
return atom;
|
||||
}
|
||||
|
||||
// Grammar: <thf_abstraction> ::= ^ [<thf_variable_list>] : <thf_unitary_formula>
|
||||
|
|
@ -1513,7 +1558,7 @@ class tptp_parser {
|
|||
// Lambda body does NOT consume @ — @ belongs to the enclosing application
|
||||
bool save_in_at_arg = m_in_at_arg;
|
||||
m_in_at_arg = true;
|
||||
expr_ref body = parse_formula();
|
||||
expr_ref body = parse_formula(false);
|
||||
m_in_at_arg = save_in_at_arg;
|
||||
m_bound.pop_back();
|
||||
if (vars.empty())
|
||||
|
|
@ -1538,9 +1583,9 @@ class tptp_parser {
|
|||
// <thf_quantified_formula> ::= <thf_quantification> <thf_unitary_formula>
|
||||
// <fof_quantifier> ::= ! | ?
|
||||
// Also handles: $ite, $let, lambda (^), parenthesized formulas, and atomic formulas.
|
||||
expr_ref parse_unary_formula() {
|
||||
expr_ref parse_unary_formula(bool is_boolean) {
|
||||
if (accept(token_kind::not_tok)) {
|
||||
expr_ref e = parse_unary_formula();
|
||||
expr_ref e = parse_unary_formula(true);
|
||||
return expr_ref(m.mk_not(ensure_bool(e)), m);
|
||||
}
|
||||
|
||||
|
|
@ -1552,7 +1597,7 @@ class tptp_parser {
|
|||
next(); // consume '['
|
||||
if (accept(token_kind::dot)) {
|
||||
expect(token_kind::rbrack, "']'");
|
||||
expr_ref sub = parse_unary_formula();
|
||||
expr_ref sub = parse_unary_formula(is_boolean);
|
||||
func_decl* f = mk_modal_op("box");
|
||||
return expr_ref(m.mk_app(f, sub.get()), m);
|
||||
}
|
||||
|
|
@ -1561,7 +1606,7 @@ class tptp_parser {
|
|||
std::string first_name = m_curr.text;
|
||||
next();
|
||||
if (accept(token_kind::rbrack)) {
|
||||
expr_ref sub = parse_unary_formula();
|
||||
expr_ref sub = parse_unary_formula(is_boolean);
|
||||
func_decl* f = mk_modal_op(mod_name);
|
||||
return expr_ref(m.mk_app(f, sub.get()), m);
|
||||
}
|
||||
|
|
@ -1575,11 +1620,11 @@ class tptp_parser {
|
|||
else if (should_create_implicit_var(first_name))
|
||||
first = expr_ref(get_or_create_implicit_var(first_name), m);
|
||||
else {
|
||||
func_decl* f = mk_decl_or_ho_const(first_name, 0, false);
|
||||
func_decl* f = mk_decl_or_ho_const(first_name, 0, is_boolean);
|
||||
first = expr_ref(m.mk_const(f), m);
|
||||
}
|
||||
while (accept(token_kind::comma))
|
||||
parse_formula(); // consume remaining elements
|
||||
parse_formula(is_boolean); // consume remaining elements
|
||||
expect(token_kind::rbrack, "']'");
|
||||
return first;
|
||||
}
|
||||
|
|
@ -1587,9 +1632,9 @@ class tptp_parser {
|
|||
// We already consumed '[', so parse as tuple inline
|
||||
if (accept(token_kind::rbrack))
|
||||
return expr_ref(m.mk_const(symbol("$nil"), m_univ), m);
|
||||
expr_ref first = parse_formula();
|
||||
expr_ref first = parse_formula(is_boolean);
|
||||
while (accept(token_kind::comma))
|
||||
parse_formula(); // consume remaining elements
|
||||
parse_formula(is_boolean); // consume remaining elements
|
||||
expect(token_kind::rbrack, "']'");
|
||||
return first;
|
||||
}
|
||||
|
|
@ -1605,7 +1650,7 @@ class tptp_parser {
|
|||
next();
|
||||
}
|
||||
expect(token_kind::gt_tok, "'>'");
|
||||
expr_ref sub = parse_unary_formula();
|
||||
expr_ref sub = parse_unary_formula(is_boolean);
|
||||
func_decl* f = mk_modal_op(mod_name);
|
||||
return expr_ref(m.mk_app(f, sub.get()), m);
|
||||
}
|
||||
|
|
@ -1652,7 +1697,13 @@ class tptp_parser {
|
|||
}
|
||||
expect(token_kind::colon, "':'");
|
||||
m_bound.push_back(scope);
|
||||
expr_ref body = parse_formula();
|
||||
// A TPTP quantifier body is a <unit_formula>: the quantifier binds
|
||||
// tighter than the binary connectives & | => <= <=> <~> ~| ~&. Parse
|
||||
// at equality precedence so the body absorbs an infix =/!= but stops
|
||||
// at any lower-precedence connective, which stays in the enclosing
|
||||
// expression. E.g. "! [X] : p(X) & q(X)" is "(! [X] : p(X)) & q(X)",
|
||||
// and "! [X] : (...) => g" keeps "=> g" outside the quantifier scope.
|
||||
expr_ref body = parse_expr(PREC_EQ, true, is_boolean);
|
||||
m_bound.pop_back();
|
||||
return mk_quantifier(is_forall, vars, body);
|
||||
}
|
||||
|
|
@ -1672,10 +1723,10 @@ class tptp_parser {
|
|||
expect(token_kind::rbrack, "']'");
|
||||
}
|
||||
expect(token_kind::colon, "':'");
|
||||
return parse_formula();
|
||||
return parse_formula(is_boolean);
|
||||
}
|
||||
|
||||
return parse_atomic_formula();
|
||||
return parse_atomic_formula(is_boolean);
|
||||
}
|
||||
|
||||
// Grammar: <tff_binary_formula> ::= <tff_binary_nonassoc> | <tff_binary_assoc>
|
||||
|
|
@ -1687,8 +1738,15 @@ class tptp_parser {
|
|||
// <tff_and_formula> ::= <tff_unit_formula> & <tff_unit_formula>
|
||||
// | <tff_and_formula> & <tff_unit_formula>
|
||||
// Implements a Pratt-style (precedence climbing) parser for binary connectives.
|
||||
expr_ref parse_expr(unsigned min_prec, bool consume_at = true) {
|
||||
expr_ref e = parse_unary_formula();
|
||||
expr_ref parse_expr(unsigned min_prec, bool consume_at, bool is_boolean) {
|
||||
expr_ref e = parse_unary_formula(is_boolean);
|
||||
return parse_binary_rest(e, min_prec, consume_at);
|
||||
}
|
||||
|
||||
// Precedence-climbing loop continued from an already-parsed left operand `e`.
|
||||
// Split out from parse_expr so callers that have consumed a leading unary unit
|
||||
// (e.g. a '~' immediately after '(') can resume binary-connective parsing.
|
||||
expr_ref parse_binary_rest(expr_ref e, unsigned min_prec, bool consume_at = true) {
|
||||
for (;;) {
|
||||
// Handle @ (function application) with highest precedence
|
||||
// But NOT when we're inside a lambda body that's an @ argument
|
||||
|
|
@ -1719,7 +1777,15 @@ class tptp_parser {
|
|||
if (it->second.precedence < min_prec) break;
|
||||
next(); // consume the operator token
|
||||
unsigned next_prec = it->second.right_assoc ? it->second.precedence : it->second.precedence + 1;
|
||||
expr_ref rhs = parse_expr(next_prec, consume_at);
|
||||
// Operands of every connective except '='/'!=' are Boolean; only equality
|
||||
// takes term operands. Derive the operand context from the operator rather
|
||||
// than inheriting is_boolean from the left operand. Otherwise, once a
|
||||
// term-valued equality literal (e.g. 'a = b') sets is_boolean to false, a
|
||||
// predicate atom later in the same clause ('a = b | q') would be parsed as a
|
||||
// term and boxed into '$box_U_to_Bool(q)', severing it from the Boolean
|
||||
// predicate 'q' used elsewhere and making refutable problems satisfiable.
|
||||
bool rhs_is_boolean = it->second.precedence != PREC_EQ;
|
||||
expr_ref rhs = parse_expr(next_prec, consume_at, rhs_is_boolean);
|
||||
expr_ref_vector args(m);
|
||||
args.push_back(e);
|
||||
args.push_back(rhs);
|
||||
|
|
@ -1786,12 +1852,27 @@ class tptp_parser {
|
|||
// Try relative to current file's directory
|
||||
std::string local = normalize_path(dirname(curr_file) + "/" + name);
|
||||
if (file_exists(local)) return local;
|
||||
// Try TPTP environment variable (standard TPTP convention)
|
||||
// Try TPTP environment variable (standard TPTP convention): includes such as
|
||||
// "Axioms/MAT001^0.ax" are resolved relative to the TPTP root directory named
|
||||
// by $TPTP. This is required when a problem is run from a directory that does
|
||||
// not contain the Axioms/ tree (e.g. an isolated benchmark harness workspace).
|
||||
char const* root = std::getenv("TPTP");
|
||||
if (root) {
|
||||
std::string env = normalize_path(std::string(root) + "/" + name);
|
||||
if (file_exists(env)) return env;
|
||||
}
|
||||
// Walk up ancestor directories of the current file. TPTP include paths are
|
||||
// relative to the TPTP root directory (e.g. "Axioms/BOO001-0.ax"), while the
|
||||
// problem file typically lives in a subdirectory such as "Problems/BOO/".
|
||||
std::string dir = dirname(curr_file);
|
||||
for (;;) {
|
||||
size_t idx = dir.find_last_of("/\\");
|
||||
if (idx == std::string::npos) break;
|
||||
dir = dir.substr(0, idx);
|
||||
if (dir.empty()) break;
|
||||
std::string candidate = normalize_path(dir + "/" + name);
|
||||
if (file_exists(candidate)) return candidate;
|
||||
}
|
||||
// Try relative to current working directory (common when running from TPTP root)
|
||||
std::string cwd_relative = normalize_path(name);
|
||||
if (file_exists(cwd_relative)) return cwd_relative;
|
||||
|
|
@ -1825,7 +1906,7 @@ class tptp_parser {
|
|||
// <annotations> ::= ,<source><optional_info> | <null>
|
||||
void parse_annotated() {
|
||||
expect(token_kind::lparen, "'('");
|
||||
parse_name();
|
||||
std::string formula_name = parse_name();
|
||||
expect(token_kind::comma, "','");
|
||||
std::string role = to_lower(parse_name());
|
||||
expect(token_kind::comma, "','");
|
||||
|
|
@ -1836,12 +1917,14 @@ class tptp_parser {
|
|||
else if (role == "logic") {
|
||||
// Modal logic declarations ($modal == [...]) — skip the formula body
|
||||
skip_annotations_until_rparen();
|
||||
warning_msg("non-classical logics are not supported");
|
||||
++m_dropped_formulas;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
implicit_var_scope implicit_scope;
|
||||
scoped_implicit_vars scoped(*this, implicit_scope);
|
||||
expr_ref f = parse_formula();
|
||||
expr_ref f = parse_formula(true);
|
||||
if (!implicit_scope.order.empty()) {
|
||||
f = mk_quantifier(true, implicit_scope.order, f);
|
||||
}
|
||||
|
|
@ -1854,13 +1937,30 @@ class tptp_parser {
|
|||
}
|
||||
m_cmd.assert_expr(f);
|
||||
} catch (z3_exception const& ex) {
|
||||
// Sort mismatch or other semantic error in this formula — skip it
|
||||
IF_VERBOSE(2, verbose_stream() << "skipping formula due to: " << ex.what() << "\n");
|
||||
// Sort mismatch or other semantic error in this formula — skip it.
|
||||
// A dropped axiom/definition removes constraints from the problem, so a
|
||||
// subsequent "sat" verdict is unsound: it may only hold because the
|
||||
// dropped formula was missing. The count is used to downgrade a sat
|
||||
// result to GaveUp rather than report a spurious CounterSatisfiable.
|
||||
++m_dropped_formulas;
|
||||
std::ostringstream oss;
|
||||
oss << "skipping formula '" << formula_name << "' due to: " << ex.what();
|
||||
warning_msg(oss.str().c_str());
|
||||
// Skip to '.' to resync the parser for the next annotated formula
|
||||
while (!is(token_kind::eof_tok) && !is(token_kind::dot))
|
||||
next();
|
||||
if (is(token_kind::dot)) next();
|
||||
return;
|
||||
} catch (std::exception const& ex) {
|
||||
++m_dropped_formulas;
|
||||
std::ostringstream oss;
|
||||
oss << "skipping formula '" << formula_name << "' (role " << role << ") due to: " << ex.what() << "\n";
|
||||
warning_msg(oss.str().c_str());
|
||||
while (!is(token_kind::eof_tok) && !is(token_kind::dot))
|
||||
next();
|
||||
if (is(token_kind::dot))
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2114,6 +2214,12 @@ public:
|
|||
}};
|
||||
}
|
||||
|
||||
// Record a double-quoted string constant as a TPTP distinct object (deduplicated by name).
|
||||
void register_distinct_object(std::string const& name, expr* c) {
|
||||
if (m_distinct_objects.emplace(name, c).second)
|
||||
m_pinned_exprs.push_back(c);
|
||||
}
|
||||
|
||||
void parse_input(std::istream& in, std::string const& current_file) {
|
||||
// Save parser state so that included files don't clobber the caller's lexer.
|
||||
std::string saved_input = std::move(m_input);
|
||||
|
|
@ -2123,6 +2229,7 @@ public:
|
|||
std::ostringstream buf;
|
||||
buf << in.rdbuf();
|
||||
m_input = buf.str();
|
||||
extract_expected_status(m_input);
|
||||
m_lex = std::make_unique<lexer>(m_input);
|
||||
next();
|
||||
parse_toplevel(current_file);
|
||||
|
|
@ -2149,6 +2256,78 @@ public:
|
|||
}
|
||||
|
||||
bool has_conjecture() const { return m_has_conjecture; }
|
||||
|
||||
// TPTP double-quoted strings ("...") denote pairwise distinct domain elements.
|
||||
// Assert a single global distinctness constraint over all collected distinct objects
|
||||
// so that e.g. "Apple" != "Microsoft" is recognized as a theorem.
|
||||
void assert_distinct_objects() {
|
||||
if (m_distinct_objects.size() < 2) return;
|
||||
expr_ref_vector objs(m);
|
||||
for (auto const& kv : m_distinct_objects)
|
||||
objs.push_back(kv.second);
|
||||
m_cmd.assert_expr(expr_ref(m.mk_distinct(objs.size(), objs.data()), m));
|
||||
}
|
||||
|
||||
// Number of axioms/definitions that were dropped during parsing because the
|
||||
// higher-order encoding could not type-check them. When non-zero, a "sat"
|
||||
// verdict cannot be trusted (the missing constraints may be exactly what
|
||||
// makes the problem unsatisfiable).
|
||||
unsigned dropped_formulas() const { return m_dropped_formulas; }
|
||||
|
||||
std::string const& expected_status() const { return m_expected_status; }
|
||||
|
||||
// Scan TPTP comments for an SZS/Status annotation, e.g.
|
||||
// % Status : Unsatisfiable
|
||||
// % SZS status Theorem
|
||||
// Only the first annotation found (the top-level file's) is recorded.
|
||||
void extract_expected_status(std::string const& text) {
|
||||
if (!m_expected_status.empty())
|
||||
return;
|
||||
std::istringstream in(text);
|
||||
std::string line;
|
||||
while (std::getline(in, line)) {
|
||||
// TPTP comment lines start with '%'.
|
||||
size_t i = line.find_first_not_of(" \t");
|
||||
if (i == std::string::npos || line[i] != '%')
|
||||
continue;
|
||||
++i; // skip '%'
|
||||
// Skip leading '%' and spaces.
|
||||
i = line.find_first_not_of("% \t", i);
|
||||
if (i == std::string::npos)
|
||||
continue;
|
||||
std::string rest = line.substr(i);
|
||||
std::string status;
|
||||
// Form 1: "SZS status <Word>"
|
||||
if (rest.compare(0, 4, "SZS ") == 0) {
|
||||
size_t p = rest.find("status");
|
||||
if (p == std::string::npos)
|
||||
continue;
|
||||
p += 6; // length of "status"
|
||||
status = next_status_word(rest, p);
|
||||
}
|
||||
// Form 2: "Status : <Word>" / "Status : <Word>"
|
||||
else if (rest.compare(0, 6, "Status") == 0) {
|
||||
size_t p = rest.find(':', 6);
|
||||
if (p == std::string::npos)
|
||||
continue;
|
||||
status = next_status_word(rest, p + 1);
|
||||
}
|
||||
if (!status.empty()) {
|
||||
m_expected_status = status;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string next_status_word(std::string const& s, size_t p) {
|
||||
size_t a = s.find_first_not_of(" \t", p);
|
||||
if (a == std::string::npos)
|
||||
return "";
|
||||
size_t b = a;
|
||||
while (b < s.size() && (isalnum((unsigned char)s[b]) || s[b] == '_'))
|
||||
++b;
|
||||
return s.substr(a, b - a);
|
||||
}
|
||||
};
|
||||
|
||||
expr_ref tptp_parser::parse_term() {
|
||||
|
|
@ -2172,12 +2351,41 @@ expr_ref tptp_parser::parse_term() {
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_ref tptp_parser::parse_formula() {
|
||||
return parse_expr(PREC_IFF);
|
||||
expr_ref tptp_parser::parse_formula(bool is_boolean) {
|
||||
return parse_expr(PREC_IFF, true, is_boolean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Classify an SZS status into the coarse verdict used for cross-checking.
|
||||
// unsat: a refutation/proof exists (Theorem, Unsatisfiable, ContradictoryAxioms, ...)
|
||||
// sat: a model exists (Satisfiable, CounterSatisfiable, ...)
|
||||
// other: no comparable verdict (Open, Unknown, Timeout, GaveUp, empty, ...)
|
||||
enum class szs_verdict { unsat, sat, other };
|
||||
|
||||
static szs_verdict classify_szs(std::string const& s) {
|
||||
if (s == "Theorem" || s == "Unsatisfiable" || s == "ContradictoryAxioms" || s == "Unsat")
|
||||
return szs_verdict::unsat;
|
||||
if (s == "Satisfiable" || s == "CounterSatisfiable" || s == "CounterTheorem" || s == "Sat")
|
||||
return szs_verdict::sat;
|
||||
return szs_verdict::other;
|
||||
}
|
||||
|
||||
// Emit the SZS status produced by z3. If the input carries an annotated status
|
||||
// that contradicts the produced verdict, prepend "BUG" to flag the mismatch.
|
||||
static void report_szs_status(char const* produced, std::string const& expected) {
|
||||
szs_verdict pv = classify_szs(produced);
|
||||
szs_verdict ev = classify_szs(expected);
|
||||
bool is_bug = !expected.empty() &&
|
||||
(pv == szs_verdict::unsat || pv == szs_verdict::sat) &&
|
||||
(ev == szs_verdict::unsat || ev == szs_verdict::sat) &&
|
||||
pv != ev;
|
||||
if (is_bug)
|
||||
std::cout << "% SZS status BUG " << produced << " (expected " << expected << ")\n";
|
||||
else
|
||||
std::cout << "% SZS status " << produced << "\n";
|
||||
}
|
||||
|
||||
static unsigned read_tptp_stream(std::istream& in, char const* current_file) {
|
||||
register_on_timeout_proc(on_timeout);
|
||||
try {
|
||||
|
|
@ -2186,6 +2394,7 @@ static unsigned read_tptp_stream(std::istream& in, char const* current_file) {
|
|||
|
||||
tptp_parser p(ctx);
|
||||
p.parse_input(in, current_file ? current_file : ".");
|
||||
p.assert_distinct_objects();
|
||||
|
||||
// Suppress default check-sat output; TPTP frontend reports SZS status explicitly.
|
||||
std::ostringstream sink;
|
||||
|
|
@ -2194,12 +2403,24 @@ static unsigned read_tptp_stream(std::istream& in, char const* current_file) {
|
|||
ctx.check_sat(0, nullptr);
|
||||
switch (ctx.cs_state()) {
|
||||
case cmd_context::css_unsat:
|
||||
if (p.has_conjecture()) std::cout << "% SZS status Theorem\n";
|
||||
else std::cout << "% SZS status Unsatisfiable\n";
|
||||
if (p.has_conjecture()) report_szs_status("Theorem", p.expected_status());
|
||||
else report_szs_status("Unsatisfiable", p.expected_status());
|
||||
break;
|
||||
case cmd_context::css_sat:
|
||||
if (p.has_conjecture()) std::cout << "% SZS status CounterSatisfiable\n";
|
||||
else std::cout << "% SZS status Satisfiable\n";
|
||||
// A "sat" verdict is only sound if the whole problem was encoded. If any
|
||||
// axiom/definition was dropped during parsing (e.g. an unsupported
|
||||
// higher-order construct), the model may be spurious — the dropped
|
||||
// constraints could rule it out. Report GaveUp instead of a misleading
|
||||
// CounterSatisfiable/Satisfiable (which would otherwise be flagged BUG
|
||||
// against an annotated Theorem/Unsatisfiable status).
|
||||
if (p.dropped_formulas() > 0) {
|
||||
std::cout << "% SZS status GaveUp\n";
|
||||
std::cout << "% SZS reason " << p.dropped_formulas()
|
||||
<< " formula(s) dropped during encoding; model is not certified\n";
|
||||
break;
|
||||
}
|
||||
if (p.has_conjecture()) report_szs_status("CounterSatisfiable", p.expected_status());
|
||||
else report_szs_status("Satisfiable", p.expected_status());
|
||||
if (g_display_model) {
|
||||
model_ref mdl;
|
||||
if (ctx.is_model_available(mdl))
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ namespace lp {
|
|||
|
||||
void limit_j(unsigned bound_j, const mpq& u, bool coeff_before_j_is_pos, bool is_lower_bound, bool strict) {
|
||||
auto* lar = &m_bp.lp();
|
||||
const auto& row = this->m_row;
|
||||
auto* row = &this->m_row;
|
||||
auto explain = [row, bound_j, coeff_before_j_is_pos, is_lower_bound, strict, lar]() {
|
||||
(void) strict;
|
||||
TRACE(bound_analyzer, tout << "explain_bound_on_var_on_coeff, bound_j = " << bound_j << ", coeff_before_j_is_pos = " << coeff_before_j_is_pos << ", is_lower_bound = " << is_lower_bound << ", strict = " << strict << "\n";);
|
||||
|
|
@ -305,7 +305,7 @@ namespace lp {
|
|||
int j_sign = (coeff_before_j_is_pos ? 1 : -1) * bound_sign;
|
||||
|
||||
u_dependency* ret = nullptr;
|
||||
for (auto const& r : row) {
|
||||
for (auto const& r : *row) {
|
||||
unsigned j = r.var();
|
||||
if (j == bound_j)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ namespace lp {
|
|||
const lar_term* m_t;
|
||||
undo_add_term(imp& s, const lar_term* t) : m_s(s), m_t(t) {}
|
||||
|
||||
void undo() {
|
||||
void undo() override {
|
||||
m_s.undo_add_term_method(m_t);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ Author:
|
|||
Revision History:
|
||||
--*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "math/lp/int_solver.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "math/lp/int_cube.h"
|
||||
|
|
@ -81,32 +84,264 @@ namespace lp {
|
|||
SASSERT(lp_status::OPTIMAL == lra.get_status() || lp_status::FEASIBLE == lra.get_status());
|
||||
}
|
||||
|
||||
impq int_cube::get_cube_delta_for_term(const lar_term& t) const {
|
||||
if (t.size() == 2) {
|
||||
bool seen_minus = false;
|
||||
bool seen_plus = false;
|
||||
for(lar_term::ival p : t) {
|
||||
if (!lia.column_is_int(p.j()))
|
||||
goto usual_delta;
|
||||
const mpq & c = p.coeff();
|
||||
if (c == one_of_type<mpq>()) {
|
||||
seen_plus = true;
|
||||
} else if (c == -one_of_type<mpq>()) {
|
||||
seen_minus = true;
|
||||
} else {
|
||||
goto usual_delta;
|
||||
// The largest cube test of Bromberger and Weidenbach:
|
||||
// maximize x_e subject to Ax + a'(x_e/2) <= b, x_e >= 0, where a'_i = ||a_i||_1,
|
||||
// with the 1-norm taken over the integer variables of the row.
|
||||
// The solution is the center z of a largest cube contained in the polyhedron.
|
||||
// If the maximal edge length is at least 1, then the rounding of z is
|
||||
// an integer solution; otherwise the rounding is checked, and possibly repaired,
|
||||
// against the original constraints.
|
||||
lia_move int_cube::find_largest_cube() {
|
||||
lia.settings().stats().m_lcube_calls++;
|
||||
TRACE(cube,
|
||||
for (unsigned j = 0; j < lra.number_of_vars(); ++j)
|
||||
lia.display_column(tout, j);
|
||||
tout << lra.constraints();
|
||||
);
|
||||
|
||||
lra.push();
|
||||
// The edge rows are ephemeral: suppress the add-term callback,
|
||||
// dioph_eq's reaction to it is not undone by pop().
|
||||
auto add_term_cb = lra.m_add_term_callback;
|
||||
lra.m_add_term_callback = nullptr;
|
||||
unsigned x_e = lra.add_var(UINT_MAX, false); // the edge length of the cube
|
||||
lra.add_var_bound(x_e, lconstraint_kind::GE, mpq(0));
|
||||
bool ok = add_cube_edge_rows(x_e);
|
||||
lra.m_add_term_callback = add_term_cb;
|
||||
if (!ok) {
|
||||
lra.pop();
|
||||
lra.set_status(lp_status::OPTIMAL);
|
||||
return lia_move::undef;
|
||||
}
|
||||
|
||||
lp_status st = lra.find_feasible_solution();
|
||||
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
|
||||
TRACE(cube, tout << "cannot find a feasible solution";);
|
||||
lra.pop();
|
||||
lra.move_non_basic_columns_to_bounds();
|
||||
// it can happen that we found an integer solution here
|
||||
return !lra.r_basis_has_inf_int()? lia_move::sat: lia_move::undef;
|
||||
}
|
||||
|
||||
impq e; // the maximal edge length
|
||||
st = lra.maximize_term(x_e, e, /*fix_int_cols*/ false);
|
||||
if (lia.settings().get_cancel_flag()) {
|
||||
lra.pop();
|
||||
return lia_move::undef;
|
||||
}
|
||||
if (st == lp_status::UNBOUNDED) {
|
||||
// infinite lattice width: the polyhedron contains cubes of arbitrary edge length
|
||||
lra.add_var_bound(x_e, lconstraint_kind::GE, mpq(1));
|
||||
st = lra.find_feasible_solution();
|
||||
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
|
||||
lra.pop();
|
||||
return lia_move::undef;
|
||||
}
|
||||
lra.pop();
|
||||
return sat_after_rounding();
|
||||
}
|
||||
TRACE(cube, tout << "max edge length = " << e << "\n";);
|
||||
if (e >= impq(mpq(1))) {
|
||||
lra.pop();
|
||||
return sat_after_rounding();
|
||||
}
|
||||
// the largest cube is smaller than the unit cube:
|
||||
// the rounded center is only a candidate
|
||||
lra.pop();
|
||||
return round_and_repair();
|
||||
}
|
||||
|
||||
bool int_cube::add_cube_edge_rows(unsigned x_e) {
|
||||
// snapshot the term columns: add_edge_rows_for_term appends to lra.terms()
|
||||
svector<unsigned> term_columns;
|
||||
for (const lar_term* t : lra.terms())
|
||||
term_columns.push_back(t->j());
|
||||
for (unsigned j : term_columns)
|
||||
if (!add_edge_rows_for_term(j, x_e)) {
|
||||
TRACE(cube, tout << "cannot add the edge rows";);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// i is the column index having the term
|
||||
bool int_cube::add_edge_rows_for_term(unsigned i, unsigned x_e) {
|
||||
if (!lra.column_associated_with_row(i))
|
||||
return true;
|
||||
const lar_term& t = lra.get_term(i);
|
||||
impq delta = get_cube_delta_for_term(t);
|
||||
TRACE(cube, lra.print_term_as_indices(t, tout); tout << ", delta = " << delta << "\n";);
|
||||
if (is_zero(delta))
|
||||
return true;
|
||||
if (!is_zero(delta.y))
|
||||
// the infinitesimal delta does not scale with x_e: tighten statically,
|
||||
// it is sound for any edge length
|
||||
return lra.tighten_term_bounds_by_delta(i, delta);
|
||||
if (lra.column_has_upper_bound(i)) {
|
||||
impq u = lra.get_upper_bound(i); // copy: add_term invalidates bound references
|
||||
vector<std::pair<mpq, unsigned>> coeffs = {{mpq(1), i}, {delta.x, x_e}};
|
||||
unsigned s = lra.add_term(coeffs, UINT_MAX);
|
||||
lra.add_var_bound(s, is_zero(u.y) ? lconstraint_kind::LE : lconstraint_kind::LT, u.x);
|
||||
}
|
||||
if (lra.column_has_lower_bound(i)) {
|
||||
impq l = lra.get_lower_bound(i); // copy: add_term invalidates bound references
|
||||
vector<std::pair<mpq, unsigned>> coeffs = {{mpq(1), i}, {-delta.x, x_e}};
|
||||
unsigned s = lra.add_term(coeffs, UINT_MAX);
|
||||
lra.add_var_bound(s, is_zero(l.y) ? lconstraint_kind::GE : lconstraint_kind::GT, l.x);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
lia_move int_cube::sat_after_rounding() {
|
||||
lra.round_to_integer_solution();
|
||||
lra.set_status(lp_status::FEASIBLE);
|
||||
SASSERT(lia.settings().get_cancel_flag() || lia.is_feasible());
|
||||
TRACE(cube, tout << "largest cube success";);
|
||||
lia.settings().stats().m_lcube_success++;
|
||||
return lia_move::sat;
|
||||
}
|
||||
|
||||
lia_move int_cube::round_and_repair() {
|
||||
lra.backup_x(); // remember the cube center
|
||||
vector<flip_candidate> flips;
|
||||
for (unsigned j = 0; j < lra.column_count(); ++j) {
|
||||
if (!lra.column_is_int(j) || lra.column_has_term(j))
|
||||
continue;
|
||||
const impq& v = lra.get_column_value(j);
|
||||
if (v.is_int())
|
||||
continue;
|
||||
flips.push_back({j, floor(v), false});
|
||||
}
|
||||
lra.round_to_integer_solution();
|
||||
for (auto& f : flips)
|
||||
f.m_at_hi = lra.get_column_value(f.m_j).x > f.m_lo;
|
||||
if (repair_rounded_candidate(flips)) {
|
||||
lra.set_status(lp_status::FEASIBLE);
|
||||
SASSERT(lia.settings().get_cancel_flag() || lia.is_feasible());
|
||||
TRACE(cube, tout << "largest cube success";);
|
||||
lia.settings().stats().m_lcube_success++;
|
||||
return lia_move::sat;
|
||||
}
|
||||
// return to the cube center: an interior point of the polyhedron
|
||||
lra.restore_x();
|
||||
lra.set_status(lp_status::FEASIBLE);
|
||||
return lia_move::undef;
|
||||
}
|
||||
|
||||
// Checks the rounded center against the original constraints. On failure
|
||||
// searches the vertices of the lattice cell around the center greedily:
|
||||
// flip a coordinate between floor and ceiling to maximally decrease the
|
||||
// total bound violation, within a budget.
|
||||
bool int_cube::repair_rounded_candidate(vector<flip_candidate>& flips) {
|
||||
vector<bounded_row> rows;
|
||||
for (const lar_term* t : lra.terms()) {
|
||||
unsigned j = t->j();
|
||||
if (!lra.column_associated_with_row(j))
|
||||
continue;
|
||||
if (!lra.column_has_upper_bound(j) && !lra.column_has_lower_bound(j))
|
||||
continue;
|
||||
bounded_row r;
|
||||
r.m_j = j;
|
||||
r.m_val = t->apply(lra.r_x());
|
||||
rows.push_back(r);
|
||||
}
|
||||
auto row_violation = [&](unsigned ri, const impq& v) {
|
||||
impq w;
|
||||
unsigned j = rows[ri].m_j;
|
||||
if (lra.column_has_upper_bound(j) && v > lra.get_upper_bound(j))
|
||||
w += v - lra.get_upper_bound(j);
|
||||
if (lra.column_has_lower_bound(j) && v < lra.get_lower_bound(j))
|
||||
w += lra.get_lower_bound(j) - v;
|
||||
return w;
|
||||
};
|
||||
impq violation;
|
||||
for (unsigned ri = 0; ri < rows.size(); ++ri)
|
||||
violation += row_violation(ri, rows[ri].m_val);
|
||||
if (is_zero(violation))
|
||||
return true; // the rounded center fits as it is
|
||||
if (flips.empty())
|
||||
return false;
|
||||
|
||||
std::unordered_map<unsigned, unsigned> flip_of_var;
|
||||
for (unsigned fi = 0; fi < flips.size(); ++fi)
|
||||
flip_of_var[flips[fi].m_j] = fi;
|
||||
// occurrences of the flip candidates in the bounded rows
|
||||
vector<vector<std::pair<unsigned, mpq>>> occs(flips.size());
|
||||
for (unsigned ri = 0; ri < rows.size(); ++ri) {
|
||||
const lar_term& t = lra.get_term(rows[ri].m_j);
|
||||
for (lar_term::ival p : t) {
|
||||
auto it = flip_of_var.find(p.j());
|
||||
if (it != flip_of_var.end())
|
||||
occs[it->second].push_back({ri, p.coeff()});
|
||||
}
|
||||
}
|
||||
|
||||
unsigned budget = std::min(2 * flips.size(), lia.settings().lcube_flips());
|
||||
bool flipped = false;
|
||||
while (!is_zero(violation) && budget-- > 0) {
|
||||
unsigned best_fi = UINT_MAX;
|
||||
impq best_gain;
|
||||
for (unsigned fi = 0; fi < flips.size(); ++fi) {
|
||||
if (occs[fi].empty())
|
||||
continue;
|
||||
mpq step = flips[fi].m_at_hi ? mpq(-1) : mpq(1);
|
||||
impq gain;
|
||||
for (const auto& o : occs[fi]) {
|
||||
const impq& v = rows[o.first].m_val;
|
||||
gain += row_violation(o.first, v + impq(step * o.second)) - row_violation(o.first, v);
|
||||
}
|
||||
if (gain < best_gain) {
|
||||
best_gain = gain;
|
||||
best_fi = fi;
|
||||
}
|
||||
}
|
||||
if (seen_minus && seen_plus)
|
||||
return zero_of_type<impq>();
|
||||
return impq(0, 1);
|
||||
if (best_fi == UINT_MAX)
|
||||
return false; // no flip decreases the violation
|
||||
mpq step = flips[best_fi].m_at_hi ? mpq(-1) : mpq(1);
|
||||
for (const auto& o : occs[best_fi])
|
||||
rows[o.first].m_val += impq(step * o.second);
|
||||
flips[best_fi].m_at_hi = !flips[best_fi].m_at_hi;
|
||||
violation += best_gain;
|
||||
flipped = true;
|
||||
TRACE(cube, tout << "flipped column " << flips[best_fi].m_j << ", violation = " << violation << "\n";);
|
||||
}
|
||||
if (!is_zero(violation))
|
||||
return false;
|
||||
|
||||
// apply the repaired candidate
|
||||
for (const auto& f : flips)
|
||||
lra.set_column_value(f.m_j, impq(f.m_at_hi ? f.m_lo + 1 : f.m_lo));
|
||||
for (const lar_term* t : lra.terms()) {
|
||||
unsigned j = t->j();
|
||||
if (!lra.column_associated_with_row(j))
|
||||
continue;
|
||||
lra.set_column_value(j, t->apply(lra.r_x()));
|
||||
}
|
||||
if (flipped)
|
||||
lia.settings().stats().m_lcube_flip_success++;
|
||||
return true;
|
||||
}
|
||||
|
||||
impq int_cube::get_cube_delta_for_term(const lar_term& t) const {
|
||||
if (t.size() == 2) {
|
||||
bool seen_minus = false, seen_plus = false, all_ok = true;
|
||||
for (lar_term::ival p : t) {
|
||||
if (!lia.column_is_int(p.j())) { all_ok = false; break; }
|
||||
const mpq& c = p.coeff();
|
||||
if (c == one_of_type<mpq>()) seen_plus = true;
|
||||
else if (c == -one_of_type<mpq>()) seen_minus = true;
|
||||
else { all_ok = false; break; }
|
||||
}
|
||||
if (all_ok) {
|
||||
if (seen_minus && seen_plus)
|
||||
return zero_of_type<impq>();
|
||||
return impq(0, 1);
|
||||
}
|
||||
}
|
||||
usual_delta:
|
||||
mpq delta = zero_of_type<mpq>();
|
||||
for (lar_term::ival p : t)
|
||||
if (lia.column_is_int(p.j()))
|
||||
delta += abs(p.coeff());
|
||||
|
||||
delta *= mpq(1, 2);
|
||||
return impq(delta);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,15 @@ Abstract:
|
|||
Cube finder
|
||||
|
||||
This routine attempts to find a feasible integer solution
|
||||
by tightnening bounds and running an LRA solver on the
|
||||
by tightnening bounds and running an LRA solver on the
|
||||
tighter system.
|
||||
|
||||
find_largest_cube() implements the largest cube test of
|
||||
Bromberger and Weidenbach (Fast Cube Tests for LIA Constraint
|
||||
Solving, IJCAR 2016): a fresh variable x_e for the cube edge
|
||||
length is introduced and maximized; the center of the largest
|
||||
cube is rounded to a candidate integer solution.
|
||||
|
||||
Author:
|
||||
Nikolaj Bjorner (nbjorner)
|
||||
Lev Nachmanson (levnach)
|
||||
|
|
@ -21,7 +27,10 @@ Revision History:
|
|||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "util/vector.h"
|
||||
#include "math/lp/lia_move.h"
|
||||
#include "math/lp/numeric_pair.h"
|
||||
#include "math/lp/lar_term.h"
|
||||
|
||||
namespace lp {
|
||||
class int_solver;
|
||||
|
|
@ -29,12 +38,30 @@ namespace lp {
|
|||
class int_cube {
|
||||
class int_solver& lia;
|
||||
class lar_solver& lra;
|
||||
// a fractional integer coordinate of the cube center:
|
||||
// the candidate value is m_lo or m_lo + 1
|
||||
struct flip_candidate {
|
||||
unsigned m_j = 0;
|
||||
mpq m_lo;
|
||||
bool m_at_hi = false;
|
||||
};
|
||||
// a term column with at least one bound, tracked during the repair
|
||||
struct bounded_row {
|
||||
unsigned m_j = 0;
|
||||
impq m_val;
|
||||
};
|
||||
bool tighten_term_for_cube(unsigned i);
|
||||
bool tighten_terms_for_cube();
|
||||
void find_feasible_solution();
|
||||
impq get_cube_delta_for_term(const lar_term& t) const;
|
||||
bool add_edge_rows_for_term(unsigned i, unsigned x_e);
|
||||
bool add_cube_edge_rows(unsigned x_e);
|
||||
lia_move sat_after_rounding();
|
||||
lia_move round_and_repair();
|
||||
bool repair_rounded_candidate(vector<flip_candidate>& flips);
|
||||
public:
|
||||
int_cube(int_solver& lia);
|
||||
lia_move operator()();
|
||||
lia_move find_largest_cube();
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ namespace lp {
|
|||
dioph_eq m_dio;
|
||||
int_gcd_test m_gcd;
|
||||
unsigned m_initial_dio_calls_period;
|
||||
|
||||
unsigned m_lcube_period;
|
||||
// The number of consecutive genuine dio calls that returned undef, reset on a dio
|
||||
// conflict. Drives the decision to start running Gomory with dio.
|
||||
unsigned m_dio_undef_in_a_row = 0;
|
||||
|
||||
bool column_is_int_inf(unsigned j) const {
|
||||
return lra.column_is_int(j) && (!lia.value_is_int(j));
|
||||
}
|
||||
|
|
@ -52,7 +56,8 @@ namespace lp {
|
|||
imp(int_solver& lia): lia(lia), lra(lia.lra), lrac(lia.lrac), m_hnf_cutter(lia), m_dio(lia), m_gcd(lia) {
|
||||
m_hnf_cut_period = settings().hnf_cut_period();
|
||||
m_initial_dio_calls_period = settings().dio_calls_period();
|
||||
}
|
||||
m_lcube_period = settings().m_int_find_cube_period;
|
||||
}
|
||||
|
||||
bool has_lower(unsigned j) const {
|
||||
switch (lrac.m_column_types()[j]) {
|
||||
|
|
@ -176,14 +181,16 @@ namespace lp {
|
|||
if (r == lia_move::conflict) {
|
||||
m_dio.explain(*this->m_ex);
|
||||
lia.settings().dio_calls_period() = m_initial_dio_calls_period;
|
||||
lia.settings().dio_enable_gomory_cuts() = false;
|
||||
m_dio_undef_in_a_row = 0;
|
||||
lia.settings().stop_running_gomory_with_dio(); // dio was productive: stop running Gomory
|
||||
lia.settings().set_run_gcd_test(false);
|
||||
return lia_move::conflict;
|
||||
}
|
||||
if (r == lia_move::undef) {
|
||||
lia.settings().dio_calls_period() *= 2;
|
||||
if (lra.settings().dio_calls_period() >= 16) {
|
||||
lia.settings().dio_enable_gomory_cuts() = true;
|
||||
lia.settings().dio_calls_period() *= 2; // throttle dio scheduling on failure
|
||||
++m_dio_undef_in_a_row;
|
||||
if (m_dio_undef_in_a_row >= lra.settings().dio_gomory_enable_period()) {
|
||||
lia.settings().start_running_gomory_with_dio(); // dio persistently unproductive: start running Gomory
|
||||
lia.settings().set_run_gcd_test(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -191,26 +198,66 @@ namespace lp {
|
|||
}
|
||||
|
||||
lp_settings& settings() { return lra.settings(); }
|
||||
|
||||
|
||||
// Decide whether a periodic heuristic fires on this call. When
|
||||
// random_hammers is enabled the gate is drawn at random with the same
|
||||
// 1/period expected rate instead of a deterministic "every k-th call"
|
||||
// modulus: a deterministic period can phase-lock with the search on
|
||||
// some families and drown the solver in conflicts while another handler
|
||||
// is starved; randomizing the gate breaks that resonance.
|
||||
bool hit_period(unsigned period) {
|
||||
if (period <= 1)
|
||||
return true;
|
||||
if (settings().random_hammers())
|
||||
return settings().random_next(period) == 0;
|
||||
return m_number_of_calls % period == 0;
|
||||
}
|
||||
|
||||
bool should_find_cube() {
|
||||
return m_number_of_calls % settings().m_int_find_cube_period == 0;
|
||||
return hit_period(settings().m_int_find_cube_period);
|
||||
}
|
||||
|
||||
// The largest cube test is throttled exponentially: when the polyhedron
|
||||
// does not contain a large enough cube it is unlikely to contain one
|
||||
// later, after more constraints are added, so each failure doubles the
|
||||
// period and a success resets it.
|
||||
bool should_find_lcube() {
|
||||
return settings().lcube() && hit_period(m_lcube_period);
|
||||
}
|
||||
|
||||
lia_move find_lcube() {
|
||||
lia_move r = int_cube(lia).find_largest_cube();
|
||||
if (r == lia_move::undef) {
|
||||
if (m_lcube_period < (1u << 30))
|
||||
m_lcube_period *= 2;
|
||||
}
|
||||
else
|
||||
m_lcube_period = settings().m_int_find_cube_period;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool should_gomory_cut() {
|
||||
bool dio_allows_gomory = !settings().dio() || settings().dio_enable_gomory_cuts() ||
|
||||
m_dio.some_terms_are_ignored();
|
||||
return dio_allows_gomory && m_number_of_calls % settings().m_int_gomory_cut_period == 0;
|
||||
return dio_allows_gomory && hit_period(settings().m_int_gomory_cut_period);
|
||||
}
|
||||
|
||||
bool should_solve_dioph_eq() {
|
||||
return lia.settings().dio() && (m_number_of_calls % settings().dio_calls_period() == 0);
|
||||
bool ret = lia.settings().dio() && hit_period(settings().dio_calls_period());
|
||||
if (!ret && lia.settings().dio_calls_period() > m_initial_dio_calls_period) {
|
||||
unsigned dec = settings().dio_calls_period_decrease();
|
||||
unsigned& period = lia.settings().dio_calls_period();
|
||||
period = period > m_initial_dio_calls_period + dec ? period - dec : m_initial_dio_calls_period;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// HNF
|
||||
|
||||
bool should_hnf_cut() {
|
||||
return (!settings().dio() || settings().dio_enable_hnf_cuts())
|
||||
&& settings().enable_hnf() && m_number_of_calls % settings().hnf_cut_period() == 0;
|
||||
&& settings().enable_hnf() && hit_period(settings().hnf_cut_period());
|
||||
}
|
||||
|
||||
lia_move hnf_cut() {
|
||||
|
|
@ -245,11 +292,12 @@ namespace lp {
|
|||
|
||||
++m_number_of_calls;
|
||||
if (r == lia_move::undef) r = patch_basic_columns();
|
||||
if (r == lia_move::undef && should_find_cube()) r = int_cube(lia)();
|
||||
if (r == lia_move::undef && should_find_cube()) r = int_cube(lia)();
|
||||
if (r == lia_move::undef && should_find_lcube()) r = find_lcube();
|
||||
if (r == lia_move::undef) lra.move_non_basic_columns_to_bounds();
|
||||
if (r == lia_move::undef && should_hnf_cut()) r = hnf_cut();
|
||||
if (r == lia_move::undef && should_gomory_cut()) r = gomory(lia).get_gomory_cuts(2);
|
||||
if (r == lia_move::undef && should_solve_dioph_eq()) r = solve_dioph_eq();
|
||||
if (r == lia_move::undef && should_gomory_cut()) r = gomory(lia).get_gomory_cuts(2);
|
||||
if (r == lia_move::undef) r = int_branch(lia)();
|
||||
if (settings().get_cancel_flag()) r = lia_move::undef;
|
||||
return r;
|
||||
|
|
|
|||
|
|
@ -864,7 +864,7 @@ namespace lp {
|
|||
}
|
||||
|
||||
lp_status lar_solver::maximize_term(unsigned j,
|
||||
impq& term_max) {
|
||||
impq& term_max, bool fix_int_cols) {
|
||||
TRACE(lar_solver, print_values(tout););
|
||||
SASSERT(get_core_solver().m_r_solver.calc_current_x_is_feasible_include_non_basis());
|
||||
lar_term term = get_term_to_maximize(j);
|
||||
|
|
@ -879,6 +879,11 @@ namespace lp {
|
|||
return lp_status::UNBOUNDED;
|
||||
}
|
||||
|
||||
if (!fix_int_cols) {
|
||||
set_status(lp_status::OPTIMAL);
|
||||
return lp_status::OPTIMAL;
|
||||
}
|
||||
|
||||
impq opt_val = term_max;
|
||||
|
||||
bool change = false;
|
||||
|
|
@ -1120,8 +1125,10 @@ namespace lp {
|
|||
|
||||
void lar_solver::explain_fixed_column(unsigned j, explanation& ex) {
|
||||
SASSERT(column_is_fixed(j));
|
||||
auto* deps = get_bound_constraint_witnesses_for_column(j);
|
||||
for (auto ci : flatten(deps))
|
||||
const column& ul = m_imp->m_columns[j];
|
||||
m_imp->m_tmp_dependencies.reset();
|
||||
m_imp->m_dependencies.linearize(ul.lower_bound_witness(), ul.upper_bound_witness(), m_imp->m_tmp_dependencies);
|
||||
for (auto ci : m_imp->m_tmp_dependencies)
|
||||
ex.push_back(ci);
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue